Sidebar and messages updates

This commit is contained in:
Darren Clarke 2023-01-11 16:18:56 +01:00
parent 6a0cc58f60
commit 016461b549
No known key found for this signature in database
GPG key ID: E2483E6F82907488
6 changed files with 1193 additions and 634 deletions

View file

@ -1,11 +1,19 @@
import { FC, useState } from "react";
import { Grid } from "@mui/material"; import { Grid } from "@mui/material";
import { Sidebar } from "./Sidebar"; import { Sidebar } from "./Sidebar";
export const Layout = ({ children }) => ( export const Layout = ({ children }) => {
<Grid container direction="row"> const [open, setOpen] = useState(true);
<Sidebar open />
<Grid item sx={{ ml: "270px", width: "100%", height: "100vh" }}> return (
{children} <Grid container direction="row">
<Sidebar open={open} setOpen={setOpen} />
<Grid
item
sx={{ ml: open ? "270px" : "100px", width: "100%", height: "100vh" }}
>
{children}
</Grid>
</Grid> </Grid>
</Grid> );
); };

View file

@ -18,6 +18,7 @@ import {
Logout as LogoutIcon, Logout as LogoutIcon,
Cottage as CottageIcon, Cottage as CottageIcon,
Settings as SettingsIcon, Settings as SettingsIcon,
ExpandCircleDown as ExpandCircleDownIcon,
} from "@mui/icons-material"; } from "@mui/icons-material";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import Link from "next/link"; import Link from "next/link";
@ -34,11 +35,16 @@ const MenuItem = ({
iconSize, iconSize,
inset = false, inset = false,
selected = false, selected = false,
open = true,
badge, badge,
}: any) => ( }: any) => (
<Link href={href}> <Link href={href}>
<ListItemButton <ListItemButton
sx={{ p: 0, mb: 1, bl: iconSize === 0 ? "1px solid white" : "inherit" }} sx={{
p: 0,
mb: 1,
bl: iconSize === 0 ? "1px solid white" : "inherit",
}}
selected={selected} selected={selected}
> >
{iconSize > 0 ? ( {iconSize > 0 ? (
@ -47,6 +53,8 @@ const MenuItem = ({
color: `white`, color: `white`,
minWidth: 0, minWidth: 0,
mr: 2, mr: 2,
textAlign: "center",
margin: open ? "0 8 0 0" : "0 auto",
}} }}
> >
<Box <Box
@ -95,23 +103,25 @@ const MenuItem = ({
/> />
</Box> </Box>
)} )}
<ListItemText {open && (
inset={inset} <ListItemText
primary={ inset={inset}
<Typography primary={
variant="body1" <Typography
sx={{ variant="body1"
fontSize: 16, sx={{
fontFamily: "Roboto", fontSize: 16,
fontWeight: "bold", fontFamily: "Roboto",
border: 0, fontWeight: "bold",
textAlign: "left", border: 0,
}} textAlign: "left",
> }}
{name} >
</Typography> {name}
} </Typography>
/> }
/>
)}
{badge && ( {badge && (
<ListItemSecondaryAction> <ListItemSecondaryAction>
<Typography <Typography
@ -137,11 +147,13 @@ const MenuItem = ({
interface SidebarProps { interface SidebarProps {
open: boolean; open: boolean;
setOpen: (open: boolean) => void;
} }
export const Sidebar: FC<SidebarProps> = ({ open }) => { export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
const { pathname } = useRouter(); const { pathname } = useRouter();
console.log({ pathname }); const [username, setUsername] = useState("Nicholas Smith");
return ( return (
<Drawer <Drawer
sx={{ width: open ? openWidth : closedWidth, flexShrink: 0 }} sx={{ width: open ? openWidth : closedWidth, flexShrink: 0 }}
@ -152,9 +164,31 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
sx: { sx: {
width: open ? openWidth : closedWidth, width: open ? openWidth : closedWidth,
border: 0, border: 0,
overflow: "visible",
}, },
}} }}
> >
<Box
sx={{
position: "absolute",
top: 20,
right: open ? -8 : -16,
color: "#1C75FD",
rotate: open ? "90deg" : "-90deg",
}}
onClick={() => {
setOpen!(!open);
}}
>
<ExpandCircleDownIcon
sx={{
width: 30,
height: 30,
background: "white",
borderRadius: 500,
}}
/>
</Box>
<Grid <Grid
container container
direction="column" direction="column"
@ -163,8 +197,14 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
sx={{ backgroundColor: "#25272A", height: "100%", p: 2 }} sx={{ backgroundColor: "#25272A", height: "100%", p: 2 }}
> >
<Grid item container> <Grid item container>
<Grid item> <Grid item sx={{ width: open ? "40px" : "100%" }}>
<Box sx={{ width: "40px", height: "40px" }}> <Box
sx={{
width: "40px",
height: "40px",
margin: open ? "0" : "0 auto",
}}
>
<Image <Image
src={LinkLogo} src={LinkLogo}
alt="Link logo" alt="Link logo"
@ -178,21 +218,23 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
</Box> </Box>
. .
</Grid> </Grid>
<Grid item> {open && (
<Typography <Grid item>
variant="h2" <Typography
sx={{ variant="h2"
fontSize: 26, sx={{
color: "white", fontSize: 26,
fontWeight: 700, color: "white",
mt: 1, fontWeight: 700,
ml: 0.5, mt: 1,
fontFamily: "Poppins", ml: 0.5,
}} fontFamily: "Poppins",
> }}
CDR Link >
</Typography> CDR Link
</Grid> </Typography>
</Grid>
)}
</Grid> </Grid>
<Grid item> <Grid item>
<Box <Box
@ -207,7 +249,12 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
<Grid item> <Grid item>
<Typography <Typography
variant="h6" variant="h6"
sx={{ fontSize: 12, color: "#999", fontWeight: "bold" }} sx={{
fontSize: 12,
color: "#999",
fontWeight: "bold",
textAlign: open ? "left" : "center",
}}
> >
Hello Hello
</Typography> </Typography>
@ -215,9 +262,20 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
<Grid item> <Grid item>
<Typography <Typography
variant="h2" variant="h2"
sx={{ fontSize: 22, color: "white", mb: 1.5, fontWeight: "bold" }} sx={{
fontSize: 22,
color: "white",
mb: 1.5,
fontWeight: "bold",
textAlign: open ? "left" : "center",
}}
> >
Nicholas {open
? username
: username
.split(" ")
.map((name) => name.substring(0, 1))
.join("")}
</Typography> </Typography>
</Grid> </Grid>
<Grid item> <Grid item>
@ -270,6 +328,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={CottageIcon} Icon={CottageIcon}
iconSize={20} iconSize={20}
selected={pathname.endsWith("/")} selected={pathname.endsWith("/")}
open={open}
/> />
<MenuItem <MenuItem
name="Tickets" name="Tickets"
@ -277,6 +336,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={FeaturedPlayListIcon} Icon={FeaturedPlayListIcon}
selected={pathname.startsWith("/tickets")} selected={pathname.startsWith("/tickets")}
iconSize={20} iconSize={20}
open={open}
/> />
<Collapse <Collapse
@ -293,6 +353,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
iconSize={0} iconSize={0}
selected={pathname.endsWith("/tickets/assigned")} selected={pathname.endsWith("/tickets/assigned")}
badge={3} badge={3}
open={open}
/> />
<MenuItem <MenuItem
name="Urgent" name="Urgent"
@ -301,6 +362,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
iconSize={0} iconSize={0}
selected={pathname.endsWith("/tickets/urgent")} selected={pathname.endsWith("/tickets/urgent")}
badge={1} badge={1}
open={open}
/> />
<MenuItem <MenuItem
name="Pending" name="Pending"
@ -309,6 +371,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
iconSize={0} iconSize={0}
selected={pathname.endsWith("/tickets/pending")} selected={pathname.endsWith("/tickets/pending")}
badge={9} badge={9}
open={open}
/> />
<MenuItem <MenuItem
name="Unassigned" name="Unassigned"
@ -317,6 +380,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
iconSize={0} iconSize={0}
selected={pathname.endsWith("/tickets/unnassigned")} selected={pathname.endsWith("/tickets/unnassigned")}
badge={27} badge={27}
open={open}
/> />
<MenuItem <MenuItem
name="New Ticket UI" name="New Ticket UI"
@ -324,6 +388,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={SettingsIcon} Icon={SettingsIcon}
iconSize={0} iconSize={0}
selected={pathname.endsWith("/tickets/181")} selected={pathname.endsWith("/tickets/181")}
open={open}
/> />
</List> </List>
</Collapse> </Collapse>
@ -334,6 +399,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={AnalyticsIcon} Icon={AnalyticsIcon}
iconSize={20} iconSize={20}
selected={pathname.endsWith("/leafcutter")} selected={pathname.endsWith("/leafcutter")}
open={open}
/> />
<Collapse <Collapse
in={pathname.startsWith("/leafcutter")} in={pathname.startsWith("/leafcutter")}
@ -347,6 +413,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
href="/leafcutter" href="/leafcutter"
iconSize={0} iconSize={0}
selected={pathname.endsWith("/leafcutter")} selected={pathname.endsWith("/leafcutter")}
open={open}
/> />
<MenuItem <MenuItem
@ -354,6 +421,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
href="/leafcutter/create" href="/leafcutter/create"
iconSize={0} iconSize={0}
selected={pathname.endsWith("/leafcutter/create")} selected={pathname.endsWith("/leafcutter/create")}
open={open}
/> />
<MenuItem <MenuItem
@ -361,6 +429,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
href="/leafcutter/trends" href="/leafcutter/trends"
iconSize={0} iconSize={0}
selected={pathname.endsWith("/leafcutter/trends")} selected={pathname.endsWith("/leafcutter/trends")}
open={open}
/> />
<MenuItem <MenuItem
@ -368,6 +437,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
href="/leafcutter/faq" href="/leafcutter/faq"
iconSize={0} iconSize={0}
selected={pathname.endsWith("/leafcutter/faq")} selected={pathname.endsWith("/leafcutter/faq")}
open={open}
/> />
<MenuItem <MenuItem
@ -376,6 +446,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={AnalyticsIcon} Icon={AnalyticsIcon}
iconSize={0} iconSize={0}
selected={pathname.endsWith("/leafcutter/about")} selected={pathname.endsWith("/leafcutter/about")}
open={open}
/> />
</List> </List>
</Collapse> </Collapse>
@ -385,12 +456,14 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={PersonIcon} Icon={PersonIcon}
iconSize={20} iconSize={20}
selected={pathname.endsWith("/profile")} selected={pathname.endsWith("/profile")}
open={open}
/> />
<MenuItem <MenuItem
name="Admin" name="Admin"
href="/admin/zammad" href="/admin/zammad"
Icon={SettingsIcon} Icon={SettingsIcon}
iconSize={20} iconSize={20}
open={open}
/> />
<Collapse <Collapse
in={pathname.startsWith("/admin/")} in={pathname.startsWith("/admin/")}
@ -405,6 +478,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={FeaturedPlayListIcon} Icon={FeaturedPlayListIcon}
iconSize={0} iconSize={0}
selected={pathname.endsWith("/admin/zammad")} selected={pathname.endsWith("/admin/zammad")}
open={open}
/> />
<MenuItem <MenuItem
name="Metamigo" name="Metamigo"
@ -412,6 +486,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={FeaturedPlayListIcon} Icon={FeaturedPlayListIcon}
iconSize={0} iconSize={0}
selected={pathname.endsWith("/admin/metamigo")} selected={pathname.endsWith("/admin/metamigo")}
open={open}
/> />
<MenuItem <MenuItem
name="Label Studio" name="Label Studio"
@ -419,6 +494,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
Icon={FeaturedPlayListIcon} Icon={FeaturedPlayListIcon}
iconSize={0} iconSize={0}
selected={pathname.endsWith("/admin/label-studio")} selected={pathname.endsWith("/admin/label-studio")}
open={open}
/> />
</List> </List>
</Collapse> </Collapse>
@ -428,6 +504,7 @@ export const Sidebar: FC<SidebarProps> = ({ open }) => {
href="/logout" href="/logout"
Icon={LogoutIcon} Icon={LogoutIcon}
iconSize={20} iconSize={20}
open={open}
/> />
</List> </List>
</Grid> </Grid>

View file

@ -1,5 +1,5 @@
import { FC, useEffect } from "react"; import { FC, useEffect } from "react";
import { Grid, Box, Typography } from "@mui/material"; import { Grid, Box, Typography, Button } from "@mui/material";
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css"; import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
import { import {
MainContainer, MainContainer,
@ -19,61 +19,124 @@ interface TicketDetailProps {
export const TicketDetail: FC<TicketDetailProps> = ({ ticket, articles }) => { export const TicketDetail: FC<TicketDetailProps> = ({ ticket, articles }) => {
console.log({ here: "here", ticket }); console.log({ here: "here", ticket });
return ( return (
<MainContainer> <>
<ChatContainer> <MainContainer>
<ConversationHeader> <ChatContainer>
<ConversationHeader.Content> <ConversationHeader>
<Box <ConversationHeader.Content>
sx={{ <Box
width: "100%", sx={{
width: "100%",
textAlign: "center", textAlign: "center",
fontWeight: "bold", fontWeight: "bold",
}} }}
>
<Typography
variant="h5"
sx={{ fontFamily: "Poppins", fontWeight: 700 }}
> >
{ticket.title} <Typography
</Typography> variant="h5"
<Typography sx={{ fontFamily: "Poppins", fontWeight: 700 }}
variant="h6" >
sx={{ fontFamily: "Roboto", fontWeight: 400 }} {ticket.title}
>{`Ticket #${ticket.number} (created ${new Date( </Typography>
ticket.created_at <Typography
).toLocaleDateString()})`}</Typography> variant="h6"
</Box> sx={{ fontFamily: "Roboto", fontWeight: 400 }}
</ConversationHeader.Content> >{`Ticket #${ticket.number} (created ${new Date(
</ConversationHeader> ticket.created_at
<MessageList> ).toLocaleDateString()})`}</Typography>
{articles.map((article: any) => ( </Box>
<Message </ConversationHeader.Content>
className={ </ConversationHeader>
article.internal <MessageList style={{ marginBottom: 80 }}>
? "internal-note" {articles.map((article: any) => (
: article.sender === "Agent" <Message
? "outgoing-message" className={
: "incoming-message" article.internal
} ? "internal-note"
model={{ : article.sender === "Agent"
message: article.body.replace(/<div>*<br>*<div>/g, ""), ? "outgoing-message"
sentTime: article.updated_at, : "incoming-message"
sender: article.from, }
direction: article.sender === "Agent" ? "outgoing" : "incoming", model={{
position: "last", message: article.body.replace(/<div>*<br>*<div>/g, ""),
type: "html", sentTime: article.updated_at,
}} sender: article.from,
/> direction:
))} article.sender === "Agent" ? "outgoing" : "incoming",
</MessageList> position: "last",
{/* <MessageInput type: "html",
}}
/>
))}
</MessageList>
{/* <MessageInput
placeholder="Type message here" placeholder="Type message here"
sendOnReturnDisabled sendOnReturnDisabled
attachButton={false} attachButton={false}
sendButton={false} sendButton={false}
/> */} /> */}
</ChatContainer> </ChatContainer>
</MainContainer> <Box
sx={{
height: 80,
background: "#eeeeee",
borderTop: "1px solid #ddd",
position: "absolute",
bottom: 0,
width: "100%",
zIndex: 1000,
}}
>
<Grid
container
spacing={4}
justifyContent="center"
alignItems="center"
alignContent={"center"}
sx={{ height: 72 }}
>
<Grid item>
<Button
variant="contained"
disableElevation
sx={{
fontFamily: "Poppins, sans-serif",
fontWeight: 700,
borderRadius: 2,
textTransform: "none",
backgroundColor: "#1982FC",
padding: "6px 30px",
margin: "20px 0px",
whiteSpace: "nowrap",
py: "10px",
}}
>
Reply to ticket
</Button>
</Grid>
<Grid item>
<Button
variant="contained"
disableElevation
sx={{
fontFamily: "Poppins, sans-serif",
fontWeight: 700,
borderRadius: 2,
textTransform: "none",
color: "black",
backgroundColor: "#FFB620",
padding: "6px 30px",
margin: "20px 0px",
whiteSpace: "nowrap",
py: "10px",
}}
>
Write note to agent
</Button>
</Grid>
</Grid>
</Box>
</MainContainer>
</>
); );
}; };

View file

@ -24,7 +24,10 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
const linkElement = document.querySelector("iframe"); const linkElement = document.querySelector("iframe");
if ( if (
linkElement.contentDocument && linkElement.contentDocument &&
linkElement.contentDocument?.querySelector linkElement.contentDocument?.querySelector &&
linkElement.contentDocument.querySelector("#navigation") &&
linkElement.contentDocument.querySelector("body") &&
linkElement.contentDocument.querySelector(".sidebar")
) { ) {
// @ts-ignore // @ts-ignore
linkElement.contentDocument.querySelector("#navigation").style = linkElement.contentDocument.querySelector("#navigation").style =
@ -38,8 +41,8 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
linkElement.contentDocument.querySelector(".sidebar").style = linkElement.contentDocument.querySelector(".sidebar").style =
"display: none"; "display: none";
} }
setDisplay("inherit");
} }
setDisplay("inherit");
}} }}
/> />
); );

1450
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@chatscope/chat-ui-kit-react": "^1.9.8", "@chatscope/chat-ui-kit-react": "^1.9.9",
"@chatscope/chat-ui-kit-styles": "^1.4.0", "@chatscope/chat-ui-kit-styles": "^1.4.0",
"@emotion/cache": "^11.10.5", "@emotion/cache": "^11.10.5",
"@emotion/react": "^11.10.5", "@emotion/react": "^11.10.5",
@ -19,15 +19,15 @@
"@fontsource/poppins": "^4.5.10", "@fontsource/poppins": "^4.5.10",
"@fontsource/roboto": "^4.5.8", "@fontsource/roboto": "^4.5.8",
"@mui/icons-material": "^5", "@mui/icons-material": "^5",
"@mui/lab": "^5.0.0-alpha.112", "@mui/lab": "^5.0.0-alpha.115",
"@mui/material": "^5", "@mui/material": "^5",
"@mui/x-data-grid-pro": "^5.17.15", "@mui/x-data-grid-pro": "^5.17.18",
"@mui/x-date-pickers-pro": "^5.0.10", "@mui/x-date-pickers-pro": "^5.0.13",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"http-proxy-middleware": "^2.0.6", "http-proxy-middleware": "^2.0.6",
"material-ui-popup-state": "^5.0.3", "material-ui-popup-state": "^5.0.4",
"next": "^13.0", "next": "^13.1",
"next-auth": "^4.18.6", "next-auth": "^4.18.8",
"next-http-proxy-middleware": "^1.2.5", "next-http-proxy-middleware": "^1.2.5",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
@ -36,18 +36,18 @@
"swr": "^2.0.0" "swr": "^2.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.5", "@babel/core": "^7.20.12",
"@types/react": "^18", "@types/react": "^18",
"@types/uuid": "^9.0.0", "@types/uuid": "^9.0.0",
"babel-loader": "^9.1.0", "babel-loader": "^9.1.2",
"eslint": "^8.29.0", "eslint": "^8.31.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "^13.0.6", "eslint-config-next": "^13.1.1",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.6.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-jsx-a11y": "^6.7.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.11", "eslint-plugin-react": "^7.32.0",
"typescript": "^4.9.4" "typescript": "^4.9.4"
} }
} }