mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-22 06:49:35 +00:00
refactor(task-modals): updated timeblocks to new local dat format
This commit is contained in:
1 parent
eaf83bf0cc
commit
0035251080
8 files changed
+1059
-597
No files matched your search
@@ -1,154 +1,226 @@
|
||||
<template>
|
||||
<v-table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th @click="getSelectedTimeblockDeadline" class="text-left">Kód projektu</th>
|
||||
<th class="text-left">Názov</th>
|
||||
<th class="text-left">Deadline</th>
|
||||
<th class="text-left">Najbližší neuzavretý</th>
|
||||
<th class="text-left">Naplánované</th>
|
||||
<th class="text-left">Zostávajúce</th>
|
||||
<th class="text-left">Akcia</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<v-table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th @click="getSelectedTimeblockDeadline" class="text-left">
|
||||
Kód projektu
|
||||
</th>
|
||||
<th class="text-left">Názov</th>
|
||||
<th class="text-left">Deadline</th>
|
||||
<th class="text-left">Najbližší neuzavretý</th>
|
||||
<th class="text-left">Naplánované</th>
|
||||
<th class="text-left">Zostávajúce</th>
|
||||
<th class="text-left">Akcia</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr class="cursor-pointer" v-for="subtask in subtasks" :key="subtask.id" @click.stop="editTask(subtask, false)">
|
||||
<td>{{ subtask.project_code }}</td>
|
||||
<td>{{ subtask.title ?? subtask.master_task }}</td>
|
||||
<td v-if="subtask.deadline">{{ getDeadline(subtask) }}</td>
|
||||
<v-tooltip text="Deadline z Mastertasku" location="end">
|
||||
<template v-slot:activator="{ props }">
|
||||
<td v-if="!subtask.deadline" v-bind="props">{{ getDeadline(subtask) }}*</td>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<td>{{ displayTimeblock(subtask) }}</td>
|
||||
<td>{{ subtask.duration }} h</td>
|
||||
<td>{{ (subtask.duration - subtask.spent_time).toFixed(2) }} h</td>
|
||||
<tbody>
|
||||
<tr
|
||||
class="cursor-pointer"
|
||||
v-for="subtask in subtasks"
|
||||
:key="subtask.id"
|
||||
@click.stop="editTask(subtask, false)"
|
||||
>
|
||||
<td>{{ subtask.project_code }}</td>
|
||||
<td>{{ subtask.title ?? subtask.master_task }}</td>
|
||||
<td v-if="subtask.deadline">{{ getDeadline(subtask) }}</td>
|
||||
<v-tooltip text="Deadline z Mastertasku" location="end">
|
||||
<template v-slot:activator="{ props }">
|
||||
<td v-if="!subtask.deadline" v-bind="props">
|
||||
{{ getDeadline(subtask) }}*
|
||||
</td>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<td>{{ displayTimeblock(subtask) }}</td>
|
||||
<td>{{ subtask.duration }} h</td>
|
||||
<td>{{ (subtask.duration - subtask.spent_time).toFixed(2) }} h</td>
|
||||
|
||||
<td class="task-action">
|
||||
<div class="d-flex justify-start align-center">
|
||||
<img class="pencil-icon mr-3" :class="{'disabled': loadingSubtask[subtask.id]}" :src="checkmarkDouble" @click.stop="handleCompleteTask(subtask)">
|
||||
<td class="task-action">
|
||||
<div class="d-flex justify-start align-center">
|
||||
<img
|
||||
class="pencil-icon mr-3"
|
||||
:class="{ disabled: loadingSubtask[subtask.id] }"
|
||||
:src="checkmarkDouble"
|
||||
@click.stop="handleCompleteTask(subtask)"
|
||||
/>
|
||||
|
||||
<template v-if="subtask.type == 'office365'">
|
||||
<img class="pencil-icon" :src="eye" @click.stop="editTask(subtask, false)">
|
||||
<img class="office-icon" :src="office365" />
|
||||
</template>
|
||||
<template v-if="subtask.type == 'office365'">
|
||||
<img
|
||||
class="pencil-icon"
|
||||
:src="eye"
|
||||
@click.stop="editTask(subtask, false)"
|
||||
/>
|
||||
<img class="office-icon" :src="office365" />
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<img class="pencil-icon" :src="eye" @click.stop="editTask(subtask, false)">
|
||||
<img class="trash-icon" :src="bin" @click.stop="deleteTask(subtask)" />
|
||||
</template>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
</v-table>
|
||||
<template v-else>
|
||||
<img
|
||||
class="pencil-icon"
|
||||
:src="eye"
|
||||
@click.stop="editTask(subtask, false)"
|
||||
/>
|
||||
<img
|
||||
class="trash-icon"
|
||||
:src="bin"
|
||||
@click.stop="deleteTask(subtask)"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { bin, eye, office365, checkmarkDouble } from '@/plugins/app/_img'
|
||||
import { bin, eye, office365, checkmarkDouble } from '@/plugins/app/_img';
|
||||
|
||||
import { mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import { mapGetters } from 'vuex';
|
||||
import moment from 'moment';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
subtasks: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
subtasks: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
eye,
|
||||
bin,
|
||||
office365,
|
||||
checkmarkDouble,
|
||||
loadingSubtask: {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
eye,
|
||||
bin,
|
||||
office365,
|
||||
checkmarkDouble,
|
||||
loadingSubtask: {},
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters('tm', ['mastertasks'])
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('tm', ['mastertasks']),
|
||||
},
|
||||
|
||||
methods: {
|
||||
editTask(subtask, editMode = false) {
|
||||
this.$events.emit('show-subtask-modal', {subtask, editMode})
|
||||
},
|
||||
methods: {
|
||||
editTask(subtask, editMode = false) {
|
||||
this.$events.emit('show-subtask-modal', { subtask, editMode });
|
||||
},
|
||||
|
||||
async handleCompleteTask(subtask) {
|
||||
const areAllTimeBlocksFinished = subtask.timeblocks.every(tb => tb.is_finished)
|
||||
async handleCompleteTask(subtask) {
|
||||
const areAllTimeBlocksFinished = subtask.timeblocks.every(
|
||||
(tb) => tb.is_finished,
|
||||
);
|
||||
|
||||
if (!areAllTimeBlocksFinished) {
|
||||
this.$events.emit('show-unable-to-complete-task-modal', { subtask })
|
||||
} else {
|
||||
await this._finishSubtask(subtask)
|
||||
}
|
||||
},
|
||||
if (!areAllTimeBlocksFinished) {
|
||||
this.$events.emit('show-unable-to-complete-task-modal', { subtask });
|
||||
} else {
|
||||
await this._finishSubtask(subtask);
|
||||
}
|
||||
},
|
||||
|
||||
deleteTask(subtask) {
|
||||
if (subtask.type == 'office365')
|
||||
return this.$events.emit('show-unable-to-edit-office-task-modal', { mode: 'delete' })
|
||||
deleteTask(subtask) {
|
||||
if (subtask.type == 'office365')
|
||||
return this.$events.emit('show-unable-to-edit-office-task-modal', {
|
||||
mode: 'delete',
|
||||
});
|
||||
|
||||
this.$events.emit('show-delete-task-modal', {subtask})
|
||||
},
|
||||
this.$events.emit('show-delete-task-modal', { subtask });
|
||||
},
|
||||
|
||||
getDeadline(subtask) {
|
||||
if (subtask?.deadline)
|
||||
return moment(subtask.deadline).format('DD.MM.yyyy')
|
||||
getDeadline(subtask) {
|
||||
if (subtask?.deadline)
|
||||
return moment(subtask.deadline).format('DD.MM.yyyy');
|
||||
|
||||
return moment(subtask.master_task_deadline).format('DD.MM.yyyy')
|
||||
},
|
||||
return moment(subtask.master_task_deadline).format('DD.MM.yyyy');
|
||||
},
|
||||
|
||||
getSelectedTimeblockDeadline(timeblocks) {
|
||||
const currentDate = moment()
|
||||
getSelectedTimeblockDeadline(timeblocks) {
|
||||
const currentDate = moment();
|
||||
|
||||
const unfinishedTimeblocks = timeblocks.filter(tb => tb.is_finished === 0)
|
||||
if (unfinishedTimeblocks.length > 0) return moment(unfinishedTimeblocks[0].end).format('DD.MM.yyyy, HH:mm')
|
||||
const unfinishedTimeblocks = timeblocks.filter(
|
||||
(tb) => tb.is_finished === 0,
|
||||
);
|
||||
if (unfinishedTimeblocks.length > 0)
|
||||
return moment(unfinishedTimeblocks[0].end).format('DD.MM.yyyy, HH:mm');
|
||||
|
||||
const upcomingTimeblocks = timeblocks
|
||||
.filter(tb => moment(tb.end).isAfter(currentDate))
|
||||
.sort((a, b) => moment(a.end).diff(moment(b.end)))
|
||||
const upcomingTimeblocks = timeblocks
|
||||
.filter((tb) => moment(tb.end).isAfter(currentDate))
|
||||
.sort((a, b) => moment(a.end).diff(moment(b.end)));
|
||||
|
||||
if (upcomingTimeblocks.length > 0 && upcomingTimeblocks.is_finished === 0) return moment(upcomingTimeblocks[0].end).format('DD.MM.yyyy, HH:mm')
|
||||
if (upcomingTimeblocks.length > 0 && upcomingTimeblocks.is_finished === 0)
|
||||
return moment(upcomingTimeblocks[0].end).format('DD.MM.yyyy, HH:mm');
|
||||
|
||||
return ''
|
||||
},
|
||||
return '';
|
||||
},
|
||||
|
||||
displayTimeblock(subtask) {
|
||||
const timeblockDeadline = this.getSelectedTimeblockDeadline(subtask.timeblocks)
|
||||
displayTimeblock(subtask) {
|
||||
const timeblockDeadline = this.getSelectedTimeblockDeadline(
|
||||
subtask.timeblocks,
|
||||
);
|
||||
|
||||
return timeblockDeadline !== '' ? timeblockDeadline : 'Žiadny termín'
|
||||
},
|
||||
return timeblockDeadline !== '' ? timeblockDeadline : 'Žiadny termín';
|
||||
},
|
||||
|
||||
async _finishSubtask(subtask) {
|
||||
const tempSubtask = {...subtask, is_finished: 1, timesheets: subtask?.timesheets.map((timesheet) => {
|
||||
delete timesheet.employee_name
|
||||
return timesheet
|
||||
}) || []}
|
||||
async _finishSubtask(subtask) {
|
||||
const timesheets =
|
||||
subtask?.timesheets.map((timesheet) => {
|
||||
delete timesheet.employee_name;
|
||||
return timesheet;
|
||||
}) || [];
|
||||
|
||||
try {
|
||||
this.loadingSubtask[subtask.id] = true
|
||||
await this.$axios.put_auth(`v1/subtasks/${tempSubtask.id}`, tempSubtask)
|
||||
// Convert timeblocks from internal format to BE format
|
||||
const timeblocks = (subtask.timeblocks || [])
|
||||
.filter((timeblock) => {
|
||||
// Filter timeblocks that have either old format (date) or new format (start)
|
||||
return timeblock.date || timeblock.start;
|
||||
})
|
||||
.map((timeblock) => {
|
||||
// If already in BE format (has start field), return as is
|
||||
if (timeblock.start && !timeblock.date) {
|
||||
return {
|
||||
id: timeblock.id || null,
|
||||
start: timeblock.start,
|
||||
end: timeblock.end,
|
||||
is_finished: timeblock.is_finished || 0,
|
||||
};
|
||||
}
|
||||
|
||||
this.$store.dispatch('tm/removeOngoingSubtask', subtask.id)
|
||||
this.$events.emit('on-subtask-edited', subtask)
|
||||
} catch (error) {
|
||||
this.$toast.error(error.message || error)
|
||||
// Convert from internal format to BE format
|
||||
const dateStr = moment(timeblock.date).format('YYYY-MM-DD');
|
||||
return {
|
||||
id: timeblock.id || null,
|
||||
start: `${dateStr} ${timeblock.starts_at_time}:00`,
|
||||
end: `${dateStr} ${timeblock.ends_at_time}:00`,
|
||||
is_finished: timeblock.is_finished || 0,
|
||||
};
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV === 'development')
|
||||
console.log('[a-ongoing-table.vue] Error: ', error)
|
||||
} finally {
|
||||
this.loadingSubtask[subtask.id] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const tempSubtask = {
|
||||
...subtask,
|
||||
is_finished: 1,
|
||||
timesheets,
|
||||
timeblocks,
|
||||
};
|
||||
|
||||
try {
|
||||
this.loadingSubtask[subtask.id] = true;
|
||||
await this.$axios.put_auth(
|
||||
`v1/subtasks/${tempSubtask.id}`,
|
||||
tempSubtask,
|
||||
);
|
||||
|
||||
this.$store.dispatch('tm/removeOngoingSubtask', subtask.id);
|
||||
this.$events.emit('on-subtask-edited', subtask);
|
||||
} catch (error) {
|
||||
this.$toast.error(error.message || error);
|
||||
|
||||
if (process.env.NODE_ENV === 'development')
|
||||
console.log('[a-ongoing-table.vue] Error: ', error);
|
||||
} finally {
|
||||
this.loadingSubtask[subtask.id] = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
Reference in new issue
Block a user