Enhance event logging in application_events.json and update last_updated and total_entries fields. Refactor PlotManager and Dashboard components to utilize schemaData and uiSchema, improving configuration management. Introduce custom widgets for RJSF, including a VariableSelectorWidget for dynamic variable selection.

This commit is contained in:
Miguel 2025-08-13 16:09:43 +02:00
parent 4af442e3e8
commit e6ccb19fd2
5 changed files with 136 additions and 31 deletions

View File

@ -10426,8 +10426,29 @@
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-13T15:49:35.843750",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-13T15:55:43.678603",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-13T16:02:51.706311",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
}
],
"last_updated": "2025-08-13T15:31:15.343148",
"total_entries": 988
"last_updated": "2025-08-13T16:02:51.706311",
"total_entries": 991
}

View File

@ -39,13 +39,14 @@ import {
} from '@chakra-ui/react'
import Form from '@rjsf/chakra-ui'
import validator from '@rjsf/validator-ajv8'
import { customWidgets } from './widgets/CustomWidgets'
import * as api from '../services/api'
// Pure RJSF Plot Manager Component
export default function PlotManager() {
const [plots, setPlots] = useState({})
const [plotsSchema, setPlotsSchema] = useState(null)
const [plotsVariablesSchema, setPlotsVariablesSchema] = useState(null)
const [plotsSchemaData, setPlotsSchemaData] = useState(null)
const [plotsVariablesSchemaData, setPlotsVariablesSchemaData] = useState(null)
const [plotsConfig, setPlotsConfig] = useState(null)
const [plotsVariablesConfig, setPlotsVariablesConfig] = useState(null)
const [loading, setLoading] = useState(true)
@ -68,8 +69,8 @@ export default function PlotManager() {
setLoading(true)
const [
plotsData,
plotsSchemaData,
plotsVariablesSchemaData,
plotsSchemaResponse,
plotsVariablesSchemaResponse,
plotsConfigData,
plotsVariablesConfigData
] = await Promise.all([
@ -81,8 +82,8 @@ export default function PlotManager() {
])
setPlots(plotsData?.plots || {})
setPlotsSchema(plotsSchemaData)
setPlotsVariablesSchema(plotsVariablesSchemaData)
setPlotsSchemaData(plotsSchemaResponse)
setPlotsVariablesSchemaData(plotsVariablesSchemaResponse)
setPlotsConfig(plotsConfigData)
setPlotsVariablesConfig(plotsVariablesConfigData)
} catch (error) {
@ -323,7 +324,7 @@ export default function PlotManager() {
<TabPanels>
<TabPanel p={0} pt={4}>
{plotsSchema && plotsConfig && (
{plotsSchemaData?.schema && plotsConfig && (
<Card bg={cardBg} borderColor={borderColor}>
<CardHeader>
<Heading size="md">Plot Session Definitions</Heading>
@ -333,9 +334,11 @@ export default function PlotManager() {
</CardHeader>
<CardBody>
<Form
schema={plotsSchema}
schema={plotsSchemaData.schema}
uiSchema={plotsSchemaData.uiSchema}
formData={plotsConfig}
validator={validator}
widgets={customWidgets}
onSubmit={({ formData }) => savePlotsConfig(formData)}
onChange={({ formData }) => setPlotsConfig(formData)}
>
@ -359,7 +362,7 @@ export default function PlotManager() {
</TabPanel>
<TabPanel p={0} pt={4}>
{plotsVariablesSchema && plotsVariablesConfig && (
{plotsVariablesSchemaData?.schema && plotsVariablesConfig && (
<Card bg={cardBg} borderColor={borderColor}>
<CardHeader>
<Heading size="md">Plot Variables Configuration</Heading>
@ -369,9 +372,11 @@ export default function PlotManager() {
</CardHeader>
<CardBody>
<Form
schema={plotsVariablesSchema}
schema={plotsVariablesSchemaData.schema}
uiSchema={plotsVariablesSchemaData.uiSchema}
formData={plotsVariablesConfig}
validator={validator}
widgets={customWidgets}
onSubmit={({ formData }) => savePlotsVariablesConfig(formData)}
onChange={({ formData }) => setPlotsVariablesConfig(formData)}
>

View File

@ -0,0 +1,69 @@
import React, { useState, useEffect } from 'react'
import { Select } from '@chakra-ui/react'
import * as api from '../../services/api'
// Custom Variable Selector Widget for RJSF
export function VariableSelectorWidget(props) {
const { value, onChange, options, placeholder, disabled, readonly } = props
const [variables, setVariables] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
const loadVariables = async () => {
try {
setLoading(true)
// Try to get variables from plot variables API
const plotVariables = await api.getPlotVariables()
// Extract the available_variables array from the response
if (plotVariables && plotVariables.available_variables && Array.isArray(plotVariables.available_variables)) {
setVariables(plotVariables.available_variables)
} else {
console.warn('Unexpected plot variables response format:', plotVariables)
setVariables([])
}
} catch (error) {
console.error('Failed to load variables:', error)
setVariables([])
} finally {
setLoading(false)
}
}
loadVariables()
}, [])
const handleChange = (event) => {
onChange(event.target.value === '' ? undefined : event.target.value)
}
if (loading) {
return (
<Select placeholder="Loading variables..." disabled>
<option value="">Loading...</option>
</Select>
)
}
return (
<Select
value={value || ''}
onChange={handleChange}
placeholder={placeholder || 'Select a variable...'}
disabled={disabled || readonly}
>
<option value="">-- Select Variable --</option>
{Array.isArray(variables) && variables.map((variable, index) => (
<option key={variable.name || index} value={variable.name || variable}>
{variable.display_name || variable.name || variable}
</option>
))}
</Select>
)
}
// Export widgets object for RJSF
export const customWidgets = {
VariableSelectorWidget
}
export default customWidgets

View File

@ -48,6 +48,7 @@ import {
import Form from '@rjsf/chakra-ui'
import validator from '@rjsf/validator-ajv8'
import PlotManager from '../components/PlotManager'
import { customWidgets } from '../components/widgets/CustomWidgets'
import * as api from '../services/api'
// Pure RJSF StatusBar Component
@ -254,11 +255,11 @@ function StatusBar({ status, onRefresh }) {
}
// Pure RJSF Configuration Panel
function ConfigurationPanel({ schemas, currentSchemaId, onSchemaChange, schema, formData, onFormChange, onSave, saving, message }) {
function ConfigurationPanel({ schemas, currentSchemaId, onSchemaChange, schemaData, formData, onFormChange, onSave, saving, message }) {
const cardBg = useColorModeValue('white', 'gray.700')
const borderColor = useColorModeValue('gray.200', 'gray.600')
if (!schema || !formData) {
if (!schemaData?.schema || !formData) {
return (
<Card bg={cardBg} borderColor={borderColor}>
<CardBody>
@ -275,7 +276,7 @@ function ConfigurationPanel({ schemas, currentSchemaId, onSchemaChange, schema,
<Box>
<Heading size="md">🔧 Configuration Editor</Heading>
<Text fontSize="sm" color="gray.500" mt={1}>
Pure RJSF configuration management
Pure RJSF configuration management with UI Schema layouts
</Text>
</Box>
<Spacer />
@ -301,9 +302,11 @@ function ConfigurationPanel({ schemas, currentSchemaId, onSchemaChange, schema,
</CardHeader>
<CardBody>
<Form
schema={schema}
schema={schemaData.schema}
uiSchema={schemaData.uiSchema}
formData={formData}
validator={validator}
widgets={customWidgets}
onChange={({ formData }) => onFormChange(formData)}
onSubmit={({ formData }) => onSave(formData)}
>
@ -330,15 +333,15 @@ function ConfigurationPanel({ schemas, currentSchemaId, onSchemaChange, schema,
function DatasetManager() {
const [datasetsConfig, setDatasetsConfig] = useState(null)
const [variablesConfig, setVariablesConfig] = useState(null)
const [datasetsSchema, setDatasetsSchema] = useState(null)
const [variablesSchema, setVariablesSchema] = useState(null)
const [datasetsSchemaData, setDatasetsSchemaData] = useState(null)
const [variablesSchemaData, setVariablesSchemaData] = useState(null)
const [loading, setLoading] = useState(true)
const toast = useToast()
const loadDatasetData = async () => {
try {
setLoading(true)
const [datasetsData, variablesData, datasetsSchemaData, variablesSchemaData] = await Promise.all([
const [datasetsData, variablesData, datasetsSchemaResponse, variablesSchemaResponse] = await Promise.all([
api.readConfig('dataset-definitions'),
api.readConfig('dataset-variables'),
api.getSchema('dataset-definitions'),
@ -347,8 +350,8 @@ function DatasetManager() {
setDatasetsConfig(datasetsData)
setVariablesConfig(variablesData)
setDatasetsSchema(datasetsSchemaData)
setVariablesSchema(variablesSchemaData)
setDatasetsSchemaData(datasetsSchemaResponse)
setVariablesSchemaData(variablesSchemaResponse)
} catch (error) {
toast({
title: '❌ Failed to load dataset data',
@ -434,7 +437,7 @@ function DatasetManager() {
<TabPanels>
<TabPanel p={0} pt={4}>
{datasetsSchema && datasetsConfig && (
{datasetsSchemaData?.schema && datasetsConfig && (
<Card>
<CardHeader>
<Heading size="md">Dataset Metadata Configuration</Heading>
@ -444,9 +447,11 @@ function DatasetManager() {
</CardHeader>
<CardBody>
<Form
schema={datasetsSchema}
schema={datasetsSchemaData.schema}
uiSchema={datasetsSchemaData.uiSchema}
formData={datasetsConfig}
validator={validator}
widgets={customWidgets}
onSubmit={({ formData }) => saveDatasets(formData)}
onChange={({ formData }) => setDatasetsConfig(formData)}
>
@ -465,7 +470,7 @@ function DatasetManager() {
</TabPanel>
<TabPanel p={0} pt={4}>
{variablesSchema && variablesConfig && (
{variablesSchemaData?.schema && variablesConfig && (
<Card>
<CardHeader>
<Heading size="md">Dataset Variables Configuration</Heading>
@ -475,9 +480,11 @@ function DatasetManager() {
</CardHeader>
<CardBody>
<Form
schema={variablesSchema}
schema={variablesSchemaData.schema}
uiSchema={variablesSchemaData.uiSchema}
formData={variablesConfig}
validator={validator}
widgets={customWidgets}
onSubmit={({ formData }) => saveVariables(formData)}
onChange={({ formData }) => setVariablesConfig(formData)}
>
@ -581,7 +588,7 @@ export default function Dashboard() {
const [schemas, setSchemas] = useState([])
const [currentSchemaId, setCurrentSchemaId] = useState('plc')
const [schema, setSchema] = useState(null)
const [schemaData, setSchemaData] = useState(null)
const [formData, setFormData] = useState(null)
const [saving, setSaving] = useState(false)
const [message, setMessage] = useState('')
@ -662,11 +669,11 @@ export default function Dashboard() {
// Load specific config
const loadConfig = useCallback(async (schemaId) => {
try {
const [schemaData, configData] = await Promise.all([
const [schemaResponse, configData] = await Promise.all([
api.getSchema(schemaId),
api.readConfig(schemaId)
])
setSchema(schemaData)
setSchemaData(schemaResponse)
setFormData(configData)
setMessage('')
} catch (error) {
@ -763,7 +770,7 @@ export default function Dashboard() {
schemas={schemas}
currentSchemaId={currentSchemaId}
onSchemaChange={setCurrentSchemaId}
schema={schema}
schemaData={schemaData}
formData={formData}
onFormChange={setFormData}
onSave={saveConfig}

View File

@ -69,8 +69,11 @@ export async function getSchema(schemaId) {
const res = await fetch(`${BASE_URL}/api/config/schema/${encodeURIComponent(schemaId)}`, { headers: { 'Accept': 'application/json' } })
const response = await toJsonOrThrow(res)
// The API returns { success: true, schema: {...}, ui_schema?: {...} }
// We need to extract just the schema part for RJSF
return response.schema || response
// Return both schema and uiSchema for RJSF
return {
schema: response.schema || response,
uiSchema: response.ui_schema || {}
}
}
export async function readConfig(configId) {