diff --git a/__test__/components/Calendar.test.tsx b/__test__/components/Calendar.test.tsx index 7a59d72..ed3dd23 100644 --- a/__test__/components/Calendar.test.tsx +++ b/__test__/components/Calendar.test.tsx @@ -1,15 +1,14 @@ +import CalendarApp from "@/components/Calendar/Calendar"; +import CalendarLayout from "@/components/Calendar/CalendarLayout"; +import * as calendarDetailThunks from "@/features/Calendars/services"; +import * as servicesModule from "@/features/Calendars/services"; +import { searchUsers } from "@/features/User/userAPI"; import { act, fireEvent, screen, waitFor } from "@testing-library/react"; -import CalendarApp from "../../src/components/Calendar/Calendar"; -import * as eventThunks from "../../src/features/Calendars/CalendarSlice"; -import { renderWithProviders } from "../utils/Renderwithproviders"; -import { searchUsers } from "../../src/features/User/userAPI"; -import * as calendarDetailThunks from "../../src/features/Calendars/services/getCalendarDetailAsync"; - -import { useRef } from "react"; - import userEvent from "@testing-library/user-event"; -import CalendarLayout from "../../src/components/Calendar/CalendarLayout"; -jest.mock("../../src/features/User/userAPI"); +import { useRef } from "react"; +import { renderWithProviders } from "../utils/Renderwithproviders"; + +jest.mock("@/features/User/userAPI"); const mockedSearchUsers = searchUsers as jest.MockedFunction< typeof searchUsers >; @@ -348,7 +347,7 @@ describe("calendar Availability search", () => { it("imports temporary calendars when selecting new users", async () => { const spy = jest - .spyOn(eventThunks, "getTempCalendarsListAsync") + .spyOn(servicesModule, "getTempCalendarsListAsync") .mockImplementation((payload) => { return () => Promise.resolve(payload) as any; }); @@ -389,7 +388,7 @@ describe("calendar Availability search", () => { }, ]); const spy = jest - .spyOn(eventThunks, "getTempCalendarsListAsync") + .spyOn(servicesModule, "getTempCalendarsListAsync") .mockImplementation((payload) => { return () => Promise.resolve(payload) as any; }); @@ -411,7 +410,7 @@ describe("calendar Availability search", () => { it("open window with attendees filled after temp search on create event button click", async () => { const spy = jest - .spyOn(eventThunks, "getTempCalendarsListAsync") + .spyOn(servicesModule, "getTempCalendarsListAsync") .mockImplementation((payload) => { return () => Promise.resolve(payload) as any; }); @@ -455,7 +454,7 @@ describe("calendar Availability search", () => { it("open window with attendees filled after temp search on enter in temp input", async () => { const spy = jest - .spyOn(eventThunks, "getTempCalendarsListAsync") + .spyOn(servicesModule, "getTempCalendarsListAsync") .mockImplementation((payload) => { return () => Promise.resolve(payload) as any; }); @@ -696,10 +695,10 @@ describe("calendar Availability search", () => { ); const selectedCalls = spy.mock.calls.filter( - (call) => call[0].calId === "user1/cal1" + (call: { calId: string }[]) => call[0].calId === "user1/cal1" ); const hiddenCalls = spy.mock.calls.filter( - (call) => + (call: { calId: string }[]) => call[0].calId === "user1/cal2" || call[0].calId === "user1/cal3" ); @@ -729,12 +728,13 @@ describe("calendar Availability search", () => { ); const callsForCal1 = spy.mock.calls.filter( - (call) => call[0].calId === "user1/cal1" + (call: { calId: string }[]) => call[0].calId === "user1/cal1" ); const uniqueRanges = new Set( callsForCal1.map( - (call) => `${call[0].match.start}_${call[0].match.end}` + (call: { match: { end: string; start: string } }[]) => + `${call[0].match.start}_${call[0].match.end}` ) ); diff --git a/__test__/components/CalendarColors.test.tsx b/__test__/components/CalendarColors.test.tsx index 6a44b06..cb5cdc5 100644 --- a/__test__/components/CalendarColors.test.tsx +++ b/__test__/components/CalendarColors.test.tsx @@ -1,13 +1,13 @@ -import { fireEvent, screen, waitFor, act } from "@testing-library/react"; +import CalendarSearch from "@/components/Calendar/CalendarSearch"; +import * as CalendarApi from "@/features/Calendars/CalendarApi"; +import * as CalendarSlice from "@/features/Calendars/services"; +import { searchUsers } from "@/features/User/userAPI"; +import { act, fireEvent, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import CalendarSearch from "../../src/components/Calendar/CalendarSearch"; -import * as CalendarApi from "../../src/features/Calendars/CalendarApi"; -import * as CalendarSlice from "../../src/features/Calendars/CalendarSlice"; -import { searchUsers } from "../../src/features/User/userAPI"; import { renderWithProviders } from "../utils/Renderwithproviders"; -jest.mock("../../src/features/User/userAPI"); -jest.mock("../../src/features/Calendars/CalendarApi"); +jest.mock("@/features/User/userAPI"); +jest.mock("@/features/Calendars/CalendarApi"); const mockedSearchUsers = searchUsers as jest.MockedFunction< typeof searchUsers diff --git a/__test__/components/CalendarSelection.test.tsx b/__test__/components/CalendarSelection.test.tsx index 76516ef..ae1c9c5 100644 --- a/__test__/components/CalendarSelection.test.tsx +++ b/__test__/components/CalendarSelection.test.tsx @@ -1,9 +1,9 @@ -import { screen, fireEvent, waitFor, cleanup } from "@testing-library/react"; +import CalendarSelection from "@/components/Calendar/CalendarSelection"; +import * as calendarThunks from "@/features/Calendars/services"; import "@testing-library/jest-dom"; -import CalendarSelection from "../../src/components/Calendar/CalendarSelection"; -import { renderWithProviders } from "../utils/Renderwithproviders"; -import * as calendarThunks from "../../src/features/Calendars/CalendarSlice"; +import { cleanup, fireEvent, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; +import { renderWithProviders } from "../utils/Renderwithproviders"; describe("CalendarSelection", () => { beforeEach(() => { diff --git a/__test__/components/DateTimeField.test.tsx b/__test__/components/DateTimeField.test.tsx index ac9a8fb..522cfd8 100644 --- a/__test__/components/DateTimeField.test.tsx +++ b/__test__/components/DateTimeField.test.tsx @@ -1,15 +1,15 @@ import { - screen, - fireEvent, - waitFor, + DateTimeFields, + DateTimeFieldsProps, +} from "@/components/Event/components/DateTimeFields"; +import { act, + fireEvent, render, + screen, + waitFor, } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { - DateTimeFieldsProps, - DateTimeFields, -} from "../../src/components/Event/components/DateTimeFields"; jest.mock("twake-i18n", () => ({ useI18n: () => ({ diff --git a/__test__/components/DuplicateEvent.test.tsx b/__test__/components/DuplicateEvent.test.tsx index 8a512b5..f112db5 100644 --- a/__test__/components/DuplicateEvent.test.tsx +++ b/__test__/components/DuplicateEvent.test.tsx @@ -1,8 +1,9 @@ +import { RootState } from "@/app/store"; +import EventDuplication from "@/components/Event/EventDuplicate"; +import EventPreviewModal from "@/features/Events/EventDisplayPreview"; +import EventPopover from "@/features/Events/EventModal"; import { fireEvent, screen, waitFor } from "@testing-library/react"; -import EventDuplication from "../../src/components/Event/EventDuplicate"; -import EventPopover from "../../src/features/Events/EventModal"; import { renderWithProviders } from "../utils/Renderwithproviders"; -import EventPreviewModal from "../../src/features/Events/EventDisplayPreview"; const day = new Date(); const preloadedState = { @@ -58,7 +59,7 @@ const preloadedState = { }, pending: false, }, -}; +} as unknown as RootState; describe("EventDuplication", () => { it("calls onOpenDuplicate when button clicked", () => { @@ -155,7 +156,7 @@ describe("EventDisplayModal", () => { expect( screen.getByDisplayValue( preloadedState.calendars.list["667037022b752d0026472254/cal1"].events - .event1.title + .event1.title as string ) ).toBeInTheDocument(); }); diff --git a/__test__/components/Event/utils/dateTimeHelpers.test.ts b/__test__/components/Event/utils/dateTimeHelpers.test.ts index f6ceb29..d012b1e 100644 --- a/__test__/components/Event/utils/dateTimeHelpers.test.ts +++ b/__test__/components/Event/utils/dateTimeHelpers.test.ts @@ -4,7 +4,7 @@ import { DATETIME_WITH_SECONDS_LENGTH, DATETIME_FORMAT_WITH_SECONDS, DATETIME_FORMAT_WITHOUT_SECONDS, -} from "../../../../src/components/Event/utils/dateTimeHelpers"; +} from "@/components/Event/utils/dateTimeHelpers"; describe("dateTimeHelpers", () => { describe("Constants", () => { diff --git a/__test__/components/EventErrorHandling.test.tsx b/__test__/components/EventErrorHandling.test.tsx index 098e881..95298df 100644 --- a/__test__/components/EventErrorHandling.test.tsx +++ b/__test__/components/EventErrorHandling.test.tsx @@ -1,6 +1,6 @@ +import CalendarLayout from "@/components/Calendar/CalendarLayout"; import { act, fireEvent, screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "../utils/Renderwithproviders"; -import CalendarLayout from "../../src/components/Calendar/CalendarLayout"; describe("Event Error Handling", () => { beforeEach(() => { diff --git a/__test__/components/EventModifications.test.tsx b/__test__/components/EventModifications.test.tsx index f859616..d36bdff 100644 --- a/__test__/components/EventModifications.test.tsx +++ b/__test__/components/EventModifications.test.tsx @@ -1,6 +1,14 @@ +import * as appHooks from "@/app/hooks"; +import { AppDispatch } from "@/app/store"; +import CalendarApp from "@/components/Calendar/Calendar"; +import { + createEventHandlers, + EventHandlersProps, +} from "@/components/Calendar/handlers/eventHandlers"; +import * as eventThunks from "@/features/Calendars/services"; +import EventUpdateModal from "@/features/Events/EventUpdateModal"; import { CalendarApi } from "@fullcalendar/core"; import { jest } from "@jest/globals"; -import { ThunkDispatch } from "@reduxjs/toolkit"; import "@testing-library/jest-dom"; import { act, @@ -9,15 +17,7 @@ import { waitFor, within, } from "@testing-library/react"; -import * as appHooks from "../../src/app/hooks"; -import * as eventThunks from "../../src/features/Calendars/CalendarSlice"; -import CalendarApp from "../../src/components/Calendar/Calendar"; -import EventUpdateModal from "../../src/features/Events/EventUpdateModal"; import { renderWithProviders } from "../utils/Renderwithproviders"; -import { - createEventHandlers, - EventHandlersProps, -} from "../../src/components/Calendar/handlers/eventHandlers"; describe("CalendarApp integration", () => { const today = new Date(); @@ -28,7 +28,7 @@ describe("CalendarApp integration", () => { beforeEach(() => { jest.clearAllMocks(); - const dispatch = jest.fn() as ThunkDispatch; + const dispatch = jest.fn() as AppDispatch; jest.spyOn(appHooks, "useAppDispatch").mockReturnValue(dispatch); }); diff --git a/__test__/components/Menubar.test.tsx b/__test__/components/Menubar.test.tsx index e9e37ff..e95bf60 100644 --- a/__test__/components/Menubar.test.tsx +++ b/__test__/components/Menubar.test.tsx @@ -1,8 +1,8 @@ -import { act, fireEvent, screen, waitFor } from "@testing-library/react"; +import { Menubar } from "@/components/Menubar/Menubar"; +import * as oidcAuth from "@/features/User/oidcAuth"; import "@testing-library/jest-dom"; -import { Menubar } from "../../src/components/Menubar/Menubar"; +import { act, fireEvent, screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "../utils/Renderwithproviders"; -import * as oidcAuth from "../../src/features/User/oidcAuth"; describe("Calendar App Component Display Tests", () => { const preloadedState = { diff --git a/__test__/components/MiniCalendarColor.test.tsx b/__test__/components/MiniCalendarColor.test.tsx index f2e478d..31e031a 100644 --- a/__test__/components/MiniCalendarColor.test.tsx +++ b/__test__/components/MiniCalendarColor.test.tsx @@ -1,15 +1,15 @@ -import { renderWithProviders } from "../utils/Renderwithproviders"; -import { screen } from "@testing-library/react"; +import * as appHooks from "@/app/hooks"; +import { AppDispatch } from "@/app/store"; +import CalendarApp from "@/components/Calendar/Calendar"; import { jest } from "@jest/globals"; -import CalendarApp from "../../src/components/Calendar/Calendar"; -import * as appHooks from "../../src/app/hooks"; -import { ThunkDispatch } from "@reduxjs/toolkit"; +import { screen } from "@testing-library/react"; +import { renderWithProviders } from "../utils/Renderwithproviders"; describe("MiniCalendar", () => { const day = new Date(); beforeEach(() => { jest.clearAllMocks(); - const dispatch = jest.fn() as ThunkDispatch; + const dispatch = jest.fn() as AppDispatch; jest.spyOn(appHooks, "useAppDispatch").mockReturnValue(dispatch); jest.useFakeTimers().clearAllTimers(); }); diff --git a/__test__/components/PeopleSearch.test.tsx b/__test__/components/PeopleSearch.test.tsx index afaf8d8..79463fa 100644 --- a/__test__/components/PeopleSearch.test.tsx +++ b/__test__/components/PeopleSearch.test.tsx @@ -1,13 +1,10 @@ -import { screen, fireEvent, waitFor, act } from "@testing-library/react"; +import { PeopleSearch, User } from "@/components/Attendees/PeopleSearch"; +import { searchUsers } from "@/features/User/userAPI"; +import { act, fireEvent, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { - User, - PeopleSearch, -} from "../../src/components/Attendees/PeopleSearch"; import { renderWithProviders } from "../utils/Renderwithproviders"; -import { searchUsers } from "../../src/features/User/userAPI"; -jest.mock("../../src/features/User/userAPI"); +jest.mock("@/features/User/userAPI"); const mockedSearchUsers = searchUsers as jest.MockedFunction< typeof searchUsers >; diff --git a/__test__/components/RepeatEvent.test.tsx b/__test__/components/RepeatEvent.test.tsx index 299215b..73c2b94 100644 --- a/__test__/components/RepeatEvent.test.tsx +++ b/__test__/components/RepeatEvent.test.tsx @@ -1,13 +1,10 @@ -import { screen, fireEvent, waitFor, act } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import { renderWithProviders } from "../utils/Renderwithproviders"; -import RepeatEvent from "../../src/components/Event/EventRepeat"; -import EventPopover from "../../src/features/Events/EventModal"; -import { RepetitionObject } from "../../src/features/Events/EventsTypes"; +import RepeatEvent from "@/components/Event/EventRepeat"; +import * as eventThunks from "@/features/Calendars/services"; +import EventPopover from "@/features/Events/EventModal"; +import { RepetitionObject } from "@/features/Events/EventsTypes"; import { DateSelectArg } from "@fullcalendar/core"; -import { formatDateToYYYYMMDDTHHMMSS } from "../../src/utils/dateUtils"; -import * as eventThunks from "../../src/features/Calendars/CalendarSlice"; -import * as apiUtils from "../../src/utils/apiUtils"; +import { act, fireEvent, screen, waitFor } from "@testing-library/react"; +import { renderWithProviders } from "../utils/Renderwithproviders"; const baseRepetition: RepetitionObject = { freq: "", diff --git a/__test__/components/ResponsiveDialog.test.tsx b/__test__/components/ResponsiveDialog.test.tsx index c5f8315..14da4ff 100644 --- a/__test__/components/ResponsiveDialog.test.tsx +++ b/__test__/components/ResponsiveDialog.test.tsx @@ -1,8 +1,7 @@ +import { ResponsiveDialog } from "@/components/Dialog"; +import { Button, TextField, TwakeMuiThemeProvider } from "@linagora/twake-mui"; import { fireEvent, render, screen } from "@testing-library/react"; import React from "react"; -import { ResponsiveDialog } from "../../src/components/Dialog"; -import { Button, TextField } from "@linagora/twake-mui"; -import { TwakeMuiThemeProvider } from "@linagora/twake-mui"; describe("ResponsiveDialog", () => { const mockOnClose = jest.fn(); diff --git a/__test__/features/Calendars/CalendarAPI.test.tsx b/__test__/features/Calendars/CalendarAPI.test.tsx index 24e510f..042f60e 100644 --- a/__test__/features/Calendars/CalendarAPI.test.tsx +++ b/__test__/features/Calendars/CalendarAPI.test.tsx @@ -1,5 +1,3 @@ -// __test__/features/calendars/calendarApi.test.ts - import { addSharedCalendar, exportCalendar, @@ -9,12 +7,12 @@ import { postCalendar, proppatchCalendar, removeCalendar, -} from "../../../src/features/Calendars/CalendarApi"; -import { clientConfig } from "../../../src/features/User/oidcAuth"; -import { api } from "../../../src/utils/apiUtils"; +} from "@/features/Calendars/CalendarApi"; +import { clientConfig } from "@/features/User/oidcAuth"; +import { api } from "@/utils/apiUtils"; clientConfig.url = "https://example.com"; -jest.mock("../../../src/utils/apiUtils"); +jest.mock("@/utils/apiUtils"); describe("Calendar API", () => { afterEach(() => { diff --git a/__test__/features/Calendars/CalendarModal.test.tsx b/__test__/features/Calendars/CalendarModal.test.tsx index 8e4518c..330f4ec 100644 --- a/__test__/features/Calendars/CalendarModal.test.tsx +++ b/__test__/features/Calendars/CalendarModal.test.tsx @@ -1,11 +1,11 @@ -import { screen, fireEvent, waitFor } from "@testing-library/react"; -import CalendarPopover from "../../../src/components/Calendar/CalendarModal"; +import CalendarPopover from "@/components/Calendar/CalendarModal"; +import { getSecretLink } from "@/features/Calendars/CalendarApi"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import * as eventThunks from "@/features/Calendars/services"; +import { fireEvent, screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "../../utils/Renderwithproviders"; -import * as eventThunks from "../../../src/features/Calendars/CalendarSlice"; -import { Calendar } from "../../../src/features/Calendars/CalendarTypes"; -import { getSecretLink } from "../../../src/features/Calendars/CalendarApi"; -jest.mock("../../../src/features/Calendars/CalendarApi", () => ({ +jest.mock("@/features/Calendars/CalendarApi", () => ({ getSecretLink: jest.fn(), })); @@ -108,7 +108,7 @@ describe("CalendarPopover (editing mode)", () => { link: "/calendars/user/cal1", name: "Work Calendar", description: "Team meetings", - color: "#33B679", + color: { light: "#33B679" }, owner: "alice", ownerEmails: ["alice@example.com"], visibility: "public", @@ -181,7 +181,7 @@ describe("CalendarPopover (editing mode)", () => { calId: "user1/cal1", calLink: "/calendars/user/cal1", patch: { - color: "#33B679", + color: { light: "#33B679" }, desc: "Team meetings", name: "Updated Calendar", }, @@ -213,7 +213,7 @@ describe("CalendarPopover - Tabs Scenarios", () => { link: "/calendars/user1/cal1.json", name: "Work Calendar", description: "Team meetings", - color: "#33B679", + color: { light: "#33B679" }, owner: "alice", ownerEmails: ["alice@example.com"], visibility: "public", diff --git a/__test__/features/Calendars/CalendarSlice.test.tsx b/__test__/features/Calendars/CalendarSlice.test.tsx index b91cd3a..2ef2aff 100644 --- a/__test__/features/Calendars/CalendarSlice.test.tsx +++ b/__test__/features/Calendars/CalendarSlice.test.tsx @@ -1,37 +1,36 @@ +import * as calAPI from "@/features/Calendars/CalendarApi"; import reducer, { addEvent, - removeEvent, createCalendar, - updateEventLocal, + removeEvent, removeTempCal, - getTempCalendarsListAsync, - putEventAsync, + updateEventLocal, +} from "@/features/Calendars/CalendarSlice"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { + addSharedCalendarAsync, + createCalendarAsync, + deleteEventAsync, + getCalendarDetailAsync, + getCalendarsListAsync, getEventAsync, - patchCalendarAsync, - removeCalendarAsync, + getTempCalendarsListAsync, moveEventAsync, patchACLCalendarAsync, - createCalendarAsync, - addSharedCalendarAsync, - deleteEventAsync, -} from "../../../src/features/Calendars/CalendarSlice"; -import { getCalendarsListAsync } from "../../../src/features/Calendars/services/getCalendarsListAsync"; -import { getCalendarDetailAsync } from "../../../src/features/Calendars/services/getCalendarDetailAsync"; - -import * as calAPI from "../../../src/features/Calendars/CalendarApi"; -import * as userAPI from "../../../src/features/User/userAPI"; - + patchCalendarAsync, + putEventAsync, + removeCalendarAsync, +} from "@/features/Calendars/services"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import * as userAPI from "@/features/User/userAPI"; +import userReducer, { setUserData } from "@/features/User/userSlice"; import { configureStore } from "@reduxjs/toolkit"; -import { Calendar } from "../../../src/features/Calendars/CalendarTypes"; -import { CalendarEvent } from "../../../src/features/Events/EventsTypes"; -import { setUserData } from "../../../src/features/User/userSlice"; -import userReducer from "../../../src/features/User/userSlice"; -jest.mock("../../../src/features/Calendars/CalendarApi"); -jest.mock("../../../src/features/User/userAPI"); -jest.mock("../../../src/features/Events/EventApi"); -jest.mock("../../../src/features/Events/eventUtils"); -jest.mock("../../../src/utils/apiUtils"); +jest.mock("@/features/Calendars/CalendarApi"); +jest.mock("@/features/User/userAPI"); +jest.mock("@/features/Events/EventApi"); +jest.mock("@/features/Events/eventUtils"); +jest.mock("@/utils/apiUtils"); describe("CalendarSlice", () => { const initialState = { diff --git a/__test__/features/Calendars/TimezoneInGrid.test.tsx b/__test__/features/Calendars/TimezoneInGrid.test.tsx index a3d0ab3..7ee0da6 100644 --- a/__test__/features/Calendars/TimezoneInGrid.test.tsx +++ b/__test__/features/Calendars/TimezoneInGrid.test.tsx @@ -1,10 +1,10 @@ +import CalendarApp from "@/components/Calendar/Calendar"; +import * as calendarUtils from "@/components/Calendar/utils/calendarUtils"; +import { updateSlotLabelVisibility } from "@/components/Calendar/utils/calendarUtils"; +import EventPreviewModal from "@/features/Events/EventDisplayPreview"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import * as SettingsSlice from "@/features/Settings/SettingsSlice"; import { fireEvent, screen, waitFor } from "@testing-library/react"; -import CalendarApp from "../../../src/components/Calendar/Calendar"; -import { updateSlotLabelVisibility } from "../../../src/components/Calendar/utils/calendarUtils"; -import EventPreviewModal from "../../../src/features/Events/EventDisplayPreview"; -import * as SettingsSlice from "../../../src/features/Settings/SettingsSlice"; -import * as calendarUtils from "../../../src/components/Calendar/utils/calendarUtils"; -import { CalendarEvent } from "../../../src/features/Events/EventsTypes"; import { renderWithProviders } from "../../utils/Renderwithproviders"; describe("Calendar - Timezone Integration", () => { @@ -199,7 +199,6 @@ describe("EventDisplayPreview - Timezone Display", () => { onClose={mockOnClose} eventId="allDayEvent" calId="user1/cal1" - event={allDayEvent} />, baseState ); @@ -236,7 +235,6 @@ describe("EventDisplayPreview - Timezone Display", () => { eventId="event1" calId="user1/cal1" onClose={mockOnClose} - event={baseEvent} />, state ); diff --git a/__test__/features/Calendars/TimezoneSelector.test.tsx b/__test__/features/Calendars/TimezoneSelector.test.tsx index 0036a17..5ef5ac0 100644 --- a/__test__/features/Calendars/TimezoneSelector.test.tsx +++ b/__test__/features/Calendars/TimezoneSelector.test.tsx @@ -1,5 +1,5 @@ -import { screen, fireEvent, waitFor, cleanup } from "@testing-library/react"; -import { TimezoneSelector } from "../../../src/components/Calendar/TimezoneSelector"; +import { TimezoneSelector } from "@/components/Calendar/TimezoneSelector"; +import { cleanup, fireEvent, screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "../../utils/Renderwithproviders"; describe("TimezoneSelector", () => { diff --git a/__test__/features/Calendars/services/refreshCalendar.test.tsx b/__test__/features/Calendars/services/refreshCalendar.test.tsx index f2ee9a2..9ea8d60 100644 --- a/__test__/features/Calendars/services/refreshCalendar.test.tsx +++ b/__test__/features/Calendars/services/refreshCalendar.test.tsx @@ -1,16 +1,16 @@ -import { configureStore } from "@reduxjs/toolkit"; -import reducer from "../../../../src/features/Calendars/CalendarSlice"; +import * as fetchSyncTokenChanges from "@/features/Calendars/api/fetchSyncTokenChanges"; +import reducer from "@/features/Calendars/CalendarSlice"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; import { refreshCalendarWithSyncToken, SyncTokenUpdates, -} from "../../../../src/features/Calendars/services/refreshCalendar"; -import { Calendar } from "../../../../src/features/Calendars/CalendarTypes"; -import { CalendarEvent } from "../../../../src/features/Events/EventsTypes"; -import * as fetchSyncTokenChanges from "../../../../src/features/Calendars/api/fetchSyncTokenChanges"; -import * as EventApi from "../../../../src/features/Events/EventApi"; +} from "@/features/Calendars/services/refreshCalendar"; +import * as EventApi from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { configureStore } from "@reduxjs/toolkit"; -jest.mock("../../../../src/features/Calendars/api/fetchSyncTokenChanges"); -jest.mock("../../../../src/features/Events/EventApi"); +jest.mock("@/features/Calendars/api/fetchSyncTokenChanges"); +jest.mock("@/features/Events/EventApi"); describe("refreshCalendarWithSyncToken", () => { const mockCalendar: Calendar = { diff --git a/__test__/features/Error/ErrorHandler.test.tsx b/__test__/features/Error/ErrorHandler.test.tsx index a87fdb3..d6c19c3 100644 --- a/__test__/features/Error/ErrorHandler.test.tsx +++ b/__test__/features/Error/ErrorHandler.test.tsx @@ -1,4 +1,4 @@ -import { EventErrorHandler } from "../../../src/components/Error/EventErrorHandler"; +import { EventErrorHandler } from "@/components/Error/EventErrorHandler"; describe("EventErrorHandler", () => { it("calls the callback when a new error is reported", () => { diff --git a/__test__/features/Events/EventApi.test.tsx b/__test__/features/Events/EventApi.test.tsx index 97689cc..3eb11a8 100644 --- a/__test__/features/Events/EventApi.test.tsx +++ b/__test__/features/Events/EventApi.test.tsx @@ -1,17 +1,18 @@ import { - putEvent, - moveEvent, deleteEvent, importEventFromFile, + moveEvent, + putEvent, searchEvent, -} from "../../../src/features/Events/EventApi"; -import { CalendarEvent } from "../../../src/features/Events/EventsTypes"; -import { calendarEventToJCal } from "../../../src/features/Events/eventUtils"; -import { clientConfig } from "../../../src/features/User/oidcAuth"; -import { api } from "../../../src/utils/apiUtils"; +} from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { calendarEventToJCal } from "@/features/Events/eventUtils"; +import { clientConfig } from "@/features/User/oidcAuth"; +import { api } from "@/utils/apiUtils"; + clientConfig.url = "https://example.com"; -jest.mock("../../../src/utils/apiUtils"); +jest.mock("@/utils/apiUtils"); const day = new Date(); diff --git a/__test__/features/Events/EventDisplay.test.tsx b/__test__/features/Events/EventDisplay.test.tsx index 738d7a2..c3f4648 100644 --- a/__test__/features/Events/EventDisplay.test.tsx +++ b/__test__/features/Events/EventDisplay.test.tsx @@ -1,23 +1,24 @@ +import * as appHooks from "@/app/hooks"; +import { AppDispatch } from "@/app/store"; +import { InfoRow } from "@/components/Event/InfoRow"; +import { LONG_DATE_FORMAT } from "@/components/Event/utils/dateTimeFormatters"; +import { + stringAvatar, + stringToColor, +} from "@/components/Event/utils/eventUtils"; +import * as calendarSlice from "@/features/Calendars/CalendarSlice"; +import * as eventThunks from "@/features/Calendars/services"; +import EventPreviewModal from "@/features/Events/EventDisplayPreview"; +import EventUpdateModal from "@/features/Events/EventUpdateModal"; import { - screen, - fireEvent, - waitFor, act, cleanup, + fireEvent, + screen, + waitFor, } from "@testing-library/react"; -import * as eventThunks from "../../../src/features/Calendars/CalendarSlice"; -import { renderWithProviders } from "../../utils/Renderwithproviders"; -import EventUpdateModal from "../../../src/features/Events/EventUpdateModal"; -import EventPreviewModal from "../../../src/features/Events/EventDisplayPreview"; -import { InfoRow } from "../../../src/components/Event/InfoRow"; -import { - stringToColor, - stringAvatar, -} from "../../../src/components/Event/utils/eventUtils"; -import * as appHooks from "../../../src/app/hooks"; -import { ThunkDispatch } from "@reduxjs/toolkit"; import dayjs from "dayjs"; -import { LONG_DATE_FORMAT } from "../../../src/components/Event/utils/dateTimeFormatters"; +import { renderWithProviders } from "../../utils/Renderwithproviders"; describe("Event Preview Display", () => { const mockOnClose = jest.fn(); @@ -747,7 +748,7 @@ describe("Event Preview Display", () => { beforeEach(() => { jest.clearAllMocks(); - const dispatch = jest.fn() as ThunkDispatch; + const dispatch = jest.fn() as AppDispatch; jest.spyOn(appHooks, "useAppDispatch").mockReturnValue(dispatch); }); @@ -1831,7 +1832,7 @@ describe("Event Full Display", () => { (promise as any).unwrap = () => promise; return () => promise as any; }); - const spyRemove = jest.spyOn(eventThunks, "removeEvent"); + const spyRemove = jest.spyOn(calendarSlice, "removeEvent"); const testDate = new Date("2025-01-15T10:00:00.000Z"); const testEndDate = new Date("2025-01-15T11:00:00.000Z"); diff --git a/__test__/features/Events/EventModal.test.tsx b/__test__/features/Events/EventModal.test.tsx index 275a0a0..8ae1037 100644 --- a/__test__/features/Events/EventModal.test.tsx +++ b/__test__/features/Events/EventModal.test.tsx @@ -1,12 +1,12 @@ +import * as eventThunks from "@/features/Calendars/services"; +import EventPopover from "@/features/Events/EventModal"; +import { api } from "@/utils/apiUtils"; import { DateSelectArg } from "@fullcalendar/core"; import { act, fireEvent, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import * as eventThunks from "../../../src/features/Calendars/CalendarSlice"; -import EventPopover from "../../../src/features/Events/EventModal"; -import { api } from "../../../src/utils/apiUtils"; import { renderWithProviders } from "../../utils/Renderwithproviders"; -jest.mock("../../../src/utils/apiUtils"); +jest.mock("@/utils/apiUtils"); describe("EventPopover", () => { beforeEach(() => { diff --git a/__test__/features/Events/EventRepetition.test.tsx b/__test__/features/Events/EventRepetition.test.tsx index a9f6cef..389c1b8 100644 --- a/__test__/features/Events/EventRepetition.test.tsx +++ b/__test__/features/Events/EventRepetition.test.tsx @@ -1,26 +1,25 @@ -import { screen, fireEvent, waitFor, act } from "@testing-library/react"; -import * as eventThunks from "../../../src/features/Calendars/CalendarSlice"; -import { renderWithProviders } from "../../utils/Renderwithproviders"; -import EventUpdateModal from "../../../src/features/Events/EventUpdateModal"; -import { EditModeDialog } from "../../../src/components/Event/EditModeDialog"; -import * as EventApi from "../../../src/features/Events/EventApi"; +import { RootState } from "@/app/store"; import { createEventHandlers, EventHandlersProps, -} from "../../../src/components/Calendar/handlers/eventHandlers"; -import EventPreviewModal from "../../../src/features/Events/EventDisplayPreview"; +} from "@/components/Calendar/handlers/eventHandlers"; +import { EditModeDialog } from "@/components/Event/EditModeDialog"; +import * as eventThunks from "@/features/Calendars/services"; +import * as EventApi from "@/features/Events/EventApi"; +import EventPreviewModal from "@/features/Events/EventDisplayPreview"; +import EventUpdateModal from "@/features/Events/EventUpdateModal"; +import { act, fireEvent, screen, waitFor } from "@testing-library/react"; +import preview from "jest-preview"; +import { renderWithProviders } from "../../utils/Renderwithproviders"; -jest.mock("../../../src/components/Event/utils/eventUtils", () => { - const actual = jest.requireActual( - "../../../src/components/Event/utils/eventUtils" - ); +jest.mock("@/components/Event/utils/eventUtils", () => { + const actual = jest.requireActual("@/components/Event/utils/eventUtils"); return { ...actual, refreshCalendars: jest.fn(() => Promise.resolve()), refreshSingularCalendar: jest.fn(() => Promise.resolve()), }; }); -import preview from "jest-preview"; const mockOnClose = jest.fn(); const day = new Date("2025-03-15T10:00:00Z"); @@ -102,7 +101,7 @@ const basePreloadedState = { pending: false, templist: {}, }, -}; +} as unknown as RootState; describe("EditModeDialog Component", () => { beforeEach(() => { @@ -946,7 +945,7 @@ describe("handleRSVP function", () => { const { handleRSVP, - } = require("../../../src/components/Event/eventHandlers/eventHandlers"); + } = require("@/components/Event/eventHandlers/eventHandlers"); jest.spyOn(eventThunks, "putEventAsync").mockImplementation((payload) => { const promise = Promise.resolve(payload); @@ -992,7 +991,7 @@ describe("handleDelete function", () => { const { handleDelete, - } = require("../../../src/components/Event/eventHandlers/eventHandlers"); + } = require("@/components/Event/eventHandlers/eventHandlers"); jest .spyOn(eventThunks, "deleteEventAsync") @@ -1028,7 +1027,7 @@ describe("handleDelete function", () => { const { handleDelete, - } = require("../../../src/components/Event/eventHandlers/eventHandlers"); + } = require("@/components/Event/eventHandlers/eventHandlers"); jest .spyOn(eventThunks, "deleteEventInstanceAsync") @@ -1059,7 +1058,7 @@ describe("handleDelete function", () => { const { handleDelete, - } = require("../../../src/components/Event/eventHandlers/eventHandlers"); + } = require("@/components/Event/eventHandlers/eventHandlers"); jest .spyOn(eventThunks, "deleteEventAsync") diff --git a/__test__/features/Events/EventUpdateModal.test.tsx b/__test__/features/Events/EventUpdateModal.test.tsx index 0229604..a11d738 100644 --- a/__test__/features/Events/EventUpdateModal.test.tsx +++ b/__test__/features/Events/EventUpdateModal.test.tsx @@ -1,12 +1,12 @@ -import { screen, fireEvent, waitFor, act } from "@testing-library/react"; +import * as eventUtils from "@/components/Event/utils/eventUtils"; +import * as CalendarApi from "@/features/Calendars/CalendarApi"; +import * as EventApi from "@/features/Events/EventApi"; +import EventUpdateModal from "@/features/Events/EventUpdateModal"; +import { act, fireEvent, screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "../../utils/Renderwithproviders"; -import EventUpdateModal from "../../../src/features/Events/EventUpdateModal"; -import * as EventApi from "../../../src/features/Events/EventApi"; -import * as CalendarApi from "../../../src/features/Calendars/CalendarApi"; -import * as eventUtils from "../../../src/components/Event/utils/eventUtils"; -jest.mock("../../../src/features/Events/EventApi"); -jest.mock("../../../src/features/Calendars/CalendarApi"); +jest.mock("@/features/Events/EventApi"); +jest.mock("@/features/Calendars/CalendarApi"); describe("EventUpdateModal Timezone Handling", () => { const mockOnClose = jest.fn(); diff --git a/__test__/features/Events/ImportAlert.test.tsx b/__test__/features/Events/ImportAlert.test.tsx index 17c7422..b7f3fca 100644 --- a/__test__/features/Events/ImportAlert.test.tsx +++ b/__test__/features/Events/ImportAlert.test.tsx @@ -1,7 +1,6 @@ -import { screen, fireEvent } from "@testing-library/react"; +import ImportAlert from "@/features/Events/ImportAlert"; +import { fireEvent, screen } from "@testing-library/react"; import { renderWithProviders } from "../../utils/Renderwithproviders"; -import ImportAlert from "../../../src/features/Events/ImportAlert"; -import { clearError } from "../../../src/features/Calendars/CalendarSlice"; // Mock the ErrorSnackbar component since we want to test ImportAlert logic, // but we can also test integration if we don't mock it. diff --git a/__test__/features/Events/TempUpdate.test.tsx b/__test__/features/Events/TempUpdate.test.tsx index f1b0094..39bb39f 100644 --- a/__test__/features/Events/TempUpdate.test.tsx +++ b/__test__/features/Events/TempUpdate.test.tsx @@ -1,21 +1,22 @@ +import * as appHooks from "@/app/hooks"; +import CalendarLayout from "@/components/Calendar/CalendarLayout"; +import * as calendarUtils from "@/components/Calendar/utils/calendarUtils"; +import * as eventUtils from "@/components/Event/utils/eventUtils"; +import * as CalendarSlice from "@/features/Calendars/CalendarSlice"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import * as eventThunks from "@/features/Calendars/services"; +import EventPreviewModal from "@/features/Events/EventDisplayPreview"; +import EventPopover from "@/features/Events/EventModal"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import EventUpdateModal from "@/features/Events/EventUpdateModal"; +import * as userApi from "@/features/User/userAPI"; +import { DateSelectArg } from "@fullcalendar/core"; import { jest } from "@jest/globals"; import { ThunkDispatch } from "@reduxjs/toolkit"; import "@testing-library/jest-dom"; -import { screen, waitFor, fireEvent, act } from "@testing-library/react"; -import * as appHooks from "../../../src/app/hooks"; -import * as eventUtils from "../../../src/components/Event/utils/eventUtils"; -import * as userApi from "../../../src/features/User/userAPI"; -import * as calendarUtils from "../../../src/components/Calendar/utils/calendarUtils"; -import * as eventThunks from "../../../src/features/Calendars/CalendarSlice"; -import EventPreviewModal from "../../../src/features/Events/EventDisplayPreview"; -import EventPopover from "../../../src/features/Events/EventModal"; -import EventUpdateModal from "../../../src/features/Events/EventUpdateModal"; -import CalendarLayout from "../../../src/components/Calendar/CalendarLayout"; -import { renderWithProviders } from "../../utils/Renderwithproviders"; +import { act, fireEvent, screen, waitFor } from "@testing-library/react"; import { SpiedFunction } from "jest-mock"; -import { Calendar } from "../../../src/features/Calendars/CalendarTypes"; -import { CalendarEvent } from "../../../src/features/Events/EventsTypes"; -import { DateSelectArg } from "@fullcalendar/core"; +import { renderWithProviders } from "../../utils/Renderwithproviders"; describe("Update tempcalendars called with correct params", () => { const today = new Date(); @@ -612,7 +613,7 @@ describe("Update tempcalendars called with correct params", () => { }); it("should call emptyEventsCal with correct params before refreshing", async () => { - const emptyEventsCalSpy = jest.spyOn(eventThunks, "emptyEventsCal"); + const emptyEventsCalSpy = jest.spyOn(CalendarSlice, "emptyEventsCal"); const preloadedState = createPreloadedState(true); diff --git a/__test__/features/Events/eventUtils.test.ts b/__test__/features/Events/eventUtils.test.ts index 492e869..1240e88 100644 --- a/__test__/features/Events/eventUtils.test.ts +++ b/__test__/features/Events/eventUtils.test.ts @@ -1,16 +1,12 @@ -import { - CalendarEvent, - RepetitionObject, -} from "../../../src/features/Events/EventsTypes"; +import { CalendarEvent, RepetitionObject } from "@/features/Events/EventsTypes"; import { calendarEventToJCal, - parseCalendarEvent, combineMasterDateWithFormTime, + detectRecurringEventChanges, normalizeRepetition, normalizeTimezone, - detectRecurringEventChanges, -} from "../../../src/features/Events/eventUtils"; -import { TIMEZONES } from "../../../src/utils/timezone-data"; + parseCalendarEvent, +} from "@/features/Events/eventUtils"; describe("parseCalendarEvent", () => { const baseColor = { light: "#00FF00" }; diff --git a/__test__/features/Search/EventSearchBar.test.tsx b/__test__/features/Search/EventSearchBar.test.tsx index e6d9c06..444a855 100644 --- a/__test__/features/Search/EventSearchBar.test.tsx +++ b/__test__/features/Search/EventSearchBar.test.tsx @@ -1,8 +1,8 @@ +import SearchBar from "@/components/Menubar/EventSearchBar"; +import * as searchThunk from "@/features/Search/SearchSlice"; import { fireEvent, screen, waitFor } from "@testing-library/react"; -import SearchBar from "../../../src/components/Menubar/EventSearchBar"; -import { renderWithProviders } from "../../utils/Renderwithproviders"; -import * as searchThunk from "../../../src/features/Search/SearchSlice"; import userEvent from "@testing-library/user-event"; +import { renderWithProviders } from "../../utils/Renderwithproviders"; describe("EventSearchBar", () => { const today = new Date(); diff --git a/__test__/features/Search/SearchResultsPage.test.tsx b/__test__/features/Search/SearchResultsPage.test.tsx index 6eefce2..bb8e8bf 100644 --- a/__test__/features/Search/SearchResultsPage.test.tsx +++ b/__test__/features/Search/SearchResultsPage.test.tsx @@ -1,5 +1,5 @@ +import SearchResultsPage from "@/features/Search/SearchResultsPage"; import { screen } from "@testing-library/react"; -import SearchResultsPage from "../../../src/features/Search/SearchResultsPage"; import { renderWithProviders } from "../../utils/Renderwithproviders"; describe("SearchResultsPage", () => { diff --git a/__test__/features/Search/SearchSlice.test.tsx b/__test__/features/Search/SearchSlice.test.tsx index 8a08f7e..9fc5438 100644 --- a/__test__/features/Search/SearchSlice.test.tsx +++ b/__test__/features/Search/SearchSlice.test.tsx @@ -1,13 +1,12 @@ -// SearchSlice.test.ts -import { configureStore } from "@reduxjs/toolkit"; +import * as EventApi from "@/features/Events/EventApi"; import searchResultReducer, { searchEventsAsync, - setResults, setHits, -} from "../../../src/features/Search/SearchSlice"; -import * as EventApi from "../../../src/features/Events/EventApi"; + setResults, +} from "@/features/Search/SearchSlice"; +import { configureStore } from "@reduxjs/toolkit"; -jest.mock("../../../src/features/Events/EventApi"); +jest.mock("@/features/Events/EventApi"); describe("SearchSlice", () => { let store: any; diff --git a/__test__/features/Settings/SettingUserSync.test.tsx b/__test__/features/Settings/SettingUserSync.test.tsx index 5a68ef8..789f232 100644 --- a/__test__/features/Settings/SettingUserSync.test.tsx +++ b/__test__/features/Settings/SettingUserSync.test.tsx @@ -1,19 +1,19 @@ -import { configureStore } from "@reduxjs/toolkit"; -import { fireEvent, screen, waitFor } from "@testing-library/react"; -import SettingsPage from "../../../src/features/Settings/SettingsPage"; +import SettingsPage from "@/features/Settings/SettingsPage"; import settingsReducer, { setIsBrowserDefaultTimeZone, setTimeZone, -} from "../../../src/features/Settings/SettingsSlice"; +} from "@/features/Settings/SettingsSlice"; import userReducer, { getOpenPaasUserDataAsync, setTimezone as setUserTimeZone, -} from "../../../src/features/User/userSlice"; -import { api } from "../../../src/utils/apiUtils"; -import { browserDefaultTimeZone } from "../../../src/utils/timezone"; +} from "@/features/User/userSlice"; +import { api } from "@/utils/apiUtils"; +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { configureStore } from "@reduxjs/toolkit"; +import { fireEvent, screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "../../utils/Renderwithproviders"; -jest.mock("../../../src/utils/apiUtils"); +jest.mock("@/utils/apiUtils"); describe("Timezone synchronization after getOpenPaasUserDataAsync", () => { let apiGetSpy: jest.SpyInstance; diff --git a/__test__/features/Settings/SettingsPage.test.tsx b/__test__/features/Settings/SettingsPage.test.tsx index db85826..cff4514 100644 --- a/__test__/features/Settings/SettingsPage.test.tsx +++ b/__test__/features/Settings/SettingsPage.test.tsx @@ -1,10 +1,10 @@ -import { fireEvent, screen, waitFor } from "@testing-library/react"; +import SettingsPage from "@/features/Settings/SettingsPage"; +import { api } from "@/utils/apiUtils"; import "@testing-library/jest-dom"; -import SettingsPage from "../../../src/features/Settings/SettingsPage"; +import { fireEvent, screen, waitFor } from "@testing-library/react"; import { renderWithProviders } from "../../utils/Renderwithproviders"; -import { api } from "../../../src/utils/apiUtils"; -jest.mock("../../../src/utils/apiUtils"); +jest.mock("@/utils/apiUtils"); describe("SettingsPage", () => { beforeEach(() => { diff --git a/__test__/features/user/HandleLogin.test.tsx b/__test__/features/user/HandleLogin.test.tsx index 6cc1717..9a3e2fa 100644 --- a/__test__/features/user/HandleLogin.test.tsx +++ b/__test__/features/user/HandleLogin.test.tsx @@ -1,12 +1,12 @@ +import * as appHooks from "@/app/hooks"; +import { AppDispatch } from "@/app/store"; +import HandleLogin from "@/features/User/HandleLogin"; +import * as oidcAuth from "@/features/User/oidcAuth"; +import { clientConfig } from "@/features/User/oidcAuth"; +import * as apiUtils from "@/utils/apiUtils"; import { screen, waitFor } from "@testing-library/react"; -import thunk, { ThunkDispatch } from "redux-thunk"; -import HandleLogin from "../../../src/features/User/HandleLogin"; -import * as oidcAuth from "../../../src/features/User/oidcAuth"; -import { renderWithProviders } from "../../utils/Renderwithproviders"; -import { clientConfig } from "../../../src/features/User/oidcAuth"; -import * as apiUtils from "../../../src/utils/apiUtils"; -import * as appHooks from "../../../src/app/hooks"; import { push } from "redux-first-history"; +import { renderWithProviders } from "../../utils/Renderwithproviders"; clientConfig.url = "https://example.com"; @@ -14,7 +14,7 @@ describe("HandleLogin", () => { beforeEach(() => { jest.clearAllMocks(); jest.spyOn(apiUtils, "redirectTo").mockImplementation(() => {}); - const dispatch = jest.fn() as ThunkDispatch; + const dispatch = jest.fn() as AppDispatch; jest.spyOn(appHooks, "useAppDispatch").mockReturnValue(dispatch); sessionStorage.clear(); }); diff --git a/__test__/features/user/LoginCallback.test.tsx b/__test__/features/user/LoginCallback.test.tsx index 22980ea..b3037d7 100644 --- a/__test__/features/user/LoginCallback.test.tsx +++ b/__test__/features/user/LoginCallback.test.tsx @@ -1,28 +1,27 @@ -// __test__/features/user/CallbackResume.test.tsx -import { render, waitFor } from "@testing-library/react"; -import { CallbackResume } from "../../../src/features/User/LoginCallback"; -import { useAppDispatch } from "../../../src/app/hooks"; -import * as oidcAuth from "../../../src/features/User/oidcAuth"; -import { push } from "redux-first-history"; +import { useAppDispatch } from "@/app/hooks"; +import { getCalendarsListAsync } from "@/features/Calendars/services/getCalendarsListAsync"; +import { CallbackResume } from "@/features/User/LoginCallback"; +import * as oidcAuth from "@/features/User/oidcAuth"; import { + getOpenPaasUserDataAsync, setTokens, setUserData, - getOpenPaasUserDataAsync, -} from "../../../src/features/User/userSlice"; -import { getCalendarsListAsync } from "../../../src/features/Calendars/services/getCalendarsListAsync"; +} from "@/features/User/userSlice"; +import { render, waitFor } from "@testing-library/react"; +import { push } from "redux-first-history"; import { renderWithProviders } from "../../utils/Renderwithproviders"; // Mocks -jest.mock("../../../src/app/hooks", () => ({ +jest.mock("@/app/hooks", () => ({ useAppDispatch: jest.fn(), useAppSelector: jest.fn(() => ({})), })); -jest.mock("../../../src/features/User/oidcAuth", () => ({ +jest.mock("@/features/User/oidcAuth", () => ({ Callback: jest.fn(), })); -jest.mock("../../../src/features/User/userSlice", () => { +jest.mock("@/features/User/userSlice", () => { const mockGetUser = Object.assign( jest.fn(() => ({ type: "GET_USER_ID" })), { @@ -39,23 +38,20 @@ jest.mock("../../../src/features/User/userSlice", () => { }; }); -jest.mock( - "../../../src/features/Calendars/services/getCalendarsListAsync", - () => { - const mockGetCalendars = Object.assign( - jest.fn(() => ({ type: "GET_CALENDARS" })), - { - pending: { type: "GET_CALENDARS/pending" }, - fulfilled: { type: "GET_CALENDARS/fulfilled" }, - rejected: { type: "GET_CALENDARS/rejected" }, - } - ); +jest.mock("@/features/Calendars/services/getCalendarsListAsync", () => { + const mockGetCalendars = Object.assign( + jest.fn(() => ({ type: "GET_CALENDARS" })), + { + pending: { type: "GET_CALENDARS/pending" }, + fulfilled: { type: "GET_CALENDARS/fulfilled" }, + rejected: { type: "GET_CALENDARS/rejected" }, + } + ); - return { - getCalendarsListAsync: mockGetCalendars, - }; - } -); + return { + getCalendarsListAsync: mockGetCalendars, + }; +}); describe("CallbackResume", () => { const dispatch = jest.fn(); diff --git a/__test__/features/user/oidcAuth.test.tsx b/__test__/features/user/oidcAuth.test.tsx index 5fe921a..4a91461 100644 --- a/__test__/features/user/oidcAuth.test.tsx +++ b/__test__/features/user/oidcAuth.test.tsx @@ -1,13 +1,13 @@ // __tests__/auth.test.ts -import * as client from "openid-client"; import { + Auth, + Callback, clientConfig, getClientConfig, - Auth, Logout, - Callback, -} from "../../../src/features/User/oidcAuth"; -import * as apiUtils from "../../../src/utils/apiUtils"; +} from "@/features/User/oidcAuth"; +import * as apiUtils from "@/utils/apiUtils"; +import * as client from "openid-client"; clientConfig.url = "https://example.com"; const localAdress = "https://local.exemple.com"; diff --git a/__test__/features/user/userAPI.test.tsx b/__test__/features/user/userAPI.test.tsx index 80e2146..edf56d8 100644 --- a/__test__/features/user/userAPI.test.tsx +++ b/__test__/features/user/userAPI.test.tsx @@ -1,11 +1,11 @@ -import { clientConfig } from "../../../src/features/User/oidcAuth"; +import { clientConfig } from "@/features/User/oidcAuth"; import { getOpenPaasUser, updateUserConfigurations, -} from "../../../src/features/User/userAPI"; -import { api } from "../../../src/utils/apiUtils"; +} from "@/features/User/userAPI"; +import { api } from "@/utils/apiUtils"; -jest.mock("../../../src/utils/apiUtils"); +jest.mock("@/utils/apiUtils"); clientConfig.url = "https://example.com"; diff --git a/__test__/features/websocket/WebSocketGate.test.tsx b/__test__/features/websocket/WebSocketGate.test.tsx index 7b796a5..b14fd98 100644 --- a/__test__/features/websocket/WebSocketGate.test.tsx +++ b/__test__/features/websocket/WebSocketGate.test.tsx @@ -1,11 +1,11 @@ -import { cleanup, render, waitFor, act } from "@testing-library/react"; -import { Provider } from "react-redux"; -import { configureStore } from "@reduxjs/toolkit"; +import { setSelectedCalendars } from "@/utils/storage/setSelectedCalendars"; import { createWebSocketConnection } from "@/websocket/connection/createConnection"; import { registerToCalendars } from "@/websocket/operations/registerToCalendars"; import { unregisterToCalendars } from "@/websocket/operations/unregisterToCalendars"; import { WebSocketGate } from "@/websocket/WebSocketGate"; -import { setSelectedCalendars } from "@/utils/storage/setSelectedCalendars"; +import { configureStore } from "@reduxjs/toolkit"; +import { act, cleanup, render, waitFor } from "@testing-library/react"; +import { Provider } from "react-redux"; jest.mock("@/websocket/connection/createConnection"); jest.mock("@/websocket/operations/registerToCalendars"); diff --git a/__test__/features/websocket/createWebSocketConnection.test.tsx b/__test__/features/websocket/createWebSocketConnection.test.tsx index 7a68fd1..5c3154c 100644 --- a/__test__/features/websocket/createWebSocketConnection.test.tsx +++ b/__test__/features/websocket/createWebSocketConnection.test.tsx @@ -1,7 +1,7 @@ -import { waitFor } from "@testing-library/dom"; import { fetchWebSocketTicket } from "@/websocket/api/fetchWebSocketTicket"; import { createWebSocketConnection } from "@/websocket/connection/createConnection"; import { WS_INBOUND_EVENTS } from "@/websocket/protocols"; +import { waitFor } from "@testing-library/dom"; import { setupWebsocket } from "./utils/setupWebsocket"; jest.mock("@/websocket/api/fetchWebSocketTicket"); diff --git a/__test__/features/websocket/utils/updateCalendars.test.tsx b/__test__/features/websocket/utils/updateCalendars.test.tsx index 8ffb7ee..4ede774 100644 --- a/__test__/features/websocket/utils/updateCalendars.test.tsx +++ b/__test__/features/websocket/utils/updateCalendars.test.tsx @@ -1,8 +1,8 @@ -import { updateCalendars } from "@/websocket/messaging/updateCalendars"; -import { refreshCalendarWithSyncToken } from "@/features/Calendars/services/refreshCalendar"; import { RootState, store } from "@/app/store"; -import { WS_INBOUND_EVENTS } from "@/websocket/protocols"; +import { refreshCalendarWithSyncToken } from "@/features/Calendars/services/refreshCalendar"; import { getDisplayedCalendarRange } from "@/utils/CalendarRangeManager"; +import { updateCalendars } from "@/websocket/messaging/updateCalendars"; +import { WS_INBOUND_EVENTS } from "@/websocket/protocols"; import { waitFor } from "@testing-library/dom"; jest.mock("@/features/Calendars/services/refreshCalendar"); diff --git a/__test__/features/websocket/websocketAPI/parseMessage.test.ts b/__test__/features/websocket/websocketAPI/parseMessage.test.ts index ed1f75f..6315fbc 100644 --- a/__test__/features/websocket/websocketAPI/parseMessage.test.ts +++ b/__test__/features/websocket/websocketAPI/parseMessage.test.ts @@ -1,5 +1,5 @@ -import { WS_INBOUND_EVENTS } from "@/websocket/protocols"; import { parseMessage } from "@/websocket/messaging/parseMessage"; +import { WS_INBOUND_EVENTS } from "@/websocket/protocols"; describe("parseMessage", () => { it("should return empty set for non-object messages", () => { diff --git a/__test__/features/websocket/websocketAPI/unregisterToCalendars.test.tsx b/__test__/features/websocket/websocketAPI/unregisterToCalendars.test.tsx index 9052725..923dd5b 100644 --- a/__test__/features/websocket/websocketAPI/unregisterToCalendars.test.tsx +++ b/__test__/features/websocket/websocketAPI/unregisterToCalendars.test.tsx @@ -1,5 +1,3 @@ -// src/websocket/__tests__/unregisterToCalendars.test.ts - import { unregisterToCalendars } from "@/websocket/operations/unregisterToCalendars"; describe("unregisterToCalendars", () => { diff --git a/__test__/utils/CalendarRangeManager.test.ts b/__test__/utils/CalendarRangeManager.test.ts index c730cd9..19f2041 100644 --- a/__test__/utils/CalendarRangeManager.test.ts +++ b/__test__/utils/CalendarRangeManager.test.ts @@ -1,9 +1,9 @@ import { - getDisplayedDate, - setDisplayedDateAndRange, calendarRangeManager, getDisplayedCalendarRange, -} from "../../src/utils/CalendarRangeManager"; + getDisplayedDate, + setDisplayedDateAndRange, +} from "@/utils/CalendarRangeManager"; describe("CalendarRangeManager", () => { beforeEach(() => { diff --git a/__test__/utils/Renderwithproviders.tsx b/__test__/utils/Renderwithproviders.tsx index fb13eb3..8e9be85 100644 --- a/__test__/utils/Renderwithproviders.tsx +++ b/__test__/utils/Renderwithproviders.tsx @@ -1,12 +1,12 @@ +import type { AppStore, RootState } from "@/app/store"; +import { setupStore } from "@/app/store"; +import { TwakeMuiThemeProvider } from "@linagora/twake-mui"; import type { RenderOptions } from "@testing-library/react"; import { render } from "@testing-library/react"; import React, { PropsWithChildren } from "react"; import { Provider } from "react-redux"; import { MemoryRouter } from "react-router-dom"; import { I18nContext } from "twake-i18n"; -import { TwakeMuiThemeProvider } from "@linagora/twake-mui"; -import type { AppStore, RootState } from "../../src/app/store"; -import { setupStore } from "../../src/app/store"; interface ExtendedRenderOptions extends Omit { preloadedState?: Partial; store?: AppStore; diff --git a/__test__/utils/avatarUtils.test.ts b/__test__/utils/avatarUtils.test.ts index 6b7d0b3..8f06d4f 100644 --- a/__test__/utils/avatarUtils.test.ts +++ b/__test__/utils/avatarUtils.test.ts @@ -1,4 +1,4 @@ -import { getInitials, stringToGradient } from "../../src/utils/avatarUtils"; +import { getInitials, stringToGradient } from "@/utils/avatarUtils"; jest.mock("@linagora/twake-mui", () => ({ nameToColor: jest.fn((name: string) => { diff --git a/__test__/utils/calendarUtils.test.tsx b/__test__/utils/calendarUtils.test.tsx index d1aa19c..a170f85 100644 --- a/__test__/utils/calendarUtils.test.tsx +++ b/__test__/utils/calendarUtils.test.tsx @@ -1,4 +1,4 @@ -import { getCalendarVisibility } from "../../src/components/Calendar/utils/calendarUtils"; +import { getCalendarVisibility } from "@/components/Calendar/utils/calendarUtils"; interface AclEntry { privilege: string; diff --git a/__test__/utils/dateUtils.test.ts b/__test__/utils/dateUtils.test.ts index 811e10a..f27c8b1 100644 --- a/__test__/utils/dateUtils.test.ts +++ b/__test__/utils/dateUtils.test.ts @@ -1,4 +1,4 @@ -import { getCalendarRange } from "../../src/utils/dateUtils"; +import { getCalendarRange } from "@/utils/dateUtils"; describe("getCalendarRange", () => { it("Nov 2025 (5 weeks): 2025-10-27 to 2025-11-30", () => { diff --git a/__test__/utils/findCalendarById.test.ts b/__test__/utils/findCalendarById.test.ts index d777302..9a72388 100644 --- a/__test__/utils/findCalendarById.test.ts +++ b/__test__/utils/findCalendarById.test.ts @@ -1,6 +1,6 @@ -import { findCalendarById } from "../../src/utils/findCalendarById"; -import { Calendar } from "../../src/features/Calendars/CalendarTypes"; -import { RootState } from "../../src/app/store"; +import { RootState } from "@/app/store"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { findCalendarById } from "@/utils"; describe("findCalendarById", () => { const mockCalendar1: Calendar = { diff --git a/__test__/utils/userUtils.test.ts b/__test__/utils/userUtils.test.ts index ef66c3b..173e38c 100644 --- a/__test__/utils/userUtils.test.ts +++ b/__test__/utils/userUtils.test.ts @@ -1,5 +1,5 @@ -import { getUserDisplayName } from "../../src/utils/userUtils"; -import { userData } from "../../src/features/User/userDataTypes"; +import { userData } from "@/features/User/userDataTypes"; +import { getUserDisplayName } from "@/utils/userUtils"; describe("userUtils", () => { describe("getUserDisplayName", () => { diff --git a/src/App.tsx b/src/App.tsx index ad8be03..5d66f3d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,18 +1,19 @@ +import { TwakeMuiThemeProvider } from "@linagora/twake-mui"; import { Suspense, useEffect } from "react"; import { Route, Routes } from "react-router-dom"; -import { HistoryRouter as Router } from "redux-first-history/rr6"; -import { CallbackResume } from "./features/User/LoginCallback"; -import { history } from "./app/store"; -import "./App.styl"; -import { Loading } from "./components/Loading/Loading"; -import HandleLogin from "./features/User/HandleLogin"; -import CalendarLayout from "./components/Calendar/CalendarLayout"; -import { Error } from "./components/Error/Error"; -import { TwakeMuiThemeProvider } from "@linagora/twake-mui"; -import { useAppDispatch, useAppSelector } from "./app/hooks"; import { push } from "redux-first-history"; +import { HistoryRouter as Router } from "redux-first-history/rr6"; +import "./App.styl"; +import { useAppDispatch, useAppSelector } from "./app/hooks"; +import { history } from "./app/store"; +import CalendarLayout from "./components/Calendar/CalendarLayout"; +import { Error as ErrorPage } from "./components/Error/Error"; import { ErrorSnackbar } from "./components/Error/ErrorSnackbar"; +import { Loading } from "./components/Loading/Loading"; import { AVAILABLE_LANGUAGES } from "./features/Settings/constants"; +import HandleLogin from "./features/User/HandleLogin"; +import { CallbackResume } from "./features/User/LoginCallback"; +import { WebSocketGate } from "./websocket/WebSocketGate"; import { enGB, @@ -21,12 +22,11 @@ import { vi as viLocale, } from "date-fns/locale"; +import I18n from "twake-i18n"; import en from "./locales/en.json"; import fr from "./locales/fr.json"; import ru from "./locales/ru.json"; import vi from "./locales/vi.json"; -import I18n from "twake-i18n"; -import { WebSocketGate } from "./websocket/WebSocketGate"; const locale = { en, fr, ru, vi }; const dateLocales = { en: enGB, fr: frLocale, ru: ruLocale, vi: viLocale }; @@ -75,7 +75,7 @@ function App() { } /> } /> } /> - } /> + } /> diff --git a/src/app/hooks.ts b/src/app/hooks.ts index 964f36d..7fd1eea 100644 --- a/src/app/hooks.ts +++ b/src/app/hooks.ts @@ -1,5 +1,5 @@ import { useDispatch, useSelector } from "react-redux"; -import type { RootState, AppDispatch } from "./store"; +import type { AppDispatch, RootState } from "./store"; export const useAppDispatch = useDispatch.withTypes(); export const useAppSelector = useSelector.withTypes(); diff --git a/src/app/store.ts b/src/app/store.ts index a63b304..bf059b5 100644 --- a/src/app/store.ts +++ b/src/app/store.ts @@ -1,10 +1,10 @@ +import eventsCalendar from "@/features/Calendars/CalendarSlice"; +import searchResultReducer from "@/features/Search/SearchSlice"; +import settingsReducer from "@/features/Settings/SettingsSlice"; +import userReducer from "@/features/User/userSlice"; import { combineReducers, configureStore } from "@reduxjs/toolkit"; -import userReducer from "../features/User/userSlice"; -import settingsReducer from "../features/Settings/SettingsSlice"; -import searchResultReducer from "../features/Search/SearchSlice"; -import eventsCalendar from "../features/Calendars/CalendarSlice"; -import { createReduxHistoryContext } from "redux-first-history"; import { createBrowserHistory } from "history"; +import { createReduxHistoryContext } from "redux-first-history"; const { createReduxHistory, routerMiddleware, routerReducer } = createReduxHistoryContext({ history: createBrowserHistory() }); diff --git a/src/components/Attendees/AttendeeSearch.tsx b/src/components/Attendees/AttendeeSearch.tsx index 4837f3b..647ce7c 100644 --- a/src/components/Attendees/AttendeeSearch.tsx +++ b/src/components/Attendees/AttendeeSearch.tsx @@ -1,10 +1,10 @@ +import { userAttendee } from "@/features/User/models/attendee"; +import { createAttendee } from "@/features/User/models/attendee.mapper"; import { useEffect, useState } from "react"; -import { userAttendee } from "../../features/User/models/attendee"; -import { createAttendee } from "../../features/User/models/attendee.mapper"; import { + ExtendedAutocompleteRenderInputParams, PeopleSearch, User, - ExtendedAutocompleteRenderInputParams, } from "./PeopleSearch"; export default function UserSearch({ diff --git a/src/components/Attendees/PeopleSearch.tsx b/src/components/Attendees/PeopleSearch.tsx index f94df95..db14fc3 100644 --- a/src/components/Attendees/PeopleSearch.tsx +++ b/src/components/Attendees/PeopleSearch.tsx @@ -1,28 +1,30 @@ +import { getAccessiblePair } from "@/components/Calendar/utils/calendarColorsUtils"; +import { stringAvatar } from "@/components/Event/utils/eventUtils"; +import { SnackbarAlert } from "@/components/Loading/SnackBarAlert"; +import { searchUsers } from "@/features/User/userAPI"; import { Autocomplete, - type AutocompleteRenderInputParams, Avatar, + Chip, CircularProgress, ListItem, ListItemAvatar, ListItemText, + PaperProps, + PopperProps, TextField, + useTheme, + type AutocompleteRenderInputParams, } from "@linagora/twake-mui"; -import { stringAvatar } from "../Event/utils/eventUtils"; +import PeopleOutlineOutlinedIcon from "@mui/icons-material/PeopleOutlineOutlined"; import { - type ReactNode, + HTMLAttributes, useCallback, useEffect, useState, - HTMLAttributes, + type ReactNode, } from "react"; -import { searchUsers } from "../../features/User/userAPI"; -import PeopleOutlineOutlinedIcon from "@mui/icons-material/PeopleOutlineOutlined"; -import { Chip, useTheme } from "@linagora/twake-mui"; -import { getAccessiblePair } from "../Calendar/utils/calendarColorsUtils"; import { useI18n } from "twake-i18n"; -import { SnackbarAlert } from "../Loading/SnackBarAlert"; -import { PopperProps, PaperProps } from "@linagora/twake-mui"; export interface User { email: string; diff --git a/src/components/Calendar/AccessTab.tsx b/src/components/Calendar/AccessTab.tsx index 03f4764..da4bf54 100644 --- a/src/components/Calendar/AccessTab.tsx +++ b/src/components/Calendar/AccessTab.tsx @@ -1,25 +1,24 @@ -import ContentCopyIcon from "@mui/icons-material/ContentCopy"; -import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined"; -import { - Box, - IconButton, - TextField, - Button, - Typography, - InputAdornment, - Backdrop, - CircularProgress, -} from "@linagora/twake-mui"; -import { useState, useEffect } from "react"; import { exportCalendar, getSecretLink, -} from "../../features/Calendars/CalendarApi"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; -import { FieldWithLabel } from "../Event/components/FieldWithLabel"; -import { SnackbarAlert } from "../Loading/SnackBarAlert"; +} from "@/features/Calendars/CalendarApi"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { + Box, + Button, + CircularProgress, + IconButton, + InputAdornment, + TextField, + Typography, +} from "@linagora/twake-mui"; +import ContentCopyIcon from "@mui/icons-material/ContentCopy"; +import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined"; +import { useEffect, useState } from "react"; import { useI18n } from "twake-i18n"; import { ErrorSnackbar } from "../Error/ErrorSnackbar"; +import { FieldWithLabel } from "../Event/components/FieldWithLabel"; +import { SnackbarAlert } from "../Loading/SnackBarAlert"; export function AccessTab({ calendar }: { calendar: Calendar }) { const { t } = useI18n(); diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx index b6ee46c..ea6f406 100644 --- a/src/components/Calendar/Calendar.tsx +++ b/src/components/Calendar/Calendar.tsx @@ -1,52 +1,51 @@ -import FullCalendar from "@fullcalendar/react"; -import dayGridPlugin from "@fullcalendar/daygrid"; -import timeGridPlugin from "@fullcalendar/timegrid"; -import interactionPlugin from "@fullcalendar/interaction"; -import { CalendarApi, DateSelectArg } from "@fullcalendar/core"; -import "./Calendar.styl"; -import "./CustomCalendar.styl"; -import { MutableRefObject, useEffect, useMemo, useRef, useState } from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import EventPopover from "../../features/Events/EventModal"; -import { CalendarEvent } from "../../features/Events/EventsTypes"; -import CalendarSelection from "./CalendarSelection"; -import { getCalendarDetailAsync } from "../../features/Calendars/services/getCalendarDetailAsync"; -import ImportAlert from "../../features/Events/ImportAlert"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { getCalendarDetailAsync } from "@/features/Calendars/services"; +import EventPreviewModal from "@/features/Events/EventDisplayPreview"; +import EventPopover from "@/features/Events/EventModal"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import ImportAlert from "@/features/Events/ImportAlert"; +import SearchResultsPage from "@/features/Search/SearchResultsPage"; +import { setTimeZone } from "@/features/Settings/SettingsSlice"; +import { setDisplayedDateAndRange } from "@/utils/CalendarRangeManager"; import { formatDateToYYYYMMDDTHHMMSS, getCalendarRange, } from "@/utils/dateUtils"; -import { push } from "redux-first-history"; -import EventPreviewModal from "../../features/Events/EventDisplayPreview"; -import AddIcon from "@mui/icons-material/Add"; -import { TempCalendarsInput } from "./TempCalendarsInput"; -import { Button, Box, radius } from "@linagora/twake-mui"; -import { - updateSlotLabelVisibility, - eventToFullCalendarFormat, - extractEvents, -} from "./utils/calendarUtils"; -import { useCalendarEventHandlers } from "./hooks/useCalendarEventHandlers"; -import { useCalendarViewHandlers } from "./hooks/useCalendarViewHandlers"; -import { EditModeDialog } from "../Event/EditModeDialog"; -import { EventErrorHandler } from "../Error/EventErrorHandler"; -import { EventErrorSnackbar } from "../Error/ErrorSnackbar"; -import momentTimezonePlugin from "@fullcalendar/moment-timezone"; -import { TimezoneSelector } from "./TimezoneSelector"; -import { MiniCalendar } from "./MiniCalendar"; -import { User } from "../Attendees/PeopleSearch"; -import { useTheme } from "@linagora/twake-mui"; -import { updateDarkColor } from "./utils/calendarColorsUtils"; -import { useI18n } from "twake-i18n"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { setSelectedCalendars as setSelectedCalendarsToStorage } from "@/utils/storage/setSelectedCalendars"; +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { CalendarApi, DateSelectArg } from "@fullcalendar/core"; import frLocale from "@fullcalendar/core/locales/fr"; import ruLocale from "@fullcalendar/core/locales/ru"; import viLocale from "@fullcalendar/core/locales/vi"; -import SearchResultsPage from "../../features/Search/SearchResultsPage"; -import { setTimeZone } from "../../features/Settings/SettingsSlice"; -import { browserDefaultTimeZone } from "@/utils/timezone"; -import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; -import { setSelectedCalendars as setSelectedCalendarsToStorage } from "@/utils/storage/setSelectedCalendars"; -import { setDisplayedDateAndRange } from "@/utils/CalendarRangeManager"; +import dayGridPlugin from "@fullcalendar/daygrid"; +import interactionPlugin from "@fullcalendar/interaction"; +import momentTimezonePlugin from "@fullcalendar/moment-timezone"; +import FullCalendar from "@fullcalendar/react"; +import timeGridPlugin from "@fullcalendar/timegrid"; +import { Box, Button, radius, useTheme } from "@linagora/twake-mui"; +import AddIcon from "@mui/icons-material/Add"; +import { MutableRefObject, useEffect, useMemo, useRef, useState } from "react"; +import { push } from "redux-first-history"; +import { useI18n } from "twake-i18n"; +import { User } from "../Attendees/PeopleSearch"; +import { EventErrorSnackbar } from "../Error/ErrorSnackbar"; +import { EventErrorHandler } from "../Error/EventErrorHandler"; +import { EditModeDialog } from "../Event/EditModeDialog"; +import "./Calendar.styl"; +import CalendarSelection from "./CalendarSelection"; +import "./CustomCalendar.styl"; +import { useCalendarEventHandlers } from "./hooks/useCalendarEventHandlers"; +import { useCalendarViewHandlers } from "./hooks/useCalendarViewHandlers"; +import { MiniCalendar } from "./MiniCalendar"; +import { TempCalendarsInput } from "./TempCalendarsInput"; +import { TimezoneSelector } from "./TimezoneSelector"; +import { updateDarkColor } from "./utils/calendarColorsUtils"; +import { + eventToFullCalendarFormat, + extractEvents, + updateSlotLabelVisibility, +} from "./utils/calendarUtils"; const localeMap: Record = { fr: frLocale, diff --git a/src/components/Calendar/CalendarItemList.tsx b/src/components/Calendar/CalendarItemList.tsx index 8a05851..2c4f1aa 100644 --- a/src/components/Calendar/CalendarItemList.tsx +++ b/src/components/Calendar/CalendarItemList.tsx @@ -1,6 +1,6 @@ -import React from "react"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; import { MenuItem } from "@linagora/twake-mui"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; +import React from "react"; import { CalendarName } from "./CalendarName"; export function CalendarItemList( diff --git a/src/components/Calendar/CalendarLayout.tsx b/src/components/Calendar/CalendarLayout.tsx index 0f3b4df..5a729fb 100644 --- a/src/components/Calendar/CalendarLayout.tsx +++ b/src/components/Calendar/CalendarLayout.tsx @@ -1,13 +1,11 @@ -import { useRef, useState, useEffect } from "react"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import SettingsPage from "@/features/Settings/SettingsPage"; +import { getCalendarRange } from "@/utils/dateUtils"; +import { useEffect, useRef, useState } from "react"; +import { ErrorSnackbar } from "../Error/ErrorSnackbar"; +import { refreshCalendars } from "../Event/utils/eventUtils"; import { Menubar, MenubarProps } from "../Menubar/Menubar"; import CalendarApp from "./Calendar"; -import { useAppDispatch } from "../../app/hooks"; -import { getCalendarRange } from "../../utils/dateUtils"; -import { useAppSelector } from "../../app/hooks"; -import { refreshCalendars } from "../Event/utils/eventUtils"; -import { ErrorSnackbar } from "../Error/ErrorSnackbar"; - -import SettingsPage from "../../features/Settings/SettingsPage"; export default function CalendarLayout() { const calendarRef = useRef(null); diff --git a/src/components/Calendar/CalendarModal.tsx b/src/components/Calendar/CalendarModal.tsx index 9bd6a34..cef2073 100644 --- a/src/components/Calendar/CalendarModal.tsx +++ b/src/components/Calendar/CalendarModal.tsx @@ -1,20 +1,20 @@ -import { Button, Tab, Tabs } from "@linagora/twake-mui"; -import { useEffect, useState } from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; import { createCalendarAsync, importEventFromFileAsync, patchACLCalendarAsync, patchCalendarAsync, -} from "../../features/Calendars/CalendarSlice"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; +} from "@/features/Calendars/services"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { Button, Tab, Tabs } from "@linagora/twake-mui"; +import { useEffect, useState } from "react"; +import { useI18n } from "twake-i18n"; import { ResponsiveDialog } from "../Dialog"; import { AccessTab } from "./AccessTab"; import { ImportTab } from "./ImportTab"; import { SettingsTab } from "./SettingsTab"; import { defaultColors } from "./utils/calendarColorsUtils"; -import { useI18n } from "twake-i18n"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; function CalendarPopover({ open, diff --git a/src/components/Calendar/CalendarName.tsx b/src/components/Calendar/CalendarName.tsx index d1daf33..70006e9 100644 --- a/src/components/Calendar/CalendarName.tsx +++ b/src/components/Calendar/CalendarName.tsx @@ -1,5 +1,5 @@ +import { Calendar } from "@/features/Calendars/CalendarTypes"; import { Box, Typography } from "@linagora/twake-mui"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; import SquareRoundedIcon from "@mui/icons-material/SquareRounded"; export function CalendarName({ calendar }: { calendar: Calendar }) { return ( diff --git a/src/components/Calendar/CalendarSearch.tsx b/src/components/Calendar/CalendarSearch.tsx index be31c8b..02ae17b 100644 --- a/src/components/Calendar/CalendarSearch.tsx +++ b/src/components/Calendar/CalendarSearch.tsx @@ -1,22 +1,22 @@ -import CloseIcon from "@mui/icons-material/Close"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { getCalendars } from "@/features/Calendars/CalendarApi"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { addSharedCalendarAsync } from "@/features/Calendars/services"; import { Avatar, Box, Button, IconButton, - Typography, TextField, + Typography, useTheme, } from "@linagora/twake-mui"; -import { useI18n } from "twake-i18n"; -import { stringAvatar } from "../Event/utils/eventUtils"; +import CloseIcon from "@mui/icons-material/Close"; import { useState } from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { getCalendars } from "../../features/Calendars/CalendarApi"; -import { addSharedCalendarAsync } from "../../features/Calendars/CalendarSlice"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; +import { useI18n } from "twake-i18n"; import { PeopleSearch, User } from "../Attendees/PeopleSearch"; import { ResponsiveDialog } from "../Dialog"; +import { stringAvatar } from "../Event/utils/eventUtils"; import { ColorPicker } from "./CalendarColorPicker"; import { defaultColors, getAccessiblePair } from "./utils/calendarColorsUtils"; diff --git a/src/components/Calendar/CalendarSelection.tsx b/src/components/Calendar/CalendarSelection.tsx index 4a0fe4e..9ea138a 100644 --- a/src/components/Calendar/CalendarSelection.tsx +++ b/src/components/Calendar/CalendarSelection.tsx @@ -1,28 +1,28 @@ +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { removeCalendarAsync } from "@/features/Calendars/services"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { trimLongTextWithoutSpace } from "@/utils/textUtils"; import { Accordion, AccordionDetails, AccordionSummary, - Typography, - IconButton, Checkbox, Divider, + IconButton, ListItem, Menu, MenuItem, + Typography, } from "@linagora/twake-mui"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; import AddIcon from "@mui/icons-material/Add"; -import { useState, useMemo, useEffect } from "react"; -import CalendarPopover from "./CalendarModal"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; -import MoreVertIcon from "@mui/icons-material/MoreVert"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import CalendarSearch from "./CalendarSearch"; -import { removeCalendarAsync } from "../../features/Calendars/CalendarSlice"; -import { DeleteCalendarDialog } from "./DeleteCalendarDialog"; -import { trimLongTextWithoutSpace } from "../../utils/textUtils"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; +import { useEffect, useMemo, useState } from "react"; import { useI18n } from "twake-i18n"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; +import CalendarPopover from "./CalendarModal"; +import CalendarSearch from "./CalendarSearch"; +import { DeleteCalendarDialog } from "./DeleteCalendarDialog"; function CalendarAccordion({ title, diff --git a/src/components/Calendar/DeleteCalendarDialog.tsx b/src/components/Calendar/DeleteCalendarDialog.tsx index a16d009..961b0a3 100644 --- a/src/components/Calendar/DeleteCalendarDialog.tsx +++ b/src/components/Calendar/DeleteCalendarDialog.tsx @@ -1,12 +1,12 @@ +import { Calendar } from "@/features/Calendars/CalendarTypes"; import { + Button, Dialog, - DialogTitle, + DialogActions, DialogContent, DialogContentText, - DialogActions, - Button, + DialogTitle, } from "@linagora/twake-mui"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; import { useI18n } from "twake-i18n"; export function DeleteCalendarDialog({ diff --git a/src/components/Calendar/ImportTab.tsx b/src/components/Calendar/ImportTab.tsx index 2988fd9..d8fa630 100644 --- a/src/components/Calendar/ImportTab.tsx +++ b/src/components/Calendar/ImportTab.tsx @@ -1,3 +1,5 @@ +import { useAppSelector } from "@/app/hooks"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; import { Box, Button, @@ -6,16 +8,12 @@ import { MenuItem, Select, TextField, - ToggleButton, - ToggleButtonGroup, Typography, } from "@linagora/twake-mui"; import { useEffect, useState } from "react"; -import { useAppSelector } from "../../app/hooks"; +import { useI18n } from "twake-i18n"; import { CalendarItemList } from "./CalendarItemList"; import { SettingsTab } from "./SettingsTab"; -import { useI18n } from "twake-i18n"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; export function ImportTab({ userId, diff --git a/src/components/Calendar/MiniCalendar.tsx b/src/components/Calendar/MiniCalendar.tsx index 135909d..ed6f38e 100644 --- a/src/components/Calendar/MiniCalendar.tsx +++ b/src/components/Calendar/MiniCalendar.tsx @@ -1,17 +1,17 @@ -import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; -import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; -import { DateCalendar } from "@mui/x-date-pickers"; -import moment from "moment"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { getCalendarDetailAsync } from "@/features/Calendars/services"; +import { setView } from "@/features/Settings/SettingsSlice"; import { computeStartOfTheWeek, formatDateToYYYYMMDDTHHMMSS, getCalendarRange, -} from "../../utils/dateUtils"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { getCalendarDetailAsync } from "../../features/Calendars/services/getCalendarDetailAsync"; +} from "@/utils/dateUtils"; +import { DateCalendar } from "@mui/x-date-pickers"; +import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; +import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; +import moment from "moment"; import { useEffect, useState } from "react"; import { useI18n } from "twake-i18n"; -import { setView } from "../../features/Settings/SettingsSlice"; export function MiniCalendar({ calendarRef, diff --git a/src/components/Calendar/SettingsTab.tsx b/src/components/Calendar/SettingsTab.tsx index d0f1528..3d80a97 100644 --- a/src/components/Calendar/SettingsTab.tsx +++ b/src/components/Calendar/SettingsTab.tsx @@ -1,21 +1,19 @@ -import FormatListBulletedIcon from "@mui/icons-material/FormatListBulleted"; -import LockOutlineIcon from "@mui/icons-material/LockOutline"; -import PublicIcon from "@mui/icons-material/Public"; +import { useAppSelector } from "@/app/hooks"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; import { Box, - Button, TextField, ToggleButton, ToggleButtonGroup, Typography, } from "@linagora/twake-mui"; +import LockOutlineIcon from "@mui/icons-material/LockOutline"; +import PublicIcon from "@mui/icons-material/Public"; +import { useEffect, useState } from "react"; import { useI18n } from "twake-i18n"; -import { useState, useEffect } from "react"; -import { useAppSelector } from "../../app/hooks"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; import { AddDescButton } from "../Event/AddDescButton"; import { ColorPicker } from "./CalendarColorPicker"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; export function SettingsTab({ name, diff --git a/src/components/Calendar/TempCalendarsInput.tsx b/src/components/Calendar/TempCalendarsInput.tsx index 9451929..32f3f92 100644 --- a/src/components/Calendar/TempCalendarsInput.tsx +++ b/src/components/Calendar/TempCalendarsInput.tsx @@ -1,15 +1,12 @@ -import { useTheme } from "@linagora/twake-mui"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { removeTempCal } from "@/features/Calendars/CalendarSlice"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { getTempCalendarsListAsync } from "@/features/Calendars/services"; +import { setView } from "@/features/Settings/SettingsSlice"; +import { TextField, useTheme } from "@linagora/twake-mui"; import { useRef } from "react"; import { useI18n } from "twake-i18n"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { - getTempCalendarsListAsync, - removeTempCal, -} from "../../features/Calendars/CalendarSlice"; -import { Calendar } from "../../features/Calendars/CalendarTypes"; -import { setView } from "../../features/Settings/SettingsSlice"; -import { TextField } from "@linagora/twake-mui"; -import { User, PeopleSearch } from "../Attendees/PeopleSearch"; +import { PeopleSearch, User } from "../Attendees/PeopleSearch"; import { getAccessiblePair } from "./utils/calendarColorsUtils"; const requestControllers = new Map(); diff --git a/src/components/Calendar/TimezoneSelector.tsx b/src/components/Calendar/TimezoneSelector.tsx index 96b17c2..082ba71 100644 --- a/src/components/Calendar/TimezoneSelector.tsx +++ b/src/components/Calendar/TimezoneSelector.tsx @@ -1,9 +1,9 @@ +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { TIMEZONES } from "@/utils/timezone-data"; import { Button, Popover } from "@linagora/twake-mui"; -import { useI18n } from "twake-i18n"; import moment from "moment"; import { MouseEvent, useMemo, useState } from "react"; -import { browserDefaultTimeZone } from "../../utils/timezone"; -import { TIMEZONES } from "../../utils/timezone-data"; +import { useI18n } from "twake-i18n"; import { TimezoneAutocomplete } from "../Timezone/TimezoneAutocomplete"; interface TimezoneSelectProps { diff --git a/src/components/Calendar/handlers/eventHandlers.ts b/src/components/Calendar/handlers/eventHandlers.ts index 15c20ac..ce42120 100644 --- a/src/components/Calendar/handlers/eventHandlers.ts +++ b/src/components/Calendar/handlers/eventHandlers.ts @@ -1,24 +1,25 @@ -import { DateSelectArg } from "@fullcalendar/core"; -import { CalendarApi } from "@fullcalendar/core"; -import { CalendarEvent } from "../../../features/Events/EventsTypes"; -import { Calendar } from "../../../features/Calendars/CalendarTypes"; -import { getDeltaInMilliseconds } from "../../../utils/dateUtils"; +import { User } from "@/components/Attendees/PeopleSearch"; +import { formatLocalDateTime } from "@/components/Event/utils/dateTimeFormatters"; +import { refreshCalendars } from "@/components/Event/utils/eventUtils"; +import { updateEventLocal } from "@/features/Calendars/CalendarSlice"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; import { + getCalendarDetailAsync, getEventAsync, putEventAsync, updateEventInstanceAsync, - updateEventLocal, updateSeriesAsync, -} from "../../../features/Calendars/CalendarSlice"; -import { getCalendarDetailAsync } from "../../../features/Calendars/services/getCalendarDetailAsync"; -import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils"; -import { getEvent } from "../../../features/Events/EventApi"; -import { refreshCalendars } from "../../Event/utils/eventUtils"; +} from "@/features/Calendars/services"; +import { getEvent } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { userAttendee } from "@/features/User/models/attendee"; +import { createAttendee } from "@/features/User/models/attendee.mapper"; +import { + formatDateToYYYYMMDDTHHMMSS, + getDeltaInMilliseconds, +} from "@/utils/dateUtils"; +import { CalendarApi, DateSelectArg } from "@fullcalendar/core"; import { updateTempCalendar } from "../utils/calendarUtils"; -import { User } from "../../Attendees/PeopleSearch"; -import { formatLocalDateTime } from "../../Event/utils/dateTimeFormatters"; -import { userAttendee } from "../../../features/User/models/attendee"; -import { createAttendee } from "../../../features/User/models/attendee.mapper"; export interface EventHandlersProps { setSelectedRange: (range: DateSelectArg | null) => void; diff --git a/src/components/Calendar/handlers/viewHandlers.ts b/src/components/Calendar/handlers/viewHandlers.ts index 6fecc2f..de60a05 100644 --- a/src/components/Calendar/handlers/viewHandlers.ts +++ b/src/components/Calendar/handlers/viewHandlers.ts @@ -1,10 +1,10 @@ -import React from "react"; +import { EventErrorHandler } from "@/components/Error/EventErrorHandler"; +import { EventChip } from "@/components/Event/EventChip/EventChip"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { userAttendee } from "@/features/User/models/attendee"; import { CalendarApi, NowIndicatorContentArg } from "@fullcalendar/core"; +import React from "react"; import { createMouseHandlers } from "./mouseHandlers"; -import { userAttendee } from "../../../features/User/models/attendee"; -import { Calendar } from "../../../features/Calendars/CalendarTypes"; -import { EventErrorHandler } from "../../Error/EventErrorHandler"; -import { EventChip } from "../../Event/EventChip/EventChip"; export interface ViewHandlersProps { calendarRef: React.RefObject; diff --git a/src/components/Calendar/utils/calendarColorsUtils.tsx b/src/components/Calendar/utils/calendarColorsUtils.tsx index 3029268..978701c 100644 --- a/src/components/Calendar/utils/calendarColorsUtils.tsx +++ b/src/components/Calendar/utils/calendarColorsUtils.tsx @@ -1,12 +1,12 @@ +import { AppDispatch } from "@/app/store"; +import { updateCalColor } from "@/features/Calendars/CalendarSlice"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; import { darken, getContrastRatio, lighten, Theme } from "@linagora/twake-mui"; -import { ThunkDispatch } from "@reduxjs/toolkit"; -import { updateCalColor } from "../../../features/Calendars/CalendarSlice"; -import { Calendar } from "../../../features/Calendars/CalendarTypes"; export function updateDarkColor( calendars: Record, theme: Theme, - dispatch: ThunkDispatch + dispatch: AppDispatch ) { Object.values(calendars).forEach((cal) => { if (!cal?.color?.light || typeof cal.color.light !== "string") return; diff --git a/src/components/Calendar/utils/calendarUtils.ts b/src/components/Calendar/utils/calendarUtils.ts index 67bb19a..e9c83d5 100644 --- a/src/components/Calendar/utils/calendarUtils.ts +++ b/src/components/Calendar/utils/calendarUtils.ts @@ -1,14 +1,14 @@ -import { CalendarEvent } from "../../../features/Events/EventsTypes"; -import { Calendar } from "../../../features/Calendars/CalendarTypes"; -import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils"; -import { getCalendarDetailAsync } from "../../../features/Calendars/services/getCalendarDetailAsync"; +import { detectDateTimeFormat } from "@/components/Event/utils/dateTimeHelpers"; +import { refreshSingularCalendar } from "@/components/Event/utils/eventUtils"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { getCalendarDetailAsync } from "@/features/Calendars/services"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatDateToYYYYMMDDTHHMMSS } from "@/utils/dateUtils"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; import { SlotLabelContentArg } from "@fullcalendar/core"; -import moment from "moment-timezone"; -import { refreshSingularCalendar } from "../../Event/utils/eventUtils"; import { ThunkDispatch } from "@reduxjs/toolkit"; +import moment from "moment-timezone"; import { useI18n } from "twake-i18n"; -import { detectDateTimeFormat } from "../../Event/utils/dateTimeHelpers"; -import { extractEventBaseUuid } from "../../../utils/extractEventBaseUuid"; function convertEventDateTimeToISO( datetime: string, diff --git a/src/components/Dialog/README.md b/src/components/Dialog/README.md index da65225..b8ef040 100644 --- a/src/components/Dialog/README.md +++ b/src/components/Dialog/README.md @@ -18,7 +18,7 @@ A highly reusable dialog component that supports both normal and expanded (fulls ## Basic Usage ```tsx -import { ResponsiveDialog } from "../../components/Dialog"; +import { ResponsiveDialog } from "@/components/Dialog"; import { useState } from "react"; function MyComponent() { @@ -199,7 +199,7 @@ All `sx` props are **merged** with base styles, not overridden: Full type inference and validation: ```tsx -import { ResponsiveDialog } from "../../components/Dialog"; +import { ResponsiveDialog } from "@/components/Dialog"; // All props are type-checked , + dispatch: AppDispatch, calendar: Calendar, event: CalendarEvent ) { @@ -78,7 +78,7 @@ async function handleSoloRSVP( } async function handleAllRSVP( - dispatch: ThunkDispatch, + dispatch: AppDispatch, event: CalendarEvent, userEmail: string, rsvp: PartStat, @@ -90,7 +90,7 @@ async function handleAllRSVP( } async function handleDefaultRSVP( - dispatch: ThunkDispatch, + dispatch: AppDispatch, calendar: Calendar, newEvent: CalendarEvent ) { @@ -98,7 +98,7 @@ async function handleDefaultRSVP( } export async function handleRSVP( - dispatch: ThunkDispatch, + dispatch: AppDispatch, calendar: Calendar, user: userData | undefined, event: CalendarEvent, diff --git a/src/components/Event/hooks/useAllDayToggle.ts b/src/components/Event/hooks/useAllDayToggle.ts index 62337c0..2822b78 100644 --- a/src/components/Event/hooks/useAllDayToggle.ts +++ b/src/components/Event/hooks/useAllDayToggle.ts @@ -1,6 +1,5 @@ import React from "react"; import { combineDateTime } from "../utils/dateTimeHelpers"; -import { getRoundedCurrentTime } from "../utils/dateTimeFormatters"; /** * Parameters for all-day toggle hook diff --git a/src/components/Event/utils/dateTimeHelpers.ts b/src/components/Event/utils/dateTimeHelpers.ts index 9b71d13..636771a 100644 --- a/src/components/Event/utils/dateTimeHelpers.ts +++ b/src/components/Event/utils/dateTimeHelpers.ts @@ -1,6 +1,6 @@ -import moment from "moment-timezone"; import dayjs, { Dayjs } from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; +import moment from "moment-timezone"; dayjs.extend(customParseFormat); diff --git a/src/components/Event/utils/eventUtils.tsx b/src/components/Event/utils/eventUtils.tsx index 90c5933..a3253d8 100644 --- a/src/components/Event/utils/eventUtils.tsx +++ b/src/components/Event/utils/eventUtils.tsx @@ -1,16 +1,17 @@ +import { AppDispatch } from "@/app/store"; +import { emptyEventsCal } from "@/features/Calendars/CalendarSlice"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { + getCalendarDetailAsync, + getCalendarsListAsync, + refreshCalendarWithSyncToken, +} from "@/features/Calendars/services"; +import { userAttendee } from "@/features/User/models/attendee"; +import { getInitials, stringToGradient } from "@/utils/avatarUtils"; +import { formatDateToYYYYMMDDTHHMMSS } from "@/utils/dateUtils"; +import { Avatar, Badge, Box, Typography } from "@linagora/twake-mui"; import CancelIcon from "@mui/icons-material/Cancel"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; -import { Avatar, Badge, Box, Typography } from "@linagora/twake-mui"; -import { stringToGradient, getInitials } from "../../../utils/avatarUtils"; -import { ThunkDispatch } from "@reduxjs/toolkit"; -import { emptyEventsCal } from "../../../features/Calendars/CalendarSlice"; -import { getCalendarsListAsync } from "../../../features/Calendars/services/getCalendarsListAsync"; -import { getCalendarDetailAsync } from "../../../features/Calendars/services/getCalendarDetailAsync"; -import { Calendar } from "../../../features/Calendars/CalendarTypes"; -import { userAttendee } from "../../../features/User/models/attendee"; -import { refreshCalendarWithSyncToken } from "../../../features/Calendars/services/refreshCalendar"; -import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils"; -import { AppDispatch } from "../../../app/store"; export function renderAttendeeBadge( a: userAttendee, @@ -139,7 +140,7 @@ export async function refreshCalendars( } export async function refreshSingularCalendar( - dispatch: ThunkDispatch, + dispatch: AppDispatch, calendar: Calendar, calendarRange: { start: Date; end: Date }, calType?: "temp" diff --git a/src/components/Loading/SnackBarAlert.tsx b/src/components/Loading/SnackBarAlert.tsx index dd603f6..a1b4393 100644 --- a/src/components/Loading/SnackBarAlert.tsx +++ b/src/components/Loading/SnackBarAlert.tsx @@ -1,5 +1,5 @@ -import { Alert, Snackbar } from "@linagora/twake-mui"; import type { AlertColor } from "@linagora/twake-mui"; +import { Alert, Snackbar } from "@linagora/twake-mui"; export function SnackbarAlert({ open, diff --git a/src/components/Menubar/EventSearchBar.tsx b/src/components/Menubar/EventSearchBar.tsx index 6f9dea8..4de8553 100644 --- a/src/components/Menubar/EventSearchBar.tsx +++ b/src/components/Menubar/EventSearchBar.tsx @@ -1,3 +1,9 @@ +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { searchEventsAsync } from "@/features/Search/SearchSlice"; +import { setView } from "@/features/Settings/SettingsSlice"; +import { userAttendee } from "@/features/User/models/attendee"; +import { createAttendee } from "@/features/User/models/attendee.mapper"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; import { Box, Button, @@ -14,22 +20,16 @@ import { Stack, TextField, Typography, + type AutocompleteRenderInputParams, } from "@linagora/twake-mui"; -import { type AutocompleteRenderInputParams } from "@linagora/twake-mui"; -import { useRef, useState, useEffect } from "react"; import HighlightOffIcon from "@mui/icons-material/HighlightOff"; import SearchIcon from "@mui/icons-material/Search"; import TuneIcon from "@mui/icons-material/Tune"; +import { useEffect, useRef, useState } from "react"; 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/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"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; +import { CalendarItemList } from "../Calendar/CalendarItemList"; export default function SearchBar() { const { t } = useI18n(); diff --git a/src/components/Menubar/Menubar.tsx b/src/components/Menubar/Menubar.tsx index 8e549f7..5ecf280 100644 --- a/src/components/Menubar/Menubar.tsx +++ b/src/components/Menubar/Menubar.tsx @@ -1,33 +1,30 @@ -import React, { useEffect, useState } from "react"; -import logo from "../../static/header-logo.svg"; -import AppsIcon from "@mui/icons-material/Apps"; -import RefreshIcon from "@mui/icons-material/Refresh"; -import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; -import ChevronRightIcon from "@mui/icons-material/ChevronRight"; -import SettingsIcon from "@mui/icons-material/Settings"; -import LogoutIcon from "@mui/icons-material/Logout"; -import "./Menubar.styl"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { stringToGradient, getInitials } from "../../utils/avatarUtils"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { setView } from "@/features/Settings/SettingsSlice"; +import { Logout } from "@/features/User/oidcAuth"; +import logo from "@/static/header-logo.svg"; +import { getInitials, stringToGradient } from "@/utils/avatarUtils"; +import { getUserDisplayName } from "@/utils/userUtils"; +import { CalendarApi } from "@fullcalendar/core"; import { Avatar, + Box, + Button, + ButtonGroup, + Divider, + FormControl, IconButton, - Popover, Menu, MenuItem, - ButtonGroup, - Button, + Popover, Select, - FormControl, Typography, - Box, - Divider, } from "@linagora/twake-mui"; -import { push } from "redux-first-history"; -import { CalendarApi } from "@fullcalendar/core"; -import { useI18n } from "twake-i18n"; -import { setView } from "../../features/Settings/SettingsSlice"; -import { getUserDisplayName } from "../../utils/userUtils"; +import AppsIcon from "@mui/icons-material/Apps"; +import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; +import ChevronRightIcon from "@mui/icons-material/ChevronRight"; +import LogoutIcon from "@mui/icons-material/Logout"; +import RefreshIcon from "@mui/icons-material/Refresh"; +import SettingsIcon from "@mui/icons-material/Settings"; import { format } from "date-fns"; import { enGB, @@ -35,8 +32,11 @@ import { ru as ruLocale, vi as viLocale, } from "date-fns/locale"; +import React, { useEffect, useState } from "react"; +import { push } from "redux-first-history"; +import { useI18n } from "twake-i18n"; import SearchBar from "./EventSearchBar"; -import { Logout } from "../../features/User/oidcAuth"; +import "./Menubar.styl"; const dateLocales = { en: enGB, fr: frLocale, ru: ruLocale, vi: viLocale }; export type AppIconProps = { diff --git a/src/features/Calendars/CalendarApi.ts b/src/features/Calendars/CalendarApi.ts index d9d2da3..48788e2 100644 --- a/src/features/Calendars/CalendarApi.ts +++ b/src/features/Calendars/CalendarApi.ts @@ -1,4 +1,4 @@ -import { api } from "../../utils/apiUtils"; +import { api } from "@/utils/apiUtils"; export async function getCalendars( userId: string, diff --git a/src/features/Calendars/CalendarSlice.ts b/src/features/Calendars/CalendarSlice.ts index b60c02a..2e1ebfe 100644 --- a/src/features/Calendars/CalendarSlice.ts +++ b/src/features/Calendars/CalendarSlice.ts @@ -1,40 +1,27 @@ -import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { Calendar } from "./CalendarTypes"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { CalendarEvent } from "../Events/EventsTypes"; +import { Calendar } from "./CalendarTypes"; import { - addSharedCalendar, - getCalendar, - getCalendars, - postCalendar, - proppatchCalendar, - removeCalendar, - updateAclCalendar, -} from "./CalendarApi"; -import { getUserDetails } from "../User/userAPI"; -import { parseCalendarEvent } from "../Events/eventUtils"; -import { - deleteEvent, - deleteEventInstance, - getEvent, - importEventFromFile, - moveEvent, - putEvent, - putEventWithOverrides, - updateSeries, -} from "../Events/EventApi"; -import { - computeWeekRange, - formatDateToYYYYMMDDTHHMMSS, -} from "../../utils/dateUtils"; -import { User } from "../../components/Attendees/PeopleSearch"; -import { getCalendarVisibility } from "../../components/Calendar/utils/calendarUtils"; -import { importFile } from "../../utils/apiUtils"; -import { formatReduxError } from "../../utils/errorUtils"; -import { browserDefaultTimeZone } from "../../utils/timezone"; -import { getCalendarDetailAsync } from "./services/getCalendarDetailAsync"; -import { refreshCalendarWithSyncToken } from "./services/refreshCalendar"; -import { getCalendarsListAsync } from "./services/getCalendarsListAsync"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; + addSharedCalendarAsync, + createCalendarAsync, + deleteEventAsync, + deleteEventInstanceAsync, + getCalendarDetailAsync, + getCalendarsListAsync, + getEventAsync, + getTempCalendarsListAsync, + importEventFromFileAsync, + moveEventAsync, + patchACLCalendarAsync, + patchCalendarAsync, + putEventAsync, + refreshCalendarWithSyncToken, + removeCalendarAsync, + updateEventInstanceAsync, + updateSeriesAsync, +} from "./services"; // Define error type for rejected actions export interface RejectedError { @@ -42,459 +29,6 @@ export interface RejectedError { status?: number; } -export const getTempCalendarsListAsync = createAsyncThunk< - Record, - User, - { rejectValue: RejectedError } ->("calendars/getTempCalendars", async (tempUser, { rejectWithValue }) => { - try { - const importedCalendars: Record = {}; - - const calendars = (await getCalendars( - tempUser.openpaasId ?? "", - "sharedPublic=true&" - )) as Record; - - const rawCalendars = calendars._embedded?.["dav:calendar"]; - if (!rawCalendars || rawCalendars.length === 0) { - const userName = tempUser.displayName || tempUser.email || "User"; - // Format: TRANSLATION:key|param1=value1 - const encodedName = encodeURIComponent(userName); - throw new Error( - `TRANSLATION:calendar.userDoesNotHavePublicCalendars|name=${encodedName}` - ); - } - - for (const cal of rawCalendars) { - const name = cal["dav:name"]; - const description = cal["caldav:description"]; - const delegated = cal["calendarserver:delegatedsource"] ? true : false; - const source = cal["calendarserver:source"] - ? cal["calendarserver:source"]._links.self.href - : cal._links.self.href; - const link = cal._links.self.href; - - const id = source.replace("/calendars/", "").replace(".json", ""); - const visibility = getCalendarVisibility(cal["acl"]); - const ownerData: any = await getUserDetails(id.split("/")[0]); - - importedCalendars[id] = { - id, - name, - link, - owner: `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ownerData.lastname}`, - ownerEmails: ownerData.emails, - description, - delegated, - color: { - light: tempUser.color?.light ?? "#a8a8a8ff", - dark: tempUser.color?.dark ?? "#a8a8a8ff", - }, - visibility, - events: {}, - }; - } - - return importedCalendars; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } -}); - -export const putEventAsync = createAsyncThunk< - { calId: string; events: CalendarEvent[]; calType?: "temp" }, - { cal: Calendar; newEvent: CalendarEvent; calType?: "temp" }, - { rejectValue: RejectedError } ->( - "calendars/putEvent", - async ({ cal, newEvent, calType }, { rejectWithValue }) => { - try { - await putEvent( - newEvent, - cal.ownerEmails ? cal.ownerEmails[0] : undefined - ); - const eventDate = new Date(newEvent.start); - - const { start: weekStart, end: weekEnd } = computeWeekRange(eventDate); - - const calEvents = (await getCalendar(cal.id, { - start: formatDateToYYYYMMDDTHHMMSS(weekStart), - end: formatDateToYYYYMMDDTHHMMSS(weekEnd), - })) as Record; - const events: CalendarEvent[] = calEvents._embedded["dav:item"].flatMap( - (eventdata: any) => { - const vevents = eventdata.data[2] as any[][]; - const eventURL = eventdata._links.self.href; - const valarm = eventdata.data[2][0][2][0]; - return vevents.map((vevent: any[]) => { - return parseCalendarEvent( - vevent[1], - cal.color ?? {}, - cal.id, - eventURL, - valarm - ); - }); - } - ); - - return { - calId: cal.id, - events, - calType, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const getEventAsync = createAsyncThunk< - { calId: string; event: CalendarEvent }, - CalendarEvent, - { rejectValue: RejectedError } ->("calendars/getEvent", async (event, { rejectWithValue }) => { - try { - const response: CalendarEvent = await getEvent(event); - return { - calId: event.calId, - event: response, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } -}); - -export const patchCalendarAsync = createAsyncThunk< - { - calId: string; - calLink: string; - patch: { name: string; desc: string; color: Record }; - }, - { - calId: string; - calLink: string; - patch: { name: string; desc: string; color: Record }; - }, - { rejectValue: RejectedError } ->( - "calendars/patchCalendar", - async ({ calId, calLink, patch }, { rejectWithValue }) => { - try { - await proppatchCalendar(calLink, patch); - return { - calId, - calLink, - patch, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const removeCalendarAsync = createAsyncThunk< - { - calId: string; - }, - { - calId: string; - calLink: string; - }, - { rejectValue: RejectedError } ->( - "calendars/removeCalendar", - async ({ calId, calLink }, { rejectWithValue }) => { - try { - await removeCalendar(calLink); - return { - calId, - calLink, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const moveEventAsync = createAsyncThunk< - { calId: string; events: CalendarEvent[] }, - { cal: Calendar; newEvent: CalendarEvent; newURL: string }, - { rejectValue: RejectedError } ->( - "calendars/moveEvent", - async ({ cal, newEvent, newURL }, { rejectWithValue }) => { - try { - await moveEvent(newEvent, newURL); - - const eventDate = new Date(newEvent.start); - const { start: weekStart, end: weekEnd } = computeWeekRange(eventDate); - - const calEvents = (await getCalendar(cal.id, { - start: formatDateToYYYYMMDDTHHMMSS(weekStart), - end: formatDateToYYYYMMDDTHHMMSS(weekEnd), - })) as Record; - const events: CalendarEvent[] = calEvents._embedded["dav:item"].flatMap( - (eventdata: any) => { - const vevents = eventdata.data[2] as any[][]; - const eventURL = eventdata._links.self.href; - return vevents.map((vevent: any[]) => { - return parseCalendarEvent( - vevent[1], - cal.color ?? {}, - cal.id, - eventURL - ); - }); - } - ); - - return { - calId: cal.id, - events, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const patchACLCalendarAsync = createAsyncThunk< - { - calId: string; - calLink: string; - request: string; - }, - { - calId: string; - calLink: string; - request: string; - }, - { rejectValue: RejectedError } ->( - "calendars/requestACLCalendar", - async ({ calId, calLink, request }, { rejectWithValue }) => { - try { - const response = await updateAclCalendar(calLink, request); - return { - calId, - calLink, - request, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const deleteEventAsync = createAsyncThunk< - { calId: string; eventId: string }, - { calId: string; eventId: string; eventURL: string }, - { rejectValue: RejectedError } ->( - "calendars/delEvent", - async ({ calId, eventId, eventURL }, { rejectWithValue }) => { - try { - await deleteEvent(eventURL); - return { calId, eventId }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const deleteEventInstanceAsync = createAsyncThunk< - { calId: string; eventId: string }, - { cal: Calendar; event: CalendarEvent }, - { rejectValue: RejectedError } ->("calendars/delEventInstance", async ({ cal, event }, { rejectWithValue }) => { - try { - await deleteEventInstance(event, cal.ownerEmails?.[0]); - return { calId: cal.id, eventId: event.uid }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } -}); - -export const updateEventInstanceAsync = createAsyncThunk< - { calId: string; event: CalendarEvent }, - { cal: Calendar; event: CalendarEvent }, - { rejectValue: RejectedError } ->( - "calendars/updateEventInstance", - async ({ cal, event }, { rejectWithValue }) => { - try { - await putEventWithOverrides(event, cal.ownerEmails?.[0]); - return { calId: cal.id, event }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const updateSeriesAsync = createAsyncThunk< - void, - { cal: Calendar; event: CalendarEvent; removeOverrides?: boolean }, - { rejectValue: RejectedError } ->( - "calendars/updateSeries", - async ({ cal, event, removeOverrides = true }, { rejectWithValue }) => { - try { - await updateSeries(event, cal.ownerEmails?.[0], removeOverrides); - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const createCalendarAsync = createAsyncThunk< - { - userId: string; - calId: string; - color: Record; - name: string; - desc: string; - owner: string; - ownerEmails: string[]; - }, - { - userId: string; - calId: string; - color: Record; - name: string; - desc: string; - }, - { rejectValue: RejectedError } ->( - "calendars/createCalendar", - async ({ userId, calId, color, name, desc }, { rejectWithValue }) => { - try { - await postCalendar(userId, calId, color, name, desc); - const ownerData: any = await getUserDetails(userId.split("/")[0]); - - return { - userId, - calId, - color, - name, - desc, - owner: `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ - ownerData.lastname - }`, - ownerEmails: ownerData.emails, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const addSharedCalendarAsync = createAsyncThunk< - { - calId: string; - color: Record; - link: string; - name: string; - desc: string; - owner: string; - ownerEmails: string[]; - }, - { userId: string; calId: string; cal: Record }, - { rejectValue: RejectedError } ->( - "calendars/addSharedCalendar", - async ({ userId, calId, cal }, { rejectWithValue }) => { - try { - await addSharedCalendar(userId, calId, cal); - const ownerData: any = await getUserDetails( - cal.cal._links.self.href - .replace("/calendars/", "") - .replace(".json", "") - .split("/")[0] - ); - - return { - calId: cal.cal._links.self.href - .replace("/calendars/", "") - .replace(".json", ""), - color: cal.color, - link: `/calendars/${userId}/${calId}.json`, - desc: cal.cal["caldav:description"], - name: - ownerData.id !== userId && cal.cal["dav:name"] === "#default" - ? `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ - ownerData.lastname - }` + "'s calendar" - : cal.cal["dav:name"], - owner: `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ - ownerData.lastname - }`, - ownerEmails: ownerData.emails, - }; - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } - } -); - -export const importEventFromFileAsync = createAsyncThunk< - void, - { - calLink: string; - file: File; - }, - { rejectValue: RejectedError } ->("calendars/importEvent", async ({ calLink, file }, { rejectWithValue }) => { - try { - const id = ((await importFile(file)) as Record)._id; - const response = await importEventFromFile(id, calLink); - } catch (err: any) { - return rejectWithValue({ - message: formatReduxError(err), - status: err.response?.status, - }); - } -}); - const CalendarSlice = createSlice({ name: "calendars", initialState: { diff --git a/src/features/Calendars/api/fetchSyncTokenChanges.ts b/src/features/Calendars/api/fetchSyncTokenChanges.ts index 15b984a..a51a3ea 100644 --- a/src/features/Calendars/api/fetchSyncTokenChanges.ts +++ b/src/features/Calendars/api/fetchSyncTokenChanges.ts @@ -1,4 +1,4 @@ -import { api } from "../../../utils/apiUtils"; +import { api } from "@/utils/apiUtils"; import { Calendar } from "../CalendarTypes"; import { DavSyncResponse } from "./types"; diff --git a/src/features/Calendars/services/addSharedCalendarAsync.ts b/src/features/Calendars/services/addSharedCalendarAsync.ts new file mode 100644 index 0000000..686a99a --- /dev/null +++ b/src/features/Calendars/services/addSharedCalendarAsync.ts @@ -0,0 +1,56 @@ +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { getUserDetails } from "@/features/User/userAPI"; +import { addSharedCalendar } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; + +export const addSharedCalendarAsync = createAsyncThunk< + { + calId: string; + color: Record; + link: string; + name: string; + desc: string; + owner: string; + ownerEmails: string[]; + }, + { userId: string; calId: string; cal: Record }, + { rejectValue: RejectedError } +>( + "calendars/addSharedCalendar", + async ({ userId, calId, cal }, { rejectWithValue }) => { + try { + await addSharedCalendar(userId, calId, cal); + const ownerData: any = await getUserDetails( + cal.cal._links.self.href + .replace("/calendars/", "") + .replace(".json", "") + .split("/")[0] + ); + + return { + calId: cal.cal._links.self.href + .replace("/calendars/", "") + .replace(".json", ""), + color: cal.color, + link: `/calendars/${userId}/${calId}.json`, + desc: cal.cal["caldav:description"], + name: + ownerData.id !== userId && cal.cal["dav:name"] === "#default" + ? `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ + ownerData.lastname + }` + "'s calendar" + : cal.cal["dav:name"], + owner: `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ + ownerData.lastname + }`, + ownerEmails: ownerData.emails, + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/createCalendarAsync.ts b/src/features/Calendars/services/createCalendarAsync.ts new file mode 100644 index 0000000..e8b2361 --- /dev/null +++ b/src/features/Calendars/services/createCalendarAsync.ts @@ -0,0 +1,50 @@ +import { getUserDetails } from "@/features/User/userAPI"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { postCalendar } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; + +export const createCalendarAsync = createAsyncThunk< + { + userId: string; + calId: string; + color: Record; + name: string; + desc: string; + owner: string; + ownerEmails: string[]; + }, + { + userId: string; + calId: string; + color: Record; + name: string; + desc: string; + }, + { rejectValue: RejectedError } +>( + "calendars/createCalendar", + async ({ userId, calId, color, name, desc }, { rejectWithValue }) => { + try { + await postCalendar(userId, calId, color, name, desc); + const ownerData: any = await getUserDetails(userId.split("/")[0]); + + return { + userId, + calId, + color, + name, + desc, + owner: [ownerData.firstname, ownerData.lastname] + .filter(Boolean) + .join(" "), + ownerEmails: ownerData.emails ?? [], + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/deleteEventAsync.ts b/src/features/Calendars/services/deleteEventAsync.ts new file mode 100644 index 0000000..52ebbd6 --- /dev/null +++ b/src/features/Calendars/services/deleteEventAsync.ts @@ -0,0 +1,23 @@ +import { deleteEvent } from "@/features/Events/EventApi"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { RejectedError } from "../CalendarSlice"; + +export const deleteEventAsync = createAsyncThunk< + { calId: string; eventId: string }, + { calId: string; eventId: string; eventURL: string }, + { rejectValue: RejectedError } +>( + "calendars/delEvent", + async ({ calId, eventId, eventURL }, { rejectWithValue }) => { + try { + await deleteEvent(eventURL); + return { calId, eventId }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/deleteEventInstanceAsync.ts b/src/features/Calendars/services/deleteEventInstanceAsync.ts new file mode 100644 index 0000000..f879b89 --- /dev/null +++ b/src/features/Calendars/services/deleteEventInstanceAsync.ts @@ -0,0 +1,22 @@ +import { deleteEventInstance } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { RejectedError } from "../CalendarSlice"; +import { Calendar } from "../CalendarTypes"; + +export const deleteEventInstanceAsync = createAsyncThunk< + { calId: string; eventId: string }, + { cal: Calendar; event: CalendarEvent }, + { rejectValue: RejectedError } +>("calendars/delEventInstance", async ({ cal, event }, { rejectWithValue }) => { + try { + await deleteEventInstance(event, cal.ownerEmails?.[0]); + return { calId: cal.id, eventId: event.uid }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } +}); diff --git a/src/features/Calendars/services/getCalendarDetailAsync.ts b/src/features/Calendars/services/getCalendarDetailAsync.ts index 1b2c6cc..532bc76 100644 --- a/src/features/Calendars/services/getCalendarDetailAsync.ts +++ b/src/features/Calendars/services/getCalendarDetailAsync.ts @@ -1,6 +1,6 @@ +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatReduxError } from "@/utils/errorUtils"; import { createAsyncThunk } from "@reduxjs/toolkit"; -import { formatReduxError } from "../../../utils/errorUtils"; -import { CalendarEvent } from "../../Events/EventsTypes"; import { getCalendar } from "../CalendarApi"; import { RejectedError } from "../CalendarSlice"; import { extractCalendarEvents } from "../utils/extractCalendarEvents"; diff --git a/src/features/Calendars/services/getCalendarsListAsync.ts b/src/features/Calendars/services/getCalendarsListAsync.ts index d68ac59..6a84296 100644 --- a/src/features/Calendars/services/getCalendarsListAsync.ts +++ b/src/features/Calendars/services/getCalendarsListAsync.ts @@ -1,6 +1,6 @@ +import { getOpenPaasUser, getUserDetails } from "@/features/User/userAPI"; +import { formatReduxError } from "@/utils/errorUtils"; import { createAsyncThunk } from "@reduxjs/toolkit"; -import { formatReduxError } from "../../../utils/errorUtils"; -import { getOpenPaasUser, getUserDetails } from "../../User/userAPI"; import { getCalendars } from "../CalendarApi"; import { RejectedError } from "../CalendarSlice"; import { Calendar } from "../CalendarTypes"; diff --git a/src/features/Calendars/services/getEventAsync.ts b/src/features/Calendars/services/getEventAsync.ts new file mode 100644 index 0000000..4989e46 --- /dev/null +++ b/src/features/Calendars/services/getEventAsync.ts @@ -0,0 +1,24 @@ +import { getEvent } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { RejectedError } from "../CalendarSlice"; + +export const getEventAsync = createAsyncThunk< + { calId: string; event: CalendarEvent }, + CalendarEvent, + { rejectValue: RejectedError } +>("calendars/getEvent", async (event, { rejectWithValue }) => { + try { + const response: CalendarEvent = await getEvent(event); + return { + calId: event.calId, + event: response, + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } +}); diff --git a/src/features/Calendars/services/getTempCalendarsListAsync.ts b/src/features/Calendars/services/getTempCalendarsListAsync.ts new file mode 100644 index 0000000..acada08 --- /dev/null +++ b/src/features/Calendars/services/getTempCalendarsListAsync.ts @@ -0,0 +1,70 @@ +import { User } from "@/components/Attendees/PeopleSearch"; +import { getCalendarVisibility } from "@/components/Calendar/utils/calendarUtils"; +import { getUserDetails } from "@/features/User/userAPI"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { getCalendars } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; +import { Calendar } from "../CalendarTypes"; + +export const getTempCalendarsListAsync = createAsyncThunk< + Record, + User, + { rejectValue: RejectedError } +>("calendars/getTempCalendars", async (tempUser, { rejectWithValue }) => { + try { + const importedCalendars: Record = {}; + + const calendars = (await getCalendars( + tempUser.openpaasId ?? "", + "sharedPublic=true&" + )) as Record; + + const rawCalendars = calendars._embedded?.["dav:calendar"]; + if (!rawCalendars || rawCalendars.length === 0) { + const userName = tempUser.displayName || tempUser.email || "User"; + // Format: TRANSLATION:key|param1=value1 + const encodedName = encodeURIComponent(userName); + throw new Error( + `TRANSLATION:calendar.userDoesNotHavePublicCalendars|name=${encodedName}` + ); + } + + for (const cal of rawCalendars) { + const name = cal["dav:name"]; + const description = cal["caldav:description"]; + const delegated = cal["calendarserver:delegatedsource"] ? true : false; + const source = cal["calendarserver:source"] + ? cal["calendarserver:source"]._links.self.href + : cal._links.self.href; + const link = cal._links.self.href; + + const id = source.replace("/calendars/", "").replace(".json", ""); + const visibility = getCalendarVisibility(cal["acl"]); + const ownerData: any = await getUserDetails(id.split("/")[0]); + + importedCalendars[id] = { + id, + name, + link, + owner: `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ownerData.lastname}`, + ownerEmails: ownerData.emails, + description, + delegated, + color: { + light: tempUser.color?.light ?? "#a8a8a8ff", + dark: tempUser.color?.dark ?? "#a8a8a8ff", + }, + visibility, + events: {}, + }; + } + + return importedCalendars; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } +}); diff --git a/src/features/Calendars/services/importEventFromFileAsync.ts b/src/features/Calendars/services/importEventFromFileAsync.ts new file mode 100644 index 0000000..cab6941 --- /dev/null +++ b/src/features/Calendars/services/importEventFromFileAsync.ts @@ -0,0 +1,31 @@ +import { importEventFromFile } from "@/features/Events/EventApi"; +import { importFile } from "@/utils/apiUtils"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { RejectedError } from "../CalendarSlice"; + +export const importEventFromFileAsync = createAsyncThunk< + void, + { + calLink: string; + file: File; + }, + { rejectValue: RejectedError } +>("calendars/importEvent", async ({ calLink, file }, { rejectWithValue }) => { + try { + const response = await importFile(file); + const id = response?._id; + if (!id) { + return rejectWithValue({ + message: "Failed to upload file: missing file ID", + status: undefined, + }); + } + await importEventFromFile(id, calLink); + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } +}); diff --git a/src/features/Calendars/services/index.ts b/src/features/Calendars/services/index.ts new file mode 100644 index 0000000..4b5f45d --- /dev/null +++ b/src/features/Calendars/services/index.ts @@ -0,0 +1,17 @@ +export { addSharedCalendarAsync } from "./addSharedCalendarAsync"; +export { createCalendarAsync } from "./createCalendarAsync"; +export { deleteEventAsync } from "./deleteEventAsync"; +export { deleteEventInstanceAsync } from "./deleteEventInstanceAsync"; +export { getCalendarDetailAsync } from "./getCalendarDetailAsync"; +export { getCalendarsListAsync } from "./getCalendarsListAsync"; +export { getEventAsync } from "./getEventAsync"; +export { getTempCalendarsListAsync } from "./getTempCalendarsListAsync"; +export { importEventFromFileAsync } from "./importEventFromFileAsync"; +export { moveEventAsync } from "./moveEventAsync"; +export { patchACLCalendarAsync } from "./patchACLCalendarAsync"; +export { patchCalendarAsync } from "./patchCalendarAsync"; +export { putEventAsync } from "./putEventAsync"; +export { refreshCalendarWithSyncToken } from "./refreshCalendar"; +export { removeCalendarAsync } from "./removeCalendarAsync"; +export { updateEventInstanceAsync } from "./updateEventInstanceAsync"; +export { updateSeriesAsync } from "./updateSeriesAsync"; diff --git a/src/features/Calendars/services/moveEventAsync.ts b/src/features/Calendars/services/moveEventAsync.ts new file mode 100644 index 0000000..a3b3362 --- /dev/null +++ b/src/features/Calendars/services/moveEventAsync.ts @@ -0,0 +1,57 @@ +import { moveEvent } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { parseCalendarEvent } from "@/features/Events/eventUtils"; +import { + computeWeekRange, + formatDateToYYYYMMDDTHHMMSS, +} from "@/utils/dateUtils"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { getCalendar } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; +import { Calendar } from "../CalendarTypes"; + +export const moveEventAsync = createAsyncThunk< + { calId: string; events: CalendarEvent[] }, + { cal: Calendar; newEvent: CalendarEvent; newURL: string }, + { rejectValue: RejectedError } +>( + "calendars/moveEvent", + async ({ cal, newEvent, newURL }, { rejectWithValue }) => { + try { + await moveEvent(newEvent, newURL); + + const eventDate = new Date(newEvent.start); + const { start: weekStart, end: weekEnd } = computeWeekRange(eventDate); + + const calEvents = (await getCalendar(cal.id, { + start: formatDateToYYYYMMDDTHHMMSS(weekStart), + end: formatDateToYYYYMMDDTHHMMSS(weekEnd), + })) as Record; + const events: CalendarEvent[] = calEvents._embedded["dav:item"].flatMap( + (eventdata: any) => { + const vevents = eventdata.data[2] as any[][]; + const eventURL = eventdata._links.self.href; + return vevents.map((vevent: any[]) => { + return parseCalendarEvent( + vevent[1], + cal.color ?? {}, + cal.id, + eventURL + ); + }); + } + ); + + return { + calId: cal.id, + events, + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/patchACLCalendarAsync.ts b/src/features/Calendars/services/patchACLCalendarAsync.ts new file mode 100644 index 0000000..93f90c9 --- /dev/null +++ b/src/features/Calendars/services/patchACLCalendarAsync.ts @@ -0,0 +1,35 @@ +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { updateAclCalendar } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; + +export const patchACLCalendarAsync = createAsyncThunk< + { + calId: string; + calLink: string; + request: string; + }, + { + calId: string; + calLink: string; + request: string; + }, + { rejectValue: RejectedError } +>( + "calendars/requestACLCalendar", + async ({ calId, calLink, request }, { rejectWithValue }) => { + try { + await updateAclCalendar(calLink, request); + return { + calId, + calLink, + request, + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/patchCalendarAsync.ts b/src/features/Calendars/services/patchCalendarAsync.ts new file mode 100644 index 0000000..1007208 --- /dev/null +++ b/src/features/Calendars/services/patchCalendarAsync.ts @@ -0,0 +1,35 @@ +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { proppatchCalendar } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; + +export const patchCalendarAsync = createAsyncThunk< + { + calId: string; + calLink: string; + patch: { name: string; desc: string; color: Record }; + }, + { + calId: string; + calLink: string; + patch: { name: string; desc: string; color: Record }; + }, + { rejectValue: RejectedError } +>( + "calendars/patchCalendar", + async ({ calId, calLink, patch }, { rejectWithValue }) => { + try { + await proppatchCalendar(calLink, patch); + return { + calId, + calLink, + patch, + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/putEventAsync.ts b/src/features/Calendars/services/putEventAsync.ts new file mode 100644 index 0000000..45ebfde --- /dev/null +++ b/src/features/Calendars/services/putEventAsync.ts @@ -0,0 +1,63 @@ +import { putEvent } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { parseCalendarEvent } from "@/features/Events/eventUtils"; +import { + computeWeekRange, + formatDateToYYYYMMDDTHHMMSS, +} from "@/utils/dateUtils"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { getCalendar } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; +import { Calendar } from "../CalendarTypes"; + +export const putEventAsync = createAsyncThunk< + { calId: string; events: CalendarEvent[]; calType?: "temp" }, + { cal: Calendar; newEvent: CalendarEvent; calType?: "temp" }, + { rejectValue: RejectedError } +>( + "calendars/putEvent", + async ({ cal, newEvent, calType }, { rejectWithValue }) => { + try { + await putEvent( + newEvent, + cal.ownerEmails ? cal.ownerEmails[0] : undefined + ); + const eventDate = new Date(newEvent.start); + + const { start: weekStart, end: weekEnd } = computeWeekRange(eventDate); + + const calEvents = (await getCalendar(cal.id, { + start: formatDateToYYYYMMDDTHHMMSS(weekStart), + end: formatDateToYYYYMMDDTHHMMSS(weekEnd), + })) as Record; + const events: CalendarEvent[] = calEvents._embedded["dav:item"].flatMap( + (eventdata: any) => { + const vevents = eventdata.data[2] as any[][]; + const eventURL = eventdata._links.self.href; + const valarm = eventdata.data[2][0][2][0]; + return vevents.map((vevent: any[]) => { + return parseCalendarEvent( + vevent[1], + cal.color ?? {}, + cal.id, + eventURL, + valarm + ); + }); + } + ); + + return { + calId: cal.id, + events, + calType, + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/refreshCalendar.ts b/src/features/Calendars/services/refreshCalendar.ts index e6ecf2e..54bfeb8 100644 --- a/src/features/Calendars/services/refreshCalendar.ts +++ b/src/features/Calendars/services/refreshCalendar.ts @@ -1,7 +1,7 @@ +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatReduxError } from "@/utils/errorUtils"; import { createAsyncThunk } from "@reduxjs/toolkit"; import pMap from "p-map"; -import { formatReduxError } from "../../../utils/errorUtils"; -import { CalendarEvent } from "../../Events/EventsTypes"; import { fetchSyncTokenChanges } from "../api/fetchSyncTokenChanges"; import { RejectedError } from "../CalendarSlice"; import { Calendar } from "../CalendarTypes"; diff --git a/src/features/Calendars/services/removeCalendarAsync.ts b/src/features/Calendars/services/removeCalendarAsync.ts new file mode 100644 index 0000000..e51b0cc --- /dev/null +++ b/src/features/Calendars/services/removeCalendarAsync.ts @@ -0,0 +1,30 @@ +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { removeCalendar } from "../CalendarApi"; +import { RejectedError } from "../CalendarSlice"; + +export const removeCalendarAsync = createAsyncThunk< + { + calId: string; + }, + { + calId: string; + calLink: string; + }, + { rejectValue: RejectedError } +>( + "calendars/removeCalendar", + async ({ calId, calLink }, { rejectWithValue }) => { + try { + await removeCalendar(calLink); + return { + calId, + }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/updateEventInstanceAsync.ts b/src/features/Calendars/services/updateEventInstanceAsync.ts new file mode 100644 index 0000000..8c2bc2e --- /dev/null +++ b/src/features/Calendars/services/updateEventInstanceAsync.ts @@ -0,0 +1,25 @@ +import { putEventWithOverrides } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { RejectedError } from "../CalendarSlice"; +import { Calendar } from "../CalendarTypes"; + +export const updateEventInstanceAsync = createAsyncThunk< + { calId: string; event: CalendarEvent }, + { cal: Calendar; event: CalendarEvent }, + { rejectValue: RejectedError } +>( + "calendars/updateEventInstance", + async ({ cal, event }, { rejectWithValue }) => { + try { + await putEventWithOverrides(event, cal.ownerEmails?.[0]); + return { calId: cal.id, event }; + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/services/updateSeriesAsync.ts b/src/features/Calendars/services/updateSeriesAsync.ts new file mode 100644 index 0000000..0eef646 --- /dev/null +++ b/src/features/Calendars/services/updateSeriesAsync.ts @@ -0,0 +1,24 @@ +import { updateSeries } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatReduxError } from "@/utils/errorUtils"; +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { RejectedError } from "../CalendarSlice"; +import { Calendar } from "../CalendarTypes"; + +export const updateSeriesAsync = createAsyncThunk< + void, + { cal: Calendar; event: CalendarEvent; removeOverrides?: boolean }, + { rejectValue: RejectedError } +>( + "calendars/updateSeries", + async ({ cal, event, removeOverrides = true }, { rejectWithValue }) => { + try { + await updateSeries(event, cal.ownerEmails?.[0] ?? "", removeOverrides); + } catch (err: any) { + return rejectWithValue({ + message: formatReduxError(err), + status: err.response?.status, + }); + } + } +); diff --git a/src/features/Calendars/utils/expandEventFunction.ts b/src/features/Calendars/utils/expandEventFunction.ts index 45d8092..eac2893 100644 --- a/src/features/Calendars/utils/expandEventFunction.ts +++ b/src/features/Calendars/utils/expandEventFunction.ts @@ -1,6 +1,6 @@ -import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils"; -import { reportEvent } from "../../Events/EventApi"; -import { CalendarEvent } from "../../Events/EventsTypes"; +import { reportEvent } from "@/features/Events/EventApi"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { formatDateToYYYYMMDDTHHMMSS } from "@/utils/dateUtils"; import { Calendar } from "../CalendarTypes"; import { extractCalendarEvents } from "./extractCalendarEvents"; diff --git a/src/features/Calendars/utils/extractCalendarEvents.ts b/src/features/Calendars/utils/extractCalendarEvents.ts index 2d23f6d..9acbb20 100644 --- a/src/features/Calendars/utils/extractCalendarEvents.ts +++ b/src/features/Calendars/utils/extractCalendarEvents.ts @@ -1,6 +1,6 @@ -import { defaultColors } from "../../../components/Calendar/utils/calendarColorsUtils"; -import { CalendarEvent } from "../../Events/EventsTypes"; -import { parseCalendarEvent } from "../../Events/eventUtils"; +import { defaultColors } from "@/components/Calendar/utils/calendarColorsUtils"; +import { CalendarEvent } from "@/features/Events/EventsTypes"; +import { parseCalendarEvent } from "@/features/Events/eventUtils"; import { CalDavItem } from "../api/types"; export function extractCalendarEvents( diff --git a/src/features/Calendars/utils/normalizeCalendar.ts b/src/features/Calendars/utils/normalizeCalendar.ts index e5ef9ec..37fc541 100644 --- a/src/features/Calendars/utils/normalizeCalendar.ts +++ b/src/features/Calendars/utils/normalizeCalendar.ts @@ -1,4 +1,4 @@ -import { getCalendarVisibility } from "../../../components/Calendar/utils/calendarUtils"; +import { getCalendarVisibility } from "@/components/Calendar/utils/calendarUtils"; export function normalizeCalendar(rawCalendar: Record) { const description = rawCalendar["caldav:description"]; diff --git a/src/features/Events/AttendanceValidation/AttendanceValidation.tsx b/src/features/Events/AttendanceValidation/AttendanceValidation.tsx index b1a7e5c..d70e10d 100644 --- a/src/features/Events/AttendanceValidation/AttendanceValidation.tsx +++ b/src/features/Events/AttendanceValidation/AttendanceValidation.tsx @@ -1,8 +1,8 @@ +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { userData } from "@/features/User/userDataTypes"; import { Box, Typography } from "@linagora/twake-mui"; import { Dispatch, SetStateAction } from "react"; import { useI18n } from "twake-i18n"; -import { Calendar } from "../../Calendars/CalendarTypes"; -import { userData } from "../../User/userDataTypes"; import { ContextualizedEvent } from "../EventsTypes"; import { RSVPButton } from "./RSVPButton"; diff --git a/src/features/Events/AttendanceValidation/RSVPButton.tsx b/src/features/Events/AttendanceValidation/RSVPButton.tsx index d3aab14..cf67ae8 100644 --- a/src/features/Events/AttendanceValidation/RSVPButton.tsx +++ b/src/features/Events/AttendanceValidation/RSVPButton.tsx @@ -1,10 +1,10 @@ +import { useAppDispatch } from "@/app/hooks"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { PartStat } from "@/features/User/models/attendee"; +import { userData } from "@/features/User/userDataTypes"; import { Button } from "@linagora/twake-mui"; import { Dispatch, SetStateAction } from "react"; import { useI18n } from "twake-i18n"; -import { useAppDispatch } from "../../../app/hooks"; -import { Calendar } from "../../Calendars/CalendarTypes"; -import { PartStat } from "../../User/models/attendee"; -import { userData } from "../../User/userDataTypes"; import { ContextualizedEvent } from "../EventsTypes"; import { handleRSVPClick } from "./handleRSVPClick"; diff --git a/src/features/Events/AttendanceValidation/handleRSVPClick.tsx b/src/features/Events/AttendanceValidation/handleRSVPClick.tsx index 5079990..becccf2 100644 --- a/src/features/Events/AttendanceValidation/handleRSVPClick.tsx +++ b/src/features/Events/AttendanceValidation/handleRSVPClick.tsx @@ -1,9 +1,9 @@ +import { AppDispatch } from "@/app/store"; +import { handleRSVP } from "@/components/Event/eventHandlers/eventHandlers"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; +import { PartStat } from "@/features/User/models/attendee"; +import { userData } from "@/features/User/userDataTypes"; import { Dispatch, SetStateAction } from "react"; -import { AppDispatch } from "../../../app/store"; -import { handleRSVP } from "../../../components/Event/eventHandlers/eventHandlers"; -import { Calendar } from "../../Calendars/CalendarTypes"; -import { PartStat } from "../../User/models/attendee"; -import { userData } from "../../User/userDataTypes"; import { ContextualizedEvent } from "../EventsTypes"; export async function handleRSVPClick( diff --git a/src/features/Events/EventApi.ts b/src/features/Events/EventApi.ts index a0f7909..85dbfe4 100644 --- a/src/features/Events/EventApi.ts +++ b/src/features/Events/EventApi.ts @@ -1,5 +1,10 @@ -import { api } from "../../utils/apiUtils"; -import { TIMEZONES } from "../../utils/timezone-data"; +import { detectDateTimeFormat } from "@/components/Event/utils/dateTimeHelpers"; +import { api } from "@/utils/apiUtils"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { TIMEZONES } from "@/utils/timezone-data"; +import ICAL from "ical.js"; +import moment from "moment-timezone"; +import { CalDavItem } from "../Calendars/api/types"; import { CalendarEvent } from "./EventsTypes"; import { calendarEventToJCal, @@ -7,11 +12,6 @@ import { makeVevent, parseCalendarEvent, } from "./eventUtils"; -import ICAL from "ical.js"; -import moment from "moment-timezone"; -import { detectDateTimeFormat } from "../../components/Event/utils/dateTimeHelpers"; -import { CalDavItem } from "../Calendars/api/types"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; function resolveTimezoneId(tzid?: string): string | undefined { if (!tzid) return undefined; diff --git a/src/features/Events/EventDisplayPreview.tsx b/src/features/Events/EventDisplayPreview.tsx index 22e336e..e8c4bec 100644 --- a/src/features/Events/EventDisplayPreview.tsx +++ b/src/features/Events/EventDisplayPreview.tsx @@ -1,4 +1,30 @@ +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { CalendarName } from "@/components/Calendar/CalendarName"; +import { getTimezoneOffset } from "@/components/Calendar/TimezoneSelector"; +import { + formatEventChipTitle, + updateTempCalendar, +} from "@/components/Calendar/utils/calendarUtils"; +import ResponsiveDialog from "@/components/Dialog/ResponsiveDialog"; +import { EditModeDialog } from "@/components/Event/EditModeDialog"; +import EventDuplication from "@/components/Event/EventDuplicate"; +import { handleDelete } from "@/components/Event/eventHandlers/eventHandlers"; +import { InfoRow } from "@/components/Event/InfoRow"; +import { renderAttendeeBadge } from "@/components/Event/utils/eventUtils"; +import { getCalendarRange } from "@/utils/dateUtils"; +import { browserDefaultTimeZone } from "@/utils/timezone"; import { DateSelectArg } from "@fullcalendar/core"; +import { + AvatarGroup, + Box, + Button, + Chip, + IconButton, + Menu, + MenuItem, + Tooltip, + Typography, +} from "@linagora/twake-mui"; import CalendarTodayIcon from "@mui/icons-material/CalendarToday"; import CircleIcon from "@mui/icons-material/Circle"; import CloseIcon from "@mui/icons-material/Close"; @@ -13,42 +39,16 @@ import PeopleAltOutlinedIcon from "@mui/icons-material/PeopleAltOutlined"; import RepeatIcon from "@mui/icons-material/Repeat"; import SubjectIcon from "@mui/icons-material/Subject"; import VideocamOutlinedIcon from "@mui/icons-material/VideocamOutlined"; -import { Box, Typography } from "@linagora/twake-mui"; -import EventPopover from "./EventModal"; -import { - Button, - Chip, - IconButton, - Menu, - MenuItem, - Tooltip, -} from "@linagora/twake-mui"; -import { AvatarGroup } from "@linagora/twake-mui"; -import { useEffect, useState, useRef } from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { CalendarName } from "../../components/Calendar/CalendarName"; -import { getTimezoneOffset } from "../../components/Calendar/TimezoneSelector"; -import { - formatEventChipTitle, - updateTempCalendar, -} from "../../components/Calendar/utils/calendarUtils"; -import ResponsiveDialog from "../../components/Dialog/ResponsiveDialog"; -import { EditModeDialog } from "../../components/Event/EditModeDialog"; -import EventDuplication from "../../components/Event/EventDuplicate"; -import { handleDelete } from "../../components/Event/eventHandlers/eventHandlers"; -import { InfoRow } from "../../components/Event/InfoRow"; -import { renderAttendeeBadge } from "../../components/Event/utils/eventUtils"; -import { getCalendarRange } from "../../utils/dateUtils"; -import { deleteEventAsync } from "../Calendars/CalendarSlice"; +import { useEffect, useRef, useState } from "react"; +import { useI18n } from "twake-i18n"; +import { deleteEventAsync } from "../Calendars/services"; +import { userAttendee } from "../User/models/attendee"; +import { AttendanceValidation } from "./AttendanceValidation/AttendanceValidation"; +import { createEventContext } from "./createEventContext"; import { dlEvent } from "./EventApi"; +import EventPopover from "./EventModal"; import { CalendarEvent } from "./EventsTypes"; import EventUpdateModal from "./EventUpdateModal"; -import { useI18n } from "twake-i18n"; -import { userAttendee } from "../User/models/attendee"; -import { browserDefaultTimeZone } from "../../utils/timezone"; -import { AttendanceValidation } from "./AttendanceValidation/AttendanceValidation"; -import { Calendar } from "../Calendars/CalendarTypes"; -import { createEventContext } from "./createEventContext"; export default function EventPreviewModal({ eventId, diff --git a/src/features/Events/EventModal.tsx b/src/features/Events/EventModal.tsx index 414f120..eb3ef9b 100644 --- a/src/features/Events/EventModal.tsx +++ b/src/features/Events/EventModal.tsx @@ -1,47 +1,47 @@ -import { CalendarApi, DateSelectArg } from "@fullcalendar/core"; -import { Box, Button } from "@linagora/twake-mui"; -import AddIcon from "@mui/icons-material/Add"; -import React, { - useEffect, - useState, - useMemo, - useCallback, - useRef, - startTransition, -} from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { ResponsiveDialog } from "../../components/Dialog"; -import { putEventAsync } from "../Calendars/CalendarSlice"; -import { Calendar } from "../Calendars/CalendarTypes"; -import { userAttendee } from "../User/models/attendee"; -import { CalendarEvent, RepetitionObject } from "./EventsTypes"; -import { createSelector } from "@reduxjs/toolkit"; -import { TIMEZONES } from "../../utils/timezone-data"; -import { addVideoConferenceToDescription } from "../../utils/videoConferenceUtils"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; import { getTimezoneOffset, resolveTimezone, -} from "../../components/Calendar/TimezoneSelector"; -import { getCalendarRange } from "../../utils/dateUtils"; -import { updateTempCalendar } from "../../components/Calendar/utils/calendarUtils"; -import EventFormFields from "../../components/Event/EventFormFields"; +} from "@/components/Calendar/TimezoneSelector"; +import { updateTempCalendar } from "@/components/Calendar/utils/calendarUtils"; +import { ResponsiveDialog } from "@/components/Dialog"; +import EventFormFields from "@/components/Event/EventFormFields"; +import { addDays } from "@/components/Event/utils/dateRules"; import { - formatLocalDateTime, formatDateTimeInTimezone, -} from "../../components/Event/utils/dateTimeFormatters"; -import { convertFormDateTimeToISO } from "../../components/Event/utils/dateTimeHelpers"; -import { addDays } from "../../components/Event/utils/dateRules"; -import { useI18n } from "twake-i18n"; + formatLocalDateTime, +} from "@/components/Event/utils/dateTimeFormatters"; +import { convertFormDateTimeToISO } from "@/components/Event/utils/dateTimeHelpers"; +import { getCalendarRange } from "@/utils/dateUtils"; import { - saveEventFormDataToTemp, - restoreEventFormDataFromTemp as restoreEventFormDataFromStorage, - clearEventFormTempData, - showErrorNotification, buildEventFormTempData, - restoreFormDataFromTemp, + clearEventFormTempData, EventFormState, -} from "../../utils/eventFormTempStorage"; -import { browserDefaultTimeZone } from "../../utils/timezone"; + restoreEventFormDataFromTemp as restoreEventFormDataFromStorage, + restoreFormDataFromTemp, + saveEventFormDataToTemp, + showErrorNotification, +} from "@/utils/eventFormTempStorage"; +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { TIMEZONES } from "@/utils/timezone-data"; +import { addVideoConferenceToDescription } from "@/utils/videoConferenceUtils"; +import { CalendarApi, DateSelectArg } from "@fullcalendar/core"; +import { Box, Button } from "@linagora/twake-mui"; +import AddIcon from "@mui/icons-material/Add"; +import { createSelector } from "@reduxjs/toolkit"; +import React, { + startTransition, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import { useI18n } from "twake-i18n"; +import { Calendar } from "../Calendars/CalendarTypes"; +import { putEventAsync } from "../Calendars/services"; +import { userAttendee } from "../User/models/attendee"; +import { CalendarEvent, RepetitionObject } from "./EventsTypes"; function EventPopover({ open, diff --git a/src/features/Events/EventUpdateModal.tsx b/src/features/Events/EventUpdateModal.tsx index 5c43c39..81cc05a 100644 --- a/src/features/Events/EventUpdateModal.tsx +++ b/src/features/Events/EventUpdateModal.tsx @@ -1,48 +1,50 @@ -import { Box, Button } from "@linagora/twake-mui"; -import AddIcon from "@mui/icons-material/Add"; -import { useEffect, useState, useMemo, useCallback, useRef } from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { ResponsiveDialog } from "../../components/Dialog"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { updateAttendeesAfterTimeChange } from "@/components/Calendar/handlers/eventHandlers"; +import { updateTempCalendar } from "@/components/Calendar/utils/calendarUtils"; +import { ResponsiveDialog } from "@/components/Dialog"; +import EventFormFields from "@/components/Event/EventFormFields"; +import { addDays } from "@/components/Event/utils/dateRules"; +import { formatDateTimeInTimezone } from "@/components/Event/utils/dateTimeFormatters"; +import { convertFormDateTimeToISO } from "@/components/Event/utils/dateTimeHelpers"; +import { refreshCalendars } from "@/components/Event/utils/eventUtils"; import { - putEventAsync, - removeEvent, moveEventAsync, + putEventAsync, updateEventInstanceAsync, updateSeriesAsync, - updateEventLocal, +} from "@/features/Calendars/services"; +import { getCalendarRange } from "@/utils/dateUtils"; +import { + buildEventFormTempData, + clearEventFormTempData, + EventFormContext, + EventFormState, + restoreEventFormDataFromTemp as restoreEventFormDataFromStorage, + restoreFormDataFromTemp, + saveEventFormDataToTemp, + showErrorNotification, +} from "@/utils/eventFormTempStorage"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { TIMEZONES } from "@/utils/timezone-data"; +import { addVideoConferenceToDescription } from "@/utils/videoConferenceUtils"; +import { Box, Button } from "@linagora/twake-mui"; +import AddIcon from "@mui/icons-material/Add"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useI18n } from "twake-i18n"; +import { clearFetchCache, + removeEvent, + updateEventLocal, } from "../Calendars/CalendarSlice"; import { Calendar } from "../Calendars/CalendarTypes"; import { userAttendee } from "../User/models/attendee"; +import { deleteEvent, getEvent, putEvent } from "./EventApi"; import { CalendarEvent, RepetitionObject } from "./EventsTypes"; -import { TIMEZONES } from "../../utils/timezone-data"; -import { addVideoConferenceToDescription } from "../../utils/videoConferenceUtils"; -import EventFormFields from "../../components/Event/EventFormFields"; -import { formatDateTimeInTimezone } from "../../components/Event/utils/dateTimeFormatters"; -import { addDays } from "../../components/Event/utils/dateRules"; -import { getEvent, deleteEvent, putEvent } from "./EventApi"; -import { refreshCalendars } from "../../components/Event/utils/eventUtils"; -import { getCalendarRange } from "../../utils/dateUtils"; import { combineMasterDateWithFormTime, detectRecurringEventChanges, } from "./eventUtils"; -import { updateTempCalendar } from "../../components/Calendar/utils/calendarUtils"; -import { useI18n } from "twake-i18n"; -import { updateAttendeesAfterTimeChange } from "../../components/Calendar/handlers/eventHandlers"; -import { convertFormDateTimeToISO } from "../../components/Event/utils/dateTimeHelpers"; -import { - saveEventFormDataToTemp, - restoreEventFormDataFromTemp as restoreEventFormDataFromStorage, - clearEventFormTempData, - showErrorNotification, - buildEventFormTempData, - restoreFormDataFromTemp, - EventFormState, - EventFormContext, -} from "../../utils/eventFormTempStorage"; -import { browserDefaultTimeZone } from "../../utils/timezone"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; function EventUpdateModal({ eventId, diff --git a/src/features/Events/EventsTypes.ts b/src/features/Events/EventsTypes.ts index bb477f1..de0e449 100644 --- a/src/features/Events/EventsTypes.ts +++ b/src/features/Events/EventsTypes.ts @@ -18,7 +18,7 @@ export interface CalendarEvent { organizer?: userOrganiser; attendee: userAttendee[]; stamp?: string; - sequence?: Number; + sequence?: number; color?: Record; allday?: boolean; error?: string; diff --git a/src/features/Events/ImportAlert.tsx b/src/features/Events/ImportAlert.tsx index ba6d27c..d3e9fe5 100644 --- a/src/features/Events/ImportAlert.tsx +++ b/src/features/Events/ImportAlert.tsx @@ -1,6 +1,6 @@ -import { useState, useMemo, useEffect } from "react"; -import { useAppSelector } from "../../app/hooks"; -import { EventErrorSnackbar } from "../../components/Error/ErrorSnackbar"; +import { useAppSelector } from "@/app/hooks"; +import { EventErrorSnackbar } from "@/components/Error/ErrorSnackbar"; +import { useMemo, useState } from "react"; export default function ImportAlert() { const calendars = useAppSelector((state) => state.calendars.list); diff --git a/src/features/Events/eventUtils.ts b/src/features/Events/eventUtils.ts index a04f076..acd139d 100644 --- a/src/features/Events/eventUtils.ts +++ b/src/features/Events/eventUtils.ts @@ -1,14 +1,14 @@ -import { userAttendee } from "../User/models/attendee"; -import { AlarmObject, CalendarEvent, RepetitionObject } from "./EventsTypes"; -import ICAL from "ical.js"; -import { TIMEZONES } from "../../utils/timezone-data"; -import moment from "moment-timezone"; import { convertFormDateTimeToISO, detectDateTimeFormat, -} from "../../components/Event/utils/dateTimeHelpers"; +} from "@/components/Event/utils/dateTimeHelpers"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { TIMEZONES } from "@/utils/timezone-data"; +import ICAL from "ical.js"; +import moment from "moment-timezone"; +import { userAttendee } from "../User/models/attendee"; import { createAttendee } from "../User/models/attendee.mapper"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; +import { AlarmObject, CalendarEvent, RepetitionObject } from "./EventsTypes"; type RawEntry = [string, Record, string, any]; function resolveTimezoneId(tzid?: string): string | undefined { diff --git a/src/features/Events/formHelpers.ts b/src/features/Events/formHelpers.ts index 3acef53..659e64e 100644 --- a/src/features/Events/formHelpers.ts +++ b/src/features/Events/formHelpers.ts @@ -1,11 +1,11 @@ -import { TIMEZONES } from "../../utils/timezone-data"; -import { resolveTimezone } from "../../components/Calendar/TimezoneSelector"; -import { CalendarEvent, RepetitionObject } from "./EventsTypes"; +import { resolveTimezone } from "@/components/Calendar/TimezoneSelector"; +import { formatDateTimeInTimezone } from "@/components/Event/utils/dateTimeFormatters"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { TIMEZONES } from "@/utils/timezone-data"; +import { addVideoConferenceToDescription } from "@/utils/videoConferenceUtils"; import { userAttendee } from "../User/models/attendee"; -import { formatDateTimeInTimezone } from "../../components/Event/utils/dateTimeFormatters"; -import { addVideoConferenceToDescription } from "../../utils/videoConferenceUtils"; -import { browserDefaultTimeZone } from "../../utils/timezone"; -import { extractEventBaseUuid } from "../../utils/extractEventBaseUuid"; +import { CalendarEvent, RepetitionObject } from "./EventsTypes"; export interface TimezoneListResult { zones: string[]; diff --git a/src/features/Search/SearchResultsPage.tsx b/src/features/Search/SearchResultsPage.tsx index 7f02e9c..634ca8d 100644 --- a/src/features/Search/SearchResultsPage.tsx +++ b/src/features/Search/SearchResultsPage.tsx @@ -1,25 +1,24 @@ +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { AppDispatch } from "@/app/store"; +import { browserDefaultTimeZone } from "@/utils/timezone"; +import { + Box, + Button, + CircularProgress, + IconButton, + Stack, + Typography, +} from "@linagora/twake-mui"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import RepeatIcon from "@mui/icons-material/Repeat"; import SquareRoundedIcon from "@mui/icons-material/SquareRounded"; import VideocamIcon from "@mui/icons-material/Videocam"; -import { - Box, - Button, - IconButton, - Stack, - Typography, - CircularProgress, -} from "@linagora/twake-mui"; -import { useI18n } from "twake-i18n"; import { useState } from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { AppDispatch } from "../../app/store"; +import { useI18n } from "twake-i18n"; import logo from "../../static/noResult-logo.svg"; -import { browserDefaultTimeZone } from "../../utils/timezone"; -import { getEventAsync } from "../Calendars/CalendarSlice"; +import { getEventAsync } from "../Calendars/services"; import EventPreviewModal from "../Events/EventDisplayPreview"; import { CalendarEvent } from "../Events/EventsTypes"; - import { setView } from "../Settings/SettingsSlice"; import "./searchResult.styl"; diff --git a/src/features/Search/SearchSlice.ts b/src/features/Search/SearchSlice.ts index f3449a3..3bd6d8d 100644 --- a/src/features/Search/SearchSlice.ts +++ b/src/features/Search/SearchSlice.ts @@ -1,5 +1,5 @@ +import { formatReduxError } from "@/utils/errorUtils"; import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { formatReduxError } from "../../utils/errorUtils"; import { searchEvent } from "../Events/EventApi"; export interface SearchResultsState { diff --git a/src/features/Settings/SettingsPage.tsx b/src/features/Settings/SettingsPage.tsx index e01112a..de39794 100644 --- a/src/features/Settings/SettingsPage.tsx +++ b/src/features/Settings/SettingsPage.tsx @@ -1,48 +1,47 @@ -import React, { useState } from "react"; +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { + getTimezoneOffset, + useTimeZoneList, +} from "@/components/Calendar/TimezoneSelector"; +import { TimezoneAutocomplete } from "@/components/Timezone/TimezoneAutocomplete"; +import { browserDefaultTimeZone } from "@/utils/timezone"; import { Box, + FormControl, + FormControlLabel, + IconButton, List, ListItem, ListItemIcon, ListItemText, - Tabs, - Tab, - IconButton, - FormControl, - Select, MenuItem, - Typography, + Select, Snackbar, Switch, - FormControlLabel, + Tab, + Tabs, + Typography, } from "@linagora/twake-mui"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import SettingsIcon from "@mui/icons-material/Settings"; -// import SyncIcon from "@mui/icons-material/Sync"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; +import React, { useState } from "react"; +import { useI18n } from "twake-i18n"; import { - setView, - setLanguage as setSettingsLanguage, - setTimeZone as setSettingsTimeZone, - setIsBrowserDefaultTimeZone, - setHideDeclinedEvents, - setDisplayWeekNumbers, -} from "./SettingsSlice"; -import { - updateUserConfigurationsAsync, + setAlarmEmails, setLanguage as setUserLanguage, setTimezone as setUserTimeZone, - setAlarmEmails, + updateUserConfigurationsAsync, } from "../User/userSlice"; import { AVAILABLE_LANGUAGES } from "./constants"; -import { useI18n } from "twake-i18n"; import "./SettingsPage.styl"; import { - useTimeZoneList, - getTimezoneOffset, -} from "../../components/Calendar/TimezoneSelector"; -import { TimezoneAutocomplete } from "../../components/Timezone/TimezoneAutocomplete"; -import { browserDefaultTimeZone } from "../../utils/timezone"; + setDisplayWeekNumbers, + setHideDeclinedEvents, + setIsBrowserDefaultTimeZone, + setLanguage as setSettingsLanguage, + setTimeZone as setSettingsTimeZone, + setView, +} from "./SettingsSlice"; type SidebarNavItem = "settings" | "sync"; type SettingsSubTab = "settings" | "notifications"; diff --git a/src/features/Settings/SettingsSlice.ts b/src/features/Settings/SettingsSlice.ts index 51bfe2b..c956c38 100644 --- a/src/features/Settings/SettingsSlice.ts +++ b/src/features/Settings/SettingsSlice.ts @@ -1,5 +1,5 @@ +import { browserDefaultTimeZone } from "@/utils/timezone"; import { createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { browserDefaultTimeZone } from "../../utils/timezone"; import { getOpenPaasUserDataAsync } from "../User/userSlice"; export interface SettingsState { diff --git a/src/features/User/HandleLogin.tsx b/src/features/User/HandleLogin.tsx index 26fcdc5..923d93e 100644 --- a/src/features/User/HandleLogin.tsx +++ b/src/features/User/HandleLogin.tsx @@ -1,11 +1,11 @@ +import { useAppDispatch, useAppSelector } from "@/app/hooks"; +import { Loading } from "@/components/Loading/Loading"; +import { redirectTo } from "@/utils/apiUtils"; import { useEffect, useRef } from "react"; -import { useAppDispatch, useAppSelector } from "../../app/hooks"; -import { Auth } from "./oidcAuth"; -import { Loading } from "../../components/Loading/Loading"; import { push } from "redux-first-history"; -import { redirectTo } from "../../utils/apiUtils"; +import { getCalendarsListAsync } from "../Calendars/services"; +import { Auth } from "./oidcAuth"; import { getOpenPaasUserDataAsync, setTokens, setUserData } from "./userSlice"; -import { getCalendarsListAsync } from "../Calendars/services/getCalendarsListAsync"; export function HandleLogin() { const userData = useAppSelector((state) => state.user); diff --git a/src/features/User/LoginCallback.tsx b/src/features/User/LoginCallback.tsx index f3e1df0..49dc2ff 100644 --- a/src/features/User/LoginCallback.tsx +++ b/src/features/User/LoginCallback.tsx @@ -1,15 +1,15 @@ +import { useAppDispatch } from "@/app/hooks"; +import { Loading } from "@/components/Loading/Loading"; import { useEffect, useRef } from "react"; -import { Callback } from "./oidcAuth"; -import { useAppDispatch } from "../../app/hooks"; import { push } from "redux-first-history"; +import { getCalendarsListAsync } from "../Calendars/services"; +import { Callback } from "./oidcAuth"; import { getOpenPaasUserDataAsync, setTokens, setUserData, setUserError, } from "./userSlice"; -import { Loading } from "../../components/Loading/Loading"; -import { getCalendarsListAsync } from "../Calendars/services/getCalendarsListAsync"; export function CallbackResume() { const dispatch = useAppDispatch(); diff --git a/src/features/User/oidcAuth.ts b/src/features/User/oidcAuth.ts index 30a68d3..eb204bf 100644 --- a/src/features/User/oidcAuth.ts +++ b/src/features/User/oidcAuth.ts @@ -1,5 +1,5 @@ import * as client from "openid-client"; -import { getLocation } from "../../utils/apiUtils"; +import { getLocation } from "@/utils/apiUtils"; export const clientConfig = { url: (window as any).SSO_BASE_URL ?? "", diff --git a/src/features/User/userAPI.ts b/src/features/User/userAPI.ts index 2a21b99..19b19d7 100644 --- a/src/features/User/userAPI.ts +++ b/src/features/User/userAPI.ts @@ -1,5 +1,5 @@ -import { User } from "../../components/Attendees/PeopleSearch"; -import { api } from "../../utils/apiUtils"; +import { User } from "@/components/Attendees/PeopleSearch"; +import { api } from "@/utils/apiUtils"; export async function getOpenPaasUser() { const user = await api.get(`api/user`); diff --git a/src/features/User/userSlice.ts b/src/features/User/userSlice.ts index 7e067c4..f1c0038 100644 --- a/src/features/User/userSlice.ts +++ b/src/features/User/userSlice.ts @@ -1,11 +1,11 @@ +import { formatReduxError } from "@/utils/errorUtils"; import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; -import { userData, userOrganiser } from "./userDataTypes"; import { getOpenPaasUser, updateUserConfigurations, UserConfigurationUpdates, } from "./userAPI"; -import { formatReduxError } from "../../utils/errorUtils"; +import { userData, userOrganiser } from "./userDataTypes"; export const getOpenPaasUserDataAsync = createAsyncThunk< Record, diff --git a/src/utils/__test__/videoConferenceUtils.test.ts b/src/utils/__test__/videoConferenceUtils.test.ts index 32a105a..906c99c 100644 --- a/src/utils/__test__/videoConferenceUtils.test.ts +++ b/src/utils/__test__/videoConferenceUtils.test.ts @@ -1,8 +1,8 @@ import { - generateMeetingId, - generateMeetingLink, addVideoConferenceToDescription, extractVideoConferenceFromDescription, + generateMeetingId, + generateMeetingLink, } from "../videoConferenceUtils"; // Mock window object for Node.js environment diff --git a/src/utils/apiUtils.ts b/src/utils/apiUtils.ts index ae788e7..98efaf0 100644 --- a/src/utils/apiUtils.ts +++ b/src/utils/apiUtils.ts @@ -1,5 +1,5 @@ +import { Auth } from "@/features/User/oidcAuth"; import ky from "ky"; -import { Auth } from "../features/User/oidcAuth"; const RETRY_CONFIG = { maxRetries: 10, diff --git a/src/utils/eventFormTempStorage.ts b/src/utils/eventFormTempStorage.ts index ea7c932..7e29641 100644 --- a/src/utils/eventFormTempStorage.ts +++ b/src/utils/eventFormTempStorage.ts @@ -1,5 +1,5 @@ -import { RepetitionObject } from "../features/Events/EventsTypes"; -import { userAttendee } from "../features/User/models/attendee"; +import { RepetitionObject } from "@/features/Events/EventsTypes"; +import { userAttendee } from "@/features/User/models/attendee"; export interface EventFormTempData { // Form fields diff --git a/src/utils/findCalendarById.ts b/src/utils/findCalendarById.ts index fb48bd9..b7fc7a3 100644 --- a/src/utils/findCalendarById.ts +++ b/src/utils/findCalendarById.ts @@ -1,5 +1,5 @@ -import { RootState } from "../app/store"; -import { Calendar } from "../features/Calendars/CalendarTypes"; +import { RootState } from "@/app/store"; +import { Calendar } from "@/features/Calendars/CalendarTypes"; export function findCalendarById( state: Partial, diff --git a/src/utils/userUtils.ts b/src/utils/userUtils.ts index 679b37e..890b7b4 100644 --- a/src/utils/userUtils.ts +++ b/src/utils/userUtils.ts @@ -1,4 +1,4 @@ -import { userData } from "../features/User/userDataTypes"; +import { userData } from "@/features/User/userDataTypes"; /** * Get user display name for UI display diff --git a/src/websocket/api/fetchWebSocketTicket.ts b/src/websocket/api/fetchWebSocketTicket.ts index 05c6505..6efd9ff 100644 --- a/src/websocket/api/fetchWebSocketTicket.ts +++ b/src/websocket/api/fetchWebSocketTicket.ts @@ -1,4 +1,4 @@ -import { api } from "../../utils/apiUtils"; +import { api } from "@/utils/apiUtils"; import { WebSocketTicket } from "./types"; export async function fetchWebSocketTicket(): Promise { diff --git a/src/websocket/messaging/updateCalendars.ts b/src/websocket/messaging/updateCalendars.ts index 3c07419..0e28e31 100644 --- a/src/websocket/messaging/updateCalendars.ts +++ b/src/websocket/messaging/updateCalendars.ts @@ -1,6 +1,6 @@ import type { AppDispatch } from "@/app/store"; import { store } from "@/app/store"; -import { refreshCalendarWithSyncToken } from "@/features/Calendars/services/refreshCalendar"; +import { refreshCalendarWithSyncToken } from "@/features/Calendars/services"; import { findCalendarById, getDisplayedCalendarRange } from "@/utils"; import { setSelectedCalendars } from "@/utils/storage/setSelectedCalendars"; import { parseCalendarPath } from "./parseCalendarPath"; diff --git a/tsconfig.json b/tsconfig.json index 7eee235..3be2644 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,6 +22,10 @@ "@/websocket/*": ["src/websocket/*"], "@/utils": ["src/utils/index.ts"], "@/features/*": ["src/features/*"], + "@/features/Calendars/services": [ + "src/features/Calendars/services/index.ts" + ], + "@/features/Calendars/services/*": ["src/features/Calendars/services/*"], "@/app/*": ["src/app/*"] } },