diff --git a/client/package-lock.json b/client/package-lock.json
index 4aec4b2..df504a9 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -21,7 +21,8 @@
"react-icons": "^5.5.0",
"react-leaflet": "^5.0.0",
"react-resizable": "^3.0.5",
- "tailwindcss": "^4.1.11"
+ "tailwindcss": "^4.1.11",
+ "uuid": "^11.1.0"
},
"devDependencies": {
"@eslint/js": "^9.29.0",
@@ -4776,6 +4777,19 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/uuid": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
+ "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/esm/bin/uuid"
+ }
+ },
"node_modules/vite": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
diff --git a/client/package.json b/client/package.json
index c14d34c..01c5bc5 100644
--- a/client/package.json
+++ b/client/package.json
@@ -23,7 +23,8 @@
"react-icons": "^5.5.0",
"react-leaflet": "^5.0.0",
"react-resizable": "^3.0.5",
- "tailwindcss": "^4.1.11"
+ "tailwindcss": "^4.1.11",
+ "uuid": "^11.1.0"
},
"devDependencies": {
"@eslint/js": "^9.29.0",
diff --git a/client/src/components/layout/Canvas/components/AddWidgetMenu.jsx b/client/src/components/layout/Canvas/components/AddWidgetMenu.jsx
new file mode 100644
index 0000000..5ce0553
--- /dev/null
+++ b/client/src/components/layout/Canvas/components/AddWidgetMenu.jsx
@@ -0,0 +1,35 @@
+import { IoIosArrowBack } from "react-icons/io";
+import { Menu, Portal } from "@chakra-ui/react";
+import { v4 as uuid } from 'uuid';
+import AlertLevel from "./AlertLevelWidget";
+
+export default function AddWidgetMenu({onAddWidget, widgetArray, setWidgetArray}) {
+ function appendWidget(name) {
+ const newID = uuid(); // could be replaced with something else like guid
+ setWidgetArray([ // updating widget array containing info on the types of widgets
+ ...widgetArray,
+ {i: newID, widget: name}
+ ]);
+ onAddWidget(newID); // updating array containing info on layout of widgets
+ }
+
+ return (
+
+
+ Add Widget
+
+
+
+
+ appendWidget(AlertLevel)}
+ >
+ Alert Level
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/client/src/components/layout/Canvas/components/AlertLevelWidget.jsx b/client/src/components/layout/Canvas/components/AlertLevelWidget.jsx
new file mode 100644
index 0000000..ba880ca
--- /dev/null
+++ b/client/src/components/layout/Canvas/components/AlertLevelWidget.jsx
@@ -0,0 +1,10 @@
+import Widget from "./Widget";
+import { Text } from "@chakra-ui/react";
+
+export default function AlertLevel({id, isEditable, isDelete, DeleteWidget}) {
+ return (
+
+ Input volcano and country
+
+ );
+}
\ No newline at end of file
diff --git a/client/src/components/layout/Canvas/components/SettingsButton.jsx b/client/src/components/layout/Canvas/components/SettingsButton.jsx
index 8937380..4eda93b 100644
--- a/client/src/components/layout/Canvas/components/SettingsButton.jsx
+++ b/client/src/components/layout/Canvas/components/SettingsButton.jsx
@@ -1,36 +1,33 @@
-// 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, IconButton, Menu, Portal } from "@chakra-ui/react";
+import { IconButton, Menu, Portal } from "@chakra-ui/react";
import { FiSettings } from "react-icons/fi";
+import AddWidgetMenu from "./AddWidgetMenu";
-export function SettingsButton({onAddWidget, onEditWidgets, onDeleteWidgets}) {
- return (
- // This uses Chakra's built in menu component
-
-
-
-
-
-
-
-
-
- Add Widget
- Edit Widgets
-
- Delete Widgets
-
-
-
-
-
- );
+export function SettingsButton({onAddWidget, onEditWidgets, onDeleteWidgets, widgetArray, setWidgetArray}) {
+ return (
+ // This uses Chakra's built in menu component
+
+
+
+
+
+
+
+
+
+
+ Edit Widgets
+
+ Delete Widgets
+
+
+
+
+
+ );
}
diff --git a/client/src/components/layout/Canvas/components/Widget.jsx b/client/src/components/layout/Canvas/components/Widget.jsx
index 74b1b71..d1ecaa2 100644
--- a/client/src/components/layout/Canvas/components/Widget.jsx
+++ b/client/src/components/layout/Canvas/components/Widget.jsx
@@ -1,13 +1,11 @@
import { useSlotRecipe, chakra, Flex, CloseButton, Text } from "@chakra-ui/react"
-export default function Widget({ id, title, isEditable, isDelete, DeleteWidget }) {
- // console.log("rendering widget");
+export default function Widget({ id, title, isEditable, isDelete, DeleteWidget, children }) {
const recipe = useSlotRecipe({ key: "widget" });
const styles = recipe();
return (
<>
- {/* {console.log("This widgets id is: ", id)} */}
{isDelete ? (
<>
@@ -23,7 +21,7 @@ export default function Widget({ id, title, isEditable, isDelete, DeleteWidget }
)}
- This is their widget content - drag or resize me!
+ {children}
>
);
diff --git a/client/src/components/layout/Canvas/views/DashboardCanvas.jsx b/client/src/components/layout/Canvas/views/DashboardCanvas.jsx
index a6b7d0c..008d0d5 100644
--- a/client/src/components/layout/Canvas/views/DashboardCanvas.jsx
+++ b/client/src/components/layout/Canvas/views/DashboardCanvas.jsx
@@ -11,25 +11,24 @@ import { CancelButton } from "../components/CancelButton";
import { SaveButton } from "../components/SaveButton";
import DeleteAllButton from "../components/DeleteAllButton";
-export function DashboardCanvas({ onCancel, isEditable, setIsEditable, isDelete, setIsDelete, view, layout, setLayout, originalLayout, setOriginalLayout, onLayoutChange, onChangeView }) {
- const [newCounter, setNewCounter] = useState(3);
+export function DashboardCanvas({ view, setView, layout, setLayout, onLayoutChange }) {
+ const [isEditable, setIsEditable] = useState(false); // editable=true means static=false (vice versa)
+ const [isDelete, setIsDelete] = useState(false);
+ const [originalLayout, setOriginalLayout] = useState([]);
+ const [widgetArray, setWidgetArray] = useState([]);
- // Adding a widget triggers Edit mode
- const onAddWidget = () => {
- const newId = newCounter.toString();
-
+ const onAddWidget = (ID) => {
setLayout(prev => [
...prev,
- {
- i: newId,
- x: (prev.length * 3) % 12,
- y: Infinity,
- w: 3,
- h: 3,
- static: false,
- }
+ {
+ i: ID,
+ x: (prev.length * 3) % 12,
+ y: Infinity,
+ w: 3,
+ h: 3,
+ static: false
+ }
]);
- setNewCounter(prev => prev + 1);
onEditWidgets();
};
@@ -73,6 +72,7 @@ export function DashboardCanvas({ onCancel, isEditable, setIsEditable, isDelete,
const DeleteWidget = (id) => {
console.log("Deleting widget with id: ", id);
setLayout(layout => layout.filter(w => w.i !== id));
+ // add removal for widgetArray here
}
const DeleteAll = () => {
@@ -81,6 +81,7 @@ export function DashboardCanvas({ onCancel, isEditable, setIsEditable, isDelete,
);
if (confirm) {
setLayout([]);
+ setWidgetArray([]);
onSave();
}
else return;
@@ -144,6 +145,8 @@ export function DashboardCanvas({ onCancel, isEditable, setIsEditable, isDelete,
onAddWidget={ onAddWidget }
onEditWidgets={ onEditWidgets }
onDeleteWidgets={ onDeleteWidgets }
+ setWidgetArray={ setWidgetArray }
+ widgetArray={ widgetArray }
/>
>
)}
@@ -153,11 +156,13 @@ export function DashboardCanvas({ onCancel, isEditable, setIsEditable, isDelete,
{/* CANVAS */}
diff --git a/client/src/components/layout/Canvas/views/DashboardCanvasNav/WidgetCanvas.jsx b/client/src/components/layout/Canvas/views/DashboardCanvasNav/WidgetCanvas.jsx
index 589979d..0c1779f 100644
--- a/client/src/components/layout/Canvas/views/DashboardCanvasNav/WidgetCanvas.jsx
+++ b/client/src/components/layout/Canvas/views/DashboardCanvasNav/WidgetCanvas.jsx
@@ -1,50 +1,50 @@
-// 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, { WidthProvider } from 'react-grid-layout';
-import Widget from '../../components/Widget.jsx';
import { useSlotRecipe, chakra, Flex } from '@chakra-ui/react';
-export default function WidgetCanvas({layout, onLayoutChange, isEditable, isDelete, DeleteWidget}) {
+export default function WidgetCanvas({layout, onLayoutChange, isEditable, isDelete, DeleteWidget, widgetArray}) {
console.log("rendering widgetcanvas");
- // 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 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 handleDragStart = () => { document.body.style.userSelect = "none"; }; // don't allow text highlighting when dragging
+ const handleDragStop = () => { document.body.style.userSelect = ""; }; // allow text highlighting all other times
+ let merged = [];
- // don't allow text highlighting when dragging
- const handleDragStart = () => {
- document.body.style.userSelect = "none";
- };
- // allow text highlighting all other times
- const handleDragStop = () => {
- document.body.style.userSelect = "";
- };
+ console.log("widgetArray: ", widgetArray);
+ console.log("layout: ", layout);
+ if (widgetArray.length && layout.length) {
+ const widgetMap = new Map(widgetArray.map(item => [item.i, item]));
+ merged = layout.map(item => {
+ return {
+ ...item,
+ ...widgetMap.get(item.i)
+ };
+ });
+ };
- return (
-
-
- {layout.map((item) => (
- // this flex wrapper allows the widget to shrink down to the header size, no less
-
-
-
- ))}
-
+ return (
+
+
+ {merged.map((item) => {
+ const Widget = item.widget;
+ return (
+
+
+
+ )
+ })}
+
);
}
diff --git a/client/src/components/layout/Dashboard.jsx b/client/src/components/layout/Dashboard.jsx
index 8cded10..2fdd67d 100644
--- a/client/src/components/layout/Dashboard.jsx
+++ b/client/src/components/layout/Dashboard.jsx
@@ -1,8 +1,8 @@
-import { Global, css } from "@emotion/react";
import Header from './Header/Header.jsx';
import Sidebar from './Sidebar/Sidebar.jsx';
import Canvas from './Canvas/Canvas.jsx';
import { Grid, GridItem, useRecipe } from '@chakra-ui/react';
+import AlertLevel from './Canvas/components/AlertLevelWidget.jsx';
import { useState } from 'react';
export default function Dashboard() {
@@ -14,11 +14,7 @@ export default function Dashboard() {
const [isDelete, setIsDelete] = useState(false);
const [originalLayout, setOriginalLayout] = useState([]);
const [view, setView] = useState("widget");
- const [layout, setLayout] = useState([
- { i: '0', x: 0, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: true },
- { i: '1', x: 3, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: true },
- { i: '2', x: 6, y: 0, w: 3, h: 3, minH: 3, minW: 1, static: true }
- ]);
+ const [layout, setLayout] = useState([]);
const onCancel = () => {
console.log("canceling changes...");
@@ -87,7 +83,7 @@ export default function Dashboard() {
isDelete={ isDelete }
setIsDelete={ setIsDelete }
/>
-
+
>
);