base_ui/pages/admin/users/groups-without-admin.vue

465 lines
13 KiB
Vue
Raw Normal View History

2025-02-01 09:34:55 +00:00
<template>
2025-02-20 06:22:41 +00:00
<NuxtLayout name="default" :menu="adminMenu">
2025-02-01 09:34:55 +00:00
<div>
<!-- <header>
<the-navbar></the-navbar>
2025-02-20 06:22:41 +00:00
</header> -->
2025-02-01 09:34:55 +00:00
<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"
>
2025-02-20 06:22:41 +00:00
<template v-slot:tableHeaderActions>
2025-02-01 09:34:55 +00:00
<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>
2025-02-20 06:22:41 +00:00
</template>
2025-02-01 09:34:55 +00:00
</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">
2025-02-20 06:22:41 +00:00
<UsersSearch
2025-02-01 09:34:55 +00:00
v-if="showPanel"
:searchResults="users"
@on-send="searchUsers"
@set-as-admin="setAsAdmin"
2025-02-20 06:22:41 +00:00
></UsersSearch>
2025-02-01 09:34:55 +00:00
</div>
</div>
</div>
</div>
</main>
</div>
2025-02-20 06:22:41 +00:00
</NuxtLayout>
2025-02-01 09:34:55 +00:00
</template>
<script>
import { mapState, mapActions } from "pinia";
2025-02-20 06:22:41 +00:00
import adminMenu from "~/json/admin/json/menu.json";
// import menu from "~/json/admin/json/menu.json";
2025-02-01 09:34:55 +00:00
import adminApi from "~/apis/adminApi";
import permitApis from "~/apis/permitApi";
2025-02-20 06:22:41 +00:00
import { defineAsyncComponent } from "vue";
import { useCommonStore } from "~/stores/commonStore";
import { usePermitStore } from "~/stores/permitStore";
2025-02-01 09:34:55 +00:00
export default {
name: "groupsWithoutAdmin",
setup() {
definePageMeta({
name: "groupsWithoutAdmin",
2025-02-20 06:22:41 +00:00
layout: false,
2025-02-01 09:34:55 +00:00
});
},
beforeMount() {
2025-02-20 06:22:41 +00:00
// this.httpService = new HttpService(import.meta.env.VITE_BASE_URL);
this.httpService = useNuxtApp()["$http"];
2025-02-01 09:34:55 +00:00
},
2025-02-20 06:22:41 +00:00
2025-02-01 09:34:55 +00:00
mounted() {
this.checkPermisionBeforGetList();
},
data() {
return {
2025-02-20 06:22:41 +00:00
adminMenu: adminMenu,
2025-02-01 09:34:55 +00:00
searchType: "getGroupsWithoutAdmin",
groupsTranslation: {
getGroupsWithoutAdmin: "گروه های بدون مدیر",
getGroupsWithAdmin: "گروه های دارای مدیر",
},
groups: [],
2025-02-20 06:22:41 +00:00
// menu: menu,
2025-02-01 09:34:55 +00:00
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,
};
},
2025-02-20 06:22:41 +00:00
computed: {
...mapState(usePermitStore, ["projectGetter"]),
...mapState(useCommonStore, ["isSidebarCollapsed"]),
// ...mapState(["isSidebarCollapsed"]),
},
2025-02-01 09:34:55 +00:00
methods: {
2025-02-20 06:22:41 +00:00
// ...mapState(["isSidebarCollapsed"]),
// ...mapActions(["checkPermissions"]),
...mapActions(useCommonStore, ["checkPermissions"]),
2025-02-01 09:34:55 +00:00
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;
});
2025-02-20 06:22:41 +00:00
mySwalToast({
2025-02-01 09:34:55 +00:00
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}`;
2025-02-20 06:22:41 +00:00
mySwalConfirm({
2025-02-01 09:34:55 +00:00
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;
});
2025-02-20 06:22:41 +00:00
mySwalToast({
2025-02-01 09:34:55 +00:00
html: res.message,
});
});
}
});
},
openCreatePanel() {
this.selectedItemClone = undefined;
this.showPanel = true;
},
},
2025-02-20 06:22:41 +00:00
components: {
UsersSearch: defineAsyncComponent(() =>
import("@/components/admin/components/UsersSearch.vue")
),
},
2025-02-01 09:34:55 +00:00
};
</script>
<style scoped lang="scss">
.side-panel {
padding: 1em;
width: 30em;
max-width: 100%;
background-color: #fafafa;
border-right: 1px solid #eee;
}
</style>