This commit is contained in:
romankko2 committed 2023-06-09 16:47:23 +02:00
commit 263dd868d9
10 files changed
+147 -83

No files matched your search

@@ -0,0 +1,17 @@
export default {
methods: {
customFilter(item, input) {
// Replace accented characters with non-accented equivalents
const normalizedItem = item.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
const normalizedInput = input.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
// Remove any character that is not a letter, number, or space from both the item and the input
const pattern = /[^a-zA-Z0-9 ]/g;
const cleanedItem = normalizedItem.replace(pattern, '');
const cleanedInput = normalizedInput.replace(pattern, '');
// Check if the cleaned item starts with the cleaned input
return cleanedItem.toLowerCase().startsWith(cleanedInput.toLowerCase());
}
}
}
@@ -1,12 +1,12 @@
<template> <template>
<v-row class="px-10 py-8 subheader"> <v-row class="px-10 py-8 subheader">
<v-autocomplete v-model="filter.projectId" class="subheader-input" :items="[...projectsOptions]" item-title="code" item-value="id" label="Projekt" variant="outlined" @update:search="projectCodeSearch = $event" /> <v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="filter.projectId" class="subheader-input" :items="[...projectsOptions]" item-title="code" item-value="id" label="Projekt" variant="outlined" @update:search="projectCodeSearch = $event" />
<v-select v-model="filter.teamId" class="subheader-input" :items="[null, ...teams]" label="Tím" variant="outlined" item-title="name" item-value="id" /> <v-select v-model="filter.teamId" class="subheader-input" :items="[null, ...teams]" label="Tím" variant="outlined" item-title="name" item-value="id" />
<v-autocomplete v-model="filter.employeeId" class="subheader-input" :items="[...enrichedEmployees]" item-title="_fullName" item-value="id" label="Zamestnanec" variant="outlined" /> <v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="filter.employeeId" class="subheader-input" :items="[...enrichedEmployees]" item-title="_fullName" item-value="id" label="Zamestnanec" variant="outlined" />
<v-autocomplete v-model="filter.createdById" class="subheader-input" :items="[...enrichedEmployees]" label="Vytvoril" variant="outlined" item-title="_fullName" item-value="id" /> <v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="filter.createdById" class="subheader-input" :items="[...enrichedEmployees]" label="Vytvoril" variant="outlined" item-title="_fullName" item-value="id" />
<v-select v-model="filter.month" class="subheader-input" :items="months" label="Mesiac" variant="outlined" /> <v-select v-model="filter.month" class="subheader-input" :items="months" label="Mesiac" variant="outlined" />
@@ -18,9 +18,11 @@
</template> </template>
<script> <script>
import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
export default { export default {
mixins: [AutocompleteMixin],
emits: ['filterChanged'], emits: ['filterChanged'],
data() { data() {
@@ -1,43 +1,31 @@
<template> <template>
<v-row class="px-7 py-5 subheader"> <v-row class="px-7 py-5 subheader">
<v-autocomplete <v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="selectedEmployee" class="subheader-input"
v-model="selectedEmployee" :items="enrichedEmployees" :menu-props="{ maxHeight: 500 }" item-title="_fullName" item-value="id"
class="subheader-input" label="Zamestnanec" variant="outlined"></v-autocomplete>
:items="enrichedEmployees"
:menu-props="{maxHeight: 500}"
item-title="_fullName"
item-value="id"
label="Zamestnanec"
variant="outlined"
></v-autocomplete>
<div class="d-flex date-wrapper"> <div class="d-flex date-wrapper">
<v-btn class="subheader-icon-button prev" variant="outlined" @click="prevWeek()"><img :src="require('@/plugins/app/_img/icons/icon-prev.svg')" alt=""></v-btn> <v-btn class="subheader-icon-button prev" variant="outlined" @click="prevWeek()"><img
<v-text-field :src="require('@/plugins/app/_img/icons/icon-prev.svg')" alt=""></v-btn>
class="subheader-input disabled" <v-text-field class="subheader-input disabled" label="Dátum" v-model="selectedDate" variant="outlined"
label="Dátum" append-inner-icon="mdi-calendar-blank-outline"></v-text-field>
v-model="selectedDate" <v-btn class="subheader-icon-button next" variant="outlined" @click="nextWeek()"><img
variant="outlined" :src="require('@/plugins/app/_img/icons/icon-next.svg')" alt=""></v-btn>
append-inner-icon="mdi-calendar-blank-outline"
></v-text-field>
<v-btn class="subheader-icon-button next" variant="outlined" @click="nextWeek()"><img :src="require('@/plugins/app/_img/icons/icon-next.svg')" alt=""></v-btn>
</div> </div>
<v-text-field <v-text-field class="subheader-input disabled" label="Nenaplánované hodiny" variant="outlined" :disabled="true"
class="subheader-input disabled" v-model="time"></v-text-field>
label="Nenaplánované hodiny"
variant="outlined"
:disabled="true"
v-model="time"
></v-text-field>
</v-row> </v-row>
</template> </template>
<script> <script>
import { addDays, subDays } from 'date-fns' import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { addDays, subDays } from 'date-fns'
export default { export default {
mixins: [AutocompleteMixin],
emits: ['filter-changed'], emits: ['filter-changed'],
props: { props: {
splitDays: { splitDays: {
type: [Array, null], type: [Array, null],
@@ -58,7 +46,7 @@ export default {
} }
} }
}, },
computed: { computed: {
...mapGetters('auth', ['user']), ...mapGetters('auth', ['user']),
...mapGetters('tm', ['enrichedEmployees']), ...mapGetters('tm', ['enrichedEmployees']),
@@ -82,9 +70,9 @@ export default {
}, },
_updateFilters() { _updateFilters() {
this.filter.start = subDays(this.date, 1) this.filter.start = subDays(this.date, 1)
this.filter.end = addDays(this.date, 5) this.filter.end = addDays(this.date, 5)
this.selectedDate = String(this.filter.start?.toLocaleDateString('sk-SK') + ' - ' + this.filter.end?.toLocaleDateString('sk-SK')) this.selectedDate = String(this.filter.start?.toLocaleDateString('sk-SK') + ' - ' + this.filter.end?.toLocaleDateString('sk-SK'))
this._emitFilterChanged() this._emitFilterChanged()
}, },
@@ -8,9 +8,21 @@
</div> </div>
</v-sheet> </v-sheet>
</v-col> </v-col>
<v-col cols="7"> <v-col cols="7">
<v-sheet class="py-3 d-flex flex-wrap flex-column"> <v-sheet class="py-3 d-flex flex-wrap flex-column">
<p class="task-badge px-4 py-2 rounded-pill flex-shrink-0">{{ team?.name || 'Nepriradený' }}</p> <template v-if="team">
<p class="task-badge px-4 py-2 rounded-pill flex-shrink-0">{{ team.name }}</p>
<div class="d-flex align-center flex-shrink-0 mt-2 task-badge px-4 py-2 rounded-pill" v-for="employee in enrichedTeamEmployees" :key="employee.id">
<p class="employee-selected-avatar d-flex justify-center align-center">
{{ employee._initials }}
</p>
<p class="ml-2">{{ employee._fullName }}</p>
</div>
<div class="mb-4"></div>
</template>
<p class="task-badge px-4 py-2 rounded-pill flex-shrink-0">Nepriradený</p>
<div class="d-flex align-center flex-shrink-0 mt-2 task-badge px-4 py-2 rounded-pill" v-for="employee in enrichedEmployees" :key="employee.id"> <div class="d-flex align-center flex-shrink-0 mt-2 task-badge px-4 py-2 rounded-pill" v-for="employee in enrichedEmployees" :key="employee.id">
<p class="employee-selected-avatar d-flex justify-center align-center"> <p class="employee-selected-avatar d-flex justify-center align-center">
{{ employee._initials }} {{ employee._initials }}
@@ -40,6 +52,12 @@ export default {
}, },
computed: { computed: {
enrichedTeamEmployees() {
if (!this.team?.employees)
return []
return tmUtils.enrichEmployees(this.team.employees)
},
enrichedEmployees() { enrichedEmployees() {
return tmUtils.enrichEmployees(this.employees) return tmUtils.enrichEmployees(this.employees)
} }
@@ -8,24 +8,25 @@
</div> </div>
<v-card-actions class="d-flex flex-column modal-content"> <v-card-actions class="d-flex flex-column modal-content">
<v-text-field @focus="onInputFocus" class="modal-input" label="Názov blockeru" :class="{ error: v$.blocker.name.$errors.length }" :hint="v$.blocker.name.$errors ? errorUtils.parseErrors(v$.blocker.name.$errors) : null" v-model="blocker.name" variant="solo"></v-text-field> <v-text-field @focus="onInputFocus" class="modal-input" label="Názov blockeru"
:class="{ error: v$.blocker.name.$errors.length }"
<v-autocomplete :hint="v$.blocker.name.$errors ? errorUtils.parseErrors(v$.blocker.name.$errors) : null"
clearable v-model="blocker.name" variant="solo"></v-text-field>
label="Vyhľadať zamestnanca"
:items="[...enrichedEmployees]"
item-title="_fullName"
item-value="id"
variant="solo"
class="modal-input"
v-model="blocker.employee_id" <v-autocomplete :custom-filter="customFilter" :match-any="true" clearable label="Vyhľadať zamestnanca"
/> :items="[...enrichedEmployees]" item-title="_fullName" item-value="id" variant="solo"
class="modal-input" v-model="blocker.employee_id" />
<!-- <Z-autocomplete label="Vyhľadať zamestnanca" :value="blocker?.employee ? `${blocker?.employee?.name} ${blocker?.employee?.surname}` : ''" :options="enrichedEmployees.map(employee => ({key: employee.id, value: employee._fullName}))" :clear-on-submit="false" :class="{ error: v$.blocker.employee.$errors.length }" class="modal-input" @option-selected="onEmployeeSelected" /> --> <!-- <Z-autocomplete label="Vyhľadať zamestnanca" :value="blocker?.employee ? `${blocker?.employee?.name} ${blocker?.employee?.surname}` : ''" :options="enrichedEmployees.map(employee => ({key: employee.id, value: employee._fullName}))" :clear-on-submit="false" :class="{ error: v$.blocker.employee.$errors.length }" class="modal-input" @option-selected="onEmployeeSelected" /> -->
<Datepicker class="modal-input mb-5" v-model="datepicker" format="dd.MM.yyyy" locale="sk" :class="{ error: v$.datepicker.$errors?.length }" :validations="v$.datepicker" select-text="Vybrať" cancel-text="Zrušiť" placeholder="Dátum" :enable-time-picker="false" ref="datepicker" /> <Datepicker class="modal-input mb-5" v-model="datepicker" format="dd.MM.yyyy" locale="sk"
:class="{ error: v$.datepicker.$errors?.length }" :validations="v$.datepicker" select-text="Vybrať"
cancel-text="Zrušiť" placeholder="Dátum" :enable-time-picker="false" ref="datepicker" />
<v-text-field v-model="starts_at_time" type="time" variant="solo" bg-color="white" :hint="v$.starts_at_time.$errors ? errorUtils.parseErrors(v$.starts_at_time.$errors) : null" :class="{ error: v$.starts_at_time.$errors.length }" class="mb-1 modal-input" label="Začiatok" /> <v-text-field v-model="starts_at_time" type="time" variant="solo" bg-color="white"
<v-text-field v-model="ends_at_time" type="time" variant="solo" bg-color="white" :hint="v$.ends_at_time.$errors ? errorUtils.parseErrors(v$.ends_at_time.$errors) : null" :class="{ error: v$.ends_at_time.$errors.length }" class="modal-input" label="Koniec" /> :hint="v$.starts_at_time.$errors ? errorUtils.parseErrors(v$.starts_at_time.$errors) : null"
:class="{ error: v$.starts_at_time.$errors.length }" class="mb-1 modal-input" label="Začiatok" />
<v-text-field v-model="ends_at_time" type="time" variant="solo" bg-color="white"
:hint="v$.ends_at_time.$errors ? errorUtils.parseErrors(v$.ends_at_time.$errors) : null"
:class="{ error: v$.ends_at_time.$errors.length }" class="modal-input" label="Koniec" />
</v-card-actions> </v-card-actions>
<v-btn class="button primary" @click="save()">{{ blocker.id ? "UPRAVIŤ" : "VYTVORIŤ" }}</v-btn> <v-btn class="button primary" @click="save()">{{ blocker.id ? "UPRAVIŤ" : "VYTVORIŤ" }}</v-btn>
@@ -35,17 +36,17 @@
</template> </template>
<script> <script>
import Datepicker from "@vuepic/vue-datepicker" import Datepicker from "@vuepic/vue-datepicker"
import useVuelidate from "@vuelidate/core" import useVuelidate from "@vuelidate/core"
import { required } from "@vuelidate/validators" import { required } from "@vuelidate/validators"
import errorUtils from "@/plugins/lib@auth/_utils/error.utils" import errorUtils from "@/plugins/lib@auth/_utils/error.utils"
import VuetifyFixFocusMixin from "@/plugins/tm@modal/_mixins/vuetify-fix-focus" import VuetifyFixFocusMixin from "@/plugins/tm@modal/_mixins/vuetify-fix-focus"
import { mapGetters } from "vuex" import { mapGetters } from "vuex"
import moment from "moment" import moment from "moment"
// import ZAutocomplete from '@/plugins/tm@_components/z-autocomplete.vue' import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
export default { export default {
mixins: [VuetifyFixFocusMixin], mixins: [VuetifyFixFocusMixin, AutocompleteMixin],
emits: ["close"], emits: ["close"],
@@ -53,6 +53,24 @@ export default {
return employee return employee
}) })
if (!this.mastertask.team)
return this.mastertask.duration = totalDuration
this.mastertask.team.employees = this.mastertask.team.employees.map(employee => {
if (isNaN(employee.duration) || isNaN(parseFloat(employee.duration)))
return employee
if (typeof employee.duration == 'string') {
totalDuration += parseFloat(employee.duration)
employee.duration = parseFloat(employee.duration)
}
else if (typeof employee.duration == 'number') {
totalDuration += employee.duration
}
return employee
})
this.mastertask.duration = totalDuration this.mastertask.duration = totalDuration
} }
}, },
@@ -62,7 +80,7 @@ export default {
if (!value) return if (!value) return
this.mastertask.team = this.teams.find(team => team.id == value) this.mastertask.team = this.teams.find(team => team.id == value)
this.mastertask.employees = this.mastertask.team.employees // this.mastertask.employees = this.mastertask.team.employees
}, },
} }
} }
@@ -8,7 +8,7 @@
</div> </div>
<v-card-actions class="d-flex flex-column modal-content"> <v-card-actions class="d-flex flex-column modal-content">
<v-autocomplete 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> <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>
@@ -21,28 +21,31 @@
:class="{ error: v$.mastertask._deadline_time.$errors.length }" :hint="v$.mastertask._deadline_time.$errors ? errorUtils.parseErrors(v$.mastertask._deadline_time.$errors) : null" /> :class="{ error: v$.mastertask._deadline_time.$errors.length }" :hint="v$.mastertask._deadline_time.$errors ? errorUtils.parseErrors(v$.mastertask._deadline_time.$errors) : null" />
</div> </div>
<v-text-field v-model="mastertask.duration" @focus="onInputFocus" class="modal-input" variant="solo" type="number" :label="`${mastertask.duration} h`"></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"></v-select> <v-select v-model="mastertask.team_id" @focus="onInputFocus" class="modal-input border-select" label="Tím" variant="solo" :items="teams" item-value="id" item-title="name"></v-select>
<template v-if="!mastertask.id && mastertask.team_id"> <template v-if="mastertask.team && mastertask.team_id">
<v-text-field v-for="(employee, index) in mastertask.team.employees" :key="employee.id" @focus="onInputFocus" class="modal-input" :label="`${employee.name} ${employee.surname}`" variant="solo" placeholder="h" v-model="mastertask.team.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>
<v-icon @click.stop="removeEmployeeFromTeam(employee)" class="remove-input" icon="mdi-close" size="small"></v-icon>
</v-text-field>
</template>
<template v-if="mastertask.employees">
<v-text-field v-for="(employee, index) in mastertask.employees" :key="employee.id" @focus="onInputFocus" class="modal-input" :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" :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"> <p class="employee-select-avatar d-flex justify-center align-center">
{{ employee?.name.charAt(0) + employee?.surname.charAt(0) }} {{ employee?.name.charAt(0) + employee?.surname.charAt(0) }}
</p> </p>
<v-icon @click.stop="removeMemberAlert(employee)" class="remove-input" icon="mdi-close" size="small"></v-icon>
</v-text-field> <v-icon @click.stop="removeEmployee(employee)" class="remove-input" icon="mdi-close" size="small"></v-icon>
</template>
<template v-if="!mastertask.id && !mastertask.team_id && mastertask.employees">
<v-text-field v-for="(employee, index) in mastertask.employees" :key="employee.id" @focus="onInputFocus" class="modal-input" :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>
<!-- <v-icon @click.stop="removeMemberAlert(employee)" class="remove-input" icon="mdi-close" size="small"></v-icon> -->
</v-text-field> </v-text-field>
</template> </template>
<v-autocomplete 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" /> --> <!-- <Z-autocomplete label="Vyhľadať zamestnanca" :options="employeesOptions" class="modal-input" @option-selected="onEmployeeSelected" /> -->
@@ -109,6 +112,7 @@ import SelectsMixin from './_mixins/selects.mixin'
import ATasksTable from './_components/a-tasks-table.vue' import ATasksTable from './_components/a-tasks-table.vue'
import AMastertaskDescription from './_components/a-mastertask-description.vue' import AMastertaskDescription from './_components/a-mastertask-description.vue'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
export default { export default {
// MIXINS // MIXINS
@@ -117,7 +121,7 @@ export default {
// watch: mastertask.team_id // watch: mastertask.team_id
emits: ['master-task-edited', 'close'], emits: ['master-task-edited', 'close'],
mixins: [VuetifyFixFocusMixin, SelectsMixin], mixins: [VuetifyFixFocusMixin, SelectsMixin, AutocompleteMixin],
components: { components: {
AMastertaskDescription, AMastertaskDescription,
@@ -170,7 +174,6 @@ export default {
return { return {
mastertask: { mastertask: {
project_id: { required }, project_id: { required },
employees: { required },
name: { required }, name: { required },
description: { required }, description: { required },
deadline: { required }, deadline: { required },
@@ -215,6 +218,17 @@ export default {
}, },
methods: { methods: {
removeEmployeeFromTeam({ id }) {
const employees = this.mastertask.team.employees.filter(employee => employee.id != id)
this.mastertask.employees = [...employees, ...this.mastertask.employees]
this.mastertask.team_id = null
this.mastertask.team = null
},
removeEmployee({ id }) {
this.mastertask.employees = this.mastertask.employees.filter(employee => employee.id != id)
},
removeMemberAlert(member) { removeMemberAlert(member) {
const team = this.mastertask.team const team = this.mastertask.team
this.$events.emit('show-delete-team-member-modal', { member, team }) this.$events.emit('show-delete-team-member-modal', { member, team })
@@ -244,7 +258,7 @@ export default {
this.editMode = editMode || !this.mastertask.id this.editMode = editMode || !this.mastertask.id
} catch (error) { } catch (error) {
this.$toast.error(error) this.$toast.error(error.message || error)
} }
}, },
@@ -254,6 +268,7 @@ export default {
}, },
async save() { async save() {
console.log(this.mastertask)
if (!(await this.v$.$validate())) return if (!(await this.v$.$validate())) return
if (this.$refs['description']) if (this.$refs['description'])
@@ -10,7 +10,7 @@
<v-card-actions class="d-flex flex-column modal-content"> <v-card-actions class="d-flex flex-column modal-content">
<v-text-field v-model="subtask.project_code" label="Kód projektu" :value="subtask.project_code" @focus="onInputFocus" class="modal-input" variant="solo" disabled></v-text-field> <v-text-field v-model="subtask.project_code" label="Kód projektu" :value="subtask.project_code" @focus="onInputFocus" class="modal-input" variant="solo" disabled></v-text-field>
<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 :custom-filter="customFilter" :match-any="true" 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.title" @focus="onInputFocus" class="modal-input" label="Názov subtasku" variant="solo"></v-text-field> <v-text-field v-model="subtask.title" @focus="onInputFocus" class="modal-input" label="Názov subtasku" variant="solo"></v-text-field>
@@ -36,7 +36,7 @@
</div> --> </div> -->
<template v-if="subtask.id"> <template v-if="subtask.id">
<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 }" <v-autocomplete :custom-filter="customFilter" :match-any="true" 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" /> @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" <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" /> @update:model-value="employeeValidations[0] ? employeeValidations[0].duration = false : null" />
@@ -44,7 +44,7 @@
<template v-else> <template v-else>
<div v-for="(employee, index) in subtask.employees" :key="`employee-${index}`" class="splitted-inputs"> <div v-for="(employee, index) in subtask.employees" :key="`employee-${index}`" class="splitted-inputs">
<v-autocomplete v-model="employee.id" label="Priradený" :items="enrichedEmployees" item-title="_fullName" item-value="id" variant="solo" class="modal-input left" :class="{ error: employeeValidations[index]?.employee }" <v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="employee.id" label="Priradený" :items="enrichedEmployees" item-title="_fullName" item-value="id" variant="solo" class="modal-input left" :class="{ error: employeeValidations[index]?.employee }"
@update:model-value="employeeValidations[index] ? employeeValidations[index].employee = false : null" /> @update:model-value="employeeValidations[index] ? employeeValidations[index].employee = false : null" />
<v-text-field v-model="employee.duration" class="modal-input right" variant="solo" type="number" label="Časový odhad" append-inner-icon="mdi-clock-outline" :class="{ error: employeeValidations[index]?.duration }" @focus="onInputFocus" <v-text-field v-model="employee.duration" class="modal-input right" 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" /> @update:model-value="employeeValidations[index] ? employeeValidations[index].duration = false : null" />
@@ -115,13 +115,14 @@ import * as FileSaver from "file-saver"
import tmUtils from "@/plugins/tm@_utils/tm.utils" import tmUtils from "@/plugins/tm@_utils/tm.utils"
import moment from 'moment' import moment from 'moment'
import "@vueup/vue-quill/dist/vue-quill.snow.css" import "@vueup/vue-quill/dist/vue-quill.snow.css"
import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
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"
export default { export default {
emits: ["close", "refresh"], emits: ["close", "refresh"],
mixins: [VuetifyFixFocusMixin, SelectsMixin], mixins: [VuetifyFixFocusMixin, SelectsMixin, AutocompleteMixin],
components: { components: {
ZTaskReadonlyInfo, ZTaskReadonlyInfo,
@@ -24,7 +24,7 @@
size="small"></v-icon> size="small"></v-icon>
</div> </div>
<v-autocomplete v-model="employeeSelect" label="Priradený" <v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="employeeSelect" label="Priradený"
:class="{ error: v$.team.employees.$errors.length }" :items="employeesOptions" :class="{ error: v$.team.employees.$errors.length }" :items="employeesOptions"
item-title="_fullName" item-value="id" variant="solo" class="modal-input" clearable item-title="_fullName" item-value="id" variant="solo" class="modal-input" clearable
ref="autocomplete" /> ref="autocomplete" />
@@ -42,10 +42,12 @@ import { required } from '@vuelidate/validators'
import errorUtils from '@/plugins/lib@auth/_utils/error.utils' import errorUtils from '@/plugins/lib@auth/_utils/error.utils'
import tmUtils from '@/plugins/tm@_utils/tm.utils' import tmUtils from '@/plugins/tm@_utils/tm.utils'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
const atLeastOne = (value) => value.length const atLeastOne = (value) => value.length
export default { export default {
mixins: [AutocompleteMixin],
emits: ['close', 'update'], emits: ['close', 'update'],
data() { data() {
@@ -1,6 +1,6 @@
<template> <template>
<v-row class="px-10 py-8 subheader"> <v-row class="px-10 py-8 subheader">
<v-autocomplete <v-autocomplete :custom-filter="customFilter" :match-any="true"
v-model="selectedEmployeeId" v-model="selectedEmployeeId"
class="subheader-input" class="subheader-input"
variant="outlined" variant="outlined"
@@ -24,8 +24,10 @@
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import AutocompleteMixin from '@/plugins/tm@_mixins/autocomplete.mixin'
export default { export default {
mixins: [AutocompleteMixin],
emits: ['search', 'employee-selected'], emits: ['search', 'employee-selected'],
data() { data() {