RWKV-Runner/frontend/src/pages/Models.tsx

223 lines
6.8 KiB
TypeScript
Raw Normal View History

2023-05-22 02:52:06 +00:00
import React, { FC } from 'react';
2023-05-06 12:17:39 +00:00
import {
createTableColumn,
DataGrid,
DataGridBody,
DataGridCell,
DataGridHeader,
DataGridHeaderCell,
DataGridRow,
TableCellLayout,
TableColumnDefinition,
Text,
Textarea
} from '@fluentui/react-components';
2023-05-22 02:52:06 +00:00
import { ToolTipButton } from '../components/ToolTipButton';
import { ArrowClockwise20Regular, ArrowDownload20Regular, Folder20Regular, Open20Regular } from '@fluentui/react-icons';
import { observer } from 'mobx-react-lite';
2023-05-20 08:07:08 +00:00
import commonStore from '../stores/commonStore';
2023-05-22 02:52:06 +00:00
import { BrowserOpenURL } from '../../wailsjs/runtime';
import { AddToDownloadList, OpenFileFolder } from '../../wailsjs/go/backend_golang/App';
import { Page } from '../components/Page';
import { bytesToGb, refreshModels, saveConfigs, toastWithButton } from '../utils';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router';
2023-05-06 12:17:39 +00:00
2023-05-20 08:07:08 +00:00
export type ModelSourceItem = {
name: string;
size: number;
lastUpdated: string;
desc?: { [lang: string]: string; };
SHA256?: string;
url?: string;
downloadUrl?: string;
isComplete?: boolean;
2023-05-20 08:07:08 +00:00
isLocal?: boolean;
localSize?: number;
2023-05-20 08:07:08 +00:00
lastUpdatedMs?: number;
hide?: boolean;
2023-05-20 08:07:08 +00:00
};
2023-05-13 12:15:18 +00:00
const columns: TableColumnDefinition<ModelSourceItem>[] = [
createTableColumn<ModelSourceItem>({
2023-05-06 12:17:39 +00:00
columnId: 'file',
compare: (a, b) => {
2023-05-13 12:15:18 +00:00
return a.name.localeCompare(b.name);
2023-05-06 12:17:39 +00:00
},
renderHeaderCell: () => {
2023-05-22 02:52:06 +00:00
const { t } = useTranslation();
2023-05-18 12:48:53 +00:00
return t('File');
2023-05-06 12:17:39 +00:00
},
renderCell: (item) => {
return (
<TableCellLayout className="break-all">
2023-05-13 12:15:18 +00:00
{item.name}
2023-05-06 12:17:39 +00:00
</TableCellLayout>
);
}
}),
2023-05-13 12:15:18 +00:00
createTableColumn<ModelSourceItem>({
2023-05-06 12:17:39 +00:00
columnId: 'desc',
compare: (a, b) => {
2023-05-19 14:18:38 +00:00
const lang: string = commonStore.settings.language;
if (a.desc && b.desc) {
if (lang in a.desc && lang in b.desc)
2023-05-19 14:37:11 +00:00
return b.desc[lang].localeCompare(a.desc[lang]);
2023-05-19 14:18:38 +00:00
else if ('en' in a.desc && 'en' in b.desc)
2023-05-19 14:37:11 +00:00
return b.desc['en'].localeCompare(a.desc['en']);
2023-05-19 14:18:38 +00:00
}
return 0;
2023-05-06 12:17:39 +00:00
},
renderHeaderCell: () => {
2023-05-22 02:52:06 +00:00
const { t } = useTranslation();
2023-05-18 12:48:53 +00:00
return t('Desc');
2023-05-06 12:17:39 +00:00
},
renderCell: (item) => {
2023-05-18 12:48:53 +00:00
const lang: string = commonStore.settings.language;
2023-05-06 12:17:39 +00:00
return (
<TableCellLayout>
2023-05-18 12:48:53 +00:00
{item.desc &&
(lang in item.desc ? item.desc[lang] :
('en' in item.desc && item.desc['en']))}
2023-05-06 12:17:39 +00:00
</TableCellLayout>
);
}
}),
2023-05-13 12:15:18 +00:00
createTableColumn<ModelSourceItem>({
2023-05-06 12:17:39 +00:00
columnId: 'size',
compare: (a, b) => {
return a.size - b.size;
},
renderHeaderCell: () => {
2023-05-22 02:52:06 +00:00
const { t } = useTranslation();
2023-05-18 12:48:53 +00:00
return t('Size');
2023-05-06 12:17:39 +00:00
},
renderCell: (item) => {
return (
<TableCellLayout>
2023-05-20 05:46:33 +00:00
{bytesToGb(item.size) + 'GB'}
2023-05-06 12:17:39 +00:00
</TableCellLayout>
);
}
}),
2023-05-13 12:15:18 +00:00
createTableColumn<ModelSourceItem>({
2023-05-06 12:17:39 +00:00
columnId: 'lastUpdated',
compare: (a, b) => {
2023-05-13 12:15:18 +00:00
if (!a.lastUpdatedMs)
a.lastUpdatedMs = Date.parse(a.lastUpdated);
if (!b.lastUpdatedMs)
b.lastUpdatedMs = Date.parse(b.lastUpdated);
2023-05-13 15:36:30 +00:00
return b.lastUpdatedMs - a.lastUpdatedMs;
2023-05-06 12:17:39 +00:00
},
renderHeaderCell: () => {
2023-05-22 02:52:06 +00:00
const { t } = useTranslation();
2023-05-18 12:48:53 +00:00
return t('Last updated');
2023-05-06 12:17:39 +00:00
},
renderCell: (item) => {
return new Date(item.lastUpdated).toLocaleString();
}
}),
2023-05-13 12:15:18 +00:00
createTableColumn<ModelSourceItem>({
2023-05-06 12:17:39 +00:00
columnId: 'actions',
compare: (a, b) => {
return a.isComplete ? -1 : 1;
2023-05-06 12:17:39 +00:00
},
renderHeaderCell: () => {
2023-05-22 02:52:06 +00:00
const { t } = useTranslation();
2023-05-18 12:48:53 +00:00
return t('Actions');
2023-05-06 12:17:39 +00:00
},
renderCell: (item) => {
2023-05-22 02:52:06 +00:00
const { t } = useTranslation();
2023-05-20 06:53:52 +00:00
const navigate = useNavigate();
2023-05-18 12:48:53 +00:00
2023-05-06 12:17:39 +00:00
return (
<TableCellLayout>
2023-05-13 12:15:18 +00:00
<div className="flex gap-1">
2023-05-13 15:36:30 +00:00
{
item.isComplete &&
2023-05-22 02:52:06 +00:00
<ToolTipButton desc={t('Open Folder')} icon={<Folder20Regular />} onClick={() => {
2023-06-14 13:11:08 +00:00
OpenFileFolder(`${commonStore.settings.customModelsPath}/${item.name}`, true);
2023-05-22 02:52:06 +00:00
}} />
2023-05-13 15:36:30 +00:00
}
{item.downloadUrl && !item.isComplete &&
2023-05-22 02:52:06 +00:00
<ToolTipButton desc={t('Download')} icon={<ArrowDownload20Regular />} onClick={() => {
2023-05-20 06:53:52 +00:00
toastWithButton(`${t('Downloading')} ${item.name}`, t('Check'), () => {
2023-05-22 02:52:06 +00:00
navigate({ pathname: '/downloads' });
2023-05-20 06:53:52 +00:00
},
2023-05-22 02:52:06 +00:00
{ autoClose: 3000 });
2023-05-31 07:21:47 +00:00
AddToDownloadList(`${commonStore.settings.customModelsPath}/${item.name}`, item.downloadUrl!);
2023-05-22 02:52:06 +00:00
}} />}
{item.url && <ToolTipButton desc={t('Open Url')} icon={<Open20Regular />} onClick={() => {
2023-05-13 15:36:30 +00:00
BrowserOpenURL(item.url!);
2023-05-22 02:52:06 +00:00
}} />}
2023-05-13 12:15:18 +00:00
</div>
2023-05-06 12:17:39 +00:00
</TableCellLayout>
);
}
})
];
2023-05-05 15:23:34 +00:00
2023-05-13 12:15:18 +00:00
export const Models: FC = observer(() => {
2023-05-22 02:52:06 +00:00
const { t } = useTranslation();
2023-05-18 12:48:53 +00:00
2023-05-05 15:23:34 +00:00
return (
2023-05-18 12:48:53 +00:00
<Page title={t('Models')} content={
2023-05-15 13:55:57 +00:00
<div className="flex flex-col gap-2 overflow-hidden">
<div className="flex flex-col gap-1">
2023-05-19 02:08:28 +00:00
<div className="flex justify-between items-center">
2023-05-18 12:48:53 +00:00
<Text weight="medium">{t('Model Source Manifest List')}</Text>
2023-05-22 02:52:06 +00:00
<ToolTipButton desc={t('Refresh')} icon={<ArrowClockwise20Regular />} onClick={() => {
2023-05-17 13:20:41 +00:00
refreshModels(false);
2023-05-17 15:27:52 +00:00
saveConfigs();
2023-05-22 02:52:06 +00:00
}} />
2023-05-13 12:15:18 +00:00
</div>
2023-05-15 13:55:57 +00:00
<Text size={100}>
2023-05-18 12:48:53 +00:00
{t('Provide JSON file URLs for the models manifest. Separate URLs with semicolons. The "models" field in JSON files will be parsed into the following table.')}
2023-05-15 13:55:57 +00:00
</Text>
<Textarea size="large" resize="vertical"
2023-05-22 02:52:06 +00:00
value={commonStore.modelSourceManifestList}
onChange={(e, data) => commonStore.setModelSourceManifestList(data.value)} />
2023-05-15 13:55:57 +00:00
</div>
<div className="flex grow overflow-hidden">
<DataGrid
items={commonStore.modelSourceList}
columns={columns}
sortable={true}
2023-05-22 02:52:06 +00:00
defaultSortState={{ sortColumn: 'actions', sortDirection: 'ascending' }}
style={{ display: 'flex' }}
2023-05-15 13:55:57 +00:00
className="flex-col w-full"
>
<DataGridHeader>
<DataGridRow>
2023-05-22 02:52:06 +00:00
{({ renderHeaderCell }) => (
2023-05-15 13:55:57 +00:00
<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
)}
</DataGridRow>
</DataGridHeader>
<div className="overflow-y-auto overflow-x-hidden">
<DataGridBody<ModelSourceItem>>
2023-05-22 02:52:06 +00:00
{({ item, rowId }) => (
(!item.hide || item.isComplete) &&
2023-05-15 13:55:57 +00:00
<DataGridRow<ModelSourceItem> key={rowId}>
2023-05-22 02:52:06 +00:00
{({ renderCell }) => (
2023-05-15 13:55:57 +00:00
<DataGridCell>{renderCell(item)}</DataGridCell>
)}
</DataGridRow>
)}
</DataGridBody>
</div>
</DataGrid>
</div>
2023-05-13 12:15:18 +00:00
</div>
2023-05-22 02:52:06 +00:00
} />
2023-05-05 15:23:34 +00:00
);
2023-05-13 12:15:18 +00:00
});