Merge branch 'main' of bitbucket.org:studiotem/jandl-taskmanager-app

This commit is contained in:
StudioTem committed 2023-06-29 13:13:36 +02:00
commit 55cbd27eaf
19 files changed
+162 -60

No files matched your search

@@ -160,4 +160,11 @@ export default {
.header-sm
justify-content: center !important
flex-wrap: wrap
@media (min-width: 561px) and (max-width: 825px)
.header
padding: 5px 15px
.menu-dropdown
border: none !important
</style>
@@ -4,7 +4,7 @@
<img
class="py-5 px-5 cursor-pointer"
:src="require('@/plugins/app/_img/jandl-logo.svg')"
alt="jandl-logo"
alt="Jandl-logo"
@click="refreshPage()"
/>
@@ -88,6 +88,7 @@ export default {
<style lang="sass" scoped>
ion-item
font-weight: 500 !important
font-size: 15px
--background: #fff
&:hover
@@ -108,7 +109,7 @@ ion-item
@media (min-width: 992px)
ion-menu
width: 257px
min-width: 257px
--width: 257px
width: 195px
min-width: 195px
--width: 195px
</style>
@@ -62,6 +62,6 @@ export default {
@media (min-width: 992px)
.split-pane-right-side
width: calc(100vw - 257px) !important
max-width: calc(100vw - 257px) !important
width: calc(100vw - 195px) !important
max-width: calc(100vw - 195px) !important
</style>
+5
View File
@@ -104,3 +104,8 @@ input[type="time"]::-webkit-calendar-picker-indicator
.v-row.subheader
.v-input
height: 40px !important
@media (max-width: 534px)
.mobile-view
flex-direction: column
gap: 20px
@@ -17,14 +17,14 @@
:scroll-to-hour="calConfig.scrollHour"
:split-days="splits"
:sticky-split-labels="true"
:min-split-width="220"
:min-split-width="140"
@ready="onReady()"
@view-change="weekChanged"
@event-drop="eventMoved"
@event-focus="eventFocused"
>
<template v-slot:split-label="{ split }">
<div class="w-100 h-100 d-flex flex-column">
<div class="colWidth h-100 d-flex flex-column">
<span v-if="split.date" class="d-flex align-center">
<img v-if="split.isHomeoffice" :src="require('@/plugins/app/_img/icons/home.svg')" class="mr-2">
<p class="weekday-label">{{ getHeadingDate(split.date) }}</p>
@@ -39,10 +39,10 @@
</span>
<div class="unscheduled-time d-flex align-center text-left" :class="{'vuecal__cell-split--weekend': split.isWeekend}">
<div class="unscheduled-time-initials d-flex align-center justify-center me-4">
<div class="unscheduled-time-initials d-flex align-center justify-center">
<p>{{ split.initials }}</p>
</div>
<div>
<div class="text-wrap me-4">
<p class="mb-0 mt-0 unscheduled-time-name">{{split.fullname}}</p>
<h1 class="mb-0 mt-0">{{split.unscheduledTime}} h</h1>
</div>
@@ -58,14 +58,14 @@
</template>
<template v-slot:event="{ event }">
<div v-if="event.type == 'non-working-hours'" class="custom-event-body non-working-event w-100 h-100 d-flex flex-column justify-center">
<div v-if="event.type == 'non-working-hours'" class="custom-event-body non-working-event colWidth h-100 d-flex flex-column justify-center">
<div class="d-flex justify-center align-center">
<v-icon icon="mdi-cancel" color="black"></v-icon>
<h3 class="mb-0 ms-2">{{ event.title }}</h3>
</div>
</div>
<div v-else-if="['subtask', 'blocker', 'adhoc', 'vacation', 'free_day'].includes(event.type)" class="custom-event-body w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLength(event) <= 9000000, 'mini-event' : getEventLength(event) <= 5400000, 'micro-event' : getEventLength(event) <= 3600000}" :style="{backgroundColor: event._timeblock_is_finished || event.subtask.is_finished ? '#dedfe0' : event.color || event.subtask.color}">
<div v-else-if="['subtask', 'blocker', 'adhoc', 'vacation', 'free_day'].includes(event.type)" class="custom-event-body colWidth h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLength(event) <= 9000000, 'mini-event' : getEventLength(event) <= 5400000, 'micro-event' : getEventLength(event) <= 3600000}" :style="{backgroundColor: event._timeblock_is_finished || event.subtask?.is_finished ? '#dedfe0' : event.color || event.subtask?.color}">
<div class="event-content" :class="{'is-blocker': event.isBlocker}">
<template v-if="event.type == 'subtask'">
<small v-if="event.subtask.project_code" class="project-code">{{ event.subtask.project_code }}</small>
@@ -166,7 +166,11 @@ export default {
is_finished: 0,
start: tmUtils.formatDateTimeForBackend(start),
end: tmUtils.formatDateTimeForBackend(end)
}]
}],
timesheets: event.subtask.timesheets.map((timesheet) => {
delete timesheet.employee_name
return timesheet
})
}
try {
@@ -240,7 +244,7 @@ export default {
const subtask = event.subtask
const timeblock = subtask.timeblocks.find(originalTimeblock => originalTimeblock.id == event._timeblock_id)
timeblock.is_finished = timeblock.is_finished ? 0 : 1
timeblock.is_finished = timeblock?.is_finished ? 0 : 1
try {
const {data: newTimeblock} = await this.$axios.put_auth(`v1/timeblocks/${timeblock.id}`, timeblock)
@@ -281,6 +285,12 @@ export default {
</script>
<style lang="sass" scoped>
.colWidth
width: 120px
@media (min-width: 1476px)
width: 100% !important
.vuecal
box-shadow: none !important
@@ -350,34 +360,42 @@ export default {
.weekday-label
justify-content: start !important
font-size: 24px
font-size: 18px
font-weight: 700
.day-name
text-align: left
font-size: 18px
font-size: 17px
font-weight: 500
text-transform: capitalize
.unscheduled-time
background: rgba(0, 0, 0, 0.04)
border-radius: 24px
padding: 10px 15px
padding: 10px 10px
margin-top: 10px
.unscheduled-time-name
.text-wrap
width: min-content
margin-left: 12px
h1
font-size: 14px
p
font-weight: 400
font-size: 15px
line-height: normal
.unscheduled-time-initials
width: 50px
height: 50px
width: 30px
height: 30px
background: #6200EE
border-radius: 50%
p
font-weight: 400
font-size: 20px
font-size: 15px
color: white
@@ -412,6 +430,7 @@ export default {
.vuecal__event
border-radius: 16px
// padding: 20px 10px
min-height: 200px !important
text-align: left
background: rgba(248, 248, 248, 1)
min-height: 40px
@@ -492,7 +511,7 @@ export default {
display: block
h3
font-size: 18px
font-size: 15px
font-weight: 400
color: Black
margin: 0 0 10px
@@ -516,11 +535,15 @@ export default {
font-size: 11px
.event-footer
flex-flow: row wrap
justify-content: center
alight-items: center
padding-top: 15px
border-top: 1px solid rgba(33, 33, 33, 0.08)
.event-footer-button
box-shadow: none !important
margin-bottom: 8px
padding: 9px !important
min-height: fit-content
height: fit-content
@@ -86,14 +86,13 @@ export default {
}
}
</script>
<style lang="sass" scoped>
// Kravarik: TODO zjednotit styly ikon v globalnom sass subore
// TODO: ↓
.subheader
max-width: 100%
margin: 0
border-bottom: 1px solid rgba(33, 33, 33, 0.08)
gap: 25px
gap: 20px
flex-wrap: wrap
position: sticky
top: 0
@@ -104,6 +103,12 @@ export default {
max-width: 250px !important
min-width: 250px
&:deep(.v-input__control)
.v-field
height: 50px !important
--v-input-control-height: 50px !important
--v-input-padding-top: 15px !important
&:deep(.v-input__details)
display: none
&:deep(.v-selection-control)
@@ -120,8 +125,6 @@ export default {
max-width: 100% !important
min-width: 100%
// TODO: ↑
.subheader-input.switch
max-width: 100px !important
min-width: 100px !important
@@ -108,8 +108,8 @@ export default {
.subheader-icon-button
border: 1px solid #ABABAB
height: 60px
width: 60px
height: 50px
width: 50px
min-width: auto !important
padding: 0
margin: 0
@@ -134,9 +134,9 @@ export default {
&:deep(.v-input__control)
.v-field
height: 60px !important
--v-input-control-height: 60px !important
--v-input-padding-top: 19px !important
height: 50px !important
--v-input-control-height: 50px !important
--v-input-padding-top: 15px !important
&:deep(.v-input__details)
display: none
@@ -156,6 +156,7 @@ export default {
.subheader-input
max-width: 100% !important
min-width: 100%
margin: 0 10px 10px 0
.date-wrapper
flex-wrap: wrap
@@ -168,4 +169,18 @@ export default {
flex: 1 1 calc( 50% - 5px )
height: 40px
@media (min-width: 601px) and (max-width: 825px)
.subheader
flex-wrap: nowrap
padding: 8px 20px 8px 20px !important
.subheader-input
max-width: calc(31.333% - 10px) !important
min-width: calc(31.333% - 10px) !important
&:nth-child(3)
max-width: calc(23.333% - 10px) !important
min-width: calc(23.333% - 10px) !important
</style>
@@ -121,8 +121,8 @@ export default {
.subheader-icon-button
border: 1px solid #ABABAB
height: 56px
width: 56px
height: 50px
width: 50px
min-width: auto !important
padding: 0
margin: 0
@@ -139,6 +139,13 @@ export default {
.subheader-input
max-width: 250px !important
min-width: 250px
height: 50px !important
&:deep(.v-input__control)
.v-field
height: 50px !important
--v-input-control-height: 50px !important
--v-input-padding-top: 15px !important
&:deep(.v-input__details)
display: none
@@ -159,6 +166,7 @@ export default {
.subheader-input
max-width: 100% !important
min-width: 100%
margin: 0 10px 10px 0
.date-wrapper
flex-wrap: wrap
@@ -170,5 +178,4 @@ export default {
margin: 0
flex: 1 1 calc( 50% - 5px )
height: 40px
</style>
@@ -11,7 +11,7 @@
class="mb-15"
></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-card-actions class="mt-10 d-flex justify-start align-center mobile-view">
<v-btn class="button primary half" variant="flat" @click="deleteBlocker()">ÁNO</v-btn>
<v-btn class="button primary half outline" @click.stop="closeModal()">ZRUŠIŤ</v-btn>
</v-card-actions>
@@ -11,7 +11,7 @@
class="mb-15"
></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-card-actions class="mt-10 d-flex justify-start align-center mobile-view">
<v-btn class="button primary half" variant="flat" @click="deleteMasterTask()">ÁNO</v-btn>
<v-btn class="button primary half outline" @click.stop="closeModal()">ZRUŠIŤ</v-btn>
</v-card-actions>
@@ -6,7 +6,7 @@
<v-icon @click.stop="closeModal()" icon="mdi-close" size="large"></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-card-actions class="mt-10 d-flex justify-start align-center mobile-view">
<v-btn class="button primary half outline" @click.stop="createTask()"
>TASK</v-btn
>
@@ -26,7 +26,7 @@
<div class="d-flex align-center flex-start width-100">
<p class="task-badge rounded-pill">{{ timesheet.time }}</p>
<p class="ml-5">{{ timesheet.employee_name }} ({{ moment(timesheet.timestamp).format('M.D.YYYY') }})</p>
<p class="ml-5">{{ timesheet.employee_name }} ({{ moment(timesheet.timestamp).format('D.M.YYYY') }})</p>
</div>
</div>
</template>
@@ -122,6 +122,10 @@ export default {
async _update(data) {
try {
data.timesheets = data.timesheets.map((timesheet) => {
delete timesheet.employee_name
return timesheet
})
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${data.id}`, data)
this.closeModal()
@@ -101,7 +101,6 @@ export default {
return
const subtask = JSON.parse(JSON.stringify(this.subtask))
const splittedStartsAtTime = this.form.starts_at_time.split(':')
const splittedEndsAtTime = this.form.ends_at_time.split(':')
const start = moment(this.form.date).hours(parseInt(splittedStartsAtTime[0])).minutes(parseInt(splittedStartsAtTime[1])).toISOString()
@@ -112,11 +111,14 @@ export default {
if (!subtask?.is_finished) { subtask.is_finished = 0 }
subtask.timeblocks.push({
end: tmUtils.formatDateTimeForBackend(end),
id: null,
start: tmUtils.formatDateTimeForBackend(start),
end: tmUtils.formatDateTimeForBackend(end)
is_finished: 0,
start: tmUtils.formatDateTimeForBackend(start)
})
if(subtask.deadline) subtask.deadline = tmUtils.formatDateTimeForBackend(subtask.deadline)
if (!subtask.id) {
this.$emit('update-unfinished-subtask', subtask)
this.closeModal()
@@ -156,6 +158,7 @@ export default {
async deleteTimeblock({ id }) {
const subtask = JSON.parse(JSON.stringify(this.subtask))
subtask.timeblocks = subtask.timeblocks.filter(timeblock => timeblock.id != id)
if(subtask.deadline) subtask.deadline = tmUtils.formatDateTimeForBackend(subtask.deadline)
this._update(subtask)
},
@@ -166,11 +169,17 @@ export default {
async _update(data) {
try {
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${data.id}`, data)
const timesheets = data.timesheets.map((timesheet) => {
delete timesheet.employee_name
return timesheet
})
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${data.id}`, {...data, timesheets})
this.closeModal()
this.$events.emit('on-subtask-edited', subtask)
} catch (error) {
console.error(error)
this.$toast.error(error.message || error)
}
},
@@ -9,7 +9,7 @@
size="large"
></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-card-actions class="mt-10 d-flex justify-start align-center mobile-view">
<v-btn class="button primary half" variant="flat" @click="complete()">ÁNO</v-btn>
<v-btn class="button primary half outline" @click.stop="visible = false">ZRUŠIŤ</v-btn>
</v-card-actions>
@@ -36,7 +36,10 @@ export default {
async complete() {
try {
const tempSubtask = {...this.subtask, is_finished: this.subtask.is_finished ? 0 : 1}
const tempSubtask = {...this.subtask, is_finished: this.subtask.is_finished ? 0 : 1, timesheets: this.subtask.timesheets.map((timesheet) => {
delete timesheet.employee_name
return timesheet
})}
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${tempSubtask.id}`, tempSubtask)
this.visible = false
@@ -11,7 +11,7 @@
class="mb-15"
></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-card-actions class="mt-10 d-flex justify-start align-center mobile-view">
<v-btn class="button primary half" variant="flat" @click="deleteTask()">ÁNO</v-btn>
<v-btn class="button primary half outline" @click.stop="closeModal()">ZRUŠIŤ</v-btn>
</v-card-actions>
@@ -60,8 +60,16 @@ export default {
time: typeof this.form.hours == 'string' ? parseFloat(this.form.hours) : this.form.hours
})
const payload = {
...this.subtask,
timesheets: this.subtask.timesheets.map((timesheet) => {
delete timesheet.employee_name
return timesheet
})
}
try {
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, this.subtask)
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, payload)
this.closeModal()
this.$events.emit('on-subtask-edited', subtask)
+22 -11
View File
@@ -195,15 +195,19 @@ export default {
try {
if (subtask?.id) {
const data = await this.$axios.get_auth_data(`v1/subtasks/${subtask.id}`)
if (!data.deadline)
return this.subtask = this._enrichTask(data)
const splittedDeadline = data.deadline.split(' ')
data.deadline = moment(splittedDeadline[0])
data._deadline_time = splittedDeadline[1]
this.subtask = this._enrichTask(data)
} else {
this.subtask = { master_task: mastertask, employees: [{}], _deadline_time: '17:00' }
// if (subtask.deadline && subtask._deadline_time) {
// this.subtask.deadline = subtask.deadline
// this.subtask._deadline_time = subtask._deadline_time
// }
}
this.editMode = editMode || !this.subtask.id
} catch (error) {
this.$toast.error(error)
@@ -229,10 +233,15 @@ export default {
this._mergeDeadlineTimeDate()
try {
this.subtask.deadline = moment(this.subtask.deadline).format('YYYY-MM-DD HH:MM:SS')
this.subtask.deadline = moment(this.subtask.deadline).format('YYYY-MM-DD HH:mm:SS')
if (this.subtask?.id) {
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, this.subtask)
const timesheets = this.subtask.timesheets.map((timesheet) => {
delete timesheet.employee_name
return timesheet
})
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${this.subtask.id}`, {...this.subtask, timesheets})
this.$store.commit('tm/update_subtask', subtask)
this.$events.emit("on-subtask-edited", this.subtask)
@@ -268,6 +277,7 @@ export default {
showCompleteTaskModal() {
this.$events.emit('show-complete-task-modal', { subtask: this.subtask })
if(this.subtask.deadline) this.subtask.deadline = tmUtils.formatDateTimeForBackend(this.subtask.deadline)
},
filesUploaded(files) {
@@ -280,10 +290,11 @@ export default {
},
_mergeDeadlineTimeDate() {
const date = new Date(this.subtask.deadline);
const timeParts = this.subtask._deadline_time.split(':');
date.setHours(parseInt(timeParts[0]));
date.setMinutes(parseInt(timeParts[1]));
const date = new Date(this.subtask.deadline)
const timeParts = this.subtask._deadline_time.split(':')
date.setHours(parseInt(timeParts[0]))
date.setMinutes(parseInt(timeParts[1]))
this.subtask.deadline = date
},
@@ -8,7 +8,7 @@
<v-icon @click.stop="closeModal()" icon="mdi-close" size="large"></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-card-actions class="mt-10 d-flex justify-start align-center mobile-view">
<v-btn class="button primary half" variant="flat" @click="deleteTeam()">ÁNO</v-btn>
<v-btn class="button primary half outline" @click.stop="closeModal()">ZRUŠIŤ</v-btn>
</v-card-actions>
@@ -72,6 +72,12 @@ export default {
min-width: 250px
height: 56px
&:deep(.v-input__control)
.v-field
height: 50px !important
--v-input-control-height: 50px !important
--v-input-padding-top: 15px !important
&:deep(.v-input__details)
display: none
@@ -82,8 +88,8 @@ export default {
.subheader
gap: 15px
padding: 20px !important
.subheader-input
max-width: 100% !important
min-width: 100%
margin-bottom: 15px
</style>