diff --git a/client/.env b/client/.env index a96328e..3df1a71 100644 --- a/client/.env +++ b/client/.env @@ -1 +1 @@ -REACT_APP_VERSION=1.3.2 \ No newline at end of file +REACT_APP_VERSION=1.3.3 \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 476f8d5..66b371f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2397,6 +2397,14 @@ "csstype": "^3.0.2" } }, + "@types/react-beautiful-dnd": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz", + "integrity": "sha512-by80tJ8aTTDXT256Gl+RfLRtFjYbUWOnZuEigJgNsJrSEGxvFe5eY6k3g4VIvf0M/6+xoLgfYWoWonlOo6Wqdg==", + "requires": { + "@types/react": "*" + } + }, "@types/react-dom": { "version": "17.0.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.3.tgz", @@ -4614,6 +4622,14 @@ "postcss": "^7.0.5" } }, + "css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "requires": { + "tiny-invariant": "^1.0.6" + } + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -9932,6 +9948,11 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -12300,6 +12321,11 @@ "performance-now": "^2.1.0" } }, + "raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -12362,6 +12388,20 @@ "whatwg-fetch": "^3.4.1" } }, + "react-beautiful-dnd": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", + "integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==", + "requires": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + } + }, "react-dev-utils": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", @@ -15077,6 +15117,11 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, + "use-memo-one": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz", + "integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==" + }, "util": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", diff --git a/client/package.json b/client/package.json index 5467e68..832d079 100644 --- a/client/package.json +++ b/client/package.json @@ -11,12 +11,14 @@ "@types/jest": "^26.0.23", "@types/node": "^12.20.12", "@types/react": "^17.0.5", + "@types/react-beautiful-dnd": "^13.0.0", "@types/react-dom": "^17.0.3", "@types/react-redux": "^7.1.16", "@types/react-router-dom": "^5.1.7", "axios": "^0.21.1", "http-proxy-middleware": "^2.0.0", "react": "^17.0.2", + "react-beautiful-dnd": "^13.1.0", "react-dom": "^17.0.2", "react-redux": "^7.2.4", "react-router-dom": "^5.2.0", diff --git a/client/src/components/Apps/AppTable/AppTable.tsx b/client/src/components/Apps/AppTable/AppTable.tsx index 728e079..1d80477 100644 --- a/client/src/components/Apps/AppTable/AppTable.tsx +++ b/client/src/components/Apps/AppTable/AppTable.tsx @@ -1,7 +1,8 @@ import { KeyboardEvent } from 'react'; import { connect } from 'react-redux'; import { App, GlobalState } from '../../../interfaces'; -import { pinApp, deleteApp } from '../../../store/actions'; +import { pinApp, deleteApp, reorderApp } from '../../../store/actions'; +import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd'; import classes from './AppTable.module.css'; import Icon from '../../UI/Icons/Icon/Icon'; @@ -12,6 +13,7 @@ interface ComponentProps { pinApp: (app: App) => void; deleteApp: (id: number) => void; updateAppHandler: (app: App) => void; + reorderApp: (apps: App[]) => void; } const AppTable = (props: ComponentProps): JSX.Element => { @@ -29,49 +31,89 @@ const AppTable = (props: ComponentProps): JSX.Element => { } } + const dragEndHanlder = (result: DropResult): void => { + console.log(result); + + if (!result.destination) { + return; + } + + const tmpApps = [...props.apps]; + const [movedApp] = tmpApps.splice(result.source.index, 1); + tmpApps.splice(result.destination.index, 0, movedApp); + + props.reorderApp(tmpApps); + } + return ( -
{app.name} | -{app.url} | -{app.icon} | -
- deleteAppHandler(app)}
- onKeyDown={(e) => keyboardActionHandler(e, app, deleteAppHandler)}
- tabIndex={0}>
-
- props.updateAppHandler(app)}
- onKeyDown={(e) => keyboardActionHandler(e, app, props.updateAppHandler)}
- tabIndex={0}>
-
- props.pinApp(app)}
- onKeyDown={(e) => keyboardActionHandler(e, app, props.pinApp)}
- tabIndex={0}>
- {app.isPinned
- ?
- |
-
{app.name} | +{app.url} | +{app.icon} | + {!snapshot.isDragging && ( +
+ deleteAppHandler(app)}
+ onKeyDown={(e) => keyboardActionHandler(e, app, deleteAppHandler)}
+ tabIndex={0}>
+
+ props.updateAppHandler(app)}
+ onKeyDown={(e) => keyboardActionHandler(e, app, props.updateAppHandler)}
+ tabIndex={0}>
+
+ props.pinApp(app)}
+ onKeyDown={(e) => keyboardActionHandler(e, app, props.pinApp)}
+ tabIndex={0}>
+ {app.isPinned
+ ?
+ |
+ )}
+