[#4] added delegated calendars
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
import { CalendarApi } from "@fullcalendar/core";
|
||||
import { jest } from "@jest/globals";
|
||||
import { ThunkDispatch } from "@reduxjs/toolkit";
|
||||
import "@testing-library/jest-dom";
|
||||
import { screen } from "@testing-library/react";
|
||||
import * as appHooks from "../../src/app/hooks";
|
||||
import CalendarApp from "../../src/components/Calendar/Calendar";
|
||||
import { renderWithProviders } from "../utils/Renderwithproviders";
|
||||
import CalendarSelection from "../../src/components/Calendar/CalendarSelection";
|
||||
|
||||
describe("CalendarSelection", () => {
|
||||
const today = new Date();
|
||||
const start = new Date(today);
|
||||
start.setHours(10, 0, 0, 0);
|
||||
const end = new Date(today);
|
||||
end.setHours(11, 0, 0, 0);
|
||||
|
||||
it("renders the all the calendars in list", async () => {
|
||||
const preloadedState = {
|
||||
user: {
|
||||
userData: {
|
||||
sub: "test",
|
||||
email: "test@test.com",
|
||||
sid: "mockSid",
|
||||
openpaasId: "user1",
|
||||
},
|
||||
tokens: { accessToken: "token" }, // required to avoid redirect
|
||||
},
|
||||
calendars: {
|
||||
list: {
|
||||
"user1/cal1": {
|
||||
name: "Calendar personnal",
|
||||
id: "user1/cal1",
|
||||
color: "#FF0000",
|
||||
ownerEmails: ["alice@example.com"],
|
||||
events: {
|
||||
event1: {
|
||||
id: "event1",
|
||||
calId: "user1/cal1",
|
||||
uid: "event1",
|
||||
title: "Test Event",
|
||||
start: start.toISOString(),
|
||||
end: end.toISOString(),
|
||||
partstat: "ACCEPTED",
|
||||
organizer: {
|
||||
cn: "Alice",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
attendee: [
|
||||
{
|
||||
cn: "Alice",
|
||||
partstat: "ACCEPTED",
|
||||
rsvp: "TRUE",
|
||||
role: "REQ-PARTICIPANT",
|
||||
cutype: "INDIVIDUAL",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"user2/cal1": {
|
||||
name: "Calendar delegated",
|
||||
delegated: true,
|
||||
id: "user2/cal1",
|
||||
color: "#FF0000",
|
||||
ownerEmails: ["alice@example.com"],
|
||||
events: {
|
||||
event1: {
|
||||
id: "event1",
|
||||
calId: "user2/cal1",
|
||||
uid: "event1",
|
||||
title: "Test Event",
|
||||
start: start.toISOString(),
|
||||
end: end.toISOString(),
|
||||
partstat: "ACCEPTED",
|
||||
organizer: {
|
||||
cn: "Alice",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
attendee: [
|
||||
{
|
||||
cn: "Alice",
|
||||
partstat: "ACCEPTED",
|
||||
rsvp: "TRUE",
|
||||
role: "REQ-PARTICIPANT",
|
||||
cutype: "INDIVIDUAL",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"user3/cal1": {
|
||||
name: "Calendar shared",
|
||||
id: "user3/cal1",
|
||||
color: "#FF0000",
|
||||
ownerEmails: ["alice@example.com"],
|
||||
events: {
|
||||
event1: {
|
||||
id: "event1",
|
||||
calId: "user3/cal1",
|
||||
uid: "event1",
|
||||
title: "Test Event",
|
||||
start: start.toISOString(),
|
||||
end: end.toISOString(),
|
||||
partstat: "ACCEPTED",
|
||||
organizer: {
|
||||
cn: "Alice",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
attendee: [
|
||||
{
|
||||
cn: "Alice",
|
||||
partstat: "ACCEPTED",
|
||||
rsvp: "TRUE",
|
||||
role: "REQ-PARTICIPANT",
|
||||
cutype: "INDIVIDUAL",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pending: false,
|
||||
},
|
||||
};
|
||||
renderWithProviders(<CalendarApp />, preloadedState);
|
||||
expect(screen.getByText("personnalCalendars")).toBeInTheDocument();
|
||||
expect(screen.getByText("delegatedCalendars")).toBeInTheDocument();
|
||||
expect(screen.getByText("sharedCalendars")).toBeInTheDocument();
|
||||
|
||||
expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument();
|
||||
expect(screen.getByLabelText("Calendar delegated")).toBeInTheDocument();
|
||||
expect(screen.getByLabelText("Calendar shared")).toBeInTheDocument();
|
||||
});
|
||||
it("renders only personnal calendars in list", async () => {
|
||||
const preloadedState = {
|
||||
user: {
|
||||
userData: {
|
||||
sub: "test",
|
||||
email: "test@test.com",
|
||||
sid: "mockSid",
|
||||
openpaasId: "user1",
|
||||
},
|
||||
tokens: { accessToken: "token" }, // required to avoid redirect
|
||||
},
|
||||
calendars: {
|
||||
list: {
|
||||
"user1/cal1": {
|
||||
name: "Calendar personnal",
|
||||
id: "user1/cal1",
|
||||
color: "#FF0000",
|
||||
ownerEmails: ["alice@example.com"],
|
||||
events: {
|
||||
event1: {
|
||||
id: "event1",
|
||||
calId: "user1/cal1",
|
||||
uid: "event1",
|
||||
title: "Test Event",
|
||||
start: start.toISOString(),
|
||||
end: end.toISOString(),
|
||||
partstat: "ACCEPTED",
|
||||
organizer: {
|
||||
cn: "Alice",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
attendee: [
|
||||
{
|
||||
cn: "Alice",
|
||||
partstat: "ACCEPTED",
|
||||
rsvp: "TRUE",
|
||||
role: "REQ-PARTICIPANT",
|
||||
cutype: "INDIVIDUAL",
|
||||
cal_address: "alice@example.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pending: false,
|
||||
},
|
||||
};
|
||||
renderWithProviders(<CalendarApp />, preloadedState);
|
||||
expect(screen.getByText("personnalCalendars")).toBeInTheDocument();
|
||||
expect(screen.queryByText("delegatedCalendars")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("sharedCalendars")).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -7,11 +7,18 @@ export default function CalendarSelection({
|
||||
selectedCalendars: string[];
|
||||
setSelectedCalendars: Function;
|
||||
}) {
|
||||
const tokens = useAppSelector((state) => state.user.tokens);
|
||||
const userId = useAppSelector((state) => state.user.userData.openpaasId);
|
||||
const dispatch = useAppDispatch();
|
||||
const calendars = useAppSelector((state) => state.calendars.list);
|
||||
|
||||
const personnalCalendars = Object.keys(calendars).filter(
|
||||
(id) => id.split("/")[0] === userId
|
||||
);
|
||||
const delegatedCalendars = Object.keys(calendars).filter(
|
||||
(id) => id.split("/")[0] !== userId && calendars[id].delegated
|
||||
);
|
||||
const sharedCalendars = Object.keys(calendars).filter(
|
||||
(id) => id.split("/")[0] !== userId && !calendars[id].delegated
|
||||
);
|
||||
const handleCalendarToggle = (name: string) => {
|
||||
setSelectedCalendars((prev: string[]) =>
|
||||
prev.includes(name) ? prev.filter((n) => n !== name) : [...prev, name]
|
||||
@@ -21,27 +28,8 @@ export default function CalendarSelection({
|
||||
return (
|
||||
<div>
|
||||
<h3>personnalCalendars</h3>
|
||||
{Object.keys(calendars)
|
||||
.filter((id) => id.split("/")[0] === userId)
|
||||
.map((id) => {
|
||||
return (
|
||||
<div key={id}>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
style={{ backgroundColor: calendars[id].color }}
|
||||
checked={selectedCalendars.includes(id)}
|
||||
onChange={() => handleCalendarToggle(id)}
|
||||
/>
|
||||
{calendars[id].name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<h3>sharedCalendars</h3>
|
||||
{Object.keys(calendars)
|
||||
.filter((id) => id.split("/")[0] !== userId)
|
||||
.map((id) => (
|
||||
{personnalCalendars.map((id) => {
|
||||
return (
|
||||
<div key={id}>
|
||||
<label>
|
||||
<input
|
||||
@@ -53,7 +41,44 @@ export default function CalendarSelection({
|
||||
{calendars[id].name}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
{delegatedCalendars.length > 0 && (
|
||||
<>
|
||||
<h3>delegatedCalendars</h3>
|
||||
{delegatedCalendars.map((id) => (
|
||||
<div key={id}>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
style={{ backgroundColor: calendars[id].color }}
|
||||
checked={selectedCalendars.includes(id)}
|
||||
onChange={() => handleCalendarToggle(id)}
|
||||
/>
|
||||
{calendars[id].name}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
{sharedCalendars.length > 0 && (
|
||||
<>
|
||||
<h3>sharedCalendars</h3>
|
||||
{sharedCalendars.map((id) => (
|
||||
<div key={id}>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
style={{ backgroundColor: calendars[id].color }}
|
||||
checked={selectedCalendars.includes(id)}
|
||||
onChange={() => handleCalendarToggle(id)}
|
||||
/>
|
||||
{calendars[id].name}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { getOpenPaasUser, getUserDetails } from "../User/userAPI";
|
||||
import { parseCalendarEvent } from "../Events/eventUtils";
|
||||
import { deleteEvent, putEvent } from "../Events/EventApi";
|
||||
import { formatDateToYYYYMMDDTHHMMSS } from "../../utils/dateUtils";
|
||||
import { responsiveFontSizes } from "@mui/material";
|
||||
|
||||
export const getCalendarsListAsync = createAsyncThunk<
|
||||
Record<string, Calendars> // Return type
|
||||
@@ -19,11 +18,17 @@ export const getCalendarsListAsync = createAsyncThunk<
|
||||
for (const cal of rawCalendars) {
|
||||
const name = cal["dav:name"];
|
||||
const description = cal["dav:description"];
|
||||
const id = cal["calendarserver:source"]
|
||||
let delegated = false;
|
||||
let source = cal["calendarserver:source"]
|
||||
? cal["calendarserver:source"]._links.self.href
|
||||
.replace("/calendars/", "")
|
||||
.replace(".json", "")
|
||||
: cal._links.self.href.replace("/calendars/", "").replace(".json", "");
|
||||
: cal._links.self.href;
|
||||
if (cal["calendarserver:delegatedsource"]) {
|
||||
source = cal["calendarserver:delegatedsource"];
|
||||
delegated = true;
|
||||
}
|
||||
console.log(source);
|
||||
const id = source.replace("/calendars/", "").replace(".json", "");
|
||||
|
||||
const ownerData: any = await getUserDetails(id.split("/")[0]);
|
||||
const color = cal["apple:color"];
|
||||
importedCalendars[id] = {
|
||||
@@ -31,6 +36,7 @@ export const getCalendarsListAsync = createAsyncThunk<
|
||||
name,
|
||||
ownerEmails: ownerData.emails,
|
||||
description,
|
||||
delegated,
|
||||
color,
|
||||
events: {},
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { CalendarEvent } from "../Events/EventsTypes";
|
||||
export interface Calendars {
|
||||
id: string;
|
||||
name: string;
|
||||
delegated?: boolean;
|
||||
prodid?: string;
|
||||
color?: string;
|
||||
ownerEmails?: string[];
|
||||
|
||||
Reference in New Issue
Block a user