added integration for calendar to have twake top bar (#576)
This commit is contained in:
Generated
+16
@@ -23,6 +23,7 @@
|
|||||||
"@mui/material": "^7.1.2",
|
"@mui/material": "^7.1.2",
|
||||||
"@mui/x-date-pickers": "^8.14.0",
|
"@mui/x-date-pickers": "^8.14.0",
|
||||||
"@reduxjs/toolkit": "^2.8.2",
|
"@reduxjs/toolkit": "^2.8.2",
|
||||||
|
"cozy-external-bridge": "^1.2.1",
|
||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
"i18next": "^23.7.9",
|
"i18next": "^23.7.9",
|
||||||
"ical.js": "^2.2.0",
|
"ical.js": "^2.2.0",
|
||||||
@@ -6387,6 +6388,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/comlink": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "9.5.0",
|
"version": "9.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||||
@@ -6547,6 +6554,15 @@
|
|||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cozy-external-bridge": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cozy-external-bridge/-/cozy-external-bridge-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Vbf3ugIuYWGHHD4fiWdUIvljadpHiV/GF1YaETMmlmOlxagiwbK3NESlAiXoGgg5aHdLjXliGJy+j9ccMdVm/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"comlink": "4.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/create-require": {
|
"node_modules/create-require": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"@mui/material": "^7.1.2",
|
"@mui/material": "^7.1.2",
|
||||||
"@mui/x-date-pickers": "^8.14.0",
|
"@mui/x-date-pickers": "^8.14.0",
|
||||||
"@reduxjs/toolkit": "^2.8.2",
|
"@reduxjs/toolkit": "^2.8.2",
|
||||||
|
"cozy-external-bridge": "^1.2.1",
|
||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
"i18next": "^23.7.9",
|
"i18next": "^23.7.9",
|
||||||
"ical.js": "^2.2.0",
|
"ical.js": "^2.2.0",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { User } from "../Attendees/PeopleSearch";
|
|||||||
import { EventErrorSnackbar } from "../Error/ErrorSnackbar";
|
import { EventErrorSnackbar } from "../Error/ErrorSnackbar";
|
||||||
import { EventErrorHandler } from "../Error/EventErrorHandler";
|
import { EventErrorHandler } from "../Error/EventErrorHandler";
|
||||||
import { EditModeDialog } from "../Event/EditModeDialog";
|
import { EditModeDialog } from "../Event/EditModeDialog";
|
||||||
|
import { Menubar, MenubarProps } from "../Menubar/Menubar";
|
||||||
import "./Calendar.styl";
|
import "./Calendar.styl";
|
||||||
import CalendarSelection from "./CalendarSelection";
|
import CalendarSelection from "./CalendarSelection";
|
||||||
import "./CustomCalendar.styl";
|
import "./CustomCalendar.styl";
|
||||||
@@ -59,12 +60,14 @@ interface CalendarAppProps {
|
|||||||
calendarRef: MutableRefObject<CalendarApi | null>;
|
calendarRef: MutableRefObject<CalendarApi | null>;
|
||||||
onDateChange?: (date: Date) => void;
|
onDateChange?: (date: Date) => void;
|
||||||
onViewChange?: (view: string) => void;
|
onViewChange?: (view: string) => void;
|
||||||
|
menubarProps?: MenubarProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CalendarApp({
|
export default function CalendarApp({
|
||||||
calendarRef,
|
calendarRef,
|
||||||
onDateChange,
|
onDateChange,
|
||||||
onViewChange,
|
onViewChange,
|
||||||
|
menubarProps,
|
||||||
}: CalendarAppProps) {
|
}: CalendarAppProps) {
|
||||||
const [selectedDate, setSelectedDate] = useState(new Date());
|
const [selectedDate, setSelectedDate] = useState(new Date());
|
||||||
const [selectedMiniDate, setSelectedMiniDate] = useState(new Date());
|
const [selectedMiniDate, setSelectedMiniDate] = useState(new Date());
|
||||||
@@ -661,6 +664,7 @@ export default function CalendarApp({
|
|||||||
</Box>
|
</Box>
|
||||||
<div className="calendar">
|
<div className="calendar">
|
||||||
<ImportAlert />
|
<ImportAlert />
|
||||||
|
{menubarProps?.isIframe && <Menubar {...menubarProps} />}
|
||||||
{view === "calendar" && (
|
{view === "calendar" && (
|
||||||
<FullCalendar
|
<FullCalendar
|
||||||
ref={(ref) => {
|
ref={(ref) => {
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { useAppDispatch, useAppSelector } from "@/app/hooks";
|
|||||||
import SettingsPage from "@/features/Settings/SettingsPage";
|
import SettingsPage from "@/features/Settings/SettingsPage";
|
||||||
import { getCalendarRange } from "@/utils/dateUtils";
|
import { getCalendarRange } from "@/utils/dateUtils";
|
||||||
import type { CalendarApi } from "@fullcalendar/core";
|
import type { CalendarApi } from "@fullcalendar/core";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import CozyBridge from "cozy-external-bridge";
|
||||||
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { ErrorSnackbar } from "../Error/ErrorSnackbar";
|
import { ErrorSnackbar } from "../Error/ErrorSnackbar";
|
||||||
import { refreshCalendars } from "../Event/utils/eventUtils";
|
import { refreshCalendars } from "../Event/utils/eventUtils";
|
||||||
import { Menubar, MenubarProps } from "../Menubar/Menubar";
|
import { Menubar, MenubarProps } from "../Menubar/Menubar";
|
||||||
@@ -17,6 +18,7 @@ export default function CalendarLayout() {
|
|||||||
const view = useAppSelector((state) => state.settings.view);
|
const view = useAppSelector((state) => state.settings.view);
|
||||||
const [currentDate, setCurrentDate] = useState<Date>(new Date());
|
const [currentDate, setCurrentDate] = useState<Date>(new Date());
|
||||||
const [currentView, setCurrentView] = useState<string>("timeGridWeek");
|
const [currentView, setCurrentView] = useState<string>("timeGridWeek");
|
||||||
|
const isInIframe = useMemo(() => new CozyBridge().isInIframe(), []);
|
||||||
|
|
||||||
const handleRefresh = async () => {
|
const handleRefresh = async () => {
|
||||||
// Get current calendar range
|
// Get current calendar range
|
||||||
@@ -70,16 +72,18 @@ export default function CalendarLayout() {
|
|||||||
onDateChange: handleDateChange,
|
onDateChange: handleDateChange,
|
||||||
currentView,
|
currentView,
|
||||||
onViewChange: handleViewChange,
|
onViewChange: handleViewChange,
|
||||||
|
isIframe: isInIframe,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<Menubar {...menubarProps} />
|
{!isInIframe && <Menubar {...menubarProps} />}
|
||||||
{(view === "calendar" || view === "search") && (
|
{(view === "calendar" || view === "search") && (
|
||||||
<CalendarApp
|
<CalendarApp
|
||||||
calendarRef={calendarRef}
|
calendarRef={calendarRef}
|
||||||
onDateChange={handleDateChange}
|
onDateChange={handleDateChange}
|
||||||
onViewChange={handleViewChange}
|
onViewChange={handleViewChange}
|
||||||
|
menubarProps={menubarProps}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{view === "settings" && <SettingsPage />}
|
{view === "settings" && <SettingsPage />}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export type MenubarProps = {
|
|||||||
onDateChange?: (date: Date) => void;
|
onDateChange?: (date: Date) => void;
|
||||||
currentView: string;
|
currentView: string;
|
||||||
onViewChange?: (view: string) => void;
|
onViewChange?: (view: string) => void;
|
||||||
|
isIframe?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Menubar({
|
export function Menubar({
|
||||||
@@ -55,6 +56,7 @@ export function Menubar({
|
|||||||
onDateChange,
|
onDateChange,
|
||||||
currentView,
|
currentView,
|
||||||
onViewChange,
|
onViewChange,
|
||||||
|
isIframe,
|
||||||
}: MenubarProps) {
|
}: MenubarProps) {
|
||||||
const { t } = useI18n(); // deliberately NOT using f()
|
const { t } = useI18n(); // deliberately NOT using f()
|
||||||
const user = useAppSelector((state) => state.user.userData);
|
const user = useAppSelector((state) => state.user.userData);
|
||||||
@@ -155,14 +157,16 @@ export function Menubar({
|
|||||||
<>
|
<>
|
||||||
<header className="menubar">
|
<header className="menubar">
|
||||||
<div className="left-menu">
|
<div className="left-menu">
|
||||||
<div className="menu-items">
|
{!isIframe && (
|
||||||
<MainTitle
|
<div className="menu-items">
|
||||||
calendarRef={calendarRef}
|
<MainTitle
|
||||||
currentView={currentView}
|
calendarRef={calendarRef}
|
||||||
onViewChange={onViewChange}
|
currentView={currentView}
|
||||||
onDateChange={onDateChange}
|
onViewChange={onViewChange}
|
||||||
/>
|
onDateChange={onDateChange}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="menu-items">
|
<div className="menu-items">
|
||||||
<div className="navigation-controls">
|
<div className="navigation-controls">
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
@@ -245,41 +249,53 @@ export function Menubar({
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
<div className="menu-items">
|
{!isIframe && (
|
||||||
<IconButton
|
<>
|
||||||
component="a"
|
<div className="menu-items">
|
||||||
href="https://twake.app/support/"
|
<IconButton
|
||||||
target="_blank"
|
component="a"
|
||||||
rel="noopener noreferrer"
|
href="https://twake.app/support/"
|
||||||
style={{ marginRight: 8 }}
|
target="_blank"
|
||||||
aria-label={t("menubar.help")}
|
rel="noopener noreferrer"
|
||||||
title={t("menubar.help")}
|
style={{ marginRight: 8 }}
|
||||||
>
|
aria-label={t("menubar.help")}
|
||||||
<HelpOutlineIcon />
|
title={t("menubar.help")}
|
||||||
</IconButton>
|
>
|
||||||
</div>
|
<HelpOutlineIcon />
|
||||||
<div className="menu-items">
|
</IconButton>
|
||||||
{applist.length > 0 && (
|
</div>
|
||||||
<IconButton
|
|
||||||
onClick={handleOpen}
|
<div className="menu-items">
|
||||||
style={{ marginRight: 8 }}
|
{applist.length > 0 && (
|
||||||
aria-label={t("menubar.apps")}
|
<IconButton
|
||||||
title={t("menubar.apps")}
|
onClick={handleOpen}
|
||||||
>
|
style={{ marginRight: 8 }}
|
||||||
<WidgetsOutlinedIcon />
|
aria-label={t("menubar.apps")}
|
||||||
</IconButton>
|
title={t("menubar.apps")}
|
||||||
)}
|
>
|
||||||
</div>
|
<WidgetsOutlinedIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="menu-items">
|
<div className="menu-items">
|
||||||
<IconButton onClick={handleUserMenuClick}>
|
<IconButton
|
||||||
<Avatar
|
onClick={!isIframe ? handleUserMenuClick : handleSettingsClick}
|
||||||
color={stringToGradient(getUserDisplayName(user))}
|
aria-label={isIframe ? t("menubar.settings") : undefined}
|
||||||
size="m"
|
>
|
||||||
aria-label={t("menubar.userProfile")}
|
{!isIframe ? (
|
||||||
>
|
<Avatar
|
||||||
{getInitials(getUserDisplayName(user))}
|
color={stringToGradient(getUserDisplayName(user))}
|
||||||
</Avatar>
|
size="m"
|
||||||
|
aria-label={t("menubar.userProfile")}
|
||||||
|
>
|
||||||
|
{getInitials(getUserDisplayName(user))}
|
||||||
|
</Avatar>
|
||||||
|
) : (
|
||||||
|
<SettingsOutlinedIcon />
|
||||||
|
)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user