diff --git a/package-lock.json b/package-lock.json index 380c0196..f3f790ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,9 @@ "@azure/core-amqp": "3.2.0", "@azure/event-hubs": "5.6.0", "@azure/msal-node": "1.14.6", + "@dnd-kit/core": "6.3.1", + "@dnd-kit/sortable": "10.0.0", + "@dnd-kit/utilities": "3.2.2", "@fluentui/react": "8.101.2", "@microsoft/applicationinsights-web": "2.8.4", "@rjsf/fluent-ui": "5.7.0", @@ -38,7 +41,6 @@ "react-jsonschema-form": "1.8.1", "react-monaco-editor": "0.54.0", "react-router-dom": "5.2.0", - "react-smooth-dnd": "0.11.0", "react-toastify": "4.4.0", "redux-saga": "1.1.3", "semver": "6.3.1", @@ -59,7 +61,7 @@ "@types/jest-plugin-context": "2.9.0", "@types/node": "18.16.15", "@types/node-fetch": "2.6.2", - "@types/react": "16.9.35", + "@types/react": "^16.9.35", "@types/react-dom": "16.9.8", "@types/react-jsonschema-form": "1.0.10", "@types/react-router-dom": "5.3.3", @@ -1142,6 +1144,55 @@ "node": ">=10.0.0" } }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", + "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", + "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", + "dependencies": { + "@dnd-kit/accessibility": "^3.1.1", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", + "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", + "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@electron/asar": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.9.tgz", @@ -16208,18 +16259,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/react-smooth-dnd": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/react-smooth-dnd/-/react-smooth-dnd-0.11.0.tgz", - "integrity": "sha512-zo14IBA3MOilZ/DOTD35CwOy1Exh+GWbMXWIsyQVlmrMBi59mc3HupKVGtS/iXb2V8FbmUOMq1csvblI86Uh0w==", - "dependencies": { - "prop-types": ">=15.6.0", - "smooth-dnd": "0.12.0" - }, - "peerDependencies": { - "react": "^16.3.0" - } - }, "node_modules/react-test-renderer": { "version": "16.14.0", "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.14.0.tgz", @@ -17951,11 +17990,6 @@ "node": ">=8" } }, - "node_modules/smooth-dnd": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/smooth-dnd/-/smooth-dnd-0.12.0.tgz", - "integrity": "sha512-w+/YW1TFram8FW/bYiirRcAGSIdVVjxFRtCBqJ2fkEJpm28zwbdMyXVQCralBUTITMjZp6VHGQJ73UTSIER1lA==" - }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", diff --git a/package.json b/package.json index f9656b1b..2de0cba5 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,9 @@ "@azure/core-amqp": "3.2.0", "@azure/event-hubs": "5.6.0", "@azure/msal-node": "1.14.6", + "@dnd-kit/core": "6.3.1", + "@dnd-kit/sortable": "10.0.0", + "@dnd-kit/utilities": "3.2.2", "@fluentui/react": "8.101.2", "@microsoft/applicationinsights-web": "2.8.4", "@rjsf/fluent-ui": "5.7.0", @@ -98,7 +101,6 @@ "react-jsonschema-form": "1.8.1", "react-monaco-editor": "0.54.0", "react-router-dom": "5.2.0", - "react-smooth-dnd": "0.11.0", "react-toastify": "4.4.0", "redux-saga": "1.1.3", "semver": "6.3.1", diff --git a/src/app/css/_deviceDetail.scss b/src/app/css/_deviceDetail.scss index c612d20c..d2ad8da6 100644 --- a/src/app/css/_deviceDetail.scss +++ b/src/app/css/_deviceDetail.scss @@ -37,6 +37,12 @@ margin-bottom: 15px; } +.ms-ContextualMenu-secondaryText { + @include themify($themes) { + color: themed('disabledText') !important; + } +} + .properties-section-command-bar { .ms-CommandBar { border-bottom: 0px !important; diff --git a/src/app/devices/cloudToDeviceMessage/components/__snapshots__/cloudToDeviceMessage.spec.tsx.snap b/src/app/devices/cloudToDeviceMessage/components/__snapshots__/cloudToDeviceMessage.spec.tsx.snap index c475a7ff..7150ada5 100644 --- a/src/app/devices/cloudToDeviceMessage/components/__snapshots__/cloudToDeviceMessage.spec.tsx.snap +++ b/src/app/devices/cloudToDeviceMessage/components/__snapshots__/cloudToDeviceMessage.spec.tsx.snap @@ -32,6 +32,7 @@ exports[`cloudToDeviceMessage matches snapshot 1`] = ` cloudToDeviceMessage.body { > {t(ResourceKeys.cloudToDeviceMessage.body)} - + - - - - - - - - - - - - - - - + + + `; exports[`ModelRepositoryLocationList matches snapshot with no items 1`] = ` -
- -
+ +
+ + `; diff --git a/src/app/modelRepository/components/modelRepositoryInstruction.tsx b/src/app/modelRepository/components/modelRepositoryInstruction.tsx index 0df275ca..43a0febf 100644 --- a/src/app/modelRepository/components/modelRepositoryInstruction.tsx +++ b/src/app/modelRepository/components/modelRepositoryInstruction.tsx @@ -5,9 +5,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from '@fluentui/react'; -import { NavLink } from 'react-router-dom'; import { ResourceKeys } from '../../../localization/resourceKeys'; -import { ROUTE_PARTS } from '../../constants/routes'; import './modelRepositoryInstruction.scss'; export const ModelRepositoryInstruction: React.FC = () => { diff --git a/src/app/modelRepository/components/modelRepositoryLocationList.tsx b/src/app/modelRepository/components/modelRepositoryLocationList.tsx index 13e4597e..d91f836e 100644 --- a/src/app/modelRepository/components/modelRepositoryLocationList.tsx +++ b/src/app/modelRepository/components/modelRepositoryLocationList.tsx @@ -3,40 +3,105 @@ * Licensed under the MIT License **********************************************************/ import * as React from 'react'; -import { Container, Draggable } from 'react-smooth-dnd'; +import { + DndContext, + closestCenter, + useSensor, + useSensors, + PointerSensor, + KeyboardSensor, +} from '@dnd-kit/core'; +import { + arrayMove, + SortableContext, + useSortable, + sortableKeyboardCoordinates, +} from '@dnd-kit/sortable'; +import { CSS } from '@dnd-kit/utilities'; import { ModelRepositoryLocationListItem } from './modelRepositoryLocationListItem'; -import { ModelRepositoryConfiguration } from '../../shared/modelRepository/state'; import { ModelRepositoryFormType } from '../hooks/useModelRepositoryForm'; +import { ModelRepositoryConfiguration } from '../../shared/modelRepository/state'; import './modelRepositoryLocationList.scss'; -export const ModelRepositoryLocationList: React.FC<{formState: ModelRepositoryFormType}> = ({formState}) => { - const[{ repositoryLocationSettings }, {setRepositoryLocationSettings, setDirtyFlag}] = formState; +export const ModelRepositoryLocationList: React.FC<{ + formState: ModelRepositoryFormType; + }> = ({ formState }) => { + const [ + { repositoryLocationSettings }, + { setRepositoryLocationSettings, setDirtyFlag }, + ] = formState; + + const sensors = useSensors( + useSensor(PointerSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }) + ); + + const handleDragEnd = (event: any) => { // tslint:disable-line: no-any + const { active, over } = event; + + if (active.id !== over?.id) { + const oldIndex = repositoryLocationSettings.findIndex( + item => item.repositoryLocationType === active.id + ); + const newIndex = repositoryLocationSettings.findIndex( + item => item.repositoryLocationType === over.id + ); - const onDrop = (e: {addedIndex: number, removedIndex: number}) => { - const updatedRepositoryLocationSettings = [...repositoryLocationSettings]; - updatedRepositoryLocationSettings.splice(e.addedIndex, 0, updatedRepositoryLocationSettings.splice(e.removedIndex, 1)[0]); + const updatedRepositoryLocationSettings = arrayMove( + repositoryLocationSettings, + oldIndex, + newIndex + ); - setDirtyFlag(true); - setRepositoryLocationSettings(updatedRepositoryLocationSettings); + setDirtyFlag(true); + setRepositoryLocationSettings(updatedRepositoryLocationSettings); + } }; - const renderModelRepositoryLocationListItem = (item: ModelRepositoryConfiguration, index: number) => { + const SortableItem: React.FC<{ item: ModelRepositoryConfiguration, index: number }> = ({ item, index }) => { + const { + attributes, + listeners, + setNodeRef, + transform, + transition, + } = useSortable({ id: item.repositoryLocationType }); + + const style = { + transform: CSS.Transform.toString(transform), + transition, + }; + return ( - - - +
+ +
); }; return ( -
- - {repositoryLocationSettings && repositoryLocationSettings.map((item, index) => renderModelRepositoryLocationListItem(item, index))} - -
+ + item.repositoryLocationType + )} + > +
+ {repositoryLocationSettings.map((item, index) => ( + + ))} +
+
+
); }; diff --git a/src/app/navigation/components/__snapshots__/breadcrumb.spec.tsx.snap b/src/app/navigation/components/__snapshots__/breadcrumb.spec.tsx.snap index 512c7c3f..24b6d51f 100644 --- a/src/app/navigation/components/__snapshots__/breadcrumb.spec.tsx.snap +++ b/src/app/navigation/components/__snapshots__/breadcrumb.spec.tsx.snap @@ -13,6 +13,11 @@ exports[`Breadcrumb matches snapshot when link is enabled 1`] = ` className="breadcrumb-item" > name @@ -25,6 +30,11 @@ exports[`Breadcrumb matches snapshot when suffix is truthy 1`] = ` className="breadcrumb-item" > name diff --git a/src/app/navigation/components/breadcrumb.tsx b/src/app/navigation/components/breadcrumb.tsx index 2f0aa457..c033adf6 100644 --- a/src/app/navigation/components/breadcrumb.tsx +++ b/src/app/navigation/components/breadcrumb.tsx @@ -11,7 +11,7 @@ export const Breadcrumb: React.FC = ({ disableLink, url, s
  • {disableLink && <>{name}} {!disableLink && - + {name} }