Merge branch 'main' of https://git2.tavasi.ir/front/base_ui into shadi/develop

This commit is contained in:
Mehdi104797 2025-02-27 06:43:06 +03:30
commit 61f02d6883
64 changed files with 1789 additions and 6787 deletions

Binary file not shown.

View File

@ -0,0 +1,9 @@
@font-face {
font-family: Takrim;
src: url("../fonts/Takrim.ttf");
src: url("../fonts/Takrim.ttf?#iefix") format("embedded-opentype"),
url("../fonts/Takrim.ttf") format("woff2"),
url("../fonts/Takrim.ttf") format("woff"),
url("../fonts/Takrim.ttf") format("truetype");
font-weight: normal;
}

View File

@ -79,7 +79,6 @@
<script> <script>
import apis from "~/apis/permitApi"; import apis from "~/apis/permitApi";
// import { mapGetters, mapMutations, mapActions } from "vuex";
import { mapActions, mapState } from "pinia"; import { mapActions, mapState } from "pinia";
import { usePermitStore } from "~/stores/permitStore"; import { usePermitStore } from "~/stores/permitStore";

View File

@ -30,7 +30,7 @@
</div> </div>
</template> </template>
<script> <script>
import newFormExtension from "@forms/extensions/newFormExtension"; import newFormExtension from "@extensions/newFormExtension";
export default { export default {
extends: newFormExtension, extends: newFormExtension,

View File

@ -198,7 +198,7 @@
</div> </div>
</template> </template>
<script> <script>
import newFormExtension from "@forms/extensions/newFormExtension"; import newFormExtension from "@extensions/newFormExtension";
export default { export default {
extends: newFormExtension, extends: newFormExtension,
@ -279,7 +279,7 @@ export default {
), ),
NewTabForm: () => NewTabForm: () =>
import( import(
"@forms/forms/NewTabForm.vue" "@components/forms/NewTabForm.vue"
), ),
}, },
}; };

View File

@ -1,381 +0,0 @@
<template>
<div class="d-flex">
<label :for="localFormElement.key" :class="$attrs.labelClass ?? 'col-md-3'">{{ localFormElement.label }}:</label>
<div class="d-flex" :class="[$attrs.inputClass ?? ' col-md-9', { error: hasError }]">
<button type="button" class="btn btn-primary" @click="openModal('DataPropertyForm', 'فرم ایجاد خصوصیت ')">
انتخاب
</button>
<base-modal v-if="uploadForFirstTime" @canel="closeModal()" :showHeaderCloseButton="true" :modalTitle="modalTitle"
class="borhan-modal" modalSize="modal-lg" height="auto" maxHeight="40em" overflow="hidden" :showSaveButton="true"
:hasFooter="false">
<component :is="slotComponentName" :uploadForFirstTime="uploadForFirstTime" @saveAnnotation="sendTextValue"
:ontologyId="ontologyIdGetter" @close="closeModal()"></component>
</base-modal>
</div>
</div>
</template>
<script>
import formBuilderMixin from "@mixins/formBuilderMixin";
import HttpService from "@services/httpService";
import apis from "@apis/borhanApi.js";
import VueTribute from "vue-tribute";
import { mapGetters, mapMutations, mapActions } from "vuex";
export default {
mixins: [formBuilderMixin],
beforeMount() {
this.httpService = new HttpService();
},
mounted() {
this.multiSelectValue(this.formElement?.key);
},
data() {
return {
taskForm: "",
httpService: undefined,
templateValue: "",
options: [
{
title: "rational",
name: "rational",
},
{
title: "real",
name: "real",
},
{
title: "plainliteral",
name: "plainliteral",
},
{
title: "xmlliteral",
name: "xmlliteral",
},
{
title: "literal",
name: "literal",
},
{
title: "anyuri",
name: "anyuri",
},
{
title: "base64binary",
name: "base64binary",
},
{
title: "double",
name: "double",
},
{
title: "byte",
name: "byte",
},
{
title: "datetime",
name: "datetime",
},
{
title: "datetimestamp",
name: "datetimestamp",
},
{
title: "decimal",
name: "decimal",
},
{
title: "float",
name: "float",
},
{
title: "hexbinary",
name: "hexbinary",
},
{
title: "int",
name: "int",
},
{
title: "integer",
name: "integer",
},
{
title: "language",
name: "language",
},
{
title: "long",
name: "long",
},
{
title: "name",
name: "name",
},
{
title: "ncname",
name: "ncname",
},
{
title: "negativeinteger",
name: "negativeinteger",
},
{
title: "nmtoken",
name: "nmtoken",
},
{
title: "nonnegativeinteger",
name: "nonnegativeinteger",
},
{
title: "nonpositiveinteger",
name: "nonpositiveinteger",
},
{
title: "normalizedstring",
name: "normalizedstring",
},
{
title: "positiveinteger",
name: "positiveinteger",
},
{
title: "short",
name: "short",
},
{
title: "string",
name: "string",
},
{
title: "token",
name: "token",
},
{
title: "unsignedbyte",
name: "unsignedbyte",
},
{
title: "unsignedint",
name: "unsignedint",
},
{
title: "unsignedlong",
name: "unsignedlong",
},
{
title: "unsignedshort",
name: "unsignedshort",
},
],
tributeOptions: {
// symbol or string that starts the lookup
trigger: "",
// element to target for @mentions
iframe: null,
// class added in the flyout menu for active item
selectClass: "highlight",
// class added to the menu container
containerClass: "tribute-container mini",
// class added to each list item
itemClass: "my-tribute-class",
// function called on select that returns the content to insert
selectTemplate: function (item) {
return item.original.title;
// return "@" + item.original.value;
},
// template for displaying item in menu
menuItemTemplate: function (item) {
return item.original.title;
},
// template for when no match is found (optional),
// If no template is provided, menu is hidden.
noMatchTemplate:
'<span class="no-result">مورد مشابهی ثبت نشده است.</span>',
// specify an alternative parent container for the menu
// container must be a positioned element for the menu to appear correctly ie. `position: relative;`
// default container is the body
menuContainer: document.body,
// column to search against in the object (accepts function or string)
lookup: "title",
// column that contains the content to insert by default
fillAttr: "title",
// REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example)
// values: [
// {
// key: null,
// value: "sghl",
// },
// ],
// values: ["سلام", "باسلام", "علیک سلام", "بی سلام", "صدتا سلام"],
values: (text, cb) => {
this.remoteSearch(text, (items) => cb(items));
},
// When your values function is async, an optional loading template to show
loadingItemTemplate: null,
// specify whether a space is required before the trigger string
requireLeadingSpace: true,
// specify whether a space is allowed in the middle of mentions
allowSpaces: true,
// optionally specify a custom suffix for the replace text
// (defaults to empty space if undefined)
// replaceTextSuffix: "",
// specify whether the menu should be positioned. Set to false and use in conjuction with menuContainer to create an inline menu
// (defaults to true)
positionMenu: true,
// when the spacebar is hit, select the current match
spaceSelectsMatch: false,
// turn tribute into an autocomplete
autocompleteMode: true,
// Customize the elements used to wrap matched strings within the results list
// defaults to <span></span> if undefined
searchOpts: {
pre: '<span style="color:red">',
post: "</span>",
skip: false, // true will skip local search, useful if doing server-side search
},
// Limits the number of items in the menu
menuItemLimit: 25,
// specify the minimum number of characters that must be typed before menu appears
menuShowMinLength: 0,
},
uploadForFirstTime: false,
slotComponentName: null,
modalTitle: null,
};
},
computed: {
...mapGetters("borhan", ["ontologyIdGetter", "clickPointNameGetter"]),
},
methods: {
sendTextValue(event) {
// this.$emit("keydown", {
// event,
// });
let url = apis[this.$route.name].add;
url = url.replace("{{key}}", this.formElement.key);
let payload = {
ontology_id: this.ontologyIdGetter,
name1: this.clickPointNameGetter,
key: event.key,
lang: event?.lang,
type: event.datatype,
value: event.value,
prop: event.prop,
};
this.httpService
.postRequest(url, payload)
.then((res) => {
this.mySwalToast({
title: res.message ?? "اطلاعات با موفقیت ثبت شد.",
html: null,
icon: "success",
});
})
.catch((err) => { })
.finally(() => { });
},
closeModal() {
$("#base-modal").modal("hide");
setTimeout(() => {
this.uploadForFirstTime = false;
// this.createOntology();
}, 500);
},
openModal(componentName, title) {
this.uploadForFirstTime = true;
this.slotComponentName = componentName;
this.modalTitle = title;
setTimeout(() => {
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
}, 500);
},
multiSelectValue(item) {
this.httpService
.getRequest(
apis.property.update +
"?ontology_id=" +
this.ontologyIdGetter +
`&name1=${"dataproperty"}`
)
.then((res) => {
const list = res.data.Subobject_property;
const processedList = [];
list.forEach((element) => {
const newItem = { title: element.title, name: element.title }; // ایجاد یک شیء جدید با ویژگی title
processedList.push(newItem); // اضافه کردن شیء جدید به لیست
});
this.options = processedList;
});
},
},
components: {
VueTribute: () =>
import( "vue-tribute"),
Multiselect: () =>
import( "vue-multiselect"),
AnnotationFormAdd: () => import("@borhan/components/AnnotationFormAdd.vue"),
DataPropertyForm: () => import("@borhan/components/DataPropertyForm.vue"),
},
};
</script>
<style scoped lang="scss">
.form-control {
position: relative !important;
}
.button-input {
background-color: unset !important;
position: absolute !important;
left: 2px !important;
height: 100% !important;
border: 0;
display: flex;
justify-content: flex-end;
align-items: center;
}
</style>
<style lang="scss">
.class-search {
.multiselect__tags {
border: unset;
input {
border: unset !important;
}
}
}
</style>

View File

@ -6,7 +6,7 @@
>{{ localFormElement.label }}</label >{{ localFormElement.label }}</label
> >
<date-picker <!-- <date-picker
v-if="localFormElement?.savetype == 'time'" v-if="localFormElement?.savetype == 'time'"
append-to="body" append-to="body"
:popover="{ :popover="{
@ -23,8 +23,8 @@
@input="$emit('oninput', $event)" @input="$emit('oninput', $event)"
:placeholder="localFormElement.placeholder" :placeholder="localFormElement.placeholder"
:type="'time'" :type="'time'"
/> /> -->
<date-picker <!-- <date-picker
v-else-if="localFormElement?.subtype == 'simple'" v-else-if="localFormElement?.subtype == 'simple'"
append-to="body" append-to="body"
:popover="{ :popover="{
@ -44,8 +44,8 @@
@input="$emit('oninput', $event)" @input="$emit('oninput', $event)"
:placeholder="localFormElement.placeholder" :placeholder="localFormElement.placeholder"
:type="'date'" :type="'date'"
/> /> -->
<date-picker <!-- <date-picker
v-else v-else
append-to="body" append-to="body"
:popover="{ :popover="{
@ -64,7 +64,7 @@
@input="$emit('oninput', $event)" @input="$emit('oninput', $event)"
:placeholder="localFormElement.placeholder" :placeholder="localFormElement.placeholder"
:type="'date'" :type="'date'"
/> /> -->
</div> </div>
</template> </template>
@ -107,7 +107,7 @@ export default {
}, },
components: { components: {
// datePicker: VuePersianDatetimePicker, // datePicker: VuePersianDatetimePicker,
datePicker: () => import("vue-persian-datetime-picker"), // datePicker: () => import("vue-persian-datetime-picker"),
}, },
}; };
</script> </script>

View File

@ -0,0 +1,86 @@
<template>
<div class="side-panel">
<div class="side-panel-header">
<h6 class="text-center">
مشخصات کامل مورد جاری
</h6>
</div>
<div class="border redios-castom px-3 py-2 ">
<div class="side-panel-content">
<form-builder
:previewMode="true"
:formElements="clonedFormElements"
:formData="selectedItem"
></form-builder>
</div>
<div class="d-flex justify-content-between">
<button-component
classes="d-inline-flex btn-default"
@click="closeFormShow"
buttonText=""
>
<span class="tavasi tavasi-Component-71--1"></span>
</button-component>
<button-component
classes="d-inline-flex btn-default"
@click="editItem"
buttonText=""
>
<i class="tavasi tavasi-Component-242--1"></i>
</button-component>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["selectedItem"],
emits: ["close-form-show", "edit-item"],
data() {
return {
clonedFormElements: {
items: [
{
key: "title",
label: "عنوان",
type: "label",
placeholder: "عنوان مختصری وارد کنید",
required: "0",
validation_regex: "",
validation_error: "",
multi_select: "0",
options: [],
value: null,
},
{
key: "comment",
label: "توضیح",
type: "label",
placeholder: "توضیح مختصری وارد کنید",
required: "0",
validation_regex: "",
validation_error: "",
multi_select: "0",
options: [],
value: null,
},
],
title: "فرم جزییات",
},
};
},
methods: {
closeFormShow() {
this.$emit("close-form-show");
},
editItem() {
this.$emit("edit-item", this.selectedItem);
},
},
};
</script>

View File

@ -18,7 +18,7 @@
</template> </template>
<script> <script>
import { mapGetters } from "vuex"; import { mapState } from "pinia";
import formBuilderMixin from "@mixins/formBuilderMixin"; import formBuilderMixin from "@mixins/formBuilderMixin";
import { codemirror } from "vue-codemirror"; import { codemirror } from "vue-codemirror";
@ -61,7 +61,7 @@ export default {
this.cmOptions.placeholder = this.localFormElement.placeholder; this.cmOptions.placeholder = this.localFormElement.placeholder;
}, },
computed: { computed: {
...mapGetters("entity", ["draftActiveStepGetter"]), ...mapState(entityStore, ["draftActiveStepGetter"]),
}, },
components: { components: {
codemirror, codemirror,

View File

@ -1,404 +0,0 @@
<template>
<div class="d-flex">
<label :for="localFormElement.key" :class="$attrs.labelClass ?? 'col-md-3'">{{ localFormElement.label }}:</label>
<div class="d-flex" :class="[$attrs.inputClass ?? ' col-md-9', { error: hasError }]">
<div class="col-md-5">
<multiselect class="class-search" track-by="id" label="title" placeholder=" انتخاب کنید... "
v-model="templateValue" :options="options" :searchable="true" :internal-search="false" :clear-on-select="false"
:close-on-select="true" :options-limit="300" :limit="3" :max-height="350" @search-change="asyncFind"
@select="forwardMessage" @close="resetFoundUsers">
</multiselect>
</div>
<div class="d-flex col-md-10">
<vue-tribute class="col-md-12 ps-0 pe-0" :options="tributeOptions">
<input class="label-1 form-control task-form-control task-title" :placeholder="localFormElement.placeholder"
:type="localFormElement.type" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue"
@tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" />
</vue-tribute>
<button type="button" class="btn btn-light button-input" :class="$attrs.buttonClass"
@click.prevent="sendTextValue" style="width: 4em">
<svg class="icon icon-Component-233--1">
<use xlink:href="#icon-Component-233--1"></use>
</svg>
</button>
</div>
<button type="button" class="btn btn-light" v-if="isUpdateitem" @click="handlerUpdate">
<svg class="icon icon-Component-294--1">
<use xlink:href="#icon-Component-294--1"></use>
</svg>
</button>
</div>
</div>
</template>
<script>
import formBuilderMixin from "@mixins/formBuilderMixin";
import HttpService from "@services/httpService";
import apis from "@apis/borhanApi.js";
import VueTribute from "vue-tribute";
import { mapGetters, mapMutations, mapActions } from "vuex";
export default {
mixins: [formBuilderMixin],
beforeMount() {
this.httpService = new HttpService();
},
mounted() {
this.multiSelectValue(this.formElement.key);
},
data() {
return {
taskForm: "",
httpService: undefined,
templateValue: "",
options: [
{
title: "rational",
name: "rational",
},
{
title: "real",
name: "real",
},
{
title: "plainliteral",
name: "plainliteral",
},
{
title: "xmlliteral",
name: "xmlliteral",
},
{
title: "literal",
name: "literal",
},
{
title: "anyuri",
name: "anyuri",
},
{
title: "base64binary",
name: "base64binary",
},
{
title: "double",
name: "double",
},
{
title: "byte",
name: "byte",
},
{
title: "datetime",
name: "datetime",
},
{
title: "datetimestamp",
name: "datetimestamp",
},
{
title: "decimal",
name: "decimal",
},
{
title: "float",
name: "float",
},
{
title: "hexbinary",
name: "hexbinary",
},
{
title: "int",
name: "int",
},
{
title: "integer",
name: "integer",
},
{
title: "language",
name: "language",
},
{
title: "long",
name: "long",
},
{
title: "name",
name: "name",
},
{
title: "ncname",
name: "ncname",
},
{
title: "negativeinteger",
name: "negativeinteger",
},
{
title: "nmtoken",
name: "nmtoken",
},
{
title: "nonnegativeinteger",
name: "nonnegativeinteger",
},
{
title: "nonpositiveinteger",
name: "nonpositiveinteger",
},
{
title: "normalizedstring",
name: "normalizedstring",
},
{
title: "positiveinteger",
name: "positiveinteger",
},
{
title: "short",
name: "short",
},
{
title: "string",
name: "string",
},
{
title: "token",
name: "token",
},
{
title: "unsignedbyte",
name: "unsignedbyte",
},
{
title: "unsignedint",
name: "unsignedint",
},
{
title: "unsignedlong",
name: "unsignedlong",
},
{
title: "unsignedshort",
name: "unsignedshort",
},
],
tributeOptions: {
// symbol or string that starts the lookup
trigger: "",
// element to target for @mentions
iframe: null,
// class added in the flyout menu for active item
selectClass: "highlight",
// class added to the menu container
containerClass: "tribute-container mini",
// class added to each list item
itemClass: "my-tribute-class",
// function called on select that returns the content to insert
selectTemplate: function (item) {
return item.original.title;
// return "@" + item.original.value;
},
// template for displaying item in menu
menuItemTemplate: function (item) {
return item.original.title;
},
// template for when no match is found (optional),
// If no template is provided, menu is hidden.
noMatchTemplate:
'<span class="no-result">مورد مشابهی ثبت نشده است.</span>',
// specify an alternative parent container for the menu
// container must be a positioned element for the menu to appear correctly ie. `position: relative;`
// default container is the body
menuContainer: document.body,
// column to search against in the object (accepts function or string)
lookup: "title",
// column that contains the content to insert by default
fillAttr: "title",
// REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example)
// values: [
// {
// key: null,
// value: "sghl",
// },
// ],
// values: ["سلام", "باسلام", "علیک سلام", "بی سلام", "صدتا سلام"],
values: (text, cb) => {
this.remoteSearch(text, (items) => cb(items));
},
// When your values function is async, an optional loading template to show
loadingItemTemplate: null,
// specify whether a space is required before the trigger string
requireLeadingSpace: true,
// specify whether a space is allowed in the middle of mentions
allowSpaces: true,
// optionally specify a custom suffix for the replace text
// (defaults to empty space if undefined)
// replaceTextSuffix: "",
// specify whether the menu should be positioned. Set to false and use in conjuction with menuContainer to create an inline menu
// (defaults to true)
positionMenu: true,
// when the spacebar is hit, select the current match
spaceSelectsMatch: false,
// turn tribute into an autocomplete
autocompleteMode: true,
// Customize the elements used to wrap matched strings within the results list
// defaults to <span></span> if undefined
searchOpts: {
pre: '<span style="color:red">',
post: "</span>",
skip: false, // true will skip local search, useful if doing server-side search
},
// Limits the number of items in the menu
menuItemLimit: 25,
// specify the minimum number of characters that must be typed before menu appears
menuShowMinLength: 0,
},
};
},
computed: {
...mapGetters("borhan", ["ontologyIdGetter", "clickPointNameGetter"]),
},
methods: {
asyncFind() { },
multiSelectValue(item) {
if (item == "objcet_property_assertions") {
this.httpService
.getRequest(
apis.property.update +
"?ontology_id=" +
this.ontologyIdGetter +
`&name1=${"objectproperty"}`
)
.then((res) => {
const list = res.data.Subobject_property;
const processedList = [];
list.forEach((element) => {
const newItem = { title: element.title, name: element.title }; // ایجاد یک شیء جدید با ویژگی title
processedList.push(newItem); // اضافه کردن شیء جدید به لیست
});
this.options = processedList;
});
}
},
forwardMessage(newTag) {
this.templateValue = newTag;
},
resetFoundUsers() { },
noMatchFound(args) {
console.info(args);
},
textReplaced(args) {
console.info(args);
},
remoteSearch(text, cb) {
let url = "";
if (this.formElement.key == "type") {
const queryParams = new URLSearchParams({
ontology_id: this.ontologyIdGetter,
search: text,
});
url = apis.class.autoComplate + "?" + queryParams;
} else {
const queryParams = new URLSearchParams({
ontology_id: this.ontologyIdGetter,
search: text,
});
url = apis[this.$route.name].autoComplate + "?" + queryParams;
}
// if (text == "") url = taskApi.workingHours.complitionAll;
this.httpService
.getRequest(url)
.then((response) => {
const list = response.data;
const processedList = [];
list.forEach((element) => {
const newItem = { title: element }; // ایجاد یک شیء جدید با ویژگی title
processedList.push(newItem); // اضافه کردن شیء جدید به لیست
});
cb(processedList);
})
.catch((error) => { })
.finally(() => { });
},
sendTextValue() {
this.$emit("keydown", {
text: this.textValue,
prop: this.templateValue.name,
key: this.keyValue,
isUpdate: this.isUpdateitem,
});
this.textValue = "";
},
handlerUpdate() {
this.textValue = "";
this.templateValue = "";
this.isUpdateitem = false;
},
},
components: {
VueTribute: () =>
import( "vue-tribute"),
Multiselect: () =>
import( "vue-multiselect"),
},
};
</script>
<style scoped lang="scss">
.form-control {
position: relative !important;
}
.button-input {
background-color: unset !important;
position: absolute !important;
left: 2px !important;
height: 100% !important;
border: 0;
display: flex;
justify-content: flex-end;
align-items: center;
}
</style>
<style lang="scss">
.class-search {
.multiselect__tags {
border: unset;
input {
border: unset !important;
}
}
}
</style>

View File

@ -1,216 +0,0 @@
<template>
<div class="d-flex">
<label :for="localFormElement.key" :class="$attrs.labelClass ?? 'col-md-3'">{{ localFormElement.label }}:</label>
<div class="d-flex" :class="[$attrs.inputClass ?? ' col-md-9', { error: hasError }]">
<vue-tribute class="col-md-12 ps-0 pe-0" :options="tributeOptions">
<input class="label-1 form-control task-form-control task-title" :placeholder="localFormElement.placeholder"
:type="localFormElement.type" :id="localFormElement.key" :name="localFormElement.key" v-model="textValue"
@tribute-no-match="noMatchFound" @tribute-replaced="textReplaced" />
</vue-tribute>
<button type="button" class="btn btn-light button-input" :class="$attrs.buttonClass" @click.prevent="sendTextValue"
style="width: 4em">
<svg class="icon icon-Component-233--1">
<use xlink:href="#icon-Component-233--1"></use>
</svg>
</button>
</div>
<button type="button" class="btn btn-light" v-if="isUpdateitem" @click="handlerUpdate">
<svg class="icon icon-Component-294--1">
<use xlink:href="#icon-Component-294--1"></use>
</svg>
</button>
</div>
</template>
<script>
import formBuilderMixin from "@mixins/formBuilderMixin";
import HttpService from "@services/httpService";
import apis from "@apis/borhanApi.js";
import VueTribute from "vue-tribute";
import { mapGetters, mapMutations, mapActions } from "vuex";
export default {
mixins: [formBuilderMixin],
beforeMount() {
this.httpService = new HttpService();
},
data() {
return {
taskForm: "",
httpService: undefined,
tributeOptions: {
// symbol or string that starts the lookup
trigger: "",
// element to target for @mentions
iframe: null,
// class added in the flyout menu for active item
selectClass: "highlight",
// class added to the menu container
containerClass: "tribute-container mini",
// class added to each list item
itemClass: "my-tribute-class",
// function called on select that returns the content to insert
selectTemplate: function (item) {
return item.original.title;
// return "@" + item.original.value;
},
// template for displaying item in menu
menuItemTemplate: function (item) {
return item.original.title;
},
// template for when no match is found (optional),
// If no template is provided, menu is hidden.
noMatchTemplate:
'<span class="no-result">مورد مشابهی ثبت نشده است.</span>',
// specify an alternative parent container for the menu
// container must be a positioned element for the menu to appear correctly ie. `position: relative;`
// default container is the body
menuContainer: document.body,
// column to search against in the object (accepts function or string)
lookup: "title",
// column that contains the content to insert by default
fillAttr: "title",
// REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example)
// values: [
// {
// key: null,
// value: "sghl",
// },
// ],
// values: ["سلام", "باسلام", "علیک سلام", "بی سلام", "صدتا سلام"],
values: (text, cb) => {
this.remoteSearch(text, items => cb(items));
},
// When your values function is async, an optional loading template to show
loadingItemTemplate: null,
// specify whether a space is required before the trigger string
requireLeadingSpace: true,
// specify whether a space is allowed in the middle of mentions
allowSpaces: true,
// optionally specify a custom suffix for the replace text
// (defaults to empty space if undefined)
// replaceTextSuffix: "",
// specify whether the menu should be positioned. Set to false and use in conjuction with menuContainer to create an inline menu
// (defaults to true)
positionMenu: true,
// when the spacebar is hit, select the current match
spaceSelectsMatch: false,
// turn tribute into an autocomplete
autocompleteMode: true,
// Customize the elements used to wrap matched strings within the results list
// defaults to <span></span> if undefined
searchOpts: {
pre: '<span style="color:red">',
post: "</span>",
skip: false, // true will skip local search, useful if doing server-side search
},
// Limits the number of items in the menu
menuItemLimit: 25,
// specify the minimum number of characters that must be typed before menu appears
menuShowMinLength: 0,
},
};
},
computed: {
...mapGetters("borhan", ["ontologyIdGetter", "clickPointNameGetter"]),
},
methods: {
noMatchFound(args) {
console.info(args);
},
textReplaced(args) {
console.info(args);
},
remoteSearch(text, cb) {
let url = "";
if (this.formElement.key == "type") {
const queryParams = new URLSearchParams({
ontology_id: this.ontologyIdGetter,
search: text,
});
url = apis.class.autoComplate + "?" + queryParams;
} else {
const queryParams = new URLSearchParams({
ontology_id: this.ontologyIdGetter,
search: text,
});
url = apis[this.$route.name].autoComplate + "?" + queryParams;
}
// if (text == "") url = taskApi.workingHours.complitionAll;
this.httpService
.getRequest(url)
.then((response) => {
const list = response.data;
const processedList = [];
list.forEach((element) => {
const newItem = { title: element }; // ایجاد یک شیء جدید با ویژگی title
processedList.push(newItem); // اضافه کردن شیء جدید به لیست
});
cb(processedList);
})
.catch((error) => { })
.finally(() => { });
},
sendTextValue() {
this.$emit("keydown", {
text: this.textValue,
key: this.keyValue,
isUpdate: this.isUpdateitem,
});
this.textValue = "";
},
handlerUpdate() {
this.textValue = "";
this.isUpdateitem = false;
},
},
components: {
VueTribute: () =>
import( "vue-tribute"),
},
};
</script>
<style scoped lang="scss">
.form-control {
position: relative !important;
}
.button-input {
background-color: unset !important;
position: absolute !important;
left: 2px !important;
height: 100% !important;
border: 0;
display: flex;
justify-content: flex-end;
align-items: center;
}
</style>

View File

@ -0,0 +1,183 @@
<template>
<div class="side-panel">
<div class="side-panel-header">
<h6 class="text-center">
افزودن آیتم جدید
</h6>
</div>
<div class="redios-castom px-3 py-2 ">
<div class="side-panel-content">
<form @submit.prevent="saveNewItemForm()" class="text__14">
<form-builder
ref="newFormItemBuilder"
:formElements="formElement"
:formData="formData"
></form-builder>
<div class="mb-3">
<button-component
type="submit"
classes="btn-outline-primary mx-3"
buttonText="افزودن"
:buttonLoading="buttonLoading"
></button-component>
<button-component
classes="btn-danger"
buttonText="انصراف"
:buttonLoading="buttonLoading"
@click="closeNewFormItem"
></button-component>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
emits: ["close-new-form-item","add-item-content"],
props: {
editFormData: {
default() {
return {};
},
},
},
watch: {
editFormData: {
handler(newVal) {
this.formData = newVal;
},
},
},
mounted(){
this.formData = this.editFormData;
},
data() {
return {
buttonLoading: false,
formData: {
name: "",
key: "",
placeholder: "",
type: "",
},
formElement: {
title: "مشخصات اصلی",
items: [
{
key: "label",
label: "عنوان",
type: "string",
placeholder: "عنوان را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "key",
label: "کلیدواژه",
type: "string",
placeholder: "کلیدواژه را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "placeholder",
label: "راهنما",
type: "string",
placeholder: "راهنمای اولیه مختصر را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "value",
label: "مقدار",
type: "string",
placeholder: "مقدار را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "type",
label: "نوع",
type: "select",
placeholder: "نوع را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [
{
title: "صوتی",
value: "sound",
},
{
title: "فیلم",
value: "video",
},
{
title: "تصویر",
value: "img",
},
{
title: "عبارت(نمایشی)",
value: "label",
},
{
title: "متن",
value: "textarea",
},
{
title: "انتخابی",
value: "select",
},
{
title: "متن کوتاه",
value: "string",
},
],
},
],
},
};
},
methods: {
closeNewFormItem() {
this.$emit("close-new-form-item");
},
saveNewItemForm() {
const formData = this.$refs.newFormItemBuilder.localFormData;
this.$emit("add-item-content", formData);
},
resetForm() {
this.formData = {
name: "",
key: "",
placeholder: "",
type: "",
};
},
},
};
</script>
<style lang="scss"></style>

View File

@ -0,0 +1,85 @@
<template>
<div class="side-panel">
<form @submit.prevent="saveNewTab()" class="text__14">
<form-builder
ref="newTabBuilder"
:formElements="formElement"
:formData="formData"
></form-builder>
<div class="mb-3">
<button-component
type="submit"
classes="btn-outline-primary mx-3"
buttonText="افزودن"
:buttonLoading="buttonLoading"
></button-component>
<button-component
classes="btn-danger"
buttonText="انصراف"
:buttonLoading="buttonLoading"
@click="closeNewFormItem"
></button-component>
</div>
</form>
</div>
</template>
<script>
export default {
emits: ["close-new-form-item", "add-item-content"],
data() {
return {
buttonLoading: false,
formData: {
title: null,
comment: null,
type: 1,
meta: null,
table_columns: null,
},
formElement: {
title: "بخش جدید",
items: [
{
key: "title",
label: "عنوان",
type: "string",
placeholder: "عنوان را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "comment",
label: "توضیحات",
type: "textarea",
placeholder: "توضیحات را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
],
},
};
},
methods: {
closeNewFormItem() {
this.$emit("close-new-form-item");
},
saveNewTab() {
const formData = this.$refs.newTabBuilder.localFormData;
this.$emit("add-item-content", formData);
},
},
};
</script>
<style lang="scss"></style>

View File

@ -98,8 +98,10 @@
<script> <script>
import repoApi from "@apis/repoApi"; import repoApi from "@apis/repoApi";
import { mapGetters, mapMutations } from "vuex"; import { mapState } from "pinia";
import HttpService from "@services/httpService"; import HttpService from "@services/httpService";
import { useEntityStore } from "~/systems/search_ui/stores/entityStore";
import { useCommonStore } from "~/systems/search_ui/stores/useCommonStore";
/** /**
* @vue-data {Object} [listUpdatedText = {}] - متنهای بهروزشده در لیست. * @vue-data {Object} [listUpdatedText = {}] - متنهای بهروزشده در لیست.
* @vue-data {undefined} [httpService = undefined] - سرویس HTTP برای درخواستها. * @vue-data {undefined} [httpService = undefined] - سرویس HTTP برای درخواستها.
@ -158,11 +160,11 @@ export default {
}; };
}, },
computed: { computed: {
...mapGetters("entity", [ ...mapGetters(useEntityStore, [
// "selectedItemEntityGetter", // "selectedItemEntityGetter",
"activeTabGetter", "activeTabGetter",
]), ]),
...mapGetters(["userPermisionGetter", "currentUser"]), ...mapGetters(useCommonStore,["userPermisionGetter", "currentUser"]),
}, },
methods: { methods: {
// ...mapMutations("entity", ["SET_ITEM_ENTITY"]), // ...mapMutations("entity", ["SET_ITEM_ENTITY"]),

View File

@ -0,0 +1,79 @@
<template>
<div class="position-relative ms-5">
<my-table
height="auto"
maxHeight="calc(100vh - 15em)"
:isSortable="true"
:isDraggable="true"
:hasSearch="false"
:hasPagination="false"
:fetchingData="fetchingData"
:items="localMainFormElements[currentTab]?.items"
:tableColumns="tableColumns"
:tableActions="formTableActions"
@delete-table-item="deleteItem"
@edit-table-item="editNewFormItem"
@onSort="onSort"
@on-linked-title-click="onLinkedTitleClick"
/>
<button-component
classes="d-inline-flex add-new-form-item"
@click="openNewFormItem"
buttonText=""
>
<span class="tavasi tavasi-Component-220--1"
><span class="path1"></span><span class="path2"></span
><span class="path3"></span
></span>
</button-component>
</div>
</template>
<script>
import newFormExtension from "@extensions/newFormExtension";
export default {
extends: newFormExtension,
props: ["newFormItem", "formTitleData"],
mounted() {
const form = [
{
title: "فرم ساده",
items: [],
active: true,
},
];
this.localMainFormElements = this.formTitleData.meta ?? form;
},
data() {
return {
localMainFormElements: [
{
title: "فرم ساده",
items: [],
active: true,
},
],
};
},
components: {
LabelComponent: () =>
import(
"@components/forms/LabelComponent.vue"
),
},
};
</script>
<style scoped lang="scss">
.add-new-form-item {
position: absolute;
left: -3em;
bottom: 0;
}
</style>

View File

@ -0,0 +1,337 @@
<template>
<div>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li
v-for="(groupItem, index) in localMainFormElements"
:key="index"
@click="setTab(index)"
class="nav-item"
role="presentation"
>
<a
class="nav-link position-relative ms-3"
id="home-tab"
data-bs-toggle="tab"
:href="'#' + groupItem.key"
role="tab"
:aria-controls="groupItem.key"
aria-selected="true"
:class="{ active: groupItem.active ?? false }"
>{{ groupItem.title }}
<button-component
classes="d-inline-flex tab-remove-btn"
@click="removeTab(index)"
buttonText=""
>
<span class="tavasi tavasi-Component-21--1"></span>
</button-component>
<button-component
classes="d-inline-flex tab-edit-btn"
@click="openEditTabFormModal(index)"
buttonText=""
title="ویرایش"
>
<span class="tavasi tavasi-Component-242--1"></span>
</button-component>
</a>
</li>
<li class="nav-item" role="presentation">
<!-- add button -->
<button-component
classes="nav-link d-inline-flex"
@click="openNewTabFormModal()"
buttonText="بخش جدید"
>
<span class="tavasi tavasi-Component-220--1 ms-1"
><span class="path1"></span><span class="path2"></span
><span class="path3"></span
></span>
</button-component>
</li>
</ul>
<div
class="tab-content"
id="myTabContent"
v-if="localMainFormElements?.length"
>
<div
class="tab-pane fade show active p-3"
id="home"
role="tabpanel"
aria-labelledby="home-tab"
>
<div
v-if="localMainFormElements[currentTab]?.hasChildren"
class="accordion"
id="accordionExample"
>
<div
v-for="(innerGroupItem, j) in localMainFormElements[currentTab]
?.items"
:key="j"
class="card"
>
<div class="card-header" :id="'heading' + j">
<h2 class="mb-0 d-flex">
<!-- حذف تب داخلی یا فرزند -->
<button-component
classes="d-inline-flex p-0"
@click="removeChildTab(j)"
buttonText=""
title="حذف"
>
<span class="tavasi tavasi-Component-295--1"></span>
</button-component>
<!-- باز کردن مودال ویرایش تب داخلی یا فرزند -->
<button-component
classes="d-inline-flex p-0"
@click="openChildTabEditModal(j)"
buttonText=""
title="ویرایش"
>
<span class="tavasi tavasi-Component-242--1"></span>
</button-component>
<button
class="btn btn-link btn-block has-indicator"
type="button"
data-bs-toggle="collapse"
:data-bs-target="'#collapse' + j"
:aria-expanded="innerGroupItem.active ?? false"
:aria-controls="'collapse' + j"
:class="{ active: innerGroupItem.active ?? false }"
>
{{ innerGroupItem.title }}
</button>
</h2>
</div>
<div
:id="'collapse' + j"
class="collapse"
:class="{ show: innerGroupItem.active ?? false }"
:aria-labelledby="'heading' + j"
data-parent="#accordionExample"
>
<div class="card-body">
<div class="position-relative ms-5">
<my-table
height="auto"
maxHeight="calc(100vh - 15em)"
:isSortable="true"
:isDraggable="true"
:hasSearch="false"
:hasPagination="false"
:fetchingData="fetchingData"
:items="localMainFormElements[currentTab]?.items[j]?.items"
:tableColumns="tableColumns"
:tableActions="formTableActions"
@delete-table-item="deleteChildItem($event, j)"
@edit-table-item="childEditNewFormItem($event, j)"
@onSort="onSort"
@on-linked-title-click="onLinkedTitleClick"
/>
<button-component
classes="d-inline-flex add-new-form-item"
@click="openChildNewFormItem(j)"
buttonText=""
>
<span class="tavasi tavasi-Component-220--1"
><span class="path1"></span><span class="path2"></span
><span class="path3"></span
></span>
</button-component>
</div>
</div>
</div>
</div>
</div>
<div v-else class="position-relative ms-5">
<my-table
height="auto"
maxHeight="calc(100vh - 15em)"
:isSortable="true"
:isDraggable="true"
:hasSearch="false"
:hasPagination="false"
:fetchingData="fetchingData"
:items="localMainFormElements[currentTab]?.items"
:tableColumns="tableColumns"
:tableActions="formTableActions"
@delete-table-item="deleteItem"
@edit-table-item="editNewFormItem"
@onSort="onSort"
@on-linked-title-click="onLinkedTitleClick"
/>
<button-component
classes="d-inline-flex add-new-form-item"
@click="openNewFormItem"
buttonText=""
>
<span class="tavasi tavasi-Component-220--1"
><span class="path1"></span><span class="path2"></span
><span class="path3"></span
></span>
</button-component>
</div>
</div>
</div>
<!-- new tab modal -->
<base-modal
v-if="showNewTabFormModal"
modalSize="modal-md"
modalTitle="فرم جدید"
@close="closeNewTabFormModal"
@save="addTab"
>
<form-builder
ref="tabFormBuilder"
:formElements="formTabElement"
:formData="formTabData"
></form-builder>
</base-modal>
</div>
</template>
<script>
import newFormExtension from "@extensions/newFormExtension";
export default {
extends: newFormExtension,
props: ["newFormItem", "formTitleData"],
mounted() {
this.localMainFormElements = this.formTitleData.meta ?? [];
if (this.localMainFormElements && this.localMainFormElements[0])
this.localMainFormElements[0].active = true;
},
data() {
return {
prevActiveTabIndex: undefined,
localMainFormElements: [],
showNewTabFormModal: false,
// form title elemnets and data.
formTabData: {
title: null,
},
formTabElement: {
title: "",
items: [
{
key: "parent",
label: "والد",
type: "select",
placeholder: "والد را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "title",
label: "عنوان",
type: "string",
placeholder: "عنوان را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
{
key: "key",
label: "کلیدواژه",
type: "string",
placeholder: "کلیدواژه را وارد کنید",
required: "1",
validation_regex: "{3-100}",
validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
multi_select: "0",
options: [],
},
// {
// key: "newButtonText",
// label: "عنوان دکمه ایجاد",
// type: "string",
// placeholder: "عنوان دکمه ایجاد را وارد کنید",
// required: "1",
// validation_regex: "{3-100}",
// validation_error: "عبارت باید حداقل 3 و حداکثر 100 حرف باشد",
// multi_select: "0",
// options: [],
// },
],
},
};
},
components: {
LabelComponent: () =>
import(
"@components/forms/LabelComponent.vue"
),
NewTabForm: () =>
import(
"@forms/forms/NewTabForm.vue"
),
},
};
</script>
<style scoped lang="scss">
.tab-remove-btn {
position: absolute;
left: -0.5em;
top: -0.5em;
background-color: #fff;
justify-content: center;
align-items: center;
padding: 0;
span {
color: var(--danger);
}
&:hover {
background-color: var(--danger);
span {
color: #fff;
}
}
}
.tab-edit-btn {
position: absolute;
left: -0.5em;
bottom: 0em;
background-color: #fff;
justify-content: center;
align-items: center;
padding: 0;
&:hover {
background-color: #ddd;
span {
color: #fff;
}
}
}
.add-new-form-item {
position: absolute;
left: -3em;
bottom: 0;
}
</style>
<style>
.accordion .card .card-body .btn::after {
content: none;
}
</style>

View File

@ -0,0 +1,106 @@
<template>
<div class="side-panel">
<div class="side-panel-header">
<h6>
انتخاب ستونها در حالت نمایش فهرستی(جدولی)
</h6>
</div>
<div class="side-panel-content">
<form @submit.prevent="saveColumn">
<div class="row form-group">
<label for="key" class="col-md-3">کلیدواژه: </label>
<select
class="form-control col-md-9"
placeholder="کلیدواژه"
type="key"
id="key"
name="key"
v-model="localFormElement.key"
>
<option
v-for="option in selectedForm.flatedItems"
:value="option.key"
>{{ option.label }}({{ option.key }})</option
>
</select>
</div>
<div class="row form-group">
<label for="title" class="col-md-3">عنوان: </label>
<input
class="form-control col-md-9"
placeholder="عنوان"
type="title"
id="title"
name="title"
v-model="localFormElement.title"
/>
</div>
<div class="row form-group">
<label for="width" class="col-md-3">وزن: </label>
<input
class="form-control col-md-9"
placeholder="وزن"
type="width"
id="width"
name="width"
v-model="localFormElement.width"
/>
</div>
<div class="row form-group">
<div class="d-flex justify-content-between">
<button-component
classes="btn btn-primary d-inline-flex btn-default"
buttonText="افزودن"
type="submit"
>
</button-component>
<button-component
classes="d-inline-flex btn-danger"
@click="closeFormShow"
buttonText="بستن"
>
<!-- <span class="tavasi tavasi-Component-71--1"></span> -->
</button-component>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
export default {
props: ["selectedItem", "selectedForm"],
emits: ["close-form-show", "update-column"],
data() {
return {
displayMode:'table',
localFormElement: {
title: null,
key: null,
width: 1,
},
};
},
mounted() {
this.localFormElement = structuredClone(this.selectedItem);
},
watch: {
selectedItem(newval) {
this.localFormElement = structuredClone(newval);
},
},
methods: {
closeFormShow() {
this.$emit("close-form-show");
},
saveColumn() {
const clonedLocalFormElement = structuredClone(this.localFormElement);
this.$emit("update-column", clonedLocalFormElement);
},
},
};
</script>

View File

@ -102,7 +102,6 @@
<script> <script>
import HttpService from "@services/httpService"; import HttpService from "@services/httpService";
import repoApi from "@apis/repoApi"; import repoApi from "@apis/repoApi";
import { mapMutations, mapGetters } from "vuex";
export default { export default {
props: { props: {

View File

@ -54,6 +54,7 @@
<script> <script>
import { mapState } from "pinia"; import { mapState } from "pinia";
import { useEntityStore } from "~/systems/search_ui/stores/entityStore";
export default { export default {
props: { props: {
@ -70,7 +71,7 @@ export default {
}, },
}, },
computed: { computed: {
...mapState("entity", ["vuexEntityGetter"]), ...mapState(useEntityStore, ["vuexEntityGetter"]),
}, },
methods: { methods: {
normalPathKey(title = "") { normalPathKey(title = "") {

View File

@ -36,7 +36,7 @@
</template> </template>
<script> <script>
import {mapActions} from 'vuex'; import {mapActions} from 'pinia';
import { useCommonStore } from "~/stores/commonStore"; import { useCommonStore } from "~/stores/commonStore";
export default { export default {

View File

@ -0,0 +1,440 @@
/* Be aware that component extension is not as classes inheritance.
In this case, Vue merges both the parent and child component options creating a new mixed object.
For the case of the mounted and destroyed hook, both the parents and childrens are kept and they
will be called in inheritance order, from parent to children.
https://vueschool.io/articles/vuejs-tutorials/reusing-logic-in-vue-components/
*/
/* hooks order
1) extension
2) mixins
3) component
*/
import formTableActions from "@json/formTableActions";
export default {
data() {
return {
addToChildren: false,
editChildTab: false,
parentRowItemIndex: 0,
childRowItemIndex: 0,
childRowItem: {},
parentRowItem: {},
tabIndex: undefined,
childTabIndex: undefined,
fetchingData: false,
tableColumns: [
{
isLink: true,
key: "label",
title: "عنوان",
width: "1",
},
{
key: "key",
title: "کلید",
width: "1",
},
{
key: "placeholder",
title: "راهنما",
width: "3",
},
{
key: "value",
title: "مقدار",
width: "1",
},
{
key: "type",
title: "نوع",
width: "1",
},
],
formTableActions: formTableActions,
localFormData: {},
currentTab: 0,
buttonLoading: false,
};
},
methods: {
onLinkedTitleClick({ rowItem, tableColumn, index }) {
this.editNewFormItem(index);
},
/*
summary: change the sort of form items(elements)
description: changing the sort of the form items
in the table by drag and drop them.
@param {Event} Sortable sort event.
@param {newIndex} String dropped into index.
@param {oldIndex} String dragged from index.
@return void.
*/
onSort({ newIndex, oldIndex }) {
const tempItem =
this.localMainFormElements[this.currentTab].items[newIndex];
this.localMainFormElements[this.currentTab].items[newIndex] =
this.localMainFormElements[this.currentTab].items[oldIndex];
this.localMainFormElements[this.currentTab].items[oldIndex] = tempItem;
},
openNewTabFormModal() {
this.showNewTabFormModal = true;
this.tabIndex = undefined;
const options = [
{
title: "بدون والد",
value: null,
},
];
this.localMainFormElements.forEach((element) => {
options.push({ title: element.title, value: element.title });
});
this.formTabElement.items[0].options = options;
setTimeout(() => {
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
}, 500);
},
openEditTabFormModal(index) {
this.editChildTab = false;
this.tabIndex = index;
this.childTabIndex = undefined;
const options = [
{
title: "بدون والد",
value: null,
},
];
this.localMainFormElements.forEach((element) => {
options.push({ title: element.title, value: element.title });
});
this.formTabElement.items[0].options = options;
this.formTabData = this.localMainFormElements[index];
this.showNewTabFormModal = true;
setTimeout(() => {
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
}, 500);
},
openChildTabEditModal(childIndex) {
this.editChildTab = true;
this.tabIndex = undefined;
this.childTabIndex = childIndex;
const options = [
{
title: "بدون والد",
value: null,
},
];
this.localMainFormElements.forEach((element) => {
options.push({ title: element.title, value: element.title });
});
this.formTabElement.items[0].options = options;
this.formTabData =
this.localMainFormElements[this.currentTab].items[childIndex];
this.showNewTabFormModal = true;
setTimeout(() => {
$("#base-modal").modal({ backdrop: "static", keyboard: false }, "show");
}, 500);
},
closeNewTabFormModal() {
$("#base-modal").modal("hide");
setTimeout(() => {
this.showNewTabFormModal = false;
}, 500);
},
addTab() {
if (this.editChildTab) this.addChildTab();
else this.addParentTab();
this.closeNewTabFormModal();
},
addParentTab() {
const tab = this.$refs.tabFormBuilder.localFormData;
if (tab.parent) {
const tabItem = this.localMainFormElements.find(
(item) => item.title == tab.parent
);
tabItem.active = true;
if (tabItem) {
tabItem.hasChildren = true;
tabItem.items.push({
parent: tab.parent,
key: tab.key,
title: tab.title,
active: true,
items: [],
});
}
} else {
if (this.tabIndex == undefined) {
this.localMainFormElements.push({
key: tab.key,
title: tab.title,
active: true,
items: [],
});
this.setTab(this.localMainFormElements?.length - 1);
} else {
this.localMainFormElements[this.tabIndex].title = tab.title;
this.localMainFormElements[this.tabIndex].key = tab.key;
}
}
},
addChildTab() {
const tab = this.$refs.tabFormBuilder.localFormData;
const tabItem =
this.localMainFormElements[this.currentTab].items[this.childTabIndex];
if (tabItem) {
tabItem.parent = tab.parent;
tabItem.title = tab.title;
tabItem.key = tab.key;
tabItem.newButtonText = tab.newButtonText ?? tab.title;
}
},
setTab(index) {
if (this.localMainFormElements[index].hasChildren) {
this.addToChildren = true;
} else {
this.addToChildren = false;
}
if (this.prevActiveTabIndex != undefined)
this.localMainFormElements[this.prevActiveTabIndex].active = false;
this.prevActiveTabIndex = this.currentTab = index;
},
removeParentTab(index) {
this.mySwalConfirm({
title: "هشدار!!!",
html: "از حذف این مورد مطمئن هستید؟",
}).then((result) => {
if (result.isConfirmed) {
this.localMainFormElements.splice(index, 1);
}
});
},
removeChildTab(childIndex) {
this.mySwalConfirm({
title: "هشدار!!!",
html: "از حذف این مورد مطمئن هستید؟",
}).then((result) => {
if (result.isConfirmed) {
this.localMainFormElements[this.currentTab].items.splice(
childIndex,
1
);
}
});
},
// addFormItemToFormElements(newFormItem) {
// if (this.localMainFormElements[this.currentTab].items?.length == 0)
// this.localMainFormElements[this.currentTab].items.push(newFormItem);
// else {
// }
// },
addFormItemToFormElements(updatedColumn) {
if (this.addToChildren) this.addItemToChildren(updatedColumn);
else this.addItemToParent(updatedColumn);
},
addItemToChildren(updatedColumn) {
if (this.childRowItemIndex)
this.$set(
this.localMainFormElements[this.currentTab].items[
this.parentRowItemIndex
].items,
this.childRowItemIndex,
updatedColumn
);
else {
// find new item in the forms table columns items.
// if exist => continue
// else catch block executs and create new table columns.
try {
const res = this.localMainFormElements[this.currentTab].items[
this.parentRowItemIndex
].items.filter((item) => item.key == updatedColumn.key);
if (res.length)
this.mySwalToast({
title: "ستونی با چنین مشخصاتی قبلا ایجاد شده است.",
html: null,
icon: "error",
});
else {
this.localMainFormElements[this.currentTab].items[
this.parentRowItemIndex
].items.push(updatedColumn);
}
} catch (msg) {
this.localMainFormElements[this.currentTab].items[
this.parentRowItemIndex
] = {
items: [updatedColumn],
title: this.formTitleData.title,
};
}
}
},
addItemToParent(updatedColumn) {
if (this.parentRowItemIndex)
this.$set(
this.localMainFormElements[this.currentTab].items,
this.parentRowItemIndex,
updatedColumn
);
else {
// find new item in the forms table columns items.
// if exist => continue
// else catch block executs and create new table columns.
try {
const res = this.localMainFormElements[this.currentTab].items.filter(
(item) => item.key == updatedColumn.key
);
if (res.length)
this.mySwalToast({
title: "ستونی با چنین مشخصاتی قبلا ایجاد شده است.",
html: null,
icon: "error",
});
else {
this.localMainFormElements[this.currentTab].items.push(
updatedColumn
);
}
} catch (msg) {
this.localMainFormElements[this.currentTab] = {
items: [updatedColumn],
title: this.formTitleData.title,
};
}
}
},
openChildNewFormItem(parentIndex) {
this.addToChildren = true;
this.parentRowItem =
this.localMainFormElements[this.currentTab].items[parentIndex];
this.childRowItem = undefined;
this.parentRowItemIndex = parentIndex;
this.childRowItemIndex = undefined;
this.$emit("open-new-form-item");
},
childEditNewFormItem(childIndex, parentIndex) {
this.addToChildren = true;
this.parentRowItem =
this.localMainFormElements[this.currentTab].items[parentIndex];
this.childRowItem =
this.localMainFormElements[this.currentTab].items[parentIndex].items[
childIndex
];
this.parentRowItemIndex = parentIndex;
this.childRowItemIndex = childIndex;
this.$emit("open-new-form-item", this.childRowItem);
},
editNewFormItem(index) {
this.addToChildren = false;
this.parentRowItem =
this.localMainFormElements[this.currentTab].items[index];
// this.parentRowItem = index;
this.$emit(
"open-new-form-item",
this.localMainFormElements[this.currentTab].items[index]
);
},
openNewFormItem() {
this.addToChildren = false;
// this.rowItem = {};
this.childRowItem = {};
this.parentRowItem = {};
this.$emit("open-new-form-item");
},
deleteChildItem(childIndex, parentIndex) {
this.mySwalConfirm({
title: "هشدار!!!",
html: "از حذف این مورد مطمئن هستید؟",
}).then((result) => {
if (result.isConfirmed) {
{
this.localMainFormElements[this.currentTab].items[
parentIndex
].items.splice(childIndex, 1);
}
}
});
},
deleteItem(index) {
this.mySwalConfirm({
title: "هشدار!!!",
html: "از حذف این مورد مطمئن هستید؟",
}).then((result) => {
if (result.isConfirmed) {
this.localMainFormElements[this.currentTab].items.splice(index, 1);
}
});
},
},
watch: {
newFormItem: {
handler(newVal) {
if (newVal) this.addFormItemToFormElements(newVal);
},
deep: true,
immediate: true,
},
},
};

View File

@ -0,0 +1,57 @@
{
"dashboard": [
{
"color": 1,
"icon": "Home-21",
"link": "home",
"title": "پیشخوان",
"subMenu": [],
"translateKey": "Dashboard"
}
],
"notifications": [
{
"icon": "Component-285--2",
"color": 3,
"link": "notifications",
"translateKey": "Notifications",
"title": "اعلانات"
}
],
"favorite": [
{
"color": 1,
"icon": "bookmark-1",
"link": "favorites",
"title": "علاقه مندی ها",
"translateKey": "Favorites",
"subMenu": [
{
"color": 5,
"icon": "bookmark-1",
"link": "favorites",
"title": "علامت ها",
"translateKey": "Marks"
},
{
"color": 5,
"icon": "bookmark-1",
"link": "histories",
"title": "تاریخچه",
"translateKey": "History"
}
]
}
],
"pages": [
{
"color": 1,
"icon": "question",
"link": "publicPagesModuleLayout",
"title": "",
"translateKey": "Pages",
"subMenu": []
}
]
}

View File

@ -0,0 +1,55 @@
{
"dashboard": [
{
"color": 1,
"icon": "Home-21",
"link": "home",
"title": "پیشخوان",
"subMenu": [],
"translateKey": "Dashboard"
},
{
"color": 1,
"icon": "layout-sections",
"link": "systems",
"title": "سامانه های من",
"translateKey": "systems",
"subMenu": []
}
],
"notifications": [
{
"icon": "Component-285--2",
"color": 3,
"link": "notifications",
"translateKey": "Notifications",
"title": "اعلانات"
}
],
"favorite": [
{
"color": 1,
"icon": "bookmark-1",
"link": "favorites",
"title": "علاقه مندی ها",
"translateKey": "Favorites",
"subMenu": [
{
"color": 5,
"icon": "bookmark-1",
"link": "favorites",
"title": "علامت ها",
"translateKey": "Marks"
},
{
"color": 5,
"icon": "bookmark-1",
"link": "histories",
"title": "تاریخچه",
"translateKey": "History"
}
]
}
]
}

View File

@ -0,0 +1,71 @@
[
{
"showOutside": true,
"show": true,
"icon": "tavasi tavasi-Component-71--1",
"title": "جزییات",
"to": {
"name": "undefined"
},
"selected": false,
"disabled": false,
"howToOpen": "",
"href": "",
"class": "btn show-detail-btn -rotate-180",
"action": "showDetails",
"can": "forms_show"
},
{
"showOutside": false,
"show": true,
"icon": "default",
"title": "ویرایش",
"to": {
"name": "undefined"
},
"selected": false,
"disabled": false,
"howToOpen": "",
"href": "",
"class": "edit-btn",
"action": "edit-table-item",
"can": "forms_edit"
},
{
"showOutside": false,
"show": true,
"icon": "default",
"title": "حذف",
"to": {
"name": "undefined"
},
"selected": false,
"disabled": false,
"howToOpen": "",
"href": "",
"class": "delete-btn",
"action": "delete-table-item",
"can": "forms_delete"
},
{
"showOutside": false,
"show": true,
"icon": "default",
"title": "ستون های فهرست",
"to": {
"name": "undefined"
},
"selected": false,
"disabled": false,
"howToOpen": "",
"href": "",
"class": "",
"action": "select-list-columns",
"can": "form_select-list-columns"
}
]

View File

@ -0,0 +1,34 @@
[
{
"showOutside": true,
"show": true,
"icon": "tavasi tavasi-Component-242--1",
"title": "ویرایش",
"to": {
"name": "undefined"
},
"selected": false,
"disabled": false,
"howToOpen": "",
"href": "",
"class": "",
"action": "edit-table-item",
"can": ""
},
{
"showOutside": true,
"show": true,
"icon": "tavasi tavasi-Component-295--1",
"title": "حذف",
"to": {
"name": "undefined"
},
"selected": false,
"disabled": false,
"howToOpen": "",
"href": "",
"class": "",
"action": "delete-table-item",
"can": ""
}
]

View File

@ -0,0 +1,36 @@
[
{
"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",
"can": ""
},
{
"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",
"can": ""
}
]

View File

@ -0,0 +1,17 @@
<script setup>
import { clearBodyClass } from "@manuals/utilities";
onMounted(() => {
clearBodyClass();
});
onUnmounted(() => {
clearBodyClass();
});
</script>
<template>
<main class="h-full">
<slot name="named-slot"></slot>
<slot></slot>
</main>
</template>

View File

@ -1,183 +0,0 @@
<template>
<div>
<div class="jahat__sidebar scroll-needed">
<ul class="sidebar-menu sidebar-menu--simple">
<li>
<router-link :to="{name:'issues'}" class="text__14">مسائل جدید</router-link>
</li>
<li>
<router-link :to="{name:'issues'}" class="text__14">مسائل مرتبط</router-link>
</li>
<li>
<router-link :to="{name:'issues'}" class="text__14">مسائل پیشنهادی</router-link>
</li>
<li>
<router-link :to="{name:'issues'}" class="text__14">مسائل کلان</router-link>
</li>
<li>
<router-link :to="{name:'issues'}" class="text__14">ایده ها</router-link>
</li>
<li>
<router-link :to="{name:'issues'}" class="text__14">مسائل حل شده</router-link>
</li>
</ul>
</div>
<div class="jahat__content-container">
<div class="jahat__content">
<div class="dashboard">
<div class="my-profile__container" style="position: relative">
<div class="my-profile">
<div class="my-profile__form">
<form action="">
<div class="form-row">
<label for="">نام</label>
<input type="text" placeholder="کاظم" />
</div>
<div class="form-row">
<label for="">نام خانوادگی</label>
<input type="text" placeholder="رحیمی" />
</div>
<div class="form-row">
<label for="">تلفن همراه</label>
<input type="text" placeholder="۰۹۱۹۲۵۱۳۰۱۱" />
</div>
<div class="form-row">
<label for="">نام کاربری</label>
<input type="text" placeholder="@rahim_arbab" />
</div>
<div class="form-row">
<label for="">پست الکترونیک</label>
<input type="text" placeholder="rahimearbab@gmail.com" />
</div>
<div class="border"></div>
<div class="text text__gray">اطلاعات بیشتر <span>( موارد را با ویرگول «،» جدا کنید )</span></div>
<div class="form-row form-row--text-area">
<label for="">تخصص ها</label>
<!-- <textarea v-model="user_properties.skills.value" cols="30" rows="10" placeholder="مهارتها و تخصصهای علمی"></textarea> -->
<!-- <textarea v-model="userInfo.skills.value" cols="30" rows="10" placeholder="مهارتها و تخصصهای علمی"></textarea> -->
<vue-select dir="rtl" multiple taggable v-model="userInfo.skills.value" :options="skills"></vue-select>
</div>
<div class="form-row form-row--text-area">
<label for="">علاقمندی ها</label>
<vue-select dir="rtl" multiple taggable v-model="userInfo.favorites.value" :options="favorites" ></vue-select>
<!-- <textarea v-model="userInfo.favorites.value" cols="30" rows="10" placeholder="موضوعات مورد علاقه ( دغدغه شما )"></textarea> -->
</div>
<div class="popUp-tab__buttons px-0">
<a href="javascript:void(0)" class="popUp-tab__submit" @click="saveUserInfo()">ثبت</a>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex';
import {GET_PERSONAL_INFO} from "../../../store/modules/profile.module";
export default {
name: "Dashboard",
data(){
return{
user_properties:{
skills:{
id: 2,
value: '',
},
favorites:{
id: 1,
value: ''
}
},
errors: {},
skills: [],
favorites: []
}
},
computed: {
...mapState(['currentUserPersonalInfo']),
userInfo(){
let userInfo = this.currentUserPersonalInfo;
let user_properties = this.user_properties;
if(userInfo && userInfo.properties && Object.keys(userInfo.properties).length > 0){
let skills = [];
let favorites = [];
if(userInfo.properties.skills.length > 0){
userInfo.properties.skills.forEach((skill) => {
skills.push({id: skill.values.id, label: skill.values.title});
});
}
if(userInfo.properties.favorites.length > 0){
userInfo.properties.favorites.forEach((favorite) => {
favorites.push({id: favorite.values.id, label: favorite.values.title});
});
}
user_properties.skills.value = skills;
user_properties.favorites.value = favorites;
}
return user_properties;
}
},
methods: {
...mapActions([ 'checkPermissions', 'SAVE_USER_PROPERTIES', 'GET_PERSONAL_INFO']),
saveUserInfo(){
let data = {...this.user_properties};
let self = this;
this.SAVE_USER_PROPERTIES(data).then(response => {
}).catch(errors => {
self.errors = errors.data.errors;
});
},
getProfileData(){
let self = this;
ApiService.get(
null,
"profile/skills-favorites",
function(response) {
response.data.favorites.forEach(item => {
let data = {
id: item.id,
label: item.title
}
self.favorites.push(data);
});
response.data.skills.forEach(item => {
let data = {
id: item.id,
label: item.title
}
self.skills.push(data);
});
},
function() {
}
);
}
},
mounted(){
this.GET_PERSONAL_INFO();
this.getProfileData();
// this.checkPermissions({ permission: "", _this: this })
}
};
</script>

View File

@ -1,356 +0,0 @@
<template>
<div>
<div
:class="mode == 1 ? 'jahat__content_list' : 'jahat__content-container'"
>
<div class="jahat__content">
<div class="search-list firefox-scrollbar">
<filter-list
v-if="subjectFilters.size"
:filters="subjectFilters.values()"
@remove-filter="removeFromFilters"
></filter-list>
<filter-list
v-if="subjectFilters.size"
:filters="creationFilters.values()"
@remove-filter="removeFromFilters"
></filter-list>
<div
v-for="(entity, index) in entities"
:key="index"
class="search-list__item"
>
<div class="search-list__content">
<div class="search-list__header">
<span
:disabled="true"
:to="{ name: 'issues' }"
class="label text__14"
>{{ getEntityName(entity._source.type_id) }}</span
>
<a
href="javascript:void(0)"
@click.prevent="routeTo(entity)"
class="search-list__title text__16"
v-html="getTitle(entity)"
>
</a>
<!-- <router-link
:title="entity._source.title"
:to="{
name: 'issuesShow',
params: { id: entity._source.id,parentRouteName:$route.name },
}"
class="search-list__title text__16"
>
{{ entity._source.title }}
</router-link> -->
</div>
<div class="search-list__meta">
<!-- <div class="search-list__sub-item text__14">با {{ entity.sub_issue_count ? entity.sub_issue_count : 0 }}
زیر مساله، با {{ entity.responses_count ? entity.responses_count : 0 }} پاسخ
</div> -->
<!-- <div class="search-list__sub-item text__14" v-if="entity.criterions && entity.criterions.length > 0">
<span> معیارها : </span>
<span class="text__semibold"> {{ (entity.criterions && entity.criterions.length > 0) ? entity.criterions[0].value_json.text : '' }}</span>
</div> -->
</div>
<div
v-if="entity._source?.favorite"
class="search-list__content text__14 text__gray"
v-html="getText(entity).unfavoriteText"
></div>
<div
v-if="entity._source?.unfavorite"
class="search-list__content text__14 text__gray"
v-html="getText(entity).text"
></div>
<div
v-if="entity._source.subject && entity._source.subject.length"
class="search-list__content text__14 text__gray"
>
<span :disabled="true" class="text__16 text__blue"
>موضوع :
</span>
<a
v-for="(subject, index) in entity._source.subject"
:key="index"
href="javascript:void(0)"
@click.prevent="addToFilters(subject)"
class="search-list__title text__16"
>
{{ subject.title }}،
</a>
</div>
<div class="search-item__actions" v-if="showActions">
<span class="tavasi tavasi-more-vert"></span>
<!-- v-can="$route.name + '_subject'" -->
<button
v-can="$route.name + '_subject'"
@click="$emit('open-subject-modal', entity)"
title="موضوع زنی"
class="btn show-detail-btn px-1"
type="button"
>
<span class="tavasi tavasi-doc-outline"></span>
</button>
<button
v-can="$route.name + '_update'"
@click="$emit('edit-entity', entity)"
title="ویرایش مسئله"
class="btn show-detail-btn px-1"
type="button"
>
<span class="tavasi tavasi-Component-242--1"></span>
</button>
<button
v-can="$route.name + '_delete'"
@click="$emit('delete-entity', entity)"
title="حذف"
class="btn show-detail-btn px-1"
type="button"
>
<span class="tavasi tavasi-Component-295--1"></span>
</button>
<button-component
title=" کپی لینک مساله"
buttonText=""
class="btn show-detail-btn px-1"
@click="copyToClipboard(entity._source.id)"
>
<svg class="icon icon-copy2 fz-8">
<use xlink:href="#icon-copy2"></use>
</svg>
</button-component>
</div>
</div>
</div>
</div>
<div class="paginations">
<!-- <jahat-pagination
:paginationInfo="paginationInfo"
@page-changed="pageChanged"
@page-limit-changed="pageLimitChanged"
>
</jahat-pagination> -->
</div>
</div>
</div>
</div>
</template>
<script>
import { commonMixin } from "~/jahat/mixins/commonMixin";
// import { apiMixin } from "~/jahat/mixins/apiMixin";
import { mapState } from "pinia";
export default {
name: "EntityContent",
mixins: [commonMixin],
mounted() {
this.pagination = this.paginationInfo;
},
data() {
return {
pagination: {
page: 1,
pages: 0,
total: 0,
offset: 0, // page * per_page
limit: 10, //per_page
},
maxlenText: 300,
};
},
props: {
subjectFilters: { type: Map, default: () => new Map() },
creationFilters: { type: Map, default: () => new Map() },
entities: { type: Array, default: () => [] },
paginationInfo: { default: () => {} },
mode: { type: Number, default: 1 },
},
computed: {
...mapState(["userPermisionGetter"]),
showActions() {
const canUpdate = this.userPermisionGetter?.includes(
this.$route.name + "_update"
);
const canDelete = this.userPermisionGetter?.includes(
this.$route.name + "_delete"
);
const canSubject = this.userPermisionGetter?.includes(
this.$route.name + "_subject"
);
const canCopy = true;
return canUpdate || canDelete || canSubject || canCopy;
},
},
methods: {
pageLimitChanged(paging) {
this.$emit("pageLimitChanged", paging);
},
pageChanged(paging) {
this.$emit("pageChanged", paging);
},
sortChanged(sorting) {
this.$emit("sortChanged", sorting);
},
resetPagination() {
this.$emit("resetPagination", sorting);
},
addToFilters(filter) {
this.$emit("add-filter", filter);
},
removeFromFilters(filter) {
this.$emit("remove-filter", filter);
},
routeTo(entity) {
this.$emit("close");
let url = "";
if (entity._source.type_id == this.getEntityTypeId("issue")) {
url = "issuesShow";
this.$router.push({
name: url,
params: {
id: entity._source.id,
parentRouteName: this.$router.name,
},
});
} else if (entity._source.type_id == this.getEntityTypeId("answer")) {
url = "answersShow";
this.$router.push({
name: url,
params: {
entityId: entity._source.entities.entity_id,
// parentRouteName: this.$router.name,
answerId: entity._source.id,
},
});
} else if (entity._source.type_id == this.getEntityTypeId("crition")) {
url = "critionsShow";
this.$router.push({
name: url,
params: {
id: entity._source.id,
parentRouteName: this.$router.name,
critionId: entity._source.id,
},
});
}
},
getTitle(entity) {
if (entity._source.type_id == this.getEntityTypeId("issue"))
return entity._source.title;
else if (
entity._source.type_id == this.getEntityTypeId("answer") &&
entity._source.entities
) {
if (Array.isArray(entity._source.entities))
return entity._source.entities[0]?.entity_title;
else return entity._source.entities.entity_title;
}
return entity._source.title;
},
getText(entity) {
let text = "";
let unfavoriteText = "";
if (entity._source.type_id == this.getEntityTypeId("issue")) {
if (entity._source.summary) text = entity._source.summary;
else text = entity._source.description;
}
if (entity._source.type_id == this.getEntityTypeId("crition")) {
if (entity._source.favorite)
text = "مطلوب : " + entity._source.favorite;
if (entity._source.unfavorite)
unfavoriteText = "\n" + "نامطلوب : " + entity._source.unfavorite;
}
if (
(text == "" ||
entity._source.type_id == this.getEntityTypeId("answer")) &&
entity._source.summary
)
text = entity._source.summary;
if (text == "" && entity._source.summary) text = entity._source.summary;
if (text == "" && entity._source.description)
text = entity._source.description;
text =
text?.length > this.maxlenText
? text.substr(0, this.maxlenText) + "..."
: text;
return {
text,
unfavoriteText,
};
},
},
};
</script>
<style lang="scss" scoped>
.search-list__item {
position: relative;
padding: 1em;
overflow: hidden;
&:not(:last-child) {
margin-bottom: 30px;
}
&:hover,
&.active {
background-color: #e8fcff;
.search-item__actions {
// width: 6.5em;
width: auto;
transition: width 0.5s;
background: #fff;
border-radius: 0 0.5em 0.5em 0;
.tavasi-more-vert {
transition: all 0.2s;
display: none;
}
}
}
}
.search-item__actions {
position: absolute;
left: 0;
width: 1.6em;
top: 1em;
// overflow: hidden;
transition: all 0.5s;
display: flex;
align-items: center;
.btn {
display: flex;
align-items: center;
justify-content: center;
&:hover {
filter: brightness(0.7);
}
.tavasi,
.icon-copy2 {
color: #adbec4;
}
.icon-copy2 {
font-size: 0.8rem;
}
}
}
</style>

View File

@ -1,656 +0,0 @@
<template>
<!-- <div style="height: 100vh; overflow: auto"> -->
<div>
<!-- <button
class="filters__open-btn--top btn buttonshow"
id="buttonshow"
@click="showfilter"
>
<svg
data-v-46e9fe5b=""
data-testid="chevron-double-lg-left-icon"
class="s12 icon-chevron-double-lg-left"
>
<use
data-v-46e9fe5b=""
href="/assets/img/icons.d6ff8c17.svg#chevron-double-lg-left"
></use>
</svg>
</button> -->
<div class="button-change">
<switch-component
@change-mode="topRepeatInListMode = !topRepeatInListMode"
name="top-repeat"
></switch-component>
<!-- "critions" -->
<div
v-if="entity_type != getEntityTypeId('answer')"
class="record-problem"
>
<a
v-can="'issues_create'"
title="ثبت مساله"
href="ثبت مساله"
class="text__14 text__blue button"
@click.prevent="openIssueModal"
>ثبت {{ getEntityName(entity_type) }}</a
>
</div>
</div>
<div v-if="topRepeatInListMode">
<div
ref="filterdiv"
class="jahat__sidebar scroll-needed hide"
id="showDiv"
:class="{ expanded: !isSidebarCollapsed }"
>
<ul class="sidebar-menu sidebar-menu--simple buttonhide">
<li>
<a
href="javascript:void(0)"
@click.prevent="updateListSpecial(1)"
class="text__14"
>{{ entitiesTitle }} جدید</a
>
</li>
<li>
<a
href="javascript:void(0)"
@click.prevent="updateListSpecial(2)"
class="text__14"
>{{ entitiesTitle }} ویرایشی</a
>
</li>
<li>
<a
href="javascript:void(0)"
@click.prevent="updateListSpecial(3)"
class="text__14"
>{{ entitiesTitle }} تولیدی من</a
>
</li>
<li>
<a
href="javascript:void(0)"
@click.prevent="updateListSpecial(4)"
class="text__14"
>{{ entitiesTitle }} مشارکتی من</a
>
</li>
<button
type="bu"
@click.prevent="hidefilter"
class="text__14 btn btnHide"
id="btnHide"
>
<svg
data-v-46e9fe5b=""
data-testid="chevron-double-lg-left-icon"
class="s12 icon-chevron-double-lg-left"
>
<use
data-v-46e9fe5b=""
href="/assets/img/icons.d6ff8c17.svg#chevron-double-lg-left"
></use>
</svg>
&nbsp; بستن
</button>
</ul>
</div>
<div
class="jahat__content-container"
:class="{ expanded: !isSidebarCollapsed }"
>
<!-- <div
v-if="entity_type == getEntityTypeId('issue')"
class="jahat__fixed-btn"
>
<a
v-can="'issues_create'"
title="ثبت مساله"
href="ثبت مساله"
class="text__14 text__blue button"
@click.prevent="openIssueModal"
>ثبت مساله</a
>
</div> -->
<the-content-loading v-if="fetchingData"></the-content-loading>
<div v-if="canView">
<div v-if="!fetchingData">
<EntityContent
v-if="pagination.total"
:creationFilters="creationFilters"
:subjectFilters="subjectFilters"
@add-filter="updateListAfterFilterAdded"
@remove-filter="updateListAfterFilterRemoved"
@delete-entity="deleteEntity"
@edit-entity="editEntity"
@open-subject-modal="openSubjectModal"
:type="listType"
:entities="listEntity"
class="entity-content"
:class="{ 'chart-and-list-mode': topRepeatInListMode }"
/>
<no-data v-else>
<p class="text-center p-3">مسئله ای ثبت نشده است.</p>
</no-data>
</div>
</div>
<no-data v-else>
<p class="text-center p-3">
<span class="tavasi tavasi-warning-circle"></span>
عدم دسترسی
</p>
</no-data>
<jahat-pagination
v-if="pagination.total"
:paginationInfo="pagination"
@page-changed="pageChanged"
@page-limit-changed="pageLimitChanged"
@sort-changed="sortChanged"
>
</jahat-pagination>
<jahat-modal
@close-modal="closeModal"
:showHeaderCloseButton="true"
v-if="showModal"
title="ایجاد مسئله"
>
<problem-modal
v-if="showIssueModal"
:data="entity"
@close-modal="closeModal"
@problem-added="closeModal"
>
</problem-modal>
<subject-form
v-if="showSubjectModal"
@update-list="closeModal"
@delete-item="updateListSpecial"
projectTagsName="jahat"
></subject-form>
</jahat-modal>
</div>
</div>
<div v-else>
<ChartContent
:class="{ 'chart-and-list-mode': topRepeatInListMode }"
class="ChartContent"
></ChartContent>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from "pinia";
import { entityMixin } from "~/jahat/mixins/entityMixin";
import { commonMixin } from "~/jahat/mixins/commonMixin";
import repoApi from "~/apis/repoApi";
// import { propertyModalMixin } from "~/jahat/mixins/propertyModalMixin";
export default {
mixins: [entityMixin, commonMixin],
mounted() {
this.checkPermissions({
permission: `${this.$route.name}_list`,
_this: this,
})
.then(() => {
this.entity_type =
this.$route.meta.entityType === undefined
? 1
: this.$route.meta.entityType;
this.entitiesTitle = this.getEntityTitle(this.entity_type);
this.getList(this.entity_type);
this.canView = true;
})
.catch(() => {
this.canView = false;
});
},
watch: {
$route: {
handler(newRoute, oldRoute) {
this.checkPermissions({
permission: `${newRoute.name}_list`,
_this: this,
})
.then(() => {
this.entity_type =
this.$route.meta.entityType === undefined
? 1
: this.$route.meta.entityType;
this.entitiesTitle = this.getEntityTitle(this.entity_type);
if (oldRoute.name != newRoute.name) {
newRoute.query.page = undefined;
history.pushState({}, document.title, newRoute.path);
// this.$router.replace({ query: {...this.$route.query, page: undefined}})
this.resetPagination();
}
this.fetchingData = false;
this.getList(this.entity_type);
this.canView = true;
})
.catch(() => {
this.canView = false;
});
},
nested: true,
// immediate: true,
},
},
data() {
return {
topRepeatInListMode: true,
subjectFilters: new Map(),
creationFilters: new Map(),
showSubjectModal: false,
showIssueModal: false,
canView: true,
// modal: "answer-modal",
entity_type: 1,
entitiesTitle: "مسائل",
listType: 1,
listEntity: [],
entity: {},
modal: undefined,
modal_title: null,
modal_data: {
entity: {},
keyName: "",
index: -1,
},
showfilters: 2,
};
},
computed: {
...mapState(["schemasGetter", "isSidebarCollapsed"]),
},
methods: {
...mapActions(["checkPermissions"]),
...mapActions("list", [
"SET_SELECTED_PROJECT",
"SET_LIST_ID",
"SET_LIST",
"SET_SELECTED_ITEM",
]),
//mehdi
showfilter() {
this.$refs.filterdiv.classList.add("show");
this.$refs.filterdiv.classList.remove("hide");
document.getElementById("buttonshow").style.display = "none";
document.getElementById("btnHide").style.display = "inline-block";
// document.getElementById("showDiv").style.display = "inline-block";
},
hidefilter() {
this.$refs.filterdiv.classList.remove("show");
this.$refs.filterdiv.classList.add("hide");
document.getElementById("buttonshow").style.display = "inline-block";
document.getElementById("btnHide").style.display = "none";
},
//mehdi
openSubjectModal(entity) {
this.showSubjectModal = true;
this.entity = entity._source;
this.SET_SELECTED_ITEM(this.entity);
this.beforeShowModal();
},
openIssueModal() {
this.showIssueModal = true;
this.entity = {
title: "",
description: "",
// weight: 0,
};
// console.log(this.entity);
this.beforeShowModal();
},
deleteEntity(entity) {
this.mySwalConfirm({
title: "هشدار!!!",
html: `از حذف این مورد اطمینان دارید؟ `,
icon: "warning",
}).then((result) => {
setTimeout(() => {
this.updateListSpecial(1);
}, 1000);
if (result.isConfirmed) {
let url = repoApi.entity.delete_jahat;
url = url.replace("{{entity_id}}", entity._id);
this.httpService
.postRequest(url)
.then((res) => {
this.getList(this.entity_type);
this.mySwalToast({
html: res.data.message,
icon: "success",
});
// this.getListSpecial(this.entity_type, this.listType);
// this.updateListSpecial()
})
.catch((err) => {
// this.mySwalToast({
// title: "خطا!!!",
// html: err.message,
// icon: "error",
// });
});
}
});
},
editEntity(entity) {
this.showIssueModal = true;
this.entity = entity._source;
this.beforeShowModal();
},
openModal(modal, property = null, index = -1) {
this.modal = modal;
// this.modal_data.entity = this.entity;
// this.modal_data.index = index;
// this.modal_data.keyName = property;
// this.modal_title = ev.target?.title ?? 'بدون عنوان';
this.beforeShowModal();
},
beforeShowModal() {
this.showModal = true;
setTimeout(() => {
$("#jahat-modal").modal(
{ backdrop: "static", keyboard: false },
"show"
);
}, 500);
},
closeModal() {
$("#jahat-modal").modal("hide");
setTimeout(() => {
this.showModal = false;
this.showSubjectModal = false;
this.showIssueModal = false;
this.updateListSpecial(1);
}, 500);
},
updateListAfterFilterAdded(filter, filterObject = "subjectFilters") {
if (!this[filterObject].has(filter.id)) {
this[filterObject].set(filter.id, filter);
this.getList(this.entity_type);
}
this.updateListSpecial();
},
updateListAfterFilterRemoved(filter, filterObject = "subjectFilters") {
if (this[filterObject].has(filter.id)) {
this[filterObject].delete(filter.id);
this.getList(this.entity_type);
}
},
updateListSpecial(listType = 0) {
this.listType = listType;
if (listType == 0) this.getList(this.entity_type);
else this.getListSpecial(this.entity_type, listType);
},
// addToList(input) {
// let e = {};
// e._source = { ...input.item };
// this.listEntity.unshift(e);
// this.paginationInfo.total += 1;
// },
},
};
</script>
<style scoped lang="scss">
.showBtn {
display: none;
}
.btn-hide {
display: none;
}
.jahat__sidebar {
top: 55px;
padding-right: 100px;
}
.btnHide {
display: none;
}
.btnHide svg {
transform: rotate(180deg);
}
.jahat__fixed-btn {
// top: calc(var(--headerHeight) + 7px);
// left: 8em
}
.button-change {
left: 1em;
width: 100%;
height: 40px;
position: absolute;
top: 6em;
display: flex;
justify-content: flex-end;
align-items: center;
// margin-top: 0rem;
// z-index: 9;
// background-color: white;
// padding: 2rem;
div {
margin: 0 10px;
}
}
@media only screen and (min-width: 768px) and (max-width: 991.98px) {
.buttonshow {
position: fixed;
color: inherit;
right: 5px;
top: 65px;
width: 50px;
height: 50px;
z-index: 999999;
}
.btnHide {
position: absolute;
display: inline-block;
left: 0px;
}
.btnHide svg {
transform: rotate(180deg);
}
.m1 {
background-color: red;
}
.hide {
transform: translateX(80%);
display: none;
}
.show {
transform: translateX(0);
}
#showDiv {
top: 55px;
}
.titelAnswerText {
max-width: 150px;
}
}
@media only screen and (min-width: 576px) and (max-width: 767.98px) {
.buttonshow {
position: fixed;
color: inherit;
right: 5px;
top: 65px;
width: 50px;
height: 50px;
z-index: 999999;
}
.btnHide {
position: absolute;
display: inline-block;
left: 0px;
}
.btnHide svg {
transform: rotate(180deg);
}
.hide {
transform: translateX(80%);
display: none;
}
.show {
transform: translateX(0);
}
#showDiv {
top: 55px;
}
.titelAnswerText {
max-width: 150px;
}
}
@media (max-width: 575.98px) {
.button-change {
left: 0em;
top: 8em;
}
.buttonshow {
position: fixed;
color: inherit;
right: 5px;
top: 95px;
width: 50px;
height: 50px;
z-index: 999999;
}
.button-change {
margin-top: 2rem;
}
.btnHide {
position: absolute;
display: inline-block;
left: 0px;
}
.m1 {
background-color: red;
}
.hide {
display: none;
}
.show {
transform: translateX(0);
}
#showDiv {
top: 95px;
}
.titelAnswer {
display: none;
}
.jahat-header__pagination {
top: 0px !important;
position: relative !important ;
}
.jahat__sidebar {
top: 108px !important;
}
}
</style>
<!-- <style lang="scss">
// @media only screen and (max-width: 575.98px) {
// .jahat__content-container {
// .problem-detail {
// .problem-detail__section {
// .problem-slider {
// .flickity {
// .flickity-viewport {
// .flickity-slider {
// // .jahat-system .problem-slider__cell {
// // width: 100% !important;
// // }
// // .jahat-system .problem-files--answer .problem-files__cell {
// // width: 100% !important;
// // }
// // .flickity-slider .problem-files__cell .is-selected {
// // width: 100% !important;
// // }
// .problem-slider__cell{
// width: 100%;
// }
// .problem-files__cell {
// width: 100% !important;
// // height: 170px;
// }
// .problem-slider__pic {
// img {
// width: 95%;
// }
// }
// }
// }
// }
// }
// .problem-section__content{
// .problem-files{
// .flickity {
// .flickity-viewport {
// .flickity-slider {
// .problem-slider__cell{
// width: 100%;
// }
// .problem-files__cell {
// width: 100% !important;
// // height: 170px;
// }
// .problem-slider__pic {
// img {
// width: 95%;
// }
// }
// }
// }
// }
// }
// }
// }
// }
// }
// }
</style> -->

View File

@ -1,17 +0,0 @@
<template>
<div class="main-container flex-grow-1">
404
</div>
</template>
<script>
export default {
name: "Error-1",
computed: {
backgroundImage() {
return import.meta.env.BASE_URL + `${fileUrl()}error/bg1.jpg`;
}
}
};
</script>

View File

@ -1,39 +0,0 @@
<template>
<div>
<router-view />
</div>
</template>
<script>
import { mapState, mapActions } from "pinia";
export default {
name: "Layout",
data() {
return {
username: "",
password: ""
};
},
methods: {
// ...mapActions("jahat",['GET_PROBLEMS'])
},
computed: {
...mapState(["layoutConfig"]),
getFooterDesc() {
return this.layoutConfig("footer_desc");
},
footerDisplay() {
return !!this.layoutConfig("footer.display");
}
},
beforeMount() {
// this.$store.dispatch(ADD_BODY_CLASSNAME, "page-loading");
// HtmlClass.init(this.layoutConfig());
},
mounted() {
// this.GET_PROBLEMS({vm:this});
}
};
</script>

View File

@ -1,64 +0,0 @@
<template>
<div
class="jahat__header jahat-header"
:class="{ expanded: !isSidebarCollapsed }"
>
<div
class="jahat-header__right jahat-header__logo"
style="padding-right: 35px"
>
<router-link :to="{ name: 'issues' }" class="">
<img
class="d-xl-inline"
src="assets/jahat/img/jahat-logo.svg"
alt=""
/>
</router-link>
</div>
<div class="jahat-header__center">
<NavbarActiveLink
class="jahat-header__menu"
:items="schemasGetter"
:routeTempalte="{
firstActive: false,
activate: 'route',
key: 'routename',
template: '/{{key}}',
}"
@change-link="changeLink"
/>
<router-link :to="{ name: 'search' }" class="jahat-header__search-icon">
<svg class="icon icon-Component-198--1">
<use xlink:href="#icon-Component-198--1"></use>
</svg>
</router-link>
</div>
<div class="jahat-header__left">
<user-avatar-dropdown class="header__user" />
</div>
</div>
</template>
<script>
import NavbarActiveLink from "../../../components/LazyNavbarActiveLink.vue";
import { mapState } from "pinia";
export default {
name: "TopHeader",
computed: {
...mapState([
"userPermisionGetter",
"schemasGetter",
"isSidebarCollapsed",
]),
},
methods: {
canViewMenuItem(permission) {
return this.userPermisionGetter?.includes(permission);
},
changeLink(key) {},
},
};
</script>
<style scoped></style>

View File

@ -1,766 +0,0 @@
<template>
<div class="m1 main-page">
<div v-if="showMainpag">
<div class="home-list p-3 m2" ref="myInput3" id="main">
<div class="row mt-1">
<Breadcrumbs
class="m-start mt-2 Breadcrumbs"
style="font-size: 12px"
/>
</div>
<div class="row mt-2">
<div
class="col-md-12 col-sm-12 d-flex"
style="justify-content: space-around"
>
<button
v-if="listGetter && listGetter.length"
:class="{ 'text-primary borderBottom': showNavigation }"
type="button"
class="popUp-tab__clear btn"
style="font-size: 12px"
@click.prevent="showNavigation = true"
>
پیمایش
</button>
<button
:class="{ 'text-primary borderBottom': !showNavigation }"
type="button"
class="popUp-tab__clear btn"
@click.prevent="showNavigation = false"
style="margin-right: -20px; font-size: 12px"
>
فهرست
</button>
<button
title="بستن"
@click="showPanel()"
type="button"
class="popUp-tab__clear btn"
style="margin-right: -20px"
>
<span class="tavasi tavasi-Component-21--1"></span>
</button>
</div>
</div>
<hr />
<div class="row" style="margin-top: 1.25rem !important">
<div class="col-md-12">
<div v-if="listGetter && listGetter.length">
<div v-if="showNavigation">
<div class="navigation">
<div
v-if="listGetter"
v-for="(item, key) in listGetter"
:key="key"
class="item"
:class="{ Active: activeItemClass(item) }"
>
<div
class="d-flex position-relative text-10 mt-2 item-navigation"
>
<a
@click.prevent="showtext(item, key)"
:href="item.branch"
class=""
:title="item.branch"
style="
font-size: 12px;
text-decoration: none;
color: black;
"
>
<i class="tavasi tavasi-Component-149--3 ml-1"></i>
{{ item.title }}
</a>
</div>
</div>
<!-- <div
v-for="(item, index, key) in items"
:id="item.id"
:key="item.id"
class="item"
>
<div
class="d-flex position-relative text-10 mt-2"
:class="{
'is-selected': item.active ?? false,
}"
>
<a
:class="{ active: item.active ?? false }"
@click.prevent="showParagraphs(item, index, key)"
:href="item.title"
class="title"
:title="item.title"
style="font-size: 12px; text-decoration: none"
>
<i class="tavasi tavasi-Component-149--3 ml-1"></i>
{{ item.title }}
</a>
</div>
</div> -->
</div>
</div>
<div v-else>
<div class="navigation mt-3" style="max-height: 230px">
<div
class="text-truncate"
style="max-width: 200px; font-size: 12px"
v-html="textlists"
></div>
</div>
</div>
</div>
<div v-else>
<div class="navigation mt-3" style="max-height: 230px">
<div
class="text-truncate"
style="max-width: 200px; font-size: 12px"
v-html="textlists"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- <div v-else>
<button @click="showpag=true">
<span class="tavasi tavasi-menu"></span>
</button>
</div> -->
<div v-else>
<div class="button-show">
<div class="button-main">
<button @click="showfilter()">
<span class="tavasi tavasi-Component-158--5"></span>
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from "pinia";
import apis from "~/apis/listApi";
export default {
props: {
listPanelUrl: {
default: "",
},
},
emits: ["show-paragraph"],
mounted() {
// this.getListItem();
this.listMindex();
this.list();
},
data() {
return {
id: this.$route.params.id,
searchText: this.$route.params.searchtext,
statuspag: 1,
showpag: true,
showMainpag: true,
showNavigation: true,
prevActiveIndex: 0,
loading: false,
fetchingData: false,
items: [],
lists: "",
textlists: "",
// pagination: {
// pages: 0,
// total: 0,
// page: 1,
// offset: 0, // page * per_page
// limit: 50, //per_page
// },
};
},
computed: {
...mapState(["isSidebarCollapsed"]),
...mapState("list", [
"selectedProjectGetter",
"listIdGetter",
"selectedItemGetter",
"listGetter",
]),
},
watch: {
selectedItemGetter(newVal) {
this.listMindex();
},
},
methods: {
...mapActions(["sidebarCollapsedSetter"]),
...mapActions("list", [
"SET_IS_RETURN_FROM_ITEM_SHOW_PAGE",
"SET_SELECTED_ITEM",
"SET_LIST",
]),
activeItemClass(item) {
if (item.id_store || item._id)
return item.id_store == this.id || item._id == this.id;
},
//newMehdi
list() {
const storedList = localStorage.getItem("myList");
if (storedList) {
const myList = JSON.parse(storedList);
this.SET_LIST(myList);
} else {
console.log("No list found in localStorage.");
}
},
showtext(item, key) {
// let items = this.listGetter[key].mindex;
// let cloneItem = structuredClone(item);
// cloneItem = { ...item,mindex:items};
// this.SET_SELECTED_ITEM(cloneItem);
this.SET_SELECTED_ITEM(item);
this.appendclass();
},
appendclass() {
const listItems = document.querySelectorAll(".item");
listItems.forEach(function (item) {
item.addEventListener("click", function () {
// حذف کلاس "active" از همه المانهای لیست
listItems.forEach(function (item) {
item.classList.remove("Active");
});
// اضافه کردن کلاس "active" به المانی که کاربر بر روی آن کلیک کرده است
this.classList.add("Active");
});
});
},
//newMehdi
getHighlight(text) {
if (window.location.href.includes("search")) {
var words = this.searchText.split(" ");
var index = 1;
words.forEach((w) => {
if (w == "" || w == " ") {
return;
}
let classname = `searchHilight${index}`;
text = text.replaceAll(
w,
"<span class='" + classname + "'>" + w + "</span>"
);
var w1 = this.normalize(w);
if (w1 != w) {
text = text.replaceAll(
w1,
"<span class='" + classname + "'>" + w1 + "</span>"
);
}
index = index + 1;
if (index > 5) index = 1;
});
return text;
} else {
return;
}
},
normalize(item) {
item = item.replaceAll("،", "");
item = item.replaceAll(":", "");
item = item.replaceAll(".", "");
item = item.replaceAll("ک", "ك");
item = item.replaceAll("ی", "ي");
item = item.replaceAll("إ", "ا");
item = item.replaceAll("أ", "ا");
item = item.replaceAll("آ", "ا");
item = item.replaceAll("ة", "ت");
return item;
},
// mehdi
showPanel() {
// this.$emit("hide-panel");
this.$emit("statusPagTest1", (this.statuspag = 2));
this.showMainpag = false;
// this.showpag= false;
},
showfilter() {
this.$emit("statusPagTest1", (this.statuspag = 1));
// this.$refs.myInput3.classList.remove("d-md-none");
// document.getElementById("main").classList.toggle("d-main-none");
// document.getElementById("main").style.display = "inline-block";
this.showMainpag = true;
},
listMindex(key) {
if (this.selectedItemGetter !== undefined) {
if (window.location.href.includes("search")) {
var list = this.getHighlight(this.selectedItemGetter.mindex).split(
"\n"
);
var tt = "";
list.forEach((list) => {
tt = tt + "<p>" + list + "</p>";
});
this.textlists = tt;
} else {
var list = this.selectedItemGetter.mindex.split("\n");
var tt = "";
list.forEach((list) => {
tt = tt + "<p>" + list + "</p>";
});
this.textlists = tt;
}
}
},
// showfilter() {
// this.$ref.myInput.classList.remove("hide");
// this.showpag1=true
// },
// hidefilter() {
// this.$ref.myInput.classList.add("hide");
// this.showpag1=false
// },
// mehdi
showParagraphs(item, index) {
this.$emit("show-paragraph", item);
this.$set(this.items[this.prevActiveIndex], "active", false);
this.$set(this.items[index], "active", true);
this.prevActiveIndex = index;
},
showParagraphs1(item, key) {
this.$emit("show-paragraph1", item);
},
// getListItem() {
// if (this.fetchingData) return;
// this.fetchingData = true;
// const payload = {
// projectid: this.selectedProjectGetter?.id,
// item_state: this.selectedProjectGetter?.item_state,
// listid: this.listIdGetter,
// subjectid: this.listIdGetter,
// bychilds: 0,
// ...this.pagination,
// // offset: offset,
// // limit: this.pagination.limit,
// };
// let url = apis.listItem.list;
// if (this.$route.params.prevPage == "subjects")
// url = apis.subjectRelation.list;
// ApiService.formData(url, payload)
// .then((res) => {
// this.items = res.data.data;
// this.items.forEach((element, index) => {
// if (element.id == this.selectedItemGetter.id) {
// element["active"] = true;
// this.prevActiveIndex = index;
// }
// });
// this.pagination = { ...this.pagination, ...res.data.pagination };
// })
// .catch((err) => {
// this.mySwalToast({
// title: err.response.data.message,
// html: "",
// text: "",
// icon: "error",
// });
// })
// .finally(() => {
// this.fetchingData = false;
// });
// },
goToListPage() {
this.SET_IS_RETURN_FROM_ITEM_SHOW_PAGE(this.listGetter.parent);
const routeName = this.$route.params.prevPage;
this.$router.push({
name: routeName,
});
},
loadMore($event) {
// const listElm = document.querySelector("#last-search");
const listElm = $event.target;
const vm = this;
if (vm.busy) return;
if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
this.busy = true;
vm.pagination.offset = vm.pagination.offset + vm.pagination.limit;
if (vm.pagination.total > vm.pagination.offset) {
setTimeout(() => {
vm.getListOnScroll();
}, 300);
} else {
vm.mySwalToast({
title: "کاربر محترم",
html: "دیگر رکوردی جهت بارگزاری وجود ندارد.",
icon: "info",
position: "bottom-start",
});
vm.busy = false;
}
} else vm.busy = false;
},
getListOnScroll() {
if (this.fetchingData) return;
this.fetchingData = true;
const payload = {
projectid: this.selectedProjectGetter?.id,
item_state: this.selectedProjectGetter?.item_state,
listid: this.listIdGetter,
subjectid: this.listIdGetter,
bychilds: 0,
...this.pagination,
};
let url = apis.listItem.list;
if (this.$route.params.prevPage == "subjects")
url = apis.subjectRelation.list;
ApiService.formData(url, payload)
.then((res) => {
this.items = [...this.items, ...res.data.data];
this.pagination = { ...this.pagination, ...res.data.pagination };
})
.finally(() => {
this.busy = false;
});
},
},
};
</script>
<style scoped lang="scss">
.open-sub-folder {
text-decoration: none;
&:hover {
background-color: #eee;
}
}
.menu-bar-content {
position: static;
flex: 1 1 100%;
max-width: 250px;
width: auto;
height: 180px;
&.show-list-panel {
right: 0px !important;
}
}
.home-list__content {
/*max-height: calc(100vh - 12em);*/
height: calc(100vh - 8.5em);
position: relative;
overflow-x: hidden;
padding-left: 0.3em;
&.loading {
//background-image: url('./img/item-loading.svg');
background-repeat: repeat-y;
background-position: top right;
background-size: 12em;
&::before {
content: "";
clear: both;
position: absolute;
right: 0;
width: 0.5em;
height: 100%;
background-color: #fff;
animation-name: example;
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
}
}
.sidebar-toggler {
right: 2.6em;
&.expanded {
right: 11.1em;
}
}
.meta-list {
display: flex;
align-items: ceter;
flex-wrap: nowrap;
white-space: nowrap;
overflow: auto;
.meta-list-item {
}
}
//mehdi
.close {
width: 20px;
}
.m2 {
// background-color: red;
position: relative;
&::before {
content: "";
height: 35em;
border-left: solid #f1f1f1 1px;
position: absolute;
top: 15px;
left: 0px;
right: 0px;
bottom: 0px;
}
}
.borderBottom {
position: relative;
&::before {
content: "";
border-bottom: solid #00b6e3 2px;
position: absolute;
top: 31px !important;
left: 0px;
right: 0px;
bottom: 0px;
}
}
hr {
margin: 0px;
}
.navigation {
overflow-y: scroll;
width: 200px;
height: 70vh;
max-width: 300px;
.item {
position: relative;
top: 10px;
.item-navigation a:hover {
color: #00b6e3 !important;
}
}
}
.lists {
overflow-y: scroll;
}
.borderBottom::before {
content: "";
border-bottom: solid #00b6e3 2px;
position: absolute;
top: 46px;
left: 0px;
right: 0px;
bottom: 0px;
}
.ctive {
position: relative;
background-color: #d8f8fd;
text-decoration: none;
}
.Active {
//text-decoration: none;
color: #00b6e3 !important;
.item-navigation a {
color: #00b6e3 !important;
}
}
.Breadcrumbs {
//width: 230px;
margin: 2px auto;
position: relative;
right: 10px;
}
.btnHide svg {
transform: rotate(180deg);
}
.button-main {
position: relative;
& button {
border: 0px;
background-color: #f8f8f8;
text-align: center;
& span {
color: #333238;
}
}
}
@media (min-width: 992px) {
.menu-bar-content {
max-width: 220px !important;
}
.d-main-none {
display: none;
}
.button-main {
top: 5px;
right: 10px;
}
}
@media only screen and (min-width: 768px) and (max-width: 991.98px) {
.Breadcrumbs {
position: relative !important;
top: 0px !important;
}
.menu-bar-content {
max-width: 220px !important;
position: relative;
top: 0px;
right: 0px;
}
.navigation {
width: 200px !important;
& div {
width: 190px !important;
}
}
.hide {
display: none;
}
.d-main-none {
display: none;
}
.button-show {
}
.button-main {
top: 20px;
right: 53px;
}
.main-page {
position: fixed;
right: 0rem;
background-color: #fff;
z-index: 9;
height: 39rem;
margin: 0px;
}
}
@media only screen and (min-width: 576px) and (max-width: 766.98px) {
.Breadcrumbs {
position: relative !important;
top: 0px !important;
}
.navigation {
width: 200px !important;
& div {
width: 190px !important;
}
}
.menu-bar-content {
max-width: 220px !important;
position: fixed;
top: 0px;
right: 0px !important;
background-color: #fff;
z-index: 999999;
}
.button-main {
display: none;
}
.main-page {
position: fixed;
right: 0rem;
background-color: #fff;
z-index: 9;
height: 39rem;
margin: 0px;
}
}
@media (max-width: 575.98px) {
.Breadcrumbs {
position: relative !important;
top: 0px !important;
}
.menu-bar-content {
max-width: 220px !important;
position: relative;
top: 0px;
right: 0px !important;
background-color: #fff;
}
.navigation {
width: 200px !important;
& div {
width: 190px !important;
}
}
.menu-bar-content {
max-width: 220px !important;
position: fixed;
top: 0px;
right: 0px !important;
background-color: #fff;
z-index: 9999999;
}
.button-main {
display: none;
}
.main-page {
position: fixed;
right: 0rem;
background-color: #fff;
z-index: 9;
height: 39rem;
margin: 0px;
}
}
//mehdi
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,293 +0,0 @@
<template>
<div class="menu-bar__content menu-bar-content home-list p-3">
<!-- <button @click="toggleSidebarMenu()" type="button" class="btn sidebar-toggler"
:class="{'expanded' : isSidebarCollapsed}">
<img src="assets/common/img/arrow-bar-left.svg" class="img-fluid" alt="">
</button> -->
<Breadcrumbs class="m-start mt-2" />
<div
class="home-list__content scroll-needed mt-4"
:class="{ loading: loading }"
>
<div class="last-search h-100">
<div class="last-search-content h-100" @scroll="loadMore">
<div v-if="items && items.length">
<div class="meta-list mb-3 prev-level" style="background:#F6F6F6">
<a
@click.prevent="goToListPage()"
:href="listGetter.title"
class="meta-list-item text__14"
:title="listGetter.title"
>
{{ listGetter.title }}
</a>
</div>
<div
v-for="(item, index, key) in items"
:id="item.id"
:key="item.id"
class="item"
>
<div
class="d-flex position-relative"
:class="{
'is-selected': item.active ?? false,
}"
>
<a
:class="{ active: item.active ?? false }"
@click.prevent="showParagraphs(item, index, key)"
:href="item.title"
class="title"
:title="item.title"
>
<i class="tavasi tavasi-Component-149--3 ml-1"></i>
{{ item.title }}
</a>
</div>
</div>
</div>
<no-data v-else />
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from "pinia";
import apis from "~/apis/listApi";
export default {
props: {
listPanelUrl: {
default: "",
},
},
emits: ["show-paragraph"],
mounted() {
this.getListItem();
},
data() {
return {
prevActiveIndex: 0,
loading: false,
fetchingData: false,
items: [],
pagination: {
pages: 0,
total: 0,
page: 1,
offset: 0, // page * per_page
limit: 50, //per_page
},
};
},
computed: {
...mapState(["isSidebarCollapsed"]),
...mapState("list", [
"selectedProjectGetter",
"listIdGetter",
"selectedItemGetter",
"listGetter",
]),
},
methods: {
...mapActions("list", ["SET_IS_RETURN_FROM_ITEM_SHOW_PAGE"]),
showParagraphs(item, index) {
this.$emit("show-paragraph", item);
this.$set(this.items[this.prevActiveIndex], "active", false);
this.$set(this.items[index], "active", true);
this.prevActiveIndex = index;
},
getListItem() {
if (this.fetchingData) return;
this.fetchingData = true;
const payload = {
projectid: this.selectedProjectGetter?.id,
item_state: this.selectedProjectGetter?.item_state,
listid: this.listIdGetter,
subjectid: this.listIdGetter,
bychilds: 0,
...this.pagination,
// offset: offset,
// limit: this.pagination.limit,
};
let url = apis.listItem.list;
if (this.$route.params.prevPage == "subjects")
url = apis.subjectRelation.list;
ApiService.formData(url, payload)
.then((res) => {
this.items = res.data.data;
this.items.forEach((element, index) => {
if (element.id == this.selectedItemGetter.id) {
element["active"] = true;
this.prevActiveIndex = index;
}
});
this.pagination = {...this.pagination,...res.data.pagination};
})
.catch((err) => {
this.mySwalToast({
title: err.response.data.message,
html: "",
text: "",
icon: "error",
});
})
.finally(() => {
this.fetchingData = false;
});
},
goToListPage() {
this.SET_IS_RETURN_FROM_ITEM_SHOW_PAGE(this.listGetter.parent);
const routeName = this.$route.params.prevPage;
this.$router.push({
name: routeName,
});
},
loadMore($event) {
// const listElm = document.querySelector("#last-search");
const listElm = $event.target;
const vm = this;
if (vm.busy) return;
if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
this.busy = true;
vm.pagination.offset = vm.pagination.offset + vm.pagination.limit;
if (vm.pagination.total > vm.pagination.offset) {
setTimeout(() => {
vm.getListOnScroll();
}, 300);
} else {
vm.mySwalToast({
title: "کاربر محترم",
html: "دیگر رکوردی جهت بارگزاری وجود ندارد.",
icon: "info",
position: "bottom-start",
});
vm.busy = false;
}
} else vm.busy = false;
},
getListOnScroll() {
if (this.fetchingData) return;
this.fetchingData = true;
const payload = {
projectid: this.selectedProjectGetter?.id,
item_state: this.selectedProjectGetter?.item_state,
listid: this.listIdGetter,
subjectid: this.listIdGetter,
bychilds: 0,
...this.pagination,
};
let url = apis.listItem.list;
if (this.$route.params.prevPage == "subjects")
url = apis.subjectRelation.list;
ApiService.formData(url, payload)
.then((res) => {
this.items = [...this.items, ...res.data.data];
this.pagination = {...this.pagination,...res.data.pagination};
})
.finally(() => {
this.busy = false;
});
},
},
};
</script>
<style scoped lang="scss">
.open-sub-folder {
text-decoration: none;
&:hover {
background-color: #eee;
}
}
.menu-bar__content {
position: static;
flex: 1 1 100%;
max-width: 305px;
width: auto;
min-width: 305px;
}
.home-list__content {
/*max-height: calc(100vh - 12em);*/
height: calc(100vh - 8.5em);
position: relative;
overflow-x: hidden;
padding-left: 0.3em;
&.loading {
//background-image: url('./img/item-loading.svg');
background-repeat: repeat-y;
background-position: top right;
background-size: 12em;
&::before {
content: "";
clear: both;
position: absolute;
right: 0;
width: 0.5em;
height: 100%;
background-color: #fff;
animation-name: example;
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
}
}
.sidebar-toggler {
right: 2.6em;
&.expanded {
right: 11.1em;
}
}
.meta-list {
display: flex;
align-items: ceter;
flex-wrap: nowrap;
white-space: nowrap;
overflow: auto;
.meta-list-item {
}
}
</style>

View File

@ -1,580 +0,0 @@
<template>
<div class="menu-bar__content menu-bar-content home-list p-3">
<!-- <button @click="toggleSidebarMenu()" type="button" class="btn sidebar-toggler"
:class="{'expanded' : isSidebarCollapsed}">
<img src="assets/common/img/arrow-bar-left.svg" class="img-fluid" alt="">
</button> -->
<Breadcrumbs class="m-start mt-2" />
<div class="home-list__header pt-3 pb-0">
<div class="flex-grow-1">
<form
class="search-form rounded-3 mx-0 w-100"
role="search"
@submit.prevent="sendQuery"
>
<div class="form-group">
<div class="d-flex">
<multiselect
:allow-empty="false"
:searchable="true"
:close-on-select="true"
:show-labels="false"
label="title"
track-by="id"
placeholder="انتخاب پروژه"
:value="selectedProjectGetter"
:options="projects"
@select="selectProject"
:hide-selected="false"
:limit-text="
(count) => {
return `و ${count} پروژه دیگر`;
}
"
:max-height="200"
>
</multiselect>
<!-- <select
v-model="projectId"
class="form-control combo"
@change="getList()"
>
<option
v-for="project in projects"
:key="project.id"
:value="project.id"
>
{{ project.title }}
</option>
</select> -->
<div class="dropdown">
<button
class="btn pl-0"
type="button"
id="dropdownMenu2"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="tavasi tavasi-Component-281--1"></i>
</button>
<div class="dropdown-menu " aria-labelledby="dropdownMenu2">
<button
class="dropdown-item text-right d-flex align-item-center"
@click.prevent="showReplaceInput = !showReplaceInput"
type="button"
>
<i class="tavasi tavasi-Component-78--9---2 mt-1"
><span class="path1"></span><span class="path2"></span
></i>
<div class="mx-1">جستجو</div>
</button>
<button
v-can="'list_new'"
data-toggle="modal"
data-target="#list-modal"
@click.prevent="openModal()"
class="dropdown-item text-right d-flex align-item-center "
type="button"
>
<span class="tavasi tavasi-add-folder ml-1"
><span class="path1"></span><span class="path2"></span
><span class="path3"></span><span class="path4"></span
><span class="path5"></span><span class="path6"></span
><span class="path7"></span><span class="path8"></span
></span>
<!-- <span class="tavasi tavasi-Component-133--1 mt-1"></span> -->
<!-- <span class="tavasi tavasi-add"></span> -->
<div class="mx-1">پوشه جدید</div>
</button>
</div>
</div>
</div>
</div>
<div v-if="showReplaceInput" class="form-group">
<div class="input-group">
<input
v-model="searchForm.query"
type="search"
required
class="form-control"
id="search-query"
placeholder="جستجو..."
name="search-query"
aria-label="جستجو در اسناد، عناوین و واژگان"
aria-describedby="basic-addon1"
size="50"
@keyup="sendQuery()"
@keydown="onKeyDown()"
/>
<div class="input-group-append">
<button
@click="showReplaceInput = !showReplaceInput"
type="button"
class="input-group-text show-reset-btn"
id="basic-addon1"
>
<i class="tavasi tavasi-Component-294--1"></i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="home-list__content scroll-needed" :class="{ loading: loading }">
<div class="last-search h-100" id="last-search">
<div class="last-search-content h-100" @scroll="loadMore">
<div v-if="list && list.length">
<div
class="meta-list mb-3 prev-level"
style="background:#F6F6F6"
v-if="meta.length"
>
<div v-for="(metaItem, index) in meta">
<a
:key="'meta' + metaItem.id"
@click.prevent="getParentList(metaItem.parent_id)"
:href="metaItem.title"
class="meta-list-item text__14"
:title="metaItem.title"
>
{{ metaItem.title }}
</a>
<span
:key="'id' + metaItem.id"
style="font-size: 1.4rem; color:blue"
v-if="index < meta.length - 1"
class="tavasi tavasi-Component-22--1"
></span>
</div>
</div>
<draggable
handle=".my-handle"
group="people"
@add="onDrop"
@choose="handleChoose"
@unchoose="handleUnChoose"
@change="handleChange"
:list="list"
>
<div
:id="item.id"
v-for="(item, index) in list"
:key="'id' + item.id"
class="item"
>
<div
class="d-flex position-relative"
:class="{ 'is-selected': item?.isSelected }"
>
<rename-form
v-if="
item?.editMode && item?.parentComponent === 'listPanel'
"
:title="item.title"
:loading="loading"
@closeForm="item.editMode = false"
@saveChanges="editItem($event, item, list)"
></rename-form>
<div v-else>
<a
v-if="item.children"
@click.prevent="getListChildren(item, index)"
:href="item.title"
class="open-sub-folder"
:title="item.title"
>
<!-- <span
v-if="item.children?.length"
class="tavasi tavasi-remove"
></span> -->
<span
v-if="item.children?.length"
class="tavasi tavasi-Component-154--22 ml-1"
></span>
<!-- <span v-else class="tavasi tavasi-add"></span> -->
<span
v-else
class="tavasi tavasi-Component-133--1 color-costom ml-1"
></span>
</a>
<a
:class="{ active: item?.active ?? false }"
@click.prevent="getItems(item, index)"
:href="item.title"
class="title"
:title="item.title"
>
<span class="my-handle">
<!-- <i v-if="item.children === 0" class="tavasi tavasi-Component-149&#45;&#45;3"></i>-->
<i
v-if="!item.children || item.children.length === 0"
class="tavasi tavasi-Component-149--3 ml-1"
></i>
<!-- <i v-else class="tavasi tavasi-Component-360&#45;&#45;58">-->
<!-- <span class="path1"></span>-->
<!-- <span class="path2"></span>-->
<!-- </i>-->
</span>
{{ item.title }}
</a>
<div v-if="!item?.isSelected">
<context-menu
v-can="'list_folder_edit'"
:parentComponent="'listPanel'"
:list="list"
:clickedItem="item"
:contextMenu="contextMenu"
@remove-item="removeItem(item, list)"
@update-order="updateOrder($event, item, list, index)"
@new-sub-folder="
openNewSubFolderModal(item, list, index)
"
>
</context-menu>
</div>
</div>
</div>
<div v-if="Array.isArray(item.children)">
<draggable
handle=".my-handle"
@add="onDrop"
group="people"
tag="ul"
class="children list-unstyled"
:list="item.children"
:id="item.id"
>
<li
:id="child.id"
class="position-relative"
v-for="(child, childIndex) in item.children"
:key="child.title"
>
<rename-form
v-if="
child?.editMode &&
child?.parentComponent === 'listPanel'
"
:title="child.title"
:loading="loading"
@closeForm="child.editMode = false"
@saveChanges="editItem($event, child, item.children)"
></rename-form>
<div v-else>
<a
:class="{ active: child?.active ?? false }"
@click.prevent="getItems(child, childIndex)"
:href="child.title"
class="title"
:title="child.title"
>
<span class="my-handle">
<i
v-if="child.children === 0"
class="tavasi tavasi-Component-149--3 ml-1"
></i>
<i v-else>
<span class="path1"></span>
<span class="path2"></span>
</i>
</span>
{{ child.title }}
</a>
<div v-if="!child?.isSelected">
<context-menu
v-can="'list_folder_edit'"
:parentComponent="'listPanel'"
:list="item.children"
:clickedItem="child"
:contextMenu="contextMenu"
@remove-item="removeItem(child, item.children)"
@new-sub-folde="openNewSubFolderModal(child)"
@update-order="
updateOrder(
$event,
child,
item.children,
childIndex
)
"
>
</context-menu>
</div>
</div>
</li>
</draggable>
</div>
</div>
</draggable>
</div>
<no-data v-else />
</div>
<!-- <div class="last-search-footer" v-if="list.length > 0">-->
<!-- <button class="btn last-search-more-btn" type="button">بیشتر</button>-->
<!-- </div>-->
</div>
</div>
<div v-if="showModal">
<new-list-modal
:apiName="currentPageName"
:selectedItem="selectedItem"
:parentId="parentId"
@close-modal="closeModal"
@delete-item="updateList"
@update-list="updateList"
/>
</div>
<div class="d-md-none hide-list-panel">
<button
name="button"
type="button"
class="toggle-mobile-nav"
@click="$emit('hide-panel')"
>
<svg class="icon icon-chevron-double-right">
<use xlink:href="#icon-chevron-double-right"></use>
</svg>
<span class="collapse-text mr-2">بستن</span>
</button>
</div>
</div>
</template>
<script>
import { listMixin } from "~/list/mixins/listMixin";
import { searchMixin } from "~/list/mixins/searchMixin";
import { dragDropMoveMixin } from "~/list/mixins/dragDropMoveMixin";
export default {
props: ["items"],
mixins: [searchMixin, listMixin, dragDropMoveMixin],
emits: ["list-changed", "list-item-changed"],
activated() {
if (this.cached === false) {
this.cached = Date.now();
} else {
// time diff since cache, in seconds
const diff = (Date.now() - this.cached) / 1000;
// if cache is older than 30 seconds, invalidate
if (diff > 1800) {
this.cached = false;
this.getProjects();
}
}
},
mounted() {
this.$refs.topheader.modetab = 2;
this.$refs.topheader.state = 2;
if (this.tq != "") {
var item = this.tq;
this.checkMultiword(item);
this.$refs.topheader.setSearchLine(this.tq);
this.$refs.content.setTextSearch(this.tq, this.countInPage);
this.getQuery();
}
},
deactivated() {
// console.log("deactivated");
},
watch: {
isReturnFromItemshowPageGetter(id) {
this.getList(id);
},
// $route: {
// handler(route) {
// this.storeUserLastState(route.name);
// },
// nested: true,
// immediate: true,
// },
},
data() {
return {
cached: false,
currentPageName: "list",
tq: this.q,
filterUrl: "",
loading: false,
showSummary: false,
countInPage: 10,
currentItem: [],
searchType: "",
searchCode: "all",
ismultword: false,
iscode: false,
page: 0,
cloneItems: [],
typingTimer: 0,
showReplaceInput: false,
doneTypingInterval: 1000,
searchForm: {
query: "",
},
};
},
methods: {
sendQuery() {
// todo: show loading.
// todo: send query and show result.
// todo: hide loading.
clearTimeout(this.typingTimer);
this.typingTimer = setTimeout(() => {
// request data from api
}, this.doneTypingInterval);
},
onKeyDown() {
clearTimeout(this.typingTimer);
},
resetForm() {
this.searchForm.query = "";
this.searchForm.replaceWith = "";
this.cloneItems = structuredClone(this.items);
},
searchTyping(type) {
this.searchType = type;
},
searchCoding(code) {
this.searchCode = code;
},
resetOptions() {
this.page = 0;
this.filterUrl = "";
this.$refs.filterlist.resetFilter();
},
showfilter: function() {
this.$refs.filterlist.showfilter();
},
checkMultiword(item) {
this.ismultword = false;
if (item == null || item == "") return;
var ww = item.split(" ");
this.iscode = /^\d+$/.test(item);
if (this.iscode == false) this.ismultword = item.split(" ").length > 1;
this.$refs.topheader.setOptions(this.ismultword, this.iscode);
},
searchStart: function(item) {
if (item != null) {
item = item.trim();
this.tq = item;
this.checkMultiword(item);
this.$refs.content.setTextSearch(item, this.countInPage);
}
this.resetOptions();
this.getQuery();
},
changePaging: function(item) {
this.page = item;
this.getQuery(true);
},
hideSummary: function() {
this.showSummary = false;
},
changeCurrent: function(item) {
if (item == this.currentItem) this.showSummary = !this.showSummary;
else this.showSummary = true;
this.currentItem = item;
this.$refs.summary.setInfo(item);
},
},
};
</script>
<style scoped lang="scss">
.open-sub-folder {
text-decoration: none;
&:hover {
background-color: #eee;
}
}
.menu-bar__content {
position: static;
flex: 1 1 100%;
max-width: 305px;
width: auto;
min-width: 305px;
&.show-list-panel {
right: 0 !important;
}
}
.home-list__content {
/*max-height: calc(100vh - 12em);*/
height: calc(100vh - 8.5em);
position: relative;
overflow-x: hidden;
padding-left: 0.3em;
&.loading {
//background-image: url('./img/item-loading.svg');
background-repeat: repeat-y;
background-position: top right;
background-size: 12em;
&::before {
content: "";
clear: both;
position: absolute;
right: 0;
width: 0.5em;
height: 100%;
background-color: #fff;
animation-name: example;
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
}
}
.sidebar-toggler {
right: 2.6em;
&.expanded {
right: 11.1em;
}
}
.meta-list {
display: flex;
align-items: ceter;
flex-wrap: nowrap;
white-space: nowrap;
overflow: auto;
.meta-list-item {
}
}
</style>

View File

@ -1,613 +0,0 @@
<template>
<div class="menu-bar__content menu-bar-content home-list p-3">
<Breadcrumbs />
<div class="home-list__header pt-3 pb-0">
<div class="flex-grow-1">
<form
class="search-form mx-0 w-100"
role="search"
@submit.prevent="sendQuery"
>
<div class="form-group">
<div class="d-flex">
<select
v-model="listTypeId"
class="form-control"
@change="getList()"
>
<option
v-for="subject in subjects"
:key="subject.id"
:value="subject.id"
>
{{ subject.title }}
</option>
</select>
<div class="context-menu-dropdown">
<div class="dropdown">
<button
class="btn pl-0"
type="button"
id="dropdownMenu2"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="tavasi tavasi-Component-281--1"></i>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenu2">
<button
class="dropdown-item text-right"
@click.prevent="showReplaceInput = !showReplaceInput"
type="button"
>
<i class="tavasi tavasi-Component-78--9---2"
><span class="path1"></span><span class="path2"></span
></i>
جستجو
</button>
<button
data-toggle="modal"
data-target="#new-item-modal"
@click.prevent="openModal()"
class="dropdown-item text-right"
type="button"
>
<span class="tavasi tavasi-Component-133--1"></span>
<!-- <span class="tavasi tavasi-add"></span> -->
پوشه جدید
</button>
</div>
</div>
</div>
</div>
</div>
<div v-if="showReplaceInput" class="form-group">
<div class="input-group">
<input
v-model="searchForm.query"
type="search"
required
class="form-control"
id="search-query"
placeholder="جستجو..."
name="search-query"
aria-label="جستجو در اسناد، عناوین و واژگان"
aria-describedby="basic-addon1"
size="50"
@keyup="sendQuery()"
@keydown="onKeyDown()"
/>
<div class="input-group-append">
<button
@click="showReplaceInput = !showReplaceInput"
type="button"
class="input-group-text show-reset-btn"
id="basic-addon1"
>
<i class="tavasi tavasi-Component-294--1"></i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="home-list__content scroll-needed" :class="{ loading: loading }">
<div class="last-search h-100">
<div class="last-search-content h-100">
<div v-if="list.length">
<div class="item mb-3 prev-level" v-if="meta.length">
<!-- <span style="font-size: 1.1rem;" class="tavasi tavasi-Component-71&#45;&#45;1 ml-2"></span>-->
<div v-for="(metaItem, index) in meta">
<a
:key="metaItem.id"
@click.prevent="getList(metaItem.parent)"
:href="metaItem.title"
class="title d-flex "
:title="metaItem.title"
>
{{ metaItem.title }}
</a>
<span
style="font-size: 1.4rem;"
v-if="index < meta.length - 1"
class="tavasi tavasi-arrow-down"
></span>
</div>
</div>
<div v-for="(item, index) in list" :key="item.title" class="item">
<draggable
:sort="false"
:disabled="false"
group="people"
@add="onDrop($event, item)"
>
<div
class="d-flex position-relative"
:class="{ 'is-selected': item?.isSelected }"
>
<rename-form
v-if="
item?.editMode && item?.parentComponent === 'subjectPanel'
"
:title="item.title"
:loading="loading"
@closeForm="item.editMode = false"
@saveChanges="editItem($event, item, list)"
></rename-form>
<div v-else>
<a
v-if="item.children"
@click.prevent="getListChildren(item, index)"
:href="item.title"
class="title"
:title="item.title"
>
<span
v-if="item.children?.length"
class="tavasi tavasi-remove"
></span>
<!-- <span v-else class="tavasi tavasi-add"></span> -->
<span
v-else
class="tavasi tavasi-Component-133--1"
></span>
</a>
<a
:class="{ active: item?.active ?? false }"
@click.prevent="getItems(item, index)"
:href="item.title"
class="title"
:title="item.title"
>
<i
v-if="!item.children || item.children.length === 0"
class="tavasi tavasi-Component-149--3"
></i>
<!-- <i v-if="item.children === 0" class="tavasi tavasi-Component-149&#45;&#45;3"></i>-->
<!-- <i v-else class="tavasi tavasi-Component-360&#45;&#45;58">-->
<!-- <span class="path1"></span>-->
<!-- <span class="path2"></span>-->
<!-- </i>-->
{{ item.title }}
</a>
<div v-if="!item?.isSelected">
<context-menu
:parentComponent="'subjectPanel'"
:list="list"
:clickedItem="item"
:contextMenu="contextMenu"
@remove-item="removeItem(item, list)"
>
</context-menu>
</div>
</div>
</div>
<ul v-if="Array.isArray(item.children)" class="children">
<li
class="position-relative"
v-for="(child, childIndex) in item.children"
:key="child.title"
>
<rename-form
v-if="
child?.editMode &&
child?.parentComponent === 'subjectPanel'
"
:title="child.title"
:loading="loading"
@closeForm="child.editMode = false"
@saveChanges="editItem($event, child, item.children)"
></rename-form>
<div v-else>
<a
@click.prevent="getItems(child, childIndex)"
:href="child.title"
class="title"
:title="child.title"
>
<i
v-if="child.children === 0"
class="tavasi tavasi-Component-149--3"
></i>
<i v-else class="tavasi tavasi-Component-360--58">
<span class="path1"></span>
<span class="path2"></span>
</i>
{{ child.title }}
</a>
<div v-if="!child?.isSelected">
<context-menu
:parentComponent="'subjectPanel'"
:list="item.children"
:clickedItem="child"
:contextMenu="contextMenu"
@remove-item="removeItem(child, item.children)"
>
</context-menu>
</div>
</div>
</li>
</ul>
</draggable>
</div>
</div>
<no-data v-else />
</div>
<!-- <div class="last-search-footer" v-if="list.length > 0">-->
<!-- <button class="btn last-search-more-btn" type="button">بیشتر</button>-->
<!-- </div>-->
</div>
</div>
<div v-if="showModal">
<NewListModal
:listTypeId="listTypeId"
:selectedItem="selectedItem"
:parentId="parentId"
@close-modal="closeModal"
@delete-item="updateList"
@update-list="updateList"
/>
</div>
</div>
</template>
<script>
import apis from "~/apis/listApi";
export default {
props: ["items", "subjectId", "index"],
emits: ["list-changed", "list-item-changed"],
data() {
return {
contextMenu: [],
subjects: [
{
id: 0,
title: "موضوعات",
},
{
id: 1,
title: "نمایه",
disabled: true,
},
{
id: 2,
title: "برچسب",
disabled: true,
},
],
showModal: false,
prevSelectedItemIndex: undefined,
prevItem: undefined,
meta: [],
projects: [],
list: [],
listItem: [],
listTypeId: 0,
parentId: undefined,
selectedItem: {},
typingTimer: 0,
doneTypingInterval: 1000,
cloneItems: [],
loading: false,
searchForm: {
query: "",
},
editMode: false,
showReplaceInput: false,
};
},
methods: {
getListItem(subjectId, index) {
this.markActive(index);
if (this.fetchingData) return;
this.fetchingData = true;
const payload = {
// projectid: this.listTypeId,
bychilds: 0,
projectid: 1,
subjectid: this.subjectId,
...this.pagination,
};
ApiService.formData(apis.subjectRelation.list, payload)
.then((res) => {
this.listItem = res.data.data;
this.listItem.forEach((item, index) => {
Object.keys(item).forEach((value, key) => {
if (value === "resource") {
item[value] = this.getProjectTitle(item[value]);
}
});
});
this.pagination = {...this.pagination,...res.data.pagination};
})
.finally(() => {
this.fetchingData = false;
});
},
addItemToList(itemId, listId) {
const payload = {
itemid: itemId,
listid: listId,
listtype: this.listTypeId,
projectid: 1,
};
ApiService.formData(apis.subject.add, payload).then((res) => {
this.mySwalToast({
title: "تبریک",
html: res.data.message,
icon: "success",
});
});
},
removeItem(listItem, listArray) {
this.mySwalConfirm({
title: "هشدار!!!",
html: `از حذف <b>${listItem.title}</b> اطمینان دارید؟ `,
icon: "warning",
}).then((result) => {
if (result.isConfirmed) {
const payload = {
subjectid: listItem.id,
};
ApiService.formData(apis.subject.delete, payload)
.then((res) => {
this.mySwalToast({
html: res.data.message,
icon: "success",
});
const indexOfList = listArray.findIndex(
(item) => item.id === listItem.id
);
listArray.splice(indexOfList, 1);
})
.catch((err) => {
this.mySwalToast({
title: "خطا!!!",
html: err.message,
icon: "error",
});
});
}
});
},
editItem(newTitle, subject, subjectArray) {
if (this.loading) return;
this.loading = true;
const model = {
title: newTitle,
subjectid: subject.id,
newparent: subject.parent ? subject.parent : 0,
};
ApiService.formData(apis.subject.edit, model)
.then((res) => {
list.editMode = false;
const resultIndex = subjectArray.findIndex(
(item) => subject.id === item.id
);
if (resultIndex > -1) {
this.$set(subjectArray[resultIndex], "title", newTitle);
}
this.mySwalToast({
title: "تبریک",
html: res.data.message,
icon: "success",
});
})
.catch((err) => {
this.mySwalToast({
title: "خطا!!!",
html: err?.message,
icon: "error",
});
})
.finally(() => (this.loading = false));
},
getListChildren(item, index) {
if (Array.isArray(item.children)) {
item = { ...item, ...{ children: item.children.length } };
this.$set(this.list, index, item);
} else {
const payload = {
parent: item.id,
sortby: "id",
offset: 0,
limit: 100,
listtype: this.listTypeId,
projectid: 1,
};
ApiService.formData(apis.subject.list, payload).then((res) => {
item = { ...item, ...{ children: res.data.data } };
this.$set(this.list, index, item);
});
}
},
getItems(item, index) {
if (Array.isArray(item.children)) {
this.$emit("set-selected-list", item.children[0]);
this.getListItem(item.children[0].id, index);
} else if (item.children > 0) {
this.parentId = item.id;
this.$emit("set-selected-list", item);
this.getList(item.id);
} else {
this.$emit("set-selected-list", item);
this.getListItem(item.id, index);
}
},
getList(parent = 0) {
const payload = {
parent: parent,
sortby: "id",
offset: 0,
limit: 100,
listtype: this.listTypeId,
projectid: 1,
};
ApiService.formData(apis.subject.list, payload).then((res) => {
this.list = res.data.data;
this.meta = res.data?.meta ?? [];
this.$emit("list-changed", {
subjectId: parent,
listTypeId: this.listTypeId,
});
// if (res.data.meta)
// this.meta = res.data.meta.filter((item, index) => index > 0);
});
},
updateList() {
this.resetPagination();
this.closeModal();
this.getList(this.parentId);
},
resetPagination() {
this.pagination = {
pages: 0,
total: 0,
page: 1,
offset: 0,// page * per_page
limit: 50//per_page
}
},
markActive(index) {
if (this.prevSelectedItemIndex !== undefined) {
this.$set(this.list[this.prevSelectedItemIndex], "active", false);
}
this.prevSelectedItemIndex = index;
this.$set(this.list[index], "active", true);
},
sendQuery() {
// todo: show loading.
// todo: send query and show result.
// todo: hide loading.
clearTimeout(this.typingTimer);
this.typingTimer = setTimeout(() => {
// request data from api
}, this.doneTypingInterval);
},
onKeyDown() {
clearTimeout(this.typingTimer);
},
resetForm() {
this.searchForm.query = "";
this.searchForm.replaceWith = "";
this.cloneItems = structuredClone(this.items);
},
onDrop(ev, list) {
const itemId = ev.item["_underlying_vm_"]["id"];
const listId = list.id;
this.addItemToList(itemId, listId);
},
closeModal() {
$("#new-item-modal").modal("hide");
setTimeout(() => {
this.showModal = false;
}, 500);
},
openModal() {
this.showModal = true;
setTimeout(() => {
$("#new-item-modal").modal(
{ backdrop: "static", keyboard: false },
"show"
);
}, 500);
},
},
mounted() {
this.this.contextMenu = require(`~/json//subjectContextMenu.json`).filter(
(item) => item.show
);
},
};
</script>
<style scoped lang="scss">
.menu-bar__content {
position: static;
flex: 1 1 100%;
max-width: 305px;
width: auto;
}
.home-list__content {
/*max-height: calc(100vh - 12em);*/
height: calc(100vh - 8em);
position: relative;
overflow-x: hidden;
padding-left: 0.3em;
&.loading {
//background-image: url('./img/item-loading.svg');
background-repeat: repeat-y;
background-position: top right;
background-size: 12em;
&::before {
content: "";
clear: both;
position: absolute;
right: 0;
width: 0.5em;
height: 100%;
background-color: #fff;
animation-name: example;
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
}
}
</style>

View File

@ -1,676 +0,0 @@
<template>
<div class="menu-bar__content menu-bar-content home-list p-3">
<!-- <button @click="toggleSidebarMenu()" type="button" class="btn sidebar-toggler"
:class="{'expanded' : isSidebarCollapsed}">
<img src="assets/common/img/arrow-bar-left.svg" class="img-fluid" alt="">
</button> -->
<Breadcrumbs />
<div class="home-list__header pt-3 pb-0">
<div class="flex-grow-1">
<form
class="search-form mx-0 w-100"
role="search"
@submit.prevent="sendQuery"
>
<div class="form-group">
<div class="d-flex">
<multiselect
:allow-empty="false"
:searchable="true"
:close-on-select="true"
:show-labels="false"
label="title"
track-by="id"
placeholder="انتخاب پروژه"
:value="selectedProjectGetter"
:options="projects"
@select="selectProject"
:hide-selected="false"
:limit-text="
(count) => {
return `و ${count} پروژه دیگر`;
}
"
:max-height="200"
>
</multiselect>
<!-- <select-->
<!-- v-model="projectId"-->
<!-- class="form-control mr-1"-->
<!-- @change="getList()"-->
<!-- >-->
<!-- <option-->
<!-- v-can="'subject_view'"-->
<!-- v-for="project in projects"-->
<!-- :key="project.id"-->
<!-- :value="project.id"-->
<!-- >-->
<!-- {{ project.title }}-->
<!-- </option>-->
<!-- </select>-->
<div class="context-menu-dropdown">
<div class="dropdown">
<button
class="btn pl-0"
type="button"
id="dropdownMenu2"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="tavasi tavasi-Component-281--1"></i>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenu2">
<button
class="dropdown-item text-right"
@click.prevent="showReplaceInput = !showReplaceInput"
type="button"
>
<i class="tavasi tavasi-Component-78--9---2"
><span class="path1"></span><span class="path2"></span
></i>
جستجو
</button>
<button
v-can="'subject_new'"
data-toggle="modal"
data-target="#list-modal"
@click.prevent="openModal()"
class="dropdown-item text-right"
type="button"
>
<!-- <span class="tavasi tavasi-add"></span> -->
<span class="tavasi tavasi-Component-133--1"></span>
پوشه جدید
</button>
</div>
</div>
</div>
</div>
</div>
<div v-if="showReplaceInput" class="form-group">
<div class="input-group">
<input
v-model="searchForm.query"
type="search"
required
class="form-control"
id="search-query"
placeholder="جستجو..."
name="search-query"
aria-label="جستجو در اسناد، عناوین و واژگان"
aria-describedby="basic-addon1"
size="50"
@keyup="sendQuery()"
@keydown="onKeyDown()"
/>
<div class="input-group-append">
<button
@click="showReplaceInput = !showReplaceInput"
type="button"
class="input-group-text show-reset-btn"
id="basic-addon1"
>
<i class="tavasi tavasi-Component-294--1"></i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="home-list__content scroll-needed" :class="{ loading: loading }">
<div class="last-search h-100">
<div class="last-search-content h-100" @scroll="loadMore">
<div v-if="list.length">
<div class="meta-list mb-3 prev-level" v-if="meta.length">
<!-- <span style="font-size: 1.1rem;" class="tavasi tavasi-Component-71&#45;&#45;1 ml-2"></span>-->
<div v-for="(metaItem, index) in meta">
<a
:key="'meta' + metaItem.id"
@click.prevent="getParentList(metaItem.parent_id)"
:href="metaItem.title"
class="meta-list-item text__14"
:title="metaItem.title"
>
{{ metaItem.title }}
</a>
<span
:key="'id' + metaItem.id"
style="font-size: 1.4rem; color: blue"
v-if="index < meta.length - 1"
class="tavasi tavasi-Component-22--1"
></span>
</div>
</div>
<!-- mehdi -->
<div class="select-export-container" v-if="list?.length">
<div class="dropdown">
<button
class="btn btn-outline-light border-0 dropdown-toggle"
type="button"
data-toggle="dropdown"
aria-expanded="false"
>
<span class="tavasi tavasi-excel-file-2 ml-1"></span>
</button>
<div class="dropdown-menu">
<button
class="dropdown-item"
type="button"
:disabled="fetchingDataForExport"
@click="exportJsonToExcel('current')"
value="current"
>
جاری
</button>
<button
class="dropdown-item"
type="button"
:disabled="fetchingDataForExport"
@click="exportJsonToExcel('all')"
value="all"
>
همه
</button>
</div>
</div>
</div>
<!-- mehdi -->
<div
:id="item.id"
v-for="(item, index) in list"
:key="item.title"
class="item"
>
<draggable
handle=".my-handle"
group="people"
@add="onDrop"
@choose="handleChoose"
@unchoose="handleUnChoose"
@change="handleChange"
:list="list"
>
<div
class="d-flex position-relative"
:class="{ 'is-selected': item?.isSelected }"
>
<rename-form
v-if="
item?.editMode &&
item?.parentComponent === 'subjectPanel' &&
!isGuest
"
:title="item.title"
:loading="loading"
@closeForm="item.editMode = false"
@saveChanges="editItem($event, item, list)"
></rename-form>
<div v-else>
<a
v-if="item.children"
@click.prevent="getListChildren(item, index)"
:href="item.title"
class="open-sub-folder"
:title="item.title"
>
<span class="my-handle">
<svg
v-if="item.children?.length"
class="icon icon-Component-154--22 color-costom ml-1"
>
<use xlink:href="#icon-Component-154--22"></use>
</svg>
<svg
v-else
class="icon icon-Component-133--1 color-costom ml-1"
>
<use xlink:href="#icon-Component-133--1"></use>
</svg>
</span>
</a>
<a
:class="{ active: item?.active ?? false }"
@click.prevent="getItems(item, index)"
:href="item.title"
class="title"
:title="item.title"
>
<span class="my-handle">
<i
v-if="!item.children || item.children.length === 0"
class="tavasi tavasi-Component-149--3 ml-1"
></i>
<!-- <i v-if="item.children === 0" class="tavasi tavasi-Component-149&#45;&#45;3"></i>-->
<!-- <i v-else class="tavasi tavasi-Component-360&#45;&#45;58">-->
<!-- <span class="path1"></span>-->
<!-- <span class="path2"></span>-->
<!-- </i>-->
</span>
{{ item.title }}
</a>
<div v-if="!item?.isSelected && !isGuest">
<!-- v-can="'list_edit'" -->
<context-menu
:parentComponent="'subjectPanel'"
:list="list"
:clickedItem="item"
:contextMenu="contextMenu"
@remove-item="removeItem(item, list)"
@update-order="updateOrder($event, item, list, index)"
@new-sub-folder="
openNewSubFolderModal(item, list, index)
"
>
</context-menu>
</div>
</div>
</div>
<ul v-if="Array.isArray(item.children)" class="children">
<li
class="position-relative"
v-for="(child, childIndex) in item.children"
:key="child.title"
>
<rename-form
v-if="
child?.editMode &&
child?.parentComponent === 'subjectPanel' &&
!isGuest
"
:title="child.title"
:loading="loading"
@closeForm="child.editMode = false"
@saveChanges="editItem($event, child, item.children)"
></rename-form>
<div v-else>
<a
@click.prevent="getItems(child, childIndex)"
:href="child.title"
class="title"
:title="child.title"
>
<span class="my-handle">
<svg
v-if="child.children === 0"
class="icon icon-Component-149--3 ml-1"
>
<use xlink:href="#icon-Component-149--3"></use>
</svg>
<!-- <i
v-if="child.children === 0"
class="tavasi tavasi-Component-149--3 ml-1"
></i> -->
<svg
v-else
class="icon icon-Component-360--2 text__14 ml-1"
>
<use xlink:href="#icon-Component-360--2"></use>
</svg>
<!-- <i
v-else
class="tavasi tavasi-Component-360--58 text__14 ml-1"
>
<span class="path1"></span>
<span class="path2"></span>
</i> -->
</span>
{{ child.title }}
</a>
<div v-if="!child?.isSelected && !isGuest">
<context-menu
:parentComponent="'subjectPanel'"
:list="item.children"
:clickedItem="child"
:contextMenu="contextMenu"
@remove-item="removeItem(child, item.children)"
@new-sub-folde="openNewSubFolderModal(child)"
@update-order="
updateOrder(
$event,
child,
item.children,
childIndex
)
"
>
</context-menu>
</div>
</div>
</li>
</ul>
</draggable>
</div>
</div>
<no-data v-else />
</div>
<!-- <div class="last-search-footer" v-if="list.length > 0">-->
<!-- <button class="btn last-search-more-btn" type="button">بیشتر</button>-->
<!-- </div>-->
</div>
</div>
<div v-if="showModal && !isGuest">
<new-list-modal
:apiName="currentPageName"
:selectedItem="selectedItem"
:parentId="parentId"
@close-modal="closeModal"
@delete-item="updateList"
@update-list="updateList"
/>
</div>
<div class="d-md-none hide-list-panel">
<button
name="button"
type="button"
class="toggle-mobile-nav"
@click="$emit('hide-panel')"
>
<svg class="s12 icon-chevron-double-lg-right">
<use
href="assets/common/img/icons.svg#chevron-double-lg-right"
></use>
</svg>
<span class="collapse-text mr-2">بستن</span>
</button>
</div>
</div>
</template>
<script>
import apis from "~/apis/listApi";
import { listMixin } from "~/list/mixins/listMixin";
import { searchMixin } from "~/list/mixins/searchMixin";
import { dragDropMoveMixin } from "~/list/mixins/dragDropMoveMixin";
import { mapState } from "pinia";
export default {
props: ["items"],
mixins: [searchMixin, listMixin, dragDropMoveMixin],
emits: ["list-changed", "list-item-changed"],
activated() {
if (this.cached === false) {
this.cached = Date.now();
} else {
// time diff since cache, in seconds
const diff = (Date.now() - this.cached) / 1000;
// if cache is older than 30 seconds, invalidate
if (diff > 1800) {
this.cached = false;
this.getProjects();
}
}
},
deactivated() {
// console.log("deactivated");
},
computed: {
...mapState(["isGuest"]),
},
watch: {
isReturnFromItemshowPageGetter(id) {
this.getList(id);
},
// $route: {
// handler(route) {
// this.storeUserLastState(route.name);
// },
// nested: true,
// immediate: true,
// },
},
data() {
return {
cached: false,
subjects: [],
listTypeId: 0,
currentPageName: "subject",
};
},
methods: {
async storeUserLastState(route) {
let payLoad = {
lastRouteName: route,
lastRouteUrl: route,
list: {
subjects: {
sorting: this.sorting,
pagination: this.pagination,
project: this.selectedProjectGetter,
item: this.selectedItemGetter,
listId: this.listIdGetter,
list: this.listGetter,
},
},
};
return await this.storeState(payLoad);
},
getProjects() {
this.checkPermissions({ permission: "subject_view", _this: this })
.then(() => {
const payload = {
isown: 3,
sortby: "created",
offset: 0,
limit: 100,
type: 3, // موضوع
};
ApiService.formData(apis.projects.list, payload).then((res) => {
const firstProject = res.data.data[0];
firstProject.meta = JSON.parse(firstProject.meta);
// console.log(firstProject.table_columns);
firstProject.table_columns = JSON.parse(firstProject.table_columns);
this.SET_SELECTED_PROJECT(firstProject);
this.$emit("list-changed", {
// listId: undefined,
// projectId: this.subjectProject.id,
});
this.projects = res.data.data;
this.getList();
this.$emit("can-view", true);
});
})
.catch(() => {
this.$emit("can-view", false);
});
},
getList(parent = 0) {
const payload = {
projectid: this.selectedProjectGetter?.id,
parent: parent,
sortby: "id",
offset: 0,
limit: 100,
listtype: this.listTypeId,
};
let self = this;
ApiService.formData(apis.subject.list, payload).then((res) => {
self.list = res.data.data;
self.meta = res.data?.meta ?? [];
self.$emit("list-changed", {
subjectId: parent,
listTypeId: self.listTypeId,
});
if (parent == 0) {
self.SET_LIST_ID(self.list[0].id);
} else {
self.SET_LIST_ID(parent);
}
self.SET_LIST(self.list[0]);
self.getListItem(self.list[0].id, 0);
self.switchActive(self.list[0]);
// if (res.data.meta)
// this.meta = res.data.meta.filter((item, index) => index > 0);
});
},
addItemToList(itemId, listId) {
const payload = {
itemid: itemId,
listid: listId,
listtype: this.listTypeId,
projectid: this.selectedProjectGetter?.id,
};
ApiService.formData(apis.subject.add, payload).then((res) => {
// this.getList()
this.mySwalToast({
title: "تبریک",
html: res.data.message,
icon: "success",
});
});
},
editItem(newTitle, subject, subjectArray) {
if (this.loading) return;
this.loading = true;
const model = {
title: newTitle,
subjectid: subject.id,
projectid: this.selectedProjectGetter?.id,
// ,newparent: subject.parent ? subject.parent : 0, // نیاز نیست
};
ApiService.formData(apis.subject.edit, model)
.then((res) => {
subject.editMode = false;
const resultIndex = subjectArray.findIndex(
(item) => subject.id === item.id
);
if (resultIndex > -1) {
this.$set(subjectArray[resultIndex], "title", newTitle);
}
this.mySwalToast({
title: "موفق",
html: res.data.message,
icon: "success",
});
})
.catch((err) => {
this.mySwalToast({
title: "خطا!!!",
html: err?.message,
icon: "error",
});
})
.finally(() => (this.loading = false));
},
// onDrop(ev, list) {
// const itemId = ev.item["_underlying_vm_"]["id"];
// const listId = list.id;
// this.addItemToList(itemId, listId);
// },
// onEnd(ev) {
// },
},
};
</script>
<style scoped lang="scss">
.my-handle {
color: #ccc;
}
.menu-bar__content {
position: static;
flex: 1 1 100%;
max-width: 305px;
width: auto;
&.show-list-panel {
right: 0 !important;
}
}
.home-list__content {
/*max-height: calc(100vh - 12em);*/
height: calc(100vh - 8em);
position: relative;
overflow-x: hidden;
padding-left: 0.3em;
&.loading {
//background-image: url('./img/item-loading.svg');
background-repeat: repeat-y;
background-position: top right;
background-size: 12em;
&::before {
content: "";
clear: both;
position: absolute;
right: 0;
width: 0.5em;
height: 100%;
background-color: #fff;
animation-name: example;
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
}
}
.sidebar-toggler {
right: 2.6em;
&.expanded {
right: 11.1em;
}
}
.meta-list {
display: flex;
align-items: ceter;
flex-wrap: nowrap;
white-space: nowrap;
overflow: auto;
.meta-list-item {
}
}
//mehdi
.select-export-container {
position: relative;
top: -5px;
left: 12rem;
//lefr: 0px;
}
//mehdi
</style>

View File

@ -1,44 +0,0 @@
<template>
<div class="menu-bar__container">
<ul class="menu-bar__link link-bar">
<li class="link-bar__item">
<a @click.prevent="redirectToRouteName()" href="/" class="btn dashboard-btn">
<img style="width: 1em;height: 1em;" src="assets/list/img/hamburger-menu.svg" class="img-fluid" alt="سامانه ها">
<span class="mx-1">سامانه ها</span>
</a>
</li>
<li
v-for="(item, i) in menu"
:key="i"
:class="
item.actionMode == currentMode
? 'link-bar__item color-' + item.color + ' active'
: 'link-bar__item color-' + item.color
"
>
<router-link
:to="item.link" :title="item.title">
<i :class="item.icon">
<span class="path1"></span><span class="path2"></span
></i>
</router-link>
</li>
</ul>
</div>
</template>
<script>
import menu from "~/json/list/json/sidebar.json"
export default {
props: ["currentMode"],
data() {
return {
menu: menu
};
},
};
</script>

View File

@ -2,8 +2,10 @@
import fs from "fs-extra"; import fs from "fs-extra";
import path from "path"; import path from "path";
const envs = import.meta.env;
let sassEnvVariables = ""; let sassEnvVariables = "";
for (let e in import.meta.env) {
for (let e in envs) {
if (/VITE_/i.test(e)) { if (/VITE_/i.test(e)) {
sassEnvVariables += `$${e}: "${import.meta.env[e]}";`; sassEnvVariables += `$${e}: "${import.meta.env[e]}";`;
} }
@ -74,12 +76,54 @@ export default defineNuxtConfig({
path: "/search/:key/:id/detail", path: "/search/:key/:id/detail",
file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue", file: "~/systems/search_ui/pages/search/(show)/[key]/[id]/index.vue",
}, },
// hadith // --------------------- start: hadith routes ---------------------
{ {
name: "hadith", name: "hadith",
path: "/hadith", path: "/hadith",
file: "~/systems/hadith_ui/pages/hadith/index.vue", file: "~/systems/hadith_ui/pages/hadith/index.vue",
},
{
name: "hadithSearch",
path: "/hadith/search",
file: "~/systems/hadith_ui/pages/hadith/search/index.vue",
},
{
name: "hadithChatBot",
path: "/hadith/chat-bot",
file: "~/systems/hadith_ui/pages/hadith/chat-bot.vue",
},
{
name: "hadithFavorites",
path: "/hadith/favorites",
file: "~/systems/hadith_ui/pages/hadith/favorites/index.vue",
},
{
name: "hadithLibrary",
path: "/hadith/library",
file: "~/systems/hadith_ui/pages/hadith/library/index.vue",
},
{
name: "hadithLibraryShow",
path: "/hadith/library/:id/:slug?",
file: "~/systems/hadith_ui/pages/hadith/library/[id]/[slug]/index.vue",
},
{
name: "hadithAbout",
path: "/hadith/about-us",
file: "~/systems/hadith_ui/pages/hadith/public-pages/about-us.vue",
},
{
name: "hadithContact",
path: "/hadith/contact-us",
file: "~/systems/hadith_ui/pages/hadith/public-pages/ContactUs.vue",
},
{
name: "hadithRules",
path: "/hadith/rules",
file: "~/systems/hadith_ui/pages/hadith/public-pages/rules.vue",
} }
// --------------------- end: hadith routes ---------------------
); );
}, },
}, },

24
package-lock.json generated
View File

@ -11913,8 +11913,6 @@
}, },
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"inBundle": true, "inBundle": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -12573,8 +12571,6 @@
}, },
"node_modules/npm/node_modules/cross-spawn/node_modules/which": { "node_modules/npm/node_modules/cross-spawn/node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -13196,8 +13192,6 @@
}, },
"node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": {
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -13220,8 +13214,6 @@
}, },
"node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": {
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -13244,8 +13236,6 @@
}, },
"node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": {
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -13271,8 +13261,6 @@
}, },
"node_modules/npm/node_modules/minizlib/node_modules/minipass": { "node_modules/npm/node_modules/minizlib/node_modules/minipass": {
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -13407,8 +13395,6 @@
}, },
"node_modules/npm/node_modules/nopt/node_modules/abbrev": { "node_modules/npm/node_modules/nopt/node_modules/abbrev": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
@ -14029,8 +14015,6 @@
}, },
"node_modules/npm/node_modules/tar/node_modules/fs-minipass": { "node_modules/npm/node_modules/tar/node_modules/fs-minipass": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -14042,8 +14026,6 @@
}, },
"node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -14055,8 +14037,6 @@
}, },
"node_modules/npm/node_modules/tar/node_modules/minipass": { "node_modules/npm/node_modules/tar/node_modules/minipass": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
"inBundle": true, "inBundle": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
@ -14218,8 +14198,6 @@
}, },
"node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"inBundle": true, "inBundle": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -14254,8 +14232,6 @@
}, },
"node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"inBundle": true, "inBundle": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@ -11,7 +11,8 @@
"postinstall": "nuxt prepare", "postinstall": "nuxt prepare",
"dev-tavasi": "env-cmd -f .env.tavasi nuxt dev --host --inspect", "dev-tavasi": "env-cmd -f .env.tavasi nuxt dev --host --inspect",
"dev-monir": "env-cmd -f .env.monir nuxt dev --host --inspect", "dev-monir": "env-cmd -f .env.monir nuxt dev --host --inspect",
"dev-hadith": "env-cmd -f .env.hadith nuxt dev --host --inspect" "dev-hadith": "env-cmd -f .env.hadith nuxt dev --host --inspect",
"build-hadith": "env-cmd -f .env.hadith nuxt build"
}, },
"dependencies": { "dependencies": {
"@nuxt/image": "^1.8.1", "@nuxt/image": "^1.8.1",

View File

@ -64,7 +64,6 @@ import { mapState, mapActions } from "pinia";
import searchApi from "~/apis/searchApi"; import searchApi from "~/apis/searchApi";
import { useStorage } from "@vueuse/core"; import { useStorage } from "@vueuse/core";
import { useCommonStore } from "~/stores/commonStore"; import { useCommonStore } from "~/stores/commonStore";
import { useSearchStore } from "~/stores/searchStore";
export default { export default {
name: "guidesList", name: "guidesList",
@ -75,8 +74,7 @@ export default {
}); });
}, },
computed: { computed: {
...mapState(useSearchStore, ["helpSchemaGetter"]), ...mapState(useCommonStore, ["organNameGetter","helpSchemaGetter"]),
...mapState(useCommonStore, ["organNameGetter"]),
// ...mapState(["organNameGetter"]), // ...mapState(["organNameGetter"]),
@ -174,7 +172,7 @@ export default {
}, },
methods: { methods: {
// ...mapActions("search", ["helpSchemaSetter"]), // ...mapActions("search", ["helpSchemaSetter"]),
...mapActions(useSearchStore, ["helpSchemaSetter"]), ...mapActions(useCommonStore, ["helpSchemaSetter"]),
openModal(componentName, title) { openModal(componentName, title) {
this.openSubjectForm = true; this.openSubjectForm = true;
this.slotComponentName = componentName; this.slotComponentName = componentName;

View File

@ -84,7 +84,6 @@ import adminMenu from "~/json/admin/json/menu.json";
import { mapState, mapActions } from "pinia"; import { mapState, mapActions } from "pinia";
import { useStorage } from "@vueuse/core"; import { useStorage } from "@vueuse/core";
import { useCommonStore } from "~/stores/commonStore"; import { useCommonStore } from "~/stores/commonStore";
import { useSearchStore } from "~/stores/searchStore";
export default { export default {
name: "adminGuides", name: "adminGuides",
@ -99,8 +98,7 @@ export default {
this.httpService = useNuxtApp()["$http"]; this.httpService = useNuxtApp()["$http"];
}, },
computed: { computed: {
...mapState(useSearchStore, ["helpSchemaGetter"]), ...mapState(useCommonStore, ["organNameGetter","helpSchemaGetter"]),
...mapState(useCommonStore, ["organNameGetter"]),
}, },
mounted() { mounted() {
let localStoageHelpSchema = useStorage("settingSchema", undefined).value; let localStoageHelpSchema = useStorage("settingSchema", undefined).value;
@ -142,7 +140,7 @@ export default {
}, },
methods: { methods: {
// ...mapActions("search", ["helpSchemaSetter"]), // ...mapActions("search", ["helpSchemaSetter"]),
...mapActions(useSearchStore, ["helpSchemaSetter"]), ...mapActions(useCommonStore, ["helpSchemaSetter"]),
// searchStore // searchStore
select(e) { select(e) {
this.value = e; this.value = e;

View File

@ -4,7 +4,11 @@
<template v-if="canView"> <template v-if="canView">
<div class="container-fluid no-gutters"> <div class="container-fluid no-gutters">
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-6 col-lg-3" v-for="project in projects" :key="project.id"> <div
class="col-sm-12 col-md-6 col-lg-3"
v-for="project in projects"
:key="project.id"
>
<a <a
@click.prevent="redirectTo(project)" @click.prevent="redirectTo(project)"
:href="project.link" :href="project.link"
@ -13,7 +17,8 @@
:title="project.title" :title="project.title"
> >
<div class="row no-gutters card-hover flex-grow-1"> <div class="row no-gutters card-hover flex-grow-1">
<div class="col-md-2 d-flex justify-content-center align-items-center" <div
class="col-md-2 d-flex justify-content-center align-items-center"
> >
<img <img
:src="projectIcon(project.link)" :src="projectIcon(project.link)"
@ -22,14 +27,13 @@
/> />
</div> </div>
<div class="col-md-10 d-flex align-items-center"> <div class="col-md-10 d-flex align-items-center">
<div class="card-body text-dark"> <div class="card-body text-dark">
<h5 class="card-title"> <h5 class="card-title">
{{ $t(project.link )}} {{ $t(project.link) }}
</h5> </h5>
<p class="card-text"> <p class="card-text">
{{ $t(project.link+'Description') }} {{ $t(project.link + "Description") }}
</p> </p>
</div> </div>
</div> </div>
@ -44,8 +48,12 @@
<the-content-loading v-if="fetchingData"></the-content-loading> <the-content-loading v-if="fetchingData"></the-content-loading>
<div v-else class="d-flex justify-content-center align-items-center"> <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"> <div
<span class="tavasi tavasi-warning-circle color-inherit ms-1 text__32"></span> 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>
{{ $t("NoFindData") }} {{ $t("NoFindData") }}
</div> </div>
</div> </div>
@ -55,8 +63,10 @@
</template> </template>
<script> <script>
import apis from "@permission/permitApi"; import apis from "@apis/permitApi";
import { mapGetters, mapMutations, mapActions } from "vuex"; import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
import { usePermitStore } from "~/stores/permitStore";
export default { export default {
data() { data() {
@ -67,11 +77,11 @@ export default {
}; };
}, },
computed: { computed: {
...mapGetters("permit", ["projectGetter"]), ...mapState(usePermitStore, ["projectGetter"]),
}, },
methods: { methods: {
...mapMutations("permit", ["SET_PROJECT"]), ...mapActions(usePermitStore, ["SET_PROJECT"]),
...mapActions(["checkPermissions"]), ...mapActions(useCommonStore, ["checkPermissions"]),
projectIcon(name) { projectIcon(name) {
try { try {

View File

@ -61,7 +61,7 @@
</template> </template>
<script> <script>
// import apis from "@permission/permitApi"; // import apis from "@apis/permitApi";
import apis from "~/apis/permitApi"; import apis from "~/apis/permitApi";
import adminMenu from "~/json/admin/json/menu.json"; import adminMenu from "~/json/admin/json/menu.json";
import { defineAsyncComponent } from "vue"; import { defineAsyncComponent } from "vue";

View File

@ -182,18 +182,19 @@
</template> </template>
<script> <script>
import apis from "@permission/permitApi"; import apis from "@apis/permitApi";
import { mapGetters } from "vuex"; import { mapState } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
export default { export default {
name: "UserAccessCustomization", name: "UserAccessCustomization",
components: { components: {
BreadCrumb: () => import("@components/BreadCrumb.vue"), BreadCrumb: () => import("@components/global/BreadCrumb.vue"),
Share: () => import("@view/modal/Share.vue"), Share: () => import("@components/admin/modal/Share.vue"),
Accordion: () => import("@permission/components/Accordion.vue"), Accordion: () => import("@components/admin/components/Accordion.vue"),
}, },
computed: { computed: {
...mapGetters(["projectGetter"]), ...mapState(useCommonStore,["projectGetter"]),
}, },
props: { props: {
items: { items: {

View File

@ -92,9 +92,9 @@
</template> </template>
<script> <script>
// import apis from "@permission/permitApi"; // import apis from "@apis/permitApi";
// import { mapGetters, mapMutations, mapActions } from "vuex"; // import { mapGetters, mapMutations, mapActions } from "vuex";
// import Share from "@permission/modal/Share.vue"; // import Share from "@apis/modal/Share.vue";
import apis from "~/apis/permitApi"; import apis from "~/apis/permitApi";
import adminMenu from "~/json/admin/json/menu.json"; import adminMenu from "~/json/admin/json/menu.json";
import { defineAsyncComponent } from "vue"; import { defineAsyncComponent } from "vue";
@ -501,7 +501,7 @@ export default {
}, },
components: { components: {
// BreadCrumb: () => import("@components/BreadCrumb.vue"), // BreadCrumb: () => import("@components/BreadCrumb.vue"),
// Accordion: () => import("@permission/components/Accordion.vue"), // Accordion: () => import("@components/Accordion.vue"),
// SubHeaderWithSelect: defineAsyncComponent(() => // SubHeaderWithSelect: defineAsyncComponent(() =>
// import("@/components/global/SubHeaderWithSelect.vue") // import("@/components/global/SubHeaderWithSelect.vue")
// ), // ),

View File

@ -57,11 +57,11 @@
<div class="form-row"> <div class="form-row">
<div class="col"> <div class="col">
<label for="" class="mt-2">توضیح مفصل:</label> <label for="" class="mt-2">توضیح مفصل:</label>
<VueEditor <!-- <VueEditor
dir="rtl" dir="rtl"
v-model="editorData" v-model="editorData"
:editorOptions="editorOptions" :editorOptions="editorOptions"
></VueEditor> ></VueEditor> -->
</div> </div>
</div> </div>
</form> </form>
@ -72,7 +72,8 @@
<script> <script>
import settingsApi from "~/apis/settingsApi"; import settingsApi from "~/apis/settingsApi";
import { VueEditor } from "vue2-editor"; // todo: install vueeditor for nuxt3/vue3
// import { VueEditor } from "vue2-editor";
import { mapState, mapActions } from "pinia"; import { mapState, mapActions } from "pinia";
import searchApi from "~/apis/searchApi"; import searchApi from "~/apis/searchApi";
import { useStorage } from "@vueuse/core"; import { useStorage } from "@vueuse/core";

View File

@ -17,7 +17,7 @@
<script> <script>
import { mapState, mapActions } from "pinia"; import { mapState, mapActions } from "pinia";
import menu from "@dashboard/default/json/menu.json"; import menu from "@json/dashboard/default/json/menu.json";
import {clearBodyClass} from "@manuals/utilities" import {clearBodyClass} from "@manuals/utilities"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,52 @@
<svg width="64" height="25" viewBox="0 0 64 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M36.0096 17.6483C37.4078 17.6483 38.5034 17.4396 39.2965 17.0223C40.1103 16.6049 40.6947 15.9788 41.0495 15.1441L39.2965 5.09567L40.5799 4.43829L42.3642 14.7371C42.5103 15.5301 42.9068 16.2188 43.5537 16.8031C44.2215 17.3666 45.0876 17.6483 46.1519 17.6483H47.4667C47.6545 17.6483 47.811 17.7318 47.9362 17.8988C48.0823 18.0657 48.1553 18.264 48.1553 18.4935C48.1553 18.7231 48.0823 18.9213 47.9362 19.0883C47.811 19.2552 47.6545 19.3387 47.4667 19.3387H46.4336C45.2441 19.3387 44.2424 19.0883 43.4285 18.5874C42.6146 18.0657 42.0512 17.3666 41.7381 16.4901C41.2999 17.3875 40.6112 18.0866 39.6721 18.5874C38.733 19.0883 37.5539 19.3387 36.1348 19.3387H33.114L32.9575 17.6483H36.0096Z" fill="url(#paint0_linear_344_2248)"/>
<path d="M47.4094 19.3387C47.2216 19.3387 47.0651 19.2552 46.9399 19.0883C46.7938 18.9213 46.7208 18.7231 46.7208 18.4935C46.7208 18.2431 46.7938 18.0448 46.9399 17.8988C47.0651 17.7318 47.2216 17.6483 47.4094 17.6483H59.8682L58.9917 11.1998C58.783 9.80161 58.3134 8.75816 57.583 8.06949C56.8735 7.35994 55.9448 7.00517 54.797 7.00517C54.5466 7.00517 54.1501 7.04691 53.6075 7.13039L49.7572 7.75645L49.9137 6.06607L53.5762 5.47131C54.0144 5.4087 54.4318 5.3774 54.8283 5.3774C56.3309 5.3774 57.5726 5.83651 58.5534 6.75475C59.5552 7.65211 60.1708 8.92512 60.4003 10.5738L61.3707 17.6483H64.0002L63.5307 19.3387H47.4094Z" fill="url(#paint1_linear_344_2248)"/>
<path d="M24.9984 17.6481C26.2506 17.6481 27.2627 17.4185 28.0348 16.9594C28.8279 16.5003 29.3705 15.8429 29.6626 14.9873L27.8783 5.97193L29.287 5.34586L30.8209 12.9526C30.9043 13.37 30.9461 13.8291 30.9461 14.3299C30.9461 15.8534 30.4243 17.0742 29.3809 17.9924C28.3583 18.8898 26.9184 19.3385 25.061 19.3385C21.3002 19.3385 21.1849 17.6481 24.9984 17.6481Z" fill="#1B2132"/>
<path d="M17.3823 17.0222C18.1962 16.6049 18.7805 15.9788 19.1353 15.144L17.5295 7.59986L18.813 6.94249L20.2686 13.2736L20.4501 14.7371C20.5961 15.5301 20.9927 16.2188 21.6396 16.8031C22.3074 17.3666 23.1735 17.6483 24.2378 17.6483H25.5525C25.7403 17.6483 25.8968 17.7318 26.0221 17.8987C26.1681 18.0657 26.2412 18.2639 26.2412 18.4935C26.2412 18.7231 26.1681 18.9213 26.0221 19.0883C25.8968 19.2552 25.7403 19.3387 25.5525 19.3387H24.5195C23.33 19.3387 22.3283 19.0883 21.5144 18.5874C20.7005 18.0657 20.137 17.3666 19.824 16.4901C19.3857 17.3875 18.6971 18.0866 17.758 18.5874L17.3823 17.0222Z" fill="#1B2132"/>
<path d="M25.4953 19.3387C25.3075 19.3387 25.1509 19.2552 25.0257 19.0883C24.8797 18.9213 24.8066 18.7231 24.8066 18.4935C24.8066 18.2431 24.8797 18.0448 25.0257 17.8987C25.1509 17.7318 25.3075 17.6483 25.4953 17.6483V19.3387Z" fill="#1B2132"/>
<path d="M7.2878 19.3381C5.70176 19.3381 4.44962 18.8998 3.53139 18.0233C2.61316 17.1469 2.15404 15.8843 2.15404 14.2356V3.29512L0.606445 3.78424V2.02342L3.50008 1.08821V13.7348C3.50008 16.3434 4.76266 17.6477 7.2878 17.6477H8.00778C8.1956 17.6477 8.35211 17.7312 8.47733 17.8981C8.62341 18.0651 8.69645 18.2633 8.69645 18.4929C8.69645 18.7225 8.62341 18.9207 8.47733 19.0877C8.35211 19.2546 8.1956 19.3381 8.00778 19.3381H7.2878Z" fill="url(#paint2_linear_344_2248)"/>
<path d="M7.96767 19.3381C7.77985 19.3381 7.62333 19.2546 7.49812 19.0877C7.35203 18.9207 7.27899 18.7225 7.27899 18.4929C7.27899 18.2633 7.35203 18.0651 7.49812 17.8981C7.62333 17.7312 7.77985 17.6477 7.96767 17.6477H11.8806C12.0684 17.6477 12.2249 17.7312 12.3501 17.8981C12.4962 18.0651 12.5693 18.2633 12.5693 18.4929C12.5693 18.7225 12.4962 18.9207 12.3501 19.0877C12.2249 19.2546 12.0684 19.3381 11.8806 19.3381H7.96767Z" fill="url(#paint3_linear_344_2248)"/>
<path d="M11.8493 19.3381C11.6615 19.3381 11.505 19.2546 11.3797 19.0877C11.2337 18.9207 11.1606 18.7225 11.1606 18.4929C11.1606 18.2425 11.2337 18.0442 11.3797 17.8981C11.505 17.7312 11.6615 17.6477 11.8493 17.6477H14.3849C15.637 17.6477 16.6491 17.4181 17.4213 16.959C18.2143 16.4999 18.7569 15.8425 19.0491 14.9869L17.4213 7.50149L18.83 6.87542L20.2073 12.9522C20.2908 13.3696 20.3325 13.8287 20.3325 14.3295C20.3325 15.853 19.8108 17.0738 18.7673 17.992C17.7448 18.8894 16.3048 19.3381 14.4475 19.3381H11.8493Z" fill="url(#paint4_linear_344_2248)"/>
<path d="M9.69727 3.04489H16.2397V4.76658H9.69727V3.04489Z" fill="url(#paint5_linear_344_2248)"/>
<path d="M11.7584 0.215851H13.9105V1.97667H11.7584V0.215851Z" fill="url(#paint6_linear_344_2248)"/>
<path d="M23.0732 22.9774H29.5844V24.6991H23.0732V22.9774Z" fill="#1B2132"/>
<defs>
<linearGradient id="paint0_linear_344_2248" x1="32.8895" y1="7.84648" x2="38.5865" y2="12.6934" gradientUnits="userSpaceOnUse">
<stop stop-color="#84FFC8"/>
<stop offset="0.419292" stop-color="#00E03C"/>
<stop offset="1" stop-color="#1B2132"/>
</linearGradient>
<linearGradient id="paint1_linear_344_2248" x1="32.8895" y1="7.84648" x2="38.5865" y2="12.6934" gradientUnits="userSpaceOnUse">
<stop stop-color="#84FFC8"/>
<stop offset="0.419292" stop-color="#00E03C"/>
<stop offset="1" stop-color="#1B2132"/>
</linearGradient>
<linearGradient id="paint2_linear_344_2248" x1="0.143793" y1="-2.0274" x2="11.5175" y2="-0.647003" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="0.245187" stop-color="#4D00FF"/>
<stop offset="1" stop-color="#1B2132"/>
</linearGradient>
<linearGradient id="paint3_linear_344_2248" x1="0.143793" y1="-2.0274" x2="11.5175" y2="-0.647003" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="0.245187" stop-color="#4D00FF"/>
<stop offset="1" stop-color="#1B2132"/>
</linearGradient>
<linearGradient id="paint4_linear_344_2248" x1="0.143793" y1="-2.0274" x2="11.5175" y2="-0.647003" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="0.245187" stop-color="#4D00FF"/>
<stop offset="1" stop-color="#1B2132"/>
</linearGradient>
<linearGradient id="paint5_linear_344_2248" x1="9.54382" y1="-0.561046" x2="25.143" y2="2.76377" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="0.245187" stop-color="#4D00FF"/>
<stop offset="0.410433"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint6_linear_344_2248" x1="9.54382" y1="-0.561046" x2="25.143" y2="2.76377" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="0.245187" stop-color="#4D00FF"/>
<stop offset="0.410433"/>
<stop offset="1"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
public/img/location.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

BIN
public/img/no-data.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,3 @@
<svg width="140" height="201" viewBox="0 0 140 201" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.28418" width="140" height="200" rx="8" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 174 B

BIN
public/img/save-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
public/img/save.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

View File

@ -22,13 +22,16 @@ import type {
import type { researchTerms } from "~/types/researchTypes"; import type { researchTerms } from "~/types/researchTypes";
import type { ActiveEntityViewSchema, ActiveTab } from "~/types/entityType"; import type { ActiveEntityViewSchema, ActiveTab } from "~/types/entityType";
import type { Domain } from "~/types/searchTypes"; import type { Domain, helpActiveSchema, helpSchema } from "~/types/searchTypes";
export const useCommonStore = defineStore("commonStore", { export const useCommonStore = defineStore("commonStore", {
persist: { persist: {
storage: piniaPluginPersistedstate.localStorage(), storage: piniaPluginPersistedstate.localStorage(),
}, },
state: () => ({ state: () => ({
// admin
helpSchema: undefined as helpSchema | undefined,
helpActiveSchema: undefined as helpActiveSchema | undefined,
// from search // from search
domainActive: undefined as Domain | undefined, domainActive: undefined as Domain | undefined,
@ -86,6 +89,13 @@ export const useCommonStore = defineStore("commonStore", {
sidebarMenu: {}, sidebarMenu: {},
}), }),
getters: { getters: {
// admin
helpSchemaGetter(state) {
return state.helpSchema;
},
helpActiveSchemaGetter(state) {
return state.helpActiveSchema;
},
// from search // from search
domainActiveGetter(state) { domainActiveGetter(state) {
return state.domainActive; return state.domainActive;
@ -145,6 +155,13 @@ export const useCommonStore = defineStore("commonStore", {
isShowHilightGetter: (state) => state.isShowHilight, isShowHilightGetter: (state) => state.isShowHilight,
}, },
actions: { actions: {
// admin
helpSchemaSetter(helpSchema = undefined) {
this.helpSchema = helpSchema;
},
helpActiveSchemaSetter(helpActiveSchema = undefined) {
this.helpActiveSchema = helpActiveSchema;
},
// from search // from search
domainActiveSetter(domain = undefined) { domainActiveSetter(domain = undefined) {
this.domainActive = domain; this.domainActive = domain;

@ -1 +1 @@
Subproject commit 49b47bb97fa7394c84ba16a340e08c1fac5384a1 Subproject commit 29e3034e3fa2e28142ae58934b9bad4dc2ce98f4