mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 14:29:34 +00:00
Merge branch 'main' of bitbucket.org:studiotem/jandl-taskmanager-app
This commit is contained in:
commit
32868dda3e
7 files changed
+98
-143
No files matched your search
@@ -79,8 +79,8 @@ export default {
|
|||||||
this.$refs['z-complete-task-modal'].showModal({ subtask })
|
this.$refs['z-complete-task-modal'].showModal({ subtask })
|
||||||
})
|
})
|
||||||
|
|
||||||
this.$events.on('show-blocker-modal', ({blocker}) => {
|
this.$events.on('show-blocker-modal', ({blocker = {}}) => {
|
||||||
this.$refs['z-blocker-modal'].showModal(blocker)
|
this.$refs['z-blocker-modal'].showModal({blocker})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.$events.on('show-task-add-time-modal', ({subtask}) => {
|
this.$events.on('show-task-add-time-modal', ({subtask}) => {
|
||||||
|
|||||||
@@ -44,18 +44,17 @@ const options: Options = {
|
|||||||
},
|
},
|
||||||
moxios: {
|
moxios: {
|
||||||
routes: {
|
routes: {
|
||||||
'GET v1/auth/info': true,
|
// 'GET v1/auth/info': true,
|
||||||
'POST v1/auth/forgot': true,
|
// 'POST v1/auth/forgot': true,
|
||||||
'POST v1/auth/reset': true,
|
// 'POST v1/auth/reset': true,
|
||||||
'POST v1/auth/info': true,
|
// 'POST v1/auth/info': true,
|
||||||
'POST v1/auth/invalidate': true,
|
// 'POST v1/auth/invalidate': true,
|
||||||
'POST v1/auth/login': true,
|
// 'POST v1/auth/login': true,
|
||||||
'POST v1/auth/post': true,
|
// 'POST v1/auth/post': true,
|
||||||
|
|
||||||
'GET v1/overview/teams': true,
|
'GET v1/overview/teams': true,
|
||||||
'GET v1/overview/tasks': true,
|
'GET v1/overview/tasks': true,
|
||||||
'GET v1/search': true,
|
'GET v1/search': true,
|
||||||
'POST v1/blockers': true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
<v-btn class="menu-dropdown" v-bind="props">
|
<v-btn class="menu-dropdown" v-bind="props">
|
||||||
<div class="d-flex justify-between align-center">
|
<div class="d-flex justify-between align-center">
|
||||||
<p class="employee-select-avatar d-flex justify-center align-center" @click.stop="$router.push({name: 'Dashboard - User'})">
|
<p class="employee-select-avatar d-flex justify-center align-center" @click.stop="$router.push({name: 'Dashboard - User'})">
|
||||||
{{ user.name?.charAt(0) || '' + user.surname?.charAt(0) || '' }}
|
{{ user.firstname.charAt(0) }}{{ user.lastname.charAt(0) }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<span class="employee-name ml-4">{{ `${user.name} ${user.surname || ''}` }}</span>
|
<span class="employee-name ml-4">{{ `${user.firstname} ${user.lastname || ''}` }}</span>
|
||||||
<v-icon class="ml-3" icon="mdi-chevron-down" size="x-small"></v-icon>
|
<v-icon class="ml-3" icon="mdi-chevron-down" size="x-small"></v-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import ZTimeline from '@/plugins/tm@dashboard/_components/z-timeline.vue
|
|||||||
import { addDays, subDays } from 'date-fns'
|
import { addDays, subDays } from 'date-fns'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import timelineUtils from './_utils/timeline.utils'
|
import timelineUtils from './_utils/timeline.utils'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -30,6 +31,10 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapGetters('auth', [
|
||||||
|
'user'
|
||||||
|
]),
|
||||||
|
|
||||||
splitDays() {
|
splitDays() {
|
||||||
const days = []
|
const days = []
|
||||||
const workingHours = {}
|
const workingHours = {}
|
||||||
|
|||||||
@@ -25,45 +25,19 @@
|
|||||||
v-model="blocker.name"
|
v-model="blocker.name"
|
||||||
variant="solo"
|
variant="solo"
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
<div
|
<v-select v-model="blocker.employee_id" ref="employee-select" @focus="onInputFocus" class="modal-input border-select" label="Priradený" :class="{ error: v$.blocker.employee_id.$errors.length }" variant="solo" :items="enrichedEmployees" item-value="id" item-title="_fullName"></v-select>
|
||||||
class="relative w-100"
|
|
||||||
v-for="(employee, index) in blocker.employees"
|
|
||||||
:key="employee.id"
|
|
||||||
>
|
|
||||||
<v-text-field
|
|
||||||
class="modal-input"
|
|
||||||
disabled
|
|
||||||
label="Zamestanec"
|
|
||||||
variant="outlined"
|
|
||||||
v-model="blocker.employees[index]._fullName"
|
|
||||||
>
|
|
||||||
</v-text-field>
|
|
||||||
<v-icon
|
|
||||||
class="remove-input"
|
|
||||||
@click.stop="blocker.employees.splice(index, 1)"
|
|
||||||
icon="mdi-close"
|
|
||||||
size="small"
|
|
||||||
></v-icon>
|
|
||||||
</div>
|
|
||||||
<Z-autocomplete
|
|
||||||
label="Vyhľadať zamestnanca"
|
|
||||||
:options="employeesOptions"
|
|
||||||
class="modal-input"
|
|
||||||
:class="{ error: v$.blocker.employees.$errors.length }"
|
|
||||||
@option-selected="employeeSelected"
|
|
||||||
/>
|
|
||||||
<Datepicker
|
<Datepicker
|
||||||
class="modal-input"
|
class="modal-input"
|
||||||
v-model="blocker.date"
|
v-model="startEndDate"
|
||||||
format="dd.MM.yyyy, HH:mm"
|
format="dd.MM.yyyy, HH:mm"
|
||||||
locale="sk"
|
locale="sk"
|
||||||
:class="{ error: v$.blocker.date.$errors.length }"
|
:class="{ error: v$.blocker.start.$errors.length || v$.blocker.end.$errors.length }"
|
||||||
@focus="onDateFocus"
|
|
||||||
:validations="v$.blocker.employees"
|
:validations="v$.blocker.employees"
|
||||||
select-text="Vybrať"
|
select-text="Vybrať"
|
||||||
cancel-text="Zrušiť"
|
cancel-text="Zrušiť"
|
||||||
placeholder="Trvanie od - do"
|
placeholder="Trvanie od - do"
|
||||||
range
|
range
|
||||||
|
ref="datepicker"
|
||||||
/>
|
/>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
|
|
||||||
@@ -74,15 +48,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ZAutocomplete from '@/plugins/tm@_components/z-autocomplete.vue'
|
|
||||||
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 tmUtils from '@/plugins/tm@_utils/tm.utils'
|
import tmUtils from '@/plugins/tm@_utils/tm.utils'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
const atLeastOne = (value) => value.length
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [VuetifyFixFocusMixin],
|
mixins: [VuetifyFixFocusMixin],
|
||||||
@@ -90,44 +62,36 @@ export default {
|
|||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
ZAutocomplete,
|
Datepicker
|
||||||
Datepicker,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
employees: null,
|
|
||||||
v$: useVuelidate(),
|
v$: useVuelidate(),
|
||||||
errorUtils,
|
errorUtils,
|
||||||
blocker: null
|
blocker: null,
|
||||||
|
startEndDate: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
employeesOptions() {
|
...mapGetters('tm', [
|
||||||
const selectedEmployeesIds = this.blocker.employees.map(
|
'enrichedEmployees'
|
||||||
(employee) => employee.id
|
]),
|
||||||
)
|
|
||||||
const employees = this.employees.filter(
|
|
||||||
(employee) => !selectedEmployeesIds.includes(employee.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
return employees.map((employee) => {
|
...mapGetters('auth', [
|
||||||
return {
|
'user'
|
||||||
key: employee.id,
|
])
|
||||||
value: `${employee.name} ${employee.surname}`,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
validations() {
|
validations() {
|
||||||
return {
|
return {
|
||||||
blocker: {
|
blocker: {
|
||||||
name: { required },
|
name: { required },
|
||||||
date: { required },
|
start: { required },
|
||||||
employees: { atLeastOne }
|
end: { required },
|
||||||
|
employee_id: { required }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -136,35 +100,30 @@ export default {
|
|||||||
async showModal({ blocker }) {
|
async showModal({ blocker }) {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.blocker = null
|
this.blocker = null
|
||||||
|
this.startEndDate = null
|
||||||
this.$nextTick(() => this.v$.$reset())
|
this.$nextTick(() => this.v$.$reset())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const employees = await this.$axios.get_auth_data('v1/employees')
|
|
||||||
this.employees = tmUtils.enrichEmployees(employees)
|
|
||||||
|
|
||||||
if (blocker?.id) {
|
if (blocker?.id) {
|
||||||
const b = await this.$axios.get_auth_data(`v1/blockers/${blocker.id}`)
|
blocker = await this.$axios.get_auth_data(`v1/blockers/${blocker.id}`)
|
||||||
this.blocker = {...b, employees: tmUtils.enrichEmployees(b.employees)}
|
blocker.employee_id = blocker.employee.id
|
||||||
|
this.startEndDate = [new Date(blocker.start), new Date(blocker.end)]
|
||||||
|
this.blocker = blocker
|
||||||
} else {
|
} else {
|
||||||
this.blocker = {employees: []}
|
this.blocker = {start: null}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$toast.error(error)
|
this.$toast.error(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
employeeSelected(selectedOption) {
|
|
||||||
const employee = this.employees.find((empl) => empl.id == selectedOption.key)
|
|
||||||
this.blocker.employees.push(employee)
|
|
||||||
},
|
|
||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
if (!(await this.v$.$validate()))
|
if (!(await this.v$.$validate()))
|
||||||
return
|
return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.blocker.id)
|
if (this.blocker.id)
|
||||||
await this.$axios.post_auth(`v1/blockers/${this.blocker.id}`, this.blocker)
|
await this.$axios.put_auth(`v1/blockers/${this.blocker.id}`, this.blocker)
|
||||||
else
|
else
|
||||||
await this.$axios.post_auth('v1/blockers', this.blocker)
|
await this.$axios.post_auth('v1/blockers', this.blocker)
|
||||||
|
|
||||||
@@ -175,9 +134,27 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
closeModal() {
|
closeModal() {
|
||||||
|
this.$refs['datepicker'].clearValue()
|
||||||
this.visible = false
|
this.visible = false
|
||||||
this.$emit('close', this.blocker)
|
this.$emit('close', this.blocker)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
startEndDate(value) {
|
||||||
|
if (!value || !value[1])
|
||||||
|
return
|
||||||
|
|
||||||
|
this.startEndDate[0] = this.startEndDate[0].setHours(this.user.work_start, 0, 0, 0)
|
||||||
|
this.startEndDate[1] = this.startEndDate[1].setHours(this.user.work_end, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
this.blocker = {
|
||||||
|
...this.blocker,
|
||||||
|
start: tmUtils.formatDateTimeForBackend(this.startEndDate[0]),
|
||||||
|
end: tmUtils.formatDateTimeForBackend(this.startEndDate[1]),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -1,61 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="border-bottom py-5 px-5">
|
<div class="border-bottom py-5 px-5">
|
||||||
<h1>Všeobecné informácie</h1>
|
<h1>Všeobecné informácie</h1>
|
||||||
<v-text-field
|
<v-text-field class="w-75" variant="solo" label="Meno" :disabled="true" v-model="user.firstname"></v-text-field>
|
||||||
class="w-75"
|
<v-text-field class="w-75" variant="solo" label="Priezvisko" v-model="user.lastname" :disabled="true"></v-text-field>
|
||||||
variant="solo"
|
|
||||||
label="Meno"
|
|
||||||
v-model="user.name"
|
|
||||||
:class="{ error: v$.user.name.$errors.length }"
|
|
||||||
:hint="
|
|
||||||
v$.user.name.$errors
|
|
||||||
? errorUtils.parseErrors(v$.user.name.$errors)
|
|
||||||
: null
|
|
||||||
"
|
|
||||||
></v-text-field>
|
|
||||||
<v-text-field
|
|
||||||
class="w-75"
|
|
||||||
variant="solo"
|
|
||||||
label="Priezvisko"
|
|
||||||
v-model="user.surname"
|
|
||||||
:class="{ error: v$.user.surname.$errors.length }"
|
|
||||||
:hint="
|
|
||||||
v$.user.surname.$errors
|
|
||||||
? errorUtils.parseErrors(v$.user.surname.$errors)
|
|
||||||
: null
|
|
||||||
"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="py-5 px-5 border-bottom">
|
<div class="py-5 px-5 border-bottom">
|
||||||
<h1>Pracovná doba</h1>
|
<h1>Pracovná doba</h1>
|
||||||
<v-text-field
|
<v-text-field class="w-75" variant="solo" label="Začiatok" v-model="form.work_start" append-inner-icon="mdi-clock-outline" type="time" :class="{ error: v$.form.work_start.$errors.length }" :hint="v$.form.work_start.$errors ? errorUtils.parseErrors(v$.form.work_start.$errors) : null"></v-text-field>
|
||||||
class="w-75"
|
<v-text-field class="w-75" variant="solo" label="Koniec" v-model="form.work_end" append-inner-icon="mdi-clock-outline" type="time" :class="{ error: v$.form.work_end.$errors.length }" :hint="v$.form.work_end.$errors ? errorUtils.parseErrors(v$.form.work_end.$errors) : null"></v-text-field>
|
||||||
variant="solo"
|
|
||||||
label="Začiatok"
|
|
||||||
v-model="user.work_hours_from"
|
|
||||||
append-inner-icon="mdi-clock-outline"
|
|
||||||
type="time"
|
|
||||||
:class="{ error: v$.user.work_hours_from.$errors.length }"
|
|
||||||
:hint="
|
|
||||||
v$.user.work_hours_from.$errors
|
|
||||||
? errorUtils.parseErrors(v$.user.work_hours_from.$errors)
|
|
||||||
: null
|
|
||||||
"
|
|
||||||
></v-text-field>
|
|
||||||
<v-text-field
|
|
||||||
class="w-75"
|
|
||||||
variant="solo"
|
|
||||||
label="Koniec"
|
|
||||||
v-model="user.work_hours_to"
|
|
||||||
append-inner-icon="mdi-clock-outline"
|
|
||||||
:class="{ error: v$.user.work_hours_to.$errors.length }"
|
|
||||||
:hint="
|
|
||||||
v$.user.work_hours_to.$errors
|
|
||||||
? errorUtils.parseErrors(v$.user.work_hours_to.$errors)
|
|
||||||
: null
|
|
||||||
"
|
|
||||||
type="time"
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="py-5 px-5">
|
<div class="py-5 px-5">
|
||||||
<v-btn class="button primary" @click="updateUserInfo()">ULOŽIŤ ZMENY</v-btn>
|
<v-btn class="button primary" @click="updateUserInfo()">ULOŽIŤ ZMENY</v-btn>
|
||||||
@@ -63,46 +15,68 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
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 { mapGetters } from 'vuex'
|
import { mapGetters } from "vuex"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
errorUtils,
|
errorUtils,
|
||||||
v$: useVuelidate(),
|
v$: useVuelidate(),
|
||||||
|
form: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('auth', ['user']),
|
...mapGetters("auth", ["user"])
|
||||||
},
|
},
|
||||||
|
|
||||||
validations() {
|
validations() {
|
||||||
return {
|
return {
|
||||||
user: {
|
form: {
|
||||||
name: { required },
|
work_start: { required },
|
||||||
surname: { required },
|
work_end: { required }
|
||||||
work_hours_from: { required },
|
|
||||||
work_hours_to: { required },
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this._setDates()
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async updateUserInfo() {
|
async updateUserInfo() {
|
||||||
if (!(await this.v$.$validate())) return
|
if (!(await this.v$.$validate())) return
|
||||||
try {
|
|
||||||
await this.$store.dispatch('auth/updateUserInfo', this.user)
|
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
id: this.user.id,
|
||||||
|
work_start: parseInt(this.form.work_start.split(':')[0]),
|
||||||
|
work_end: parseInt(this.form.work_end.split(':')[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('auth/updateUserInfo', data)
|
||||||
this.$toast.success('Profil bol úspešne zmenený')
|
this.$toast.success('Profil bol úspešne zmenený')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$toast.error(error)
|
this.$toast.error(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_setDates() {
|
||||||
|
this.form = {
|
||||||
|
work_start: this.user.work_start < 10 ? `0${this.user.work_start}:00` : `${this.user.work_start}:00`,
|
||||||
|
work_end: this.user.work_end < 10 ? `0${this.user.work_end}:00` : `${this.user.work_end}:00`
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
user() {
|
||||||
|
this._setDates()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ export default {
|
|||||||
},
|
},
|
||||||
updateUserInfo({commit}: {commit: any}, data: any) {
|
updateUserInfo({commit}: {commit: any}, data: any) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios.post_auth_data('v1/auth/info', data)
|
axios.put_auth(`v1/users/${data.id}`, {data: data})
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
const user = response.user
|
const user = response.user
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user