From d61fd3dd0251271c6a63e126317536c90751c940 Mon Sep 17 00:00:00 2001 From: "Daniel S. Hansen" Date: Wed, 23 Jul 2025 16:40:52 -0700 Subject: [PATCH] Add dynamic widget adding functionality, along with boilerplate for edit and delete functionality --- .../src/components/layout/Canvas/Canvas.jsx | 45 ++++++++++++++++++- .../components/layout/Canvas/CanvasHeader.jsx | 10 +++-- .../layout/Canvas/SettingsButton.jsx | 32 ++++++------- .../layout/Canvas/views/WidgetCanvas.jsx | 20 ++++----- 4 files changed, 75 insertions(+), 32 deletions(-) diff --git a/client/src/components/layout/Canvas/Canvas.jsx b/client/src/components/layout/Canvas/Canvas.jsx index a527aa8..f4242f4 100644 --- a/client/src/components/layout/Canvas/Canvas.jsx +++ b/client/src/components/layout/Canvas/Canvas.jsx @@ -3,6 +3,7 @@ // of 'WidgetCanvas' import { Box } from "@chakra-ui/react"; +import { useState } from 'react'; import CanvasHeader from "./CanvasHeader"; import WidgetCanvas from "./views/WidgetCanvas"; import GlobalMapCanvas from "./views/GlobalMapCanvas"; @@ -11,10 +12,50 @@ import VolcanoCanvas from "./views/VolcanoCanvas"; import AdminCanvas from "./views/AdminCanvas"; export default function Canvas({ view }) { + const [layout, setLayout] = useState([ + { i: '0', x: 0, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false }, + { i: '1', x: 3, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false }, + { i: '2', x: 6, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false } + ]); + const [newCounter, setNewCounter] = useState(3); + + const addWidget = () => { + const newId = newCounter.toString(); + setLayout(prev => [ + ...prev, + { + i: newId, + x: (prev.length * 3) % 12, + y: Infinity, + w: 3, + h: 3 + } + ]); + setNewCounter(prev => prev + 1); + }; + + const removeWidget = (id) => { + setLayout(prev => prev.filter(w => w.i !== id)); + } + + const onLayoutChange = (newLayout) => { + setLayout(newLayout); + console.log('Updated layout:', newLayout) + }; + return ( - - {view === "widget" && } + console.log('Edit Widgets')} + onDeleteWidgets={() => console.log('Delete Widgets')} + /> + {view === "widget" && + } {view === "global" && } {view === "regional" && } {view === "volcano" && } diff --git a/client/src/components/layout/Canvas/CanvasHeader.jsx b/client/src/components/layout/Canvas/CanvasHeader.jsx index cfe2076..d387d30 100644 --- a/client/src/components/layout/Canvas/CanvasHeader.jsx +++ b/client/src/components/layout/Canvas/CanvasHeader.jsx @@ -3,9 +3,7 @@ import { CanvasHeaderNav } from "./CanvasHeaderNav"; import { SearchBar } from "./SearchBar"; import { SettingsButton } from "./SettingsButton"; - - -export default function CanvasHeader() { +export default function CanvasHeader({ onAddWidget, onEditWidgets, onDeleteWidgets }) { const recipe = useRecipe({ key: "canvas" }); const styles = recipe(); return ( @@ -25,7 +23,11 @@ export default function CanvasHeader() { - + diff --git a/client/src/components/layout/Canvas/SettingsButton.jsx b/client/src/components/layout/Canvas/SettingsButton.jsx index afb7936..40d91b4 100644 --- a/client/src/components/layout/Canvas/SettingsButton.jsx +++ b/client/src/components/layout/Canvas/SettingsButton.jsx @@ -5,21 +5,21 @@ import { Button, IconButton, 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 - } +export function SettingsButton({ onAddWidget, onEditWidgets, onDeleteWidgets }) { + // 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 handleEditWidgdets = () => { + // console.log("Edit Widgets clicked") + // // TODO: Implement widget-editing logic + // } - const handleDeleteWidgets = () => { - console.log("Delete Widgets clicked"); - // TODO: Implement widget-deletion logic - } + // const handleDeleteWidgets = () => { + // console.log("Delete Widgets clicked"); + // // TODO: Implement widget-deletion logic + // } return ( // This uses Chakra's built in menu component @@ -32,10 +32,10 @@ export function SettingsButton(props) { - Add Widget - Edit Widgets + Add Widget + Edit Widgets diff --git a/client/src/components/layout/Canvas/views/WidgetCanvas.jsx b/client/src/components/layout/Canvas/views/WidgetCanvas.jsx index 33e0912..f4389c9 100644 --- a/client/src/components/layout/Canvas/views/WidgetCanvas.jsx +++ b/client/src/components/layout/Canvas/views/WidgetCanvas.jsx @@ -7,23 +7,23 @@ import GridLayout, { WidthProvider } from 'react-grid-layout'; import Widget from '../Widget.jsx'; import { useSlotRecipe, chakra, Flex } from '@chakra-ui/react'; -export default function WidgetCanvas() { +export default function WidgetCanvas({ layout, onLayoutChange, removeWidget }) { // Define widgets initial position and size // TODO Add dynamic adding/deleting of widgets via options button const recipe = useSlotRecipe({ key: "widget" }); const styles = recipe(); // using root recipe for widget below const ResponsiveGridLayout = WidthProvider(GridLayout); // canvas width now adjusts to window size - const [layout, setLayout] = useState([ - { i: '0', x: 0, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false }, - { i: '1', x: 3, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false }, - { i: '2', x: 6, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false } - ]); + // const [layout, setLayout] = useState([ + // { i: '0', x: 0, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false }, + // { i: '1', x: 3, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false }, + // { i: '2', x: 6, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: false } + // ]); - const onLayoutChange = (newLayout) => { - setLayout(newLayout); - console.log('Updated layout:', newLayout) - }; + // const onLayoutChange = (newLayout) => { + // setLayout(newLayout); + // console.log('Updated layout:', newLayout) + // }; // don't allow text highlighting when dragging const handleDragStart = () => {