[task overview, teams overview] nenaplanovany cas

This commit is contained in:
Filip Kaluža committed 2023-01-11 17:02:13 +01:00
1 parent 8d49ad7122
commit 536fa40609
7 files changed
+285 -13946

No files matched your search

+189 -13925
View File
File diff suppressed because it is too large. Load diff
+4 -4
View File
@@ -24,7 +24,7 @@
"task_id": 2, "task_id": 2,
"starts_at": "2023-01-11T08:30:00+00:00", "starts_at": "2023-01-11T08:30:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00", "ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min Lorem ipsum dolor sit amet, consectetur adipiscing e", "title": "Kratky 30min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
"completed": false "completed": false
@@ -66,7 +66,7 @@
"task_id": 2, "task_id": 2,
"starts_at": "2023-01-11T08:30:00+00:00", "starts_at": "2023-01-11T08:30:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00", "ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min Lorem ipsum dolor sit amet, consectetur adipiscing e", "title": "Kratky 30min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
"completed": false "completed": false
@@ -108,7 +108,7 @@
"task_id": 2, "task_id": 2,
"starts_at": "2023-01-11T08:30:00+00:00", "starts_at": "2023-01-11T08:30:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00", "ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min Lorem ipsum dolor sit amet, consectetur adipiscing e", "title": "Kratky 30min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
"completed": false "completed": false
@@ -150,7 +150,7 @@
"task_id": 2, "task_id": 2,
"starts_at": "2023-01-11T08:30:00+00:00", "starts_at": "2023-01-11T08:30:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00", "ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min Lorem ipsum dolor sit amet, consectetur adipiscing e", "title": "Kratky 30min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
"completed": false "completed": false
@@ -19,23 +19,31 @@
<v-btn class="subheader-icon-button next" variant="outlined" @click="nextWeek()"><img :src="require('./_img/icon-next.svg')" alt=""></v-btn> <v-btn class="subheader-icon-button next" variant="outlined" @click="nextWeek()"><img :src="require('./_img/icon-next.svg')" alt=""></v-btn>
</div> </div>
<v-text-field <v-text-field
class="subheader-input" class="subheader-input disabled"
label="Nenaplánované hodiny" label="Nenaplánované hodiny"
v-model="plannedTime" v-model="time"
variant="outlined" variant="outlined"
></v-text-field> ></v-text-field>
</v-row> </v-row>
</template> </template>
<script> <script>
import { startOfWeek, endOfWeek, addDays, subDays } from 'date-fns' import { addDays, subDays } from 'date-fns'
export default { export default {
props: {
unscheduledTime: {
type: Number,
default() {
return 0
}
}
},
data() { data() {
return { return {
employees: ['Foo', 'Bar', 'Fizz', 'Buzz'], employees: ['Foo', 'Bar', 'Fizz', 'Buzz'],
selectedDate: "13.11.2022 - 17.11.2022", selectedDate: "13.11.2022 - 17.11.2022",
plannedTime: "35 h",
selectedEmployee: 'Bar', selectedEmployee: 'Bar',
date: new Date() date: new Date()
} }
@@ -45,6 +53,12 @@ export default {
this.getWeek() this.getWeek()
}, },
computed: {
time() {
return this.unscheduledTime
}
},
methods: { methods: {
getWeek() { getWeek() {
this.firstDay = subDays(this.date, 1) this.firstDay = subDays(this.date, 1)
@@ -53,7 +53,8 @@
</template> </template>
<template v-slot:event="{ event }"> <template v-slot:event="{ event }">
<div v-if="!event.nonWorking" @click.stop="editTask(event.id)" class="w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLenght(event) <= 9000000, 'mini-event' : getEventLenght(event) <= 5400000, 'micro-event' : getEventLenght(event) <= 3600000}"> <!-- <div v-if="!event.nonWorking" @click.stop="editTask(event.id)" class="w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLenght(event) <= 9000000, 'mini-event' : getEventLenght(event) <= 5400000, 'micro-event' : getEventLenght(event) <= 3600000}"> -->
<div v-if="!event.nonWorking" class="w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLenght(event) <= 9000000, 'mini-event' : getEventLenght(event) <= 5400000, 'micro-event' : getEventLenght(event) <= 3600000}">
<div class="event-content"> <div class="event-content">
<small v-if="(event.project_code && !event.is_blocker)" class="project-code">{{ event.project_code }}</small> <small v-if="(event.project_code && !event.is_blocker)" class="project-code">{{ event.project_code }}</small>
<h3>{{ event.title }}</h3> <h3>{{ event.title }}</h3>
@@ -66,7 +67,7 @@
</div> </div>
<div class="event-footer d-flex"> <div class="event-footer d-flex">
<v-btn rounded class="event-footer-button me-2" :class="{'completed': event.completed}" @click="this.showCompleteModal = {task: event}"><img :src="require('./_img/checkmark.svg')" alt=""></v-btn> <v-btn rounded class="event-footer-button me-2" :class="{'completed': event.completed}" @click="clickCompleteTask(event)"><img :src="require('./_img/checkmark.svg')" alt=""></v-btn>
<v-btn rounded class="event-footer-button me-2" @click.stop="editTask(event.id, true)"><img :src="require('./_img/pencil.svg')" alt=""></v-btn> <v-btn rounded class="event-footer-button me-2" @click.stop="editTask(event.id, true)"><img :src="require('./_img/pencil.svg')" alt=""></v-btn>
<v-btn rounded class="event-footer-button me-2" @click.stop="this.showDeleteModal = {task: event}"><img :src="require('./_img/bin.svg')" alt=""></v-btn> <v-btn rounded class="event-footer-button me-2" @click.stop="this.showDeleteModal = {task: event}"><img :src="require('./_img/bin.svg')" alt=""></v-btn>
</div> </div>
@@ -202,6 +203,11 @@ export default {
// console.log(`Focused: ${event.task_id}`) // console.log(`Focused: ${event.task_id}`)
}, },
clickCompleteTask(event) {
if (event.completed) this.$emit('reopenTask', event.id)
else this.showCompleteModal = {task: event}
},
completeTask(id) { completeTask(id) {
this.$emit('completeTask', id) this.$emit('completeTask', id)
}, },
@@ -342,8 +348,10 @@ export default {
min-height: 40px min-height: 40px
transition: min-height .4s, height .4s, box-shadow .4s, width .4s, left .4s transition: min-height .4s, height .4s, box-shadow .4s, width .4s, left .4s
// &:has(.completed) &:has(.completed)
// filter: grayscale(.9) !important // filter: grayscale(.9) !important
// background: rgb(245, 245, 245) !important
// border: 1px solid rgb(224, 224, 224) !important
&:has(.non-working-event) &:has(.non-working-event)
background: repeating-linear-gradient(135deg, rgba(215, 215, 215, 1), rgba(215, 215, 215, 1) 1px, rgba(224, 224, 224, 1) 1px, rgba(224, 224, 224, 1) 20px) background: repeating-linear-gradient(135deg, rgba(215, 215, 215, 1), rgba(215, 215, 215, 1) 1px, rgba(224, 224, 224, 1) 1px, rgba(224, 224, 224, 1) 20px)
@@ -452,7 +460,7 @@ export default {
width: fit-content width: fit-content
&.completed &.completed
background: #00B3A6 background: #06dece
img img
width: 18px width: 18px
+16 -2
View File
@@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<A-task-filter @weekChange="getWeekData" /> <A-task-filter :unscheduledTime="unscheduledTime" @weekChange="getWeekData" />
<W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!"> <W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!">
<Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" @completeTask="completeTask" @deleteTask="deleteTask" /> <Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" @completeTask="completeTask" @reopenTask="reopenTask" @deleteTask="deleteTask" />
</W-loadable> </W-loadable>
<v-snackbar <v-snackbar
@@ -36,6 +36,7 @@ export default {
errorToastMessage: "Nepodarilo sa nacitat data!", errorToastMessage: "Nepodarilo sa nacitat data!",
dataLoaded: false, dataLoaded: false,
splitDays: [], splitDays: [],
unscheduledTime: 0,
config: { config: {
date: new Date(), date: new Date(),
scrollHour: 7, scrollHour: 7,
@@ -87,11 +88,16 @@ export default {
event.split = diffInDays * (-1) + 1 event.split = diffInDays * (-1) + 1
}) })
this.unscheduledTime = 0
this.timelineData.unscheduled_times.forEach(time => { this.timelineData.unscheduled_times.forEach(time => {
time.name = this.timelineData.name time.name = this.timelineData.name
time.surname = this.timelineData.surname time.surname = this.timelineData.surname
this.unscheduledTime += time.time
}) })
this.unscheduledTime = Math.floor(this.unscheduledTime / 60) + "," + String(this.unscheduledTime % 60)[0] + " h"
this.config.scrollHour = Number(this.timelineData.work_hours_from.split(':')[0]) - 1 this.config.scrollHour = Number(this.timelineData.work_hours_from.split(':')[0]) - 1
}, },
@@ -153,6 +159,14 @@ export default {
} }
}) })
}, },
reopenTask(id) {
this.timelineData.tasks.filter(task => {
if (task.id == id) {
task.completed = false
}
})
},
deleteTask(id) { deleteTask(id) {
this.timelineData.tasks.splice(this.timelineData.tasks.findIndex(item => item.id === id), 1) this.timelineData.tasks.splice(this.timelineData.tasks.findIndex(item => item.id === id), 1)
@@ -19,9 +19,9 @@
<v-btn class="subheader-icon-button next" variant="outlined" @click="nextDay()"><img :src="require('../../tasks/_components/_img/icon-next.svg')" alt=""></v-btn> <v-btn class="subheader-icon-button next" variant="outlined" @click="nextDay()"><img :src="require('../../tasks/_components/_img/icon-next.svg')" alt=""></v-btn>
</div> </div>
<v-text-field <v-text-field
class="subheader-input" class="subheader-input disabled"
label="Nenaplánované hodiny" label="Nenaplánované hodiny"
v-model="plannedTime" v-model="time"
variant="outlined" variant="outlined"
></v-text-field> ></v-text-field>
</v-row> </v-row>
@@ -31,12 +31,20 @@
import { addDays, subDays } from 'date-fns' import { addDays, subDays } from 'date-fns'
export default { export default {
props: {
unscheduledTime: {
type: Number,
default() {
return 0
}
}
},
data() { data() {
return { return {
employees: ['Foo', 'Bar', 'Fizz', 'Buzz'], employees: ['Foo', 'Bar', 'Fizz', 'Buzz'],
selectedDate: new Date(), selectedDate: new Date(),
day: new Date(), day: new Date(),
plannedTime: "35 h",
selectedEmployee: 'Bar', selectedEmployee: 'Bar',
date: new Date() date: new Date()
} }
@@ -46,6 +54,12 @@ export default {
this.getDay() this.getDay()
}, },
computed: {
time() {
return this.unscheduledTime
}
},
methods: { methods: {
getDay() { getDay() {
const today = new Date() const today = new Date()
+28 -3
View File
@@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<A-team-filter @dayChanged="getDayData" /> <A-team-filter :unscheduledTime="unscheduledTime" @dayChanged="getDayData" />
<W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!"> <W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!">
<Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" /> <Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" @completeTask="completeTask" @reopenTask="reopenTask" @deleteTask="deleteTask" />
</W-loadable> </W-loadable>
<v-snackbar <v-snackbar
@@ -37,6 +37,7 @@ export default {
errorToastMessage: "Nepodarilo sa nacitat data!", errorToastMessage: "Nepodarilo sa nacitat data!",
dataLoaded: false, dataLoaded: false,
splitDays: [], splitDays: [],
unscheduledTime: 0,
config: { config: {
date: new Date(), date: new Date(),
scrollHour: 7, scrollHour: 7,
@@ -75,7 +76,8 @@ export default {
formatData() { formatData() {
this.timelineData.tasks = [] this.timelineData.tasks = []
this.unscheduledTime = 0
// format events // format events
this.timelineData.forEach(user => { this.timelineData.forEach(user => {
user.tasks.forEach(event => { user.tasks.forEach(event => {
@@ -87,7 +89,10 @@ export default {
event.split = user.splitId event.split = user.splitId
}) })
this.timelineData.tasks.push(...user.tasks) this.timelineData.tasks.push(...user.tasks)
this.unscheduledTime += user.unscheduled_time
}) })
this.unscheduledTime = Math.floor(this.unscheduledTime / 60) + "," + String(this.unscheduledTime % 60)[0] + " h"
}, },
generateNonWorkingHours(date) { generateNonWorkingHours(date) {
@@ -144,6 +149,26 @@ export default {
// } // }
// }) // })
// } // }
},
completeTask(id) {
this.timelineData.tasks.filter(task => {
if (task.id == id) {
task.completed = true
}
})
},
reopenTask(id) {
this.timelineData.tasks.filter(task => {
if (task.id == id) {
task.completed = false
}
})
},
deleteTask(id) {
this.timelineData.tasks.splice(this.timelineData.tasks.findIndex(item => item.id === id), 1)
} }
} }
} }