From efe9fdf915d7c5c16c0fb9c266595e55923cc2ae Mon Sep 17 00:00:00 2001 From: Patrick Robertson Date: Thu, 27 Feb 2025 13:02:50 +0000 Subject: [PATCH] Tidy ups to config editor page --- scripts/settings/package-lock.json | 174 ++++++++---- scripts/settings/package.json | 6 +- scripts/settings/src/App.tsx | 267 +++++++----------- scripts/settings/src/StepCard.tsx | 200 +++++++++++++ scripts/settings/src/schema.json | 2 + .../modules/local_storage/__manifest__.py | 4 +- 6 files changed, 434 insertions(+), 219 deletions(-) create mode 100644 scripts/settings/src/StepCard.tsx diff --git a/scripts/settings/package-lock.json b/scripts/settings/package-lock.json index 6ef055b..cd40c14 100644 --- a/scripts/settings/package-lock.json +++ b/scripts/settings/package-lock.json @@ -8,12 +8,14 @@ "name": "material-ui-vite-ts", "version": "5.0.0", "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", "@emotion/react": "latest", "@emotion/styled": "latest", "@mui/icons-material": "latest", "@mui/material": "latest", - "react": "latest", - "react-dom": "latest", + "react": "19.0.0", + "react-dom": "19.0.0", "react-markdown": "^10.0.0", "yaml": "^2.7.0" }, @@ -322,6 +324,59 @@ "node": ">=6.9.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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.13.5", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", @@ -942,9 +997,9 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.5.tgz", - "integrity": "sha512-zoXvHU1YuoodgMlPS+epP084Pqv9V+Vg+5IGv9n/7IIFVQ2nkTngYHYxElCq8pdTTbDcgji+nNh0lxri2abWgA==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.6.tgz", + "integrity": "sha512-rho5Q4IscbrVmK9rCrLTJmjLjfH6m/NcqKr/mchvck0EIXlyYUB9+Z0oVmkt/+Mben43LMRYBH8q/Uzxj/c4Vw==", "license": "MIT", "funding": { "type": "opencollective", @@ -952,9 +1007,9 @@ } }, "node_modules/@mui/icons-material": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.4.5.tgz", - "integrity": "sha512-4A//t8Nrc+4u4pbVhGarIFU98zpuB5AV9hTNzgXx1ySZJ1tWtx+i/1SbQ8PtGJxWeXlljhwimZJNPQ3x0CiIFw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.4.6.tgz", + "integrity": "sha512-rGJBvIQQbQAlyKYljHQ8wAQS/K2/uYwvemcpygnAmCizmCI4zSF9HQPuiG8Ql4YLZ6V/uKjA3WHIYmF/8sV+pQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0" @@ -967,7 +1022,7 @@ "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@mui/material": "^6.4.5", + "@mui/material": "^6.4.6", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, @@ -978,16 +1033,16 @@ } }, "node_modules/@mui/material": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.5.tgz", - "integrity": "sha512-5eyEgSXocIeV1JkXs8mYyJXU0aFyXZIWI5kq2g/mCnIgJe594lkOBNAKnCIaGVfQTu2T6TTEHF8/hHIqpiIRGA==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.6.tgz", + "integrity": "sha512-6UyAju+DBOdMogfYmLiT3Nu7RgliorimNBny1pN/acOjc+THNFVE7hlxLyn3RDONoZJNDi/8vO4AQQr6dLAXqA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/core-downloads-tracker": "^6.4.5", - "@mui/system": "^6.4.3", + "@mui/core-downloads-tracker": "^6.4.6", + "@mui/system": "^6.4.6", "@mui/types": "^7.2.21", - "@mui/utils": "^6.4.3", + "@mui/utils": "^6.4.6", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.12", "clsx": "^2.1.1", @@ -1006,7 +1061,7 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^6.4.3", + "@mui/material-pigment-css": "^6.4.6", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" @@ -1027,13 +1082,13 @@ } }, "node_modules/@mui/private-theming": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.3.tgz", - "integrity": "sha512-7x9HaNwDCeoERc4BoEWLieuzKzXu5ZrhRnEM6AUcRXUScQLvF1NFkTlP59+IJfTbEMgcGg1wWHApyoqcksrBpQ==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.6.tgz", + "integrity": "sha512-T5FxdPzCELuOrhpA2g4Pi6241HAxRwZudzAuL9vBvniuB5YU82HCmrARw32AuCiyTfWzbrYGGpZ4zyeqqp9RvQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/utils": "^6.4.3", + "@mui/utils": "^6.4.6", "prop-types": "^15.8.1" }, "engines": { @@ -1054,9 +1109,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.3.tgz", - "integrity": "sha512-OC402VfK+ra2+f12Gef8maY7Y9n7B6CZcoQ9u7mIkh/7PKwW/xH81xwX+yW+Ak1zBT3HYcVjh2X82k5cKMFGoQ==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.6.tgz", + "integrity": "sha512-vSWYc9ZLX46be5gP+FCzWVn5rvDr4cXC5JBZwSIkYk9xbC7GeV+0kCvB8Q6XLFQJy+a62bbqtmdwS4Ghi9NBlQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", @@ -1088,16 +1143,16 @@ } }, "node_modules/@mui/system": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.3.tgz", - "integrity": "sha512-Q0iDwnH3+xoxQ0pqVbt8hFdzhq1g2XzzR4Y5pVcICTNtoCLJmpJS3vI4y/OIM1FHFmpfmiEC2IRIq7YcZ8nsmg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.6.tgz", + "integrity": "sha512-FQjWwPec7pMTtB/jw5f9eyLynKFZ6/Ej9vhm5kGdtmts1z5b7Vyn3Rz6kasfYm1j2TfrfGnSXRvvtwVWxjpz6g==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/private-theming": "^6.4.3", - "@mui/styled-engine": "^6.4.3", + "@mui/private-theming": "^6.4.6", + "@mui/styled-engine": "^6.4.6", "@mui/types": "^7.2.21", - "@mui/utils": "^6.4.3", + "@mui/utils": "^6.4.6", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -1142,9 +1197,9 @@ } }, "node_modules/@mui/utils": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.3.tgz", - "integrity": "sha512-jxHRHh3BqVXE9ABxDm+Tc3wlBooYz/4XPa0+4AI+iF38rV1/+btJmSUgG4shDtSWVs/I97aDn5jBCt6SF2Uq2A==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.6.tgz", + "integrity": "sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", @@ -1642,6 +1697,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -1881,9 +1937,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.105", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.105.tgz", - "integrity": "sha512-ccp7LocdXx3yBhwiG0qTQ7XFrK48Ua2pxIxBdJO8cbddp/MvbBtPFzvnTchtyHQTsgqqczO8cdmAIbpMa0u2+g==", + "version": "1.5.107", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.107.tgz", + "integrity": "sha512-dJr1o6yCntRkXElnhsHh1bAV19bo/hKyFf7tCcWgpXbuFIF0Lakjgqv5LRfSDaNzAII8Fnxg2tqgHkgCvxdbxw==", "dev": true, "license": "ISC" }, @@ -1980,6 +2036,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2205,6 +2262,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -2896,6 +2954,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -3026,6 +3085,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3090,28 +3150,24 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.25.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.0.0" } }, "node_modules/react-is": { @@ -3281,13 +3337,10 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -3374,6 +3427,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -3401,6 +3455,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/typescript": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", @@ -3503,9 +3563,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { diff --git a/scripts/settings/package.json b/scripts/settings/package.json index 6608693..aec7706 100644 --- a/scripts/settings/package.json +++ b/scripts/settings/package.json @@ -9,12 +9,14 @@ "preview": "vite preview" }, "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", "@emotion/react": "latest", "@emotion/styled": "latest", "@mui/icons-material": "latest", "@mui/material": "latest", - "react": "latest", - "react-dom": "latest", + "react": "19.0.0", + "react-dom": "19.0.0", "react-markdown": "^10.0.0", "yaml": "^2.7.0" }, diff --git a/scripts/settings/src/App.tsx b/scripts/settings/src/App.tsx index 6e6e813..126836c 100644 --- a/scripts/settings/src/App.tsx +++ b/scripts/settings/src/App.tsx @@ -3,42 +3,34 @@ import { useEffect, useState } from 'react'; import Container from '@mui/material/Container'; import Typography from '@mui/material/Typography'; import Box from '@mui/material/Box'; -import Link from '@mui/material/Link'; -import { modules, steps, configs, module_types } from './schema.json'; + +// +import { + DndContext, + closestCenter, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, + DragOverlay +} from "@dnd-kit/core"; +import { + arrayMove, + SortableContext, + sortableKeyboardCoordinates, + rectSortingStrategy +} from "@dnd-kit/sortable"; + + +import { modules, steps, module_types } from './schema.json'; import { - Checkbox, - Select, - MenuItem, - FormControl, - FormControlLabel, - InputLabel, - FormHelperText, Stack, - TextField, - Card, - CardContent, - CardActions, Button, - Dialog, - DialogTitle, - DialogContent, } from '@mui/material'; import Grid from '@mui/material/Grid2'; -import Accordion from '@mui/material/Accordion'; -import AccordionDetails from '@mui/material/AccordionDetails'; -import AccordionSummary from '@mui/material/AccordionSummary'; -import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; -import ReactMarkdown from 'react-markdown'; -import { parseDocument, ParsedNode, Document } from 'yaml' -import { set } from 'yaml/dist/schema/yaml-1.1/set'; - -Object.defineProperty(String.prototype, 'capitalize', { - value: function() { - return this.charAt(0).toUpperCase() + this.slice(1); - }, - enumerable: false -}); +import { parseDocument, Document } from 'yaml' +import StepCard from './StepCard'; function FileDrop({ setYamlFile }) { @@ -86,117 +78,21 @@ function FileDrop({ setYamlFile }) { ); } - -function ModuleCheckbox({ module, toggleModule, enabledModules, configValues }: { module: object, toggleModule: any, enabledModules: any, configValues: any }) { - let name = module.name; - const [helpOpen, setHelpOpen] = useState(false); - const [configOpen, setConfigOpen] = useState(false); - if (name == 'metadata_enricher') { - console.log("hi"); - } - return ( - <> - - - } - label={module.display_name} /> - - - - {enabledModules.includes(name) && module.configs && name != 'cli_feeder' ? ( - - ) : null} - - - setHelpOpen(false)} - maxWidth="lg" - > - - {module.display_name} - - - - {module.manifest.description.split("\n").map((line: string) => line.trim()).join("\n")} - - - - {module.configs && name != 'cli_feeder' && } - - ) -} - - -function ConfigPanel({ module, open, setOpen, configValues }: { module: any, open: boolean, setOpen: any, configValues: any }) { - return ( - <> - setOpen(false)} - maxWidth="lg" - > - - {module.display_name} - - - - {Object.keys(module.configs).map((config_value: any) => { - let config_args = module.configs[config_value]; - let config_name = config_value.replace(/_/g," "); - return ( - - - { config_args.type === 'bool' ? - } label={config_name} /> - : - ( config_args.type === 'int' ? - - : - ( - config_args.choices !== undefined ? - <> - {config_name} - - - : - - ) - ) - } - {config_args.help} - - - ); - })} - - - - - ); -} - -function ModuleTypes({ stepType, toggleModule, enabledModules, configValues }: { stepType: string, toggleModule: any, enabledModules: any, configValues: any }) { +function ModuleTypes({ stepType, setEnabledModules, enabledModules, configValues }: { stepType: string, setEnabledModules: any, enabledModules: any, configValues: any }) { const [showError, setShowError] = useState(false); + const [activeId, setActiveId] = useState(null); + const [items, setItems] = useState(enabledModules[stepType].map(([name, enabled]: [string, boolean]) => name)); - const _toggleModule = (event: any) => { + const toggleModule = (event: any) => { // make sure that 'feeder' and 'formatter' types only have one value let name = event.target.id; + let checked = event.target.checked; if (stepType === 'feeder' || stepType === 'formatter') { - let checked = event.target.checked; // check how many modules of this type are enabled - let modules = steps[stepType].filter((m: string) => (m !== name && enabledModules.includes(m)) || (checked && m === name)); - if (modules.length > 1) { + const checkedModules = enabledModules[stepType].filter(([m, enabled]: [string, boolean]) => { + return (m !== name && enabled) || (checked && m === name) + }); + if (checkedModules.length > 1) { setShowError(true); } else { setShowError(false); @@ -204,24 +100,85 @@ function ModuleTypes({ stepType, toggleModule, enabledModules, configValues }: { } else { setShowError(false); } - toggleModule(event); + let newEnabledModules = { ...enabledModules }; + newEnabledModules[stepType] = enabledModules[stepType].map(([m, enabled]: [string, boolean]) => { + return (m === name) ? [m, checked] : [m, enabled]; + } + ); + setEnabledModules(newEnabledModules); } + + const sensors = useSensors( + useSensor(PointerSensor), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates + }) + ); + + const handleDragStart = (event) => { + setActiveId(event.active.id); + }; + + const handleDragEnd = (event) => { + setActiveId(null); + const { active, over } = event; + + if (active.id !== over.id) { + const oldIndex = items.indexOf(active.id); + const newIndex = items.indexOf(over.id); + + let newArray = arrayMove(items, oldIndex, newIndex); + // set it also on steps + let newEnabledModules = { ...enabledModules }; + newEnabledModules[stepType] = enabledModules[stepType].sort((a, b) => { + return newArray.indexOf(a[0]) - newArray.indexOf(b[0]); + }) + setEnabledModules(newEnabledModules); + setItems(newArray); + } + }; return ( <> + {stepType}s + + Select the {stepType}s you wish to enable. You can drag and drop them to reorder them. + + {showError ? Only one {stepType} can be enabled at a time. : null} + + - {steps[stepType].map((name: string) => { + + {items.map((name: string) => { let m = modules[name]; return ( - - - + ); })} + + {activeId ? ( +
+ + ) : null} +
+
+
); } @@ -229,7 +186,7 @@ function ModuleTypes({ stepType, toggleModule, enabledModules, configValues }: { export default function App() { const [yamlFile, setYamlFile] = useState(new Document()); - const [enabledModules, setEnabledModules] = useState<[]>([]); + const [enabledModules, setEnabledModules] = useState<{}>(Object.fromEntries(module_types.map(type => [type, steps[type].map((name: string) => [name, false])]))); const [configValues, setConfigValues] = useState<{}>( Object.keys(modules).reduce((acc, module) => { acc[module] = {}; @@ -241,15 +198,14 @@ export default function App() { // edit the yamlFile // generate the steps config - let stepsConfig = {} - module_types.forEach((stepType: string) => { - stepsConfig[stepType] = enabledModules.filter((m: string) => steps[stepType].includes(m)); - } - ); + let stepsConfig = enabledModules; // create a yaml file from const finalYaml = { - 'steps': stepsConfig + 'steps': Object.keys(stepsConfig).reduce((acc, stepType) => { + acc[stepType] = stepsConfig[stepType].filter(([name, enabled]: [string, boolean]) => enabled).map(([name, enabled]: [string, boolean]) => name); + return acc; + }, {}) }; Object.keys(configValues).map((module: string) => { @@ -274,17 +230,6 @@ export default function App() { } } - const toggleModule = function (event: any) { - let module = event.target.id; - let checked = event.target.checked - - if (checked) { - setEnabledModules([...enabledModules, module]); - } else { - setEnabledModules(enabledModules.filter((m: string) => m !== module)); - } - } - useEffect(() => { // load the configs, and set the default values if they exist let newConfigValues = {}; @@ -339,7 +284,9 @@ export default function App() { {Object.keys(steps).map((stepType: string) => { return ( - + + + ); })} @@ -355,8 +302,10 @@ export default function App() { 4. Save your settings + + diff --git a/scripts/settings/src/StepCard.tsx b/scripts/settings/src/StepCard.tsx new file mode 100644 index 0000000..d401d25 --- /dev/null +++ b/scripts/settings/src/StepCard.tsx @@ -0,0 +1,200 @@ +import { useState } from "react"; +import { useSortable } from "@dnd-kit/sortable"; +import ReactMarkdown from 'react-markdown'; + +import { CSS } from "@dnd-kit/utilities"; + +import { + Card, + CardContent, + CardActions, + CardHeader, + Button, + Dialog, + DialogTitle, + DialogContent, + Box, + IconButton, + Checkbox, + Select, + MenuItem, + FormControl, + FormControlLabel, + InputLabel, + FormHelperText, + TextField, + Stack, + Typography, + } from '@mui/material'; +import Grid from '@mui/material/Grid2'; +import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; +import { set } from "yaml/dist/schema/yaml-1.1/set"; + + +Object.defineProperty(String.prototype, 'capitalize', { + value: function() { + return this.charAt(0).toUpperCase() + this.slice(1); + }, + enumerable: false +}); + +const StepCard = ({ + type, + module, + toggleModule, + enabledModules, + configValues +}: { + type: string, + module: object, + toggleModule: any, + enabledModules: any, + configValues: any +}) => { + const { + attributes, + listeners, + setNodeRef, + transform, + transition, + isDragging + } = useSortable({ id: module.name }); + + + const style = { + transform: CSS.Transform.toString(transform), + transition, + zIndex: isDragging ? "100" : "auto", + opacity: isDragging ? 0.3 : 1 + }; + + let name = module.name; + const [helpOpen, setHelpOpen] = useState(false); + const [configOpen, setConfigOpen] = useState(false); + const enabled = enabledModules[type].find((m: any) => m[0] === name)[1]; + + return ( + + + } + label={module.display_name} /> + } + action ={ + + + + } + /> + + + {enabled && module.configs && name != 'cli_feeder' ? ( + + ) : null} + + + + setHelpOpen(false)} + maxWidth="lg" + > + + {module.display_name} + + + + {module.manifest.description.split("\n").map((line: string) => line.trim()).join("\n")} + + + + {module.configs && name != 'cli_feeder' && } + + ) + } + + +function ConfigPanel({ module, open, setOpen, configValues }: { module: any, open: boolean, setOpen: any, configValues: any }) { + + function setConfigValue(config: any, value: any) { + configValues[module.name][config] = value; + } + return ( + <> + setOpen(false)} + maxWidth="lg" + > + + {module.display_name} + + + + {Object.keys(module.configs).map((config_value: any) => { + const config_args = module.configs[config_value]; + const config_name = config_value.replace(/_/g," "); + const config_display_name = config_name.capitalize(); + const value = configValues[module.name][config_value] || config_args.default; + return ( + + {config_display_name} + + { config_args.type === 'bool' ? + { + setConfigValue(config_value, e.target.checked); + }} + /> + : + ( + config_args.choices !== undefined ? + + : + ( config_args.type === 'json_loader' ? + { + try { + val = JSON.parse(e.target.value); + setConfigValue(config_value, val); + } catch (e) { + console.log(e); + } + } + } type='text' /> + : + { + setConfigValue(config_value, e.target.value); + }} /> + ) + ) + } + {config_args.help} + + + ); + })} + + + + + ); + } + +export default StepCard; \ No newline at end of file diff --git a/scripts/settings/src/schema.json b/scripts/settings/src/schema.json index e02067c..e4f470d 100644 --- a/scripts/settings/src/schema.json +++ b/scripts/settings/src/schema.json @@ -1914,6 +1914,7 @@ }, "save_absolute": { "default": false, + "type": "bool", "help": "whether the path to the stored file is absolute or relative in the output result inc. formatters (WARN: leaks the file structure)" } } @@ -1942,6 +1943,7 @@ }, "save_absolute": { "default": false, + "type": "bool", "help": "whether the path to the stored file is absolute or relative in the output result inc. formatters (WARN: leaks the file structure)" } } diff --git a/src/auto_archiver/modules/local_storage/__manifest__.py b/src/auto_archiver/modules/local_storage/__manifest__.py index 6d9cf53..4f6c2df 100644 --- a/src/auto_archiver/modules/local_storage/__manifest__.py +++ b/src/auto_archiver/modules/local_storage/__manifest__.py @@ -17,7 +17,9 @@ "choices": ["random", "static"], }, "save_to": {"default": "./local_archive", "help": "folder where to save archived content"}, - "save_absolute": {"default": False, "help": "whether the path to the stored file is absolute or relative in the output result inc. formatters (WARN: leaks the file structure)"}, + "save_absolute": {"default": False, + "type": "bool", + "help": "whether the path to the stored file is absolute or relative in the output result inc. formatters (WARN: leaks the file structure)"}, }, "description": """ LocalStorage: A storage module for saving archived content locally on the filesystem.