[Subtask modal] Add multiple employees

This commit is contained in:
Matej Glasnák committed 2023-05-29 11:07:20 +02:00
1 parent 769fce0427
commit 994d3449d3
1 file changed
+87 -25
+87 -25
View File
@@ -12,18 +12,24 @@
<v-autocomplete v-model="subtask.master_task_id" label="Master task" :class="{error: v$.subtask.master_task_id.$errors.length}" :items="mastertasks" item-title="name" item-value="id" variant="solo" class="modal-input" clearable /> <v-autocomplete v-model="subtask.master_task_id" label="Master task" :class="{error: v$.subtask.master_task_id.$errors.length}" :items="mastertasks" item-title="name" item-value="id" variant="solo" class="modal-input" clearable />
<v-text-field v-model="subtask.name" @focus="onInputFocus" class="modal-input" label="Názov subtasku" variant="solo" :class="{ error: v$.subtask.name.$errors.length }" :hint="v$.subtask.name.$errors ? errorUtils.parseErrors(v$.subtask.name.$errors) : null"></v-text-field> <v-text-field v-model="subtask.title" @focus="onInputFocus" class="modal-input" label="Názov subtasku" variant="solo"></v-text-field>
<template v-if="subtask.id"> <template v-if="subtask.id">
<v-autocomplete v-model="subtask.employee_id" :class="{error: employeeError}" label="Priradený" :items="enrichedEmployees" item-title="_fullName" item-value="id" variant="solo" class="modal-input" clearable /> <v-autocomplete v-model="subtask.employee_id" label="Priradený" :items="enrichedEmployees" item-title="_fullName" item-value="id" variant="solo" class="modal-input" :class="{ error: employeeValidations[0]?.employee }"
@update:model-value="employeeValidations[0] ? employeeValidations[0].employee = false : null" />
<v-text-field v-model="subtask.duration" class="modal-input" variant="solo" type="number" label="Časový odhad" :class="{ error: employeeValidations[0]?.duration }" append-inner-icon="mdi-clock-outline" @focus="onInputFocus"
@update:model-value="employeeValidations[0] ? employeeValidations[0].duration = false : null" />
</template> </template>
<template v-else> <template v-else>
<v-autocomplete v-for="(employee, index) in [...subtask.employees, null]" v-model="subtask.employees[index]" :key="`employee-${index}`" :class="{error: employeeError}" label="Priradený" :items="enrichedEmployees" item-title="_fullName" item-value="id" variant="solo" class="modal-input" clearable /> <div v-for="(employee, index) in subtask.employees" :key="`employee-${index}`" class="multiple-employee-select">
<v-autocomplete v-model="employee.id" label="Priradený" :items="enrichedEmployees" item-title="_fullName" item-value="id" variant="solo" class="modal-input employee" :class="{ error: employeeValidations[index]?.employee }"
@update:model-value="employeeValidations[index] ? employeeValidations[index].employee = false : null" />
<v-text-field v-model="employee.duration" class="modal-input duration" variant="solo" type="number" label="Časový odhad" append-inner-icon="mdi-clock-outline" :class="{ error: employeeValidations[index]?.duration }" @focus="onInputFocus"
@update:model-value="employeeValidations[index] ? employeeValidations[index].duration = false : null" />
</div>
</template> </template>
<v-text-field v-model="subtask.duration" @focus="onInputFocus" class="modal-input" variant="solo" type="number" label="Časový odhad" :class="{ error: v$.subtask.duration.$errors.length }" :hint="v$.subtask.duration.$errors ? errorUtils.parseErrors(v$.subtask.duration.$errors) : null" append-inner-icon="mdi-clock-outline"></v-text-field>
<div class="w-100 modal-input"> <div class="w-100 modal-input">
<QuillEditor ref="description" v-model="subtask.description" placeholder="Popis" theme="snow" class="rich-text-editor" @input="subtask.description = $event.srcElement.innerHTML" /> <QuillEditor ref="description" v-model="subtask.description" placeholder="Popis" theme="snow" class="rich-text-editor" @input="subtask.description = $event.srcElement.innerHTML" />
</div> </div>
@@ -78,11 +84,9 @@ import SelectsMixin from "../master-task/_mixins/selects.mixin"
import * as FileSaver from "file-saver" import * as FileSaver from "file-saver"
import tmUtils from "@/plugins/tm@_utils/tm.utils" import tmUtils from "@/plugins/tm@_utils/tm.utils"
import "@vueup/vue-quill/dist/vue-quill.snow.css" import "@vueup/vue-quill/dist/vue-quill.snow.css"
import ZAutocomplete from "@/plugins/tm@_components/z-autocomplete.vue"
import ZTaskReadonlyInfo from "./_components/z-task-readonly-info.vue" import ZTaskReadonlyInfo from "./_components/z-task-readonly-info.vue"
import { mapGetters } from "vuex" import { mapGetters } from "vuex"
import moment from "moment"
export default { export default {
emits: ["close", "refresh"], emits: ["close", "refresh"],
@@ -91,8 +95,7 @@ export default {
components: { components: {
ZTaskReadonlyInfo, ZTaskReadonlyInfo,
ZFilesUpload, ZFilesUpload,
QuillEditor, QuillEditor
// ZAutocomplete
}, },
data() { data() {
@@ -103,9 +106,9 @@ export default {
subtask: null, subtask: null,
errorUtils, errorUtils,
v$: useVuelidate(), v$: useVuelidate(),
employeeValidations: [],
preventInputFocus: false, preventInputFocus: false,
showDatePicker: false, showDatePicker: false,
employeeError: false,
selectedNewDate: [] selectedNewDate: []
} }
}, },
@@ -121,8 +124,7 @@ export default {
return { return {
subtask: { subtask: {
master_task_id: { required }, master_task_id: { required },
duration: { required }, // title: { required }
name: { required }
} }
} }
}, },
@@ -152,7 +154,7 @@ export default {
const data = await this.$axios.get_auth_data(`v1/subtasks/${subtask.id}`) const data = await this.$axios.get_auth_data(`v1/subtasks/${subtask.id}`)
this.subtask = this._enrichTask(data) this.subtask = this._enrichTask(data)
} else { } else {
this.subtask = { master_task: mastertask, employees: [], timeblocks: [] } this.subtask = { master_task: mastertask, employees: [{}] }
} }
this.editMode = editMode || !this.subtask.id this.editMode = editMode || !this.subtask.id
@@ -167,13 +169,9 @@ export default {
}, },
async save() { async save() {
if (!this.subtask.employee_id && !this.subtask.employees.length) const employeesValid = await this._validateEmployees()
this.employeeError = true
if (!(await this.v$.$validate())) if (!(await this.v$.$validate()) || !employeesValid)
return
if (!this.subtask.employee_id && !this.subtask.employees.length)
return return
this.subtask.description = this.$refs['description'].getHTML() this.subtask.description = this.$refs['description'].getHTML()
@@ -181,14 +179,19 @@ export default {
try { try {
if (this.subtask?.id) { if (this.subtask?.id) {
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, this.subtask) const { subtask } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, this.subtask)
this.$store.commit('tm/update_subtask', subtask) this.$store.commit('tm/update_subtask', subtask)
this.$events.emit("on-subtask-edited", this.subtask)
} else { } else {
const { subtask } = await this.$axios.post_auth(`v1/mastertasks/${this.subtask.master_task_id}/subtasks`, this.subtask) const { subtasks } = await this.$axios.post_auth(`v1/mastertasks/${this.subtask.master_task_id}/subtasks`, this.subtask)
this.subtask.id = subtask.id this.subtask.id = subtasks[0].id
subtasks.forEach(subtask => {
this.$store.commit('tm/update_subtask', subtask) this.$store.commit('tm/update_subtask', subtask)
this.$events.emit("on-subtask-edited", this.subtask)
})
} }
this.$events.emit("on-subtask-edited", this.subtask)
this.closeModal() this.closeModal()
} catch (error) { } catch (error) {
this.$toast.error(error) this.$toast.error(error)
@@ -221,6 +224,45 @@ export default {
this.subtask = subtask this.subtask = subtask
}, },
_validateEmployees() {
return new Promise((resolve) => {
this.employeeValidations = []
if (this.subtask.id) {
if (this.subtask.employee && this.subtask.duration)
return
this.employeeValidations[0] = {}
if (!this.subtask.employee_id)
this.employeeValidations[0].employee = true
if (!this.subtask.duration)
this.employeeValidations[0].duration = true
} else {
this.subtask.employees.forEach((employee, index) => {
if (index == this.subtask.employees.length - 1 && index > 0)
return // Skip the last which is allways empty
if (employee.id && employee.duration)
return
this.employeeValidations[index] = {}
if (!employee.id)
this.employeeValidations[index].employee = true
if (!employee.duration)
this.employeeValidations[index].duration = true
})
}
const isError = this.employeeValidations.some(employee => employee.duration || employee.employee)
resolve(!isError)
})
},
_enrichTask(subtask) { _enrichTask(subtask) {
return { return {
...subtask, ...subtask,
@@ -233,15 +275,22 @@ export default {
watch: { watch: {
'subtask.employee_id'(value, oldValue) { 'subtask.employee_id'(value, oldValue) {
this.employeeError = false
if (!value || !oldValue) return if (!value || !oldValue) return
this.subtask.timeblocks = [] this.subtask.timeblocks = []
this.subtask._employee = this.enrichedEmployees.find((employee) => employee.id == this.subtask.employee_id) this.subtask._employee = this.enrichedEmployees.find((employee) => employee.id == this.subtask.employee_id)
}, },
'subtask.employees'() { 'subtask.employees': {
this.employeeError = false handler() {
if (!this.subtask?.employees)
return
const lastEmployee = this.subtask.employees[this.subtask.employees.length - 1]
if (lastEmployee.id || lastEmployee.duration)
this.subtask.employees.push({})
},
deep: true
}, },
'subtask.master_task_id'(value) { 'subtask.master_task_id'(value) {
@@ -275,4 +324,17 @@ export default {
@media screen and (max-width: 522px) @media screen and (max-width: 522px)
.files .files
margin-top: 104px !important margin-top: 104px !important
.multiple-employee-select
width: 100%
.modal-input
display: inline-block
.employee
width: 70% !important
.duration
width: 25% !important
margin-left: 5%
</style> </style>