search_ui/components/entity/sidebar-panels/Research.vue

454 lines
14 KiB
Vue
Raw Normal View History

2025-02-01 11:06:10 +00:00
<template>
<div class="research p-0 container-fluid">
<div class="row px-3 border-bottom">
<div class="col mb-4">
<div class="d-flex align-items-center">
<label for="repositories-desktop" class="float-labels no-wrap ms-2">
<svg class="icon icon-filter">
<use xlink:href="#icon-filter"></use>
</svg>
</label>
<USelectMenu
option-attribute="title"
:popper="{ placement: 'left-end' }"
searchable
searchable-placeholder="Search a person..."
v-model="multiSelectValue"
:options="multiSelectOptions"
placeholder="انتخاب فیلتر "
@update:model-value="onSelectNavigation"
>
</USelectMenu>
<!-- <multiselect
:allow-empty="false"
:searchable="true"
:close-on-select="true"
:show-labels="false"
label="title"
track-by="key"
placeholder="انتخاب فیلتر "
:value="multiSelectValue"
:options="multiSelectOptions"
@select="fetchResearchItems"
:hide-selected="false"
:max-height="200"
:width="50"
openDirection="rtl"
id="repositories-desktop"
class="multiselect mt-1"
>
</multiselect> -->
</div>
</div>
</div>
<!-- #region لیست تمام تحقیقات -->
<div class="row mx-0">
<the-content-loading
v-if="loading"
:loadingTitle="'در حال دریافت اطلاعات'"
class="table-loading"
></the-content-loading>
<template v-else>
<template v-if="listResearch?.length">
<template v-for="(item, index) in listResearch">
<div class="col">
<div class="card_fish mt-4 mb-1">
<div class="card_fish_header">
<div class="img">
<div class="d-flex">
<img
:alt="userFullname(item._source.user)"
class="rounded img-fluid user-avatar"
:src="userAvatar(item._source.user)"
/>
<div class="d-flex flex-column">
<P class="me-3 mb-0"
>{{ item._source.research_type }}
<span class="me-3 text-date">
{{ dateTofarsi(item._source.date_create) }}
</span>
</P>
<div v-if="item._source.text_subject" class="me-3">
{{ item._source?.text_subject }}
</div>
</div>
</div>
<context-menu
:contextMenu="tableActions"
@edit-item="showResearch(item)"
@remove-item="removeItemHandler(item)"
style="position: relative"
></context-menu>
</div>
</div>
<div
role="button"
class="card_fish_main"
@click.prevent="showResearch(item, true)"
>
<div class="text_fish">
<p>
{{ itemTextMain(item._source) }}
</p>
</div>
</div>
</div>
</div>
</template>
</template>
<no-data v-else>
<div 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>
</template>
</div>
<!-- #endregion -->
</div>
</template>
<script>
import entityApi from "~/apis/entityApi.js";
import { mapActions, mapState } from "pinia";
2025-02-11 07:09:05 +00:00
import { useEntityStore } from "@search/stores/entityStore";
2025-02-01 11:06:10 +00:00
import { cloneDeep } from "lodash";
/**
* @vue-data {undefined} httpService - سرویس HTTP برای درخواستها.
* @vue-data {Array} listResearch - لیست تحقیقات
* @vue-data {Array} tableActions - لیست اقدامات context-menu
*/
export default {
props: {
activeSchema: {
default() {
return [];
},
},
},
data() {
return {
loading: false,
httpService: undefined,
multiSelectValue: undefined,
listResearch: [],
tableActions: [
{
showOutside: false,
show: true,
icon: "Component-108--1",
title: "ویرایش",
to: { name: "undefined" },
selected: false,
disabled: false,
howToOpen: "",
href: "",
class: "edit-btn",
action: "edit-item",
can: "item-info_edit",
},
{
showOutside: false,
show: true,
icon: "Component-295--1",
title: "حذف",
to: { name: "undefined" },
selected: false,
disabled: false,
howToOpen: "",
href: "",
class: "delete-btn",
action: "remove",
can: "item-list_delete",
},
{
showOutside: false,
show: true,
icon: "Component-145--1",
title: "موضوع",
to: { name: "undefined" },
selected: false,
disabled: false,
howToOpen: "",
href: "",
class: "",
action: "showSubjectForm",
can: "list-item-subject_new",
},
],
multiSelectOptions: [],
};
},
beforeMount() {
this.httpService = useNuxtApp()["$http"];
},
mounted() {
setTimeout(() => {
this.handleMultiSelect(this.activeEntityViewSchemaGetter?.researchs);
}, 1000);
if (this.$route.query.research_type) {
let id = this.$route.query.research_id;
this.getResearchById(id).then((res) => {
if (res) {
this.showResearch(res);
}
});
}
},
methods: {
...mapActions(useEntityStore, ["activeResearchTypeSetter"]),
async handleMultiSelect(options) {
let listOptions = options;
this.multiSelectOptions = listOptions;
// if (this.activeResearchTypeGetter == undefined) {
// listOptions.forEach((element) => {
// if (element.key == "all") {
// this.activeResearchTypeSetter(element);
// }
// });
// }
let schema = "";
if (this.$route.query.research_type) {
schema = options.find(
(itemKey) => itemKey.title === this.$route.query.research_type
);
this.fetchResearchItems(schema);
} else {
listOptions.forEach((element) => {
if (element.key == "all") {
this.activeResearchTypeSetter(element);
this.fetchResearchItems(element);
}
});
}
},
async getResearchById(id, isReadonly = false) {
let url = repoUrl() + entityApi.fish.get_byids;
url = url.replace("{{index_key}}", "research");
url = url.replace("{{id}}", id);
return await this.httpService
.getRequest(url)
.then((res) => {
if (res.status == 0) return res;
else return undefined;
})
.catch((error) => {
console.error("خطا :", error);
return undefined;
});
},
showResearch(item, isReadonly = false) {
let schema = this.activeEntityViewSchemaGetter?.researchs.find(
(itemKey) => itemKey.key === item._source?.research_key
);
this.$emit("fishHandlerInResearch", {
action: "edit",
itemEdit: item,
itemSchema: schema,
isReadonly: isReadonly,
});
},
/**
* تبدیل تاریخ به فرمت فارسی
* @param {Number} item - تاریخ به صورت timestamp
* @returns {String} تاریخ به فرمت فارسی
* @example
* // استفاده:
* dateTofarsi(1609459200); // returns "1399/10/11"
*/
dateTofarsi(item) {
const m = item * 1000;
const d = new Date(m).toLocaleDateString("fa-IR");
return d;
},
/**
* گرداننده حذف آیتم
* @param {Object} item - آیتمی که باید حذف شود
*/
removeItemHandler(item) {
this.mySwalConfirm({
title: "هشدار!!!",
html: `از حذف <b>${item._source.research_type}</b> اطمینان دارید؟ `,
icon: "warning",
}).then((result) => {
if (result.isConfirmed) {
let url = repoUrl() + entityApi.research.deleteItem;
// let key = "";
// if (this.$route.params?.key) key = this.$route.params.key;
url = url.replace("{{index_key}}", this.multiSelectValue?.index_key);
url = url.replace("{{id}}", item._id);
this.httpService.postRequest(url).then((res) => {
this.mySwalToast({
html: res.message,
});
setTimeout(() => {
this.fetchResearchItems(this.activeResearchTypeGetter);
}, 500);
});
}
});
},
/**
* گرفتن متن اصلی آیتم
* @param {Object} item - آیتمی که متن اصلی آن باید گرفته شود
* @returns {String} متن اصلی آیتم
*/
itemTextMain(item) {
return item.text_main;
},
/**
* گرفتن لیست آیتمهای تحقیق.
* @description این متد لیست آیتمهای تحقیق را از سرور دریافت کرده و مقدار `listResearch` را بهروز میکند.
* اگر فیلتر انتخاب شده دارای کلید "all" باشد، تمام آیتمها را دریافت میکند و در غیر این صورت، آیتمها را بر اساس نوع تحقیق فیلتر میکند.
* @param {Object} selectedItem - فیلتر انتخاب شده.
* @param {String} selectedItem.key - کلید فیلتر انتخاب شده.
* @param {String} selectedItem.title - عنوان فیلتر انتخاب شده.
* @example
* this.fetchResearchItems({ key: 'all', title: 'All Research' });
*/
async fetchResearchItems(selectedItem) {
if (this.loading) return;
this.loading = true;
this.multiSelectValue = selectedItem;
this.activeResearchTypeSetter(selectedItem);
// معنی نداره چک این !!!!
// if (!this.selectedItemEntityGetter) return;
if (!selectedItem) return;
let url = "";
if (selectedItem.key == "all") {
url = repoUrl() + entityApi.research.listByEntityId;
} else {
url = repoUrl() + entityApi.research.listByEntityIdByFilter;
url = url.replace("{{filter}}", "research_type=" + selectedItem.title);
}
url = url.replace("{{entity_id}}", this.$route.params.id);
return await this.httpService
.getRequest(url)
.then((res) => {
this.listResearch = res?.hits.hits;
})
.catch((error) => {
console.error("خطای شبکه:", error);
this.loading = false;
})
.finally(() => {
this.loading = false;
});
},
/**
* پر کردن مقدار `multiSelectOptions`.
* @description این متد در قدم اول تغییراتی در `listSchema` ایجاد کرده و مقدار "all" را اضافه میکند.
* سپس `multiSelectOptions` را بهروز کرده و برای هر آیتم در `multiSelectOptions`، اگر کلید آن "all" باشد، آیتمهای تحقیق را دریافت میکند.
* @param {Array} listSchema - ساختار سایت.
* @example
* this.updateMultiSelectOptions([{ key: 'link', title: 'Link' }, { key: 'type', title: 'Type' }]);
* @deprecated "بصورت مستقیم درخواست زدیم و دیگه نیازی به این متد نبود."
*/
// updateMultiSelectOptions(listSchema) {
// listSchema.forEach((item) => {
// if (item.key == "link") {
// item.key = "all";
// item.title = "همه";
// this.fetchResearchItems(item);
// }
// });
// this.multiSelectOptions = listSchema;
// const index = listSchema.findIndex((item) => item.key === "link");
// if (index !== -1) {
// listSchema.splice(index, 1);
// }
// listSchema.push({
// key: "all",
// title: "همه",
// });
// this.multiSelectOptions = listSchema;
// this.multiSelectOptions.forEach((item) => {
// if (item.key == "all") {
// this.fetchResearchItems(item);
// }
// });
// },
},
computed: {
...mapState(useEntityStore, [
"selectedItemEntityGetter",
"activeEntityViewSchemaGetter",
"activeResearchTypeGetter",
]),
},
};
</script>
<style scoped lang="scss">
.research {
overflow-y: auto;
overflow-x: hidden;
height: 90dvh;
width: 19em;
}
.card_fish {
width: 17em;
height: 150px;
display: grid;
grid-template-rows: 1fr 2fr 1fr;
justify-self: center;
background-color: #f2f2f2;
border-radius: 10px;
// box-shadow: 0px 3px 7px;
box-shadow: 0px 1px 3px;
.img {
display: flex;
justify-content: space-between;
margin: 6px 10px;
.text-date {
font-size: 0.875em;
color: #a7a098;
}
}
.card_fish_main {
&:hover {
.text_fish {
p {
color: var(--primary-color);
}
}
}
.text_fish {
margin: 0px 12px;
height: 73px;
overflow: hidden;
p {
font-size: 12px;
}
}
}
}
</style>