calendar list display improvments (#115)
* [#60] added collapsible groups * [#60] factorized code and fixed tests * fixup! [#60] added collapsible groups * fixup! [#60] added collapsible groups --------- Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
@@ -123,7 +123,7 @@ describe("CalendarSelection", () => {
|
|||||||
renderWithProviders(<CalendarApp />, preloadedState);
|
renderWithProviders(<CalendarApp />, preloadedState);
|
||||||
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Shared Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Other Calendars")).toBeInTheDocument();
|
||||||
|
|
||||||
expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument();
|
expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText("Calendar delegated")).toBeInTheDocument();
|
expect(screen.getByLabelText("Calendar delegated")).toBeInTheDocument();
|
||||||
@@ -147,4 +147,25 @@ describe("CalendarSelection", () => {
|
|||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("open accordeon when clicking on button only", () => {
|
||||||
|
renderWithProviders(<CalendarApp />, preloadedState);
|
||||||
|
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("Other Calendars")).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByLabelText("Calendar personnal")).toBeInTheDocument();
|
||||||
|
expect(screen.getByLabelText("Calendar delegated")).toBeInTheDocument();
|
||||||
|
expect(screen.getByLabelText("Calendar shared")).toBeInTheDocument();
|
||||||
|
|
||||||
|
const delegatedAccordionSummary = screen
|
||||||
|
.getByText("Delegated Calendars")
|
||||||
|
.closest(".MuiAccordionSummary-root");
|
||||||
|
|
||||||
|
const addButton = screen.getAllByTestId("AddIcon")[1];
|
||||||
|
fireEvent.click(addButton);
|
||||||
|
expect(delegatedAccordionSummary).toHaveAttribute("aria-expanded", "true");
|
||||||
|
|
||||||
|
fireEvent.click(addButton);
|
||||||
|
expect(delegatedAccordionSummary).toHaveAttribute("aria-expanded", "true");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ describe("CalendarSelection", () => {
|
|||||||
|
|
||||||
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Shared Calendars")).toBeInTheDocument();
|
expect(screen.getByText("Other Calendars")).toBeInTheDocument();
|
||||||
|
|
||||||
expect(screen.getByLabelText("Calendar personnal")).toBeChecked();
|
expect(screen.getByLabelText("Calendar personnal")).toBeChecked();
|
||||||
expect(screen.getByLabelText("Calendar delegated")).not.toBeChecked();
|
expect(screen.getByLabelText("Calendar delegated")).not.toBeChecked();
|
||||||
@@ -113,7 +113,7 @@ describe("CalendarSelection", () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const addButton = screen.getByTestId("AddIcon");
|
const addButton = screen.getAllByTestId("AddIcon")[0];
|
||||||
fireEvent.click(addButton);
|
fireEvent.click(addButton);
|
||||||
|
|
||||||
expect(screen.getByRole("presentation")).toBeInTheDocument();
|
expect(screen.getByRole("presentation")).toBeInTheDocument();
|
||||||
|
|||||||
@@ -1,12 +1,78 @@
|
|||||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
import Accordion from "@mui/material/Accordion";
|
||||||
|
import AccordionDetails from "@mui/material/AccordionDetails";
|
||||||
|
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import { useAppSelector } from "../../app/hooks";
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import CalendarPopover from "../../features/Calendars/CalendarModal";
|
import CalendarPopover from "../../features/Calendars/CalendarModal";
|
||||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||||
import MoreVertIcon from "@mui/icons-material/MoreVert";
|
import MoreVertIcon from "@mui/icons-material/MoreVert";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import Checkbox from "@mui/material/Checkbox";
|
import Checkbox from "@mui/material/Checkbox";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
|
||||||
|
function CalendarAccordion({
|
||||||
|
title,
|
||||||
|
calendars,
|
||||||
|
selectedCalendars,
|
||||||
|
handleToggle,
|
||||||
|
showAddButton = false,
|
||||||
|
onAddClick,
|
||||||
|
defaultExpanded = false,
|
||||||
|
setOpen,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
calendars: string[];
|
||||||
|
selectedCalendars: string[];
|
||||||
|
handleToggle: (id: string) => void;
|
||||||
|
showAddButton?: boolean;
|
||||||
|
onAddClick?: Function;
|
||||||
|
defaultExpanded?: boolean;
|
||||||
|
setOpen: Function;
|
||||||
|
}) {
|
||||||
|
const allCalendars = useAppSelector((state) => state.calendars.list);
|
||||||
|
|
||||||
|
if (calendars.length === 0) return null;
|
||||||
|
const [expended, setExpended] = useState(defaultExpanded);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion defaultExpanded={defaultExpanded} expanded={expended}>
|
||||||
|
<AccordionSummary
|
||||||
|
expandIcon={<ExpandMoreIcon />}
|
||||||
|
aria-controls={`${title}-content`}
|
||||||
|
id={`${title}-header`}
|
||||||
|
className="calendarListHeader"
|
||||||
|
onClick={() => setExpended(!expended)}
|
||||||
|
>
|
||||||
|
<Typography component="h3">{title}</Typography>
|
||||||
|
{showAddButton && (
|
||||||
|
<IconButton
|
||||||
|
component="span"
|
||||||
|
onClick={(e) => {
|
||||||
|
expended && e.stopPropagation();
|
||||||
|
onAddClick && onAddClick();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AddIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
{calendars.map((id) =>
|
||||||
|
CalendarSelector(
|
||||||
|
allCalendars,
|
||||||
|
id,
|
||||||
|
selectedCalendars,
|
||||||
|
handleToggle,
|
||||||
|
() => setOpen(id)
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function CalendarSelection({
|
export default function CalendarSelection({
|
||||||
selectedCalendars,
|
selectedCalendars,
|
||||||
@@ -17,6 +83,7 @@ export default function CalendarSelection({
|
|||||||
}) {
|
}) {
|
||||||
const userId = useAppSelector((state) => state.user.userData.openpaasId);
|
const userId = useAppSelector((state) => state.user.userData.openpaasId);
|
||||||
const calendars = useAppSelector((state) => state.calendars.list);
|
const calendars = useAppSelector((state) => state.calendars.list);
|
||||||
|
|
||||||
const personnalCalendars = Object.keys(calendars).filter(
|
const personnalCalendars = Object.keys(calendars).filter(
|
||||||
(id) => id.split("/")[0] === userId
|
(id) => id.split("/")[0] === userId
|
||||||
);
|
);
|
||||||
@@ -26,6 +93,7 @@ export default function CalendarSelection({
|
|||||||
const sharedCalendars = Object.keys(calendars).filter(
|
const sharedCalendars = Object.keys(calendars).filter(
|
||||||
(id) => id.split("/")[0] !== userId && !calendars[id].delegated
|
(id) => id.split("/")[0] !== userId && !calendars[id].delegated
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCalendarToggle = (name: string) => {
|
const handleCalendarToggle = (name: string) => {
|
||||||
setSelectedCalendars((prev: string[]) =>
|
setSelectedCalendars((prev: string[]) =>
|
||||||
prev.includes(name) ? prev.filter((n) => n !== name) : [...prev, name]
|
prev.includes(name) ? prev.filter((n) => n !== name) : [...prev, name]
|
||||||
@@ -37,67 +105,53 @@ export default function CalendarSelection({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<div className="calendarListHeader">
|
<CalendarAccordion
|
||||||
<h3>Personnal Calendars</h3>
|
title="Personnal Calendars"
|
||||||
<Button onClick={() => setAnchorElCal(document.body)}>
|
calendars={personnalCalendars}
|
||||||
<AddIcon />
|
selectedCalendars={selectedCalendars}
|
||||||
</Button>
|
handleToggle={handleCalendarToggle}
|
||||||
</div>
|
showAddButton
|
||||||
{personnalCalendars.map((id) =>
|
onAddClick={() => setAnchorElCal(document.body)}
|
||||||
CalendarSelector(
|
setOpen={(id: string) => {
|
||||||
calendars,
|
setAnchorElCal(document.body);
|
||||||
id,
|
setSelectedCalId(id);
|
||||||
selectedCalendars,
|
}}
|
||||||
handleCalendarToggle,
|
defaultExpanded
|
||||||
() => {
|
/>
|
||||||
setAnchorElCal(document.body);
|
|
||||||
setSelectedCalId(id);
|
<CalendarAccordion
|
||||||
}
|
title="Delegated Calendars"
|
||||||
)
|
calendars={delegatedCalendars}
|
||||||
)}
|
selectedCalendars={selectedCalendars}
|
||||||
{delegatedCalendars.length > 0 && (
|
handleToggle={handleCalendarToggle}
|
||||||
<>
|
defaultExpanded
|
||||||
<span className="calendarListHeader">
|
setOpen={(id: string) => {
|
||||||
<h3>Delegated Calendars</h3>
|
setAnchorElCal(document.body);
|
||||||
</span>
|
setSelectedCalId(id);
|
||||||
{delegatedCalendars.map((id) =>
|
}}
|
||||||
CalendarSelector(
|
/>
|
||||||
calendars,
|
|
||||||
id,
|
<CalendarAccordion
|
||||||
selectedCalendars,
|
title="Other Calendars"
|
||||||
handleCalendarToggle,
|
calendars={sharedCalendars}
|
||||||
() => {
|
selectedCalendars={selectedCalendars}
|
||||||
setAnchorElCal(document.body);
|
showAddButton
|
||||||
setSelectedCalId(id);
|
onAddClick={() => {
|
||||||
}
|
setAnchorElCal(document.body);
|
||||||
)
|
}}
|
||||||
)}
|
handleToggle={handleCalendarToggle}
|
||||||
</>
|
setOpen={(id: string) => {
|
||||||
)}
|
setAnchorElCal(document.body);
|
||||||
{sharedCalendars.length > 0 && (
|
setSelectedCalId(id);
|
||||||
<>
|
}}
|
||||||
<span className="calendarListHeader">
|
/>
|
||||||
<h3>Shared Calendars</h3>
|
|
||||||
</span>
|
|
||||||
{sharedCalendars.map((id) =>
|
|
||||||
CalendarSelector(
|
|
||||||
calendars,
|
|
||||||
id,
|
|
||||||
selectedCalendars,
|
|
||||||
handleCalendarToggle,
|
|
||||||
() => {
|
|
||||||
setAnchorElCal(document.body);
|
|
||||||
setSelectedCalId(id);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CalendarPopover
|
<CalendarPopover
|
||||||
anchorEl={anchorElCal}
|
anchorEl={anchorElCal}
|
||||||
open={Boolean(anchorElCal)}
|
open={Boolean(anchorElCal)}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
|
setSelectedCalId("");
|
||||||
setAnchorElCal(null);
|
setAnchorElCal(null);
|
||||||
}}
|
}}
|
||||||
calendar={calendars[selectedCalId] ?? undefined}
|
calendar={calendars[selectedCalId] ?? undefined}
|
||||||
|
|||||||
Reference in New Issue
Block a user