chore: ram vram usage in resource
This commit is contained in:
@@ -908,7 +908,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
|||||||
onClick={handleFitView}
|
onClick={handleFitView}
|
||||||
size="middle"
|
size="middle"
|
||||||
type="text"
|
type="text"
|
||||||
disabled={disabled}
|
disabled={isDisabled}
|
||||||
>
|
>
|
||||||
<ExpandOutlined className="font-size-14" />
|
<ExpandOutlined className="font-size-14" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { memo, useMemo } from 'react';
|
|||||||
|
|
||||||
const RenderProgress = memo(
|
const RenderProgress = memo(
|
||||||
(props: {
|
(props: {
|
||||||
|
open?: boolean;
|
||||||
percent: number;
|
percent: number;
|
||||||
steps?: number;
|
steps?: number;
|
||||||
download?: boolean;
|
download?: boolean;
|
||||||
@@ -11,6 +12,7 @@ const RenderProgress = memo(
|
|||||||
successColor?: string;
|
successColor?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
|
open,
|
||||||
percent,
|
percent,
|
||||||
steps = 5,
|
steps = 5,
|
||||||
download,
|
download,
|
||||||
@@ -62,7 +64,9 @@ const RenderProgress = memo(
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{label ? (
|
{label ? (
|
||||||
<Tooltip title={label}>{renderProgress}</Tooltip>
|
<Tooltip title={label} open={open}>
|
||||||
|
{renderProgress}
|
||||||
|
</Tooltip>
|
||||||
) : (
|
) : (
|
||||||
renderProgress
|
renderProgress
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { convertFileSize } from '@/utils';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Divider } from 'antd';
|
||||||
|
|
||||||
|
interface InfoColumnProps {
|
||||||
|
fieldList: { label: string; key: string }[];
|
||||||
|
data: Record<string, any>;
|
||||||
|
}
|
||||||
|
const InfoColumn: React.FC<InfoColumnProps> = (props) => {
|
||||||
|
const { data, fieldList } = props;
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="flex">
|
||||||
|
{fieldList.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span className="flex-column flex-center">
|
||||||
|
<span> {intl.formatMessage({ id: item.label })}</span>
|
||||||
|
<span> {convertFileSize(data[item.key], 0)}</span>
|
||||||
|
</span>
|
||||||
|
{index < fieldList.length - 1 ? (
|
||||||
|
<Divider
|
||||||
|
type="vertical"
|
||||||
|
style={{
|
||||||
|
height: 30,
|
||||||
|
marginInline: 16,
|
||||||
|
borderColor: 'var(--color-white-light-2)',
|
||||||
|
alignSelf: 'center'
|
||||||
|
}}
|
||||||
|
></Divider>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InfoColumn;
|
||||||
@@ -49,6 +49,10 @@ html {
|
|||||||
--color-white-secondary: rgba(255, 255, 255, 90%);
|
--color-white-secondary: rgba(255, 255, 255, 90%);
|
||||||
--color-white-tertiary: rgba(255, 255, 255, 70%);
|
--color-white-tertiary: rgba(255, 255, 255, 70%);
|
||||||
--color-white-quaternary: rgba(255, 255, 255, 50%);
|
--color-white-quaternary: rgba(255, 255, 255, 50%);
|
||||||
|
--color-white-light-1: rgba(255, 255, 255, 15%);
|
||||||
|
--color-white-light-2: rgba(255, 255, 255, 25%);
|
||||||
|
--color-white-light-3: rgba(255, 255, 255, 35%);
|
||||||
|
--color-white-light-4: rgba(255, 255, 255, 45%);
|
||||||
--color-text-1: var(--ant-color-text);
|
--color-text-1: var(--ant-color-text);
|
||||||
--color-text-3: rgba(0, 0, 0, 45%);
|
--color-text-3: rgba(0, 0, 0, 45%);
|
||||||
--color-text-2: rgba(0, 0, 0, 65%);
|
--color-text-2: rgba(0, 0, 0, 65%);
|
||||||
|
|||||||
@@ -295,7 +295,6 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
|||||||
required
|
required
|
||||||
showSearch
|
showSearch
|
||||||
expandTrigger="hover"
|
expandTrigger="hover"
|
||||||
onChange={handleGPUSelectorChange}
|
|
||||||
multiple={backend !== backendOptionsMap.voxBox}
|
multiple={backend !== backendOptionsMap.voxBox}
|
||||||
popupClassName="cascader-popup-wrapper gpu-selector"
|
popupClassName="cascader-popup-wrapper gpu-selector"
|
||||||
maxTagCount={1}
|
maxTagCount={1}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = forwardRef(
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}, [formFields, intl, watchFields]);
|
}, [formFields, paramsConfig, intl, watchFields]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
initialValues,
|
initialValues,
|
||||||
parameters,
|
parameters,
|
||||||
isOpenaiCompatible
|
isOpenaiCompatible
|
||||||
} = useInitImageMeta(props);
|
} = useInitImageMeta(props, {
|
||||||
|
type: 'create'
|
||||||
|
});
|
||||||
const {
|
const {
|
||||||
loading,
|
loading,
|
||||||
tokenResult,
|
tokenResult,
|
||||||
|
|||||||
@@ -75,13 +75,16 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
updateParamsConfig,
|
updateParamsConfig,
|
||||||
setParamsConfig,
|
setParamsConfig,
|
||||||
form,
|
form,
|
||||||
|
modelMeta,
|
||||||
watchFields,
|
watchFields,
|
||||||
formFields,
|
formFields,
|
||||||
paramsConfig,
|
paramsConfig,
|
||||||
initialValues,
|
initialValues,
|
||||||
parameters,
|
parameters,
|
||||||
isOpenaiCompatible
|
isOpenaiCompatible
|
||||||
} = useInitImageMeta(props);
|
} = useInitImageMeta(props, {
|
||||||
|
type: 'edit'
|
||||||
|
});
|
||||||
const {
|
const {
|
||||||
loading,
|
loading,
|
||||||
tokenResult,
|
tokenResult,
|
||||||
@@ -225,10 +228,21 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
|
|
||||||
const handleOnScaleImageSize = useCallback(
|
const handleOnScaleImageSize = useCallback(
|
||||||
(data: { rawWidth: number; rawHeight: number }) => {
|
(data: { rawWidth: number; rawHeight: number }) => {
|
||||||
const { width, height } = scaleImageSize({
|
let { width, height } = scaleImageSize({
|
||||||
width: data.rawWidth,
|
width: data.rawWidth,
|
||||||
height: data.rawHeight
|
height: data.rawHeight
|
||||||
});
|
});
|
||||||
|
const { max_width: maxWidth, max_height: maxHeight } = modelMeta;
|
||||||
|
|
||||||
|
// update width, height
|
||||||
|
if (maxWidth) {
|
||||||
|
width = Math.max(Math.min(width, maxWidth), 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxHeight) {
|
||||||
|
height = Math.max(Math.min(height, maxHeight), 512);
|
||||||
|
}
|
||||||
|
|
||||||
const newParamsConfig = updateParamsConfig({
|
const newParamsConfig = updateParamsConfig({
|
||||||
size: 'custom',
|
size: 'custom',
|
||||||
isOpenaiCompatible
|
isOpenaiCompatible
|
||||||
@@ -248,7 +262,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
});
|
});
|
||||||
setInitialValues(newParameters);
|
setInitialValues(newParameters);
|
||||||
},
|
},
|
||||||
[parameters, isOpenaiCompatible]
|
[parameters, modelMeta, isOpenaiCompatible]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleUpdateImageList = useCallback(
|
const handleUpdateImageList = useCallback(
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
||||||
import {
|
import {
|
||||||
ImageAdvancedParamsConfig,
|
|
||||||
ImageCountConfig,
|
ImageCountConfig,
|
||||||
ImageCustomSizeConfig,
|
ImageCustomSizeConfig,
|
||||||
ImageSizeConfig,
|
ImageSizeConfig,
|
||||||
ImageSizeItem,
|
ImageSizeItem,
|
||||||
ImageconstExtraConfig,
|
ImageconstExtraConfig,
|
||||||
|
ImageAdvancedParamsConfig as ImgAdvancedParamsConfig,
|
||||||
imageSizeOptions as imageSizeList
|
imageSizeOptions as imageSizeList
|
||||||
} from '@/pages/playground/config/params-config';
|
} from '@/pages/playground/config/params-config';
|
||||||
import { useSearchParams } from '@umijs/max';
|
import { useSearchParams } from '@umijs/max';
|
||||||
@@ -117,7 +117,7 @@ export const useInitLLmMeta = (
|
|||||||
if (!val) return;
|
if (!val) return;
|
||||||
const model = modelList.find((item) => item.value === val);
|
const model = modelList.find((item) => item.value === val);
|
||||||
const { form: initialData, meta } = extractLLMMeta(model?.meta);
|
const { form: initialData, meta } = extractLLMMeta(model?.meta);
|
||||||
setModelMeta(meta || {});
|
setModelMeta(meta);
|
||||||
setInitialValues({
|
setInitialValues({
|
||||||
...initialData,
|
...initialData,
|
||||||
model: val
|
model: val
|
||||||
@@ -185,8 +185,16 @@ export const useInitLLmMeta = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useInitImageMeta = (props: MessageProps) => {
|
export const useInitImageMeta = (
|
||||||
|
props: MessageProps,
|
||||||
|
options: { type: string }
|
||||||
|
) => {
|
||||||
const { modelList } = props;
|
const { modelList } = props;
|
||||||
|
const ImageAdvancedParamsConfig =
|
||||||
|
options.type === 'edit'
|
||||||
|
? ImgAdvancedParamsConfig
|
||||||
|
: ImgAdvancedParamsConfig.filter((item) => item.name !== 'strength');
|
||||||
|
|
||||||
const form = useRef<any>(null);
|
const form = useRef<any>(null);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const [modelMeta, setModelMeta] = useState<any>({});
|
const [modelMeta, setModelMeta] = useState<any>({});
|
||||||
@@ -473,6 +481,7 @@ export const useInitImageMeta = (props: MessageProps) => {
|
|||||||
updateParamsConfig,
|
updateParamsConfig,
|
||||||
setParamsConfig,
|
setParamsConfig,
|
||||||
form,
|
form,
|
||||||
|
modelMeta,
|
||||||
formFields,
|
formFields,
|
||||||
watchFields,
|
watchFields,
|
||||||
paramsConfig,
|
paramsConfig,
|
||||||
|
|||||||
@@ -118,12 +118,7 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
<HighlightCode
|
<HighlightCode theme="dark" code={code} lang="bash"></HighlightCode>
|
||||||
theme="dark"
|
|
||||||
code={code}
|
|
||||||
lang="bash"
|
|
||||||
height={130}
|
|
||||||
></HighlightCode>
|
|
||||||
<h3 className="m-b-0 m-t-10">
|
<h3 className="m-b-0 m-t-10">
|
||||||
3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}
|
3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}
|
||||||
</h3>
|
</h3>
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import DeleteModal from '@/components/delete-modal';
|
|||||||
import DropdownButtons from '@/components/drop-down-buttons';
|
import DropdownButtons from '@/components/drop-down-buttons';
|
||||||
import PageTools from '@/components/page-tools';
|
import PageTools from '@/components/page-tools';
|
||||||
import ProgressBar from '@/components/progress-bar';
|
import ProgressBar from '@/components/progress-bar';
|
||||||
|
import InfoColumn from '@/components/simple-table/info-column';
|
||||||
import StatusTag from '@/components/status-tag';
|
import StatusTag from '@/components/status-tag';
|
||||||
import Hotkeys from '@/config/hotkeys';
|
import Hotkeys from '@/config/hotkeys';
|
||||||
import useTableRowSelection from '@/hooks/use-table-row-selection';
|
import useTableRowSelection from '@/hooks/use-table-row-selection';
|
||||||
import useTableSort from '@/hooks/use-table-sort';
|
import useTableSort from '@/hooks/use-table-sort';
|
||||||
import { convertFileSize, handleBatchRequest } from '@/utils';
|
import { handleBatchRequest } from '@/utils';
|
||||||
import {
|
import {
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
EditOutlined,
|
EditOutlined,
|
||||||
@@ -37,6 +38,21 @@ import UpdateLabels from './update-labels';
|
|||||||
|
|
||||||
const { Column } = Table;
|
const { Column } = Table;
|
||||||
|
|
||||||
|
const fieldList = [
|
||||||
|
{
|
||||||
|
label: 'resources.table.total',
|
||||||
|
key: 'total'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'resources.table.used',
|
||||||
|
key: 'used'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'resources.table.allocated',
|
||||||
|
key: 'allocated'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
const ActionList = [
|
const ActionList = [
|
||||||
{
|
{
|
||||||
label: 'common.button.edit',
|
label: 'common.button.edit',
|
||||||
@@ -186,27 +202,6 @@ const Workers: React.FC = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderStorageTooltip = (files: Filesystem[]) => {
|
|
||||||
const mountRoot = _.find(
|
|
||||||
files,
|
|
||||||
(item: Filesystem) => item.mount_point === '/'
|
|
||||||
);
|
|
||||||
return mountRoot ? (
|
|
||||||
<span className="flex-column">
|
|
||||||
<span>
|
|
||||||
{intl.formatMessage({ id: 'resources.table.total' })}:{' '}
|
|
||||||
{convertFileSize(mountRoot?.total, 0)}
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
{intl.formatMessage({ id: 'resources.table.used' })}:{' '}
|
|
||||||
{convertFileSize(mountRoot?.used, 0)}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
0
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleUpdateLabelsOk = useCallback(
|
const handleUpdateLabelsOk = useCallback(
|
||||||
async (values: Record<string, any>) => {
|
async (values: Record<string, any>) => {
|
||||||
try {
|
try {
|
||||||
@@ -264,27 +259,18 @@ const Workers: React.FC = () => {
|
|||||||
return <div></div>;
|
return <div></div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderProgressLabels = (data: {
|
const renderStorageTooltip = (files: Filesystem[]) => {
|
||||||
total: number;
|
const mountRoot = _.find(
|
||||||
used: number;
|
files,
|
||||||
allocated: number;
|
(item: Filesystem) => item.mount_point === '/'
|
||||||
}) => {
|
);
|
||||||
const { total, used, allocated } = data;
|
return mountRoot ? (
|
||||||
return (
|
<InfoColumn
|
||||||
<span className="flex-column">
|
fieldList={fieldList.filter((item) => item.key !== 'allocated')}
|
||||||
<span>
|
data={mountRoot}
|
||||||
{intl.formatMessage({ id: 'resources.table.total' })}:{' '}
|
></InfoColumn>
|
||||||
{convertFileSize(total, 0)}
|
) : (
|
||||||
</span>
|
0
|
||||||
<span>
|
|
||||||
{intl.formatMessage({ id: 'resources.table.used' })}:{' '}
|
|
||||||
{convertFileSize(used, 0)}
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
{intl.formatMessage({ id: 'resources.table.allocated' })}:{' '}
|
|
||||||
{convertFileSize(allocated, 0)}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -449,7 +435,12 @@ const Workers: React.FC = () => {
|
|||||||
record?.status?.memory?.used,
|
record?.status?.memory?.used,
|
||||||
record?.status?.memory?.total
|
record?.status?.memory?.total
|
||||||
)}
|
)}
|
||||||
label={renderProgressLabels(record?.status?.memory)}
|
label={
|
||||||
|
<InfoColumn
|
||||||
|
fieldList={fieldList}
|
||||||
|
data={record.status.memory}
|
||||||
|
></InfoColumn>
|
||||||
|
}
|
||||||
></ProgressBar>
|
></ProgressBar>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@@ -520,7 +511,12 @@ const Workers: React.FC = () => {
|
|||||||
0
|
0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
label={renderProgressLabels(item.memory)}
|
label={
|
||||||
|
<InfoColumn
|
||||||
|
fieldList={fieldList}
|
||||||
|
data={item.memory}
|
||||||
|
></InfoColumn>
|
||||||
|
}
|
||||||
></ProgressBar>
|
></ProgressBar>
|
||||||
{item.memory.is_unified_memory && (
|
{item.memory.is_unified_memory && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -528,7 +524,10 @@ const Workers: React.FC = () => {
|
|||||||
id: 'resources.table.unified'
|
id: 'resources.table.unified'
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<InfoCircleOutlined className="m-l-5" />
|
<InfoCircleOutlined
|
||||||
|
className="m-l-5"
|
||||||
|
style={{ color: 'var(--ant-blue-5)' }}
|
||||||
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ export const addWorkerGuide: Record<string, any> = {
|
|||||||
return `docker run -d --name gpustack-worker --restart=unless-stopped --gpus all -p 10150:10150 -p 40000-41024:40000-41024 -p 50000-51024:50000-51024 --ipc=host -v gpustack-worker-data:/var/lib/gpustack gpustack/gpustack:${params.tag} --server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
return `docker run -d --name gpustack-worker --restart=unless-stopped --gpus all -p 10150:10150 -p 40000-41024:40000-41024 -p 50000-51024:50000-51024 --ipc=host -v gpustack-worker-data:/var/lib/gpustack gpustack/gpustack:${params.tag} --server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
npu: {
|
npu: {
|
||||||
getToken:
|
getToken:
|
||||||
'Get-Content -Path (Join-Path -Path $env:APPDATA -ChildPath "gpustack\\token") -Raw',
|
'Get-Content -Path (Join-Path -Path $env:APPDATA -ChildPath "gpustack\\token") -Raw',
|
||||||
@@ -54,31 +53,7 @@ export const addWorkerGuide: Record<string, any> = {
|
|||||||
token: string;
|
token: string;
|
||||||
workerip: string;
|
workerip: string;
|
||||||
}) {
|
}) {
|
||||||
return `docker run -d --name gpustack-worker \\
|
return `docker run -d --name gpustack-worker --restart=unless-stopped -e ASCEND_VISIBLE_DEVICES=0 -p 10150:10150 -p 40000-41024:40000-41024 -p 50000-51024:50000-51024 --ipc=host -v gpustack-worker-data:/var/lib/gpustack gpustack/gpustack:${params.tag} --server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
||||||
--restart=unless-stopped \\
|
|
||||||
--device /dev/davinci0 \\
|
|
||||||
--device /dev/davinci1 \\
|
|
||||||
--device /dev/davinci2 \\
|
|
||||||
--device /dev/davinci3 \\
|
|
||||||
--device /dev/davinci4 \\
|
|
||||||
--device /dev/davinci5 \\
|
|
||||||
--device /dev/davinci6 \\
|
|
||||||
--device /dev/davinci7 \\
|
|
||||||
--device /dev/davinci_manager \\
|
|
||||||
--device /dev/devmm_svm \\
|
|
||||||
--device /dev/hisi_hdc \\
|
|
||||||
-v /usr/local/dcmi:/usr/local/dcmi \\
|
|
||||||
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \\
|
|
||||||
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \\
|
|
||||||
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \\
|
|
||||||
-v /etc/ascend_install.info:/etc/ascend_install.info \\
|
|
||||||
-p 10150:10150 \\
|
|
||||||
-p 40000-41024:40000-41024 \\
|
|
||||||
-p 50000-51024:50000-51024 \\
|
|
||||||
--ipc=host \\
|
|
||||||
-v gpustack-worker-data:/var/lib/gpustack \\
|
|
||||||
gpustack/gpustack:${params.tag} \\
|
|
||||||
--server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
musa: {
|
musa: {
|
||||||
|
|||||||
+4
-1
@@ -19,7 +19,10 @@ export const handleBatchRequest = async (
|
|||||||
return Promise.all(list.map((item) => fn(item)));
|
return Promise.all(list.map((item) => fn(item)));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertFileSize = (sizeInBytes: number, prec?: number) => {
|
export const convertFileSize = (
|
||||||
|
sizeInBytes: number | undefined,
|
||||||
|
prec?: number
|
||||||
|
) => {
|
||||||
const precision = prec ?? 1;
|
const precision = prec ?? 1;
|
||||||
if (!sizeInBytes) {
|
if (!sizeInBytes) {
|
||||||
return '0';
|
return '0';
|
||||||
|
|||||||
Reference in New Issue
Block a user