Skip to content

Commit 4df05d6

Browse files
authored
Merge pull request #24 from PADAS/23-v2-uischema-generator
v2 UISchema Generator
2 parents d9a8326 + 883b948 commit 4df05d6

14 files changed

Lines changed: 1923 additions & 50 deletions

README.md

Lines changed: 348 additions & 36 deletions
Large diffs are not rendered by default.

component-diagram.md

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
i# React Native JSONForms Formatter - Component Diagram
2+
3+
```mermaid
4+
graph TD
5+
%% External consumers
6+
RN[React Native App]
7+
8+
%% Main library interface
9+
LIB[📦 @earthranger/react-native-jsonforms-formatter]
10+
11+
%% V1 API (Original)
12+
V1_API[🔷 V1 API]
13+
VALIDATE[🔍 validateJSONSchema]
14+
GENERATE_V1[🎨 generateUISchema V1]
15+
16+
%% V2 API (New Schema Format)
17+
V2_API[🔶 V2 API]
18+
GENERATE_V2[🎨 generateUISchema V2]
19+
20+
%% V1 Processing modules
21+
JSON_PROC[📝 JSON Processing]
22+
SCHEMA_VAL[✅ Schema Validation]
23+
NUMBER_NORM[🔢 Number Normalization]
24+
FIELD_PROC[🏗️ Field Processing]
25+
UI_GEN_V1[🖼️ UI Generation V1]
26+
27+
%% V2 Processing modules
28+
FIELD_VISIBILITY[👁️ Field Visibility Processing]
29+
FIELD_GROUPING[📋 Field Grouping by Section]
30+
SECTION_ORDER[📑 Section Order Processing]
31+
CONTROL_CREATION[🎛️ Field Control Creation]
32+
LAYOUT_CREATION[🏗️ Section Layout Creation]
33+
34+
%% V1 Utility functions
35+
UTILS_V1[🛠️ V1 Utils]
36+
TRAVERSE[traverseSchema]
37+
NORMALIZE[normalizeDecimalSeparators]
38+
DUPLICATE[hasDuplicatedItems]
39+
REQUIRED[isRequiredProperty]
40+
CHECKBOX[isCheckbox]
41+
FIELDSET[isFieldSet]
42+
43+
%% V2 Utility functions
44+
UTILS_V2[🛠️ V2 Utils]
45+
IS_VISIBLE[isFieldVisible]
46+
GET_VISIBLE[getVisibleFields]
47+
GROUP_FIELDS[groupFieldsBySection]
48+
CREATE_CONTROL[createControl]
49+
CREATE_HEADER[createHeaderLabel]
50+
CREATE_SECTION[createSectionLayout]
51+
COLLECTION_INTERNAL[generateCollectionUISchemaInternal]
52+
53+
%% Shared Schema Utilities
54+
SCHEMA_UTILS[🔧 Schema Utils]
55+
DETECT_VERSION[detectSchemaVersion]
56+
PROCESS_SCHEMA[processSchema]
57+
58+
%% Data flow
59+
RN --> LIB
60+
61+
LIB --> V1_API
62+
LIB --> V2_API
63+
LIB --> SCHEMA_UTILS
64+
65+
%% V1 Flow
66+
V1_API --> VALIDATE
67+
V1_API --> GENERATE_V1
68+
69+
VALIDATE --> JSON_PROC
70+
VALIDATE --> SCHEMA_VAL
71+
VALIDATE --> NUMBER_NORM
72+
VALIDATE --> FIELD_PROC
73+
74+
GENERATE_V1 --> UI_GEN_V1
75+
76+
JSON_PROC --> UTILS_V1
77+
SCHEMA_VAL --> UTILS_V1
78+
NUMBER_NORM --> UTILS_V1
79+
FIELD_PROC --> UTILS_V1
80+
UI_GEN_V1 --> UTILS_V1
81+
82+
UTILS_V1 --> TRAVERSE
83+
UTILS_V1 --> NORMALIZE
84+
UTILS_V1 --> DUPLICATE
85+
UTILS_V1 --> REQUIRED
86+
UTILS_V1 --> CHECKBOX
87+
UTILS_V1 --> FIELDSET
88+
89+
%% V2 Flow
90+
V2_API --> GENERATE_V2
91+
92+
GENERATE_V2 --> FIELD_VISIBILITY
93+
GENERATE_V2 --> FIELD_GROUPING
94+
GENERATE_V2 --> SECTION_ORDER
95+
GENERATE_V2 --> CONTROL_CREATION
96+
GENERATE_V2 --> LAYOUT_CREATION
97+
98+
FIELD_VISIBILITY --> UTILS_V2
99+
FIELD_GROUPING --> UTILS_V2
100+
SECTION_ORDER --> UTILS_V2
101+
CONTROL_CREATION --> UTILS_V2
102+
LAYOUT_CREATION --> UTILS_V2
103+
104+
UTILS_V2 --> IS_VISIBLE
105+
UTILS_V2 --> GET_VISIBLE
106+
UTILS_V2 --> GROUP_FIELDS
107+
UTILS_V2 --> CREATE_CONTROL
108+
UTILS_V2 --> CREATE_HEADER
109+
UTILS_V2 --> CREATE_SECTION
110+
UTILS_V2 --> COLLECTION_INTERNAL
111+
112+
SCHEMA_UTILS --> DETECT_VERSION
113+
SCHEMA_UTILS --> PROCESS_SCHEMA
114+
115+
%% Styling
116+
classDef publicAPI fill:#e1f5fe,stroke:#0277bd,stroke-width:3px
117+
classDef v1Internal fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
118+
classDef v2Internal fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
119+
classDef v1Utility fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
120+
classDef v2Utility fill:#fce4ec,stroke:#c2185b,stroke-width:2px
121+
classDef sharedUtility fill:#f0f4c3,stroke:#827717,stroke-width:2px
122+
123+
class LIB,V1_API,V2_API,VALIDATE,GENERATE_V1,GENERATE_V2 publicAPI
124+
class JSON_PROC,SCHEMA_VAL,NUMBER_NORM,FIELD_PROC,UI_GEN_V1 v1Internal
125+
class FIELD_VISIBILITY,FIELD_GROUPING,SECTION_ORDER,CONTROL_CREATION,LAYOUT_CREATION v2Internal
126+
class UTILS_V1,TRAVERSE,NORMALIZE,DUPLICATE,REQUIRED,CHECKBOX,FIELDSET v1Utility
127+
class UTILS_V2,IS_VISIBLE,GET_VISIBLE,GROUP_FIELDS,CREATE_CONTROL,CREATE_HEADER,CREATE_SECTION,COLLECTION_INTERNAL v2Utility
128+
class SCHEMA_UTILS,DETECT_VERSION,PROCESS_SCHEMA sharedUtility
129+
```
130+
131+
## Component Description
132+
133+
### 🔵 Public API (Blue)
134+
- **Main Library**: Entry point for consumers
135+
- **V1 API**: Original schema format processing
136+
- **validateJSONSchema**: Validates and normalizes JSON schemas
137+
- **generateUISchema V1**: Generates UI schema from validated JSON schema
138+
- **V2 API**: New EarthRanger schema format processing
139+
- **generateUISchema V2**: Generates UI schema from V2 schema format (automatically handles collections)
140+
141+
### 🟣 V1 Internal Processing (Purple)
142+
- **JSON Processing**: Handles JSON parsing, cleaning, and formatting
143+
- **Schema Validation**: Validates schema structure and detects errors
144+
- **Number Normalization**: Converts comma decimal separators to periods
145+
- **Field Processing**: Processes fieldsets, checkboxes, and other field types
146+
- **UI Generation V1**: Creates UI schema elements from JSON schema
147+
148+
### 🟠 V2 Internal Processing (Orange)
149+
- **Field Visibility Processing**: Filters deprecated and invisible fields using getVisibleFields
150+
- **Field Grouping by Section**: Groups visible fields by their parent sections using groupFieldsBySection
151+
- **Section Order Processing**: Processes sections in the order specified by the schema's ui.order array
152+
- **Field Control Creation**: Creates JSONForms controls for each visible field with field-type-specific options
153+
- **Section Layout Creation**: Creates single-column VerticalLayout sections with ordered elements (leftColumn first, then rightColumn)
154+
155+
### 🟢 V1 Utilities (Green)
156+
- **V1 Utils Module**: Core utility functions for V1 processing
157+
- **traverseSchema**: Recursively processes nested schema objects
158+
- **normalizeDecimalSeparators**: Converts comma decimals (12,99 → 12.99)
159+
- **hasDuplicatedItems**: Detects duplicate items in arrays
160+
- **isRequiredProperty**: Checks if a property is required
161+
- **isCheckbox**: Identifies checkbox field types
162+
- **isFieldSet**: Identifies fieldset structures
163+
164+
### 🔴 V2 Utilities (Pink)
165+
- **V2 Utils Module**: Specialized utility functions for V2 processing
166+
- **isFieldVisible**: Checks if field should be rendered (not deprecated)
167+
- **getVisibleFields**: Filters and returns all visible fields from schema
168+
- **groupFieldsBySection**: Groups fields by their parent section for layout processing
169+
- **createControl**: Creates JSONForms control elements with field-type-specific options and collection embedding
170+
- **createHeaderLabel**: Creates header/label elements for sections
171+
- **createSectionLayout**: Creates single-column VerticalLayout optimized for React Native with ordered elements
172+
- **generateCollectionUISchemaInternal**: Internal function for automatic collection item UI schema generation
173+
174+
### 🟡 Shared Schema Utilities (Yellow-Green)
175+
- **Schema Utils Module**: Cross-version utility functions for schema processing
176+
- **detectSchemaVersion**: Analyzes schema structure to determine if it's V1 or V2 format
177+
- **processSchema**: Processes schema string and returns version-appropriate data structure
178+
179+
## Data Flow
180+
181+
### V1 Flow (Original)
182+
1. Consumer apps import the library
183+
2. Raw JSON schema strings are passed to validation functions
184+
3. V1 processors clean, validate, and normalize the data
185+
4. V1 utility functions handle specific transformations
186+
5. Clean, validated schemas are returned to consumers
187+
188+
### V2 Flow (New Schema Format)
189+
1. Consumer apps import V2 functions
190+
2. Structured V2 schema objects are passed to generateUISchema
191+
3. **Field Visibility Processing**: getVisibleFields filters out deprecated fields
192+
4. **Field Grouping**: groupFieldsBySection organizes fields by their parent sections
193+
5. **Section Processing**: Iterate through ui.order array to process sections in specified order
194+
6. **Control Creation**: createControl generates JSONForms controls with field-type-specific options
195+
7. **Layout Creation**: createSectionLayout builds single-column VerticalLayout with ordered elements
196+
8. React Native optimized UI schemas with embedded collection details are returned to consumers
197+
198+
## Key Differences
199+
- **V1**: Processes raw JSON strings, requires validation and normalization
200+
- **V2**: Processes structured schema objects, optimized for React Native single-column layouts
201+
- **V2**: Supports advanced features like headers, sections, collections, and field visibility
202+
- **V2**: Automatically embeds collection item UI schemas (no separate function calls needed)
203+
- **V2**: Handles all EarthRanger custom field types (TEXT, NUMERIC, CHOICE_LIST, DATE_TIME, LOCATION, COLLECTION, ATTACHMENT)
204+
- **V2**: Processes field constraints (maxItems/minItems, leftColumn/rightColumn layout)
205+
- **V2**: Mobile-first design with always-vertical layouts for React Native
206+
- **V2**: Compatible with JSONForms React Native custom renderers

package.json

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
{
22
"name": "@earthranger/react-native-jsonforms-formatter",
3-
"version": "1.0.7",
3+
"version": "2.0.0-beta.5",
44
"description": "Converts JTD into JSON Schema ",
55
"main": "./dist/bundle.js",
6-
"types": "./dist/src/index.d.ts",
7-
"module": "./dist/src/index.js",
6+
"types": "./dist/index.d.ts",
7+
"module": "./dist/index.js",
88
"browser": "./dist/bundle.js",
99
"exports": {
1010
".": {
11-
"types": "./dist/src/index.d.ts",
12-
"import": "./dist/src/index.js",
11+
"types": "./dist/index.d.ts",
12+
"import": "./dist/index.js",
1313
"require": "./dist/bundle.js"
1414
},
1515
"./v1": {
16-
"types": "./dist/src/v1.d.ts",
17-
"import": "./dist/src/v1.js",
16+
"types": "./dist/v1.d.ts",
17+
"import": "./dist/v1.js",
18+
"require": "./dist/bundle.js"
19+
},
20+
"./v2": {
21+
"types": "./dist/v2/index.d.ts",
22+
"import": "./dist/v2/index.js",
1823
"require": "./dist/bundle.js"
1924
}
2025
},
2126
"react-native": "./dist/bundle.js",
2227
"scripts": {
2328
"preinstall": "git config core.hooksPath .githooks",
24-
"build": "npx webpack",
29+
"build": "npm run clean && npm run build:lib && npm run build:bundle",
30+
"build:lib": "tsc",
31+
"build:bundle": "npx webpack",
2532
"clean": "rm -rf dist",
2633
"lint": "eslint src/ --ext .js,.jsx,.ts,.tsx",
2734
"lint:test": "eslint 'test/**/*.{ts,tsx}'",
@@ -36,8 +43,7 @@
3643
"access": "public"
3744
},
3845
"files": [
39-
"./dist/src",
40-
"./dist/bundle.js"
46+
"dist"
4147
],
4248
"keywords": [
4349
"json",

src/common/schemaUtils.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Utility functions for schema version detection and handling
3+
*/
4+
5+
export type SchemaVersion = 'v1' | 'v2';
6+
7+
export interface ParsedSchema {
8+
version: SchemaVersion;
9+
data: any;
10+
}
11+
12+
/**
13+
* Detects whether a schema string contains v1 or v2 format
14+
*
15+
* v1 schema structure: { schema: {...}, definition: [...] } or { data: { schema: {...}, definition: [...] } }
16+
* v2 schema structure: { json: {...}, ui: {...} } or { data: { json: {...}, ui: {...} } }
17+
*/
18+
export const detectSchemaVersion = (schemaString: string): ParsedSchema => {
19+
try {
20+
const parsed = JSON.parse(schemaString);
21+
22+
// Handle wrapped responses (API responses with data wrapper)
23+
const actualSchema = parsed.data || parsed;
24+
25+
// Check for v2 schema structure
26+
if (actualSchema.json && actualSchema.ui) {
27+
return {
28+
version: 'v2',
29+
data: actualSchema
30+
};
31+
}
32+
33+
// Check for v1 schema structure
34+
if (actualSchema.schema && actualSchema.definition) {
35+
return {
36+
version: 'v1',
37+
data: actualSchema
38+
};
39+
}
40+
41+
// If we have a schema property but no ui property, assume v1
42+
if (actualSchema.schema && !actualSchema.ui) {
43+
return {
44+
version: 'v1',
45+
data: actualSchema
46+
};
47+
}
48+
49+
// Default to v1 for backward compatibility
50+
return {
51+
version: 'v1',
52+
data: actualSchema
53+
};
54+
55+
} catch (error) {
56+
throw new Error(`Invalid JSON schema: ${error instanceof Error ? error.message : 'Unknown error'}`);
57+
}
58+
};
59+
60+
/**
61+
* Processes a schema string and returns the appropriate data structure for the detected version
62+
*/
63+
export const processSchema = (schemaString: string): { version: SchemaVersion; processedData: string } => {
64+
const { version, data } = detectSchemaVersion(schemaString);
65+
66+
return {
67+
version,
68+
processedData: JSON.stringify(data)
69+
};
70+
};

0 commit comments

Comments
 (0)