research_ui/pages/TermPage.vue

422 lines
12 KiB
Vue
Raw Normal View History

2025-02-04 12:40:58 +00:00
<template>
<section :class="$route.name">
<div class="container-fluid mt-3">
<div class="row">
<div class="col col-md-3 border-start right-panel" v-if="isRightPanel">
<div class="pages-content" ref="navigationFilter">
<div class="container-fluid">
<div class="row">
<div class="d-flex justify-content-between w-100">
<multiselect
:allow-empty="false"
:searchable="true"
:close-on-select="true"
:show-labels="false"
label="title"
track-by="id"
placeholder="انتخاب پروژه"
:value="newProjects"
:options="projects"
@select="selectProject"
:hide-selected="false"
:max-height="200"
style="width: auto"
>
<template #singleLabel="props">
<span class="option__desc"
><span
class="option__title text-truncate"
style="display: block; max-width: 120px"
>
{{ props.option.title }}
</span></span
>
</template>
</multiselect>
<button
type="button"
class="close btn-right-panel"
aria-label="Close"
@click="isRightPanel = false"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
</div>
<div class="row">
<ResearchTreeList
:treeItems="treeItems"
:newProjects="newProjects"
@on-click="clickOnTreeItem"
></ResearchTreeList>
</div>
</div>
</div>
</div>
<div class="col">
<div class="row border-bottom mx-0">
<div
class="col-12 order-1 order-lg-1 col-lg-1 d-flex justify-content-start"
>
<div
class="d-flex position-relative align-items-center"
style="top: -0.3em"
>
<button
class="btn btn-right-panel"
@click="isRightPanel = true"
>
<svg class="icon icon-Component-356--1">
<use xlink:href="#icon-Component-356--1"></use>
</svg>
</button>
<button
name="button"
type="button"
class="toggle-mobile-nav dropdown-hamburger d-md-none"
@click.prevent="toggleSidebarMenu()"
>
<span class="sr-only">باز کردن منوی کنار</span>
<svg class="s18" data-testid="sidebar-icon">
<use href="assets/common/img/icons.svg#sidebar"></use>
</svg>
</button>
</div>
</div>
<div class="col-12 order-2 order-lg-1 col-lg-10">
<div class="nav-tabs-container nav-tabs border-bottom-0">
<ul class="nav">
<li
class="nav-item desktop"
v-for="(navItem, index) in myActiveSchema?.tabs"
:key="index"
>
<button
:title="navItem.label"
type="button"
@click.prevent="updateCategoryList(navItem, index)"
class="btn nav-link"
:class="{ active: activeTab?.key == navItem.key }"
>
{{ navItem.title }}
</button>
</li>
<li
class="nav-item mobile tabs-more-btn d-md-none"
v-if="myActiveSchema?.tabs?.length > 2"
>
<div class="dropdown">
<button
class="btn"
type="button"
id="dropdownMenuButton"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<svg class="icon icon-Component-81--1">
<use xlink:href="#icon-Component-81--1"></use>
</svg>
</button>
<div
class="dropdown-menu"
aria-labelledby="dropdownMenuButton"
>
<a
class="dropdown-item"
@click.prevent="updateCategoryList(navItem, index)"
v-for="(navItem, index) in myActiveSchema?.tabs"
:key="index"
:class="{ active: activeTab?.key == navItem.key }"
>
{{ navItem.title }}</a
>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="col-12 pt-3">
<component
:is="contentComponentName(activeTab?.key)"
:listAnswer="listAnswerForTerm"
:pagination="pagination"
@changePage="changePaging"
@researchModalHandler="researchModalHandler"
></component>
</div>
</div>
</div>
</div>
<base-modal-v2
v-if="showModal"
@close="closeBaseModal"
:showHeaderCloseButton="true"
:hasFooter="false"
:modalTitle="modalTitle"
minHeight="17em"
overflow="hidden"
:showSaveButton="true"
:showCloseButton="true"
:showDeleteButton="false"
>
<slot> {{ modalTitle }}</slot>
<slot name="body">
<component
:is="slotComponentName"
:valueModal="valueModalResearch"
@closeAfterSaving="closeAfterSaving"
></component>
</slot>
</base-modal-v2>
</div>
</section>
</template>
<script>
import { mapState, mapActions } from "pinia";
import researchApi from "~/apis/researchApi";
import { useResearchStore } from "~/stores/researchStore";
export default {
beforeMount() {
this.httpService = new HttpService(import.meta.env.VITE_BASE_URL);
},
mounted() {
if (this.myActiveSchema) {
this.researchActiveSchemaSetter(this.myActiveSchema);
this.getMultiSelect(this.myActiveSchema.lists.url_GET);
this.activeTab = this.myActiveTabs;
}
},
beforeDestroy() {},
data() {
return {
projects: [],
showModal: false,
modalTitle: null,
slotComponentName: null,
valueModalResearch: {},
newProjects: "",
listAnswerForTerm: [],
treeItems: [],
childrenList: [],
parentList: {},
httpService: undefined,
activeTab: null,
listTypeId: 0,
firstChoiceOfTree: "",
isRightPanel: true,
pagination: {
page: 1,
pages: 0,
total: 0,
offset: 0, // page * per_page
limit: 10, //per_page
},
};
},
computed: {
...mapState(useResearchStore, ["researchSchemaGetter", "researchTermsGetter"]),
repoUrl() {
return import.meta.env.VITE_REPO + "/";
},
myActiveSchema() {
return this.researchSchemaGetter.find((item) => {
return item.key == "term";
});
},
myActiveTabs() {
return this.myActiveSchema.tabs.find((item) => {
return item.key == "fish";
});
},
},
methods: {
...mapActions(useResearchStore, [
"researchTermsSetter",
"researchActiveSchemaSetter",
]),
closeAfterSaving() {
this.closeBaseModal();
setTimeout(() => {
this.getItemsForResearch(this.firstChoiceOfTree.id);
}, 1000);
},
// #region function all
researchModalHandler(event) {
this.openBaseModal("ResearchFishModal", event.itemSchema.title);
this.valueModalResearch = event;
},
openBaseModal(componentName, title) {
this.showModal = true;
this.slotComponentName = componentName;
this.modalTitle = title;
},
closeBaseModal() {
this.showModal = false;
},
updateCategoryList(navItem, index) {
this.activeTab = navItem;
},
contentComponentName(key) {
if (key == "fish") return "ResearchContent";
else if (key == "wiki") return "WikiPage";
else if (key == "change") return "ProcessologyPage";
else if (key == "treechart") return "Tree";
return "ResearchContent";
},
selectProject(item) {
this.researchTermsSetter(item);
this.newProjects = item;
this.getListTree();
},
// #endregion
// #region function for tree and MultiSelect
getMultiSelect(url) {
this.httpService.getRequest(url).then((res) => {
this.researchTermsSetter(res.data[0]);
this.projects = res.data;
this.newProjects = res.data[0];
this.getListTree();
});
},
getListTree(parent = 0, ischildren = false, parentItem = {}) {
const payload = {
projectid: this.newProjects?.id,
parent: parent,
sortby: "id",
offset: 0,
limit: 100,
listtype: this.listTypeId,
};
let url = researchApi.subject.list;
this.httpService.formDataRequest(url, payload).then((res) => {
if (!ischildren) {
this.treeItems = res.data;
this.firstChoiceOfTree = res.data[0];
this.getItemsForResearch(res.data[0].id);
} else {
this.childrenList = res.data;
this.parentList = parentItem;
}
});
},
clickOnTreeItem(item) {
this.firstChoiceOfTree = item;
this.resetPagination();
this.getItemsForResearch(item.id);
},
// #endregion
// #region function for component
getItemsForResearch(id) {
let url = this.activeTab?.url_GET;
url = url.replace("{{offset}}", this.pagination.offset);
url = url.replace("{{limit}}", this.pagination.limit);
let filter = "";
if (id == 0)
filter = `&f_rt=${this.myActiveSchema.label}`; // برای نمایش همه
else filter = `&f_rt=${this.myActiveSchema.label}&f_sb=${id}`;
url = url.replace("{{filter}}", filter);
this.httpService.getRequest(url).then((res) => {
this.listAnswerForTerm = res.hits.hits;
const total = res.hits.total.value;
const pages = Math.ceil(total / this.pagination.limit);
const pagination = {
total: total,
pages: pages == 0 ? 1 : pages,
};
this.pagination = { ...this.pagination, ...pagination };
});
},
changePaging(item) {
this.pagination = item;
this.getItemsForResearch(this.firstChoiceOfTree.id);
},
resetPagination() {
this.pagination = {
page: 1,
pages: 0,
total: 0,
offset: 0, // page * per_page
limit: 10, //per_page
};
},
// #endregion
},
};
</script>
<style scoped lang="scss">
.v-popper--theme-dropdown {
display: flex;
.v-popper__inner {
.my-tooltip-content {
color: white;
background-color: black;
padding: 1em;
}
}
}
.btn-right-panel {
display: none;
}
@media screen and (max-width: 61.998em) {
.right-panel {
padding-top: 0.5em;
position: fixed;
z-index: 9;
width: 24em;
top: 0;
bottom: 0;
right: 0;
margin-right: var(--sidebar-collapsed-width);
background: #fff;
justify-content: center;
// box-shadow: -1px 0px 7px 1px #eee;
}
.btn-right-panel {
display: block;
}
}
@media screen and (max-width: 47.938em) {
.nav {
li {
.nav-link {
font-size: 0.8rem;
}
}
li.desktop:nth-child(n + 3) {
display: none;
}
.dropdown-menu {
a.dropdown-item:nth-child(-n + 2) {
display: none;
}
}
// .combo-list {
// margin-top: 1em;
// }
}
.right-panel {
margin-right: 0;
width: 18em;
}
}
</style>