SCGR commited on
Commit
0bd8b79
·
1 Parent(s): 9579cfb

dynamic json schema

Browse files
frontend/src/pages/AdminPage/AdminPage.tsx CHANGED
@@ -36,6 +36,14 @@ interface ImageTypeData {
36
  label: string;
37
  }
38
 
 
 
 
 
 
 
 
 
39
  export default function AdminPage() {
40
  const { isAuthenticated, isLoading, login, logout } = useAdmin();
41
  const [password, setPassword] = useState('');
@@ -51,6 +59,17 @@ export default function AdminPage() {
51
 
52
  const [imageTypes, setImageTypes] = useState<ImageTypeData[]>([]);
53
 
 
 
 
 
 
 
 
 
 
 
 
54
  // Prompt management state
55
  const [showEditPromptForm, setShowEditPromptForm] = useState(false);
56
  const [showAddPromptForm, setShowAddPromptForm] = useState(false);
@@ -161,13 +180,32 @@ export default function AdminPage() {
161
  });
162
  }, []);
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  useEffect(() => {
165
  if (isAuthenticated) {
166
  fetchModels();
167
  fetchPrompts();
168
  fetchImageTypes();
 
169
  }
170
- }, [isAuthenticated, fetchModels, fetchPrompts, fetchImageTypes]);
171
 
172
 
173
 
@@ -282,6 +320,66 @@ export default function AdminPage() {
282
  }
283
  };
284
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  const toggleModelAvailability = async (modelCode: string, currentStatus: boolean) => {
286
  try {
287
  const response = await fetch(`/api/models/${modelCode}/toggle`, {
@@ -1080,6 +1178,64 @@ Model "${newModelData.label}" added successfully!
1080
  </div>
1081
  </Container>
1082
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1083
  {/* Utilities Section */}
1084
  <Container
1085
  heading="Utilities"
@@ -1117,50 +1273,6 @@ Model "${newModelData.label}" added successfully!
1117
  Test Connection
1118
  </Button>
1119
 
1120
- <Button
1121
- name="view-schemas"
1122
- variant="secondary"
1123
- onClick={() => {
1124
- fetch('/api/schemas', {
1125
- headers: {
1126
- 'Authorization': `Bearer ${localStorage.getItem('adminToken')}`
1127
- }
1128
- })
1129
- .then(r => r.json())
1130
- .then(data => {
1131
- console.log('Schemas Response:', data);
1132
-
1133
- let results = '';
1134
- let title = 'Schemas Response';
1135
-
1136
- if (data && Array.isArray(data)) {
1137
- results = `Found ${data.length} schemas:\n\n`;
1138
- data.forEach((schema, index) => {
1139
- results += `=== Schema ${index + 1} ===\n`;
1140
- results += JSON.stringify(schema, null, 2);
1141
- results += '\n\n';
1142
- });
1143
- } else if (data && typeof data === 'object') {
1144
- results = `Prompts Response:\n\nResponse type: ${typeof data}\nKeys: ${Object.keys(data).join(', ')}\n\nRaw data:\n${JSON.stringify(data, null, 2)}`;
1145
- } else {
1146
- results = `Prompts Response:\n\nUnexpected data type: ${typeof data}\nValue: ${data}`;
1147
- }
1148
-
1149
- setTestResults(results);
1150
- setTestResultsTitle(title);
1151
- setShowTestResultsModal(true);
1152
- })
1153
- .catch((error) => {
1154
- console.error('Schemas Error:', error);
1155
- const results = `Failed to fetch prompts: ${error.message || 'Unknown error'}`;
1156
- setTestResults(results);
1157
- setTestResultsTitle('Schemas Error');
1158
- setShowTestResultsModal(true);
1159
- });
1160
- }}
1161
- >
1162
- View Schemas
1163
- </Button>
1164
  </div>
1165
  </Container>
1166
  </div>
@@ -1416,6 +1528,63 @@ Model "${newModelData.label}" added successfully!
1416
  </div>
1417
  </div>
1418
  )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1419
  </PageContainer>
1420
  );
1421
  }
 
36
  label: string;
37
  }
38
 
39
+ interface SchemaData {
40
+ schema_id: string;
41
+ title: string;
42
+ version: string;
43
+ created_at?: string;
44
+ schema: any;
45
+ }
46
+
47
  export default function AdminPage() {
48
  const { isAuthenticated, isLoading, login, logout } = useAdmin();
49
  const [password, setPassword] = useState('');
 
59
 
60
  const [imageTypes, setImageTypes] = useState<ImageTypeData[]>([]);
61
 
62
+ // Schema management state
63
+ const [availableSchemas, setAvailableSchemas] = useState<SchemaData[]>([]);
64
+ const [showEditSchemaForm, setShowEditSchemaForm] = useState(false);
65
+ const [editingSchema, setEditingSchema] = useState<SchemaData | null>(null);
66
+ const [newSchemaData, setNewSchemaData] = useState<SchemaData>({
67
+ schema_id: '',
68
+ title: '',
69
+ version: '',
70
+ schema: {}
71
+ });
72
+
73
  // Prompt management state
74
  const [showEditPromptForm, setShowEditPromptForm] = useState(false);
75
  const [showAddPromptForm, setShowAddPromptForm] = useState(false);
 
180
  });
181
  }, []);
182
 
183
+ const fetchSchemas = useCallback(() => {
184
+ console.log('=== fetchSchemas called ===');
185
+ fetch('/api/schemas', {
186
+ headers: {
187
+ 'Authorization': `Bearer ${localStorage.getItem('adminToken')}`
188
+ }
189
+ })
190
+ .then(r => r.json())
191
+ .then(schemasData => {
192
+ console.log('Schemas data received:', schemasData);
193
+ setAvailableSchemas(schemasData || []);
194
+ })
195
+ .catch((error) => {
196
+ console.error('Error fetching schemas:', error);
197
+ // Handle error silently
198
+ });
199
+ }, []);
200
+
201
  useEffect(() => {
202
  if (isAuthenticated) {
203
  fetchModels();
204
  fetchPrompts();
205
  fetchImageTypes();
206
+ fetchSchemas();
207
  }
208
+ }, [isAuthenticated, fetchModels, fetchPrompts, fetchImageTypes, fetchSchemas]);
209
 
210
 
211
 
 
320
  }
321
  };
322
 
323
+ // Schema management handlers
324
+ const handleEditSchema = (schema: SchemaData) => {
325
+ setEditingSchema(schema);
326
+ setNewSchemaData({
327
+ schema_id: schema.schema_id,
328
+ title: schema.title,
329
+ version: schema.version,
330
+ schema: schema.schema
331
+ });
332
+ setShowEditSchemaForm(true);
333
+ };
334
+
335
+ const handleSaveSchema = async () => {
336
+ try {
337
+ if (!editingSchema) {
338
+ alert('No schema selected for editing');
339
+ return;
340
+ }
341
+
342
+ const response = await fetch(`/api/schemas/${editingSchema.schema_id}`, {
343
+ method: 'PUT',
344
+ headers: {
345
+ 'Content-Type': 'application/json',
346
+ 'Authorization': `Bearer ${localStorage.getItem('adminToken')}`
347
+ },
348
+ body: JSON.stringify(newSchemaData),
349
+ });
350
+
351
+ if (response.ok) {
352
+ // Refresh schemas and close form
353
+ fetchSchemas();
354
+ setShowEditSchemaForm(false);
355
+ setEditingSchema(null);
356
+ setNewSchemaData({
357
+ schema_id: '',
358
+ title: '',
359
+ version: '',
360
+ schema: {}
361
+ });
362
+ } else {
363
+ const errorData = await response.json();
364
+ alert(`Failed to save schema: ${errorData.detail || 'Unknown error'}`);
365
+ }
366
+ } catch (error) {
367
+ console.error('Error saving schema:', error);
368
+ alert('Error saving schema');
369
+ }
370
+ };
371
+
372
+ const handleCancelSchema = () => {
373
+ setShowEditSchemaForm(false);
374
+ setEditingSchema(null);
375
+ setNewSchemaData({
376
+ schema_id: '',
377
+ title: '',
378
+ version: '',
379
+ schema: {}
380
+ });
381
+ };
382
+
383
  const toggleModelAvailability = async (modelCode: string, currentStatus: boolean) => {
384
  try {
385
  const response = await fetch(`/api/models/${modelCode}/toggle`, {
 
1178
  </div>
1179
  </Container>
1180
 
1181
+ {/* Schema Management Section */}
1182
+ <Container
1183
+ heading="Schema Management"
1184
+ headingLevel={2}
1185
+ withHeaderBorder
1186
+ withInternalPadding
1187
+ >
1188
+ <div className={styles.modelManagementArea}>
1189
+ <div className={styles.modelsTable}>
1190
+ <table>
1191
+ <thead>
1192
+ <tr>
1193
+ <th>Schema ID</th>
1194
+ <th>Schema Content</th>
1195
+ <th>Actions</th>
1196
+ </tr>
1197
+ </thead>
1198
+ <tbody>
1199
+ {availableSchemas
1200
+ .sort((a, b) => a.schema_id.localeCompare(b.schema_id))
1201
+ .map(schema => (
1202
+ <tr key={schema.schema_id}>
1203
+ <td className={styles.modelCode}>{schema.schema_id}</td>
1204
+ <td className={styles.promptLabel} style={{ maxWidth: '400px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
1205
+ {JSON.stringify(schema.schema)}
1206
+ </td>
1207
+ <td>
1208
+ <div className={styles.modelActions}>
1209
+ <Button
1210
+ name={`view-schema-${schema.schema_id}`}
1211
+ variant="secondary"
1212
+ size={1}
1213
+ onClick={() => {
1214
+ setTestResults(`=== Schema Details ===\nSchema ID: ${schema.schema_id}\n\nSchema Definition:\n${JSON.stringify(schema.schema, null, 2)}`);
1215
+ setTestResultsTitle(`Schema: ${schema.schema_id}`);
1216
+ setShowTestResultsModal(true);
1217
+ }}
1218
+ >
1219
+ View
1220
+ </Button>
1221
+ <Button
1222
+ name={`edit-schema-${schema.schema_id}`}
1223
+ variant="secondary"
1224
+ size={1}
1225
+ onClick={() => handleEditSchema(schema)}
1226
+ >
1227
+ Edit
1228
+ </Button>
1229
+ </div>
1230
+ </td>
1231
+ </tr>
1232
+ ))}
1233
+ </tbody>
1234
+ </table>
1235
+ </div>
1236
+ </div>
1237
+ </Container>
1238
+
1239
  {/* Utilities Section */}
1240
  <Container
1241
  heading="Utilities"
 
1273
  Test Connection
1274
  </Button>
1275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1276
  </div>
1277
  </Container>
1278
  </div>
 
1528
  </div>
1529
  </div>
1530
  )}
1531
+
1532
+ {/* Edit Schema Form Modal */}
1533
+ {showEditSchemaForm && (
1534
+ <div className={styles.modalOverlay} onClick={() => setShowEditSchemaForm(false)}>
1535
+ <div className={styles.modalContent} onClick={(e) => e.stopPropagation()}>
1536
+ <div className={styles.modalBody}>
1537
+ <h3 className={styles.modalTitle}>Edit Schema: {editingSchema?.schema_id}</h3>
1538
+ <div className={styles.modalForm}>
1539
+ <div className={styles.formField}>
1540
+ <label className={styles.formLabel}>Schema ID:</label>
1541
+ <TextInput
1542
+ name="schema-id"
1543
+ value={newSchemaData.schema_id}
1544
+ onChange={(value) => setNewSchemaData(prev => ({ ...prev, schema_id: value || '' }))}
1545
+ className={styles.formInput}
1546
+ disabled
1547
+ />
1548
+ </div>
1549
+ <div className={styles.formField}>
1550
+ <label className={styles.formLabel}>Schema Definition (JSON):</label>
1551
+ <textarea
1552
+ name="schema-definition"
1553
+ value={JSON.stringify(newSchemaData.schema, null, 2)}
1554
+ onChange={(e) => {
1555
+ try {
1556
+ const parsedSchema = JSON.parse(e.target.value);
1557
+ setNewSchemaData(prev => ({ ...prev, schema: parsedSchema }));
1558
+ } catch (error) {
1559
+ // Invalid JSON, don't update
1560
+ }
1561
+ }}
1562
+ className={`${styles.formInput} ${styles.textarea}`}
1563
+ rows={20}
1564
+ style={{ fontFamily: 'monospace' }}
1565
+ />
1566
+ </div>
1567
+ </div>
1568
+ <div className={styles.modalButtons}>
1569
+ <Button
1570
+ name="cancel-edit-schema"
1571
+ variant="tertiary"
1572
+ onClick={handleCancelSchema}
1573
+ >
1574
+ Cancel
1575
+ </Button>
1576
+ <Button
1577
+ name="save-schema"
1578
+ variant="primary"
1579
+ onClick={handleSaveSchema}
1580
+ >
1581
+ Save Changes
1582
+ </Button>
1583
+ </div>
1584
+ </div>
1585
+ </div>
1586
+ </div>
1587
+ )}
1588
  </PageContainer>
1589
  );
1590
  }