From 21ff522f67f31d4a1479b55d13d0e441a5bf336c Mon Sep 17 00:00:00 2001 From: Nalvazhuthi Date: Mon, 12 May 2025 18:01:45 +0530 Subject: [PATCH] Develop Ui for Version history --- app/src/components/footer/shortcutHelper.tsx | 7 + .../components/icons/ExportCommonIcons.tsx | 19 +++ .../layout/sidebarRight/SideBarRight.tsx | 41 ++++- .../versionHisory/VersionHistory.tsx | 116 +++++++++++++ app/src/components/ui/ModuleToggle.tsx | 6 + app/src/components/ui/menu/menu.tsx | 11 +- app/src/store/store.ts | 12 ++ app/src/styles/layout/sidebar.scss | 155 +++++++++++++++++- 8 files changed, 354 insertions(+), 13 deletions(-) create mode 100644 app/src/components/footer/shortcutHelper.tsx create mode 100644 app/src/components/layout/sidebarRight/versionHisory/VersionHistory.tsx diff --git a/app/src/components/footer/shortcutHelper.tsx b/app/src/components/footer/shortcutHelper.tsx new file mode 100644 index 0000000..af6dacd --- /dev/null +++ b/app/src/components/footer/shortcutHelper.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +const ShortcutHelper = () => { + return
; +}; + +export default ShortcutHelper; diff --git a/app/src/components/icons/ExportCommonIcons.tsx b/app/src/components/icons/ExportCommonIcons.tsx index 9b66849..83505e9 100644 --- a/app/src/components/icons/ExportCommonIcons.tsx +++ b/app/src/components/icons/ExportCommonIcons.tsx @@ -947,3 +947,22 @@ export const ErrorIcon = () => { ); }; + +export const LocationIcon = () => { + return ( + + + + ); +}; diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index 0cff6eb..953aa74 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -13,7 +13,9 @@ import useToggleStore from "../../../store/useUIToggleStore"; import Visualization from "./visualization/Visualization"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; -import { useSelectedFloorItem } from "../../../store/store"; +import useVersionHistoryStore, { + useSelectedFloorItem, +} from "../../../store/store"; import { useSelectedEventData, useSelectedEventSphere, @@ -22,6 +24,7 @@ import GlobalProperties from "./properties/GlobalProperties"; import AsstePropertiies from "./properties/AssetProperties"; import ZoneProperties from "./properties/ZoneProperties"; import EventProperties from "./properties/eventProperties/EventProperties"; +import VersionHistory from "./versionHisory/VersionHistory"; const SideBarRight: React.FC = () => { const { activeModule } = useModuleStore(); @@ -30,6 +33,7 @@ const SideBarRight: React.FC = () => { const { selectedFloorItem } = useSelectedFloorItem(); const { selectedEventData } = useSelectedEventData(); const { selectedEventSphere } = useSelectedEventSphere(); + const { viewVersionHistory, setVersionHistory } = useVersionHistoryStore(); // Reset activeList whenever activeModule changes useEffect(() => { @@ -64,7 +68,10 @@ const SideBarRight: React.FC = () => { className={`sidebar-action-list ${ subModule === "properties" ? "active" : "" }`} - onClick={() => setSubModule("properties")} + onClick={() => { + setSubModule("properties"); + setVersionHistory(false); + }} >
properties
@@ -76,7 +83,10 @@ const SideBarRight: React.FC = () => { className={`sidebar-action-list ${ subModule === "simulations" ? "active" : "" }`} - onClick={() => setSubModule("simulations")} + onClick={() => { + setSubModule("simulations"); + setVersionHistory(false); + }} >
simulations
@@ -85,7 +95,10 @@ const SideBarRight: React.FC = () => { className={`sidebar-action-list ${ subModule === "mechanics" ? "active" : "" }`} - onClick={() => setSubModule("mechanics")} + onClick={() => { + setSubModule("mechanics"); + setVersionHistory(false); + }} >
mechanics
@@ -94,7 +107,10 @@ const SideBarRight: React.FC = () => { className={`sidebar-action-list ${ subModule === "analysis" ? "active" : "" }`} - onClick={() => setSubModule("analysis")} + onClick={() => { + setSubModule("analysis"); + setVersionHistory(false); + }} >
analysis
@@ -103,8 +119,18 @@ const SideBarRight: React.FC = () => { )} )} + + {toggleUI && viewVersionHistory && ( +
+
+ +
+
+ )} + {/* process builder */} {toggleUI && + !viewVersionHistory && subModule === "properties" && activeModule !== "visualization" && !selectedFloorItem && ( @@ -115,6 +141,7 @@ const SideBarRight: React.FC = () => { )} {toggleUI && + !viewVersionHistory && subModule === "properties" && activeModule !== "visualization" && selectedFloorItem && ( @@ -124,7 +151,9 @@ const SideBarRight: React.FC = () => { )} + {toggleUI && + !viewVersionHistory && subModule === "zoneProperties" && (activeModule === "builder" || activeModule === "simulation") && (
@@ -134,7 +163,7 @@ const SideBarRight: React.FC = () => {
)} {/* simulation */} - {toggleUI && activeModule === "simulation" && ( + {toggleUI && !viewVersionHistory && activeModule === "simulation" && ( <> {subModule === "simulations" && (
diff --git a/app/src/components/layout/sidebarRight/versionHisory/VersionHistory.tsx b/app/src/components/layout/sidebarRight/versionHisory/VersionHistory.tsx new file mode 100644 index 0000000..9e49b48 --- /dev/null +++ b/app/src/components/layout/sidebarRight/versionHisory/VersionHistory.tsx @@ -0,0 +1,116 @@ +import React, { useState } from "react"; +import { + AddIcon, + CloseIcon, + KebabIcon, + LocationIcon, +} from "../../../icons/ExportCommonIcons"; + +const VersionHistory = () => { + // Start with only v1.0 + const initialVersions = [ + { + versionName: "v1.0", + timestamp: "April 09, 2025", + savedBy: "Nanni", + }, + ]; + + const [versions, setVersions] = useState(initialVersions); + const [selectedVersion, setSelectedVersion] = useState(initialVersions[0]); + const userName = localStorage.getItem("userName") ?? "Anonymous"; + + // Function to simulate adding a new version + const addNewVersion = () => { + const newVersionNumber = versions.length + 1; + const newVersion = { + versionName: `v${newVersionNumber}.0`, + timestamp: new Date().toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "2-digit", + }), + savedBy: userName, // Simulate user name + }; + + const updated = [newVersion, ...versions]; + setVersions(updated); + setSelectedVersion(newVersion); + }; + + // Handle user selecting a version + const handleSelectVersion = (version: any) => { + setSelectedVersion(version); + const reordered = [version, ...versions.filter((v) => v !== version)]; + setVersions(reordered); + }; + + return ( +
+ {/* Header */} +
+
Version History
+
+ +
+ +
+
+ +
+
+
+ + {/* Shortcut Info */} +
+
i
+
+ Press Ctrl + Alt + S to add to version history while editing +
+
+ + {/* Current Version Display */} +
+
+ +
+
+
+ Current Version ({selectedVersion.versionName}) +
+
+ {versions.length} Saved History +
+
+
+ + {/* Versions List */} +
+ {versions.map((version, index) => ( + + ))} +
+
+ ); +}; + +export default VersionHistory; diff --git a/app/src/components/ui/ModuleToggle.tsx b/app/src/components/ui/ModuleToggle.tsx index a1583e1..63a11ee 100644 --- a/app/src/components/ui/ModuleToggle.tsx +++ b/app/src/components/ui/ModuleToggle.tsx @@ -7,10 +7,12 @@ import { VisualizationIcon, } from "../icons/ExportModuleIcons"; import useToggleStore from "../../store/useUIToggleStore"; +import useVersionHistoryStore from "../../store/store"; const ModuleToggle: React.FC = () => { const { activeModule, setActiveModule } = useModuleStore(); const { setToggleUI } = useToggleStore(); + const { setVersionHistory } = useVersionHistoryStore(); return (
@@ -18,6 +20,7 @@ const ModuleToggle: React.FC = () => { className={`module-list ${activeModule === "builder" ? "active" : ""}`} onClick={() => { setActiveModule("builder"); + setVersionHistory(false); setToggleUI( localStorage.getItem("navBarUi") ? localStorage.getItem("navBarUi") === "true" @@ -36,6 +39,7 @@ const ModuleToggle: React.FC = () => { }`} onClick={() => { setActiveModule("simulation"); + setVersionHistory(false); setToggleUI( localStorage.getItem("navBarUi") ? localStorage.getItem("navBarUi") === "true" @@ -54,6 +58,7 @@ const ModuleToggle: React.FC = () => { }`} onClick={() => { setActiveModule("visualization"); + setVersionHistory(false); setToggleUI( localStorage.getItem("navBarUi") ? localStorage.getItem("navBarUi") === "true" @@ -70,6 +75,7 @@ const ModuleToggle: React.FC = () => { className={`module-list ${activeModule === "market" ? "active" : ""}`} onClick={() => { setActiveModule("market"); + setVersionHistory(false); setToggleUI(false); }} > diff --git a/app/src/components/ui/menu/menu.tsx b/app/src/components/ui/menu/menu.tsx index 39508b6..c5f24a9 100644 --- a/app/src/components/ui/menu/menu.tsx +++ b/app/src/components/ui/menu/menu.tsx @@ -1,6 +1,8 @@ import React, { useState } from "react"; import { ArrowIcon } from "../../icons/ExportCommonIcons"; import { toggleTheme } from "../../../utils/theme"; +import useVersionHistoryStore from "../../../store/store"; +import { useSubModuleStore } from "../../../store/useModuleStore"; interface MenuBarProps { setOpenMenu: (isOpen: boolean) => void; // Function to update menu state @@ -10,6 +12,9 @@ const MenuBar: React.FC = ({ setOpenMenu }) => { const [activeMenu, setActiveMenu] = useState(null); const [activeSubMenu, setActiveSubMenu] = useState(null); + const { viewVersionHistory, setVersionHistory } = useVersionHistoryStore(); + const { subModule, setSubModule } = useSubModuleStore(); + // State to track selection for all menu items const [selectedItems, setSelectedItems] = useState>( {} @@ -23,7 +28,7 @@ const MenuBar: React.FC = ({ setOpenMenu }) => { })); }; - function handleThemeChange(){ + function handleThemeChange() { toggleTheme(); window.location.reload(); } @@ -373,6 +378,10 @@ const MenuBar: React.FC = ({ setOpenMenu }) => { setActiveMenu(null); setActiveSubMenu(null); }} + onClick={() => { + setVersionHistory(true); + setSubModule("properties"); + }} >
Version history
diff --git a/app/src/store/store.ts b/app/src/store/store.ts index 61d84d5..35ccdd5 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -435,3 +435,15 @@ export const useZoneAssetId = create((set) => ({ zoneAssetId: null, setZoneAssetId: (asset) => set({ zoneAssetId: asset }), })); + +interface VersionHistoryState { + viewVersionHistory: boolean; + setVersionHistory: (value: boolean) => void; +} + +const useVersionHistoryStore = create((set) => ({ + viewVersionHistory: false, + setVersionHistory: (value) => set({ viewVersionHistory: value }), +})); + +export default useVersionHistoryStore; diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 4d321d4..efa77a3 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -456,6 +456,144 @@ position: relative; width: 304px; + .version-history-container { + max-height: calc(62vh - 12px); + display: flex; + flex-direction: column; + padding: 0 8px; + gap: 10px; + + .version-history-header { + display: flex; + justify-content: space-between; + align-items: center; + + .version-history-icons { + display: flex; + align-items: center; + gap: 6px; + + .kebab-icon { + transform: rotate(90deg); + } + } + } + + .version-history-shortcut-info { + display: flex; + gap: 6px; + border: 1px solid var(--border-color); + + background: var(--background-color); + padding: 10px 8px; + border-radius: 13px; + + .info-icon { + width: 12px; + height: 12px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; + border: 1px solid var(--border-color); + padding: 4px; + font-size: 10px; + } + + .shortcut-text { + color: var(--text-disabled); + } + } + + .version-history-location { + display: flex; + align-items: center; + gap: 6px; + + .location-details { + display: flex; + flex-direction: column; + gap: 4px; + + .saved-history-count { + font-size: var(--font-size-tiny) + } + } + } + + .saved-versions-list { + padding-top: 16px; + display: flex; + flex-direction: column; + gap: 20px; + + .saved-version { + display: flex; + align-items: center; + gap: 12px; + + .version-name { + + background: var(--background-color); + border: 1px solid var(--border-color); + color: var(--text-color); + border-radius: 13px; + padding: 4px 8px; + position: relative; + /* Ensure position relative for ::after */ + } + + &:not(:first-child) .version-name::after { + content: ""; + position: absolute; + top: -35px; + left: 50%; + transform: translateX(-50%); + width: 1px; + height: 32px; + background-color: var(--text-disabled); + } + + .version-details { + display: flex; + flex-direction: column; + gap: 6px; + + .saved-by { + display: flex; + align-items: center; + gap: 6px; + + .user-profile { + + background: var(--background-color-accent); + color: var(--text-button-color); + width: 20px; + height: 20px; + border-radius: 50%; + + display: flex; + justify-content: center; + align-items: center; + text-transform: uppercase; + } + + .user-name { + text-transform: capitalize; + + } + } + + .timestamp { + text-align: start; + } + } + } + } + + + } + .no-event-selected { color: #666; padding: 16px; @@ -513,6 +651,7 @@ max-height: 60vh; .sidebar-right-content-container { + .dataSideBar { .inputs-wrapper { display: flex; @@ -995,6 +1134,7 @@ margin: 6px 0; padding-left: 16px; position: relative; + &::after { content: "↶"; rotate: -90deg; @@ -1009,6 +1149,7 @@ top: 0; left: 4px; } + &:last-child { &::after { display: none; @@ -1462,11 +1603,9 @@ width: 100%; height: 100%; font-size: var(--font-size-regular); - background: linear-gradient( - 0deg, - rgba(37, 24, 51, 0) 0%, - rgba(52, 41, 61, 0.5) 100% - ); + background: linear-gradient(0deg, + rgba(37, 24, 51, 0) 0%, + rgba(52, 41, 61, 0.5) 100%); pointer-events: none; backdrop-filter: blur(8px); opacity: 0; @@ -1519,6 +1658,7 @@ .sidebar-right-wrapper.open { height: fit-content; animation: openSidebar 0.2s linear; + .sidebar-right-container, .sidebar-left-container { opacity: 0; @@ -1530,6 +1670,7 @@ from { opacity: 0; } + to { opacity: 1; } @@ -1539,6 +1680,7 @@ from { height: 60%; } + to { height: 52px; } @@ -1548,7 +1690,8 @@ from { height: 52px; } + to { height: 60%; } -} +} \ No newline at end of file