Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"Frgmts",
"Gaudi",
"hoverable",
"huggingface",
"Hyperaccel",
"keypair",
"Keypairs",
Expand Down
2 changes: 1 addition & 1 deletion packages/backend.ai-ui/src/components/Table/BAITable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ const BAITable = <RecordType extends object = any>({
{tableProps.pagination !== false && (
<BAIFlex justify="end" gap={'xs'}>
<Pagination
size={tableProps.size === 'small' ? 'small' : 'default'}
size={tableProps.pagination?.size || 'small'}
align="end"
pageSizeOptions={['10', '20', '50']}
showSizeChanger={true}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,13 @@ const BAIArtifactTable = ({

return (
<BAITable<Artifact>
size="small"
rowKey={(record) => record.id}
columns={filterOutEmpty(columns)}
dataSource={filterOutNullAndUndefined(artifact)}
scroll={{ x: 'max-content' }}
{...tableProps}
></BAITable>
/>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { BAIHuggingFaceRegistrySettingModalFragment$key } from '../../__generated__/BAIHuggingFaceRegistrySettingModalFragment.graphql';
import { UpdateHuggingFaceRegistryInput } from '../../__generated__/BAIHuggingFaceRegistrySettingModalMutation.graphql';
import { toLocalId } from '../../helper';
import { useErrorMessageResolver } from '../../hooks';
import BAIFlex from '../BAIFlex';
import BAIModal, { BAIModalProps } from '../BAIModal';
import BAIUnmountAfterClose from '../BAIUnmountAfterClose';
import { EditOutlined } from '@ant-design/icons';
import { App, Button, Form, FormInstance, Input } from 'antd';
import { useState, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { graphql, useFragment, useMutation } from 'react-relay';

export type BAIHuggingFaceRegistrySettingModalFragmentKey =
BAIHuggingFaceRegistrySettingModalFragment$key;

export interface BAIHuggingFaceRegistrySettingModalProps extends BAIModalProps {
huggingFaceRegistryFragment?: BAIHuggingFaceRegistrySettingModalFragmentKey;
}

const BAIHuggingFaceRegistrySettingModal = ({
huggingFaceRegistryFragment,
...baiModalProps
}: BAIHuggingFaceRegistrySettingModalProps) => {
'use memo';
const { t } = useTranslation();
const { message, modal } = App.useApp();
const { getErrorMessage } = useErrorMessageResolver();

const formRef = useRef<FormInstance>(null);

const huggingFaceRegistry = useFragment(
graphql`
fragment BAIHuggingFaceRegistrySettingModalFragment on HuggingFaceRegistry {
id
token
}
`,
huggingFaceRegistryFragment,
);

const [updateHuggingFaceRegistry, isInflightUpdateHuggingFaceRegistry] =
useMutation(graphql`
mutation BAIHuggingFaceRegistrySettingModalMutation(
$input: UpdateHuggingFaceRegistryInput!
) {
updateHuggingfaceRegistry(input: $input) {
huggingfaceRegistry {
id
token
}
}
}
`);

const initialToken = huggingFaceRegistry?.token;
const [isEditing, setIsEditing] = useState(false);

const hasToken = initialToken && initialToken.length > 0;

const executeUpdate = (values: UpdateHuggingFaceRegistryInput) => {
updateHuggingFaceRegistry({
variables: {
input: {
id: toLocalId(huggingFaceRegistry!.id),
token: values.token ?? '',
},
},
onCompleted: (_res, errors) => {
if (errors && errors.length > 0) {
errors.forEach((err) => message.error(getErrorMessage(err)));
return;
}
message.success(
t('comp:HuggingFaceRegistrySettingModal.TokenUpdatedSuccessfully'),
);
baiModalProps.onOk?.({} as React.MouseEvent<HTMLButtonElement>);
},
onError: (err) => {
message.error(getErrorMessage(err));
},
});
};

const handleOk = () => {
if (!huggingFaceRegistry?.id) {
message.error(
t('comp:HuggingFaceRegistrySettingModal.HuggingFaceRegistryNotFound'),
);
return;
}

if (hasToken && !isEditing) {
// If not editing, no need to update
message.success(
t('comp:HuggingFaceRegistrySettingModal.NoChangesToSave'),
);
baiModalProps.onOk?.({} as React.MouseEvent<HTMLButtonElement>);
return;
}

formRef.current
?.validateFields()
.then((values) => {
// Check if current token exists and is empty string, but new token is not empty
if (hasToken && !values.token) {
modal.confirm({
title: t('comp:HuggingFaceRegistrySettingModal.ResetTokenConfirm'),
content: t(
'comp:HuggingFaceRegistrySettingModal.ResetTokenConfirmMessage',
),
onOk() {
executeUpdate(values);
},
onCancel() {
// Don't proceed with update
},
okButtonProps: { danger: true },
okText: t('general.button.Reset'),
});
} else {
executeUpdate(values);
}
})
.catch(() => {});
};

return (
<BAIUnmountAfterClose>
<BAIModal
destroyOnHidden
afterClose={() => setIsEditing(false)}
{...baiModalProps}
title={t('comp:HuggingFaceRegistrySettingModal.HuggingFaceSettings')}
centered
okText={t('general.button.Save')}
onOk={handleOk}
okButtonProps={{
loading: isInflightUpdateHuggingFaceRegistry,
}}
>
<Form ref={formRef} layout="vertical">
<Form.Item
label={t('comp:HuggingFaceRegistrySettingModal.Token')}
name="token"
>
{hasToken && !isEditing ? (
<BAIFlex gap={'xs'}>
{/* For security, we display a masked token instead of initial value. */}
<Input type="password" disabled value="••••••••••••••••" />
<Button
icon={<EditOutlined />}
onClick={() => {
setIsEditing(true);
}}
type="text"
/>
</BAIFlex>
) : (
<Input.Password
placeholder={t(
'comp:HuggingFaceRegistrySettingModal.EnterToken',
)}
autoFocus={isEditing}
/>
)}
</Form.Item>
</Form>
</BAIModal>
</BAIUnmountAfterClose>
);
};

export default BAIHuggingFaceRegistrySettingModal;
5 changes: 5 additions & 0 deletions packages/backend.ai-ui/src/components/fragments/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@ export type {
BAIActivateArtifactsModalArtifactsFragmentKey,
} from './BAIActivateArtifactsModal';
export { default as BAIVFolderDeleteButton } from './BAIVFolderDeleteButton';
export { default as BAIHuggingFaceRegistrySettingModal } from './BAIHuggingFaceRegistrySettingModal';
export type {
BAIHuggingFaceRegistrySettingModalProps,
BAIHuggingFaceRegistrySettingModalFragmentKey,
} from './BAIHuggingFaceRegistrySettingModal';
11 changes: 11 additions & 0 deletions packages/backend.ai-ui/src/locale/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@
"FileNameRequired": "Bitte geben Sie einen Datei- oder Ordnernamen ein."
}
},
"comp:HuggingFaceRegistrySettingModal": {
"HuggingFaceRegistryNotFound": "Hugging Face-Registrierung nicht gefunden.",
"HuggingFaceSettings": "Einstellungen für Hugging Face.",
"NoChangesToSave": "Keine Änderungen zum Speichern",
"ResetTokenConfirm": "Token zurücksetzen",
"ResetTokenConfirmMessage": "Der Token scheint leer zu sein. \nMöchten Sie es mit einem neuen Wert initialisieren?",
"Token": "Token",
"TokenUpdatedSuccessfully": "Token erfolgreich aktualisiert."
},
"comp:PaginationInfoText": {
"Total": "{{start}} - {{end}} von {{total}} Elementen"
},
Expand All @@ -156,6 +165,8 @@
"Delete": "Löschen",
"Expand": "Expandieren",
"Remove": "Entfernen",
"Reset": "Zurücksetzen",
"Save": "Speichern",
"Upload": "Hochladen"
},
"modal": {
Expand Down
11 changes: 11 additions & 0 deletions packages/backend.ai-ui/src/locale/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@
"FileNameRequired": "Εισαγάγετε ένα αρχείο ή ένα όνομα φακέλου."
}
},
"comp:HuggingFaceRegistrySettingModal": {
"HuggingFaceRegistryNotFound": "Το μητρώο Hugging Face δεν βρέθηκε.",
"HuggingFaceSettings": "Ρυθμίσεις Hugging Face",
"NoChangesToSave": "Δεν υπάρχουν αλλαγές για αποθήκευση",
"ResetTokenConfirm": "Επαναφορά διακριτικού",
"ResetTokenConfirmMessage": "Το διακριτικό φαίνεται να είναι κενό. \nΘέλετε να το αρχικοποιήσετε με μια νέα τιμή;",
"Token": "Ενδειξη",
"TokenUpdatedSuccessfully": "Το διακριτικό ενημερώθηκε με επιτυχία."
},
"comp:PaginationInfoText": {
"Total": "{{start}} - {{end}} των στοιχείων {{total}}"
},
Expand All @@ -156,6 +165,8 @@
"Delete": "Διαγράφω",
"Expand": "Διαστέλλω",
"Remove": "Αφαιρώ",
"Reset": "Επαναφορά",
"Save": "Αποθήκευση",
"Upload": "Μεταφορτώσω"
},
"modal": {
Expand Down
12 changes: 12 additions & 0 deletions packages/backend.ai-ui/src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,16 @@
"FileNameRequired": "Please enter a file or folder name."
}
},
"comp:HuggingFaceRegistrySettingModal": {
"EnterToken": "Enter your HuggingFace token",
"HuggingFaceRegistryNotFound": "Hugging Face Registry not found.",
"HuggingFaceSettings": "Hugging Face Settings",
"NoChangesToSave": "No changes to save",
"ResetTokenConfirm": "Reset Token",
"ResetTokenConfirmMessage": "The token appears to be empty. Would you like to initialize it with a new value?",
"Token": "Token",
"TokenUpdatedSuccessfully": "Token updated successfully."
},
"comp:PaginationInfoText": {
"Total": "{{start}} - {{end}} of {{total}} items"
},
Expand All @@ -159,6 +169,8 @@
"Delete": "Delete",
"Expand": "Expand",
"Remove": "Remove",
"Reset": "Reset",
"Save": "Save",
"Upload": "Upload"
},
"modal": {
Expand Down
11 changes: 11 additions & 0 deletions packages/backend.ai-ui/src/locale/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@
"FileNameRequired": "Ingrese un nombre de archivo o carpeta."
}
},
"comp:HuggingFaceRegistrySettingModal": {
"HuggingFaceRegistryNotFound": "Hugging Face Registro no encontrado.",
"HuggingFaceSettings": "Configuración de Hugging Face",
"NoChangesToSave": "No hay cambios que guardar",
"ResetTokenConfirm": "Restablecer token",
"ResetTokenConfirmMessage": "El token parece estar vacío. \n¿Le gustaría inicializarlo con un nuevo valor?",
"Token": "Simbólico",
"TokenUpdatedSuccessfully": "Token actualizado exitosamente."
},
"comp:PaginationInfoText": {
"Total": "{{start}} - {{end}} de {{total}} elementos"
},
Expand All @@ -156,6 +165,8 @@
"Delete": "Borrar",
"Expand": "Expandir",
"Remove": "Eliminar",
"Reset": "Reiniciar",
"Save": "Ahorrar",
"Upload": "Subir"
},
"modal": {
Expand Down
11 changes: 11 additions & 0 deletions packages/backend.ai-ui/src/locale/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@
"FileNameRequired": "Anna tiedoston tai kansionimi."
}
},
"comp:HuggingFaceRegistrySettingModal": {
"HuggingFaceRegistryNotFound": "Hugging Face-rekisteriä ei löydy.",
"HuggingFaceSettings": "Halaavat kasvot -asetukset",
"NoChangesToSave": "Ei tallennettavia muutoksia",
"ResetTokenConfirm": "Reset Token",
"ResetTokenConfirmMessage": "Tunnus näyttää olevan tyhjä. \nHaluatko alustaa sen uudella arvolla?",
"Token": "Token",
"TokenUpdatedSuccessfully": "Tunnus päivitetty onnistuneesti."
},
"comp:PaginationInfoText": {
"Total": "{{start}}–{{end}} yhteensä {{total}} kohteesta"
},
Expand All @@ -156,6 +165,8 @@
"Delete": "Poistaa",
"Expand": "Laajentaa",
"Remove": "Poistaa",
"Reset": "Nollaa",
"Save": "Tallentaa",
"Upload": "Ladata"
},
"modal": {
Expand Down
11 changes: 11 additions & 0 deletions packages/backend.ai-ui/src/locale/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@
"FileNameRequired": "Veuillez saisir un fichier ou un nom de dossier."
}
},
"comp:HuggingFaceRegistrySettingModal": {
"HuggingFaceRegistryNotFound": "Registre Hugging Face introuvable.",
"HuggingFaceSettings": "Paramètres Hugging Face",
"NoChangesToSave": "Aucune modification à enregistrer",
"ResetTokenConfirm": "Réinitialiser le jeton",
"ResetTokenConfirmMessage": "Le jeton semble vide. \nSouhaitez-vous l'initialiser avec une nouvelle valeur ?",
"Token": "Jeton",
"TokenUpdatedSuccessfully": "Jeton mis à jour avec succès."
},
"comp:PaginationInfoText": {
"Total": "{{start}} - {{end}} des éléments {{total}}"
},
Expand All @@ -156,6 +165,8 @@
"Delete": "Supprimer",
"Expand": "Développer",
"Remove": "Retirer",
"Reset": "Réinitialiser",
"Save": "Sauvegarder",
"Upload": "Télécharger"
},
"modal": {
Expand Down
9 changes: 9 additions & 0 deletions packages/backend.ai-ui/src/locale/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@
"FileNameRequired": "Harap masukkan file atau nama folder."
}
},
"comp:HuggingFaceRegistrySettingModal": {
"HuggingFaceRegistryNotFound": "Registri Wajah Memeluk tidak ditemukan.",
"NoChangesToSave": "Tidak ada perubahan untuk disimpan",
"ResetTokenConfirm": "Setel Ulang Token",
"ResetTokenConfirmMessage": "Tokennya tampaknya kosong. \nApakah Anda ingin menginisialisasinya dengan nilai baru?",
"TokenUpdatedSuccessfully": "Token berhasil diperbarui."
},
"comp:PaginationInfoText": {
"Total": "{{start}} - {{end}} dari {{total}} item"
},
Expand All @@ -156,6 +163,8 @@
"Delete": "Menghapus",
"Expand": "Memperluas",
"Remove": "Menghapus",
"Reset": "Mengatur ulang",
"Save": "Simpan",
"Upload": "Mengunggah"
},
"modal": {
Expand Down
Loading