552 lines
14 KiB
Vue
552 lines
14 KiB
Vue
![]() |
<template>
|
||
|
<div class="form-row form-group" :key="$attrs.key">
|
||
|
<vue-tribute class="tribute-container" :options="tributeOptions">
|
||
|
<div class="ta-header">
|
||
|
<div class="ta-type-selection">
|
||
|
<multiselect
|
||
|
v-model="types[0]"
|
||
|
id="group-filter"
|
||
|
placeholder=""
|
||
|
track-by="id"
|
||
|
label="title"
|
||
|
:options="types"
|
||
|
:searchable="true"
|
||
|
:options-limit="300"
|
||
|
:limit="10"
|
||
|
:max-height="350"
|
||
|
selectLabel=""
|
||
|
selectedLabel=""
|
||
|
deselectLabel=""
|
||
|
:close-on-select="true"
|
||
|
:clear-on-select="false"
|
||
|
:preserve-search="true"
|
||
|
>
|
||
|
<!-- <template slot="selection" slot-scope="{ values, search, isOpen }"
|
||
|
><span
|
||
|
class="multiselect__single"
|
||
|
v-if="values.length"
|
||
|
v-show="!isOpen"
|
||
|
>{{ values.length }} فیلتر</span
|
||
|
></template
|
||
|
> -->
|
||
|
<!-- <template slot="noResult" slot-scope="{ values, search, isOpen }">
|
||
|
چیزی یافت نشد.
|
||
|
</template>
|
||
|
<template slot="noOptions" slot-scope="{ values, search, isOpen }">
|
||
|
فهرست خالی است.
|
||
|
</template> -->
|
||
|
</multiselect>
|
||
|
</div>
|
||
|
|
||
|
<div class="ta-options">
|
||
|
<div class="ta-options-item">
|
||
|
<svg role="graphics-symbol" viewBox="0 0 14 16" class="copy">
|
||
|
<path
|
||
|
d="M2.404 15.322h5.701c1.26 0 1.887-.662 1.887-1.927V12.38h1.154c1.254 0 1.91-.662 1.91-1.928V5.555c0-.774-.158-1.266-.626-1.74L9.512.837C9.066.387 8.545.21 7.865.21H5.463c-1.254 0-1.91.662-1.91 1.928v1.084H2.404c-1.254 0-1.91.668-1.91 1.933v8.239c0 1.265.656 1.927 1.91 1.927zm7.588-6.62c0-.792-.1-1.161-.592-1.665L6.225 3.814c-.452-.462-.844-.58-1.5-.591V2.215c0-.533.28-.832.843-.832h2.38v2.883c0 .726.386 1.113 1.107 1.113h2.83v4.998c0 .539-.276.832-.844.832H9.992V8.701zm-.79-4.29c-.206 0-.288-.088-.288-.287V1.594l2.771 2.818H9.201zM2.503 14.15c-.563 0-.844-.293-.844-.832V5.232c0-.539.281-.837.85-.837h1.91v3.187c0 .85.416 1.26 1.26 1.26h3.14v4.476c0 .54-.28.832-.843.832H2.504zM5.79 7.816c-.24 0-.346-.105-.346-.345V4.547l3.223 3.27H5.791z"
|
||
|
></path>
|
||
|
</svg>
|
||
|
کپی
|
||
|
</div>
|
||
|
|
||
|
<div class="ta-options-item">کپشن</div>
|
||
|
|
||
|
<div class="ta-options-item">
|
||
|
<div class="dropdown">
|
||
|
<button
|
||
|
class="btn btn-secondary dropdown-toggle"
|
||
|
type="button"
|
||
|
>
|
||
|
<svg
|
||
|
role="graphics-symbol"
|
||
|
viewBox="0 0 13 3"
|
||
|
class="dots"
|
||
|
style="
|
||
|
width: 14px;
|
||
|
height: 14px;
|
||
|
display: block;
|
||
|
fill: inherit;
|
||
|
flex-shrink: 0;
|
||
|
"
|
||
|
>
|
||
|
<g>
|
||
|
<path
|
||
|
d="M3,1.5A1.5,1.5,0,1,1,1.5,0,1.5,1.5,0,0,1,3,1.5Z"
|
||
|
></path>
|
||
|
<path
|
||
|
d="M8,1.5A1.5,1.5,0,1,1,6.5,0,1.5,1.5,0,0,1,8,1.5Z"
|
||
|
></path>
|
||
|
<path
|
||
|
d="M13,1.5A1.5,1.5,0,1,1,11.5,0,1.5,1.5,0,0,1,13,1.5Z"
|
||
|
></path>
|
||
|
</g>
|
||
|
</svg>
|
||
|
</button>
|
||
|
|
||
|
<div class="dropdown-menu" aria-labelledby="dropdownMenu2">
|
||
|
<button class="dropdown-item" type="button">Action</button>
|
||
|
<button class="dropdown-item" type="button">
|
||
|
Another action
|
||
|
</button>
|
||
|
<button class="dropdown-item" type="button">
|
||
|
Something else here
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<textarea
|
||
|
@tribute-no-match="noMatchFound"
|
||
|
@tribute-replaced="textReplaced"
|
||
|
:ref="localFormElement.key"
|
||
|
class="form-control"
|
||
|
@focus="clearErrors"
|
||
|
@blur="validate"
|
||
|
@change="validate"
|
||
|
:placeholder="localFormElement.placeholder"
|
||
|
:id="localFormElement.key"
|
||
|
:name="localFormElement.key"
|
||
|
v-model="textValue"
|
||
|
cols="1"
|
||
|
rows="1"
|
||
|
>
|
||
|
</textarea>
|
||
|
|
||
|
<div class="ta-footer">
|
||
|
<input
|
||
|
class="form-control ta-footer-input"
|
||
|
type="text"
|
||
|
value="فریم وظیفه"
|
||
|
/>
|
||
|
</div>
|
||
|
</vue-tribute>
|
||
|
|
||
|
<context-menu
|
||
|
style="position: static; display: inline-flex"
|
||
|
v-if="contextMenu.length"
|
||
|
:id="'context-menu-' + localFormElement.key"
|
||
|
:contextMenu="contextMenu"
|
||
|
@other="methodName($event)"
|
||
|
>
|
||
|
</context-menu>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import formBuilderMixin from "~/extensions/formBuilderExtension";
|
||
|
|
||
|
import VueTribute from "vue-tribute";
|
||
|
import apis from "~/apis/borhanApi.js";
|
||
|
|
||
|
export default {
|
||
|
props: {
|
||
|
enableSuggestion: {
|
||
|
default: false,
|
||
|
},
|
||
|
contextMenu: {
|
||
|
default() {
|
||
|
return [];
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
extends: formBuilderMixin,
|
||
|
|
||
|
data() {
|
||
|
return {
|
||
|
types: [
|
||
|
{
|
||
|
id: "1",
|
||
|
title: "javascript",
|
||
|
},
|
||
|
{
|
||
|
id: "2",
|
||
|
title: "PHP",
|
||
|
},
|
||
|
{
|
||
|
id: "3",
|
||
|
title: "SpareQL",
|
||
|
},
|
||
|
{
|
||
|
id: "4",
|
||
|
title: "Paython",
|
||
|
},
|
||
|
{
|
||
|
id: "5",
|
||
|
title: "BASIC",
|
||
|
},
|
||
|
],
|
||
|
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 large",
|
||
|
|
||
|
// 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.value;
|
||
|
// return "@" + item.original.value;
|
||
|
},
|
||
|
|
||
|
// template for displaying item in menu
|
||
|
menuItemTemplate: function (item) {
|
||
|
return item.string;
|
||
|
},
|
||
|
|
||
|
// 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: "key",
|
||
|
|
||
|
// column that contains the content to insert by default
|
||
|
fillAttr: "value",
|
||
|
|
||
|
// REQUIRED: array of objects to match or a function that returns data (see 'Loading remote data' for an example)
|
||
|
values: [
|
||
|
{
|
||
|
key: "سلام",
|
||
|
value: "سلام",
|
||
|
},
|
||
|
{
|
||
|
key: "باسلام",
|
||
|
value: "باسلام",
|
||
|
},
|
||
|
{
|
||
|
key: "علیک سلام",
|
||
|
value: "علیک سلام",
|
||
|
},
|
||
|
{
|
||
|
key: "بی سلام",
|
||
|
value: "بی سلام",
|
||
|
},
|
||
|
{
|
||
|
key: "صدتا سلام",
|
||
|
value: "صدتا سلام",
|
||
|
},
|
||
|
],
|
||
|
// 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>",
|
||
|
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,
|
||
|
},
|
||
|
httpService: undefined,
|
||
|
};
|
||
|
},
|
||
|
mounted() {
|
||
|
this.httpService = new HttpService(import.meta.env.VITE_BASE_URL);
|
||
|
},
|
||
|
methods: {
|
||
|
limitText(count) {
|
||
|
return `و ${count} کاربر دیگر`;
|
||
|
},
|
||
|
noMatchFound(args) {
|
||
|
},
|
||
|
textReplaced(args) {
|
||
|
},
|
||
|
methodName(action, index = 0) {
|
||
|
try {
|
||
|
this[action](index);
|
||
|
} catch (err) {
|
||
|
this.$emit(action, index);
|
||
|
}
|
||
|
},
|
||
|
remoteSearch(input, callback) {
|
||
|
|
||
|
return this.httpService
|
||
|
.getRequest(apis.concept.annotations.read + "?ontology_id=" + input)
|
||
|
.then((res) => {
|
||
|
callback(res.data);
|
||
|
})
|
||
|
.catch((e) => {
|
||
|
callback([]);
|
||
|
})
|
||
|
.finally(() => {
|
||
|
this.fetchingData = false;
|
||
|
});
|
||
|
},
|
||
|
},
|
||
|
|
||
|
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<!-- #region tribute -->
|
||
|
<style scoped lang="scss">
|
||
|
.multiselect {
|
||
|
font-size: 11px;
|
||
|
-webkit-box-sizing: content-box;
|
||
|
box-sizing: content-box;
|
||
|
display: block;
|
||
|
position: relative;
|
||
|
width: 100%;
|
||
|
min-height: 30px;
|
||
|
text-align: left;
|
||
|
color: #35495e;
|
||
|
|
||
|
&.multiselect--active {
|
||
|
background-color: #fff;
|
||
|
z-index: 999999;
|
||
|
}
|
||
|
}
|
||
|
.multiselect__content-wrapper {
|
||
|
z-index: 9999;
|
||
|
}
|
||
|
.multiselect__select {
|
||
|
position: absolute;
|
||
|
width: 40px;
|
||
|
height: 33px;
|
||
|
right: 1px;
|
||
|
top: 1px;
|
||
|
padding: 4px 8px;
|
||
|
text-align: center;
|
||
|
-webkit-transition: -webkit-transform 0.2s ease;
|
||
|
transition: -webkit-transform 0.2s ease;
|
||
|
transition: transform 0.2s ease;
|
||
|
transition: transform 0.2s ease, -webkit-transform 0.2s ease;
|
||
|
|
||
|
&::before {
|
||
|
position: relative;
|
||
|
right: 0;
|
||
|
top: unset;
|
||
|
color: #999;
|
||
|
margin-top: 0;
|
||
|
border: none;
|
||
|
background-size: contain;
|
||
|
width: 2em;
|
||
|
height: 2em;
|
||
|
display: inline-block;
|
||
|
background-repeat: no-repeat;
|
||
|
background-image: url("../../assets/common/img/Component-25--1.svg");
|
||
|
}
|
||
|
}
|
||
|
.multiselect__tags {
|
||
|
min-height: 30px;
|
||
|
display: block;
|
||
|
padding: 8px 40px 0 8px;
|
||
|
border-radius: 5px;
|
||
|
border: 1px solid #e8e8e8;
|
||
|
background: #fff;
|
||
|
font-size: 14px;
|
||
|
border-color: transparent;
|
||
|
background: transparent;
|
||
|
}
|
||
|
[dir="rtl"] .multiselect__tags {
|
||
|
padding: 5px 5px 0 30px;
|
||
|
}
|
||
|
.multiselect__input,
|
||
|
.multiselect__single {
|
||
|
position: relative;
|
||
|
display: inline-block;
|
||
|
min-height: 20px;
|
||
|
line-height: 20px;
|
||
|
border: none;
|
||
|
border-radius: 5px;
|
||
|
background: transparent;
|
||
|
padding: 0 0 0 5px;
|
||
|
width: 100%;
|
||
|
-webkit-transition: border 0.1s ease;
|
||
|
transition: border 0.1s ease;
|
||
|
-webkit-box-sizing: border-box;
|
||
|
box-sizing: border-box;
|
||
|
margin-bottom: 8px;
|
||
|
vertical-align: top;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
.form-group {
|
||
|
&:hover {
|
||
|
.ta-header,
|
||
|
.ta-options {
|
||
|
opacity: 1;
|
||
|
visibility: visible;
|
||
|
transition: opacity 300ms ease-in 0s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&.active,
|
||
|
&:active {
|
||
|
.ta-header,
|
||
|
.ta-options {
|
||
|
opacity: 1;
|
||
|
visibility: visible;
|
||
|
transition: opacity 300ms ease-in 0s;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</style>
|
||
|
<!-- #endregion tribute -->
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
.ta-header {
|
||
|
position: absolute;
|
||
|
top: 3px;
|
||
|
right: 8px;
|
||
|
left: 1px;
|
||
|
|
||
|
display: flex;
|
||
|
justify-content: space-between;
|
||
|
|
||
|
opacity: 0;
|
||
|
visibility: hidden;
|
||
|
|
||
|
transition: opacity 300ms ease-in 0s;
|
||
|
|
||
|
.ta-type-selection {
|
||
|
// position: absolute;
|
||
|
// top: 8px;
|
||
|
// right: 8px;
|
||
|
z-index: 1;
|
||
|
color: rgba(55, 53, 47, 0.65);
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
justify-content: flex-end;
|
||
|
opacity: 1;
|
||
|
transition: opacity 300ms ease-in 0s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.ta-options {
|
||
|
opacity: 0;
|
||
|
visibility: hidden;
|
||
|
|
||
|
// position: absolute;
|
||
|
// top: 3px;
|
||
|
// left: 1px;
|
||
|
z-index: 1;
|
||
|
color: rgba(55, 53, 47, 0.65);
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
justify-content: flex-end;
|
||
|
height: 25px;
|
||
|
font-size: 11.5px;
|
||
|
transition: opacity 300ms ease-in 0s;
|
||
|
|
||
|
.ta-options-item {
|
||
|
user-select: none;
|
||
|
transition: background 20ms ease-in 0s;
|
||
|
cursor: pointer;
|
||
|
display: inline-flex;
|
||
|
align-items: center;
|
||
|
white-space: nowrap;
|
||
|
height: 25px;
|
||
|
border-radius: 4px 0px 0px 4px;
|
||
|
font-size: 11.5px;
|
||
|
line-height: 1.2;
|
||
|
padding: 4px 6px;
|
||
|
color: rgb(55, 53, 47);
|
||
|
background: rgb(234, 233, 229);
|
||
|
font-weight: 400;
|
||
|
|
||
|
svg {
|
||
|
width: 16px;
|
||
|
height: 16px;
|
||
|
display: block;
|
||
|
fill: inherit;
|
||
|
flex-shrink: 0;
|
||
|
padding-right: 4px;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.ta-footer {
|
||
|
background: white;
|
||
|
padding-left: 105px;
|
||
|
|
||
|
.ta-footer-input {
|
||
|
border-radius: unset;
|
||
|
height: unset;
|
||
|
|
||
|
max-width: 100%;
|
||
|
width: 100%;
|
||
|
white-space: pre-wrap;
|
||
|
word-break: break-word;
|
||
|
caret-color: rgb(55, 53, 47);
|
||
|
font-size: 14px;
|
||
|
line-height: 1.4;
|
||
|
color: rgba(55, 53, 47, 0.65);
|
||
|
padding-top: 6px;
|
||
|
padding-bottom: 6px;
|
||
|
padding-left: 2px;
|
||
|
border-color: transparent !important;
|
||
|
background-color: #fff;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.form-control {
|
||
|
flex-grow: 1;
|
||
|
flex-shrink: 1;
|
||
|
tab-size: 2;
|
||
|
padding: 34px 16px 32px 32px;
|
||
|
min-height: 1em;
|
||
|
color: rgb(55, 53, 47);
|
||
|
white-space: pre;
|
||
|
|
||
|
border-radius: 4px;
|
||
|
position: relative;
|
||
|
background: rgb(247, 246, 243);
|
||
|
min-width: 0px;
|
||
|
width: 100%;
|
||
|
resize: none;
|
||
|
border-color: transparent;
|
||
|
}
|
||
|
|
||
|
.main-page__content .form-builder div input {
|
||
|
border-color: transparent !important;
|
||
|
}
|
||
|
</style>
|