mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 14:29:34 +00:00
Merge branch 'task001/add-labels' of bitbucket.org:studiotem/jandl-taskmanager-app
This commit is contained in:
commit
4edc33c316
26 files changed
+380
-756
No files matched your search
@@ -51,7 +51,7 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-dialog v-model="showModal" max-width="750" persistent>
|
||||
<v-dialog v-model="showModal" :width="modalWidth" :height="modalHeight" persistent :retain-focus="false">
|
||||
<v-card>
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h1>Pridať odpracovaný čas</h1>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-dialog v-model="showModal" max-width="750" persistent>
|
||||
<v-dialog v-model="showModal" max-width="750" persistent :retain-focus="false">
|
||||
<v-card>
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h1>Pridať dátum</h1>
|
||||
@@ -70,8 +70,9 @@
|
||||
</div>
|
||||
|
||||
<v-card-actions class="mt-10 d-flex flex-column modal-content">
|
||||
<Datepicker
|
||||
<Z-datepicker
|
||||
v-model="form.date"
|
||||
label="Dátum"
|
||||
format="dd.MM.yyyy"
|
||||
locale="sk"
|
||||
select-text="Vybrať"
|
||||
@@ -115,7 +116,7 @@
|
||||
<v-btn class="button primary mt-5" @click="submit()">Potvrdiť</v-btn>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="visible" max-width="750" persistent>
|
||||
<v-dialog v-model="visible" max-width="750" persistent :retain-focus="false">
|
||||
<v-card>
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h1 class="text-red">
|
||||
@@ -152,7 +153,7 @@ import tmUtils from '@/plugins/tm@_utils/tm.utils';
|
||||
import errorUtils from '@/plugins/lib@auth/_utils/error.utils';
|
||||
import useVuelidate from '@vuelidate/core';
|
||||
import { required } from '@vuelidate/validators';
|
||||
import Datepicker from '@vuepic/vue-datepicker';
|
||||
import ZDatepicker from '@/plugins/tm@_components/z-datepicker.vue';
|
||||
import moment from 'moment';
|
||||
import modalMixin from '@/plugins/tm@modal/_mixins/modal.mixin';
|
||||
import { mapGetters } from 'vuex';
|
||||
@@ -160,7 +161,7 @@ import { mapGetters } from 'vuex';
|
||||
export default {
|
||||
|
||||
components: {
|
||||
Datepicker,
|
||||
ZDatepicker,
|
||||
},
|
||||
mixins: [modalMixin],
|
||||
|
||||
|
||||
@@ -3,14 +3,10 @@
|
||||
<div v-if="deletable && editable" class="x-button">
|
||||
<button class="x-button" @click="$emit('removeTimeblock')">x</button>
|
||||
</div>
|
||||
<div
|
||||
:ref="`timeblock-datepicker-wrapper-${index}`"
|
||||
class="datepicker-wrapper"
|
||||
@click="handleDatepickerClick"
|
||||
>
|
||||
<Datepicker
|
||||
:ref="`timeblock-datepicker-${index}`"
|
||||
<div class="datepicker-wrapper">
|
||||
<Z-datepicker
|
||||
:model-value="timeblock.date"
|
||||
label="Dátum"
|
||||
format="dd.MM.yyyy"
|
||||
locale="sk"
|
||||
select-text="Vybrať"
|
||||
@@ -48,11 +44,11 @@
|
||||
<script>
|
||||
import useVuelidate from '@vuelidate/core';
|
||||
import { requiredIf } from '@vuelidate/validators';
|
||||
import Datepicker from '@vuepic/vue-datepicker';
|
||||
import ZDatepicker from '@/plugins/tm@_components/z-datepicker.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Datepicker,
|
||||
ZDatepicker,
|
||||
},
|
||||
|
||||
props: {
|
||||
@@ -71,21 +67,6 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
|
||||
preventInputFocus: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
onInputFocus: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
onDateOpen: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
index: {
|
||||
type: Number,
|
||||
},
|
||||
@@ -107,49 +88,6 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleDatepickerClick() {
|
||||
// Pass the datepicker wrapper element reference to the mixin
|
||||
const scrollTarget =
|
||||
this.$refs[`timeblock-datepicker-wrapper-${this.index}`];
|
||||
this.onDateOpen(scrollTarget);
|
||||
// Open the datepicker
|
||||
this.openDatepicker(`timeblock-datepicker-${this.index}`);
|
||||
|
||||
setTimeout(() => {
|
||||
const calendar = document.querySelector(
|
||||
'.dp__menu.dp__menu_index.dp__theme_light',
|
||||
);
|
||||
|
||||
if (!calendar) return;
|
||||
|
||||
// Get the datepicker wrapper element
|
||||
const datepickerWrapper =
|
||||
this.$refs[`timeblock-datepicker-wrapper-${this.index}`];
|
||||
|
||||
// Get the modal container
|
||||
const modalContainer = document.querySelector('.v-overlay__content');
|
||||
|
||||
if (!datepickerWrapper || !modalContainer) return;
|
||||
|
||||
// Get bounding rectangles
|
||||
const wrapperRect = datepickerWrapper.getBoundingClientRect();
|
||||
const modalRect = modalContainer.getBoundingClientRect();
|
||||
|
||||
// Calculate position relative to modal
|
||||
const topPosition =
|
||||
wrapperRect.top - modalRect.top + wrapperRect.height;
|
||||
|
||||
// Apply positioning
|
||||
// calendar.style.position = 'absolute';
|
||||
calendar.style.top = `${topPosition + 210}px`;
|
||||
// calendar.style.left = `${leftPosition}px`;
|
||||
}, 100);
|
||||
},
|
||||
|
||||
async openDatepicker(ref) {
|
||||
this.$refs[ref].openMenu();
|
||||
},
|
||||
|
||||
updateDate(date) {
|
||||
const updated = { ...this.timeblock, date };
|
||||
this.$emit('updateTimeblock', updated);
|
||||
@@ -194,7 +132,4 @@ export default {
|
||||
|
||||
.datepicker-wrapper
|
||||
width: 100%
|
||||
.datepicker-input
|
||||
width: 100% !important
|
||||
pointer-events: none
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent :retain-focus="false">
|
||||
<v-card style="position: relative">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h1>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent :retain-focus="false">
|
||||
<v-card style="position: relative">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h1>Ste si istý, že chcete zmazať sub task z mastertasku <b>{{ subtask.project_code }}</b>?</h1>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent :retain-focus="false">
|
||||
<v-card style="position: relative">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h4 class="mt-3">Vyberte časový úsek, ktorý chcete odstrániť</h4>
|
||||
@@ -85,8 +85,9 @@ export default {
|
||||
this._update(subtask);
|
||||
},
|
||||
|
||||
deleteTimeblockWithoutId(i) {
|
||||
this.$emit('delete-timeblock');
|
||||
deleteTimeblockWithoutId(index) {
|
||||
this.subtask.timeblocks.splice(index, 1);
|
||||
this._update(this.subtask);
|
||||
},
|
||||
|
||||
async _update(data) {
|
||||
@@ -132,15 +133,6 @@ export default {
|
||||
this.$events.emit('on-subtask-edited', subtask);
|
||||
} catch (error) {
|
||||
this.$toast.error(error.message || error);
|
||||
|
||||
if (process.env.NODE_ENV === 'development')
|
||||
/* eslint-disable */ /* eslint-disable */console.log(
|
||||
...oo_oo(`3629952935_137_31_143_11_4`,...oo_oo(
|
||||
`2789641604_128_10_128_70_4`,
|
||||
'[z-delete-timeblock-modal.vue] Error: ',
|
||||
error,
|
||||
)),
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent>
|
||||
<v-dialog v-model="visible" :width="modalWidth" :height="modalHeight" persistent :retain-focus="false">
|
||||
<v-card style="position: relative">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h1>Pridať odpracovaný čas</h1>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
:width="modalWidth"
|
||||
:height="modalHeight"
|
||||
persistent
|
||||
:retain-focus="false"
|
||||
>
|
||||
<W-loadable :content="subtask" class="h-100">
|
||||
<v-card
|
||||
@@ -28,7 +29,6 @@
|
||||
class="modal-input"
|
||||
variant="solo"
|
||||
disabled
|
||||
@focus="onInputFocus"
|
||||
></v-text-field>
|
||||
|
||||
<v-autocomplete
|
||||
@@ -43,7 +43,6 @@
|
||||
variant="solo"
|
||||
class="modal-input"
|
||||
clearable
|
||||
@focus="onInputFocus"
|
||||
/>
|
||||
|
||||
<v-text-field
|
||||
@@ -51,7 +50,6 @@
|
||||
class="modal-input"
|
||||
label="Názov subtasku"
|
||||
variant="solo"
|
||||
@focus="onInputFocus"
|
||||
></v-text-field>
|
||||
|
||||
<div class="splitted-inputs">
|
||||
@@ -71,7 +69,6 @@
|
||||
placeholder="Deadline"
|
||||
:class="{ error: v$.subtask.deadline.$errors?.length }"
|
||||
:validations="v$.subtask.deadline"
|
||||
@open="onDateOpen"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -88,7 +85,6 @@
|
||||
? errorUtils.parseErrors(v$.subtask._deadline_time.$errors)
|
||||
: null
|
||||
"
|
||||
@focus="onInputFocus"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -159,7 +155,6 @@
|
||||
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)
|
||||
@@ -221,7 +216,6 @@
|
||||
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)
|
||||
@@ -239,12 +233,9 @@
|
||||
:timeblock="timeblock"
|
||||
:deletable="index > 0"
|
||||
:editable="true"
|
||||
:prevent-input-focus="preventInputFocus"
|
||||
:on-input-focus="onInputFocus"
|
||||
:on-date-open="onDateOpen"
|
||||
:index="index"
|
||||
@updateTimeblock="(val) => updateTimeblock(val, index)"
|
||||
@removeTimeblock="removeTimeblock(index)"
|
||||
@update-timeblock="(val) => updateTimeblock(val, index)"
|
||||
@remove-timeblock="removeTimeblock(index)"
|
||||
/>
|
||||
<div v-if="!subtask.id" class="end-button w-100">
|
||||
<button @click="addTimeblock">Pridať časový blok</button>
|
||||
@@ -351,7 +342,6 @@ import useVuelidate from '@vuelidate/core';
|
||||
import { required } from '@vuelidate/validators';
|
||||
import errorUtils from '@/plugins/lib@auth/_utils/error.utils';
|
||||
import { QuillEditor } from '@vueup/vue-quill';
|
||||
import VuetifyFixFocusMixin from '@/plugins/tm@modal/_mixins/vuetify-fix-focus';
|
||||
import SelectsMixin from '../master-task/_mixins/selects.mixin';
|
||||
import tmUtils from '@/plugins/tm@_utils/tm.utils';
|
||||
import moment from 'moment';
|
||||
@@ -367,6 +357,7 @@ import AResetSizeButton from '@/plugins/tm@modal/_components/a-reset-size-button
|
||||
import ACloseButton from '@/plugins/tm@modal/_components/a-close-button.vue';
|
||||
|
||||
export default {
|
||||
|
||||
components: {
|
||||
ZTaskReadonlyInfo,
|
||||
ATimeblock,
|
||||
@@ -378,7 +369,7 @@ export default {
|
||||
AResetSizeButton,
|
||||
ACloseButton,
|
||||
},
|
||||
mixins: [VuetifyFixFocusMixin, SelectsMixin, AutocompleteMixin, modalMixin],
|
||||
mixins: [SelectsMixin, AutocompleteMixin, modalMixin],
|
||||
emits: ['close', 'refresh'],
|
||||
|
||||
data() {
|
||||
@@ -446,6 +437,61 @@ export default {
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
'subtask.employee_id'(value, oldValue) {
|
||||
if (!value || !oldValue) return;
|
||||
|
||||
this.subtask.timeblocks = [];
|
||||
this.subtask._employee = this.enrichedEmployees.find(
|
||||
(employee) => employee.id == this.subtask.employee_id,
|
||||
);
|
||||
},
|
||||
|
||||
'subtask.employees': {
|
||||
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) {
|
||||
if (!value) return;
|
||||
this.subtask._master_task = this.mastertasks.find(
|
||||
(mastertask) => mastertask.id == this.subtask.master_task_id,
|
||||
);
|
||||
this.subtask.project_code =
|
||||
this.subtask._master_task?.project_code || null;
|
||||
},
|
||||
|
||||
editMode() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs['description']?.setHTML(this.subtask.description || '');
|
||||
});
|
||||
},
|
||||
|
||||
subtask: {
|
||||
handler(val) {
|
||||
if (this.editMode && !this.subtask?.id) {
|
||||
const employees = val?.employees?.filter(
|
||||
(employee) => employee?.id || employee?.duration,
|
||||
) || [{}];
|
||||
|
||||
const subtaskData = {
|
||||
...val,
|
||||
employees: employees && employees.length > 0 ? employees : [{}],
|
||||
};
|
||||
localStorage.setItem('subtaskData', JSON.stringify(subtaskData));
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$events.on('add-timeblock', (timeblock) => {
|
||||
if (!this.subtask?.timeblocks) {
|
||||
@@ -507,29 +553,6 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
// Override onDateOpen from VuetifyFixFocusMixin to add logging
|
||||
onDateOpen($event) {
|
||||
// Call the parent mixin's onDateOpen method
|
||||
if (
|
||||
VuetifyFixFocusMixin.methods &&
|
||||
VuetifyFixFocusMixin.methods.onDateOpen
|
||||
) {
|
||||
VuetifyFixFocusMixin.methods.onDateOpen.call(this, $event);
|
||||
}
|
||||
},
|
||||
|
||||
// Override onInputFocus from VuetifyFixFocusMixin to add logging
|
||||
onInputFocus($event) {
|
||||
const target = $event?.target;
|
||||
// Call the parent mixin's onInputFocus method
|
||||
if (
|
||||
VuetifyFixFocusMixin.methods &&
|
||||
VuetifyFixFocusMixin.methods.onInputFocus
|
||||
) {
|
||||
VuetifyFixFocusMixin.methods.onInputFocus.call(this, $event);
|
||||
}
|
||||
},
|
||||
|
||||
toggleEditMode() {
|
||||
if (this.subtask.type == 'office365')
|
||||
return this.$events.emit('show-unable-to-edit-office-task-modal', {
|
||||
@@ -599,7 +622,6 @@ export default {
|
||||
];
|
||||
this.$nextTick(() => {
|
||||
this.v$.$reset();
|
||||
this.setFocusEvent();
|
||||
|
||||
// Reset after modal is fully rendered and v-dialog autofocus has been blocked
|
||||
setTimeout(() => {
|
||||
@@ -671,13 +693,6 @@ export default {
|
||||
throw new Error('subtaskData is null or undefined');
|
||||
}
|
||||
} catch (error) {
|
||||
/* eslint-disable */ /* eslint-disable */console.error(
|
||||
...oo_tx(`721229222_674_33_680_13_11`,...oo_tx(
|
||||
`3261980582_640_12_640_62_11`,
|
||||
'Error parsing subtaskData:',
|
||||
error,
|
||||
)),
|
||||
);
|
||||
this.subtask = {
|
||||
master_task: mastertask,
|
||||
employees: [{}],
|
||||
@@ -706,15 +721,6 @@ export default {
|
||||
this.editMode = editMode || !this.subtask.id;
|
||||
} catch (error) {
|
||||
this.$toast.error(this.$parseError(error));
|
||||
|
||||
if (process.env.NODE_ENV === 'development')
|
||||
/* eslint-disable */ /* eslint-disable */console.log(
|
||||
...oo_oo(`721229222_711_31_717_11_4`,...oo_oo(
|
||||
`3261980582_671_10_671_58_4`,
|
||||
'[z-task-modal.vue] Error: ',
|
||||
error,
|
||||
)),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -837,15 +843,6 @@ export default {
|
||||
this.closeModal();
|
||||
} catch (error) {
|
||||
this.$toast.error(this.$parseError(error));
|
||||
|
||||
if (process.env.NODE_ENV === 'development')
|
||||
/* eslint-disable */ /* eslint-disable */console.log(
|
||||
...oo_oo(`721229222_842_31_848_11_4`,...oo_oo(
|
||||
`3261980582_788_10_788_58_4`,
|
||||
'[z-task-modal.vue] Error: ',
|
||||
error,
|
||||
)),
|
||||
);
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
}
|
||||
@@ -878,9 +875,6 @@ export default {
|
||||
|
||||
_mergeDeadlineTimeDate() {
|
||||
const date = new Date(this.subtask.deadline);
|
||||
/* eslint-disable */ /* eslint-disable */console.log(
|
||||
...oo_oo(`721229222_881_27_883_7_4`,...oo_oo(`3261980582_821_6_821_47_4`, 'z-task-modal', this.subtask)),
|
||||
);
|
||||
const timeParts = this.subtask._deadline_time.split(':');
|
||||
|
||||
date.setHours(parseInt(timeParts[0]));
|
||||
@@ -971,64 +965,6 @@ export default {
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
'subtask.employee_id'(value, oldValue) {
|
||||
if (!value || !oldValue) return;
|
||||
|
||||
this.subtask.timeblocks = [];
|
||||
this.subtask._employee = this.enrichedEmployees.find(
|
||||
(employee) => employee.id == this.subtask.employee_id,
|
||||
);
|
||||
},
|
||||
|
||||
'subtask.employees': {
|
||||
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) {
|
||||
if (!value) return;
|
||||
this.subtask._master_task = this.mastertasks.find(
|
||||
(mastertask) => mastertask.id == this.subtask.master_task_id,
|
||||
);
|
||||
this.subtask.project_code =
|
||||
this.subtask._master_task?.project_code || null;
|
||||
},
|
||||
|
||||
editMode() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs['description']?.setHTML(this.subtask.description || '');
|
||||
});
|
||||
},
|
||||
|
||||
subtask: {
|
||||
handler(val) {
|
||||
if (this.editMode && !this.subtask?.id) {
|
||||
const employees = val?.employees?.filter(
|
||||
(employee) => employee?.id || employee?.duration,
|
||||
) || [{}];
|
||||
|
||||
const subtaskData = {
|
||||
...val,
|
||||
employees: employees && employees.length > 0 ? employees : [{}],
|
||||
};
|
||||
/* eslint-disable */ /* eslint-disable */console.log(
|
||||
...oo_oo(`721229222_1023_31_1025_11_4`,...oo_oo(`3261980582_961_10_961_49_4`, 'subtaskData', subtaskData)),
|
||||
);
|
||||
localStorage.setItem('subtaskData', JSON.stringify(subtaskData));
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
:width="modalWidth"
|
||||
:height="modalHeight"
|
||||
persistent
|
||||
:retain-focus="false"
|
||||
>
|
||||
<v-card style="position: relative">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
:width="modalWidth"
|
||||
:height="modalHeight"
|
||||
persistent
|
||||
:retain-focus="false"
|
||||
>
|
||||
<v-card style="position: relative">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
|
||||
Reference in new issue
Block a user