405 back reload token with synctokens (#436)

* [#405] added syncToken in calendar params and fetch with sync token

* [#405] changed reload to work with sync-token

* [#405] fixup promise handling, added calendar adding and removing hanlding with refresh

* [#405]  fixed event expansion calls

* [#405 & refactor] added helperfunction to get base event uid + refactored synctoken updates management

* [#405] added pMap lib to process event expansion

* [#405] added flag for no synctoken / new synctoken
This commit is contained in:
Camille Moussu
2026-01-13 11:06:34 +01:00
committed by GitHub
parent bcc3019e4b
commit 478a0e0eb0
36 changed files with 1323 additions and 281 deletions
+3 -2
View File
@@ -10,7 +10,7 @@ import { useAppDispatch, useAppSelector } from "../../app/hooks";
import EventPopover from "../../features/Events/EventModal";
import { CalendarEvent } from "../../features/Events/EventsTypes";
import CalendarSelection from "./CalendarSelection";
import { getCalendarDetailAsync } from "../../features/Calendars/CalendarSlice";
import { getCalendarDetailAsync } from "../../features/Calendars/services/getCalendarDetailAsync";
import ImportAlert from "../../features/Events/ImportAlert";
import {
formatDateToYYYYMMDDTHHMMSS,
@@ -44,6 +44,7 @@ import viLocale from "@fullcalendar/core/locales/vi";
import SearchResultsPage from "../../features/Search/SearchResultsPage";
import { setTimeZone } from "../../features/Settings/SettingsSlice";
import { browserDefaultTimeZone } from "../../utils/timezone";
import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid";
const localeMap: Record<string, any> = {
fr: frLocale,
@@ -152,7 +153,7 @@ export default function CalendarApp({
setSelectedCalendars(valid);
} else {
const personalCalendarIds = calendarIds.filter(
(id) => id.split("/")[0] === userId
(id) => extractEventBaseUuid(id) === userId
);
setSelectedCalendars(personalCalendarIds);
}
@@ -8,7 +8,6 @@ import { refreshCalendars } from "../Event/utils/eventUtils";
import { ErrorSnackbar } from "../Error/ErrorSnackbar";
import SettingsPage from "../../features/Settings/SettingsPage";
import SearchResultsPage from "../../features/Search/SearchResultsPage";
export default function CalendarLayout() {
const calendarRef = useRef<any>(null);
+4 -1
View File
@@ -14,6 +14,7 @@ import { ImportTab } from "./ImportTab";
import { SettingsTab } from "./SettingsTab";
import { defaultColors } from "./utils/calendarColorsUtils";
import { useI18n } from "twake-i18n";
import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid";
function CalendarPopover({
open,
@@ -32,7 +33,9 @@ function CalendarPopover({
const userId =
useAppSelector((state) => state.user.userData?.openpaasId) ?? "";
const calendars = useAppSelector((state) => state.calendars.list);
const isOwn = calendar ? calendar?.id.split("/")[0] === userId : true;
const isOwn = calendar?.id
? extractEventBaseUuid(calendar.id) === userId
: true;
// existing calendar params
const [name, setName] = useState("");
@@ -22,6 +22,7 @@ import { removeCalendarAsync } from "../../features/Calendars/CalendarSlice";
import { DeleteCalendarDialog } from "./DeleteCalendarDialog";
import { trimLongTextWithoutSpace } from "../../utils/textUtils";
import { useI18n } from "twake-i18n";
import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid";
function CalendarAccordion({
title,
@@ -112,13 +113,13 @@ export default function CalendarSelection({
const calendars = useAppSelector((state) => state.calendars.list);
const personalCalendars = Object.keys(calendars || {}).filter(
(id) => id.split("/")[0] === userId
(id) => extractEventBaseUuid(id) === userId
);
const delegatedCalendars = Object.keys(calendars || {}).filter(
(id) => id.split("/")[0] !== userId && calendars[id]?.delegated
(id) => extractEventBaseUuid(id) !== userId && calendars[id]?.delegated
);
const sharedCalendars = Object.keys(calendars || {}).filter(
(id) => id.split("/")[0] !== userId && !calendars?.[id]?.delegated
(id) => extractEventBaseUuid(id) !== userId && !calendars?.[id]?.delegated
);
const handleCalendarToggle = (name: string) => {
+2 -1
View File
@@ -15,6 +15,7 @@ import { useAppSelector } from "../../app/hooks";
import { CalendarItemList } from "./CalendarItemList";
import { SettingsTab } from "./SettingsTab";
import { useI18n } from "twake-i18n";
import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid";
export function ImportTab({
userId,
@@ -44,7 +45,7 @@ export function ImportTab({
const [importUrl, setImportUrl] = useState("");
const calendars = useAppSelector((state) => state.calendars.list);
const personalCalendars = Object.values(calendars).filter(
(cal) => cal.id.split("/")[0] === userId
(cal) => extractEventBaseUuid(cal.id) === userId
);
useEffect(() => {
+1 -1
View File
@@ -8,7 +8,7 @@ import {
getCalendarRange,
} from "../../utils/dateUtils";
import { useAppDispatch, useAppSelector } from "../../app/hooks";
import { getCalendarDetailAsync } from "../../features/Calendars/CalendarSlice";
import { getCalendarDetailAsync } from "../../features/Calendars/services/getCalendarDetailAsync";
import { useEffect, useState } from "react";
import { useI18n } from "twake-i18n";
import { setView } from "../../features/Settings/SettingsSlice";
+2 -1
View File
@@ -15,6 +15,7 @@ import { useAppSelector } from "../../app/hooks";
import { Calendar } from "../../features/Calendars/CalendarTypes";
import { AddDescButton } from "../Event/AddDescButton";
import { ColorPicker } from "./CalendarColorPicker";
import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid";
export function SettingsTab({
name,
@@ -41,7 +42,7 @@ export function SettingsTab({
const [toggleDesc, setToggleDesc] = useState(Boolean(description));
const userId =
useAppSelector((state) => state.user.userData?.openpaasId) ?? "";
const isOwn = calendar ? calendar.id.split("/")[0] === userId : true;
const isOwn = calendar ? extractEventBaseUuid(calendar.id) === userId : true;
useEffect(() => {
if (description) setToggleDesc(true);
@@ -4,13 +4,13 @@ import { CalendarEvent } from "../../../features/Events/EventsTypes";
import { Calendar } from "../../../features/Calendars/CalendarTypes";
import { getDeltaInMilliseconds } from "../../../utils/dateUtils";
import {
getCalendarDetailAsync,
getEventAsync,
putEventAsync,
updateEventInstanceAsync,
updateEventLocal,
updateSeriesAsync,
} from "../../../features/Calendars/CalendarSlice";
import { getCalendarDetailAsync } from "../../../features/Calendars/services/getCalendarDetailAsync";
import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils";
import { getEvent } from "../../../features/Events/EventApi";
import { refreshCalendars } from "../../Event/utils/eventUtils";
@@ -1,13 +1,14 @@
import { CalendarEvent } from "../../../features/Events/EventsTypes";
import { Calendar } from "../../../features/Calendars/CalendarTypes";
import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils";
import { getCalendarDetailAsync } from "../../../features/Calendars/CalendarSlice";
import { getCalendarDetailAsync } from "../../../features/Calendars/services/getCalendarDetailAsync";
import { SlotLabelContentArg } from "@fullcalendar/core";
import moment from "moment-timezone";
import { refreshSingularCalendar } from "../../Event/utils/eventUtils";
import { ThunkDispatch } from "@reduxjs/toolkit";
import { useI18n } from "twake-i18n";
import { detectDateTimeFormat } from "../../Event/utils/dateTimeHelpers";
import { extractEventBaseUuid } from "../../../utils/extractEventBaseUuid";
function convertEventDateTimeToISO(
datetime: string,
@@ -102,7 +103,7 @@ export const eventToFullCalendarFormat = (
.map((e) => {
const eventTimezone = e.timezone || "Etc/UTC";
const isAllDay = e.allday ?? false;
const isPersonnalEvent = e.calId.split("/")[0] === userId;
const isPersonnalEvent = extractEventBaseUuid(e.calId) === userId;
const convertedEvent: any = {
...e,