diff --git a/assets/css/app.css b/assets/css/app.css index eb78a69a13a9..b7b58953357d 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -5,6 +5,8 @@ @import './tooltip.css'; @import './flatpickr-colors.css'; @import './chartjs.css'; +@import 'react-grid-layout/css/styles.css'; +@import 'react-resizable/css/styles.css'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities'; @@ -50,7 +52,8 @@ html { body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - width: 100vw; /* Prevents content from jumping when scrollbar is added/removed due to vertical overflow */ + width: 100vw; + /* Prevents content from jumping when scrollbar is added/removed due to vertical overflow */ overflow-x: hidden; } @@ -284,20 +287,23 @@ iframe[hidden] { .active-prop-heading { /* Properties related to text-decoration are all here in one place. TailwindCSS does support underline but that's about it. */ text-decoration-line: underline; - text-decoration-color: #4338ca; /* tailwind's indigo-700 */ + text-decoration-color: #4338ca; + /* tailwind's indigo-700 */ text-decoration-thickness: 2px; } @media (prefers-color-scheme: dark) { .active-prop-heading { - text-decoration-color: #6366f1; /* tailwind's indigo-500 */ + text-decoration-color: #6366f1; + /* tailwind's indigo-500 */ } } /* This class is used for styling embedded dashboards. Do not remove. */ /* stylelint-disable */ /* prettier-ignore */ -.date-option-group { } +.date-option-group {} + /* stylelint-enable */ .popper-tooltip { @@ -320,4 +326,4 @@ iframe[hidden] { visibility: visible; content: ''; transform: rotate(45deg) translateY(1px); -} +} \ No newline at end of file diff --git a/assets/js/dashboard/index.tsx b/assets/js/dashboard/index.tsx index f4c51038cff4..b4a74f7ce962 100644 --- a/assets/js/dashboard/index.tsx +++ b/assets/js/dashboard/index.tsx @@ -8,6 +8,82 @@ import { TopBar } from './nav-menu/top-bar' import Behaviours from './stats/behaviours' import { useQueryContext } from './query-context' import { isRealTimeDashboard } from './util/filters' +import { Layout, Responsive, WidthProvider, ResizeHandle } from 'react-grid-layout' + +const ResponsiveGridLayout = WidthProvider(Responsive); + +type Layouts = { + lg: Layout[]; + md: Layout[]; + sm: Layout[]; + xs: Layout[]; + xxs: Layout[]; +}; + +//NOTE: Here can be problem as ResizeHandle is not exported from react-grid-layout by default, create own type or export it from react-grid-layout +//type ResizeHandle = "se" | "sw" | "ne" | "nw" | "e" | "w" | "n" | "s"; +const availableResizers: ResizeHandle[] = ["se"]; + +const breakpointsConfig: { [key in keyof Layouts]: { columns: number; width: number; height: number } } = { + lg: { columns: 2, width: 15, height: 13 }, + md: { columns: 2, width: 8, height: 13 }, + sm: { columns: 1, width: 16, height: 13 }, + xs: { columns: 1, width: 12, height: 13 }, + xxs: { columns: 1, width: 8, height: 13 }, +}; + +interface ItemConfig { + id: string; + minW?: number; + minH?: number; +} + +const items: ItemConfig[] = [ + { id: "sources", minW: 5, minH: 12 }, + { id: "pages", minW: 5, minH: 12 }, + { id: "locations", minW: 5, minH: 12 }, + { id: "devices", minW: 5, minH: 12 }, +]; + +const generateLayouts = (): Layouts => { + const layouts = {} as Layouts; + + for (const bp in breakpointsConfig) { + const config = breakpointsConfig[bp as keyof Layouts]; + layouts[bp as keyof Layouts] = items.map((item, index) => { + // For single-column layouts, x is always 0, and y increases by the height of each item. + // For multi-column layouts, x depends on the column position and y on the row. + const x = config.columns === 1 ? 0 : (index % config.columns) * config.width; + const y = config.columns === 1 ? index * config.height : Math.floor(index / config.columns) * config.height; + return { + i: item.id, + x, + y, + w: config.width, + h: config.height, + minW: item.minW, + minH: item.minH, + resizeHandles: availableResizers, + }; + }); + } + return layouts; +}; + +function getFromLS() { + if (typeof window === 'undefined') return null; + try { + return JSON.parse(window.localStorage.getItem("dashboard-layout") || "null"); + } catch (_error) { + return null; + } +} + +function saveToLS(layouts: Layouts) { + if (typeof window !== 'undefined') { + window.localStorage.setItem("dashboard-layout", JSON.stringify(layouts)); + } +} function DashboardStats({ importedDataInView, @@ -16,30 +92,56 @@ function DashboardStats({ importedDataInView?: boolean updateImportedDataInView?: (v: boolean) => void }) { + const initialLayouts = getFromLS() || generateLayouts(); + const [layouts, setLayouts] = useState(initialLayouts); + + const onLayoutChange = (_currentLayout: Layout[], allLayouts: Layouts) => { + setLayouts(allLayouts); + saveToLS(allLayouts); + if (typeof updateImportedDataInView === 'function') { + updateImportedDataInView(true); + } + }; + const statsBoxClass = - 'stats-item relative w-full mt-6 p-4 flex flex-col bg-white dark:bg-gray-825 shadow-xl rounded' + 'relative p-4 flex flex-col bg-white dark:bg-gray-825 shadow-xl rounded' + + const dragHandleClass = + 'drag-handle absolute top-0 left-0 right-0 h-5 rounded-t' return ( <> -
-
+ +
+
-
+
+
-
- -
-
+
+
-
+
+
-
- + ) @@ -71,4 +173,4 @@ function Dashboard() { ) } -export default Dashboard +export default Dashboard; diff --git a/assets/js/dashboard/stats/behaviours/index.js b/assets/js/dashboard/stats/behaviours/index.js index 43d8b8c74dc3..55e9a339c68b 100644 --- a/assets/js/dashboard/stats/behaviours/index.js +++ b/assets/js/dashboard/stats/behaviours/index.js @@ -445,7 +445,7 @@ export default function Behaviours({ importedDataInView }) { if (mode) { return ( -
+
diff --git a/assets/package-lock.json b/assets/package-lock.json index 1fe7a6dc228e..9ff47bf0a269 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -30,6 +30,8 @@ "react-dom": "^18.3.1", "react-flatpickr": "3.10.5", "react-flip-move": "^3.0.4", + "react-grid-dnd": "^2.1.2", + "react-grid-layout": "^1.5.1", "react-intersection-observer": "^9.5.2", "react-popper": "^2.3.0", "react-router-dom": "^6.25.1", @@ -49,6 +51,7 @@ "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/react-flatpickr": "^3.8.11", + "@types/react-grid-layout": "^1.3.5", "@types/topojson-client": "^3.1.4", "@typescript-eslint/eslint-plugin": "^8.0.1", "@typescript-eslint/parser": "^8.0.1", @@ -76,17 +79,6 @@ "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", "dev": true }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1646,6 +1638,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1659,6 +1652,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -1667,6 +1661,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -1674,12 +1669,14 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1702,6 +1699,7 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -1713,6 +1711,7 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -1720,6 +1719,7 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -2506,8 +2506,7 @@ "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { "version": "18.3.3", @@ -2538,6 +2537,22 @@ "flatpickr": "^4.0.6" } }, + "node_modules/@types/react-grid-layout": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/react-grid-layout/-/react-grid-layout-1.3.5.tgz", + "integrity": "sha512-WH/po1gcEcoR6y857yAnPGug+ZhkF4PaTUxgAbwfeSH/QOgVSakKHBXoPGad/sEznmkiaK3pqHk+etdWisoeBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -2954,13 +2969,9 @@ "node": ">=4" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "license": "MIT", - "peer": true - }, "node_modules/anymatch": { "version": "3.1.3", + "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -2970,11 +2981,6 @@ "node": ">= 8" } }, - "node_modules/arg": { - "version": "5.0.2", - "license": "MIT", - "peer": true - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3386,18 +3392,12 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "dev": true, "license": "MIT" }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3408,6 +3408,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -3511,14 +3512,6 @@ "node": ">=6" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001651", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", @@ -3572,43 +3565,6 @@ "chart.js": ">=3.0.0" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "license": "ISC", - "peer": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -3652,6 +3608,15 @@ "node": ">=12" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -3709,6 +3674,7 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "dev": true, "license": "MIT" }, "node_modules/convert-source-map": { @@ -3877,6 +3843,7 @@ }, "node_modules/cssesc": { "version": "3.0.0", + "dev": true, "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -4505,11 +4472,6 @@ "node": ">=8" } }, - "node_modules/didyoumean": { - "version": "1.2.2", - "license": "Apache-2.0", - "peer": true - }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -4531,11 +4493,6 @@ "node": ">=8" } }, - "node_modules/dlv": { - "version": "1.1.3", - "license": "MIT", - "peer": true - }, "node_modules/doctrine": { "version": "3.0.0", "dev": true, @@ -5429,10 +5386,17 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-equals": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", + "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==", + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -5446,6 +5410,7 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -5481,6 +5446,7 @@ }, "node_modules/fastq": { "version": "1.15.0", + "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -5540,6 +5506,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5625,10 +5592,12 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "dev": true, "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.2", + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5642,6 +5611,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5780,6 +5750,7 @@ }, "node_modules/glob-parent": { "version": "6.0.2", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -5966,6 +5937,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -6123,6 +6095,7 @@ }, "node_modules/inflight": { "version": "1.0.6", + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -6131,6 +6104,7 @@ }, "node_modules/inherits": { "version": "2.0.4", + "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -6223,17 +6197,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "license": "MIT", - "peer": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-boolean-object": { "version": "1.1.2", "dev": true, @@ -6264,6 +6227,7 @@ "version": "2.15.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "dev": true, "dependencies": { "hasown": "^2.0.2" }, @@ -6305,6 +6269,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6357,6 +6322,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -6393,6 +6359,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "engines": { "node": ">=0.12.0" } @@ -8388,14 +8355,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jiti": { - "version": "1.19.3", - "license": "MIT", - "peer": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "license": "MIT" @@ -8658,16 +8617,9 @@ "node": ">= 0.8.0" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", + "dev": true, "license": "MIT" }, "node_modules/locate-path": { @@ -8824,6 +8776,7 @@ }, "node_modules/merge2": { "version": "1.4.1", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -8833,6 +8786,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -8889,6 +8843,7 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -8920,20 +8875,11 @@ "dev": true, "license": "MIT" }, - "node_modules/mz": { - "version": "2.7.0", - "license": "MIT", - "peer": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, "funding": [ { "type": "github", @@ -8966,6 +8912,7 @@ }, "node_modules/normalize-path": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8996,14 +8943,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -9122,6 +9061,7 @@ }, "node_modules/once": { "version": "1.4.0", + "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -9257,6 +9197,7 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9272,6 +9213,7 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -9308,10 +9250,12 @@ "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -9320,16 +9264,9 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pirates": { "version": "4.0.6", + "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -9412,6 +9349,7 @@ "version": "8.4.40", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", + "dev": true, "funding": [ { "type": "opencollective", @@ -9435,94 +9373,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-import": { - "version": "15.1.0", - "license": "MIT", - "peer": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "license": "MIT", - "peer": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.1", - "license": "MIT", - "peer": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - }, - "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.3.2", - "license": "ISC", - "peer": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "license": "MIT", - "peer": true, - "dependencies": { - "postcss-selector-parser": "^6.0.11" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.4.tgz", @@ -9559,6 +9409,7 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9569,6 +9420,7 @@ }, "node_modules/postcss-value-parser": { "version": "4.2.0", + "dev": true, "license": "MIT" }, "node_modules/prelude-ls": { @@ -9688,6 +9540,7 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "dev": true, "funding": [ { "type": "github", @@ -9727,6 +9580,29 @@ "react": "^18.3.1" } }, + "node_modules/react-draggable": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.6.tgz", + "integrity": "sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==", + "license": "MIT", + "dependencies": { + "clsx": "^1.1.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, + "node_modules/react-draggable/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/react-fast-compare": { "version": "3.2.0", "license": "MIT" @@ -9747,6 +9623,62 @@ "react-dom": ">=16.3.x" } }, + "node_modules/react-grid-dnd": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/react-grid-dnd/-/react-grid-dnd-2.1.2.tgz", + "integrity": "sha512-E+XcyemjmRm5Dk3Rn4e2KPpRK4dF1e8NyuOXhm4ZsmVIJVnkP+AzojkTn333ec2Fbe55PUxuHqYA6Fl0Wz65Ng==", + "license": "MIT", + "dependencies": { + "@types/react": "^16.8.10", + "@types/react-dom": "^16.8.3", + "react-spring": "9.0.0-beta.8", + "resize-observer-polyfill": "^1.5.1", + "tslib": "^1.9.3" + }, + "peerDependencies": { + "react": "^16.8.6", + "react-dom": "^16.8.6", + "react-gesture-responder": "^2.1.0" + } + }, + "node_modules/react-grid-dnd/node_modules/@types/react": { + "version": "16.14.63", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.63.tgz", + "integrity": "sha512-s83gano0fRBVEw3ejdLpjgvU83F0LIeeuXqdxfPZF/Sc2bhr60tEqCK1zZ+aLirBwRSD6V5zCtOsEjcwKow3JQ==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "^0.16", + "csstype": "^3.0.2" + } + }, + "node_modules/react-grid-dnd/node_modules/@types/react-dom": { + "version": "16.9.25", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.25.tgz", + "integrity": "sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^16.0.0" + } + }, + "node_modules/react-grid-layout": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.5.1.tgz", + "integrity": "sha512-4Fr+kKMk0+m1HL/BWfHxi/lRuaOmDNNKQDcu7m12+NEYcen20wIuZFo789u3qWCyvUsNUxCiyf0eKq4WiJSNYw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "fast-equals": "^4.0.3", + "prop-types": "^15.8.1", + "react-draggable": "^4.4.5", + "react-resizable": "^3.0.5", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, "node_modules/react-intersection-observer": { "version": "9.5.2", "license": "MIT", @@ -9771,6 +9703,19 @@ "react-dom": "^16.8.0 || ^17 || ^18" } }, + "node_modules/react-resizable": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz", + "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==", + "license": "MIT", + "dependencies": { + "prop-types": "15.x", + "react-draggable": "^4.0.3" + }, + "peerDependencies": { + "react": ">= 16.3" + } + }, "node_modules/react-router": { "version": "6.25.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", @@ -9801,6 +9746,20 @@ "react-dom": ">=16.8" } }, + "node_modules/react-spring": { + "version": "9.0.0-beta.8", + "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.0.0-beta.8.tgz", + "integrity": "sha512-pcyQqr5W9HBM5Rm0rmdbVIEQz7wocAfWBNWSUm/EEvpb4M0OQ3Xp9JW6Ayo+6ZgV7fLzJJHO/QgNdUMpAtVaTw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.3.1", + "prop-types": "^15.5.8" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "license": "BSD-3-Clause", @@ -9815,25 +9774,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "license": "MIT", - "peer": true, - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "license": "MIT", - "peer": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -9914,8 +9854,15 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.4", + "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", @@ -9979,6 +9926,7 @@ }, "node_modules/reusify": { "version": "1.0.4", + "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -10006,6 +9954,7 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "dev": true, "funding": [ { "type": "github", @@ -10256,6 +10205,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10698,54 +10648,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/sucrase": { - "version": "3.34.0", - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "7.1.6", - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/supports-color": { "version": "5.5.0", "dev": true, @@ -10793,6 +10695,7 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10849,42 +10752,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/tailwindcss": { - "version": "3.3.3", - "license": "MIT", - "peer": true, - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.12", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.18.2", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -10913,25 +10780,6 @@ "dev": true, "license": "MIT" }, - "node_modules/thenify": { - "version": "3.3.1", - "license": "MIT", - "peer": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "license": "MIT", - "peer": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -10951,6 +10799,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -11015,11 +10864,6 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "license": "Apache-2.0", - "peer": true - }, "node_modules/ts-jest": { "version": "29.2.4", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", @@ -11104,6 +10948,12 @@ "strip-bom": "^3.0.0" } }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -11309,6 +11159,7 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "dev": true, "license": "MIT" }, "node_modules/v8-to-istanbul": { @@ -11605,6 +11456,7 @@ }, "node_modules/wrappy": { "version": "1.0.2", + "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { diff --git a/assets/package.json b/assets/package.json index eaf03c58f123..32139eaf7dc6 100644 --- a/assets/package.json +++ b/assets/package.json @@ -34,6 +34,8 @@ "react-dom": "^18.3.1", "react-flatpickr": "3.10.5", "react-flip-move": "^3.0.4", + "react-grid-dnd": "^2.1.2", + "react-grid-layout": "^1.5.1", "react-intersection-observer": "^9.5.2", "react-popper": "^2.3.0", "react-router-dom": "^6.25.1", @@ -53,6 +55,7 @@ "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/react-flatpickr": "^3.8.11", + "@types/react-grid-layout": "^1.3.5", "@types/topojson-client": "^3.1.4", "@typescript-eslint/eslint-plugin": "^8.0.1", "@typescript-eslint/parser": "^8.0.1",