<template> <NuxtLayout name="default" :menu="adminMenu"> <div> <!-- <header> <the-navbar></the-navbar> </header> --> <main class="pages-content-container"> <div class="pages-content mt-4 mt-lg-0"> <div class="p-3" :class="{ 'd-flex': showPanel }"> <div v-if="canView"> <my-table :tableActions="tableActions" height="calc(100vh - 17em)" :hasSearch="true" minHeight="25em" maxHeight="calc(100dvh - 5em)" :paginationInfo="pagination" :sortingInfo="sorting" :items="groups" :fetchingData="fetchingData" :tableColumns="tableColumns" :totalPages="pagination.pages" @search="searchGroups" @reset-form="searchGroups" @delete-table-item="deleteItem" @edit-table-item="toggleUsersPanel" @page-changed="pageChanged" @page-limit-changed="pageLimitChanged" @sort-changed="sortChanged" > <template v-slot:tableHeaderActions> <div class="dropdown"> <button class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" > {{ groupsTranslation[searchType] }} </button> <div class="dropdown-menu text-end"> <button class="dropdown-item" type="button" @click.prevent="setSearchType('getGroupsWithoutAdmin')" :class="{ active: searchType == 'getGroupsWithoutAdmin' }" value="getGroupsWithoutAdmin" > {{ groupsTranslation["getGroupsWithoutAdmin"] }} </button> <button class="dropdown-item" type="button" @click.prevent="setSearchType('getGroupsWithAdmin')" :class="{ active: searchType == 'getGroupsWithAdmin' }" value="getGroupsWithAdmin" > {{ groupsTranslation["getGroupsWithAdmin"] }} </button> </div> </div> </template> </my-table> </div> <no-data v-else> <the-content-loading v-if="fetchingData"></the-content-loading> <div v-else class="d-flex justify-content-center align-items-center" > <div class="alert alert-warning d-flex justify-content-center align-items-center" > <span class="tavasi tavasi-warning-circle color-inherit ms-1 text__32" ></span> عدم دسترسی </div> </div> </no-data> <div class="side-panel" v-if="showPanel"> <div class="side-panel-header d-flex mb-3 pb-3 border-bottom align-items-center" > <h5 class="m-0">جستجو و انتخاب مدیر گروه</h5> <button @click.prevent="toggleUsersPanel(undefined)" class="btn me-auto" type="button" > <svg class="icon icon-Component-294--1"> <use xlink:href="#icon-Component-294--1"></use> </svg> </button> </div> <div class="side-panel-content"> <UsersSearch v-if="showPanel" :searchResults="users" @on-send="searchUsers" @set-as-admin="setAsAdmin" ></UsersSearch> </div> </div> </div> </div> </main> </div> </NuxtLayout> </template> <script> import { mapState, mapActions } from "pinia"; import adminMenu from "~/json/admin/json/menu.json"; // import menu from "~/json/admin/json/menu.json"; import adminApi from "~/apis/adminApi"; import permitApis from "~/apis/permitApi"; import { defineAsyncComponent } from "vue"; import { useCommonStore } from "~/stores/commonStore"; import { usePermitStore } from "~/stores/permitStore"; export default { name: "groupsWithoutAdmin", setup() { definePageMeta({ name: "groupsWithoutAdmin", layout: false, }); }, beforeMount() { // this.httpService = new HttpService(import.meta.env.VITE_BASE_URL); this.httpService = useNuxtApp()["$http"]; }, mounted() { this.checkPermisionBeforGetList(); }, data() { return { adminMenu: adminMenu, searchType: "getGroupsWithoutAdmin", groupsTranslation: { getGroupsWithoutAdmin: "گروه های بدون مدیر", getGroupsWithAdmin: "گروه های دارای مدیر", }, groups: [], // menu: menu, firstTimeSearching: false, httpService: undefined, tableActions: [ { showOutside: true, show: true, icon: "tavasi tavasi-Component-242--1", title: "تعیین مدیر", to: { name: "undefined", }, selected: false, disabled: false, howToOpen: "", href: "", class: "edit-btn", action: "edit-table-item", }, { showOutside: true, show: true, icon: "tavasi tavasi-Component-295--1", title: "حذف", to: { name: "undefined", }, selected: false, disabled: false, howToOpen: "", href: "", class: "delete-btn", action: "delete-table-item", }, ], canView: false, fetchingData: false, tableColumns: [ { isLink: true, key: "title", title: "عنوان", width: "2", }, { isLink: true, key: "desc", title: "توضیحات", width: "2", }, ], pagination: { page: 1, pages: 0, total: 0, offset: 0, limit: 10, }, sorting: { sortby: "title", sortorder: "asc", // asc | desc | none }, users: [], loading: false, showPanel: false, selectedItemClone: undefined, prevSelectedItemIndex: undefined, }; }, computed: { ...mapState(usePermitStore, ["projectGetter"]), ...mapState(useCommonStore, ["isSidebarCollapsed"]), // ...mapState(["isSidebarCollapsed"]), }, methods: { // ...mapState(["isSidebarCollapsed"]), // ...mapActions(["checkPermissions"]), ...mapActions(useCommonStore, ["checkPermissions"]), checkPermisionBeforGetList() { if (this.fetchingData) return; this.fetchingData = true; this.checkPermissions({ _this: this, permission: "groups_view" }) .then(() => { this.getGroupsWithoutAdmin() .then(() => { this.canView = true; this.fetchingData = false; }) .catch(() => { this.canView = false; this.fetchingData = false; }); }) .catch(() => { this.canView = false; this.fetchingData = false; }); }, async getGroupsWithoutAdmin(query = "") { let url = `${messageUrl()}/${adminApi.groups.groupsWithoutAdmin}`; return await this.httpService .getRequest(this.updateUrl(url, query)) .then((res) => { this.groups = res.data; this.pagination = { ...this.pagination, ...res.pagination }; }); }, getGroupsWithAdmin() { if (this.fetchingData) return; this.fetchingData = true; let url = `${messageUrl()}/${adminApi.groups.groupsWithAdmin}`; this.httpService .getRequest(this.updateUrl(url)) .then((response) => { this.groups = response.data; this.pagination = { ...this.pagination, ...response.pagination }; }) .finally(() => { this.fetchingData = false; }); }, updateUrl(url, query = "") { url = url.replace("@offset", this.pagination.offset); url = url.replace("@limit", this.pagination.limit); url = url.replace("@sortby", this.sorting.sortby); url = url.replace("@sortorder", this.sorting.sortorder); // for searching groups. if (query?.length) url = url.replace("@query", query); else url = url.replace("/@query", query); return url; }, async searchUsers(query = "") { // this.resetPagination(); let url = loginUrl() + permitApis.users.search; url = url.replace("{{offset}}", 0); url = url.replace("{{limit}}", 50); url = url.replace("{{sortby}}", "username"); url = url.replace("{{sortorder}}", "desc"); // removing '/' before query if query is empty. if (query) url = url.replace("{{query}}", query); else url = url.replace("/{{query}}", query); return await this.httpService.getRequest(url).then((res) => { this.users = res.data; // this.pagination = { ...this.pagination, ...res.pagination }; }); }, // searchUsers(query = "") { // this.resetPagination(); // this[this.searchType](query); // // this.getGroupsWithoutAdmin(query); // }, searchGroups(query) { this.resetPagination(); this[this.searchType](query); }, setSearchType(groupType) { this.searchType = groupType; this.resetPagination(); this[groupType](); }, removeGroupMember() {}, setAsAdmin(user) { if (this.loading) return; this.loading = true; const url = messageUrl() + "/" + chatApi.groups.setAdmin; let payload = { user_id: user.id, group_id: this.selectedItemClone.id, }; this.httpService .postRequest(url, payload) .then((res) => { this.getGroupsWithoutAdmin().then(() => { this.loading = false; }); mySwalToast({ html: res.message, }); this.showPanel = false; this.resetForm(); }) .finally(() => { this.loading = false; }); }, toggleUsersPanel(index = undefined) { if (index !== undefined) { if (this.prevSelectedItemIndex !== undefined) this.groups[this.prevSelectedItemIndex].active = false; this.prevSelectedItemIndex = index; this.$set(this.groups[index], "active", true); this.selectedItemClone = structuredClone(this.groups[index]); this.showPanel = true; } else { this.resetForm(); } }, resetForm() { this.selectedItemClone = undefined; this.users = []; this.showPanel = false; }, // pagination and sorting resetPagination() { this.pagination = { pages: 0, total: 0, page: 1, offset: 0, limit: 10, }; }, pageLimitChanged(paging) { this.resetPagination(); this.pagination.limit = paging.limit; this[this.searchType](); }, pageChanged(paging) { let page = paging.pageNumber; page -= 1; this.pagination.offset = page * paging.limit; this.pagination.limit = paging.limit; this.pagination.page = paging.pageNumber; this[this.searchType](); }, sortChanged(sorting) { this.pagination.page = this.pagination.offset = 0; this.sorting = sorting; this[this.searchType](); }, // not used yet. deleteItem(index) { if (this.loading) return; this.loading = true; let groupId = this.groups[index].id; const payload = { group_id: groupId, }; const url = `${messageUrl()}/${adminApi.groups.delete}`; mySwalConfirm({ title: "هشدار", html: "با حذف گروه، تمامی مسائل و پاسخ های آن نیز حذف خواهد شد.", icon: "warning", }).then((result) => { if (result.isConfirmed) { this.httpService.postRequest(url, payload).then((res) => { this[this.searchType]().then(() => { this.loading = false; // this.showPanel = false; }); mySwalToast({ html: res.message, }); }); } }); }, openCreatePanel() { this.selectedItemClone = undefined; this.showPanel = true; }, }, components: { UsersSearch: defineAsyncComponent(() => import("@/components/admin/components/UsersSearch.vue") ), }, }; </script> <style scoped lang="scss"> .side-panel { padding: 1em; width: 30em; max-width: 100%; background-color: #fafafa; border-right: 1px solid #eee; } </style>