Refactor continuing to work on UI
This commit is contained in:
@@ -1,162 +1,170 @@
|
||||
import { useState, useMemo, useRef } from "react";
|
||||
import {useState, useMemo, useRef} from "react";
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Box,
|
||||
Text,
|
||||
Flex,
|
||||
Grid,
|
||||
Dialog,
|
||||
Tabs,
|
||||
Badge,
|
||||
Menu,
|
||||
HStack
|
||||
Button,
|
||||
Box,
|
||||
Text,
|
||||
Flex,
|
||||
Grid,
|
||||
Dialog,
|
||||
Tabs,
|
||||
Badge,
|
||||
Menu,
|
||||
HStack,
|
||||
useRecipe, useSlotRecipe
|
||||
} from "@chakra-ui/react";
|
||||
import { Settings, Plus, LayoutGrid, Move, Save, X } from 'lucide-react';
|
||||
import { useDashboardStore } from "../../store/useDashboardStore.jsx";
|
||||
import { WIDGET_REGISTRY } from "../../constants/widgetRegistry.jsx";
|
||||
import {Settings, Plus, LayoutGrid, Move, Save, X} from 'lucide-react';
|
||||
import {useDashboardStore} from "../../store/useDashboardStore.jsx";
|
||||
import {WIDGET_REGISTRY} from "../../constants/widgetRegistry.jsx";
|
||||
|
||||
export function SettingsButton() {
|
||||
// 1. ☁Store connections
|
||||
const isEditing = useDashboardStore(state => state.isEditing);
|
||||
const enterEditMode = useDashboardStore(state => state.enterEditMode);
|
||||
// 1. ☁Store connections
|
||||
const isEditing = useDashboardStore(state => state.isEditing);
|
||||
const enterEditMode = useDashboardStore(state => state.enterEditMode);
|
||||
const saveEdit = useDashboardStore(state => state.saveEdit);
|
||||
const cancelEdit = useDashboardStore(state => state.cancelEdit);
|
||||
const addWidget = useDashboardStore(state => state.addWidget);
|
||||
|
||||
// This now handles both local UI lock AND database saving!
|
||||
const saveEdit = useDashboardStore(state => state.saveEdit);
|
||||
const recipe = useRecipe({key: "glassTab"});
|
||||
const tabStyles = recipe();
|
||||
|
||||
const cancelEdit = useDashboardStore(state => state.cancelEdit);
|
||||
const addWidget = useDashboardStore(state => state.addWidget);
|
||||
// Pull the glass container styles for the dropdown
|
||||
const panelRecipe = useSlotRecipe({key: "glassPanel"});
|
||||
const panelStyles = panelRecipe({ layout: "dropdown" });
|
||||
|
||||
const [isLibraryOpen, setIsLibraryOpen] = useState(false);
|
||||
const [isLibraryOpen, setIsLibraryOpen] = useState(false);
|
||||
|
||||
// Smart Add Handler
|
||||
const handleAddWidget = (widgetId, sizeKey) => {
|
||||
enterEditMode();
|
||||
addWidget(widgetId, sizeKey);
|
||||
};
|
||||
// Smart Add Handler
|
||||
const handleAddWidget = (widgetId, sizeKey) => {
|
||||
enterEditMode();
|
||||
addWidget(widgetId, sizeKey);
|
||||
};
|
||||
|
||||
const categorizedWidgets = useMemo(() => {
|
||||
return Object.entries(WIDGET_REGISTRY).reduce((acc, [id, widget]) => {
|
||||
const cat = widget.category || 'General';
|
||||
if (!acc[cat]) acc[cat] = [];
|
||||
acc[cat].push({ id, ...widget });
|
||||
return acc;
|
||||
}, {});
|
||||
}, []);
|
||||
const categorizedWidgets = useMemo(() => {
|
||||
return Object.entries(WIDGET_REGISTRY).reduce((acc, [id, widget]) => {
|
||||
const cat = widget.category || 'General';
|
||||
if (!acc[cat]) acc[cat] = [];
|
||||
acc[cat].push({id, ...widget});
|
||||
return acc;
|
||||
}, {});
|
||||
}, []);
|
||||
|
||||
const categories = Object.keys(categorizedWidgets);
|
||||
const categories = Object.keys(categorizedWidgets);
|
||||
|
||||
// use ref to capture html node for placing menu accordingly
|
||||
const menuRef = useRef(null);
|
||||
const getAnchorRect = () => {
|
||||
if (!menuRef.current) return null;
|
||||
return menuRef.current.getBoundingClientRect();
|
||||
};
|
||||
// use ref to capture html node for placing menu accordingly
|
||||
const menuRef = useRef(null);
|
||||
const getAnchorRect = () => {
|
||||
if (!menuRef.current) return null;
|
||||
return menuRef.current.getBoundingClientRect();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* THE STATIC DROPDOWN MENU */}
|
||||
<Menu.Root positioning={{ getAnchorRect }}>
|
||||
<Menu.Trigger asChild>
|
||||
<IconButton
|
||||
ref={menuRef}
|
||||
aria-label="Settings"
|
||||
bg="vdap.darkGreen"
|
||||
color="white"
|
||||
size="sm"
|
||||
borderRadius="md"
|
||||
_hover={{ bg: "vdap.darkGreenHover" }}
|
||||
>
|
||||
<Settings size={18} />
|
||||
</IconButton>
|
||||
</Menu.Trigger>
|
||||
<Menu.Positioner>
|
||||
<Menu.Content bg="white" boxShadow="lg" borderRadius="md" p={1} zIndex="dropdown">
|
||||
{isEditing ? (
|
||||
<>
|
||||
{/* WIRE DIRECTLY TO saveEdit */}
|
||||
<Menu.Item onClick={saveEdit} color="green.600" fontWeight="bold" cursor="pointer" _hover={{ bg: "green.50" }}>
|
||||
<Save size={16} style={{ marginRight: '8px' }} /> Save Layout
|
||||
</Menu.Item>
|
||||
return (
|
||||
<>
|
||||
{/* THE STATIC DROPDOWN MENU */}
|
||||
<Menu.Root positioning={{getAnchorRect}}>
|
||||
<Menu.Trigger asChild>
|
||||
<Box
|
||||
ref={menuRef}
|
||||
as="button"
|
||||
css={tabStyles}
|
||||
>
|
||||
{/* size increased to 24 to match tabs. flexShrink: 0 is CRITICAL */}
|
||||
<Settings size={24} style={{flexShrink: 0}}/>
|
||||
|
||||
<Menu.Item onClick={cancelEdit} color="red.500" cursor="pointer" _hover={{ bg: "red.50" }}>
|
||||
<X size={16} style={{ marginRight: '8px' }} /> Discard Changes
|
||||
</Menu.Item>
|
||||
</>
|
||||
) : (
|
||||
<Menu.Item onClick={enterEditMode} cursor="pointer" _hover={{ bg: "gray.100" }}>
|
||||
<Move size={16} style={{ marginRight: '8px' }} /> Edit Layout
|
||||
</Menu.Item>
|
||||
)}
|
||||
{/* Dynamic text based on editing state! */}
|
||||
<Box as="span">
|
||||
{isEditing ? "Editing Layout..." : "Dashboard Settings"}
|
||||
</Box>
|
||||
</Box>
|
||||
</Menu.Trigger>
|
||||
|
||||
<Menu.Separator my={1} borderColor="gray.200" />
|
||||
<Menu.Positioner>
|
||||
<Menu.Content css={panelStyles.root} zIndex="dropdown" minW="200px">
|
||||
{isEditing ? (
|
||||
<>
|
||||
<Menu.Item onClick={saveEdit} color="green.600" cursor="pointer" _hover={{fontWeight: "semibold"}}>
|
||||
<Save size={16} style={{marginRight: '8px'}}/> Save Layout
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item onClick={() => setIsLibraryOpen(true)} cursor="pointer" _hover={{ bg: "gray.100" }}>
|
||||
<LayoutGrid size={16} style={{ marginRight: '8px' }} /> Widget Library
|
||||
</Menu.Item>
|
||||
</Menu.Content>
|
||||
</Menu.Positioner>
|
||||
</Menu.Root>
|
||||
<Menu.Item onClick={cancelEdit} color="red.500" cursor="pointer" _hover={{fontWeight: "semibold"}}>
|
||||
<X size={16} style={{marginRight: '8px'}}/> Discard Changes
|
||||
</Menu.Item>
|
||||
</>
|
||||
) : (
|
||||
<Menu.Item onClick={enterEditMode} cursor="pointer" _hover={{fontWeight: "semibold"}}>
|
||||
<Move size={16} style={{marginRight: '8px'}}/> Edit Layout
|
||||
</Menu.Item>
|
||||
)}
|
||||
|
||||
{/* THE WIDGET LIBRARY MODAL (Controlled by isLibraryOpen) */}
|
||||
<Dialog.Root open={isLibraryOpen} onOpenChange={(e) => setIsLibraryOpen(e.open)} size="xl" placement="center">
|
||||
<Dialog.Backdrop bg="blackAlpha.600" />
|
||||
<Dialog.Positioner>
|
||||
<Dialog.Content bg="gray.50" borderRadius="xl" overflow="hidden" boxShadow="xl" maxW="800px">
|
||||
<Dialog.Header bg="vdap.darkGreen" color="white" py={4}>
|
||||
<Dialog.Title fontSize="xl" fontWeight="bold">Add Dashboard Widgets</Dialog.Title>
|
||||
</Dialog.Header>
|
||||
<Menu.Separator my={1} borderColor="glassSeperator"/>
|
||||
|
||||
<Dialog.Body p={0}>
|
||||
<Tabs.Root defaultValue={categories[0]} variant="enclosed" colorScheme="blue">
|
||||
<Tabs.List bg="white" px={4} pt={4} borderBottom="1px solid" borderColor="gray.200">
|
||||
{categories.map(cat => (
|
||||
<Tabs.Trigger key={cat} value={cat} pb={2}>{cat}</Tabs.Trigger>
|
||||
))}
|
||||
</Tabs.List>
|
||||
<Menu.Item onClick={() => setIsLibraryOpen(true)} cursor="pointer" _hover={{fontWeight: "semibold"}}>
|
||||
<LayoutGrid size={16} style={{marginRight: '8px'}}/> Widget Library
|
||||
</Menu.Item>
|
||||
</Menu.Content>
|
||||
</Menu.Positioner>
|
||||
</Menu.Root>
|
||||
|
||||
{categories.map(cat => (
|
||||
<Tabs.Content key={cat} value={cat} p={6}>
|
||||
<Grid templateColumns="repeat(auto-fill, minmax(300px, 1fr))" gap={4}>
|
||||
{categorizedWidgets[cat].map(widget => (
|
||||
<Flex key={widget.id} direction="column" bg="white" p={4} borderRadius="md" border="1px solid" borderColor="gray.200" boxShadow="sm">
|
||||
<Text fontWeight="bold" fontSize="md" mb={1}>{widget.name}</Text>
|
||||
<Text fontSize="sm" color="gray.500" mb={4} flex="1">{widget.description}</Text>
|
||||
{/* THE WIDGET LIBRARY MODAL (Controlled by isLibraryOpen) */}
|
||||
<Dialog.Root open={isLibraryOpen} onOpenChange={(e) => setIsLibraryOpen(e.open)} size="xl" placement="center">
|
||||
<Dialog.Backdrop bg="blackAlpha.600"/>
|
||||
<Dialog.Positioner>
|
||||
<Dialog.Content bg="gray.50" borderRadius="xl" overflow="hidden" boxShadow="xl" maxW="800px">
|
||||
<Dialog.Header bg="gray.800" color="white" py={4}>
|
||||
<Dialog.Title fontSize="xl" fontWeight="bold">Add Dashboard Widgets</Dialog.Title>
|
||||
</Dialog.Header>
|
||||
|
||||
<Box borderTop="1px solid" borderColor="gray.100" pt={3}>
|
||||
<Text fontSize="xs" fontWeight="bold" color="gray.400" textTransform="uppercase" mb={2}>Add to Grid:</Text>
|
||||
<HStack gap={2} flexWrap="wrap">
|
||||
{Object.keys(widget.allowedSizes).map(sizeKey => (
|
||||
<Badge
|
||||
key={sizeKey}
|
||||
as="button"
|
||||
onClick={() => handleAddWidget(widget.id, sizeKey)}
|
||||
colorScheme="gray"
|
||||
variant="subtle"
|
||||
px={3}
|
||||
py={1}
|
||||
borderRadius="full"
|
||||
cursor="pointer"
|
||||
_hover={{ bg: "blue.50", color: "blue.600", transform: "scale(1.05)" }}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<Plus size={12} style={{ display: 'inline', marginRight: '4px' }}/>
|
||||
{sizeKey.charAt(0).toUpperCase() + sizeKey.slice(1)}
|
||||
</Badge>
|
||||
))}
|
||||
</HStack>
|
||||
</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</Grid>
|
||||
</Tabs.Content>
|
||||
))}
|
||||
</Tabs.Root>
|
||||
</Dialog.Body>
|
||||
<Dialog.CloseTrigger position="absolute" top={3} right={3} color="white" />
|
||||
</Dialog.Content>
|
||||
</Dialog.Positioner>
|
||||
</Dialog.Root>
|
||||
</>
|
||||
);
|
||||
<Dialog.Body p={0}>
|
||||
<Tabs.Root defaultValue={categories[0]} variant="enclosed" colorScheme="blue">
|
||||
<Tabs.List bg="white" px={4} pt={4} borderBottom="1px solid" borderColor="gray.200">
|
||||
{categories.map(cat => (
|
||||
<Tabs.Trigger key={cat} value={cat} pb={2}>{cat}</Tabs.Trigger>
|
||||
))}
|
||||
</Tabs.List>
|
||||
|
||||
{categories.map(cat => (
|
||||
<Tabs.Content key={cat} value={cat} p={6}>
|
||||
<Grid templateColumns="repeat(auto-fill, minmax(300px, 1fr))" gap={4}>
|
||||
{categorizedWidgets[cat].map(widget => (
|
||||
<Flex key={widget.id} direction="column" bg="white" p={4} borderRadius="md" border="1px solid"
|
||||
borderColor="gray.200" boxShadow="sm">
|
||||
<Text fontWeight="bold" fontSize="md" mb={1}>{widget.name}</Text>
|
||||
<Text fontSize="sm" color="gray.500" mb={4} flex="1">{widget.description}</Text>
|
||||
|
||||
<Box borderTop="1px solid" borderColor="gray.100" pt={3}>
|
||||
<Text fontSize="xs" fontWeight="bold" color="gray.400" textTransform="uppercase" mb={2}>Add
|
||||
to Grid:</Text>
|
||||
<HStack gap={2} flexWrap="wrap">
|
||||
{Object.keys(widget.allowedSizes).map(sizeKey => (
|
||||
<Badge
|
||||
key={sizeKey}
|
||||
as="button"
|
||||
onClick={() => handleAddWidget(widget.id, sizeKey)}
|
||||
colorScheme="gray"
|
||||
variant="subtle"
|
||||
px={3}
|
||||
py={1}
|
||||
borderRadius="full"
|
||||
cursor="pointer"
|
||||
_hover={{bg: "blue.50", color: "blue.600", transform: "scale(1.05)"}}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<Plus size={12} style={{display: 'inline', marginRight: '4px'}}/>
|
||||
{sizeKey.charAt(0).toUpperCase() + sizeKey.slice(1)}
|
||||
</Badge>
|
||||
))}
|
||||
</HStack>
|
||||
</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</Grid>
|
||||
</Tabs.Content>
|
||||
))}
|
||||
</Tabs.Root>
|
||||
</Dialog.Body>
|
||||
<Dialog.CloseTrigger position="absolute" top={3} right={3} color="white"/>
|
||||
</Dialog.Content>
|
||||
</Dialog.Positioner>
|
||||
</Dialog.Root>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
import Widget from "./Widget.jsx";
|
||||
import { Fieldset, NativeSelect, For, Box, Field, Input, Button, Text, Flex } from "@chakra-ui/react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useState } from "react";
|
||||
import { Asterisk } from 'lucide-react';
|
||||
|
||||
export default function AlertLevel({id, isEditable, isDelete, DeleteWidget}) {
|
||||
const { register, handleSubmit, reset, formState: {errors} } = useForm();
|
||||
const [isSubmit, setIsSubmit] = useState(false);
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setIsSubmit(true);
|
||||
reset();
|
||||
}
|
||||
|
||||
// Prop Forwarding
|
||||
const widgetProps = { id, isEditable, isDelete, DeleteWidget, isSubmit, setIsSubmit }
|
||||
|
||||
return (
|
||||
<Widget title="Alert Level" {...widgetProps} >
|
||||
{!isSubmit ? (
|
||||
// DISPLAYING INPUT FIElDS AND LABELS
|
||||
<Box
|
||||
as="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
width="100%"
|
||||
p={3}
|
||||
display="flex"
|
||||
flexDir="column"
|
||||
>
|
||||
<Fieldset.Root size="md" maxW="md">
|
||||
<Fieldset.Content>
|
||||
<Field.Root>
|
||||
<Field.Label fontWeight="semibold">Volcano</Field.Label>
|
||||
<Input name="volcanoname" />
|
||||
</Field.Root>
|
||||
|
||||
<Field.Root>
|
||||
<Field.Label fontWeight="semibold">Country</Field.Label>
|
||||
<NativeSelect.Root>
|
||||
<NativeSelect.Field name="country">
|
||||
<For each={["United Kingdom", "Canada", "United States"]}>
|
||||
{(item) => (
|
||||
<option key={item} value={item}>
|
||||
{item}
|
||||
</option>
|
||||
)}
|
||||
</For>
|
||||
</NativeSelect.Field>
|
||||
<NativeSelect.Indicator />
|
||||
</NativeSelect.Root>
|
||||
</Field.Root>
|
||||
</Fieldset.Content>
|
||||
|
||||
<Button type="submit" size="sm">Submit</Button>
|
||||
</Fieldset.Root>
|
||||
</Box>
|
||||
):(
|
||||
// DISPLAYING ALERT LEVEL DATA
|
||||
<Box p={1} mt={1} ml="auto" mr="auto" width="200px">
|
||||
<Box
|
||||
bg="bg"
|
||||
shadow="md"
|
||||
borderRadius="md"
|
||||
p={8}
|
||||
width="200px"
|
||||
height="10px"
|
||||
textAlign="center"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Text fontsize="2xl" fontWeight="bold" color="gray.700">Alert Level Data Coming Soon.</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Widget>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Button } from "@chakra-ui/react";
|
||||
|
||||
export function CancelButton ({onCancel}) {
|
||||
return (
|
||||
<Button onClick={onCancel} borderRadius="md">Cancel</Button>
|
||||
)
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// DEPRECATED
|
||||
|
||||
// import GlobalMap from "./views/GlobalMap";
|
||||
// import RegionalMap from "./views/RegionalMap";
|
||||
// import Volcano from "./views/Volcano";
|
||||
// import Admin from "./views/Admin";
|
||||
// import Account from "./views/Account"
|
||||
// import Home from "./views/Home";
|
||||
// import { DASHBOARD_VIEWS, ADMIN_VIEWS, VOLCANO_VIEWS } from "@/constants/viewKeys";
|
||||
// import { chakra } from "@chakra-ui/react";
|
||||
// import Personal from "./views/Personal";
|
||||
// import Security from "./views/Security";
|
||||
//
|
||||
// export default function Canvas(props) {
|
||||
// const { view } = props;
|
||||
//
|
||||
// return (
|
||||
// <chakra.div width="100%" height="100%">
|
||||
// {/* Check if view is a tab inside the Home Header */}
|
||||
// { DASHBOARD_VIEWS.includes(view) && (
|
||||
// <Home {...props}/>
|
||||
// )}
|
||||
// {/* Check if view is a tab inside the Volcano Header */}
|
||||
// { VOLCANO_VIEWS.includes(view) && (
|
||||
// <Volcano {...props}/>
|
||||
// )}
|
||||
// {/* Check if view is a tab inside the Admin Header */}
|
||||
// { ADMIN_VIEWS.includes(view) && (
|
||||
// <Admin {...props}/>
|
||||
// )}
|
||||
// {view === "global" && <GlobalMap />}
|
||||
// {view === "regional" && <RegionalMap />}
|
||||
// {view === "account" && <Account />}
|
||||
// {view === "settings" && <Personal />}
|
||||
// {view === "personal" && <Personal />}
|
||||
// {view === "security" && <Security />}
|
||||
// </chakra.div>
|
||||
// );
|
||||
// }
|
||||
@@ -1,27 +0,0 @@
|
||||
import { MoveDiagonal2 } from 'lucide-react';
|
||||
import React from "react";
|
||||
|
||||
const CustomResizeHandle = React.forwardRef((props, ref) => {
|
||||
const { handleAxis, isVisable, ...restProps } = props;
|
||||
if (!isVisable) return null;
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
{...restProps}
|
||||
className={`resize-hande-${handleAxis}`}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
cursor: "pointer",
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
zIndex: "1",
|
||||
}}
|
||||
>
|
||||
<MoveDiagonal2 />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default CustomResizeHandle;
|
||||
@@ -1,95 +0,0 @@
|
||||
// DEPRECATED
|
||||
|
||||
// import Header from './Header/Header.jsx';
|
||||
// import Sidebar from './Sidebar/Sidebar.jsx';
|
||||
// import Canvas from './Canvas/Canvas.jsx';
|
||||
// import { Grid, GridItem, useRecipe, useDialog } from '@chakra-ui/react';
|
||||
// import { useState } from 'react';
|
||||
// import DialogPopup from './Canvas/CanvasComponents/DialogPopup.jsx';
|
||||
//
|
||||
// export default function Dashboard() {
|
||||
// const recipe = useRecipe({ key: "dashboard" });
|
||||
// const styles = recipe();
|
||||
//
|
||||
// const [darkMode, setDarkMode] = useState(false);
|
||||
// const [isEditable, setIsEditable] = useState(false); // editable=true means static=false (vice versa)
|
||||
// const [isDelete, setIsDelete] = useState(false);
|
||||
// const [originalLayout, setOriginalLayout] = useState([]);
|
||||
// const [originalWidgets, setOriginalWidgets] = useState([]);
|
||||
// const [view, setView] = useState("mydashboard");
|
||||
// const [layout, setLayout] = useState([]);
|
||||
// const [widgetArray, setWidgetArray] = useState([]);
|
||||
// const dialog = useDialog();
|
||||
//
|
||||
// const beginEditIfNeeded = () => {
|
||||
// if ( !isEditable ) {
|
||||
// setOriginalLayout(layout);
|
||||
// setOriginalWidgets(widgetArray);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// const onCancel = () => {
|
||||
// console.log("canceling changes...");
|
||||
// console.log(originalWidgets);
|
||||
// if (originalLayout.length) {
|
||||
// setLayout(originalLayout.map(item => ({
|
||||
// ...item,
|
||||
// static: true
|
||||
// })));
|
||||
// };
|
||||
// setWidgetArray(originalWidgets);
|
||||
// setIsEditable(false);
|
||||
// setIsDelete(false);
|
||||
// setOriginalLayout([]);
|
||||
// setOriginalWidgets([]);
|
||||
// }
|
||||
//
|
||||
// // Prevent navigation while in Edit mode without saving or cancelling
|
||||
// const handleViewChange = (nextView) => {
|
||||
// console.log("1. handling view change")
|
||||
// if (view === "mydashboard" && isEditable) {
|
||||
// console.log("2. currently editing");
|
||||
// dialog.setOpen(true);
|
||||
// return;
|
||||
//
|
||||
// // const confirmed = window.confirm(
|
||||
// // "You have unsaved changes. Discard them and continue?"
|
||||
// // );
|
||||
// // if (!confirmed) return;
|
||||
// // onCancel();
|
||||
// }
|
||||
// setView(nextView);
|
||||
// };
|
||||
//
|
||||
// const onLayoutChange = (newLayout) => setLayout(newLayout);
|
||||
//
|
||||
// // Prop Forwarding
|
||||
// const canvasProps = { view, layout, setLayout, setOriginalLayout, onLayoutChange, onChangeView: handleViewChange,
|
||||
// onCancel, isEditable, setIsEditable, isDelete, setIsDelete, widgetArray, setWidgetArray, originalWidgets, setOriginalWidgets, beginEditIfNeeded
|
||||
// };
|
||||
// const sidebarProps = { view, onChangeView: handleViewChange, darkMode, setDarkMode };
|
||||
// const headerProps = { onChangeView: handleViewChange };
|
||||
//
|
||||
// return (
|
||||
// <>
|
||||
// <DialogPopup dialog={dialog} />
|
||||
// <Grid css={styles}
|
||||
// templateRows="1fr 11fr"
|
||||
// // templateColumns="1fr 20fr"
|
||||
// templateColumns="auto 1fr"
|
||||
// height="100vh"
|
||||
// width="100vw"
|
||||
// >
|
||||
// <GridItem rowSpan={1} colSpan={2}>
|
||||
// <Header {...headerProps}/>
|
||||
// </GridItem>
|
||||
// <GridItem colSpan={1}>
|
||||
// <Sidebar {...sidebarProps}/>
|
||||
// </GridItem>
|
||||
// <GridItem colSpan={1} width="100%" overflow="auto">
|
||||
// <Canvas {...canvasProps}/>
|
||||
// </GridItem>
|
||||
// </Grid>
|
||||
// </>
|
||||
// );
|
||||
// }
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Button } from "@chakra-ui/react";
|
||||
|
||||
export default function DeleteAllButton ({onDeleteAll}) {
|
||||
return (
|
||||
<Button onClick={onDeleteAll} color="#FFFFFF" bg="#EF4444" _hover={{ bg: "bg.error", color: "#EF4444"}}>
|
||||
Delete All
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { Box, Menu, Portal } from '@chakra-ui/react'
|
||||
import AlertLevel from "@/components/deprecated/AlertLevelWidget.jsx";
|
||||
|
||||
export default function FirstWidgetButton({ appendWidget }) {
|
||||
const triggerItem = (
|
||||
<>
|
||||
<Menu.Trigger asChild>
|
||||
<Box
|
||||
p={6}
|
||||
m="auto"
|
||||
mt={6}
|
||||
align="center"
|
||||
textAlign="center"
|
||||
justify="center"
|
||||
width="400px"
|
||||
borderRadius="md"
|
||||
boxShadow="md"
|
||||
border="2px dashed"
|
||||
borderColor="gray.300"
|
||||
bg="gray.50"
|
||||
cursor="pointer"
|
||||
_hover = {{
|
||||
bg: "gray.100",
|
||||
borderColor: "gray.400",
|
||||
boxShadow: "lg",
|
||||
}}
|
||||
>
|
||||
Add Your First Widget
|
||||
</Box>
|
||||
</Menu.Trigger>
|
||||
</>
|
||||
);
|
||||
const positioning = { placement: "bottom-middle" };
|
||||
// const WidgetMenuProps = { appendWidget, triggerItem, positioning };
|
||||
return (
|
||||
// <WidgetMenu {...WidgetMenuProps} />
|
||||
<Menu.Root positioning={positioning}>
|
||||
{triggerItem}
|
||||
<Portal>
|
||||
<Menu.Positioner>
|
||||
<Menu.Content>
|
||||
<Menu.Item
|
||||
value="AlertLevel"
|
||||
onClick={() => appendWidget(AlertLevel, 4, 7, 4, 7, 8, 14)} // width and height are passed through here for each widget
|
||||
>
|
||||
Alert Level
|
||||
</Menu.Item>
|
||||
<Menu.Item value="CO2">CO2</Menu.Item>
|
||||
<Menu.Item value="Ivans">IVANS</Menu.Item>
|
||||
<Menu.Item value="PlumeHeights">Plume Heights</Menu.Item>
|
||||
<Menu.Item value="AlertLevelChanges">Alert Level Changes</Menu.Item>
|
||||
</Menu.Content>
|
||||
</Menu.Positioner>
|
||||
</Portal>
|
||||
</Menu.Root>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Button } from "@chakra-ui/react";
|
||||
|
||||
export function SaveButton ({onSave}) {
|
||||
return (
|
||||
<Button onClick={onSave} borderRadius="md" bg="primary" _hover={{bg: "primaryLt"}}>Save</Button>
|
||||
)
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import { useSlotRecipe, chakra, Flex, CloseButton, Text, IconButton } from "@chakra-ui/react"
|
||||
import { Undo } from 'lucide-react';
|
||||
|
||||
export default function Widget(props) {
|
||||
// deconstructing props
|
||||
const { id, title, isEditable, isDelete, DeleteWidget, isSubmit, setIsSubmit, children } = props;
|
||||
|
||||
const recipe = useSlotRecipe({ key: "widget" });
|
||||
const styles = recipe();
|
||||
|
||||
return (
|
||||
<Flex flexDirection="column" w="100%" h="auto">
|
||||
{/* HEADER */}
|
||||
<Flex css={styles.header} cursor={isEditable ? "move":"default"} flexDirection="row" w="100%" h="auto" justifyContent="space-between" alignItems="center">
|
||||
<Text className="widget-handle" w="100%" display="flex" alignItems="center" height="32px" fontWeight="bold">{title}</Text>
|
||||
{isDelete ? (
|
||||
<CloseButton onClick={() => DeleteWidget(id)} size="xs" _hover={{bg: "tomato", color: "white"}}/>
|
||||
):(
|
||||
isSubmit ? (
|
||||
<IconButton onClick={() => setIsSubmit(false)} size="xs" bg="base300" cursor="pointer"><Undo fill="text" /></IconButton>
|
||||
):null
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{/* CHILDREN */}
|
||||
<Flex w="100%" h="auto">
|
||||
{children}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Menu, Portal } from "@chakra-ui/react";
|
||||
import AlertLevel from "./AlertLevelWidget.jsx";
|
||||
|
||||
export default function WidgetMenu({appendWidget, triggerItem, positioning}) {
|
||||
return (
|
||||
<Menu.Root positioning={positioning}>
|
||||
{triggerItem}
|
||||
<Portal>
|
||||
<Menu.Positioner>
|
||||
<Menu.Content>
|
||||
<Menu.Item
|
||||
value="AlertLevel"
|
||||
onClick={() => appendWidget(AlertLevel, 4, 7, 4, 7, 8, 14)} // width and height are passed through here for each widget
|
||||
>
|
||||
Alert Level
|
||||
</Menu.Item>
|
||||
<Menu.Item value="CO2">CO2</Menu.Item>
|
||||
<Menu.Item value="Ivans">IVANS</Menu.Item>
|
||||
<Menu.Item value="PlumeHeights">Plume Heights</Menu.Item>
|
||||
<Menu.Item value="AlertLevelChanges">Alert Level Changes</Menu.Item>
|
||||
</Menu.Content>
|
||||
</Menu.Positioner>
|
||||
</Portal>
|
||||
</Menu.Root>
|
||||
)
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { Tooltip as ChakraTooltip, Portal } from '@chakra-ui/react'
|
||||
import * as React from 'react'
|
||||
|
||||
export const Tooltip = React.forwardRef(function Tooltip(props, ref) {
|
||||
const {
|
||||
showArrow,
|
||||
children,
|
||||
disabled,
|
||||
portalled = true,
|
||||
content,
|
||||
contentProps,
|
||||
portalRef,
|
||||
...rest
|
||||
} = props
|
||||
|
||||
if (disabled) return children
|
||||
|
||||
return (
|
||||
<ChakraTooltip.Root {...rest}>
|
||||
<ChakraTooltip.Trigger asChild>{children}</ChakraTooltip.Trigger>
|
||||
<Portal disabled={!portalled} container={portalRef}>
|
||||
<ChakraTooltip.Positioner>
|
||||
<ChakraTooltip.Content ref={ref} {...contentProps}>
|
||||
{showArrow && (
|
||||
<ChakraTooltip.Arrow>
|
||||
<ChakraTooltip.ArrowTip />
|
||||
</ChakraTooltip.Arrow>
|
||||
)}
|
||||
{content}
|
||||
</ChakraTooltip.Content>
|
||||
</ChakraTooltip.Positioner>
|
||||
</Portal>
|
||||
</ChakraTooltip.Root>
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user