feat: add duplicate functionality to CalendarEventDetails and CalendarEventPanel components
This commit is contained in:
parent
1cc972ea8b
commit
38b838ec97
2
frontend/components.d.ts
vendored
2
frontend/components.d.ts
vendored
@ -191,8 +191,10 @@ declare module 'vue' {
|
|||||||
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
ListRows: typeof import('./src/components/ListViews/ListRows.vue')['default']
|
||||||
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.vue')['default']
|
||||||
LostReasonModal: typeof import('./src/components/Modals/LostReasonModal.vue')['default']
|
LostReasonModal: typeof import('./src/components/Modals/LostReasonModal.vue')['default']
|
||||||
|
LucideChevronLeft: typeof import('~icons/lucide/chevron-left')['default']
|
||||||
LucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
LucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
||||||
LucideEarth: typeof import('~icons/lucide/earth')['default']
|
LucideEarth: typeof import('~icons/lucide/earth')['default']
|
||||||
|
LucideLetterText: typeof import('~icons/lucide/letter-text')['default']
|
||||||
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
||||||
LucideText: typeof import('~icons/lucide/text')['default']
|
LucideText: typeof import('~icons/lucide/text')['default']
|
||||||
LucideX: typeof import('~icons/lucide/x')['default']
|
LucideX: typeof import('~icons/lucide/x')['default']
|
||||||
|
|||||||
@ -4,24 +4,24 @@
|
|||||||
class="flex items-center justify-between p-4.5 text-ink-gray-7 text-lg font-medium"
|
class="flex items-center justify-between p-4.5 text-ink-gray-7 text-lg font-medium"
|
||||||
>
|
>
|
||||||
<div>{{ __('Event details') }}</div>
|
<div>{{ __('Event details') }}</div>
|
||||||
<div class="flex items-center gap-x-2">
|
<div class="flex items-center gap-x-1">
|
||||||
<Button variant="ghost" @click="editDetails">
|
<Button variant="ghost" @click="editDetails">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<EditIcon class="size-4" />
|
<EditIcon class="size-4" />
|
||||||
</template>
|
</template>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button icon="trash-2" variant="ghost" @click="deleteEvent" />
|
||||||
<Dropdown
|
<Dropdown
|
||||||
v-if="event.id"
|
v-if="event.id"
|
||||||
:options="[
|
:options="[
|
||||||
{
|
{
|
||||||
label: __('Delete'),
|
label: __('Duplicate'),
|
||||||
value: 'delete',
|
icon: 'copy',
|
||||||
icon: 'trash-2',
|
onClick: duplicateEvent,
|
||||||
onClick: deleteEvent,
|
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<Button variant="ghost" icon="more-horizontal" />
|
<Button variant="ghost" icon="more-vertical" />
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Button
|
<Button
|
||||||
icon="x"
|
icon="x"
|
||||||
@ -98,6 +98,10 @@ function deleteEvent() {
|
|||||||
emit('delete', props.event.id)
|
emit('delete', props.event.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function duplicateEvent() {
|
||||||
|
emit('duplicate', props.event)
|
||||||
|
}
|
||||||
|
|
||||||
function editDetails() {
|
function editDetails() {
|
||||||
emit('edit', props.event)
|
emit('edit', props.event)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,20 +3,32 @@
|
|||||||
<div
|
<div
|
||||||
class="flex items-center justify-between p-4.5 text-ink-gray-7 text-lg font-medium"
|
class="flex items-center justify-between p-4.5 text-ink-gray-7 text-lg font-medium"
|
||||||
>
|
>
|
||||||
<div>{{ __(title) }}</div>
|
<div
|
||||||
<div class="flex items-center gap-x-2">
|
class="flex items-center gap-x-2"
|
||||||
|
:class="event.id && 'cursor-pointer hover:text-ink-gray-8'"
|
||||||
|
@click="event.id && goToDetails()"
|
||||||
|
>
|
||||||
|
<LucideChevronLeft v-if="event.id" class="size-4" />
|
||||||
|
{{ __(title) }}
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-x-1">
|
||||||
|
<Button
|
||||||
|
v-if="event.id"
|
||||||
|
icon="trash-2"
|
||||||
|
variant="ghost"
|
||||||
|
@click="deleteEvent"
|
||||||
|
/>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
v-if="event.id"
|
v-if="event.id"
|
||||||
:options="[
|
:options="[
|
||||||
{
|
{
|
||||||
label: __('Delete'),
|
label: __('Duplicate'),
|
||||||
value: 'delete',
|
icon: 'copy',
|
||||||
icon: 'trash-2',
|
onClick: duplicateEvent,
|
||||||
onClick: deleteEvent,
|
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<Button variant="ghost" icon="more-horizontal" />
|
<Button variant="ghost" icon="more-vertical" />
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Button
|
<Button
|
||||||
icon="x"
|
icon="x"
|
||||||
@ -177,7 +189,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['save', 'delete'])
|
const emit = defineEmits(['save', 'delete', 'goToDetails'])
|
||||||
|
|
||||||
const show = defineModel()
|
const show = defineModel()
|
||||||
|
|
||||||
@ -198,11 +210,18 @@ watch(
|
|||||||
|
|
||||||
if (newEvent && newEvent.id) {
|
if (newEvent && newEvent.id) {
|
||||||
title.value = 'Editing event'
|
title.value = 'Editing event'
|
||||||
} else {
|
} else if (!newEvent.title) {
|
||||||
title.value = 'New event'
|
title.value = 'New event'
|
||||||
|
} else {
|
||||||
|
title.value = 'Duplicate event'
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick(() => (_event.value = { ...newEvent }))
|
nextTick(() => {
|
||||||
|
_event.value = { ...newEvent }
|
||||||
|
if (title.value == 'Duplicate event') {
|
||||||
|
_event.value.title = `${_event.value.title} (Copy)`
|
||||||
|
}
|
||||||
|
})
|
||||||
setTimeout(() => eventTitle.value?.el?.focus(), 100)
|
setTimeout(() => eventTitle.value?.el?.focus(), 100)
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
@ -257,10 +276,23 @@ function saveEvent() {
|
|||||||
emit('save', _event.value)
|
emit('save', _event.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function duplicateEvent() {
|
||||||
|
props.event.id = ''
|
||||||
|
title.value = 'Duplicate event'
|
||||||
|
_event.value = { ...props.event }
|
||||||
|
_event.value.title = `${_event.value.title} (Copy)`
|
||||||
|
nextTick(() => eventTitle.value?.el?.focus())
|
||||||
|
}
|
||||||
|
|
||||||
function deleteEvent() {
|
function deleteEvent() {
|
||||||
emit('delete', _event.value.id)
|
emit('delete', _event.value.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goToDetails() {
|
||||||
|
show.value = false
|
||||||
|
emit('goToDetails', _event.value)
|
||||||
|
}
|
||||||
|
|
||||||
const colors = Object.keys(colorMap).map((color) => ({
|
const colors = Object.keys(colorMap).map((color) => ({
|
||||||
label: color.charAt(0).toUpperCase() + color.slice(1),
|
label: color.charAt(0).toUpperCase() + color.slice(1),
|
||||||
value: colorMap[color].color,
|
value: colorMap[color].color,
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<ViewBreadcrumbs routeName="Calendar" />
|
<ViewBreadcrumbs routeName="Calendar" />
|
||||||
</template>
|
</template>
|
||||||
<template #right-header>
|
<template #right-header>
|
||||||
<Button variant="solid" :label="__('Create')" @click="showEventPanelArea">
|
<Button variant="solid" :label="__('Create')" @click="newEvent">
|
||||||
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
<template #prefix><FeatherIcon name="plus" class="h-4" /></template>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
@delete="(eventID) => deleteEvent(eventID)"
|
@delete="(eventID) => deleteEvent(eventID)"
|
||||||
:onClick="showDetails"
|
:onClick="showDetails"
|
||||||
:onDblClick="editDetails"
|
:onDblClick="editDetails"
|
||||||
:onCellDblClick="showEventPanelArea"
|
:onCellDblClick="newEvent"
|
||||||
>
|
>
|
||||||
<template
|
<template
|
||||||
#header="{
|
#header="{
|
||||||
@ -88,6 +88,7 @@
|
|||||||
:event="event"
|
:event="event"
|
||||||
@save="saveEvent"
|
@save="saveEvent"
|
||||||
@delete="deleteEvent"
|
@delete="deleteEvent"
|
||||||
|
@goToDetails="showDetails"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CalendarEventDetails
|
<CalendarEventDetails
|
||||||
@ -96,6 +97,7 @@
|
|||||||
:event="event"
|
:event="event"
|
||||||
@edit="editDetails"
|
@edit="editDetails"
|
||||||
@delete="deleteEvent"
|
@delete="deleteEvent"
|
||||||
|
@duplicate="duplicateEvent"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -249,10 +251,11 @@ const showEventDetails = ref(false)
|
|||||||
const event = ref({})
|
const event = ref({})
|
||||||
|
|
||||||
function showDetails(e) {
|
function showDetails(e) {
|
||||||
|
let _e = e?.calendarEvent || e
|
||||||
showEventPanel.value = false
|
showEventPanel.value = false
|
||||||
showEventDetails.value = true
|
showEventDetails.value = true
|
||||||
event.value = { ...e.calendarEvent }
|
event.value = { ..._e }
|
||||||
activeEvent.value = e.calendarEvent.id
|
activeEvent.value = _e.id
|
||||||
}
|
}
|
||||||
|
|
||||||
function editDetails(e) {
|
function editDetails(e) {
|
||||||
@ -263,7 +266,7 @@ function editDetails(e) {
|
|||||||
activeEvent.value = _e.id
|
activeEvent.value = _e.id
|
||||||
}
|
}
|
||||||
|
|
||||||
function showEventPanelArea(e) {
|
function newEvent(e) {
|
||||||
let [fromTime, toTime] = getFromToTime(e.time)
|
let [fromTime, toTime] = getFromToTime(e.time)
|
||||||
|
|
||||||
let fromDate = dayjs(e.date).format('YYYY-MM-DD')
|
let fromDate = dayjs(e.date).format('YYYY-MM-DD')
|
||||||
@ -284,6 +287,13 @@ function showEventPanelArea(e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function duplicateEvent(e) {
|
||||||
|
showEventDetails.value = false
|
||||||
|
showEventPanel.value = true
|
||||||
|
e.id = ''
|
||||||
|
event.value = { ...e }
|
||||||
|
}
|
||||||
|
|
||||||
// utils
|
// utils
|
||||||
function getFromToTime(time) {
|
function getFromToTime(time) {
|
||||||
let currentTime = dayjs().format('HH:mm') || '00:00'
|
let currentTime = dayjs().format('HH:mm') || '00:00'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user