Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { userAttendee } from "../../features/User/userDataTypes";
|
||||
import { userAttendee } from "../../features/User/models/attendee";
|
||||
import { createAttendee } from "../../features/User/models/attendee.mapper";
|
||||
import {
|
||||
PeopleSearch,
|
||||
User,
|
||||
@@ -20,18 +21,18 @@ export default function UserSearch({
|
||||
) => React.ReactNode;
|
||||
}) {
|
||||
const [selectedUsers, setSelectedUsers] = useState(
|
||||
attendees.map((a) => ({
|
||||
email: a.cal_address,
|
||||
displayName: a.cn ?? "",
|
||||
attendees.map((attendee) => ({
|
||||
email: attendee.cal_address,
|
||||
displayName: attendee.cn ?? "",
|
||||
avatarUrl: "",
|
||||
openpaasId: "",
|
||||
})) ?? []
|
||||
);
|
||||
useEffect(() => {
|
||||
setSelectedUsers(
|
||||
attendees.map((a) => ({
|
||||
email: a.cal_address,
|
||||
displayName: a.cn ?? "",
|
||||
attendees.map((attendee) => ({
|
||||
email: attendee.cal_address,
|
||||
displayName: attendee.cn ?? "",
|
||||
avatarUrl: "",
|
||||
openpaasId: "",
|
||||
}))
|
||||
@@ -45,14 +46,12 @@ export default function UserSearch({
|
||||
inputSlot={inputSlot}
|
||||
onChange={(event: any, value: User[]) => {
|
||||
setAttendees(
|
||||
value.map((a: User) => ({
|
||||
cn: a.displayName,
|
||||
cal_address: a.email,
|
||||
partstat: "NEED_ACTION",
|
||||
rsvp: "FALSE",
|
||||
role: "REQ-PARTICIPANT",
|
||||
cutype: "INDIVIDUAL",
|
||||
}))
|
||||
value.map((attendee: User) =>
|
||||
createAttendee({
|
||||
cal_address: attendee.email,
|
||||
cn: attendee.displayName,
|
||||
})
|
||||
)
|
||||
);
|
||||
setSelectedUsers(value);
|
||||
}}
|
||||
|
||||
@@ -15,13 +15,13 @@ import {
|
||||
exportCalendar,
|
||||
getSecretLink,
|
||||
} from "../../features/Calendars/CalendarApi";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import { FieldWithLabel } from "../Event/components/FieldWithLabel";
|
||||
import { SnackbarAlert } from "../Loading/SnackBarAlert";
|
||||
import { useI18n } from "twake-i18n";
|
||||
import { ErrorSnackbar } from "../Error/ErrorSnackbar";
|
||||
|
||||
export function AccessTab({ calendar }: { calendar: Calendars }) {
|
||||
export function AccessTab({ calendar }: { calendar: Calendar }) {
|
||||
const { t } = useI18n();
|
||||
const calDAVLink = `${(window as any).CALENDAR_BASE_URL}${calendar.link.replace(".json", "")}`;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from "react";
|
||||
import { MenuItem } from "@mui/material";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import { CalendarName } from "./CalendarName";
|
||||
|
||||
export function CalendarItemList(
|
||||
userPersonalCalendars: Calendars[]
|
||||
userPersonalCalendars: Calendar[]
|
||||
): React.ReactNode {
|
||||
return Object.values(userPersonalCalendars).map((calendar) => (
|
||||
<MenuItem key={calendar.id} value={calendar.id}>
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
patchACLCalendarAsync,
|
||||
patchCalendarAsync,
|
||||
} from "../../features/Calendars/CalendarSlice";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import { ResponsiveDialog } from "../Dialog";
|
||||
import { AccessTab } from "./AccessTab";
|
||||
import { ImportTab } from "./ImportTab";
|
||||
@@ -25,7 +25,7 @@ function CalendarPopover({
|
||||
event: object | null,
|
||||
reason: "backdropClick" | "escapeKeyDown"
|
||||
) => void;
|
||||
calendar?: Calendars;
|
||||
calendar?: Calendar;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import SquareRoundedIcon from "@mui/icons-material/SquareRounded";
|
||||
export function CalendarName({ calendar }: { calendar: Calendars }) {
|
||||
export function CalendarName({ calendar }: { calendar: Calendar }) {
|
||||
return (
|
||||
<Box style={{ display: "flex", flexDirection: "row", gap: 8 }}>
|
||||
<SquareRoundedIcon
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useState } from "react";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import { getCalendars } from "../../features/Calendars/CalendarApi";
|
||||
import { addSharedCalendarAsync } from "../../features/Calendars/CalendarSlice";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { PeopleSearch, User } from "../Attendees/PeopleSearch";
|
||||
import { ResponsiveDialog } from "../Dialog";
|
||||
@@ -93,7 +93,7 @@ function SelectedCalendarsList({
|
||||
onRemove,
|
||||
onColorChange,
|
||||
}: {
|
||||
calendars: Record<string, Calendars>;
|
||||
calendars: Record<string, Calendar>;
|
||||
selectedCal: CalendarWithOwner[];
|
||||
onRemove: (cal: CalendarWithOwner) => void;
|
||||
onColorChange: (
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import { useState, useMemo, useEffect } from "react";
|
||||
import CalendarPopover from "./CalendarModal";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import MoreVertIcon from "@mui/icons-material/MoreVert";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import Checkbox from "@mui/material/Checkbox";
|
||||
@@ -206,7 +206,7 @@ function CalendarSelector({
|
||||
handleCalendarToggle,
|
||||
setOpen,
|
||||
}: {
|
||||
calendars: Record<string, Calendars>;
|
||||
calendars: Record<string, Calendar>;
|
||||
id: string;
|
||||
isPersonal: boolean;
|
||||
selectedCalendars: string[];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import DialogContentText from "@mui/material/DialogContentText";
|
||||
@@ -17,7 +17,7 @@ export function DeleteCalendarDialog({
|
||||
}: {
|
||||
deletePopupOpen: boolean;
|
||||
setDeletePopupOpen: (e: boolean) => void;
|
||||
calendars: Record<string, Calendars>;
|
||||
calendars: Record<string, Calendar>;
|
||||
id: string;
|
||||
isPersonal: boolean;
|
||||
handleDeleteConfirm: () => void;
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { useI18n } from "twake-i18n";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useAppSelector } from "../../app/hooks";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import { AddDescButton } from "../Event/AddDescButton";
|
||||
import { ColorPicker } from "./CalendarColorPicker";
|
||||
|
||||
@@ -35,7 +35,7 @@ export function SettingsTab({
|
||||
setColor: Function;
|
||||
visibility: "public" | "private";
|
||||
setVisibility: Function;
|
||||
calendar?: Calendars;
|
||||
calendar?: Calendar;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const [toggleDesc, setToggleDesc] = useState(Boolean(description));
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
getTempCalendarsListAsync,
|
||||
removeTempCal,
|
||||
} from "../../features/Calendars/CalendarSlice";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import { setView } from "../../features/Settings/SettingsSlice";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { User, PeopleSearch } from "../Attendees/PeopleSearch";
|
||||
@@ -134,7 +134,7 @@ function getCalendarsFromUsersDelta(
|
||||
return { calendarsToImport, calendarsToToggle };
|
||||
}
|
||||
|
||||
function buildEmailToCalendarMap(calRecord: Record<string, Calendars>) {
|
||||
function buildEmailToCalendarMap(calRecord: Record<string, Calendar>) {
|
||||
const map = new Map<string, string[]>();
|
||||
for (const [id, cal] of Object.entries(calRecord)) {
|
||||
cal.ownerEmails?.forEach((email) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DateSelectArg } from "@fullcalendar/core";
|
||||
import { CalendarApi } from "@fullcalendar/core";
|
||||
import { CalendarEvent } from "../../../features/Events/EventsTypes";
|
||||
import { Calendars } from "../../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../../features/Calendars/CalendarTypes";
|
||||
import { getDeltaInMilliseconds } from "../../../utils/dateUtils";
|
||||
import {
|
||||
getCalendarDetailAsync,
|
||||
@@ -17,21 +17,22 @@ import { refreshCalendars } from "../../Event/utils/eventUtils";
|
||||
import { updateTempCalendar } from "../utils/calendarUtils";
|
||||
import { User } from "../../Attendees/PeopleSearch";
|
||||
import { formatLocalDateTime } from "../../Event/utils/dateTimeFormatters";
|
||||
import { userAttendee } from "../../../features/User/userDataTypes";
|
||||
import { userAttendee } from "../../../features/User/models/attendee";
|
||||
import { createAttendee } from "../../../features/User/models/attendee.mapper";
|
||||
|
||||
export interface EventHandlersProps {
|
||||
setSelectedRange: (range: DateSelectArg | null) => void;
|
||||
setAnchorEl: (el: HTMLElement | null) => void;
|
||||
calendarRef: React.RefObject<CalendarApi | null>;
|
||||
selectedCalendars: string[];
|
||||
tempcalendars: Record<string, Calendars>;
|
||||
tempcalendars: Record<string, Calendar>;
|
||||
calendarRange: { start: Date; end: Date };
|
||||
dispatch: any;
|
||||
setOpenEventDisplay: (open: boolean) => void;
|
||||
setEventDisplayedId: (id: string) => void;
|
||||
setEventDisplayedCalId: (id: string) => void;
|
||||
setEventDisplayedTemp: (temp: boolean) => void;
|
||||
calendars: Record<string, Calendars>;
|
||||
calendars: Record<string, Calendar>;
|
||||
setSelectedEvent: (event: CalendarEvent) => void;
|
||||
setAfterChoiceFunc: (func: Function) => void;
|
||||
setOpenEditModePopup: (open: string) => void;
|
||||
@@ -72,14 +73,13 @@ export const createEventHandlers = (props: EventHandlersProps) => {
|
||||
end: selectInfo?.end
|
||||
? formatLocalDateTime(selectInfo?.end, timezone)
|
||||
: "",
|
||||
attendee: tempUsers.map((u) => ({
|
||||
cn: u.displayName,
|
||||
cal_address: u.email,
|
||||
partstat: "NEED-ACTION",
|
||||
role: "REQ-PARTICIPANT",
|
||||
rsvp: "TRUE",
|
||||
cutype: "INDIVIDUAL",
|
||||
})),
|
||||
attendee: tempUsers.map((user) =>
|
||||
createAttendee({
|
||||
cal_address: user.email,
|
||||
cn: user.displayName,
|
||||
rsvp: "TRUE",
|
||||
})
|
||||
),
|
||||
} as CalendarEvent;
|
||||
|
||||
setTempEvent(newEvent);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import { CalendarApi, NowIndicatorContentArg } from "@fullcalendar/core";
|
||||
import { createMouseHandlers } from "./mouseHandlers";
|
||||
import { userAttendee } from "../../../features/User/userDataTypes";
|
||||
import { Calendars } from "../../../features/Calendars/CalendarTypes";
|
||||
import { userAttendee } from "../../../features/User/models/attendee";
|
||||
import { Calendar } from "../../../features/Calendars/CalendarTypes";
|
||||
import { EventErrorHandler } from "../../Error/EventErrorHandler";
|
||||
import { EventChip } from "../../Event/EventChip/EventChip";
|
||||
|
||||
@@ -11,8 +11,8 @@ export interface ViewHandlersProps {
|
||||
setSelectedDate: (date: Date) => void;
|
||||
setSelectedMiniDate: (date: Date) => void;
|
||||
onViewChange?: (view: string) => void;
|
||||
calendars: Record<string, Calendars>;
|
||||
tempcalendars: Record<string, Calendars>;
|
||||
calendars: Record<string, Calendar>;
|
||||
tempcalendars: Record<string, Calendar>;
|
||||
errorHandler: EventErrorHandler;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { darken, getContrastRatio, lighten, Theme } from "@mui/material";
|
||||
import { ThunkDispatch } from "@reduxjs/toolkit";
|
||||
import { updateCalColor } from "../../../features/Calendars/CalendarSlice";
|
||||
import { Calendars } from "../../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../../features/Calendars/CalendarTypes";
|
||||
|
||||
export function updateDarkColor(
|
||||
calendars: Record<string, Calendars>,
|
||||
calendars: Record<string, Calendar>,
|
||||
theme: Theme,
|
||||
dispatch: ThunkDispatch<any, any, any>
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CalendarEvent } from "../../../features/Events/EventsTypes";
|
||||
import { Calendars } from "../../../features/Calendars/CalendarTypes";
|
||||
import { Calendar } from "../../../features/Calendars/CalendarTypes";
|
||||
import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils";
|
||||
import { getCalendarDetailAsync } from "../../../features/Calendars/CalendarSlice";
|
||||
import { SlotLabelContentArg } from "@fullcalendar/core";
|
||||
@@ -140,7 +140,7 @@ export const eventToFullCalendarFormat = (
|
||||
|
||||
export const extractEvents = (
|
||||
selectedCalendars: string[],
|
||||
calendars: Record<string, Calendars>,
|
||||
calendars: Record<string, Calendar>,
|
||||
userAddress?: string,
|
||||
hideDeclinedEvents?: boolean | null
|
||||
) => {
|
||||
@@ -272,7 +272,7 @@ export function getCalendarVisibility(acl: AclEntry[]): "private" | "public" {
|
||||
}
|
||||
|
||||
export async function updateTempCalendar(
|
||||
tempcalendars: Record<string, Calendars>,
|
||||
tempcalendars: Record<string, Calendar>,
|
||||
event: CalendarEvent,
|
||||
dispatch: ThunkDispatch<any, any, any>,
|
||||
calendarRange: { start: Date; end: Date }
|
||||
|
||||
@@ -4,8 +4,8 @@ import LockOutlineIcon from "@mui/icons-material/LockOutline";
|
||||
import { Box, getContrastRatio } from "@mui/material";
|
||||
import moment from "moment";
|
||||
import React, { useLayoutEffect, useState } from "react";
|
||||
import { Calendars } from "../../../features/Calendars/CalendarTypes";
|
||||
import { userAttendee } from "../../../features/User/userDataTypes";
|
||||
import { Calendar } from "../../../features/Calendars/CalendarTypes";
|
||||
import { userAttendee } from "../../../features/User/models/attendee";
|
||||
import { EventErrorHandler } from "../../Error/EventErrorHandler";
|
||||
import { EVENT_DURATION } from "./EventChip";
|
||||
|
||||
@@ -13,8 +13,8 @@ const COMPACT_WIDTH_THRESHOLD = 100;
|
||||
|
||||
export interface EventChipProps {
|
||||
arg: any;
|
||||
calendars: Record<string, Calendars>;
|
||||
tempcalendars: Record<string, Calendars>;
|
||||
calendars: Record<string, Calendar>;
|
||||
tempcalendars: Record<string, Calendar>;
|
||||
errorHandler: EventErrorHandler;
|
||||
}
|
||||
export interface IconDisplayConfig {
|
||||
|
||||
@@ -25,8 +25,8 @@ import {
|
||||
import AttendeeSelector from "../Attendees/AttendeeSearch";
|
||||
import RepeatEvent from "./EventRepeat";
|
||||
import { RepetitionObject } from "../../features/Events/EventsTypes";
|
||||
import { userAttendee } from "../../features/User/userDataTypes";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { userAttendee } from "../../features/User/models/attendee";
|
||||
import { Calendar } from "../../features/Calendars/CalendarTypes";
|
||||
import {
|
||||
generateMeetingLink,
|
||||
addVideoConferenceToDescription,
|
||||
@@ -87,7 +87,7 @@ interface EventFormFieldsProps {
|
||||
isOpen?: boolean;
|
||||
|
||||
// Data
|
||||
userPersonalCalendars: Calendars[];
|
||||
userPersonalCalendars: Calendar[];
|
||||
timezoneList: {
|
||||
zones: string[];
|
||||
browserTz: string;
|
||||
|
||||
@@ -1,51 +1,128 @@
|
||||
import { ThunkDispatch } from "@reduxjs/toolkit";
|
||||
import { useAppSelector } from "../../../app/hooks";
|
||||
import {
|
||||
updateEventInstanceAsync,
|
||||
updateSeriesAsync,
|
||||
putEventAsync,
|
||||
deleteEventInstanceAsync,
|
||||
deleteEventAsync,
|
||||
} from "../../../features/Calendars/CalendarSlice";
|
||||
import { Calendars } from "../../../features/Calendars/CalendarTypes";
|
||||
import {
|
||||
getEvent,
|
||||
updateSeriesPartstat,
|
||||
} from "../../../features/Events/EventApi";
|
||||
import { Calendar } from "../../../features/Calendars/CalendarTypes";
|
||||
import { updateSeriesPartstat } from "../../../features/Events/EventApi";
|
||||
import { CalendarEvent } from "../../../features/Events/EventsTypes";
|
||||
import { PartStat } from "../../../features/User/models/attendee";
|
||||
import { createAttendee } from "../../../features/User/models/attendee.mapper";
|
||||
import { userData } from "../../../features/User/userDataTypes";
|
||||
import { buildFamilyName } from "../../../utils/buildFamilyName";
|
||||
import { getCalendarRange } from "../../../utils/dateUtils";
|
||||
import { refreshCalendars } from "../utils/eventUtils";
|
||||
|
||||
function updateEventAttendees(
|
||||
event: CalendarEvent,
|
||||
user: userData | undefined,
|
||||
rsvp: PartStat
|
||||
) {
|
||||
if (!user) {
|
||||
throw new Error("Cannot update attendees without user data");
|
||||
}
|
||||
|
||||
const eventHasNoAttendees = !event?.attendee || event.attendee.length === 0;
|
||||
const isOrganizer =
|
||||
!event.organizer ||
|
||||
event.organizer.cal_address?.toLowerCase() === user.email?.toLowerCase();
|
||||
if (eventHasNoAttendees) {
|
||||
const userdata = createAttendee({
|
||||
cal_address: user.email,
|
||||
cn: buildFamilyName(user.given_name, user.family_name, user.email),
|
||||
role: isOrganizer ? "CHAIR" : "REQ-PARTICIPANT",
|
||||
partstat: rsvp,
|
||||
});
|
||||
return {
|
||||
organizer: isOrganizer ? userdata : event.organizer,
|
||||
attendee: [userdata],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
attendee: (() => {
|
||||
const userEmailLower = user.email?.toLowerCase();
|
||||
const userExists = event.attendee.some(
|
||||
(attendee) => attendee.cal_address?.toLowerCase() === userEmailLower
|
||||
);
|
||||
|
||||
const updatedAttendees = event.attendee.map((attendeeData) =>
|
||||
attendeeData.cal_address?.toLowerCase() === userEmailLower
|
||||
? { ...attendeeData, partstat: rsvp }
|
||||
: attendeeData
|
||||
);
|
||||
|
||||
if (!userExists) {
|
||||
const newUserAttendee = createAttendee({
|
||||
cal_address: user.email,
|
||||
cn: buildFamilyName(user.given_name, user.family_name, user.email),
|
||||
role: "REQ-PARTICIPANT",
|
||||
partstat: rsvp,
|
||||
});
|
||||
return [...updatedAttendees, newUserAttendee];
|
||||
}
|
||||
|
||||
return updatedAttendees;
|
||||
})(),
|
||||
};
|
||||
}
|
||||
|
||||
async function handleSoloRSVP(
|
||||
dispatch: ThunkDispatch<any, any, any>,
|
||||
calendar: Calendar,
|
||||
event: CalendarEvent
|
||||
) {
|
||||
dispatch(updateEventInstanceAsync({ cal: calendar, event }));
|
||||
}
|
||||
|
||||
async function handleAllRSVP(
|
||||
dispatch: ThunkDispatch<any, any, any>,
|
||||
event: CalendarEvent,
|
||||
userEmail: string,
|
||||
rsvp: PartStat,
|
||||
calendars: Calendar[]
|
||||
) {
|
||||
const calendarRange = getCalendarRange(new Date(event.start));
|
||||
await updateSeriesPartstat(event, userEmail, rsvp);
|
||||
await refreshCalendars(dispatch, calendars, calendarRange);
|
||||
}
|
||||
|
||||
async function handleDefaultRSVP(
|
||||
dispatch: ThunkDispatch<any, any, any>,
|
||||
calendar: Calendar,
|
||||
newEvent: CalendarEvent
|
||||
) {
|
||||
dispatch(putEventAsync({ cal: calendar, newEvent }));
|
||||
}
|
||||
|
||||
export async function handleRSVP(
|
||||
dispatch: ThunkDispatch<any, any, any>,
|
||||
calendar: Calendars,
|
||||
user: { userData: userData },
|
||||
calendar: Calendar,
|
||||
user: userData | undefined,
|
||||
event: CalendarEvent,
|
||||
rsvp: string,
|
||||
onClose?: (event: {}, reason: "backdropClick" | "escapeKeyDown") => void,
|
||||
rsvp: PartStat,
|
||||
typeOfAction?: string,
|
||||
calendars?: Calendars[]
|
||||
calendars?: Calendar[]
|
||||
) {
|
||||
const newEvent = {
|
||||
...event,
|
||||
attendee: event.attendee?.map((a) =>
|
||||
a.cal_address === user.userData?.email ? { ...a, partstat: rsvp } : a
|
||||
),
|
||||
...updateEventAttendees(event, user, rsvp),
|
||||
};
|
||||
|
||||
if (typeOfAction === "solo") {
|
||||
dispatch(updateEventInstanceAsync({ cal: calendar, event: newEvent }));
|
||||
await handleSoloRSVP(dispatch, calendar, newEvent);
|
||||
} else if (typeOfAction === "all") {
|
||||
const calendarRange = getCalendarRange(new Date(event.start));
|
||||
|
||||
// Update PARTSTAT on ALL VEVENTs (master + exceptions)
|
||||
await updateSeriesPartstat(event, user.userData?.email, rsvp);
|
||||
|
||||
if (calendars) {
|
||||
await refreshCalendars(dispatch, calendars, calendarRange);
|
||||
if (!calendars || calendars.length === 0) {
|
||||
throw new Error("Cannot update all occurrences without calendar list");
|
||||
}
|
||||
if (!user?.email) {
|
||||
throw new Error("Cannot update all occurrences without user email");
|
||||
}
|
||||
await handleAllRSVP(dispatch, event, user.email, rsvp, calendars);
|
||||
} else {
|
||||
dispatch(putEventAsync({ cal: calendar, newEvent }));
|
||||
await handleDefaultRSVP(dispatch, calendar, newEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +131,7 @@ export function handleDelete(
|
||||
typeOfAction: "solo" | "all" | undefined,
|
||||
onClose: (event: {}, reason: "backdropClick" | "escapeKeyDown") => void,
|
||||
dispatch: Function,
|
||||
calendar: Calendars,
|
||||
calendar: Calendar,
|
||||
event: CalendarEvent,
|
||||
calId: string,
|
||||
eventId: string
|
||||
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
getCalendarDetailAsync,
|
||||
getCalendarsListAsync,
|
||||
} from "../../../features/Calendars/CalendarSlice";
|
||||
import { Calendars } from "../../../features/Calendars/CalendarTypes";
|
||||
import { userAttendee } from "../../../features/User/userDataTypes";
|
||||
import { Calendar } from "../../../features/Calendars/CalendarTypes";
|
||||
import { userAttendee } from "../../../features/User/models/attendee";
|
||||
import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils";
|
||||
|
||||
export function renderAttendeeBadge(
|
||||
@@ -111,7 +111,7 @@ export function stringAvatar(name: string) {
|
||||
|
||||
export async function refreshCalendars(
|
||||
dispatch: ThunkDispatch<any, any, any>,
|
||||
calendars: Calendars[],
|
||||
calendars: Calendar[],
|
||||
calendarRange: { start: Date; end: Date },
|
||||
calType?: "temp"
|
||||
) {
|
||||
@@ -163,7 +163,7 @@ export async function refreshCalendars(
|
||||
|
||||
export async function refreshSingularCalendar(
|
||||
dispatch: ThunkDispatch<any, any, any>,
|
||||
calendar: Calendars,
|
||||
calendar: Calendar,
|
||||
calendarRange: { start: Date; end: Date },
|
||||
calType?: "temp"
|
||||
) {
|
||||
|
||||
@@ -24,10 +24,11 @@ import { useI18n } from "twake-i18n";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import { searchEventsAsync } from "../../features/Search/SearchSlice";
|
||||
import { setView } from "../../features/Settings/SettingsSlice";
|
||||
import { userAttendee } from "../../features/User/userDataTypes";
|
||||
import { userAttendee } from "../../features/User/models/attendee";
|
||||
import UserSearch from "../Attendees/AttendeeSearch";
|
||||
import { CalendarItemList } from "../Calendar/CalendarItemList";
|
||||
import { PeopleSearch, User } from "../Attendees/PeopleSearch";
|
||||
import { createAttendee } from "../../features/User/models/attendee.mapper";
|
||||
|
||||
export default function SearchBar() {
|
||||
const { t } = useI18n();
|
||||
@@ -151,14 +152,12 @@ export default function SearchBar() {
|
||||
if (contacts.length > 0) {
|
||||
handleSearch("", {
|
||||
...filters,
|
||||
organizers: contacts.map((c) => ({
|
||||
cal_address: c.email || c.displayName || "",
|
||||
cutype: "INDIVIDUAL",
|
||||
cn: c.displayName || c.email,
|
||||
role: "Participant",
|
||||
rsvp: "TRUE",
|
||||
partstat: "",
|
||||
})),
|
||||
organizers: contacts.map((contact) =>
|
||||
createAttendee({
|
||||
cal_address: contact.email,
|
||||
cn: contact.displayName,
|
||||
})
|
||||
),
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -334,14 +333,12 @@ export default function SearchBar() {
|
||||
handleFilterChange("keywords", query);
|
||||
handleFilterChange(
|
||||
"organizers",
|
||||
selectedContacts.map((a: User) => ({
|
||||
cn: a.displayName,
|
||||
cal_address: a.email || "",
|
||||
partstat: "NEEDS-ACTION",
|
||||
rsvp: "FALSE",
|
||||
role: "REQ-PARTICIPANT",
|
||||
cutype: "INDIVIDUAL",
|
||||
}))
|
||||
selectedContacts.map((attendee: User) =>
|
||||
createAttendee({
|
||||
cal_address: attendee.email,
|
||||
cn: attendee.displayName,
|
||||
})
|
||||
)
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user