diff --git a/src/components/AppShelf/AddAppShelfItem.tsx b/src/components/AppShelf/AddAppShelfItem.tsx index af44ad651..0c92a0e9d 100644 --- a/src/components/AppShelf/AddAppShelfItem.tsx +++ b/src/components/AppShelf/AddAppShelfItem.tsx @@ -6,21 +6,16 @@ import { Image, Button, Select, - AspectRatio, - Text, - Card, LoadingOverlay, ActionIcon, Tooltip, Title, } from '@mantine/core'; import { useForm } from '@mantine/form'; -import { motion } from 'framer-motion'; import { useState } from 'react'; import { Apps } from 'tabler-icons-react'; import { useConfig } from '../../tools/state'; import { ServiceTypeList } from '../../tools/types'; -import { AppShelfItemWrapper } from './AppShelfItemWrapper'; export function AddItemShelfButton(props: any) { const [opened, setOpened] = useState(false); @@ -51,56 +46,6 @@ export function AddItemShelfButton(props: any) { ); } -export default function AddItemShelfItem(props: any) { - const [opened, setOpened] = useState(false); - return ( - <> - setOpened(false)} - title="Add a service" - > - - - - - - - Add a service - - - - - - - setOpened(true)} size={60} /> - - - - - - ); -} - function MatchIcon(name: string, form: any) { fetch( `https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/${name diff --git a/src/components/AppShelf/AppShelf.tsx b/src/components/AppShelf/AppShelf.tsx index 9d689e157..2d4bf5768 100644 --- a/src/components/AppShelf/AppShelf.tsx +++ b/src/components/AppShelf/AppShelf.tsx @@ -1,112 +1,79 @@ import React, { useState } from 'react'; -import { motion } from 'framer-motion'; -import { Text, AspectRatio, Card, Image, Center, Grid, createStyles, Anchor } from '@mantine/core'; +import { Grid } from '@mantine/core'; +import { + closestCenter, + DndContext, + DragOverlay, + MouseSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; +import { arrayMove, SortableContext } from '@dnd-kit/sortable'; import { useConfig } from '../../tools/state'; -import { serviceItem } from '../../tools/types'; -import AppShelfMenu from './AppShelfMenu'; -import PingComponent from '../modules/ping/PingModule'; -const useStyles = createStyles((theme) => ({ - item: { - transition: 'box-shadow 150ms ease, transform 100ms ease', - - '&:hover': { - boxShadow: `${theme.shadows.md} !important`, - transform: 'scale(1.05)', - }, - }, -})); +import { SortableAppShelfItem, AppShelfItem } from './AppShelfItem'; const AppShelf = (props: any) => { - const { config } = useConfig(); + const [activeId, setActiveId] = useState(null); + const { config, setConfig } = useConfig(); + const sensors = useSensors( + useSensor(MouseSensor, { + // Require the mouse to move by 10 pixels before activating + activationConstraint: { + delay: 250, + tolerance: 5, + }, + }) + ); + + function handleDragStart(event: any) { + const { active } = event; + + setActiveId(active.id); + } + + function handleDragEnd(event: any) { + const { active, over } = event; + + if (active.id !== over.id) { + const newConfig = { ...config }; + const activeIndex = newConfig.services.findIndex((e) => e.id === active.id); + const overIndex = newConfig.services.findIndex((e) => e.id === over.id); + newConfig.services = arrayMove(newConfig.services, activeIndex, overIndex); + setConfig(newConfig); + } + + setActiveId(null); + } + return ( - - {config.services.map((service) => ( - - - - ))} - + + + + {config.services.map((service) => ( + + + + ))} + + + + {activeId ? ( + e.id === activeId)} id={activeId} /> + ) : null} + + ); }; -export function AppShelfItem(props: any) { - const { service }: { service: serviceItem } = props; - const [hovering, setHovering] = useState(false); - const { classes, theme } = useStyles(); - return ( - { - setHovering(true); - }} - onHoverEnd={() => { - setHovering(false); - }} - > - - - - - {service.name} - - - - - - -
- - - - { - window.open(service.url); - }} - /> - - - - -
-
-
- ); -} - export default AppShelf; diff --git a/src/components/AppShelf/AppShelfItem.tsx b/src/components/AppShelf/AppShelfItem.tsx new file mode 100644 index 000000000..585f14bd1 --- /dev/null +++ b/src/components/AppShelf/AppShelfItem.tsx @@ -0,0 +1,123 @@ +import { + Text, + Card, + Anchor, + AspectRatio, + Image, + Center, + createStyles, +} from '@mantine/core'; +import { motion } from 'framer-motion'; +import { useState } from 'react'; +import { useSortable } from '@dnd-kit/sortable'; +import { CSS } from '@dnd-kit/utilities'; +import { serviceItem } from '../../tools/types'; +import PingComponent from '../modules/ping/PingModule'; +import AppShelfMenu from './AppShelfMenu'; + +const useStyles = createStyles((theme) => ({ + item: { + transition: 'box-shadow 150ms ease, transform 100ms ease', + + '&:hover': { + boxShadow: `${theme.shadows.md} !important`, + transform: 'scale(1.05)', + }, + }, +})); + +export function SortableAppShelfItem(props: any) { + const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ + id: props.id, + }); + + const style = { + transform: CSS.Transform.toString(transform), + transition, + }; + + return ( +
+ +
+ ); +} + +export function AppShelfItem(props: any) { + const { service }: { service: serviceItem } = props; + const [hovering, setHovering] = useState(false); + const { classes, theme } = useStyles(); + return ( + { + setHovering(true); + }} + onHoverEnd={() => { + setHovering(false); + }} + > + + + + + {service.name} + + + + + + +
+ + + + { + window.open(service.url); + }} + /> + + + + +
+
+
+ ); +} diff --git a/src/components/AppShelf/AppShelfItemWrapper.tsx b/src/components/AppShelf/AppShelfItemWrapper.tsx deleted file mode 100644 index ffe409062..000000000 --- a/src/components/AppShelf/AppShelfItemWrapper.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useMantineTheme, Card } from '@mantine/core'; - -export function AppShelfItemWrapper(props: any) { - const { children, hovering } = props; - const theme = useMantineTheme(); - return ( - - {children} - - ); -} diff --git a/src/components/AppShelf/index.ts b/src/components/AppShelf/index.ts new file mode 100644 index 000000000..fd496bd5b --- /dev/null +++ b/src/components/AppShelf/index.ts @@ -0,0 +1,2 @@ +export { default as AppShelf } from './AppShelf'; +export * from './AppShelfItem';