api-client/packages/hoppscotch-sh-admin/src/pages/teams/index.vue
2023-03-21 16:05:01 +05:30

230 lines
7.9 KiB
Vue

<template>
<div>
<h3 class="sm:px-6 p-4 text-3xl font-medium text-gray-200">Teams</h3>
<div class="flex flex-col" v-if="!fetching">
<div class="py-2 overflow-x-auto">
<div class="inline-block min-w-full overflow-hidden align-middle">
<div class="sm:px-7 p-4">
<div class="flex w-full items-center mb-7">
<button
class="inline-flex mr-3 items-center h-8 pl-2.5 pr-2 rounded-md shadow text-gray-400 border-gray-800 border-2 leading-none py-0"
>
Last 30 days
<icon-lucide-chevron-down class="w-4 ml-1.5 text-gray-600" />
</button>
<button
class="inline-flex items-center h-8 pl-2.5 pr-2 rounded-md shadow text-gray-400 border-gray-800 border-2 leading-none py-0"
>
Filter by
<icon-lucide-chevron-down class="w-4 ml-1.5 text-gray-600" />
</button>
<router-link to="/teams/addteam">
<button
class="inline-flex items-center bg-emerald-700 h-8 ml-3 pl-2.5 pr-2 rounded-md shadow border-gray-800 border leading-none py-0 hover:bg-emerald-700 focus:outline-none focus:bg-emerald-800"
>
Create Team
</button>
</router-link>
<div
class="ml-auto text-gray-400 text-xs sm:inline-flex hidden items-center"
>
<span class="mr-3">Page 2 of 4</span>
<button
class="inline-flex mr-2 items-center h-8 w-8 justify-center text-gray-400 rounded-md shadow border border-gray-800 leading-none py-0"
>
<icon-lucide-chevron-left class="text-xl" />
</button>
<button
class="inline-flex items-center h-8 w-8 justify-center text-gray-400 rounded-md shadow border border-gray-800 leading-none py-0"
>
<icon-lucide-chevron-right class="text-xl" />
</button>
</div>
</div>
<div>
<table class="w-full text-left">
<thead>
<tr class="text-gray-200 border-b border-gray-600 text-sm">
<th class="font-normal px-3 pt-0 pb-3"></th>
<th class="font-normal px-3 pt-0 pb-3">Team Name</th>
<th class="font-normal px-3 pt-0 pb-3">Team ID</th>
<th class="font-normal px-3 pt-0 pb-3 md:table-cell">
Number of Members
</th>
<th class="font-normal px-3 pt-0 pb-3">Action</th>
</tr>
</thead>
<tbody class="text-gray-300">
<!-- <router-link :custom="true" class="" :to="'/team/detail'"> -->
<tr
v-for="(team, index) in teamList"
:key="team.id"
class="border-b border-gray-300 dark:border-gray-600 hover:bg-zinc-800 rounded-xl"
>
<td>
<label>
<input
type="checkbox"
class="appearance-none bg-gray-600 checked:bg-emerald-600 rounded-md ml-3 w-5 h-5"
name="radio"
/>
</label>
</td>
<td
class="sm:p-3 py-2 px-1 md:table-cell hidden text-sky-300"
@click="goToTeam(team.id)"
>
<span class="hover:underline cursor-pointer">
{{ team.name }}
</span>
</td>
<td @click="goToTeam(team.id)" class="sm:p-3 py-2 px-1">
<span class="hover:underline cursor-pointer">
{{ team.id }}
</span>
</td>
<td class="sm:p-3 py-2 px-1 justify-center">
{{ team.members?.length }}
</td>
<td>
<tippy
interactive
trigger="click"
theme="popover"
:on-shown="() => tippyActions![index].focus()"
>
<span class="cursor-pointer">
<icon-lucide-more-horizontal />
</span>
<template #content="{ hide }">
<div
ref="tippyActions"
class="flex flex-col focus:outline-none"
tabindex="0"
@keyup.escape="hide()"
>
<HoppSmartItem
label="Delete"
@click="
() => {
deleteTeam(team.id);
hide();
}
"
/>
</div>
</template>
</tippy>
</td>
</tr>
<!-- </router-link> -->
</tbody>
</table>
</div>
<div v-if="teamList.length >= 20" class="text-center">
<button
@click="fetchNextTeams"
class="mt-5 p-2 rounded-3xl bg-gray-700"
>
<icon-lucide-chevron-down class="text-xl" />
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<HoppSmartConfirmModal
:show="confirmDeletion"
:title="`Confirm Deletion of the team?`"
@hide-modal="confirmDeletion = false"
@resolve="deleteTeamMutation(deleteTeamID)"
/>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router';
import {
RemoveTeamDocument,
TeamListDocument,
} from '../../helpers/backend/graphql';
import { usePagedQuery } from '../../composables/usePagedQuery';
import { onMounted, onBeforeUnmount, ref } from 'vue';
import { useMutation } from '@urql/vue';
import { useToast } from '../../composables/toast';
const toast = useToast();
const router = useRouter();
const {
fetching,
goToNextPage: fetchNextTeams,
refetch,
list: teamList,
} = usePagedQuery(
TeamListDocument,
(x) => x.admin.allTeams,
(x) => x.id,
{ cursor: undefined }
);
const goToTeam = (teamId: string) => {
router.push('/teams/' + teamId);
};
// Open the side menu dropdown of only the selected user
const activeTeamId = ref<null | String>(null);
// Template refs
const tippyActions = ref<any | null>(null);
// Hide dropdown when user clicks elsewhere
const close = (e: any) => {
if (!e.target.closest('.dropdown')) {
activeTeamId.value = null;
}
};
onMounted(() => document.addEventListener('click', close));
onBeforeUnmount(() => document.removeEventListener('click', close));
// User Deletion
const teamDeletion = useMutation(RemoveTeamDocument);
const confirmDeletion = ref(false);
const deleteTeamID = ref<string | null>(null);
const deleteTeam = (id: string) => {
confirmDeletion.value = true;
deleteTeamID.value = id;
};
const deleteTeamMutation = async (id: string | null) => {
if (!id) {
confirmDeletion.value = false;
toast.error('Team Deletion Failed');
return;
}
const variables = { uid: id };
await teamDeletion.executeMutation(variables).then((result) => {
if (result.error) {
toast.error('Team Deletion Failed');
} else {
refetch();
toast.success('Team Deleted Successfully');
}
});
confirmDeletion.value = false;
deleteTeamID.value = null;
router.push('/teams');
};
</script>