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']
|
||||
LoadingIndicator: typeof import('./src/components/Icons/LoadingIndicator.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']
|
||||
LucideEarth: typeof import('~icons/lucide/earth')['default']
|
||||
LucideLetterText: typeof import('~icons/lucide/letter-text')['default']
|
||||
LucidePlus: typeof import('~icons/lucide/plus')['default']
|
||||
LucideText: typeof import('~icons/lucide/text')['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"
|
||||
>
|
||||
<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">
|
||||
<template #icon>
|
||||
<EditIcon class="size-4" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button icon="trash-2" variant="ghost" @click="deleteEvent" />
|
||||
<Dropdown
|
||||
v-if="event.id"
|
||||
:options="[
|
||||
{
|
||||
label: __('Delete'),
|
||||
value: 'delete',
|
||||
icon: 'trash-2',
|
||||
onClick: deleteEvent,
|
||||
label: __('Duplicate'),
|
||||
icon: 'copy',
|
||||
onClick: duplicateEvent,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<Button variant="ghost" icon="more-horizontal" />
|
||||
<Button variant="ghost" icon="more-vertical" />
|
||||
</Dropdown>
|
||||
<Button
|
||||
icon="x"
|
||||
@ -98,6 +98,10 @@ function deleteEvent() {
|
||||
emit('delete', props.event.id)
|
||||
}
|
||||
|
||||
function duplicateEvent() {
|
||||
emit('duplicate', props.event)
|
||||
}
|
||||
|
||||
function editDetails() {
|
||||
emit('edit', props.event)
|
||||
}
|
||||
|
||||
@ -3,20 +3,32 @@
|
||||
<div
|
||||
class="flex items-center justify-between p-4.5 text-ink-gray-7 text-lg font-medium"
|
||||
>
|
||||
<div>{{ __(title) }}</div>
|
||||
<div class="flex items-center gap-x-2">
|
||||
<div
|
||||
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
|
||||
v-if="event.id"
|
||||
:options="[
|
||||
{
|
||||
label: __('Delete'),
|
||||
value: 'delete',
|
||||
icon: 'trash-2',
|
||||
onClick: deleteEvent,
|
||||
label: __('Duplicate'),
|
||||
icon: 'copy',
|
||||
onClick: duplicateEvent,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<Button variant="ghost" icon="more-horizontal" />
|
||||
<Button variant="ghost" icon="more-vertical" />
|
||||
</Dropdown>
|
||||
<Button
|
||||
icon="x"
|
||||
@ -177,7 +189,7 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['save', 'delete'])
|
||||
const emit = defineEmits(['save', 'delete', 'goToDetails'])
|
||||
|
||||
const show = defineModel()
|
||||
|
||||
@ -198,11 +210,18 @@ watch(
|
||||
|
||||
if (newEvent && newEvent.id) {
|
||||
title.value = 'Editing event'
|
||||
} else {
|
||||
} else if (!newEvent.title) {
|
||||
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)
|
||||
},
|
||||
{ immediate: true },
|
||||
@ -257,10 +276,23 @@ function saveEvent() {
|
||||
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() {
|
||||
emit('delete', _event.value.id)
|
||||
}
|
||||
|
||||
function goToDetails() {
|
||||
show.value = false
|
||||
emit('goToDetails', _event.value)
|
||||
}
|
||||
|
||||
const colors = Object.keys(colorMap).map((color) => ({
|
||||
label: color.charAt(0).toUpperCase() + color.slice(1),
|
||||
value: colorMap[color].color,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<ViewBreadcrumbs routeName="Calendar" />
|
||||
</template>
|
||||
<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>
|
||||
</Button>
|
||||
</template>
|
||||
@ -29,7 +29,7 @@
|
||||
@delete="(eventID) => deleteEvent(eventID)"
|
||||
:onClick="showDetails"
|
||||
:onDblClick="editDetails"
|
||||
:onCellDblClick="showEventPanelArea"
|
||||
:onCellDblClick="newEvent"
|
||||
>
|
||||
<template
|
||||
#header="{
|
||||
@ -88,6 +88,7 @@
|
||||
:event="event"
|
||||
@save="saveEvent"
|
||||
@delete="deleteEvent"
|
||||
@goToDetails="showDetails"
|
||||
/>
|
||||
|
||||
<CalendarEventDetails
|
||||
@ -96,6 +97,7 @@
|
||||
:event="event"
|
||||
@edit="editDetails"
|
||||
@delete="deleteEvent"
|
||||
@duplicate="duplicateEvent"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -249,10 +251,11 @@ const showEventDetails = ref(false)
|
||||
const event = ref({})
|
||||
|
||||
function showDetails(e) {
|
||||
let _e = e?.calendarEvent || e
|
||||
showEventPanel.value = false
|
||||
showEventDetails.value = true
|
||||
event.value = { ...e.calendarEvent }
|
||||
activeEvent.value = e.calendarEvent.id
|
||||
event.value = { ..._e }
|
||||
activeEvent.value = _e.id
|
||||
}
|
||||
|
||||
function editDetails(e) {
|
||||
@ -263,7 +266,7 @@ function editDetails(e) {
|
||||
activeEvent.value = _e.id
|
||||
}
|
||||
|
||||
function showEventPanelArea(e) {
|
||||
function newEvent(e) {
|
||||
let [fromTime, toTime] = getFromToTime(e.time)
|
||||
|
||||
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
|
||||
function getFromToTime(time) {
|
||||
let currentTime = dayjs().format('HH:mm') || '00:00'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user