update header bar
This commit is contained in:
@@ -1,9 +1,14 @@
|
|||||||
import { Menubar } from "@/components/Menubar/Menubar";
|
import { Menubar } from "@/components/Menubar/Menubar";
|
||||||
import * as oidcAuth from "@/features/User/oidcAuth";
|
import * as oidcAuth from "@/features/User/oidcAuth";
|
||||||
|
import { redirectTo } from "@/utils/navigation";
|
||||||
import "@testing-library/jest-dom";
|
import "@testing-library/jest-dom";
|
||||||
import { act, fireEvent, screen, waitFor } from "@testing-library/react";
|
import { act, fireEvent, screen, waitFor } from "@testing-library/react";
|
||||||
import { renderWithProviders } from "../utils/Renderwithproviders";
|
import { renderWithProviders } from "../utils/Renderwithproviders";
|
||||||
|
|
||||||
|
jest.mock("@/utils/navigation", () => ({
|
||||||
|
redirectTo: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
describe("Calendar App Component Display Tests", () => {
|
describe("Calendar App Component Display Tests", () => {
|
||||||
const preloadedState = {
|
const preloadedState = {
|
||||||
user: {
|
user: {
|
||||||
@@ -320,7 +325,7 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
expect(avatar).toBeInTheDocument();
|
expect(avatar).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows AppsIcon when applist is not empty", () => {
|
it("shows apps button when applist is not empty", () => {
|
||||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||||
const mockCalendarRef = { current: null };
|
const mockCalendarRef = { current: null };
|
||||||
const mockOnRefresh = jest.fn();
|
const mockOnRefresh = jest.fn();
|
||||||
@@ -335,10 +340,10 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
/>,
|
/>,
|
||||||
preloadedState
|
preloadedState
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId("AppsIcon")).toBeInTheDocument();
|
expect(screen.getByLabelText("menubar.apps")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("opens popover when clicking AppsIcon", () => {
|
it("opens popover when clicking apps button", () => {
|
||||||
(window as any).appList = [
|
(window as any).appList = [
|
||||||
{ name: "Twake", icon: "twake.svg", link: "/twake" },
|
{ name: "Twake", icon: "twake.svg", link: "/twake" },
|
||||||
{ name: "Calendar", icon: "calendar.svg", link: "/calendar" },
|
{ name: "Calendar", icon: "calendar.svg", link: "/calendar" },
|
||||||
@@ -356,7 +361,7 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
/>,
|
/>,
|
||||||
preloadedState
|
preloadedState
|
||||||
);
|
);
|
||||||
const appsButton = screen.getByTestId("AppsIcon");
|
const appsButton = screen.getByLabelText("menubar.apps");
|
||||||
fireEvent.click(appsButton);
|
fireEvent.click(appsButton);
|
||||||
expect(screen.getByText("Twake")).toBeInTheDocument();
|
expect(screen.getByText("Twake")).toBeInTheDocument();
|
||||||
expect(screen.getByText("Calendar")).toBeInTheDocument();
|
expect(screen.getByText("Calendar")).toBeInTheDocument();
|
||||||
@@ -377,7 +382,7 @@ describe("Calendar App Component Display Tests", () => {
|
|||||||
/>,
|
/>,
|
||||||
preloadedState
|
preloadedState
|
||||||
);
|
);
|
||||||
const appsButton = screen.getByTestId("AppsIcon");
|
const appsButton = screen.getByLabelText("menubar.apps");
|
||||||
fireEvent.click(appsButton);
|
fireEvent.click(appsButton);
|
||||||
|
|
||||||
const testLink = screen.getByRole("link", { name: /test/i });
|
const testLink = screen.getByRole("link", { name: /test/i });
|
||||||
@@ -532,7 +537,7 @@ describe("Menubar interaction with expanded Dialog", () => {
|
|||||||
preloadedState
|
preloadedState
|
||||||
);
|
);
|
||||||
|
|
||||||
const appsButton = screen.getByTestId("AppsIcon");
|
const appsButton = screen.getByLabelText("menubar.apps");
|
||||||
expect(appsButton).toBeVisible();
|
expect(appsButton).toBeVisible();
|
||||||
|
|
||||||
fireEvent.click(appsButton);
|
fireEvent.click(appsButton);
|
||||||
@@ -717,10 +722,17 @@ describe("Menubar interaction with expanded Dialog", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("Menubar logout flow", () => {
|
describe("Menubar logout flow", () => {
|
||||||
|
const redirectToMock = redirectTo as jest.Mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
sessionStorage.clear();
|
sessionStorage.clear();
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
redirectToMock.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
redirectToMock.mockReset();
|
||||||
});
|
});
|
||||||
|
|
||||||
function renderMenubar(user = { name: "John", email: "test@example.com" }) {
|
function renderMenubar(user = { name: "John", email: "test@example.com" }) {
|
||||||
@@ -756,6 +768,7 @@ describe("Menubar logout flow", () => {
|
|||||||
fireEvent.click(screen.getByText("menubar.logout"));
|
fireEvent.click(screen.getByText("menubar.logout"));
|
||||||
});
|
});
|
||||||
expect(logoutSpy).toHaveBeenCalled();
|
expect(logoutSpy).toHaveBeenCalled();
|
||||||
|
expect(redirectToMock).toHaveBeenCalledWith("https://logout.url/");
|
||||||
|
|
||||||
expect(sessionStorage.length).toBe(0);
|
expect(sessionStorage.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ describe("ResponsiveDialog", () => {
|
|||||||
onClose={mockOnClose}
|
onClose={mockOnClose}
|
||||||
title="Test"
|
title="Test"
|
||||||
isExpanded={true}
|
isExpanded={true}
|
||||||
headerHeight="100px"
|
headerHeight="70px"
|
||||||
>
|
>
|
||||||
<div>Custom Header Content</div>
|
<div>Custom Header Content</div>
|
||||||
</ResponsiveDialog>
|
</ResponsiveDialog>
|
||||||
|
|||||||
Generated
+45
@@ -83,6 +83,51 @@
|
|||||||
"node": "24.x"
|
"node": "24.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"../twake-ui/packages/twake-mui": {
|
||||||
|
"name": "@linagora/twake-mui",
|
||||||
|
"version": "1.1.7",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/eslint-parser": "7.19.1",
|
||||||
|
"@types/react": "18.3.26",
|
||||||
|
"@types/react-dom": "18.3.7",
|
||||||
|
"@typescript-eslint/eslint-plugin": "6.21.0",
|
||||||
|
"@typescript-eslint/parser": "6.21.0",
|
||||||
|
"cozy-tsconfig": "1.8.1",
|
||||||
|
"eslint": "8.35.0",
|
||||||
|
"eslint-config-cozy-app": "6.7.1",
|
||||||
|
"eslint-config-prettier": "8.6.0",
|
||||||
|
"eslint-plugin-import": "2.27.5",
|
||||||
|
"eslint-plugin-jest": "27.9.0",
|
||||||
|
"eslint-plugin-prettier": "4.2.1",
|
||||||
|
"eslint-plugin-promise": "6.1.1",
|
||||||
|
"eslint-plugin-react": "7.32.2",
|
||||||
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
|
"prettier": "2.8.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "24.x"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/react": "^11.14.0",
|
||||||
|
"@emotion/styled": "^11.14.1",
|
||||||
|
"@mui/material": "^7.1.2",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react": {
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@adobe/css-tools": {
|
"node_modules/@adobe/css-tools": {
|
||||||
"version": "4.4.4",
|
"version": "4.4.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
.main-layout
|
.main-layout
|
||||||
display flex
|
display flex
|
||||||
height calc(100vh - 90px)
|
height calc(100vh - 70px)
|
||||||
|
|
||||||
.main-layout.calendar-layout
|
.main-layout.calendar-layout
|
||||||
background-color #fff
|
background-color #fff
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ tbody > tr.fc-scrollgrid-section:first-of-type .fc-scroller
|
|||||||
overflow hidden !important
|
overflow hidden !important
|
||||||
|
|
||||||
.navigation-controls
|
.navigation-controls
|
||||||
margin-right 40px
|
margin-right 16px
|
||||||
|
|
||||||
.fc .fc-timegrid-slot-minor
|
.fc .fc-timegrid-slot-minor
|
||||||
border-top-style: none
|
border-top-style: none
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ function MyComponent() {
|
|||||||
| `onExpandToggle` | `() => void` | - | Handler for back button click when expanded |
|
| `onExpandToggle` | `() => void` | - | Handler for back button click when expanded |
|
||||||
| `normalMaxWidth` | `string` | `"570px"` | Max width in normal mode |
|
| `normalMaxWidth` | `string` | `"570px"` | Max width in normal mode |
|
||||||
| `expandedContentMaxWidth` | `string` | `"990px"` | Content container max-width in expanded mode |
|
| `expandedContentMaxWidth` | `string` | `"990px"` | Content container max-width in expanded mode |
|
||||||
| `headerHeight` | `string` | `"90px"` | App header height to preserve |
|
| `headerHeight` | `string` | `"70px"` | App header height to preserve |
|
||||||
| `normalSpacing` | `number` | `2` | Stack spacing in normal mode (MUI spacing units: 1 = 8px) |
|
| `normalSpacing` | `number` | `2` | Stack spacing in normal mode (MUI spacing units: 1 = 8px) |
|
||||||
| `expandedSpacing` | `number` | `2` | Stack spacing in expanded mode (MUI spacing units: 1 = 8px) |
|
| `expandedSpacing` | `number` | `2` | Stack spacing in expanded mode (MUI spacing units: 1 = 8px) |
|
||||||
| `contentSx` | `SxProps<Theme>` | - | Custom styles for DialogContent |
|
| `contentSx` | `SxProps<Theme>` | - | Custom styles for DialogContent |
|
||||||
@@ -149,7 +149,7 @@ For apps with different header heights:
|
|||||||
open={open}
|
open={open}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
title="Custom Header Height"
|
title="Custom Header Height"
|
||||||
headerHeight="80px"
|
headerHeight="70px"
|
||||||
isExpanded={true}
|
isExpanded={true}
|
||||||
>
|
>
|
||||||
<TextField label="Content" />
|
<TextField label="Content" />
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ function ResponsiveDialog({
|
|||||||
onExpandToggle,
|
onExpandToggle,
|
||||||
normalMaxWidth = "570px",
|
normalMaxWidth = "570px",
|
||||||
expandedContentMaxWidth = "990px",
|
expandedContentMaxWidth = "990px",
|
||||||
headerHeight = "90px",
|
headerHeight = "70px",
|
||||||
normalSpacing = 2,
|
normalSpacing = 2,
|
||||||
expandedSpacing = 2,
|
expandedSpacing = 2,
|
||||||
contentSx,
|
contentSx,
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ export default function SearchBar() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!extended && (
|
{!extended && (
|
||||||
<IconButton onClick={() => setExtended(true)}>
|
<IconButton sx={{ mr: 1 }} onClick={() => setExtended(true)}>
|
||||||
<SearchIcon />
|
<SearchIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -38,20 +38,22 @@
|
|||||||
padding 0.5rem
|
padding 0.5rem
|
||||||
width 100%
|
width 100%
|
||||||
z-index 1300
|
z-index 1300
|
||||||
height 80px
|
height 60px
|
||||||
background-color #fff
|
background-color #fff
|
||||||
|
|
||||||
.menubar-item
|
.menubar-item
|
||||||
display flex
|
display flex
|
||||||
align-items center
|
align-items center
|
||||||
width calc(330px - 0.5rem)
|
margin-right 65px
|
||||||
|
|
||||||
.tc-home
|
.tc-home
|
||||||
cursor pointer
|
cursor pointer
|
||||||
|
|
||||||
.logo
|
.logo
|
||||||
padding 0.5rem 1rem
|
padding 0
|
||||||
font-size 1.5rem
|
font-size 1.5rem
|
||||||
|
max-width 230px
|
||||||
|
margin-left 1rem
|
||||||
|
|
||||||
.nav-month
|
.nav-month
|
||||||
padding-right 2px
|
padding-right 2px
|
||||||
@@ -91,6 +93,14 @@
|
|||||||
justify-content flex-end
|
justify-content flex-end
|
||||||
align-items center
|
align-items center
|
||||||
|
|
||||||
|
.current-date-time
|
||||||
|
font-family Roboto
|
||||||
|
font-size 22px
|
||||||
|
font-style normal
|
||||||
|
font-weight 400
|
||||||
|
line-height 36px
|
||||||
|
color #243B55
|
||||||
|
|
||||||
body.fullscreen-view .navigation-controls,
|
body.fullscreen-view .navigation-controls,
|
||||||
body.fullscreen-view .current-date-time,
|
body.fullscreen-view .current-date-time,
|
||||||
body.fullscreen-view .refresh-button,
|
body.fullscreen-view .refresh-button,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Logout } from "@/features/User/oidcAuth";
|
|||||||
import logo from "@/static/header-logo.svg";
|
import logo from "@/static/header-logo.svg";
|
||||||
import { getInitials, stringToGradient } from "@/utils/avatarUtils";
|
import { getInitials, stringToGradient } from "@/utils/avatarUtils";
|
||||||
import { getUserDisplayName } from "@/utils/userUtils";
|
import { getUserDisplayName } from "@/utils/userUtils";
|
||||||
|
import { redirectTo } from "@/utils/navigation";
|
||||||
import { CalendarApi } from "@fullcalendar/core";
|
import { CalendarApi } from "@fullcalendar/core";
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
@@ -19,7 +20,8 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@linagora/twake-mui";
|
} from "@linagora/twake-mui";
|
||||||
import AppsIcon from "@mui/icons-material/Apps";
|
import WidgetsOutlinedIcon from "@mui/icons-material/WidgetsOutlined";
|
||||||
|
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
|
||||||
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
|
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
|
||||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||||
import LogoutIcon from "@mui/icons-material/Logout";
|
import LogoutIcon from "@mui/icons-material/Logout";
|
||||||
@@ -139,7 +141,7 @@ export function Menubar({
|
|||||||
const handleLogoutClick = async () => {
|
const handleLogoutClick = async () => {
|
||||||
const logoutUrl = await Logout();
|
const logoutUrl = await Logout();
|
||||||
sessionStorage.removeItem("tokenSet");
|
sessionStorage.removeItem("tokenSet");
|
||||||
window.location.assign(logoutUrl.href);
|
redirectTo(logoutUrl.href);
|
||||||
handleUserMenuClose();
|
handleUserMenuClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -195,9 +197,9 @@ export function Menubar({
|
|||||||
</div>
|
</div>
|
||||||
<div className="menu-items">
|
<div className="menu-items">
|
||||||
<div className="current-date-time">
|
<div className="current-date-time">
|
||||||
<Typography variant="h3" component="div">
|
<p>
|
||||||
{dateLabel}
|
{dateLabel}
|
||||||
</Typography>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -211,6 +213,7 @@ export function Menubar({
|
|||||||
onClick={onRefresh}
|
onClick={onRefresh}
|
||||||
aria-label={t("menubar.refresh")}
|
aria-label={t("menubar.refresh")}
|
||||||
title={t("menubar.refresh")}
|
title={t("menubar.refresh")}
|
||||||
|
sx={{ mr: 1 }}
|
||||||
>
|
>
|
||||||
<RefreshIcon />
|
<RefreshIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@@ -226,7 +229,11 @@ export function Menubar({
|
|||||||
onChange={(e) => handleViewChange(e.target.value)}
|
onChange={(e) => handleViewChange(e.target.value)}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
aria-label={t("menubar.viewSelector")}
|
aria-label={t("menubar.viewSelector")}
|
||||||
sx={{ height: "43px" }}
|
sx={{
|
||||||
|
borderRadius: "12px",
|
||||||
|
marginLeft: 1,
|
||||||
|
"& fieldset": { borderRadius: "12px" }
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value="dayGridMonth">
|
<MenuItem value="dayGridMonth">
|
||||||
{t("menubar.views.month")}
|
{t("menubar.views.month")}
|
||||||
@@ -240,6 +247,19 @@ export function Menubar({
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="menu-items">
|
||||||
|
<IconButton
|
||||||
|
component="a"
|
||||||
|
href="https://twake.app/support/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ marginRight: 8 }}
|
||||||
|
aria-label={t("menubar.help")}
|
||||||
|
title={t("menubar.help")}
|
||||||
|
>
|
||||||
|
<HelpOutlineIcon />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
<div className="menu-items">
|
<div className="menu-items">
|
||||||
{applist.length > 0 && (
|
{applist.length > 0 && (
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -248,7 +268,7 @@ export function Menubar({
|
|||||||
aria-label={t("menubar.apps")}
|
aria-label={t("menubar.apps")}
|
||||||
title={t("menubar.apps")}
|
title={t("menubar.apps")}
|
||||||
>
|
>
|
||||||
<AppsIcon />
|
<WidgetsOutlinedIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.main-layout.settings-layout
|
.main-layout.settings-layout
|
||||||
display flex
|
display flex
|
||||||
flex-direction row
|
flex-direction row
|
||||||
height calc(100vh - 90px)
|
height calc(100vh - 70px)
|
||||||
padding 0 10px 10px 0;
|
padding 0 10px 10px 0;
|
||||||
|
|
||||||
.settings-sidebar
|
.settings-sidebar
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export function redirectTo(url: string): void {
|
||||||
|
window.location.assign(url);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user