From 3d3ded20b78e3acecc150a3a8e59ff625dee5a7b Mon Sep 17 00:00:00 2001 From: theau Date: Fri, 20 Jun 2025 14:21:24 +0200 Subject: [PATCH 1/5] feat: user documentation directly in the application --- package-lock.json | 1543 ++++++++++++++++- packages/diracx-web-components/package.json | 1 + .../DashboardLayout/DashboardDrawer.tsx | 16 +- .../DashboardLayout/HelpOverlay.tsx | 196 +++ .../src/components/UserDocumentation.ts | 86 + .../src/components/index.ts | 3 + .../src/contexts/ApplicationsProvider.tsx | 11 +- .../src/types/UserDocumentation.ts | 14 + .../diracx-web-components/src/types/index.ts | 1 + .../stories/Dashboard.stories.tsx | 1 + .../extensions/src/app/(dashboard)/layout.tsx | 2 + .../src/gubbins/UserDocumentation.ts | 28 + 12 files changed, 1857 insertions(+), 45 deletions(-) create mode 100644 packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx create mode 100644 packages/diracx-web-components/src/components/UserDocumentation.ts create mode 100644 packages/diracx-web-components/src/types/UserDocumentation.ts create mode 100644 packages/extensions/src/gubbins/UserDocumentation.ts diff --git a/package-lock.json b/package-lock.json index 4224a408..fc417fc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,37 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/install-pkg/node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "license": "MIT", + "optional": true + }, + "node_modules/@antfu/utils": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", + "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@atlaskit/atlassian-context": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@atlaskit/atlassian-context/-/atlassian-context-0.2.0.tgz", @@ -2114,6 +2145,57 @@ "dev": true, "license": "MIT" }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", + "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==", + "license": "MIT", + "optional": true + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0", + "optional": true + }, "node_modules/@chromatic-com/storybook": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-3.2.6.tgz", @@ -3324,6 +3406,43 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT", + "optional": true + }, + "node_modules/@iconify/utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", + "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@antfu/install-pkg": "^1.0.0", + "@antfu/utils": "^8.1.0", + "@iconify/types": "^2.0.0", + "debug": "^4.4.0", + "globals": "^15.14.0", + "kolorist": "^1.8.0", + "local-pkg": "^1.0.0", + "mlly": "^1.7.4" + } + }, + "node_modules/@iconify/utils/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", @@ -4577,6 +4696,16 @@ "react": ">=16" } }, + "node_modules/@mermaid-js/parser": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.5.0.tgz", + "integrity": "sha512-AiaN7+VjXC+3BYE+GwNezkpjIcCI2qIMB/K4S2/vMWe0q/XJCBbx5+K7iteuz7VyltX9iAK4FmVTvGc9kjOV4w==", + "license": "MIT", + "optional": true, + "dependencies": { + "langium": "3.3.1" + } + }, "node_modules/@microsoft/api-extractor": { "version": "7.52.5", "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.52.5.tgz", @@ -7252,6 +7381,290 @@ "@types/node": "*" } }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", + "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -7298,6 +7711,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT", + "optional": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -7441,6 +7861,13 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "license": "MIT" }, + "node_modules/@types/prismjs": { + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz", + "integrity": "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==", + "license": "MIT", + "optional": true + }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -7517,6 +7944,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -8305,7 +8739,7 @@ "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -9965,6 +10399,34 @@ "node": ">= 0.8.0" } }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -10327,6 +10789,13 @@ "dev": true, "license": "MIT" }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "license": "MIT", + "optional": true + }, "node_modules/consola": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", @@ -10435,6 +10904,16 @@ "dev": true, "license": "MIT" }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "optional": true, + "dependencies": { + "layout-base": "^1.0.0" + } + }, "node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", @@ -10831,57 +11310,608 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cypress/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cytoscape": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.0.tgz", + "integrity": "sha512-5JHBC9n75kz5851jeklCPmZWcg3hUe6sjqJvyk3+hVqFaKcHwHgxsjeN1yLmggoUc6STbtm9/NQyabQehfjvWQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "optional": true, + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT", + "optional": true + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "optional": true, + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "optional": true, + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "optional": true, + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC", + "optional": true + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "optional": true, + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "optional": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" }, "engines": { - "node": ">=10" + "node": ">=12" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "d3-selection": "2 - 3" } }, - "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "optional": true, "dependencies": { - "has-flag": "^4.0.0" + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/cypress/node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cypress/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, + "node_modules/dagre-d3-es": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", + "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", "license": "MIT", + "optional": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" + "d3": "^7.9.0", + "lodash-es": "^4.17.21" } }, "node_modules/damerau-levenshtein": { @@ -11110,6 +12140,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "optional": true, + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -11327,6 +12367,16 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", + "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -12686,6 +13736,13 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/exsolve": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.6.tgz", + "integrity": "sha512-Q05uIdxhPBVBwK29gcPsl2K220xSBy52TZQPdeYWE0zOs8jM+yJ6y5h7jm6cpAo1p+OOMZRIj/Ftku4EQQBLnQ==", + "license": "MIT", + "optional": true + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -13692,6 +14749,13 @@ "resolved": "packages/extensions", "link": true }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT", + "optional": true + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -14060,7 +15124,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -14269,6 +15333,16 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/is-arguments": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", @@ -16956,6 +18030,33 @@ "node": ">=4.0" } }, + "node_modules/katex": { + "version": "0.16.22", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", + "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -16966,6 +18067,12 @@ "json-buffer": "3.0.1" } }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==", + "optional": true + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -16976,6 +18083,30 @@ "node": ">=6" } }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "license": "MIT", + "optional": true + }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "license": "MIT", + "optional": true, + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", @@ -16996,6 +18127,13 @@ "node": ">=0.10" } }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT", + "optional": true + }, "node_modules/lazy-ass": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", @@ -17528,6 +18666,24 @@ "node": ">= 12.13.0" } }, + "node_modules/local-pkg": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz", + "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.0.1", + "quansync": "^0.2.8" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", @@ -17551,6 +18707,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT", + "optional": true + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -17917,6 +19080,32 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/markdown-to-jsx": { + "version": "7.7.8", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.7.8.tgz", + "integrity": "sha512-e+5bQJ30iIyJUV4tH/3wuBjpE5muLXsuBBi30N9t3B9O+UomC1Ocdqu7uD3X4YqtPrNLz+6QwHJaD7CXURBi+w==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/marked": { + "version": "15.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", + "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", + "license": "MIT", + "optional": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -18205,6 +19394,56 @@ "node": ">= 8" } }, + "node_modules/mermaid": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.7.0.tgz", + "integrity": "sha512-/1/5R0rt0Z1Ak0CuznAnCF3HtQgayRXUz6SguzOwN4L+DuCobz0UxnQ+ZdTSZ3AugKVVh78tiVmsHpHWV25TCw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@braintree/sanitize-url": "^7.0.4", + "@iconify/utils": "^2.1.33", + "@mermaid-js/parser": "^0.5.0", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.11", + "dayjs": "^1.11.13", + "dompurify": "^3.2.5", + "katex": "^0.16.9", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^15.0.7", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/mermaid/node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT", + "optional": true + }, + "node_modules/mermaid/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -18934,12 +20173,60 @@ "node": ">=8" } }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "license": "MIT", + "optional": true, + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT", + "optional": true + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/mui-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mui-markdown/-/mui-markdown-2.0.1.tgz", + "integrity": "sha512-R++Ju6+a0qRPyMDY3JBXo1zt6RncntuQ1r684ECTxSbED9/fDSu7GT2pNQsxQivs4QRLAw11glrsRBTOspBwoA==", + "license": "MIT", + "optionalDependencies": { + "mermaid": "^11.6.0", + "prism-react-renderer": "^2.0.3" + }, + "peerDependencies": { + "@mui/material": ">=5.0.0", + "markdown-to-jsx": ">=7.0.0", + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -19966,6 +21253,13 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "license": "MIT", + "optional": true + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -20063,6 +21357,13 @@ "dev": true, "license": "MIT" }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT", + "optional": true + }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -20142,6 +21443,13 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT", + "optional": true + }, "node_modules/pathval": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", @@ -20314,6 +21622,18 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", + "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", + "license": "MIT", + "optional": true, + "dependencies": { + "confbox": "^0.2.1", + "exsolve": "^1.0.1", + "pathe": "^2.0.3" + } + }, "node_modules/pkg-up": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", @@ -20406,6 +21726,24 @@ "node": ">=6" } }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT", + "optional": true + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "optional": true, + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/polished": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", @@ -20697,6 +22035,20 @@ "dev": true, "license": "MIT" }, + "node_modules/prism-react-renderer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.4.1.tgz", + "integrity": "sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -20841,6 +22193,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", + "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT", + "optional": true + }, "node_modules/querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", @@ -21691,6 +23060,13 @@ "inherits": "^2.0.1" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense", + "optional": true + }, "node_modules/rollup": { "version": "4.40.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", @@ -21731,6 +23107,19 @@ "fsevents": "~2.3.2" } }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -21755,6 +23144,13 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause", + "optional": true + }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -21845,7 +23241,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/sass-loader": { @@ -23373,7 +24769,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6.10" @@ -23856,6 +25252,13 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT", + "optional": true + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -24275,6 +25678,61 @@ "dev": true, "license": "MIT" }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "optional": true, + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "optional": true, + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT", + "optional": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT", + "optional": true + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT", + "optional": true + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -24936,6 +26394,7 @@ "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "dayjs": "^1.11.13", + "mui-markdown": "^2.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-virtuoso": "^4.12.3", diff --git a/packages/diracx-web-components/package.json b/packages/diracx-web-components/package.json index 1e0750c9..a269e3ab 100644 --- a/packages/diracx-web-components/package.json +++ b/packages/diracx-web-components/package.json @@ -35,6 +35,7 @@ "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "dayjs": "^1.11.13", + "mui-markdown": "^2.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-virtuoso": "^4.12.3", diff --git a/packages/diracx-web-components/src/components/DashboardLayout/DashboardDrawer.tsx b/packages/diracx-web-components/src/components/DashboardLayout/DashboardDrawer.tsx index ebc8ee76..f6ba6d70 100644 --- a/packages/diracx-web-components/src/components/DashboardLayout/DashboardDrawer.tsx +++ b/packages/diracx-web-components/src/components/DashboardLayout/DashboardDrawer.tsx @@ -16,7 +16,7 @@ import { Toolbar, useTheme, } from "@mui/material"; -import { MenuBook, Add } from "@mui/icons-material"; +import { MenuBook, Add, TipsAndUpdates } from "@mui/icons-material"; import React, { useContext, useEffect, useState } from "react"; import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge"; @@ -24,6 +24,7 @@ import { ApplicationsContext } from "../../contexts/ApplicationsProvider"; import { DashboardGroup } from "../../types"; import DrawerItemGroup from "./DrawerItemGroup"; import AppDialog from "./ApplicationDialog"; +import HelpOverlay from "./HelpOverlay"; interface DashboardDrawerProps { /** The variant of the drawer. Usually temporary if on mobile and permanent otherwise. */ @@ -78,6 +79,8 @@ export default function DashboardDrawer({ const [renamingGroupId, setRenamingGroupId] = useState(null); const [renameValue, setRenameValue] = useState(""); + const [helpOpen, setHelpOpen] = useState(false); + // Define the applications that are accessible to users. // Each application has an associated icon and path. const [userDashboard, setUserDashboard, , , setCurrentAppId] = @@ -456,6 +459,15 @@ export default function DashboardDrawer({ + + setHelpOpen(true)} + data-testid="user-guide-button" + > + {} + + + {} @@ -523,6 +535,8 @@ export default function DashboardDrawer({ setAppDialogOpen={setAppDialogOpen} handleCreateApp={handleAppCreation} /> + + setHelpOpen(false)} /> ); } diff --git a/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx b/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx new file mode 100644 index 00000000..b0b61840 --- /dev/null +++ b/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx @@ -0,0 +1,196 @@ +import { useState, useContext } from "react"; +import { MuiMarkdown, defaultOverrides } from "mui-markdown"; + +import { + Box, + Typography, + ListItemButton, + IconButton, + List, + ListItemText, + Divider, + Modal, + Collapse, + useTheme, +} from "@mui/material"; + +import { grey } from "@mui/material/colors"; + +import CloseIcon from "@mui/icons-material/Close"; + +import ExpandLess from "@mui/icons-material/ExpandLess"; +import ExpandMore from "@mui/icons-material/ExpandMore"; +import { ApplicationsContext } from "../../contexts"; + +/** + * + * @param isOpen Boolean indicating if the help page is open + * @param closeHelp Function to close the help page + * @returns Component to display the help overlay with user documentation + */ +export default function HelpOverlay({ + isOpen, + closeHelp, +}: { + isOpen: boolean; + closeHelp: () => void; +}) { + const [selected, setSelected] = useState("general"); + const [expandedApps, setExpandedApps] = useState>({}); + + const userDocumentation = useContext(ApplicationsContext)[5]; + const theme = useTheme(); + + const backgroundColor = theme.palette.mode === "dark" ? grey[900] : grey[50]; + + const customOverrides = { + ...defaultOverrides, + h1: { + component: Typography, + props: { + variant: "h3", + gutterBottom: true, + sx: { + marginTop: "1.5rem", + marginBottom: "1.5rem", + }, + } as React.HTMLProps, + }, + h2: { + component: Typography, + props: { + variant: "h4", + gutterBottom: true, + sx: { + marginTop: "1rem", + marginBottom: "0.5rem", + }, + } as React.HTMLProps, + }, + h3: { + component: Typography, + props: { + variant: "h5", + gutterBottom: true, + sx: { + marginTop: "0.75rem", + marginBottom: "0.25rem", + }, + } as React.HTMLProps, + }, + p: { + component: Typography, + props: { + paragraph: true, + } as React.HTMLProps, + }, + }; + // Handle application section toggle + const toggleApp = (appName: string) => { + setExpandedApps((prev) => ({ + ...prev, + [appName]: !prev[appName], + })); + }; + + // Render content based on selected item + const RenderContent = () => { + if (selected === "general") { + return ( + <> + + {userDocumentation.generalUsage} + + + ); + } + + const [appName, sectionTitle] = selected.split("::"); + const app = userDocumentation.applications.find( + (a) => a.appName === appName, + ); + const section = app?.sections.find((s) => s.title === sectionTitle); + + return ( + <> + + {section?.content} + + + ); + }; + + return ( + + + {/* Left vertical menu */} + + + + + + setSelected("general")} + > + + + + {userDocumentation.applications.map((app, index) => ( + + toggleApp(app.appName)}> + + {expandedApps[app.appName] ? : } + + + + {app.sections.map((section) => ( + + setSelected(`${app.appName}::${section.title}`) + } + > + + + ))} + + + + ))} + + + + {/* Right content pane */} + {RenderContent()} + + + ); +} diff --git a/packages/diracx-web-components/src/components/UserDocumentation.ts b/packages/diracx-web-components/src/components/UserDocumentation.ts new file mode 100644 index 00000000..7160d3ba --- /dev/null +++ b/packages/diracx-web-components/src/components/UserDocumentation.ts @@ -0,0 +1,86 @@ +import { UserDocumentation } from "../types/UserDocumentation"; + +/** + * User documentation for DiracX web. + * + */ +export const userDocumentation: UserDocumentation = { + generalUsage: ` +# General usage + +## Navigate between applications + +You can click on the \`Add application\` button to create a new instance of an application. The list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard + +## Share applications + +To share applications, click the \`Export\` button at the top right of the screen. Then, select the applications you want to share and copy them to the clipboard. + +## Import applications + +To import applications, click the \`Import\` button at the top right of the screen. Paste the copied applications into the input field and click \`Import\`. The imported applications will appear in the sidebar. +If the states are outdated, you can copy the updated version of them by clicking the \`Copy all updated states\` button. + +## Save you dashoard +To save your dashboard, clicke the \`Export\`button at the top right of the screen. Then, select the applications you want to save and click on the \`Save in the browser\` button. The saved applications will be stored in your browser's local storage. +When you want to load the saved applications, click the \`Import\` button at the top right of the screen and select the \`Load from the browser\` option. The saved applications will be loaded into the sidebar. + +`, + applications: [ + { + appName: "Job Monitor", + sections: [ + { + title: "General Usage", + content: ` +# General Usage + +The \`Job Monitor\` application allows you to track and manage jobs. It provides a search bar to filter jobs by criteria such as job type, status, and submission date. The application displays a list of jobs in a table format, with each job showing its status and other relevant information.`, + }, + { + title: "The Search Bar", + content: ` +# How to use the search bar + +The search bar allows you to filter jobs based on various criteria. The filters are represented as equations in the search bar, where each equation consists of a job attribute, an operator, and a value. + +A resarch is automatically performed when all the equations in the search bar are valid. + +## How to create a filter +To create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. + +The search bar only suggests attributes, operators, and values that are available in your current set of jobs. + +## How to edit a filter +To edit a filter, click on the filter in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. + +## How to remove a filter + +To remove a filter, you can either press the \`Backspace\` key to remove the last token or right-click on the equation to remove the entire equation. `, + }, + { + title: "The table", + content: ` +# How to use the table + +The table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date. + +## Actions on the table + +You can click on the eye icon to select more columns to display in the table. +You can sort the table by clicking on the column headers. Clicking on a column header will sort the table in ascending order, and clicking again will sort it in descending order. +You can set the page size by clicking on the \`Row per page\` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page. + +## Actions on a job + +You can do a right-click on a job to open the \`Job History\`. +You can select one or more jobs by clicking on the checkboxes next to each job. Once you have selected jobs, you can perform actions on them using the buttons at the top of the table. The available actions include: +- **Get IDs**: This button will copy the IDs of the selected jobs to the clipboard. +- **Rechedule**: This button will reschedule the selected jobs. +- **Kill**: This button will kill the selected jobs. +- **Delete**: This button will delete the selected jobs.`, + }, + ], + }, + ], +}; diff --git a/packages/diracx-web-components/src/components/index.ts b/packages/diracx-web-components/src/components/index.ts index f5da5865..40788e9f 100644 --- a/packages/diracx-web-components/src/components/index.ts +++ b/packages/diracx-web-components/src/components/index.ts @@ -1,6 +1,9 @@ // Application list export { applicationList } from "./applicationList"; +// User Documentation +export { userDocumentation } from "./UserDocumentation"; + // Dashboard Layout export * from "./DashboardLayout"; diff --git a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx index c0996263..29b788c2 100644 --- a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx +++ b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx @@ -4,7 +4,9 @@ import React, { createContext, useEffect, useState } from "react"; import { applicationList } from "../components/applicationList"; import { defaultDashboard } from "../components/defaultDashboard"; import { DashboardGroup } from "../types/DashboardGroup"; +import { userDocumentation as userDoc } from "../components/UserDocumentation"; import ApplicationMetadata from "../types/ApplicationMetadata"; +import { UserDocumentation } from "../types"; // Create a context for the UserDashboard state export const ApplicationsContext = createContext< @@ -14,13 +16,15 @@ export const ApplicationsContext = createContext< ApplicationMetadata[], string, // Id of the current application React.Dispatch>, + UserDocumentation, ] ->([[], () => {}, [], "", () => {}]); +>([[], () => {}, [], "", () => {}, userDoc]); interface ApplicationsProviderProps { children: React.ReactNode; appList?: ApplicationMetadata[]; defaultUserDashboard?: DashboardGroup[]; + userDocumentation?: UserDocumentation; } /** @@ -29,12 +33,14 @@ interface ApplicationsProviderProps { * @param children - The child components to be wrapped by the provider. * @param appList - The list of application configurations. * @param defaultUserDashboard - The default user dashboard. + * @param userDocunentation - The user documentation for the applications. * @returns The applications provider. */ export const ApplicationsProvider = ({ children, appList = applicationList, - defaultUserDashboard = defaultDashboard, + defaultUserDashboard, + userDocumentation = userDoc, }: ApplicationsProviderProps) => { const loadedDashboard = sessionStorage.getItem("savedDashboard"); const parsedDashboard: DashboardGroup[] = loadedDashboard @@ -70,6 +76,7 @@ export const ApplicationsProvider = ({ appList, currentAppId, setCurrentAppId, + userDocumentation, ]} > {children} diff --git a/packages/diracx-web-components/src/types/UserDocumentation.ts b/packages/diracx-web-components/src/types/UserDocumentation.ts new file mode 100644 index 00000000..b231492c --- /dev/null +++ b/packages/diracx-web-components/src/types/UserDocumentation.ts @@ -0,0 +1,14 @@ +interface DocumentationSection { + title: string; + content: string; +} + +interface appDocumentation { + appName: string; + sections: DocumentationSection[]; +} + +export interface UserDocumentation { + generalUsage: string; + applications: appDocumentation[]; +} diff --git a/packages/diracx-web-components/src/types/index.ts b/packages/diracx-web-components/src/types/index.ts index 880b578e..f369ee86 100644 --- a/packages/diracx-web-components/src/types/index.ts +++ b/packages/diracx-web-components/src/types/index.ts @@ -15,3 +15,4 @@ export * from "./EquationStatus"; export * from "./operators"; export * from "./SearchBarTokenNature"; export * from "./CategoryType"; +export * from "./UserDocumentation"; diff --git a/packages/diracx-web-components/stories/Dashboard.stories.tsx b/packages/diracx-web-components/stories/Dashboard.stories.tsx index 1a05227c..b6c7c4b4 100644 --- a/packages/diracx-web-components/stories/Dashboard.stories.tsx +++ b/packages/diracx-web-components/stories/Dashboard.stories.tsx @@ -52,6 +52,7 @@ const meta = { applicationList, currentAppId, setCurrentAppId, + userDocumentation, ]} > diff --git a/packages/extensions/src/app/(dashboard)/layout.tsx b/packages/extensions/src/app/(dashboard)/layout.tsx index 1f464574..546eaf6b 100644 --- a/packages/extensions/src/app/(dashboard)/layout.tsx +++ b/packages/extensions/src/app/(dashboard)/layout.tsx @@ -6,6 +6,7 @@ import { DiracXWebProviders } from "@dirac-grid/diracx-web-components/contexts"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { applicationList } from "@/gubbins/applicationList"; import { defaultSections } from "@/gubbins/DefaultUserDashboard"; +import { userDocumentation } from "@/gubbins/UserDocumentation"; // Layout for the dashboard: setup the providers and the dashboard for the applications export default function DashboardLayout({ @@ -29,6 +30,7 @@ export default function DashboardLayout({ // You can optionally pass a list of applications and a default user dashboard appList={applicationList} defaultUserDashboard={defaultSections} + userDocumentation={userDocumentation} > {/* Dashboard is the main layout for the applications, you can optionally give it a custom logo URL and a drawer width */} diff --git a/packages/extensions/src/gubbins/UserDocumentation.ts b/packages/extensions/src/gubbins/UserDocumentation.ts new file mode 100644 index 00000000..2de2beca --- /dev/null +++ b/packages/extensions/src/gubbins/UserDocumentation.ts @@ -0,0 +1,28 @@ +import { userDocumentation } from "@dirac-grid/diracx-web-components/components"; +import { UserDocumentation } from "@dirac-grid/diracx-web-components/types"; + +// New Application List with the default ones + the Owner Monitor +const userDoc: UserDocumentation = userDocumentation; + +userDoc.applications.push({ + appName: "Owner Monitor", + sections: [ + { + title: "General Usage", + content: ` +# General Usage + +Manage and monitor the owners of electric scooters in your area. The Owner Monitor application allows you to view, add, and manage owners, ensuring that all scooters are accounted for and properly maintained. You can track ownership details, monitor scooter conditions, and ensure compliance with local regulations.`, + }, + { + title: "Definition", + content: ` +# Definition of Gubbins + +**Gubbins** is a British informal noun referring to small, miscellaneous items or bits and pieces, often of little value or importance. It can describe gadgets, parts, or knick-knacks whose exact names might not be known or remembered. The term is frequently used to refer to odds and ends lying around or small components in a machine. Sometimes, it can imply something trivial or unimportant, almost like "stuff" or "junk." In some contexts, it can also humorously refer to technical or mechanical parts, especially those that are confusing or complicated. While common in UK English, the word is less known in American English, where similar expressions might be "bits and bobs" or "thingamajigs." Overall, "gubbins" conveys a casual, somewhat affectionate sense of miscellaneous small items`, + }, + ], +}); + +export { userDoc as userDocumentation }; +export default userDoc; From 3e5142df9b8bb9566108800f70326d37108a9a9b Mon Sep 17 00:00:00 2001 From: theau Date: Thu, 24 Jul 2025 10:44:03 +0200 Subject: [PATCH 2/5] feat: auto-build the doc --- .prettierignore | 1 + docs/developer/create_application.md | 2 + docs/developer/index.md | 8 +- docs/developer/manage_extension.md | 2 +- .../list_and_share_applications.md | 0 docs/user/{ => Dashboard}/login_out.md | 0 docs/user/{ => Job_Monitor}/monitor_jobs.md | 0 docs/user/generalUsage.md | 18 ++ package-lock.json | 211 +++++++++++++++++- package.json | 4 +- .../diracx-web-components/.prettierignore | 1 + packages/diracx-web-components/package.json | 6 +- .../script/generateDocs.js | 77 +++++++ .../DashboardLayout/HelpOverlay.tsx | 5 +- .../src/components/UserDocumentation.ts | 86 ------- .../src/components/index.ts | 3 - .../src/contexts/ApplicationsProvider.tsx | 18 +- .../src/contexts/DiracXWebProviders.tsx | 9 +- .../src/generatedDocs.ts | 34 +++ .../stories/Dashboard.stories.tsx | 1 + packages/diracx-web/package.json | 3 +- packages/extensions/README.md | 2 +- packages/extensions/docs/dev/contribute.md | 4 + .../docs/user/Owner_Monitor/definition.md | 3 + .../docs/user/Owner_Monitor/presentation.md | 3 + packages/extensions/docs/user/generalUsage.md | 3 + packages/extensions/package.json | 5 +- packages/extensions/script/generateDocs.js | 77 +++++++ .../extensions/src/app/(dashboard)/layout.tsx | 2 +- packages/extensions/src/generatedDocs.ts | 27 +++ .../src/gubbins/UserDocumentation.ts | 28 --- 31 files changed, 497 insertions(+), 146 deletions(-) rename docs/user/{ => Dashboard}/list_and_share_applications.md (100%) rename docs/user/{ => Dashboard}/login_out.md (100%) rename docs/user/{ => Job_Monitor}/monitor_jobs.md (100%) create mode 100644 docs/user/generalUsage.md create mode 100644 packages/diracx-web-components/script/generateDocs.js delete mode 100644 packages/diracx-web-components/src/components/UserDocumentation.ts create mode 100644 packages/diracx-web-components/src/generatedDocs.ts create mode 100644 packages/extensions/docs/dev/contribute.md create mode 100644 packages/extensions/docs/user/Owner_Monitor/definition.md create mode 100644 packages/extensions/docs/user/Owner_Monitor/presentation.md create mode 100644 packages/extensions/docs/user/generalUsage.md create mode 100644 packages/extensions/script/generateDocs.js create mode 100644 packages/extensions/src/generatedDocs.ts delete mode 100644 packages/extensions/src/gubbins/UserDocumentation.ts diff --git a/.prettierignore b/.prettierignore index a7a8580a..6df372ae 100644 --- a/.prettierignore +++ b/.prettierignore @@ -19,6 +19,7 @@ packages/*/tsup.config.ts packages/*/.next packages/*/.tsup packages/*/out +packages/*/src/generatedDocs.ts **/release-please-config.json **/.release-please-manifest.json diff --git a/docs/developer/create_application.md b/docs/developer/create_application.md index 52b552b6..2f65f811 100644 --- a/docs/developer/create_application.md +++ b/docs/developer/create_application.md @@ -22,4 +22,6 @@ The code of your app should be in `packages/diracx-web-components/src/components In order to be compatible with the share and import buttons, the application must write its state to the session storage at `_State`. This slot is read from and written to by the corresponding functions. +You can create documentation for your new application. If you create documentation for the users (in `docs/user/`), you should follow the structure: each folder represents an application, and each file explains a section of that application. This folder is used to automatically build the documentation that will be available in the web application. + 💡You can look at `JobMonitor` as an example. \ No newline at end of file diff --git a/docs/developer/index.md b/docs/developer/index.md index c6223efa..633e6f11 100644 --- a/docs/developer/index.md +++ b/docs/developer/index.md @@ -38,14 +38,14 @@ flowchart TD This repository is organized as a monorepo, with the following key packages: -- [**DiracX-Web-Components**](packages/diracx-web-components): A library of reusable React components designed for integration within the `DiracX-Web` package and to facilitate the creation of custom DiracX web extensions. +- [**DiracX-Web-Components**](../../packages/diracx-web-components): A library of reusable React components designed for integration within the `DiracX-Web` package and to facilitate the creation of custom DiracX web extensions. -- [**DiracX-Web**](packages/diracx-web): Vanilla Dirac web interface based on Next.js. Leverages components from `DiracX-Web-Components` to provide core functionalities. +- [**DiracX-Web**](../../packages/diracx-web): Vanilla Dirac web interface based on Next.js. Leverages components from `DiracX-Web-Components` to provide core functionalities. -- [**Extensions**](packages/extensions): An illustrative example of a web extension, also based on Next.js, demonstrating how to extend the functionality of `DiracX-Web` using the components from the `DiracX-Web-Components` package. +- [**Extensions**](../../packages/extensions): An illustrative example of a web extension, also based on Next.js, demonstrating how to extend the functionality of `DiracX-Web` using the components from the `DiracX-Web-Components` package. -The monorepo structure is based on *npm workspaces* to ensure that related packages ([DiracX-Web-Components](packages/diracx-web-components)) are automatically used from their local versions instead of fetching them from the npm registry. +The monorepo structure is based on *npm workspaces* to ensure that related packages ([DiracX-Web-Components](../../packages/diracx-web-components)) are automatically used from their local versions instead of fetching them from the npm registry. ## Ramping up diff --git a/docs/developer/manage_extension.md b/docs/developer/manage_extension.md index be82b526..0546474f 100644 --- a/docs/developer/manage_extension.md +++ b/docs/developer/manage_extension.md @@ -89,4 +89,4 @@ Follow the instructions from the [Gubbins extension README](https://github.com/D ## Creating a new extension -More details available in the [**extensions** README](/packages/extensions/README.md) \ No newline at end of file +More details available in the [**extensions** README](../../packages/extensions/README.md) \ No newline at end of file diff --git a/docs/user/list_and_share_applications.md b/docs/user/Dashboard/list_and_share_applications.md similarity index 100% rename from docs/user/list_and_share_applications.md rename to docs/user/Dashboard/list_and_share_applications.md diff --git a/docs/user/login_out.md b/docs/user/Dashboard/login_out.md similarity index 100% rename from docs/user/login_out.md rename to docs/user/Dashboard/login_out.md diff --git a/docs/user/monitor_jobs.md b/docs/user/Job_Monitor/monitor_jobs.md similarity index 100% rename from docs/user/monitor_jobs.md rename to docs/user/Job_Monitor/monitor_jobs.md diff --git a/docs/user/generalUsage.md b/docs/user/generalUsage.md new file mode 100644 index 00000000..0dad74f0 --- /dev/null +++ b/docs/user/generalUsage.md @@ -0,0 +1,18 @@ +# General usage + +## Navigate between applications + +You can click on the \`Add application\` button to create a new instance of an application. The list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard + +## Share applications + +To share applications, click the \`Export\` button at the top right of the screen. Then, select the applications you want to share and copy them to the clipboard. + +## Import applications + +To import applications, click the \`Import\` button at the top right of the screen. Paste the copied applications into the input field and click \`Import\`. The imported applications will appear in the sidebar. +If the states are outdated, you can copy the updated version of them by clicking the \`Copy all updated states\` button. + +## Save you dashoard +To save your dashboard, clicke the \`Export\`button at the top right of the screen. Then, select the applications you want to save and click on the \`Save in the browser\` button. The saved applications will be stored in your browser's local storage. +When you want to load the saved applications, click the \`Import\` button at the top right of the screen and select the \`Load from the browser\` option. The saved applications will be loaded into the sidebar. diff --git a/package-lock.json b/package-lock.json index fc417fc4..f1968b39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,9 @@ "devDependencies": { "@commitlint/cli": "^19.7.1", "@commitlint/config-conventional": "^19.7.1", - "husky": "^9.0.11" + "@types/node": "^24.1.0", + "husky": "^9.0.11", + "ts-node": "^10.9.2" } }, "node_modules/@adobe/css-tools": { @@ -2485,6 +2487,30 @@ "node": ">=v18" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@cypress/request": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.8.tgz", @@ -6123,6 +6149,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -7301,6 +7339,34 @@ "node": ">= 10" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, "node_modules/@tybys/wasm-util": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", @@ -7846,13 +7912,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", - "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", + "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/parse-json": { @@ -9031,6 +9097,13 @@ ], "license": "MIT" }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -10362,7 +10435,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -11074,6 +11146,13 @@ "node": ">=8" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -12213,6 +12292,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -12514,6 +12603,12 @@ "dev": true, "license": "MIT" }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "license": "MIT" + }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -20789,6 +20884,21 @@ "dev": true, "license": "MIT" }, + "node_modules/node-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -23610,6 +23720,18 @@ "dev": true, "license": "MIT" }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "license": "MIT", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -24845,6 +24967,50 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, "node_modules/ts-pnp": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", @@ -25279,9 +25445,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true, "license": "MIT" }, @@ -25295,6 +25461,15 @@ "node": ">=4" } }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/unicode-match-property-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", @@ -25611,6 +25786,13 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -26310,6 +26492,16 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -26395,6 +26587,7 @@ "@types/react-dom": "^18.3.1", "dayjs": "^1.11.13", "mui-markdown": "^2.0.1", + "node-emoji": "^2.2.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-virtuoso": "^4.12.3", diff --git a/package.json b/package.json index de4dc815..81d1e2c3 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "devDependencies": { "@commitlint/cli": "^19.7.1", "@commitlint/config-conventional": "^19.7.1", - "husky": "^9.0.11" + "@types/node": "^24.1.0", + "husky": "^9.0.11", + "ts-node": "^10.9.2" }, "scripts": { "dev": "npm --prefix packages/diracx-web run dev", diff --git a/packages/diracx-web-components/.prettierignore b/packages/diracx-web-components/.prettierignore index 523cdf01..ae9be1d2 100644 --- a/packages/diracx-web-components/.prettierignore +++ b/packages/diracx-web-components/.prettierignore @@ -7,3 +7,4 @@ jest.config.mjs release-please-config.json .release-please-manifest.json CHANGELOG.md +src/generatedDocs.ts \ No newline at end of file diff --git a/packages/diracx-web-components/package.json b/packages/diracx-web-components/package.json index a269e3ab..f57266db 100644 --- a/packages/diracx-web-components/package.json +++ b/packages/diracx-web-components/package.json @@ -7,7 +7,7 @@ "access": "public" }, "scripts": { - "build": "tsup --minify", + "build": "node script/generateDocs && tsup --minify", "dev": "tsup --watch", "test": "jest --ci", "lint": "eslint ./src", @@ -15,7 +15,8 @@ "ts-lint": "tsc -noEmit -incremental", "prepack": "rm -rf dist && npm run build", "doc": "storybook dev -p 6006", - "build-doc": "storybook build" + "build-doc": "storybook build", + "generate-docs": "node script/generateDocs.js" }, "license": "GPL-3.0", "type": "module", @@ -36,6 +37,7 @@ "@types/react-dom": "^18.3.1", "dayjs": "^1.11.13", "mui-markdown": "^2.0.1", + "node-emoji": "^2.2.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-virtuoso": "^4.12.3", diff --git a/packages/diracx-web-components/script/generateDocs.js b/packages/diracx-web-components/script/generateDocs.js new file mode 100644 index 00000000..857cc6df --- /dev/null +++ b/packages/diracx-web-components/script/generateDocs.js @@ -0,0 +1,77 @@ +import * as fs from "fs"; +import * as path from "path"; + +const DOCS_PATH = "../../docs/user"; +const OUTPUT_PATH = "./src/generatedDocs.ts"; + +async function readMarkdown(filePath) { + return fs.promises.readFile(filePath, "utf-8"); +} + +async function getTitleAndContent(filePath, fallbackName) { + const content = await readMarkdown(filePath); + const lines = content.split("\n").map((line) => line.trim()); + + let title = fallbackName; + + if (lines.length > 0 && lines[0].startsWith("# ")) { + title = lines[0].substring(2).trim(); + } + + return { title, content }; +} + +async function generate() { + const apps = []; + + const files = await fs.promises.readdir(DOCS_PATH); + + let generalUsage = ""; + + for (const entry of files) { + const fullPath = path.join(DOCS_PATH, entry); + const stat = await fs.promises.stat(fullPath); + + if (entry === "generalUsage.md") { + generalUsage = await readMarkdown(fullPath); + } else if (stat.isDirectory()) { + const sections = []; + const sectionFiles = await fs.promises.readdir(fullPath); + for (const sectionFile of sectionFiles) { + const sectionPath = path.join(fullPath, sectionFile); + const { title, content } = await getTitleAndContent( + sectionPath, + sectionFile.replace(".md", "").replace(/_/g, " "), // Use file name as title + ); + + sections.push({ + title: title, + content, + }); + } + apps.push({ + appName: entry.replace(/_/g, " "), // Convert directory name to app name + sections, + }); + } + } + + const doc = { + generalUsage, + applications: apps, + }; + + const fileContent = `/** +*File generated by generateDocs.js from /docs/user. +*Do not edit this file directly. +*/ + +import { UserDocumentation } from './types'; + +export const userDocumentation: UserDocumentation = ${JSON.stringify(doc, null, 2)}; +`; + + await fs.promises.writeFile(OUTPUT_PATH, fileContent, "utf-8"); +} + +generate().catch(console.error); diff --git a/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx b/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx index b0b61840..d7588812 100644 --- a/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx +++ b/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx @@ -1,5 +1,6 @@ import { useState, useContext } from "react"; import { MuiMarkdown, defaultOverrides } from "mui-markdown"; +import { emojify } from "node-emoji"; import { Box, @@ -99,7 +100,7 @@ export default function HelpOverlay({ return ( <> - {userDocumentation.generalUsage} + {emojify(userDocumentation.generalUsage)} ); @@ -114,7 +115,7 @@ export default function HelpOverlay({ return ( <> - {section?.content} + {emojify(section?.content || "")} ); diff --git a/packages/diracx-web-components/src/components/UserDocumentation.ts b/packages/diracx-web-components/src/components/UserDocumentation.ts deleted file mode 100644 index 7160d3ba..00000000 --- a/packages/diracx-web-components/src/components/UserDocumentation.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { UserDocumentation } from "../types/UserDocumentation"; - -/** - * User documentation for DiracX web. - * - */ -export const userDocumentation: UserDocumentation = { - generalUsage: ` -# General usage - -## Navigate between applications - -You can click on the \`Add application\` button to create a new instance of an application. The list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard - -## Share applications - -To share applications, click the \`Export\` button at the top right of the screen. Then, select the applications you want to share and copy them to the clipboard. - -## Import applications - -To import applications, click the \`Import\` button at the top right of the screen. Paste the copied applications into the input field and click \`Import\`. The imported applications will appear in the sidebar. -If the states are outdated, you can copy the updated version of them by clicking the \`Copy all updated states\` button. - -## Save you dashoard -To save your dashboard, clicke the \`Export\`button at the top right of the screen. Then, select the applications you want to save and click on the \`Save in the browser\` button. The saved applications will be stored in your browser's local storage. -When you want to load the saved applications, click the \`Import\` button at the top right of the screen and select the \`Load from the browser\` option. The saved applications will be loaded into the sidebar. - -`, - applications: [ - { - appName: "Job Monitor", - sections: [ - { - title: "General Usage", - content: ` -# General Usage - -The \`Job Monitor\` application allows you to track and manage jobs. It provides a search bar to filter jobs by criteria such as job type, status, and submission date. The application displays a list of jobs in a table format, with each job showing its status and other relevant information.`, - }, - { - title: "The Search Bar", - content: ` -# How to use the search bar - -The search bar allows you to filter jobs based on various criteria. The filters are represented as equations in the search bar, where each equation consists of a job attribute, an operator, and a value. - -A resarch is automatically performed when all the equations in the search bar are valid. - -## How to create a filter -To create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. - -The search bar only suggests attributes, operators, and values that are available in your current set of jobs. - -## How to edit a filter -To edit a filter, click on the filter in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. - -## How to remove a filter - -To remove a filter, you can either press the \`Backspace\` key to remove the last token or right-click on the equation to remove the entire equation. `, - }, - { - title: "The table", - content: ` -# How to use the table - -The table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date. - -## Actions on the table - -You can click on the eye icon to select more columns to display in the table. -You can sort the table by clicking on the column headers. Clicking on a column header will sort the table in ascending order, and clicking again will sort it in descending order. -You can set the page size by clicking on the \`Row per page\` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page. - -## Actions on a job - -You can do a right-click on a job to open the \`Job History\`. -You can select one or more jobs by clicking on the checkboxes next to each job. Once you have selected jobs, you can perform actions on them using the buttons at the top of the table. The available actions include: -- **Get IDs**: This button will copy the IDs of the selected jobs to the clipboard. -- **Rechedule**: This button will reschedule the selected jobs. -- **Kill**: This button will kill the selected jobs. -- **Delete**: This button will delete the selected jobs.`, - }, - ], - }, - ], -}; diff --git a/packages/diracx-web-components/src/components/index.ts b/packages/diracx-web-components/src/components/index.ts index 40788e9f..f5da5865 100644 --- a/packages/diracx-web-components/src/components/index.ts +++ b/packages/diracx-web-components/src/components/index.ts @@ -1,9 +1,6 @@ // Application list export { applicationList } from "./applicationList"; -// User Documentation -export { userDocumentation } from "./UserDocumentation"; - // Dashboard Layout export * from "./DashboardLayout"; diff --git a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx index 29b788c2..b02d0b2b 100644 --- a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx +++ b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx @@ -4,7 +4,7 @@ import React, { createContext, useEffect, useState } from "react"; import { applicationList } from "../components/applicationList"; import { defaultDashboard } from "../components/defaultDashboard"; import { DashboardGroup } from "../types/DashboardGroup"; -import { userDocumentation as userDoc } from "../components/UserDocumentation"; +import { userDocumentation as userDoc } from "../generatedDocs"; import ApplicationMetadata from "../types/ApplicationMetadata"; import { UserDocumentation } from "../types"; @@ -39,8 +39,8 @@ interface ApplicationsProviderProps { export const ApplicationsProvider = ({ children, appList = applicationList, - defaultUserDashboard, - userDocumentation = userDoc, + defaultUserDashboard = defaultDashboard, + userDocumentation, }: ApplicationsProviderProps) => { const loadedDashboard = sessionStorage.getItem("savedDashboard"); const parsedDashboard: DashboardGroup[] = loadedDashboard @@ -66,6 +66,16 @@ export const ApplicationsProvider = ({ sessionStorage.setItem("savedDashboard", JSON.stringify(userDashboard)); }, [userDashboard]); + const mergedDocumentation: UserDocumentation = { ...userDoc }; + + if (userDocumentation) { + mergedDocumentation.applications = mergedDocumentation.applications.concat( + userDocumentation.applications, + ); + mergedDocumentation.generalUsage = + userDocumentation.generalUsage || mergedDocumentation.generalUsage; + } + return ( {children} diff --git a/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx b/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx index 856a7e2c..063d1ff2 100644 --- a/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx +++ b/packages/diracx-web-components/src/contexts/DiracXWebProviders.tsx @@ -1,6 +1,10 @@ "use client"; -import type { ApplicationMetadata, DashboardGroup } from "../types"; +import type { + ApplicationMetadata, + DashboardGroup, + UserDocumentation, +} from "../types"; import { OIDCSecure } from "../components"; import { @@ -17,6 +21,7 @@ interface DiracXWebProvidersProps { getSearchParams: () => URLSearchParams; appList?: ApplicationMetadata[]; defaultUserDashboard?: DashboardGroup[]; + userDocumentation?: UserDocumentation; } export function DiracXWebProviders({ @@ -26,6 +31,7 @@ export function DiracXWebProviders({ getSearchParams, appList, defaultUserDashboard, + userDocumentation, }: DiracXWebProvidersProps) { return ( @@ -37,6 +43,7 @@ export function DiracXWebProviders({ {children} diff --git a/packages/diracx-web-components/src/generatedDocs.ts b/packages/diracx-web-components/src/generatedDocs.ts new file mode 100644 index 00000000..b0b8b94f --- /dev/null +++ b/packages/diracx-web-components/src/generatedDocs.ts @@ -0,0 +1,34 @@ +/** +*File generated by generateDocs.js from /docs/user. +*Do not edit this file directly. +*/ + +import { UserDocumentation } from './types'; + +export const userDocumentation: UserDocumentation = { + "generalUsage": "# General usage \n\n## Navigate between applications \n\nYou can click on the \\`Add application\\` button to create a new instance of an application. The list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard\n\n## Share applications\n\nTo share applications, click the \\`Export\\` button at the top right of the screen. Then, select the applications you want to share and copy them to the clipboard.\n\n## Import applications\n\nTo import applications, click the \\`Import\\` button at the top right of the screen. Paste the copied applications into the input field and click \\`Import\\`. The imported applications will appear in the sidebar.\nIf the states are outdated, you can copy the updated version of them by clicking the \\`Copy all updated states\\` button. \n\n## Save you dashoard\nTo save your dashboard, clicke the \\`Export\\`button at the top right of the screen. Then, select the applications you want to save and click on the \\`Save in the browser\\` button. The saved applications will be stored in your browser's local storage.\nWhen you want to load the saved applications, click the \\`Import\\` button at the top right of the screen and select the \\`Load from the browser\\` option. The saved applications will be loaded into the sidebar.\n", + "applications": [ + { + "appName": "Dashboard", + "sections": [ + { + "title": "Managing Application Instances", + "content": "# Managing Application Instances\n\nAn *application instance* is a graphical web interface that allows users to interact with DiracX services. DiracX-Web is essentially a collection of such applications, and users can \"spawn\" instances to interact with them.\n\nBy default, a few application instances are displayed (e.g., `My Jobs`, an instance of `Job Monitor`). This guide will help you manage, organize, and share application instances effectively.\n\n## Basics\n\n### Accessing More Applications\n\n1. Click the **Add Application** button at the bottom of the sidebar.\n - :bulb: On mobile devices, first open the sidebar by clicking the **menu icon** (☰) at the top-left corner.\n2. Select an application from the list in the dialog box.\n - :bulb: The selected application will appear in the sidebar.\n\n### Opening Multiple Instances of the Same Application\n\n- Repeat the steps above to open additional instances of the same application.\n - :bulb: Each instance has its own state, making it ideal for monitoring different job groups with specific criteria for instance.\n\n### Renaming an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The instance name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving an Application Instance\n\n1. Locate the **handle icon** next to the instance name.\n2. Click and hold the handle to select the instance.\n3. Drag it to the desired position within the sidebar.\n4. Release the mouse button to place the instance.\n\n### Deleting an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The application instance will disappear from the sidebar.\n\n### Sharing Your Dashboard\n\n1. Copy the URL from your browser.\n - :bulb: The URL encodes the current state of your dashboard.\n2. Share it with others.\n - :warning: The recipient will see a similar dashboard layout but may not see identical content if:\n - They belong to a different VO or group.\n - Time-sensitive data has changed since sharing.\n - :warning: Encoding too many application instances may create discrepancies as the URL has a theoretical limit of 8000 characters based on [RFC9110](https://www.rfc-editor.org/rfc/rfc9110#section-4.1-5) \n\n## Advanced Features\n\nWhen managing multiple instances of the same application, grouping can help you organize your dashboard efficiently.\n\n### Creating a New Group\n\n1. **Right-click** anywhere in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **New Group**.\n - :bulb: A new group with a default name will appear in the sidebar.\n3. Add new application instances to the group using the **Add Application** button.\n - :bulb: By default, new instances will be placed in the most recently created group.\n\n### Renaming a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The group name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving a Group\n\n1. Locate the **handle icon** next to the group name.\n2. Click and hold the handle to select the group.\n3. Drag the group to the desired position within the sidebar.\n - :bulb: All application instances within the group will move together.\n4. Release the mouse button to place the group.\n\n### Moving Instances Between Groups\n\n1. Drag an application instance from one group.\n2. Drop it into another group using the same drag-and-drop process as moving instances within a group.\n\n### Deleting a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The group and all its application instances will disappear from the sidebar.\n\n\n### Share and import the settings of an application\n\n1. **Share**: You can export the status of an app by clicking on the share button in the top-right corner of the screen. After clicking, you can select which group and app you want to share and then copy a text corresponding to the states of the selected applications.\n\n2. **Import**: Next to the export button you can find the import button. You can paste into the window opened by the button the text corresponding to one or multiple shared apps. This will create a new group named *Imported App* with the imported applications and their settings. \n\n**Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. \n" + }, + { + "title": "Logging in & out", + "content": "# Logging in & out\n\n## Basics\n### Logging in\n\n1. Go to the DiracX-Web instance homepage. \n - 💡 You should end up on an authentication page.\n2. Authenticate you as a user of a given VO/group:\n - If your instance supports multiple VOs, select your VO in the list box.\n - Select your Group in the list box below.\n3. Click the **Login** button. \n - 💡 You should be redirected to the VO login page.\n4. Enter your credentials (e.g., Username/Password, X509 certificates). \n - 💡 You should see a page asking for permission to access your profile.\n5. Accept the permissions to access your DiracX dashboard. \n - 💡 You should be redirected to the DiracX-Web instance as a logged-in user, and the dashboard should appear.\n\n### Logging out\n\n1. Click on your profile icon in the top-right corner of the dashboard.\n - :bulb: A dropdown menu should appear\n2. Select **Logout** from the dropdown menu.\n \n## Advanced\n### Logging in with specific properties\n\nTODO\n" + } + ] + }, + { + "appName": "Job Monitor", + "sections": [ + { + "title": "Job Monitor documentation", + "content": "# Job Monitor documentation\n\n## The search bar\n\n The search bar allows you to filter jobs based on various criteria. The filters are represented as equations in the search bar, where each equation consists of a job attribute, an operator, and a value. \n A resarch is automatically performed when all the equations in the search bar are valid. \n\n ### Create a filter\n To create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by.\n The search bar only suggests attributes, operators, and values that are available in your current set of jobs.\n\n ### Edit a filter\n To edit a filter, click on the filter in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. \n\n ### Remove a filter\n To remove a filter, you can either press the `Backspace` key to remove the last token or right-click on the equation to remove the entire equation.\n\n\n## Use the table\nThe table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date.\n\n### Actions on the table\nYou can click on the eye icon to select more columns to display in the table. \nYou can sort the table by clicking on the column headers. Clicking on a column header will sort the table in ascending order, and clicking again will sort it in descending order.\nYou can set the page size by clicking on the `Row per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page.\n\n### Actions on a job\nYou can do a right-click on a job to open the `Job History`.\nYou can select one or more jobs by clicking on the checkboxes next to each job. Once you have selected jobs, you can perform actions on them using the buttons at the top of the table. The available actions include:\n- **Get IDs**: This button will copy the IDs of the selected jobs to the clipboard.\n- **Rechedule**: This button will reschedule the selected jobs.\n- **Kill**: This button will kill the selected jobs.\n- **Delete**: This button will delete the selected jobs.\n\n" + } + ] + } + ] +}; diff --git a/packages/diracx-web-components/stories/Dashboard.stories.tsx b/packages/diracx-web-components/stories/Dashboard.stories.tsx index b6c7c4b4..3ad71ba5 100644 --- a/packages/diracx-web-components/stories/Dashboard.stories.tsx +++ b/packages/diracx-web-components/stories/Dashboard.stories.tsx @@ -7,6 +7,7 @@ import { applicationList } from "../src/components/applicationList"; import { DashboardGroup } from "../src/types/DashboardGroup"; import Dashboard from "../src/components/DashboardLayout/Dashboard"; import { ThemeProvider } from "../src/contexts/ThemeProvider"; +import { userDocumentation } from "../src/generatedDocs"; const meta = { title: "Dashboard Layout/Dashboard", diff --git a/packages/diracx-web/package.json b/packages/diracx-web/package.json index b2e9e694..c222df24 100644 --- a/packages/diracx-web/package.json +++ b/packages/diracx-web/package.json @@ -11,7 +11,8 @@ "lint": "next lint", "lint-staged": "lint-staged", "ts-lint": "tsc -noEmit -incremental", - "postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public" + "postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public", + "generate-docs": "ts-node script/generateDocs.ts" }, "dependencies": { "@axa-fr/react-oidc": "^7.24.0", diff --git a/packages/extensions/README.md b/packages/extensions/README.md index ef02c6bf..09d3e70b 100644 --- a/packages/extensions/README.md +++ b/packages/extensions/README.md @@ -170,7 +170,7 @@ Having a directory dedicated to your extension components will help you keep you To add new apps to your extension, you can create new components in your extension directory. -[`testApp`](src/gubbins/components/TestApp/testApp.tsx) provides an example of a basic app component and the [Storybook documentation](https://diracgrid.github.io/diracx-web/) showcases all the components you can use from the library in an interactive interface. +[`OwnerMonitor`](src/gubbins/components/OwnerMonitor/OwnerMonitor.tsx) provides an example of a basic app component and the [Storybook documentation](https://diracgrid.github.io/diracx-web/) showcases all the components you can use from the library in an interactive interface. It is then pretty easy to add them to DiracX Web by extending the `applicationList` (the list of apps available in DiracX-Web) from `diracx-web-components/components`. diff --git a/packages/extensions/docs/dev/contribute.md b/packages/extensions/docs/dev/contribute.md new file mode 100644 index 00000000..f59434a7 --- /dev/null +++ b/packages/extensions/docs/dev/contribute.md @@ -0,0 +1,4 @@ +# Create your own extension + +This whole project is just an example about how you can create your own extension. +If you want more details, look at the documentation in the project [diracx-web](https://github.com/diracggrid/diracx-web). diff --git a/packages/extensions/docs/user/Owner_Monitor/definition.md b/packages/extensions/docs/user/Owner_Monitor/definition.md new file mode 100644 index 00000000..0c565a0a --- /dev/null +++ b/packages/extensions/docs/user/Owner_Monitor/definition.md @@ -0,0 +1,3 @@ +# Definition of Gubbins + +**Gubbins** is a British informal noun referring to small, miscellaneous items or bits and pieces, often of little value or importance. It can describe gadgets, parts, or knick-knacks whose exact names might not be known or remembered. The term is frequently used to refer to odds and ends lying around or small components in a machine. Sometimes, it can imply something trivial or unimportant, almost like "stuff" or "junk." In some contexts, it can also humorously refer to technical or mechanical parts, especially those that are confusing or complicated. While common in UK English, the word is less known in American English, where similar expressions might be "bits and bobs" or "thingamajigs." Overall, "gubbins" conveys a casual, somewhat affectionate sense of miscellaneous small items. diff --git a/packages/extensions/docs/user/Owner_Monitor/presentation.md b/packages/extensions/docs/user/Owner_Monitor/presentation.md new file mode 100644 index 00000000..2e082100 --- /dev/null +++ b/packages/extensions/docs/user/Owner_Monitor/presentation.md @@ -0,0 +1,3 @@ +# Presentation of this module + +This is just an example. diff --git a/packages/extensions/docs/user/generalUsage.md b/packages/extensions/docs/user/generalUsage.md new file mode 100644 index 00000000..e501f8ea --- /dev/null +++ b/packages/extensions/docs/user/generalUsage.md @@ -0,0 +1,3 @@ +# Custom general Usage + +You can define you own `General Usage`. diff --git a/packages/extensions/package.json b/packages/extensions/package.json index 350bddca..075669e3 100644 --- a/packages/extensions/package.json +++ b/packages/extensions/package.json @@ -6,13 +6,14 @@ "license": "GPL-3.0-only", "scripts": { "dev": "next dev", - "build": "next build", + "build": "node script/generateDocs.js && next build", "test": "cypress open --config baseUrl=$DIRACX_URL", "start": "next start", "lint": "next lint", "lint-staged": "lint-staged", "ts-lint": "tsc -noEmit -incremental", - "postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public" + "postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public", + "generate-docs": "node script/generateDocs.js" }, "dependencies": { "@axa-fr/react-oidc": "^7.24.0", diff --git a/packages/extensions/script/generateDocs.js b/packages/extensions/script/generateDocs.js new file mode 100644 index 00000000..e311c3d7 --- /dev/null +++ b/packages/extensions/script/generateDocs.js @@ -0,0 +1,77 @@ +import { promises } from "fs"; +import { join } from "path"; + +const DOCS_PATH = "./docs/user"; +const OUTPUT_PATH = "./src/generatedDocs.ts"; + +async function readMarkdown(filePath) { + return promises.readFile(filePath, "utf-8"); +} + +async function getTitleAndContent(filePath, fallbackName) { + const content = await readMarkdown(filePath); + const lines = content.split("\n").map((line) => line.trim()); + + let title = fallbackName; + + if (lines.length > 0 && lines[0].startsWith("# ")) { + title = lines[0].substring(2).trim(); + } + + return { title, content }; +} + +async function generate() { + const apps = []; + + const files = await promises.readdir(DOCS_PATH); + + let generalUsage = ""; + + for (const entry of files) { + const fullPath = join(DOCS_PATH, entry); + const stat = await promises.stat(fullPath); + + if (entry === "generalUsage.md") { + generalUsage = await readMarkdown(fullPath); + } else if (stat.isDirectory()) { + const sections = []; + const sectionFiles = await promises.readdir(fullPath); + for (const sectionFile of sectionFiles) { + const sectionPath = join(fullPath, sectionFile); + const { title, content } = await getTitleAndContent( + sectionPath, + sectionFile.replace(".md", "").replace(/_/g, " "), // Use file name as title + ); + + sections.push({ + title: title, + content, + }); + } + apps.push({ + appName: entry.replace(/_/g, " "), // Convert directory name to app name + sections, + }); + } + } + + const doc = { + generalUsage, + applications: apps, + }; + + const fileContent = `/** +*File generated by generateDocs.js from /docs/user. +*Do not edit this file directly. +*/ + +import { UserDocumentation } from '@dirac-grid/diracx-web-components/types'; + +export const userDocumentation: UserDocumentation = ${JSON.stringify(doc, null, 2)}; +`; + + await promises.writeFile(OUTPUT_PATH, fileContent, "utf-8"); +} + +generate().catch(console.error); diff --git a/packages/extensions/src/app/(dashboard)/layout.tsx b/packages/extensions/src/app/(dashboard)/layout.tsx index 546eaf6b..36ed9349 100644 --- a/packages/extensions/src/app/(dashboard)/layout.tsx +++ b/packages/extensions/src/app/(dashboard)/layout.tsx @@ -4,9 +4,9 @@ import { Box } from "@mui/material"; import { Dashboard } from "@dirac-grid/diracx-web-components/components"; import { DiracXWebProviders } from "@dirac-grid/diracx-web-components/contexts"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import { userDocumentation } from "../../generatedDocs"; import { applicationList } from "@/gubbins/applicationList"; import { defaultSections } from "@/gubbins/DefaultUserDashboard"; -import { userDocumentation } from "@/gubbins/UserDocumentation"; // Layout for the dashboard: setup the providers and the dashboard for the applications export default function DashboardLayout({ diff --git a/packages/extensions/src/generatedDocs.ts b/packages/extensions/src/generatedDocs.ts new file mode 100644 index 00000000..6f0edbee --- /dev/null +++ b/packages/extensions/src/generatedDocs.ts @@ -0,0 +1,27 @@ +/** + *File generated by generateDocs.js from /docs/user. + *Do not edit this file directly. + */ + +import { UserDocumentation } from "@dirac-grid/diracx-web-components/types"; + +export const userDocumentation: UserDocumentation = { + generalUsage: + "# Custom general Usage\n\nYou can define you own `General Usage`.", + applications: [ + { + appName: "Owner Monitor", + sections: [ + { + title: "Definition of Gubbins", + content: + '# Definition of Gubbins\n\n**Gubbins** is a British informal noun referring to small, miscellaneous items or bits and pieces, often of little value or importance. It can describe gadgets, parts, or knick-knacks whose exact names might not be known or remembered. The term is frequently used to refer to odds and ends lying around or small components in a machine. Sometimes, it can imply something trivial or unimportant, almost like "stuff" or "junk." In some contexts, it can also humorously refer to technical or mechanical parts, especially those that are confusing or complicated. While common in UK English, the word is less known in American English, where similar expressions might be "bits and bobs" or "thingamajigs." Overall, "gubbins" conveys a casual, somewhat affectionate sense of miscellaneous small items. ', + }, + { + title: "Presentation of this module", + content: "# Presentation of this module\n\nThis is just an example.", + }, + ], + }, + ], +}; diff --git a/packages/extensions/src/gubbins/UserDocumentation.ts b/packages/extensions/src/gubbins/UserDocumentation.ts deleted file mode 100644 index 2de2beca..00000000 --- a/packages/extensions/src/gubbins/UserDocumentation.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { userDocumentation } from "@dirac-grid/diracx-web-components/components"; -import { UserDocumentation } from "@dirac-grid/diracx-web-components/types"; - -// New Application List with the default ones + the Owner Monitor -const userDoc: UserDocumentation = userDocumentation; - -userDoc.applications.push({ - appName: "Owner Monitor", - sections: [ - { - title: "General Usage", - content: ` -# General Usage - -Manage and monitor the owners of electric scooters in your area. The Owner Monitor application allows you to view, add, and manage owners, ensuring that all scooters are accounted for and properly maintained. You can track ownership details, monitor scooter conditions, and ensure compliance with local regulations.`, - }, - { - title: "Definition", - content: ` -# Definition of Gubbins - -**Gubbins** is a British informal noun referring to small, miscellaneous items or bits and pieces, often of little value or importance. It can describe gadgets, parts, or knick-knacks whose exact names might not be known or remembered. The term is frequently used to refer to odds and ends lying around or small components in a machine. Sometimes, it can imply something trivial or unimportant, almost like "stuff" or "junk." In some contexts, it can also humorously refer to technical or mechanical parts, especially those that are confusing or complicated. While common in UK English, the word is less known in American English, where similar expressions might be "bits and bobs" or "thingamajigs." Overall, "gubbins" conveys a casual, somewhat affectionate sense of miscellaneous small items`, - }, - ], -}); - -export { userDoc as userDocumentation }; -export default userDoc; From bad2bdb330f3b2ef495054b1717266063b44184e Mon Sep 17 00:00:00 2001 From: theau Date: Tue, 29 Jul 2025 12:53:20 +0200 Subject: [PATCH 3/5] refactor: clean and update the doc --- .../Dashboard/list_and_share_applications.md | 25 ++++++-------- docs/user/Job_Monitor/manage_job.md | 19 +++++++++++ docs/user/Job_Monitor/monitor_jobs.md | 34 ------------------- docs/user/Job_Monitor/use_searchbar.md | 19 +++++++++++ docs/user/Job_Monitor/use_table.md | 16 +++++++++ docs/user/generalUsage.md | 28 +++++++++------ package.json | 3 +- packages/diracx-web-components/package.json | 4 +-- .../{generateDocs.js => generateDoc.js} | 3 +- .../DashboardLayout/HelpOverlay.tsx | 5 +-- .../src/generatedDocs.ts | 16 ++++++--- packages/diracx-web/package.json | 3 +- packages/extensions/docs/user/generalUsage.md | 2 +- packages/extensions/package.json | 6 ++-- .../{generateDocs.js => generateDoc.js} | 3 +- packages/extensions/src/generatedDocs.ts | 8 +++-- 16 files changed, 116 insertions(+), 78 deletions(-) create mode 100644 docs/user/Job_Monitor/manage_job.md delete mode 100644 docs/user/Job_Monitor/monitor_jobs.md create mode 100644 docs/user/Job_Monitor/use_searchbar.md create mode 100644 docs/user/Job_Monitor/use_table.md rename packages/diracx-web-components/script/{generateDocs.js => generateDoc.js} (97%) rename packages/extensions/script/{generateDocs.js => generateDoc.js} (97%) diff --git a/docs/user/Dashboard/list_and_share_applications.md b/docs/user/Dashboard/list_and_share_applications.md index 4dd03d8a..8b7af8c9 100644 --- a/docs/user/Dashboard/list_and_share_applications.md +++ b/docs/user/Dashboard/list_and_share_applications.md @@ -25,6 +25,7 @@ By default, a few application instances are displayed (e.g., `My Jobs`, an insta 2. Select **Rename**. - :bulb: The instance name will change to an input field. 3. Enter a new name and press **Enter** to save it. + - :bulb: You can't use the same name for several intances ### Moving an Application Instance @@ -42,13 +43,16 @@ By default, a few application instances are displayed (e.g., `My Jobs`, an insta ### Sharing Your Dashboard -1. Copy the URL from your browser. - - :bulb: The URL encodes the current state of your dashboard. -2. Share it with others. - - :warning: The recipient will see a similar dashboard layout but may not see identical content if: - - They belong to a different VO or group. - - Time-sensitive data has changed since sharing. - - :warning: Encoding too many application instances may create discrepancies as the URL has a theoretical limit of 8000 characters based on [RFC9110](https://www.rfc-editor.org/rfc/rfc9110#section-4.1-5) +1. Click on the **Export** button at the top-right corner of the page. +2. Select the instances you want to share. + - :bulb: You can select a group to select all instances within that group. + - :bulb: For each instance, the shared content will include the name you gave it and the settings you configured. +3. Click on **Export N Selected**. + - :bulb: A menu will appear with a text box containing the exported JSON. +4. Click on the **Copy to Clipboard** button. +5. Send this text to the person you want to share it with. + - :bulb: If you're using **Mattermost**, you can wrap the text with triple backticks (```) to display it nicely. + ## Advanced Features @@ -91,11 +95,4 @@ When managing multiple instances of the same application, grouping can help you 2. Select **Delete**. - :bulb: The group and all its application instances will disappear from the sidebar. - -### Share and import the settings of an application - -1. **Share**: You can export the status of an app by clicking on the share button in the top-right corner of the screen. After clicking, you can select which group and app you want to share and then copy a text corresponding to the states of the selected applications. - -2. **Import**: Next to the export button you can find the import button. You can paste into the window opened by the button the text corresponding to one or multiple shared apps. This will create a new group named *Imported App* with the imported applications and their settings. - **Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. diff --git a/docs/user/Job_Monitor/manage_job.md b/docs/user/Job_Monitor/manage_job.md new file mode 100644 index 00000000..b8f2484d --- /dev/null +++ b/docs/user/Job_Monitor/manage_job.md @@ -0,0 +1,19 @@ +# Manage Your Jobs + +## Change Their Statuses + +You can select one or more jobs by clicking on the checkboxes next to each job. Once jobs are selected, you can perform actions on them using the buttons at the top of the table. The available actions include: + +- **Reschedule**: Reschedules the selected jobs. +- **Kill**: Marks the selected jobs as `KILLED`. +- **Delete**: Marks the selected jobs as `DELETED`. + +**Note**: +- You can only delete jobs that are already killed. +- A job cannot be rescheduled more than three times. + +## View a Job's History + +You can right-click on a job to open its **Job History**. +The history shows the different statuses the job has gone through, along with the corresponding dates and the authors of the changes. + diff --git a/docs/user/Job_Monitor/monitor_jobs.md b/docs/user/Job_Monitor/monitor_jobs.md deleted file mode 100644 index 95fc67c4..00000000 --- a/docs/user/Job_Monitor/monitor_jobs.md +++ /dev/null @@ -1,34 +0,0 @@ -# Job Monitor documentation - -## The search bar - - The search bar allows you to filter jobs based on various criteria. The filters are represented as equations in the search bar, where each equation consists of a job attribute, an operator, and a value. - A resarch is automatically performed when all the equations in the search bar are valid. - - ### Create a filter - To create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. - The search bar only suggests attributes, operators, and values that are available in your current set of jobs. - - ### Edit a filter - To edit a filter, click on the filter in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. - - ### Remove a filter - To remove a filter, you can either press the `Backspace` key to remove the last token or right-click on the equation to remove the entire equation. - - -## Use the table -The table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date. - -### Actions on the table -You can click on the eye icon to select more columns to display in the table. -You can sort the table by clicking on the column headers. Clicking on a column header will sort the table in ascending order, and clicking again will sort it in descending order. -You can set the page size by clicking on the `Row per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page. - -### Actions on a job -You can do a right-click on a job to open the `Job History`. -You can select one or more jobs by clicking on the checkboxes next to each job. Once you have selected jobs, you can perform actions on them using the buttons at the top of the table. The available actions include: -- **Get IDs**: This button will copy the IDs of the selected jobs to the clipboard. -- **Rechedule**: This button will reschedule the selected jobs. -- **Kill**: This button will kill the selected jobs. -- **Delete**: This button will delete the selected jobs. - diff --git a/docs/user/Job_Monitor/use_searchbar.md b/docs/user/Job_Monitor/use_searchbar.md new file mode 100644 index 00000000..188b44e5 --- /dev/null +++ b/docs/user/Job_Monitor/use_searchbar.md @@ -0,0 +1,19 @@ +# The Search Bar + +The search bar allows you to filter jobs based on various criteria. Filters are represented as equations, where each equation consists of a job attribute, an operator, and a value. The search bar analyzes these equations to evaluate their consistency. A green equation is valid, a yellow equation is incomplete, and a red equation is invalid. + +A search is automatically performed when all equations in the search bar are valid. + +## Create a Filter + +To create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. +The search bar only suggests attributes, operators, and values that are available in your current set of jobs. + +## Edit a Filter + +To edit a filter, click on it in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. Press `ESCAPE` to return to the end of the search bar. + +## Remove a Filter + +To remove a filter, press the `Backspace` key to remove the last token, or right-click on the equation to remove the entire equation. +You can also clear the entire search bar by clicking on the trash can button at the end of the search bar. diff --git a/docs/user/Job_Monitor/use_table.md b/docs/user/Job_Monitor/use_table.md new file mode 100644 index 00000000..ae220ed2 --- /dev/null +++ b/docs/user/Job_Monitor/use_table.md @@ -0,0 +1,16 @@ +# The Table + +The table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date. + +## Change the Visibility + +You can click on the eye icon to select additional columns to display in the table. Some columns are hidden by default. + +You can sort the table by clicking on the column headers. Clicking once will sort the table in ascending order; clicking again will sort it in descending order. + +You can set the page size by using the `Rows per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page. + +## Select a Job + +You can select one or multiple jobs using the checkboxes on the left side of the table. +Once you have selected at least one job, you can perform actions on it. You can manage the selected jobs or copy their IDs to your clipboard. diff --git a/docs/user/generalUsage.md b/docs/user/generalUsage.md index 0dad74f0..55762518 100644 --- a/docs/user/generalUsage.md +++ b/docs/user/generalUsage.md @@ -1,18 +1,24 @@ -# General usage +# General Usage -## Navigate between applications +## Navigate Between Applications -You can click on the \`Add application\` button to create a new instance of an application. The list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard +You can click on the `Add application` button to create a new instance of an application. +The list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard. -## Share applications +## Share Applications -To share applications, click the \`Export\` button at the top right of the screen. Then, select the applications you want to share and copy them to the clipboard. +To share applications, click the `Export` button at the top right of the screen. +Then, select the applications you want to share and copy them to the clipboard. -## Import applications +## Import Applications -To import applications, click the \`Import\` button at the top right of the screen. Paste the copied applications into the input field and click \`Import\`. The imported applications will appear in the sidebar. -If the states are outdated, you can copy the updated version of them by clicking the \`Copy all updated states\` button. +To import applications, click the `Import` button at the top right of the screen. +Paste the copied applications into the input field and click `Import`. The imported applications will appear in the sidebar. +If the states are outdated, you can copy the updated version of them by clicking the `Copy all updated states` button. -## Save you dashoard -To save your dashboard, clicke the \`Export\`button at the top right of the screen. Then, select the applications you want to save and click on the \`Save in the browser\` button. The saved applications will be stored in your browser's local storage. -When you want to load the saved applications, click the \`Import\` button at the top right of the screen and select the \`Load from the browser\` option. The saved applications will be loaded into the sidebar. +## Save Your Dashboard + +To save your dashboard, click the `Export` button at the top right of the screen. +Then, select the applications you want to save and click the `Save in the browser` button. The saved applications will be stored in your browser's local storage. +When you want to load the saved applications, click the `Import` button at the top right of the screen and select the `Load from the browser` option. +The saved applications will be loaded into the sidebar. diff --git a/package.json b/package.json index 81d1e2c3..4eecb072 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "doc:diracx-web-components": "npm --prefix packages/diracx-web-components run doc", "lint": "npm --prefix packages/diracx-web-components run lint && npm --prefix packages/diracx-web run lint", "ts-lint": "npm --prefix packages/diracx-web-components run ts-lint && npm --prefix packages/diracx-web run ts-lint", - "prepare": "husky" + "prepare": "husky", + "generate-doc": "npm --prefix packages/diracx-web-components run generate-doc && npm --prefix packages/extensions run generate-doc" } } diff --git a/packages/diracx-web-components/package.json b/packages/diracx-web-components/package.json index f57266db..73f6c92b 100644 --- a/packages/diracx-web-components/package.json +++ b/packages/diracx-web-components/package.json @@ -7,7 +7,7 @@ "access": "public" }, "scripts": { - "build": "node script/generateDocs && tsup --minify", + "build": "npm run generate-doc && tsup --minify", "dev": "tsup --watch", "test": "jest --ci", "lint": "eslint ./src", @@ -16,7 +16,7 @@ "prepack": "rm -rf dist && npm run build", "doc": "storybook dev -p 6006", "build-doc": "storybook build", - "generate-docs": "node script/generateDocs.js" + "generate-doc": "node script/generateDoc.js" }, "license": "GPL-3.0", "type": "module", diff --git a/packages/diracx-web-components/script/generateDocs.js b/packages/diracx-web-components/script/generateDoc.js similarity index 97% rename from packages/diracx-web-components/script/generateDocs.js rename to packages/diracx-web-components/script/generateDoc.js index 857cc6df..7f68c81a 100644 --- a/packages/diracx-web-components/script/generateDocs.js +++ b/packages/diracx-web-components/script/generateDoc.js @@ -61,7 +61,8 @@ async function generate() { applications: apps, }; - const fileContent = `/** + const fileContent = `/* eslint-disable */ +/** *File generated by generateDocs.js from /docs/user. *Do not edit this file directly. */ diff --git a/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx b/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx index d7588812..ec95de27 100644 --- a/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx +++ b/packages/diracx-web-components/src/components/DashboardLayout/HelpOverlay.tsx @@ -74,7 +74,7 @@ export default function HelpOverlay({ variant: "h5", gutterBottom: true, sx: { - marginTop: "0.75rem", + marginTop: "1rem", marginBottom: "0.25rem", }, } as React.HTMLProps, @@ -145,6 +145,7 @@ export default function HelpOverlay({ > + @@ -190,7 +191,7 @@ export default function HelpOverlay({ {/* Right content pane */} - {RenderContent()} + {RenderContent()} ); diff --git a/packages/diracx-web-components/src/generatedDocs.ts b/packages/diracx-web-components/src/generatedDocs.ts index b0b8b94f..c3d0e296 100644 --- a/packages/diracx-web-components/src/generatedDocs.ts +++ b/packages/diracx-web-components/src/generatedDocs.ts @@ -6,14 +6,14 @@ import { UserDocumentation } from './types'; export const userDocumentation: UserDocumentation = { - "generalUsage": "# General usage \n\n## Navigate between applications \n\nYou can click on the \\`Add application\\` button to create a new instance of an application. The list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard\n\n## Share applications\n\nTo share applications, click the \\`Export\\` button at the top right of the screen. Then, select the applications you want to share and copy them to the clipboard.\n\n## Import applications\n\nTo import applications, click the \\`Import\\` button at the top right of the screen. Paste the copied applications into the input field and click \\`Import\\`. The imported applications will appear in the sidebar.\nIf the states are outdated, you can copy the updated version of them by clicking the \\`Copy all updated states\\` button. \n\n## Save you dashoard\nTo save your dashboard, clicke the \\`Export\\`button at the top right of the screen. Then, select the applications you want to save and click on the \\`Save in the browser\\` button. The saved applications will be stored in your browser's local storage.\nWhen you want to load the saved applications, click the \\`Import\\` button at the top right of the screen and select the \\`Load from the browser\\` option. The saved applications will be loaded into the sidebar.\n", + "generalUsage": "# General Usage\n\n## Navigate Between Applications\n\nYou can click on the `Add application` button to create a new instance of an application. \nThe list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard.\n\n## Share Applications\n\nTo share applications, click the `Export` button at the top right of the screen.\nThen, select the applications you want to share and copy them to the clipboard.\n\n## Import Applications\n\nTo import applications, click the `Import` button at the top right of the screen.\nPaste the copied applications into the input field and click `Import`. The imported applications will appear in the sidebar.\nIf the states are outdated, you can copy the updated version of them by clicking the `Copy all updated states` button.\n\n## Save Your Dashboard\n\nTo save your dashboard, click the `Export` button at the top right of the screen. \nThen, select the applications you want to save and click the `Save in the browser` button. The saved applications will be stored in your browser's local storage.\nWhen you want to load the saved applications, click the `Import` button at the top right of the screen and select the `Load from the browser` option. \nThe saved applications will be loaded into the sidebar.\n", "applications": [ { "appName": "Dashboard", "sections": [ { "title": "Managing Application Instances", - "content": "# Managing Application Instances\n\nAn *application instance* is a graphical web interface that allows users to interact with DiracX services. DiracX-Web is essentially a collection of such applications, and users can \"spawn\" instances to interact with them.\n\nBy default, a few application instances are displayed (e.g., `My Jobs`, an instance of `Job Monitor`). This guide will help you manage, organize, and share application instances effectively.\n\n## Basics\n\n### Accessing More Applications\n\n1. Click the **Add Application** button at the bottom of the sidebar.\n - :bulb: On mobile devices, first open the sidebar by clicking the **menu icon** (☰) at the top-left corner.\n2. Select an application from the list in the dialog box.\n - :bulb: The selected application will appear in the sidebar.\n\n### Opening Multiple Instances of the Same Application\n\n- Repeat the steps above to open additional instances of the same application.\n - :bulb: Each instance has its own state, making it ideal for monitoring different job groups with specific criteria for instance.\n\n### Renaming an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The instance name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving an Application Instance\n\n1. Locate the **handle icon** next to the instance name.\n2. Click and hold the handle to select the instance.\n3. Drag it to the desired position within the sidebar.\n4. Release the mouse button to place the instance.\n\n### Deleting an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The application instance will disappear from the sidebar.\n\n### Sharing Your Dashboard\n\n1. Copy the URL from your browser.\n - :bulb: The URL encodes the current state of your dashboard.\n2. Share it with others.\n - :warning: The recipient will see a similar dashboard layout but may not see identical content if:\n - They belong to a different VO or group.\n - Time-sensitive data has changed since sharing.\n - :warning: Encoding too many application instances may create discrepancies as the URL has a theoretical limit of 8000 characters based on [RFC9110](https://www.rfc-editor.org/rfc/rfc9110#section-4.1-5) \n\n## Advanced Features\n\nWhen managing multiple instances of the same application, grouping can help you organize your dashboard efficiently.\n\n### Creating a New Group\n\n1. **Right-click** anywhere in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **New Group**.\n - :bulb: A new group with a default name will appear in the sidebar.\n3. Add new application instances to the group using the **Add Application** button.\n - :bulb: By default, new instances will be placed in the most recently created group.\n\n### Renaming a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The group name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving a Group\n\n1. Locate the **handle icon** next to the group name.\n2. Click and hold the handle to select the group.\n3. Drag the group to the desired position within the sidebar.\n - :bulb: All application instances within the group will move together.\n4. Release the mouse button to place the group.\n\n### Moving Instances Between Groups\n\n1. Drag an application instance from one group.\n2. Drop it into another group using the same drag-and-drop process as moving instances within a group.\n\n### Deleting a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The group and all its application instances will disappear from the sidebar.\n\n\n### Share and import the settings of an application\n\n1. **Share**: You can export the status of an app by clicking on the share button in the top-right corner of the screen. After clicking, you can select which group and app you want to share and then copy a text corresponding to the states of the selected applications.\n\n2. **Import**: Next to the export button you can find the import button. You can paste into the window opened by the button the text corresponding to one or multiple shared apps. This will create a new group named *Imported App* with the imported applications and their settings. \n\n**Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. \n" + "content": "# Managing Application Instances\n\nAn *application instance* is a graphical web interface that allows users to interact with DiracX services. DiracX-Web is essentially a collection of such applications, and users can \"spawn\" instances to interact with them.\n\nBy default, a few application instances are displayed (e.g., `My Jobs`, an instance of `Job Monitor`). This guide will help you manage, organize, and share application instances effectively.\n\n## Basics\n\n### Accessing More Applications\n\n1. Click the **Add Application** button at the bottom of the sidebar.\n - :bulb: On mobile devices, first open the sidebar by clicking the **menu icon** (☰) at the top-left corner.\n2. Select an application from the list in the dialog box.\n - :bulb: The selected application will appear in the sidebar.\n\n### Opening Multiple Instances of the Same Application\n\n- Repeat the steps above to open additional instances of the same application.\n - :bulb: Each instance has its own state, making it ideal for monitoring different job groups with specific criteria for instance.\n\n### Renaming an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The instance name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n - :bulb: You can't use the same name for several intances\n\n### Moving an Application Instance\n\n1. Locate the **handle icon** next to the instance name.\n2. Click and hold the handle to select the instance.\n3. Drag it to the desired position within the sidebar.\n4. Release the mouse button to place the instance.\n\n### Deleting an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The application instance will disappear from the sidebar.\n\n### Sharing Your Dashboard\n\n1. Click on the **Export** button at the top-right corner of the page.\n2. Select the instances you want to share.\n - :bulb: You can select a group to select all instances within that group.\n - :bulb: For each instance, the shared content will include the name you gave it and the settings you configured.\n3. Click on **Export N Selected**.\n - :bulb: A menu will appear with a text box containing the exported JSON.\n4. Click on the **Copy to Clipboard** button.\n5. Send this text to the person you want to share it with.\n - :bulb: If you're using **Mattermost**, you can wrap the text with triple backticks (```) to display it nicely.\n\n\n## Advanced Features\n\nWhen managing multiple instances of the same application, grouping can help you organize your dashboard efficiently.\n\n### Creating a New Group\n\n1. **Right-click** anywhere in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **New Group**.\n - :bulb: A new group with a default name will appear in the sidebar.\n3. Add new application instances to the group using the **Add Application** button.\n - :bulb: By default, new instances will be placed in the most recently created group.\n\n### Renaming a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The group name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving a Group\n\n1. Locate the **handle icon** next to the group name.\n2. Click and hold the handle to select the group.\n3. Drag the group to the desired position within the sidebar.\n - :bulb: All application instances within the group will move together.\n4. Release the mouse button to place the group.\n\n### Moving Instances Between Groups\n\n1. Drag an application instance from one group.\n2. Drop it into another group using the same drag-and-drop process as moving instances within a group.\n\n### Deleting a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The group and all its application instances will disappear from the sidebar.\n\n**Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. \n" }, { "title": "Logging in & out", @@ -25,8 +25,16 @@ export const userDocumentation: UserDocumentation = { "appName": "Job Monitor", "sections": [ { - "title": "Job Monitor documentation", - "content": "# Job Monitor documentation\n\n## The search bar\n\n The search bar allows you to filter jobs based on various criteria. The filters are represented as equations in the search bar, where each equation consists of a job attribute, an operator, and a value. \n A resarch is automatically performed when all the equations in the search bar are valid. \n\n ### Create a filter\n To create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by.\n The search bar only suggests attributes, operators, and values that are available in your current set of jobs.\n\n ### Edit a filter\n To edit a filter, click on the filter in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. \n\n ### Remove a filter\n To remove a filter, you can either press the `Backspace` key to remove the last token or right-click on the equation to remove the entire equation.\n\n\n## Use the table\nThe table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date.\n\n### Actions on the table\nYou can click on the eye icon to select more columns to display in the table. \nYou can sort the table by clicking on the column headers. Clicking on a column header will sort the table in ascending order, and clicking again will sort it in descending order.\nYou can set the page size by clicking on the `Row per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page.\n\n### Actions on a job\nYou can do a right-click on a job to open the `Job History`.\nYou can select one or more jobs by clicking on the checkboxes next to each job. Once you have selected jobs, you can perform actions on them using the buttons at the top of the table. The available actions include:\n- **Get IDs**: This button will copy the IDs of the selected jobs to the clipboard.\n- **Rechedule**: This button will reschedule the selected jobs.\n- **Kill**: This button will kill the selected jobs.\n- **Delete**: This button will delete the selected jobs.\n\n" + "title": "Manage Your Jobs", + "content": "# Manage Your Jobs\n\n## Change Their Statuses\n\nYou can select one or more jobs by clicking on the checkboxes next to each job. Once jobs are selected, you can perform actions on them using the buttons at the top of the table. The available actions include:\n\n- **Reschedule**: Reschedules the selected jobs.\n- **Kill**: Marks the selected jobs as `KILLED`.\n- **Delete**: Marks the selected jobs as `DELETED`.\n\n**Note**: \n- You can only delete jobs that are already killed. \n- A job cannot be rescheduled more than three times.\n\n## View a Job's History\n\nYou can right-click on a job to open its **Job History**. \nThe history shows the different statuses the job has gone through, along with the corresponding dates and the authors of the changes.\n\n" + }, + { + "title": "The Search Bar", + "content": "# The Search Bar\n\nThe search bar allows you to filter jobs based on various criteria. Filters are represented as equations, where each equation consists of a job attribute, an operator, and a value. The search bar analyzes these equations to evaluate their consistency. A green equation is valid, a yellow equation is incomplete, and a red equation is invalid.\n\nA search is automatically performed when all equations in the search bar are valid.\n\n## Create a Filter\n\nTo create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. \nThe search bar only suggests attributes, operators, and values that are available in your current set of jobs.\n\n## Edit a Filter\n\nTo edit a filter, click on it in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. Press `ESCAPE` to return to the end of the search bar.\n\n## Remove a Filter\n\nTo remove a filter, press the `Backspace` key to remove the last token, or right-click on the equation to remove the entire equation. \nYou can also clear the entire search bar by clicking on the trash can button at the end of the search bar.\n" + }, + { + "title": "The Table", + "content": "# The Table\n\nThe table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date.\n\n## Change the Visibility\n\nYou can click on the eye icon to select additional columns to display in the table. Some columns are hidden by default.\n\nYou can sort the table by clicking on the column headers. Clicking once will sort the table in ascending order; clicking again will sort it in descending order.\n\nYou can set the page size by using the `Rows per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page.\n\n## Select a Job\n\nYou can select one or multiple jobs using the checkboxes on the left side of the table. \nOnce you have selected at least one job, you can perform actions on it. You can manage the selected jobs or copy their IDs to your clipboard.\n" } ] } diff --git a/packages/diracx-web/package.json b/packages/diracx-web/package.json index c222df24..b2e9e694 100644 --- a/packages/diracx-web/package.json +++ b/packages/diracx-web/package.json @@ -11,8 +11,7 @@ "lint": "next lint", "lint-staged": "lint-staged", "ts-lint": "tsc -noEmit -incremental", - "postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public", - "generate-docs": "ts-node script/generateDocs.ts" + "postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public" }, "dependencies": { "@axa-fr/react-oidc": "^7.24.0", diff --git a/packages/extensions/docs/user/generalUsage.md b/packages/extensions/docs/user/generalUsage.md index e501f8ea..e0440a91 100644 --- a/packages/extensions/docs/user/generalUsage.md +++ b/packages/extensions/docs/user/generalUsage.md @@ -1,3 +1,3 @@ # Custom general Usage -You can define you own `General Usage`. +You can define your own `General Usage`. diff --git a/packages/extensions/package.json b/packages/extensions/package.json index 075669e3..bdf736ac 100644 --- a/packages/extensions/package.json +++ b/packages/extensions/package.json @@ -6,14 +6,14 @@ "license": "GPL-3.0-only", "scripts": { "dev": "next dev", - "build": "node script/generateDocs.js && next build", + "build": "npm run generate-doc && next build", "test": "cypress open --config baseUrl=$DIRACX_URL", "start": "next start", "lint": "next lint", "lint-staged": "lint-staged", "ts-lint": "tsc -noEmit -incremental", "postinstall": "node ../../node_modules/@axa-fr/react-oidc/bin/copy-service-worker-files.mjs public", - "generate-docs": "node script/generateDocs.js" + "generate-doc": "node script/generateDoc.js" }, "dependencies": { "@axa-fr/react-oidc": "^7.24.0", @@ -40,6 +40,8 @@ "eslint": "^9", "eslint-config-next": "15.0.2", "eslint-config-prettier": "^10.0.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-unused-imports": "^4.1.4", "lint-staged": "^15.2.2", "prettier": "^3.2.5", "typescript": "^5" diff --git a/packages/extensions/script/generateDocs.js b/packages/extensions/script/generateDoc.js similarity index 97% rename from packages/extensions/script/generateDocs.js rename to packages/extensions/script/generateDoc.js index e311c3d7..25e725cd 100644 --- a/packages/extensions/script/generateDocs.js +++ b/packages/extensions/script/generateDoc.js @@ -61,7 +61,8 @@ async function generate() { applications: apps, }; - const fileContent = `/** + const fileContent = `/* eslint-disable */ +/** *File generated by generateDocs.js from /docs/user. *Do not edit this file directly. */ diff --git a/packages/extensions/src/generatedDocs.ts b/packages/extensions/src/generatedDocs.ts index 6f0edbee..b6ee14df 100644 --- a/packages/extensions/src/generatedDocs.ts +++ b/packages/extensions/src/generatedDocs.ts @@ -1,3 +1,4 @@ + /** *File generated by generateDocs.js from /docs/user. *Do not edit this file directly. @@ -7,7 +8,7 @@ import { UserDocumentation } from "@dirac-grid/diracx-web-components/types"; export const userDocumentation: UserDocumentation = { generalUsage: - "# Custom general Usage\n\nYou can define you own `General Usage`.", + "# Custom general Usage\n\nYou can define your own `General Usage`.\n", applications: [ { appName: "Owner Monitor", @@ -15,11 +16,12 @@ export const userDocumentation: UserDocumentation = { { title: "Definition of Gubbins", content: - '# Definition of Gubbins\n\n**Gubbins** is a British informal noun referring to small, miscellaneous items or bits and pieces, often of little value or importance. It can describe gadgets, parts, or knick-knacks whose exact names might not be known or remembered. The term is frequently used to refer to odds and ends lying around or small components in a machine. Sometimes, it can imply something trivial or unimportant, almost like "stuff" or "junk." In some contexts, it can also humorously refer to technical or mechanical parts, especially those that are confusing or complicated. While common in UK English, the word is less known in American English, where similar expressions might be "bits and bobs" or "thingamajigs." Overall, "gubbins" conveys a casual, somewhat affectionate sense of miscellaneous small items. ', + '# Definition of Gubbins\n\n**Gubbins** is a British informal noun referring to small, miscellaneous items or bits and pieces, often of little value or importance. It can describe gadgets, parts, or knick-knacks whose exact names might not be known or remembered. The term is frequently used to refer to odds and ends lying around or small components in a machine. Sometimes, it can imply something trivial or unimportant, almost like "stuff" or "junk." In some contexts, it can also humorously refer to technical or mechanical parts, especially those that are confusing or complicated. While common in UK English, the word is less known in American English, where similar expressions might be "bits and bobs" or "thingamajigs." Overall, "gubbins" conveys a casual, somewhat affectionate sense of miscellaneous small items.\n', }, { title: "Presentation of this module", - content: "# Presentation of this module\n\nThis is just an example.", + content: + "# Presentation of this module\n\nThis is just an example.\n", }, ], }, From 5f6e47bb6be8bd6809ae448ce3f51d05117c42e3 Mon Sep 17 00:00:00 2001 From: theau Date: Wed, 30 Jul 2025 09:09:54 +0200 Subject: [PATCH 4/5] fix: review suggestions --- .husky/pre-commit | 1 + docs/user/Job_Monitor/manage_job.md | 8 ++-- docs/user/Job_Monitor/use_table.md | 3 +- .../script/generateDoc.js | 2 +- .../src/contexts/ApplicationsProvider.tsx | 2 +- .../diracx-web-components/src/generatedDoc.ts | 48 +++++++++++++++++++ .../src/generatedDocs.ts | 42 ---------------- packages/extensions/script/generateDoc.js | 2 +- .../extensions/src/app/(dashboard)/layout.tsx | 2 +- .../src/{generatedDocs.ts => generatedDoc.ts} | 0 10 files changed, 58 insertions(+), 52 deletions(-) create mode 100644 packages/diracx-web-components/src/generatedDoc.ts delete mode 100644 packages/diracx-web-components/src/generatedDocs.ts rename packages/extensions/src/{generatedDocs.ts => generatedDoc.ts} (100%) diff --git a/.husky/pre-commit b/.husky/pre-commit index 514e42af..b485d7f4 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,3 +1,4 @@ +npm run generate-doc && git add packages/*/*/generatedDoc.ts npm --prefix packages/diracx-web-components run lint-staged npm --prefix packages/diracx-web run lint-staged npm --prefix packages/extensions run lint-staged diff --git a/docs/user/Job_Monitor/manage_job.md b/docs/user/Job_Monitor/manage_job.md index b8f2484d..145a4b81 100644 --- a/docs/user/Job_Monitor/manage_job.md +++ b/docs/user/Job_Monitor/manage_job.md @@ -1,16 +1,16 @@ # Manage Your Jobs -## Change Their Statuses +## Status transitions You can select one or more jobs by clicking on the checkboxes next to each job. Once jobs are selected, you can perform actions on them using the buttons at the top of the table. The available actions include: - **Reschedule**: Reschedules the selected jobs. -- **Kill**: Marks the selected jobs as `KILLED`. -- **Delete**: Marks the selected jobs as `DELETED`. +- **Kill**: Marks the selected jobs to be killed. +- **Delete**: Marks the selected jobs for deletion. **Note**: - You can only delete jobs that are already killed. -- A job cannot be rescheduled more than three times. +- A job cannot typically be rescheduled more than three times. ## View a Job's History diff --git a/docs/user/Job_Monitor/use_table.md b/docs/user/Job_Monitor/use_table.md index ae220ed2..24284298 100644 --- a/docs/user/Job_Monitor/use_table.md +++ b/docs/user/Job_Monitor/use_table.md @@ -2,8 +2,7 @@ The table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date. -## Change the Visibility - +## Table display settings You can click on the eye icon to select additional columns to display in the table. Some columns are hidden by default. You can sort the table by clicking on the column headers. Clicking once will sort the table in ascending order; clicking again will sort it in descending order. diff --git a/packages/diracx-web-components/script/generateDoc.js b/packages/diracx-web-components/script/generateDoc.js index 7f68c81a..1a0c3105 100644 --- a/packages/diracx-web-components/script/generateDoc.js +++ b/packages/diracx-web-components/script/generateDoc.js @@ -2,7 +2,7 @@ import * as fs from "fs"; import * as path from "path"; const DOCS_PATH = "../../docs/user"; -const OUTPUT_PATH = "./src/generatedDocs.ts"; +const OUTPUT_PATH = "./src/generatedDoc.ts"; async function readMarkdown(filePath) { return fs.promises.readFile(filePath, "utf-8"); diff --git a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx index b02d0b2b..7e712f1b 100644 --- a/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx +++ b/packages/diracx-web-components/src/contexts/ApplicationsProvider.tsx @@ -4,7 +4,7 @@ import React, { createContext, useEffect, useState } from "react"; import { applicationList } from "../components/applicationList"; import { defaultDashboard } from "../components/defaultDashboard"; import { DashboardGroup } from "../types/DashboardGroup"; -import { userDocumentation as userDoc } from "../generatedDocs"; +import { userDocumentation as userDoc } from "../generatedDoc"; import ApplicationMetadata from "../types/ApplicationMetadata"; import { UserDocumentation } from "../types"; diff --git a/packages/diracx-web-components/src/generatedDoc.ts b/packages/diracx-web-components/src/generatedDoc.ts new file mode 100644 index 00000000..9dff001b --- /dev/null +++ b/packages/diracx-web-components/src/generatedDoc.ts @@ -0,0 +1,48 @@ +/** + *File generated by generateDocs.js from /docs/user. + *Do not edit this file directly. + */ + +import { UserDocumentation } from "./types"; + +export const userDocumentation: UserDocumentation = { + generalUsage: + "# General Usage\n\n## Navigate Between Applications\n\nYou can click on the `Add application` button to create a new instance of an application. \nThe list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard.\n\n## Share Applications\n\nTo share applications, click the `Export` button at the top right of the screen.\nThen, select the applications you want to share and copy them to the clipboard.\n\n## Import Applications\n\nTo import applications, click the `Import` button at the top right of the screen.\nPaste the copied applications into the input field and click `Import`. The imported applications will appear in the sidebar.\nIf the states are outdated, you can copy the updated version of them by clicking the `Copy all updated states` button.\n\n## Save Your Dashboard\n\nTo save your dashboard, click the `Export` button at the top right of the screen. \nThen, select the applications you want to save and click the `Save in the browser` button. The saved applications will be stored in your browser's local storage.\nWhen you want to load the saved applications, click the `Import` button at the top right of the screen and select the `Load from the browser` option. \nThe saved applications will be loaded into the sidebar.\n", + applications: [ + { + appName: "Dashboard", + sections: [ + { + title: "Managing Application Instances", + content: + "# Managing Application Instances\n\nAn *application instance* is a graphical web interface that allows users to interact with DiracX services. DiracX-Web is essentially a collection of such applications, and users can \"spawn\" instances to interact with them.\n\nBy default, a few application instances are displayed (e.g., `My Jobs`, an instance of `Job Monitor`). This guide will help you manage, organize, and share application instances effectively.\n\n## Basics\n\n### Accessing More Applications\n\n1. Click the **Add Application** button at the bottom of the sidebar.\n - :bulb: On mobile devices, first open the sidebar by clicking the **menu icon** (☰) at the top-left corner.\n2. Select an application from the list in the dialog box.\n - :bulb: The selected application will appear in the sidebar.\n\n### Opening Multiple Instances of the Same Application\n\n- Repeat the steps above to open additional instances of the same application.\n - :bulb: Each instance has its own state, making it ideal for monitoring different job groups with specific criteria for instance.\n\n### Renaming an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The instance name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n - :bulb: You can't use the same name for several intances\n\n### Moving an Application Instance\n\n1. Locate the **handle icon** next to the instance name.\n2. Click and hold the handle to select the instance.\n3. Drag it to the desired position within the sidebar.\n4. Release the mouse button to place the instance.\n\n### Deleting an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The application instance will disappear from the sidebar.\n\n### Sharing Your Dashboard\n\n1. Click on the **Export** button at the top-right corner of the page.\n2. Select the instances you want to share.\n - :bulb: You can select a group to select all instances within that group.\n - :bulb: For each instance, the shared content will include the name you gave it and the settings you configured.\n3. Click on **Export N Selected**.\n - :bulb: A menu will appear with a text box containing the exported JSON.\n4. Click on the **Copy to Clipboard** button.\n5. Send this text to the person you want to share it with.\n - :bulb: If you're using **Mattermost**, you can wrap the text with triple backticks (```) to display it nicely.\n\n\n## Advanced Features\n\nWhen managing multiple instances of the same application, grouping can help you organize your dashboard efficiently.\n\n### Creating a New Group\n\n1. **Right-click** anywhere in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **New Group**.\n - :bulb: A new group with a default name will appear in the sidebar.\n3. Add new application instances to the group using the **Add Application** button.\n - :bulb: By default, new instances will be placed in the most recently created group.\n\n### Renaming a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The group name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving a Group\n\n1. Locate the **handle icon** next to the group name.\n2. Click and hold the handle to select the group.\n3. Drag the group to the desired position within the sidebar.\n - :bulb: All application instances within the group will move together.\n4. Release the mouse button to place the group.\n\n### Moving Instances Between Groups\n\n1. Drag an application instance from one group.\n2. Drop it into another group using the same drag-and-drop process as moving instances within a group.\n\n### Deleting a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The group and all its application instances will disappear from the sidebar.\n\n**Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. \n", + }, + { + title: "Logging in & out", + content: + "# Logging in & out\n\n## Basics\n### Logging in\n\n1. Go to the DiracX-Web instance homepage. \n - 💡 You should end up on an authentication page.\n2. Authenticate you as a user of a given VO/group:\n - If your instance supports multiple VOs, select your VO in the list box.\n - Select your Group in the list box below.\n3. Click the **Login** button. \n - 💡 You should be redirected to the VO login page.\n4. Enter your credentials (e.g., Username/Password, X509 certificates). \n - 💡 You should see a page asking for permission to access your profile.\n5. Accept the permissions to access your DiracX dashboard. \n - 💡 You should be redirected to the DiracX-Web instance as a logged-in user, and the dashboard should appear.\n\n### Logging out\n\n1. Click on your profile icon in the top-right corner of the dashboard.\n - :bulb: A dropdown menu should appear\n2. Select **Logout** from the dropdown menu.\n \n## Advanced\n### Logging in with specific properties\n\nTODO\n", + }, + ], + }, + { + appName: "Job Monitor", + sections: [ + { + title: "Manage Your Jobs", + content: + "# Manage Your Jobs\n\n## Status transitions\n\nYou can select one or more jobs by clicking on the checkboxes next to each job. Once jobs are selected, you can perform actions on them using the buttons at the top of the table. The available actions include:\n\n- **Reschedule**: Reschedules the selected jobs.\n- **Kill**: Marks the selected jobs to be killed.\n- **Delete**: Marks the selected jobs for deletion.\n\n**Note**: \n- You can only delete jobs that are already killed. \n- A job cannot typically be rescheduled more than three times.\n\n## View a Job's History\n\nYou can right-click on a job to open its **Job History**. \nThe history shows the different statuses the job has gone through, along with the corresponding dates and the authors of the changes.\n\n", + }, + { + title: "The Search Bar", + content: + "# The Search Bar\n\nThe search bar allows you to filter jobs based on various criteria. Filters are represented as equations, where each equation consists of a job attribute, an operator, and a value. The search bar analyzes these equations to evaluate their consistency. A green equation is valid, a yellow equation is incomplete, and a red equation is invalid.\n\nA search is automatically performed when all equations in the search bar are valid.\n\n## Create a Filter\n\nTo create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. \nThe search bar only suggests attributes, operators, and values that are available in your current set of jobs.\n\n## Edit a Filter\n\nTo edit a filter, click on it in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. Press `ESCAPE` to return to the end of the search bar.\n\n## Remove a Filter\n\nTo remove a filter, press the `Backspace` key to remove the last token, or right-click on the equation to remove the entire equation. \nYou can also clear the entire search bar by clicking on the trash can button at the end of the search bar.\n", + }, + { + title: "The Table", + content: + "# The Table\n\nThe table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date.\n\n## Table display settings\nYou can click on the eye icon to select additional columns to display in the table. Some columns are hidden by default.\n\nYou can sort the table by clicking on the column headers. Clicking once will sort the table in ascending order; clicking again will sort it in descending order.\n\nYou can set the page size by using the `Rows per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page.\n\n## Select a Job\n\nYou can select one or multiple jobs using the checkboxes on the left side of the table. \nOnce you have selected at least one job, you can perform actions on it. You can manage the selected jobs or copy their IDs to your clipboard.\n", + }, + ], + }, + ], +}; diff --git a/packages/diracx-web-components/src/generatedDocs.ts b/packages/diracx-web-components/src/generatedDocs.ts deleted file mode 100644 index c3d0e296..00000000 --- a/packages/diracx-web-components/src/generatedDocs.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** -*File generated by generateDocs.js from /docs/user. -*Do not edit this file directly. -*/ - -import { UserDocumentation } from './types'; - -export const userDocumentation: UserDocumentation = { - "generalUsage": "# General Usage\n\n## Navigate Between Applications\n\nYou can click on the `Add application` button to create a new instance of an application. \nThe list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard.\n\n## Share Applications\n\nTo share applications, click the `Export` button at the top right of the screen.\nThen, select the applications you want to share and copy them to the clipboard.\n\n## Import Applications\n\nTo import applications, click the `Import` button at the top right of the screen.\nPaste the copied applications into the input field and click `Import`. The imported applications will appear in the sidebar.\nIf the states are outdated, you can copy the updated version of them by clicking the `Copy all updated states` button.\n\n## Save Your Dashboard\n\nTo save your dashboard, click the `Export` button at the top right of the screen. \nThen, select the applications you want to save and click the `Save in the browser` button. The saved applications will be stored in your browser's local storage.\nWhen you want to load the saved applications, click the `Import` button at the top right of the screen and select the `Load from the browser` option. \nThe saved applications will be loaded into the sidebar.\n", - "applications": [ - { - "appName": "Dashboard", - "sections": [ - { - "title": "Managing Application Instances", - "content": "# Managing Application Instances\n\nAn *application instance* is a graphical web interface that allows users to interact with DiracX services. DiracX-Web is essentially a collection of such applications, and users can \"spawn\" instances to interact with them.\n\nBy default, a few application instances are displayed (e.g., `My Jobs`, an instance of `Job Monitor`). This guide will help you manage, organize, and share application instances effectively.\n\n## Basics\n\n### Accessing More Applications\n\n1. Click the **Add Application** button at the bottom of the sidebar.\n - :bulb: On mobile devices, first open the sidebar by clicking the **menu icon** (☰) at the top-left corner.\n2. Select an application from the list in the dialog box.\n - :bulb: The selected application will appear in the sidebar.\n\n### Opening Multiple Instances of the Same Application\n\n- Repeat the steps above to open additional instances of the same application.\n - :bulb: Each instance has its own state, making it ideal for monitoring different job groups with specific criteria for instance.\n\n### Renaming an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The instance name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n - :bulb: You can't use the same name for several intances\n\n### Moving an Application Instance\n\n1. Locate the **handle icon** next to the instance name.\n2. Click and hold the handle to select the instance.\n3. Drag it to the desired position within the sidebar.\n4. Release the mouse button to place the instance.\n\n### Deleting an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The application instance will disappear from the sidebar.\n\n### Sharing Your Dashboard\n\n1. Click on the **Export** button at the top-right corner of the page.\n2. Select the instances you want to share.\n - :bulb: You can select a group to select all instances within that group.\n - :bulb: For each instance, the shared content will include the name you gave it and the settings you configured.\n3. Click on **Export N Selected**.\n - :bulb: A menu will appear with a text box containing the exported JSON.\n4. Click on the **Copy to Clipboard** button.\n5. Send this text to the person you want to share it with.\n - :bulb: If you're using **Mattermost**, you can wrap the text with triple backticks (```) to display it nicely.\n\n\n## Advanced Features\n\nWhen managing multiple instances of the same application, grouping can help you organize your dashboard efficiently.\n\n### Creating a New Group\n\n1. **Right-click** anywhere in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **New Group**.\n - :bulb: A new group with a default name will appear in the sidebar.\n3. Add new application instances to the group using the **Add Application** button.\n - :bulb: By default, new instances will be placed in the most recently created group.\n\n### Renaming a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The group name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving a Group\n\n1. Locate the **handle icon** next to the group name.\n2. Click and hold the handle to select the group.\n3. Drag the group to the desired position within the sidebar.\n - :bulb: All application instances within the group will move together.\n4. Release the mouse button to place the group.\n\n### Moving Instances Between Groups\n\n1. Drag an application instance from one group.\n2. Drop it into another group using the same drag-and-drop process as moving instances within a group.\n\n### Deleting a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The group and all its application instances will disappear from the sidebar.\n\n**Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. \n" - }, - { - "title": "Logging in & out", - "content": "# Logging in & out\n\n## Basics\n### Logging in\n\n1. Go to the DiracX-Web instance homepage. \n - 💡 You should end up on an authentication page.\n2. Authenticate you as a user of a given VO/group:\n - If your instance supports multiple VOs, select your VO in the list box.\n - Select your Group in the list box below.\n3. Click the **Login** button. \n - 💡 You should be redirected to the VO login page.\n4. Enter your credentials (e.g., Username/Password, X509 certificates). \n - 💡 You should see a page asking for permission to access your profile.\n5. Accept the permissions to access your DiracX dashboard. \n - 💡 You should be redirected to the DiracX-Web instance as a logged-in user, and the dashboard should appear.\n\n### Logging out\n\n1. Click on your profile icon in the top-right corner of the dashboard.\n - :bulb: A dropdown menu should appear\n2. Select **Logout** from the dropdown menu.\n \n## Advanced\n### Logging in with specific properties\n\nTODO\n" - } - ] - }, - { - "appName": "Job Monitor", - "sections": [ - { - "title": "Manage Your Jobs", - "content": "# Manage Your Jobs\n\n## Change Their Statuses\n\nYou can select one or more jobs by clicking on the checkboxes next to each job. Once jobs are selected, you can perform actions on them using the buttons at the top of the table. The available actions include:\n\n- **Reschedule**: Reschedules the selected jobs.\n- **Kill**: Marks the selected jobs as `KILLED`.\n- **Delete**: Marks the selected jobs as `DELETED`.\n\n**Note**: \n- You can only delete jobs that are already killed. \n- A job cannot be rescheduled more than three times.\n\n## View a Job's History\n\nYou can right-click on a job to open its **Job History**. \nThe history shows the different statuses the job has gone through, along with the corresponding dates and the authors of the changes.\n\n" - }, - { - "title": "The Search Bar", - "content": "# The Search Bar\n\nThe search bar allows you to filter jobs based on various criteria. Filters are represented as equations, where each equation consists of a job attribute, an operator, and a value. The search bar analyzes these equations to evaluate their consistency. A green equation is valid, a yellow equation is incomplete, and a red equation is invalid.\n\nA search is automatically performed when all equations in the search bar are valid.\n\n## Create a Filter\n\nTo create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. \nThe search bar only suggests attributes, operators, and values that are available in your current set of jobs.\n\n## Edit a Filter\n\nTo edit a filter, click on it in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. Press `ESCAPE` to return to the end of the search bar.\n\n## Remove a Filter\n\nTo remove a filter, press the `Backspace` key to remove the last token, or right-click on the equation to remove the entire equation. \nYou can also clear the entire search bar by clicking on the trash can button at the end of the search bar.\n" - }, - { - "title": "The Table", - "content": "# The Table\n\nThe table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date.\n\n## Change the Visibility\n\nYou can click on the eye icon to select additional columns to display in the table. Some columns are hidden by default.\n\nYou can sort the table by clicking on the column headers. Clicking once will sort the table in ascending order; clicking again will sort it in descending order.\n\nYou can set the page size by using the `Rows per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page.\n\n## Select a Job\n\nYou can select one or multiple jobs using the checkboxes on the left side of the table. \nOnce you have selected at least one job, you can perform actions on it. You can manage the selected jobs or copy their IDs to your clipboard.\n" - } - ] - } - ] -}; diff --git a/packages/extensions/script/generateDoc.js b/packages/extensions/script/generateDoc.js index 25e725cd..736ed7cf 100644 --- a/packages/extensions/script/generateDoc.js +++ b/packages/extensions/script/generateDoc.js @@ -2,7 +2,7 @@ import { promises } from "fs"; import { join } from "path"; const DOCS_PATH = "./docs/user"; -const OUTPUT_PATH = "./src/generatedDocs.ts"; +const OUTPUT_PATH = "./src/generatedDoc.ts"; async function readMarkdown(filePath) { return promises.readFile(filePath, "utf-8"); diff --git a/packages/extensions/src/app/(dashboard)/layout.tsx b/packages/extensions/src/app/(dashboard)/layout.tsx index 36ed9349..d24d47ff 100644 --- a/packages/extensions/src/app/(dashboard)/layout.tsx +++ b/packages/extensions/src/app/(dashboard)/layout.tsx @@ -4,7 +4,7 @@ import { Box } from "@mui/material"; import { Dashboard } from "@dirac-grid/diracx-web-components/components"; import { DiracXWebProviders } from "@dirac-grid/diracx-web-components/contexts"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; -import { userDocumentation } from "../../generatedDocs"; +import { userDocumentation } from "../../generatedDoc"; import { applicationList } from "@/gubbins/applicationList"; import { defaultSections } from "@/gubbins/DefaultUserDashboard"; diff --git a/packages/extensions/src/generatedDocs.ts b/packages/extensions/src/generatedDoc.ts similarity index 100% rename from packages/extensions/src/generatedDocs.ts rename to packages/extensions/src/generatedDoc.ts From 4bebaa519608f61242a0fcd6e7a3f896e311ef83 Mon Sep 17 00:00:00 2001 From: theau Date: Wed, 30 Jul 2025 09:24:01 +0200 Subject: [PATCH 5/5] chore(test) --- .prettierignore | 2 +- .../diracx-web-components/.prettierignore | 2 +- .../diracx-web-components/src/generatedDoc.ts | 59 +++++++++---------- .../stories/Dashboard.stories.tsx | 2 +- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/.prettierignore b/.prettierignore index 6df372ae..55a0eb66 100644 --- a/.prettierignore +++ b/.prettierignore @@ -19,7 +19,7 @@ packages/*/tsup.config.ts packages/*/.next packages/*/.tsup packages/*/out -packages/*/src/generatedDocs.ts +packages/*/src/generatedDoc.ts **/release-please-config.json **/.release-please-manifest.json diff --git a/packages/diracx-web-components/.prettierignore b/packages/diracx-web-components/.prettierignore index ae9be1d2..6b3078ad 100644 --- a/packages/diracx-web-components/.prettierignore +++ b/packages/diracx-web-components/.prettierignore @@ -7,4 +7,4 @@ jest.config.mjs release-please-config.json .release-please-manifest.json CHANGELOG.md -src/generatedDocs.ts \ No newline at end of file +src/generatedDoc.ts \ No newline at end of file diff --git a/packages/diracx-web-components/src/generatedDoc.ts b/packages/diracx-web-components/src/generatedDoc.ts index 9dff001b..abaaece6 100644 --- a/packages/diracx-web-components/src/generatedDoc.ts +++ b/packages/diracx-web-components/src/generatedDoc.ts @@ -1,48 +1,43 @@ + /** - *File generated by generateDocs.js from /docs/user. - *Do not edit this file directly. - */ +*File generated by generateDocs.js from /docs/user. +*Do not edit this file directly. +*/ -import { UserDocumentation } from "./types"; +import { UserDocumentation } from './types'; export const userDocumentation: UserDocumentation = { - generalUsage: - "# General Usage\n\n## Navigate Between Applications\n\nYou can click on the `Add application` button to create a new instance of an application. \nThe list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard.\n\n## Share Applications\n\nTo share applications, click the `Export` button at the top right of the screen.\nThen, select the applications you want to share and copy them to the clipboard.\n\n## Import Applications\n\nTo import applications, click the `Import` button at the top right of the screen.\nPaste the copied applications into the input field and click `Import`. The imported applications will appear in the sidebar.\nIf the states are outdated, you can copy the updated version of them by clicking the `Copy all updated states` button.\n\n## Save Your Dashboard\n\nTo save your dashboard, click the `Export` button at the top right of the screen. \nThen, select the applications you want to save and click the `Save in the browser` button. The saved applications will be stored in your browser's local storage.\nWhen you want to load the saved applications, click the `Import` button at the top right of the screen and select the `Load from the browser` option. \nThe saved applications will be loaded into the sidebar.\n", - applications: [ + "generalUsage": "# General Usage\n\n## Navigate Between Applications\n\nYou can click on the `Add application` button to create a new instance of an application. \nThe list of open instances appears in the sidebar on the left. Clicking on one of these instances will display it in the center of the dashboard.\n\n## Share Applications\n\nTo share applications, click the `Export` button at the top right of the screen.\nThen, select the applications you want to share and copy them to the clipboard.\n\n## Import Applications\n\nTo import applications, click the `Import` button at the top right of the screen.\nPaste the copied applications into the input field and click `Import`. The imported applications will appear in the sidebar.\nIf the states are outdated, you can copy the updated version of them by clicking the `Copy all updated states` button.\n\n## Save Your Dashboard\n\nTo save your dashboard, click the `Export` button at the top right of the screen. \nThen, select the applications you want to save and click the `Save in the browser` button. The saved applications will be stored in your browser's local storage.\nWhen you want to load the saved applications, click the `Import` button at the top right of the screen and select the `Load from the browser` option. \nThe saved applications will be loaded into the sidebar.\n", + "applications": [ { - appName: "Dashboard", - sections: [ + "appName": "Dashboard", + "sections": [ { - title: "Managing Application Instances", - content: - "# Managing Application Instances\n\nAn *application instance* is a graphical web interface that allows users to interact with DiracX services. DiracX-Web is essentially a collection of such applications, and users can \"spawn\" instances to interact with them.\n\nBy default, a few application instances are displayed (e.g., `My Jobs`, an instance of `Job Monitor`). This guide will help you manage, organize, and share application instances effectively.\n\n## Basics\n\n### Accessing More Applications\n\n1. Click the **Add Application** button at the bottom of the sidebar.\n - :bulb: On mobile devices, first open the sidebar by clicking the **menu icon** (☰) at the top-left corner.\n2. Select an application from the list in the dialog box.\n - :bulb: The selected application will appear in the sidebar.\n\n### Opening Multiple Instances of the Same Application\n\n- Repeat the steps above to open additional instances of the same application.\n - :bulb: Each instance has its own state, making it ideal for monitoring different job groups with specific criteria for instance.\n\n### Renaming an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The instance name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n - :bulb: You can't use the same name for several intances\n\n### Moving an Application Instance\n\n1. Locate the **handle icon** next to the instance name.\n2. Click and hold the handle to select the instance.\n3. Drag it to the desired position within the sidebar.\n4. Release the mouse button to place the instance.\n\n### Deleting an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The application instance will disappear from the sidebar.\n\n### Sharing Your Dashboard\n\n1. Click on the **Export** button at the top-right corner of the page.\n2. Select the instances you want to share.\n - :bulb: You can select a group to select all instances within that group.\n - :bulb: For each instance, the shared content will include the name you gave it and the settings you configured.\n3. Click on **Export N Selected**.\n - :bulb: A menu will appear with a text box containing the exported JSON.\n4. Click on the **Copy to Clipboard** button.\n5. Send this text to the person you want to share it with.\n - :bulb: If you're using **Mattermost**, you can wrap the text with triple backticks (```) to display it nicely.\n\n\n## Advanced Features\n\nWhen managing multiple instances of the same application, grouping can help you organize your dashboard efficiently.\n\n### Creating a New Group\n\n1. **Right-click** anywhere in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **New Group**.\n - :bulb: A new group with a default name will appear in the sidebar.\n3. Add new application instances to the group using the **Add Application** button.\n - :bulb: By default, new instances will be placed in the most recently created group.\n\n### Renaming a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The group name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving a Group\n\n1. Locate the **handle icon** next to the group name.\n2. Click and hold the handle to select the group.\n3. Drag the group to the desired position within the sidebar.\n - :bulb: All application instances within the group will move together.\n4. Release the mouse button to place the group.\n\n### Moving Instances Between Groups\n\n1. Drag an application instance from one group.\n2. Drop it into another group using the same drag-and-drop process as moving instances within a group.\n\n### Deleting a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The group and all its application instances will disappear from the sidebar.\n\n**Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. \n", + "title": "Managing Application Instances", + "content": "# Managing Application Instances\n\nAn *application instance* is a graphical web interface that allows users to interact with DiracX services. DiracX-Web is essentially a collection of such applications, and users can \"spawn\" instances to interact with them.\n\nBy default, a few application instances are displayed (e.g., `My Jobs`, an instance of `Job Monitor`). This guide will help you manage, organize, and share application instances effectively.\n\n## Basics\n\n### Accessing More Applications\n\n1. Click the **Add Application** button at the bottom of the sidebar.\n - :bulb: On mobile devices, first open the sidebar by clicking the **menu icon** (☰) at the top-left corner.\n2. Select an application from the list in the dialog box.\n - :bulb: The selected application will appear in the sidebar.\n\n### Opening Multiple Instances of the Same Application\n\n- Repeat the steps above to open additional instances of the same application.\n - :bulb: Each instance has its own state, making it ideal for monitoring different job groups with specific criteria for instance.\n\n### Renaming an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The instance name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n - :bulb: You can't use the same name for several intances\n\n### Moving an Application Instance\n\n1. Locate the **handle icon** next to the instance name.\n2. Click and hold the handle to select the instance.\n3. Drag it to the desired position within the sidebar.\n4. Release the mouse button to place the instance.\n\n### Deleting an Application Instance\n\n1. **Right-click** on the instance name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The application instance will disappear from the sidebar.\n\n### Sharing Your Dashboard\n\n1. Click on the **Export** button at the top-right corner of the page.\n2. Select the instances you want to share.\n - :bulb: You can select a group to select all instances within that group.\n - :bulb: For each instance, the shared content will include the name you gave it and the settings you configured.\n3. Click on **Export N Selected**.\n - :bulb: A menu will appear with a text box containing the exported JSON.\n4. Click on the **Copy to Clipboard** button.\n5. Send this text to the person you want to share it with.\n - :bulb: If you're using **Mattermost**, you can wrap the text with triple backticks (```) to display it nicely.\n\n\n## Advanced Features\n\nWhen managing multiple instances of the same application, grouping can help you organize your dashboard efficiently.\n\n### Creating a New Group\n\n1. **Right-click** anywhere in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **New Group**.\n - :bulb: A new group with a default name will appear in the sidebar.\n3. Add new application instances to the group using the **Add Application** button.\n - :bulb: By default, new instances will be placed in the most recently created group.\n\n### Renaming a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Rename**.\n - :bulb: The group name will change to an input field.\n3. Enter a new name and press **Enter** to save it.\n\n### Moving a Group\n\n1. Locate the **handle icon** next to the group name.\n2. Click and hold the handle to select the group.\n3. Drag the group to the desired position within the sidebar.\n - :bulb: All application instances within the group will move together.\n4. Release the mouse button to place the group.\n\n### Moving Instances Between Groups\n\n1. Drag an application instance from one group.\n2. Drop it into another group using the same drag-and-drop process as moving instances within a group.\n\n### Deleting a Group\n\n1. **Right-click** on the group name in the sidebar.\n - :bulb: A context menu will appear.\n2. Select **Delete**.\n - :bulb: The group and all its application instances will disappear from the sidebar.\n\n**Good to know:** When switching to a new version, the settings you are trying to import may no longer be valid. In this case, a new window will appear, offering to resolve the issue by updating the state copied to your clipboard. This updated version preserves your imported rules as much as possible. \n" }, { - title: "Logging in & out", - content: - "# Logging in & out\n\n## Basics\n### Logging in\n\n1. Go to the DiracX-Web instance homepage. \n - 💡 You should end up on an authentication page.\n2. Authenticate you as a user of a given VO/group:\n - If your instance supports multiple VOs, select your VO in the list box.\n - Select your Group in the list box below.\n3. Click the **Login** button. \n - 💡 You should be redirected to the VO login page.\n4. Enter your credentials (e.g., Username/Password, X509 certificates). \n - 💡 You should see a page asking for permission to access your profile.\n5. Accept the permissions to access your DiracX dashboard. \n - 💡 You should be redirected to the DiracX-Web instance as a logged-in user, and the dashboard should appear.\n\n### Logging out\n\n1. Click on your profile icon in the top-right corner of the dashboard.\n - :bulb: A dropdown menu should appear\n2. Select **Logout** from the dropdown menu.\n \n## Advanced\n### Logging in with specific properties\n\nTODO\n", - }, - ], + "title": "Logging in & out", + "content": "# Logging in & out\n\n## Basics\n### Logging in\n\n1. Go to the DiracX-Web instance homepage. \n - 💡 You should end up on an authentication page.\n2. Authenticate you as a user of a given VO/group:\n - If your instance supports multiple VOs, select your VO in the list box.\n - Select your Group in the list box below.\n3. Click the **Login** button. \n - 💡 You should be redirected to the VO login page.\n4. Enter your credentials (e.g., Username/Password, X509 certificates). \n - 💡 You should see a page asking for permission to access your profile.\n5. Accept the permissions to access your DiracX dashboard. \n - 💡 You should be redirected to the DiracX-Web instance as a logged-in user, and the dashboard should appear.\n\n### Logging out\n\n1. Click on your profile icon in the top-right corner of the dashboard.\n - :bulb: A dropdown menu should appear\n2. Select **Logout** from the dropdown menu.\n \n## Advanced\n### Logging in with specific properties\n\nTODO\n" + } + ] }, { - appName: "Job Monitor", - sections: [ + "appName": "Job Monitor", + "sections": [ { - title: "Manage Your Jobs", - content: - "# Manage Your Jobs\n\n## Status transitions\n\nYou can select one or more jobs by clicking on the checkboxes next to each job. Once jobs are selected, you can perform actions on them using the buttons at the top of the table. The available actions include:\n\n- **Reschedule**: Reschedules the selected jobs.\n- **Kill**: Marks the selected jobs to be killed.\n- **Delete**: Marks the selected jobs for deletion.\n\n**Note**: \n- You can only delete jobs that are already killed. \n- A job cannot typically be rescheduled more than three times.\n\n## View a Job's History\n\nYou can right-click on a job to open its **Job History**. \nThe history shows the different statuses the job has gone through, along with the corresponding dates and the authors of the changes.\n\n", + "title": "Manage Your Jobs", + "content": "# Manage Your Jobs\n\n## Status transitions\n\nYou can select one or more jobs by clicking on the checkboxes next to each job. Once jobs are selected, you can perform actions on them using the buttons at the top of the table. The available actions include:\n\n- **Reschedule**: Reschedules the selected jobs.\n- **Kill**: Marks the selected jobs to be killed.\n- **Delete**: Marks the selected jobs for deletion.\n\n**Note**: \n- You can only delete jobs that are already killed. \n- A job cannot typically be rescheduled more than three times.\n\n## View a Job's History\n\nYou can right-click on a job to open its **Job History**. \nThe history shows the different statuses the job has gone through, along with the corresponding dates and the authors of the changes.\n\n" }, { - title: "The Search Bar", - content: - "# The Search Bar\n\nThe search bar allows you to filter jobs based on various criteria. Filters are represented as equations, where each equation consists of a job attribute, an operator, and a value. The search bar analyzes these equations to evaluate their consistency. A green equation is valid, a yellow equation is incomplete, and a red equation is invalid.\n\nA search is automatically performed when all equations in the search bar are valid.\n\n## Create a Filter\n\nTo create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. \nThe search bar only suggests attributes, operators, and values that are available in your current set of jobs.\n\n## Edit a Filter\n\nTo edit a filter, click on it in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. Press `ESCAPE` to return to the end of the search bar.\n\n## Remove a Filter\n\nTo remove a filter, press the `Backspace` key to remove the last token, or right-click on the equation to remove the entire equation. \nYou can also clear the entire search bar by clicking on the trash can button at the end of the search bar.\n", + "title": "The Search Bar", + "content": "# The Search Bar\n\nThe search bar allows you to filter jobs based on various criteria. Filters are represented as equations, where each equation consists of a job attribute, an operator, and a value. The search bar analyzes these equations to evaluate their consistency. A green equation is valid, a yellow equation is incomplete, and a red equation is invalid.\n\nA search is automatically performed when all equations in the search bar are valid.\n\n## Create a Filter\n\nTo create a filter, click on the search bar and start typing. Suggestions will appear based on the available job attributes. You can select a suggestion to choose the criterion. After that, you can either type or select an operator and a value to filter by. \nThe search bar only suggests attributes, operators, and values that are available in your current set of jobs.\n\n## Edit a Filter\n\nTo edit a filter, click on it in the search bar. You can change the operator or value by clicking on them. You can also use the arrow keys to navigate through the equations and edit them. Press `ESCAPE` to return to the end of the search bar.\n\n## Remove a Filter\n\nTo remove a filter, press the `Backspace` key to remove the last token, or right-click on the equation to remove the entire equation. \nYou can also clear the entire search bar by clicking on the trash can button at the end of the search bar.\n" }, { - title: "The Table", - content: - "# The Table\n\nThe table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date.\n\n## Table display settings\nYou can click on the eye icon to select additional columns to display in the table. Some columns are hidden by default.\n\nYou can sort the table by clicking on the column headers. Clicking once will sort the table in ascending order; clicking again will sort it in descending order.\n\nYou can set the page size by using the `Rows per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page.\n\n## Select a Job\n\nYou can select one or multiple jobs using the checkboxes on the left side of the table. \nOnce you have selected at least one job, you can perform actions on it. You can manage the selected jobs or copy their IDs to your clipboard.\n", - }, - ], - }, - ], + "title": "The Table", + "content": "# The Table\n\nThe table displays the jobs that match the criteria specified in the search bar. Each row represents a job, and the columns show various attributes of the job, such as its ID, status, type, and submission date.\n\n## Table display settings\nYou can click on the eye icon to select additional columns to display in the table. Some columns are hidden by default.\n\nYou can sort the table by clicking on the column headers. Clicking once will sort the table in ascending order; clicking again will sort it in descending order.\n\nYou can set the page size by using the `Rows per page` dropdown at the bottom of the table. This allows you to control how many jobs are displayed per page.\n\n## Select a Job\n\nYou can select one or multiple jobs using the checkboxes on the left side of the table. \nOnce you have selected at least one job, you can perform actions on it. You can manage the selected jobs or copy their IDs to your clipboard.\n" + } + ] + } + ] }; diff --git a/packages/diracx-web-components/stories/Dashboard.stories.tsx b/packages/diracx-web-components/stories/Dashboard.stories.tsx index 3ad71ba5..cdb76f31 100644 --- a/packages/diracx-web-components/stories/Dashboard.stories.tsx +++ b/packages/diracx-web-components/stories/Dashboard.stories.tsx @@ -7,7 +7,7 @@ import { applicationList } from "../src/components/applicationList"; import { DashboardGroup } from "../src/types/DashboardGroup"; import Dashboard from "../src/components/DashboardLayout/Dashboard"; import { ThemeProvider } from "../src/contexts/ThemeProvider"; -import { userDocumentation } from "../src/generatedDocs"; +import { userDocumentation } from "../src/generatedDoc"; const meta = { title: "Dashboard Layout/Dashboard",