Implement destructive CalDAV move saga
This commit is contained in:
@@ -58,6 +58,7 @@ import {
|
||||
} from "./CalendarCollectionDialogs";
|
||||
import { CalendarEventDialog } from "./CalendarEventDialog";
|
||||
import { CalendarOutboxDialog } from "./CalendarOutboxDialog";
|
||||
import { CalendarMigrationDialog } from "./CalendarMigrationDialog";
|
||||
import {
|
||||
CalendarTimeGrid,
|
||||
CalendarWeekRows,
|
||||
@@ -134,6 +135,7 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
|
||||
const [calendarDialog, setCalendarDialog] = useState<CalendarCollectionDialogState | null>(null);
|
||||
const [calendarDeleteDialog, setCalendarDeleteDialog] = useState<CalendarDeleteDialogState | null>(null);
|
||||
const [outboxDialog, setOutboxDialog] = useState<{ calendar: CalendarCollection; source: CalendarSyncSource } | null>(null);
|
||||
const [migrationBatchId, setMigrationBatchId] = useState("");
|
||||
const [syncingSourceId, setSyncingSourceId] = useState("");
|
||||
const [continuousViewport, setContinuousViewport] = useState<ContinuousViewport>({ scrollTop: 0, height: 0 });
|
||||
const [draggingEventId, setDraggingEventId] = useState("");
|
||||
@@ -238,7 +240,7 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
|
||||
return () => window.cancelAnimationFrame(frame);
|
||||
}, [days, mode]);
|
||||
|
||||
async function loadCalendars() {
|
||||
async function loadCalendars(): Promise<CalendarCollection[]> {
|
||||
setLoading(true);
|
||||
setError("");
|
||||
try {
|
||||
@@ -254,8 +256,10 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
|
||||
return next.length > 0 ? next : ids;
|
||||
});
|
||||
setEventCalendarId((current) => current && ids.includes(current) ? current : ids[0] ?? "");
|
||||
return response.calendars;
|
||||
} catch (err) {
|
||||
setError(errorText(err));
|
||||
return [];
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -387,11 +391,19 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
|
||||
await deleteCalendar(settings, calendar.id, payload);
|
||||
setCalendarDialog(null);
|
||||
setCalendarDeleteDialog(null);
|
||||
setCalendars((current) => current.filter((item) => item.id !== calendar.id));
|
||||
setSyncSources((current) => current.filter((item) => item.calendar_id !== calendar.id));
|
||||
setVisibleCalendarIds((current) => current.filter((id) => id !== calendar.id));
|
||||
setEventCalendarId((current) => current === calendar.id ? "" : current);
|
||||
await loadCalendars();
|
||||
const remoteMove = payload.external_action === "remote_move";
|
||||
if (!remoteMove) {
|
||||
setCalendars((current) => current.filter((item) => item.id !== calendar.id));
|
||||
setSyncSources((current) => current.filter((item) => item.calendar_id !== calendar.id));
|
||||
setVisibleCalendarIds((current) => current.filter((id) => id !== calendar.id));
|
||||
setEventCalendarId((current) => current === calendar.id ? "" : current);
|
||||
}
|
||||
const refreshedCalendars = await loadCalendars();
|
||||
if (remoteMove) {
|
||||
const refreshedSource = refreshedCalendars.find((item) => item.id === calendar.id);
|
||||
const batchId = refreshedSource ? calendarRemoteMoveBatchId(refreshedSource) : "";
|
||||
if (batchId) setMigrationBatchId(batchId);
|
||||
}
|
||||
if (calendars.length > 1 || payload.event_action === "move") {
|
||||
await loadEvents();
|
||||
} else {
|
||||
@@ -1012,6 +1024,10 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
|
||||
setOutboxDialog({ calendar: calendarDialog.calendar, source });
|
||||
}
|
||||
}}
|
||||
onOpenMigration={(batchId) => {
|
||||
setCalendarDialog(null);
|
||||
setMigrationBatchId(batchId);
|
||||
}}
|
||||
onDiscover={handleCalDavDiscovery} />
|
||||
|
||||
}
|
||||
@@ -1022,6 +1038,17 @@ export default function CalendarPage({ settings, auth }: {settings: ApiSettings;
|
||||
source={outboxDialog.source}
|
||||
onClose={() => setOutboxDialog(null)} />
|
||||
|
||||
}
|
||||
{migrationBatchId &&
|
||||
<CalendarMigrationDialog
|
||||
settings={settings}
|
||||
batchId={migrationBatchId}
|
||||
onClose={() => setMigrationBatchId("")}
|
||||
onChanged={() => {
|
||||
void loadCalendars();
|
||||
void loadEvents();
|
||||
}} />
|
||||
|
||||
}
|
||||
{calendarDeleteDialog &&
|
||||
<CalendarCollectionDeleteDialog
|
||||
@@ -1042,6 +1069,13 @@ function compareCalendars(left: CalendarCollection, right: CalendarCollection):
|
||||
return left.name.localeCompare(right.name);
|
||||
}
|
||||
|
||||
function calendarRemoteMoveBatchId(calendar: CalendarCollection): string {
|
||||
const remoteMove = calendar.metadata?.remote_move;
|
||||
if (!remoteMove || typeof remoteMove !== "object" || Array.isArray(remoteMove)) return "";
|
||||
const batchId = (remoteMove as Record<string, unknown>).batch_id;
|
||||
return typeof batchId === "string" ? batchId : "";
|
||||
}
|
||||
|
||||
function calendarViewPreferences(
|
||||
response: CalendarViewPreferencesResponse
|
||||
): CalendarViewPreferences {
|
||||
|
||||
Reference in New Issue
Block a user