-
setActiveTab("live")}>
- Live
+
+ {options.map((option) => (
+
setActiveTab(option.value)}
+ >
+ {activeTab === option.value && }
+ {option.label}
-
setActiveTab("final")}>
- Final
-
-
+ ))}
);
};
diff --git a/frontend/src/modules/Data/components/JSONEditor.module.scss b/frontend/src/modules/Data/components/JSONEditor.module.scss
index f91cc254..b8069c56 100644
--- a/frontend/src/modules/Data/components/JSONEditor.module.scss
+++ b/frontend/src/modules/Data/components/JSONEditor.module.scss
@@ -14,6 +14,18 @@
line-height: normal;
}
+.titleRow {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-top: 10px;
+ padding-bottom: 5px;
+}
+
+.titleNoMargin {
+ margin: 0;
+}
+
.switchWrapper {
display: flex;
vertical-align: middle;
diff --git a/frontend/src/modules/Data/components/JSONEditor.tsx b/frontend/src/modules/Data/components/JSONEditor.tsx
index d365ec85..2b870eb0 100644
--- a/frontend/src/modules/Data/components/JSONEditor.tsx
+++ b/frontend/src/modules/Data/components/JSONEditor.tsx
@@ -1,4 +1,6 @@
import React, { ChangeEvent, useEffect, useState } from "react";
+/* eslint-disable css-modules/no-unused-class */
+import styles from "./JSONEditor.module.scss";
import jp from "jsonpath";
import { defineDataType, JsonViewer, Path } from "@textea/json-viewer";
import InputField from "../../../common/ui-components/common/Input/InputField";
@@ -137,7 +139,19 @@ export const JSONEditor = ({ title, jsonDataProp, height, showSearch = true, tog
}}
>
{!toggleSwitch &&
{title}
}
- {toggleSwitch &&
}
+ {toggleSwitch && (
+
+
{title}
+
+
+ )}
{showSearch && (
handleSearch(event.target.value, event)}>
)}
diff --git a/frontend/src/modules/GraphLibrary/GraphLibrary.module.scss b/frontend/src/modules/GraphLibrary/GraphLibrary.module.scss
index cd169d52..a965233f 100644
--- a/frontend/src/modules/GraphLibrary/GraphLibrary.module.scss
+++ b/frontend/src/modules/GraphLibrary/GraphLibrary.module.scss
@@ -30,6 +30,14 @@
.buttonWrapper {
align-content: center;
+
+ &:hover {
+ opacity: 0.8;
+ }
+
+ &:active {
+ opacity: 0.6;
+ }
}
.listWrapper {
diff --git a/frontend/src/modules/GraphLibrary/components/GraphElement/GraphElement.tsx b/frontend/src/modules/GraphLibrary/components/GraphElement/GraphElement.tsx
index 46af5c2e..6bd2b3da 100644
--- a/frontend/src/modules/GraphLibrary/components/GraphElement/GraphElement.tsx
+++ b/frontend/src/modules/GraphLibrary/components/GraphElement/GraphElement.tsx
@@ -39,7 +39,7 @@ export const GraphElement: React.FC
= ({ calibrat
setLastRunInfo,
fetchWorkflowGraph,
} = useGraphContext();
- const { openTab } = useFlexLayoutContext();
+ const { openTab, setGraphTab } = useFlexLayoutContext();
const updateParameter = (paramKey: string, newValue: boolean | number | string, workflow?: NodeDTO | GraphWorkflow) => {
const updatedParameters = {
@@ -121,6 +121,7 @@ export const GraphElement: React.FC = ({ calibrat
const response = await GraphLibraryApi.submitWorkflow(selectedWorkflowName, transformDataForSubmit());
if (response.isOk) {
openTab("graph-status");
+ setGraphTab("active");
} else {
setErrorObject(response.error);
}
diff --git a/frontend/src/modules/GraphLibrary/index.tsx b/frontend/src/modules/GraphLibrary/index.tsx
index 0eb620c9..736cc75b 100644
--- a/frontend/src/modules/GraphLibrary/index.tsx
+++ b/frontend/src/modules/GraphLibrary/index.tsx
@@ -5,7 +5,7 @@ import { GraphContextProvider, useGraphContext } from "./context/GraphContext";
import { GraphList } from "./components/GraphList";
import { SelectionContextProvider } from "../common/context/SelectionContext";
import { useFlexLayoutContext } from "../../routing/flexLayout/FlexLayoutContext";
-import BlueButton from "../../ui-lib/components/Button/BlueButton";
+import RefreshIcon from "../../ui-lib/Icons/RefreshIcon";
export const GraphLibrary = () => {
const { fetchAllCalibrationGraphs } = useGraphContext();
@@ -13,7 +13,7 @@ export const GraphLibrary = () => {
const GraphLibraryTopBarRefreshButton = () => {
return (
- fetchAllCalibrationGraphs(true)}>Refresh
+
);
};
diff --git a/frontend/src/modules/Nodes/NodesPage.module.scss b/frontend/src/modules/Nodes/NodesPage.module.scss
index c33e63ed..b0f2760b 100644
--- a/frontend/src/modules/Nodes/NodesPage.module.scss
+++ b/frontend/src/modules/Nodes/NodesPage.module.scss
@@ -57,6 +57,14 @@
display: flex;
background-color: #28292F;
align-self: center;
+
+ &:hover {
+ opacity: 0.8;
+ }
+
+ &:active {
+ opacity: 0.6;
+ }
}
.nodeElementListWrapper {
diff --git a/frontend/src/modules/Nodes/index.tsx b/frontend/src/modules/Nodes/index.tsx
index 23e038a9..f1fb5fe6 100644
--- a/frontend/src/modules/Nodes/index.tsx
+++ b/frontend/src/modules/Nodes/index.tsx
@@ -6,8 +6,8 @@ import { NodeElementList } from "./components/NodeElement/NodeElementList";
import { RunningJob } from "./components/RunningJob/RunningJob";
import { Results } from "./components/Results/Results";
import { SelectionContextProvider } from "../common/context/SelectionContext";
-import BlueButton from "../../ui-lib/components/Button/BlueButton";
import { useFlexLayoutContext } from "../../routing/flexLayout/FlexLayoutContext";
+import RefreshIcon from "../../ui-lib/Icons/RefreshIcon";
export const NodesPage = () => {
const { allNodes, runningNodeInfo, fetchAllNodes } = useNodesContext();
@@ -15,7 +15,7 @@ export const NodesPage = () => {
const NodeTopBarRefreshButton = () => {
return (
- fetchAllNodes()}>Refresh
+
);
};
diff --git a/frontend/src/modules/SidebarMenu/SidebarMenu.tsx b/frontend/src/modules/SidebarMenu/SidebarMenu.tsx
index 6de49f2f..f0ed1ab5 100644
--- a/frontend/src/modules/SidebarMenu/SidebarMenu.tsx
+++ b/frontend/src/modules/SidebarMenu/SidebarMenu.tsx
@@ -11,10 +11,12 @@ import QUAlibrateLogoIcon from "../../ui-lib/Icons/QUAlibrateLogoIcon";
import QUAlibrateLogoSmallIcon from "../../ui-lib/Icons/QualibrateLogoSmall";
import ExpandSideMenuIcon from "../../ui-lib/Icons/ExpandSideMenuIcon";
import CollapseSideMenuIcon from "../../ui-lib/Icons/CollapseSideMenuIcon";
+import { useFlexLayoutContext } from "../../routing/flexLayout/FlexLayoutContext";
const SidebarMenu: React.FunctionComponent = () => {
const { pinSideMenu } = useContext(GlobalThemeContext) as GlobalThemeContextState;
const [minify, setMinify] = useState(true);
+ const { openTab, graphTab } = useFlexLayoutContext();
const [selectedMenuItem, setSelectedMenuItem] = useState(NODES_KEY);
const containerClassName = classNames(styles.sidebarMenu, minify ? styles.collapsed : styles.expanded);
@@ -34,19 +36,28 @@ const SidebarMenu: React.FunctionComponent = () => {
{minify ? : }
-
-
- {menuItems.map((item) => (
+
+
+ {menuItems.filter((item) => !item.hidden).map((item) => {
+ const handleClick = () => {
+ setSelectedMenuItem(item.keyId);
+ if (item.keyId === "graph-library") {
+ openTab(graphTab === "run" ? "graph-library" : "graph-status");
+ }
+ };
+
+ return (
+ );
+ })}
+
{bottomMenuItems.map((item) => {
diff --git a/frontend/src/modules/TopbarMenu/TitleBarGraphCard/TitleBarGraphCard.tsx b/frontend/src/modules/TopbarMenu/TitleBarGraphCard/TitleBarGraphCard.tsx
index d5aa7f2b..c32f6fc1 100644
--- a/frontend/src/modules/TopbarMenu/TitleBarGraphCard/TitleBarGraphCard.tsx
+++ b/frontend/src/modules/TopbarMenu/TitleBarGraphCard/TitleBarGraphCard.tsx
@@ -13,6 +13,7 @@ import { SnapshotsApi } from "../../Snapshots/api/SnapshotsApi";
import { GraphItem, useWebSocketData } from "../../../contexts/WebSocketContext";
const TitleBarGraphCard: React.FC = () => {
+ const { openTab, setGraphTab } = useFlexLayoutContext();
const { runStatus } = useWebSocketData();
const [node, setNode] = useState
(fallbackNode);
const [graph, setGraph] = useState(fallbackGraph);
@@ -28,9 +29,12 @@ const TitleBarGraphCard: React.FC = () => {
}
}, [runStatus]);
- const { openTab } = useFlexLayoutContext();
- const handleClick = () => openTab(graph.status === "pending" ? "graph-library" : "graph-status");
-
+ const handleClick = () => {
+ const isPending = graph.status === "pending";
+ setGraphTab(isPending ? "run" : "active");
+ openTab(isPending ? "graph-library" : "graph-status");
+ };
+
const renderElapsedTime = (time: number) => (
diff --git a/frontend/src/modules/TopbarMenu/TitleBarMenu.tsx b/frontend/src/modules/TopbarMenu/TitleBarMenu.tsx
index abcc53be..b30bfbc9 100644
--- a/frontend/src/modules/TopbarMenu/TitleBarMenu.tsx
+++ b/frontend/src/modules/TopbarMenu/TitleBarMenu.tsx
@@ -4,13 +4,38 @@ import { useFlexLayoutContext } from "../../routing/flexLayout/FlexLayoutContext
import modulesMap from "../../routing/ModulesRegistry";
import PageName from "../../common/ui-components/common/Page/PageName";
import TitleBarGraphCard from "./TitleBarGraphCard/TitleBarGraphCard";
+import ToggleSwitch from "../../common/ui-components/common/ToggleSwitch/ToggleSwitch";
const TitleBarMenu: React.FC = () => {
- const { activeTab, topBarAdditionalComponents } = useFlexLayoutContext();
+ const { activeTab, topBarAdditionalComponents, openTab, graphTab, setGraphTab } = useFlexLayoutContext();
+
+ const handleTabChange = (value: string) => {
+ setGraphTab(value);
+ if (value === "run") openTab("graph-library");
+ else openTab("graph-status");
+ };
+
return (
-
{modulesMap[activeTab ?? ""]?.menuItem?.title ?? ""}
- {topBarAdditionalComponents && topBarAdditionalComponents[activeTab ?? ""]}
+
+
+
{modulesMap[activeTab ?? ""]?.menuItem?.title ?? ""}
+
+ {(activeTab === "graph-library" || activeTab === "graph-status") && (
+
+ )}
+
+ {topBarAdditionalComponents && topBarAdditionalComponents[activeTab ?? ""]}
+
+
+
diff --git a/frontend/src/modules/TopbarMenu/styles/TitleBarMenu.module.scss b/frontend/src/modules/TopbarMenu/styles/TitleBarMenu.module.scss
index 1c8cf838..76ea19ee 100644
--- a/frontend/src/modules/TopbarMenu/styles/TitleBarMenu.module.scss
+++ b/frontend/src/modules/TopbarMenu/styles/TitleBarMenu.module.scss
@@ -14,11 +14,22 @@
.menuCardsWrapper {
display: flex;
+ align-items: center;
+ justify-content: flex-end;
flex-wrap: wrap;
gap: 12px;
- margin-left: auto;
- justify-content: flex-end;
padding-right: 25px;
margin-right: 25px;
}
+.topBarRow {
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 10px;
+}
+
+.titleAndControls {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
diff --git a/frontend/src/routing/ModulesRegistry.ts b/frontend/src/routing/ModulesRegistry.ts
index 3abdde28..340061ea 100644
--- a/frontend/src/routing/ModulesRegistry.ts
+++ b/frontend/src/routing/ModulesRegistry.ts
@@ -52,6 +52,7 @@ export type Module = {
path?: string;
dataCy?: string;
};
+ hidden?: boolean;
// onClick?: () => void;
};
@@ -86,7 +87,7 @@ export const ModulesRegistry: Array
= [
Component: CalibrationGraph,
menuItem: {
sideBarTitle: "Graph Library",
- title: "Run calibration graph",
+ title: "Calibration graph",
icon: GraphLibraryIcon,
dataCy: cyKeys.CALIBRATION_TAB,
},
@@ -97,10 +98,11 @@ export const ModulesRegistry: Array = [
Component: GraphStatus,
menuItem: {
sideBarTitle: "Graph Status",
- title: "Graph Status",
+ title: "Calibration graph",
icon: GraphStatusIcon,
dataCy: cyKeys.NODES_TAB,
},
+ hidden: true,
},
{
keyId: DATA_KEY,
diff --git a/frontend/src/routing/flexLayout/FlexLayoutContext.tsx b/frontend/src/routing/flexLayout/FlexLayoutContext.tsx
index 0c575b91..d6681515 100644
--- a/frontend/src/routing/flexLayout/FlexLayoutContext.tsx
+++ b/frontend/src/routing/flexLayout/FlexLayoutContext.tsx
@@ -18,6 +18,8 @@ interface IFlexLayoutContext {
setTopBarAdditionalComponents: (a: { [id: string]: React.JSX.Element } | undefined) => void;
selectedPageName: ModuleKey | null;
setSelectedPageName: (a: ModuleKey | null) => void;
+ graphTab: string;
+ setGraphTab: (tab: string) => void;
}
const FlexLayoutContext = React.createContext(null);
@@ -38,6 +40,7 @@ export function FlexLayoutContextProvider(props: PropsWithChildren(undefined);
const [selectedPageName, setSelectedPageName] = useState(null);
+ const [graphTab, setGraphTab] = useState("run");
useEffect(() => {
// openTab("nodes");
@@ -47,10 +50,10 @@ export function FlexLayoutContextProvider(props: PropsWithChildren {
if (tab === "graph-status") {
setSelectedPageName("graph-status");
- } else if (tab === "nodes") {
- setSelectedPageName("nodes");
} else if (tab === "graph-library") {
setSelectedPageName("graph-library");
+ } else if (tab === "nodes") {
+ setSelectedPageName("nodes");
} else if (tab === "data") {
setSelectedPageName("data");
} else {
@@ -108,6 +111,8 @@ export function FlexLayoutContextProvider(props: PropsWithChildren
{children}
diff --git a/frontend/src/ui-lib/Icons/GraphLibraryIcon.tsx b/frontend/src/ui-lib/Icons/GraphLibraryIcon.tsx
index faab6479..ec0817ef 100644
--- a/frontend/src/ui-lib/Icons/GraphLibraryIcon.tsx
+++ b/frontend/src/ui-lib/Icons/GraphLibraryIcon.tsx
@@ -20,10 +20,6 @@ const GraphLibraryIcon: React.FC<{ width?: number; height?: number; className?:
-
diff --git a/frontend/src/ui-lib/Icons/RefreshIcon.tsx b/frontend/src/ui-lib/Icons/RefreshIcon.tsx
new file mode 100644
index 00000000..b0cbc896
--- /dev/null
+++ b/frontend/src/ui-lib/Icons/RefreshIcon.tsx
@@ -0,0 +1,34 @@
+import React from "react";
+
+const RefreshButton: React.FC<{ onClick?: () => void }> = ({ onClick }) => {
+ return (
+
+ );
+};
+
+export default RefreshButton;