Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ THEME_SWITCHING.md
VERCEL_CHANGES_SUMMARY.md
VERCEL_DEPLOYMENT_ASSESSMENT.md
VERCEL_MIGRATION_GUIDE.md
node_modules/
227 changes: 227 additions & 0 deletions report_analyst_enterprise/components/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# Report Analyst Enterprise Components

Framework-agnostic JSON Schema form components using RJSF engine.

## Overview

This module provides JSON Schema-based form components that work across multiple frameworks:
- **Streamlit** - Python integration
- **React** - React wrapper component
- **Svelte** - Direct web component usage (no generator needed!)
- **HTML/Vanilla JS** - Direct web component usage

The core uses RJSF's (`@rjsf/utils` and `@rjsf/validator-ajv8`) for JSON Schema Draft-07 validation and processing, wrapped in a web component for framework-agnostic usage.

## Architecture

```
Web Component (json-schema-form.js)
├── Uses @rjsf/utils for schema processing
├── Uses @rjsf/validator-ajv8 for validation
└── Framework wrappers:
├── Streamlit (Python)
├── React (TypeScript)
└── Svelte (direct usage)
```

## Installation

### Python (Streamlit)

```bash
pip install -r report_analyst_enterprise/components/requirements.txt
```

### JavaScript/TypeScript

```bash
cd report_analyst_enterprise/components/web
npm install
```

## Usage

### Streamlit

```python
from report_analyst_enterprise.components.streamlit import json_schema_form
import json

# Load schema
with open('schemas/pdf_upload_schema.json') as f:
schema = json.load(f)

with open('schemas/pdf_upload_ui_schema.json') as f:
ui_schema = json.load(f)

# Render form
form_data = json_schema_form(
schema=schema,
ui_schema=ui_schema,
key="pdf_upload"
)

if form_data:
st.write("Form submitted:", form_data)
```

### React

```tsx
import { JsonSchemaForm } from '@report-analyst/components/react';
import schema from './schemas/pdf_upload_schema.json';
import uiSchema from './schemas/pdf_upload_ui_schema.json';

function App() {
const [formData, setFormData] = useState({});

return (
<JsonSchemaForm
schema={schema}
uiSchema={uiSchema}
formData={formData}
onChange={(e) => setFormData(e.detail.formData)}
onSubmit={(e) => console.log('Submitted:', e.detail.formData)}
/>
);
}
```

### Svelte

```svelte
<script>
import schema from './schemas/pdf_upload_schema.json';
import uiSchema from './schemas/pdf_upload_ui_schema.json';

let formData = {};

function handleSubmit(event) {
formData = event.detail.formData;
console.log('Submitted:', formData);
}
</script>

<json-schema-form
schema={JSON.stringify(schema)}
ui-schema={JSON.stringify(uiSchema)}
form-data={JSON.stringify(formData)}
on:submit={handleSubmit}
/>
```

### HTML/Vanilla JS

```html
<!DOCTYPE html>
<html>
<head>
<script type="module" src="./json-schema-form.js"></script>
</head>
<body>
<json-schema-form id="form"></json-schema-form>

<script type="module">
const form = document.getElementById('form');
form.setAttribute('schema', JSON.stringify({
type: 'object',
properties: {
name: { type: 'string', title: 'Name' }
}
}));

form.addEventListener('submit', (e) => {
console.log('Form data:', e.detail.formData);
});
</script>
</body>
</html>
```

## JSON Schema Support

Full JSON Schema Draft-07 support via RJSF:
- All basic types (string, number, integer, boolean, array, object, null)
- Validation keywords (required, format, pattern, minLength, maxLength, etc.)
- Composition (allOf, anyOf, oneOf, not)
- Conditional logic (if/then/else, dependencies)
- Arrays (items, additionalItems, minItems, maxItems, uniqueItems)
- Objects (properties, additionalProperties, patternProperties)
- References ($ref, $id, $anchor)

## UI Schema Support

Customize form appearance without modifying JSON Schema:
- `ui:widget` - Widget type (text, textarea, select, checkbox, radio, etc.)
- `ui:options` - Widget-specific options
- `ui:placeholder` - Placeholder text
- `ui:help` - Help text
- `ui:label` - Custom labels
- `ui:order` - Field ordering
- `ui:classNames` - CSS classes
- `ui:disabled` - Disable field
- `ui:readonly` - Readonly field

## Example Schemas

See `schemas/` directory for example schemas:
- `pdf_upload_schema.json` - PDF upload form schema (used in Streamlit app)
- `pdf_upload_ui_schema.json` - UI customization for PDF upload form
- `question_set_editor_schema.json` - Question set editor schema (for creating/editing question sets)
- `question_set_editor_ui_schema.json` - UI customization for question set editor

### Future: Question Set Editor

The question set editor schema can be used to create a visual editor for question sets in the Streamlit app, allowing users to:
- Create custom question sets
- Edit existing question sets
- Add questions with metadata (category, guidelines, etc.)
- Export/import question sets as YAML or JSON

## Web Component API

### Attributes

- `schema` - JSON Schema (stringified JSON)
- `ui-schema` - UI Schema (stringified JSON, optional)
- `form-data` - Initial form data (stringified JSON, optional)

### Events

- `change` - Fired when form data changes
- `detail.formData` - Current form data
- `detail.errors` - Validation errors
- `submit` - Fired when form is submitted
- `detail.formData` - Submitted form data
- `error` - Fired when validation fails
- `detail.errors` - Validation errors
- `validate` - Fired after validation
- `detail.errors` - Validation errors
- `detail.valid` - Whether form is valid

## Development

### Building Web Component

```bash
cd report_analyst_enterprise/components/web
npm install
# Add bundler if needed (e.g., Vite, Rollup)
```

### Testing

```bash
# Test Streamlit component
streamlit run test_streamlit_form.py

# Test web component
cd web
python -m http.server 8000
# Open http://localhost:8000/test.html
```

## License

See LICENSE file in parent directory.

9 changes: 9 additions & 0 deletions report_analyst_enterprise/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""
Report Analyst Enterprise Components

Framework-agnostic JSON Schema form components using RJSF engine.
"""

__version__ = "0.1.0"


Binary file not shown.
Binary file not shown.
56 changes: 56 additions & 0 deletions report_analyst_enterprise/components/example_streamlit_usage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Example usage of JSON Schema form in Streamlit.

This demonstrates how to use the PDF upload form component.
"""

import json
import streamlit as st
from pathlib import Path

# Import the component
from report_analyst_enterprise.components.streamlit import json_schema_form

# Load schemas
SCHEMA_DIR = Path(__file__).parent / "schemas"

def load_schema(name: str) -> dict:
"""Load a JSON schema file."""
with open(SCHEMA_DIR / f"{name}.json", "r") as f:
return json.load(f)

def main():
st.title("PDF Upload Form Example")
st.markdown("This form is generated from JSON Schema using the web component.")

# Load schemas
schema = load_schema("pdf_upload_schema")
ui_schema = load_schema("pdf_upload_ui_schema")

# Render form
form_data = json_schema_form(
schema=schema,
ui_schema=ui_schema,
key="pdf_upload_form",
height=700
)

# Display results
if form_data:
st.success("Form submitted successfully!")
st.json(form_data)

# You can now use form_data to process the upload
st.write("### Form Data Summary")
st.write(f"**Filename:** {form_data.get('filename', 'N/A')}")
st.write(f"**Category:** {form_data.get('category', 'N/A')}")
st.write(f"**Tags:** {', '.join(form_data.get('tags', []))}")
if form_data.get('description'):
st.write(f"**Description:** {form_data.get('description')}")
if form_data.get('year'):
st.write(f"**Year:** {form_data.get('year')}")

if __name__ == "__main__":
main()


Loading
Loading