[#32] added app list and user icon to menubar
This commit is contained in:
committed by
Benoit TELLIER
parent
4b93d7dea9
commit
aa498ac91f
@@ -17,6 +17,7 @@
|
||||
.env.development.js
|
||||
.env.test.js
|
||||
.env.production.js
|
||||
appList.js
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
@@ -1,13 +1,65 @@
|
||||
import React from "react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import { fireEvent, screen } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom";
|
||||
import { Menubar } from "../../src/components/Menubar/Menubar";
|
||||
import { renderWithProviders } from "../utils/Renderwithproviders";
|
||||
|
||||
describe("Calendar App Component Display Tests", () => {
|
||||
const preloadedState = {
|
||||
user: {
|
||||
userData: {
|
||||
sub: "test",
|
||||
email: "test@test.com",
|
||||
family_name: "Doe",
|
||||
name: "John",
|
||||
sid: "mockSid",
|
||||
openpaasId: "667037022b752d0026472254",
|
||||
},
|
||||
},
|
||||
};
|
||||
test("renders the Menubar component", () => {
|
||||
renderWithProviders(<Menubar />);
|
||||
(window as any).appList = [
|
||||
{ name: "Twake", link: "/twake", icon: "twake.svg" },
|
||||
{ name: "Calendar", link: "/calendar", icon: "calendar.svg" },
|
||||
];
|
||||
renderWithProviders(<Menubar />, preloadedState);
|
||||
const navbarElement = screen.getByText("Twake");
|
||||
expect(navbarElement).toBeInTheDocument();
|
||||
});
|
||||
it("renders the main title", () => {
|
||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||
renderWithProviders(<Menubar />, preloadedState);
|
||||
expect(screen.getByText(/Twake/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Calendar/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows avatar with user initials", () => {
|
||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||
renderWithProviders(<Menubar />, preloadedState);
|
||||
expect(screen.getByText("JD")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows AppsIcon when applist is not empty", () => {
|
||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||
renderWithProviders(<Menubar />, preloadedState);
|
||||
expect(screen.getByTestId("AppsIcon")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("opens popover when clicking AppsIcon", () => {
|
||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||
renderWithProviders(<Menubar />, preloadedState);
|
||||
const appsButton = screen.getByRole("button");
|
||||
fireEvent.click(appsButton);
|
||||
expect(screen.getByText("Twake")).toBeInTheDocument();
|
||||
expect(screen.getByText("Calendar")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders app icons as links", () => {
|
||||
(window as any).appList = [{ name: "test", icon: "test", link: "test" }];
|
||||
renderWithProviders(<Menubar />, preloadedState);
|
||||
const appsButton = screen.getByRole("button");
|
||||
fireEvent.click(appsButton);
|
||||
|
||||
const twakeLink = screen.getByRole("link", { name: /test/i });
|
||||
expect(twakeLink).toHaveAttribute("href", "test");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
var appList = [
|
||||
{
|
||||
name: "Twake",
|
||||
link: "/twake",
|
||||
icon: "https://twake-chat.com/tild3037-6365-4134-b838-383030366263__twake-chat-logo.svg",
|
||||
},
|
||||
];
|
||||
@@ -32,6 +32,7 @@
|
||||
/>
|
||||
<title>React App</title>
|
||||
<script src="<%= assetPrefix %>/.env.js"></script>
|
||||
<script src="<%= assetPrefix %>/appList.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
||||
@@ -73,10 +73,22 @@
|
||||
left: 887px;
|
||||
}
|
||||
|
||||
.menu-tools {
|
||||
width: 383.20001220703125;
|
||||
height: 49;
|
||||
top: 16px;
|
||||
left: 1511px;
|
||||
gap: 24px;
|
||||
.app-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
padding: 16px;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.app-grid img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.app-grid p {
|
||||
margin-top: 6px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,79 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import logo from "../../static/images/calendar.svg";
|
||||
import AppsIcon from "@mui/icons-material/Apps";
|
||||
import "./Menubar.css";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import { stringToColor } from "../../features/Events/EventDisplay";
|
||||
import { Avatar, IconButton, Popover } from "@mui/material";
|
||||
import { push } from "redux-first-history";
|
||||
|
||||
export type AppIconProps = {
|
||||
name: string;
|
||||
link: string;
|
||||
icon: string;
|
||||
};
|
||||
|
||||
export function Menubar() {
|
||||
const user = useAppSelector((state) => state.user.userData);
|
||||
const applist: AppIconProps[] = (window as any).appList;
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
if (!user) {
|
||||
dispatch(push("/"));
|
||||
}
|
||||
const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
return (
|
||||
<header className="menubar">
|
||||
<MainTitle/>
|
||||
<div className="menubar-item search-bar">
|
||||
<p>big search bar</p>
|
||||
</div>
|
||||
<div className="menubar-item">
|
||||
<p>Account stuff</p>
|
||||
</div>
|
||||
</header>
|
||||
<>
|
||||
<header className="menubar">
|
||||
<MainTitle />
|
||||
<div className="menubar-item search-bar">
|
||||
<p>big search bar</p>
|
||||
</div>
|
||||
|
||||
<div className="menubar-item">
|
||||
{applist.length > 0 && (
|
||||
<IconButton onClick={handleOpen}>
|
||||
<AppsIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
<Avatar
|
||||
sx={{ bgcolor: stringToColor(user.family_name) }}
|
||||
sizes="large"
|
||||
>
|
||||
{user.name[0]}
|
||||
{user.family_name[0]}
|
||||
</Avatar>
|
||||
</div>
|
||||
</header>
|
||||
<Popover
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "right",
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
>
|
||||
<div className="app-grid">
|
||||
{applist.map((prop: AppIconProps) => (
|
||||
<AppIcon prop={prop} />
|
||||
))}
|
||||
</div>
|
||||
</Popover>
|
||||
</>
|
||||
);
|
||||
}
|
||||
export function MainTitle() {
|
||||
@@ -25,3 +87,18 @@ export function MainTitle() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AppIcon({ prop }: { prop: AppIconProps }) {
|
||||
return (
|
||||
<a
|
||||
key={prop.name}
|
||||
href={prop.link}
|
||||
style={{ textDecoration: "none", color: "inherit" }}
|
||||
>
|
||||
<div>
|
||||
<img src={prop.icon} alt={prop.name} />
|
||||
<p>{prop.name}</p>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ function formatDate(date: Date) {
|
||||
});
|
||||
}
|
||||
|
||||
function stringToColor(string: string) {
|
||||
export function stringToColor(string: string) {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
hash = string.charCodeAt(i) + ((hash << 5) - hash);
|
||||
|
||||
Reference in New Issue
Block a user