Skip to content

Commit 7026414

Browse files
committed
feat(FR-1774): Disable auto-mounted Project vfolder creation (#4798)
Resolves #4797 ([FR-1774](https://lablup.atlassian.net/browse/FR-1774)) ## Summary - Replace Ant Design `Button` with `BAIButton` components from backend.ai-ui - Add real-time form validation to dynamically enable/disable the submit button based on form validity - Improve validation logic to prevent auto-mount folders from being created as project folders - Add new i18n translation key `ChangeTheVFolderTypeToCreateAutoMountFolder` across all 21 language files - Remove deprecated i18n key and add proper async handling for form submission ## Test plan - [ ] Verify folder creation modal opens correctly - [ ] Confirm submit button is disabled when form is invalid - [ ] Test auto-mount folder type selection - should not allow "Project" type - [ ] Verify error message displays when attempting to create auto-mount folder as project folder - [ ] Test form reset button functionality - [ ] Confirm loading state displays during folder creation [FR-1774]: https://lablup.atlassian.net/browse/FR-1774?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 819c5bd commit 7026414

22 files changed

Lines changed: 58 additions & 43 deletions

react/src/components/FolderCreateModal.tsx

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import QuestionIconWithTooltip from './QuestionIconWithTooltip';
88
import StorageSelect from './StorageSelect';
99
import {
1010
App,
11-
Button,
1211
Divider,
1312
Form,
1413
Input,
@@ -21,6 +20,7 @@ import {
2120
import { createStyles } from 'antd-style';
2221
import { FormInstance } from 'antd/lib';
2322
import {
23+
BAIButton,
2424
BAIFlex,
2525
BAIModal,
2626
BAIModalProps,
@@ -153,15 +153,15 @@ const FolderCreateModal: React.FC<FolderCreateModalProps> = ({
153153
cloneable: false,
154154
};
155155

156-
const handleOk = () => {
157-
formRef.current
156+
const handleOk = async () => {
157+
await formRef.current
158158
?.validateFields()
159159
.then((values) => {
160160
const input = {
161161
...values,
162162
group: values.type === 'user' ? null : values.group,
163163
};
164-
mutationToCreateFolder.mutate(input, {
164+
return mutationToCreateFolder.mutateAsync(input, {
165165
onSuccess: (result) => {
166166
upsertNotification({
167167
key: `folder-create-success-${result.id}`,
@@ -198,36 +198,35 @@ const FolderCreateModal: React.FC<FolderCreateModalProps> = ({
198198
title={t('data.CreateANewStorageFolder')}
199199
footer={
200200
<BAIFlex justify="between">
201-
<Button
201+
<BAIButton
202202
danger
203203
onClick={() => {
204204
formRef.current?.resetFields();
205205
}}
206206
>
207207
{t('button.Reset')}
208-
</Button>
208+
</BAIButton>
209209
<BAIFlex gap={token.marginSM}>
210-
<Button
210+
<BAIButton
211211
onClick={() => {
212212
onRequestClose();
213213
}}
214214
>
215215
{t('button.Cancel')}
216-
</Button>
217-
<Button
216+
</BAIButton>
217+
<BAIButton
218218
type="primary"
219219
data-testid="create-folder-button"
220-
onClick={() => {
221-
handleOk();
220+
action={async () => {
221+
await handleOk();
222222
}}
223223
>
224224
{t('data.Create')}
225-
</Button>
225+
</BAIButton>
226226
</BAIFlex>
227227
</BAIFlex>
228228
}
229229
width={MODAL_WIDTH}
230-
okButtonProps={{ loading: mutationToCreateFolder.isPending }}
231230
onCancel={() => {
232231
onRequestClose();
233232
}}
@@ -335,8 +334,9 @@ const FolderCreateModal: React.FC<FolderCreateModalProps> = ({
335334
{({ getFieldValue }) => {
336335
const usageMode = getFieldValue('usage_mode');
337336
const shouldDisableProject =
338-
usageMode === 'model' &&
339-
currentProject?.name !== MODEL_STORE_PROJECT_NAME;
337+
(usageMode === 'model' &&
338+
currentProject?.name !== MODEL_STORE_PROJECT_NAME) ||
339+
usageMode === 'automount';
340340

341341
return (
342342
<Form.Item
@@ -348,21 +348,32 @@ const FolderCreateModal: React.FC<FolderCreateModalProps> = ({
348348
({ getFieldValue }) => ({
349349
validator(__, value) {
350350
const currentUsageMode = getFieldValue('usage_mode');
351-
const isInvalid =
351+
const isInvalidModelProjectFolder =
352352
value === 'project' &&
353353
currentUsageMode === 'model' &&
354354
currentProject?.name !== MODEL_STORE_PROJECT_NAME;
355+
const isInvalidAutoMountFolder =
356+
value === 'project' && currentUsageMode === 'automount';
355357

356-
if (isInvalid) {
358+
if (isInvalidModelProjectFolder) {
359+
return Promise.reject(
360+
new Error(
361+
t(
362+
'data.folders.CreateModelFolderOnlyInExclusiveProject',
363+
),
364+
),
365+
);
366+
} else if (isInvalidAutoMountFolder) {
357367
return Promise.reject(
358368
new Error(
359369
t(
360-
'data.folders.ChangeTheCurrentProjectToModelStoreOrSelectUserType',
370+
'data.folders.ChangeTheVFolderTypeToCreateAutoMountFolder',
361371
),
362372
),
363373
);
374+
} else {
375+
return Promise.resolve();
364376
}
365-
return Promise.resolve();
366377
},
367378
}),
368379
{
@@ -404,9 +415,13 @@ const FolderCreateModal: React.FC<FolderCreateModalProps> = ({
404415
<Tooltip
405416
title={
406417
shouldDisableProject
407-
? t(
408-
'data.folders.CreateModelFolderOnlyInExclusiveProject',
409-
)
418+
? usageMode === 'model'
419+
? t(
420+
'data.folders.CreateModelFolderOnlyInExclusiveProject',
421+
)
422+
: t(
423+
'data.folders.ChangeTheVFolderTypeToCreateAutoMountFolder',
424+
)
410425
: undefined
411426
}
412427
>

resources/i18n/de.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@
358358
"CannotDeleteFolder": "Der in einer oder mehreren Sitzungen bereitgestellte Ordner kann nicht gelöscht werden. Bitte beenden Sie zuerst die Sitzung.",
359359
"CannotDeletePipelineFolder": "Sie können Pipeline -Ordner nicht löschen.",
360360
"CannotRestorePipelineFolder": "Sie können Pipeline -Ordner nicht wiederherstellen.",
361-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Modellprojektordner können nur in Model Store -Exclusive -Projekten erstellt werden. \nÄndern Sie das aktuelle Projekt- oder Benutzertyp.",
361+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "Der automatisch eingebundene Ordner kann nicht als Projektordner angelegt werden.",
362362
"CloneAFolder": "Einen Ordner klonen",
363363
"CloneFolder": "Ordner klonen",
364364
"Cloneable": "klonbar",

resources/i18n/el.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@
356356
"CannotDeleteFolder": "Δεν είναι δυνατή η διαγραφή του φακέλου που είναι τοποθετημένος σε μία ή περισσότερες περιόδους σύνδεσης. Κλείστε πρώτα τη συνεδρία.",
357357
"CannotDeletePipelineFolder": "Δεν μπορείτε να διαγράψετε τους φακέλους αγωγών.",
358358
"CannotRestorePipelineFolder": "Δεν μπορείτε να επαναφέρετε τους φακέλους αγωγών.",
359-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Οι φακέλοι έργων μοντέλων μπορούν να δημιουργηθούν μόνο σε αποκλειστικά έργα Model Store. \nΑλλάξτε το τρέχον έργο ή τον τύπο χρήστη.",
359+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "Δεν είναι δυνατή η δημιουργία του φακέλου αυτόματης προσάρτησης ως φακέλου του έργου.",
360360
"CloneAFolder": "Κλωνοποίηση φακέλου",
361361
"CloneFolder": "Φάκελος κλωνοποίησης",
362362
"Cloneable": "Κλωνοποιήσιμο",

resources/i18n/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@
361361
"CannotDeleteFolder": "Cannot delete folder mounted in one or more sessions. Please terminate the session first.",
362362
"CannotDeletePipelineFolder": "You can't delete pipeline folders.",
363363
"CannotRestorePipelineFolder": "You can't restore pipeline folders.",
364-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Model project folders can only be created in model store–exclusive projects. Change the current project or user type.",
364+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "Unable to create the auto-mount folder as a project folder.",
365365
"CloneAFolder": "Clone folder",
366366
"CloneFolder": "Clone folder",
367367
"Cloneable": "Cloneable",

resources/i18n/es.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@
358358
"CannotDeleteFolder": "No se puede eliminar la carpeta montada en una o más sesiones. Por favor, termine la sesión primero.",
359359
"CannotDeletePipelineFolder": "No puede eliminar las carpetas de tuberías.",
360360
"CannotRestorePipelineFolder": "No puedes restaurar las carpetas de tuberías.",
361-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Las carpetas de proyectos modelo solo se pueden crear en proyectos exclusivos de Model Store. \nCambie el proyecto o tipo de usuario actual.",
361+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "No se puede crear la carpeta de montaje automática como carpeta del proyecto.",
362362
"CloneAFolder": "Clonar una carpeta",
363363
"CloneFolder": "Clonar carpeta",
364364
"Cloneable": "Clonable",

resources/i18n/fi.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@
358358
"CannotDeleteFolder": "Yhdessä tai useammassa istunnossa asennettua kansiota ei voi poistaa. Lopeta istunto ensin.",
359359
"CannotDeletePipelineFolder": "Et voi poistaa putkilinjan kansioita.",
360360
"CannotRestorePipelineFolder": "Putkilinjan kansiot eivät voi palauttaa.",
361-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Malliprojektin kansiot voidaan luoda vain Model Store - Exclusive -projekteihin. \nVaihda nykyinen projekti tai käyttäjätyyppi.",
361+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "Automaattisesti liitettävää kansiota ei voi luoda projektikansioksi.",
362362
"CloneAFolder": "Kloonaa kansio",
363363
"CloneFolder": "Kloonattu kansio",
364364
"Cloneable": "Kloonattavissa",

resources/i18n/fr.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@
358358
"CannotDeleteFolder": "Impossible de supprimer le dossier monté dans une ou plusieurs sessions. Veuillez d'abord terminer la session.",
359359
"CannotDeletePipelineFolder": "Vous ne pouvez pas supprimer les dossiers du pipeline.",
360360
"CannotRestorePipelineFolder": "Vous ne pouvez pas restaurer les dossiers du pipeline.",
361-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Les dossiers de projets modèles ne peuvent être créés que dans des projets exclusifs en magasin de modèles. \nModifiez le projet ou le type d'utilisateur actuel.",
361+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "Impossible de créer le dossier de montage automatique en tant que dossier de projet.",
362362
"CloneAFolder": "Cloner un dossier",
363363
"CloneFolder": "Cloner un dossier",
364364
"Cloneable": "Clonable",

resources/i18n/id.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@
357357
"CannotDeleteFolder": "Tidak dapat menghapus folder yang dipasang di satu atau beberapa sesi. Mohon hentikan sesi terlebih dahulu.",
358358
"CannotDeletePipelineFolder": "Anda tidak dapat menghapus folder pipa.",
359359
"CannotRestorePipelineFolder": "Anda tidak dapat mengembalikan folder pipa.",
360-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Folder Proyek Model hanya dapat dibuat di proyek Model Store -Eksklusif. \nUbah proyek atau jenis pengguna saat ini.",
360+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "Tidak dapat membuat folder mount otomatis sebagai folder proyek.",
361361
"CloneAFolder": "Klon folder",
362362
"CloneFolder": "Folder klon",
363363
"Cloneable": "Dapat diklon",

resources/i18n/it.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@
357357
"CannotDeleteFolder": "Impossibile eliminare la cartella montata in una o più sessioni. Si prega di terminare prima la sessione.",
358358
"CannotDeletePipelineFolder": "Non puoi eliminare le cartelle della pipeline.",
359359
"CannotRestorePipelineFolder": "Non puoi ripristinare le cartelle della pipeline.",
360-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "Le cartelle del progetto di modello possono essere create solo in progetti esclusivi del negozio di modelli. \nModificare il progetto corrente o il tipo di utente.",
360+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "Impossibile creare la cartella di montaggio automatica come cartella del progetto.",
361361
"CloneAFolder": "Clonare una cartella",
362362
"CloneFolder": "Clona la cartella",
363363
"Cloneable": "Clonabile",

resources/i18n/ja.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@
357357
"CannotDeleteFolder": "1つ以上のセッションでマウントされたフォルダを削除できません。最初にセッションを終了してください。",
358358
"CannotDeletePipelineFolder": "パイプラインフォルダーを削除することはできません。",
359359
"CannotRestorePipelineFolder": "パイプラインフォルダーを復元することはできません。",
360-
"ChangeTheCurrentProjectToModelStoreOrSelectUserType": "モデルプロジェクトフォルダーは、モデルストアと独占プロジェクトでのみ作成できます。\n現在のプロジェクトまたはユーザータイプを変更します",
360+
"ChangeTheVFolderTypeToCreateAutoMountFolder": "自動マウントフォルダをプロジェクトフォルダとして作成できません",
361361
"CloneAFolder": "フォルダのクローンを作成する",
362362
"CloneFolder": "フォルダクローン",
363363
"Cloneable": "クローン可能",

0 commit comments

Comments
 (0)