import AutoTooltip from '@/components/auto-tooltip'; import DropdownButtons from '@/components/drop-down-buttons'; import IconFont from '@/components/icon-font'; import LabelsCell from '@/components/label-cell'; import ProgressBar from '@/components/progress-bar'; import InfoColumn from '@/components/simple-table/info-column'; import StatusTag from '@/components/status-tag'; import { tableSorter } from '@/config/settings'; import { convertFileSize } from '@/utils'; import { DeleteOutlined, DownloadOutlined, EditOutlined, InfoCircleOutlined, SafetyOutlined, ToolOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Tooltip } from 'antd'; import { ColumnsType } from 'antd/lib/table'; import _ from 'lodash'; import { useMemo } from 'react'; import styled from 'styled-components'; import { status, WorkerStatusMap, WorkerStatusMapValue } from '../config'; import { Filesystem, GPUDeviceItem, ListItem } from '../config/types'; const IPWrapper = styled.span` display: flex; flex-direction: column; .item { display: grid; grid-template-columns: auto 1fr; gap: 4px 8px; .label { text-align: right; font-size: 13px; display: flex; align-items: center; color: var(--ant-color-text-tertiary); } } `; const ActionList = [ { label: 'common.button.edit', key: 'edit', icon: }, { label: 'resources.metrics.details', key: 'metrics', icon: }, // { // label: 'common.button.detail', // key: 'details', // icon: // }, { label: 'resources.worker.download.privatekey', key: 'download_ssh_key', icon: }, { label: 'resources.worker.maintenance.enable', key: 'star_maintenance', icon: }, { label: 'resources.worker.maintenance.disable', key: 'stop_maintenance', icon: }, // { // label: 'common.button.logs', // locale: false, // key: 'logs', // icon: // }, // { label: 'common.button.terminal', key: 'terminal', icon: }, { label: 'common.button.delete', key: 'delete', props: { danger: true }, icon: } ]; const setActions = (row: ListItem) => { return ActionList.filter((action) => { if (action.key === 'download_ssh_key') { return !!row.ssh_key_id; } if (action.key === 'star_maintenance') { return !row.maintenance?.enabled; } if (action.key === 'stop_maintenance') { return row.maintenance?.enabled; } return true; }); }; const fieldList = [ { label: 'resources.table.total', key: 'total', locale: true, render: (val: any) => convertFileSize(val, 0) }, { label: 'resources.table.used', key: 'used', locale: true, render: (val: any) => convertFileSize(val, 0) }, { label: 'resources.table.allocated', key: 'allocated', locale: true, render: (val: any) => convertFileSize(val, 0) } ]; const formateUtilization = (val1: number, val2: number): number => val1 && val2 ? _.round((val1 / val2) * 100, 0) : 0; const calcStorage = (files: Filesystem[]) => { const mountRoot = _.find( files, (item: Filesystem) => item.mount_point === '/' ); return mountRoot ? formateUtilization(mountRoot.used, mountRoot.total) : 0; }; const GPUCell = ({ devices }: { devices: GPUDeviceItem[] }) => ( {_.map( _.sortBy(devices || [], ['index']), (item: GPUDeviceItem, index: number) => ( [{item.index}] {item.core ? ( ) : ( '-' )} ) )} ); const VRAMCell = ({ devices, intl, rIndex, loadend, firstLoad }: { devices: GPUDeviceItem[]; intl: any; rIndex: number; loadend: boolean; firstLoad: boolean; }) => ( {_.map( _.sortBy(devices || [], ['index']), (item: GPUDeviceItem, index: number) => ( [{item.index}] } /> {item.memory.is_unified_memory && ( )} ) )} ); const StorageCell = ({ files }: { files: Filesystem[] }) => { const mountRoot = _.find( files, (item: Filesystem) => item.mount_point === '/' ); return ( f.key !== 'allocated')} data={mountRoot} /> ) : ( 0 ) } /> ); }; const statusAvailable = (record: ListItem) => { return ( WorkerStatusMap.initializing !== record.state && WorkerStatusMap.provisioning !== record.state && record.status ); }; const HolderStatus = () => { return N/A; }; const useWorkerColumns = ({ clusterData, loadend, firstLoad, sortOrder, sourceType, handleSelect }: { clusterData: { list: Global.BaseOption[]; data: Record; }; loadend: boolean; firstLoad: boolean; sortOrder: string[]; sourceType: string; handleSelect: (action: string, record: ListItem) => void; }): ColumnsType => { const intl = useIntl(); const renderIP = (text: string, record: ListItem) => { if (record.advertise_address === record.ip) { return record.ip; } if ( record.advertise_address !== record.ip && record.advertise_address && record.ip ) { return ( {record.ip} {`(${intl.formatMessage({ id: 'clusters.table.ip.internal' })})`} {record.advertise_address} {`(${intl.formatMessage({ id: 'clusters.table.ip.external' })})`} ); } return record.ip || record.advertise_address || ''; }; return useMemo>( () => [ { title: intl.formatMessage({ id: 'common.table.name' }), dataIndex: 'name', width: 100, sorter: tableSorter(1), render: (text: string) => ( {text} ) }, { title: intl.formatMessage({ id: 'resources.table.labels' }), dataIndex: 'labels', width: 200, render: (_, record) => }, { title: intl.formatMessage({ id: 'clusters.title' }), dataIndex: 'cluster_id', hidden: sourceType === 'cluster', render: (id: number) => ( {_.get(clusterData.data, id, '')} ) }, { title: intl.formatMessage({ id: 'common.table.status' }), dataIndex: 'state', sorter: tableSorter(2), render: (_, record) => ( ) }, { title: 'IP', dataIndex: 'ip', sorter: tableSorter(3), render: (text: string, record) => ( {renderIP(text, record)} ) }, { title: 'CPU', dataIndex: 'status.cpu.utilization_rate', sorter: tableSorter(4), render: (text: string, record) => statusAvailable(record) ? ( ) : ( ) }, { title: intl.formatMessage({ id: 'resources.table.memory' }), dataIndex: 'status.memory.utilization_rate', sorter: tableSorter(5), render: (_, record) => statusAvailable(record) ? ( } /> ) : ( ) }, { title: 'GPU', dataIndex: 'gpu', render: (_, record) => statusAvailable(record) ? ( ) : ( ) }, { title: intl.formatMessage({ id: 'resources.table.vram' }), dataIndex: 'vram', render: (_, record, rIndex) => statusAvailable(record) ? ( ) : ( ) }, { title: intl.formatMessage({ id: 'resources.table.disk' }), dataIndex: 'storage', render: (_, record) => statusAvailable(record) ? ( ) : ( ) }, { title: intl.formatMessage({ id: 'common.table.operation' }), key: 'operation', render: (_, record) => ( handleSelect(val, record)} /> ) } ], [intl, sourceType, sortOrder, clusterData, loadend, firstLoad, handleSelect] ); }; export default useWorkerColumns;