mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-12 15:04:04 +00:00
WIP: Adding custom tempus event loader
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import FhcCalendar from "./Base.js";
|
||||
|
||||
import { useEventLoader } from '../../composables/EventLoader.js';
|
||||
import { useEventLoader } from '../../composables/Tempus/TempusEventLoader.js';
|
||||
|
||||
import ModeWeek from './Mode/Week.js';
|
||||
import ModeMonth from './Mode/Month.js';
|
||||
@@ -171,14 +171,10 @@ export default {
|
||||
},
|
||||
setup(props, context) {
|
||||
const rangeInterval = Vue.ref(null);
|
||||
const preserveRequestedRange = Vue.computed(() => {
|
||||
return ['week', 'month'].includes(props.mode?.toLowerCase());
|
||||
});
|
||||
|
||||
const { events, lv, reset } = useEventLoader(
|
||||
rangeInterval,
|
||||
props.getPromiseFunc,
|
||||
preserveRequestedRange,
|
||||
() => props.cacheMultiplier
|
||||
);
|
||||
|
||||
|
||||
@@ -1301,6 +1301,7 @@ export default {
|
||||
:mode="currentMode"
|
||||
:parkedEvents="parkedKeys"
|
||||
:visible-lecturers="visibleLecturerUids"
|
||||
:cacheMultiplier="currentMode === 'week' ? 0 : 0"
|
||||
@drop="dropHandler"
|
||||
@resize="resizeHandler"
|
||||
@update:date="handleChangeDate"
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
export function useEventLoader(
|
||||
rangeInterval,
|
||||
getPromiseFunc,
|
||||
cacheMultiplier = 1,
|
||||
) {
|
||||
let allEvents = Vue.ref([]);
|
||||
const events = [];
|
||||
|
||||
const lv = Vue.ref(null);
|
||||
|
||||
let newlyLoadedEvents = [];
|
||||
|
||||
let cachedEventsStartTimestamp = null;
|
||||
let cachedEventsEndTimestamp = null;
|
||||
|
||||
let allowedCacheStartTimestamp = null;
|
||||
let allowedCacheEndTimestamp = null;
|
||||
|
||||
let currentlyDisplayedDateRange;
|
||||
|
||||
const reload = () => {
|
||||
if (
|
||||
currentlyDisplayedDateRange &&
|
||||
currentlyDisplayedDateRange?.start?.ts ===
|
||||
rangeInterval?.value?.start?.ts &&
|
||||
currentlyDisplayedDateRange?.end?.ts === rangeInterval?.value?.end?.ts
|
||||
) {
|
||||
console.log(
|
||||
"cached range is the same as requested range, skipping reload",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
currentlyDisplayedDateRange = Vue.toValue(rangeInterval);
|
||||
|
||||
if (
|
||||
!currentlyDisplayedDateRange?.start ||
|
||||
!currentlyDisplayedDateRange?.end
|
||||
)
|
||||
return;
|
||||
|
||||
if (!(currentlyDisplayedDateRange instanceof luxon.Interval)) return;
|
||||
|
||||
if (
|
||||
cachedEventsStartTimestamp === currentlyDisplayedDateRange.start.ts &&
|
||||
cachedEventsEndTimestamp === currentlyDisplayedDateRange.end.ts
|
||||
) {
|
||||
console.log(
|
||||
"cached range is the same as requested range, skipping reload",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const promises = requestEvents(
|
||||
currentlyDisplayedDateRange.start.ts,
|
||||
currentlyDisplayedDateRange.end.ts,
|
||||
);
|
||||
|
||||
ensureCacheRangeIsAllowedRange(
|
||||
allowedCacheStartTimestamp,
|
||||
allowedCacheEndTimestamp,
|
||||
);
|
||||
|
||||
if (promises.length === 0) {
|
||||
allEvents.value = removeVisualForEventsLoading(
|
||||
ensureEventsAreInValidCacheRange(allEvents.value),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
addVisualForEventsLoading();
|
||||
|
||||
Promise.allSettled(promises).then((results) => {
|
||||
let newlyLoadedEvents = [];
|
||||
|
||||
results.forEach((res) => {
|
||||
if (
|
||||
!(res.status === "fulfilled" && res.value.meta.status === "success")
|
||||
)
|
||||
return;
|
||||
if (res.value.meta.lv) lv.value = res.value.meta.lv;
|
||||
newlyLoadedEvents = res.value.data;
|
||||
});
|
||||
|
||||
let tempAllEvents = Array.from(
|
||||
new Map(
|
||||
[...allEvents.value, ...newlyLoadedEvents].map((event) => [
|
||||
event.eindeutige_gruppen_id,
|
||||
event,
|
||||
]),
|
||||
).values(),
|
||||
);
|
||||
|
||||
allEvents.value = removeVisualForEventsLoading(
|
||||
ensureEventsAreInValidCacheRange(tempAllEvents),
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
Vue.watchEffect(reload);
|
||||
|
||||
const reset = () => {
|
||||
reload();
|
||||
};
|
||||
|
||||
const requestEvents = (startTimestamp, endTimestamp) => {
|
||||
let result = [];
|
||||
|
||||
if (!startTimestamp || !endTimestamp) return result;
|
||||
if (startTimestamp >= endTimestamp) return result;
|
||||
|
||||
let modifiedRequestStartTimestamp = startTimestamp;
|
||||
let modifiedRequestEndTimestamp = endTimestamp;
|
||||
|
||||
if (cachedEventsStartTimestamp && cachedEventsEndTimestamp) {
|
||||
if (
|
||||
startTimestamp < cachedEventsStartTimestamp &&
|
||||
endTimestamp > cachedEventsEndTimestamp
|
||||
) {
|
||||
modifiedRequestStartTimestamp = startTimestamp;
|
||||
modifiedRequestEndTimestamp = endTimestamp;
|
||||
cachedEventsStartTimestamp = startTimestamp;
|
||||
cachedEventsEndTimestamp = endTimestamp;
|
||||
} else if (
|
||||
startTimestamp < cachedEventsStartTimestamp &&
|
||||
endTimestamp <= cachedEventsEndTimestamp
|
||||
) {
|
||||
modifiedRequestStartTimestamp = startTimestamp;
|
||||
modifiedRequestEndTimestamp = cachedEventsStartTimestamp;
|
||||
cachedEventsStartTimestamp = startTimestamp;
|
||||
} else if (
|
||||
startTimestamp >= cachedEventsStartTimestamp &&
|
||||
endTimestamp > cachedEventsEndTimestamp
|
||||
) {
|
||||
modifiedRequestStartTimestamp = cachedEventsEndTimestamp;
|
||||
modifiedRequestEndTimestamp = endTimestamp;
|
||||
cachedEventsEndTimestamp = endTimestamp;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
cachedEventsStartTimestamp = modifiedRequestStartTimestamp;
|
||||
cachedEventsEndTimestamp = modifiedRequestEndTimestamp;
|
||||
}
|
||||
|
||||
const cacheSize = Math.max(Vue.toValue(cacheMultiplier), 0);
|
||||
const cachePadding = Math.round(
|
||||
currentlyDisplayedDateRange.length() * cacheSize,
|
||||
);
|
||||
|
||||
allowedCacheStartTimestamp = startTimestamp - cachePadding;
|
||||
allowedCacheEndTimestamp = endTimestamp + cachePadding;
|
||||
|
||||
return mergePromiseElements(
|
||||
getPromiseFunc(
|
||||
getLuxonDateFromMillis(modifiedRequestStartTimestamp),
|
||||
getLuxonDateFromMillis(modifiedRequestEndTimestamp),
|
||||
),
|
||||
result,
|
||||
);
|
||||
};
|
||||
|
||||
const addVisualForEventsLoading = (startTimestamp, endTimestamp) => {
|
||||
allEvents.value.push({
|
||||
loading_id: 1,
|
||||
type: "loading",
|
||||
isostart: getISODateFromTimestamp(currentlyDisplayedDateRange.start.ts),
|
||||
isoend: getISODateFromTimestamp(currentlyDisplayedDateRange.end.ts),
|
||||
});
|
||||
};
|
||||
|
||||
const removeVisualForEventsLoading = (events) => {
|
||||
return events.filter((event) => event.type !== "loading");
|
||||
};
|
||||
|
||||
const ensureEventsAreInValidCacheRange = (events) => {
|
||||
events = events.filter((event) => {
|
||||
const start = getTimestampFromISODate(event.isostart);
|
||||
const end = getTimestampFromISODate(event.isoend);
|
||||
return (
|
||||
allowedCacheStartTimestamp <= start && allowedCacheEndTimestamp >= end
|
||||
);
|
||||
});
|
||||
|
||||
return events;
|
||||
};
|
||||
|
||||
const ensureCacheRangeIsAllowedRange = (
|
||||
allowedCacheStartTimestamp,
|
||||
allowedCacheEndTimestamp,
|
||||
) => {
|
||||
const cacheSize = Math.max(Vue.toValue(cacheMultiplier), 0);
|
||||
const cachePadding = Math.round(
|
||||
currentlyDisplayedDateRange.length() * cacheSize,
|
||||
);
|
||||
|
||||
if (
|
||||
cachedEventsStartTimestamp < allowedCacheEndTimestamp &&
|
||||
cachedEventsEndTimestamp > allowedCacheStartTimestamp
|
||||
) {
|
||||
if (cachedEventsStartTimestamp < allowedCacheStartTimestamp) {
|
||||
cachedEventsStartTimestamp = allowedCacheStartTimestamp;
|
||||
}
|
||||
if (cachedEventsEndTimestamp > allowedCacheEndTimestamp) {
|
||||
cachedEventsEndTimestamp = allowedCacheEndTimestamp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return { events: allEvents, lv, reset };
|
||||
}
|
||||
|
||||
const mergePromiseElements = (n, o) => {
|
||||
if (Array.isArray(n)) return o.concat(n);
|
||||
return (o.push(n), o);
|
||||
};
|
||||
|
||||
const getDateFromTimestamp = (timestamp) => {
|
||||
return luxon.DateTime.fromMillis(timestamp).toFormat("yyyy-MM-dd");
|
||||
};
|
||||
|
||||
const getISODateFromTimestamp = (timestamp) => {
|
||||
return luxon.DateTime.fromMillis(timestamp).toISO();
|
||||
};
|
||||
|
||||
const getTimestampFromISODate = (isoDate) => {
|
||||
return luxon.DateTime.fromISO(isoDate).ts;
|
||||
};
|
||||
|
||||
const getLuxonDateFromMillis = (millis) => {
|
||||
return luxon.DateTime.fromMillis(millis);
|
||||
};
|
||||
Reference in New Issue
Block a user