From c0e9b70d9ff9a9c5fa59e37ec2b38493102f535f Mon Sep 17 00:00:00 2001 From: Bowen Tan Date: Thu, 25 Jul 2024 17:55:32 +0800 Subject: [PATCH 1/2] feat: add more pvc columns and fields --- packages/refine/src/App.tsx | 2 + .../src/components/ResourceFiledDisplays.tsx | 34 +++++++ .../src/components/ShowContent/fields.tsx | 99 +++++++++++++++++-- .../src/components/ShowContent/groups.tsx | 2 +- packages/refine/src/components/index.ts | 1 + .../src/hooks/useEagleTable/columns.tsx | 79 +++++++++++---- .../refine/src/locales/en-US/dovetail.json | 16 ++- .../refine/src/locales/zh-CN/dovetail.json | 15 ++- .../src/pages/persistentvolumeclaims/index.ts | 56 +++++++++++ .../src/pages/persistentvolumes/index.ts | 20 ++-- .../refine/src/pages/storageclasses/index.ts | 9 +- 11 files changed, 285 insertions(+), 48 deletions(-) create mode 100644 packages/refine/src/components/ResourceFiledDisplays.tsx create mode 100644 packages/refine/src/pages/persistentvolumeclaims/index.ts diff --git a/packages/refine/src/App.tsx b/packages/refine/src/App.tsx index 1bce248c..48a2338f 100644 --- a/packages/refine/src/App.tsx +++ b/packages/refine/src/App.tsx @@ -22,6 +22,7 @@ import { IngressConfig } from './pages/ingresses'; import { JobConfig } from './pages/jobs'; import { NetworkPolicyConfig } from './pages/networkPolicies'; import { NodeList, NodeShow } from './pages/nodes'; +import { PersistentVolumeClaimConfig } from './pages/persistentvolumeclaims'; import { PersistentVolumeConfig } from './pages/persistentvolumes'; import { PodShow, PodList, PodForm } from './pages/pods'; import { SecretsConfig } from './pages/secrets'; @@ -93,6 +94,7 @@ function App() { }, StorageClassConfig(i18n), PersistentVolumeConfig(i18n), + PersistentVolumeClaimConfig(i18n), { name: 'serverinstances', basePath: '/apis/kubesmart.smtx.io/v1alpha1', diff --git a/packages/refine/src/components/ResourceFiledDisplays.tsx b/packages/refine/src/components/ResourceFiledDisplays.tsx new file mode 100644 index 00000000..551dcdc5 --- /dev/null +++ b/packages/refine/src/components/ResourceFiledDisplays.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +interface Props { + value: string; +} + +export function PVPhaseDisplay(props: Props) { + const {value} = props; + const i18n = useTranslation(); + + const map = { + Available: i18n.t('dovetail.pv_phase_available'), + Bound: i18n.t('dovetail.pv_phase_bound'), + Failed: i18n.t('dovetail.pv_phase_released'), + Pending: i18n.t('dovetail.pv_phase_failed'), + Released: i18n.t('dovetail.pv_phase_pending'), + }; + + return
{map[value as keyof typeof map] || value}
; +} + +export function PVVolumeModeDisplay(props: Props) { + const {value} = props; + const i18n = useTranslation(); + + const map = { + Block: i18n.t('dovetail.block'), + Filesystem: i18n.t('dovetail.file_system'), + }; + + return
{map[value as keyof typeof map] || value}
; +} + diff --git a/packages/refine/src/components/ShowContent/fields.tsx b/packages/refine/src/components/ShowContent/fields.tsx index 22a9aec1..b3cbbf95 100644 --- a/packages/refine/src/components/ShowContent/fields.tsx +++ b/packages/refine/src/components/ShowContent/fields.tsx @@ -1,3 +1,4 @@ +import { Units } from '@cloudtower/eagle'; import { i18n as I18nType } from 'i18next'; import { Unstructured } from 'k8s-api-provider'; import { Condition } from 'kubernetes-types/meta/v1'; @@ -26,14 +27,17 @@ import { ServiceType, StorageClassModel, PersistentVolumeModel, + PersistentVolumeClaimModel, } from '../../models'; import { ExtendObjectMeta } from '../../plugins/relation-plugin'; +import { parseSi } from '../../utils/unit'; import { ConditionsTable } from '../ConditionsTable'; import { CronjobJobsTable } from '../CronjobJobsTable'; import { EventsTable } from '../EventsTable'; import { ImageNames } from '../ImageNames'; import { IngressRulesTable } from '../IngressRulesTable'; import { KeyValue, KeyValueAnnotation, KeyValueSecret } from '../KeyValue'; +import { PVPhaseDisplay, PVVolumeModeDisplay } from '../ResourceFiledDisplays'; import { ResourceLink } from '../ResourceLink'; import { Time } from '../Time'; import { WorkloadPodsTable } from '../WorkloadPodsTable'; @@ -393,16 +397,6 @@ export const StorageClassProvisionerField = ( }; }; -export const StorageClassFsTypeField = ( - i18n: I18nType -): ShowField => { - return { - key: 'fstype', - path: ['parameters', 'csi.storage.k8s.io/fstype'], - title: i18n.t('dovetail.file_system'), - }; -}; - export const StorageClassPvField = < Model extends StorageClassModel, >(): ShowField => { @@ -422,3 +416,88 @@ export const StorageClassPvField = < }, }; }; + +export const PVCapacityField = ( + i18n: I18nType +): ShowField => { + return { + key: 'capacity', + path: ['spec', 'capacity', 'storage'], + title: i18n.t('dovetail.capacity'), + renderContent(value) { + return ; + }, + }; +}; + +export const PVCStorageField = ( + i18n: I18nType +): ShowField => { + return { + key: 'storage', + path: ['spec', 'resources', 'requests', 'storage'], + title: i18n.t('dovetail.capacity'), + renderContent(value) { + return ; + }, + }; +}; + +export const PVStorageClassField = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( + i18n: I18nType +): ShowField => { + return { + key: 'storageClass', + path: ['spec', 'storageClassName'], + title: i18n.t('dovetail.storage_class'), + renderContent(value) { + return ( + + ); + }, + }; +}; + +export const PVPhaseField = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( + i18n: I18nType +): ShowField => { + return { + key: 'phase', + path: ['status', 'phase'], + title: i18n.t('dovetail.phase'), + renderContent(value) { + return ; + }, + }; +}; + +export const PVVolumeModeField = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( + i18n: I18nType +): ShowField => { + return { + key: 'mode', + path: ['spec', 'volumeMode'], + title: i18n.t('dovetail.volume_mode'), + renderContent(value) { + return ; + }, + }; +}; + +export const PVAccessModeField = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( + i18n: I18nType +): ShowField => { + return { + key: 'accessMode', + path: ['spec', 'accessModes'], + title: i18n.t('dovetail.access_mode'), + }; +}; diff --git a/packages/refine/src/components/ShowContent/groups.tsx b/packages/refine/src/components/ShowContent/groups.tsx index 03966365..c3ac955a 100644 --- a/packages/refine/src/components/ShowContent/groups.tsx +++ b/packages/refine/src/components/ShowContent/groups.tsx @@ -234,7 +234,7 @@ export const NetworkPolicyEgressRulesGroup = ( export const StorageClassPvGroup = ( i18n: I18nType ): ShowGroup => ({ - title: i18n.t('dovetail.persistent_volumn'), + title: i18n.t('dovetail.persistent_volume'), areas: [ { fields: [StorageClassPvField()], diff --git a/packages/refine/src/components/index.ts b/packages/refine/src/components/index.ts index caf4f6b2..bcc4af17 100644 --- a/packages/refine/src/components/index.ts +++ b/packages/refine/src/components/index.ts @@ -38,6 +38,7 @@ export * from './Tags'; export * from './TextTags'; export * from './PodLog'; export * from './NetworkPolicyRulesViewer'; +export * from './ResourceFiledDisplays'; export * from './Tabs'; export * as ValueDisplay from './ValueDisplay'; export * from './ResourceSelect'; diff --git a/packages/refine/src/hooks/useEagleTable/columns.tsx b/packages/refine/src/hooks/useEagleTable/columns.tsx index 121b89ef..5939749b 100644 --- a/packages/refine/src/hooks/useEagleTable/columns.tsx +++ b/packages/refine/src/hooks/useEagleTable/columns.tsx @@ -1,4 +1,12 @@ -import { Button, Time as BaseTime, Tooltip, OverflowTooltip, Divider, Link } from '@cloudtower/eagle'; +import { + Button, + Time as BaseTime, + Tooltip, + OverflowTooltip, + Divider, + Link, + Units, +} from '@cloudtower/eagle'; import { css } from '@linaria/core'; import { useGo, useNavigation, useParsed } from '@refinedev/core'; import { i18n as I18nType } from 'i18next'; @@ -11,6 +19,9 @@ import { useTranslation } from 'react-i18next'; import { DurationTime } from 'src/components/DurationTime'; import ValueDisplay from 'src/components/ValueDisplay'; import { + PVPhaseDisplay, + PVVolumeModeDisplay, + ResourceLink, ServiceInClusterAccessComponent, ServiceOutClusterAccessComponent, } from '../../components'; @@ -31,8 +42,10 @@ import { ServiceModel, DaemonSetModel, StorageClassModel, - PersistentVolumeModel + PersistentVolumeModel, + PersistentVolumeClaimModel, } from '../../models'; +import { parseSi } from '../../utils/unit'; const DashedTitleStyle = css` border-bottom: 1px dashed rgba(107, 128, 167, 0.6); @@ -135,12 +148,12 @@ export const NameSpaceColumnRenderer = ( export const StateDisplayColumnRenderer = < Model extends - | WorkloadModel - | CronJobModel - | PodModel - | ServiceModel - | DaemonSetModel - | JobModel, + | WorkloadModel + | CronJobModel + | PodModel + | ServiceModel + | DaemonSetModel + | JobModel, >( i18n: I18nType ): Column => { @@ -614,7 +627,6 @@ export const PortMappingColumnRenderer = ( }; }; - export const ProvisionerColumnRenderer = ( i18n: I18nType ): Column => { @@ -628,33 +640,43 @@ export const ProvisionerColumnRenderer = ( }; }; -export const FsTypeColumnRenderer = ( +export const PVCapacityColumnRenderer = ( i18n: I18nType ): Column => { return { - key: 'fstype', + key: 'capacity', display: true, - dataIndex: ['parameters', 'csi.storage.k8s.io/fstype'], - title: i18n.t('dovetail.file_system'), + dataIndex: ['spec', 'capacity', 'storage'], + title: i18n.t('dovetail.capacity'), width: 120, sortable: true, + align:'right', + render(value) { + return ; + }, }; }; -export const PVCapacityColumnRenderer = ( +export const PVCStorageColumnRenderer = ( i18n: I18nType ): Column => { return { - key: 'capacity', + key: 'storage', display: true, - dataIndex: ['spec', 'capacity', 'storage'], + dataIndex: ['spec', 'resources', 'requests', 'storage'], title: i18n.t('dovetail.capacity'), width: 120, sortable: true, + align:'right', + render(value) { + return ; + }, }; }; -export const PVStorageClassColumnRenderer = ( +export const PVStorageClassColumnRenderer = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( i18n: I18nType ): Column => { return { @@ -664,10 +686,17 @@ export const PVStorageClassColumnRenderer = + ); + }, }; }; -export const PVPhaseColumnRenderer = ( +export const PVPhaseColumnRenderer = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( i18n: I18nType ): Column => { return { @@ -677,10 +706,15 @@ export const PVPhaseColumnRenderer = ( title: i18n.t('dovetail.phase'), width: 120, sortable: true, + render(value) { + return ; + }, }; }; -export const PVModeColumnRenderer = ( +export const PVVolumeModeColumnRenderer = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( i18n: I18nType ): Column => { return { @@ -690,10 +724,15 @@ export const PVModeColumnRenderer = ( title: i18n.t('dovetail.volume_mode'), width: 120, sortable: true, + render(value) { + return ; + }, }; }; -export const PVAccessModeColumnRenderer = ( +export const PVAccessModeColumnRenderer = < + Model extends PersistentVolumeModel | PersistentVolumeClaimModel, +>( i18n: I18nType ): Column => { return { diff --git a/packages/refine/src/locales/en-US/dovetail.json b/packages/refine/src/locales/en-US/dovetail.json index 9187f98a..6427d686 100644 --- a/packages/refine/src/locales/en-US/dovetail.json +++ b/packages/refine/src/locales/en-US/dovetail.json @@ -153,5 +153,19 @@ "only_support_one_yaml": "Only one YAML configuration is supported at a time.", "not_support": "Not supported", "stopped": "Stopped", - "any_node_ip": "Any node IP" + "any_node_ip": "Any node IP", + "storage_class": "Storage class", + "persistent_volume": "Persistent volume", + "provisioner": "Provisioner", + "file_system": "File system", + "capacity": "Capacity", + "phase": "Phase", + "volume_mode": "Volume mode", + "access_mode": "Access mode", + "block": "Block", + "pv_phase_available": "Available", + "pv_phase_bound": "Bound", + "pv_phase_released": "Released", + "pv_phase_failed": "Failed", + "pv_phase_pending": "Pending" } diff --git a/packages/refine/src/locales/zh-CN/dovetail.json b/packages/refine/src/locales/zh-CN/dovetail.json index 5f6ca8c1..6b037a8a 100644 --- a/packages/refine/src/locales/zh-CN/dovetail.json +++ b/packages/refine/src/locales/zh-CN/dovetail.json @@ -154,8 +154,19 @@ "only_support_one_yaml": "一次仅支持输入一个 YAML 配置。", "not_support": "不支持", "stopped": "已停止", + "any_node_ip": "任意节点 IP", "storage_class": "存储类", - "persistent_volumn": "持久卷", + "persistent_volume": "持久卷", "provisioner": "制备器", - "file_system": "文件系统" + "file_system": "文件系统", + "capacity": "容量", + "phase": "阶段", + "volume_mode": "卷模式", + "access_mode": "访问模式", + "block": "块", + "pv_phase_available": "可用", + "pv_phase_bound": "已绑定", + "pv_phase_released": "已释放", + "pv_phase_failed": "失败", + "pv_phase_pending": "等待中" } diff --git a/packages/refine/src/pages/persistentvolumeclaims/index.ts b/packages/refine/src/pages/persistentvolumeclaims/index.ts new file mode 100644 index 00000000..f16ec3a6 --- /dev/null +++ b/packages/refine/src/pages/persistentvolumeclaims/index.ts @@ -0,0 +1,56 @@ +import { i18n as I18n } from 'i18next'; +import { BasicGroup } from 'src/components/ShowContent/groups'; +import { + AgeColumnRenderer, + PVAccessModeColumnRenderer, + PVCStorageColumnRenderer, + PVVolumeModeColumnRenderer, + PVPhaseColumnRenderer, + PVStorageClassColumnRenderer, +} from 'src/hooks/useEagleTable/columns'; +import { RESOURCE_GROUP, ResourceConfig } from 'src/types'; +import { + PVAccessModeField, + PVCStorageField, + PVPhaseField, + PVStorageClassField, + PVVolumeModeField, +} from '../../components'; +import { PersistentVolumeClaimModel } from '../../models'; + +export const PersistentVolumeClaimConfig = (i18n: I18n): ResourceConfig => ({ + name: 'persistentvolumeclaims', + basePath: '/api/v1', + apiVersion: 'v1', + kind: 'PersistentVolumeclaim', + parent: RESOURCE_GROUP.STORAGE, + label: 'PersistentVolumeclaims', + initValue: {}, + columns: () => [ + PVCStorageColumnRenderer(i18n), + PVStorageClassColumnRenderer(i18n), + PVPhaseColumnRenderer(i18n), + PVVolumeModeColumnRenderer(i18n), + PVAccessModeColumnRenderer(i18n), + AgeColumnRenderer(i18n), + ], + showConfig: () => ({ + tabs: [ + { + title: i18n.t('dovetail.detail'), + key: 'detail', + groups: [ + BasicGroup(i18n, { + basicFields: [ + PVCStorageField(i18n), + PVStorageClassField(i18n), + PVPhaseField(i18n), + PVVolumeModeField(i18n), + PVAccessModeField(i18n), + ], + }), + ], + }, + ], + }), +}); diff --git a/packages/refine/src/pages/persistentvolumes/index.ts b/packages/refine/src/pages/persistentvolumes/index.ts index 08d68e56..8060f8da 100644 --- a/packages/refine/src/pages/persistentvolumes/index.ts +++ b/packages/refine/src/pages/persistentvolumes/index.ts @@ -2,16 +2,17 @@ import { i18n as I18n } from 'i18next'; import { BasicGroup } from 'src/components/ShowContent/groups'; import { AgeColumnRenderer, - NameSpaceColumnRenderer, PVAccessModeColumnRenderer, PVCapacityColumnRenderer, - PVModeColumnRenderer, + PVVolumeModeColumnRenderer, PVPhaseColumnRenderer, PVStorageClassColumnRenderer, } from 'src/hooks/useEagleTable/columns'; -import { RESOURCE_GROUP } from 'src/types'; +import { RESOURCE_GROUP, ResourceConfig } from 'src/types'; +import { PVAccessModeField, PVCapacityField, PVPhaseField, PVStorageClassField, PVVolumeModeField } from '../../components'; +import { PersistentVolumeModel } from '../../models'; -export const PersistentVolumeConfig = (i18n: I18n) => ({ +export const PersistentVolumeConfig = (i18n: I18n): ResourceConfig => ({ name: 'persistentvolumes', basePath: '/api/v1', apiVersion: 'v1', @@ -20,11 +21,10 @@ export const PersistentVolumeConfig = (i18n: I18n) => ({ label: 'PersistentVolumes', initValue: {}, columns: () => [ - NameSpaceColumnRenderer(i18n), PVCapacityColumnRenderer(i18n), PVStorageClassColumnRenderer(i18n), PVPhaseColumnRenderer(i18n), - PVModeColumnRenderer(i18n), + PVVolumeModeColumnRenderer(i18n), PVAccessModeColumnRenderer(i18n), AgeColumnRenderer(i18n), ], @@ -35,7 +35,13 @@ export const PersistentVolumeConfig = (i18n: I18n) => ({ key: 'detail', groups: [ BasicGroup(i18n, { - basicFields: [], + basicFields: [ + PVCapacityField(i18n), + PVStorageClassField(i18n), + PVPhaseField(i18n), + PVVolumeModeField(i18n), + PVAccessModeField(i18n) + ], }), ], }, diff --git a/packages/refine/src/pages/storageclasses/index.ts b/packages/refine/src/pages/storageclasses/index.ts index 57005b89..b147d8f4 100644 --- a/packages/refine/src/pages/storageclasses/index.ts +++ b/packages/refine/src/pages/storageclasses/index.ts @@ -4,11 +4,10 @@ import { STORAGE_CLASS_INIT_VALUE } from 'src/constants/k8s'; import { NameSpaceColumnRenderer, ProvisionerColumnRenderer, - FsTypeColumnRenderer, AgeColumnRenderer, } from 'src/hooks/useEagleTable/columns'; import { RESOURCE_GROUP } from 'src/types'; -import { StorageClassFsTypeField, StorageClassProvisionerField } from '../../components'; +import { StorageClassProvisionerField } from '../../components'; import { generateStorageClassFormConfig } from './form'; export const StorageClassConfig = (i18n: I18n) => ({ @@ -26,7 +25,6 @@ export const StorageClassConfig = (i18n: I18n) => ({ columns: () => [ NameSpaceColumnRenderer(i18n), ProvisionerColumnRenderer(i18n), - FsTypeColumnRenderer(i18n), AgeColumnRenderer(i18n), ], showConfig: () => ({ @@ -38,10 +36,7 @@ export const StorageClassConfig = (i18n: I18n) => ({ BasicGroup(i18n, { downAreas: [ { - fields: [ - StorageClassProvisionerField(i18n), - StorageClassFsTypeField(i18n), - ], + fields: [StorageClassProvisionerField(i18n)], }, ], }), From 11abdd5691157519777e95d130360246f7a56603 Mon Sep 17 00:00:00 2001 From: Bowen Tan Date: Fri, 26 Jul 2024 13:42:15 +0800 Subject: [PATCH 2/2] 0.1.0 --- packages/refine/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/refine/package.json b/packages/refine/package.json index 7a8e58f2..8b17e37f 100644 --- a/packages/refine/package.json +++ b/packages/refine/package.json @@ -1,6 +1,6 @@ { "name": "@dovetail-v2/refine", - "version": "0.0.66", + "version": "0.1.0", "type": "module", "files": [ "dist",