Skip to content

Commit 60b66bb

Browse files
committed
8 Stable Components
1 parent 61cc1e6 commit 60b66bb

File tree

2 files changed

+34
-44
lines changed

2 files changed

+34
-44
lines changed

src/components/FormSections/SceneConfigurationSection.tsx

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// SceneConfigurationSection.tsx
2+
23
import React, { useMemo } from 'react';
34
import { JsonForms } from '@jsonforms/react';
45
import {
@@ -8,6 +9,8 @@ import {
89
import { Alert, AlertDescription } from '../ui/alert';
910
import { Scene, ValidationError } from '../../types';
1011

12+
// The schema for Scenes remains the same.
13+
// It defines Scenes as an array of scene objects, each with a Layouts array.
1114
const sceneConfigSchema = {
1215
type: 'object',
1316
properties: {
@@ -18,15 +21,8 @@ const sceneConfigSchema = {
1821
type: 'object',
1922
required: ['Id', 'ProjectorMode', 'Layouts'],
2023
properties: {
21-
Id: {
22-
type: 'string',
23-
title: 'Scene ID',
24-
description: 'Unique identifier for this scene',
25-
},
26-
Variant: {
27-
type: 'string',
28-
title: 'Scene Variant',
29-
},
24+
Id: { type: 'string', title: 'Scene ID' },
25+
Variant: { type: 'string', title: 'Scene Variant' },
3026
ProjectorMode: {
3127
type: 'string',
3228
title: 'Projector Mode',
@@ -147,6 +143,7 @@ const sceneConfigSchema = {
147143
required: ['Scenes'],
148144
};
149145

146+
// UI schema
150147
const sceneConfigUiSchema = {
151148
type: 'VerticalLayout',
152149
elements: [
@@ -157,7 +154,6 @@ const sceneConfigUiSchema = {
157154
detail: {
158155
type: 'VerticalLayout',
159156
elements: [
160-
// Scene Basic Info
161157
{
162158
type: 'Group',
163159
label: 'Basic Scene Information',
@@ -167,11 +163,11 @@ const sceneConfigUiSchema = {
167163
elements: [
168164
{
169165
type: 'Control',
170-
scope: '#/properties/Id',
166+
scope: '#/properties/Id', // Changed from #/items/properties/Id
171167
},
172168
{
173169
type: 'Control',
174-
scope: '#/properties/ProjectorMode',
170+
scope: '#/properties/ProjectorMode', // Changed from #/items/properties/ProjectorMode
175171
},
176172
],
177173
},
@@ -190,7 +186,6 @@ const sceneConfigUiSchema = {
190186
},
191187
],
192188
},
193-
// Scene Features
194189
{
195190
type: 'Group',
196191
label: 'Scene Features',
@@ -231,7 +226,6 @@ const sceneConfigUiSchema = {
231226
},
232227
],
233228
},
234-
// Layouts
235229
{
236230
type: 'Control',
237231
scope: '#/properties/Layouts',
@@ -279,20 +273,22 @@ const sceneConfigUiSchema = {
279273

280274
interface SceneConfigurationSectionProps {
281275
data: Scene[];
282-
onChange: (event: { data: Scene[]; errors?: ValidationError[] }) => void;
276+
onChange: (event: {
277+
data: Scene[]; // Changed from { Scenes: Scene[] }
278+
errors?: ValidationError[];
279+
}) => void;
283280
}
284281

285282
export const SceneConfigurationSection: React.FC<
286283
SceneConfigurationSectionProps
287284
> = ({ data, onChange }) => {
288-
// Validation helper for unique IDs
285+
// Validate unique IDs, root scene, layouts, etc.
289286
const validateUniqueIds = (scenes: Scene[]): ValidationError[] => {
290287
const errors: ValidationError[] = [];
291288
const sceneIds = new Set<string>();
292289
const layoutIds = new Set<string>();
293290

294291
scenes.forEach((scene, sceneIndex) => {
295-
// Check scene ID uniqueness
296292
if (scene.Id) {
297293
if (sceneIds.has(scene.Id)) {
298294
errors.push({
@@ -303,7 +299,6 @@ export const SceneConfigurationSection: React.FC<
303299
sceneIds.add(scene.Id);
304300
}
305301

306-
// Check layout ID uniqueness within scene
307302
scene.Layouts?.forEach((layout, layoutIndex) => {
308303
if (layout.Id) {
309304
if (layoutIds.has(layout.Id)) {
@@ -320,15 +315,12 @@ export const SceneConfigurationSection: React.FC<
320315
return errors;
321316
};
322317

323-
// Custom validation
324-
const validate = (scenes: Scene[]): ValidationError[] => {
318+
const validateScenes = (scenes: Scene[]): ValidationError[] => {
325319
const errors: ValidationError[] = [];
326-
327-
// Add unique ID validation
328320
errors.push(...validateUniqueIds(scenes));
329321

330-
// Check for root scene
331-
const rootScenes = scenes.filter(scene => scene.IsRoot);
322+
// Exactly one root scene required
323+
const rootScenes = scenes.filter(s => s.IsRoot);
332324
if (rootScenes.length === 0) {
333325
errors.push({
334326
path: 'Scenes',
@@ -341,9 +333,8 @@ export const SceneConfigurationSection: React.FC<
341333
});
342334
}
343335

344-
// Validate each scene
336+
// Each scene must have at least one layout
345337
scenes.forEach((scene, index) => {
346-
// Validate required layouts
347338
if (!scene.Layouts || scene.Layouts.length === 0) {
348339
errors.push({
349340
path: `Scenes[${index}].Layouts`,
@@ -366,24 +357,16 @@ export const SceneConfigurationSection: React.FC<
366357
return errors;
367358
};
368359

369-
const handleChange = (event: {
370-
data: { Scenes: Scene[] };
371-
errors: any[];
372-
}) => {
373-
const customErrors = validate(event.data.Scenes);
374-
360+
const handleChange = (event: { data: any; errors: any[] }) => {
361+
const customErrors = validateScenes(event.data.Scenes);
375362
onChange({
376363
data: event.data.Scenes,
377364
errors: [...(event.errors || []), ...customErrors],
378365
});
379366
};
380367

381-
const formData = useMemo(
382-
() => ({
383-
Scenes: data || [],
384-
}),
385-
[data],
386-
);
368+
// Provide the formData as { Scenes: [...] } since schema expects Scenes to be a property of an object
369+
const formData = useMemo(() => ({ Scenes: data || [] }), [data]);
387370

388371
return (
389372
<div className="space-y-6">
@@ -392,7 +375,6 @@ export const SceneConfigurationSection: React.FC<
392375
Scene Configuration
393376
</h2>
394377

395-
{/* Quick summary */}
396378
<Alert className="mb-4">
397379
<AlertDescription>
398380
{`Current configuration: ${data.length} scene${data.length !== 1 ? 's' : ''}`}
@@ -401,6 +383,10 @@ export const SceneConfigurationSection: React.FC<
401383
</AlertDescription>
402384
</Alert>
403385

386+
{/*
387+
By using the updated scopes (#/items/properties/...) in the uischema,
388+
JsonForms knows how to render the Scenes array and its items properly.
389+
*/}
404390
<JsonForms
405391
schema={sceneConfigSchema}
406392
uischema={sceneConfigUiSchema}
@@ -411,7 +397,6 @@ export const SceneConfigurationSection: React.FC<
411397
/>
412398
</div>
413399

414-
{/* Help Section */}
415400
<div className="bg-white rounded-lg shadow p-6">
416401
<h3 className="font-medium text-gray-900 mb-2">
417402
Configuration Guidelines
@@ -424,7 +409,7 @@ export const SceneConfigurationSection: React.FC<
424409
<li>Background transparency must be between 0 and 1</li>
425410
<li>
426411
ProjectorMode determines how content is displayed:
427-
<ul className="ml-6 mt-1">
412+
<ul className="ml-6 mt-1 list-disc">
428413
<li>Meet: Standard meeting view</li>
429414
<li>Split: Divided screen layout</li>
430415
<li>Focus: Emphasized content view</li>

src/components/JsonFormsDemo.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,14 @@ function JsonFormsDemo({
127127
return (
128128
<SceneConfigurationSection
129129
data={data.Scenes || []}
130-
onChange={event =>
131-
handleSectionChange({ Scenes: event.data }, event.errors)
132-
}
130+
onChange={event => {
131+
handleSectionChange(
132+
{
133+
Scenes: event.data, // event.data is already Scene[]
134+
},
135+
event.errors,
136+
);
137+
}}
133138
/>
134139
);
135140

0 commit comments

Comments
 (0)