task_ui/components/TaskForm.vue
2025-04-21 11:49:42 +03:30

494 lines
15 KiB
Vue

<template>
<form class="task-form">
<div class="row row-basic mx-0 justify-content-end">
<div
class="main-page_body-items items items-top d-flex align-items-center col-12"
>
<div
v-if="templateValue.title == 'multi-org_workbase'"
class="col-1 ps-0 pe-0 task-Form-Organ"
style="color: #97f295 !important"
>
<multiselect
v-model.number="taskForm.organ"
class="multiselect Organ"
tag-placeholder="Add this as new tag"
placeholder="سازمان"
:options="organOptions"
:taggable="true"
:close-on-select="true"
:clear-on-select="false"
:searchable="true"
:max-height="250"
:preserve-search="true"
@tag="addTagOrgan"
@select="organSelect"
></multiselect>
</div>
<div class="col-2 ps-0 pe-0 task-Form-category">
<multiselect
class="multiselect category"
id="task-Form-category"
v-model.number="taskForm.category"
tag-placeholder="Add this as new tag"
placeholder="دسته"
:options="categoryOptions"
:taggable="true"
:close-on-select="true"
:clear-on-select="false"
:searchable="true"
:max-height="250"
:preserve-search="true"
@tag="addTagCategury"
></multiselect>
<!-- <pre
class="language-json"
><code>{{ taskForm.category }}</code></pre> -->
</div>
<vue-tribute
class="col-3 ps-0 pe-0 tribute-container"
:options="tributeOptions"
>
<input
class="label-1 form-control task-form-control task-title"
placeholder="عنوان"
v-model="taskForm.title"
cols="20"
rows="3"
@tribute-no-match="noMatchFound"
@tribute-replaced="textReplaced"
@keydown.tab="foucsNext('duration')"
/>
</vue-tribute>
<div class="col-1">
<input
v-model="taskForm.duration"
ref="duration"
type="text"
placeholder="مدت "
@blur="timeCorrect(taskForm.duration)"
v-on:focus="timeFocus('duration', taskForm.duration)"
class="label-3 form-control task-form-control"
/>
</div>
<div class="col-4 label-4">
<input
v-model="taskForm.description"
type="text"
placeholder="گویا و مختصر بنویسید"
class="label-4 form-control task-form-control Description"
@keydown.tab="postInTaskWork(taskForm)"
/>
<div class="d-flex align-items-center">
<span
@click="postInTaskWork(taskForm)"
title="ثبت"
class="btn main-page_body-items-icon ps-0"
>
<svg
class="icon icon-Component-233--1 main-page_body-items-icon-add"
>
<use xlink:href="#icon-Component-233--1"></use>
</svg>
</span>
<button-component
@click="closeFormTaskInformation(taskForm)"
buttonText=""
v-tooltip="'حذف فرایند'"
>
<span class="text-danger">
<svg class="icon icon-Component-295--1">
<use xlink:href="#icon-Component-295--1"></use>
</svg>
</span>
</button-component>
</div>
</div>
</div>
</div>
<div class="row row-mobile mx-0 justify-content-end">
<div
class="main-page_body-items items items-top d-flex align-items-center col-12"
>
<!-- <vue-tribute class="col-6 ps-0 pe-0" :options="tributeOptions"> -->
<div
v-if="templateValue.title == 'multi-org_workbase'"
class="col-6"
style="color: #97f295 !important"
>
<multiselect
v-model.number="taskForm.organ"
class="multiselect Organ Organ-mobile"
tag-placeholder="Add this as new tag"
placeholder="سازمان"
:options="organOptions"
:taggable="true"
:close-on-select="true"
:clear-on-select="false"
:searchable="true"
:max-height="250"
:preserve-search="true"
@tag="addTagOrgan"
@select="organSelect"
></multiselect>
<!-- <pre
class="language-json"
><code>{{ taskForm.category }}</code></pre> -->
</div>
<div class="col-6">
<multiselect
id="task-Form-category"
v-model.number="taskForm.category"
tag-placeholder="Add this as new tag"
placeholder="دسته"
:options="categoryOptions"
:taggable="true"
:close-on-select="true"
:clear-on-select="false"
:searchable="true"
:max-height="250"
:preserve-search="true"
@tag="addTagCategury"
></multiselect>
</div>
<!-- </vue-tribute> -->
</div>
<div
class="col-12 label-4 main-page_body-items items items-bottom d-flex align-items-center mb-1"
>
<vue-tribute class="col-5 ps-0 pe-0" :options="tributeOptions">
<input
class="label-1 form-control task-form-control task-title"
placeholder="عنوان"
v-model="taskForm.title"
cols="20"
rows="3"
@tribute-no-match="noMatchFound"
@tribute-replaced="textReplaced"
/>
</vue-tribute>
<input
v-model="taskForm.duration"
ref="duration2"
type="text"
placeholder="مدت "
@blur="timeCorrect(taskForm.duration)"
v-on:focus="timeFocus('duration2', taskForm.duration)"
class="col-2 label-3 form-control task-form-control"
/>
<input
v-model="taskForm.description"
type="text"
placeholder="توضیحات(گویا،مختصر)"
class="label-5 form-control task-form-control Description"
/>
</div>
<div class="d-flex align-items-center ms-2">
<span
@click="postInTaskWork(taskForm)"
title="ثبت"
class="btn main-page_body-items-icon ps-0"
>
<svg class="icon icon-Component-233--1 main-page_body-items-icon-add">
<use xlink:href="#icon-Component-233--1"></use>
</svg>
</span>
<span title="حذف" class="btn ps-0">
<svg
@click="closeFormTaskInformation(taskForm)"
class="icon icon-Component-295--1 main-page_body-items-icon-close"
>
<use xlink:href="#icon-Component-295--1"></use>
</svg>
</span>
</div>
</div>
</form>
</template>
<script>
import taskApi from "@apis/taskApi";
import HttpService from "@services/httpService";
import { mapGetters } from "vuex";
import VueTribute from "vue-tribute";
export default {
props: {
itemIndex: {
default: 0,
},
isMultiOrgan: {
default: false,
},
taskForm: {
default() {
return {
organ: "",
category: "",
title: "",
duration: "",
description: "",
};
},
},
templateValue: {
default() {
return {
name: "تک سازمانی - کارمحور",
title: "single-org_workbase",
};
},
},
},
emits: ["close-form-tasks", "save-form-tasks", "add-new-record"],
beforeMount() {
this.httpService = new HttpService(this.taskMicroServiceName);
},
mounted() {
if (this.taskSchemaGetter?.categoryOptions)
this.categoryOptions = this.taskSchemaGetter?.categoryOptions;
if (this.taskSchemaGetter?.organOptions) {
this.organOptions = this.taskSchemaGetter?.organOptions;
}
if( this.taskForm.organ == "" && this.organOptions.length ){
this.taskForm.organ = this.organOptions[0];
}
},
data() {
return {
categoryOptions: [],
organOptions: [],
showOrgan: this.isMultiOrgan,
userLang: "fa-IR",
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(["taskSchemaGetter"]),
taskMicroServiceName() {
return process.env.VUE_APP_TASK;
},
},
methods: {
organSelect($event) {
// console.log($event);
// console.log(this.taskForm?.organ);
// console.log(this.taskSchemaGetter?.organCategories);
if (
this.taskForm?.organ &&
this.taskSchemaGetter?.organCategories &&
this.taskSchemaGetter?.organCategories[this.taskForm?.organ]
) {
// console.log("this.taskForm.organ");
this.categoryOptions =
this.taskSchemaGetter?.organCategories[this.taskForm?.organ];
} else {
this.categoryOptions = this.taskSchemaGetter?.categoryOptions;
}
},
foucsNext(ref) {
this.$refs[ref].focus();
},
// setMultiOrgan(value){
// this.isMultiOrgan = value;
// },
timeFocus(ref, value) {
//if (value == "00:00" || value == "" || value == "مدت")
this.$refs[ref].select();
},
timeCorrect(duration) {
duration = duration.trim();
duration = duration.replace(".", ":");
duration = duration.replace(" ", ":");
if (duration.indexOf(":") == -1) {
if (duration.length == 0) duration = "00:00";
else if (duration.length == 1) duration = "0" + duration + ":00";
else if (duration.length == 2) duration = duration + ":00";
else if (duration.length == 3)
duration =
"0" + duration.substring(0, 1) + ":" + duration.substring(1);
else if (duration.length == 4)
duration =
duration.substring(0, 2) +
":" +
duration.substring(2).padStart(2, "0");
else if (duration.length > 4)
duration = duration.substring(0, 2) + ":" + duration.substring(3, 5);
}
this.taskForm.duration = duration;
},
noMatchFound(args) {
// console.info(args);
},
textReplaced(args) {
// console.info(args);
},
closeFormTaskInformation() {
this.$emit("close-form-tasks");
},
postInTaskWork(taskForm) {
this.$emit("save-form-tasks", taskForm);
},
openFormTaskInformation() {
this.$emit("add-new-record");
},
addTagCategury(newTag) {
// const tag = {
// name: newTag,
// };
this.taskForm.category = newTag;
},
addTagOrgan(newTag) {
// const tag = {
// name: newTag,
// };
this.taskForm.organ = newTag;
},
addTagTitle(newTag) {
// const tag = {
// name: newTag,
// };
this.taskForm.title = newTag;
},
remoteSearch(text, cb) {
let url = taskApi.workingHours.complition.replace("{{query}}", text);
if (text == "") url = taskApi.workingHours.complitionAll;
this.httpService.getRequest(url).then((response) => {
cb(response.data);
});
},
isNumberKey(evt) {
var charCode = evt.which ? evt.which : evt.keyCode;
if (charCode > 31 && (charCode < 48 || charCode > 57)) return false;
return true;
},
},
components: {
VueTribute: () => import("vue-tribute"),
Multiselect: () => import("vue-multiselect"),
},
};
</script>
<style lang="scss" scoped>
// input::placeholder {
// color: #d4dce3;
// }
// textarea::placeholder {
// color: #d4dce3;
// }
.row {
border: 1px rgb(223 223 223) solid;
border-radius: 0.5em;
margin-bottom: 0.5em;
}
.task-Form-title {
border-right: 1px var(--color-items-7) solid;
}
// .my-tribute-class {
// background: #d4dce3;
// }
</style>