From 8656adc59b47d981e9b806d5b4b8b83ba5f1734b Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 3 Apr 2026 13:41:06 -0400 Subject: [PATCH 01/45] rename NodeStats to NodeDetails --- Source/Applications/SystemCenter/SystemCenter.csproj | 3 ++- .../Scripts/TSX/SystemCenter/AppHost/AppHost.tsx | 2 +- .../AppHost/{NodeStats.tsx => NodeDetails.tsx} | 10 +++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) rename Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/{NodeStats.tsx => NodeDetails.tsx} (93%) diff --git a/Source/Applications/SystemCenter/SystemCenter.csproj b/Source/Applications/SystemCenter/SystemCenter.csproj index 532ac87a8..8a7456a9d 100644 --- a/Source/Applications/SystemCenter/SystemCenter.csproj +++ b/Source/Applications/SystemCenter/SystemCenter.csproj @@ -547,7 +547,8 @@ - + + diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx index f6a36825f..c3ad983c6 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx @@ -26,7 +26,7 @@ import { Application } from '@gpa-gemstone/application-typings'; import { LoadingScreen, ServerErrorIcon, LayoutGrid } from '@gpa-gemstone/react-interactive'; import ApplicationCard, { IHost } from './ApplicationCard'; import ConsoleWindow from './ConsoleWindow'; -import NodeStats from './NodeStats'; +import NodeStats from './NodeDetails'; import { useMediaQuery } from '@gpa-gemstone/helper-functions'; diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeStats.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx similarity index 93% rename from Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeStats.tsx rename to Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index b6b9c2fbb..64d618eae 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeStats.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -1,5 +1,5 @@ //****************************************************************************************************** -// NodeStats.tsx - Gbtc +// NodeDetails.tsx - Gbtc // // Copyright © 2023, Grid Protection Alliance. All Rights Reserved. // @@ -18,15 +18,19 @@ // ---------------------------------------------------------------------------------------------------- // 10/14/2024 - G. Santos // Generated original version of source code. +// 04/03/2026 - N. Beatty +// Renamed to NodeDetails. // //****************************************************************************************************** import * as React from 'react'; -import { Modal, ServerErrorIcon } from '@gpa-gemstone/react-interactive'; +import { Modal, TabSelector } from '@gpa-gemstone/react-interactive'; import { Application } from '@gpa-gemstone/application-typings'; import NodeHealth from './NodeHealth'; import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; +type tabs = 'Connections' | 'Health' | 'Console' + export interface IMessage { Message: string, Type: number } export interface IProps { @@ -88,7 +92,7 @@ const NodeStats = (props: IProps) => { CallBack={() => { props.Close(); setStatus('uninitiated'); setStatInfo('') }} Title={'Statistics - ' + props.ApplicationName} > - {(props.StatsURL ?? "") === "" ? + {(props.StatsURL ?? "") === "" ? // only set if it's openXDA. certainly a better way to do this dear natalie. move XDA health into another component.
Date: Fri, 3 Apr 2026 13:45:07 -0400 Subject: [PATCH 02/45] rename NodeStats component to NodeDetails --- .../TSX/SystemCenter/AppHost/AppHost.tsx | 18 +++++++++--------- .../SystemCenter/AppHost/ApplicationCard.tsx | 11 +++-------- .../TSX/SystemCenter/AppHost/NodeDetails.tsx | 4 ++-- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx index c3ad983c6..ded861586 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx @@ -26,7 +26,7 @@ import { Application } from '@gpa-gemstone/application-typings'; import { LoadingScreen, ServerErrorIcon, LayoutGrid } from '@gpa-gemstone/react-interactive'; import ApplicationCard, { IHost } from './ApplicationCard'; import ConsoleWindow from './ConsoleWindow'; -import NodeStats from './NodeDetails'; +import NodeDetails from './NodeDetails'; import { useMediaQuery } from '@gpa-gemstone/helper-functions'; @@ -34,7 +34,7 @@ const AppHost: Application.Types.iByComponent = (props) => { const [hosts, setHosts] = React.useState([]); const [status, setStatus] = React.useState('uninitiated'); const [console, setConsole] = React.useState(null); - const [stats, setStats] = React.useState(null); + const [details, setDetails] = React.useState(null); const shouldHaveTwoRowsHeight = useMediaQuery('(max-height: 1250px)'); const shouldBeSmall = useMediaQuery('(max-width: 1750px)'); @@ -68,7 +68,7 @@ const AppHost: Application.Types.iByComponent = (props) => { {hosts.map((h) => setConsole(h)} - OpenStats={() => setStats(h)} + OpenDetails={() => setDetails(h)} key={h.PingURL} IsSmall={shouldBeSmall} />)} @@ -79,12 +79,12 @@ const AppHost: Application.Types.iByComponent = (props) => { Close={() => setConsole(null)} ConsoleURL={console?.ConsoleURL} /> - setStats(null)} - StatsURL={stats?.StatsURL} - ApplicationType={stats?.App ?? null} - Properties={stats?.Properties} + setDetails(null)} + StatsURL={details?.StatsURL} + ApplicationType={details?.App ?? null} + Properties={details?.Properties} />
) } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx index 1abc07a1e..029275e9a 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx @@ -35,7 +35,7 @@ export interface IHost { Name: string, App: 'XDA' | 'MiMD' | 'SystemCenter', OpenConsole: () => void, - OpenStats: () => void + OpenDetails: () => void } export interface IApplicationCard extends IHost { @@ -98,13 +98,8 @@ const ApplicationCard = (props: IApplicationCard) => {
-
- -
-
- {props.App === 'MiMD' ? null : - - } +
+
diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 64d618eae..888133984 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -49,7 +49,7 @@ const statStyle: React.CSSProperties = { wordBreak: 'break-word' } -const NodeStats = (props: IProps) => { +const NodeDetails = (props: IProps) => { const [statInfo, setStatInfo] = React.useState(''); const [status, setStatus] = React.useState('uninitiated'); const [autoScroll, setAutoScroll] = React.useState(true); @@ -139,4 +139,4 @@ const NodeStats = (props: IProps) => { } -export default NodeStats; \ No newline at end of file +export default NodeDetails; \ No newline at end of file From 19ab4a7148dafad5723a9bfc0ac77384fb0b792b Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 3 Apr 2026 13:58:24 -0400 Subject: [PATCH 03/45] move openXDA stats into separate component --- .../TSX/SystemCenter/AppHost/NodeDetails.tsx | 97 ++------------- .../SystemCenter/AppHost/OpenXDAHealth.tsx | 110 ++++++++++++++++++ 2 files changed, 119 insertions(+), 88 deletions(-) create mode 100644 Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 888133984..65f757ce4 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -25,9 +25,7 @@ import * as React from 'react'; import { Modal, TabSelector } from '@gpa-gemstone/react-interactive'; -import { Application } from '@gpa-gemstone/application-typings'; import NodeHealth from './NodeHealth'; -import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; type tabs = 'Connections' | 'Health' | 'Console' @@ -41,100 +39,23 @@ export interface IProps { Properties: { Name: string, Value: string }[] } -const statStyle: React.CSSProperties = { - fontSize: "1em", - display: 'inline-block', - overflow: 'auto', - whiteSpace: 'pre-wrap', - wordBreak: 'break-word' -} const NodeDetails = (props: IProps) => { - const [statInfo, setStatInfo] = React.useState(''); - const [status, setStatus] = React.useState('uninitiated'); - const [autoScroll, setAutoScroll] = React.useState(true); - const [lastUpdate, setLastUpdate] = React.useState(''); - - React.useEffect(() => { - if (props.StatsURL == null || props.StatsURL.length == 0) return; - - setStatus('loading'); - let statHandle: JQuery.jqXHR; - const intervalHandle = setInterval(() => { - if (statHandle != null && statHandle?.abort != null) statHandle.abort(); - - statHandle = $.ajax({ - type: "GET", - url: props.StatsURL, - dataType: 'text', - cache: false, - async: true - }).done((stat: string) => { - setStatus('idle'); - // Regex remove wrapping quotes, carriage return, and format \\ to \ - setStatInfo(stat.replace(/^\"+|\"+$/g, '').replace(/\\r\\n/g, '\n').replace(/\\\\/g, '\\')); - }).fail((_a, _b, e) => { - console.error(e); - setStatus('error'); - }); - }, 5000); - - return () => { - clearInterval(intervalHandle); - if (statHandle != null && statHandle.abort != null) statHandle.abort(); - }; - }, [props.ApplicationName]); return ( { props.Close(); setStatus('uninitiated'); setStatInfo('') }} - Title={'Statistics - ' + props.ApplicationName} + CallBack={() => { props.Close(); /**setStatus('uninitiated'); setStatInfo('')*/ }} + Title={'Details - ' + props.ApplicationName} > - {(props.StatsURL ?? "") === "" ? // only set if it's openXDA. certainly a better way to do this dear natalie. move XDA health into another component. -
- -
: -
-
- XDA Stats: - { - status === "error" ? - -
- - - -
- Failed to get openXDA stats. -
-
: - status === "loading" ? - : -
-
-                                            {statInfo}
-                                        
-
- } -
-
- -
-
- } - +
+ +
); } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx new file mode 100644 index 000000000..c731a2961 --- /dev/null +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx @@ -0,0 +1,110 @@ +//****************************************************************************************************** +// OpenXDAHealth.tsx - Gbtc +// +// Copyright © 2026, Grid Protection Alliance. All Rights Reserved. +// +// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See +// the NOTICE file distributed with this work for additional information regarding copyright ownership. +// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this +// file except in compliance with the License. You may obtain a copy of the License at: +// +// http://opensource.org/licenses/MIT +// +// Unless agreed to in writing, the subject software distributed under the License is distributed on an +// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the +// License for the specific language governing permissions and limitations. +// +// Code Modification History: +// ---------------------------------------------------------------------------------------------------- +// 10/14/2024 - G. Santos +// Generated original version of source code. +// 04/02/2026 - N. Beatty +// Moved from NodeStats.tsx to OpenXDAHealth.tsx +// +//****************************************************************************************************** + + +import * as React from 'react'; +import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; +import { Application } from '@gpa-gemstone/application-typings'; + +const statStyle: React.CSSProperties = { + fontSize: "1em", + display: 'inline-block', + overflow: 'auto', + whiteSpace: 'pre-wrap', + wordBreak: 'break-word' +} + +export interface IProps { + StatsURL: string, + ApplicationName: string, + ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD', + Close: () => void + Properties: { Name: string, Value: string }[] +} + +const OpenXDAHealth = (props: IProps) => { + + const [statInfo, setStatInfo] = React.useState(''); + const [status, setStatus] = React.useState('uninitiated'); + const [autoScroll, setAutoScroll] = React.useState(true); + const [lastUpdate, setLastUpdate] = React.useState(''); + + React.useEffect(() => { + if (props.StatsURL == null || props.StatsURL.length == 0) return; + + setStatus('loading'); + let statHandle: JQuery.jqXHR; + const intervalHandle = setInterval(() => { + if (statHandle != null && statHandle?.abort != null) statHandle.abort(); + + statHandle = $.ajax({ + type: "GET", + url: props.StatsURL, + dataType: 'text', + cache: false, + async: true + }).done((stat: string) => { + setStatus('idle'); + // Regex remove wrapping quotes, carriage return, and format \\ to \ + setStatInfo(stat.replace(/^\"+|\"+$/g, '').replace(/\\r\\n/g, '\n').replace(/\\\\/g, '\\')); + }).fail((_a, _b, e) => { + console.error(e); + setStatus('error'); + }); + }, 5000); + + return () => { + clearInterval(intervalHandle); + if (statHandle != null && statHandle.abort != null) statHandle.abort(); + }; + }, [props.ApplicationName]); + + return ( +
+ XDA Stats: + { + status === "error" ? + +
+ + + +
+ Failed to get openXDA stats. +
+
: + status === "loading" ? + : +
+
+                                    {statInfo}
+                                
+
+ } +
+ ) +} \ No newline at end of file From 6391bb78ee01308b1dbaadcc47bca66ed7f1b688 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 3 Apr 2026 14:02:43 -0400 Subject: [PATCH 04/45] rename NodeHealth to NodeConnections --- Source/Applications/SystemCenter/SystemCenter.csproj | 2 +- .../AppHost/{NodeHealth.tsx => NodeConnections.tsx} | 7 +++++-- .../Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) rename Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/{NodeHealth.tsx => NodeConnections.tsx} (96%) diff --git a/Source/Applications/SystemCenter/SystemCenter.csproj b/Source/Applications/SystemCenter/SystemCenter.csproj index 8a7456a9d..0e6377a34 100644 --- a/Source/Applications/SystemCenter/SystemCenter.csproj +++ b/Source/Applications/SystemCenter/SystemCenter.csproj @@ -547,7 +547,7 @@ - + diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx similarity index 96% rename from Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx rename to Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index e211eaa4d..92f1e0bf0 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -19,6 +19,9 @@ // 02/26/2026 - Natalie Beatty // Generated original version of source code. // +// 04/03/2026 - Natalie Beatty +// Renamed to NodeConnections.tsx +// //****************************************************************************************************** import * as React from 'react' @@ -26,7 +29,7 @@ import { Application, SystemCenter, OpenXDA } from '@gpa-gemstone/application-ty import { SystemCenter as SC } from '../global' import StatusGroup from './StatusGroup' -const NodeHealth = (props: { ApplicationName: string, ApplicationType: 'SystemCenter' | 'MiMD' | 'XDA', Properties: { Name: string, Value: string }[] }) => { +const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'SystemCenter' | 'MiMD' | 'XDA', Properties: { Name: string, Value: string }[] }) => { const [status, setStatus] = React.useState('uninitiated'); const [extDBStatus, setExtDBStatus] = React.useState([{Name: "Loading...", Status: "Loading", Details: [] }]); const [remoteXDAStatus, setRemoteXDAStatus] = React.useState([{ Name: "Loading...", Status: "Loading", Details: [] }]); @@ -212,4 +215,4 @@ const NodeHealth = (props: { ApplicationName: string, ApplicationType: 'SystemCe ) } -export default NodeHealth; \ No newline at end of file +export default NodeConnections; \ No newline at end of file diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 65f757ce4..ea556b16a 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -25,7 +25,7 @@ import * as React from 'react'; import { Modal, TabSelector } from '@gpa-gemstone/react-interactive'; -import NodeHealth from './NodeHealth'; +import NodeConnections from './NodeConnections'; type tabs = 'Connections' | 'Health' | 'Console' @@ -50,7 +50,7 @@ const NodeDetails = (props: IProps) => { Title={'Details - ' + props.ApplicationName} >
- Date: Fri, 3 Apr 2026 14:02:58 -0400 Subject: [PATCH 05/45] include openXDAHealth in solution --- Source/Applications/SystemCenter/SystemCenter.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Applications/SystemCenter/SystemCenter.csproj b/Source/Applications/SystemCenter/SystemCenter.csproj index 0e6377a34..1f23df871 100644 --- a/Source/Applications/SystemCenter/SystemCenter.csproj +++ b/Source/Applications/SystemCenter/SystemCenter.csproj @@ -549,6 +549,7 @@ + From 1b02a3bbd42e9a0950ce3c733bb27ec83551a2bb Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 3 Apr 2026 15:08:21 -0400 Subject: [PATCH 06/45] move health, connections, and console to tabs --- .../TSX/SystemCenter/AppHost/AppHost.tsx | 10 +-- .../TSX/SystemCenter/AppHost/NodeDetails.tsx | 68 ++++++++++++++++--- .../SystemCenter/AppHost/OpenXDAHealth.tsx | 4 +- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx index ded861586..4e1351d91 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx @@ -25,7 +25,6 @@ import * as React from 'react'; import { Application } from '@gpa-gemstone/application-typings'; import { LoadingScreen, ServerErrorIcon, LayoutGrid } from '@gpa-gemstone/react-interactive'; import ApplicationCard, { IHost } from './ApplicationCard'; -import ConsoleWindow from './ConsoleWindow'; import NodeDetails from './NodeDetails'; import { useMediaQuery } from '@gpa-gemstone/helper-functions'; @@ -74,17 +73,14 @@ const AppHost: Application.Types.iByComponent = (props) => { />)}
- setConsole(null)} - ConsoleURL={console?.ConsoleURL} - /> setDetails(null)} StatsURL={details?.StatsURL} ApplicationType={details?.App ?? null} Properties={details?.Properties} + SetDetails={setDetails} + SetConsole={setConsole} + ConsoleURL={console?.ConsoleURL} />
) } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index ea556b16a..e90bbaafd 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -26,37 +26,83 @@ import * as React from 'react'; import { Modal, TabSelector } from '@gpa-gemstone/react-interactive'; import NodeConnections from './NodeConnections'; +import OpenXDAHealth from './OpenXDAHealth'; +import ConsoleWindow from './ConsoleWindow' +import { IHost } from './ApplicationCard'; -type tabs = 'Connections' | 'Health' | 'Console' +type tab = 'connections' | 'health' | 'console' export interface IMessage { Message: string, Type: number } export interface IProps { StatsURL: string, + ConsoleURL: string, ApplicationName: string, ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD', - Close: () => void - Properties: { Name: string, Value: string }[] + Properties: { Name: string, Value: string }[], + SetDetails: React.Dispatch> + SetConsole: React.Dispatch> } const NodeDetails = (props: IProps) => { + const [tab, setTab] = React.useState('connections'); return ( { props.Close(); /**setStatus('uninitiated'); setStatInfo('')*/ }} + CallBack={() => { props.SetDetails(null); /**setStatus('uninitiated'); setStatInfo('')*/ }} Title={'Details - ' + props.ApplicationName} > -
- +
+ setTab(t)} Tabs={ + props.ApplicationType === 'SystemCenter' ? + [ + { Label: 'Connections', Id: 'connections' }, + { Label: 'Console', Id: 'console' } + ] + : props.ApplicationType === 'XDA' ? + [ + { Label: 'Connections', Id: 'connections' }, + { Label: 'Health', Id: 'health' }, + { Label: 'Console', Id: 'console' } + ] + : [{ Label: 'Console', Id: 'console' }] + } />
- ); +
+
+
+ {tab === "connections" ? +
+ +
+ : tab === "health" ?
+ props.SetDetails(null)} + Properties={props.Properties} + /> +
+ : tab === "console" ?
+ props.SetConsole(null)} + /> +
+ : null} +
+
+
+ ); } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx index c731a2961..fdf5f3dc6 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/OpenXDAHealth.tsx @@ -107,4 +107,6 @@ const OpenXDAHealth = (props: IProps) => { } ) -} \ No newline at end of file +} + +export default OpenXDAHealth; \ No newline at end of file From db5cafb9ef6d0ac6d0dc731b70b3c841f9b7cf18 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 3 Apr 2026 16:07:14 -0400 Subject: [PATCH 07/45] standardize layout --- .../SystemCenter/AppHost/NodeConnections.tsx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 92f1e0bf0..ddd277e2f 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -31,7 +31,7 @@ import StatusGroup from './StatusGroup' const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'SystemCenter' | 'MiMD' | 'XDA', Properties: { Name: string, Value: string }[] }) => { const [status, setStatus] = React.useState('uninitiated'); - const [extDBStatus, setExtDBStatus] = React.useState([{Name: "Loading...", Status: "Loading", Details: [] }]); + const [extDBStatus, setExtDBStatus] = React.useState([{ Name: "Loading...", Status: "Loading", Details: [] }]); const [remoteXDAStatus, setRemoteXDAStatus] = React.useState([{ Name: "Loading...", Status: "Loading", Details: [] }]); const [hoveredItem, setHoveredItem] = React.useState(null) const [fawgStatus, setFawgStatus] = React.useState({ Name: "FAWG", Status: "Loading", Details: [] }) @@ -71,7 +71,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys }).fail((d) => { setExtDBStatus([{ Status: 'Error', Name: 'External Database Connections', Details: [{ Status: "Error", Description: "Errors occured in retrieving External DB Connection status" }] }]) }) - + return function cleanup() { if (h.abort != null) @@ -159,7 +159,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys d.Name = 'SCADA' setSCADAStatus(d) }).fail(() => { - setSCADAStatus({ Status: 'Error', Name: 'SCADA Resource', Details: [{Status: "Error", Description: "Errors occured in retrieving SCADA Resource"}] }) + setSCADAStatus({ Status: 'Error', Name: 'SCADA Resource', Details: [{ Status: "Error", Description: "Errors occured in retrieving SCADA Resource" }] }) }) return function cleanup() { @@ -174,11 +174,11 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys
+ />
: props.ApplicationType === "XDA" ? -
-
+
+
+ />
-
+
Date: Fri, 3 Apr 2026 16:07:43 -0400 Subject: [PATCH 08/45] get console working --- .../TSX/SystemCenter/AppHost/AppHost.tsx | 2 +- .../SystemCenter/AppHost/ConsoleWindow.tsx | 97 +++++++++---------- 2 files changed, 45 insertions(+), 54 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx index 4e1351d91..abdc739c5 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx @@ -67,7 +67,7 @@ const AppHost: Application.Types.iByComponent = (props) => { {hosts.map((h) => setConsole(h)} - OpenDetails={() => setDetails(h)} + OpenDetails={() => { setDetails(h), setConsole(h) }} key={h.PingURL} IsSmall={shouldBeSmall} />)} diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx index b98fb0ffa..551c6d752 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx @@ -22,8 +22,6 @@ //****************************************************************************************************** import * as React from 'react'; -import { Modal } from '@gpa-gemstone/react-interactive'; - export interface IMessage { Message: string, Type: number } export interface IProps { @@ -103,7 +101,7 @@ const ConsoleWindow = (props: IProps) => { React.useEffect(() => { - if (props.ConsoleURL != undefined && props.ConsoleURL.length > 0) + if (props.ConsoleURL != undefined && props.ConsoleURL.length > 0) document.addEventListener("keydown", handleKeyPress, false); return () => { @@ -113,19 +111,19 @@ const ConsoleWindow = (props: IProps) => { React.useEffect(() => { cmdRef.current = cmd; }, [cmd]); React.useEffect(() => { lastCmdRef.current = lastCmd; }, [lastCmd]); - + function handleKeyPress(event) { if (event.keyCode == 38 && cmd.length > 0) // arrow down key { event.preventDefault(); - setCMD(lastCmdRef.current); + setCMD(lastCmdRef.current); } else if (event.keyCode == 13) // enter key { event.preventDefault(); sendCmd(cmdRef.current); - setCMD(''); + setCMD(''); } } @@ -179,55 +177,48 @@ const ConsoleWindow = (props: IProps) => { }, [props.ConsoleURL]); return ( - <> - 0} - CallBack={(_conf, button) => { if (!button) { props.Close(); sessionIDRef.current = ''; } else { sendCmd(cmd); setCMD(''); } }} - ShowCancel={false} Size={'xlg'} - Title={'Console - ' + props.ApplicationName} - ShowX={true} - ConfirmText={'Send'} - > -
-
-
- -
-
- -
-
-
-
-
 setAutoScroll(false)}
-                                onMouseLeave={() => setAutoScroll(true)}
-                            >
-                                {messages.map((m) => 
-                                    {m.Message}
-                                )}
-                            
-
+
+
+
+ +
+
+ +
+
+
+
+
 setAutoScroll(false)}
+                        onMouseLeave={() => setAutoScroll(true)}
+                    >
+                        {messages.map((m) => 
+                            {m.Message}
+                        )}
+                    
+
+
+
+
+
+ setCMD(evt.target.value)} + value={cmd} + />
-
-
-
- setCMD(evt.target.value)} - value={cmd} - /> -
-
-
- - ) +
+ +
+
+
+ ) } From fdbda1ee70fe02b70c43af2041049787d897c276 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 6 Apr 2026 13:25:34 -0400 Subject: [PATCH 09/45] move openXDAHealth to NodeHealth --- .../Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 4 ++-- .../AppHost/{OpenXDAHealth.tsx => NodeHealth.tsx} | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) rename Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/{OpenXDAHealth.tsx => NodeHealth.tsx} (96%) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index e90bbaafd..321b07081 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -26,7 +26,7 @@ import * as React from 'react'; import { Modal, TabSelector } from '@gpa-gemstone/react-interactive'; import NodeConnections from './NodeConnections'; -import OpenXDAHealth from './OpenXDAHealth'; +import NodeHealth from './NodeHealth'; import ConsoleWindow from './ConsoleWindow' import { IHost } from './ApplicationCard'; @@ -83,7 +83,7 @@ const NodeDetails = (props: IProps) => { />
: tab === "health" ?
- { +const NodeHealth = (props: IProps) => { const [statInfo, setStatInfo] = React.useState(''); const [status, setStatus] = React.useState('uninitiated'); @@ -109,4 +109,4 @@ const OpenXDAHealth = (props: IProps) => { ) } -export default OpenXDAHealth; \ No newline at end of file +export default NodeHealth; \ No newline at end of file From 420859839f6fb5b66ed5f2606012d9a4717bc73c Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 6 Apr 2026 13:31:24 -0400 Subject: [PATCH 10/45] add openMIC to Nodes tab --- .../SystemCenter/AppHostController.cs | 50 +++++++++- .../SystemCenter/SystemCenter.csproj | 12 ++- .../wwwroot/Images/NodeTiles/openMIC.png | Bin 0 -> 57783 bytes .../wwwroot/Images/NodeTiles/openMICIcon.png | Bin 0 -> 98441 bytes .../SystemCenter/AppHost/ConsoleWindow.tsx | 6 +- .../SystemCenter/AppHost/NodeConnections.tsx | 2 +- .../TSX/SystemCenter/AppHost/NodeDetails.tsx | 33 ++++--- .../TSX/SystemCenter/AppHost/NodeHealth.tsx | 90 ++++++++++++------ .../SystemCenter/AppHost/StatusDetails.tsx | 52 ++++++++++ 9 files changed, 194 insertions(+), 51 deletions(-) create mode 100644 Source/Applications/SystemCenter/wwwroot/Images/NodeTiles/openMIC.png create mode 100644 Source/Applications/SystemCenter/wwwroot/Images/NodeTiles/openMICIcon.png create mode 100644 Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx diff --git a/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs b/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs index dd8f67867..4f064d7c2 100644 --- a/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs +++ b/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs @@ -26,13 +26,14 @@ using GSF.Data.Model; using GSF.Reflection; using Newtonsoft.Json; -using openXDA.APIMiddleware; using openXDA.APIAuthentication; +using openXDA.APIMiddleware; using openXDA.Model; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Diagnostics.Metrics; using System.Linq; using System.Net.Http; using System.Text; @@ -88,6 +89,8 @@ public IHttpActionResult Get() // Add MiMD hosts.Add(GetMiMD()); + hosts.Add(GetOpenMIC()); + // Add XDA Nodes using (AdoDataConnection connection = CreateDbConnection()) { @@ -208,6 +211,28 @@ void ConfigureRequest(HttpRequestMessage request) return ResponseMessage(responseMessage); } + [Route("openMIC/Ping"), HttpGet] + public IHttpActionResult openMICPing() + { + using (AdoDataConnection connection = new AdoDataConnection("systemSettings")) + { + string url = new TableOperations(connection).QueryRecordWhere($"Name = 'OpenMIC.Url'")?.Value ?? ""; + string credential = new TableOperations(connection).QueryRecordWhere($"Name = 'OpenMIC.Credential'")?.Value ?? ""; + string password = new TableOperations(connection).QueryRecordWhere($"Name = 'OpenMIC.Password'")?.Value ?? ""; + + //string token = GenerateAntiForgeryToken(application); + //return Get(httpClient, url, requestURI, credential, password, token); + APIQuery query = new APIQuery(credential, password, url); + void ConfigureRequest(HttpRequestMessage request) + { + request.Method = HttpMethod.Get; + } + HttpResponseMessage response = query.SendWebRequestAsync(ConfigureRequest, $"api/health").Result; + if (response.IsSuccessStatusCode) return Ok(1); + return ResponseMessage(response); + } + } + [Route("MiMDConsole/Ping"), HttpGet] public IHttpActionResult MiMDPing() { @@ -299,6 +324,14 @@ private string GetMiMDBaseURL() } } + private string GetOpenMICBaseURL() + { + using (AdoDataConnection connection = CreateDbConnection()) + { + return connection.ExecuteScalar("", "SELECT Value FROM [SystemCenter.Setting] WHERE Name = {0}", "OpenMIC.Url"); + } + } + private AdoDataConnection CreateDbConnection() { AdoDataConnection connection = new AdoDataConnection("systemSettings"); @@ -344,6 +377,21 @@ private AppHost GetMiMD() }; } + private AppHost GetOpenMIC() + { + return new AppHost() + { + Name = "openMIC", + App = "openMIC", + PingURL = "./api/SystemCenter/AppHost/openMIC/Ping", + Properties = new AppProperty[] + { + new AppProperty() { Name= "Host", Value = GetOpenMICBaseURL() } + }, + Image = "../Images/NodeTiles/openMIC.png" + }; + } + private string DatabaseName { get diff --git a/Source/Applications/SystemCenter/SystemCenter.csproj b/Source/Applications/SystemCenter/SystemCenter.csproj index 1f23df871..337b8ec91 100644 --- a/Source/Applications/SystemCenter/SystemCenter.csproj +++ b/Source/Applications/SystemCenter/SystemCenter.csproj @@ -492,6 +492,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -504,6 +507,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -549,7 +555,10 @@ - + + + + @@ -576,6 +585,7 @@ + diff --git a/Source/Applications/SystemCenter/wwwroot/Images/NodeTiles/openMIC.png b/Source/Applications/SystemCenter/wwwroot/Images/NodeTiles/openMIC.png new file mode 100644 index 0000000000000000000000000000000000000000..acc388b0cc148f8b01c3b5354464c74f40370d1c GIT binary patch literal 57783 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 lcS(Q$`1=a{A6Ex!N& literal 0 HcmV?d00001 diff --git a/Source/Applications/SystemCenter/wwwroot/Images/NodeTiles/openMICIcon.png b/Source/Applications/SystemCenter/wwwroot/Images/NodeTiles/openMICIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..2bccc6c7b07434566dbdba215bf97c5fcc5bcee7 GIT binary patch literal 98441 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 {

-
+
{ />
-
- +
+
diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index ddd277e2f..3e124937b 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -29,7 +29,7 @@ import { Application, SystemCenter, OpenXDA } from '@gpa-gemstone/application-ty import { SystemCenter as SC } from '../global' import StatusGroup from './StatusGroup' -const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'SystemCenter' | 'MiMD' | 'XDA', Properties: { Name: string, Value: string }[] }) => { +const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'SystemCenter' | 'MiMD' | 'XDA' | 'openMIC', Properties: { Name: string, Value: string }[] }) => { const [status, setStatus] = React.useState('uninitiated'); const [extDBStatus, setExtDBStatus] = React.useState([{ Name: "Loading...", Status: "Loading", Details: [] }]); const [remoteXDAStatus, setRemoteXDAStatus] = React.useState([{ Name: "Loading...", Status: "Loading", Details: [] }]); diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 321b07081..7d4b0f2de 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -32,47 +32,46 @@ import { IHost } from './ApplicationCard'; type tab = 'connections' | 'health' | 'console' +interface ITab { Label: string, Id: string } export interface IMessage { Message: string, Type: number } export interface IProps { StatsURL: string, ConsoleURL: string, ApplicationName: string, - ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD', + ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD' | 'openMIC', Properties: { Name: string, Value: string }[], SetDetails: React.Dispatch> SetConsole: React.Dispatch> } +const ApplicationTabs = { + '': '', + 'SystemCenter': 'Connections,Console', + 'XDA': 'Connections,Health,Console', + 'MiMD': 'Console', + 'openMIC': 'Health' +} const NodeDetails = (props: IProps) => { const [tab, setTab] = React.useState('connections'); + const availableTabs = ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return t.toLowerCase() }) + if (!availableTabs.includes(tab) && availableTabs.length != 0) + setTab(availableTabs[0] as tab) + return ( { props.SetDetails(null); /**setStatus('uninitiated'); setStatInfo('')*/ }} + CallBack={() => { props.SetDetails(null); setTab('connections') }} Title={'Details - ' + props.ApplicationName} >
- setTab(t)} Tabs={ - props.ApplicationType === 'SystemCenter' ? - [ - { Label: 'Connections', Id: 'connections' }, - { Label: 'Console', Id: 'console' } - ] - : props.ApplicationType === 'XDA' ? - [ - { Label: 'Connections', Id: 'connections' }, - { Label: 'Health', Id: 'health' }, - { Label: 'Console', Id: 'console' } - ] - : [{ Label: 'Console', Id: 'console' }] - } /> + setTab(t)} Tabs={ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return { Label: t, Id: t.toLowerCase() } })} />
-
+
{tab === "connections" ?
diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx index 20ba6eaec..199b4a269 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx @@ -1,7 +1,7 @@ //****************************************************************************************************** // NodeHealth.tsx - Gbtc // -// Copyright © 2026, Grid Protection Alliance. All Rights Reserved. +// Copyright � 2026, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. @@ -27,6 +27,8 @@ import * as React from 'react'; import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { Application } from '@gpa-gemstone/application-typings'; +import { SystemCenter as SC } from '../global' +import StatusDetails from './StatusDetails' const statStyle: React.CSSProperties = { fontSize: "1em", @@ -39,7 +41,7 @@ const statStyle: React.CSSProperties = { export interface IProps { StatsURL: string, ApplicationName: string, - ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD', + ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD' | 'openMIC', Close: () => void Properties: { Name: string, Value: string }[] } @@ -48,10 +50,14 @@ const NodeHealth = (props: IProps) => { const [statInfo, setStatInfo] = React.useState(''); const [status, setStatus] = React.useState('uninitiated'); - const [autoScroll, setAutoScroll] = React.useState(true); - const [lastUpdate, setLastUpdate] = React.useState(''); + const [openMICStatus, setOpenMICStatus] = React.useState({ Name: 'openMIC', Status: 'Loading', Details: [] }); React.useEffect(() => { + if (props.ApplicationType === 'openMIC') { + GetOpenMICHealth() + return + } + if (props.StatsURL == null || props.StatsURL.length == 0) return; setStatus('loading'); @@ -81,31 +87,59 @@ const NodeHealth = (props: IProps) => { }; }, [props.ApplicationName]); + const GetOpenMICHealth = () => { + const h = $.ajax({ + type: "GET", + url: `${homePath}api/DeviceHealthReport/OpenMICStatus`, + contentType: "application/json; charset=utf-8", + dataType: 'json', + cache: false, + async: true + }); + + h.done((d: SC.StatusItem) => { + setOpenMICStatus(d) + }).fail(() => { + setOpenMICStatus({ Status: 'Error', Name: 'openMIC', Details: [{ Status: "Error", Description: "Errors occured in retrieving openMIC health." }] }) + }) + + return function cleanup() { + if (h.abort != null) + h.abort(); + } + } + return ( -
- XDA Stats: - { - status === "error" ? - -
- - - -
- Failed to get openXDA stats. -
-
: - status === "loading" ? - : -
-
-                                    {statInfo}
-                                
-
- } -
+
+ {props.ApplicationType} Health: + + {status === "error" ? + +
+ + + +
+ Failed to get {props.ApplicationType} health. +
+
: + status === "loading" ? + : + props.ApplicationType === 'XDA' ? +
+
+                                {statInfo}
+                            
+
+ : props.ApplicationType === 'openMIC' + ? : + null} + +
) } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx new file mode 100644 index 000000000..160e5a9fa --- /dev/null +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx @@ -0,0 +1,52 @@ +//****************************************************************************************************** +// StatusDetails.tsx - Gbtc +// +// Copyright © 2026, Grid Protection Alliance. All Rights Reserved. +// +// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See +// the NOTICE file distributed with this work for additional information regarding copyright ownership. +// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this +// file except in compliance with the License. You may obtain a copy of the License at: +// +// http://opensource.org/licenses/MIT +// +// Unless agreed to in writing, the subject software distributed under the License is distributed on an +// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the +// License for the specific language governing permissions and limitations. +// +// Code Modification History: +// ---------------------------------------------------------------------------------------------------- +// 04/06/2026 - Natalie Beatty +// Generated original version of source code. +// +//****************************************************************************************************** +import * as React from 'react' +import { SystemCenter } from '../global' +import { ReactIcons } from '@gpa-gemstone/gpa-symbols' +import { GetStatusSymbol, GetStatusItemAlertClass } from './StatusItem' + +interface IProps { + StatusItem: SystemCenter.StatusItem +} + +const StatusDetails = (props: IProps) => { + return ( +
+ {props.StatusItem.Details.length == 0 ? + : props.StatusItem.Details.map((d) => { + return ( +
+
+ {GetStatusSymbol(d.Status)} +
+ {d.Description} +
+
+
+ ) + })} +
+ ) +} + +export default StatusDetails; \ No newline at end of file From 80d3956b3ba067976e09a6fb11ad8a8a8c7cde90 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 6 Apr 2026 15:38:16 -0400 Subject: [PATCH 11/45] condense openMIC AppStatus --- .../DeviceHealthReport/AppStatus.tsx | 26 ++++++++++--------- .../DeviceHealthReport/DeviceHealthReport.tsx | 2 ++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx index da92636ee..e1544e7b3 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx @@ -31,17 +31,17 @@ import { ErrorBoundary } from '@gpa-gemstone/common-pages' interface IOpenMICStatus { Details: { - Status: 'Success' | 'Error' + Status: 'Success' | 'Error' Description: string }[], Status: 'Success' | 'Error' | 'N/A' } -const AppStatus = (props: { Name: string, Endpoint: string }) => { +const AppStatus = (props: { Name: string, Endpoint: string, IsCondensed: boolean }) => { const [isHovered, setIsHovered] = React.useState(false); const [status, setStatus] = React.useState('uninitiated'); - const [appStatusData, setAppStatusData] = React.useState({Status: 'N/A', Details: []}); + const [appStatusData, setAppStatusData] = React.useState({ Status: 'N/A', Details: [] }); React.useEffect(() => { let handle = getAppStatus(); @@ -79,21 +79,23 @@ const AppStatus = (props: { Name: string, Endpoint: string }) => { > {status === 'idle' ? props.Name : null} - +
0} Position={'bottom'} Target={`statusbutton${props.Name}`} > - {appStatusData?.Details == null ? <> : - appStatusData.Details.map((data, index) => ( -
- {GetStatusSymbol(data.Status)} -

{data.Description}

-
+ {appStatusData?.Details == null ? null + : appStatusData.Details.map((data, index) => ( + appStatusData.Details.some(d => d.Status === 'Error') && data.Status === 'Success' && props.IsCondensed ? null // if there is an error, and this detail is a success, skip it. + : !appStatusData.Details.some(d => d.Status === 'Error') && index !== appStatusData.Details.length - 1 && props.IsCondensed ? null // if there are no errors, and this detail is not the last, skip it. + :
+ {GetStatusSymbol(data.Status)} +

{data.Description}

+
)) } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx index 0ceddab45..b8c47c655 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx @@ -192,10 +192,12 @@ const DeviceHealthReport: Application.Types.iByComponent = (props) => {
From 0d6bc5fbf5c80449c861d2bbe04eb7328016512c Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Wed, 8 Apr 2026 10:12:35 -0400 Subject: [PATCH 12/45] fix Stats layout --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx index 199b4a269..5af84e0a4 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx @@ -110,7 +110,7 @@ const NodeHealth = (props: IProps) => { } return ( -
+
{props.ApplicationType} Health: {status === "error" ? From 7b76dbe720ec43aca00a6aa4450547af767eca90 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Wed, 8 Apr 2026 10:22:16 -0400 Subject: [PATCH 13/45] improve console layout --- .../SystemCenter/AppHost/ConsoleWindow.tsx | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx index ee89980bd..bc6a2a181 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx @@ -177,33 +177,36 @@ const ConsoleWindow = (props: IProps) => { }, [props.ConsoleURL]); return ( -
-
-
- -
-
- + <> +
+
+
+ +
+
+ +
-
-
-
-
 setAutoScroll(false)}
-                        onMouseLeave={() => setAutoScroll(true)}
-                    >
-                        {messages.map((m) => 
-                            {m.Message}
-                        )}
-                    
+
+
+
 setAutoScroll(false)}
+                            onMouseLeave={() => setAutoScroll(true)}
+                        >
+                            {messages.map((m) => 
+                                {m.Message}
+                            )}
+                        
+
-
+ +
{
-
+ ) } From 5e175323e98d0d9fcb0d60aba1cc5b032cc95352 Mon Sep 17 00:00:00 2001 From: nbeatty-gpa Date: Thu, 9 Apr 2026 10:10:50 -0400 Subject: [PATCH 14/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx Co-authored-by: Erika Wills Signed-off-by: nbeatty-gpa --- .../TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx index b8c47c655..5ffc54907 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx @@ -195,7 +195,7 @@ const DeviceHealthReport: Application.Types.iByComponent = (props) => { IsCondensed={true} /> From 11ba1c9a9eee46bc2ca043603c7a5ab61eb621f5 Mon Sep 17 00:00:00 2001 From: nbeatty-gpa Date: Thu, 9 Apr 2026 10:11:01 -0400 Subject: [PATCH 15/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx Co-authored-by: Erika Wills Signed-off-by: nbeatty-gpa --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 3e124937b..974fee1b6 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -1,7 +1,7 @@ //****************************************************************************************************** // NodeHealth.tsx - Gbtc // -// Copyright © 2026, Grid Protection Alliance. All Rights Reserved. +// Copyright © 2026, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. @@ -198,7 +198,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys Status={status} HoveredItem={hoveredItem} SetHoveredItem={setHoveredItem} - Name="Remote XDA Connections" + Name="Remote openXDA Connections" />
From acd4657e323251df02d7c080c3787ffa21a57419 Mon Sep 17 00:00:00 2001 From: nbeatty-gpa Date: Thu, 9 Apr 2026 10:11:12 -0400 Subject: [PATCH 16/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx Co-authored-by: Erika Wills Signed-off-by: nbeatty-gpa --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 974fee1b6..5b9ddf876 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -159,7 +159,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys d.Name = 'SCADA' setSCADAStatus(d) }).fail(() => { - setSCADAStatus({ Status: 'Error', Name: 'SCADA Resource', Details: [{ Status: "Error", Description: "Errors occured in retrieving SCADA Resource" }] }) + setSCADAStatus({ Status: 'Error', Name: 'SCADA Resource', Details: [{ Status: "Error", Description: "Errors occurred in retrieving SCADA Resource connection status." }] }) }) return function cleanup() { From b5b41e67656d3248bc97a360daf4bc3df3a9b844 Mon Sep 17 00:00:00 2001 From: nbeatty-gpa Date: Thu, 9 Apr 2026 10:11:22 -0400 Subject: [PATCH 17/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx Co-authored-by: Erika Wills Signed-off-by: nbeatty-gpa --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 5b9ddf876..3defc8dfa 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -137,7 +137,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys d.Name = 'PQI' setPQIStatus(d) }).fail(() => { - setPQIStatus({ Status: 'Error', Name: 'PQI', Details: [{ Status: "Error", Description: "Errors occured in retrieving PQI status" }] }) + setPQIStatus({ Status: 'Error', Name: 'PQI', Details: [{ Status: "Error", Description: "Errors occurred in retrieving PQI connection status." }] }) }) return function cleanup() { From 1ebf109a667624d564317653ab5ab0af319cb4ee Mon Sep 17 00:00:00 2001 From: nbeatty-gpa Date: Thu, 9 Apr 2026 10:11:31 -0400 Subject: [PATCH 18/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx Co-authored-by: Erika Wills Signed-off-by: nbeatty-gpa --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 3defc8dfa..6498022e2 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -114,7 +114,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys d.Name = 'FAWG' setFawgStatus(d) }).fail(() => { - setFawgStatus({ Status: 'Error', Name: 'FAWG', Details: [{ Status: "Error", Description: "Errors occured in retrieving FAWG status" }] }) + setFawgStatus({ Status: 'Error', Name: 'FAWG', Details: [{ Status: "Error", Description: "Errors occurred in retrieving FAWG connection status." }] }) }) return function cleanup() { From 34577e12fddeeb1aed27654e0574f60e78de176f Mon Sep 17 00:00:00 2001 From: nbeatty-gpa Date: Thu, 9 Apr 2026 10:11:41 -0400 Subject: [PATCH 19/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx Co-authored-by: Erika Wills Signed-off-by: nbeatty-gpa --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 6498022e2..719e079a7 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -92,7 +92,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys h.done((statuses: SC.StatusItem[]) => { setRemoteXDAStatus(statuses) }).fail(() => { - setRemoteXDAStatus([{ Status: 'Error', Name: 'Remote XDA Connection', Details: [{ Status: "Error", Description: "Errors occured in retrieving Remote XDA Connection status" }] }]) + setRemoteXDAStatus([{ Status: 'Error', Name: 'Remote XDA Connection', Details: [{ Status: "Error", Description: "Errors occurred in retrieving Remote openXDA Connection status." }] }]) }) return function cleanup() { if (h.abort != null) From f7d8d70c945b0b39d6ac3e91961f2da20f483674 Mon Sep 17 00:00:00 2001 From: nbeatty-gpa Date: Thu, 9 Apr 2026 10:11:51 -0400 Subject: [PATCH 20/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx Co-authored-by: Erika Wills Signed-off-by: nbeatty-gpa --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 719e079a7..000de01e2 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -69,7 +69,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'Sys h.done((statuses: SC.StatusItem[]) => { setExtDBStatus(statuses) }).fail((d) => { - setExtDBStatus([{ Status: 'Error', Name: 'External Database Connections', Details: [{ Status: "Error", Description: "Errors occured in retrieving External DB Connection status" }] }]) + setExtDBStatus([{ Status: 'Error', Name: 'External Database Connections', Details: [{ Status: "Error", Description: "Errors occurred in retrieving External DB Connection status." }] }]) }) From 5a8ec178dedfe234d34c3e231ca05d2b05fbdafb Mon Sep 17 00:00:00 2001 From: Erika Wills Date: Thu, 9 Apr 2026 10:30:05 -0400 Subject: [PATCH 21/45] Update Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Erika Wills --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx index 5af84e0a4..549d712b2 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx @@ -100,7 +100,7 @@ const NodeHealth = (props: IProps) => { h.done((d: SC.StatusItem) => { setOpenMICStatus(d) }).fail(() => { - setOpenMICStatus({ Status: 'Error', Name: 'openMIC', Details: [{ Status: "Error", Description: "Errors occured in retrieving openMIC health." }] }) + setOpenMICStatus({ Status: 'Error', Name: 'openMIC', Details: [{ Status: "Error", Description: "Errors occurred in retrieving openMIC health." }] }) }) return function cleanup() { From 17e4b06959f27c08f09bc68dcddbe7d42b57a136 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 09:24:09 -0400 Subject: [PATCH 22/45] correct comma to semicolon --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx index abdc739c5..919ef9ca3 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx @@ -67,7 +67,7 @@ const AppHost: Application.Types.iByComponent = (props) => { {hosts.map((h) => setConsole(h)} - OpenDetails={() => { setDetails(h), setConsole(h) }} + OpenDetails={() => { setDetails(h); setConsole(h) }} key={h.PingURL} IsSmall={shouldBeSmall} />)} From 94a04a6d5a913021c0151db163f53ca6ac7fa13b Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 09:25:35 -0400 Subject: [PATCH 23/45] make application type nullabel --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 7d4b0f2de..43329e214 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -39,7 +39,7 @@ export interface IProps { StatsURL: string, ConsoleURL: string, ApplicationName: string, - ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD' | 'openMIC', + ApplicationType?: 'SystemCenter' | 'XDA' | 'MiMD' | 'openMIC', Properties: { Name: string, Value: string }[], SetDetails: React.Dispatch> SetConsole: React.Dispatch> From d7022ed2fd774c42e10f461be1694fa1083d5d40 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 09:30:31 -0400 Subject: [PATCH 24/45] remove duplicate application type definitions --- .../Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx | 3 ++- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 2 +- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 3 ++- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx | 2 +- .../SystemCenter/wwwroot/Scripts/TSX/SystemCenter/global.d.ts | 2 ++ 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx index 029275e9a..fb4a5935c 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx @@ -23,6 +23,7 @@ import * as React from 'react'; import { useAppDispatch } from '../hooks'; +import { SystemCenter as SC } from '../global' export interface IHostProperties { Name: string, Value: string } @@ -33,7 +34,7 @@ export interface IHost { StatsURL?: string, ConsoleURL: string, Name: string, - App: 'XDA' | 'MiMD' | 'SystemCenter', + App: SC.ApplicationType, OpenConsole: () => void, OpenDetails: () => void } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 000de01e2..7e194cd1e 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -29,7 +29,7 @@ import { Application, SystemCenter, OpenXDA } from '@gpa-gemstone/application-ty import { SystemCenter as SC } from '../global' import StatusGroup from './StatusGroup' -const NodeConnections = (props: { ApplicationName: string, ApplicationType: 'SystemCenter' | 'MiMD' | 'XDA' | 'openMIC', Properties: { Name: string, Value: string }[] }) => { +const NodeConnections = (props: { ApplicationName: string, ApplicationType: SC.ApplicationType, Properties: { Name: string, Value: string }[] }) => { const [status, setStatus] = React.useState('uninitiated'); const [extDBStatus, setExtDBStatus] = React.useState([{ Name: "Loading...", Status: "Loading", Details: [] }]); const [remoteXDAStatus, setRemoteXDAStatus] = React.useState([{ Name: "Loading...", Status: "Loading", Details: [] }]); diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 43329e214..b6eb059e6 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -29,6 +29,7 @@ import NodeConnections from './NodeConnections'; import NodeHealth from './NodeHealth'; import ConsoleWindow from './ConsoleWindow' import { IHost } from './ApplicationCard'; +import { SystemCenter as SC } from '../global' type tab = 'connections' | 'health' | 'console' @@ -39,7 +40,7 @@ export interface IProps { StatsURL: string, ConsoleURL: string, ApplicationName: string, - ApplicationType?: 'SystemCenter' | 'XDA' | 'MiMD' | 'openMIC', + ApplicationType: SC.ApplicationType, Properties: { Name: string, Value: string }[], SetDetails: React.Dispatch> SetConsole: React.Dispatch> diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx index 549d712b2..958e82787 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx @@ -41,7 +41,7 @@ const statStyle: React.CSSProperties = { export interface IProps { StatsURL: string, ApplicationName: string, - ApplicationType: 'SystemCenter' | 'XDA' | 'MiMD' | 'openMIC', + ApplicationType: SC.ApplicationType, Close: () => void Properties: { Name: string, Value: string }[] } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/global.d.ts b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/global.d.ts index f2eb75457..14afb7e59 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/global.d.ts +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/global.d.ts @@ -65,6 +65,8 @@ export namespace SystemCenter { Content?: (item: IColDatum) => React.ReactNode; } + type ApplicationType = 'XDA' | 'MiMD' | 'SystemCenter' | 'openMIC' | '' + // Todo: There is a pr for this in gemstone, when its merged and published, remove this and ues gemstone version interface SEBrowserSetting extends GemstoneSC.Types.Setting { ApplicationInstance: boolean, Scope: string, Roles: string } From 55c623419af856cc0f6049eb31489ede2fcf2132 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 13:17:38 -0400 Subject: [PATCH 25/45] correct header --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 7e194cd1e..0a68168e1 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -1,5 +1,5 @@ //****************************************************************************************************** -// NodeHealth.tsx - Gbtc +// NodeConnections.tsx - Gbtc // // Copyright © 2026, Grid Protection Alliance. All Rights Reserved. // From 48c370939ff215a4397f7c2a659cbb3aa0b7962e Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 13:18:52 -0400 Subject: [PATCH 26/45] move available tab setting logic into use effect --- .../Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index b6eb059e6..86148cb1c 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -57,9 +57,16 @@ const ApplicationTabs = { const NodeDetails = (props: IProps) => { const [tab, setTab] = React.useState('connections'); - const availableTabs = ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return t.toLowerCase() }) - if (!availableTabs.includes(tab) && availableTabs.length != 0) + const [availableTabs, setAvailableTabs] = React.useState([]) + + React.useEffect(() => { + if (props.ApplicationType === '') { + setAvailableTabs([]) + return + } + setAvailableTabs(ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return t.toLowerCase() })) setTab(availableTabs[0] as tab) + }, [props.ApplicationType]) return ( Date: Thu, 9 Apr 2026 13:43:40 -0400 Subject: [PATCH 27/45] move hasError logic out of tooltip render --- .../TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx index e1544e7b3..e2b16400d 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/AppStatus.tsx @@ -42,6 +42,7 @@ const AppStatus = (props: { Name: string, Endpoint: string, IsCondensed: boolean const [isHovered, setIsHovered] = React.useState(false); const [status, setStatus] = React.useState('uninitiated'); const [appStatusData, setAppStatusData] = React.useState({ Status: 'N/A', Details: [] }); + const [hasError, setHasError] = React.useState(false); React.useEffect(() => { let handle = getAppStatus(); @@ -49,6 +50,7 @@ const AppStatus = (props: { Name: string, Endpoint: string, IsCondensed: boolean handle.done((dt) => { setStatus('idle') setAppStatusData(dt) + setHasError(dt.Details.some(d => d.Status === 'Error')) }).fail((d) => setStatus('error')); return function cleanup() { @@ -88,8 +90,8 @@ const AppStatus = (props: { Name: string, Endpoint: string, IsCondensed: boolean > {appStatusData?.Details == null ? null : appStatusData.Details.map((data, index) => ( - appStatusData.Details.some(d => d.Status === 'Error') && data.Status === 'Success' && props.IsCondensed ? null // if there is an error, and this detail is a success, skip it. - : !appStatusData.Details.some(d => d.Status === 'Error') && index !== appStatusData.Details.length - 1 && props.IsCondensed ? null // if there are no errors, and this detail is not the last, skip it. + hasError && data.Status === 'Success' && props.IsCondensed ? null // if there is an error, and this detail is a success, skip it. + : !hasError && index !== appStatusData.Details.length - 1 && props.IsCondensed ? null // if there are no errors, and this detail is not the last, skip it. :
From 7421b151443d603f447eb4f5b25f38c6fe3ddf90 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 13:44:56 -0400 Subject: [PATCH 28/45] provide defaults for nullable values --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx index 919ef9ca3..7ed2ed541 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/AppHost.tsx @@ -75,12 +75,12 @@ const AppHost: Application.Types.iByComponent = (props) => {
) } From 202a8bd66b6c8a1b2321b8dac7755e801008dbdf Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 13:48:19 -0400 Subject: [PATCH 29/45] return cleanup in openMIC branch --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx index 958e82787..3203de11c 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx @@ -54,8 +54,9 @@ const NodeHealth = (props: IProps) => { React.useEffect(() => { if (props.ApplicationType === 'openMIC') { - GetOpenMICHealth() - return + setStatus('loading') + const cleanup = GetOpenMICHealth() + return cleanup } if (props.StatsURL == null || props.StatsURL.length == 0) return; From 8dfbcbbebfd182eaa50607699d64a0dc73ca746f Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Thu, 9 Apr 2026 13:50:09 -0400 Subject: [PATCH 30/45] add key to child map --- .../Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx index 160e5a9fa..ee68522ce 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusDetails.tsx @@ -33,9 +33,9 @@ const StatusDetails = (props: IProps) => { return (
{props.StatusItem.Details.length == 0 ? - : props.StatusItem.Details.map((d) => { + : props.StatusItem.Details.map((d, i) => { return ( -
+
{GetStatusSymbol(d.Status)}
From 1d5e0e453d332e9ae539d2fd994eb9713a1343ac Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 10 Apr 2026 11:41:54 -0400 Subject: [PATCH 31/45] memoize available tabs --- .../TSX/SystemCenter/AppHost/NodeDetails.tsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 86148cb1c..2028384d0 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -57,17 +57,15 @@ const ApplicationTabs = { const NodeDetails = (props: IProps) => { const [tab, setTab] = React.useState('connections'); - const [availableTabs, setAvailableTabs] = React.useState([]) - React.useEffect(() => { - if (props.ApplicationType === '') { - setAvailableTabs([]) - return - } - setAvailableTabs(ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return t.toLowerCase() })) - setTab(availableTabs[0] as tab) + const availableTabs = React.useMemo(() => { + return ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return { Label: t, Id: t.toLowerCase() } }) }, [props.ApplicationType]) + React.useEffect(() => { + setTab(availableTabs[0].Id as tab) + }, [availableTabs]) + return ( { Title={'Details - ' + props.ApplicationName} >
- setTab(t)} Tabs={ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return { Label: t, Id: t.toLowerCase() } })} /> + setTab(t)} Tabs={availableTabs} />
From 6dbce3790ae9c5557c4e0f94c8fffc5a79e9641a Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 13 Apr 2026 14:34:44 -0400 Subject: [PATCH 32/45] remove RemoteXDAConnections fieldset if there are no remote XDA connections configured --- .../Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx index 0a68168e1..f02e4d972 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx @@ -192,6 +192,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: SC.A
: props.ApplicationType === "XDA" ?
+ {remoteXDAStatus.length == 0 ? null :
-
+ } +
Date: Mon, 13 Apr 2026 14:35:34 -0400 Subject: [PATCH 33/45] remove scrolling from node details modal --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 2028384d0..3fedbea78 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -72,6 +72,7 @@ const NodeDetails = (props: IProps) => { ShowCancel={false} ShowConfirm={false} ShowX={true} Size={'xlg'} CallBack={() => { props.SetDetails(null); setTab('connections') }} Title={'Details - ' + props.ApplicationName} + BodyStyle={{ overflow: 'hidden' } } >
setTab(t)} Tabs={availableTabs} /> From 1825aad7c973d9d7fb53b615d5c1b6e7f2b8e356 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 13 Apr 2026 16:25:18 -0400 Subject: [PATCH 34/45] add scrolling to node health fieldset --- .../SystemCenter/AppHost/ConsoleWindow.tsx | 76 ++++++++++--------- .../TSX/SystemCenter/AppHost/NodeDetails.tsx | 4 +- .../TSX/SystemCenter/AppHost/NodeHealth.tsx | 2 +- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx index bc6a2a181..d9b9b493c 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx @@ -177,50 +177,52 @@ const ConsoleWindow = (props: IProps) => { }, [props.ConsoleURL]); return ( - <> -
-
-
- +
+
+
+
+
+ +
+
+ +
-
- +
+
+
 setAutoScroll(false)}
+                                onMouseLeave={() => setAutoScroll(true)}
+                            >
+                                {messages.map((m) => 
+                                    {m.Message}
+                                )}
+                            
+
-
-
-
 setAutoScroll(false)}
-                            onMouseLeave={() => setAutoScroll(true)}
-                        >
-                            {messages.map((m) => 
-                                {m.Message}
-                            )}
-                        
-
-
-
-
-
-
- setCMD(evt.target.value)} - value={cmd} - /> +
+
+
+ setCMD(evt.target.value)} + value={cmd} + /> +
+
+
+
-
-
-
- +
) } diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 3fedbea78..f73fb7fb2 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -72,12 +72,12 @@ const NodeDetails = (props: IProps) => { ShowCancel={false} ShowConfirm={false} ShowX={true} Size={'xlg'} CallBack={() => { props.SetDetails(null); setTab('connections') }} Title={'Details - ' + props.ApplicationName} - BodyStyle={{ overflow: 'hidden' } } + BodyStyle={{ overflow: 'hidden', height: 'calc(100vh - 210px)', display: 'flex', flexDirection: 'column'} } >
setTab(t)} Tabs={availableTabs} />
-
+
{tab === "connections" ? diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx index 3203de11c..b734a9f2c 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx @@ -111,7 +111,7 @@ const NodeHealth = (props: IProps) => { } return ( -
+
{props.ApplicationType} Health: {status === "error" ? From a7452721b1b4c2611acdc5b1febe04f1364bb5b2 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Tue, 14 Apr 2026 12:29:31 -0400 Subject: [PATCH 35/45] set status according to openMIC status call success --- .../Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx index b734a9f2c..149616be5 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeHealth.tsx @@ -77,7 +77,6 @@ const NodeHealth = (props: IProps) => { // Regex remove wrapping quotes, carriage return, and format \\ to \ setStatInfo(stat.replace(/^\"+|\"+$/g, '').replace(/\\r\\n/g, '\n').replace(/\\\\/g, '\\')); }).fail((_a, _b, e) => { - console.error(e); setStatus('error'); }); }, 5000); @@ -100,8 +99,10 @@ const NodeHealth = (props: IProps) => { h.done((d: SC.StatusItem) => { setOpenMICStatus(d) + setStatus('idle') }).fail(() => { setOpenMICStatus({ Status: 'Error', Name: 'openMIC', Details: [{ Status: "Error", Description: "Errors occurred in retrieving openMIC health." }] }) + setStatus('error') }) return function cleanup() { @@ -130,10 +131,10 @@ const NodeHealth = (props: IProps) => { : props.ApplicationType === 'XDA' ?
-
-                                {statInfo}
-                            
-
+
+                                    {statInfo}
+                                
+
: props.ApplicationType === 'openMIC' ? Date: Tue, 14 Apr 2026 12:32:16 -0400 Subject: [PATCH 36/45] remove unneeded using --- .../SystemCenter/Controllers/SystemCenter/AppHostController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs b/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs index 4f064d7c2..765381061 100644 --- a/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs +++ b/Source/Applications/SystemCenter/Controllers/SystemCenter/AppHostController.cs @@ -33,7 +33,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; -using System.Diagnostics.Metrics; using System.Linq; using System.Net.Http; using System.Text; From d9cd94f01ec81cb06bbbaa10c15a6510f4bbba63 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Tue, 14 Apr 2026 12:39:06 -0400 Subject: [PATCH 37/45] clean up tab selection --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index f73fb7fb2..9421ad2eb 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -47,7 +47,6 @@ export interface IProps { } const ApplicationTabs = { - '': '', 'SystemCenter': 'Connections,Console', 'XDA': 'Connections,Health,Console', 'MiMD': 'Console', @@ -59,10 +58,12 @@ const NodeDetails = (props: IProps) => { const [tab, setTab] = React.useState('connections'); const availableTabs = React.useMemo(() => { + if (!Object.keys(ApplicationTabs).includes(props.ApplicationType)) return [] return ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return { Label: t, Id: t.toLowerCase() } }) }, [props.ApplicationType]) React.useEffect(() => { + if (availableTabs.length == 0) return setTab(availableTabs[0].Id as tab) }, [availableTabs]) From fbf8d3dd279d014faa2dc09091bad0fffd9ee861 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Tue, 14 Apr 2026 12:39:23 -0400 Subject: [PATCH 38/45] add margin to node details --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index 9421ad2eb..bdd52e733 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -80,7 +80,7 @@ const NodeDetails = (props: IProps) => {
-
+
{tab === "connections" ?
Date: Fri, 17 Apr 2026 11:37:37 -0400 Subject: [PATCH 39/45] fix guard against empty details --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusItem.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusItem.tsx index 98f7db793..768da2dc8 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusItem.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/StatusItem.tsx @@ -46,7 +46,7 @@ const StatusItem = (props: {StatusItem: SC.StatusItem, HoveredItem: String, SetH {props.StatusItem.Status === "N/A" ?

{props.StatusItem.Name} is disabled.

: null} {props.StatusItem.Status !== 'Error' ? null :

{props.StatusItem.Details.find((detail) => detail.Status === 'Error')?.Description}

} 0} + Show={props.HoveredItem === props.StatusItem.Name && props.StatusItem.Status !== 'Loading' && (props.StatusItem.Details ?? []).length > 0} Position={'right'} Target={`statusbutton${props.StatusItem.Name}`} > From 30f6c819584e247753aa21eee0efa1ec4af32027 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 17 Apr 2026 11:38:26 -0400 Subject: [PATCH 40/45] move well div --- .../wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx index d9b9b493c..3627c2a10 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx @@ -179,7 +179,6 @@ const ConsoleWindow = (props: IProps) => { return (
-
+
 setAutoScroll(false)}
                                 onMouseLeave={() => setAutoScroll(true)}

From 9202378738513154386d73fdb66d26fc16f1f2b7 Mon Sep 17 00:00:00 2001
From: natalie beatty 
Date: Mon, 20 Apr 2026 14:06:24 -0400
Subject: [PATCH 41/45] make disabled apphost buttons more clear

---
 .../Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx
index fb4a5935c..f4c29faf1 100644
--- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx
+++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ApplicationCard.tsx
@@ -100,7 +100,7 @@ const ApplicationCard = (props: IApplicationCard) => {
                 
- +
From d37eca4691d1beb99e961a422904314d93bcda79 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 20 Apr 2026 14:06:45 -0400 Subject: [PATCH 42/45] improve scrolling and removal of empty status groups --- .../SystemCenter/AppHost/ConsoleWindow.tsx | 32 +++++++++---------- .../SystemCenter/AppHost/NodeConnections.tsx | 18 ++++++----- .../TSX/SystemCenter/AppHost/StatusGroup.tsx | 7 ++-- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx index 3627c2a10..4c21befee 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/ConsoleWindow.tsx @@ -177,23 +177,23 @@ const ConsoleWindow = (props: IProps) => { }, [props.ConsoleURL]); return ( -
-
-
-
- -
-
- -
+
+
+
+
+
-
-
+
+ +
+
+
+
 setAutoScroll(false)}
diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx
index f02e4d972..4ebe9fe2c 100644
--- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx
+++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeConnections.tsx
@@ -69,7 +69,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: SC.A
         h.done((statuses: SC.StatusItem[]) => {
             setExtDBStatus(statuses)
         }).fail((d) => {
-            setExtDBStatus([{ Status: 'Error', Name: 'External Database Connections', Details: [{ Status: "Error", Description: "Errors occurred in retrieving External DB Connection status." }] }])
+            setExtDBStatus([])
         })
 
 
@@ -92,7 +92,7 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: SC.A
         h.done((statuses: SC.StatusItem[]) => {
             setRemoteXDAStatus(statuses)
         }).fail(() => {
-            setRemoteXDAStatus([{ Status: 'Error', Name: 'Remote XDA Connection', Details: [{ Status: "Error", Description: "Errors occurred in retrieving Remote openXDA Connection status." }] }])
+            setRemoteXDAStatus([])
         })
         return function cleanup() {
             if (h.abort != null)
@@ -170,8 +170,9 @@ const NodeConnections = (props: { ApplicationName: string, ApplicationType: SC.A
 
     return (
         props.ApplicationType === 'SystemCenter' ?
-            
-
+
+ {extDBStatus.length == 0 ? null : +
-
+ } +
: props.ApplicationType === "XDA" ? -
+
{remoteXDAStatus.length == 0 ? null : -
+
} -
+
> }) => { return ( -
+
{`${props.Name}:`} {props.StatusItems.map((statusItem, index) => ( - )) - } + ))}
) } From eb9349e5750cf38b4c48cd24f80c9504e624f6f9 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 20 Apr 2026 14:07:09 -0400 Subject: [PATCH 43/45] add pagination information to results message --- .../SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx index 5ffc54907..6e28c80d3 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx @@ -73,7 +73,7 @@ const DeviceHealthReport: Application.Types.iByComponent = (props) => { const settings = useAppSelector(SystemCenterSettingSlice.Data); const settingStatus = useAppSelector(SystemCenterSettingSlice.Status); const [hovered, setHovered] = React.useState(null); - const [pagedData, setPagedData] = React.useState(null); + const [pagedData, setPagedData] = React.useState({TotalRecords: 0, NumberOfPages: 0, Data: '', RecordsPerPage: 0}); const [page, setPage] = React.useState(0); React.useEffect(() => { @@ -165,7 +165,7 @@ const DeviceHealthReport: Application.Types.iByComponent = (props) => {
CollumnList={filterableList} SetFilter={setSearch} Direction={'left'} defaultCollumn={standardSearch} Width={'50%'} Label={'Search'} StorageID="DeviceHealthReportFilter" - ShowLoading={searchState == 'Loading'} ResultNote={searchState == 'Error' ? 'Could not complete Search' : 'Found ' + data.length + ' Meter(s)'} + ShowLoading={searchState == 'Loading'} ResultNote={searchState == 'Error' ? 'Could not complete Search' : ('Displaying Device Health Report(s) ' + (pagedData.TotalRecords > 0 ? (pagedData.RecordsPerPage * page + 1) : 0) + ' - ' + (pagedData.RecordsPerPage * page + data.length)) + ' out of ' + pagedData.TotalRecords} GetEnum={(setOptions, field) => { let handle = null; if (field.type != 'enum' || field.enum == undefined || field.enum.length != 1) From c358ea73fd6232b44d62683977b9aabcdcfa2a3a Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 20 Apr 2026 14:07:25 -0400 Subject: [PATCH 44/45] remove bullets from bad days tooltip --- .../DeviceHealthReport/DeviceHealthReport.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx index 6e28c80d3..160ce5d1e 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/DeviceHealthReport/DeviceHealthReport.tsx @@ -363,18 +363,18 @@ const DeviceHealthReport: Application.Types.iByComponent = (props) => { Position={'bottom'} Target={`badDays${index}`} > -
    {item['MICBadDays'] == null ? null : -
  • +
    {item['MICBadDays'] == null ? null : +

    {`openMIC: ${item['MICBadDays']}`} -

  • +

    } -
  • +

    {`miMD: ${item['MiMDBadDays']}`} -

  • -
  • +

    +

    {`openXDA: ${item['XDABadDays']}`} -

  • -
+

+
) From 2e2e1a5974e35428762d841c792459cef2b51d4d Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Fri, 24 Apr 2026 14:35:30 -0400 Subject: [PATCH 45/45] simplify tab typing --- .../Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx index bdd52e733..7fbf35f8e 100644 --- a/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx +++ b/Source/Applications/SystemCenter/wwwroot/Scripts/TSX/SystemCenter/AppHost/NodeDetails.tsx @@ -47,10 +47,10 @@ export interface IProps { } const ApplicationTabs = { - 'SystemCenter': 'Connections,Console', - 'XDA': 'Connections,Health,Console', - 'MiMD': 'Console', - 'openMIC': 'Health' + 'SystemCenter': [{ Label: 'Connections', Id: 'connections' }, { Label: 'Console', Id: 'console' }], + 'XDA': [{ Label: 'Connections', Id: 'connections' }, { Label: 'Health', Id: 'health' }, { Label: 'Console', Id: 'console' }], + 'MiMD': [{ Label: 'Console', Id: 'console' }], + 'openMIC': [{ Label: 'Health', Id: 'health' }] } const NodeDetails = (props: IProps) => { @@ -59,7 +59,7 @@ const NodeDetails = (props: IProps) => { const availableTabs = React.useMemo(() => { if (!Object.keys(ApplicationTabs).includes(props.ApplicationType)) return [] - return ApplicationTabs[props.ApplicationType ?? ''].split(',').map((t) => { return { Label: t, Id: t.toLowerCase() } }) + return ApplicationTabs[props.ApplicationType] }, [props.ApplicationType]) React.useEffect(() => {