From 635300fd11a10186d8d845255e1cd49cb026d357 Mon Sep 17 00:00:00 2001 From: daeyeon ko Date: Tue, 17 Dec 2024 11:18:29 +0900 Subject: [PATCH 1/9] fix: display verification message after checking user search input Signed-off-by: daeyeon ko --- .../iam/components/UserManagementAddUser.vue | 73 ++++++++----------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/apps/web/src/services/iam/components/UserManagementAddUser.vue b/apps/web/src/services/iam/components/UserManagementAddUser.vue index df19a173ef..ce4c15c20c 100644 --- a/apps/web/src/services/iam/components/UserManagementAddUser.vue +++ b/apps/web/src/services/iam/components/UserManagementAddUser.vue @@ -5,8 +5,6 @@ import { } from 'vue'; import type { TranslateResult } from 'vue-i18n'; -import { debounce } from 'lodash'; - import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; import { PContextMenu, PEmpty, PFieldGroup, PIconButton, PSelectDropdown, PBadge, @@ -26,7 +24,6 @@ import { checkEmailFormat } from '@/services/iam/helpers/user-management-form-va import { useUserPageStore } from '@/services/iam/store/user-page-store'; import type { AddModalMenuItem, LocalType } from '@/services/iam/types/user-type'; - const userPageStore = useUserPageStore(); const userPageState = userPageStore.state; const domainStore = useDomainStore(); @@ -62,70 +59,63 @@ const validationState = reactive({ const hideMenu = () => { emit('change-input', { userList: state.selectedItems }); state.menuVisible = false; - validationState.userIdInvalid = false; - validationState.userIdInvalidText = ''; - formState.searchText = ''; }; const handleClickTextInput = async () => { state.menuVisible = true; resetValidationState(); }; const handleChangeTextInput = (value: string) => { - validationState.userIdInvalid = false; - validationState.userIdInvalidText = ''; + resetValidationState(); formState.searchText = value; if (!userPageState.isAdminMode || userPageState.afterWorkspaceCreated) { fetchListUsers(); state.menuVisible = true; } }; -const handleEnterTextInput = debounce(async (value) => { +const handleEnterTextInput = async () => { if (formState.searchText === '') return; if (validateUserId()) { - const isFocusOut = value.type === 'focusout'; - await getUserList(isFocusOut); + await getUserList(); } -}, 100); +}; const handleClickDeleteButton = (idx: number) => { state.selectedItems.splice(idx, 1); emit('change-input', { userList: state.selectedItems }); }; const handleSelectDropdownItem = (selected: AuthType|LocalType) => { formState.selectedMenuItem = selected; - validationState.userIdInvalid = false; - validationState.userIdInvalidText = ''; + resetValidationState(); }; -const getUserList = async (isFocusOut?: boolean) => { + +const getUserList = async () => { let isNew = userPageState.isAdminMode || userPageState.afterWorkspaceCreated; try { + const trimmedText = formState.searchText?.trim(); if (userPageState.isAdminMode || userPageState.afterWorkspaceCreated) { - await fetchGetUsers(formState.searchText); + await fetchGetUsers(trimmedText); } else { const isIndependentUser = state.independentUsersList.find((user) => user.user_id === formState.searchText); isNew = !isIndependentUser; - await fetchGetWorkspaceUsers(formState.searchText); + await fetchGetWorkspaceUsers(trimmedText); } } catch (e) { - if (!isFocusOut) { - addSelectedItem(isNew); - } - } finally { + addSelectedItem(isNew); await hideMenu(); + formState.searchText = ''; + resetValidationState(); } }; const checkEmailValidation = () => { const { isValid, invalidText } = checkEmailFormat(formState.searchText); if (formState.selectedMenuItem === 'EMAIL') { if (!isValid) { - validationState.userIdInvalid = true; - validationState.userIdInvalidText = invalidText; + updateValidationState(invalidText); return false; } } if (formState.selectedMenuItem === 'ID') { if (isValid) { - validationState.userIdInvalid = true; - validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.ID_INVALID'); + updateValidationState(i18n.t('IAM.USER.FORM.ID_INVALID')); return false; } } @@ -135,10 +125,14 @@ const resetValidationState = () => { validationState.userIdInvalid = false; validationState.userIdInvalidText = ''; }; + +const updateValidationState = (invalidText: TranslateResult = '', isInvalid = true) => { + validationState.userIdInvalid = isInvalid; + validationState.userIdInvalidText = invalidText; +}; const validateUserId = () => { if (formState.searchText === '') { - validationState.userIdInvalid = true; - validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.ALT_E_INVALID_FULL_NAME'); + updateValidationState(i18n.t('IAM.USER.FORM.ALT_E_INVALID_FULL_NAME')); return false; } return checkEmailValidation(); @@ -163,15 +157,16 @@ const initAuthTypeList = async () => { }; const addSelectedItem = (isNew: boolean) => { if (!formState.searchText) return; + const trimmedText = formState.searchText?.trim(); + if (state.selectedItems.some((item) => item.name === trimmedText && item.auth_type === formState.selectedMenuItem)) return; + state.selectedItems.unshift({ - user_id: formState.searchText?.trim(), - label: formState.searchText?.trim(), - name: formState.searchText?.trim(), + user_id: trimmedText, + label: trimmedText, + name: trimmedText, isNew, auth_type: formState.selectedMenuItem, }); - formState.searchText = ''; - resetValidationState(); }; /* API */ @@ -205,19 +200,13 @@ const fetchGetWorkspaceUsers = async (userId: string) => { await SpaceConnector.clientV2.identity.workspaceUser.get({ user_id: userId, }); - validationState.userIdInvalid = true; - validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.USER_ID_INVALID_WORKSPACE', { userId }); + updateValidationState(i18n.t('IAM.USER.FORM.USER_ID_INVALID_WORKSPACE', { userId })); }; -const fetchGetUsers = async (userId: string) => { +const fetchGetUsers = async (userId: string) : Promise => { await SpaceConnector.clientV2.identity.user.get({ user_id: userId, }); - if (userPageState.afterWorkspaceCreated) { - addSelectedItem(false); - } else { - validationState.userIdInvalid = true; - validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.USER_ID_INVALID_DOMAIN', { userId }); - } + updateValidationState(i18n.t('IAM.USER.FORM.USER_ID_INVALID_DOMAIN', { userId })); }; onClickOutside(containerRef, clickOutside); @@ -271,7 +260,7 @@ onMounted(() => { class="user-id-input" :class="{'invalid': invalid}" @click="handleClickTextInput" - @focusout="handleEnterTextInput" + @blur="handleEnterTextInput" @keyup.enter="handleEnterTextInput" @input="handleChangeTextInput($event.target.value)" > From 155b792842376a40a8cbb763b13e4011d1221842 Mon Sep 17 00:00:00 2001 From: daeyeon ko Date: Mon, 16 Dec 2024 22:19:28 +0900 Subject: [PATCH 2/9] chore(language): en, jp, ko translation added Signed-off-by: daeyeon ko --- .../console-translation-2.8.babel | 21 +++++++++++++++++++ packages/language-pack/en.json | 1 + packages/language-pack/ja.json | 1 + packages/language-pack/ko.json | 1 + 4 files changed, 24 insertions(+) diff --git a/packages/language-pack/console-translation-2.8.babel b/packages/language-pack/console-translation-2.8.babel index 5669086e1b..9da355c07c 100644 --- a/packages/language-pack/console-translation-2.8.babel +++ b/packages/language-pack/console-translation-2.8.babel @@ -46174,6 +46174,27 @@ + + ID_INVALID + false + + + + + + en-US + true + + + ja-JP + true + + + ko-KR + true + + + MEMBER false diff --git a/packages/language-pack/en.json b/packages/language-pack/en.json index a404de9aa6..ce612df424 100644 --- a/packages/language-pack/en.json +++ b/packages/language-pack/en.json @@ -2559,6 +2559,7 @@ "EMAIL_INVALID": "Invalid e-mail format.", "GENERATE": "Generate", "GENERATE_PLACEHOLDER": "Generate or Enter Password", + "ID_INVALID": "Invalid ID format.", "MEMBER": "Member", "NAME": "Name", "NAME_VALID": "You can use this ID", diff --git a/packages/language-pack/ja.json b/packages/language-pack/ja.json index 34171b13cb..31dbd59eb3 100644 --- a/packages/language-pack/ja.json +++ b/packages/language-pack/ja.json @@ -2559,6 +2559,7 @@ "EMAIL_INVALID": "無効なメール形式です", "GENERATE": "生成", "GENERATE_PLACEHOLDER": "生成またはパスワード入力", + "ID_INVALID": "無効なID形式です。", "MEMBER": "構成員", "NAME": "お名前", "NAME_VALID": "使用可能なIDです", diff --git a/packages/language-pack/ko.json b/packages/language-pack/ko.json index 0ef031e42f..6dae843ce5 100644 --- a/packages/language-pack/ko.json +++ b/packages/language-pack/ko.json @@ -2559,6 +2559,7 @@ "EMAIL_INVALID": "잘못된 이메일 형식입니다. ", "GENERATE": "생성", "GENERATE_PLACEHOLDER": "비밀번호 자동 생성 또는 입력", + "ID_INVALID": "잘못된 ID 형식입니다.", "MEMBER": "멤버", "NAME": "이름", "NAME_VALID": "사용 가능한 아이디입니다.", From ccb5aedbb4404e38e870f46483d9af20792b8619 Mon Sep 17 00:00:00 2001 From: daeyeon ko Date: Mon, 16 Dec 2024 22:21:10 +0900 Subject: [PATCH 3/9] feat: enable the double-click option for verticalLayout Signed-off-by: daeyeon ko --- .../vertical-layout/PVerticalLayout.vue | 91 +++++++++++++++---- .../layouts/vertical-layout/story-helper.ts | 16 ++++ 2 files changed, 91 insertions(+), 16 deletions(-) diff --git a/packages/mirinae/src/layouts/vertical-layout/PVerticalLayout.vue b/packages/mirinae/src/layouts/vertical-layout/PVerticalLayout.vue index 8e06528cfa..e7063c81ec 100644 --- a/packages/mirinae/src/layouts/vertical-layout/PVerticalLayout.vue +++ b/packages/mirinae/src/layouts/vertical-layout/PVerticalLayout.vue @@ -1,6 +1,6 @@