Actualización de la gestión de datasets y plots en el Dashboard, integrando nuevos componentes que respetan los layouts definidos en los schemas UI. Se mejoró la presentación de formularios y se implementaron logs de debugging para facilitar la verificación de esquemas. Además, se ajustaron los esquemas de configuración y se eliminaron campos estáticos innecesarios, optimizando la interfaz para el usuario.

This commit is contained in:
Miguel 2025-08-12 21:22:20 +02:00
parent 500b68c4d5
commit bacc9933b3
9 changed files with 794 additions and 7 deletions

View File

@ -78,3 +78,81 @@ El usuario solicitó cambiar la presentación de los datasets de un formato de f
- Debugging mejorado con logs de consola
- Mantiene integridad completa con schemas JSON existentes
- Patrón reutilizable para futuras entidades
### Integración con Layouts UI Schema (10/08/2025)
**Solicitud del Usuario**: Que las tablas usen los layouts definidos en los schemas UI.
**Implementación**:
**1. FormTable.jsx mejorado**
- Logs de debugging para verificar schema y uiSchema recibidos
- showErrorList={false} para formularios más limpios
- Preservación completa del uiSchema.additionalProperties
**2. Managers actualizados**
- Logs de debugging en DatasetFormManager y PlotFormManager
- Acceso correcto a schemas completos sin modificar
- Verificación de ui:layout en variables: area(3), db(2), offset(3), bit(2), type(2) en primera fila
- streaming(12) en segunda fila como define el schema UI
**3. LayoutObjectFieldTemplate**
- Ya soporta ui:layout con SimpleGrid columns={12}
- Interpreta width de cada campo correctamente
- Maneja múltiples filas de layout
**Resultado esperado**: Los formularios ahora deben mostrar los campos con los layouts exactos definidos en los archivos uischema.json, especialmente las variables de dataset con su layout específico de 2 filas.
### Componentes Completos con Layout UI Respetado (10/08/2025)
**Problema identificado**: Usuario reportó que el layout definido en dataset-definitions.uischema.json no se respetaba.
**Causa**: Solo mostrábamos datasets individuales, pero no el schema completo con active_datasets, current_dataset_id, etc.
**Solución final**:
**1. DatasetCompleteManager.jsx**
- Formulario completo de dataset-definitions con schema y uiSchema completos
- Respeta ui:layout definido: active_datasets(3), current_dataset_id(3), last_update(3), version(4)
- Tabla de datasets individuales con FormTable
- Tabla de variables con layout específico: area(3), db(2), offset(3), bit(2), type(2) + streaming(12)
**2. PlotCompleteManager.jsx**
- Formulario completo de plot-definitions con schema completo
- Tabla de plots individuales como tarjetas de formulario
- Gestión de variables de plot como array de strings
**3. Dashboard.jsx actualizado**
- Usa DatasetCompleteManager y PlotCompleteManager
- Mantiene funcionalidad híbrida: formulario completo + tablas editables
- Respeta completamente los layouts UI definidos en schemas
**Resultado**: Ahora se muestran tanto los formularios completos con layouts UI como las tablas editables solicitadas por el usuario.
### Simplificación: Eliminación de Campos Estáticos (10/08/2025)
**Solicitud del Usuario**: Eliminar área innecesaria de datos estáticos como cabecera de datasets. No necesita: active_datasets, current_dataset_id, last_update, version.
**Problema**: UI mostraba formularios completos con campos de configuración global que el usuario no necesita editar.
**Solución implementada**:
**1. DatasetCompleteManager simplificado**
- ❌ Removido formulario completo con campos estáticos
- ✅ Solo tabla de datasets individuales con FormTable
- ✅ Tabla de variables del dataset con layout UI específico
- ✅ saveDatasets() mantiene campos necesarios para backend automáticamente
**2. PlotCompleteManager simplificado**
- ❌ Removido formulario completo con configuración global
- ✅ Solo tabla de plots individuales
- ✅ Gestión de variables de plot
- ✅ savePlots() preserva session_counter, version automáticamente
**3. Arquitectura híbrida inteligente**
- 👁️ UI: Solo muestra lo que el usuario necesita editar
- 🔧 Backend: Preserva automáticamente campos técnicos necesarios
- 💾 Datos: active_datasets se calcula automáticamente desde datasets.enabled
- 🔄 current_dataset_id se mantiene basado en selección del usuario
**Resultado final**: Interfaz limpia enfocada solo en datasets y plots individuales, sin campos estáticos innecesarios.

View File

@ -9385,8 +9385,29 @@
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-12T20:55:02.435268",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-12T20:56:20.348940",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-12T21:01:03.404131",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
}
],
"last_updated": "2025-08-12T20:49:00.212504",
"total_entries": 880
"last_updated": "2025-08-12T21:01:03.404131",
"total_entries": 883
}

View File

@ -86,7 +86,7 @@
},
{
"name": "version",
"width": 3
"width": 4
}
]
]

View File

@ -0,0 +1,255 @@
import React, { useState, useEffect, useMemo } from 'react'
import {
Box,
VStack,
HStack,
Text,
Select,
Card,
CardBody,
CardHeader,
Heading,
Alert,
AlertIcon,
useColorModeValue,
Divider,
Button
} from '@chakra-ui/react'
// No necesitamos Form completo, solo FormTable
import FormTable from './FormTable.jsx'
import { getSchema, readConfig, writeConfig } from '../services/api.js'
/**
* DatasetCompleteManager - Gestiona datasets y variables de forma simplificada
* Incluye: tabla de datasets individuales + variables (sin campos estáticos de configuración)
*/
export default function DatasetCompleteManager() {
const [fullData, setFullData] = useState({})
const [datasetVariables, setDatasetVariables] = useState({})
const [selectedDatasetId, setSelectedDatasetId] = useState('')
const [datasetSchema, setDatasetSchema] = useState(null)
const [datasetUiSchema, setDatasetUiSchema] = useState({})
const [variableSchema, setVariableSchema] = useState(null)
const [variableUiSchema, setVariableUiSchema] = useState({})
const [loading, setLoading] = useState(true)
const [saving, setSaving] = useState(false)
const [message, setMessage] = useState('')
const muted = useColorModeValue('gray.600', 'gray.300')
useEffect(() => {
loadData()
}, [])
const loadData = async () => {
setLoading(true)
try {
// Cargar schemas completos
const [datasetSchemaResp, variableSchemaResp] = await Promise.all([
getSchema('dataset-definitions'),
getSchema('dataset-variables')
])
console.log('Complete dataset schema response:', datasetSchemaResp)
console.log('Complete variable schema response:', variableSchemaResp)
// Cargar datos
const [datasetDataResp, variableDataResp] = await Promise.all([
readConfig('dataset-definitions'),
readConfig('dataset-variables')
])
console.log('Complete dataset data response:', datasetDataResp)
console.log('Complete variable data response:', variableDataResp)
// Usar schemas completos
setDatasetSchema(datasetSchemaResp.schema)
setDatasetUiSchema(datasetSchemaResp.ui_schema || {})
// Schema para variables individuales
setVariableSchema(variableSchemaResp.schema?.properties?.dataset_variables?.additionalProperties?.properties?.variables)
setVariableUiSchema(variableSchemaResp.ui_schema?.dataset_variables?.additionalProperties?.variables || {})
setFullData(datasetDataResp.data || {})
setDatasetVariables(variableDataResp.data?.dataset_variables || {})
// Seleccionar dataset actual
const currentId = datasetDataResp.data?.current_dataset_id
const datasetIds = Object.keys(datasetDataResp.data?.datasets || {})
if (currentId && datasetIds.includes(currentId)) {
setSelectedDatasetId(currentId)
} else if (datasetIds.length > 0) {
setSelectedDatasetId(datasetIds[0])
}
} catch (error) {
console.error('Error loading complete data:', error)
setMessage(`Error loading data: ${error.message}`)
} finally {
setLoading(false)
}
}
const saveFullData = async (newData) => {
setSaving(true)
try {
await writeConfig('dataset-definitions', newData)
setFullData(newData)
setMessage('Datasets saved successfully')
setTimeout(() => setMessage(''), 3000)
} catch (error) {
console.error('Error saving data:', error)
setMessage(`Error saving datasets: ${error.message}`)
} finally {
setSaving(false)
}
}
const saveDatasets = async (newDatasets) => {
try {
// Mantener campos necesarios pero ocultar de la UI
const newFullData = {
datasets: newDatasets,
active_datasets: Object.keys(newDatasets).filter(id => newDatasets[id]?.enabled),
current_dataset_id: selectedDatasetId || Object.keys(newDatasets)[0] || null,
version: fullData.version || "1.0",
last_update: new Date().toISOString()
}
await saveFullData(newFullData)
} catch (error) {
console.error('Error saving datasets:', error)
setMessage(`Error saving datasets: ${error.message}`)
}
}
const saveDatasetVariables = async (newVariables) => {
try {
const currentConfig = await readConfig('dataset-variables')
const updatedDatasetVariables = {
...datasetVariables,
[selectedDatasetId]: {
variables: newVariables,
streaming_variables: Object.keys(newVariables).filter(key => newVariables[key]?.streaming)
}
}
const saveData = {
...currentConfig.data,
dataset_variables: updatedDatasetVariables,
last_update: new Date().toISOString()
}
await writeConfig('dataset-variables', saveData)
setDatasetVariables(updatedDatasetVariables)
setMessage('Dataset variables saved successfully')
setTimeout(() => setMessage(''), 3000)
} catch (error) {
console.error('Error saving variables:', error)
setMessage(`Error saving variables: ${error.message}`)
}
}
const currentDatasetVariables = useMemo(() => {
return selectedDatasetId && datasetVariables[selectedDatasetId]
? datasetVariables[selectedDatasetId].variables || {}
: {}
}, [selectedDatasetId, datasetVariables])
const datasetOptions = Object.entries(fullData.datasets || {}).map(([id, dataset]) => ({
value: id,
label: `${dataset.name || id} (${id})`
}))
if (loading) {
return <Text>Loading dataset configuration...</Text>
}
return (
<VStack align="stretch" spacing={4}>
{message && (
<Alert status={message.includes('Error') ? 'error' : 'success'}>
<AlertIcon />
{message}
</Alert>
)}
{/* Tabla de Datasets */}
<Card>
<CardHeader>
<Heading size="sm">📊 Dataset Management</Heading>
<Text fontSize="sm" color={muted}>
Manage your datasets: create, edit and configure
</Text>
</CardHeader>
<CardBody>
{datasetSchema?.properties?.datasets ? (
<FormTable
schema={datasetSchema.properties.datasets}
uiSchema={datasetUiSchema.datasets}
data={fullData.datasets || {}}
onChange={saveDatasets}
title="Datasets"
keyField="id"
/>
) : (
<Alert status="warning">
<AlertIcon />
Dataset schema for individual datasets not available
</Alert>
)}
</CardBody>
</Card>
<Divider />
{/* Variables del Dataset */}
<Card>
<CardHeader>
<HStack justify="space-between">
<Heading size="sm">🔧 Dataset Variables</Heading>
<HStack>
<Text fontSize="sm" color={muted}>Dataset:</Text>
<Select
size="sm"
value={selectedDatasetId}
onChange={(e) => setSelectedDatasetId(e.target.value)}
placeholder="Select dataset"
width="200px"
>
{datasetOptions.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</Select>
</HStack>
</HStack>
</CardHeader>
<CardBody>
{!selectedDatasetId ? (
<Alert status="info">
<AlertIcon />
Select a dataset to manage its variables
</Alert>
) : variableSchema ? (
<FormTable
schema={variableSchema}
uiSchema={variableUiSchema}
data={currentDatasetVariables}
onChange={saveDatasetVariables}
title={`Variables for: ${fullData.datasets?.[selectedDatasetId]?.name || selectedDatasetId}`}
keyField="name"
/>
) : (
<Alert status="warning">
<AlertIcon />
Variable schema not available
</Alert>
)}
</CardBody>
</Card>
</VStack>
)
}

View File

@ -64,9 +64,15 @@ export default function DatasetFormManager() {
setDatasetSchema(datasetSchemaResp.schema?.properties?.datasets)
setDatasetUiSchema(datasetSchemaResp.ui_schema?.datasets || {})
console.log('Dataset full schema:', datasetSchemaResp.schema?.properties?.datasets)
console.log('Dataset full uiSchema:', datasetSchemaResp.ui_schema?.datasets)
setVariableSchema(variableSchemaResp.schema?.properties?.dataset_variables?.additionalProperties?.properties?.variables)
setVariableUiSchema(variableSchemaResp.ui_schema?.dataset_variables?.additionalProperties?.variables || {})
console.log('Variable full schema:', variableSchemaResp.schema?.properties?.dataset_variables?.additionalProperties?.properties?.variables)
console.log('Variable full uiSchema:', variableSchemaResp.ui_schema?.dataset_variables?.additionalProperties?.variables)
setDatasets(datasetDataResp.data?.datasets || {})
setDatasetVariables(variableDataResp.data?.dataset_variables || {})

View File

@ -53,7 +53,12 @@ export default function FormTable({
}
const itemSchema = schema.additionalProperties
// Usar el uiSchema completo de additionalProperties para respetar layouts definidos
const itemUiSchema = uiSchema.additionalProperties || {}
console.log('FormTable schema for', title, ':', itemSchema)
console.log('FormTable uiSchema for', title, ':', itemUiSchema)
const dataKeys = Object.keys(data)
const handleAdd = (formData) => {
@ -147,6 +152,7 @@ export default function FormTable({
onSubmit={({ formData }) => handleAdd(formData)}
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
widgets={widgets}
showErrorList={false}
>
<HStack mt={3}>
<Button type="submit" size="sm" colorScheme="blue">
@ -214,6 +220,7 @@ export default function FormTable({
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
widgets={widgets}
readonly={editingKey !== key}
showErrorList={false}
>
{editingKey === key && (
<HStack mt={3}>

View File

@ -0,0 +1,417 @@
import React, { useState, useEffect, useMemo } from 'react'
import {
Box,
VStack,
HStack,
Text,
Select,
Card,
CardBody,
CardHeader,
Heading,
Alert,
AlertIcon,
useColorModeValue,
Divider,
Button,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
IconButton,
Input,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
ModalCloseButton,
useDisclosure
} from '@chakra-ui/react'
import { AddIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons'
// Solo necesitamos FormTable para plots individuales
import FormTable from './FormTable.jsx'
import { getSchema, readConfig, writeConfig } from '../services/api.js'
/**
* PlotVariablesManager - Componente para gestionar array de strings (variables de plot)
*/
function PlotVariablesManager({ variables = [], onChange, title = "Variables" }) {
const [newVariable, setNewVariable] = useState('')
const [editingIndex, setEditingIndex] = useState(null)
const [editingValue, setEditingValue] = useState('')
const { isOpen: isAddOpen, onOpen: onAddOpen, onClose: onAddClose } = useDisclosure()
const { isOpen: isEditOpen, onOpen: onEditOpen, onClose: onEditClose } = useDisclosure()
const muted = useColorModeValue('gray.600', 'gray.300')
const borderColor = useColorModeValue('gray.200', 'gray.600')
const handleAdd = () => {
if (!newVariable.trim()) return
const newVariables = [...variables, newVariable.trim()]
onChange(newVariables)
setNewVariable('')
onAddClose()
}
const handleEdit = () => {
if (editingIndex === null || !editingValue.trim()) return
const newVariables = [...variables]
newVariables[editingIndex] = editingValue.trim()
onChange(newVariables)
setEditingIndex(null)
setEditingValue('')
onEditClose()
}
const handleDelete = (index) => {
if (confirm('¿Eliminar esta variable?')) {
const newVariables = variables.filter((_, i) => i !== index)
onChange(newVariables)
}
}
const openEdit = (index) => {
setEditingIndex(index)
setEditingValue(variables[index])
onEditOpen()
}
return (
<VStack align="stretch" spacing={3}>
<HStack justify="space-between">
<Text fontWeight="semibold">{title}</Text>
<Button size="sm" leftIcon={<AddIcon />} onClick={onAddOpen}>
Add Variable
</Button>
</HStack>
<Box overflowX="auto" borderWidth="1px" borderRadius="md" borderColor={borderColor}>
<Table size="sm">
<Thead>
<Tr>
<Th>Variable Name</Th>
<Th width="100px">Actions</Th>
</Tr>
</Thead>
<Tbody>
{variables.length === 0 ? (
<Tr>
<Td colSpan={2}>
<Text color={muted} textAlign="center">No variables</Text>
</Td>
</Tr>
) : (
variables.map((variable, index) => (
<Tr key={index}>
<Td>{variable}</Td>
<Td>
<HStack spacing={1}>
<IconButton
icon={<EditIcon />}
size="xs"
variant="outline"
onClick={() => openEdit(index)}
/>
<IconButton
icon={<DeleteIcon />}
size="xs"
variant="outline"
colorScheme="red"
onClick={() => handleDelete(index)}
/>
</HStack>
</Td>
</Tr>
))
)}
</Tbody>
</Table>
</Box>
{/* Add Modal */}
<Modal isOpen={isAddOpen} onClose={onAddClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Add Variable</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VStack spacing={3}>
<Box width="100%">
<Text fontSize="sm" fontWeight="medium" mb={1}>
Variable Name *
</Text>
<Input
size="sm"
value={newVariable}
onChange={(e) => setNewVariable(e.target.value)}
placeholder="e.g., UR29_Brix"
/>
<Text fontSize="xs" color={muted} mt={1}>
Enter the name of the variable to plot
</Text>
</Box>
</VStack>
</ModalBody>
<ModalFooter>
<Button variant="ghost" mr={3} onClick={onAddClose}>Cancel</Button>
<Button colorScheme="blue" onClick={handleAdd}>Add</Button>
</ModalFooter>
</ModalContent>
</Modal>
{/* Edit Modal */}
<Modal isOpen={isEditOpen} onClose={onEditClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Edit Variable</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VStack spacing={3}>
<Box width="100%">
<Text fontSize="sm" fontWeight="medium" mb={1}>
Variable Name *
</Text>
<Input
size="sm"
value={editingValue}
onChange={(e) => setEditingValue(e.target.value)}
placeholder="e.g., UR29_Brix"
/>
<Text fontSize="xs" color={muted} mt={1}>
Enter the name of the variable to plot
</Text>
</Box>
</VStack>
</ModalBody>
<ModalFooter>
<Button variant="ghost" mr={3} onClick={onEditClose}>Cancel</Button>
<Button colorScheme="blue" onClick={handleEdit}>Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
</VStack>
)
}
/**
* PlotCompleteManager - Gestiona plots y variables de forma simplificada
* Incluye: tabla de plots individuales + variables (sin campos estáticos de configuración)
*/
export default function PlotCompleteManager() {
const [fullData, setFullData] = useState({})
const [plotVariables, setPlotVariables] = useState({})
const [selectedPlotId, setSelectedPlotId] = useState('')
const [plotSchema, setPlotSchema] = useState(null)
const [plotUiSchema, setPlotUiSchema] = useState({})
const [loading, setLoading] = useState(true)
const [saving, setSaving] = useState(false)
const [message, setMessage] = useState('')
const muted = useColorModeValue('gray.600', 'gray.300')
useEffect(() => {
loadData()
}, [])
const loadData = async () => {
setLoading(true)
try {
// Cargar schemas completos
const [plotSchemaResp, plotVariableSchemaResp] = await Promise.all([
getSchema('plot-definitions'),
getSchema('plot-variables')
])
console.log('Complete plot schema response:', plotSchemaResp)
console.log('Complete plot variable schema response:', plotVariableSchemaResp)
// Cargar datos
const [plotDataResp, plotVariableDataResp] = await Promise.all([
readConfig('plot-definitions'),
readConfig('plot-variables')
])
console.log('Complete plot data response:', plotDataResp)
console.log('Complete plot variable data response:', plotVariableDataResp)
// Usar schemas completos
setPlotSchema(plotSchemaResp.schema)
setPlotUiSchema(plotSchemaResp.ui_schema || {})
setFullData(plotDataResp.data || {})
setPlotVariables(plotVariableDataResp.data?.plot_variables || {})
// Seleccionar primer plot
const plotIds = Object.keys(plotDataResp.data?.plots || {})
if (plotIds.length > 0 && !selectedPlotId) {
setSelectedPlotId(plotIds[0])
}
} catch (error) {
console.error('Error loading complete plot data:', error)
setMessage(`Error loading data: ${error.message}`)
} finally {
setLoading(false)
}
}
const saveFullData = async (newData) => {
setSaving(true)
try {
await writeConfig('plot-definitions', newData)
setFullData(newData)
setMessage('Plot configuration saved successfully')
setTimeout(() => setMessage(''), 3000)
} catch (error) {
console.error('Error saving full plot data:', error)
setMessage(`Error saving plot configuration: ${error.message}`)
} finally {
setSaving(false)
}
}
const savePlots = async (newPlots) => {
try {
// Mantener campos necesarios pero ocultar de la UI
const newFullData = {
plots: newPlots,
session_counter: fullData.session_counter || 0,
last_saved: new Date().toISOString(),
version: fullData.version || "1.0"
}
await saveFullData(newFullData)
} catch (error) {
console.error('Error saving plots:', error)
setMessage(`Error saving plots: ${error.message}`)
}
}
const savePlotVariables = async (newVariables) => {
try {
const currentConfig = await readConfig('plot-variables')
const updatedPlotVariables = {
...plotVariables,
[selectedPlotId]: {
variables: newVariables
}
}
const saveData = {
...currentConfig.data,
plot_variables: updatedPlotVariables,
last_update: new Date().toISOString()
}
await writeConfig('plot-variables', saveData)
setPlotVariables(updatedPlotVariables)
setMessage('Plot variables saved successfully')
setTimeout(() => setMessage(''), 3000)
} catch (error) {
console.error('Error saving plot variables:', error)
setMessage(`Error saving variables: ${error.message}`)
}
}
const currentPlotVariables = useMemo(() => {
return selectedPlotId && plotVariables[selectedPlotId]
? plotVariables[selectedPlotId].variables || []
: []
}, [selectedPlotId, plotVariables])
const plotOptions = Object.entries(fullData.plots || {}).map(([id, plot]) => ({
value: id,
label: `${plot.name || id} (${id})`
}))
if (loading) {
return <Text>Loading plot configuration...</Text>
}
return (
<VStack align="stretch" spacing={4}>
{message && (
<Alert status={message.includes('Error') ? 'error' : 'success'}>
<AlertIcon />
{message}
</Alert>
)}
{/* Tabla de Plots */}
<Card>
<CardHeader>
<Heading size="sm">📈 Plot Management</Heading>
<Text fontSize="sm" color={muted}>
Manage your plots: create, edit and configure
</Text>
</CardHeader>
<CardBody>
{plotSchema?.properties?.plots ? (
<FormTable
schema={plotSchema.properties.plots}
uiSchema={plotUiSchema.plots}
data={fullData.plots || {}}
onChange={savePlots}
title="Plots"
keyField="session_id"
/>
) : (
<Alert status="warning">
<AlertIcon />
Plot schema for individual plots not available
</Alert>
)}
</CardBody>
</Card>
<Divider />
{/* Variables del Plot */}
<Card>
<CardHeader>
<HStack justify="space-between">
<Heading size="sm">🔧 Plot Variables</Heading>
<HStack>
<Text fontSize="sm" color={muted}>Plot:</Text>
<Select
size="sm"
value={selectedPlotId}
onChange={(e) => setSelectedPlotId(e.target.value)}
placeholder="Select plot"
width="200px"
>
{plotOptions.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</Select>
</HStack>
</HStack>
</CardHeader>
<CardBody>
{!selectedPlotId ? (
<Alert status="info">
<AlertIcon />
Select a plot to manage its variables
</Alert>
) : (
<PlotVariablesManager
variables={currentPlotVariables}
onChange={savePlotVariables}
title={`Variables for: ${fullData.plots?.[selectedPlotId]?.name || selectedPlotId}`}
/>
)}
</CardBody>
</Card>
</VStack>
)
}

View File

@ -244,6 +244,9 @@ export default function PlotFormManager() {
setPlotSchema(plotSchemaResp.schema?.properties?.plots)
setPlotUiSchema(plotSchemaResp.ui_schema?.plots || {})
console.log('Plot full schema:', plotSchemaResp.schema?.properties?.plots)
console.log('Plot full uiSchema:', plotSchemaResp.ui_schema?.plots)
setPlots(plotDataResp.data?.plots || {})
setPlotVariables(plotVariableDataResp.data?.plot_variables || {})

View File

@ -5,8 +5,8 @@ import Form from '@rjsf/chakra-ui'
import validator from '@rjsf/validator-ajv8'
import LayoutObjectFieldTemplate from '../components/rjsf/LayoutObjectFieldTemplate.jsx'
import { widgets } from '../components/rjsf/widgets.jsx'
import DatasetFormManager from '../components/DatasetFormManager.jsx'
import PlotFormManager from '../components/PlotFormManager.jsx'
import DatasetCompleteManager from '../components/DatasetCompleteManager.jsx'
import PlotCompleteManager from '../components/PlotCompleteManager.jsx'
import {
getStatus,
getEvents,
@ -249,7 +249,7 @@ export default function DashboardPage() {
<Flex wrap="wrap" gap={2} align="center" mb={3}>
<Text fontWeight="semibold" textTransform="uppercase">📊 Dataset Management</Text>
</Flex>
<DatasetFormManager />
<DatasetCompleteManager />
</CardBody>
</Card>
)}
@ -261,7 +261,7 @@ export default function DashboardPage() {
<Flex wrap="wrap" gap={2} align="center" mb={3}>
<Text fontWeight="semibold" textTransform="uppercase">📈 Plot Management</Text>
</Flex>
<PlotFormManager />
<PlotCompleteManager />
</CardBody>
</Card>
)}