Files
hoppscotch/packages/hoppscotch-sh-admin/src/pages/users/index.vue

250 lines
7.0 KiB
Vue

<template>
<div class="flex flex-col">
<!-- Table View for All Users -->
<div class="flex flex-col">
<h1 class="text-lg font-bold text-secondaryDark">
{{ t('users.users') }}
</h1>
<div class="flex items-center space-x-4 py-10">
<HoppButtonPrimary
:label="t('users.invite_user')"
@click="showInviteUserModal = true"
:icon="IconAddUser"
/>
<div class="flex">
<HoppButtonSecondary
outline
filled
:label="t('users.invited_users')"
:to="'/users/invited'"
/>
</div>
</div>
<div class="overflow-x-auto">
<div
v-if="fetching && !error && usersList.length === 0"
class="flex justify-center"
>
<HoppSmartSpinner />
</div>
<div v-else-if="error">{{ t('users.load_list_error') }}</div>
<UsersTable
v-else-if="usersList.length >= 1"
:usersList="usersList"
:fetching="fetching"
:error="error"
@goToUserDetails="goToUserDetails"
@makeUserAdmin="makeUserAdmin"
@makeAdminToUser="makeAdminToUser"
@deleteUser="deleteUser"
/>
<div v-else class="flex justify-center">{{ t('users.no_users') }}</div>
<div
v-if="hasNextPage && usersList.length >= usersPerPage"
class="flex justify-center my-5 px-3 py-2 cursor-pointer font-semibold rounded-3xl bg-dividerDark hover:bg-divider transition mx-auto w-38 text-secondaryDark"
@click="fetchNextUsers"
>
<span>{{ t('users.show_more') }}</span>
<icon-lucide-chevron-down class="ml-2 text-lg" />
</div>
</div>
</div>
<UsersInviteModal
:show="showInviteUserModal"
@hide-modal="showInviteUserModal = false"
@send-invite="sendInvite"
/>
<HoppSmartConfirmModal
:show="confirmDeletion"
:title="t('users.confirm_user_deletion')"
@hide-modal="confirmDeletion = false"
@resolve="deleteUserMutation(deleteUserUID)"
/>
<HoppSmartConfirmModal
:show="confirmUserToAdmin"
:title="t('users.confirm_user_to_admin')"
@hide-modal="confirmUserToAdmin = false"
@resolve="makeUserAdminMutation(userToAdminUID)"
/>
<HoppSmartConfirmModal
:show="confirmAdminToUser"
:title="t('users.confirm_admin_to_user')"
@hide-modal="confirmAdminToUser = false"
@resolve="makeAdminToUserMutation(adminToUserUID)"
/>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useMutation } from '@urql/vue';
import {
InviteNewUserDocument,
MakeUserAdminDocument,
RemoveUserByAdminDocument,
RemoveUserAsAdminDocument,
UsersListDocument,
} from '../../helpers/backend/graphql';
import { usePagedQuery } from '~/composables/usePagedQuery';
import { useRoute, useRouter } from 'vue-router';
import { useToast } from '~/composables/toast';
import { HoppButtonSecondary } from '@hoppscotch/ui';
import IconAddUser from '~icons/lucide/user-plus';
import { useI18n } from '~/composables/i18n';
const t = useI18n();
const toast = useToast();
// Get Paginated Results of all the users in the infra
const usersPerPage = 20;
const {
fetching,
error,
goToNextPage: fetchNextUsers,
list: usersList,
hasNextPage,
} = usePagedQuery(
UsersListDocument,
(x) => x.infra.allUsers,
(x) => x.uid,
usersPerPage,
{ cursor: undefined, take: usersPerPage }
);
// Send Invitation through Email
const sendInvitation = useMutation(InviteNewUserDocument);
const showInviteUserModal = ref(false);
const sendInvite = async (email: string) => {
if (!email.trim()) {
toast.error(`${t('state.invalid_email')}`);
return;
}
const variables = { inviteeEmail: email.trim() };
await sendInvitation.executeMutation(variables).then((result) => {
if (result.error) {
toast.error(`${t('state.email_failure')}`);
} else {
toast.success(`${t('state.email_success')}`);
showInviteUserModal.value = false;
}
});
};
// Go to Individual User Details Page
const route = useRoute();
const router = useRouter();
const goToUserDetails = (uid: string) => {
router.push('/users/' + uid);
};
watch(
() => route.params.id,
() => window.location.reload()
);
// User Deletion
const userDeletion = useMutation(RemoveUserByAdminDocument);
const confirmDeletion = ref(false);
const deleteUserUID = ref<string | null>(null);
const deleteUserMutation = async (id: string | null) => {
if (!id) {
confirmDeletion.value = false;
toast.error(`${t('state.delete_user_failure')}`);
return;
}
const variables = { uid: id };
await userDeletion.executeMutation(variables).then((result) => {
if (result.error) {
toast.error(`${t('state.delete_user_failure')}`);
} else {
toast.success(`${t('state.delete_user_success')}`);
usersList.value = usersList.value.filter((user) => user.uid !== id);
}
});
confirmDeletion.value = false;
deleteUserUID.value = null;
};
// Make User Admin
const userToAdmin = useMutation(MakeUserAdminDocument);
const confirmUserToAdmin = ref(false);
const userToAdminUID = ref<string | null>(null);
const makeUserAdmin = (id: string) => {
confirmUserToAdmin.value = true;
userToAdminUID.value = id;
};
const makeUserAdminMutation = async (id: string | null) => {
if (!id) {
confirmUserToAdmin.value = false;
toast.error(`${t('state.admin_failure')}`);
return;
}
const variables = { uid: id };
await userToAdmin.executeMutation(variables).then((result) => {
if (result.error) {
toast.error(`${t('state.admin_failure')}`);
} else {
toast.success(`${t('state.admin_success')}`);
usersList.value = usersList.value.map((user) => {
if (user.uid === id) {
user.isAdmin = true;
}
return user;
});
}
});
confirmUserToAdmin.value = false;
userToAdminUID.value = null;
};
// Remove Admin Status from a current Admin
const adminToUser = useMutation(RemoveUserAsAdminDocument);
const confirmAdminToUser = ref(false);
const adminToUserUID = ref<string | null>(null);
const makeAdminToUser = (id: string) => {
confirmAdminToUser.value = true;
adminToUserUID.value = id;
};
const deleteUser = (id: string) => {
confirmDeletion.value = true;
deleteUserUID.value = id;
};
const makeAdminToUserMutation = async (id: string | null) => {
if (!id) {
confirmAdminToUser.value = false;
toast.error(`${t('state.remove_admin_failure')}`);
return;
}
const variables = { uid: id };
await adminToUser.executeMutation(variables).then((result) => {
if (result.error) {
toast.error(`${t('state.remove_admin_failure')}`);
} else {
toast.success(`${t('state.remove_admin_success')}`);
usersList.value = usersList.value.map((user) => {
if (user.uid === id) {
user.isAdmin = false;
}
return user;
});
}
});
confirmAdminToUser.value = false;
adminToUserUID.value = null;
};
</script>