mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-22 14:59:34 +00:00
refactor podla review
This commit is contained in:
1 parent
d46a9151fc
commit
c542ea7760
14 files changed
+89
-182
No files matched your search
@@ -0,0 +1,466 @@
|
||||
<template>
|
||||
<div class="calendar-wrapper">
|
||||
<Vue-cal
|
||||
:hide-view-selector="true"
|
||||
:hide-title-bar="true"
|
||||
:disable-views="['years', 'year', 'month', 'week']"
|
||||
active-view="day"
|
||||
:selected-date="calConfig.date"
|
||||
:onEventClick="taskClicked"
|
||||
:editable-events="vueCalConfig.editing"
|
||||
:events="calData.tasks"
|
||||
:unscheduledTime="calData.unscheduled_times"
|
||||
:overlaps-per-time-step="false"
|
||||
:showTimeInCells="false"
|
||||
:time-cell-height="timeCellHeight"
|
||||
:snap-to-time="15"
|
||||
:scroll-to-hour="calConfig.scrollHour"
|
||||
:split-days="splits"
|
||||
:sticky-split-labels="true"
|
||||
:min-split-width="300"
|
||||
@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">
|
||||
<span v-if="split.date" class="d-flex align-center">
|
||||
<img v-if="getHeadingDate(split.date) == 'Dnes'" :src="require('./_img/home-icon.svg')" class="mr-2">
|
||||
<p class="weekday-label">{{ getHeadingDate(split.date) }}</p>
|
||||
</span>
|
||||
<span v-else class="d-flex align-center">
|
||||
<p class="weekday-label">{{ split.firstName }}</p>
|
||||
</span>
|
||||
|
||||
<div v-if="split.unscheduledTime && split.initials" class="unscheduled-time d-flex align-center text-left">
|
||||
<div class="unscheduled-time-initials d-flex align-center justify-center me-4">
|
||||
<p>{{split.initials}}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-0 mt-0 unscheduled-time-name">{{split.name}}</p>
|
||||
<h1 class="mb-0 mt-0">{{split.unscheduledTime}} h</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:time-cell="{ hours, minutes }">
|
||||
<span class="d-flex align-center justify-center">
|
||||
<p>{{hours}}:{{String(minutes).padStart(2, '0')}}</p>
|
||||
<div class="time-column-line"></div>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<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" 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">
|
||||
<small v-if="(event.project_code && !event.is_blocker)" class="project-code">{{ event.project_code }}</small>
|
||||
<h3>{{ event.title }}</h3>
|
||||
<div class="d-flex align-center event-details event-initials-wrapper">
|
||||
<div class="event-initials d-flex justify-center align-center">
|
||||
<small>{{ getUserInitials(event) }}</small>
|
||||
</div>
|
||||
<small class="event-initials-date">{{ new Date(event.starts_at).toLocaleDateString('sk-SK') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="event-footer d-flex">
|
||||
<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="this.showDeleteModal = {task: event}"><img :src="require('./_img/bin.svg')" alt=""></v-btn>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="non-working-event w-100 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>
|
||||
</template>
|
||||
</Vue-cal>
|
||||
|
||||
<Z-sub-task-modal ref="z-sub-task-modal" />
|
||||
|
||||
<!-- Kravarik: Prerobit modaly na novy sposob -->
|
||||
<Z-complete-task-modal v-if="showCompleteModal" :visible="showCompleteModal ? true : false" :task="showCompleteModal.task" @completeTask="completeTask" @close="showCompleteModal = null" />
|
||||
<Z-delete-task-modal v-if="showDeleteModal" :visible="showDeleteModal ? true : false" :task="showDeleteModal.task" @deleteTask="deleteTask" @close="showDeleteModal = null" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ZCompleteTaskModal from '@/plugins/tm@modal/task/z-complete-task-modal.vue'
|
||||
import ZDeleteTaskModal from '@/plugins/tm@modal/task/z-delete-task-modal.vue'
|
||||
import ZSubTaskModal from '@/plugins/tm@modal/sub-task/z-sub-task-modal.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ZCompleteTaskModal,
|
||||
ZDeleteTaskModal,
|
||||
ZSubTaskModal
|
||||
},
|
||||
|
||||
props: {
|
||||
calData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
calConfig: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default() {
|
||||
return {date: new Date(), scrollHour: 7}
|
||||
}
|
||||
},
|
||||
splits: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
vueCalConfig: {
|
||||
editing: {
|
||||
title: false,
|
||||
drag: true,
|
||||
resize: false,
|
||||
delete: false,
|
||||
create: false
|
||||
}
|
||||
},
|
||||
focusedEventId: null,
|
||||
showCompleteModal: null,
|
||||
showDeleteModal: null,
|
||||
timeCellHeight: 100,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
weekChanged() {
|
||||
const scrollContainer = this.$el.getElementsByClassName('vuecal__scrollable-body')[0]
|
||||
scrollContainer.scrollLeft = 0
|
||||
},
|
||||
|
||||
async eventMoved(e) {
|
||||
this.focusedEventId = e.event.id
|
||||
this.$emit('eventMoved', e)
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.correctMargins()
|
||||
},
|
||||
|
||||
correctMargins() {
|
||||
if (!this.$el.getElementsByClassName('vuecal__split-days-headers').length)
|
||||
return
|
||||
|
||||
const heightOfDayHeader = this.$el.getElementsByClassName('vuecal__split-days-headers')[0].clientHeight
|
||||
this.$el.getElementsByClassName('vuecal__time-column')[0].style.marginTop = `${heightOfDayHeader}px`
|
||||
this.$el.getElementsByClassName('vuecal__cells-body')[0].style.marginTop = `${heightOfDayHeader}px`
|
||||
},
|
||||
|
||||
getHeadingDate(value) {
|
||||
const date = new Date(value)
|
||||
|
||||
const today = new Date()
|
||||
const yesterday = new Date((new Date()).setDate(today.getDate() - 1))
|
||||
const tomorrow = new Date((new Date()).setDate(today.getDate() + 1))
|
||||
|
||||
if (today.toLocaleDateString('sk-SK') === date.toLocaleDateString('sk-SK')) return "Dnes"
|
||||
if (yesterday.toLocaleDateString('sk-SK') === date.toLocaleDateString('sk-SK')) return "Včera"
|
||||
if (tomorrow.toLocaleDateString('sk-SK') === date.toLocaleDateString('sk-SK')) return "Zajtra"
|
||||
|
||||
return date.toLocaleDateString('sk-SK')
|
||||
},
|
||||
|
||||
getUserInitials(event) {
|
||||
return event.name.charAt(0).toUpperCase() + event.surname.charAt(0).toUpperCase()
|
||||
},
|
||||
|
||||
getEventLenght(event) {
|
||||
return event.end.getTime() - event.start.getTime()
|
||||
},
|
||||
|
||||
taskClicked(task) {
|
||||
if (task.nonWorking) return
|
||||
console.log("task", task)
|
||||
if (task.end.getTime() - task.start.getTime() <= 3600000) {
|
||||
console.log("ShortTask")
|
||||
}
|
||||
},
|
||||
|
||||
eventFocused(event) {
|
||||
this.focusedEventId = event.task_id
|
||||
// console.log(`Focused: ${event.task_id}`)
|
||||
},
|
||||
|
||||
clickCompleteTask(event) {
|
||||
if (event.completed) this.completeTask(event.id)
|
||||
else this.showCompleteModal = {task: event}
|
||||
},
|
||||
|
||||
completeTask(id) {
|
||||
this.$emit('completeTask', id)
|
||||
},
|
||||
|
||||
editTask(subTask, editMode) {
|
||||
this.$refs['z-sub-task-modal'].create(subTask, editMode)
|
||||
},
|
||||
|
||||
deleteTask(id) {
|
||||
this.$emit('deleteTask', id)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.vuecal
|
||||
box-shadow: none !important
|
||||
|
||||
.calendar-wrapper
|
||||
width: 100%
|
||||
height: 100%
|
||||
// padding: 0 20px 0 0
|
||||
|
||||
&:deep()
|
||||
.vuecal__cells
|
||||
-ms-overflow-style: none
|
||||
scrollbar-width: none
|
||||
&::-webkit-scrollbar
|
||||
display: none
|
||||
|
||||
border-left: 1px solid rgba(0, 0, 0, .1)
|
||||
padding-left: 20px
|
||||
|
||||
.vuecal__flex
|
||||
flex-wrap: nowrap !important
|
||||
|
||||
|
||||
// TIME COLUMN
|
||||
.vuecal__time-column
|
||||
width: 150px
|
||||
box-shadow: none !important
|
||||
|
||||
.time-column-line
|
||||
width: 40px
|
||||
height: 0
|
||||
border: 1px solid rgba(33, 33, 33, 0.08)
|
||||
margin-left: 10px
|
||||
|
||||
@media (max-width: 450px)
|
||||
.vuecal__time-column
|
||||
width: 70px
|
||||
|
||||
.time-column-line
|
||||
width: 10px
|
||||
|
||||
|
||||
// HEADING
|
||||
// .vuecal__weekdays-headings,
|
||||
.vuecal__cell:before
|
||||
border: none
|
||||
|
||||
.vuecal__scrollable-body
|
||||
position: relative
|
||||
|
||||
// .vuecal__weekdays-headings
|
||||
.vuecal__split-days-headers
|
||||
position: absolute
|
||||
top: 0
|
||||
left: 20px
|
||||
z-index: 999
|
||||
background: white
|
||||
padding-bottom: 15px
|
||||
width: calc( 100% - 20px )
|
||||
|
||||
.vuecal__cell-split
|
||||
margin-right: 20px
|
||||
|
||||
.day-split-header
|
||||
height: fit-content
|
||||
min-height: 100%
|
||||
padding-right: 20px
|
||||
|
||||
.weekday-label
|
||||
justify-content: start !important
|
||||
font-size: 24px
|
||||
font-weight: 700
|
||||
|
||||
.unscheduled-time
|
||||
background: rgba(0, 0, 0, 0.04)
|
||||
border-radius: 24px
|
||||
padding: 10px 15px
|
||||
margin-top: 10px
|
||||
|
||||
.unscheduled-time-name
|
||||
font-weight: 400
|
||||
font-size: 15px
|
||||
|
||||
.unscheduled-time-initials
|
||||
width: 50px
|
||||
height: 50px
|
||||
background: #6200EE
|
||||
border-radius: 50%
|
||||
|
||||
p
|
||||
font-weight: 400
|
||||
font-size: 20px
|
||||
color: white
|
||||
|
||||
|
||||
// BODY
|
||||
.vuecal__body
|
||||
-ms-overflow-style: none
|
||||
scrollbar-width: none
|
||||
&::-webkit-scrollbar
|
||||
display: none
|
||||
|
||||
.vuecal__now-line
|
||||
display: none !important
|
||||
|
||||
// .vuecal__cell
|
||||
// padding: 10px 20px 10px 0px
|
||||
|
||||
.vuecal:not(.vuecal--day-view) .vuecal__cell--selected:not(.vuecal__cell--today) ,
|
||||
.vuecal__cell--current:not(.vuecal__cell--today),
|
||||
.vuecal__cell--today,
|
||||
.vuecal__cell--highlighted,
|
||||
.vuecal__cell--selected
|
||||
background-color: white
|
||||
|
||||
// EVENT
|
||||
|
||||
.vuecal__event
|
||||
border-radius: 16px
|
||||
padding: 20px 10px
|
||||
text-align: left
|
||||
background: rgba(248, 248, 248, 1)
|
||||
min-height: 40px
|
||||
transition: min-height .4s, height .4s, box-shadow .4s, width .4s, left .4s
|
||||
|
||||
&:has(.completed)
|
||||
background: rgb(251, 251, 251) !important
|
||||
border: 1px solid #cccccc !important
|
||||
|
||||
&: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)
|
||||
border: 1px solid rgba(215, 215, 215, 1)
|
||||
|
||||
&.vuecal__event--focus
|
||||
z-index: 100 !important
|
||||
min-height: 250px !important
|
||||
width: 100% !important
|
||||
left: 0 !important
|
||||
|
||||
&:not(.vuecal__event--focus)
|
||||
&:has(.short-event)
|
||||
padding: 10px !important
|
||||
|
||||
&:has(.micro-event)
|
||||
padding: 5px 10px !important
|
||||
|
||||
.short-event
|
||||
.project-code
|
||||
display: none !important
|
||||
|
||||
h3
|
||||
font-size: 16px !important
|
||||
|
||||
.mini-event
|
||||
.event-content
|
||||
display: flex
|
||||
align-items: center
|
||||
flex-wrap: nowrap
|
||||
justify-content: space-between
|
||||
width: 100%
|
||||
|
||||
.event-initials-wrapper
|
||||
margin-bottom: 0
|
||||
.event-initials
|
||||
margin-right: 0
|
||||
|
||||
h3
|
||||
font-size: 14px !important
|
||||
text-overflow: ellipsis
|
||||
width: calc( 100% - 35px )
|
||||
white-space: nowrap
|
||||
overflow: hidden
|
||||
margin: 0
|
||||
|
||||
.event-initials-date
|
||||
display: none !important
|
||||
|
||||
.micro-event
|
||||
|
||||
.event-footer
|
||||
display: none !important
|
||||
|
||||
&.event-blocker
|
||||
background: #B00020 !important
|
||||
|
||||
h3,
|
||||
.event-details *
|
||||
color: white !important
|
||||
|
||||
.event-details .event-initials
|
||||
border: 1px solid white
|
||||
|
||||
.event-footer
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.19)
|
||||
|
||||
.project-code
|
||||
margin: 0 0 20px
|
||||
display: block
|
||||
|
||||
h3
|
||||
font-size: 18px
|
||||
font-weight: 400
|
||||
color: Black
|
||||
margin: 0 0 10px
|
||||
max-height: 100%
|
||||
|
||||
small
|
||||
color: black
|
||||
|
||||
.event-initials-wrapper
|
||||
margin-bottom: 20px
|
||||
|
||||
.event-initials
|
||||
height: 30px
|
||||
width: 30px
|
||||
border: 1px solid black
|
||||
border-radius: 50%
|
||||
padding: 5px
|
||||
margin-right: 7px
|
||||
|
||||
small
|
||||
font-size: 11px
|
||||
|
||||
.event-footer
|
||||
padding-top: 15px
|
||||
border-top: 1px solid rgba(33, 33, 33, 0.08)
|
||||
|
||||
.event-footer-button
|
||||
box-shadow: none !important
|
||||
padding: 9px !important
|
||||
min-height: fit-content
|
||||
height: fit-content
|
||||
min-width: fit-content
|
||||
width: fit-content
|
||||
|
||||
&.completed
|
||||
background: #06dece
|
||||
|
||||
img
|
||||
width: 18px
|
||||
</style>
|
||||
Reference in new issue
Block a user