Sidebar and edit updates
This commit is contained in:
parent
d73b194d1f
commit
f13530f043
32 changed files with 3057 additions and 1114 deletions
|
|
@ -17,24 +17,24 @@
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/server": "^11.11.0",
|
"@emotion/server": "^11.11.0",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@fontsource/playfair-display": "^5.0.13",
|
"@fontsource/playfair-display": "^5.0.15",
|
||||||
"@fontsource/poppins": "^5.0.8",
|
"@fontsource/poppins": "^5.0.8",
|
||||||
"@fontsource/roboto": "^5.0.8",
|
"@fontsource/roboto": "^5.0.8",
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/lab": "^5.0.0-alpha.146",
|
"@mui/lab": "^5.0.0-alpha.148",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^6.16.0",
|
"@mui/x-data-grid-pro": "^6.16.2",
|
||||||
"@mui/x-date-pickers-pro": "^6.16.0",
|
"@mui/x-date-pickers-pro": "^6.16.2",
|
||||||
"@opensearch-project/opensearch": "^2.3.1",
|
"@opensearch-project/opensearch": "^2.4.0",
|
||||||
"cryptr": "^6.3.0",
|
"cryptr": "^6.3.0",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"leafcutter-common": "*",
|
"leafcutter-common": "*",
|
||||||
"material-ui-popup-state": "^5.0.9",
|
"material-ui-popup-state": "^5.0.9",
|
||||||
"next": "13.5.3",
|
"next": "13.5.4",
|
||||||
"next-auth": "^4.23.1",
|
"next-auth": "^4.23.2",
|
||||||
"next-http-proxy-middleware": "^1.2.5",
|
"next-http-proxy-middleware": "^1.2.6",
|
||||||
"nodemailer": "^6.9.5",
|
"nodemailer": "^6.9.6",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-cookie": "^6.1.1",
|
"react-cookie": "^6.1.1",
|
||||||
"react-cookie-consent": "^8.0.1",
|
"react-cookie-consent": "^8.0.1",
|
||||||
|
|
@ -48,18 +48,18 @@
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.23.0",
|
"@babel/core": "^7.23.2",
|
||||||
"@types/node": "^20.8.0",
|
"@types/node": "^20.8.6",
|
||||||
"@types/react": "18.2.24",
|
"@types/react": "18.2.28",
|
||||||
"@types/uuid": "^9.0.4",
|
"@types/uuid": "^9.0.5",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.51.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-next": "^13.5.3",
|
"eslint-config-next": "^13.5.4",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-plugin-import": "^2.28.1",
|
"eslint-plugin-import": "^2.28.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"typescript": "5.2.2"
|
"typescript": "5.2.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
150
apps/link/app/(main)/_components/SearchBox.tsx
Normal file
150
apps/link/app/(main)/_components/SearchBox.tsx
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
import { FC, useState, useEffect } from "react";
|
||||||
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
|
import useSWR from "swr";
|
||||||
|
import { Grid, Box, TextField, Autocomplete } from "@mui/material";
|
||||||
|
import { searchQuery } from "@/app/_graphql/searchQuery";
|
||||||
|
import { colors } from "@/app/_styles/theme";
|
||||||
|
|
||||||
|
type SearchResultProps = {
|
||||||
|
props: any;
|
||||||
|
option: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SearchInput = (params: any) => (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
placeholder="Search"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderRadius: 10,
|
||||||
|
"& .MuiOutlinedInput-root": {
|
||||||
|
borderRadius: 10,
|
||||||
|
py: 0,
|
||||||
|
legend: {
|
||||||
|
marginLeft: "30px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"& .MuiAutocomplete-inputRoot": {
|
||||||
|
paddingLeft: "20px !important",
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
"& .MuiInputLabel-outlined": {
|
||||||
|
paddingLeft: "20px",
|
||||||
|
},
|
||||||
|
"& .MuiInputLabel-shrink": {
|
||||||
|
marginLeft: "20px",
|
||||||
|
paddingLeft: "10px",
|
||||||
|
paddingRight: 0,
|
||||||
|
background: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const SearchResult: FC<SearchResultProps> = ({ props, option }) => {
|
||||||
|
console.log({ option });
|
||||||
|
|
||||||
|
const { lightGrey, mediumGray, black, white } = colors;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
{...props}
|
||||||
|
sx={{
|
||||||
|
px: 2,
|
||||||
|
py: 1.25,
|
||||||
|
":hover": {
|
||||||
|
background: `${lightGrey}`,
|
||||||
|
},
|
||||||
|
a: {
|
||||||
|
color: `${black} !important`,
|
||||||
|
},
|
||||||
|
borderBottom: `1px solid ${mediumGray}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid container direction="column" spacing={0.1}>
|
||||||
|
<Grid item container direction="row" justifyContent="space-between">
|
||||||
|
<Grid item>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
py: 0,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: 500,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{option.title}
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
color: "#999",
|
||||||
|
fontSize: 13,
|
||||||
|
wrap: "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{option.note}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SearchBox: FC = () => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [selectedValue, setSelectedValue] = useState(null);
|
||||||
|
const [searchTerms, setSearchTerms] = useState(null);
|
||||||
|
const pathname = usePathname();
|
||||||
|
const router = useRouter();
|
||||||
|
const { data, error }: any = useSWR({
|
||||||
|
document: searchQuery,
|
||||||
|
variables: {
|
||||||
|
search: searchTerms ?? "",
|
||||||
|
limit: 50,
|
||||||
|
},
|
||||||
|
refreshInterval: 10000,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOpen(false);
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Autocomplete
|
||||||
|
forcePopupIcon={false}
|
||||||
|
openOnFocus
|
||||||
|
blurOnSelect
|
||||||
|
value={selectedValue}
|
||||||
|
onBlur={() => setOpen(false)}
|
||||||
|
inputValue={searchTerms}
|
||||||
|
onChange={(_event, option, reason) => {
|
||||||
|
if (!option) return;
|
||||||
|
const url = `/tickets/${option.internalId}`;
|
||||||
|
setSelectedValue("");
|
||||||
|
router.push(url);
|
||||||
|
}}
|
||||||
|
onInputChange={(_event, value) => {
|
||||||
|
setSearchTerms(value);
|
||||||
|
}}
|
||||||
|
open={open}
|
||||||
|
onOpen={() => setOpen(true)}
|
||||||
|
noOptionsText="No results"
|
||||||
|
options={data?.search ?? []}
|
||||||
|
getOptionLabel={(option: any) => {
|
||||||
|
if (option) {
|
||||||
|
return option.title;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
renderOption={(props, option: any) => (
|
||||||
|
<SearchResult props={props} key={option.id} option={option} />
|
||||||
|
)}
|
||||||
|
sx={{ width: "100%" }}
|
||||||
|
renderInput={(params: any) => <SearchInput {...params} />}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FC, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
|
|
@ -26,6 +26,7 @@ import {
|
||||||
Assessment as AssessmentIcon,
|
Assessment as AssessmentIcon,
|
||||||
LibraryBooks as LibraryBooksIcon,
|
LibraryBooks as LibraryBooksIcon,
|
||||||
School as SchoolIcon,
|
School as SchoolIcon,
|
||||||
|
Search as SearchIcon,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
@ -33,8 +34,8 @@ import Image from "next/image";
|
||||||
import LinkLogo from "public/link-logo-small.png";
|
import LinkLogo from "public/link-logo-small.png";
|
||||||
import { useSession, signOut } from "next-auth/react";
|
import { useSession, signOut } from "next-auth/react";
|
||||||
import { getTicketOverviewCountsQuery } from "app/_graphql/getTicketOverviewCountsQuery";
|
import { getTicketOverviewCountsQuery } from "app/_graphql/getTicketOverviewCountsQuery";
|
||||||
|
import { SearchBox } from "./SearchBox";
|
||||||
|
|
||||||
console.log;
|
|
||||||
const openWidth = 270;
|
const openWidth = 270;
|
||||||
const closedWidth = 100;
|
const closedWidth = 100;
|
||||||
|
|
||||||
|
|
@ -174,13 +175,15 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
},
|
},
|
||||||
{ refreshInterval: 10000 },
|
{ refreshInterval: 10000 },
|
||||||
);
|
);
|
||||||
|
console.log({ overviewData });
|
||||||
const findOverviewCountByID = (id: number) =>
|
const findOverviewCountByID = (id: number) =>
|
||||||
overviewData?.ticketOverviews?.edges?.find((overview: any) =>
|
overviewData?.ticketOverviews?.edges?.find((overview: any) =>
|
||||||
overview.node.id.endsWith(`/${id}`),
|
overview.node.id.endsWith(`/${id}`),
|
||||||
)?.node?.ticketCount ?? 0;
|
)?.node?.ticketCount ?? 0;
|
||||||
|
const recentCount = 0;
|
||||||
const assignedCount = findOverviewCountByID(1);
|
const assignedCount = findOverviewCountByID(1);
|
||||||
|
const openCount = findOverviewCountByID(5);
|
||||||
const urgentCount = findOverviewCountByID(7);
|
const urgentCount = findOverviewCountByID(7);
|
||||||
const pendingCount = findOverviewCountByID(3);
|
|
||||||
const unassignedCount = findOverviewCountByID(2);
|
const unassignedCount = findOverviewCountByID(2);
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
|
|
@ -227,6 +230,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
direction="column"
|
direction="column"
|
||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
wrap="nowrap"
|
wrap="nowrap"
|
||||||
|
spacing={0}
|
||||||
sx={{ backgroundColor: "#25272A", height: "100%", p: 2 }}
|
sx={{ backgroundColor: "#25272A", height: "100%", p: 2 }}
|
||||||
>
|
>
|
||||||
<Grid item container>
|
<Grid item container>
|
||||||
|
|
@ -313,9 +317,17 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Box
|
<Box
|
||||||
sx={{ height: "0.5px", width: "100%", backgroundColor: "#666" }}
|
sx={{
|
||||||
|
height: "0.5px",
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: "#666",
|
||||||
|
mb: 2,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<SearchBox />
|
||||||
|
</Grid>
|
||||||
<Grid
|
<Grid
|
||||||
item
|
item
|
||||||
container
|
container
|
||||||
|
|
@ -377,7 +389,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
/>
|
/>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
name="Tickets"
|
name="Tickets"
|
||||||
href="/overview/assigned"
|
href="/overview/recent"
|
||||||
Icon={FeaturedPlayListIcon}
|
Icon={FeaturedPlayListIcon}
|
||||||
selected={
|
selected={
|
||||||
pathname.startsWith("/overview") ||
|
pathname.startsWith("/overview") ||
|
||||||
|
|
@ -397,12 +409,21 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
>
|
>
|
||||||
<List component="div" disablePadding>
|
<List component="div" disablePadding>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
name="Assigned"
|
name="Recent"
|
||||||
href="/overview/assigned"
|
href="/overview/recent"
|
||||||
Icon={FeaturedPlayListIcon}
|
Icon={FeaturedPlayListIcon}
|
||||||
iconSize={0}
|
iconSize={0}
|
||||||
selected={pathname.endsWith("/overview/assigned")}
|
selected={pathname.endsWith("/overview/recent")}
|
||||||
badge={assignedCount}
|
badge={recentCount}
|
||||||
|
open={open}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
name="Open"
|
||||||
|
href="/overview/open"
|
||||||
|
Icon={FeaturedPlayListIcon}
|
||||||
|
iconSize={0}
|
||||||
|
selected={pathname.endsWith("/overview/open")}
|
||||||
|
badge={openCount}
|
||||||
open={open}
|
open={open}
|
||||||
/>
|
/>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|
@ -415,12 +436,12 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
|
||||||
open={open}
|
open={open}
|
||||||
/>
|
/>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
name="Pending"
|
name="Assigned"
|
||||||
href="/overview/pending"
|
href="/overview/assigned"
|
||||||
Icon={FeaturedPlayListIcon}
|
Icon={FeaturedPlayListIcon}
|
||||||
iconSize={0}
|
iconSize={0}
|
||||||
selected={pathname.endsWith("/overview/pending")}
|
selected={pathname.endsWith("/overview/assigned")}
|
||||||
badge={pendingCount}
|
badge={assignedCount}
|
||||||
open={open}
|
open={open}
|
||||||
/>
|
/>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FC, useState, useEffect } from "react";
|
import { FC, useState, useEffect, useRef } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Iframe from "react-iframe";
|
import Iframe from "react-iframe";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
|
|
@ -16,7 +16,8 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
|
||||||
hideSidebar = true,
|
hideSidebar = true,
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession({ required: true });
|
||||||
|
const timeoutRef = useRef(null);
|
||||||
const [authenticated, setAuthenticated] = useState(false);
|
const [authenticated, setAuthenticated] = useState(false);
|
||||||
const [display, setDisplay] = useState("none");
|
const [display, setDisplay] = useState("none");
|
||||||
const url = `/zammad${path}`;
|
const url = `/zammad${path}`;
|
||||||
|
|
@ -28,7 +29,7 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
redirect: "manual",
|
redirect: "manual",
|
||||||
});
|
});
|
||||||
|
console.log({ res });
|
||||||
if (res.type === "opaqueredirect") {
|
if (res.type === "opaqueredirect") {
|
||||||
setAuthenticated(true);
|
setAuthenticated(true);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -39,8 +40,24 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
|
||||||
checkAuthenticated();
|
checkAuthenticated();
|
||||||
}, [path]);
|
}, [path]);
|
||||||
|
|
||||||
if (!session) {
|
useEffect(() => {
|
||||||
console.log("No session");
|
if (session === null) {
|
||||||
|
timeoutRef.current = setTimeout(() => {
|
||||||
|
if (session === null) {
|
||||||
|
router.push("/login");
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session !== null) {
|
||||||
|
clearTimeout(timeoutRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => clearTimeout(timeoutRef.current);
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
|
if (!session || !authenticated) {
|
||||||
|
console.log("Not authenticated");
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: "100%" }}>
|
<Box sx={{ width: "100%" }}>
|
||||||
<Grid
|
<Grid
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { FC, useState } from "react";
|
||||||
|
import {
|
||||||
|
Grid,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
TextField,
|
||||||
|
Autocomplete
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useSWRConfig } from "swr";
|
||||||
|
import { createTicketMutation } from "app/_graphql/createTicketMutation";
|
||||||
|
|
||||||
|
interface TicketCreateDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
closeDialog: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TicketCreateDialog: FC<TicketCreateDialogProps> = ({
|
||||||
|
open,
|
||||||
|
closeDialog,
|
||||||
|
}) => {
|
||||||
|
const [kind, setKind] = useState("note");
|
||||||
|
const [customerID, setCustomerID] = useState("");
|
||||||
|
const [groupID, setGroupID] = useState("");
|
||||||
|
const [ownerID, setOwnerID] = useState("");
|
||||||
|
const [priorityID, setPriorityID] = useState("");
|
||||||
|
const [stateID, setStateID] = useState("");
|
||||||
|
const [tags, setTags] = useState([]);
|
||||||
|
const [title, setTitle] = useState("");
|
||||||
|
const [body, setBody] = useState("");
|
||||||
|
const backgroundColor = kind === "note" ? "#FFB620" : "#1982FC";
|
||||||
|
const color = kind === "note" ? "black" : "white";
|
||||||
|
const { fetcher } = useSWRConfig();
|
||||||
|
const ticket = {
|
||||||
|
customerId: customerID,
|
||||||
|
groupId: groupID,
|
||||||
|
ownerId: ownerID,
|
||||||
|
priorityId: priorityID,
|
||||||
|
stateId: stateID,
|
||||||
|
tags,
|
||||||
|
title,
|
||||||
|
article: {
|
||||||
|
body,
|
||||||
|
type: kind,
|
||||||
|
internal: kind === "note",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const createTicket = async () => {
|
||||||
|
await fetcher({
|
||||||
|
document: createTicketMutation,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
ticket
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
closeDialog();
|
||||||
|
setBody("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} maxWidth="md" fullWidth>
|
||||||
|
<DialogContent>
|
||||||
|
<Grid container direction="column" spacing={2}>
|
||||||
|
<Grid item>
|
||||||
|
<TextField
|
||||||
|
label={"Title"}
|
||||||
|
fullWidth
|
||||||
|
value={title}
|
||||||
|
onChange={(e: any) => setTitle(e.target.value)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Autocomplete
|
||||||
|
disablePortal
|
||||||
|
options={[{ label: "Test One", id: 1 }, { label: "Test Two", id: 2 }]}
|
||||||
|
sx={{ width: 300 }}
|
||||||
|
onChange={(e: any) => setCustomerID(e.target.value)}
|
||||||
|
renderInput={(params) => <TextField {...params} label="Customer" />}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<TextField
|
||||||
|
label={"Details"}
|
||||||
|
multiline
|
||||||
|
rows={10}
|
||||||
|
fullWidth
|
||||||
|
value={body}
|
||||||
|
onChange={(e: any) => setBody(e.target.value)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions sx={{ px: 3, pt: 0, pb: 3 }}>
|
||||||
|
<Grid container justifyContent="space-between">
|
||||||
|
<Grid item>
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
color: "#666",
|
||||||
|
fontFamily: "Poppins, sans-serif",
|
||||||
|
fontWeight: 700,
|
||||||
|
borderRadius: 2,
|
||||||
|
textTransform: "none",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setBody("");
|
||||||
|
closeDialog();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
backgroundColor,
|
||||||
|
color,
|
||||||
|
fontFamily: "Poppins, sans-serif",
|
||||||
|
fontWeight: 700,
|
||||||
|
borderRadius: 2,
|
||||||
|
textTransform: "none",
|
||||||
|
px: 3,
|
||||||
|
}}
|
||||||
|
onClick={createTicket}
|
||||||
|
>
|
||||||
|
{kind === "note" ? "Save Note" : "Send Reply"}
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FC } from "react";
|
import { FC, useState } from "react";
|
||||||
import { Grid, Box } from "@mui/material";
|
import { Grid, Box } from "@mui/material";
|
||||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||||
import { StyledDataGrid } from "../../../_components/StyledDataGrid";
|
import { StyledDataGrid } from "../../../_components/StyledDataGrid";
|
||||||
import { Button } from "../../../../_components/Button";
|
import { Button } from "../../../../_components/Button";
|
||||||
import { typography } from "../../../../_styles/theme";
|
import { typography } from "../../../../_styles/theme";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { TicketCreateDialog } from "./TicketCreateDialog";
|
||||||
|
|
||||||
interface TicketListProps {
|
interface TicketListProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -14,72 +15,96 @@ interface TicketListProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TicketList: FC<TicketListProps> = ({ title, tickets }) => {
|
export const TicketList: FC<TicketListProps> = ({ title, tickets }) => {
|
||||||
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
let gridColumns: GridColDef[] = [
|
let gridColumns: GridColDef[] = [
|
||||||
{
|
{
|
||||||
field: "number",
|
field: "number",
|
||||||
headerName: "Number",
|
headerName: "Number",
|
||||||
flex: 0.3,
|
flex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "title",
|
field: "title",
|
||||||
headerName: "Title",
|
headerName: "Title",
|
||||||
flex: 1.5,
|
flex: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "customer",
|
field: "customer",
|
||||||
headerName: "Sender",
|
headerName: "Sender",
|
||||||
valueGetter: (params) => params.row?.customer?.fullname,
|
valueGetter: (params) => params.row?.customer?.fullname,
|
||||||
flex: 0.6,
|
flex: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "createdAt",
|
||||||
|
headerName: "Created At",
|
||||||
|
valueGetter: (params) => new Date(params.row?.createdAt).toLocaleString(),
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "updatedAt",
|
||||||
|
headerName: "Updated At",
|
||||||
|
valueGetter: (params) => new Date(params.row?.updatedAt).toLocaleString(),
|
||||||
|
flex: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "group",
|
field: "group",
|
||||||
headerName: "Group",
|
headerName: "Group",
|
||||||
valueGetter: (params) => params.row?.group?.name,
|
valueGetter: (params) => params.row?.group?.name,
|
||||||
flex: 0.3,
|
flex: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
console.log({ tickets });
|
|
||||||
const rowClick = ({ row }) => {
|
const rowClick = ({ row }) => {
|
||||||
router.push(`/tickets/${row.internalId}`);
|
router.push(`/tickets/${row.internalId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ height: "100vh", backgroundColor: "#ddd", p: 3 }}>
|
<>
|
||||||
<Grid container direction="column">
|
<Box sx={{ height: "100vh", backgroundColor: "#ddd", p: 3 }}>
|
||||||
<Grid
|
<Grid container direction="column">
|
||||||
item
|
<Grid
|
||||||
container
|
item
|
||||||
direction="row"
|
container
|
||||||
justifyContent="space-between"
|
direction="row"
|
||||||
alignItems="center"
|
justifyContent="space-between"
|
||||||
>
|
alignItems="center"
|
||||||
<Grid item>
|
>
|
||||||
<Box
|
<Grid item>
|
||||||
sx={{
|
<Box
|
||||||
backgroundColor: "#ddd",
|
sx={{
|
||||||
px: "8px",
|
backgroundColor: "#ddd",
|
||||||
pb: "16px",
|
px: "8px",
|
||||||
...typography.h4,
|
pb: "16px",
|
||||||
fontSize: 24,
|
...typography.h4,
|
||||||
}}
|
fontSize: 24,
|
||||||
>
|
}}
|
||||||
{title}
|
>
|
||||||
</Box>
|
{title}
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Button
|
||||||
|
href={""}
|
||||||
|
onClick={() => setDialogOpen(true)}
|
||||||
|
text="Create"
|
||||||
|
color="#1982FC"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Button href="/tickets/create" text="Create" color="#1982FC" />
|
<StyledDataGrid
|
||||||
|
name={title}
|
||||||
|
columns={gridColumns}
|
||||||
|
rows={tickets}
|
||||||
|
onRowClick={rowClick}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
</Box>
|
||||||
<StyledDataGrid
|
<TicketCreateDialog
|
||||||
name={title}
|
open={dialogOpen}
|
||||||
columns={gridColumns}
|
closeDialog={() => setDialogOpen(false)}
|
||||||
rows={tickets}
|
/>
|
||||||
onRowClick={rowClick}
|
</>
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FC } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { TicketList } from "./TicketList";
|
import { TicketList } from "./TicketList";
|
||||||
import { getTicketsByOverviewQuery } from "../../../../_graphql/getTicketsByOverviewQuery";
|
import { getTicketsByOverviewQuery } from "../../../../_graphql/getTicketsByOverviewQuery";
|
||||||
|
|
@ -11,6 +11,8 @@ type ZammadOverviewProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ZammadOverview: FC<ZammadOverviewProps> = ({ name, id }) => {
|
export const ZammadOverview: FC<ZammadOverviewProps> = ({ name, id }) => {
|
||||||
|
const [tickets, setTickets] = useState([]);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
const { data: ticketData, error: ticketError }: any = useSWR(
|
const { data: ticketData, error: ticketError }: any = useSWR(
|
||||||
{
|
{
|
||||||
document: getTicketsByOverviewQuery,
|
document: getTicketsByOverviewQuery,
|
||||||
|
|
@ -19,24 +21,57 @@ export const ZammadOverview: FC<ZammadOverviewProps> = ({ name, id }) => {
|
||||||
{ refreshInterval: 10000 },
|
{ refreshInterval: 10000 },
|
||||||
);
|
);
|
||||||
|
|
||||||
const shouldRender = !ticketError && ticketData;
|
const restFetcher = (url: string) => fetch(url).then((r) => r.json());
|
||||||
const tickets =
|
const { data: recent } = useSWR("/api/v1/recent_view", restFetcher);
|
||||||
ticketData?.ticketsByOverview?.edges.map((edge: any) => edge.node) || [];
|
|
||||||
|
|
||||||
const sortedTickets = tickets.sort((a: any, b: any) => {
|
const sortTickets = (tickets: any) => {
|
||||||
if (a.internalId < b.internalId) {
|
return tickets.sort((a: any, b: any) => {
|
||||||
return 1;
|
if (a.internalId < b.internalId) {
|
||||||
}
|
return 1;
|
||||||
if (a.internalId > b.internalId) {
|
}
|
||||||
return -1;
|
if (a.internalId > b.internalId) {
|
||||||
}
|
return -1;
|
||||||
return 0;
|
}
|
||||||
});
|
return 0;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<>
|
if (name != "Recent") {
|
||||||
{shouldRender && <TicketList title={name} tickets={sortedTickets} />}
|
const edges = ticketData?.ticketsByOverview?.edges;
|
||||||
{/*ticketError && <div>{ticketError.toString()}</div>*/}
|
if (edges) {
|
||||||
</>
|
const nodes = edges.map((edge: any) => edge.node);
|
||||||
);
|
setTickets(sortTickets(nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticketError) {
|
||||||
|
setError(ticketError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [ticketData, ticketError]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchRecentTickets = async () => {
|
||||||
|
if (name === "Recent" && recent) {
|
||||||
|
let allTickets = [];
|
||||||
|
for (const rec of recent) {
|
||||||
|
const res = await fetch(`/api/v1/tickets/${rec.o_id}`);
|
||||||
|
const tkt = await res.json();
|
||||||
|
allTickets.push({
|
||||||
|
...tkt,
|
||||||
|
internalId: tkt.id,
|
||||||
|
createdAt: tkt.created_at,
|
||||||
|
updatedAt: tkt.updated_at,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setTickets(sortTickets(allTickets));
|
||||||
|
console.log({ allTickets });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchRecentTickets();
|
||||||
|
}, [name]);
|
||||||
|
|
||||||
|
const shouldRender = tickets && !error;
|
||||||
|
|
||||||
|
return shouldRender && <TicketList title={name} tickets={tickets} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ export async function generateMetadata({
|
||||||
const overviews = {
|
const overviews = {
|
||||||
assigned: 1,
|
assigned: 1,
|
||||||
unassigned: 2,
|
unassigned: 2,
|
||||||
pending: 3,
|
recent: 3,
|
||||||
|
open: 5,
|
||||||
urgent: 7,
|
urgent: 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -36,6 +37,7 @@ type PageProps = {
|
||||||
|
|
||||||
export default function Page({ params: { overview } }: PageProps) {
|
export default function Page({ params: { overview } }: PageProps) {
|
||||||
const section = getSection(overview);
|
const section = getSection(overview);
|
||||||
|
console.log({ section });
|
||||||
|
|
||||||
return <ZammadOverview name={section} id={overviews[overview]} />;
|
return <ZammadOverview name={section} id={overviews[overview]} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ interface ArticleCreateDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
closeDialog: () => void;
|
closeDialog: () => void;
|
||||||
kind: string;
|
kind: string;
|
||||||
|
recipient?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ArticleCreateDialog: FC<ArticleCreateDialogProps> = ({
|
export const ArticleCreateDialog: FC<ArticleCreateDialogProps> = ({
|
||||||
|
|
@ -24,22 +25,29 @@ export const ArticleCreateDialog: FC<ArticleCreateDialogProps> = ({
|
||||||
open,
|
open,
|
||||||
closeDialog,
|
closeDialog,
|
||||||
kind,
|
kind,
|
||||||
|
recipient,
|
||||||
}) => {
|
}) => {
|
||||||
const [body, setBody] = useState("");
|
const [body, setBody] = useState("");
|
||||||
const backgroundColor = kind === "note" ? "#FFB620" : "#1982FC";
|
const backgroundColor = kind === "note" ? "#FFB620" : "#1982FC";
|
||||||
const color = kind === "note" ? "black" : "white";
|
const color = kind === "note" ? "black" : "white";
|
||||||
const { fetcher } = useSWRConfig();
|
const { fetcher } = useSWRConfig();
|
||||||
|
const article = {
|
||||||
|
body,
|
||||||
|
type: kind,
|
||||||
|
internal: kind === "note",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (kind === "email") {
|
||||||
|
article["to"] = recipient;
|
||||||
|
}
|
||||||
|
|
||||||
const createArticle = async () => {
|
const createArticle = async () => {
|
||||||
await fetcher({
|
await fetcher({
|
||||||
document: updateTicketMutation,
|
document: updateTicketMutation,
|
||||||
variables: {
|
variables: {
|
||||||
ticketId: `gid://zammad/Ticket/${ticketID}`,
|
ticketId: `gid://zammad/Ticket/${ticketID}`,
|
||||||
input: {
|
input: {
|
||||||
article: {
|
article,
|
||||||
body,
|
|
||||||
type: kind,
|
|
||||||
internal: kind === "note",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,10 @@ export const TicketDetail: FC<TicketDetailProps> = ({ id }) => {
|
||||||
: null;
|
: null;
|
||||||
const mostRecentExternalArticleKind =
|
const mostRecentExternalArticleKind =
|
||||||
mostRecentExternalArticle?.type?.name ?? "phone";
|
mostRecentExternalArticle?.type?.name ?? "phone";
|
||||||
|
const mostRecentEmailRecipient = mostRecentExternalArticle?.to?.name ?? "";
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const [articleKind, setArticleKind] = useState("phone");
|
const [articleKind, setArticleKind] = useState("phone");
|
||||||
|
const [recipient, setRecipient] = useState("");
|
||||||
const closeDialog = () => setDialogOpen(false);
|
const closeDialog = () => setDialogOpen(false);
|
||||||
|
|
||||||
const shouldRender =
|
const shouldRender =
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,11 @@ import {
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { MuiChipsInput } from "mui-chips-input";
|
import { MuiChipsInput } from "mui-chips-input";
|
||||||
import useSWR, { useSWRConfig } from "swr";
|
import useSWR, { useSWRConfig } from "swr";
|
||||||
import { getTicketQuery } from "../../../../../_graphql/getTicketQuery";
|
import { getTicketQuery } from "app/_graphql/getTicketQuery";
|
||||||
import { updateTicketMutation } from "../../../../../_graphql/updateTicketMutation";
|
import { updateTicketMutation } from "app/_graphql/updateTicketMutation";
|
||||||
import { updateTagsMutation } from "../../../../../_graphql/updateTagsMutation";
|
import { updateTagsMutation } from "app/_graphql/updateTagsMutation";
|
||||||
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
|
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
|
||||||
|
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
|
||||||
|
|
||||||
interface TicketEditProps {
|
interface TicketEditProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -26,6 +27,8 @@ export const TicketEdit: FC<TicketEditProps> = ({ id }) => {
|
||||||
const [selectedOwner, setSelectedOwner] = useState("");
|
const [selectedOwner, setSelectedOwner] = useState("");
|
||||||
const [selectedPriority, setSelectedPriority] = useState("");
|
const [selectedPriority, setSelectedPriority] = useState("");
|
||||||
const [selectedState, setSelectedState] = useState("");
|
const [selectedState, setSelectedState] = useState("");
|
||||||
|
const [pendingDate, setPendingDate] = useState(new Date());
|
||||||
|
const [pendingVisible, setPendingVisible] = useState(false);
|
||||||
const [selectedTags, setSelectedTags] = useState([]);
|
const [selectedTags, setSelectedTags] = useState([]);
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
console.info("You clicked the delete icon.");
|
console.info("You clicked the delete icon.");
|
||||||
|
|
@ -36,8 +39,13 @@ export const TicketEdit: FC<TicketEditProps> = ({ id }) => {
|
||||||
const { data: users } = useSWR("/api/v1/users", restFetcher);
|
const { data: users } = useSWR("/api/v1/users", restFetcher);
|
||||||
const { data: states } = useSWR("/api/v1/ticket_states", restFetcher);
|
const { data: states } = useSWR("/api/v1/ticket_states", restFetcher);
|
||||||
const { data: priorities } = useSWR("/api/v1/ticket_priorities", restFetcher);
|
const { data: priorities } = useSWR("/api/v1/ticket_priorities", restFetcher);
|
||||||
const { data: tags } = useSWR("/api/v1/tags", restFetcher);
|
const { data: recent } = useSWR("/api/v1/recent_view", restFetcher);
|
||||||
|
console.log({ recent });
|
||||||
|
// const { data: tags } = useSWR("/api/v1/tags", restFetcher);
|
||||||
|
const filteredStates = states?.filter(
|
||||||
|
(state: any) => !["new", "merged", "removed"].includes(state.name),
|
||||||
|
);
|
||||||
|
const agents = users?.filter((user: any) => user.role_ids.includes(2)) ?? [];
|
||||||
const { fetcher } = useSWRConfig();
|
const { fetcher } = useSWRConfig();
|
||||||
const { data: ticketData, error: ticketError }: any = useSWR(
|
const { data: ticketData, error: ticketError }: any = useSWR(
|
||||||
{
|
{
|
||||||
|
|
@ -60,6 +68,13 @@ export const TicketEdit: FC<TicketEditProps> = ({ id }) => {
|
||||||
setSelectedTags(ticket.tags);
|
setSelectedTags(ticket.tags);
|
||||||
}
|
}
|
||||||
}, [ticketData, ticketError]);
|
}, [ticketData, ticketError]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const stateName = filteredStates?.find(
|
||||||
|
(state: any) => state.id === selectedState,
|
||||||
|
)?.name;
|
||||||
|
setPendingVisible(stateName?.includes("pending") ?? false);
|
||||||
|
}, [selectedState]);
|
||||||
const updateTicket = async (input: any) => {
|
const updateTicket = async (input: any) => {
|
||||||
console.log({ input });
|
console.log({ input });
|
||||||
const res = await fetcher({
|
const res = await fetcher({
|
||||||
|
|
@ -128,14 +143,14 @@ export const TicketEdit: FC<TicketEditProps> = ({ id }) => {
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{users?.map((user: any) => (
|
{agents?.map((user: any) => (
|
||||||
<MenuItem key={user.id} value={user.id}>
|
<MenuItem key={user.id} value={`${user.id}`}>
|
||||||
{user.firstname} {user.lastname}
|
{user.firstname} {user.lastname}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item xs={12}>
|
||||||
<Box sx={{ m: 1, mt: 0 }}>State</Box>
|
<Box sx={{ m: 1, mt: 0 }}>State</Box>
|
||||||
<Select
|
<Select
|
||||||
value={selectedState}
|
value={selectedState}
|
||||||
|
|
@ -144,6 +159,7 @@ export const TicketEdit: FC<TicketEditProps> = ({ id }) => {
|
||||||
setSelectedState(newState);
|
setSelectedState(newState);
|
||||||
updateTicket({
|
updateTicket({
|
||||||
stateId: `gid://zammad/Ticket::State/${newState}`,
|
stateId: `gid://zammad/Ticket::State/${newState}`,
|
||||||
|
pendingTime: pendingDate.toISOString(),
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
size="small"
|
size="small"
|
||||||
|
|
@ -152,13 +168,35 @@ export const TicketEdit: FC<TicketEditProps> = ({ id }) => {
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{states?.map((state: any) => (
|
{filteredStates?.map((state: any) => (
|
||||||
<MenuItem key={state.id} value={state.id}>
|
<MenuItem key={state.id} value={state.id}>
|
||||||
{state.name}
|
{state.name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={12}
|
||||||
|
sx={{ display: pendingVisible ? "inherit" : "none" }}
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
label="Pending Date"
|
||||||
|
value={pendingDate}
|
||||||
|
onChange={(newValue: any) => {
|
||||||
|
console.log(newValue);
|
||||||
|
setPendingDate(newValue);
|
||||||
|
updateTicket({
|
||||||
|
pendingTime: newValue.toISOString(),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
slotProps={{ textField: { size: "small" } }}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: "white",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Box sx={{ m: 1, mt: 0 }}>Priority</Box>
|
<Box sx={{ m: 1, mt: 0 }}>Priority</Box>
|
||||||
<Select
|
<Select
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,15 @@ interface ButtonProps {
|
||||||
text: string;
|
text: string;
|
||||||
color: string;
|
color: string;
|
||||||
href: string;
|
href: string;
|
||||||
|
onClick: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Button: FC<ButtonProps> = ({ text, color, href }) => (
|
export const Button: FC<ButtonProps> = ({ text, color, href, onClick }) => (
|
||||||
<Link href={href} passHref>
|
<Link href={href} passHref>
|
||||||
<MUIButton
|
<MUIButton
|
||||||
variant="contained"
|
variant="contained"
|
||||||
disableElevation
|
disableElevation
|
||||||
|
onClick={onClick}
|
||||||
sx={{
|
sx={{
|
||||||
fontFamily: "Poppins, sans-serif",
|
fontFamily: "Poppins, sans-serif",
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FC, PropsWithChildren, useState } from "react";
|
import { FC, PropsWithChildren, useState, useEffect } from "react";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
import { CssBaseline } from "@mui/material";
|
import { CssBaseline } from "@mui/material";
|
||||||
import { CookiesProvider } from "react-cookie";
|
import { CookiesProvider } from "react-cookie";
|
||||||
import { SessionProvider } from "next-auth/react";
|
import { SessionProvider } from "next-auth/react";
|
||||||
|
|
@ -31,22 +32,45 @@ export const MultiProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||||
});
|
});
|
||||||
const messages: any = { en: locales.en, fr: locales.fr };
|
const messages: any = { en: locales.en, fr: locales.fr };
|
||||||
const locale = "en";
|
const locale = "en";
|
||||||
const graphQLFetcher = async ({ document, variables }: any) => {
|
const fetchAndCheckAuth = async ({ document, variables }: any) => {
|
||||||
const requestHeaders = {
|
const requestHeaders = {
|
||||||
"X-CSRF-Token": csrfToken,
|
"X-CSRF-Token": csrfToken,
|
||||||
};
|
};
|
||||||
const { data, headers } = await client.rawRequest(
|
const { data, headers, status } = await client.rawRequest(
|
||||||
document,
|
document,
|
||||||
variables,
|
variables,
|
||||||
requestHeaders,
|
requestHeaders,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
const res = await fetch("/zammad/auth/sso", {
|
||||||
|
method: "GET",
|
||||||
|
redirect: "manual",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log({ checkAuth: res });
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const token = headers.get("CSRF-Token");
|
const token = headers.get("CSRF-Token");
|
||||||
setCsrfToken(token);
|
setCsrfToken(token);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const graphQLFetcher = async ({ document, variables }: any) => {
|
||||||
|
let checks = 0;
|
||||||
|
let data = null;
|
||||||
|
|
||||||
|
while (!data && checks < 2) {
|
||||||
|
data = await fetchAndCheckAuth({ document, variables });
|
||||||
|
checks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
|
|
|
||||||
13
apps/link/app/_graphql/createTicketMutation.ts
Normal file
13
apps/link/app/_graphql/createTicketMutation.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { gql } from "graphql-request";
|
||||||
|
|
||||||
|
export const createTicketMutation = gql`
|
||||||
|
mutation CreateTicket($ticketId: ID!, $input: TicketCreateInput!) {
|
||||||
|
ticketCreate(input: $input) {
|
||||||
|
ticket {
|
||||||
|
id
|
||||||
|
priority {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
20
apps/link/app/_graphql/searchQuery.ts
Normal file
20
apps/link/app/_graphql/searchQuery.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { gql } from 'graphql-request';
|
||||||
|
|
||||||
|
export const searchQuery = gql`
|
||||||
|
query search($search: String!, $limit: Int = 10, $onlyIn: EnumSearchableModels = Ticket) {
|
||||||
|
search(search: $search, limit: $limit, onlyIn: $onlyIn) {
|
||||||
|
... on Ticket {
|
||||||
|
id
|
||||||
|
number
|
||||||
|
internalId
|
||||||
|
title
|
||||||
|
state {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
stateColorCode
|
||||||
|
note
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
@ -18,7 +18,6 @@ const fetchRoles = async () => {
|
||||||
|
|
||||||
const fetchUser = async (email: string) => {
|
const fetchUser = async (email: string) => {
|
||||||
const url = `${process.env.ZAMMAD_URL}/api/v1/users/search?query=email:${email}&limit=1`;
|
const url = `${process.env.ZAMMAD_URL}/api/v1/users/search?query=email:${email}&limit=1`;
|
||||||
console.log({ url });
|
|
||||||
const res = await fetch(url, { headers });
|
const res = await fetch(url, { headers });
|
||||||
const users = await res.json();
|
const users = await res.json();
|
||||||
const user = users?.[0];
|
const user = users?.[0];
|
||||||
|
|
|
||||||
|
|
@ -15,29 +15,29 @@
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/server": "^11.11.0",
|
"@emotion/server": "^11.11.0",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@fontsource/playfair-display": "^5.0.13",
|
"@fontsource/playfair-display": "^5.0.15",
|
||||||
"@fontsource/poppins": "^5.0.8",
|
"@fontsource/poppins": "^5.0.8",
|
||||||
"@fontsource/roboto": "^5.0.8",
|
"@fontsource/roboto": "^5.0.8",
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/lab": "^5.0.0-alpha.146",
|
"@mui/lab": "^5.0.0-alpha.148",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^6.16.0",
|
"@mui/x-data-grid-pro": "^6.16.2",
|
||||||
"@mui/x-date-pickers-pro": "^6.16.0",
|
"@mui/x-date-pickers-pro": "^6.16.2",
|
||||||
"cryptr": "^6.3.0",
|
"cryptr": "^6.3.0",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"graphql-request": "^6.1.0",
|
"graphql-request": "^6.1.0",
|
||||||
"leafcutter-common": "*",
|
"leafcutter-common": "*",
|
||||||
"material-ui-popup-state": "^5.0.9",
|
"material-ui-popup-state": "^5.0.9",
|
||||||
"mui-chips-input": "^2.1.3",
|
"mui-chips-input": "^2.1.3",
|
||||||
"next": "13.5.3",
|
"next": "13.5.4",
|
||||||
"next-auth": "^4.23.1",
|
"next-auth": "^4.23.2",
|
||||||
"ra-data-graphql": "^4.14.3",
|
"ra-data-graphql": "^4.14.3",
|
||||||
"ra-i18n-polyglot": "^4.14.4",
|
"ra-i18n-polyglot": "^4.15.0",
|
||||||
"ra-input-rich-text": "^4.14.4",
|
"ra-input-rich-text": "^4.15.0",
|
||||||
"ra-language-english": "^4.14.4",
|
"ra-language-english": "^4.15.0",
|
||||||
"ra-postgraphile": "^6.1.1",
|
"ra-postgraphile": "^6.1.2",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-admin": "^4.14.4",
|
"react-admin": "^4.15.0",
|
||||||
"react-cookie": "^6.1.1",
|
"react-cookie": "^6.1.1",
|
||||||
"react-digit-input": "^2.1.0",
|
"react-digit-input": "^2.1.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
|
@ -51,18 +51,18 @@
|
||||||
"twilio-client": "^1.15.0"
|
"twilio-client": "^1.15.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.23.0",
|
"@babel/core": "^7.23.2",
|
||||||
"@types/node": "^20.8.0",
|
"@types/node": "^20.8.6",
|
||||||
"@types/react": "18.2.24",
|
"@types/react": "18.2.28",
|
||||||
"@types/uuid": "^9.0.4",
|
"@types/uuid": "^9.0.5",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.51.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-next": "^13.5.3",
|
"eslint-config-next": "^13.5.4",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-plugin-import": "^2.28.1",
|
"eslint-plugin-import": "^2.28.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"typescript": "5.2.2"
|
"typescript": "5.2.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@
|
||||||
"hapi-auth-bearer-token": "^8.0.0",
|
"hapi-auth-bearer-token": "^8.0.0",
|
||||||
"hapi-auth-jwt2": "^10.4.0",
|
"hapi-auth-jwt2": "^10.4.0",
|
||||||
"hapi-swagger": "^17.1.0",
|
"hapi-swagger": "^17.1.0",
|
||||||
"joi": "^17.10.2",
|
"joi": "^17.11.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"jwks-rsa": "^3.0.1",
|
"jwks-rsa": "^3.1.0",
|
||||||
"long": "^5.2.3",
|
"long": "^5.2.3",
|
||||||
"p-memoize": "^7.1.1",
|
"p-memoize": "^7.1.1",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
|
|
@ -40,8 +40,8 @@
|
||||||
"pg-promise": "^11.5.4",
|
"pg-promise": "^11.5.4",
|
||||||
"postgraphile": "4.12.3",
|
"postgraphile": "4.12.3",
|
||||||
"postgraphile-plugin-connection-filter": "^2.3.0",
|
"postgraphile-plugin-connection-filter": "^2.3.0",
|
||||||
"remeda": "^1.27.0",
|
"remeda": "^1.27.1",
|
||||||
"twilio": "^4.18.0",
|
"twilio": "^4.18.1",
|
||||||
"typeorm": "^0.3.17",
|
"typeorm": "^0.3.17",
|
||||||
"@whiskeysockets/baileys": "^6.5.0"
|
"@whiskeysockets/baileys": "^6.5.0"
|
||||||
},
|
},
|
||||||
|
|
@ -54,11 +54,11 @@
|
||||||
"jest-config-link": "*",
|
"jest-config-link": "*",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"pg-monitor": "^2.0.0",
|
"pg-monitor": "^2.0.0",
|
||||||
"pino-pretty": "^10.2.0",
|
"pino-pretty": "^10.2.3",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.0.4",
|
||||||
"tsconfig-link": "*",
|
"tsconfig-link": "*",
|
||||||
"typedoc": "^0.25.1",
|
"typedoc": "^0.25.2",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"nodemonConfig": {
|
"nodemonConfig": {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
"@digiresilience/metamigo-db": "*",
|
"@digiresilience/metamigo-db": "*",
|
||||||
"@digiresilience/metamigo-api": "*",
|
"@digiresilience/metamigo-api": "*",
|
||||||
"@digiresilience/metamigo-worker": "*",
|
"@digiresilience/metamigo-worker": "*",
|
||||||
"commander": "^11.0.0",
|
"commander": "^11.1.0",
|
||||||
"graphile-migrate": "^1.4.1",
|
"graphile-migrate": "^1.4.1",
|
||||||
"graphile-worker": "^0.13.0",
|
"graphile-worker": "^0.13.0",
|
||||||
"node-jose": "^2.2.0",
|
"node-jose": "^2.2.0",
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.5",
|
"@types/jest": "^29.5.5",
|
||||||
"pino-pretty": "^10.2.0",
|
"pino-pretty": "^10.2.3",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"tsconfig-link": "*",
|
"tsconfig-link": "*",
|
||||||
"eslint-config-link": "*",
|
"eslint-config-link": "*",
|
||||||
|
|
@ -40,4 +40,4 @@
|
||||||
"lint": "eslint src --ext .ts && prettier \"src/**/*.ts\" --list-different",
|
"lint": "eslint src --ext .ts && prettier \"src/**/*.ts\" --list-different",
|
||||||
"test": "echo no tests"
|
"test": "echo no tests"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,24 +14,24 @@
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
"node-fetch": "^3",
|
"node-fetch": "^3",
|
||||||
"pg-promise": "^11.5.4",
|
"pg-promise": "^11.5.4",
|
||||||
"remeda": "^1.27.0",
|
"remeda": "^1.27.1",
|
||||||
"twilio": "^4.18.0"
|
"twilio": "^4.18.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.23.0",
|
"@babel/core": "7.23.2",
|
||||||
"@babel/preset-env": "7.22.20",
|
"@babel/preset-env": "7.23.2",
|
||||||
"@babel/preset-typescript": "7.23.0",
|
"@babel/preset-typescript": "7.23.2",
|
||||||
"@types/fluent-ffmpeg": "^2.1.22",
|
"@types/fluent-ffmpeg": "^2.1.22",
|
||||||
"@types/jest": "^29.5.5",
|
"@types/jest": "^29.5.5",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.51.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-circus": "^29.7.0",
|
"jest-circus": "^29.7.0",
|
||||||
"jest-junit": "^16.0.0",
|
"jest-junit": "^16.0.0",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"pino-pretty": "^10.2.0",
|
"pino-pretty": "^10.2.3",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typedoc": "^0.25.1",
|
"typedoc": "^0.25.2",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"nodemonConfig": {
|
"nodemonConfig": {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ RUN if [ "$EMBEDDED" = "true" ] ; then sed -i '/proxy_set_header X-Forwarded-Use
|
||||||
USER root
|
USER root
|
||||||
RUN set -ex; \
|
RUN set -ex; \
|
||||||
apt-get update; \
|
apt-get update; \
|
||||||
apt-get install -y --no-install-recommends;
|
apt-get install -y --no-install-recommends gpg;
|
||||||
WORKDIR ${ZAMMAD_DIR}
|
WORKDIR ${ZAMMAD_DIR}
|
||||||
RUN bundle install --without test development mysql
|
RUN bundle install --without test development mysql
|
||||||
RUN sed -i '/^[[:space:]]*# create install ready file/ i\
|
RUN sed -i '/^[[:space:]]*# create install ready file/ i\
|
||||||
|
|
|
||||||
3274
package-lock.json
generated
3274
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "link-stack",
|
"name": "link-stack",
|
||||||
"version": "2.0.0b4",
|
"version": "2.0.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
"docker:label-studio:down": "docker compose -f docker-compose.label-studio.yml -f docker-compose.metamigo-postgresql.yml down",
|
"docker:label-studio:down": "docker compose -f docker-compose.label-studio.yml -f docker-compose.metamigo-postgresql.yml down",
|
||||||
"upgrade:setup": "npm i -g npm-check-updates",
|
"upgrade:setup": "npm i -g npm-check-updates",
|
||||||
"upgrade:check": "ncu && ncu -ws -x graphql -x postgraphile",
|
"upgrade:check": "ncu && ncu -ws -x graphql -x postgraphile",
|
||||||
"upgrade:all": "ncu -u && ncu -ws -u -x graphql -x postgraphile && npm i",
|
"upgrade:all": "ncu -u && ncu -ws -u -x graphql -x postgraphile -x graphile-worker && npm i",
|
||||||
"clean": "rm -f package-lock.json && rm -rf node_modules && rm -rf apps/*/node_modules && rm -rf packages/*/node_modules && rm -rf apps/*/.next && rm -rf packages/*/.turbo && rm -rf apps/*/.turbo && rm -rf docker/zammad/addons/*"
|
"clean": "rm -f package-lock.json && rm -rf node_modules && rm -rf apps/*/node_modules && rm -rf packages/*/node_modules && rm -rf apps/*/.next && rm -rf packages/*/.turbo && rm -rf apps/*/.turbo && rm -rf docker/zammad/addons/*"
|
||||||
},
|
},
|
||||||
"packageManager": "npm@9.6.7",
|
"packageManager": "npm@9.6.7",
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@
|
||||||
"lint": "eslint index.js"
|
"lint": "eslint index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "7.23.0",
|
"@babel/core": "7.23.2",
|
||||||
"@babel/preset-env": "7.22.20",
|
"@babel/preset-env": "7.23.2",
|
||||||
"@babel/preset-typescript": "7.23.0"
|
"@babel/preset-typescript": "7.23.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {},
|
"peerDependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.50.0"
|
"eslint": "^8.51.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.5.1",
|
"@rushstack/eslint-patch": "^1.5.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
"@typescript-eslint/eslint-plugin": "^6.7.5",
|
||||||
"@typescript-eslint/parser": "^6.7.3",
|
"@typescript-eslint/parser": "^6.7.5",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-config-xo-space": "^0.34.0",
|
"eslint-config-xo-space": "^0.34.0",
|
||||||
"eslint-plugin-cypress": "^2.15.1",
|
"eslint-plugin-cypress": "^2.15.1",
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.51.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hapi/hapi": "^21.3.2",
|
"@hapi/hapi": "^21.3.2",
|
||||||
"@hapi/hoek": "^11.0.2",
|
"@hapi/hoek": "^11.0.2",
|
||||||
"joi": "^17.10.2",
|
"joi": "^17.11.0",
|
||||||
"next-auth": "4.23.1"
|
"next-auth": "4.23.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p tsconfig.json",
|
"build": "tsc -p tsconfig.json",
|
||||||
|
|
|
||||||
|
|
@ -9,22 +9,22 @@
|
||||||
"@emotion/react": "^11.11.1",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/server": "^11.11.0",
|
"@emotion/server": "^11.11.0",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@fontsource/playfair-display": "^5.0.13",
|
"@fontsource/playfair-display": "^5.0.15",
|
||||||
"@fontsource/poppins": "^5.0.8",
|
"@fontsource/poppins": "^5.0.8",
|
||||||
"@fontsource/roboto": "^5.0.8",
|
"@fontsource/roboto": "^5.0.8",
|
||||||
"@mui/icons-material": "^5",
|
"@mui/icons-material": "^5",
|
||||||
"@mui/lab": "^5.0.0-alpha.146",
|
"@mui/lab": "^5.0.0-alpha.148",
|
||||||
"@mui/material": "^5",
|
"@mui/material": "^5",
|
||||||
"@mui/x-data-grid-pro": "^6.16.0",
|
"@mui/x-data-grid-pro": "^6.16.2",
|
||||||
"@mui/x-date-pickers-pro": "^6.16.0",
|
"@mui/x-date-pickers-pro": "^6.16.2",
|
||||||
"@opensearch-project/opensearch": "^2.3.1",
|
"@opensearch-project/opensearch": "^2.4.0",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"material-ui-popup-state": "^5.0.9",
|
"material-ui-popup-state": "^5.0.9",
|
||||||
"next": "13.5.3",
|
"next": "13.5.4",
|
||||||
"next-auth": "^4.23.1",
|
"next-auth": "^4.23.2",
|
||||||
"next-http-proxy-middleware": "^1.2.5",
|
"next-http-proxy-middleware": "^1.2.6",
|
||||||
"nodemailer": "^6.9.5",
|
"nodemailer": "^6.9.6",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-cookie": "^6.1.1",
|
"react-cookie": "^6.1.1",
|
||||||
"react-cookie-consent": "^8.0.1",
|
"react-cookie-consent": "^8.0.1",
|
||||||
|
|
@ -38,18 +38,18 @@
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.23.0",
|
"@babel/core": "^7.23.2",
|
||||||
"@types/node": "^20.8.0",
|
"@types/node": "^20.8.6",
|
||||||
"@types/react": "18.2.24",
|
"@types/react": "18.2.28",
|
||||||
"@types/uuid": "^9.0.4",
|
"@types/uuid": "^9.0.5",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.51.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-next": "^13.5.3",
|
"eslint-config-next": "^13.5.4",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-plugin-import": "^2.28.1",
|
"eslint-plugin-import": "^2.28.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"typescript": "5.2.2"
|
"typescript": "5.2.2"
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -20,11 +20,11 @@
|
||||||
"@types/figlet": "^1.5.6",
|
"@types/figlet": "^1.5.6",
|
||||||
"@types/lodash": "^4.14.199",
|
"@types/lodash": "^4.14.199",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/uuid": "^9.0.4",
|
"@types/uuid": "^9.0.5",
|
||||||
"camelcase-keys": "^9.1.0",
|
"camelcase-keys": "^9.1.0",
|
||||||
"pg-monitor": "^2.0.0",
|
"pg-monitor": "^2.0.0",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.0.4",
|
||||||
"typedoc": "^0.25.1",
|
"typedoc": "^0.25.2",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -36,29 +36,29 @@
|
||||||
"@hapi/inert": "^7.1.0",
|
"@hapi/inert": "^7.1.0",
|
||||||
"@hapi/vision": "^7.0.3",
|
"@hapi/vision": "^7.0.3",
|
||||||
"@hapipal/schmervice": "^3.0.0",
|
"@hapipal/schmervice": "^3.0.0",
|
||||||
"@promster/hapi": "^10.0.1",
|
"@promster/hapi": "^12.0.0",
|
||||||
"@promster/server": "^9.0.0",
|
"@promster/server": "^12.0.0",
|
||||||
"@promster/types": "^5.0.0",
|
"@promster/types": "^12.0.0",
|
||||||
"@types/convict": "^6.1.4",
|
"@types/convict": "^6.1.4",
|
||||||
"@types/hapi__glue": "^6.1.7",
|
"@types/hapi__glue": "^6.1.7",
|
||||||
"@types/hapi__hapi": "^20.0.13",
|
"@types/hapi__hapi": "^20.0.13",
|
||||||
"@types/hapi__inert": "^5.2.7",
|
"@types/hapi__inert": "^5.2.8",
|
||||||
"@types/hapi__vision": "^5.5.5",
|
"@types/hapi__vision": "^5.5.5",
|
||||||
"@types/hapipal__schmervice": "^2.0.4",
|
"@types/hapipal__schmervice": "^2.0.5",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"commander": "^11.0.0",
|
"commander": "^11.1.0",
|
||||||
"convict": "^6.2.4",
|
"convict": "^6.2.4",
|
||||||
"decamelcase-keys": "^1.1.1",
|
"decamelcase-keys": "^1.1.1",
|
||||||
"figlet": "^1.6.0",
|
"figlet": "^1.6.0",
|
||||||
"hapi-pino": "^12.1.0",
|
"hapi-pino": "^12.1.0",
|
||||||
"http-terminator": "^3.2.0",
|
"http-terminator": "^3.2.0",
|
||||||
"joi": "^17.10.2",
|
"joi": "^17.11.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"next-auth": "^4.23.1",
|
"next-auth": "^4.23.2",
|
||||||
"pg-promise": "^11.5.4",
|
"pg-promise": "^11.5.4",
|
||||||
"pino": "^8.15.3",
|
"pino": "^8.16.0",
|
||||||
"pino-pretty": "^10.2.0",
|
"pino-pretty": "^10.2.3",
|
||||||
"prom-client": "^14.x.x",
|
"prom-client": "^15.x.x",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,15 @@
|
||||||
"@digiresilience/montar": "*"
|
"@digiresilience/montar": "*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.23.0",
|
"@babel/core": "7.23.2",
|
||||||
"@babel/preset-env": "7.22.20",
|
"@babel/preset-env": "7.23.2",
|
||||||
"@babel/preset-typescript": "7.23.0",
|
"@babel/preset-typescript": "7.23.2",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.51.0",
|
||||||
"pino-pretty": "^10.2.0",
|
"pino-pretty": "^10.2.3",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.0.4",
|
||||||
"typedoc": "^0.25.1",
|
"typedoc": "^0.25.2",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,18 @@
|
||||||
"pg-promise": "^11.5.4"
|
"pg-promise": "^11.5.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.23.0",
|
"@babel/core": "7.23.2",
|
||||||
"@babel/preset-env": "7.22.20",
|
"@babel/preset-env": "7.23.2",
|
||||||
"@babel/preset-typescript": "7.23.0",
|
"@babel/preset-typescript": "7.23.2",
|
||||||
"@types/jest": "^29.5.5",
|
"@types/jest": "^29.5.5",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.51.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-junit": "^16.0.0",
|
"jest-junit": "^16.0.0",
|
||||||
"pino-pretty": "^10.2.0",
|
"pino-pretty": "^10.2.3",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.0.4",
|
||||||
"typedoc": "^0.25.1",
|
"typedoc": "^0.25.2",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
"jest-config-link": "*",
|
"jest-config-link": "*",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.0.4",
|
||||||
"tsconfig-link": "*",
|
"tsconfig-link": "*",
|
||||||
"typedoc": "^0.25.1"
|
"typedoc": "^0.25.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"backoff": "^2.5.0",
|
"backoff": "^2.5.0",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue