From 2f93989d775ec7cc69ed151882d9916b35b6b4b4 Mon Sep 17 00:00:00 2001 From: "cheney.yin" Date: Thu, 23 Feb 2023 13:54:11 +0800 Subject: [PATCH 1/3] Fix. equal. --- metal-ui/src/model/Metal.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/metal-ui/src/model/Metal.ts b/metal-ui/src/model/Metal.ts index 1743f85..a108d0e 100644 --- a/metal-ui/src/model/Metal.ts +++ b/metal-ui/src/model/Metal.ts @@ -52,7 +52,7 @@ export const MetalSink: IMetal = { return false }, canAddInput: (graphTopology: GraphTopology, id: string) => { - return graphTopology.inDegree(id) == 0 + return graphTopology.inDegree(id) === 0 } } @@ -64,7 +64,7 @@ export const MetalMapper: IMetal = { return true }, canAddInput: (graphTopology: GraphTopology, id: string) => { - return graphTopology.inDegree(id) == 0 + return graphTopology.inDegree(id) === 0 } } @@ -100,4 +100,4 @@ export const Metals = { } } } -} \ No newline at end of file +} From 3a726db5877deb61239be79509d9b9e901b4550a Mon Sep 17 00:00:00 2001 From: "cheney.yin" Date: Thu, 23 Feb 2023 15:24:19 +0800 Subject: [PATCH 2/3] Add. metal package page. --- metal-ui/src/features/home/Home.tsx | 4 +- metal-ui/src/features/main/Main.tsx | 57 +++++- .../src/features/project/ProjectProfile.tsx | 7 + .../src/features/repository/MetalRepo.tsx | 186 +++++++++++++++++- 4 files changed, 244 insertions(+), 10 deletions(-) diff --git a/metal-ui/src/features/home/Home.tsx b/metal-ui/src/features/home/Home.tsx index b047285..e67ca98 100644 --- a/metal-ui/src/features/home/Home.tsx +++ b/metal-ui/src/features/home/Home.tsx @@ -59,7 +59,9 @@ export function Home(props: HomeProps) { }; const onOpenMetalRepo = () => { - mainHandler.openMetalRepo({}); + mainHandler.openMetalRepo({ + mainHandler: mainHandler + }); }; const onOpenUserPage = () => { diff --git a/metal-ui/src/features/main/Main.tsx b/metal-ui/src/features/main/Main.tsx index 5bcc2b6..51c901a 100644 --- a/metal-ui/src/features/main/Main.tsx +++ b/metal-ui/src/features/main/Main.tsx @@ -15,12 +15,12 @@ import { Skeleton } from "@mui/material"; import { AiOutlineDeploymentUnit } from "react-icons/ai"; import { FaProjectDiagram } from "react-icons/fa"; import { RiFunctionLine } from "react-icons/ri"; -import { VscAccount, VscBrowser, VscCircuitBoard, VscExtensions, VscHome, VscPreview } from "react-icons/vsc"; +import { VscAccount, VscBrowser, VscCircuitBoard, VscExtensions, VscHome, VscPackage, VscPreview } from "react-icons/vsc"; import { GrTasks } from "react-icons/gr"; import { ProjectStarter, ProjectStarterProps } from "../project/ProjectStarter"; import { DesignerProvider } from "../designer/DesignerProvider"; import { Home, HomeProps } from "../home/Home"; -import { MetalRepo, MetalRepoProps } from "../repository/MetalRepo"; +import { MetalPkgPage, MetalPkgPageProps, MetalRepo, MetalRepoProps } from "../repository/MetalRepo"; import create from "zustand"; import { subscribeWithSelector } from "zustand/middleware"; import _ from "lodash"; @@ -28,6 +28,7 @@ import { Executions, ExecutionsProps } from "../execution/Executions"; import { Viewer, ViewerProps } from "../designer/Viewer"; import { ExecutionPage, ExecutionPageProps } from "../execution/ExecutionPage"; import { UserPage, UserPageProps } from "../user/UserPage"; +import { MetalPkgProps } from "../designer/explorer/MetalExplorer"; interface Component { id: string, @@ -85,6 +86,8 @@ function iconFatory(node: TabNode) { return ; case "metalRepoIcon": return ; + case "metalPkgPageIcon": + return ; case "deploymentIcon": return ; case "executionPageIcon": @@ -111,11 +114,16 @@ export function execPageId(id: string) { return `exec[${id}]`; } +export function metalPkgPageId(id: string) { + return `metal pkg[${id}]`; +} + export interface MainHandler { openProjectStarter: (props: ProjectStarterProps) => void; openDesigner: (props: DesignerProps) => void; openViewer: (props: ViewerProps) => void; openMetalRepo: (props: MetalRepoProps) => void; + openMetalPkgPage: (props: MetalPkgPageProps) => void; openExecutionPage: (props: ExecutionPageProps) => void; openUserPage: (props: UserPageProps) => void; select: (id: string) => void; @@ -346,6 +354,35 @@ export function Main() { } }; + const openMetalPkgPage = (props: MetalPkgPageProps) => { + const {id} = props.pkg; + const tab: IJsonTabNode = { + type: "tab", + id: metalPkgPageId(id), + name: `Metal[${props.pkg.class}]`, + icon: "metalPkgPageIcon", + component: "metalPkgPage", + config: props, + } + + const action: Action = Actions.addNode( + tab, + "main", + DockLocation.CENTER, + 1 + ); + try{ + layoutModel.doAction(action); + }catch (error) { + console.error(error); + if ( + (error as Error).message.startsWith('Error: each node must have a unique id') && + tab.id !== undefined) { + select(tab.id); + } + } + }; + const close = (id: string) => { @@ -407,6 +444,7 @@ export function Main() { openDesigner: openDesigner, openViewer: openViewer, openMetalRepo: openMetalRepo, + openMetalPkgPage: openMetalPkgPage, openExecutionPage: openExecutionPage, openUserPage: openUserPage, select: select, @@ -460,12 +498,25 @@ export function Main() { } case "metalRepo": { - const props: MetalRepoProps = config; + const props: MetalRepoProps = { + ...config, + mainHandler: mainHandler + }; return memorizeCmps(component, props, ()=>( ), id); } + case "metalPkgPage": { + const props: MetalPkgPageProps = { + ...config, + mainHandler: mainHandler + }; + return memorizeCmps(component, props, ()=>( + + ), id); + } + case "executionPage": { const props: ExecutionPageProps = { ...config, diff --git a/metal-ui/src/features/project/ProjectProfile.tsx b/metal-ui/src/features/project/ProjectProfile.tsx index 0ef7ad6..17e6eba 100644 --- a/metal-ui/src/features/project/ProjectProfile.tsx +++ b/metal-ui/src/features/project/ProjectProfile.tsx @@ -462,6 +462,12 @@ export function BackendArgsProfile(props: BackendArgsProfileProps) { type: "string", }, }; + const uiSchema = { + items: { + 'ui:widget': 'textarea', + 'ui:description': 'Item should be \'{string}\'. And " in {string} should be escape by \\.' + } + } const onSubmit = (data: IChangeEvent) => { const newProfile: string[] = data.formData; @@ -483,6 +489,7 @@ export function BackendArgsProfile(props: BackendArgsProfileProps) {
diff --git a/metal-ui/src/features/repository/MetalRepo.tsx b/metal-ui/src/features/repository/MetalRepo.tsx index 8d89293..243e6a4 100644 --- a/metal-ui/src/features/repository/MetalRepo.tsx +++ b/metal-ui/src/features/repository/MetalRepo.tsx @@ -3,21 +3,26 @@ import { AccordionDetails, AccordionSummary, Alert, + Chip, Divider, FormControl, + Grid, + IconButton, InputLabel, MenuItem, + Paper, Select, SelectChangeEvent, Snackbar, + Stack, Typography, } from "@mui/material"; import { LoadingButton } from "@mui/lab"; -import { DataGrid, GridColDef } from "@mui/x-data-grid"; +import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import Editor, { Monaco } from "@monaco-editor/react"; import * as EditorApi from "monaco-editor/esm/vs/editor/editor.api"; import { useCallback, useEffect, useRef, useState } from "react"; -import { VscChevronDown, VscCloudUpload } from "react-icons/vsc"; +import { VscBrowser, VscChevronDown, VscCloudUpload } from "react-icons/vsc"; import { useAsync } from "../../api/Hooks"; import { addMetalPkgsFromManifest, getAllMetalPkgsOfUserAccess } from "../../api/MetalPkgApi"; import { useAppSelector } from "../../app/hooks"; @@ -27,9 +32,16 @@ import { Mutable } from "../../model/Mutable"; import { State } from "../../api/State"; import { Logger, loggerSelector, useNotice } from "../notice/Notice"; import shallow from 'zustand/shallow'; -export interface MetalRepoProps {} +import { MainHandler } from "../main/Main"; +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism"; +import moment from "moment"; +export interface MetalRepoProps { + mainHandler: MainHandler; +} export function MetalRepo(props: MetalRepoProps) { + const {mainHandler} = props; const token: string | null = useAppSelector((state) => { return tokenSelector(state); }); @@ -44,14 +56,150 @@ export function MetalRepo(props: MetalRepoProps) { paddingBottom: "1vh", }} > - + ); } +export interface MetalPkgPageProps { + pkg: MetalPkg, + mainHandler: MainHandler +} + +export function MetalPkgPage(props: MetalPkgPageProps) { + const { pkg } = props; + const { id } = pkg; + return ( +
+ + {`${pkg.type} [${id}]`} + + + + + + {"Class"} + + + + + + {"Package"} + + + + + + + + + + {"Scope"} + + + {pkg.scope} + + + {"Create Time"} + + + {moment(pkg.createTime).format("YYYY-MM-DD HH:mm:ss")} + + + {"Publisher"} + + + {pkg.userId} + + + {"Description"} + + + {pkg.description} + + + {"Form Schema"} + + +
+
+ + {JSON.stringify(pkg.formSchema, null, 2)} + +
+
+
+ + {"UI Schema"} + + +
+
+ + {JSON.stringify(pkg.uiSchema, null, 2)} + +
+
+
+
+
+
+ ); +} + interface MetalRepoViewerProps { token: string | null; + mainHandler: MainHandler } const columns: GridColDef[] = [ @@ -61,6 +209,21 @@ const columns: GridColDef[] = [ { field: "groupId", headerName: "Group ID", filterable: true, minWidth: 150 }, { field: "artifactId", headerName: "Artifact ID", filterable: true, minWidth: 200 }, { field: "version", headerName: "Version", filterable: true, minWidth: 150 }, + { + field: "action", + headerName: "Action", + filterable: false, + minWidth: 150, + renderCell: (params: GridRenderCellParams<()=>void>) => { + return ( + + + + ) + }, + } ]; function useMetalPkgs(token: string | null) { @@ -75,8 +238,19 @@ function useMetalPkgs(token: string | null) { } function MetalRepoViewer(props: MetalRepoViewerProps) { - const { token } = props; + const { token, mainHandler } = props; const pkgs: MetalPkg[] | null = useMetalPkgs(token); + const pkgsWithAciton = pkgs === null + ? [] + : pkgs.map(pkg => ({ + ...pkg, + action: () => { + mainHandler.openMetalPkgPage({ + pkg: pkg, + mainHandler: mainHandler + }) + } + })) return ( @@ -98,7 +272,7 @@ function MetalRepoViewer(props: MetalRepoViewerProps) { > Date: Fri, 3 Mar 2023 13:15:25 +0800 Subject: [PATCH 3/3] Add. calendar heatmap. --- metal-ui/package-lock.json | 756 +++++++++++++++++- metal-ui/package.json | 2 + metal-ui/src/App.css | 2 + metal-ui/src/api/ProjectApi.ts | 2 +- metal-ui/src/api/UserApi.ts | 5 +- metal-ui/src/features/designer/MetalView.tsx | 2 +- .../features/designer/backend/BackendBar.tsx | 2 +- metal-ui/src/features/home/Home.tsx | 121 ++- metal-ui/src/features/ui/ResizeBackdrop.tsx | 2 +- metal-ui/src/index.css | 3 +- 10 files changed, 844 insertions(+), 53 deletions(-) diff --git a/metal-ui/package-lock.json b/metal-ui/package-lock.json index 5d3607e..0b65bea 100644 --- a/metal-ui/package-lock.json +++ b/metal-ui/package-lock.json @@ -30,6 +30,7 @@ "@types/react-dom": "^18.0.8", "ajv": "^8.11.2", "axios": "^1.1.3", + "cal-heatmap": "^4.1.0", "elkjs": "^0.8.2", "flexlayout-react": "^0.7.5", "http-proxy-middleware": "^2.0.6", @@ -48,6 +49,7 @@ "web-vitals": "^2.1.4" }, "devDependencies": { + "@types/lodash-es": "^4.17.6", "@types/react-syntax-highlighter": "^15.5.5", "@types/uuid": "^8.3.4" } @@ -3448,35 +3450,11 @@ } } }, - "node_modules/@mui/material/node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "node_modules/@mui/material/node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, - "node_modules/@mui/material/node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, "node_modules/@mui/private-theming": { "version": "5.11.1", "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.1.tgz", @@ -3698,6 +3676,19 @@ "node": ">= 8" } }, + "node_modules/@observablehq/plot": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.4.tgz", + "integrity": "sha512-1UQJAPKmpWb8kfJDfag2/1kvUiehJISwnbFkKUOnHokuhmjxGrVpbj+YKJBrEOBS1wK8C5VDIxJK1SSMso3fUg==", + "dependencies": { + "d3": "^7.8.0", + "interval-tree-1d": "^1.0.0", + "isoformat": "^0.2.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.8.tgz", @@ -4895,6 +4886,15 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.187.tgz", "integrity": "sha512-MrO/xLXCaUgZy3y96C/iOsaIqZSeupyTImKClHunL5GrmaiII2VwvWmLBu2hwa0Kp0sV19CsyjtrTc/Fx8rg/A==" }, + "node_modules/@types/lodash-es": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.6.tgz", + "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -6232,6 +6232,11 @@ "node": ">=8" } }, + "node_modules/binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -6392,6 +6397,27 @@ "node": ">= 0.8" } }, + "node_modules/cal-heatmap": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cal-heatmap/-/cal-heatmap-4.1.0.tgz", + "integrity": "sha512-viwIR2/j0FcjmYDR0HndtUV7vey1EaTNrv8WJsaEApYxxhjsjmywf3U5tZYnVk0gp4vng4nUWboRKJss4EHw0Q==", + "dependencies": { + "@observablehq/plot": "^0.6.0", + "@popperjs/core": "^2.11.6", + "d3-color": "^3.1.0", + "d3-fetch": "^3.0.1", + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1", + "dayjs": "^1.11.7", + "eventemitter3": "^5.0.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/cal-heatmap/node_modules/eventemitter3": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.0.tgz", + "integrity": "sha512-riuVbElZZNXLeLEoprfNYoDSwTBRR44X3mnhdI1YcnENpWTCsTTVZ2zFuqQcpoyqPQIUXdiPEU0ECAq0KQRaHg==" + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -7310,6 +7336,91 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" }, + "node_modules/d3": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.2.tgz", + "integrity": "sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ==", + "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.2", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==", + "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==", + "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==", + "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==", + "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", @@ -7318,6 +7429,28 @@ "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==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz", + "integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==", + "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", @@ -7338,6 +7471,38 @@ "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==", + "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==", + "engines": { + "node": ">= 10" + } + }, "node_modules/d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", @@ -7346,6 +7511,57 @@ "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==", + "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==", + "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==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "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==", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-interpolate": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", @@ -7357,6 +7573,65 @@ "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==", + "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==", + "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==", + "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==", + "engines": { + "node": ">=12" + } + }, + "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==", + "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.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "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", @@ -7365,6 +7640,39 @@ "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==", + "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==", + "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==", + "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", @@ -7424,6 +7732,11 @@ "node": ">=10" } }, + "node_modules/dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -7535,6 +7848,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "^3.0.0" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7687,6 +8008,15 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -10137,6 +10467,22 @@ "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==", + "engines": { + "node": ">=12" + } + }, + "node_modules/interval-tree-1d": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.4.tgz", + "integrity": "sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==", + "dependencies": { + "binary-search-bounds": "^2.0.0" + } + }, "node_modules/ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -10569,6 +10915,11 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/isoformat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/isoformat/-/isoformat-0.2.1.tgz", + "integrity": "sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==" + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -15644,6 +15995,21 @@ "react": ">= 0.14.0" } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/reactflow": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.2.0.tgz", @@ -16029,6 +16395,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, "node_modules/rollup": { "version": "2.79.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", @@ -16119,6 +16490,11 @@ "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==" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -20832,30 +21208,10 @@ "react-transition-group": "^4.4.5" }, "dependencies": { - "dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "requires": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, - "react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "requires": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - } } } }, @@ -20979,6 +21335,16 @@ "fastq": "^1.6.0" } }, + "@observablehq/plot": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.4.tgz", + "integrity": "sha512-1UQJAPKmpWb8kfJDfag2/1kvUiehJISwnbFkKUOnHokuhmjxGrVpbj+YKJBrEOBS1wK8C5VDIxJK1SSMso3fUg==", + "requires": { + "d3": "^7.8.0", + "interval-tree-1d": "^1.0.0", + "isoformat": "^0.2.0" + } + }, "@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.8.tgz", @@ -21897,6 +22263,15 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.187.tgz", "integrity": "sha512-MrO/xLXCaUgZy3y96C/iOsaIqZSeupyTImKClHunL5GrmaiII2VwvWmLBu2hwa0Kp0sV19CsyjtrTc/Fx8rg/A==" }, + "@types/lodash-es": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.6.tgz", + "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, "@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -22917,6 +23292,11 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, + "binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -23041,6 +23421,29 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" }, + "cal-heatmap": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cal-heatmap/-/cal-heatmap-4.1.0.tgz", + "integrity": "sha512-viwIR2/j0FcjmYDR0HndtUV7vey1EaTNrv8WJsaEApYxxhjsjmywf3U5tZYnVk0gp4vng4nUWboRKJss4EHw0Q==", + "requires": { + "@observablehq/plot": "^0.6.0", + "@popperjs/core": "^2.11.6", + "d3-color": "^3.1.0", + "d3-fetch": "^3.0.1", + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1", + "dayjs": "^1.11.7", + "eventemitter3": "^5.0.0", + "lodash-es": "^4.17.21" + }, + "dependencies": { + "eventemitter3": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.0.tgz", + "integrity": "sha512-riuVbElZZNXLeLEoprfNYoDSwTBRR44X3mnhdI1YcnENpWTCsTTVZ2zFuqQcpoyqPQIUXdiPEU0ECAq0KQRaHg==" + } + } + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -23698,11 +24101,97 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" }, + "d3": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.2.tgz", + "integrity": "sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ==", + "requires": { + "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" + } + }, + "d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==", + "requires": { + "internmap": "1 - 2" + } + }, + "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==" + }, + "d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + } + }, + "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==", + "requires": { + "d3-path": "1 - 3" + } + }, "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==" }, + "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==", + "requires": { + "d3-array": "^3.2.0" + } + }, + "d3-delaunay": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz", + "integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==", + "requires": { + "delaunator": "5" + } + }, "d3-dispatch": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", @@ -23717,11 +24206,64 @@ "d3-selection": "3" } }, + "d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "requires": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + } + } + }, "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==" }, + "d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "requires": { + "d3-dsv": "1 - 3" + } + }, + "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==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "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==" + }, + "d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "requires": { + "d3-array": "2.5.0 - 3" + } + }, + "d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==" + }, "d3-interpolate": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", @@ -23730,11 +24272,76 @@ "d3-color": "1 - 3" } }, + "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==" + }, + "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==" + }, + "d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==" + }, + "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==" + }, + "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==", + "requires": { + "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" + } + }, + "d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "requires": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + } + }, "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==" }, + "d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "requires": { + "d3-path": "^3.1.0" + } + }, + "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==", + "requires": { + "d3-array": "2 - 3" + } + }, + "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==", + "requires": { + "d3-time": "1 - 3" + } + }, "d3-timer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", @@ -23779,6 +24386,11 @@ "whatwg-url": "^8.0.0" } }, + "dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -23863,6 +24475,14 @@ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==" }, + "delaunator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "requires": { + "robust-predicates": "^3.0.0" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -23979,6 +24599,15 @@ "utila": "~0.4" } }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -25770,6 +26399,19 @@ "side-channel": "^1.0.4" } }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, + "interval-tree-1d": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.4.tgz", + "integrity": "sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==", + "requires": { + "binary-search-bounds": "^2.0.0" + } + }, "ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -26045,6 +26687,11 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "isoformat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/isoformat/-/isoformat-0.2.1.tgz", + "integrity": "sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==" + }, "istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -29550,6 +30197,17 @@ "refractor": "^3.6.0" } }, + "react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, "reactflow": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.2.0.tgz", @@ -29830,6 +30488,11 @@ "glob": "^7.1.3" } }, + "robust-predicates": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz", + "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==" + }, "rollup": { "version": "2.79.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", @@ -29890,6 +30553,11 @@ "queue-microtask": "^1.2.2" } }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", diff --git a/metal-ui/package.json b/metal-ui/package.json index 66b4866..7516841 100644 --- a/metal-ui/package.json +++ b/metal-ui/package.json @@ -25,6 +25,7 @@ "@types/react-dom": "^18.0.8", "ajv": "^8.11.2", "axios": "^1.1.3", + "cal-heatmap": "^4.1.0", "elkjs": "^0.8.2", "flexlayout-react": "^0.7.5", "http-proxy-middleware": "^2.0.6", @@ -67,6 +68,7 @@ ] }, "devDependencies": { + "@types/lodash-es": "^4.17.6", "@types/react-syntax-highlighter": "^15.5.5", "@types/uuid": "^8.3.4" } diff --git a/metal-ui/src/App.css b/metal-ui/src/App.css index f4199c8..5fdd075 100644 --- a/metal-ui/src/App.css +++ b/metal-ui/src/App.css @@ -1,4 +1,5 @@ @import "flexlayout-react/style/underline.css"; +@import 'cal-heatmap/cal-heatmap.css'; .App { left: 0px; @@ -18,3 +19,4 @@ box-sizing: border-box; overflow: hidden; } + diff --git a/metal-ui/src/api/ProjectApi.ts b/metal-ui/src/api/ProjectApi.ts index b63aafd..56d8fb7 100644 --- a/metal-ui/src/api/ProjectApi.ts +++ b/metal-ui/src/api/ProjectApi.ts @@ -1,4 +1,4 @@ -import axios, { AxiosError } from "axios"; +import axios from "axios"; import {ApiResponse, ApiResponseEntity, timeout} from "./APIs"; import {BackendStatus, Deploy, Project} from "../model/Project"; import _ from "lodash" diff --git a/metal-ui/src/api/UserApi.ts b/metal-ui/src/api/UserApi.ts index c590554..3b8c85e 100644 --- a/metal-ui/src/api/UserApi.ts +++ b/metal-ui/src/api/UserApi.ts @@ -1,5 +1,5 @@ import axios, {AxiosBasicCredentials} from "axios"; -import {ApiResponse, ApiResponseEntity, ApiResponseStatus, timeout} from "./APIs"; +import {ApiResponse, ApiResponseEntity, timeout} from "./APIs"; import {User} from "../model/User"; const instance = axios.create({ @@ -38,10 +38,9 @@ export async function sync(token: string): Promise { const user: User = resp.data return user } else { - if (resp.msg == undefined) { + if (resp.msg === undefined) { throw new Error('Response is failure, and no msg found in response.') } - const msg: string = resp.msg throw new Error(resp.msg) } } catch (err) { diff --git a/metal-ui/src/features/designer/MetalView.tsx b/metal-ui/src/features/designer/MetalView.tsx index e69004b..4e5af43 100644 --- a/metal-ui/src/features/designer/MetalView.tsx +++ b/metal-ui/src/features/designer/MetalView.tsx @@ -510,7 +510,7 @@ export function MetalNode(props: NodeProps) { ), - [badgeContent, isInputReady, isReadOnly, metal.id, metal.name, metal.props, metalPkg.class, msg, nodeView, onDelete, onEdit, props.data, status] + [badgeContent, isInputReady, isPropDefined, isReadOnly, metal.id, metal.name, metalPkg.class, msg, nodeView, onDelete, onEdit, props.data, status] ); return (<>{view}) diff --git a/metal-ui/src/features/designer/backend/BackendBar.tsx b/metal-ui/src/features/designer/backend/BackendBar.tsx index 5e9f805..da48576 100644 --- a/metal-ui/src/features/designer/backend/BackendBar.tsx +++ b/metal-ui/src/features/designer/backend/BackendBar.tsx @@ -405,7 +405,7 @@ function BackendStatusBrief() { startIcon={icon} sx={{ borderRadius: "0px", - width: "15vw", + width: "20vw", }} > {tip} diff --git a/metal-ui/src/features/home/Home.tsx b/metal-ui/src/features/home/Home.tsx index e67ca98..95e46b3 100644 --- a/metal-ui/src/features/home/Home.tsx +++ b/metal-ui/src/features/home/Home.tsx @@ -27,13 +27,24 @@ import { FaStop } from "react-icons/fa"; import { ImDownload, ImUpload } from "react-icons/im"; import { AiOutlineFunction } from "react-icons/ai"; import { useAsync } from "../../api/Hooks"; -import { useEffect, useRef } from "react"; +import { useCallback, useEffect, useRef } from "react"; import { BackendState, Project } from "../../model/Project"; import { getAllProjectOfUser } from "../../api/ProjectApi"; import { MetalPkg } from "../../model/MetalPkg"; import { metalType, MetalTypes } from "../../model/Metal"; import { getAllMetalPkgsOfUserAccess } from "../../api/MetalPkgApi"; import { MainHandler } from "../main/Main"; +import { useUIAsync } from "../ui/UIHooks"; +import { Exec } from "../../model/Exec"; +import { getAllExecsOfUser } from "../../api/ExecApi"; +import moment from "moment"; +import _ from "lodash"; +import { State } from "../../api/State"; +import CalHeatmap from 'cal-heatmap'; + + +import { OptionsType } from "cal-heatmap/src/options/Options"; + export interface HomeProps { mainHandler: MainHandler; @@ -109,12 +120,120 @@ export function Home(props: HomeProps) { + ); } +interface ExecutionSummaryProps { + token: string | null +} + +function useExecutionSummary(token: string | null): [ + () => void, + {date: string, value: number}[] +] { + const [run, status, result] = useUIAsync(); + const fetch = useCallback(()=>{ + if (token === null) { + return + } + + run(getAllExecsOfUser(token)); + }, [run, token]); + + const summary = result === null + ? [] + : _.entries( + _.countBy( + result, exec => moment(exec?.createTime).format("YYYY-MM-DD") + ) + ).map(e => ({date: e[0], value: e[1]})) ; + + useEffect(() => { + if (status === State.idle) { + fetch(); + } + }, [fetch, status]); + + return [fetch, summary]; +} + +function ExecutionSummary(props: ExecutionSummaryProps) { + const { token } = props; + const [, summary] = useExecutionSummary(token); + const start = moment().subtract(12, "month").format("YYYY-MM-DD"); + return ( + + }> + Executions + + + + ( + value + ) + }} + date={{ + start: new Date(start) + }} + scale={{ + color: { + range: ['yellow', 'red'], + interpolate: 'hsl', + type: 'linear', + domain: [0, 30] + } + }} + /> + + + ); +} + +declare type HeatmapProps = CalHeatmap.DeepPartial; + +function Heatmap(props: HeatmapProps) { + + useEffect(()=>{ + const cal: CalHeatmap = new CalHeatmap(); + + cal.paint({ + ...props, + itemSelector: '#heat-map' + }); + + return () => { + cal.destroy(); + } + }, [props]); + + return ( +
+ +
+ ) +} + + + const ICON_SIZE = "4vw"; const CARD_H_PAD = "2vw"; const CARD_V_PAD = "2vh"; diff --git a/metal-ui/src/features/ui/ResizeBackdrop.tsx b/metal-ui/src/features/ui/ResizeBackdrop.tsx index 549bcdb..f9b6093 100644 --- a/metal-ui/src/features/ui/ResizeBackdrop.tsx +++ b/metal-ui/src/features/ui/ResizeBackdrop.tsx @@ -1,5 +1,5 @@ -import { ReactNode, useCallback, useEffect, useRef, useState } from "react"; +import { ReactNode } from "react"; export interface PendingBackdropSize { width: number; diff --git a/metal-ui/src/index.css b/metal-ui/src/index.css index 51ae945..8e8cf92 100644 --- a/metal-ui/src/index.css +++ b/metal-ui/src/index.css @@ -83,4 +83,5 @@ code { .react-flow .react-flow__edge path, .react-flow__connectionline path { stroke-width: 2; -} \ No newline at end of file +} +