fix: miss gpu_selector value in catalog
This commit is contained in:
@@ -2,7 +2,7 @@ import { CheckCircleFilled, CopyOutlined } from '@ant-design/icons';
|
|||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Tooltip, message } from 'antd';
|
import { Button, Tooltip, message } from 'antd';
|
||||||
import ClipboardJS from 'clipboard';
|
import ClipboardJS from 'clipboard';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
type CopyButtonProps = {
|
type CopyButtonProps = {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@@ -63,6 +63,13 @@ const CopyButton: React.FC<CopyButtonProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tipTitle = useMemo(() => {
|
||||||
|
if (copied) {
|
||||||
|
return intl.formatMessage({ id: 'common.button.copied' });
|
||||||
|
}
|
||||||
|
return tips ?? intl.formatMessage({ id: 'common.button.copy' });
|
||||||
|
}, [copied, intl, tips]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initClipboard();
|
initClipboard();
|
||||||
return () => {
|
return () => {
|
||||||
@@ -71,10 +78,7 @@ const CopyButton: React.FC<CopyButtonProps> = ({
|
|||||||
}, [buttonRef]);
|
}, [buttonRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip title={tipTitle} placement={placement}>
|
||||||
title={tips ?? intl.formatMessage({ id: 'common.button.copy' })}
|
|
||||||
placement={placement}
|
|
||||||
>
|
|
||||||
<Button
|
<Button
|
||||||
className="copy-button"
|
className="copy-button"
|
||||||
ref={buttonRef}
|
ref={buttonRef}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default {
|
|||||||
'common.button.run': 'Run',
|
'common.button.run': 'Run',
|
||||||
'common.button.viewcode': 'View Code',
|
'common.button.viewcode': 'View Code',
|
||||||
'common.button.copy': 'Copy',
|
'common.button.copy': 'Copy',
|
||||||
|
'common.button.copied': 'Copied',
|
||||||
'common.button.collapse': 'Collapse',
|
'common.button.collapse': 'Collapse',
|
||||||
'common.button.expand': 'Expand',
|
'common.button.expand': 'Expand',
|
||||||
'common.button.cancel': 'Cancel',
|
'common.button.cancel': 'Cancel',
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default {
|
|||||||
'common.button.run': '実行',
|
'common.button.run': '実行',
|
||||||
'common.button.viewcode': 'コードを表示',
|
'common.button.viewcode': 'コードを表示',
|
||||||
'common.button.copy': 'コピー',
|
'common.button.copy': 'コピー',
|
||||||
|
'common.button.copied': 'Copied',
|
||||||
'common.button.collapse': '折りたたむ',
|
'common.button.collapse': '折りたたむ',
|
||||||
'common.button.expand': '展開',
|
'common.button.expand': '展開',
|
||||||
'common.button.cancel': 'キャンセル',
|
'common.button.cancel': 'キャンセル',
|
||||||
@@ -235,3 +236,7 @@ export default {
|
|||||||
'common.text.error': 'エラー',
|
'common.text.error': 'エラー',
|
||||||
'common.text.tips': 'ヒント'
|
'common.text.tips': 'ヒント'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
// 1. 'common.button.copied',
|
||||||
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default {
|
|||||||
'common.button.run': 'Запустить',
|
'common.button.run': 'Запустить',
|
||||||
'common.button.viewcode': 'Посмотреть код',
|
'common.button.viewcode': 'Посмотреть код',
|
||||||
'common.button.copy': 'Копировать',
|
'common.button.copy': 'Копировать',
|
||||||
|
'common.button.copied': 'Copied',
|
||||||
'common.button.collapse': 'Свернуть',
|
'common.button.collapse': 'Свернуть',
|
||||||
'common.button.expand': 'Развернуть',
|
'common.button.expand': 'Развернуть',
|
||||||
'common.button.cancel': 'Отмена',
|
'common.button.cancel': 'Отмена',
|
||||||
@@ -233,3 +234,7 @@ export default {
|
|||||||
'common.text.error': 'Ошибка',
|
'common.text.error': 'Ошибка',
|
||||||
'common.text.tips': 'Советы'
|
'common.text.tips': 'Советы'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
// 1. 'common.button.copied',
|
||||||
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default {
|
|||||||
'common.button.run': '运行',
|
'common.button.run': '运行',
|
||||||
'common.button.viewcode': '查看代码',
|
'common.button.viewcode': '查看代码',
|
||||||
'common.button.copy': '复制',
|
'common.button.copy': '复制',
|
||||||
|
'common.button.copied': '复制成功',
|
||||||
'common.button.collapse': '折叠',
|
'common.button.collapse': '折叠',
|
||||||
'common.button.expand': '展开',
|
'common.button.expand': '展开',
|
||||||
'common.button.submit': '提交',
|
'common.button.submit': '提交',
|
||||||
|
|||||||
@@ -157,32 +157,18 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
|||||||
|
|
||||||
const handleBackendParametersOnBlur = () => {
|
const handleBackendParametersOnBlur = () => {
|
||||||
const backendParams = form.getFieldValue('backend_parameters');
|
const backendParams = form.getFieldValue('backend_parameters');
|
||||||
console.log('backendParams==', backendParams);
|
onValuesChange?.({}, form.getFieldsValue());
|
||||||
onValuesChange?.({
|
|
||||||
source: source,
|
|
||||||
allValues: form.getFieldsValue(),
|
|
||||||
changedValues: {}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectorOnBlur = () => {
|
const handleSelectorOnBlur = () => {
|
||||||
const workerSelector = form.getFieldValue('worker_selector');
|
const workerSelector = form.getFieldValue('worker_selector');
|
||||||
console.log('workerSelector==', workerSelector);
|
onValuesChange?.({}, form.getFieldsValue());
|
||||||
onValuesChange?.({
|
|
||||||
source: source,
|
|
||||||
allValues: form.getFieldsValue(),
|
|
||||||
changedValues: {}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBackendVersionOnBlur = () => {
|
const handleBackendVersionOnBlur = () => {
|
||||||
const backendVersion = form.getFieldValue('backend_version');
|
const backendVersion = form.getFieldValue('backend_version');
|
||||||
if (backendVersion) {
|
if (backendVersion) {
|
||||||
onValuesChange?.({
|
onValuesChange?.({}, form.getFieldsValue());
|
||||||
source: source,
|
|
||||||
allValues: form.getFieldsValue(),
|
|
||||||
changedValues: {}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,11 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
form.current?.submit?.();
|
form.current?.submit?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pickSomeFieldsValue = () => {
|
||||||
|
const formData = form.current?.getFieldsValue();
|
||||||
|
return _.pick(formData, ['worker_selector', 'gpu_selector', 'env']);
|
||||||
|
};
|
||||||
|
|
||||||
const generateSubmitData = (formData: FormData) => {
|
const generateSubmitData = (formData: FormData) => {
|
||||||
const gpuSelector = generateGPUIds(formData);
|
const gpuSelector = generateGPUIds(formData);
|
||||||
const data = {
|
const data = {
|
||||||
@@ -285,13 +290,32 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onValuesChange = async (changedValues: any, allValues: any) => {
|
const onValuesChange = async (changedValues: any, allValues: any) => {
|
||||||
|
const data = {
|
||||||
|
..._.omit(selectSpecRef.current, ['name']),
|
||||||
|
...allValues
|
||||||
|
};
|
||||||
handleOnValuesChange?.({
|
handleOnValuesChange?.({
|
||||||
changedValues,
|
changedValues,
|
||||||
allValues: generateSubmitData(allValues),
|
allValues: data,
|
||||||
source: props.source
|
source: props.source
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAdvanceOnValuesChange = (data: {
|
||||||
|
changedValues: any;
|
||||||
|
allValues: any;
|
||||||
|
source: string;
|
||||||
|
}) => {
|
||||||
|
handleOnValuesChange?.({
|
||||||
|
changedValues: data.changedValues,
|
||||||
|
allValues: {
|
||||||
|
..._.omit(selectSpecRef.current, ['name']),
|
||||||
|
...data.allValues
|
||||||
|
},
|
||||||
|
source: data.source
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleBackendChange = (backend: string) => {
|
const handleBackendChange = (backend: string) => {
|
||||||
if (backend === backendOptionsMap.vllm) {
|
if (backend === backendOptionsMap.vllm) {
|
||||||
setIsGGUF(false);
|
setIsGGUF(false);
|
||||||
@@ -392,7 +416,8 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
quantization: val
|
quantization: val
|
||||||
});
|
});
|
||||||
form.current.setFieldsValue({
|
form.current.setFieldsValue({
|
||||||
...data
|
...data,
|
||||||
|
...pickSomeFieldsValue()
|
||||||
});
|
});
|
||||||
handleCheckFormData();
|
handleCheckFormData();
|
||||||
};
|
};
|
||||||
@@ -413,7 +438,8 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
|
|
||||||
// set form data
|
// set form data
|
||||||
form.current.setFieldsValue({
|
form.current.setFieldsValue({
|
||||||
...data
|
...data,
|
||||||
|
...pickSomeFieldsValue()
|
||||||
});
|
});
|
||||||
handleCheckFormData();
|
handleCheckFormData();
|
||||||
};
|
};
|
||||||
@@ -497,7 +523,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
quantizationOptions: quantizationOptions,
|
quantizationOptions: quantizationOptions,
|
||||||
onSizeChange: handleOnSizeChange,
|
onSizeChange: handleOnSizeChange,
|
||||||
onQuantizationChange: handleOnQuantizationChange,
|
onQuantizationChange: handleOnQuantizationChange,
|
||||||
onValuesChange: handleOnValuesChange
|
onValuesChange: onValuesChange
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FormWrapper>
|
<FormWrapper>
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
value={{
|
value={{
|
||||||
isGGUF: isGGUF,
|
isGGUF: isGGUF,
|
||||||
modelFileOptions: props.modelFileOptions,
|
modelFileOptions: props.modelFileOptions,
|
||||||
onValuesChange: handleOnValuesChange
|
onValuesChange: onValuesChange
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FormWrapper>
|
<FormWrapper>
|
||||||
|
|||||||
@@ -331,6 +331,14 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleManulOnValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
handleOnValuesChange({
|
||||||
|
changedValues,
|
||||||
|
allValues,
|
||||||
|
source: formData?.source as string
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleOnClose = () => {
|
const handleOnClose = () => {
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
};
|
};
|
||||||
@@ -425,7 +433,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<FormContext.Provider
|
<FormContext.Provider
|
||||||
value={{
|
value={{
|
||||||
onValuesChange: handleOnValuesChange
|
onValuesChange: handleManulOnValuesChange
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface FormContextProps {
|
|||||||
modelFileOptions?: any[];
|
modelFileOptions?: any[];
|
||||||
onSizeChange?: (val: number) => void;
|
onSizeChange?: (val: number) => void;
|
||||||
onQuantizationChange?: (val: string) => void;
|
onQuantizationChange?: (val: string) => void;
|
||||||
onValuesChange?: (val: any) => void;
|
onValuesChange?: (changedValues: any, allValues: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FormInnerContextProps {
|
interface FormInnerContextProps {
|
||||||
|
|||||||
@@ -366,7 +366,6 @@ export const getSourceRepoConfigValue = (
|
|||||||
omits.push(key);
|
omits.push(key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
values: { ...result, ..._.omit(data, omits) }
|
values: { ...result, ..._.omit(data, omits) }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ export const useCheckCompatibility = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
gpu_selector: {
|
gpu_selector: {
|
||||||
gpu_ids: result
|
gpu_ids: result || []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -393,6 +393,7 @@ export const useCheckCompatibility = () => {
|
|||||||
source: string;
|
source: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { changedValues, allValues, source } = params;
|
const { changedValues, allValues, source } = params;
|
||||||
|
console.log('params+++++++', params);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
_.isEqual(cacheFormValuesRef.current, allValues) ||
|
_.isEqual(cacheFormValuesRef.current, allValues) ||
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { modelsExpandKeysAtom } from '@/atoms/models';
|
import { modelsExpandKeysAtom } from '@/atoms/models';
|
||||||
import AutoTooltip from '@/components/auto-tooltip';
|
import AutoTooltip from '@/components/auto-tooltip';
|
||||||
import CopyButton from '@/components/copy-button';
|
|
||||||
import DeleteModal from '@/components/delete-modal';
|
import DeleteModal from '@/components/delete-modal';
|
||||||
import DropdownButtons from '@/components/drop-down-buttons';
|
import DropdownButtons from '@/components/drop-down-buttons';
|
||||||
|
import OverlayScroller from '@/components/overlay-scroller';
|
||||||
import { FilterBar } from '@/components/page-tools';
|
import { FilterBar } from '@/components/page-tools';
|
||||||
import StatusTag from '@/components/status-tag';
|
import StatusTag from '@/components/status-tag';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
@@ -25,12 +25,25 @@ import {
|
|||||||
import { SourceType } from '@/pages/llmodels/config/types';
|
import { SourceType } from '@/pages/llmodels/config/types';
|
||||||
import DownloadModal from '@/pages/llmodels/download';
|
import DownloadModal from '@/pages/llmodels/download';
|
||||||
import { convertFileSize } from '@/utils';
|
import { convertFileSize } from '@/utils';
|
||||||
|
import {
|
||||||
|
CheckCircleFilled,
|
||||||
|
CopyOutlined,
|
||||||
|
InfoCircleOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
import { useIntl, useNavigate } from '@umijs/max';
|
import { useIntl, useNavigate } from '@umijs/max';
|
||||||
import { ConfigProvider, Empty, Table, Tag, message } from 'antd';
|
import {
|
||||||
|
ConfigProvider,
|
||||||
|
Empty,
|
||||||
|
Table,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
|
message
|
||||||
|
} from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import {
|
import {
|
||||||
useGenerateFormEditInitialValues,
|
useGenerateFormEditInitialValues,
|
||||||
@@ -86,6 +99,44 @@ const PathWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ItemWrapper = styled.ul`
|
||||||
|
max-width: 300px;
|
||||||
|
margin: 0;
|
||||||
|
padding-inline: 8px 0;
|
||||||
|
word-break: break-word;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const FilesTag = styled(Tag)`
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-inline: 4px 0;
|
||||||
|
height: 22px;
|
||||||
|
border-radius: var(--border-radius-base);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TooltipTitle: React.FC<{ path: string }> = ({ path }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
return (
|
||||||
|
<Typography.Paragraph
|
||||||
|
style={{ background: 'transparent', color: 'inherit' }}
|
||||||
|
copyable={{
|
||||||
|
icon: [
|
||||||
|
<CopyOutlined key="copy-icon" />,
|
||||||
|
<CheckCircleFilled key="copied-icon" />
|
||||||
|
],
|
||||||
|
text: path,
|
||||||
|
tooltips: [
|
||||||
|
intl.formatMessage({ id: 'common.button.copy' }),
|
||||||
|
intl.formatMessage({ id: 'common.button.copied' })
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{path}
|
||||||
|
</Typography.Paragraph>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const getWorkerName = (
|
const getWorkerName = (
|
||||||
id: number,
|
id: number,
|
||||||
workersList: Global.BaseOption<number>[]
|
workersList: Global.BaseOption<number>[]
|
||||||
@@ -260,27 +311,33 @@ const ModelFiles = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderParts = (record: ListItem) => {
|
const renderParts = (record: ListItem) => {
|
||||||
const parts = _.tail(record.resolved_paths);
|
const parts = record.resolved_paths || [];
|
||||||
if (!parts.length) {
|
if (parts.length <= 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const renderItem = () => {
|
||||||
|
return (
|
||||||
|
<ItemWrapper>
|
||||||
|
{parts.map((item: string, index: number) => {
|
||||||
|
return <li key={index}>{_.split(item, /[\\/]/).pop()}</li>;
|
||||||
|
})}
|
||||||
|
</ItemWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tag
|
<Tooltip
|
||||||
className="flex-center"
|
title={<OverlayScroller>{renderItem()}</OverlayScroller>}
|
||||||
color="purple"
|
overlayInnerStyle={{ width: 'max-content', maxWidth: 300 }}
|
||||||
style={{
|
|
||||||
marginRight: 0,
|
|
||||||
marginLeft: 4,
|
|
||||||
height: 22,
|
|
||||||
borderRadius: 'var(--border-radius-base)'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<span style={{ opacity: 1 }}>
|
<FilesTag color="purple" icon={<InfoCircleOutlined />}>
|
||||||
{record.resolved_paths?.length}{' '}
|
<span style={{ opacity: 1 }}>
|
||||||
{intl.formatMessage({ id: 'models.form.files' })}
|
{record.resolved_paths?.length}{' '}
|
||||||
</span>
|
{intl.formatMessage({ id: 'models.form.files' })}
|
||||||
</Tag>
|
</span>
|
||||||
|
</FilesTag>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -467,19 +524,17 @@ const ModelFiles = () => {
|
|||||||
return (
|
return (
|
||||||
record.resolved_paths?.length > 0 && (
|
record.resolved_paths?.length > 0 && (
|
||||||
<PathWrapper>
|
<PathWrapper>
|
||||||
<AutoTooltip ghost title={record.resolved_paths?.[0]} showTitle>
|
<AutoTooltip
|
||||||
|
ghost
|
||||||
|
showTitle
|
||||||
|
title={
|
||||||
|
<TooltipTitle
|
||||||
|
path={record.resolved_paths?.[0]}
|
||||||
|
></TooltipTitle>
|
||||||
|
}
|
||||||
|
>
|
||||||
<span>{getResolvedPath(record.resolved_paths)}</span>
|
<span>{getResolvedPath(record.resolved_paths)}</span>
|
||||||
</AutoTooltip>
|
</AutoTooltip>
|
||||||
<span className="btn-wrapper">
|
|
||||||
<CopyButton
|
|
||||||
text={record.resolved_paths?.[0]}
|
|
||||||
type="link"
|
|
||||||
btnStyle={{ width: 18, paddingInline: 2 }}
|
|
||||||
tips={intl.formatMessage({
|
|
||||||
id: 'resources.modelfiles.copy.tips'
|
|
||||||
})}
|
|
||||||
></CopyButton>
|
|
||||||
</span>
|
|
||||||
{renderParts(record)}
|
{renderParts(record)}
|
||||||
</PathWrapper>
|
</PathWrapper>
|
||||||
)
|
)
|
||||||
@@ -493,7 +548,7 @@ const ModelFiles = () => {
|
|||||||
render: (text: string, record: ListItem) => {
|
render: (text: string, record: ListItem) => {
|
||||||
return (
|
return (
|
||||||
<AutoTooltip ghost maxWidth={100}>
|
<AutoTooltip ghost maxWidth={100}>
|
||||||
<span>{convertFileSize(record.size, 1)}</span>
|
<span>{convertFileSize(record.size, 1, true)}</span>
|
||||||
</AutoTooltip>
|
</AutoTooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -21,11 +21,12 @@ export const handleBatchRequest = async (
|
|||||||
|
|
||||||
export const convertFileSize = (
|
export const convertFileSize = (
|
||||||
sizeInBytes: number | undefined,
|
sizeInBytes: number | undefined,
|
||||||
prec?: number
|
prec?: number,
|
||||||
|
allowEmpty = false
|
||||||
) => {
|
) => {
|
||||||
const precision = prec ?? 1;
|
const precision = prec ?? 1;
|
||||||
if (!sizeInBytes) {
|
if (!sizeInBytes) {
|
||||||
return '0';
|
return allowEmpty ? '' : '0';
|
||||||
}
|
}
|
||||||
if (sizeInBytes < 1024) {
|
if (sizeInBytes < 1024) {
|
||||||
return `${sizeInBytes.toFixed(precision)} B`;
|
return `${sizeInBytes.toFixed(precision)} B`;
|
||||||
|
|||||||
Reference in New Issue
Block a user