From 26e06adefc8ff7486bf813dcae45b0fa43b8f482 Mon Sep 17 00:00:00 2001 From: Wishrem <97738578+Wishrem@users.noreply.github.com> Date: Wed, 10 Jan 2024 18:41:18 +0800 Subject: [PATCH] style & feat: new UI components & automatically re-watch (#4433) * feat: Replaced mobx with zustand * fix: displayed wrong time and info * fix: The content of badge overflow * style: Collected theme and added dumpKubeObject function * feat: Ingress & Secret resource * fix: errors in using next build * feat: Events overview and new UI components * feat: kubeconfig parser * feat: KubePanel v1.0.0 * fix: merge conflict * fix: Add clear logo and icon * fix: Fixed Sider * feat: Auto deploy * fix: Wrong margin-left in Content due to fixed style Sider * fix: tailwind css conflict with antd * style: clean codes * feat: styled monaco editor * style: change ui style * style: make new style for create resource modal * style: change file location * style: action button and delete popconfirm * fix: import error * style: clean packages * feat: automatically watch * feat: table pagination * feat: resource filter triggered by name * style: reposition components to fix next build problems * feat: automatically re-watch --- frontend/plugins/kubepanel/package.json | 5 +- frontend/plugins/kubepanel/pnpm-lock.yaml | 425 ++++++++++-------- frontend/plugins/kubepanel/postcss.config.js | 6 + .../common/action/action-button.tsx | 56 +++ .../common/action/create-resource-modal.tsx | 143 ++++++ .../common/action/delete-popconfirm.tsx | 61 +++ .../src/components/common/action/toggle.tsx | 112 +++++ .../common/action}/update-editor-modal.tsx | 26 +- .../common}/drawer/drawer-collapse.tsx | 6 +- .../common}/drawer/drawer-item.tsx | 4 +- .../common}/drawer/drawer-panel.tsx | 6 +- .../common}/drawer/drawer-title.tsx | 4 +- .../common}/drawer/drawer.tsx | 6 +- .../src/components/common/editor/styled.tsx | 9 + .../common/panel-table/pagination.tsx | 97 ++++ .../common/panel-table/search-filter.tsx | 123 +++++ .../common}/panel-table/table.tsx | 62 +-- .../common}/sidebar/sidebar.tsx | 4 +- .../src/components/common/title/title.tsx | 11 +- .../detail/kube-object-detail-info-list.tsx | 2 +- .../plugins/kubepanel/src/constants/theme.ts | 53 ++- .../kubepanel/src/hooks/useWatcher.tsx | 52 +++ frontend/plugins/kubepanel/src/pages/_app.tsx | 10 + .../src/pages/api/kubernetes/watch.ts | 2 +- .../action-button/action-button.tsx | 70 --- .../action-button/delete-waring-modal.tsx | 85 ---- .../modal/create-resource-modal.tsx | 193 -------- .../kubepanel/src/pages/kubepanel/index.tsx | 22 +- .../config/config-map/config-map-detail.tsx | 4 +- .../config/config-map/config-map.tsx | 10 +- .../config/secret/secret-detail.tsx | 4 +- .../kube-object/config/secret/secret.tsx | 10 +- .../network/ingress/ingress-detail.tsx | 6 +- .../kube-object/network/ingress/ingress.tsx | 10 +- .../volume-claim/volume-claim-detail.tsx | 6 +- .../storage/volume-claim/volume-claim.tsx | 20 +- .../workload/deployment/deployment-detail.tsx | 6 +- .../workload/deployment/deployment.tsx | 10 +- .../workload/overview/event-overview.tsx | 24 +- .../workload/overview/overview.tsx | 32 +- .../workload/overview/status-chart.tsx | 0 .../workload/overview/status-overview.tsx | 0 .../workload/pod/container-detail.tsx | 4 +- .../workload/pod/container-status-brick.tsx | 0 .../workload/pod/container-status.tsx | 0 .../workload/pod/pod-detail-affinities.tsx | 2 +- .../workload/pod/pod-detail-statuses.tsx | 0 .../workload/pod/pod-detail-tolerations.tsx | 2 +- .../kube-object/workload/pod/pod-detail.tsx | 6 +- .../kube-object/workload/pod/pod-status.tsx | 0 .../kube-object/workload/pod/pod.tsx | 10 +- .../statefulset/statefulset-detail.tsx | 21 +- .../workload/statefulset/statefulset.tsx | 22 +- .../kubepanel/{components => }/layout.tsx | 2 +- .../kubepanel/src/store/k8s/kube.store.ts | 23 +- .../plugins/kubepanel/src/styles/globals.css | 36 ++ .../plugins/kubepanel/src/utils/pie-chart.ts | 2 +- 57 files changed, 1150 insertions(+), 777 deletions(-) create mode 100644 frontend/plugins/kubepanel/src/components/common/action/action-button.tsx create mode 100644 frontend/plugins/kubepanel/src/components/common/action/create-resource-modal.tsx create mode 100644 frontend/plugins/kubepanel/src/components/common/action/delete-popconfirm.tsx create mode 100644 frontend/plugins/kubepanel/src/components/common/action/toggle.tsx rename frontend/plugins/kubepanel/src/{pages/kubepanel/components/action-button => components/common/action}/update-editor-modal.tsx (83%) rename frontend/plugins/kubepanel/src/{pages/kubepanel/components => components/common}/drawer/drawer-collapse.tsx (74%) rename frontend/plugins/kubepanel/src/{pages/kubepanel/components => components/common}/drawer/drawer-item.tsx (82%) rename frontend/plugins/kubepanel/src/{pages/kubepanel/components => components/common}/drawer/drawer-panel.tsx (72%) rename frontend/plugins/kubepanel/src/{pages/kubepanel/components => components/common}/drawer/drawer-title.tsx (68%) rename frontend/plugins/kubepanel/src/{pages/kubepanel/components => components/common}/drawer/drawer.tsx (82%) create mode 100644 frontend/plugins/kubepanel/src/components/common/editor/styled.tsx create mode 100644 frontend/plugins/kubepanel/src/components/common/panel-table/pagination.tsx create mode 100644 frontend/plugins/kubepanel/src/components/common/panel-table/search-filter.tsx rename frontend/plugins/kubepanel/src/{pages/kubepanel/components => components/common}/panel-table/table.tsx (53%) rename frontend/plugins/kubepanel/src/{pages/kubepanel/components => components/common}/sidebar/sidebar.tsx (96%) create mode 100644 frontend/plugins/kubepanel/src/hooks/useWatcher.tsx delete mode 100644 frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/action-button.tsx delete mode 100644 frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/delete-waring-modal.tsx delete mode 100644 frontend/plugins/kubepanel/src/pages/kubepanel/components/modal/create-resource-modal.tsx rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/config/config-map/config-map-detail.tsx (90%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/config/config-map/config-map.tsx (83%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/config/secret/secret-detail.tsx (96%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/config/secret/secret.tsx (85%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/network/ingress/ingress-detail.tsx (93%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/network/ingress/ingress.tsx (89%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/storage/volume-claim/volume-claim-detail.tsx (91%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/storage/volume-claim/volume-claim.tsx (83%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/deployment/deployment-detail.tsx (92%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/deployment/deployment.tsx (88%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/overview/event-overview.tsx (81%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/overview/overview.tsx (59%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/overview/status-chart.tsx (100%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/overview/status-overview.tsx (100%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/container-detail.tsx (96%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/container-status-brick.tsx (100%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/container-status.tsx (100%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/pod-detail-affinities.tsx (90%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/pod-detail-statuses.tsx (100%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/pod-detail-tolerations.tsx (90%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/pod-detail.tsx (94%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/pod-status.tsx (100%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/pod/pod.tsx (92%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/statefulset/statefulset-detail.tsx (72%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/kube-object/workload/statefulset/statefulset.tsx (71%) rename frontend/plugins/kubepanel/src/pages/kubepanel/{components => }/layout.tsx (94%) diff --git a/frontend/plugins/kubepanel/package.json b/frontend/plugins/kubepanel/package.json index ca16815a9a5..9d05690be78 100644 --- a/frontend/plugins/kubepanel/package.json +++ b/frontend/plugins/kubepanel/package.json @@ -12,16 +12,14 @@ }, "dependencies": { "@ant-design/charts": "^1.4.2", - "@ant-design/colors": "^7.0.0", "@ant-design/cssinjs": "^1.17.2", "@ant-design/icons": "^5.2.6", "@ant-design/plots": "^1.2.5", "@chakra-ui/react": "^2.8.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@kubernetes/client-node": "^0.19.0", "@monaco-editor/react": "^4.6.0", - "antd": "^5.11.0", + "antd": "^5.12.0", "auto-bind": "^5.0.1", "axios": "^1.5.1", "byline": "^5.0.0", @@ -64,6 +62,7 @@ "eslint-plugin-xss": "^0.1.12", "monaco-editor": "^0.44.0", "postcss": "^8.4.31", + "postcss-nesting": "^12.0.1", "tailwindcss": "^3.3.4", "typescript": "^5" } diff --git a/frontend/plugins/kubepanel/pnpm-lock.yaml b/frontend/plugins/kubepanel/pnpm-lock.yaml index 2070e75824b..cd2bab47e19 100644 --- a/frontend/plugins/kubepanel/pnpm-lock.yaml +++ b/frontend/plugins/kubepanel/pnpm-lock.yaml @@ -10,10 +10,7 @@ importers: dependencies: '@ant-design/charts': specifier: ^1.4.2 - version: 1.4.2(@ant-design/icons@5.2.6)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) - '@ant-design/colors': - specifier: ^7.0.0 - version: 7.0.0 + version: 1.4.2(@ant-design/icons@5.2.6)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) '@ant-design/cssinjs': specifier: ^1.17.2 version: 1.17.2(react-dom@18.2.0)(react@18.2.0) @@ -32,15 +29,12 @@ importers: '@emotion/styled': specifier: ^11.11.0 version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.37)(react@18.2.0) - '@kubernetes/client-node': - specifier: ^0.19.0 - version: 0.19.0 '@monaco-editor/react': specifier: ^4.6.0 version: 4.6.0(monaco-editor@0.44.0)(react-dom@18.2.0)(react@18.2.0) antd: - specifier: ^5.11.0 - version: 5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) + specifier: ^5.12.0 + version: 5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) auto-bind: specifier: ^5.0.1 version: 5.0.1 @@ -162,6 +156,9 @@ importers: postcss: specifier: ^8.4.31 version: 8.4.31 + postcss-nesting: + specifier: ^12.0.1 + version: 12.0.1(postcss@8.4.31) tailwindcss: specifier: ^3.3.4 version: 3.3.4 @@ -234,7 +231,7 @@ packages: resolution: {integrity: sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==} dev: false - /@ant-design/charts@1.4.2(@ant-design/icons@5.2.6)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): + /@ant-design/charts@1.4.2(@ant-design/icons@5.2.6)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-BcVx6AAnwxSdzAVUZReSuvUVtnT5AkJivq3wmcYj17scll26HHficg35yimGskAj3Gu1upYjBQBz6Tk7GEMJsQ==} peerDependencies: '@ant-design/icons': ^4.6.0 @@ -243,12 +240,12 @@ packages: react: '>=16.8.4' react-dom: '>=16.8.4' dependencies: - '@ant-design/flowchart': 1.2.2(@ant-design/icons@5.2.6)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) + '@ant-design/flowchart': 1.2.2(@ant-design/icons@5.2.6)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) '@ant-design/graphs': 1.4.0(react-dom@18.2.0)(react@18.2.0) '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) '@ant-design/maps': 1.0.7(react-dom@18.2.0)(react@18.2.0) '@ant-design/plots': 1.2.5(react-dom@18.2.0)(react@18.2.0) - antd: 5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) + antd: 5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) lodash: 4.17.21 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -288,7 +285,24 @@ packages: stylis: 4.2.0 dev: false - /@ant-design/flowchart@1.2.2(@ant-design/icons@5.2.6)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): + /@ant-design/cssinjs@1.18.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1JURAPrsjK1GwpqByTq3bJ7nF7lbMKDZpehqeR2n8/IR5O58/W1U4VcOeaw5ZyTHri3tEMcom7dyP2tvxpW54g==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.23.6 + '@emotion/hash': 0.8.0 + '@emotion/unitless': 0.7.5 + classnames: 2.3.2 + csstype: 3.1.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + stylis: 4.2.0 + dev: false + + /@ant-design/flowchart@1.2.2(@ant-design/icons@5.2.6)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-bzHZ81qqHjWIrXcCMInDB6eMTzbswaVCOAdUTCQJ+B45aybkVsU9LMCKquyOwRM7U7PWNfPC9S/lAlx2i2BvBQ==} peerDependencies: '@ant-design/icons': ^4.6.0 @@ -300,10 +314,10 @@ packages: '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) '@antv/layout': 0.1.31 '@antv/x6': 1.35.0 - '@antv/x6-react-components': 1.1.20(antd@5.11.0)(react-dom@18.2.0)(react@18.2.0) + '@antv/x6-react-components': 1.1.20(antd@5.12.2)(react-dom@18.2.0)(react@18.2.0) '@antv/x6-react-shape': 1.6.4(@antv/x6@1.35.0)(react-dom@18.2.0)(react@18.2.0) - '@antv/xflow': 1.0.55(@ant-design/icons@5.2.6)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) - antd: 5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) + '@antv/xflow': 1.0.55(@ant-design/icons@5.2.6)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) + antd: 5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) lodash: 4.17.21 react: 18.2.0 react-color: 2.17.3(react@18.2.0) @@ -385,7 +399,7 @@ packages: peerDependencies: react: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 json2mq: 0.2.0 react: 18.2.0 @@ -966,14 +980,14 @@ packages: tslib: 2.6.2 dev: false - /@antv/x6-react-components@1.1.20(antd@5.11.0)(react-dom@18.2.0)(react@18.2.0): + /@antv/x6-react-components@1.1.20(antd@5.12.2)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-HpQqjPCUo+jfcbfW2sr9oxuXMCxWnXxWvE8jXKJzvrlMNZ3kgfxNqMCRxwGi2QTCxLB3g/KYi5/n8kze8ui1/Q==} peerDependencies: antd: '>=4.4.2 || >=5.0.0-beta.0' react: '>=16.8.6 || >=17.0.0' react-dom: '>=16.8.6 || >=17.0.0' dependencies: - antd: 5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) + antd: 5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) clamp: 1.0.1 classnames: 2.3.2 rc-dropdown: 3.6.2(react-dom@18.2.0)(react@18.2.0) @@ -1008,7 +1022,7 @@ packages: utility-types: 3.10.0 dev: false - /@antv/xflow-core@1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.11.0)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0): + /@antv/xflow-core@1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.12.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-FhjTstp/ZdO6mj8ERARJ6M9PWgikXvOpWwMTLCjc+i8vS4O3t4XL/fIu16MqJNuNdqfETcjJluHd06c32MTB/w==} peerDependencies: '@ant-design/icons': ^4.6.0 @@ -1022,10 +1036,10 @@ packages: dependencies: '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) '@antv/x6': 1.35.0 - '@antv/x6-react-components': 1.1.20(antd@5.11.0)(react-dom@18.2.0)(react@18.2.0) + '@antv/x6-react-components': 1.1.20(antd@5.12.2)(react-dom@18.2.0)(react@18.2.0) '@antv/x6-react-shape': 1.6.4(@antv/x6@1.35.0)(react-dom@18.2.0)(react@18.2.0) '@antv/xflow-hook': 1.0.55 - antd: 5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) + antd: 5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 immer: 9.0.21 lodash: 4.17.21 @@ -1037,7 +1051,7 @@ packages: rxjs: 6.6.7 dev: false - /@antv/xflow-extension@1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): + /@antv/xflow-extension@1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-iHRfO/ae4/9xvC5xVFmA9eIFg813DQa06hTgTdxLlt0Aojnfa5VnsGrIrPQoDDQovCXG8SavMDlnLZUpa491GQ==} peerDependencies: '@ant-design/icons': ^4.6.0 @@ -1052,11 +1066,11 @@ packages: dependencies: '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) '@antv/x6': 1.35.0 - '@antv/x6-react-components': 1.1.20(antd@5.11.0)(react-dom@18.2.0)(react@18.2.0) + '@antv/x6-react-components': 1.1.20(antd@5.12.2)(react-dom@18.2.0)(react@18.2.0) '@antv/x6-react-shape': 1.6.4(@antv/x6@1.35.0)(react-dom@18.2.0)(react@18.2.0) - '@antv/xflow-core': 1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.11.0)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0) + '@antv/xflow-core': 1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.12.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0) '@antv/xflow-hook': 1.0.55 - antd: 5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) + antd: 5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 mana-syringe: 0.2.2 moment: 2.29.4 @@ -1075,7 +1089,7 @@ packages: toposort: 2.0.2 dev: false - /@antv/xflow@1.0.55(@ant-design/icons@5.2.6)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): + /@antv/xflow@1.0.55(@ant-design/icons@5.2.6)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-1LRFZsDZDVuRwEYD0xFt7SGCbHducgXQ4GgPOzmaCMA5FMbQfZVpXhsOG4o/a9X+gKfYdpOELCLqpz7iykyArQ==} peerDependencies: '@ant-design/icons': ^4.6.0 @@ -1087,12 +1101,12 @@ packages: '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) '@antv/layout': 0.1.31 '@antv/x6': 1.35.0 - '@antv/x6-react-components': 1.1.20(antd@5.11.0)(react-dom@18.2.0)(react@18.2.0) + '@antv/x6-react-components': 1.1.20(antd@5.12.2)(react-dom@18.2.0)(react@18.2.0) '@antv/x6-react-shape': 1.6.4(@antv/x6@1.35.0)(react-dom@18.2.0)(react@18.2.0) - '@antv/xflow-core': 1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.11.0)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0) - '@antv/xflow-extension': 1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.11.0)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) + '@antv/xflow-core': 1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.12.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0) + '@antv/xflow-extension': 1.0.55(@ant-design/icons@5.2.6)(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.4)(@antv/x6@1.35.0)(antd@5.12.2)(classnames@2.3.2)(lodash@4.17.21)(react-dom@18.2.0)(react@18.2.0)(reflect-metadata@0.1.13) '@antv/xflow-hook': 1.0.55 - antd: 5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) + antd: 5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) lodash: 4.17.21 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -1138,6 +1152,13 @@ packages: dependencies: regenerator-runtime: 0.14.0 + /@babel/runtime@7.23.6: + resolution: {integrity: sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.0 + dev: false + /@babel/types@7.23.0: resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} engines: {node: '>=6.9.0'} @@ -2234,6 +2255,15 @@ packages: react: 18.2.0 dev: false + /@csstools/selector-specificity@3.0.0(postcss-selector-parser@6.0.13): + resolution: {integrity: sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss-selector-parser: ^6.0.13 + dependencies: + postcss-selector-parser: 6.0.13 + dev: true + /@ctrl/tinycolor@3.6.1: resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} @@ -2509,30 +2539,6 @@ packages: - utf-8-validate dev: true - /@kubernetes/client-node@0.19.0: - resolution: {integrity: sha512-WTOjGuFQ8yeW3+qD6JrAYhpwpoQbe9R8cA/61WCyFrNawSTUgLstHu7EsZRYEs39er3jDn3wCEaczz+VOFlc2Q==} - dependencies: - '@types/js-yaml': 4.0.8 - '@types/node': 20.8.7 - '@types/request': 2.48.10 - '@types/ws': 8.5.7 - byline: 5.0.0 - isomorphic-ws: 5.0.0(ws@8.14.2) - js-yaml: 4.1.0 - jsonpath-plus: 7.2.0 - request: 2.88.2 - rfc4648: 1.5.2 - stream-buffers: 3.0.2 - tar: 6.2.0 - tslib: 2.6.2 - ws: 8.14.2 - optionalDependencies: - openid-client: 5.6.1 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false - /@ljharb/resumer@0.0.1: resolution: {integrity: sha512-skQiAOrCfO7vRTq53cxznMpks7wS1va95UCidALlOVWqvBAzwPVErwizDwoMqNVMEn1mDq0utxZd02eIrvF1lw==} engines: {node: '>= 0.4'} @@ -2766,10 +2772,10 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@ctrl/tinycolor': 3.6.1 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -2780,8 +2786,8 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.23.6 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -2790,7 +2796,7 @@ packages: resolution: {integrity: sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==} engines: {node: '>=8.x'} dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 dev: false /@rc-component/mutate-observer@1.1.0(react-dom@18.2.0)(react@18.2.0): @@ -2800,9 +2806,9 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -2814,42 +2820,42 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /@rc-component/tour@1.10.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-voV0BKaTJbewB9LLgAHQ7tAGG7rgDkKQkZo82xw2gIk542hY+o7zwoqdN16oHhIKk7eG/xi+mdXrONT62Dt57A==} + /@rc-component/tour@1.11.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-c9Lw3/oVinj5D64Rsp8aDLOXcgdViE+hq7bj0Qoo8fTuQEh9sSpUw5OZcum943JkjeIE4hLcc5FD4a5ANtMJ4w==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /@rc-component/trigger@1.18.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-bAcxJJ1Y+EJVgn8BRik7d8JjjAPND5zKkHQ3159zeR0gVoG4Z0RgEDAiXFFoie3/WpoJ9dRJyjrIpnH4Ef7PEg==} + /@rc-component/trigger@1.18.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-jRLYgFgjLEPq3MvS87fIhcfuywFSRDaDrYw1FLku7Cm4esszvzTbA0JBsyacAyLrK9rF3TiHFcvoEDMzoD3CTA==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -2961,6 +2967,7 @@ packages: /@types/caseless@0.12.4: resolution: {integrity: sha512-2in/lrHRNmDvHPgyormtEralhPcN3An1gLjJzj2Bw145VBxkQ75JEXW6CTdMAwShiHQcYsl2d10IjQSdJSJz4g==} + dev: true /@types/d3-timer@2.0.2: resolution: {integrity: sha512-Dz39VLKZhWWeqSqbgYKF5BDJDUiPITo9M2cev/+HQBvXs+biES2d3LndnopuJ5YwaKK1h56CPWqDB+ghUXhm9A==} @@ -3001,6 +3008,7 @@ packages: /@types/js-yaml@4.0.8: resolution: {integrity: sha512-m6jnPk1VhlYRiLFm3f8X9Uep761f+CK8mHyS65LutH2OhmBF0BeMEjHgg05usH8PLZMWWc/BUR9RPmkvpWnyRA==} + dev: true /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} @@ -3039,6 +3047,7 @@ packages: resolution: {integrity: sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==} dependencies: undici-types: 5.25.3 + dev: true /@types/nprogress@0.2.0: resolution: {integrity: sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==} @@ -3071,12 +3080,14 @@ packages: '@types/node': 20.8.7 '@types/tough-cookie': 4.0.3 form-data: 2.5.1 + dev: true /@types/scheduler@0.16.6: resolution: {integrity: sha512-Vlktnchmkylvc9SnwwwozTv04L/e1NykF5vgoQ0XTmI8DD+wxfjQuHuvHS3p0r2jz2x2ghPs2h1FVeDirIteWA==} /@types/tough-cookie@4.0.3: resolution: {integrity: sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==} + dev: true /@types/uuid@9.0.6: resolution: {integrity: sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==} @@ -3086,6 +3097,7 @@ packages: resolution: {integrity: sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==} dependencies: '@types/node': 20.8.7 + dev: true /@typescript-eslint/parser@6.8.0(eslint@8.51.0)(typescript@5.0.2): resolution: {integrity: sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==} @@ -3250,58 +3262,58 @@ packages: color-convert: 2.0.1 dev: true - /antd@5.11.0(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-34T5Y6z+Ip+j4faXPTcanTFCLLpR4V0rLHtuz0lbN9gF4coGY/YYa8bhgwXrT6muW0Afwyo3NmbMF52hvIarog==} + /antd@5.12.2(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lJ4pdBRboN2Tl5hXTqgxUjGIercB2YIK7Z8fVDushgrJ55RhywJjvcQVnBmuxcSPuWEF2Yu8SNBVAnaV4EqzWA==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: '@ant-design/colors': 7.0.0 - '@ant-design/cssinjs': 1.17.2(react-dom@18.2.0)(react@18.2.0) + '@ant-design/cssinjs': 1.18.1(react-dom@18.2.0)(react@18.2.0) '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) '@ant-design/react-slick': 1.0.2(react@18.2.0) - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@ctrl/tinycolor': 3.6.1 '@rc-component/color-picker': 1.4.1(react-dom@18.2.0)(react@18.2.0) '@rc-component/mutate-observer': 1.1.0(react-dom@18.2.0)(react@18.2.0) - '@rc-component/tour': 1.10.0(react-dom@18.2.0)(react@18.2.0) - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/tour': 1.11.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 copy-to-clipboard: 3.3.3 dayjs: 1.11.10 qrcode.react: 3.1.0(react@18.2.0) rc-cascader: 3.20.0(react-dom@18.2.0)(react@18.2.0) rc-checkbox: 3.1.0(react-dom@18.2.0)(react@18.2.0) - rc-collapse: 3.7.1(react-dom@18.2.0)(react@18.2.0) + rc-collapse: 3.7.2(react-dom@18.2.0)(react@18.2.0) rc-dialog: 9.3.4(react-dom@18.2.0)(react@18.2.0) rc-drawer: 6.5.2(react-dom@18.2.0)(react@18.2.0) rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) - rc-field-form: 1.40.0(react-dom@18.2.0)(react@18.2.0) - rc-image: 7.3.2(react-dom@18.2.0)(react@18.2.0) - rc-input: 1.3.5(react-dom@18.2.0)(react@18.2.0) + rc-field-form: 1.41.0(react-dom@18.2.0)(react@18.2.0) + rc-image: 7.5.1(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.3.11(react-dom@18.2.0)(react@18.2.0) rc-input-number: 8.4.0(react-dom@18.2.0)(react@18.2.0) rc-mentions: 2.9.1(react-dom@18.2.0)(react@18.2.0) - rc-menu: 9.12.2(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.12.4(react-dom@18.2.0)(react@18.2.0) rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) rc-notification: 5.3.0(react-dom@18.2.0)(react@18.2.0) - rc-pagination: 3.7.0(react-dom@18.2.0)(react@18.2.0) + rc-pagination: 4.0.3(react-dom@18.2.0)(react@18.2.0) rc-picker: 3.14.6(dayjs@1.11.10)(moment@2.29.4)(react-dom@18.2.0)(react@18.2.0) rc-progress: 3.5.1(react-dom@18.2.0)(react@18.2.0) rc-rate: 2.12.0(react-dom@18.2.0)(react@18.2.0) rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) rc-segmented: 2.2.2(react-dom@18.2.0)(react@18.2.0) rc-select: 14.10.0(react-dom@18.2.0)(react@18.2.0) - rc-slider: 10.4.0(react-dom@18.2.0)(react@18.2.0) + rc-slider: 10.5.0(react-dom@18.2.0)(react@18.2.0) rc-steps: 6.0.1(react-dom@18.2.0)(react@18.2.0) rc-switch: 4.1.0(react-dom@18.2.0)(react@18.2.0) - rc-table: 7.35.2(react-dom@18.2.0)(react@18.2.0) - rc-tabs: 12.13.1(react-dom@18.2.0)(react@18.2.0) - rc-textarea: 1.5.2(react-dom@18.2.0)(react@18.2.0) + rc-table: 7.36.0(react-dom@18.2.0)(react@18.2.0) + rc-tabs: 12.14.1(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.5.3(react-dom@18.2.0)(react@18.2.0) rc-tooltip: 6.1.2(react-dom@18.2.0)(react@18.2.0) rc-tree: 5.8.2(react-dom@18.2.0)(react@18.2.0) rc-tree-select: 5.15.0(react-dom@18.2.0)(react@18.2.0) rc-upload: 4.3.5(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) scroll-into-view-if-needed: 3.1.0 @@ -3645,6 +3657,7 @@ packages: /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + dev: true /clamp@1.0.1: resolution: {integrity: sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA==} @@ -4643,6 +4656,7 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 + dev: true /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} @@ -4695,6 +4709,7 @@ packages: engines: {node: '>= 8'} dependencies: minipass: 3.3.6 + dev: true /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -5245,6 +5260,7 @@ packages: ws: '*' dependencies: ws: 8.14.2 + dev: true /isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} @@ -5267,6 +5283,7 @@ packages: /jose@4.15.4: resolution: {integrity: sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==} requiresBuild: true + dev: true optional: true /jquery-mousewheel@3.1.13: @@ -5348,6 +5365,7 @@ packages: /jsonpath-plus@7.2.0: resolution: {integrity: sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA==} engines: {node: '>=12.0.0'} + dev: true /jsprim@1.4.2: resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} @@ -5479,6 +5497,7 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 + dev: true /magic-string@0.26.7: resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} @@ -5569,10 +5588,12 @@ packages: engines: {node: '>=8'} dependencies: yallist: 4.0.0 + dev: true /minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} + dev: true /minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} @@ -5580,11 +5601,13 @@ packages: dependencies: minipass: 3.3.6 yallist: 4.0.0 + dev: true /mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true + dev: true /ml-array-max@1.2.4: resolution: {integrity: sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==} @@ -5762,6 +5785,7 @@ packages: resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} engines: {node: '>= 6'} requiresBuild: true + dev: true optional: true /object-hash@3.0.0: @@ -5844,6 +5868,7 @@ packages: resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} engines: {node: ^10.13.0 || >=12.0.0} requiresBuild: true + dev: true optional: true /once@1.4.0: @@ -5864,6 +5889,7 @@ packages: lru-cache: 6.0.0 object-hash: 2.2.0 oidc-token-hash: 5.0.3 + dev: true optional: true /optionator@0.9.3: @@ -6029,6 +6055,17 @@ packages: postcss-selector-parser: 6.0.13 dev: true + /postcss-nesting@12.0.1(postcss@8.4.31): + resolution: {integrity: sha512-6LCqCWP9pqwXw/njMvNK0hGY44Fxc4B2EsGbn6xDcxbNRzP8GYoxT7yabVVMLrX3quqOJ9hg2jYMsnkedOf8pA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/selector-specificity': 3.0.0(postcss-selector-parser@6.0.13) + postcss: 8.4.31 + postcss-selector-parser: 6.0.13 + dev: true + /postcss-selector-parser@6.0.13: resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} engines: {node: '>=4'} @@ -6136,12 +6173,12 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 array-tree-filter: 2.1.0 classnames: 2.3.2 rc-select: 14.10.0(react-dom@18.2.0)(react@18.2.0) rc-tree: 5.8.2(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6152,23 +6189,23 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-collapse@3.7.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-N/7ejyiTf3XElNJBBpxqnZBUuMsQWEOPjB2QkfNvZ/Ca54eAvJXuOD1EGbCWCk2m7v/MSxku7mRpdeaLOCd4Gg==} + /rc-collapse@3.7.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ZRw6ipDyOnfLFySxAiCMdbHtb5ePAsB9mT17PA6y1mRD/W6KHRaZeb5qK/X9xDV1CqgyxMpzw0VdS74PCcUk4A==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6179,11 +6216,11 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6194,11 +6231,11 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6223,10 +6260,10 @@ packages: react: '>=16.11.0' react-dom: '>=16.11.0' dependencies: - '@babel/runtime': 7.23.2 - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.23.6 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6245,32 +6282,32 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /rc-field-form@1.40.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-OM3N01X2BYFGJDJcwpk9/BBtlwgveE7eh2SQAKIxVCt9KVWlODYJ9ypTHQdxchfDbeJKJKxMBFXlLAmyvlgPHg==} + /rc-field-form@1.41.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-k9AS0wmxfJfusWDP/YXWTpteDNaQ4isJx9UKxx4/e8Dub4spFeZ54/EuN2sYrMRID/+hUznPgVZeg+Gf7XSYCw==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 async-validator: 4.2.5 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-image@7.3.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ICEF6SWv9YKhDXxy1vrXcmf0TVvEcQWIww5Yg+f+mn7e4oGX7FNP4+FExwMjNO5UHBEuWrigbGhlCgI6yZZ1jg==} + /rc-image@7.5.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Z9loECh92SQp0nSipc0MBuf5+yVC05H/pzC+Nf8xw1BKDFUJzUeehYBjaWlxly8VGBZJcTHYri61Fz9ng1G3Ag==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 rc-dialog: 9.3.4(react-dom@18.2.0)(react@18.2.0) rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6281,24 +6318,24 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@rc-component/mini-decimal': 1.1.0 classnames: 2.3.2 - rc-input: 1.3.5(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.3.11(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-input@1.3.5(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-SPPwbTJa5ACHNoDdGZF/70AOqqm1Rir3WleuFBKq+nFby1zvpnzvWsHJgzWOr6uJ0GNt8dTMzBrmVGQJkTXqqQ==} + /rc-input@1.3.11(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-jhH7QP5rILanSHCGSUkdoFE5DEtpv8FIseYhuYkOZzUBeiVAiwM3q26YqZ6xBB0QFEZ/yUAgms4xW4iuub3xFQ==} peerDependencies: react: '>=16.0.0' react-dom: '>=16.0.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6309,29 +6346,29 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.23.6 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 - rc-input: 1.3.5(react-dom@18.2.0)(react@18.2.0) - rc-menu: 9.12.2(react-dom@18.2.0)(react@18.2.0) - rc-textarea: 1.5.2(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.3.11(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.12.4(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.5.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-menu@9.12.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-NzloFH2pRUYmQ3S/YbJAvRkgCZaLvq0sRa5rgJtuIHLfPPprNHNyepeSlT64+dbVqI4qRWL44VN0lUCldCbbfg==} + /rc-menu@9.12.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-t2NcvPLV1mFJzw4F21ojOoRVofK2rWhpKPx69q2raUsiHPDP6DDevsBILEYdsIegqBeSXoWs2bf6CueBKg3BFg==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.23.6 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) rc-overflow: 1.3.2(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6356,10 +6393,10 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6370,23 +6407,23 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-pagination@3.7.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-IxSzKapd13L91/195o1TPkKnCNw8gIR25UP1GCW/7c7n/slhld4npu2j2PB9IWjXm4SssaAaSAt2lscYog7wzg==} + /rc-pagination@4.0.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-s1MNwyU83AgycikYckRdpmkN+4ZZuul0E0YdDp7dMgcjg/d2fak767ZIbLP4Q5YPPla7NDorfVFTvGQAPj6jXA==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6411,12 +6448,12 @@ packages: moment: optional: true dependencies: - '@babel/runtime': 7.23.2 - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.23.6 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 dayjs: 1.11.10 moment: 2.29.4 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6427,9 +6464,9 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6441,9 +6478,9 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6454,9 +6491,9 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) resize-observer-polyfill: 1.5.1 @@ -6468,10 +6505,10 @@ packages: react: '>=16.0.0' react-dom: '>=16.0.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6483,27 +6520,27 @@ packages: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.23.2 - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.23.6 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) rc-overflow: 1.3.2(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) rc-virtual-list: 3.11.2(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-slider@10.4.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ZlpWjFhOlEf0w4Ng31avFBkXNNBj60NAcTPaIoiCxBkJ29wOtHSPMqv9PZeEoqmx64bpJkgK7kPa47HG4LPzww==} + /rc-slider@10.5.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-xiYght50cvoODZYI43v3Ylsqiw14+D7ELsgzR40boDZaya1HFa1Etnv9MDkQE8X/UrXAffwv2AcNAhslgYuDTw==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6515,9 +6552,9 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6528,59 +6565,59 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-table@7.35.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ZLIZdAEdfen21FI21xt2LDg9chQ7gc5Lpy4nkjWKPDgmQMnH0KJ8JQQzrd3zrEN16xzjiVdHHvRmi1RU8BtgYg==} + /rc-table@7.36.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3xVcdCC5OLeOOhaCg+5Lps2oPreM/GWXmUXWTSX4p6vF7F76ABM4dfPpMJ9Dnf5yGRyh+8pe7FRyhRVnWw2H/w==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 '@rc-component/context': 1.4.0(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) rc-virtual-list: 3.11.2(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-tabs@12.13.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-83u3l2QkO0UznCzdBLEk9WnNcT+imtmDmMT993sUUEOGnNQAmqOdev0XjeqrcvsAMe9CDpAWDFd7L/RZw+LVJQ==} + /rc-tabs@12.14.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1xlE7JQNYxD5RwBsM7jf2xSdUrkmTSDFLFEm2gqAgnsRlOGydEzXXNAVTOT6QcgM1G/gCm+AgG+FYPUGb4Hs4g==} engines: {node: '>=8.x'} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) - rc-menu: 9.12.2(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.12.4(react-dom@18.2.0)(react@18.2.0) rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /rc-textarea@1.5.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-VVwKYtkp5whZVhP+llX8zM8TtI3dv+BDA0FUbmBMGLaW/tuBJ7Yh35yPabO63V+Bi68xv17eI4hy+/4p2G0gFg==} + /rc-textarea@1.5.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-oH682ghHx++stFNYrosPRBfwsypywrTXpaD0/5Z8MPkUOnyOQUaY9ueL9tMu6BP1LfsuYQ1VLpg5OtshViLNgA==} peerDependencies: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-input: 1.3.5(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.3.11(react-dom@18.2.0)(react@18.2.0) rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6591,8 +6628,8 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 - '@rc-component/trigger': 1.18.1(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.23.6 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -6604,11 +6641,11 @@ packages: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-select: 14.10.0(react-dom@18.2.0)(react@18.2.0) rc-tree: 5.8.2(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6620,10 +6657,10 @@ packages: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) rc-virtual-list: 3.11.2(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -6651,9 +6688,9 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6680,6 +6717,18 @@ packages: react-is: 18.2.0 dev: false + /rc-util@5.38.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-e4ZMs7q9XqwTuhIK7zBIVFltUtMSjphuPPQXHoHlzRzNdOwUxDejo0Zls5HYaJfRKNURcsS/ceKVULlhjBrxng==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.6 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-is: 18.2.0 + dev: false + /rc-virtual-list@3.11.2(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-MTFLL2LOHr3+/+r+WjTIs6j8XmJE6EqdOsJvCH8SWig7qyik3aljCEImUtw5tdWR0tQhXUfbv7P7nZaLY91XPg==} engines: {node: '>=8.x'} @@ -6687,10 +6736,10 @@ packages: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.23.6 classnames: 2.3.2 rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) - rc-util: 5.38.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -7020,6 +7069,7 @@ packages: /rfc4648@1.5.2: resolution: {integrity: sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==} + dev: true /rfc6902@5.0.1: resolution: {integrity: sha512-tYGfLpKIq9X7lrt4o3IkD9w9bpeAtsejfAqWNR98AoxfTsZqCepKa8eDlRiX8QMiCOD9vMx0/YbKLx0G1nPi5w==} @@ -7303,6 +7353,7 @@ packages: /stream-buffers@3.0.2: resolution: {integrity: sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==} engines: {node: '>= 0.10.0'} + dev: true /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} @@ -7504,6 +7555,7 @@ packages: minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 + dev: true /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -7743,6 +7795,7 @@ packages: /undici-types@5.25.3: resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==} + dev: true /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -7980,9 +8033,11 @@ packages: optional: true utf-8-validate: optional: true + dev: true /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true /yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} diff --git a/frontend/plugins/kubepanel/postcss.config.js b/frontend/plugins/kubepanel/postcss.config.js index 5cbc2c7d877..694395b04b1 100644 --- a/frontend/plugins/kubepanel/postcss.config.js +++ b/frontend/plugins/kubepanel/postcss.config.js @@ -1,5 +1,11 @@ module.exports = { plugins: { + /** + * fix: nesting + * @link https://tailwindcss.com/docs/using-with-preprocessors#nesting + */ + 'postcss-import': {}, + 'tailwindcss/nesting': 'postcss-nesting', tailwindcss: {}, autoprefixer: {} } diff --git a/frontend/plugins/kubepanel/src/components/common/action/action-button.tsx b/frontend/plugins/kubepanel/src/components/common/action/action-button.tsx new file mode 100644 index 00000000000..72f79eecf1f --- /dev/null +++ b/frontend/plugins/kubepanel/src/components/common/action/action-button.tsx @@ -0,0 +1,56 @@ +import { CloseOutlined, MoreOutlined, RetweetOutlined } from '@ant-design/icons'; +import { Button, type MenuProps, Dropdown } from 'antd'; +import { useState } from 'react'; +import { UpdateEditorModal } from './update-editor-modal'; +import { KubeObject } from '@/k8slens/kube-object'; +import { DeletePopconfirm } from './delete-popconfirm'; + +interface Props { + obj: K; +} + +export const ActionButton = ({ obj }: Props) => { + const [openUpdateModal, setOpenUpdateModal] = useState(false); + + const items: MenuProps['items'] = [ + { + key: 'delete', + label: ( + + + + ) + }, + { + key: 'update', + label: ( + + ) + } + ].filter((item) => item.label); + + return ( + // wrapper to stop click event propagation +
e.stopPropagation()}> + + + + setOpenUpdateModal(false)} + onOk={() => setOpenUpdateModal(false)} + /> +
+ ); +}; diff --git a/frontend/plugins/kubepanel/src/components/common/action/create-resource-modal.tsx b/frontend/plugins/kubepanel/src/components/common/action/create-resource-modal.tsx new file mode 100644 index 00000000000..5f6f500f610 --- /dev/null +++ b/frontend/plugins/kubepanel/src/components/common/action/create-resource-modal.tsx @@ -0,0 +1,143 @@ +import { editor as EditorNS } from 'monaco-editor'; +import { Button, Flex, Modal, Spin, notification } from 'antd'; +import React, { useCallback, useRef, useState } from 'react'; +import { createResource, getTemplate } from '@/api/kubernetes'; +import { TemplateToggle, TemplateToggleChooseEventHandler } from './toggle'; +import { buildErrorResponse } from '@/services/backend/response'; +import { KubeObjectKind } from '@/constants/kube-object'; +import Title from '@/components/common/title/title'; +import StyledEditor from '@/components/common/editor/styled'; + +interface Props { + open: boolean; + setClose: () => void; +} + +const defaultTemplate = 'Please select a template first.'; +const noticeKey = 'createResource'; + +export const CreateResourceModal = ({ open, setClose }: Props) => { + const [disabled, setDisabled] = useState(true); + const [kind, setKind] = useState(undefined); + const [loading, setLoading] = useState(false); + const [template, setTemplate] = useState(defaultTemplate); + const [confirmLoading, setConfirmLoading] = useState(false); + const [notifyApi, contextHolder] = notification.useNotification(); + const editorRef = useRef(null); + const onEditorMount = (editor: EditorNS.IStandaloneCodeEditor) => { + editorRef.current = editor; + }; + + const onChoose = useCallback( + (kind) => { + setKind(kind); + setDisabled(false); + const storage = localStorage.getItem(`template-${kind}`); + if (storage) { + setTemplate(storage); + return; + } + setLoading(true); + // fetch template + getTemplate(kind) + .then((res) => { + setTemplate(res.data); + }) + .catch((err: any) => { + const errResp = buildErrorResponse(err); + notifyApi.error({ + key: noticeKey, + message: errResp.error.reason, + description: errResp.error.message + }); + }) + .finally(() => { + setLoading(false); + }); + }, + [notifyApi] + ); + + const onCreate = useCallback(() => { + setConfirmLoading(true); + const editor = editorRef.current; + if (!editor) { + setConfirmLoading(false); + notifyApi.error({ + key: noticeKey, + message: 'Editor Not Found', + description: 'Please reopen the create resource panel, sorry for the inconvenience.' + }); + return; + } + if (!kind) { + setConfirmLoading(false); + notifyApi.error({ + key: noticeKey, + message: 'Template Not Found', + description: 'Please select a template first, sorry for the inconvenience.' + }); + return; + } + const value = editor.getValue(); + createResource(kind, value) + .then(() => { + notifyApi.success({ + key: noticeKey, + message: 'Success', + description: 'Your resource has been created.' + }); + }) + .catch((err: any) => { + const errResp = buildErrorResponse(err); + notifyApi.error({ + key: noticeKey, + message: errResp.error.reason, + description: errResp.error.message + }); + }) + .finally(() => { + setConfirmLoading(false); + }); + }, [kind, notifyApi]); + return ( + <> + {contextHolder} + + Cancel + , + + ]} + > + + Create Resource + + + + + + + + + + ); +}; diff --git a/frontend/plugins/kubepanel/src/components/common/action/delete-popconfirm.tsx b/frontend/plugins/kubepanel/src/components/common/action/delete-popconfirm.tsx new file mode 100644 index 00000000000..fdd3dde2a1f --- /dev/null +++ b/frontend/plugins/kubepanel/src/components/common/action/delete-popconfirm.tsx @@ -0,0 +1,61 @@ +import { deleteResource } from '@/api/kubernetes'; +import { KubeObject } from '@/k8slens/kube-object'; +import { buildErrorResponse } from '@/services/backend/response'; +import { WarningOutlined } from '@ant-design/icons'; +import { Popconfirm, message } from 'antd'; +import { useState } from 'react'; + +interface Props { + obj: K; + children: React.ReactNode; +} + +export function DeletePopconfirm({ obj, children }: Props) { + if (!obj) return null; + const [confirmLoading, setConfirmLoading] = useState(false); + const [msgApi, contextHolder] = message.useMessage(); + const msgKey = 'deletedMsg'; + return ( + <> + {contextHolder} + + Are you sure to delete{' '} + + {obj.kind}: {obj.getName()} + + ? + + } + icon={} + onConfirm={() => { + setConfirmLoading(true); + deleteResource(obj.kind, obj.getName()) + .then((res) => { + msgApi.success({ + content: `Successfully deleted ${res.data.kind} ${res.data.metadata.name}`, + key: msgKey + }); + }) + .catch((err) => { + const errResp = buildErrorResponse(err); + msgApi.error({ + content: `Failed to update ${obj.kind} ${obj.getName()}: ${errResp.error.message}`, + key: msgKey + }); + }) + .finally(() => { + setConfirmLoading(false); + }); + }} + okText="Yes" + okButtonProps={{ loading: confirmLoading }} + cancelText="No" + > + {children} + + + ); +} diff --git a/frontend/plugins/kubepanel/src/components/common/action/toggle.tsx b/frontend/plugins/kubepanel/src/components/common/action/toggle.tsx new file mode 100644 index 00000000000..53436894b81 --- /dev/null +++ b/frontend/plugins/kubepanel/src/components/common/action/toggle.tsx @@ -0,0 +1,112 @@ +import { KubeObjectKind } from '@/constants/kube-object'; +import { + DashboardOutlined, + DatabaseOutlined, + DownOutlined, + GatewayOutlined, + SettingOutlined +} from '@ant-design/icons'; +import { Dropdown, MenuProps, Space } from 'antd'; +import { useCallback, useState } from 'react'; + +const items: MenuProps['items'] = [ + { + key: 'Workload', + label: 'Workload', + icon: , + children: [ + { + key: KubeObjectKind.Pod, + label: 'Pod' + }, + { + key: KubeObjectKind.Deployment, + label: 'Deployment' + }, + { + key: KubeObjectKind.StatefulSet, + label: 'Stateful Set' + } + ] + }, + { + key: 'Network', + label: 'Network', + icon: , + children: [ + { + key: KubeObjectKind.Ingress, + label: 'Ingress' + } + ] + }, + { + key: 'Config', + label: 'Config', + icon: , + children: [ + { + key: KubeObjectKind.ConfigMap, + label: 'Config Map' + }, + { + key: KubeObjectKind.Secret, + label: 'Secret' + } + ] + }, + { + key: 'Storage', + label: 'Storage', + icon: , + children: [ + { + key: KubeObjectKind.PersistentVolumeClaim, + label: 'Persistent Volume Claim' + } + ] + } +]; + +export type TemplateToggleChooseEventHandler = (kind: KubeObjectKind) => void; + +interface TemplateToggleProps { + onChoose: TemplateToggleChooseEventHandler; +} + +const placeholder = 'Choose a Template'; + +export function TemplateToggle({ onChoose }: TemplateToggleProps) { + const [input, setInput] = useState(placeholder); + const [hovered, setHovered] = useState(false); + + const onClick = useCallback['onClick']>( + (e) => { + setInput(e.key); + onChoose(e.key as KubeObjectKind); + }, + [setInput, onChoose] + ); + + return ( +
+ setHovered(e)}> + + + {input} + + + + +
+ ); +} diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/update-editor-modal.tsx b/frontend/plugins/kubepanel/src/components/common/action/update-editor-modal.tsx similarity index 83% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/update-editor-modal.tsx rename to frontend/plugins/kubepanel/src/components/common/action/update-editor-modal.tsx index a81c227eb3d..a0dbaa418d1 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/update-editor-modal.tsx +++ b/frontend/plugins/kubepanel/src/components/common/action/update-editor-modal.tsx @@ -1,8 +1,9 @@ import { updateResource } from '@/api/kubernetes'; +import StyledEditor from '@/components/common/editor/styled'; +import Title from '@/components/common/title/title'; import { KubeObject } from '@/k8slens/kube-object'; import { buildErrorResponse } from '@/services/backend/response'; import { dumpKubeObject } from '@/utils/yaml'; -import { Editor } from '@monaco-editor/react'; import { Button, Modal, message } from 'antd'; import { editor } from 'monaco-editor'; import { useRef } from 'react'; @@ -14,7 +15,7 @@ interface Props { onOk: () => void; } -const UpdateEditorModal = ({ +export const UpdateEditorModal = ({ obj, open, onCancel, @@ -32,14 +33,16 @@ const UpdateEditorModal = ({ <> {contextHolder} {`${obj.kind}: ${obj.getName()}`}} open={open} + width={'90vw'} onCancel={onCancel} - destroyOnClose footer={[ + , , - ]} > - + {obj.kind}: {obj.getName()} + + (editorRef.current = editor)} value={editorValue} language="yaml" - height="50vh" /> ); }; - -export default UpdateEditorModal; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-collapse.tsx b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-collapse.tsx similarity index 74% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-collapse.tsx rename to frontend/plugins/kubepanel/src/components/common/drawer/drawer-collapse.tsx index cd3f27e2f93..5457b8de6f7 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-collapse.tsx +++ b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-collapse.tsx @@ -1,4 +1,4 @@ -import DrawerItem from '@/pages/kubepanel/components/drawer/drawer-item'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import { Collapse } from 'antd'; interface Props { @@ -8,7 +8,7 @@ interface Props { value?: React.ReactNode; }; } -const DrawerCollapse = ({ children, header }: Props) => { +export const DrawerCollapse = ({ children, header }: Props) => { if (!header) return null; return ( @@ -21,5 +21,3 @@ const DrawerCollapse = ({ children, header }: Props) => { ); }; - -export default DrawerCollapse; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-item.tsx b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-item.tsx similarity index 82% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-item.tsx rename to frontend/plugins/kubepanel/src/components/common/drawer/drawer-item.tsx index c3264399cc9..eb3cfa94e85 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-item.tsx +++ b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-item.tsx @@ -5,7 +5,7 @@ interface DrawerItemProps { padding?: boolean; } -const DrawerItem = ({ name, value, hidden = false }: DrawerItemProps) => { +export const DrawerItem = ({ name, value, hidden = false }: DrawerItemProps) => { if (hidden) return null; return ( @@ -18,5 +18,3 @@ const DrawerItem = ({ name, value, hidden = false }: DrawerItemProps) => { ); }; - -export default DrawerItem; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-panel.tsx b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-panel.tsx similarity index 72% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-panel.tsx rename to frontend/plugins/kubepanel/src/components/common/drawer/drawer-panel.tsx index b87fa07ea6c..f406b63f26e 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-panel.tsx +++ b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-panel.tsx @@ -1,11 +1,11 @@ -import DrawerTitle from './drawer-title'; +import { DrawerTitle } from './drawer-title'; interface Props { title?: React.ReactNode; children: React.ReactNode; } -const DrawerPanel = ({ title, children }: Props) => { +export const DrawerPanel = ({ title, children }: Props) => { return (
@@ -15,5 +15,3 @@ const DrawerPanel = ({ title, children }: Props) => {
); }; - -export default DrawerPanel; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-title.tsx b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-title.tsx similarity index 68% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-title.tsx rename to frontend/plugins/kubepanel/src/components/common/drawer/drawer-title.tsx index 2a2f24c8fb0..57cc68ae437 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer-title.tsx +++ b/frontend/plugins/kubepanel/src/components/common/drawer/drawer-title.tsx @@ -2,10 +2,8 @@ interface Props { children: React.ReactNode; } -const DrawerTitle = ({ children }: Props) => { +export const DrawerTitle = ({ children }: Props) => { return (
{children}
); }; - -export default DrawerTitle; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer.tsx b/frontend/plugins/kubepanel/src/components/common/drawer/drawer.tsx similarity index 82% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer.tsx rename to frontend/plugins/kubepanel/src/components/common/drawer/drawer.tsx index e2636f32f66..bd1a02a1525 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/drawer/drawer.tsx +++ b/frontend/plugins/kubepanel/src/components/common/drawer/drawer.tsx @@ -1,12 +1,12 @@ import { CloseOutlined } from '@ant-design/icons'; -import { Drawer as AntdDrawer, Button } from 'antd'; +import { Drawer as AntdDrawer } from 'antd'; interface Props { title: string; children: React.ReactNode; open: boolean; onClose: () => void; } -const Drawer = ({ title, children, open, onClose }: Props) => { +export const Drawer = ({ title, children, open, onClose }: Props) => { return ( { ); }; - -export default Drawer; diff --git a/frontend/plugins/kubepanel/src/components/common/editor/styled.tsx b/frontend/plugins/kubepanel/src/components/common/editor/styled.tsx new file mode 100644 index 00000000000..6666d15a913 --- /dev/null +++ b/frontend/plugins/kubepanel/src/components/common/editor/styled.tsx @@ -0,0 +1,9 @@ +import { Editor, EditorProps } from '@monaco-editor/react'; + +export default function StyledEditor(props: EditorProps) { + return ( +
+ +
+ ); +} diff --git a/frontend/plugins/kubepanel/src/components/common/panel-table/pagination.tsx b/frontend/plugins/kubepanel/src/components/common/panel-table/pagination.tsx new file mode 100644 index 00000000000..1c93d136406 --- /dev/null +++ b/frontend/plugins/kubepanel/src/components/common/panel-table/pagination.tsx @@ -0,0 +1,97 @@ +import { + LeftOutlined, + RightOutlined, + VerticalLeftOutlined, + VerticalRightOutlined +} from '@ant-design/icons'; +import { PaginationProps, Space } from 'antd'; +import { useCallback, useMemo, useState } from 'react'; + +interface SwitchButtonProps { + onClick?: () => void; + disabled: boolean; + icon: React.ReactNode; +} + +const SwitchButton = ({ onClick, disabled, icon }: SwitchButtonProps) => { + const disabledClass = disabled + ? 'cursor-no-drop text-[#667085]' + : 'cursor-pointer text-[#111824]'; + + return ( + + ); +}; + +export function usePaginationProps(total: number): PaginationProps { + const [nxtPage, setNxtPage] = useState(1); + const [pageSize, setPageSize] = useState(10); + + const totalPageNum = useMemo(() => Math.ceil(total / pageSize), [total, pageSize]); + + const itemRender = useCallback['itemRender']>( + (_, type, originalElement) => { + let disabled: boolean; + switch (type) { + case 'prev': + disabled = nxtPage === 1; // current is index-0 page + return ( + + } + onClick={() => setNxtPage(1)} + disabled={disabled} + /> + } + onClick={() => setNxtPage(nxtPage - 1)} + disabled={disabled} + /> + + ); + case 'next': + disabled = nxtPage === totalPageNum; + return ( + + } + onClick={() => setNxtPage(nxtPage + 1)} + disabled={disabled} + /> + } + onClick={() => setNxtPage(totalPageNum)} + disabled={disabled} + /> + + ); + } + return originalElement; + }, + [nxtPage, totalPageNum] + ); + + return { + showTotal: (total) =>
{`Total ${total} items`}
, + current: nxtPage, + pageSize, + size: 'default', + simple: true, + hideOnSinglePage: true, + onChange: (page) => setNxtPage(page), + onShowSizeChange(_, size) { + setNxtPage(1); + setPageSize(size); + }, + itemRender + }; +} diff --git a/frontend/plugins/kubepanel/src/components/common/panel-table/search-filter.tsx b/frontend/plugins/kubepanel/src/components/common/panel-table/search-filter.tsx new file mode 100644 index 00000000000..6d1cca36998 --- /dev/null +++ b/frontend/plugins/kubepanel/src/components/common/panel-table/search-filter.tsx @@ -0,0 +1,123 @@ +import { SearchOutlined } from '@ant-design/icons'; +import { Button, Flex, Input, InputRef } from 'antd'; +import { ColumnType } from 'antd/lib/table'; +import { useCallback, useEffect, useRef, useState } from 'react'; + +interface SearchFilterPanelProps { + onSearched: (value: string) => void; + onReset: () => void; + visible: boolean; +} + +function SearchFilterPanel({ onSearched, onReset, visible }: SearchFilterPanelProps) { + const searchInput = useRef(null); + const [searchText, setSearchText] = useState(''); + + useEffect(() => { + console.log('visible', visible); + if (visible) { + setTimeout(() => searchInput.current?.focus(), 100); + } + }, [visible]); + + return ( + + { + onSearched(e.target.value); + setSearchText(e.target.value); + }} + value={searchText} + /> + + + ); +} + +interface HighlightNameProps { + name: string; + highlight: string; + enable?: boolean; +} + +function HighlightName({ name, highlight, enable = true }: HighlightNameProps) { + if (!enable) { + return <>{name}; + } + + const begin_idx = name.toLocaleLowerCase().indexOf(highlight.toLocaleLowerCase()); + if (begin_idx === -1) { + return <>{name}; + } + + const end_idx = begin_idx + highlight.length; + const begin = name.slice(0, begin_idx); + const middle = name.slice(begin_idx, end_idx); + const end = name.slice(end_idx); + + return ( + <> + {begin} +
{middle}
+ {end} + + ); +} + +type onFilter = Required>['onFilter']; + +export function useSearchNameFilterProps( + getName: (value: any, data: DataType) => string +): ColumnType { + const [searchText, setSearchText] = useState(''); + const [searched, setSearched] = useState(false); + const [visible, setVisible] = useState(false); + + const onFilter = useCallback>( + (value, record) => + getName(null, record) + .toLocaleLowerCase() + .includes((value as String).toLocaleLowerCase()), + [getName] + ); + + return { + filterDropdown({ setSelectedKeys, confirm }) { + return ( + { + setSelectedKeys([value]); + setSearchText(value); + setSearched(true); + confirm({ closeDropdown: false }); + }} + onReset={() => { + setSelectedKeys([]); + setSearchText(''); + setSearched(false); + confirm({ closeDropdown: false }); + }} + visible={visible} + /> + ); + }, + filterIcon(_) { + return ; + }, + onFilter, + onFilterDropdownOpenChange: (visible) => setVisible(visible), + render: (value, data) => ( + + ) + }; +} diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/panel-table/table.tsx b/frontend/plugins/kubepanel/src/components/common/panel-table/table.tsx similarity index 53% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/panel-table/table.tsx rename to frontend/plugins/kubepanel/src/components/common/panel-table/table.tsx index 8fac64cb8ba..1ce096b0ac9 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/panel-table/table.tsx +++ b/frontend/plugins/kubepanel/src/components/common/panel-table/table.tsx @@ -1,10 +1,13 @@ import { Section } from '@/components/common/section/section'; import Title from '@/components/common/title/title'; -import { APICallback, KubeStoreAction, WatchCloser } from '@/types/state'; +import { useWatcher } from '@/hooks/useWatcher'; +import { KubeStoreAction } from '@/types/state'; import { TableProps } from 'antd'; import { Table } from 'antd'; -import useNotification from 'antd/lib/notification/useNotification'; -import { useCallback, useEffect, useState } from 'react'; +import { useMemo, useState } from 'react'; +import { usePaginationProps } from './pagination'; +import { KubeObject } from '@/k8slens/kube-object'; +import { useSearchNameFilterProps } from './search-filter'; type DefaultRecordType = Record; @@ -17,13 +20,13 @@ interface Props extends Omit) => JSX.Element | null; } -const PanelTable = ( +export const PanelTable = ( tableProps: Props ) => { const { scroll = { x: true }, - pagination = false, sectionTitle: title, + columns = [], DetailDrawer, getRowKey, getDetailItem, @@ -32,39 +35,19 @@ const PanelTable = ( } = tableProps; const [selectedItem, setSelectedItem] = useState(null); const [openDetail, setOpenDetail] = useState(false); - const [watchTrigger, setWatchTrigger] = useState(false); - const [notifyApi, cxtHolder] = useNotification({ placement: 'topRight' }); - - const trigger = useCallback((_, e) => { - if (e) { - if (e.code === 410) { - notifyApi.error({ - description: 'Resource version is too old, you need to refresh the page', - message: 'Outdated Resource' - }); - setWatchTrigger(!watchTrigger); - return; - } - notifyApi.error({ - description: ( -
-

code: {e.error.errno}

-

{e.error.message}

-
- ), - message: e.error.reason, - duration: 5 - }); - } - }, []); + const cxtHolder = useWatcher({ initializers, watchers }); + const searchNameFilterProps = useSearchNameFilterProps((_, record) => + getDetailItem(record).getName() + ); + const paginationProps = usePaginationProps(tableProps.dataSource?.length || 0); - useEffect(() => { - let closers: Array; - Promise.allSettled(initializers.map((initializer) => initializer(trigger))).finally(() => { - closers = watchers.map((watcher) => watcher(trigger)); - }); - return () => closers.forEach((c) => c()); - }, [watchTrigger]); + const modifiedCols = useMemo( + () => [ + { title: 'Name', key: 'name', fixed: 'left' as 'left', ...searchNameFilterProps }, + ...columns + ], + [columns, searchNameFilterProps] + ); return (
@@ -72,9 +55,10 @@ const PanelTable = ( {title} ({ onClick: () => { @@ -90,5 +74,3 @@ const PanelTable = ( ); }; - -export default PanelTable; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/sidebar/sidebar.tsx b/frontend/plugins/kubepanel/src/components/common/sidebar/sidebar.tsx similarity index 96% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/sidebar/sidebar.tsx rename to frontend/plugins/kubepanel/src/components/common/sidebar/sidebar.tsx index 9f435e4934f..15be103a8b7 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/sidebar/sidebar.tsx +++ b/frontend/plugins/kubepanel/src/components/common/sidebar/sidebar.tsx @@ -58,7 +58,7 @@ interface Props { onClick?: (key: SideNavItemKey) => void; } -const ResourceSideNav = ({ onClick = () => {} }: Props) => { +export const ResourceSideNav = ({ onClick = () => {} }: Props) => { const router = useRouter(); return ( @@ -84,5 +84,3 @@ const ResourceSideNav = ({ onClick = () => {} }: Props) => { ); }; - -export default ResourceSideNav; diff --git a/frontend/plugins/kubepanel/src/components/common/title/title.tsx b/frontend/plugins/kubepanel/src/components/common/title/title.tsx index 0f339a650b1..3e04daa98ac 100644 --- a/frontend/plugins/kubepanel/src/components/common/title/title.tsx +++ b/frontend/plugins/kubepanel/src/components/common/title/title.tsx @@ -1,5 +1,6 @@ interface PageTitleProps { - children: string; + children: string | string[]; + className?: string; type: 'primary' | 'secondary' | 'table'; } @@ -17,6 +18,10 @@ const titleClassName: Record = { * @param {string} props.type - The type of the title component. * @return {JSX.Element} The rendered title component. */ -export default function Title({ children, type }: PageTitleProps) { - return {children}; +export default function Title({ children, type, className }: PageTitleProps) { + return ( +
+ {children} +
+ ); } diff --git a/frontend/plugins/kubepanel/src/components/kube/object/detail/kube-object-detail-info-list.tsx b/frontend/plugins/kubepanel/src/components/kube/object/detail/kube-object-detail-info-list.tsx index 673057898cc..94481d617f3 100644 --- a/frontend/plugins/kubepanel/src/components/kube/object/detail/kube-object-detail-info-list.tsx +++ b/frontend/plugins/kubepanel/src/components/kube/object/detail/kube-object-detail-info-list.tsx @@ -1,4 +1,4 @@ -import DrawerItem from '../../../../pages/kubepanel/components/drawer/drawer-item'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import { KubeObjectAge } from '../kube-object-age'; import { LocaleDate } from '../../local-date'; import moment from 'moment-timezone'; diff --git a/frontend/plugins/kubepanel/src/constants/theme.ts b/frontend/plugins/kubepanel/src/constants/theme.ts index 07a685f2759..0d19e1f5352 100644 --- a/frontend/plugins/kubepanel/src/constants/theme.ts +++ b/frontend/plugins/kubepanel/src/constants/theme.ts @@ -1,10 +1,14 @@ import { ThemeConfig } from 'antd'; +import { editor } from 'monaco-editor'; export const theme: ThemeConfig = { components: { Menu: { - itemSelectedBg: '#9699B41A', - itemColor: '#485058' + itemSelectedBg: '#1118240D', + itemSelectedColor: '#0884DD', + itemHoverColor: '#485264', + itemHoverBg: '#1118240D', + itemColor: '#485264' }, Collapse: { headerPadding: 0 @@ -13,5 +17,50 @@ export const theme: ThemeConfig = { headerBorderRadius: 0, headerBg: '#F6F8F9' } + }, + token: { + controlItemBgHover: '#1118240D' + }, + cssVar: true +}; + +export const monacoTheme: editor.IStandaloneThemeData = { + base: 'vs', + inherit: false, + rules: [ + { + token: 'string', + foreground: 'E82F72' + }, + { + token: 'symbol', + foreground: '027A48' + }, + { + token: 'number', + foreground: '667085' + }, + { + token: 'comment', + foreground: '9E53C1' + }, + { + token: 'operators', + foreground: '027A48' + }, + { + token: 'keyword', + foreground: '00A9A6' + } + ], + colors: { + 'editor.foreground': '#0770BC', + 'editor.background': '#FBFBFC', + 'editor.selectionBackground': '#DBF3FF', + 'editor.lineHighlightBackground': '#F4F4F7', + 'editorLineNumber.foreground': '#787A90', + 'editorLineNumber.activeForeground': '#219bf4', + 'editorCursor.foreground': '#111824', + 'editorWhitespace.foreground': '#BBBBBB' } }; diff --git a/frontend/plugins/kubepanel/src/hooks/useWatcher.tsx b/frontend/plugins/kubepanel/src/hooks/useWatcher.tsx new file mode 100644 index 00000000000..2333799b778 --- /dev/null +++ b/frontend/plugins/kubepanel/src/hooks/useWatcher.tsx @@ -0,0 +1,52 @@ +import { APICallback, KubeStoreAction, WatchCloser } from '@/types/state'; +import useNotification from 'antd/lib/notification/useNotification'; + +import { useCallback, useEffect, useRef, useState } from 'react'; + +interface Props { + initializers: Array['initialize']>; + watchers: Array['watch']>; +} + +export function useWatcher({ watchers, initializers }: Props) { + const [rewatchTrigger, setRewatchTrigger] = useState(false); + const closers = useRef>([]); + const [notifyApi, cxtHolder] = useNotification(); + + const callback = useCallback( + (_, e) => { + if (e) { + if (e.code === 410) { + notifyApi.info({ + description: 'Resource is outdated. We will reinitialize the resource.', + message: 'Outdated Resource' + }); + setRewatchTrigger(!rewatchTrigger); + return; + } + notifyApi.error({ + message: e.error.reason, + description: e.error.message, + duration: 5 + }); + } + }, + [notifyApi, rewatchTrigger] + ); + + useEffect(() => { + Promise.allSettled(initializers.map((initializer) => initializer(callback))).finally(() => { + closers.current = watchers.map((watcher) => watcher(callback)); + }); + }, [initializers, watchers, callback, rewatchTrigger]); + + useEffect(() => { + return () => { + closers.current.forEach((closer) => { + closer(); + }); + }; + }, []); + + return cxtHolder; +} diff --git a/frontend/plugins/kubepanel/src/pages/_app.tsx b/frontend/plugins/kubepanel/src/pages/_app.tsx index 11cc01e664f..23220e4c3d2 100644 --- a/frontend/plugins/kubepanel/src/pages/_app.tsx +++ b/frontend/plugins/kubepanel/src/pages/_app.tsx @@ -9,6 +9,8 @@ import { throttle } from 'lodash'; import { sealosApp, createSealosApp } from 'sealos-desktop-sdk/app'; import { SEALOS_DOMAIN, loadInitData } from '@/store/static'; import Head from 'next/head'; +import { useMonaco } from '@monaco-editor/react'; +import { monacoTheme } from '@/constants/theme'; import 'nprogress/nprogress.css'; import '@ant-design/flowchart/dist/index.css'; @@ -28,6 +30,14 @@ export default function App({ Component, pageProps }: AppProps) { content: '该应用不允许单独使用,点击确认前往 Sealos Desktop 使用。' }); + // monaco theme + const monaco = useMonaco(); + useEffect(() => { + if (monaco) { + monaco.editor.defineTheme('kubepanel', monacoTheme); + } + }, [monaco]); + useEffect(() => { NProgress.start(); const response = createSealosApp(); diff --git a/frontend/plugins/kubepanel/src/pages/api/kubernetes/watch.ts b/frontend/plugins/kubepanel/src/pages/api/kubernetes/watch.ts index 7cefc5f607d..4b3e994bc5c 100644 --- a/frontend/plugins/kubepanel/src/pages/api/kubernetes/watch.ts +++ b/frontend/plugins/kubepanel/src/pages/api/kubernetes/watch.ts @@ -43,7 +43,7 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse params: { resourceVersion, watch: 1, - allowBookmarks: true + allowWatchBookmarks: true }, signal: abortController.signal, responseType: 'stream' diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/action-button.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/action-button.tsx deleted file mode 100644 index a6c0bf2eb2f..00000000000 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/action-button.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { BarsOutlined, CloseOutlined, RetweetOutlined } from '@ant-design/icons'; -import { Button, type MenuProps, Dropdown } from 'antd'; -import DeleteWarningModal from './delete-waring-modal'; -import { Dispatch, SetStateAction, useCallback, useState } from 'react'; -import UpdateEditorModal from './update-editor-modal'; -import { KubeObject } from '@/k8slens/kube-object'; - -interface Props { - obj: K; -} - -const ActionButton = ({ obj }: Props) => { - const [openDeleteModal, setOpenDeleteModal] = useState(false); - const [openUpdateModal, setOpenUpdateModal] = useState(false); - - const items: MenuProps['items'] = [ - { - key: 'delete', - label: ( - - ) - }, - { - key: 'update', - label: ( - - ) - } - ].filter((item) => item.label); - - return ( - // wrapper to stop click event propagation -
e.stopPropagation()}> - - - - setOpenDeleteModal(false)} - onOk={() => setOpenDeleteModal(false)} - /> - setOpenUpdateModal(false)} - onOk={() => setOpenUpdateModal(false)} - /> -
- ); -}; - -export default ActionButton; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/delete-waring-modal.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/delete-waring-modal.tsx deleted file mode 100644 index 460b66a0bb3..00000000000 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/action-button/delete-waring-modal.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { deleteResource } from '@/api/kubernetes'; -import { KubeObject } from '@/k8slens/kube-object'; -import { buildErrorResponse } from '@/services/backend/response'; -import { Button, Input, Modal, message } from 'antd'; -import { useState } from 'react'; - -interface Props { - obj: K; - open: boolean; - onCancel: () => void; - onOk: () => void; -} - -const DeleteWarningModal = ({ - obj, - open, - onCancel, - onOk -}: Props) => { - if (!obj) return null; - - const [isConfirmed, setIsConfirmed] = useState(false); - const [msgApi, contextHolder] = message.useMessage(); - const msgKey = 'deletedMsg'; - - return ( - <> - {contextHolder} - Delete Warning} - open={open} - onCancel={onCancel} - destroyOnClose - footer={[ - , - - ]} - > -
-

- Are you sure to delete {obj.getName()}? -

-

- Please enter Confirm to confirm deletion: -

- { - setIsConfirmed(e.target.value === 'Confirm'); - }} - /> -
-
- - ); -}; - -export default DeleteWarningModal; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/modal/create-resource-modal.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/components/modal/create-resource-modal.tsx deleted file mode 100644 index 58f2f0192f8..00000000000 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/modal/create-resource-modal.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import { KubeObjectKind } from '@/constants/kube-object'; -import { Editor } from '@monaco-editor/react'; -import { editor as EditorNS } from 'monaco-editor'; -import { Button, Cascader, Modal, Spin, message } from 'antd'; -import { BaseOptionType } from 'antd/lib/cascader'; -import React, { useEffect, useRef, useState } from 'react'; -import { createResource, getTemplate } from '@/api/kubernetes'; - -interface Props { - open: boolean; - setClose: () => void; -} - -interface Option extends BaseOptionType { - value: string; - label: string; - children?: Option[]; -} - -const options: Option[] = [ - { - value: 'workload', - label: 'Workload', - children: [ - { - value: KubeObjectKind.Pod, - label: 'Pod' - }, - { - value: KubeObjectKind.Deployment, - label: 'Deployment' - }, - { - value: KubeObjectKind.StatefulSet, - label: 'Stateful Set' - } - ] - }, - { - value: 'network', - label: 'Network', - children: [ - { - value: KubeObjectKind.Ingress, - label: 'Ingress' - } - ] - }, - { - value: 'config', - label: 'Config', - children: [ - { - value: KubeObjectKind.ConfigMap, - label: 'Config Map' - }, - { - value: KubeObjectKind.Secret, - label: 'Secret' - } - ] - }, - { - value: 'storage', - label: 'Storage', - children: [ - { - value: KubeObjectKind.PersistentVolumeClaim, - label: 'Persistent Volume Claim' - } - ] - } -]; - -const defaultTemplate = 'Please select a template first.'; - -const CreateResourceModal = ({ open, setClose }: Props) => { - const [disabled, setDisabled] = useState(true); - const [loading, setLoading] = useState(false); - const [optionValue, setOptionValue] = useState(); - const [template, setTemplate] = useState(defaultTemplate); - const [confirmLoading, setConfirmLoading] = useState(false); - const [msgApi, contextHolder] = message.useMessage(); - - const editorRef = useRef(null); - const onEditorMount = (editor: EditorNS.IStandaloneCodeEditor) => { - editorRef.current = editor; - }; - - const onChange = (value: (string | number)[]) => { - if (!value || value.length === 0) { - setDisabled(true); - setTemplate(defaultTemplate); - return; - } - setDisabled(false); - setOptionValue(value[value.length - 1] as KubeObjectKind); - setLoading(true); - }; - - useEffect(() => { - if (!optionValue) return; - const fetchTemplate = async () => { - const storage = localStorage.getItem(`template-${optionValue}`); - if (!storage) { - try { - const data = await getTemplate(optionValue).then((res) => res.data); - localStorage.setItem(`template-${optionValue}`, data); - setTemplate(data); - } catch (err) { - // TODO: handle error and give a retry button - msgApi.error('Failed to fetch template'); - console.error(err); - } - } else { - setTemplate(storage); - } - setLoading(false); - }; - - fetchTemplate(); - }, [msgApi, optionValue]); - - useEffect(() => { - if (!confirmLoading || !optionValue) return; - const postRequest = async () => { - if (!editorRef.current) return; - try { - const response = await createResource(optionValue, editorRef.current.getValue()); - if (response.code !== 201) { - msgApi.error(`Failed to create resource: ${response.data.message}`); - } else { - msgApi.success('Successfully created resource'); - } - } catch (err) { - msgApi.error(`Failed to create resource: ${err}`); - console.error(err); - } - - setConfirmLoading(false); - }; - - postRequest(); - }, [confirmLoading, msgApi, optionValue]); - - const onCreate = () => { - setConfirmLoading(true); - }; - - return ( - <> - {contextHolder} - - Create - , - - ]} - > -
-
choose a template
- -
- -
- -
-
-
- - ); -}; - -export default CreateResourceModal; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/index.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/index.tsx index 1b89f7aa771..8963eea9625 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/index.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/index.tsx @@ -1,17 +1,17 @@ -import AppLayout from './components/layout'; -import OverviewPage from './components/kube-object/workload/overview/overview'; +import AppLayout from './layout'; +import OverviewPage from './kube-object/workload/overview/overview'; import { useState } from 'react'; -import { SideNavItemKey } from './components/sidebar/sidebar'; -import PodOverviewPage from './components/kube-object/workload/pod/pod'; -import DeploymentOverviewPage from './components/kube-object/workload/deployment/deployment'; -import StatefulSetOverviewPage from './components/kube-object/workload/statefulset/statefulset'; -import ConfigMapOverviewPage from './components/kube-object/config/config-map/config-map'; -import PersistentVolumeClaimOverviewPage from './components/kube-object/storage/volume-claim/volume-claim'; +import { SideNavItemKey } from '../../components/common/sidebar/sidebar'; +import PodOverviewPage from './kube-object/workload/pod/pod'; +import DeploymentOverviewPage from './kube-object/workload/deployment/deployment'; +import StatefulSetOverviewPage from './kube-object/workload/statefulset/statefulset'; +import ConfigMapOverviewPage from './kube-object/config/config-map/config-map'; +import PersistentVolumeClaimOverviewPage from './kube-object/storage/volume-claim/volume-claim'; import { FloatButton } from 'antd'; -import CreateResourceModal from './components/modal/create-resource-modal'; +import { CreateResourceModal } from '@/components/common/action/create-resource-modal'; import { PlusOutlined } from '@ant-design/icons'; -import SecretOverviewPage from './components/kube-object/config/secret/secret'; -import IngressOverviewPage from './components/kube-object/network/ingress/ingress'; +import SecretOverviewPage from './kube-object/config/secret/secret'; +import IngressOverviewPage from './kube-object/network/ingress/ingress'; const switchPage = (key: SideNavItemKey): React.ReactNode => { switch (key) { diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/config-map/config-map-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/config-map/config-map-detail.tsx similarity index 90% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/config-map/config-map-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/config-map/config-map-detail.tsx index 3ae72ec180c..84a2ed37034 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/config-map/config-map-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/config-map/config-map-detail.tsx @@ -1,8 +1,8 @@ import { ConfigMap } from '@/k8slens/kube-object'; -import Drawer from '../../../drawer/drawer'; +import { Drawer } from '@/components/common/drawer/drawer'; import { KubeObjectInfoList } from '@/components/kube/object/detail/kube-object-detail-info-list'; import { entries } from 'lodash'; -import DrawerPanel from '../../../drawer/drawer-panel'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; import { Editor } from '@monaco-editor/react'; const ConfigMapDetail = ({ obj: configMap, open, onClose }: DetailDrawerProps) => { diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/config-map/config-map.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/config-map/config-map.tsx similarity index 83% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/config-map/config-map.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/config-map/config-map.tsx index 98d4825aacd..327e23aa325 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/config-map/config-map.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/config-map/config-map.tsx @@ -3,16 +3,10 @@ import { ConfigMap } from '@/k8slens/kube-object'; import { ColumnsType } from 'antd/es/table'; import ConfigMapDetail from './config-map-detail'; import { useConfigMapStore } from '@/store/kube'; -import PanelTable from '../../../panel-table/table'; -import ActionButton from '../../../action-button/action-button'; +import { PanelTable } from '@/components/common/panel-table/table'; +import { ActionButton } from '@/components/common/action/action-button'; const columns: ColumnsType = [ - { - title: 'Name', - key: 'name', - fixed: 'left', - render: (_, configMap) => configMap.getName() - }, { title: 'Keys', key: 'keys', diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/secret/secret-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/secret/secret-detail.tsx similarity index 96% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/secret/secret-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/secret/secret-detail.tsx index eb95fc2c2df..d15dc35e71d 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/secret/secret-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/secret/secret-detail.tsx @@ -1,7 +1,7 @@ import { Secret } from '@/k8slens/kube-object'; -import DrawerPanel from '../../../drawer/drawer-panel'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; import { KubeObjectInfoList } from '@/components/kube/object/detail/kube-object-detail-info-list'; -import Drawer from '../../../drawer/drawer'; +import { Drawer } from '@/components/common/drawer/drawer'; import React from 'react'; import { Button, Input, Space } from 'antd'; import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons'; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/secret/secret.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/secret/secret.tsx similarity index 85% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/secret/secret.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/secret/secret.tsx index a3e9ecb2226..e5125552c40 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/config/secret/secret.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/config/secret/secret.tsx @@ -4,16 +4,10 @@ import { Secret } from '@/k8slens/kube-object'; import { ColumnsType } from 'antd/lib/table'; import { useSecretStore } from '@/store/kube'; import SecretDetail from './secret-detail'; -import PanelTable from '../../../panel-table/table'; -import ActionButton from '../../../action-button/action-button'; +import { PanelTable } from '@/components/common/panel-table/table'; +import { ActionButton } from '@/components/common/action/action-button'; const columns: ColumnsType = [ - { - title: 'Name', - key: 'name', - fixed: 'left', - render: (_, secret) => secret.getName() - }, { title: 'Labels', key: 'labels', diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/network/ingress/ingress-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/network/ingress/ingress-detail.tsx similarity index 93% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/network/ingress/ingress-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/network/ingress/ingress-detail.tsx index 57282023ec4..6a4fa627d0a 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/network/ingress/ingress-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/network/ingress/ingress-detail.tsx @@ -5,9 +5,9 @@ import { Ingress, computeRuleDeclarations } from '@/k8slens/kube-object'; -import DrawerPanel from '../../../drawer/drawer-panel'; -import Drawer from '../../../drawer/drawer'; -import DrawerItem from '../../../drawer/drawer-item'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; +import { Drawer } from '@/components/common/drawer/drawer'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import { Button, Table } from 'antd'; import { ColumnsType } from 'antd/lib/table'; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/network/ingress/ingress.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/network/ingress/ingress.tsx similarity index 89% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/network/ingress/ingress.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/network/ingress/ingress.tsx index 9f321754d04..2c12c6d99fc 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/network/ingress/ingress.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/network/ingress/ingress.tsx @@ -4,16 +4,10 @@ import { ColumnsType } from 'antd/lib/table'; import { useIngressStore } from '@/store/kube'; import { Button } from 'antd'; import IngressDetail from './ingress-detail'; -import PanelTable from '../../../panel-table/table'; -import ActionButton from '../../../action-button/action-button'; +import { PanelTable } from '@/components/common/panel-table/table'; +import { ActionButton } from '@/components/common/action/action-button'; const columns: ColumnsType = [ - { - title: 'Name', - key: 'name', - fixed: 'left', - render: (_, ingress) => ingress.getName() - }, { title: 'LoadBalancers', key: 'load-balancers', diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/storage/volume-claim/volume-claim-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/storage/volume-claim/volume-claim-detail.tsx similarity index 91% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/storage/volume-claim/volume-claim-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/storage/volume-claim/volume-claim-detail.tsx index 2c07119bb47..71fa1600296 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/storage/volume-claim/volume-claim-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/storage/volume-claim/volume-claim-detail.tsx @@ -1,10 +1,10 @@ import { PersistentVolumeClaim, Pod } from '@/k8slens/kube-object'; -import Drawer from '../../../drawer/drawer'; +import { Drawer } from '@/components/common/drawer/drawer'; import { KubeObjectInfoList } from '@/components/kube/object/detail/kube-object-detail-info-list'; -import DrawerItem from '@/pages/kubepanel/components/drawer/drawer-item'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import { KubeBadge } from '@/components/kube/kube-badge'; import React from 'react'; -import DrawerPanel from '../../../drawer/drawer-panel'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; import { isArray } from 'lodash'; const PersistentVolumeClaimDetail = ({ diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/storage/volume-claim/volume-claim.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/storage/volume-claim/volume-claim.tsx similarity index 83% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/storage/volume-claim/volume-claim.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/storage/volume-claim/volume-claim.tsx index 2672aa70144..b68b91c4459 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/storage/volume-claim/volume-claim.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/storage/volume-claim/volume-claim.tsx @@ -3,16 +3,10 @@ import { PersistentVolumeClaim, Pod } from '@/k8slens/kube-object'; import { ColumnsType } from 'antd/es/table'; import PersistentVolumeClaimDetail from './volume-claim-detail'; import { usePodStore, useVolumeClaimStore } from '@/store/kube'; -import PanelTable from '../../../panel-table/table'; -import ActionButton from '../../../action-button/action-button'; +import { PanelTable } from '@/components/common/panel-table/table'; +import { ActionButton } from '@/components/common/action/action-button'; const columns: ColumnsType<{ volumeClaim: PersistentVolumeClaim; pods: Pod[] }> = [ - { - title: 'Name', - key: 'name', - fixed: 'left', - render: (_, { volumeClaim }) => volumeClaim.getName() - }, { title: 'Storage Class', key: 'storageClass', @@ -79,11 +73,17 @@ const PersistentVolumeClaimOverviewPage = () => { dataSource={dataSource} loading={!isVolumeClaimsLoaded || !isPodsLoaded} sectionTitle="Persistent Volume Claims" - DetailDrawer={PersistentVolumeClaimDetail} + DetailDrawer={({ obj, open, onClose }) => ( + + )} getRowKey={({ volumeClaim }) => volumeClaim.getId()} initializers={[initializeVolumeClaims, initializePods]} watchers={[watchVolumeClaims, watchPods]} - getDetailItem={(record) => record} + getDetailItem={(record) => record.volumeClaim} /> ); }; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/deployment/deployment-detail.tsx similarity index 92% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/deployment/deployment-detail.tsx index c526aab02a7..e634f741d9f 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/deployment/deployment-detail.tsx @@ -1,13 +1,13 @@ import { KubeBadge } from '@/components/kube/kube-badge'; -import DrawerItem from '@/pages/kubepanel/components/drawer/drawer-item'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import { KubeObjectInfoList } from '@/components/kube/object/detail/kube-object-detail-info-list'; import { Deployment } from '@/k8slens/kube-object'; import { getConditionColor } from '@/utils/condtion-color'; import { Tooltip } from 'antd'; import PodDetailTolerations from '../pod/pod-detail-tolerations'; import PodDetailAffinities from '../pod/pod-detail-affinities'; -import Drawer from '../../../drawer/drawer'; -import DrawerPanel from '../../../drawer/drawer-panel'; +import { Drawer } from '@/components/common/drawer/drawer'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; const DeploymentDetail = ({ obj: dep, open, onClose }: DetailDrawerProps) => { if (!dep || !(dep instanceof Deployment)) { diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/deployment/deployment.tsx similarity index 88% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/deployment/deployment.tsx index 2b04a08598c..b4bb0f0b19a 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/deployment/deployment.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/deployment/deployment.tsx @@ -5,16 +5,10 @@ import { Tooltip } from 'antd'; import { ColumnsType } from 'antd/es/table'; import DeploymentDetail from './deployment-detail'; import { useDeploymentStore } from '@/store/kube'; -import PanelTable from '../../../panel-table/table'; -import ActionButton from '../../../action-button/action-button'; +import { PanelTable } from '@/components/common/panel-table/table'; +import { ActionButton } from '@/components/common/action/action-button'; const columns: ColumnsType = [ - { - title: 'Name', - key: 'name', - fixed: 'left', - render: (_, dep) => dep.getName() - }, { title: 'Pods', key: 'pods', diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/event-overview.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/event-overview.tsx similarity index 81% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/event-overview.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/event-overview.tsx index 3e799e7d8f8..f5951adc686 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/event-overview.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/event-overview.tsx @@ -1,13 +1,11 @@ import Title from '@/components/common/title/title'; import { KubeObjectAge } from '@/components/kube/object/kube-object-age'; import { ReactiveDuration } from '@/components/kube/reactive-duration'; +import { useWatcher } from '@/hooks/useWatcher'; import { KubeEvent, ObjectReference } from '@/k8slens/kube-object'; import { useEventStore } from '@/store/k8s/event.store'; -import { APICallback } from '@/types/state'; import { Table, Tooltip } from 'antd'; -import useNotification from 'antd/lib/notification/useNotification'; import { ColumnsType } from 'antd/lib/table'; -import { useCallback, useEffect } from 'react'; const columns: ColumnsType = [ { @@ -79,24 +77,8 @@ const columns: ColumnsType = [ ]; const EventOverview = () => { - const { items, initialize, isLoaded } = useEventStore(); - const [notifyApi, cxtHolder] = useNotification(); - const callback = useCallback( - (_, e) => { - if (e) { - notifyApi.error({ - message: e.error.reason, - description: e.error.message, - duration: 5 - }); - } - }, - [notifyApi] - ); - - useEffect(() => { - initialize(callback); - }, []); + const { items, initialize, isLoaded, watch } = useEventStore(); + const cxtHolder = useWatcher({ initializers: [initialize], watchers: [watch] }); return ( <> diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/overview.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/overview.tsx similarity index 59% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/overview.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/overview.tsx index 5de5c5e57c8..3a7db147d0c 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/overview.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/overview.tsx @@ -2,7 +2,6 @@ import { Flex } from 'antd'; import WorkloadStatusOverview from './status-overview'; import { convertToPieChartStatusData } from '@/utils/pie-chart'; import { entries, startCase } from 'lodash'; -import { useCallback, useEffect } from 'react'; import { getDeploymentsStatuses, getStatefulSetsStatuses, @@ -13,32 +12,17 @@ import { import { Section } from '@/components/common/section/section'; import Title from '@/components/common/title/title'; import EventOverview from './event-overview'; -import { APICallback } from '@/types/state'; -import useNotification from 'antd/lib/notification/useNotification'; +import { useWatcher } from '@/hooks/useWatcher'; const OverviewPage = () => { - const { items: pods, initialize: initializePods, getStatuses: getPodStatuses } = usePodStore(); - const { items: deps, initialize: initializeDeployments } = useDeploymentStore(); - const { items: stats, initialize: initializeStatefulSets } = useStatefulSetStore(); - const [notifyApi, cxtHolder] = useNotification(); - const callback = useCallback( - (_, e) => { - if (e) { - notifyApi.error({ - message: e.error.reason, - description: e.error.message, - duration: 5 - }); - } - }, - [notifyApi] - ); + const { items: pods, initialize: initializePods, watch: watchPods, getStatuses: getPodStatuses } = usePodStore(); + const { items: deps, initialize: initializeDeployments, watch: watchDeployments } = useDeploymentStore(); + const { items: stats, initialize: initializeStatefulSets, watch: watchStatefulSets } = useStatefulSetStore(); - useEffect(() => { - initializePods(callback); - initializeDeployments(callback); - initializeStatefulSets(callback); - }, []); + const cxtHolder = useWatcher({ + initializers: [initializePods, initializeDeployments, initializeStatefulSets], + watchers: [watchPods, watchDeployments, watchStatefulSets] + }); const statuses = { Pod: convertToPieChartStatusData(getPodStatuses), diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/status-chart.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/status-chart.tsx similarity index 100% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/status-chart.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/status-chart.tsx diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/status-overview.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/status-overview.tsx similarity index 100% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/overview/status-overview.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/overview/status-overview.tsx diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/container-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/container-detail.tsx similarity index 96% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/container-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/container-detail.tsx index 8d7c05a9cae..87b6fab2764 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/container-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/container-detail.tsx @@ -1,13 +1,13 @@ import { Container, Pod } from '@/k8slens/kube-object'; import ContainerStatusBrick from './container-status-brick'; import { keys } from 'lodash'; -import DrawerItem from '@/pages/kubepanel/components/drawer/drawer-item'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import ContainerStatus, { ContainerLastState } from './container-status'; import { KubeBadge } from '@/components/kube/kube-badge'; import { Tooltip } from 'antd'; import { isDefined } from '@/k8slens/utilities'; import React from 'react'; -import DrawerPanel from '../../../drawer/drawer-panel'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; interface Props { pod?: Pod; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/container-status-brick.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/container-status-brick.tsx similarity index 100% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/container-status-brick.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/container-status-brick.tsx diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/container-status.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/container-status.tsx similarity index 100% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/container-status.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/container-status.tsx diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-affinities.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-affinities.tsx similarity index 90% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-affinities.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-affinities.tsx index d48c54d4fad..0c9a02e3152 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-affinities.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-affinities.tsx @@ -1,7 +1,7 @@ import { Input } from 'antd'; import { DaemonSet, Deployment, Job, Pod, ReplicaSet, StatefulSet } from '@/k8slens/kube-object'; import yaml from 'js-yaml'; -import DrawerCollapse from '../../../drawer/drawer-collapse'; +import { DrawerCollapse } from '@/components/common/drawer/drawer-collapse'; export type Props = { workload?: Pod | Deployment | DaemonSet | StatefulSet | ReplicaSet | Job; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-statuses.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-statuses.tsx similarity index 100% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-statuses.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-statuses.tsx diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-tolerations.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-tolerations.tsx similarity index 90% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-tolerations.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-tolerations.tsx index 0780e683485..7833d6c07b9 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail-tolerations.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail-tolerations.tsx @@ -1,6 +1,6 @@ import { KubeObjectTolerations } from '@/components/kube/object/kube-object-tolerations'; import { KubeObject, Toleration } from '@/k8slens/kube-object'; -import DrawerCollapse from '../../../drawer/drawer-collapse'; +import { DrawerCollapse } from '@/components/common/drawer/drawer-collapse'; interface KubeObjectWithTolerations extends KubeObject { getTolerations(): Toleration[]; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail.tsx similarity index 94% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail.tsx index 3e414b5d89e..53be503acfb 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-detail.tsx @@ -1,4 +1,4 @@ -import DrawerItem from '@/pages/kubepanel/components/drawer/drawer-item'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import { KubeObjectInfoList } from '@/components/kube/object/detail/kube-object-detail-info-list'; import { Pod } from '@/k8slens/kube-object'; import { Tooltip } from 'antd'; @@ -7,8 +7,8 @@ import { KubeBadge } from '@/components/kube/kube-badge'; import PodDetailTolerations from './pod-detail-tolerations'; import PodDetailAffinities from './pod-detail-affinities'; import ContainerDetail from './container-detail'; -import Drawer from '../../../drawer/drawer'; -import DrawerPanel from '../../../drawer/drawer-panel'; +import { Drawer } from '@/components/common/drawer/drawer'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; const PodDetail = ({ obj: pod, open, onClose }: DetailDrawerProps) => { if (!pod || !(pod instanceof Pod)) return null; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-status.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-status.tsx similarity index 100% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod-status.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod-status.tsx diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod.tsx similarity index 92% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod.tsx index 29870c59756..f216f53d3e5 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/pod/pod.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/pod/pod.tsx @@ -9,16 +9,10 @@ import { PodStatusMessage } from '@/constants/pod'; import PodStatus from './pod-status'; import PodDetail from './pod-detail'; import { usePodStore } from '@/store/kube'; -import PanelTable from '../../../panel-table/table'; -import ActionButton from '../../../action-button/action-button'; +import { PanelTable } from '@/components/common/panel-table/table'; +import { ActionButton } from '@/components/common/action/action-button'; const columns: ColumnsType = [ - { - title: 'Name', - key: 'name', - fixed: 'left', - render: (_, pod) => pod.getName() - }, { title: 'Containers', key: 'containers', diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/statefulset/statefulset-detail.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/statefulset/statefulset-detail.tsx similarity index 72% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/statefulset/statefulset-detail.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/statefulset/statefulset-detail.tsx index 42cfd7fc663..a2adf2e65c5 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/statefulset/statefulset-detail.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/statefulset/statefulset-detail.tsx @@ -1,22 +1,21 @@ -import { Pod, StatefulSet } from '@/k8slens/kube-object'; -import Drawer from '../../../drawer/drawer'; +import { StatefulSet } from '@/k8slens/kube-object'; +import { Drawer } from '@/components/common/drawer/drawer'; import { KubeObjectInfoList } from '@/components/kube/object/detail/kube-object-detail-info-list'; import PodDetailTolerations from '../pod/pod-detail-tolerations'; import PodDetailAffinities from '../pod/pod-detail-affinities'; -import DrawerItem from '@/pages/kubepanel/components/drawer/drawer-item'; +import { DrawerItem } from '@/components/common/drawer/drawer-item'; import PodDetailStatuses from '../pod/pod-detail-statuses'; import { KubeBadge } from '@/components/kube/kube-badge'; -import DrawerPanel from '../../../drawer/drawer-panel'; +import { DrawerPanel } from '@/components/common/drawer/drawer-panel'; import { isArray } from 'lodash'; +import { getPodsByOwnerId, usePodStore } from '@/store/kube'; -const StatefulSetDetail = ({ - obj, - open, - onClose -}: DetailDrawerProps<{ stat: StatefulSet; childPods: Pod[] }>) => { - if (!obj) return null; +const StatefulSetDetail = ({ obj: stat, open, onClose }: DetailDrawerProps) => { + if (!stat) return null; + + const { items: pods } = usePodStore(); + const childPods = getPodsByOwnerId(pods, stat.getId()); - const { stat, childPods } = obj; if (!stat || !(stat instanceof StatefulSet)) return null; if (!childPods || !isArray(childPods)) return null; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/statefulset/statefulset.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/statefulset/statefulset.tsx similarity index 71% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/statefulset/statefulset.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/statefulset/statefulset.tsx index 61d74c5753b..74c9b908d8e 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/kube-object/workload/statefulset/statefulset.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/kube-object/workload/statefulset/statefulset.tsx @@ -2,17 +2,11 @@ import { KubeObjectAge } from '@/components/kube/object/kube-object-age'; import { StatefulSet } from '@/k8slens/kube-object'; import { ColumnsType } from 'antd/es/table'; import StatefulSetDetail from './statefulset-detail'; -import { getPodsByOwnerId, usePodStore, useStatefulSetStore } from '@/store/kube'; -import PanelTable from '../../../panel-table/table'; -import ActionButton from '../../../action-button/action-button'; +import { usePodStore, useStatefulSetStore } from '@/store/kube'; +import { PanelTable } from '@/components/common/panel-table/table'; +import { ActionButton } from '@/components/common/action/action-button'; const columns: ColumnsType = [ - { - title: 'Name', - key: 'name', - fixed: 'left', - render: (_, stat) => stat.getName() - }, { title: 'Pods', key: 'pods', @@ -39,12 +33,8 @@ const columns: ColumnsType = [ ]; const StatefulSetOverviewPage = () => { - const { - items: pods, - initialize: initializePods, - isLoaded: isPodsLoaded, - watch: watchPods - } = usePodStore(); + // The detailed information of Stateful Set resource needs to be provided by Pod resource. + const { initialize: initializePods, isLoaded: isPodsLoaded, watch: watchPods } = usePodStore(); const { items: stats, initialize: initializeStats, @@ -62,7 +52,7 @@ const StatefulSetOverviewPage = () => { getRowKey={(stat) => stat.getId()} initializers={[initializeStats, initializePods]} watchers={[watchStats, watchPods]} - getDetailItem={(stat) => ({ stat, childPods: getPodsByOwnerId(pods, stat.getId()) })} + getDetailItem={(stat) => stat} /> ); }; diff --git a/frontend/plugins/kubepanel/src/pages/kubepanel/components/layout.tsx b/frontend/plugins/kubepanel/src/pages/kubepanel/layout.tsx similarity index 94% rename from frontend/plugins/kubepanel/src/pages/kubepanel/components/layout.tsx rename to frontend/plugins/kubepanel/src/pages/kubepanel/layout.tsx index 9cf3dbcf00c..f33c643ee2c 100644 --- a/frontend/plugins/kubepanel/src/pages/kubepanel/components/layout.tsx +++ b/frontend/plugins/kubepanel/src/pages/kubepanel/layout.tsx @@ -1,5 +1,5 @@ import { ConfigProvider, Layout } from 'antd'; -import ResourceSideNav, { SideNavItemKey } from './sidebar/sidebar'; +import { ResourceSideNav, SideNavItemKey } from '@/components/common/sidebar/sidebar'; import { theme } from '@/constants/theme'; import { useCallback, useState } from 'react'; import { CollapseType } from 'antd/es/layout/Sider'; diff --git a/frontend/plugins/kubepanel/src/store/k8s/kube.store.ts b/frontend/plugins/kubepanel/src/store/k8s/kube.store.ts index 93641237988..9d11323a93e 100644 --- a/frontend/plugins/kubepanel/src/store/k8s/kube.store.ts +++ b/frontend/plugins/kubepanel/src/store/k8s/kube.store.ts @@ -85,7 +85,7 @@ export function createKubeStoreSlice< callback(undefined, evt.data); }; - nxtES.addEventListener('watch', (evt) => { + nxtES.addEventListener('watch', async (evt) => { const data = JSON.parse(evt.data) as WatchEvent; if (data.type === 'ERROR') { const kubeStatus = data.object as KubeStatus; @@ -93,9 +93,22 @@ export function createKubeStoreSlice< // callback hook must recall this function if (kubeStatus.code === 410) { nxtES.close(); - console.log('finished watching'); - } - console.log('watch error', kubeStatus); + console.log('finished watching, then start reinitialize'); + try { + const res = await listResources(kind); + const parsed = parseResponse(res.data, kind, objConstructor); + set({ + items: parsed.sort((a, b) => a.getName().localeCompare(b.getName())), + resourceVersion: res.data.metadata.resourceVersion + }); + } catch (err: any) { + console.log('Failed to reinitialize', err); + err.message = + 'Failed to reinitialize, you need to refresh this page, sorry.\n' + err.message; + callback(undefined, buildErrorResponse(err)); + } + } else console.log('watch error', kubeStatus); + callback( undefined, buildErrorResponse( @@ -110,7 +123,7 @@ export function createKubeStoreSlice< return; } - set({ resourceVersion: data.object.metadata.resourceVersion }); + console.log('watch data', data); switch (data.type) { case 'ADDED': case 'MODIFIED': diff --git a/frontend/plugins/kubepanel/src/styles/globals.css b/frontend/plugins/kubepanel/src/styles/globals.css index f39f257a89b..871b9b9bbb9 100644 --- a/frontend/plugins/kubepanel/src/styles/globals.css +++ b/frontend/plugins/kubepanel/src/styles/globals.css @@ -21,3 +21,39 @@ @tailwind base; @tailwind components; @tailwind utilities; + +/* dropdown style overrides */ +#app .ant-dropdown-menu-item { + text-align: center; + color: #485264; + + &:hover { + color: #0884dd; + background-color: #9699b41a; + } +} +#app .ant-dropdown-menu-submenu-title { + color: #485264; + + &:hover { + color: #0884dd; + background-color: #9699b41a; + } +} + +/* btn style overrides */ +#app .ant-btn-primary { + color: #fff; + background-color: #111824; + + &:hover { + background-color: #111824e5; + } + + &:disabled { + cursor: not-allowed; + border-color: var(--ant-button-border-color-disabled); + color: var(--ant-color-text-disabled); + background: var(--ant-color-bg-container-disabled); + } +} \ No newline at end of file diff --git a/frontend/plugins/kubepanel/src/utils/pie-chart.ts b/frontend/plugins/kubepanel/src/utils/pie-chart.ts index a7bb23a16f5..0d5aa7975ba 100644 --- a/frontend/plugins/kubepanel/src/utils/pie-chart.ts +++ b/frontend/plugins/kubepanel/src/utils/pie-chart.ts @@ -1,4 +1,4 @@ -import { WorkloadStatusData } from '@/pages/kubepanel/components/kube-object/workload/overview/status-chart'; +import { WorkloadStatusData } from '@/pages/kubepanel/kube-object/workload/overview/status-chart'; import { Dictionary, capitalize, entries } from 'lodash'; export const convertToPieChartStatusData = (dict: Dictionary) => {