refactor: leverage helpers
This commit is contained in:
121
packages/hoppscotch-sh-admin/src/helpers/userManagement.ts
Normal file
121
packages/hoppscotch-sh-admin/src/helpers/userManagement.ts
Normal file
@@ -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: null;
|
||||||
|
};
|
||||||
|
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<string>;
|
||||||
|
|
||||||
|
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 };
|
||||||
|
};
|
||||||
@@ -1,7 +1,23 @@
|
|||||||
import { createI18n } from 'vue-i18n';
|
import { I18n, createI18n } from 'vue-i18n';
|
||||||
import { HoppModule } from '.';
|
import { HoppModule } from '.';
|
||||||
import messages from '@intlify/unplugin-vue-i18n/messages';
|
import messages from '@intlify/unplugin-vue-i18n/messages';
|
||||||
|
|
||||||
|
// A reference to the i18n instance
|
||||||
|
let i18nInstance: I18n<
|
||||||
|
Record<string, unknown>,
|
||||||
|
Record<string, unknown>,
|
||||||
|
Record<string, unknown>,
|
||||||
|
string,
|
||||||
|
false
|
||||||
|
> | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the i18n instance
|
||||||
|
*/
|
||||||
|
export function getI18n() {
|
||||||
|
return i18nInstance!.global.t;
|
||||||
|
}
|
||||||
|
|
||||||
export default <HoppModule>{
|
export default <HoppModule>{
|
||||||
onVueAppInit(app) {
|
onVueAppInit(app) {
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
@@ -11,6 +27,9 @@ export default <HoppModule>{
|
|||||||
legacy: false,
|
legacy: false,
|
||||||
allowComposition: true,
|
allowComposition: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(i18n);
|
app.use(i18n);
|
||||||
|
|
||||||
|
i18nInstance = i18n;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ import {
|
|||||||
RemoveUsersByAdminDocument,
|
RemoveUsersByAdminDocument,
|
||||||
UserInfoDocument,
|
UserInfoDocument,
|
||||||
} from '~/helpers/backend/graphql';
|
} from '~/helpers/backend/graphql';
|
||||||
import { ADMIN_CANNOT_BE_DELETED, USER_IS_OWNER } from '~/helpers/errors';
|
import { handleUserDeletion } from '~/helpers/userManagement';
|
||||||
|
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
@@ -210,35 +210,10 @@ const deleteUserMutation = async (id: string | null) => {
|
|||||||
} else {
|
} else {
|
||||||
const deletedUsers = result.data?.removeUsersByAdmin || [];
|
const deletedUsers = result.data?.removeUsersByAdmin || [];
|
||||||
|
|
||||||
const uniqueErrorMessages = new Set(
|
handleUserDeletion(deletedUsers, {
|
||||||
deletedUsers.map(({ errorMessage }) => errorMessage).filter(Boolean)
|
type: 'individual',
|
||||||
) as Set<string>;
|
metadata: null,
|
||||||
|
|
||||||
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'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
confirmDeletion.value = false;
|
confirmDeletion.value = false;
|
||||||
deleteUserUID.value = null;
|
deleteUserUID.value = null;
|
||||||
|
|||||||
@@ -258,11 +258,8 @@ import {
|
|||||||
UsersListQuery,
|
UsersListQuery,
|
||||||
UsersListV2Document,
|
UsersListV2Document,
|
||||||
} from '~/helpers/backend/graphql';
|
} from '~/helpers/backend/graphql';
|
||||||
import {
|
import { USER_ALREADY_INVITED } from '~/helpers/errors';
|
||||||
ADMIN_CANNOT_BE_DELETED,
|
import { handleUserDeletion } from '~/helpers/userManagement';
|
||||||
USER_ALREADY_INVITED,
|
|
||||||
USER_IS_OWNER,
|
|
||||||
} from '~/helpers/errors';
|
|
||||||
import IconCheck from '~icons/lucide/check';
|
import IconCheck from '~icons/lucide/check';
|
||||||
import IconLeft from '~icons/lucide/chevron-left';
|
import IconLeft from '~icons/lucide/chevron-left';
|
||||||
import IconRight from '~icons/lucide/chevron-right';
|
import IconRight from '~icons/lucide/chevron-right';
|
||||||
@@ -586,57 +583,16 @@ const deleteUsers = async (id: string | null) => {
|
|||||||
.filter((user) => user.isDeleted)
|
.filter((user) => user.isDeleted)
|
||||||
.map((user) => user.userUID);
|
.map((user) => user.userUID);
|
||||||
|
|
||||||
const uniqueErrorMessages = new Set(
|
const { data } = handleUserDeletion(deletedUsers, {
|
||||||
deletedUsers.map(({ errorMessage }) => errorMessage).filter(Boolean)
|
type: 'bulk',
|
||||||
) as Set<string>;
|
metadata: {
|
||||||
|
areMultipleUsersSelected: areMultipleUsersSelected.value,
|
||||||
if (uniqueErrorMessages.size > 0) {
|
deletedIDs,
|
||||||
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 (data?.timeoutID) {
|
||||||
if (
|
toastTimeout = data.timeoutID;
|
||||||
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')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usersList.value = usersList.value.filter(
|
usersList.value = usersList.value.filter(
|
||||||
|
|||||||
Reference in New Issue
Block a user