feat: Add new application events and update system state management
This commit is contained in:
parent
087a9458ce
commit
d6190f3323
|
@ -450,8 +450,44 @@
|
|||
"trigger_variable": null,
|
||||
"auto_started": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T13:26:50.126159",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T13:26:50.175938",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T13:26:50.178048",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T13:26:50.239908",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
}
|
||||
],
|
||||
"last_updated": "2025-08-14T13:10:18.671577",
|
||||
"total_entries": 41
|
||||
"last_updated": "2025-08-14T13:26:50.239908",
|
||||
"total_entries": 45
|
||||
}
|
|
@ -2,12 +2,7 @@ import React from 'react'
|
|||
import recLogo from './assets/logo/record.png'
|
||||
import { Routes, Route, Link } from 'react-router-dom'
|
||||
import { Box, Container, Flex, HStack, Select, Button, Heading, Text, useColorMode, useColorModeValue, Stack } from '@chakra-ui/react'
|
||||
import EventsPage from './pages/Events.jsx'
|
||||
import ConfigPage from './pages/Config.jsx'
|
||||
import PlotsPage from './pages/Plots.jsx'
|
||||
import PLCConfigModal from './components/PLCConfigModal.jsx'
|
||||
import DashboardPage from './pages/DashboardNew.jsx'
|
||||
import DatasetManager from './components/DatasetManager.jsx'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
|
@ -85,10 +80,6 @@ function NavBar() {
|
|||
<Heading as="span" size="sm">PLC Streamer</Heading>
|
||||
</HStack>
|
||||
<HStack spacing={2}>
|
||||
<Button as={Link} to="/datasets" size="sm" variant="outline">📊 Datasets</Button>
|
||||
<Button as={Link} to="/events" size="sm" variant="outline">Events</Button>
|
||||
<Button as={Link} to="/config" size="sm" variant="outline">Config</Button>
|
||||
<Button as={Link} to="/plots" size="sm" variant="outline">📈 Plots</Button>
|
||||
<ColorModeSelector />
|
||||
</HStack>
|
||||
</Flex>
|
||||
|
@ -104,10 +95,7 @@ function App() {
|
|||
<NavBar />
|
||||
<Routes>
|
||||
<Route path="/" element={<DashboardPage />} />
|
||||
<Route path="/datasets" element={<DatasetManager />} />
|
||||
<Route path="/events" element={<EventsPage />} />
|
||||
<Route path="/config" element={<ConfigPage />} />
|
||||
<Route path="/plots" element={<PlotsPage />} />
|
||||
<Route path="/*" element={<DashboardPage />} />
|
||||
</Routes>
|
||||
</Box>
|
||||
)
|
||||
|
|
|
@ -4,11 +4,6 @@ import {
|
|||
Container,
|
||||
VStack,
|
||||
Heading,
|
||||
Tabs,
|
||||
TabList,
|
||||
TabPanels,
|
||||
Tab,
|
||||
TabPanel,
|
||||
Card,
|
||||
CardBody,
|
||||
CardHeader,
|
||||
|
@ -455,188 +450,176 @@ function DatasetManager() {
|
|||
</Button>
|
||||
</Flex>
|
||||
|
||||
<Tabs variant="enclosed" colorScheme="blue">
|
||||
<TabList>
|
||||
<Tab>📋 Dataset Definitions</Tab>
|
||||
<Tab>⚙️ Dataset Variables</Tab>
|
||||
</TabList>
|
||||
{/* Dataset Definitions Section */}
|
||||
{datasetsSchemaData?.schema && datasetsConfig && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Heading size="md">📋 Dataset Metadata Configuration</Heading>
|
||||
<Text fontSize="sm" color="gray.500" mt={1}>
|
||||
Configure dataset names, prefixes, sampling intervals and enable/disable datasets
|
||||
</Text>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<Form
|
||||
schema={datasetsSchemaData.schema}
|
||||
uiSchema={datasetsSchemaData.uiSchema}
|
||||
formData={datasetsConfig}
|
||||
validator={validator}
|
||||
widgets={allWidgets}
|
||||
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
|
||||
onSubmit={({ formData }) => saveDatasets(formData)}
|
||||
onChange={({ formData }) => setDatasetsConfig(formData)}
|
||||
>
|
||||
<HStack spacing={2} mt={4}>
|
||||
<Button type="submit" colorScheme="blue">
|
||||
💾 Save Definitions
|
||||
</Button>
|
||||
<Button variant="outline" onClick={loadDatasetData}>
|
||||
🔄 Reset
|
||||
</Button>
|
||||
</HStack>
|
||||
</Form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<TabPanels>
|
||||
<TabPanel p={0} pt={4}>
|
||||
{datasetsSchemaData?.schema && datasetsConfig && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Heading size="md">Dataset Metadata Configuration</Heading>
|
||||
<Text fontSize="sm" color="gray.500" mt={1}>
|
||||
Configure dataset names, prefixes, sampling intervals and enable/disable datasets
|
||||
</Text>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<Form
|
||||
schema={datasetsSchemaData.schema}
|
||||
uiSchema={datasetsSchemaData.uiSchema}
|
||||
formData={datasetsConfig}
|
||||
validator={validator}
|
||||
widgets={allWidgets}
|
||||
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
|
||||
onSubmit={({ formData }) => saveDatasets(formData)}
|
||||
onChange={({ formData }) => setDatasetsConfig(formData)}
|
||||
>
|
||||
<HStack spacing={2} mt={4}>
|
||||
<Button type="submit" colorScheme="blue">
|
||||
💾 Save Definitions
|
||||
</Button>
|
||||
<Button variant="outline" onClick={loadDatasetData}>
|
||||
🔄 Reset
|
||||
</Button>
|
||||
</HStack>
|
||||
</Form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel p={0} pt={4}>
|
||||
{/* Dataset Variables Configuration with Combo Selector */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Heading size="md">Dataset Variables Configuration</Heading>
|
||||
<Text fontSize="sm" color="gray.500" mt={1}>
|
||||
Select a dataset, then configure its PLC variables and streaming settings
|
||||
{/* Dataset Variables Configuration Section */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Heading size="md">⚙️ Dataset Variables Configuration</Heading>
|
||||
<Text fontSize="sm" color="gray.500" mt={1}>
|
||||
Select a dataset, then configure its PLC variables and streaming settings
|
||||
</Text>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
{/* Step 1: Dataset Selector (Combo) */}
|
||||
<VStack spacing={4} align="stretch">
|
||||
<Box>
|
||||
<Text fontSize="sm" fontWeight="bold" mb={2}>
|
||||
🎯 Select Dataset
|
||||
</Text>
|
||||
<Select
|
||||
value={selectedDatasetId}
|
||||
onChange={(e) => setSelectedDatasetId(e.target.value)}
|
||||
placeholder="Choose a dataset to configure..."
|
||||
size="md"
|
||||
>
|
||||
{availableDatasets.map(dataset => (
|
||||
<option key={dataset.id} value={dataset.id}>
|
||||
📊 {dataset.name} ({dataset.id})
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
{availableDatasets.length === 0 && (
|
||||
<Text fontSize="sm" color="orange.500" mt={2}>
|
||||
⚠️ No datasets available. Configure datasets first in the "Dataset Definitions" section above.
|
||||
</Text>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
{/* Step 1: Dataset Selector (Combo) */}
|
||||
<VStack spacing={4} align="stretch">
|
||||
<Box>
|
||||
<Text fontSize="sm" fontWeight="bold" mb={2}>
|
||||
🎯 Select Dataset
|
||||
</Text>
|
||||
<Select
|
||||
value={selectedDatasetId}
|
||||
onChange={(e) => setSelectedDatasetId(e.target.value)}
|
||||
placeholder="Choose a dataset to configure..."
|
||||
size="md"
|
||||
>
|
||||
{availableDatasets.map(dataset => (
|
||||
<option key={dataset.id} value={dataset.id}>
|
||||
📊 {dataset.name} ({dataset.id})
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
{availableDatasets.length === 0 && (
|
||||
<Text fontSize="sm" color="orange.500" mt={2}>
|
||||
⚠️ No datasets available. Configure datasets first in the "Dataset Definitions" tab.
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Variables Configuration Form */}
|
||||
{selectedDatasetId && (
|
||||
<Box>
|
||||
<Divider mb={4} />
|
||||
<Text fontSize="sm" fontWeight="bold" mb={2}>
|
||||
⚙️ Configure Variables for Dataset "{selectedDatasetId}"
|
||||
</Text>
|
||||
|
||||
{/* Simplified schema for selected dataset variables */}
|
||||
{(() => {
|
||||
const selectedDatasetVars = getSelectedDatasetVariables()
|
||||
|
||||
// Schema for this dataset's variables
|
||||
const singleDatasetSchema = {
|
||||
{/* Variables Configuration Form */}
|
||||
{selectedDatasetId && (
|
||||
<Box>
|
||||
<Divider mb={4} />
|
||||
<Text fontSize="sm" fontWeight="bold" mb={2}>
|
||||
⚙️ Configure Variables for Dataset "{selectedDatasetId}"
|
||||
</Text>
|
||||
|
||||
{/* Simplified schema for selected dataset variables */}
|
||||
{(() => {
|
||||
const selectedDatasetVars = getSelectedDatasetVariables()
|
||||
|
||||
// Schema for this dataset's variables
|
||||
const singleDatasetSchema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
variables: {
|
||||
type: "array",
|
||||
title: "Variables",
|
||||
description: `PLC variables to record in dataset ${selectedDatasetId}`,
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
variables: {
|
||||
type: "array",
|
||||
title: "Variables",
|
||||
description: `PLC variables to record in dataset ${selectedDatasetId}`,
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
name: { type: "string", title: "Variable Name" },
|
||||
area: {
|
||||
type: "string",
|
||||
title: "Memory Area",
|
||||
enum: ["db", "mw", "m", "pew", "pe", "paw", "pa", "e", "a", "mb"],
|
||||
default: "db"
|
||||
},
|
||||
db: { type: "integer", title: "DB Number", minimum: 1, maximum: 9999 },
|
||||
offset: { type: "integer", title: "Offset", minimum: 0, maximum: 8191 },
|
||||
bit: { type: "integer", title: "Bit Position", minimum: 0, maximum: 7 },
|
||||
type: {
|
||||
type: "string",
|
||||
title: "Data Type",
|
||||
enum: ["real", "int", "dint", "bool", "word", "byte"],
|
||||
default: "real"
|
||||
},
|
||||
streaming: { type: "boolean", title: "Stream to UDP", default: false }
|
||||
},
|
||||
required: ["name", "area", "offset", "type"]
|
||||
}
|
||||
}
|
||||
}
|
||||
name: { type: "string", title: "Variable Name" },
|
||||
area: {
|
||||
type: "string",
|
||||
title: "Memory Area",
|
||||
enum: ["db", "mw", "m", "pew", "pe", "paw", "pa", "e", "a", "mb"],
|
||||
default: "db"
|
||||
},
|
||||
db: { type: "integer", title: "DB Number", minimum: 1, maximum: 9999 },
|
||||
offset: { type: "integer", title: "Offset", minimum: 0, maximum: 8191 },
|
||||
bit: { type: "integer", title: "Bit Position", minimum: 0, maximum: 7 },
|
||||
type: {
|
||||
type: "string",
|
||||
title: "Data Type",
|
||||
enum: ["real", "int", "dint", "bool", "word", "byte"],
|
||||
default: "real"
|
||||
},
|
||||
streaming: { type: "boolean", title: "Stream to UDP", default: false }
|
||||
},
|
||||
required: ["name", "area", "offset", "type"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const singleDatasetUiSchema = {
|
||||
variables: {
|
||||
items: {
|
||||
"ui:layout": [[
|
||||
{ "name": "name", "width": 3 },
|
||||
{ "name": "area", "width": 2 },
|
||||
{ "name": "db", "width": 1 },
|
||||
{ "name": "offset", "width": 2 },
|
||||
{ "name": "type", "width": 2 },
|
||||
{ "name": "streaming", "width": 2 }
|
||||
]]
|
||||
}
|
||||
}
|
||||
}
|
||||
const singleDatasetUiSchema = {
|
||||
variables: {
|
||||
items: {
|
||||
"ui:layout": [[
|
||||
{ "name": "name", "width": 3 },
|
||||
{ "name": "area", "width": 2 },
|
||||
{ "name": "db", "width": 1 },
|
||||
{ "name": "offset", "width": 2 },
|
||||
{ "name": "type", "width": 2 },
|
||||
{ "name": "streaming", "width": 2 }
|
||||
]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Form
|
||||
schema={singleDatasetSchema}
|
||||
uiSchema={singleDatasetUiSchema}
|
||||
formData={selectedDatasetVars}
|
||||
validator={validator}
|
||||
widgets={allWidgets}
|
||||
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
|
||||
onSubmit={({ formData }) => {
|
||||
updateSelectedDatasetVariables(formData)
|
||||
saveVariables(variablesConfig).then(() => {
|
||||
// Additional trigger after successful save
|
||||
triggerVariableRefresh()
|
||||
})
|
||||
}}
|
||||
onChange={({ formData }) => updateSelectedDatasetVariables(formData)}
|
||||
>
|
||||
<HStack spacing={2} mt={4}>
|
||||
<Button type="submit" colorScheme="blue">
|
||||
💾 Save Variables for {selectedDatasetId}
|
||||
</Button>
|
||||
<Button variant="outline" onClick={loadDatasetData}>
|
||||
🔄 Reset
|
||||
</Button>
|
||||
</HStack>
|
||||
</Form>
|
||||
)
|
||||
})()}
|
||||
</Box>
|
||||
)}
|
||||
return (
|
||||
<Form
|
||||
schema={singleDatasetSchema}
|
||||
uiSchema={singleDatasetUiSchema}
|
||||
formData={selectedDatasetVars}
|
||||
validator={validator}
|
||||
widgets={allWidgets}
|
||||
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
|
||||
onSubmit={({ formData }) => {
|
||||
updateSelectedDatasetVariables(formData)
|
||||
saveVariables(variablesConfig).then(() => {
|
||||
// Additional trigger after successful save
|
||||
triggerVariableRefresh()
|
||||
})
|
||||
}}
|
||||
onChange={({ formData }) => updateSelectedDatasetVariables(formData)}
|
||||
>
|
||||
<HStack spacing={2} mt={4}>
|
||||
<Button type="submit" colorScheme="blue">
|
||||
💾 Save Variables for {selectedDatasetId}
|
||||
</Button>
|
||||
<Button variant="outline" onClick={loadDatasetData}>
|
||||
🔄 Reset
|
||||
</Button>
|
||||
</HStack>
|
||||
</Form>
|
||||
)
|
||||
})()}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{!selectedDatasetId && availableDatasets.length > 0 && (
|
||||
<Box textAlign="center" py={8}>
|
||||
<Text color="gray.500">
|
||||
👆 Select a dataset above to configure its variables
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</VStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
{!selectedDatasetId && availableDatasets.length > 0 && (
|
||||
<Box textAlign="center" py={8}>
|
||||
<Text color="gray.500">
|
||||
👆 Select a dataset above to configure its variables
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</VStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
@ -853,43 +836,28 @@ function DashboardContent() {
|
|||
|
||||
<StatusBar status={status} onRefresh={loadStatus} />
|
||||
|
||||
<Tabs variant="enclosed" colorScheme="blue">
|
||||
<TabList>
|
||||
<Tab>🔧 Configuration</Tab>
|
||||
<Tab>📊 Datasets</Tab>
|
||||
<Tab>📈 Plotting</Tab>
|
||||
<Tab>📋 Events</Tab>
|
||||
</TabList>
|
||||
{/* Configuration Panel */}
|
||||
<ConfigurationPanel
|
||||
schemaData={schemaData}
|
||||
formData={formData}
|
||||
onFormChange={setFormData}
|
||||
onSave={saveConfig}
|
||||
saving={saving}
|
||||
message={message}
|
||||
/>
|
||||
|
||||
<TabPanels>
|
||||
<TabPanel p={0} pt={4}>
|
||||
<ConfigurationPanel
|
||||
schemaData={schemaData}
|
||||
formData={formData}
|
||||
onFormChange={setFormData}
|
||||
onSave={saveConfig}
|
||||
saving={saving}
|
||||
message={message}
|
||||
/>
|
||||
</TabPanel>
|
||||
{/* Dataset Management */}
|
||||
<DatasetManager />
|
||||
|
||||
<TabPanel p={0} pt={4}>
|
||||
<DatasetManager />
|
||||
</TabPanel>
|
||||
{/* Plot Management */}
|
||||
<PlotManager />
|
||||
|
||||
<TabPanel p={0} pt={4}>
|
||||
<PlotManager />
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel p={0} pt={4}>
|
||||
<EventsDisplay
|
||||
events={events}
|
||||
loading={eventsLoading}
|
||||
onRefresh={loadEvents}
|
||||
/>
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
{/* Events Display */}
|
||||
<EventsDisplay
|
||||
events={events}
|
||||
loading={eventsLoading}
|
||||
onRefresh={loadEvents}
|
||||
/>
|
||||
</VStack>
|
||||
</Container>
|
||||
)
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
"should_stream": false,
|
||||
"active_datasets": [
|
||||
"DAR",
|
||||
"Test",
|
||||
"Fast"
|
||||
"Fast",
|
||||
"Test"
|
||||
]
|
||||
},
|
||||
"auto_recovery_enabled": true,
|
||||
"last_update": "2025-08-14T13:09:58.767138"
|
||||
"last_update": "2025-08-14T13:26:50.179055"
|
||||
}
|
Loading…
Reference in New Issue