KI-AGENT: Ergänze wiederholende Termine für Kalender und Plantafel
This commit is contained in:
@@ -6,6 +6,7 @@ import timeGridPlugin from "@fullcalendar/timegrid"
|
||||
import resourceTimelinePlugin from "@fullcalendar/resource-timeline";
|
||||
import interactionPlugin from "@fullcalendar/interaction";
|
||||
import dayjs from "dayjs";
|
||||
import { expandRecurringEvent } from "~/utils/eventRecurrence"
|
||||
|
||||
//TODO BACKEND CHANGE COLOR IN TENANT FOR RENDERING
|
||||
|
||||
@@ -33,6 +34,124 @@ const selectedEvent = ref({})
|
||||
const selectedResources = ref([])
|
||||
|
||||
const events = ref([])
|
||||
const sourceEvents = ref([])
|
||||
const sourceAbsenceRequests = ref([])
|
||||
const sourceProjects = ref([])
|
||||
const sourceProfiles = ref([])
|
||||
const sourceVehicles = ref([])
|
||||
const sourceInventoryItems = ref([])
|
||||
const sourceInventoryItemGroups = ref([])
|
||||
|
||||
const buildEventTitle = (event) => {
|
||||
if (event.name) return event.name
|
||||
if (event.project) {
|
||||
const project = sourceProjects.value.find((item) => item.id === event.project)
|
||||
return project?.name || ""
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
const buildEventColor = (event) =>
|
||||
profileStore.ownTenant.calendarConfig.eventTypes.find(type => type.label === event.eventtype)?.color || "black"
|
||||
|
||||
const expandEventsForRange = (rangeStart, rangeEnd) => {
|
||||
const gridEvents = sourceEvents.value.flatMap((event) =>
|
||||
expandRecurringEvent(event, rangeStart, rangeEnd, (occurrenceStart, occurrenceEnd, occurrenceIndex) => {
|
||||
const eventColor = buildEventColor(event)
|
||||
|
||||
return {
|
||||
...event,
|
||||
start: occurrenceStart.toISOString(),
|
||||
end: occurrenceEnd ? occurrenceEnd.toISOString() : null,
|
||||
title: buildEventTitle(event),
|
||||
borderColor: eventColor,
|
||||
textColor: eventColor,
|
||||
backgroundColor: "black",
|
||||
entrytype: "event",
|
||||
eventId: event.id,
|
||||
occurrenceIndex
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const absenceEvents = sourceAbsenceRequests.value.map(absence => ({
|
||||
id: absence.id,
|
||||
resourceId: absence.user,
|
||||
resourceType: "person",
|
||||
title: `${absence.reason} - ${absence.profile.fullName}`,
|
||||
start: dayjs(absence.startDate).toDate(),
|
||||
end: dayjs(absence.endDate).add(1, 'day').toDate(),
|
||||
allDay: true,
|
||||
absencerequestId: absence.id,
|
||||
entrytype: "absencerequest",
|
||||
}))
|
||||
|
||||
calendarOptionsGrid.value.initialEvents = [
|
||||
...gridEvents,
|
||||
...absenceEvents
|
||||
]
|
||||
|
||||
const timelineEvents = sourceEvents.value.flatMap((event) => {
|
||||
const eventColor = buildEventColor(event)
|
||||
const title = buildEventTitle(event)
|
||||
|
||||
return expandRecurringEvent(event, rangeStart, rangeEnd, (occurrenceStart, occurrenceEnd) => {
|
||||
const returnData = {
|
||||
title,
|
||||
borderColor: eventColor,
|
||||
textColor: "white",
|
||||
backgroundColor: eventColor,
|
||||
start: occurrenceStart.toISOString(),
|
||||
end: occurrenceEnd ? occurrenceEnd.toISOString() : null,
|
||||
resourceIds: [],
|
||||
entrytype: "event",
|
||||
eventId: event.id
|
||||
}
|
||||
|
||||
if(event.profiles.length > 0) {
|
||||
event.profiles.forEach(profile => {
|
||||
returnData.resourceIds.push(`P-${profile}`)
|
||||
})
|
||||
}
|
||||
|
||||
if(event.vehicles.length > 0) {
|
||||
event.vehicles.forEach(vehicle => {
|
||||
returnData.resourceIds.push(`F-${vehicle}`)
|
||||
})
|
||||
}
|
||||
|
||||
if(event.inventoryitems.length > 0) {
|
||||
event.inventoryitems.forEach(inventoryitem => {
|
||||
returnData.resourceIds.push(`I-${inventoryitem}`)
|
||||
})
|
||||
}
|
||||
|
||||
if(event.inventoryitemgroups.length > 0) {
|
||||
event.inventoryitemgroups.forEach(inventoryitemgroup => {
|
||||
returnData.resourceIds.push(`G-${inventoryitemgroup}`)
|
||||
})
|
||||
}
|
||||
|
||||
return returnData
|
||||
})
|
||||
})
|
||||
|
||||
sourceAbsenceRequests.value.forEach(absencerequest => {
|
||||
timelineEvents.push({
|
||||
title: `${absencerequest.reason}`,
|
||||
backgroundColor: "red",
|
||||
borderColor: "red",
|
||||
start: absencerequest.startDate,
|
||||
end: absencerequest.endDate,
|
||||
resourceIds: [`P-${absencerequest.profile.id}`],
|
||||
entrytype: "absencerequest",
|
||||
allDay: true,
|
||||
absencerequestId: absencerequest.id
|
||||
})
|
||||
})
|
||||
|
||||
calendarOptionsTimeline.value.initialEvents = timelineEvents
|
||||
}
|
||||
const calendarOptionsGrid = computed(() => {
|
||||
return {
|
||||
locale: deLocale,
|
||||
@@ -62,6 +181,9 @@ const calendarOptionsGrid = computed(() => {
|
||||
}
|
||||
|
||||
},
|
||||
datesSet: function(info) {
|
||||
expandEventsForRange(info.startStr, info.endStr)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -93,6 +215,9 @@ const calendarOptionsTimeline = ref({
|
||||
router.push(`/standardEntity/events/show/${info.event.extendedProps.eventId}`)
|
||||
}
|
||||
},
|
||||
datesSet: function(info) {
|
||||
expandEventsForRange(info.startStr, info.endStr)
|
||||
},
|
||||
resourceGroupField: "type",
|
||||
resourceOrder: "-type",
|
||||
resources: [],
|
||||
@@ -127,75 +252,37 @@ const calendarOptionsTimeline = ref({
|
||||
|
||||
const loaded = ref(false)
|
||||
const setupPage = async () => {
|
||||
let tempData = (await useEntities("events").select()).filter(i => !i.archived)
|
||||
let absencerequests = (await useEntities("absencerequests").select("*, profile(*)")).filter(i => !i.archived)
|
||||
let projects = (await useEntities("projects").select( "*")).filter(i => !i.archived)
|
||||
let inventoryitems = (await useEntities("inventoryitems").select()).filter(i => !i.archived)
|
||||
let inventoryitemgroups = (await useEntities("inventoryitemgroups").select()).filter(i => !i.archived)
|
||||
let profiles = (await useEntities("profiles").select()).filter(i => !i.archived)
|
||||
let vehicles = (await useEntities("vehicles").select()).filter(i => !i.archived)
|
||||
|
||||
calendarOptionsGrid.value.initialEvents = [
|
||||
...tempData.map(event => {
|
||||
let eventColor = profileStore.ownTenant.calendarConfig.eventTypes.find(type => type.label === event.eventtype).color
|
||||
|
||||
let title = ""
|
||||
if (event.name) {
|
||||
title = event.name
|
||||
} else if (event.project) {
|
||||
title = projects.find(i => i.id === event.project) ? projects.find(i => i.id === event.project).name : ""
|
||||
}
|
||||
|
||||
return {
|
||||
...event,
|
||||
start: event.startDate,
|
||||
end: event.endDate,
|
||||
title: title,
|
||||
borderColor: eventColor,
|
||||
textColor: eventColor,
|
||||
backgroundColor: "black",
|
||||
entrytype: "event",
|
||||
eventId: event.id
|
||||
}
|
||||
}),
|
||||
...absencerequests.map(absence => {
|
||||
return {
|
||||
id: absence.id,
|
||||
resourceId: absence.user,
|
||||
resourceType: "person",
|
||||
title: `${absence.reason} - ${absence.profile.fullName}`,
|
||||
start: dayjs(absence.startDate).toDate(),
|
||||
end: dayjs(absence.endDate).add(1, 'day').toDate(),
|
||||
allDay: true,
|
||||
absencerequestId: absence.id,
|
||||
entrytype: "absencerequest",
|
||||
}
|
||||
})
|
||||
]
|
||||
sourceEvents.value = (await useEntities("events").select()).filter(i => !i.archived)
|
||||
sourceAbsenceRequests.value = (await useEntities("absencerequests").select("*, profile(*)")).filter(i => !i.archived)
|
||||
sourceProjects.value = (await useEntities("projects").select( "*")).filter(i => !i.archived)
|
||||
sourceInventoryItems.value = (await useEntities("inventoryitems").select()).filter(i => !i.archived)
|
||||
sourceInventoryItemGroups.value = (await useEntities("inventoryitemgroups").select()).filter(i => !i.archived)
|
||||
sourceProfiles.value = (await useEntities("profiles").select()).filter(i => !i.archived)
|
||||
sourceVehicles.value = (await useEntities("vehicles").select()).filter(i => !i.archived)
|
||||
|
||||
calendarOptionsTimeline.value.resources = [
|
||||
...profiles.filter(i => i.tenant === profileStore.currentTenant).map(profile => {
|
||||
...sourceProfiles.value.filter(i => i.tenant === profileStore.currentTenant).map(profile => {
|
||||
return {
|
||||
type: 'Mitarbeiter',
|
||||
title: profile.fullName,
|
||||
id: `P-${profile.id}`
|
||||
}
|
||||
}),
|
||||
...vehicles.map(vehicle => {
|
||||
...sourceVehicles.value.map(vehicle => {
|
||||
return {
|
||||
type: 'Fahrzeug',
|
||||
title: vehicle.licensePlate,
|
||||
id: `F-${vehicle.id}`
|
||||
}
|
||||
}),
|
||||
...inventoryitems.filter(i=> i.usePlanning).map(item => {
|
||||
...sourceInventoryItems.value.filter(i=> i.usePlanning).map(item => {
|
||||
return {
|
||||
type: 'Inventar',
|
||||
title: item.name,
|
||||
id: `I-${item.id}`
|
||||
}
|
||||
}),
|
||||
...inventoryitemgroups.filter(i=> i.usePlanning).map(item => {
|
||||
...sourceInventoryItemGroups.value.filter(i=> i.usePlanning).map(item => {
|
||||
return {
|
||||
type: 'Inventargruppen',
|
||||
title: item.name,
|
||||
@@ -234,83 +321,7 @@ const setupPage = async () => {
|
||||
]
|
||||
*/
|
||||
|
||||
let tempEvents = []
|
||||
|
||||
tempData.forEach(event => {
|
||||
console.log(event)
|
||||
let eventColor = profileStore.ownTenant.calendarConfig.eventTypes.find(type => type.label === event.eventtype).color
|
||||
|
||||
let title = ""
|
||||
if (event.name) {
|
||||
title = event.name
|
||||
} else if (event.project) {
|
||||
projects.find(i => i.id === event.project) ? projects.find(i => i.id === event.project).name : ""
|
||||
}
|
||||
|
||||
let returnData = {
|
||||
title: title,
|
||||
borderColor: eventColor,
|
||||
textColor: "white",
|
||||
backgroundColor: eventColor,
|
||||
start: event.startDate,
|
||||
end: event.endDate,
|
||||
resourceIds: [],
|
||||
entrytype: "event",
|
||||
eventId: event.id
|
||||
}
|
||||
|
||||
|
||||
if(event.profiles.length > 0) {
|
||||
event.profiles.forEach(profile => {
|
||||
returnData.resourceIds.push(`P-${profile}`)
|
||||
})
|
||||
}
|
||||
|
||||
if(event.vehicles.length > 0) {
|
||||
event.vehicles.forEach(vehicle => {
|
||||
returnData.resourceIds.push(`F-${vehicle}`)
|
||||
})
|
||||
}
|
||||
|
||||
if(event.inventoryitems.length > 0) {
|
||||
event.inventoryitems.forEach(inventoryitem => {
|
||||
returnData.resourceIds.push(`I-${inventoryitem}`)
|
||||
})
|
||||
}
|
||||
|
||||
if(event.inventoryitemgroups.length > 0) {
|
||||
event.inventoryitemgroups.forEach(inventoryitemgroup => {
|
||||
returnData.resourceIds.push(`G-${inventoryitemgroup}`)
|
||||
})
|
||||
}
|
||||
|
||||
console.log(returnData)
|
||||
|
||||
tempEvents.push(returnData)
|
||||
|
||||
})
|
||||
|
||||
absencerequests.forEach(absencerequest => {
|
||||
let returnData = {
|
||||
title: `${absencerequest.reason}`,
|
||||
backgroundColor: "red",
|
||||
borderColor: "red",
|
||||
start: absencerequest.startDate,
|
||||
end: absencerequest.endDate,
|
||||
resourceIds: [`P-${absencerequest.profile.id}`],
|
||||
entrytype: "absencerequest",
|
||||
allDay: true,
|
||||
absencerequestId: absencerequest.id
|
||||
}
|
||||
|
||||
tempEvents.push(returnData)
|
||||
})
|
||||
|
||||
console.log(tempEvents)
|
||||
|
||||
calendarOptionsTimeline.value.initialEvents = tempEvents
|
||||
|
||||
console.log(calendarOptionsTimeline.value)
|
||||
expandEventsForRange(dayjs().startOf("month").toISOString(), dayjs().endOf("month").toISOString())
|
||||
|
||||
loaded.value = true
|
||||
|
||||
@@ -385,4 +396,4 @@ const convertResourceIds = () => {
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -5,6 +5,7 @@ import interactionPlugin from "@fullcalendar/interaction"
|
||||
import resourceTimelinePlugin from "@fullcalendar/resource-timeline"
|
||||
import { parseDate } from "@internationalized/date"
|
||||
import { useDraggable } from "@vueuse/core"
|
||||
import { expandRecurringEvent } from "~/utils/eventRecurrence"
|
||||
|
||||
const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
@@ -534,7 +535,7 @@ function buildResources({ profiles, inventoryitems }) {
|
||||
function buildEvents({ rawEvents, projectsById }) {
|
||||
const mappedEvents = rawEvents
|
||||
.filter((event) => !event.archived)
|
||||
.map((event) => {
|
||||
.flatMap((event) => {
|
||||
const resourceIds = [
|
||||
...(profiles.value
|
||||
.filter((profile) => (event.profiles || []).includes(profile.id))
|
||||
@@ -542,20 +543,26 @@ function buildEvents({ rawEvents, projectsById }) {
|
||||
...(event.inventoryitems || []).map((itemId) => `I-${itemId}`)
|
||||
]
|
||||
|
||||
return {
|
||||
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
|
||||
}
|
||||
return expandRecurringEvent(
|
||||
event,
|
||||
`${visibleRange.value.from}T00:00:00`,
|
||||
`${visibleRange.value.to}T23:59:59`,
|
||||
(occurrenceStart, occurrenceEnd, occurrenceIndex) => ({
|
||||
title: resolveDisplayedEventTitle(event, projectsById),
|
||||
start: occurrenceStart.toISOString(),
|
||||
end: occurrenceEnd ? occurrenceEnd.toISOString() : null,
|
||||
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,
|
||||
occurrenceIndex
|
||||
})
|
||||
)
|
||||
})
|
||||
.filter((event) => event.resourceIds.length > 0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user