base_ui/components/forms/InputSelectVueTribute.vue

405 lines
11 KiB
Vue
Raw Permalink Normal View History

2025-02-01 09:34:55 +00:00
<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>