mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 14:29:34 +00:00
Feat(task): Added support for Office 365 events, that are not editable from the application
This commit is contained in:
1 parent
36f992c063
commit
687681865c
48 files changed
+408
-165
No files matched your search
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="event" :class="{ 'event--office': isOfficeEvent }">
|
||||
<div v-if="props.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">{{ props.event.title }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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="subtaskCssClass" :style="{ backgroundColor: event._timeblock_is_finished || event.subtask?.is_finished ? '#dedfe0' : event.color || event.subtask?.color }">
|
||||
<div class="event-content" :class="{ 'is-blocker': props.event.isBlocker }">
|
||||
<template v-if="props.event.type == 'subtask'">
|
||||
<small v-if="props.event.subtask.project_code" class="project-code">{{ props.event.subtask.project_code }}</small>
|
||||
<h3>{{ props.event.subtask.title ?? props.event.subtask.master_task?.name ?? props.event.subtask.master_task }}</h3>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<v-tooltip :text="event.blocker?.approved ? 'Schválený' : 'Neschválený'" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<div v-bind="props">
|
||||
<h3>{{ props.event.blocker?.approved ? props.event.blocker.name : props.event.blocker.name + '*' }}</h3>
|
||||
</div>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
|
||||
<div class="d-flex align-center event-details event-initials-wrapper">
|
||||
<div class="event-initials d-flex justify-center align-center">
|
||||
<small>{{ props.event.initials }}</small>
|
||||
</div>
|
||||
<small class="event-initials-date">{{ props.event.date?.toLocaleDateString('sk-SK') }}</small>
|
||||
</div>
|
||||
|
||||
<div v-if="event.type == 'subtask'" class="d-flex align-center">
|
||||
<v-icon icon="mdi-skull-outline" size="small" />
|
||||
<small v-if="props.event?.subtask.deadline" class="ml-1">{{ deadline }}</small>
|
||||
<v-tooltip v-else text="Deadline z Mastertasku" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<small class="cursor-pointer ml-1" v-if="!props.event?.subtask?.deadline" v-bind="props">{{ deadline }}*</small>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="event__office-footer" v-if="isOfficeEvent">
|
||||
<img :src="office365" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="event__footer d-flex">
|
||||
<template v-if="isOfficeEvent">
|
||||
<v-btn rounded class="event__footer__button me-2" @click.stop="editOfficeEvent"><img :src="eye" alt="" /></v-btn>
|
||||
</template>
|
||||
|
||||
<template v-else-if="event.type == 'adhoc'">
|
||||
<v-btn rounded class="event__footer__button me-2" @click.stop="emits('edit-blocker', props.event)"><img :src="pencil" alt="" /></v-btn>
|
||||
<v-btn rounded class="event__footer__button me-2" @click.stop="emits('delete-blocker', props.event)"><img :src="bin" alt="" /></v-btn>
|
||||
</template>
|
||||
|
||||
<template v-else-if="props.event.type == 'subtask'">
|
||||
<v-btn rounded class="event__footer__button me-2" :class="{ completed: props.event.subtask?.is_finished }" @click.stop="emits('complete-task', props.event)"><img :src="checkmarkDouble" alt="" /></v-btn>
|
||||
<v-btn rounded class="event__footer__button me-2" :class="{ completed: props.event._timeblock_is_finished }" @click.stop="emits('toggle-timeblock-is-finished', props.event)"><img :src="checkmark" alt="" /></v-btn>
|
||||
<v-btn rounded class="event__footer__button me-2" @click.stop="emits('edit-task', props.event)"><img :src="eye" alt="" /></v-btn>
|
||||
<v-btn rounded class="event__footer__button me-2" @click.stop="emits('delete-timeblock-in-task', props.event)"><img :src="bin" alt="" /></v-btn>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { bin, checkmarkDouble, checkmark, eye, pencil, office365 } from '@/plugins/app/_img'
|
||||
import { computed, ComputedRef, defineProps, defineEmits, getCurrentInstance } from 'vue'
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
|
||||
const props = defineProps<{
|
||||
event: any // TODO office365: Define type
|
||||
}>()
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'edit-blocker', event: any): void,
|
||||
(e: 'delete-blocker', event: any): void,
|
||||
(e: 'complete-task', event: any): void,
|
||||
(e: 'toggle-timeblock-is-finished', event: any): void,
|
||||
(e: 'edit-task', event: any): void,
|
||||
(e: 'delete-timeblock-in-task', event: any): void
|
||||
}>()
|
||||
|
||||
const deadline: ComputedRef<string | undefined> = computed(() => {
|
||||
if (!props.event.subtask)
|
||||
return undefined
|
||||
|
||||
if (props.event.subtask.deadline)
|
||||
return props.event.subtask.deadline
|
||||
|
||||
return props.event.subtask.master_task_deadline
|
||||
})
|
||||
|
||||
const eventLength: ComputedRef<number> = computed(() => props.event.end.getTime() - props.event.start.getTime())
|
||||
|
||||
const subtaskCssClass: ComputedRef<string> = computed(() => {
|
||||
const classes = []
|
||||
if (eventLength.value <= 9000000) classes.push('short-event')
|
||||
if (eventLength.value <= 5400000) classes.push('mini-event')
|
||||
if (eventLength.value <= 3600000) classes.push('micro-event')
|
||||
if (!props.event.blocker?.approved && props.event.isBlocker) classes.push('not-approved')
|
||||
return classes.join(' ')
|
||||
})
|
||||
|
||||
const isOfficeEvent: ComputedRef<boolean> = computed(() => {
|
||||
return true
|
||||
})
|
||||
|
||||
const editOfficeEvent = () => {
|
||||
const eventBus = instance?.appContext.config.globalProperties.$events
|
||||
eventBus.emit('show-unable-to-edit-office-task-modal', props.event)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.event
|
||||
height: 100%
|
||||
|
||||
&__office-footer
|
||||
padding: 5px 15px
|
||||
|
||||
img
|
||||
height: 19px
|
||||
user-select: none
|
||||
|
||||
.custom-event-body
|
||||
padding: 20px 10px
|
||||
width: 100%
|
||||
|
||||
&__footer
|
||||
flex-flow: row wrap
|
||||
justify-content: center
|
||||
alight-items: center
|
||||
padding-top: 15px
|
||||
border-top: 1px solid rgba(33, 33, 33, 0.08)
|
||||
|
||||
&__button
|
||||
box-shadow: none !important
|
||||
margin-bottom: 8px
|
||||
padding: 9px !important
|
||||
min-height: fit-content
|
||||
height: fit-content
|
||||
min-width: fit-content
|
||||
width: fit-content
|
||||
|
||||
&.completed
|
||||
background: #06dece
|
||||
|
||||
img
|
||||
width: 18px
|
||||
</style>
|
||||
@@ -24,7 +24,7 @@
|
||||
@event-focus="eventFocused"
|
||||
>
|
||||
<template v-slot:split-label="{ split }">
|
||||
<div class="colWidth h-100 d-flex flex-column">
|
||||
<div class="w-[120px] 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>
|
||||
@@ -65,62 +65,14 @@
|
||||
</template>
|
||||
|
||||
<template v-slot:event="{ event }">
|
||||
<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 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, 'not-approved': !event.blocker?.approved && event.isBlocker }" :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>
|
||||
<h3>{{ event.subtask.title ?? event.subtask.master_task?.name ?? event.subtask.master_task }}</h3>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<v-tooltip :text="event.blocker?.approved ? 'Schválený' : 'Neschválený'" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<div v-bind="props">
|
||||
<h3>{{ event.blocker?.approved ? event.blocker.name : (event.blocker.name + '*') }}</h3>
|
||||
</div>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
|
||||
<div class="d-flex align-center event-details event-initials-wrapper">
|
||||
<div class="event-initials d-flex justify-center align-center">
|
||||
<small>{{ event.initials }}</small>
|
||||
</div>
|
||||
<small class="event-initials-date">{{ event.date?.toLocaleDateString('sk-SK') }}</small>
|
||||
</div>
|
||||
|
||||
<div v-if="event.type == 'subtask'" class="d-flex align-center">
|
||||
<v-icon icon="mdi-skull-outline" size="small" />
|
||||
<small v-if="event?.subtask.deadline" class="ml-1">{{ getDeadline(event?.subtask) }}</small>
|
||||
<v-tooltip v-else text="Deadline z Mastertasku" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<small class="cursor-pointer ml-1" v-if="!event?.subtask?.deadline" v-bind="props">{{ getDeadline(event?.subtask) }}*</small>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="event-footer d-flex">
|
||||
<template v-if="event.type == 'adhoc'">
|
||||
<v-btn rounded class="event-footer-button me-2" @click.stop="editBlocker(event)"><img :src="require('@/plugins/app/_img/icons/pencil.svg')" alt=""></v-btn>
|
||||
<v-btn rounded class="event-footer-button me-2" @click.stop="deleteBlocker(event)"><img :src="require('@/plugins/app/_img/icons/bin.svg')" alt=""></v-btn>
|
||||
</template>
|
||||
|
||||
<template v-else-if="event.type == 'subtask'">
|
||||
<v-btn rounded class="event-footer-button me-2" :class="{'completed': event.subtask?.is_finished}" @click.stop="completeTask(event)"><img :src="require('@/plugins/app/_img/icons/checkmark-double.svg')" alt=""></v-btn>
|
||||
<v-btn rounded class="event-footer-button me-2" :class="{'completed': event._timeblock_is_finished}" @click.stop="toggleTimeblockIsFinished(event)"><img :src="require('@/plugins/app/_img/icons/checkmark.svg')" alt=""></v-btn>
|
||||
<v-btn rounded class="event-footer-button me-2" @click.stop="editTask(event)"><img :src="require('@/plugins/app/_img/icons/eye.svg')" alt=""></v-btn>
|
||||
<v-btn rounded class="event-footer-button me-2" @click.stop="deleteTimeBlockInTask(event)"><img :src="require('@/plugins/app/_img/icons/bin.svg')" alt=""></v-btn>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<A-timeline-event :event="event"
|
||||
@edit-blocker="editBlocker"
|
||||
@delete-blocker="deleteBlocker"
|
||||
@complete-task="completeTask"
|
||||
@toggle-timeblock-is-finished="toggleTimeblockIsFinished"
|
||||
@edit-task="editTask"
|
||||
@delete-timeblock-in-task="deleteTimeBlockInTask"
|
||||
/>
|
||||
</template>
|
||||
</Vue-cal>
|
||||
</div>
|
||||
@@ -131,8 +83,12 @@ import { addDays } from 'date-fns'
|
||||
import tmUtils from '@/plugins/tm@_utils/tm.utils'
|
||||
import { mapGetters } from 'vuex'
|
||||
import moment from 'moment'
|
||||
import ATimelineEvent from './a-timeline-event.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ATimelineEvent,
|
||||
},
|
||||
props: {
|
||||
calData: {
|
||||
type: Object,
|
||||
@@ -300,10 +256,6 @@ export default {
|
||||
return date.toLocaleDateString('sk-SK')
|
||||
},
|
||||
|
||||
getEventLength(event) {
|
||||
return event.end.getTime() - event.start.getTime()
|
||||
},
|
||||
|
||||
taskClicked(subtask) {
|
||||
// console.log('task clicked')
|
||||
},
|
||||
@@ -377,12 +329,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.colWidth
|
||||
width: 120px
|
||||
|
||||
// @media (min-width: 1476px)
|
||||
// width: 100% !important
|
||||
|
||||
.vuecal
|
||||
box-shadow: none !important
|
||||
|
||||
@@ -526,26 +472,11 @@ export default {
|
||||
background: rgba(248, 248, 248, 1)
|
||||
transition: min-height .4s, height .4s, box-shadow .4s, width .4s, left .4s
|
||||
|
||||
.custom-event-body
|
||||
padding: 20px 10px
|
||||
width: 100%
|
||||
|
||||
.event-content
|
||||
&.is-blocker
|
||||
*
|
||||
color: #ffffff !important
|
||||
|
||||
.event-details .event-initials
|
||||
border: 1px solid white
|
||||
|
||||
.event-footer
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.19)
|
||||
|
||||
&:has(.completed)
|
||||
background: rgb(251, 251, 251) !important
|
||||
border: 1px solid #cccccc !important
|
||||
|
||||
&:has(.non-working-event)
|
||||
&:has(.event__body--non-working-hours)
|
||||
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)
|
||||
|
||||
@@ -556,10 +487,10 @@ export default {
|
||||
left: 0 !important
|
||||
|
||||
&:not(.vuecal__event--focus)
|
||||
&:has(.micro-event) .custom-event-body
|
||||
&:has(.micro-event) .event__body
|
||||
padding: 5px !important
|
||||
|
||||
&:has(.short-event) .custom-event-body:not(.micro-event)
|
||||
&:has(.short-event) .event__body:not(.micro-event)
|
||||
padding: 10px 5px !important
|
||||
.short-event
|
||||
.project-code
|
||||
@@ -570,15 +501,10 @@ export default {
|
||||
|
||||
.mini-event
|
||||
.event-content
|
||||
// display: flex
|
||||
// align-items: center
|
||||
// flex-wrap: nowrap
|
||||
// justify-content: space-between
|
||||
width: 100%
|
||||
padding: 5px 10px
|
||||
|
||||
.event-initials-wrapper
|
||||
// margin-bottom: 0
|
||||
.event-initials
|
||||
margin-right: 0
|
||||
|
||||
@@ -595,7 +521,7 @@ export default {
|
||||
|
||||
.micro-event
|
||||
|
||||
.event-footer
|
||||
.event__footer
|
||||
display: none !important
|
||||
|
||||
.project-code
|
||||
@@ -626,28 +552,6 @@ export default {
|
||||
small
|
||||
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
|
||||
min-width: fit-content
|
||||
width: fit-content
|
||||
|
||||
&.completed
|
||||
background: #06dece
|
||||
|
||||
img
|
||||
width: 18px
|
||||
|
||||
.not-approved
|
||||
background: repeating-linear-gradient(135deg, rgb(215, 215, 215), rgb(215, 215, 215) 1px, rgb(224, 224, 224) 1px, rgb(224, 224, 224) 20px) !important
|
||||
</style>
|
||||
@@ -64,7 +64,8 @@ export default {
|
||||
_timeblock_id: timeblock.id,
|
||||
_timeblock_is_finished: timeblock.is_finished,
|
||||
_real_start: new Date(timeblock.start),
|
||||
_real_end: new Date(timeblock.end)
|
||||
_real_end: new Date(timeblock.end),
|
||||
draggable: false // TODO office365: Disable only for office 365 events
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in new issue
Block a user