From eab46d424e97b5fd45ca66235788373b80d9714a Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Fri, 11 Jul 2025 15:58:38 -0700 Subject: [PATCH 01/10] Add CanvasHeader along with sub components CanvasHeaderNav, SearchBar, SettingsButton --- README.md | 20 --------------- client/package-lock.json | 1 + client/src/App.jsx | 25 ++++++++++++++++--- client/src/components/CanvasHeader.jsx | 30 +++++++++++++++++++++++ client/src/components/CanvasHeaderNav.jsx | 22 +++++++++++++++++ client/src/components/SearchBar.jsx | 10 ++++++++ client/src/components/SettingsButton.jsx | 25 +++++++++++++++++++ client/src/components/Widget.jsx | 7 +++++- 8 files changed, 116 insertions(+), 24 deletions(-) delete mode 100644 README.md create mode 100644 client/src/components/CanvasHeader.jsx create mode 100644 client/src/components/CanvasHeaderNav.jsx create mode 100644 client/src/components/SearchBar.jsx create mode 100644 client/src/components/SettingsButton.jsx diff --git a/README.md b/README.md deleted file mode 100644 index 650bfeb..0000000 --- a/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# website-framework - - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://code.usgs.gov/vkuchenik/website-framework.git -git branch -M main -git push -uf origin main -``` - -## Name -Basic Webapp Framework - -## Description -Building a foundational webapp framework that can be repurposed. \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index e8ead07..b015727 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -4286,6 +4286,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", "peerDependencies": { "react": "*" } diff --git a/client/src/App.jsx b/client/src/App.jsx index 591c1c2..75d84e6 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -2,10 +2,22 @@ import { useState } from 'react' import Header from './components/header.jsx'; import Sidebar from './components/sidebar.jsx'; import Widget from './components/Widget.jsx' +import CanvasHeader from './components/CanvasHeader.jsx' +// import { CanvasHeaderNav } from './components/CanvasHeaderNav.jsx' +// import { SearchBar } from './components/SearchBar.jsx' +// import { SettingsButton } from './components/SettingsButton.jsx' import { Grid, GridItem } from "@chakra-ui/react" function App() { + // UGLY SANITY CHECK - DELETE LATER + // return ( + //
+ // {/* */} + // {/* */} + // {/* */} + //
+ // ) return ( - + + + + + + @@ -34,3 +51,5 @@ function App() { } export default App + + diff --git a/client/src/components/CanvasHeader.jsx b/client/src/components/CanvasHeader.jsx new file mode 100644 index 0000000..dbbb111 --- /dev/null +++ b/client/src/components/CanvasHeader.jsx @@ -0,0 +1,30 @@ +import { Flex, HStack } from "@chakra-ui/react"; +import { CanvasHeaderNav } from "./CanvasHeaderNav"; +import { SearchBar } from "./SearchBar"; +import { SettingsButton } from "./SettingsButton"; + +export default function CanvasHeader() { + return ( + <> + + + + + + + + + ); +} \ No newline at end of file diff --git a/client/src/components/CanvasHeaderNav.jsx b/client/src/components/CanvasHeaderNav.jsx new file mode 100644 index 0000000..32b914e --- /dev/null +++ b/client/src/components/CanvasHeaderNav.jsx @@ -0,0 +1,22 @@ +import { HStack, Link } from "@chakra-ui/react" + +const navItems = [ + { label: "My Dashboard", href: "#dashboard" }, + { label: "Gas", href: "gas" }, + { label: "Seismic", href: "#seismic" }, + { label: "Remote Sensing", href: "#remote" }, + { label: "Daily Activity", href: "#daily" }, +]; + +export function CanvasHeaderNav() { + return ( + + {navItems.map(({ label, href }) => ( + + {label} + + ))} + + ); +} + diff --git a/client/src/components/SearchBar.jsx b/client/src/components/SearchBar.jsx new file mode 100644 index 0000000..93bd743 --- /dev/null +++ b/client/src/components/SearchBar.jsx @@ -0,0 +1,10 @@ +import { Input, InputGroup } from "@chakra-ui/react"; +import { FiSearch } from "react-icons/fi" + +export function SearchBar({ placeholder="Search...", size="sm", width="200px"}) { + return ( + }> + + + ); +} \ No newline at end of file diff --git a/client/src/components/SettingsButton.jsx b/client/src/components/SettingsButton.jsx new file mode 100644 index 0000000..5ce122d --- /dev/null +++ b/client/src/components/SettingsButton.jsx @@ -0,0 +1,25 @@ +import { IconButton, Box } from "@chakra-ui/react"; +import { FiSettings } from "react-icons/fi"; + +export function SettingsButton(props) { + return ( + + + + ); +} + + + + + diff --git a/client/src/components/Widget.jsx b/client/src/components/Widget.jsx index a23327d..b3413ad 100644 --- a/client/src/components/Widget.jsx +++ b/client/src/components/Widget.jsx @@ -1,8 +1,13 @@ +// This component defines a generic Widget that can be dynamically resized and +// dragged inside the canvas +// Content not included, must be populated using custom charts plots and notifications + import { useState } from 'react'; import GridLayout from 'react-grid-layout'; export default function Widget() { - // Define widgets initial position and size + // Define widgets initial position and size + // TODO Add dynamic adding/deleting of widgets via options button const [layout, setLayout] = useState([ { i: 'myWidget1', x: 0, y: 0, w: 3, h: 3, minH: 3, static: false }, { i: 'myWidget2', x: 3, y: 0, w: 3, h: 3, minH: 3, static: false }, From 1223ecc0b6ad1df633d61927b12440ea3b34d135 Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Mon, 14 Jul 2025 12:10:10 -0700 Subject: [PATCH 02/10] Add drop down menu to settings button --- client/src/components/SettingsButton.jsx | 57 ++++++++++++++++++------ 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/client/src/components/SettingsButton.jsx b/client/src/components/SettingsButton.jsx index 5ce122d..332c84f 100644 --- a/client/src/components/SettingsButton.jsx +++ b/client/src/components/SettingsButton.jsx @@ -1,21 +1,50 @@ -import { IconButton, Box } from "@chakra-ui/react"; +// This component displays a drop down menu when clicked, with custom functionality +// for 'Add Widget', 'Edit Widgets', and 'Remove Widgets'. This component will +// control settings related to the Widgets on the main canvas. + +import { Button, Menu, Portal } from "@chakra-ui/react"; import { FiSettings } from "react-icons/fi"; export function SettingsButton(props) { + const handleAddWidget = () => { + console.log("Add Widget clicked"); + // TODO: Implement widget-adding logic + } + + const handleEditWidgdets = () => { + console.log("Edit Widgets clicked") + // TODO: Implement widget-editing logic + } + + const handleDeleteWidgets = () => { + console.log("Delete Widgets clicked"); + // TODO: Implement widget-deletion logic + } + return ( - - - + // This uses Chakra's built in menu component + + + + + + + + Add Widget + Edit Widgets + + Delete Widgets + + + + + ); } From bc83710acc47a231ea71d7aee118046fd2003111 Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Mon, 14 Jul 2025 12:23:26 -0700 Subject: [PATCH 03/10] Add drop-down menu to Avatar --- client/src/components/CanvasHeader.jsx | 2 +- client/src/components/header.jsx | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/client/src/components/CanvasHeader.jsx b/client/src/components/CanvasHeader.jsx index dbbb111..fd0a10b 100644 --- a/client/src/components/CanvasHeader.jsx +++ b/client/src/components/CanvasHeader.jsx @@ -10,7 +10,7 @@ export default function CanvasHeader() { as="header" position="sticky" top="0" - zIndex="banner" + // zIndex="banner" bg="white" borderBottom="1px solid" borderColor="gray.200" diff --git a/client/src/components/header.jsx b/client/src/components/header.jsx index 72d8271..da9402c 100644 --- a/client/src/components/header.jsx +++ b/client/src/components/header.jsx @@ -1,5 +1,5 @@ -import { Box, Button, Avatar, HStack, Stack, Text } from "@chakra-ui/react" +import { Box, Button, Avatar, HStack, Stack, Text, Menu, Portal } from "@chakra-ui/react" export default function Header() { return ( @@ -20,10 +20,25 @@ export default function Header() { {user.name} {user.email} - - - - + {/* Add a drop down menu to the avatar */} + + + + + + + + + + + Account + Settings + Logout + + + + + From 94aa70a307753c09cd5e81d15fbc44caff5da34d Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Mon, 14 Jul 2025 13:13:47 -0700 Subject: [PATCH 04/10] Adjust spacing on CanvasHeaderNav items --- client/src/components/CanvasHeaderNav.jsx | 2 +- client/src/components/header.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/CanvasHeaderNav.jsx b/client/src/components/CanvasHeaderNav.jsx index 32b914e..3a3c2bb 100644 --- a/client/src/components/CanvasHeaderNav.jsx +++ b/client/src/components/CanvasHeaderNav.jsx @@ -10,7 +10,7 @@ const navItems = [ export function CanvasHeaderNav() { return ( - + {navItems.map(({ label, href }) => ( {label} diff --git a/client/src/components/header.jsx b/client/src/components/header.jsx index da9402c..c1aa092 100644 --- a/client/src/components/header.jsx +++ b/client/src/components/header.jsx @@ -38,7 +38,7 @@ export default function Header() { - + {/* End drop down menu */} From 6cbfb4e29a73061735c27dde9373f28519d85f5b Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Mon, 14 Jul 2025 13:31:11 -0700 Subject: [PATCH 05/10] Edit sidebar close symbol from 'X' to 'RxHamburgerMenu' and aligned to the right --- client/src/components/sidebar.jsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/client/src/components/sidebar.jsx b/client/src/components/sidebar.jsx index 9a32fce..2f40b1f 100644 --- a/client/src/components/sidebar.jsx +++ b/client/src/components/sidebar.jsx @@ -74,7 +74,19 @@ export default function Sidebar () { gap={4} paddingTop={4} paddingLeft={14} paddingRight={3} > - setIsOpen(!isOpen)}> + {/* setIsOpen(!isOpen)}> */} + {/* setIsOpen(!isOpen)}> */} + @@ -104,7 +116,7 @@ export default function Sidebar () { alignItems="start" gap={4} padding={4} > - setIsOpen(!isOpen)}> + setIsOpen(!isOpen)}> setActiveButton("Dashboard")} bg={activeButton === "Dashboard" ? "#A4B6B6" : "transparent"}> From b6a3b3d9d88ff5ba1756e74aafe0e5b391ff6ff5 Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Mon, 14 Jul 2025 15:08:20 -0700 Subject: [PATCH 06/10] Fix Gas nav link to use hash instead of path. Page no longer reloads upon clicking Gas link --- client/src/components/CanvasHeaderNav.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/CanvasHeaderNav.jsx b/client/src/components/CanvasHeaderNav.jsx index 3a3c2bb..b80d7c5 100644 --- a/client/src/components/CanvasHeaderNav.jsx +++ b/client/src/components/CanvasHeaderNav.jsx @@ -2,7 +2,7 @@ import { HStack, Link } from "@chakra-ui/react" const navItems = [ { label: "My Dashboard", href: "#dashboard" }, - { label: "Gas", href: "gas" }, + { label: "Gas", href: "#gas" }, { label: "Seismic", href: "#seismic" }, { label: "Remote Sensing", href: "#remote" }, { label: "Daily Activity", href: "#daily" }, From 9f61ab2216378cace7b1120e9f971979e0932ba6 Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Tue, 15 Jul 2025 13:51:56 -0700 Subject: [PATCH 07/10] Add side bar transition animation between open and closed --- client/src/components/SettingsButton.jsx | 6 +- client/src/components/sidebar.jsx | 393 ++++++++++++++++++----- 2 files changed, 319 insertions(+), 80 deletions(-) diff --git a/client/src/components/SettingsButton.jsx b/client/src/components/SettingsButton.jsx index 332c84f..afb7936 100644 --- a/client/src/components/SettingsButton.jsx +++ b/client/src/components/SettingsButton.jsx @@ -2,7 +2,7 @@ // for 'Add Widget', 'Edit Widgets', and 'Remove Widgets'. This component will // control settings related to the Widgets on the main canvas. -import { Button, Menu, Portal } from "@chakra-ui/react"; +import { Button, IconButton, Menu, Portal } from "@chakra-ui/react"; import { FiSettings } from "react-icons/fi"; export function SettingsButton(props) { @@ -25,9 +25,9 @@ export function SettingsButton(props) { // This uses Chakra's built in menu component - + diff --git a/client/src/components/sidebar.jsx b/client/src/components/sidebar.jsx index 2f40b1f..39ea197 100644 --- a/client/src/components/sidebar.jsx +++ b/client/src/components/sidebar.jsx @@ -1,4 +1,4 @@ -import { Box, Button, createIcon, CloseButton, IconButton, Stack } from "@chakra-ui/react"; +import { Box, Button, createIcon, CloseButton, IconButton, Stack, useDisclosure, Tooltip } from "@chakra-ui/react"; import { FaVolcano } from "react-icons/fa6"; import { RxHamburgerMenu } from "react-icons/rx"; import { useState } from "react"; @@ -56,87 +56,326 @@ export const Users = createIcon({ ), }); -export default function Sidebar () { + +export default function Sidebar() { const [isOpen, setIsOpen] = useState(true); - const [activeButton, setActiveButton] = useState("Dashboard") + const [activeButton, setActiveButton] = useState("Dashboard"); return ( - <> - {isOpen && ( - - {/* setIsOpen(!isOpen)}> */} - {/* setIsOpen(!isOpen)}> */} - - - - - - - - )} + + setIsOpen(!isOpen)} + // icon={} + > + + + {/* Dashboard */} + - {!isOpen && ( - - setIsOpen(!isOpen)}> - - - setActiveButton("Dashboard")} bg={activeButton === "Dashboard" ? "#A4B6B6" : "transparent"}> - - - setActiveButton("Global")} bg={activeButton === "Global" ? "#A4B6B6" : "transparent"}> + {/* Global Map */} + + + {/* Regional Map */} + + + {/* Volcano */} + + + {/* Admin */} + + ); } + +// THIS CODE WORKS, SAVE IN CASE OF EMERGENCY +// Needed to refactor in order allow transitions to work properly + +// export default function Sidebar () { +// const [isOpen, setIsOpen] = useState(true); +// const [activeButton, setActiveButton] = useState("Dashboard") + +// return ( +// <> +// {isOpen && ( +// +// {/* setIsOpen(!isOpen)}> */} +// {/* setIsOpen(!isOpen)}> */} +// +// +// +// +// +// +// +// )} + +// {!isOpen && ( +// +// setIsOpen(!isOpen)}> +// +// +// setActiveButton("Dashboard")} bg={activeButton === "Dashboard" ? "#A4B6B6" : "transparent"}> +// +// +// setActiveButton("Global")} bg={activeButton === "Global" ? "#A4B6B6" : "transparent"}> +// +// +// setActiveButton("Regional")} bg={activeButton === "Regional" ? "#A4B6B6" : "transparent"}> +// +// +// setActiveButton("Volcano")} bg={activeButton === "Volcano" ? "#A4B6B6" : "transparent"}> +// +// +// setActiveButton("Admin")} bg={activeButton === "Admin" ? "#A4B6B6" : "transparent"}> +// +// +// +// )} + +// +// ); +// } From dc1f4fcdafcb47f35c8ec63b8406374f9a73b089 Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Tue, 15 Jul 2025 15:55:20 -0700 Subject: [PATCH 08/10] Save point, working on sidebar icon positioning during transition --- client/src/components/sidebar.jsx | 107 ++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 29 deletions(-) diff --git a/client/src/components/sidebar.jsx b/client/src/components/sidebar.jsx index 39ea197..a1a9f25 100644 --- a/client/src/components/sidebar.jsx +++ b/client/src/components/sidebar.jsx @@ -57,13 +57,27 @@ export const Users = createIcon({ }); + + export default function Sidebar() { const [isOpen, setIsOpen] = useState(true); + const [hasFinishedClosing, setHasFinishedClosing] = useState(true); const [activeButton, setActiveButton] = useState("Dashboard"); + const toggleSidebar = () => { + if (isOpen) { + setHasFinishedClosing(false); + setTimeout(() => setIsOpen(false), 10); // Kick off transition + setTimeout(() => setHasFinishedClosing(true), 400) // Match sidebar transition duration + } else { + setIsOpen(true); + setHasFinishedClosing(true); + } + }; + return ( setIsOpen(!isOpen)} + // onClick={() => setIsOpen(!isOpen)} + onClick={toggleSidebar} // icon={} > @@ -90,9 +105,10 @@ export default function Sidebar() { color="#19332D" fontSize="lg" variant="ghost" - justifyContent={isOpen ? "flex-start" : "center"} + justifyContent={isOpen || !hasFinishedClosing ? "flex-start" : "center"} w="100%" onClick={() => setActiveButton("Dashboard")} + // onClick={toggleSidebar} bg={activeButton === "Dashboard" ? "#A4B6B6" : "transparent"} _hover={{ bg: activeButton === "Dashboard" ? "#A4B6B6" : "#EDF1F1", @@ -101,13 +117,15 @@ export default function Sidebar() { {isOpen ? ( <> {/* */} + + {/* Make text appear gradually instead of popping in */} Dashboard @@ -131,8 +150,11 @@ export default function Sidebar() { color="#19332D" fontSize="lg" variant="ghost" - justifyContent={isOpen ? "flex-start" : "center"} + // justifyContent={isOpen || !hasFinishedClosing ? "flex-start" : "center"} + justifyContent="flex-start" w="100%" + h="48px" + px={0} onClick={() => setActiveButton("Global")} bg={activeButton === "Global" ? "#A4B6B6" : "transparent"} _hover={{ @@ -141,29 +163,53 @@ export default function Sidebar() { > {isOpen ? ( <> - {/* */} - - {/* Make text appear gradually instead of popping in */} - - Global Map - + {/* Fixed-width icon container (works both open & closed) */} + + {/* */} + + + + Global Map + + + ) : ( // - + + + )} @@ -172,7 +218,7 @@ export default function Sidebar() { color="#19332D" fontSize="lg" variant="ghost" - justifyContent={isOpen ? "flex-start" : "center"} + justifyContent={isOpen || !hasFinishedClosing ? "flex-start" : "center"} w="100%" onClick={() => setActiveButton("Regional")} bg={activeButton === "Regional" ? "#A4B6B6" : "transparent"} @@ -189,7 +235,7 @@ export default function Sidebar() { style={{ marginLeft: "8px", opacity: isOpen ? 1 : 0, - maxWidth: isOpen ? "200px" : "0px", // prevent layout from expanding before fade-in + maxWidth: isOpen ? "250px" : "0px", // prevent layout from expanding before fade-in overflow: "hidden", whiteSpace: "nowrap", display: "inline-block", @@ -197,6 +243,7 @@ export default function Sidebar() { transitionDuration: "0.3s", transitionTimingFunction: "ease", transitionDelay: isOpen ? "0.1s" : "0s", + visibility: isOpen || !hasFinishedClosing ? "visible" : "hidden", }} > Regional Map @@ -213,7 +260,7 @@ export default function Sidebar() { color="#19332D" fontSize="lg" variant="ghost" - justifyContent={isOpen ? "flex-start" : "center"} + justifyContent={isOpen || !hasFinishedClosing ? "flex-start" : "center"} w="100%" onClick={() => setActiveButton("Volcano")} bg={activeButton === "Volcano" ? "#A4B6B6" : "transparent"} @@ -229,7 +276,7 @@ export default function Sidebar() { style={{ marginLeft: "8px", opacity: isOpen ? 1 : 0, - maxWidth: isOpen ? "200px" : "0px", // prevent layout from expanding before fade-in + maxWidth: isOpen ? "250px" : "0px", // prevent layout from expanding before fade-in overflow: "hidden", whiteSpace: "nowrap", display: "inline-block", @@ -237,6 +284,7 @@ export default function Sidebar() { transitionDuration: "0.3s", transitionTimingFunction: "ease", transitionDelay: isOpen ? "0.1s" : "0s", + visibility: isOpen || !hasFinishedClosing ? "visible" : "hidden", }} > Volcano @@ -253,7 +301,7 @@ export default function Sidebar() { color="#19332D" fontSize="lg" variant="ghost" - justifyContent={isOpen ? "flex-start" : "center"} + justifyContent={isOpen || !hasFinishedClosing ? "flex-start" : "center"} w="100%" onClick={() => setActiveButton("Admin")} bg={activeButton === "Admin" ? "#A4B6B6" : "transparent"} @@ -278,6 +326,7 @@ export default function Sidebar() { transitionDuration: "0.3s", transitionTimingFunction: "ease", transitionDelay: isOpen ? "0.1s" : "0s", + visibility: isOpen || !hasFinishedClosing ? "visible" : "hidden", }} > Admin From 1d1bf314e71b20cbe74895475bedea2bde4b752e Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Wed, 16 Jul 2025 11:06:36 -0700 Subject: [PATCH 09/10] Refactor sidebar transition to keep icons stationary --- client/src/components/sidebar.jsx | 70 ++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/client/src/components/sidebar.jsx b/client/src/components/sidebar.jsx index a1a9f25..6036423 100644 --- a/client/src/components/sidebar.jsx +++ b/client/src/components/sidebar.jsx @@ -68,16 +68,18 @@ export default function Sidebar() { if (isOpen) { setHasFinishedClosing(false); setTimeout(() => setIsOpen(false), 10); // Kick off transition - setTimeout(() => setHasFinishedClosing(true), 400) // Match sidebar transition duration + setTimeout(() => setHasFinishedClosing(true), 400); // Match sidebar transition duration } else { setIsOpen(true); setHasFinishedClosing(true); + // setTimeout(() => setIsOpen(true), 5); + // setTimeout(() => setHasFinishedClosing(false), 200); } }; return ( setActiveButton("Dashboard")} // onClick={toggleSidebar} @@ -147,6 +150,52 @@ export default function Sidebar() { {/* Global Map */} + + {/* EXPERIMENTAL STYLING */} + {/* + */} {/* Regional Map */}