From 4ba94ed95bad63e498267999ca70c671afbc59bd Mon Sep 17 00:00:00 2001 From: jamesgeorge007 Date: Wed, 27 Mar 2024 13:05:32 +0530 Subject: [PATCH] refactor: leverage helpers --- .../src/helpers/userManagement.ts | 121 ++++++++++++++++++ .../hoppscotch-sh-admin/src/modules/i18n.ts | 21 ++- .../src/pages/users/_id.vue | 35 +---- .../src/pages/users/index.vue | 68 ++-------- 4 files changed, 158 insertions(+), 87 deletions(-) create mode 100644 packages/hoppscotch-sh-admin/src/helpers/userManagement.ts diff --git a/packages/hoppscotch-sh-admin/src/helpers/userManagement.ts b/packages/hoppscotch-sh-admin/src/helpers/userManagement.ts new file mode 100644 index 00000000000..799e79dddde --- /dev/null +++ b/packages/hoppscotch-sh-admin/src/helpers/userManagement.ts @@ -0,0 +1,121 @@ +import { useToast } from '~/composables/toast'; +import { getI18n } from '~/modules/i18n'; +import { UserDeletionResult } from './backend/graphql'; +import { ADMIN_CANNOT_BE_DELETED, USER_IS_OWNER } from './errors'; + +type IndividualActionInput = { + type: 'individual'; + metadata: {}; +}; +type BulkActionInput = { + type: 'bulk'; + metadata: { + areMultipleUsersSelected: boolean; + deletedIDs: string[]; + }; +}; + +type IndividualActionResult = { + data: null; +}; +type BulkActionResult = { + data: { timeoutID: NodeJS.Timeout | null }; +}; + +type HandleUserDeletion = { + ( + deletedUsersList: UserDeletionResult[], + action: IndividualActionInput | BulkActionInput + ): IndividualActionResult | BulkActionResult; +}; + +const t = getI18n(); +const toast = useToast(); + +export const handleUserDeletion: HandleUserDeletion = ( + deletedUsersList, + action +) => { + let timeoutID: NodeJS.Timeout | null = null; + + const uniqueErrorMessages = new Set( + deletedUsersList.map(({ errorMessage }) => errorMessage).filter(Boolean) + ) as Set; + + const { type, metadata } = action; + + // Show the success toast based on the action type if there are no errors + if (uniqueErrorMessages.size === 0) { + if (type === 'bulk') { + toast.success( + metadata.areMultipleUsersSelected + ? t('state.delete_user_success') + : t('state.delete_users_success') + ); + + return { type, data: { timeoutID } }; + } + + toast.success(t('state.delete_user_success')); + return { type, data: null }; + } + + const errMsgMap = { + [ADMIN_CANNOT_BE_DELETED]: + type === 'bulk' + ? t('state.remove_admin_for_deletion') + : t('state.remove_admin_to_delete_user'), + + [USER_IS_OWNER]: + type === 'bulk' + ? t('state.remove_owner_for_deletion') + : t('state.remove_owner_to_delete_user'), + }; + const errMsgMapKeys = Object.keys(errMsgMap); + + if (type === 'bulk') { + const { areMultipleUsersSelected, deletedIDs } = metadata; + + // Show toast messages with the count of users deleted only if multiple users are selected + if (areMultipleUsersSelected) { + toast.success( + t('state.delete_some_users_success', { count: deletedIDs.length }) + ); + toast.error( + t('state.delete_some_users_failure', { + count: deletedUsersList.length - deletedIDs.length, + }) + ); + } + } + + uniqueErrorMessages.forEach((errorMessage) => { + if (errMsgMapKeys.includes(errorMessage)) { + if (type === 'bulk') { + timeoutID = setTimeout( + () => { + toast.error(errMsgMap[errorMessage as keyof typeof errMsgMap]); + }, + metadata.areMultipleUsersSelected ? 2000 : 0 + ); + + return; + } + + toast.error(errMsgMap[errorMessage as keyof typeof errMsgMap]); + } + }); + + // Fallback for the case where the error message is not in the compiled list + if ( + Array.from(uniqueErrorMessages).some( + (key) => !((key as string) in errMsgMap) + ) + ) { + type === 'bulk' && metadata.areMultipleUsersSelected + ? t('state.delete_users_failure') + : t('state.delete_user_failure'); + } + + return { data: type === 'bulk' ? { timeoutID } : null }; +}; diff --git a/packages/hoppscotch-sh-admin/src/modules/i18n.ts b/packages/hoppscotch-sh-admin/src/modules/i18n.ts index ac123b5016a..a7cd885b119 100644 --- a/packages/hoppscotch-sh-admin/src/modules/i18n.ts +++ b/packages/hoppscotch-sh-admin/src/modules/i18n.ts @@ -1,7 +1,23 @@ -import { createI18n } from 'vue-i18n'; +import { I18n, createI18n } from 'vue-i18n'; import { HoppModule } from '.'; import messages from '@intlify/unplugin-vue-i18n/messages'; +// A reference to the i18n instance +let i18nInstance: I18n< + Record, + Record, + Record, + string, + false +> | null = null; + +/** + * Returns the i18n instance + */ +export function getI18n() { + return i18nInstance!.global.t; +} + export default { onVueAppInit(app) { const i18n = createI18n({ @@ -11,6 +27,9 @@ export default { legacy: false, allowComposition: true, }); + app.use(i18n); + + i18nInstance = i18n; }, }; diff --git a/packages/hoppscotch-sh-admin/src/pages/users/_id.vue b/packages/hoppscotch-sh-admin/src/pages/users/_id.vue index a4f68ce1841..ba5fa0ceeae 100644 --- a/packages/hoppscotch-sh-admin/src/pages/users/_id.vue +++ b/packages/hoppscotch-sh-admin/src/pages/users/_id.vue @@ -73,7 +73,7 @@ import { RemoveUsersByAdminDocument, UserInfoDocument, } from '~/helpers/backend/graphql'; -import { ADMIN_CANNOT_BE_DELETED, USER_IS_OWNER } from '~/helpers/errors'; +import { handleUserDeletion } from '~/helpers/userManagement'; const t = useI18n(); const toast = useToast(); @@ -210,35 +210,10 @@ const deleteUserMutation = async (id: string | null) => { } else { const deletedUsers = result.data?.removeUsersByAdmin || []; - const uniqueErrorMessages = new Set( - deletedUsers.map(({ errorMessage }) => errorMessage).filter(Boolean) - ) as Set; - - if (uniqueErrorMessages.size > 0) { - const errMsgMap = { - [ADMIN_CANNOT_BE_DELETED]: t('state.remove_admin_to_delete_user'), - [USER_IS_OWNER]: t('state.remove_owner_to_delete_user'), - }; - - const errMsgMapKeys = Object.keys(errMsgMap); - - uniqueErrorMessages.forEach((errorMessage) => { - if (errMsgMapKeys.includes(errorMessage)) { - toast.error(errMsgMap[errorMessage as keyof typeof errMsgMap]); - } - }); - - // Fallback for the case where the error message is not in the compiled list - if ( - Array.from(uniqueErrorMessages).some( - (key) => !((key as string) in errMsgMap) - ) - ) { - toast.error(t('state.delete_user_failure')); - } - } else { - toast.success(t('state.delete_user_success')); - } + handleUserDeletion(deletedUsers, { + type: 'individual', + metadata: {}, + }); } confirmDeletion.value = false; deleteUserUID.value = null; diff --git a/packages/hoppscotch-sh-admin/src/pages/users/index.vue b/packages/hoppscotch-sh-admin/src/pages/users/index.vue index ac3f0a12c42..88aa9f50328 100644 --- a/packages/hoppscotch-sh-admin/src/pages/users/index.vue +++ b/packages/hoppscotch-sh-admin/src/pages/users/index.vue @@ -258,11 +258,8 @@ import { UsersListQuery, UsersListV2Document, } from '~/helpers/backend/graphql'; -import { - ADMIN_CANNOT_BE_DELETED, - USER_ALREADY_INVITED, - USER_IS_OWNER, -} from '~/helpers/errors'; +import { USER_ALREADY_INVITED } from '~/helpers/errors'; +import { handleUserDeletion } from '~/helpers/userManagement'; import IconCheck from '~icons/lucide/check'; import IconLeft from '~icons/lucide/chevron-left'; import IconRight from '~icons/lucide/chevron-right'; @@ -586,57 +583,16 @@ const deleteUsers = async (id: string | null) => { .filter((user) => user.isDeleted) .map((user) => user.userUID); - const uniqueErrorMessages = new Set( - deletedUsers.map(({ errorMessage }) => errorMessage).filter(Boolean) - ) as Set; - - if (uniqueErrorMessages.size > 0) { - const errMsgMap = { - [ADMIN_CANNOT_BE_DELETED]: t('state.remove_admin_for_deletion'), - [USER_IS_OWNER]: t('state.remove_owner_for_deletion'), - }; - - const errMsgMapKeys = Object.keys(errMsgMap); - - // Show toast messages with the count of users deleted only if multiple users are selected - if (areMultipleUsersSelected.value) { - toast.success( - t('state.delete_some_users_success', { count: deletedIDs.length }) - ); - toast.error( - t('state.delete_some_users_failure', { - count: deletedUsers.length - deletedIDs.length, - }) - ); - } - - uniqueErrorMessages.forEach((errorMessage) => { - if (errMsgMapKeys.includes(errorMessage)) { - toastTimeout = setTimeout( - () => { - toast.error(errMsgMap[errorMessage as keyof typeof errMsgMap]); - }, - areMultipleUsersSelected.value ? 2000 : 0 - ); - } - }); - - // Fallback for the case where the error message is not in the compiled list - if ( - Array.from(uniqueErrorMessages).some( - (key) => !((key as string) in errMsgMap) - ) - ) { - areMultipleUsersSelected.value - ? t('state.delete_users_failure') - : t('state.delete_user_failure'); - } - } else { - toast.success( - areMultipleUsersSelected.value - ? t('state.delete_users_success') - : t('state.delete_user_success') - ); + const { data } = handleUserDeletion(deletedUsers, { + type: 'bulk', + metadata: { + areMultipleUsersSelected: areMultipleUsersSelected.value, + deletedIDs, + }, + }); + + if (data?.timeoutID) { + toastTimeout = data.timeoutID; } usersList.value = usersList.value.filter(