Skip to content

Commit cad7b3b

Browse files
committed
feat(FR-2452): add missing schema fields to VFolderNodes table as hidden columns (#6362)
Resolves #6361 (FR-2452) ## Summary - Add all available but missing VirtualFolderNode schema fields to the VFolderNodes table as default-hidden columns - New columns: usage_mode, creator, created_at, last_used, num_files, cur_size, max_files, max_size, cloneable, quota_scope_id - All new columns support sorting; usage_mode and cloneable also support filtering - Add `data.folders.Creator` i18n key to all 21 language files
1 parent 5d7906d commit cad7b3b

23 files changed

Lines changed: 158 additions & 4 deletions

react/src/components/VFolderNodes.tsx

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@ import {
3030
BAITableProps,
3131
BAIFlex,
3232
BAINameActionCell,
33+
BAIText,
3334
toLocalId,
3435
useErrorMessageResolver,
3536
BAILink,
3637
BAIConfirmModalWithInput,
3738
BAITag,
39+
bytesToGB,
3840
} from 'backend.ai-ui';
3941
import type { BAINameActionCellAction } from 'backend.ai-ui';
42+
import dayjs from 'dayjs';
4043
import _ from 'lodash';
4144
import React, { useState } from 'react';
4245
import { useTranslation } from 'react-i18next';
@@ -59,6 +62,25 @@ export const statusTagColor = {
5962

6063
export type VFolderNodeInList = NonNullable<VFolderNodesFragment$data[number]>;
6164

65+
const availableVFolderSorterKeys = [
66+
'name',
67+
'host',
68+
'quota_scope_id',
69+
'usage_mode',
70+
'ownership_type',
71+
'max_files',
72+
'max_size',
73+
'created_at',
74+
'last_used',
75+
'cloneable',
76+
'status',
77+
'cur_size',
78+
] as const;
79+
80+
const isEnableSorter = (key: string) => {
81+
return _.includes(availableVFolderSorterKeys, key);
82+
};
83+
6284
interface VFolderNameCellProps {
6385
vfolder: VFolderNodeInList;
6486
onShare: () => void;
@@ -207,12 +229,20 @@ const VFolderNodes: React.FC<VFolderNodesProps> = ({
207229
status
208230
name
209231
host
232+
quota_scope_id
210233
ownership_type
211234
user
212235
user_email
213236
group
214237
group_name
215238
usage_mode
239+
max_files
240+
max_size
241+
created_at
242+
last_used
243+
num_files
244+
cur_size
245+
cloneable
216246
permissions @since(version: "24.09.0")
217247
...VFolderPermissionCellFragment
218248
...VFolderNodeIdenticonFragment
@@ -357,7 +387,7 @@ const VFolderNodes: React.FC<VFolderNodesProps> = ({
357387
/>
358388
);
359389
},
360-
sorter: true,
390+
sorter: isEnableSorter('name'),
361391
},
362392
{
363393
key: 'status',
@@ -376,13 +406,13 @@ const VFolderNodes: React.FC<VFolderNodesProps> = ({
376406
</BAITag>
377407
);
378408
},
379-
sorter: true,
409+
sorter: isEnableSorter('status'),
380410
},
381411
{
382412
key: 'host',
383413
title: t('data.folders.Location'),
384414
dataIndex: 'host',
385-
sorter: true,
415+
sorter: isEnableSorter('host'),
386416
},
387417
{
388418
key: 'permissions',
@@ -410,7 +440,7 @@ const VFolderNodes: React.FC<VFolderNodesProps> = ({
410440
</BAIFlex>
411441
);
412442
},
413-
sorter: true,
443+
sorter: isEnableSorter('ownership_type'),
414444
},
415445

416446
{
@@ -421,6 +451,99 @@ const VFolderNodes: React.FC<VFolderNodesProps> = ({
421451
? vfolder?.user_email
422452
: vfolder?.group_name,
423453
},
454+
{
455+
key: 'usage_mode',
456+
title: t('data.UsageMode'),
457+
dataIndex: 'usage_mode',
458+
defaultHidden: true,
459+
sorter: isEnableSorter('usage_mode'),
460+
render: (mode: string) => {
461+
switch (mode) {
462+
case 'general':
463+
return t('data.General');
464+
case 'data':
465+
return t('webui.menu.Data');
466+
case 'model':
467+
return t('data.Models');
468+
default:
469+
return mode;
470+
}
471+
},
472+
},
473+
{
474+
key: 'num_files',
475+
title: t('data.folders.NumberOfFiles'),
476+
dataIndex: 'num_files',
477+
defaultHidden: true,
478+
sorter: isEnableSorter('num_files'),
479+
render: (value: number) =>
480+
value != null ? value.toLocaleString() : '-',
481+
},
482+
{
483+
key: 'cur_size',
484+
title: t('data.folders.FolderUsage'),
485+
dataIndex: 'cur_size',
486+
defaultHidden: true,
487+
sorter: isEnableSorter('cur_size'),
488+
render: (value: string) =>
489+
value != null ? `${bytesToGB(Number(value))} GB` : '-',
490+
},
491+
{
492+
key: 'max_files',
493+
title: t('data.folders.MaxFolderQuota'),
494+
dataIndex: 'max_files',
495+
defaultHidden: true,
496+
sorter: isEnableSorter('max_files'),
497+
render: (value: number) =>
498+
value != null && value > 0 ? value.toLocaleString() : '-',
499+
},
500+
{
501+
key: 'max_size',
502+
title: t('data.folders.MaxSize'),
503+
dataIndex: 'max_size',
504+
defaultHidden: true,
505+
sorter: isEnableSorter('max_size'),
506+
render: (value: string) =>
507+
value != null && Number(value) > 0
508+
? `${bytesToGB(Number(value))} GB`
509+
: '-',
510+
},
511+
{
512+
key: 'cloneable',
513+
title: t('data.folders.Cloneable'),
514+
dataIndex: 'cloneable',
515+
defaultHidden: true,
516+
sorter: isEnableSorter('cloneable'),
517+
render: (value: boolean) =>
518+
value ? t('button.Yes') : t('button.No'),
519+
},
520+
{
521+
key: 'quota_scope_id',
522+
title: t('data.QuotaScopeId'),
523+
dataIndex: 'quota_scope_id',
524+
defaultHidden: true,
525+
sorter: isEnableSorter('quota_scope_id'),
526+
render: (value: string) =>
527+
value ? <BAIText copyable>{value}</BAIText> : '-',
528+
},
529+
{
530+
key: 'last_used',
531+
title: t('credential.LastUsed'),
532+
dataIndex: 'last_used',
533+
defaultHidden: true,
534+
sorter: isEnableSorter('last_used'),
535+
render: (value: string) =>
536+
value ? dayjs(value).format('ll LT') : '-',
537+
},
538+
{
539+
key: 'created_at',
540+
title: t('data.folders.CreatedAt'),
541+
dataIndex: 'created_at',
542+
defaultHidden: true,
543+
sorter: isEnableSorter('created_at'),
544+
render: (value: string) =>
545+
value ? dayjs(value).format('ll LT') : '-',
546+
},
424547
]}
425548
{...tableProps}
426549
/>

react/src/pages/VFolderNodeListPage.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,16 @@ const VFolderNodeListPage: React.FC<VFolderNodeListPageProps> = ({
567567
},
568568
],
569569
},
570+
{
571+
key: 'cloneable',
572+
propertyLabel: t('data.folders.Cloneable'),
573+
type: 'boolean',
574+
},
575+
{
576+
key: 'quota_scope_id',
577+
propertyLabel: t('data.QuotaScopeId'),
578+
type: 'string',
579+
},
570580
]}
571581
value={queryParams.filter || undefined}
572582
onChange={(value) => {

resources/i18n/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
"ProjectFolder": "Projekt-Ordner",
476476
"ProjectFolders": "Projektordner",
477477
"QuotaPerStorageVolume": "Kontingent pro Speichervolumen",
478+
"QuotaScopeId": "ID des Kontingentsbereichs",
478479
"ReadOnly": "Nur lesen",
479480
"ReadWrite": "Lesen und schreiben",
480481
"SearchByName": "Suche mit Name",

resources/i18n/el.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
"ProjectFolder": "Φάκελος έργου",
476476
"ProjectFolders": "Φακέλοι έργου",
477477
"QuotaPerStorageVolume": "Ποσοστό ανά τόμο αποθήκευσης",
478+
"QuotaScopeId": "Αναγνωριστικό πεδίου ποσόστωσης",
478479
"ReadOnly": "Μόνο διαβάστε",
479480
"ReadWrite": "Διαβάστε και γράψτε",
480481
"SearchByName": "Αναζήτηση με όνομα",

resources/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@
476476
"ProjectFolder": "Project Folder",
477477
"ProjectFolders": "Project Folders",
478478
"QuotaPerStorageVolume": "Quota per storage volume",
479+
"QuotaScopeId": "Quota Scope ID",
479480
"ReadOnly": "Read only",
480481
"ReadWrite": "Read & Write",
481482
"SearchByName": "Search by name",

resources/i18n/es.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
"ProjectFolder": "Carpeta de proyectos",
476476
"ProjectFolders": "Carpetas de proyectos",
477477
"QuotaPerStorageVolume": "Cuota por volumen de almacenamiento",
478+
"QuotaScopeId": "ID del ámbito de cuotas",
478479
"ReadOnly": "Solo lectura",
479480
"ReadWrite": "Leer y escribir",
480481
"SearchByName": "Buscar por nombre",

resources/i18n/fi.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
"ProjectFolder": "Projektikansio",
476476
"ProjectFolders": "Projektikansiot",
477477
"QuotaPerStorageVolume": "Kiintiö tallennustilavuutta kohti",
478+
"QuotaScopeId": "Kiintiön laajuuden ID",
478479
"ReadOnly": "Vain lue",
479480
"ReadWrite": "Lue ja kirjoita",
480481
"SearchByName": "Hae nimellä",

resources/i18n/fr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
"ProjectFolder": "Dossier de projet",
476476
"ProjectFolders": "Dossiers de projet",
477477
"QuotaPerStorageVolume": "Quota par volume de stockage",
478+
"QuotaScopeId": "ID de l'étendue du quota",
478479
"ReadOnly": "Lire uniquement",
479480
"ReadWrite": "Lire et écrire",
480481
"SearchByName": "Rechercher par nom",

resources/i18n/id.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
"ProjectFolder": "Folder Proyek",
476476
"ProjectFolders": "Folder Proyek",
477477
"QuotaPerStorageVolume": "Kuota per volume penyimpanan",
478+
"QuotaScopeId": "ID Cakupan Kuota",
478479
"ReadOnly": "Baca saja",
479480
"ReadWrite": "Baca dan tulis",
480481
"SearchByName": "Cari berdasarkan nama",

resources/i18n/it.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
"ProjectFolder": "Cartella del progetto",
476476
"ProjectFolders": "Cartelle di progetto",
477477
"QuotaPerStorageVolume": "Quota per volume di archiviazione",
478+
"QuotaScopeId": "ID ambito quota",
478479
"ReadOnly": "Solo lettura",
479480
"ReadWrite": "Leggi e scrivi",
480481
"SearchByName": "Ricerca per nome",

0 commit comments

Comments
 (0)