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';