Fix(Mastertask) Moved estimated_duration to mastertask.

This commit is contained in:
Matej Glasnák committed 2025-03-19 13:57:51 +01:00
1 parent b2495b7035
commit 6b42c0ae3d
5 files changed
+145 -154

No files matched your search

@@ -8,27 +8,25 @@
</div>
<v-card-actions class="d-flex flex-column modal-content">
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="mastertask.project_id" :label="$t('Project code')" :class="{error: v$.mastertask.project_id.$errors.length}" :items="projectsOptions" item-title="code" item-value="id" variant="solo" class="modal-input" clearable @update:search="projectCodeSearch = $event" />
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="mastertask.project_id" :label="$t('Project code')" :class="{ error: v$.mastertask.project_id.$errors.length }" :items="projectsOptions" item-title="code" item-value="id" variant="solo" class="modal-input" clearable @update:search="projectCodeSearch = $event" />
<v-text-field v-model="mastertask.name" @focus="onInputFocus" class="modal-input" label="Názov mastertasku" variant="solo" :class="{ error: v$.mastertask.name.$errors.length }" :hint="v$.mastertask.name.$errors ? errorUtils.parseErrors(v$.mastertask.name.$errors) : null"></v-text-field>
<div class="splitted-inputs">
<!-- TODO: Bialko validacie -->
<Datepicker v-model="mastertask.deadline" :auto-apply="true" @focus="onDateFocus" :min-date="new Date()" class="modal-input left" format="dd.MM.yyyy" locale="sk" select-text="Vybrať" cancel-text="Zrušiť" placeholder="Dátum"
:class="{ error: v$.mastertask.deadline.$errors?.length }" :validations="v$.mastertask.deadline" />
<Datepicker v-model="mastertask.deadline" :auto-apply="true" @focus="onDateFocus" :min-date="new Date()" class="modal-input left" format="dd.MM.yyyy" locale="sk" select-text="Vybrať" cancel-text="Zrušiť" placeholder="Dátum" :class="{ error: v$.mastertask.deadline.$errors?.length }" :validations="v$.mastertask.deadline" />
<v-text-field class="modal-input right" variant="solo" v-model="mastertask._deadline_time" label="Čas" append-inner-icon="mdi-clock-outline" type="time" @focus="onInputFocus"
:class="{ error: v$.mastertask._deadline_time.$errors.length }" :hint="v$.mastertask._deadline_time.$errors ? errorUtils.parseErrors(v$.mastertask._deadline_time.$errors) : null" />
<v-text-field class="modal-input right" variant="solo" v-model="mastertask._deadline_time" label="Čas" append-inner-icon="mdi-clock-outline" type="time" @focus="onInputFocus" :class="{ error: v$.mastertask._deadline_time.$errors.length }" :hint="v$.mastertask._deadline_time.$errors ? errorUtils.parseErrors(v$.mastertask._deadline_time.$errors) : null" />
</div>
<v-text-field v-model="mastertask.estimated_duration" @focus="onInputFocus" class="modal-input" variant="solo" type="number" label="Nacenené hodiny"></v-text-field>
<v-text-field v-model="mastertask.estimated_duration" @focus="onInputFocus" class="modal-input" variant="solo" type="number" label="Nacenené hodiny" :class="{ error: v$.mastertask.estimated_duration.$errors.length }" :hint="v$.mastertask.estimated_duration.$errors ? errorUtils.parseErrors(v$.mastertask.estimated_duration.$errors) : null"></v-text-field>
<v-text-field v-model="mastertask.duration" @focus="onInputFocus" class="modal-input" variant="solo" type="number" :label="`${mastertask.duration} h`" :disabled="true"></v-text-field>
<v-select v-model="mastertask.team_id" @focus="onInputFocus" class="modal-input border-select" :class="{error: v$.mastertask.employees.$errors.length}" label="Tím" variant="solo" :items="teams" item-value="id" item-title="name" :disabled="!!mastertask.id" :clearable="true" />
<v-select v-model="mastertask.team_id" @focus="onInputFocus" class="modal-input border-select" :class="{ error: v$.mastertask.employees.$errors.length }" label="Tím" variant="solo" :items="teams" item-value="id" item-title="name" :disabled="!!mastertask.id" :clearable="true" />
<template v-if="!mastertask.id">
<v-text-field v-for="(employee, index) in mastertask.employees" :key="employee.id" @focus="onInputFocus" class="modal-input" :class="{error: employee.invalid}" :label="`${employee.name} ${employee.surname}`" variant="solo" placeholder="h" v-model="mastertask.employees[index].duration" type="number" min="1" @input="onEmployeeDurationChanged">
<v-text-field v-for="(employee, index) in mastertask.employees" :key="employee.id" @focus="onInputFocus" class="modal-input" :class="{ error: employee.invalid }" :label="`${employee.name} ${employee.surname}`" variant="solo" placeholder="h" v-model="mastertask.employees[index].duration" type="number" min="1" @input="onEmployeeDurationChanged">
<p class="employee-select-avatar d-flex justify-center align-center">
{{ employee?.name.charAt(0) + employee?.surname.charAt(0) }}
</p>
@@ -48,11 +46,11 @@
</v-text-field>
</template>
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-if="showAddEmployeeInput" :label="$t('Search for employee')" :class="{error: v$.mastertask.project_id.$errors.length}" :items="employeesOptions" item-title="_fullName" item-value="id" variant="solo" class="modal-input" clearable @update:model-value="onEmployeeSelected" />
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-if="showAddEmployeeInput" :label="$t('Search for employee')" :class="{ error: v$.mastertask.project_id.$errors.length }" :items="employeesOptions" item-title="_fullName" item-value="id" variant="solo" class="modal-input" clearable @update:model-value="onEmployeeSelected" />
<!-- <Z-autocomplete label="Vyhľadať zamestnanca" :options="employeesOptions" class="modal-input" @option-selected="onEmployeeSelected" /> -->
<v-btn :disabled="!!mastertask.id" class="w-100 mb-5 button secondary" :class="{error: v$.mastertask.project_id.$errors.length}" @click="showAddEmployeeInput = true"> <v-icon class="mx-1" icon="mdi-plus" />Pridať zamestnanca </v-btn>
<v-btn :disabled="!!mastertask.id" class="w-100 mb-5 button secondary" :class="{ error: v$.mastertask.project_id.$errors.length }" @click="showAddEmployeeInput = true"> <v-icon class="mx-1" icon="mdi-plus" />Pridať zamestnanca </v-btn>
<div class="w-100 modal-input" :class="{ error: v$.mastertask.description.$errors.length }">
<QuillEditor ref="description" v-model="mastertask.description" placeholder="Popis" theme="snow" class="rich-text-editor" @keyup="onQuillEditorInput" />
@@ -62,7 +60,7 @@
</v-card-actions>
<v-btn class="button primary" v-if="!isSaving" @click="save()">{{ mastertask.id ? 'ULOŽIŤ' : 'VYTVORIŤ' }}</v-btn>
<v-btn class="button primary disabled" v-else disabled>{{ $t('Ukladám...')}}</v-btn>
<v-btn class="button primary disabled" v-else disabled>{{ $t('Ukladám...') }}</v-btn>
</v-card>
<v-card v-else height="100%" class="d-flex flex-column scrolling">
@@ -88,8 +86,8 @@
<A-tasks-table :subtasks="mastertask.subtasks" />
<div class="d-flex align-center ">
<v-btn class="subtask-btn w-100" @click="addTask()" ><v-icon class="mx-1" icon="mdi-plus" />Pridať sub task</v-btn>
<div class="d-flex align-center">
<v-btn class="subtask-btn w-100" @click="addTask()"><v-icon class="mx-1" icon="mdi-plus" />Pridať sub task</v-btn>
</div>
</div>
</v-card-actions>
@@ -153,44 +151,40 @@ export default {
},
computed: {
...mapGetters('tm', [
'teams',
'projects',
'enrichedEmployees'
]),
...mapGetters('tm', ['teams', 'projects', 'enrichedEmployees']),
enrichedSubtasks() {
if (!this.mastertask?.subtasks)
return null
if (!this.mastertask?.subtasks) return null
return this.mastertask.subtasks.map(subtask => {
const employee = this.enrichedEmployees.find(employee => employee.id == subtask.employee_id)
return this.mastertask.subtasks
.map((subtask) => {
const employee = this.enrichedEmployees.find((employee) => employee.id == subtask.employee_id)
return {
...subtask,
_initials: employee ? employee.name.charAt(0) + employee.surname.charAt(0) : '?',
_fullName: employee ? `${employee.name} ${employee.surname}` : ''
}
}).filter(subtask => subtask !== null)
return {
...subtask,
_initials: employee ? employee.name.charAt(0) + employee.surname.charAt(0) : '?',
_fullName: employee ? `${employee.name} ${employee.surname}` : ''
}
})
.filter((subtask) => subtask !== null)
}
},
validations() {
const quillEditorRequired = (value) => {
if (!value || !value.length || !value.replace(/<[^>]*>/g, '').length)
return false
if (!value || !value.length || !value.replace(/<[^>]*>/g, '').length) return false
return true
}
return {
mastertask: {
employees: { required, minLength: minLength(1), $each: {duration: { required}} },
employees: { required, minLength: minLength(1), $each: { duration: { required } } },
project_id: { required },
name: { required },
description: { quillEditorRequired },
deadline: { required },
estimated_duration: { required },
_deadline_time: { required }
}
}
@@ -200,15 +194,13 @@ export default {
this.$events.on('close-both-modals', this.closeBothModals)
this.$events.on('master-task:team-member-deleted', ({ teamId, memberId }) => {
if (this.mastertask.team_id != teamId)
return
if (this.mastertask.team_id != teamId) return
this.mastertask.employees = this.mastertask.employees.filter(employee => employee.id != memberId)
this.mastertask.employees = this.mastertask.employees.filter((employee) => employee.id != memberId)
}),
this.$events.on('on-mastertask-deleted', (mastertask) => {
if (mastertask?.id == this.mastertask?.id) this.closeModal()
})
this.$events.on('on-mastertask-deleted', (mastertask) => {
if (mastertask?.id == this.mastertask?.id) this.closeModal()
})
this.$events.on('on-subtask-deleted', (task) => {
if (!this.mastertask) return
@@ -218,8 +210,8 @@ export default {
this.$events.on('on-subtask-edited', (task) => {
if (!this.mastertask?.subtasks) return
if (this.mastertask.subtasks.find(subtask => subtask.id == task.id)) {
this.mastertask.subtasks = this.mastertask.subtasks.map(t => t.id == task.id ? task : t)
if (this.mastertask.subtasks.find((subtask) => subtask.id == task.id)) {
this.mastertask.subtasks = this.mastertask.subtasks.map((t) => (t.id == task.id ? task : t))
} else {
this.mastertask.subtasks.push(task)
}
@@ -248,7 +240,7 @@ export default {
// this.mastertask.team = null
// }
this.mastertask.employees = this.mastertask.employees.filter(employee => employee.id != id)
this.mastertask.employees = this.mastertask.employees.filter((employee) => employee.id != id)
},
removeMemberAlert(member) {
@@ -256,10 +248,10 @@ export default {
this.$events.emit('show-delete-team-member-modal', { member, team })
},
async showModal({mastertask, editMode = false}) {
this.isSaving = false
this.editMode = null
this.visible = true
async showModal({ mastertask, editMode = false }) {
this.isSaving = false
this.editMode = null
this.visible = true
this.mastertask = null
this.$nextTick(() => {
this.setFocusEvent()
@@ -273,20 +265,22 @@ export default {
// TODO zmazat ked zacne prichadzat project_id a team_id
console.log('1', this.mastertask)
const project = this.projects.find((project) => project.code == this.mastertask.project_code)
this.mastertask.project_id = project?.id || null
this.mastertask.team_id = this.mastertask.team?.id || null
this.mastertask.project_id = project?.id || null
this.mastertask.team_id = this.mastertask.team?.id || null
this.mastertask._allEmployees = this.mastertask.subtasks.map(({ employee_id, duration}) => {
const employee = this.enrichedEmployees.find(({ id }) => id == employee_id)
this.mastertask._allEmployees = this.mastertask.subtasks
.map(({ employee_id, duration }) => {
const employee = this.enrichedEmployees.find(({ id }) => id == employee_id)
if (!employee) {
return null
}
if (!employee) {
return null
}
employee.duration = duration
employee.duration = duration
return employee
}).filter(employee => employee !== null)
return employee
})
.filter((employee) => employee !== null)
// this.mastertask.project_code = project.code
} else {
@@ -300,13 +294,13 @@ export default {
throw new Error('Parsed mastertask is not an object')
}
this.$nextTick(() => {
this.$refs['description']?.setHTML(this.mastertask.description || '');
this.$refs['description']?.setHTML(this.mastertask.description || '')
})
} else {
throw new Error('mastertaskData is null or undefined')
}
} catch (error) {
console.error('Error parsing mastertaskData:', error);
console.error('Error parsing mastertaskData:', error)
this.mastertask = { employees: [], duration: 0, _deadline_time: '17:00' }
}
}
@@ -315,8 +309,7 @@ export default {
} catch (error) {
this.$toast.error(error.message || error)
if (process.env.NODE_ENV === 'development')
console.log('[z-master-task-modal.vue] Error: ', error)
if (process.env.NODE_ENV === 'development') console.log('[z-master-task-modal.vue] Error: ', error)
}
},
@@ -326,7 +319,7 @@ export default {
async save() {
if (this.mastertask.id) {
this.mastertask.employees = this.mastertask.employees.map(employee => {
this.mastertask.employees = this.mastertask.employees.map((employee) => {
const { duration } = this.mastertask.subtasks.find(({ employee_id }) => employee_id == employee.id) || {}
employee.duration = duration
return employee
@@ -338,8 +331,7 @@ export default {
if (!vuelidateValid || !employeesValid) return
if (this.$refs['description'])
this.mastertask.description = this.$refs['description'].getHTML()
if (this.$refs['description']) this.mastertask.description = this.$refs['description'].getHTML()
this._mergeDeadlineTimeDate()
@@ -355,8 +347,7 @@ export default {
} catch (error) {
this.$toast.error(this.$parseError(error))
if (process.env.NODE_ENV === 'development')
console.log('[z-master-task-modal.vue] Error: ', error)
if (process.env.NODE_ENV === 'development') console.log('[z-master-task-modal.vue] Error: ', error)
} finally {
this.isSaving = false
}
@@ -400,7 +391,7 @@ export default {
_validateEmployees() {
let isValid = true
this.mastertask.employees = this.mastertask.employees.map(employee => {
this.mastertask.employees = this.mastertask.employees.map((employee) => {
if (!employee.duration) {
employee.invalid = true
isValid = false
@@ -438,10 +429,10 @@ export default {
},
'mastertask.team_id': {
handler(value, oldValue) {
if (this.editMode && (!value && oldValue)) {
if (this.editMode && !value && oldValue) {
// Removes only employees from the old team when team_id is removed
const oldTeamEmployeesIds = this.teams.find(team => team.id == oldValue)?.employees.map(employee => employee?.id) || []
const employeesNotInOldTeam = this.mastertask.employees.filter(employee => !oldTeamEmployeesIds.includes(employee?.id))
const oldTeamEmployeesIds = this.teams.find((team) => team.id == oldValue)?.employees.map((employee) => employee?.id) || []
const employeesNotInOldTeam = this.mastertask.employees.filter((employee) => !oldTeamEmployeesIds.includes(employee?.id))
this.mastertask.employees = employeesNotInOldTeam
}
},