From 4b71a6e3c714dbe169ab86bb6bf466d9674931ce Mon Sep 17 00:00:00 2001 From: ducdonghiem <40622158+ducdonghiem@users.noreply.github.com> Date: Thu, 11 Sep 2025 14:17:54 +0700 Subject: [PATCH] ISSUE-91 add lock icon indication for private events (#98) --- .../components/EventModifications.test.tsx | 92 ++++++++++++++++++- src/components/Calendar/Calendar.tsx | 7 +- 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/__test__/components/EventModifications.test.tsx b/__test__/components/EventModifications.test.tsx index 8a20947..8b8eda0 100644 --- a/__test__/components/EventModifications.test.tsx +++ b/__test__/components/EventModifications.test.tsx @@ -2,7 +2,7 @@ import { CalendarApi } from "@fullcalendar/core"; import { jest } from "@jest/globals"; import { ThunkDispatch } from "@reduxjs/toolkit"; import "@testing-library/jest-dom"; -import { act, screen } from "@testing-library/react"; +import { act, screen, within } from "@testing-library/react"; import * as appHooks from "../../src/app/hooks"; import CalendarApp from "../../src/components/Calendar/Calendar"; import { renderWithProviders } from "../utils/Renderwithproviders"; @@ -101,4 +101,94 @@ describe("CalendarApp integration", () => { } }); }); + + const createPreloadedState = (eventProps = {}) => ({ + user: { + userData: { + sub: "test", + email: "test@test.com", + sid: "mockSid", + openpaasId: "667037022b752d0026472254", + }, + tokens: { + accessToken: "token" + }, + }, + calendars: { + list: { + "667037022b752d0026472254/cal1": { + name: "Calendar 1", + id: "667037022b752d0026472254/cal1", + color: "#FF0000", + ownerEmails: ["alice@example.com"], + events: { + event1: { + id: "event1", + calId: "667037022b752d0026472254/cal1", + uid: "event1", + start: new Date().toISOString(), + end: new Date(Date.now() + 3600000).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", + }, ], + ...eventProps, + }, + }, + }, + }, + pending: false, + }, + }); + + it("renders lock icon for private events on the calendar", async () => { + const preloadedState = createPreloadedState({ + class: "PRIVATE", + title: "Private Event", + }); + renderWithProviders(, preloadedState); + + const eventEls = screen.getAllByText("Private Event"); + const found = eventEls.some((eventEl) => + within(eventEl.parentElement as HTMLElement).queryByTestId("lock-icon") + ); + expect(found).toBe(true); + }); + + it("renders lock icon for confidential events on the calendar", async () => { + const preloadedState = createPreloadedState({ + class: "CONFIDENTIAL", + title: "Confidential Event", + }); + renderWithProviders(, preloadedState); + + const eventEls = screen.getAllByText("Confidential Event"); + const found = eventEls.some((eventEl) => + within(eventEl.parentElement as HTMLElement).queryByTestId("lock-icon") + ); + expect(found).toBe(true); + }); + + it("does NOT render a lock icon for public events on the calendar", async () => { + const preloadedState = createPreloadedState({ + class: "PUBLIC", + title: "Public Event", + }); + renderWithProviders(, preloadedState); + + const eventEls = screen.getAllByText("Public Event"); + const found = eventEls.some((eventEl) => + within(eventEl.parentElement as HTMLElement).queryByTestId("lock-icon") + ); + expect(found).toBe(false); + }); }); diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx index 5488380..4b8121b 100644 --- a/src/components/Calendar/Calendar.tsx +++ b/src/components/Calendar/Calendar.tsx @@ -31,6 +31,7 @@ import { createSelector } from "@reduxjs/toolkit"; import HelpOutlineIcon from "@mui/icons-material/HelpOutline"; import ClearIcon from "@mui/icons-material/Clear"; import AccessTimeIcon from "@mui/icons-material/AccessTime"; +import LockIcon from '@mui/icons-material/Lock'; import { userAttendee } from "../../features/User/userDataTypes"; const computeStartOfTheWeek = (date: Date): Date => { @@ -407,6 +408,7 @@ export default function CalendarApp() { if (!calendars[arg.event._def.extendedProps.calId]) return; const attendees = event._def.extendedProps.attendee || []; + const isPrivate = event._def.extendedProps.class === "PRIVATE" || event._def.extendedProps.class === "CONFIDENTIAL"; let Icon = null; let titleStyle: React.CSSProperties = {}; const ownerEmails = new Set( @@ -437,8 +439,9 @@ export default function CalendarApp() { } return ( -
- {Icon && } +
+ {isPrivate && } + {Icon && } {event.title}
);