Ergänze Entwurfsstatus für Termine und Plantafel
This commit is contained in:
@@ -30,6 +30,9 @@ const resources = ref([])
|
||||
const events = ref([])
|
||||
const profiles = ref([])
|
||||
const inventoryitems = ref([])
|
||||
const isDraftModeActive = ref(false)
|
||||
const isFinalizeDraftsModalOpen = ref(false)
|
||||
const finalizingDrafts = ref(false)
|
||||
const savingQuickConfig = ref(false)
|
||||
const isQuickConfigModalOpen = ref(false)
|
||||
const quickConfigWindowEl = ref(null)
|
||||
@@ -273,6 +276,14 @@ const visibleEvents = computed(() => {
|
||||
)
|
||||
})
|
||||
|
||||
const visibleDraftEventIds = computed(() =>
|
||||
[...new Set(
|
||||
visibleEvents.value
|
||||
.filter((event) => event.state === "Entwurf" && event.entrytype === "event" && event.eventId)
|
||||
.map((event) => event.eventId)
|
||||
)]
|
||||
)
|
||||
|
||||
const calendarOptions = computed(() => ({
|
||||
schedulerLicenseKey: "CC-Attribution-NonCommercial-NoDerivatives",
|
||||
locale: deLocale,
|
||||
@@ -388,10 +399,15 @@ function resolveEventTitle(event, projectsById) {
|
||||
}
|
||||
|
||||
function resolveRenderedEventColor(event) {
|
||||
if (event?.quick) return activeQuickEntryConfig.value.color
|
||||
if (event?.quick) return event?.color || activeQuickEntryConfig.value.color
|
||||
return resolveEventColor(event.eventtype)
|
||||
}
|
||||
|
||||
function resolveDisplayedEventTitle(event, projectsById) {
|
||||
const baseTitle = resolveEventTitle(event, projectsById)
|
||||
return event?.state === "Entwurf" ? `[Entwurf] ${baseTitle}` : baseTitle
|
||||
}
|
||||
|
||||
function getProfileLabel(profile) {
|
||||
return profile?.full_name || profile?.fullName || [profile?.first_name, profile?.last_name].filter(Boolean).join(" ") || profile?.email || `Profil ${profile?.id || ""}`.trim()
|
||||
}
|
||||
@@ -527,13 +543,16 @@ function buildEvents({ rawEvents, projectsById }) {
|
||||
]
|
||||
|
||||
return {
|
||||
title: resolveEventTitle(event, projectsById),
|
||||
title: resolveDisplayedEventTitle(event, projectsById),
|
||||
start: event.startDate,
|
||||
end: event.endDate,
|
||||
resourceIds,
|
||||
color: event.color || null,
|
||||
state: event.state || "Final",
|
||||
backgroundColor: resolveRenderedEventColor(event),
|
||||
borderColor: resolveRenderedEventColor(event),
|
||||
textColor: "#ffffff",
|
||||
classNames: event.state === "Entwurf" ? ["planning-board-draft-event"] : [],
|
||||
entrytype: "event",
|
||||
eventId: event.id
|
||||
}
|
||||
@@ -755,6 +774,8 @@ async function createQuickEvent(info) {
|
||||
const payload = {
|
||||
name: activeQuickEntryConfig.value.name,
|
||||
quick: true,
|
||||
state: isDraftModeActive.value ? "Entwurf" : "Final",
|
||||
color: activeQuickEntryConfig.value.color,
|
||||
startDate: info.startStr,
|
||||
endDate: info.endStr,
|
||||
profiles: resourceIds
|
||||
@@ -786,6 +807,54 @@ async function createQuickEvent(info) {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleDraftMode() {
|
||||
if (isDraftModeActive.value) {
|
||||
if (!visibleDraftEventIds.value.length) {
|
||||
isDraftModeActive.value = false
|
||||
toast.add({ title: "Entwurfsmodus deaktiviert", color: "green" })
|
||||
return
|
||||
}
|
||||
|
||||
isFinalizeDraftsModalOpen.value = true
|
||||
return
|
||||
}
|
||||
|
||||
isDraftModeActive.value = true
|
||||
toast.add({ title: "Entwurfsmodus aktiviert", description: "Neue Schichten werden als Entwurf angelegt.", color: "green" })
|
||||
}
|
||||
|
||||
async function finalizeVisibleDrafts() {
|
||||
if (finalizingDrafts.value || !visibleDraftEventIds.value.length) return
|
||||
|
||||
finalizingDrafts.value = true
|
||||
const draftCount = visibleDraftEventIds.value.length
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
visibleDraftEventIds.value.map((eventId) =>
|
||||
$api(`/api/resource/events/${eventId}`, {
|
||||
method: "PUT",
|
||||
body: { state: "Final" }
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
isDraftModeActive.value = false
|
||||
isFinalizeDraftsModalOpen.value = false
|
||||
toast.add({ title: "Entwürfe finalisiert", description: `${draftCount} Termine wurden finalisiert.`, color: "green" })
|
||||
await loadPlanningBoard()
|
||||
} catch (error) {
|
||||
console.error("finalizeVisibleDrafts failed", error)
|
||||
toast.add({
|
||||
title: "Entwürfe konnten nicht finalisiert werden",
|
||||
description: error?.message || "Bitte erneut versuchen.",
|
||||
color: "red"
|
||||
})
|
||||
} finally {
|
||||
finalizingDrafts.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function openAbsenceModal(type = "vacation", preset = {}) {
|
||||
absenceForm.mode = preset.entry ? "edit" : "create"
|
||||
absenceForm.entry = preset.entry || null
|
||||
@@ -983,6 +1052,14 @@ onMounted(() => {
|
||||
>
|
||||
Quick-Einträge
|
||||
</UButton>
|
||||
<UButton
|
||||
:color="isDraftModeActive ? 'amber' : 'neutral'"
|
||||
:variant="isDraftModeActive ? 'solid' : 'outline'"
|
||||
icon="i-heroicons-document-duplicate"
|
||||
@click="toggleDraftMode"
|
||||
>
|
||||
{{ isDraftModeActive ? "Entwurfsmodus aktiv" : "Entwurfsmodus" }}
|
||||
</UButton>
|
||||
<UButton
|
||||
color="amber"
|
||||
variant="soft"
|
||||
@@ -1211,6 +1288,53 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UModal v-model:open="isFinalizeDraftsModalOpen">
|
||||
<template #content>
|
||||
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Entwürfe finalisieren
|
||||
</h3>
|
||||
<p class="text-sm text-muted">
|
||||
Beim Beenden des Entwurfsmodus können die aktuell sichtbaren Entwürfe finalisiert werden.
|
||||
</p>
|
||||
</div>
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="-my-1"
|
||||
@click="isFinalizeDraftsModalOpen = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="space-y-4">
|
||||
<UAlert
|
||||
color="amber"
|
||||
variant="soft"
|
||||
icon="i-heroicons-exclamation-triangle"
|
||||
:title="`${visibleDraftEventIds.length} sichtbare Entwürfe gefunden`"
|
||||
description="Diese Termine werden beim Finalisieren auf den Status Final gesetzt."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end gap-2">
|
||||
<UButton color="gray" variant="soft" @click="isFinalizeDraftsModalOpen = false">
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton color="primary" :loading="finalizingDrafts" @click="finalizeVisibleDrafts">
|
||||
Entwürfe finalisieren
|
||||
</UButton>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
</template>
|
||||
</UModal>
|
||||
|
||||
<UModal v-model:open="isAbsenceModalOpen">
|
||||
<template #content>
|
||||
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
@@ -1506,3 +1630,13 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.planning-board-draft-event) {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
:deep(.planning-board-draft-event .fc-timeline-event) {
|
||||
border-style: dashed;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user