diff --git a/src/components/shared/Entity/Details/Logs/Status/SectionFormatter.tsx b/src/components/shared/Entity/Details/Logs/Status/SectionFormatter.tsx
new file mode 100644
index 000000000..a9ef28926
--- /dev/null
+++ b/src/components/shared/Entity/Details/Logs/Status/SectionFormatter.tsx
@@ -0,0 +1,42 @@
+import { Box, ToggleButtonGroup } from '@mui/material';
+import OutlinedToggleButton from 'components/shared/buttons/OutlinedToggleButton';
+import { outlinedToggleButtonGroupStyling } from 'context/Theme';
+import { useIntl } from 'react-intl';
+import { useEntityStatusStore } from 'stores/EntityStatus/Store';
+
+export default function SectionFormatter() {
+ const intl = useIntl();
+
+ const format = useEntityStatusStore((state) => state.format);
+ const setFormat = useEntityStatusStore((state) => state.setFormat);
+
+ return (
+
+
+ setFormat(value, 'code')}
+ >
+ {intl.formatMessage({
+ id: 'details.ops.status.cta.formatted',
+ })}
+
+
+ setFormat(value, 'dashboard')}
+ >
+ {intl.formatMessage({ id: 'details.ops.status.cta.raw' })}
+
+
+
+ );
+}
diff --git a/src/components/shared/Entity/Details/Logs/Status/SectionViews.tsx b/src/components/shared/Entity/Details/Logs/Status/SectionViews.tsx
new file mode 100644
index 000000000..25b4ecc5e
--- /dev/null
+++ b/src/components/shared/Entity/Details/Logs/Status/SectionViews.tsx
@@ -0,0 +1,34 @@
+import { Divider, Typography } from '@mui/material';
+import ControllerStatusHistoryTable from 'components/tables/ControllerStatusHistory';
+import { useIntl } from 'react-intl';
+import { useEntityStatusStore } from 'stores/EntityStatus/Store';
+import Overview from './Overview';
+import StatusResponseViewer from './StatusResponseViewer';
+
+export default function SectionViews() {
+ const intl = useIntl();
+
+ const format = useEntityStatusStore((state) => state.format);
+
+ if (format === 'dashboard') {
+ return (
+ <>
+
+
+
+
+
+ {intl.formatMessage({
+ id: 'details.ops.status.table.header',
+ })}
+
+
+
+ >
+ );
+ } else {
+ return ;
+ }
+}
diff --git a/src/components/shared/Entity/Details/Logs/Status/StatusResponseViewer.tsx b/src/components/shared/Entity/Details/Logs/Status/StatusResponseViewer.tsx
new file mode 100644
index 000000000..cdffcb3c3
--- /dev/null
+++ b/src/components/shared/Entity/Details/Logs/Status/StatusResponseViewer.tsx
@@ -0,0 +1,64 @@
+import { Editor } from '@monaco-editor/react';
+import { Box, Divider, Paper, useTheme } from '@mui/material';
+import { MonacoEditorSkeleton } from 'components/editor/MonacoEditor/EditorSkeletons';
+import { editorToolBarSx } from 'context/Theme';
+import * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api';
+import { useRef } from 'react';
+import { logRocketConsole } from 'services/shared';
+import { stringifyJSON } from 'services/stringify';
+import { useEntityStatusStore } from 'stores/EntityStatus/Store';
+import { DEFAULT_TOOLBAR_HEIGHT } from 'utils/editor-utils';
+import { hasLength } from 'utils/misc-utils';
+
+const EDITOR_HEIGHT = 400;
+
+export default function StatusResponseViewer() {
+ const theme = useTheme();
+ const editorRef = useRef(
+ null
+ );
+
+ const response = useEntityStatusStore((state) => state.response);
+
+ if (response) {
+ return (
+
+
+
+
+
+ {
+ logRocketConsole('handlers:mount');
+ editorRef.current = editor;
+ }}
+ options={{
+ readOnly: true,
+ minimap: {
+ enabled: false,
+ },
+ }}
+ path={
+ hasLength(response.catalog_name)
+ ? response.catalog_name
+ : 'preset_status_path'
+ }
+ saveViewState={false}
+ theme={theme.palette.mode === 'light' ? 'vs' : 'vs-dark'}
+ value={stringifyJSON(response)}
+ />
+
+ );
+ } else {
+ return ;
+ }
+}
diff --git a/src/components/shared/Entity/Details/Logs/Status/index.tsx b/src/components/shared/Entity/Details/Logs/Status/index.tsx
index 6f3e9f344..261e78eb8 100644
--- a/src/components/shared/Entity/Details/Logs/Status/index.tsx
+++ b/src/components/shared/Entity/Details/Logs/Status/index.tsx
@@ -1,13 +1,12 @@
-import { Box, Button, Divider, Stack, Typography } from '@mui/material';
-import ControllerStatusHistoryTable from 'components/tables/ControllerStatusHistory';
+import { Box, Button, Stack, Typography } from '@mui/material';
import useEntityStatus from 'hooks/entityStatus/useEntityStatus';
import useGlobalSearchParams, {
GlobalSearchParams,
} from 'hooks/searchParams/useGlobalSearchParams';
import { Refresh } from 'iconoir-react';
import { useIntl } from 'react-intl';
-import { isEntityControllerStatus } from 'utils/entityStatus-utils';
-import Overview from './Overview';
+import SectionFormatter from './SectionFormatter';
+import SectionViews from './SectionViews';
export default function Status() {
const catalogName = useGlobalSearchParams(GlobalSearchParams.CATALOG_NAME);
@@ -18,55 +17,44 @@ export default function Status() {
return (
-
-
-
- {intl.formatMessage({
- id: 'details.ops.status.header',
- })}
-
-
- }
- onClick={() => refresh()}
- disabled={data === undefined}
+
+
+
- {intl.formatMessage({ id: 'cta.refresh' })}
-
-
-
-
- This is a placeholder description for this section that is
- used to mock the Account Access tab of the Admin page.
-
-
-
-
-
-
+
+ {intl.formatMessage({
+ id: 'details.ops.status.header',
+ })}
+
+
+ }
+ onClick={() => refresh()}
+ disabled={data === undefined}
+ >
+ {intl.formatMessage({ id: 'cta.refresh' })}
+
+
+
+
+ This is a placeholder description for this section that
+ is used to mock the Account Access tab of the Admin
+ page.
+
+
-
- {intl.formatMessage({
- id: 'details.ops.status.table.header',
- })}
-
+
+
-
+
);
}
diff --git a/src/components/tables/ControllerStatusHistory/index.tsx b/src/components/tables/ControllerStatusHistory/index.tsx
index e05c00b26..2fbf4ca8c 100644
--- a/src/components/tables/ControllerStatusHistory/index.tsx
+++ b/src/components/tables/ControllerStatusHistory/index.tsx
@@ -2,10 +2,13 @@ import { Box, Table, TableContainer } from '@mui/material';
import EntityTableBody from 'components/tables/EntityTable/TableBody';
import EntityTableHeader from 'components/tables/EntityTable/TableHeader';
import { useDisplayTableColumns } from 'context/TableSettings';
+import { PublicationInfo } from 'deps/control-plane/types';
import { useEffect, useMemo, useState } from 'react';
import { useIntl } from 'react-intl';
+import { useEntityStatusStore } from 'stores/EntityStatus/Store';
import { TablePrefixes } from 'stores/Tables/hooks';
import { SortDirection, TableColumns, TableState, TableStatuses } from 'types';
+import { isEntityControllerStatus } from 'utils/entityStatus-utils';
import Rows from './Rows';
import { TableProps } from './types';
@@ -41,11 +44,18 @@ const evaluateColumnsToShow = (columnsToHide: string[]) =>
);
export default function ControllerStatusHistoryTable({
- history,
serverErrorExists,
}: TableProps) {
const intl = useIntl();
+ const history: PublicationInfo[] | null | undefined = useEntityStatusStore(
+ (state) =>
+ state.response?.controller_status &&
+ isEntityControllerStatus(state.response.controller_status)
+ ? state.response.controller_status.publications?.history
+ : []
+ );
+
const [tableState, setTableState] = useState({
status: TableStatuses.LOADING,
});
@@ -66,9 +76,9 @@ export default function ControllerStatusHistoryTable({
};
useEffect(() => {
- if (history === null) {
+ if (!history) {
setTableState({ status: TableStatuses.LOADING });
- } else if (history && history.length > 0) {
+ } else if (history.length > 0) {
setTableState({
status: TableStatuses.DATA_FETCHED,
});
diff --git a/src/components/tables/ControllerStatusHistory/types.ts b/src/components/tables/ControllerStatusHistory/types.ts
index 5e99a0401..b038536df 100644
--- a/src/components/tables/ControllerStatusHistory/types.ts
+++ b/src/components/tables/ControllerStatusHistory/types.ts
@@ -12,6 +12,5 @@ export interface RowsProps {
}
export interface TableProps {
- history: PublicationInfo[] | null | undefined;
serverErrorExists: boolean;
}
diff --git a/src/lang/en-US/Details.ts b/src/lang/en-US/Details.ts
index f30db2420..7c92d0ffd 100644
--- a/src/lang/en-US/Details.ts
+++ b/src/lang/en-US/Details.ts
@@ -10,6 +10,8 @@ export const Details: Record = {
'details.history.noPublications': `No publications were found.`,
'details.ops.status.header': `Status`,
+ 'details.ops.status.cta.formatted': `Dashboard`,
+ 'details.ops.status.cta.raw': `Code`,
'details.ops.status.overview.autoDiscovery.header': `Auto Discovery`,
'details.ops.status.overview.autoDiscovery.subheaderFirstFailure': `First Failed`,
'details.ops.status.overview.autoDiscovery.subheaderLastSuccess': `Last Success`,
diff --git a/src/stores/EntityStatus/Store.ts b/src/stores/EntityStatus/Store.ts
index ad129318c..083371ee3 100644
--- a/src/stores/EntityStatus/Store.ts
+++ b/src/stores/EntityStatus/Store.ts
@@ -4,7 +4,11 @@ import { create, StoreApi } from 'zustand';
import { devtools, NamedSet } from 'zustand/middleware';
import { EntityStatusState } from './types';
-const getInitialStateData = (): Pick => ({
+const getInitialStateData = (): Pick<
+ EntityStatusState,
+ 'format' | 'response'
+> => ({
+ format: 'dashboard',
response: null,
});
@@ -14,6 +18,16 @@ const getInitialState = (
): EntityStatusState => ({
...getInitialStateData(),
+ setFormat: (value, invertedValue) => {
+ set(
+ produce((state: EntityStatusState) => {
+ state.format = state.format === value ? invertedValue : value;
+ }),
+ false,
+ 'Format set'
+ );
+ },
+
setResponse: (value) => {
set(
produce((state: EntityStatusState) => {
diff --git a/src/stores/EntityStatus/types.ts b/src/stores/EntityStatus/types.ts
index 95c27cdd6..b9992083c 100644
--- a/src/stores/EntityStatus/types.ts
+++ b/src/stores/EntityStatus/types.ts
@@ -3,4 +3,10 @@ import { EntityStatusResponse } from 'deps/control-plane/types';
export interface EntityStatusState {
response: EntityStatusResponse | null;
setResponse: (value: EntityStatusResponse) => void;
+
+ format: 'code' | 'dashboard';
+ setFormat: (
+ value: EntityStatusState['format'],
+ invertedValue: EntityStatusState['format']
+ ) => void;
}