Refactor imports (#470)

This commit is contained in:
Camille Moussu
2026-01-20 17:33:30 +01:00
committed by GitHub
parent aeb8670895
commit 23d50f250d
149 changed files with 1439 additions and 1374 deletions
+13 -13
View File
@@ -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() {
<Route path="/" element={<HandleLogin />} />
<Route path="/calendar" element={<CalendarLayout />} />
<Route path="/callback" element={<CallbackResume />} />
<Route path="/error" element={<Error />} />
<Route path="/error" element={<ErrorPage />} />
</Routes>
</Router>
<ErrorSnackbar error={error} type="user" />
+1 -1
View File
@@ -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<AppDispatch>();
export const useAppSelector = useSelector.withTypes<RootState>();
+5 -5
View File
@@ -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() });
+3 -3
View File
@@ -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({
+12 -10
View File
@@ -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;
+16 -17
View File
@@ -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();
+41 -42
View File
@@ -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<string, any> = {
fr: frLocale,
+2 -2
View File
@@ -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(
+6 -8
View File
@@ -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<any>(null);
+7 -7
View File
@@ -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,
+1 -1
View File
@@ -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 (
+8 -8
View File
@@ -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";
+12 -12
View File
@@ -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,
@@ -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({
+3 -5
View File
@@ -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,
+8 -8
View File
@@ -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,
+6 -8
View File
@@ -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,
+7 -10
View File
@@ -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<string, AbortController>();
+3 -3
View File
@@ -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 {
@@ -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;
@@ -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<CalendarApi | null>;
@@ -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<string, Calendar>,
theme: Theme,
dispatch: ThunkDispatch<any, any, any>
dispatch: AppDispatch
) {
Object.values(calendars).forEach((cal) => {
if (!cal?.color?.light || typeof cal.color.light !== "string") return;
@@ -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,
+2 -2
View File
@@ -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
<ResponsiveDialog
+2 -2
View File
@@ -1,16 +1,16 @@
import {
Box,
Dialog,
DialogActions,
DialogContent,
DialogContentProps,
DialogProps,
DialogTitle,
DialogTitleProps,
DialogProps,
IconButton,
Stack,
SxProps,
Theme,
Box,
} from "@linagora/twake-mui";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import CloseIcon from "@mui/icons-material/Close";
+3 -3
View File
@@ -1,5 +1,4 @@
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import ReplayIcon from "@mui/icons-material/Replay";
import { useAppDispatch, useAppSelector } from "@/app/hooks";
import {
Box,
Button,
@@ -8,9 +7,10 @@ import {
Stack,
Typography,
} from "@linagora/twake-mui";
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import ReplayIcon from "@mui/icons-material/Replay";
import { useEffect, useRef } from "react";
import { push } from "redux-first-history";
import { useAppDispatch, useAppSelector } from "../../app/hooks";
import { useI18n } from "twake-i18n";
export function Error() {
+4 -4
View File
@@ -1,7 +1,7 @@
import { Snackbar, Alert, Button } from "@linagora/twake-mui";
import { useAppDispatch } from "../../app/hooks";
import { clearError as calendarClearError } from "../../features/Calendars/CalendarSlice";
import { clearError as userClearError } from "../../features/User/userSlice";
import { useAppDispatch } from "@/app/hooks";
import { clearError as calendarClearError } from "@/features/Calendars/CalendarSlice";
import { clearError as userClearError } from "@/features/User/userSlice";
import { Alert, Button, Snackbar } from "@linagora/twake-mui";
import { useI18n } from "twake-i18n";
export function ErrorSnackbar({
+1 -1
View File
@@ -1,7 +1,7 @@
import { Box, Button, TextField } from "@linagora/twake-mui";
import { Description as DescriptionIcon } from "@mui/icons-material";
import { useI18n } from "twake-i18n";
import { FieldWithLabel } from "./components/FieldWithLabel";
import { Description as DescriptionIcon } from "@mui/icons-material";
export function AddDescButton({
showDescription,
+1 -1
View File
@@ -1,3 +1,4 @@
import { CalendarEvent } from "@/features/Events/EventsTypes";
import {
Button,
ButtonGroup,
@@ -9,7 +10,6 @@ import {
Radio,
RadioGroup,
} from "@linagora/twake-mui";
import { CalendarEvent } from "../../features/Events/EventsTypes";
import { useState } from "react";
import { useI18n } from "twake-i18n";
@@ -1,6 +1,6 @@
import { EventErrorHandler } from "@/components/Error/EventErrorHandler";
import { Card, Typography } from "@linagora/twake-mui";
import { useRef, useEffect } from "react";
import { EventErrorHandler } from "../../Error/EventErrorHandler";
import { useEffect, useRef } from "react";
export function ErrorEventChip({
event,
+1 -2
View File
@@ -6,7 +6,7 @@ import {
CardHeader,
Typography,
} from "@linagora/twake-mui";
import React, { useEffect, useRef, useState } from "react";
import { useRef } from "react";
import { stringAvatar } from "../utils/eventUtils";
import { ErrorEventChip } from "./ErrorEventChip";
import {
@@ -21,7 +21,6 @@ import {
IconDisplayConfig,
useCompactMode,
} from "./EventChipUtils";
import { SimpleEventChip } from "./SimpleEventChip";
const PRIVATE_CLASSIFICATIONS = ["PRIVATE", "CONFIDENTIAL"];
@@ -1,12 +1,12 @@
import { EventErrorHandler } from "@/components/Error/EventErrorHandler";
import { Calendar } from "@/features/Calendars/CalendarTypes";
import { userAttendee } from "@/features/User/models/attendee";
import { getContrastRatio } from "@linagora/twake-mui";
import CancelIcon from "@mui/icons-material/Cancel";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
import LockOutlineIcon from "@mui/icons-material/LockOutline";
import { Box, getContrastRatio } from "@linagora/twake-mui";
import moment from "moment";
import React, { useLayoutEffect, useState } from "react";
import { Calendar } from "../../../features/Calendars/CalendarTypes";
import { userAttendee } from "../../../features/User/models/attendee";
import { EventErrorHandler } from "../../Error/EventErrorHandler";
import { EVENT_DURATION } from "./EventChip";
const COMPACT_WIDTH_THRESHOLD = 100;
@@ -1,4 +1,3 @@
import React from "react";
import { Card, Typography } from "@linagora/twake-mui";
export function SimpleEventChip({ title }: { title: string }) {
+1 -1
View File
@@ -1,5 +1,5 @@
import { CalendarEvent } from "@/features/Events/EventsTypes";
import { MenuItem } from "@linagora/twake-mui";
import { CalendarEvent } from "../../features/Events/EventsTypes";
import { useI18n } from "twake-i18n";
export default function EventDuplication({
+21 -26
View File
@@ -1,4 +1,11 @@
import React from "react";
import { Calendar } from "@/features/Calendars/CalendarTypes";
import { RepetitionObject } from "@/features/Events/EventsTypes";
import { userAttendee } from "@/features/User/models/attendee";
import iconCamera from "@/static/images/icon-camera.svg";
import {
addVideoConferenceToDescription,
generateMeetingLink,
} from "@/utils/videoConferenceUtils";
import {
Box,
Button,
@@ -6,45 +13,33 @@ import {
FormControl,
FormControlLabel,
IconButton,
InputLabel,
MenuItem,
Select,
SelectChangeEvent,
TextField,
ToggleButtonGroup,
ToggleButton,
ToggleButtonGroup,
Typography,
} from "@linagora/twake-mui";
import {
Description as DescriptionIcon,
Public as PublicIcon,
VideocamOutlined as VideocamOutlinedIcon,
ContentCopy as CopyIcon,
Close as DeleteIcon,
ContentCopy as CopyIcon,
Public as PublicIcon,
} from "@mui/icons-material";
import iconCamera from "../../static/images/icon-camera.svg";
import LockOutlineIcon from "@mui/icons-material/LockOutline";
import AttendeeSelector from "../Attendees/AttendeeSearch";
import RepeatEvent from "./EventRepeat";
import { RepetitionObject } from "../../features/Events/EventsTypes";
import { userAttendee } from "../../features/User/models/attendee";
import { Calendar } from "../../features/Calendars/CalendarTypes";
import {
generateMeetingLink,
addVideoConferenceToDescription,
} from "../../utils/videoConferenceUtils";
import { TimezoneAutocomplete } from "../Timezone/TimezoneAutocomplete";
import { CalendarItemList } from "../Calendar/CalendarItemList";
import React from "react";
import { useI18n } from "twake-i18n";
import { FieldWithLabel } from "./components/FieldWithLabel";
import { DateTimeFields } from "./components/DateTimeFields";
import { useAllDayToggle } from "./hooks/useAllDayToggle";
import { splitDateTime, combineDateTime } from "./utils/dateTimeHelpers";
import {} from "./utils/dateRules";
import {} from "./utils/dateTimeFormatters";
import { validateEventForm } from "./utils/formValidation";
import AttendeeSelector from "../Attendees/AttendeeSearch";
import { CalendarItemList } from "../Calendar/CalendarItemList";
import { SnackbarAlert } from "../Loading/SnackBarAlert";
import { TimezoneAutocomplete } from "../Timezone/TimezoneAutocomplete";
import { AddDescButton } from "./AddDescButton";
import { DateTimeFields } from "./components/DateTimeFields";
import { FieldWithLabel } from "./components/FieldWithLabel";
import RepeatEvent from "./EventRepeat";
import { useAllDayToggle } from "./hooks/useAllDayToggle";
import { combineDateTime, splitDateTime } from "./utils/dateTimeHelpers";
import { validateEventForm } from "./utils/formValidation";
interface EventFormFieldsProps {
// Form state
+8 -8
View File
@@ -1,20 +1,20 @@
import { RepetitionObject } from "@/features/Events/EventsTypes";
import {
FormControl,
Select,
SelectChangeEvent,
MenuItem,
Box,
Stack,
Typography,
TextField,
Checkbox,
FormControl,
FormControlLabel,
FormGroup,
MenuItem,
Radio,
RadioGroup,
Select,
SelectChangeEvent,
Stack,
TextField,
Typography,
} from "@linagora/twake-mui";
import { useEffect, useState } from "react";
import { RepetitionObject } from "../../features/Events/EventsTypes";
import { useI18n } from "twake-i18n";
export default function RepeatEvent({
+1 -1
View File
@@ -1,5 +1,5 @@
import { Box, Link, Typography } from "@linagora/twake-mui";
import React from "react";
import { Box, Typography, Link } from "@linagora/twake-mui";
type InfoRowProps = {
icon: React.ReactNode;
@@ -1,25 +1,27 @@
import React, { useMemo } from "react";
import { Box, Typography } from "@linagora/twake-mui";
import { TextFieldProps } from "@linagora/twake-mui";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { DatePickerFieldProps } from "@mui/x-date-pickers/DatePicker";
import { TimePicker } from "@mui/x-date-pickers/TimePicker";
import { TimePickerFieldProps } from "@mui/x-date-pickers/TimePicker";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { Box, TextFieldProps, Typography } from "@linagora/twake-mui";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import {
DatePicker,
DatePickerFieldProps,
} from "@mui/x-date-pickers/DatePicker";
import { PickerValue } from "@mui/x-date-pickers/internals";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import {
TimePicker,
TimePickerFieldProps,
} from "@mui/x-date-pickers/TimePicker";
import dayjs, { Dayjs } from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";
import { useI18n } from "twake-i18n";
import { LONG_DATE_FORMAT } from "../utils/dateTimeFormatters";
import "dayjs/locale/fr";
import "dayjs/locale/en";
import "dayjs/locale/fr";
import "dayjs/locale/ru";
import "dayjs/locale/vi";
import { PickerValue } from "@mui/x-date-pickers/internals";
import customParseFormat from "dayjs/plugin/customParseFormat";
import React, { useMemo } from "react";
import { useI18n } from "twake-i18n";
import { LONG_DATE_FORMAT } from "../utils/dateTimeFormatters";
import { dtDate, dtTime, toDateTime } from "../utils/dateTimeHelpers";
import { ReadOnlyDateField } from "./ReadOnlyPickerField";
import { EditableTimeField } from "./EditableTimeField";
import { ReadOnlyDateField } from "./ReadOnlyPickerField";
dayjs.extend(customParseFormat);
@@ -1,20 +1,20 @@
import React, { useState, useRef, useEffect, useCallback } from "react";
import { TextField } from "@linagora/twake-mui";
import {
useParsedFormat,
usePickerActionsContext,
usePickerContext,
useSplitFieldProps,
} from "@mui/x-date-pickers/hooks";
import { PickerFieldProps } from "@mui/x-date-pickers/models";
import { TimePickerFieldProps } from "@mui/x-date-pickers/TimePicker";
import {
PickerFieldAdapter,
PickerValidationScope,
useValidation,
validateTime,
} from "@mui/x-date-pickers/validation";
import {
useSplitFieldProps,
useParsedFormat,
usePickerContext,
usePickerActionsContext,
} from "@mui/x-date-pickers/hooks";
import { PickerFieldProps } from "@mui/x-date-pickers/models";
import { TimePickerFieldProps } from "@mui/x-date-pickers/TimePicker";
import dayjs, { Dayjs } from "dayjs";
import { Dayjs } from "dayjs";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { parseTimeInput } from "../utils/dateTimeHelpers";
type FieldType = "date" | "time" | "date-time";
@@ -1,5 +1,5 @@
import { Box, SxProps, Theme, Typography } from "@linagora/twake-mui";
import React from "react";
import { Box, Typography, SxProps, Theme } from "@linagora/twake-mui";
/**
* Helper component for field with label
@@ -1,18 +1,17 @@
import React from "react";
import { TextField } from "@linagora/twake-mui";
import { DatePickerFieldProps } from "@mui/x-date-pickers/DatePicker";
import {
useParsedFormat,
usePickerContext,
useSplitFieldProps,
} from "@mui/x-date-pickers/hooks";
import { PickerFieldProps } from "@mui/x-date-pickers/models";
import {
PickerFieldAdapter,
PickerValidationScope,
useValidation,
validateDate,
} from "@mui/x-date-pickers/validation";
import {
useSplitFieldProps,
useParsedFormat,
usePickerContext,
} from "@mui/x-date-pickers/hooks";
import { PickerFieldProps } from "@mui/x-date-pickers/models";
import { DatePickerFieldProps } from "@mui/x-date-pickers/DatePicker";
type FieldType = "date" | "time" | "date-time";
@@ -1,18 +1,18 @@
import { ThunkDispatch } from "@reduxjs/toolkit";
import { AppDispatch } from "@/app/store";
import { Calendar } from "@/features/Calendars/CalendarTypes";
import {
updateEventInstanceAsync,
putEventAsync,
deleteEventInstanceAsync,
deleteEventAsync,
} from "../../../features/Calendars/CalendarSlice";
import { Calendar } from "../../../features/Calendars/CalendarTypes";
import { updateSeriesPartstat } from "../../../features/Events/EventApi";
import { CalendarEvent } from "../../../features/Events/EventsTypes";
import { PartStat } from "../../../features/User/models/attendee";
import { createAttendee } from "../../../features/User/models/attendee.mapper";
import { userData } from "../../../features/User/userDataTypes";
import { buildFamilyName } from "../../../utils/buildFamilyName";
import { getCalendarRange } from "../../../utils/dateUtils";
deleteEventInstanceAsync,
putEventAsync,
updateEventInstanceAsync,
} from "@/features/Calendars/services";
import { updateSeriesPartstat } from "@/features/Events/EventApi";
import { CalendarEvent } from "@/features/Events/EventsTypes";
import { PartStat } from "@/features/User/models/attendee";
import { createAttendee } from "@/features/User/models/attendee.mapper";
import { userData } from "@/features/User/userDataTypes";
import { buildFamilyName } from "@/utils/buildFamilyName";
import { getCalendarRange } from "@/utils/dateUtils";
import { refreshCalendars } from "../utils/eventUtils";
function updateEventAttendees(
@@ -70,7 +70,7 @@ function updateEventAttendees(
}
async function handleSoloRSVP(
dispatch: ThunkDispatch<any, any, any>,
dispatch: AppDispatch,
calendar: Calendar,
event: CalendarEvent
) {
@@ -78,7 +78,7 @@ async function handleSoloRSVP(
}
async function handleAllRSVP(
dispatch: ThunkDispatch<any, any, any>,
dispatch: AppDispatch,
event: CalendarEvent,
userEmail: string,
rsvp: PartStat,
@@ -90,7 +90,7 @@ async function handleAllRSVP(
}
async function handleDefaultRSVP(
dispatch: ThunkDispatch<any, any, any>,
dispatch: AppDispatch,
calendar: Calendar,
newEvent: CalendarEvent
) {
@@ -98,7 +98,7 @@ async function handleDefaultRSVP(
}
export async function handleRSVP(
dispatch: ThunkDispatch<any, any, any>,
dispatch: AppDispatch,
calendar: Calendar,
user: userData | undefined,
event: CalendarEvent,
@@ -1,6 +1,5 @@
import React from "react";
import { combineDateTime } from "../utils/dateTimeHelpers";
import { getRoundedCurrentTime } from "../utils/dateTimeFormatters";
/**
* Parameters for all-day toggle hook
@@ -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);
+13 -12
View File
@@ -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<any, any, any>,
dispatch: AppDispatch,
calendar: Calendar,
calendarRange: { start: Date; end: Date },
calType?: "temp"
+1 -1
View File
@@ -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,
+9 -9
View File
@@ -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();
+23 -23
View File
@@ -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 = {
+1 -1
View File
@@ -1,4 +1,4 @@
import { api } from "../../utils/apiUtils";
import { api } from "@/utils/apiUtils";
export async function getCalendars(
userId: string,
+22 -488
View File
@@ -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<string, Calendar>,
User,
{ rejectValue: RejectedError }
>("calendars/getTempCalendars", async (tempUser, { rejectWithValue }) => {
try {
const importedCalendars: Record<string, Calendar> = {};
const calendars = (await getCalendars(
tempUser.openpaasId ?? "",
"sharedPublic=true&"
)) as Record<string, any>;
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<string, any>;
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<string, string> };
},
{
calId: string;
calLink: string;
patch: { name: string; desc: string; color: Record<string, string> };
},
{ 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<string, any>;
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<string, string>;
name: string;
desc: string;
owner: string;
ownerEmails: string[];
},
{
userId: string;
calId: string;
color: Record<string, string>;
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<string, string>;
link: string;
name: string;
desc: string;
owner: string;
ownerEmails: string[];
},
{ userId: string; calId: string; cal: Record<string, any> },
{ 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<string, string>)._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: {
@@ -1,4 +1,4 @@
import { api } from "../../../utils/apiUtils";
import { api } from "@/utils/apiUtils";
import { Calendar } from "../CalendarTypes";
import { DavSyncResponse } from "./types";
@@ -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<string, string>;
link: string;
name: string;
desc: string;
owner: string;
ownerEmails: string[];
},
{ userId: string; calId: string; cal: Record<string, any> },
{ 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,
});
}
}
);
@@ -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<string, string>;
name: string;
desc: string;
owner: string;
ownerEmails: string[];
},
{
userId: string;
calId: string;
color: Record<string, string>;
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,
});
}
}
);
@@ -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,
});
}
}
);
@@ -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,
});
}
});
@@ -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";
@@ -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";
@@ -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,
});
}
});
@@ -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<string, Calendar>,
User,
{ rejectValue: RejectedError }
>("calendars/getTempCalendars", async (tempUser, { rejectWithValue }) => {
try {
const importedCalendars: Record<string, Calendar> = {};
const calendars = (await getCalendars(
tempUser.openpaasId ?? "",
"sharedPublic=true&"
)) as Record<string, any>;
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,
});
}
});
@@ -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,
});
}
});
+17
View File
@@ -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";
@@ -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<string, any>;
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,
});
}
}
);
@@ -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,
});
}
}
);
@@ -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<string, string> };
},
{
calId: string;
calLink: string;
patch: { name: string; desc: string; color: Record<string, string> };
},
{ 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,
});
}
}
);
@@ -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<string, any>;
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,
});
}
}
);
@@ -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";
@@ -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,
});
}
}
);
@@ -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,
});
}
}
);
@@ -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,
});
}
}
);
@@ -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";
@@ -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(
@@ -1,4 +1,4 @@
import { getCalendarVisibility } from "../../../components/Calendar/utils/calendarUtils";
import { getCalendarVisibility } from "@/components/Calendar/utils/calendarUtils";
export function normalizeCalendar(rawCalendar: Record<string, any>) {
const description = rawCalendar["caldav:description"];
@@ -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";
@@ -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";
@@ -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(
+7 -7
View File
@@ -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;
+33 -33
View File
@@ -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,
+36 -36
View File
@@ -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,
+34 -32
View File
@@ -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,
+1 -1
View File
@@ -18,7 +18,7 @@ export interface CalendarEvent {
organizer?: userOrganiser;
attendee: userAttendee[];
stamp?: string;
sequence?: Number;
sequence?: number;
color?: Record<string, string>;
allday?: boolean;
error?: string;
+3 -3
View File
@@ -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);
+7 -7
View File
@@ -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, string>, string, any];
function resolveTimezoneId(tzid?: string): string | undefined {
+7 -7
View File
@@ -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[];
+13 -14
View File
@@ -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";
+1 -1
View File
@@ -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 {
+25 -26
View File
@@ -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";
+1 -1
View File
@@ -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 {
+5 -5
View File
@@ -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);
+4 -4
View File
@@ -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();
+1 -1
View File
@@ -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 ?? "",
+2 -2
View File
@@ -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`);
+2 -2
View File
@@ -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<string, any>,
@@ -1,8 +1,8 @@
import {
generateMeetingId,
generateMeetingLink,
addVideoConferenceToDescription,
extractVideoConferenceFromDescription,
generateMeetingId,
generateMeetingLink,
} from "../videoConferenceUtils";
// Mock window object for Node.js environment
+1 -1
View File
@@ -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,
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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<RootState>,
+1 -1
View File
@@ -1,4 +1,4 @@
import { userData } from "../features/User/userDataTypes";
import { userData } from "@/features/User/userDataTypes";
/**
* Get user display name for UI display
+1 -1
View File
@@ -1,4 +1,4 @@
import { api } from "../../utils/apiUtils";
import { api } from "@/utils/apiUtils";
import { WebSocketTicket } from "./types";
export async function fetchWebSocketTicket(): Promise<WebSocketTicket> {
+1 -1
View File
@@ -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";