diff --git a/react/data/schema.graphql b/react/data/schema.graphql index 6cd6b7182c..ab1837274d 100644 --- a/react/data/schema.graphql +++ b/react/data/schema.graphql @@ -596,6 +596,12 @@ type KeyPairResourcePolicy { max_vfolder_count: Int @deprecated(reason: "Deprecated since 23.09.4") max_vfolder_size: BigInt @deprecated(reason: "Deprecated since 23.09.4") max_quota_scope_size: BigInt @deprecated(reason: "Deprecated since 23.09.4") + + """Added in 24.03.4.""" + max_pending_session_count: Int + + """Added in 24.03.4.""" + max_pending_session_resource_slots: JSONString } type UserResourcePolicy { @@ -1387,6 +1393,12 @@ input CreateKeyPairResourcePolicyInput { max_vfolder_count: Int @deprecated(reason: "Deprecated since 23.09.4") max_vfolder_size: BigInt @deprecated(reason: "Deprecated since 23.09.4") max_quota_scope_size: BigInt @deprecated(reason: "Deprecated since 23.09.4") + + """Added in 24.03.4.""" + max_pending_session_count: Int + + """Added in 24.03.4.""" + max_pending_session_resource_slots: JSONString } type ModifyKeyPairResourcePolicy { @@ -1406,6 +1418,12 @@ input ModifyKeyPairResourcePolicyInput { max_vfolder_count: Int @deprecated(reason: "Deprecated since 23.09.4") max_vfolder_size: BigInt @deprecated(reason: "Deprecated since 23.09.4") max_quota_scope_size: BigInt @deprecated(reason: "Deprecated since 23.09.4") + + """Added in 24.03.4.""" + max_pending_session_count: Int + + """Added in 24.03.4.""" + max_pending_session_resource_slots: JSONString } type DeleteKeyPairResourcePolicy { diff --git a/react/src/components/AllowedHostNamesSelect.tsx b/react/src/components/AllowedHostNamesSelect.tsx new file mode 100644 index 0000000000..1f0c0a3815 --- /dev/null +++ b/react/src/components/AllowedHostNamesSelect.tsx @@ -0,0 +1,24 @@ +import { useAllowedHostNames } from '../hooks/backendai'; +import { Select, SelectProps } from 'antd'; +import _ from 'lodash'; +import React from 'react'; + +interface AllowedHostNamesSelectProps extends SelectProps {} + +const AllowedHostNamesSelect: React.FC = ({ + ...selectProps +}) => { + const allowedHostNames = useAllowedHostNames(); + + return ( + + ); +}; + +export default AllowedHostNamesSelect; diff --git a/react/src/components/DynamicUnitInputNumberWithUnlimitedFormItems.tsx b/react/src/components/DynamicUnitInputNumberWithUnlimitedFormItems.tsx new file mode 100644 index 0000000000..c476d8762e --- /dev/null +++ b/react/src/components/DynamicUnitInputNumberWithUnlimitedFormItems.tsx @@ -0,0 +1,72 @@ +import DynamicUnitInputNumber, { + DynamicUnitInputNumberProps, +} from './DynamicUnitInputNumber'; +import Flex from './Flex'; +import { Form } from 'antd'; +import Checkbox, { CheckboxChangeEvent } from 'antd/es/checkbox'; +import _ from 'lodash'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +interface DynamicUnitInputNumberWithUnlimitedFormItemsProps + extends DynamicUnitInputNumberProps { + fieldName: string | string[]; + checkboxFieldName: string; +} + +const DynamicUnitInputNumberWithUnlimitedFormItems: React.FC< + DynamicUnitInputNumberWithUnlimitedFormItemsProps +> = ({ fieldName, checkboxFieldName, ...otherProps }) => { + const { t } = useTranslation(); + const form = Form.useFormInstance(); + return ( + + + prevValues?.[checkboxFieldName] !== currentValues?.[checkboxFieldName] + } + > + {() => { + const disabled = form.getFieldValue(checkboxFieldName) === true; + return ( + + + + ); + }} + + + { + if (e.target.checked) { + form.setFieldValue(fieldName, null); + } else { + form.setFieldValue( + fieldName, + form.getFieldValue(fieldName) || + otherProps.value || + otherProps.defaultValue, + ); + } + form.validateFields( + typeof fieldName === 'string' ? [fieldName] : fieldName, + ); + }} + > + {t('resourcePolicy.Unlimited')} + + + + ); +}; + +export default DynamicUnitInputNumberWithUnlimitedFormItems; diff --git a/react/src/components/FormItemWithUnlimited.tsx b/react/src/components/FormItemWithUnlimited.tsx new file mode 100644 index 0000000000..8ad6512209 --- /dev/null +++ b/react/src/components/FormItemWithUnlimited.tsx @@ -0,0 +1,66 @@ +import Flex from './Flex'; +import { Form, FormInstance } from 'antd'; +import Checkbox, { CheckboxChangeEvent } from 'antd/es/checkbox'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +interface FormItemWithUnlimitedProps { + form: FormInstance; + fieldName: string | Array; + checkboxFieldName: string; + label?: string; + fallbackValue?: any; + render: (disabled: boolean) => React.ReactNode; +} + +const FormItemWithUnlimited: React.FC = ({ + form, + fieldName, + checkboxFieldName, + label, + fallbackValue, + render, +}) => { + const { t } = useTranslation(); + + return ( + + { + return ( + prevValues[checkboxFieldName] !== currentValues[checkboxFieldName] + ); + }} + > + {() => { + const disabled = form.getFieldValue(checkboxFieldName); + return ( + + {render?.(disabled)} + + ); + }} + + + { + if (e.target.checked) { + form.setFieldValue(fieldName, null); + } else if (fallbackValue) { + form.setFieldValue(fieldName, fallbackValue); + } + form.validateFields( + typeof fieldName === 'string' ? [fieldName] : fieldName, + ); + }} + > + {t('resourcePolicy.Unlimited')} + + + + ); +}; + +export default FormItemWithUnlimited; diff --git a/react/src/components/KeypairResourcePolicyList.tsx b/react/src/components/KeypairResourcePolicyList.tsx index b9b6622489..aaee361ea0 100644 --- a/react/src/components/KeypairResourcePolicyList.tsx +++ b/react/src/components/KeypairResourcePolicyList.tsx @@ -1,5 +1,6 @@ import { useSuspendedBackendaiClient, useUpdatableState } from '../hooks'; import Flex from './Flex'; +import KeypairResourcePolicySettingModal from './KeypairResourcePolicySettingModal'; import ResourceNumber from './ResourceNumber'; import TableColumnsSettingModal from './TableColumnsSettingModal'; import { KeypairResourcePolicyListMutation } from './__generated__/KeypairResourcePolicyListMutation.graphql'; @@ -7,6 +8,7 @@ import { KeypairResourcePolicyListQuery, KeypairResourcePolicyListQuery$data, } from './__generated__/KeypairResourcePolicyListQuery.graphql'; +import { KeypairResourcePolicySettingModalFragment$key } from './__generated__/KeypairResourcePolicySettingModalFragment.graphql'; import { DeleteOutlined, PlusOutlined, @@ -40,10 +42,13 @@ const KeypairResourcePolicyList: React.FC = ( const [keypairResourcePolicyFetchKey, updateKeypairResourcePolicyFetchKey] = useUpdatableState('initial-fetch'); - const [isOpenColumnsSetting, setIsOpenColumnsSetting] = useState(false); const [isRefetchPending, startRefetchTransition] = useTransition(); + const [isOpenColumnsSetting, setIsOpenColumnsSetting] = useState(false); + const [isCreatingPolicySetting, setIsCreatingPolicySetting] = useState(false); const [inFlightResourcePolicyName, setInFlightResourcePolicyName] = useState(); + const [editingKeypairResourcePolicy, setEditingKeypairResourcePolicy] = + useState(); const baiClient = useSuspendedBackendaiClient(); const enableParsingStoragePermission = @@ -66,6 +71,7 @@ const KeypairResourcePolicyList: React.FC = ( max_vfolder_count @deprecatedSince(version: "23.09.4") max_vfolder_size @deprecatedSince(version: "23.09.4") max_quota_scope_size @deprecatedSince(version: "23.09.4") + ...KeypairResourcePolicySettingModalFragment } } `, @@ -187,7 +193,9 @@ const KeypairResourcePolicyList: React.FC = ( style={{ color: token.colorInfo, }} - onClick={() => {}} + onClick={() => { + setEditingKeypairResourcePolicy(row); + }} /> = ( }} /> } - onClick={() => {}} + loading={ + inFlightResourcePolicyName === + row?.name + keypairResourcePolicyFetchKey + } + disabled={ + isInflightDelete && + inFlightResourcePolicyName !== + row?.name + keypairResourcePolicyFetchKey + } /> @@ -273,14 +289,19 @@ const KeypairResourcePolicyList: React.FC = ( ); }} /> - displayedColumnKeys?.includes(_.toString(column.key)), @@ -317,6 +338,23 @@ const KeypairResourcePolicyList: React.FC = ( }} /> + policy?.name || '', + )} + open={!!editingKeypairResourcePolicy || isCreatingPolicySetting} + keypairResourcePolicyFrgmt={editingKeypairResourcePolicy || null} + onRequestClose={(success) => { + setEditingKeypairResourcePolicy(null); + setIsCreatingPolicySetting(false); + if (success) { + startRefetchTransition(() => { + updateKeypairResourcePolicyFetchKey(); + }); + } + }} + /> ); }; diff --git a/react/src/components/KeypairResourcePolicySettingModal.tsx b/react/src/components/KeypairResourcePolicySettingModal.tsx new file mode 100644 index 0000000000..cdcb8b2f54 --- /dev/null +++ b/react/src/components/KeypairResourcePolicySettingModal.tsx @@ -0,0 +1,347 @@ +import { iSizeToSize } from '../helper'; +import { useSuspendedBackendaiClient } from '../hooks'; +import AllowedHostNamesSelect from './AllowedHostNamesSelect'; +import DynamicUnitInputNumber from './DynamicUnitInputNumber'; +import FormItemWithUnlimited from './FormItemWithUnlimited'; +import { + KeypairResourcePolicySettingModalFragment$data, + KeypairResourcePolicySettingModalFragment$key, +} from './__generated__/KeypairResourcePolicySettingModalFragment.graphql'; +import { + Card, + Col, + Form, + Input, + InputNumber, + Modal, + ModalProps, + Row, +} from 'antd'; +import graphql from 'babel-plugin-relay/macro'; +import _ from 'lodash'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useFragment } from 'react-relay'; + +type TotalResourceSlots = { + cpu?: number; + mem?: number; + 'cuda.device'?: number; + 'cuda.shares'?: number; +}; + +interface KeypairResourcePolicySettingModalProps extends ModalProps { + existingPolicyNames?: string[]; + keypairResourcePolicyFrgmt?: KeypairResourcePolicySettingModalFragment$key | null; + onRequestClose: (success?: boolean) => void; +} + +const KeypairResourcePolicySettingModal: React.FC< + KeypairResourcePolicySettingModalProps +> = ({ + existingPolicyNames, + keypairResourcePolicyFrgmt = null, + onRequestClose, + ...props +}) => { + const { t } = useTranslation(); + const [form] = Form.useForm(); + const baiClient = useSuspendedBackendaiClient(); + const isDeprecatedMaxVfolderCountInKeypairResourcePolicy = + baiClient?.supports( + 'deprecated-max-vfolder-count-in-keypair-resource-policy', + ); + + const keypairResourcePolicy = useFragment( + graphql` + fragment KeypairResourcePolicySettingModalFragment on KeyPairResourcePolicy { + name + total_resource_slots + max_session_lifetime + max_concurrent_sessions + max_containers_per_session + idle_timeout + allowed_vfolder_hosts + max_vfolder_count @deprecatedSince(version: "23.09.4") + max_vfolder_size @deprecatedSince(version: "23.09.4") + max_quota_scope_size @deprecatedSince(version: "23.09.4") + } + `, + keypairResourcePolicyFrgmt, + ); + + const generateResourcePolicySettingUnlimitedFlags = ( + policy: TotalResourceSlots, + ) => ({ + totalResourceSlotsCPUUnlimited: _.isUndefined(policy?.cpu), + totalResourceSlotsMEMUnlimited: _.isUndefined(policy?.mem), + totalResourceSlotsGPUUnlimited: _.isUndefined(policy?.['cuda.device']), + totalResourceSlotsFGPUUnlimited: _.isUndefined(policy?.['cuda.shares']), + }); + + const generateSessionSettingUnlimitedFlags = ( + policy: KeypairResourcePolicySettingModalFragment$data | null | undefined, + ) => ({ + maxContainersPerSessionUnlimited: + _.isUndefined(policy?.max_containers_per_session) || + policy?.max_containers_per_session === 0, + maxSessionLifetimeUnlimited: + _.isUndefined(policy?.max_session_lifetime) || + policy?.max_session_lifetime === 0, + maxConcurrentSessionsUnlimited: + _.isUndefined(policy?.max_concurrent_sessions) || + policy?.max_concurrent_sessions === 0, + idleTimeoutUnlimited: + _.isUndefined(policy?.idle_timeout) || policy?.idle_timeout === 0, + }); + + const parsedTotalResourceSlots = JSON.parse( + keypairResourcePolicy?.total_resource_slots || '{}', + ); + + const initialValues = useMemo(() => { + if (parsedTotalResourceSlots?.mem) { + parsedTotalResourceSlots.mem = iSizeToSize( + parsedTotalResourceSlots?.mem + 'b', + 'g', + 2, + true, + )?.numberUnit; + } + + return { + parsedTotalResourceSlots, + allowedVfolderHostNames: _.keys( + JSON.parse(keypairResourcePolicy?.allowed_vfolder_hosts || '{}'), + ), + ...keypairResourcePolicy, + ...generateResourcePolicySettingUnlimitedFlags(parsedTotalResourceSlots), + ...generateSessionSettingUnlimitedFlags(keypairResourcePolicy), + }; + }, [keypairResourcePolicy]); + + const handleOk = () => { + return form.validateFields().then((values) => { + console.log(values); + }); + }; + + return ( + onRequestClose()} + destroyOnClose + {...props} + > +
+ { + if ( + !keypairResourcePolicy && + existingPolicyNames?.includes(value) + ) { + return Promise.reject( + t('resourcePolicy.ResourcePolicyNameAlreadyExists'), + ); + } + return Promise.resolve(); + }, + }, + ]} + > + + + + + +
+ ( + + )} + /> + + + ( + + )} + /> + + + + + ( + + )} + /> + + + ( + + )} + /> + + + + + + + + + ( + + )} + /> + + + ( + + )} + /> + + + + + ( + + )} + /> + + + ( + + )} + /> + + + + + + + + + + {isDeprecatedMaxVfolderCountInKeypairResourcePolicy ? undefined : ( + + + + )} + + + + + ); +}; + +export default KeypairResourcePolicySettingModal; diff --git a/react/src/hooks/backendai.tsx b/react/src/hooks/backendai.tsx index 47635655bc..9d62418fc3 100644 --- a/react/src/hooks/backendai.tsx +++ b/react/src/hooks/backendai.tsx @@ -279,3 +279,19 @@ export const useTOTPSupported = () => { return { isTOTPSupported, isLoading }; }; + +export const useAllowedHostNames = () => { + const baiClient = useSuspendedBackendaiClient(); + const { data: allowedHosts } = useTanQuery<{ + allowed: Array; + }>( + ['useAllowedHostNames'], + () => { + return baiClient.vfolder.list_all_hosts(); + }, + { + suspense: false, + }, + ); + return allowedHosts?.allowed; +}; diff --git a/react/src/hooks/index.tsx b/react/src/hooks/index.tsx index 297069a9dc..d8e4e1d24c 100644 --- a/react/src/hooks/index.tsx +++ b/react/src/hooks/index.tsx @@ -117,6 +117,7 @@ export const useSuspendedBackendaiClient = () => { vfolder: { list: (path: string) => Promise; list_hosts: () => Promise; + list_all_hosts: () => Promise; list_files: (path: string, id: string) => Promise; list_allowed_types: () => Promise; clone: (input: any, name: string) => Promise; diff --git a/resources/i18n/de.json b/resources/i18n/de.json index 65cf7ec320..cdf54e73a1 100644 --- a/resources/i18n/de.json +++ b/resources/i18n/de.json @@ -405,7 +405,8 @@ "SessionName": "Sitzungsname", "SessionId": "Session-ID", "EnvironmentAndVersion": "Umgebung und Version", - "Tags": "Stichworte" + "Tags": "Stichworte", + "fGPU": "fGPU" }, "button": { "Cancel": "Stornieren", @@ -963,7 +964,9 @@ "User": "Benutzer", "Project": "Projekt", "KeypairResourcePolicy": "Schlüsselpaar-Ressourcenrichtlinie", - "IdleTimeout": "Leerlauf-Timeout" + "IdleTimeout": "Leerlauf-Timeout", + "CreateResourcePolicy": "Erstellen Sie eine Ressourcenrichtlinie", + "ResourcePolicyNameAlreadyExists": "Der Name der Ressourcenrichtlinie ist bereits vorhanden. \nBitte ändern Sie den hinzuzufügenden Namen." }, "registry": { "Hostname": "Hostname", diff --git a/resources/i18n/el.json b/resources/i18n/el.json index 2e7274938a..58426be6b5 100644 --- a/resources/i18n/el.json +++ b/resources/i18n/el.json @@ -405,7 +405,8 @@ "SessionName": "Όνομα συνεδρίας", "SessionId": "Αναγνωριστικό συνεδρίας", "EnvironmentAndVersion": "Περιβάλλον και Έκδοση", - "Tags": "Ετικέτες" + "Tags": "Ετικέτες", + "fGPU": "fGPU" }, "button": { "Cancel": "Ματαίωση", @@ -963,7 +964,9 @@ "User": "Χρήστης", "Project": "Εργο", "KeypairResourcePolicy": "Πολιτική πόρων ζεύγους κλειδιών", - "IdleTimeout": "Χρονικό όριο αδράνειας" + "IdleTimeout": "Χρονικό όριο αδράνειας", + "CreateResourcePolicy": "Δημιουργία Πολιτικής Πόρων", + "ResourcePolicyNameAlreadyExists": "Το όνομα της πολιτικής πόρων υπάρχει ήδη. \nΑλλάξτε το όνομα για προσθήκη." }, "registry": { "Hostname": "Όνομα κεντρικού υπολογιστή", diff --git a/resources/i18n/en.json b/resources/i18n/en.json index f4bcbc4f3a..e255678d61 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -419,7 +419,8 @@ "SessionName": "Session Name", "SessionId": "Session ID", "EnvironmentAndVersion": "Environment and Version", - "Tags": "Tags" + "Tags": "Tags", + "fGPU": "fGPU" }, "modelService": { "Services": "Services", @@ -1066,7 +1067,9 @@ "User": "User", "Project": "Project", "KeypairResourcePolicy": "Keypair Resource Policy", - "IdleTimeout": "Idle Timeout" + "IdleTimeout": "Idle Timeout", + "CreateResourcePolicy": "Create Resource Policy", + "ResourcePolicyNameAlreadyExists": "Resource policy name already exists. Please change the name to add." }, "registry": { "Hostname": "Hostname", diff --git a/resources/i18n/es.json b/resources/i18n/es.json index 9ce748415d..971dd2890b 100644 --- a/resources/i18n/es.json +++ b/resources/i18n/es.json @@ -903,7 +903,9 @@ "User": "Usuario", "Project": "Proyecto", "KeypairResourcePolicy": "Política de recursos de par de claves", - "IdleTimeout": "Tiempo de inactividad" + "IdleTimeout": "Tiempo de inactividad", + "CreateResourcePolicy": "Crear política de recursos", + "ResourcePolicyNameAlreadyExists": "El nombre de la política de recursos ya existe. \nCambie el nombre para agregarlo." }, "resourcePreset": { "AboutToDeletePreset": "Está a punto de borrar este preajuste:", @@ -1215,7 +1217,8 @@ "SessionName": "Nombre de la sesión", "SessionId": "ID de sesión", "EnvironmentAndVersion": "Entorno y versión", - "Tags": "Etiquetas" + "Tags": "Etiquetas", + "fGPU": "fGPU" }, "settings": { "ATOMsupport": "ATOM", diff --git a/resources/i18n/fi.json b/resources/i18n/fi.json index 77029f55d9..dc483a5fa2 100644 --- a/resources/i18n/fi.json +++ b/resources/i18n/fi.json @@ -901,7 +901,9 @@ "User": "Käyttäjä", "Project": "Projekti", "KeypairResourcePolicy": "Avainparin resurssikäytäntö", - "IdleTimeout": "Idle Timeout" + "IdleTimeout": "Idle Timeout", + "CreateResourcePolicy": "Luo resurssikäytäntö", + "ResourcePolicyNameAlreadyExists": "Resurssikäytännön nimi on jo olemassa. \nMuuta lisättävä nimi." }, "resourcePreset": { "AboutToDeletePreset": "Olet poistamassa tätä esiasetusta:", @@ -1213,7 +1215,8 @@ "SessionName": "Istunnon nimi", "SessionId": "Istunnon tunniste", "EnvironmentAndVersion": "Ympäristö ja versio", - "Tags": "Tunnisteet" + "Tags": "Tunnisteet", + "fGPU": "fGPU" }, "settings": { "ATOMsupport": "ATOM", diff --git a/resources/i18n/fr.json b/resources/i18n/fr.json index c732e2ddfd..a8d785ce82 100644 --- a/resources/i18n/fr.json +++ b/resources/i18n/fr.json @@ -405,7 +405,8 @@ "SessionName": "Nom de la session", "SessionId": "ID de session", "EnvironmentAndVersion": "Environnement et version", - "Tags": "Mots clés" + "Tags": "Mots clés", + "fGPU": "fGPU" }, "button": { "Cancel": "Annuler", @@ -963,7 +964,9 @@ "User": "Utilisateur", "Project": "Projet", "KeypairResourcePolicy": "Politique de ressources de paires de clés", - "IdleTimeout": "Délai d'inactivité" + "IdleTimeout": "Délai d'inactivité", + "CreateResourcePolicy": "Créer une stratégie de ressources", + "ResourcePolicyNameAlreadyExists": "Le nom de la stratégie de ressources existe déjà. \nVeuillez modifier le nom à ajouter." }, "registry": { "Hostname": "Nom d'hôte", diff --git a/resources/i18n/id.json b/resources/i18n/id.json index 8f819521b8..b135b575d5 100644 --- a/resources/i18n/id.json +++ b/resources/i18n/id.json @@ -406,7 +406,8 @@ "SessionId": "Id Sesi", "EnvironmentAndVersion": "Lingkungan dan Versi", "Tags": "Tag", - "Agents": "Agen" + "Agents": "Agen", + "fGPU": "fGPU" }, "button": { "Cancel": "Batalkan", @@ -964,7 +965,9 @@ "User": "Pengguna", "Project": "Proyek", "KeypairResourcePolicy": "Kebijakan Sumber Daya Pasangan Kunci", - "IdleTimeout": "Batas Waktu Diam" + "IdleTimeout": "Batas Waktu Diam", + "CreateResourcePolicy": "Buat Kebijakan Sumber Daya", + "ResourcePolicyNameAlreadyExists": "Nama kebijakan sumber daya sudah ada. \nSilakan ubah nama untuk ditambahkan." }, "registry": { "Hostname": "Nama host", diff --git a/resources/i18n/it.json b/resources/i18n/it.json index 24f34f8b1f..1822e48f48 100644 --- a/resources/i18n/it.json +++ b/resources/i18n/it.json @@ -405,7 +405,8 @@ "SessionName": "Nome della sessione", "SessionId": "ID sessione", "EnvironmentAndVersion": "Ambiente e versione", - "Tags": "Tag" + "Tags": "Tag", + "fGPU": "fGPU" }, "button": { "Cancel": "Annulla", @@ -963,7 +964,9 @@ "User": "Utente", "Project": "Progetto", "KeypairResourcePolicy": "Politica delle risorse per la coppia di chiavi", - "IdleTimeout": "Timeout di inattività" + "IdleTimeout": "Timeout di inattività", + "CreateResourcePolicy": "Creare una politica delle risorse", + "ResourcePolicyNameAlreadyExists": "Il nome della policy delle risorse esiste già. \nSi prega di modificare il nome da aggiungere." }, "registry": { "Hostname": "Nome host", diff --git a/resources/i18n/ja.json b/resources/i18n/ja.json index 196fecf31b..5260e0f9ab 100644 --- a/resources/i18n/ja.json +++ b/resources/i18n/ja.json @@ -405,7 +405,8 @@ "SessionName": "セッション名", "SessionId": "セッションID", "EnvironmentAndVersion": "環境とバージョン", - "Tags": "タグ" + "Tags": "タグ", + "fGPU": "fGPU" }, "button": { "Cancel": "キャンセル", @@ -963,7 +964,9 @@ "User": "ユーザー", "Project": "プロジェクト", "KeypairResourcePolicy": "キーペアのリソースポリシー", - "IdleTimeout": "アイドルタイムアウト" + "IdleTimeout": "アイドルタイムアウト", + "CreateResourcePolicy": "リソースポリシーの作成", + "ResourcePolicyNameAlreadyExists": "リソースポリシー名はすでに存在します。\n追加する名前を変更してください。" }, "registry": { "Hostname": "ホスト名", diff --git a/resources/i18n/ko.json b/resources/i18n/ko.json index a2039dcb18..1cf8d39d05 100644 --- a/resources/i18n/ko.json +++ b/resources/i18n/ko.json @@ -406,7 +406,8 @@ "SessionName": "세션 이름", "SessionId": "세션 ID", "EnvironmentAndVersion": "환경 및 버전", - "Tags": "태그" + "Tags": "태그", + "fGPU": "fGPU" }, "modelService": { "Services": "모델 서비스", @@ -1053,7 +1054,9 @@ "User": "사용자", "Project": "프로젝트", "KeypairResourcePolicy": "키페어 자원 정책", - "IdleTimeout": "유휴 대기 시간" + "IdleTimeout": "유휴 대기 시간", + "CreateResourcePolicy": "자원 정책 만들기", + "ResourcePolicyNameAlreadyExists": "리소스 정책 이름이 이미 존재합니다. \n추가하려면 이름을 변경하세요." }, "registry": { "Hostname": "호스트명", diff --git a/resources/i18n/mn.json b/resources/i18n/mn.json index 4f69bb61bd..7c9d823fae 100644 --- a/resources/i18n/mn.json +++ b/resources/i18n/mn.json @@ -406,7 +406,8 @@ "SessionName": "Сеанс нэр", "SessionId": "Сешн Id", "EnvironmentAndVersion": "Хүрээлэн буй орчин ба хувилбар", - "Tags": "Шошго" + "Tags": "Шошго", + "fGPU": "fGPU" }, "button": { "Cancel": "Цуцлах", @@ -964,7 +965,9 @@ "User": "Хэрэглэгч", "Project": "Төсөл", "KeypairResourcePolicy": "Түлхүүрийн нөөцийн бодлого", - "IdleTimeout": "Сул зогсолтын хугацаа" + "IdleTimeout": "Сул зогсолтын хугацаа", + "CreateResourcePolicy": "Нөөцийн бодлогыг бий болгох", + "ResourcePolicyNameAlreadyExists": "Нөөцийн бодлогын нэр аль хэдийн байна. \nНэмэх нэрээ өөрчилнө үү." }, "registry": { "Hostname": "Хостын нэр", diff --git a/resources/i18n/ms.json b/resources/i18n/ms.json index 08ceea19c1..05795e48da 100644 --- a/resources/i18n/ms.json +++ b/resources/i18n/ms.json @@ -405,7 +405,8 @@ "SessionName": "Nama Sesi", "SessionId": "Id Sesi", "EnvironmentAndVersion": "Persekitaran dan Versi", - "Tags": "Tag" + "Tags": "Tag", + "fGPU": "fGPU" }, "button": { "Cancel": "Batal", @@ -963,7 +964,9 @@ "User": "pengguna", "Project": "Projek", "KeypairResourcePolicy": "Dasar Sumber Pasangan Kunci", - "IdleTimeout": "Tamat Masa Terbiar" + "IdleTimeout": "Tamat Masa Terbiar", + "CreateResourcePolicy": "Buat Dasar Sumber", + "ResourcePolicyNameAlreadyExists": "Nama dasar sumber sudah wujud. \nSila tukar nama untuk ditambah." }, "registry": { "Hostname": "Nama Hos", diff --git a/resources/i18n/pl.json b/resources/i18n/pl.json index 627376e7e4..6441382c8f 100644 --- a/resources/i18n/pl.json +++ b/resources/i18n/pl.json @@ -405,7 +405,8 @@ "SessionName": "Nazwa sesji", "SessionId": "Identyfikator sesji", "EnvironmentAndVersion": "Środowisko i wersja", - "Tags": "Tagi" + "Tags": "Tagi", + "fGPU": "fGPU" }, "button": { "Cancel": "Anuluj", @@ -963,7 +964,9 @@ "User": "Użytkownik", "Project": "Projekt", "KeypairResourcePolicy": "Polityka zasobów pary kluczy", - "IdleTimeout": "Limit czasu bezczynności" + "IdleTimeout": "Limit czasu bezczynności", + "CreateResourcePolicy": "Utwórz politykę zasobów", + "ResourcePolicyNameAlreadyExists": "Nazwa zasady zasobów już istnieje. \nAby dodać, zmień nazwę." }, "registry": { "Hostname": "Nazwa hosta", diff --git a/resources/i18n/pt-BR.json b/resources/i18n/pt-BR.json index 91ec1007d2..7491b66c99 100644 --- a/resources/i18n/pt-BR.json +++ b/resources/i18n/pt-BR.json @@ -405,7 +405,8 @@ "SessionName": "Nome da sessão", "SessionId": "Identificação de sessão", "EnvironmentAndVersion": "Ambiente e versão", - "Tags": "Tag" + "Tags": "Tag", + "fGPU": "fGPU" }, "button": { "Cancel": "Cancelar", @@ -963,7 +964,9 @@ "User": "Do utilizador", "Project": "Projeto", "KeypairResourcePolicy": "Política de recursos de par de chaves", - "IdleTimeout": "Tempo limite ocioso" + "IdleTimeout": "Tempo limite ocioso", + "CreateResourcePolicy": "Criar Política de Recursos", + "ResourcePolicyNameAlreadyExists": "O nome da política de recursos já existe. \nPor favor, altere o nome para adicionar." }, "registry": { "Hostname": "nome de anfitrião", diff --git a/resources/i18n/pt.json b/resources/i18n/pt.json index 4348679415..f5c4d78a66 100644 --- a/resources/i18n/pt.json +++ b/resources/i18n/pt.json @@ -405,7 +405,8 @@ "SessionName": "Nome da sessão", "SessionId": "Identificação de sessão", "EnvironmentAndVersion": "Ambiente e versão", - "Tags": "Tag" + "Tags": "Tag", + "fGPU": "fGPU" }, "button": { "Cancel": "Cancelar", @@ -963,7 +964,9 @@ "User": "Do utilizador", "Project": "Projeto", "KeypairResourcePolicy": "Política de recursos de par de chaves", - "IdleTimeout": "Tempo limite ocioso" + "IdleTimeout": "Tempo limite ocioso", + "CreateResourcePolicy": "Criar Política de Recursos", + "ResourcePolicyNameAlreadyExists": "O nome da política de recursos já existe. \nPor favor, altere o nome para adicionar." }, "registry": { "Hostname": "nome de anfitrião", diff --git a/resources/i18n/ru.json b/resources/i18n/ru.json index 90398aa700..0b062fd2dd 100644 --- a/resources/i18n/ru.json +++ b/resources/i18n/ru.json @@ -405,7 +405,8 @@ "SessionName": "Имя сеанса", "SessionId": "Идентификатор сессии", "EnvironmentAndVersion": "Окружающая среда и версия", - "Tags": "Теги" + "Tags": "Теги", + "fGPU": "фГПУ" }, "button": { "Cancel": "Отмена", @@ -963,7 +964,9 @@ "User": "Пользователь", "Project": "Проект", "KeypairResourcePolicy": "Политика ресурсов пары ключей", - "IdleTimeout": "Тайм-аут простоя" + "IdleTimeout": "Тайм-аут простоя", + "CreateResourcePolicy": "Создать политику ресурсов", + "ResourcePolicyNameAlreadyExists": "Название политики ресурсов уже существует. \nПожалуйста, измените имя, чтобы добавить." }, "registry": { "Hostname": "Имя хоста", diff --git a/resources/i18n/tr.json b/resources/i18n/tr.json index 417fcf2a9e..74db85b7d5 100644 --- a/resources/i18n/tr.json +++ b/resources/i18n/tr.json @@ -405,7 +405,8 @@ "SessionName": "Oturum Adı", "SessionId": "Oturum kimliği", "EnvironmentAndVersion": "Ortam ve Sürüm", - "Tags": "Etiketler" + "Tags": "Etiketler", + "fGPU": "fGPU" }, "button": { "Cancel": "İptal etmek", @@ -963,7 +964,9 @@ "User": "Kullanıcı", "Project": "Proje", "KeypairResourcePolicy": "Anahtar Çifti Kaynak Politikası", - "IdleTimeout": "Boşta Kalma Zaman Aşımı" + "IdleTimeout": "Boşta Kalma Zaman Aşımı", + "CreateResourcePolicy": "Kaynak Politikası Oluşturun", + "ResourcePolicyNameAlreadyExists": "Kaynak politikası adı zaten mevcut. \nLütfen eklenecek adı değiştirin." }, "registry": { "Hostname": "ana bilgisayar adı", diff --git a/resources/i18n/vi.json b/resources/i18n/vi.json index 800bffcfcd..03195e6828 100644 --- a/resources/i18n/vi.json +++ b/resources/i18n/vi.json @@ -405,7 +405,8 @@ "SessionName": "Tên phiên", "SessionId": "Id phiên", "EnvironmentAndVersion": "Môi trường và phiên bản", - "Tags": "Thẻ" + "Tags": "Thẻ", + "fGPU": "fGPU" }, "button": { "Cancel": "Huỷ bỏ", @@ -963,7 +964,9 @@ "User": "Người dùng", "Project": "Dự án", "KeypairResourcePolicy": "Chính sách tài nguyên cặp khóa", - "IdleTimeout": "Hết thời gian chờ" + "IdleTimeout": "Hết thời gian chờ", + "CreateResourcePolicy": "Tạo chính sách tài nguyên", + "ResourcePolicyNameAlreadyExists": "Tên chính sách tài nguyên đã tồn tại. \nVui lòng thay đổi tên để thêm." }, "registry": { "Hostname": "Tên máy chủ", diff --git a/resources/i18n/zh-CN.json b/resources/i18n/zh-CN.json index 10fbc04ca9..e531a8b9af 100644 --- a/resources/i18n/zh-CN.json +++ b/resources/i18n/zh-CN.json @@ -405,7 +405,8 @@ "SessionName": "会话名称", "SessionId": "会话 ID", "EnvironmentAndVersion": "环境及版本", - "Tags": "标签" + "Tags": "标签", + "fGPU": "GPU" }, "button": { "Cancel": "取消", @@ -963,7 +964,9 @@ "User": "用户", "Project": "项目", "KeypairResourcePolicy": "密钥对资源策略", - "IdleTimeout": "空闲超时" + "IdleTimeout": "空闲超时", + "CreateResourcePolicy": "创建资源策略", + "ResourcePolicyNameAlreadyExists": "资源策略名称已存在。\n请更改名称以添加。" }, "registry": { "Hostname": "主机名", diff --git a/resources/i18n/zh-TW.json b/resources/i18n/zh-TW.json index 871468d472..9407d0fd84 100644 --- a/resources/i18n/zh-TW.json +++ b/resources/i18n/zh-TW.json @@ -405,7 +405,8 @@ "SessionName": "會話名稱", "SessionId": "會話 ID", "EnvironmentAndVersion": "環境及版本", - "Tags": "標籤" + "Tags": "標籤", + "fGPU": "GPU" }, "button": { "Cancel": "取消", @@ -963,7 +964,9 @@ "User": "使用者", "Project": "專案", "KeypairResourcePolicy": "密鑰對資源策略", - "IdleTimeout": "空閒超時" + "IdleTimeout": "空閒超時", + "CreateResourcePolicy": "建立資源策略", + "ResourcePolicyNameAlreadyExists": "資源策略名稱已存在。\n請更改名稱以新增。" }, "registry": { "Hostname": "主機名",