Add more graphql support to Link
This commit is contained in:
parent
d7f8c87ccb
commit
60f6061d49
14 changed files with 251 additions and 159 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import { Grid, Button, Dialog, DialogActions, DialogContent, TextField } from "@mui/material";
|
import { Grid, Button, Dialog, DialogActions, DialogContent, TextField } from "@mui/material";
|
||||||
// import { request, gql } from "graphql-request";
|
import { useSWRConfig } from "swr";
|
||||||
|
import { updateTicketMutation } from "graphql/updateTicketMutation";
|
||||||
|
|
||||||
interface ArticleCreateDialogProps {
|
interface ArticleCreateDialogProps {
|
||||||
ticketID: string;
|
ticketID: string;
|
||||||
|
|
@ -10,54 +11,25 @@ interface ArticleCreateDialogProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ArticleCreateDialog: FC<ArticleCreateDialogProps> = ({ ticketID, open, closeDialog, kind }) => {
|
export const ArticleCreateDialog: FC<ArticleCreateDialogProps> = ({ ticketID, open, closeDialog, kind }) => {
|
||||||
console.log({ ticketID })
|
|
||||||
const [body, setBody] = useState("");
|
const [body, setBody] = useState("");
|
||||||
const backgroundColor = kind === "reply" ? "#1982FC" : "#FFB620";
|
const backgroundColor = kind === "reply" ? "#1982FC" : "#FFB620";
|
||||||
const color = kind === "reply" ? "white" : "black";
|
const color = kind === "reply" ? "white" : "black";
|
||||||
const origin = typeof window !== 'undefined' && window.location.origin
|
const { fetcher } = useSWRConfig();
|
||||||
? window.location.origin
|
|
||||||
: '';
|
|
||||||
const createArticle = async () => {
|
const createArticle = async () => {
|
||||||
// const token = document?.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
await fetcher(
|
||||||
// console.log({ token })
|
{
|
||||||
const res = await fetch(`${origin}/api/v1/ticket_articles`, {
|
document: updateTicketMutation,
|
||||||
method: "POST",
|
variables: {
|
||||||
headers: {
|
ticketId: `gid://zammad/Ticket/${ticketID}`,
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-CSRF-Token": "BG3wYuvTgi4ALfaZ-Mdq6i08wRFRJHeCPJbfGjfVarLRhwaxRC8J-AZvGiSNOiWrN38WT3C9WGLhcmaMb0AqBQ",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
ticket_id: ticketID,
|
|
||||||
body,
|
|
||||||
internal: kind === "note",
|
|
||||||
sender: "Agent",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
console.log({ res })
|
|
||||||
/*
|
|
||||||
const document = gql`
|
|
||||||
|
|
||||||
mutation {
|
|
||||||
ticketUpdate(
|
|
||||||
input: {
|
input: {
|
||||||
ticketId: "1"
|
article: {
|
||||||
body: "This is a test article"
|
body,
|
||||||
internal: false
|
type: kind === "note" ? "note" : "phone",
|
||||||
}
|
internal: kind === "note"
|
||||||
) {
|
}
|
||||||
article {
|
|
||||||
id
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
`;
|
|
||||||
const data = await request({
|
|
||||||
url: `${origin}/graphql`,
|
|
||||||
document,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log({ data })
|
|
||||||
*/
|
|
||||||
closeDialog();
|
closeDialog();
|
||||||
setBody("");
|
setBody("");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ export const TicketDetail: FC<TicketDetailProps> = ({ ticket }) => {
|
||||||
<MessageList style={{ marginBottom: 80 }}>
|
<MessageList style={{ marginBottom: 80 }}>
|
||||||
{ticket.articles.edges.map(({ node: article }: any) => (
|
{ticket.articles.edges.map(({ node: article }: any) => (
|
||||||
<Message
|
<Message
|
||||||
|
key={article.id}
|
||||||
className={
|
className={
|
||||||
article.internal
|
article.internal
|
||||||
? "internal-note"
|
? "internal-note"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { FC, useEffect, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
import { Grid, Box, Typography, TextField, Stack, Chip, Select, MenuItem } from "@mui/material";
|
import { Grid, Box, Typography, TextField, Stack, Chip, Select, MenuItem } from "@mui/material";
|
||||||
|
import useSWR, { useSWRConfig } from "swr";
|
||||||
|
import { updateTicketMutation } from "graphql/updateTicketMutation";
|
||||||
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
|
import "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";
|
||||||
|
|
||||||
interface TicketEditProps {
|
interface TicketEditProps {
|
||||||
|
|
@ -7,34 +9,58 @@ interface TicketEditProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TicketEdit: FC<TicketEditProps> = ({ ticket }) => {
|
export const TicketEdit: FC<TicketEditProps> = ({ ticket }) => {
|
||||||
const [selectedGroup, setSelectedGroup] = useState("group1");
|
const [selectedGroup, setSelectedGroup] = useState(1);
|
||||||
const [selectedOwner, setSelectedOwner] = useState("owner1");
|
const [selectedOwner, setSelectedOwner] = useState(1);
|
||||||
const [selectedPriority, setSelectedPriority] = useState("priority1");
|
const [selectedPriority, setSelectedPriority] = useState(1);
|
||||||
const [selectedState, setSelectedState] = useState("state2");
|
const [selectedState, setSelectedState] = useState(1);
|
||||||
|
const [selectedTags, setSelectedTags] = useState(["tag1", "tag2"]);
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
console.info("You clicked the delete icon.");
|
console.info("You clicked the delete icon.");
|
||||||
};
|
};
|
||||||
|
const restFetcher = (url: string) => fetch(url).then((r) => r.json());
|
||||||
|
const { data: groups } = useSWR("/api/v1/groups", restFetcher);
|
||||||
|
console.log({ groups });
|
||||||
|
const { data: users } = useSWR("/api/v1/users", restFetcher);
|
||||||
|
console.log({ users });
|
||||||
|
const { data: states } = useSWR("/api/v1/ticket_states", restFetcher);
|
||||||
|
console.log({ states });
|
||||||
|
const { data: priorities } = useSWR("/api/v1/ticket_priorities", restFetcher);
|
||||||
|
console.log({ priorities });
|
||||||
|
|
||||||
|
const { fetcher } = useSWRConfig();
|
||||||
|
const updateTicket = async () => {
|
||||||
|
await fetcher(
|
||||||
|
{
|
||||||
|
document: updateTicketMutation,
|
||||||
|
variables: {
|
||||||
|
ticketId: ticket.id,
|
||||||
|
input: {
|
||||||
|
ownerId: `gid://zammad/User/${selectedOwner}`,
|
||||||
|
tags: ["tag1", "tag2"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ height: "100vh", background: "#ddd", p: 2 }}>
|
<Box sx={{ height: "100vh", background: "#ddd", p: 2 }}>
|
||||||
<Grid container direction="column" spacing={3}>
|
<Grid container direction="column" spacing={3}>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Box sx={{ m: 1 }}>Group</Box>
|
<Box sx={{ m: 1 }}>Group</Box>
|
||||||
<Select defaultValue={selectedGroup} value={selectedGroup} onChange={(e: any) => setSelectedGroup(e.target.value)} size="small" sx={{
|
<Select defaultValue={selectedGroup} value={selectedGroup} onChange={(e: any) => { setSelectedGroup(e.target.value); updateTicket() }} size="small" sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: "white"
|
backgroundColor: "white"
|
||||||
}} >
|
}} >
|
||||||
<MenuItem key="group1" value="group1">Default Group</MenuItem>
|
{groups?.map((group: any) => <MenuItem key={group.id} value={group.id}>{group.name}</MenuItem>)}
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Box sx={{ m: 1, mt: 0 }}>Owner</Box>
|
<Box sx={{ m: 1, mt: 0 }}>Owner</Box>
|
||||||
<Select value={selectedOwner} onChange={(e: any) => setSelectedOwner(e.target.value)} size="small" sx={{
|
<Select value={selectedOwner} onChange={(e: any) => { setSelectedOwner(e.target.value); updateTicket() }} size="small" sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
}} >
|
}} >
|
||||||
<MenuItem value="owner1">Darren Clarke</MenuItem>
|
{users?.map((user: any) => <MenuItem key={user.id} value={user.id}>{user.firstname} {user.lastname}</MenuItem>)}
|
||||||
<MenuItem value="owner2">Darren Gpcmdln</MenuItem>
|
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
|
|
@ -43,11 +69,7 @@ export const TicketEdit: FC<TicketEditProps> = ({ ticket }) => {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: "white"
|
backgroundColor: "white"
|
||||||
}} >
|
}} >
|
||||||
<MenuItem value="state1">closed</MenuItem>
|
{states?.map((state: any) => <MenuItem key={state.id} value={state.id}>{state.name}</MenuItem>)}
|
||||||
<MenuItem value="state2">new</MenuItem>
|
|
||||||
<MenuItem value="state3">open</MenuItem>
|
|
||||||
<MenuItem value="state4">pending close</MenuItem>
|
|
||||||
<MenuItem value="state4">pending reminder</MenuItem>
|
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
|
|
@ -56,17 +78,14 @@ export const TicketEdit: FC<TicketEditProps> = ({ ticket }) => {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: "white"
|
backgroundColor: "white"
|
||||||
}} >
|
}} >
|
||||||
<MenuItem value="priority1">1 low</MenuItem>
|
{priorities?.map((priority: any) => <MenuItem key={priority.id} value={priority.id}>{priority.name}</MenuItem>)}
|
||||||
<MenuItem value="priority2">2 normal</MenuItem>
|
|
||||||
<MenuItem value="priority3">3 high</MenuItem>
|
|
||||||
</Select>
|
</Select>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<Box sx={{ mb: 1, }}>Tags</Box>
|
<Box sx={{ mb: 1, }}>Tags</Box>
|
||||||
<Stack direction="row" spacing={1} sx={{ backgroundColor: "white", p: 1, borderRadius: "6px", border: "1px solid #bbb", minHeight: 120 }} flexWrap="wrap">
|
<Stack direction="row" spacing={1} sx={{ backgroundColor: "white", p: 1, borderRadius: "6px", border: "1px solid #bbb", minHeight: 120 }} flexWrap="wrap">
|
||||||
<Chip label="First" onDelete={handleDelete} />
|
{selectedTags.map((tag: string) => <Chip key={tag} label={tag} onDelete={handleDelete} />)}
|
||||||
<Chip label="Another" onDelete={handleDelete} />
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
import Iframe from "react-iframe";
|
import Iframe from "react-iframe";
|
||||||
|
|
||||||
type ZammadWrapperProps = {
|
type ZammadWrapperProps = {
|
||||||
|
|
@ -10,11 +11,12 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
|
||||||
path,
|
path,
|
||||||
hideSidebar = true,
|
hideSidebar = true,
|
||||||
}) => {
|
}) => {
|
||||||
|
const router = useRouter();
|
||||||
const origin =
|
const origin =
|
||||||
typeof window !== "undefined" && window.location.origin
|
typeof window !== "undefined" && window.location.origin
|
||||||
? window.location.origin
|
? window.location.origin
|
||||||
: "";
|
: "";
|
||||||
const [display, setDisplay] = useState("hidden");
|
const [display, setDisplay] = useState("none");
|
||||||
const url = `${origin}/zammad${path}`;
|
const url = `${origin}/zammad${path}`;
|
||||||
console.log({ origin, path, url });
|
console.log({ origin, path, url });
|
||||||
|
|
||||||
|
|
@ -49,7 +51,28 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
|
||||||
"display: none";
|
"display: none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if (linkElement.contentDocument.querySelector(".overview-header")) {
|
||||||
|
// @ts-ignore
|
||||||
|
linkElement.contentDocument.querySelector(".overview-header").style =
|
||||||
|
"display: none";
|
||||||
|
}
|
||||||
|
|
||||||
setDisplay("inherit");
|
setDisplay("inherit");
|
||||||
|
|
||||||
|
if (linkElement.contentWindow) {
|
||||||
|
linkElement.contentWindow.addEventListener('hashchange', () => {
|
||||||
|
const hash = linkElement.contentWindow?.location?.hash ?? ""
|
||||||
|
if (hash.startsWith("#ticket/zoom/")) {
|
||||||
|
setDisplay("none");
|
||||||
|
const ticketID = hash.split("/").pop();
|
||||||
|
router.push(`/tickets/${ticketID}`);
|
||||||
|
setTimeout(() => {
|
||||||
|
setDisplay("inherit");
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
40
apps/link/graphql/getTicketQuery.ts
Normal file
40
apps/link/graphql/getTicketQuery.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { gql } from 'graphql-request';
|
||||||
|
|
||||||
|
export const getTicketQuery = gql`
|
||||||
|
query getTicket($ticketId: ID!) {
|
||||||
|
ticket(ticket: { ticketId: $ticketId }) {
|
||||||
|
id
|
||||||
|
internalId
|
||||||
|
title
|
||||||
|
note
|
||||||
|
number
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
closeAt
|
||||||
|
tags
|
||||||
|
state {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
owner {
|
||||||
|
id
|
||||||
|
email
|
||||||
|
}
|
||||||
|
articles {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
body
|
||||||
|
internal
|
||||||
|
type {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
sender {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
10
apps/link/graphql/updateTicketMutation.ts
Normal file
10
apps/link/graphql/updateTicketMutation.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { gql } from "graphql-request";
|
||||||
|
|
||||||
|
export const updateTicketMutation = gql`
|
||||||
|
mutation UpdateTicket($ticketId: ID!, $input: TicketUpdateInput!) {
|
||||||
|
ticketUpdate(ticketId: $ticketId, input: $input) {
|
||||||
|
ticket {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
rewrites: async () => ({
|
rewrites: async () => ({
|
||||||
beforeFiles: [
|
|
||||||
{
|
|
||||||
source: "/#ticket/zoom/:path*",
|
|
||||||
destination: "/ticket/:path*",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
fallback: [
|
fallback: [
|
||||||
{
|
{
|
||||||
source: "/:path*",
|
source: "/:path*",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
/* eslint-disable react/jsx-props-no-spreading */
|
/* eslint-disable react/jsx-props-no-spreading */
|
||||||
|
import { useState } from "react";
|
||||||
import { AppProps } from "next/app";
|
import { AppProps } from "next/app";
|
||||||
import { SessionProvider } from "next-auth/react";
|
import { SessionProvider } from "next-auth/react";
|
||||||
import { CssBaseline } from "@mui/material";
|
import { CssBaseline } from "@mui/material";
|
||||||
|
|
@ -13,6 +14,8 @@ import "@fontsource/roboto/700.css";
|
||||||
import "@fontsource/playfair-display/900.css";
|
import "@fontsource/playfair-display/900.css";
|
||||||
import "styles/global.css";
|
import "styles/global.css";
|
||||||
import { LicenseInfo } from "@mui/x-data-grid-pro";
|
import { LicenseInfo } from "@mui/x-data-grid-pro";
|
||||||
|
import { SWRConfig } from "swr";
|
||||||
|
import { GraphQLClient } from "graphql-request";
|
||||||
|
|
||||||
LicenseInfo.setLicenseKey(
|
LicenseInfo.setLicenseKey(
|
||||||
"fd009c623acc055adb16370731be92e4T1JERVI6NDA3NTQsRVhQSVJZPTE2ODAyNTAwMTUwMDAsS0VZVkVSU0lPTj0x"
|
"fd009c623acc055adb16370731be92e4T1JERVI6NDA3NTQsRVhQSVJZPTE2ODAyNTAwMTUwMDAsS0VZVkVSU0lPTj0x"
|
||||||
|
|
@ -27,14 +30,40 @@ interface LinkWebProps extends AppProps {
|
||||||
|
|
||||||
const LinkWeb = (props: LinkWebProps) => {
|
const LinkWeb = (props: LinkWebProps) => {
|
||||||
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
|
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
|
||||||
|
const [csrfToken, setCsrfToken] = useState("");
|
||||||
|
const origin = typeof window !== 'undefined' && window.location.origin
|
||||||
|
? window.location.origin : null;
|
||||||
|
const client = new GraphQLClient(`${origin}/graphql`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const graphQLFetcher = async ({ document, variables }: any) => {
|
||||||
|
const requestHeaders = {
|
||||||
|
"X-CSRF-Token": csrfToken,
|
||||||
|
};
|
||||||
|
const { data, headers } = await client.rawRequest(
|
||||||
|
document,
|
||||||
|
variables,
|
||||||
|
requestHeaders
|
||||||
|
);
|
||||||
|
|
||||||
|
const token = headers.get('CSRF-Token');
|
||||||
|
setCsrfToken(token);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SessionProvider session={(pageProps as any).session}>
|
<SessionProvider session={(pageProps as any).session}>
|
||||||
<CacheProvider value={emotionCache}>
|
<CacheProvider value={emotionCache}>
|
||||||
<CssBaseline />
|
<SWRConfig value={{ fetcher: graphQLFetcher }}>
|
||||||
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
<CssBaseline />
|
||||||
<Component {...pageProps} />
|
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
||||||
</LocalizationProvider>
|
<Component {...pageProps} />
|
||||||
|
</LocalizationProvider>
|
||||||
|
</SWRConfig>
|
||||||
</CacheProvider>
|
</CacheProvider>
|
||||||
</SessionProvider>
|
</SessionProvider>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -13,19 +13,11 @@ const withAuthInfo =
|
||||||
return res.redirect("/login");
|
return res.redirect("/login");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (req.headers) {
|
||||||
const res2 = await fetch(`http://127.0.0.1:8001`);
|
req.headers['X-Forwarded-User'] = session.email.toLowerCase();
|
||||||
console.log({ res2 })
|
req.headers['host'] = 'zammad.example.com';
|
||||||
} catch (e) {
|
|
||||||
console.log({ e })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log({ zammad: process.env.ZAMMAD_URL })
|
|
||||||
req.headers['X-Forwarded-User'] = session.email.toLowerCase();
|
|
||||||
req.headers['host'] = 'zammad.example.com';
|
|
||||||
|
|
||||||
console.log({ headers: req.headers })
|
|
||||||
|
|
||||||
return handler(req, res);
|
return handler(req, res);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -33,7 +25,7 @@ const proxy = createProxyMiddleware({
|
||||||
target: process.env.ZAMMAD_URL,
|
target: process.env.ZAMMAD_URL,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
xfwd: true,
|
xfwd: true,
|
||||||
ws: true,
|
ws: false,
|
||||||
pathRewrite: { "^/zammad": "" },
|
pathRewrite: { "^/zammad": "" },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,84 +1,24 @@
|
||||||
import { GetServerSideProps, GetServerSidePropsContext } from "next";
|
import { GetServerSideProps, GetServerSidePropsContext } from "next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { request, gql } from "graphql-request";
|
|
||||||
import { NextPage } from "next";
|
import { NextPage } from "next";
|
||||||
import { Grid } from "@mui/material";
|
import { Grid } from "@mui/material";
|
||||||
import { Layout } from "components/Layout";
|
import { Layout } from "components/Layout";
|
||||||
import { TicketDetail } from "components/TicketDetail";
|
import { TicketDetail } from "components/TicketDetail";
|
||||||
import { TicketEdit } from "components/TicketEdit";
|
import { TicketEdit } from "components/TicketEdit";
|
||||||
|
import { getTicketQuery } from "graphql/getTicketQuery";
|
||||||
|
|
||||||
type TicketProps = {
|
type TicketProps = {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Ticket: NextPage<TicketProps> = ({ id }) => {
|
const Ticket: NextPage<TicketProps> = ({ id }) => {
|
||||||
const origin =
|
|
||||||
typeof window !== "undefined" && window.location.origin
|
|
||||||
? window.location.origin
|
|
||||||
: "";
|
|
||||||
const graphQLFetcher = async ({ document, variables }: any) => {
|
|
||||||
const data = await request({
|
|
||||||
url: `${origin}/graphql`,
|
|
||||||
document,
|
|
||||||
variables,
|
|
||||||
});
|
|
||||||
console.log({ data });
|
|
||||||
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data: ticketData, error: ticketError }: any = useSWR(
|
const { data: ticketData, error: ticketError }: any = useSWR(
|
||||||
{
|
{
|
||||||
document: gql`
|
document: getTicketQuery,
|
||||||
query getTicket($ticketId: Int!) {
|
variables: { ticketId: `gid://zammad/Ticket/${id}` },
|
||||||
ticket(ticket: { ticketInternalId: $ticketId }) {
|
|
||||||
id
|
|
||||||
internalId
|
|
||||||
title
|
|
||||||
note
|
|
||||||
number
|
|
||||||
createdAt
|
|
||||||
updatedAt
|
|
||||||
closeAt
|
|
||||||
articles {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
id
|
|
||||||
body
|
|
||||||
internal
|
|
||||||
sender {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: { ticketId: parseInt(id, 10) },
|
|
||||||
},
|
},
|
||||||
graphQLFetcher,
|
{ refreshInterval: 100000 }
|
||||||
{ refreshInterval: 1000 }
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data: graphqlData2, error: graphqlError2 } = useSWR(
|
|
||||||
{
|
|
||||||
document: gql`
|
|
||||||
{
|
|
||||||
__schema {
|
|
||||||
queryType {
|
|
||||||
name
|
|
||||||
fields {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: {},
|
|
||||||
},
|
|
||||||
graphQLFetcher
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const shouldRender = !ticketError && ticketData;
|
const shouldRender = !ticketError && ticketData;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const Assigned: FC = () => (
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ZammadWrapper path="/#ticket/view/my_tickets" />
|
<ZammadWrapper path="/#ticket/view/my_assigned" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,15 @@ services:
|
||||||
container_name: zammad-elasticsearch
|
container_name: zammad-elasticsearch
|
||||||
environment:
|
environment:
|
||||||
- discovery.type=single-node
|
- discovery.type=single-node
|
||||||
|
- ES_JAVA_OPTS=-Xms750m -Xmx750m
|
||||||
|
- xpack.security.enabled=false
|
||||||
build: ./docker/elasticsearch
|
build: ./docker/elasticsearch
|
||||||
restart: ${RESTART}
|
restart: ${RESTART}
|
||||||
volumes:
|
volumes:
|
||||||
- elasticsearch-data:/usr/share/elasticsearch/data
|
- elasticsearch-data:/usr/share/elasticsearch/data
|
||||||
|
|
||||||
zammad-init:
|
zammad-init:
|
||||||
|
platform: linux/x86_64
|
||||||
container_name: zammad-init
|
container_name: zammad-init
|
||||||
command: [ "zammad-init" ]
|
command: [ "zammad-init" ]
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
@ -68,6 +71,7 @@ services:
|
||||||
restart: ${RESTART}
|
restart: ${RESTART}
|
||||||
|
|
||||||
zammad-nginx:
|
zammad-nginx:
|
||||||
|
platform: linux/x86_64
|
||||||
container_name: zammad-nginx
|
container_name: zammad-nginx
|
||||||
command: [ "zammad-nginx" ]
|
command: [ "zammad-nginx" ]
|
||||||
expose:
|
expose:
|
||||||
|
|
@ -97,6 +101,7 @@ services:
|
||||||
- postgresql-data:/var/lib/postgresql/data
|
- postgresql-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
zammad-railsserver:
|
zammad-railsserver:
|
||||||
|
platform: linux/x86_64
|
||||||
container_name: zammad-railsserver
|
container_name: zammad-railsserver
|
||||||
command: [ "zammad-railsserver" ]
|
command: [ "zammad-railsserver" ]
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
@ -115,6 +120,7 @@ services:
|
||||||
restart: ${RESTART}
|
restart: ${RESTART}
|
||||||
|
|
||||||
zammad-scheduler:
|
zammad-scheduler:
|
||||||
|
platform: linux/x86_64
|
||||||
container_name: zammad-scheduler
|
container_name: zammad-scheduler
|
||||||
command: [ "zammad-scheduler" ]
|
command: [ "zammad-scheduler" ]
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
@ -128,6 +134,7 @@ services:
|
||||||
- zammad-data:/opt/zammad
|
- zammad-data:/opt/zammad
|
||||||
|
|
||||||
zammad-websocket:
|
zammad-websocket:
|
||||||
|
platform: linux/x86_64
|
||||||
container_name: zammad-websocket
|
container_name: zammad-websocket
|
||||||
command: [ "zammad-websocket" ]
|
command: [ "zammad-websocket" ]
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
@ -173,7 +180,6 @@ services:
|
||||||
# environment: *common-metamigo-variables
|
# environment: *common-metamigo-variables
|
||||||
|
|
||||||
metamigo-postgresql:
|
metamigo-postgresql:
|
||||||
container_name: metamigo-postgresql
|
|
||||||
build: ./docker/postgresql
|
build: ./docker/postgresql
|
||||||
restart: ${RESTART}
|
restart: ${RESTART}
|
||||||
volumes:
|
volumes:
|
||||||
|
|
@ -197,14 +203,14 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- ../signald:/signald
|
- ../signald:/signald
|
||||||
|
|
||||||
nginx-proxy:
|
# nginx-proxy:
|
||||||
container_name: nginx-proxy
|
# container_name: nginx-proxy
|
||||||
build: ./docker/nginx-proxy
|
# build: ./docker/nginx-proxy
|
||||||
restart: ${RESTART}
|
# restart: ${RESTART}
|
||||||
ports:
|
# ports:
|
||||||
- "80:80"
|
# - "80:80"
|
||||||
volumes:
|
# volumes:
|
||||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
# - /var/run/docker.sock:/tmp/docker.sock:ro
|
||||||
|
|
||||||
link:
|
link:
|
||||||
container_name: link
|
container_name: link
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
FROM bitnami/elasticsearch:8.5.1
|
FROM docker.elastic.co/elasticsearch/elasticsearch:8.6.2
|
||||||
|
|
|
||||||
66
package-lock.json
generated
66
package-lock.json
generated
|
|
@ -11878,6 +11878,18 @@
|
||||||
"integrity": "sha512-vo76VJ44MkUBZL/BzpGXaKzMfroF4ZR6+haRuw9p+eSWfoNaH2AxVc8xmiEPC08jhzJSeM6w7/iMUGet8b4oBQ==",
|
"integrity": "sha512-vo76VJ44MkUBZL/BzpGXaKzMfroF4ZR6+haRuw9p+eSWfoNaH2AxVc8xmiEPC08jhzJSeM6w7/iMUGet8b4oBQ==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hapi/node_modules/b64": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/b64/-/b64-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-+GUspBxlH3CJaxMUGUE1EBoWM6RKgWiYwUDal0qdf8m3ArnXNN1KzKVo5HOnE/FSq4HHyWf3TlHLsZI8PKQgrQ==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
|
"node_modules/hapi/node_modules/big-time": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/big-time/-/big-time-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-qtwYYoocwpiAxTXC5sIpB6nH5j6ckt+n/jhD7J5OEiFHnUZEFn0Xk8STUaE5s10LdazN/87bTDMe+fSihaW7Kg==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
"node_modules/hapi/node_modules/boom": {
|
"node_modules/hapi/node_modules/boom": {
|
||||||
"version": "7.2.2",
|
"version": "7.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/boom/-/boom-7.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/boom/-/boom-7.2.2.tgz",
|
||||||
|
|
@ -11890,6 +11902,12 @@
|
||||||
"integrity": "sha512-1LPcXg3fkGVhjdA/P3DcR5cDktKEYtDpruJv9Nhmy36RoYaoxZfC82Zr2JmS3vysDJKqMtP0qJw3/P6iisTASg==",
|
"integrity": "sha512-1LPcXg3fkGVhjdA/P3DcR5cDktKEYtDpruJv9Nhmy36RoYaoxZfC82Zr2JmS3vysDJKqMtP0qJw3/P6iisTASg==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hapi/node_modules/bourne": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/bourne/-/bourne-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Ou0l3W8+n1FuTOoIfIrCk9oF9WVWc+9fKoAl67XQr9Ws0z7LgILRZ7qtc9xdT4BveSKtnYXfKPgn8pFAqeQRew==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
"node_modules/hapi/node_modules/call": {
|
"node_modules/hapi/node_modules/call": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/call/-/call-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/call/-/call-5.0.3.tgz",
|
||||||
|
|
@ -11908,6 +11926,18 @@
|
||||||
"integrity": "sha512-1tDnll066au0HXBSDHS/YQ34MQ2omBsmnA9g/jseyq/M3m7UPrajVtPDZK/rXgikSC1dfjo9Pa+kQ1qcyG2d3g==",
|
"integrity": "sha512-1tDnll066au0HXBSDHS/YQ34MQ2omBsmnA9g/jseyq/M3m7UPrajVtPDZK/rXgikSC1dfjo9Pa+kQ1qcyG2d3g==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hapi/node_modules/content": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/content/-/content-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-lR9ND3dXiMdmsE84K6l02rMdgiBVmtYWu1Vr/gfSGHcIcznBj2QxmSdUgDuNFOA+G9yrb1IIWkZ7aKtB6hDGyA==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
|
"node_modules/hapi/node_modules/cryptiles": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-gT9nyTMSUC1JnziQpPbxKGBbUg8VL7Zn2NB4E1cJYvuXdElHrwxrV9bmltZGDzet45zSDGyYceueke1TjynGzw==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
"node_modules/hapi/node_modules/heavy": {
|
"node_modules/hapi/node_modules/heavy": {
|
||||||
"version": "6.1.2",
|
"version": "6.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/heavy/-/heavy-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/heavy/-/heavy-6.1.2.tgz",
|
||||||
|
|
@ -11920,18 +11950,42 @@
|
||||||
"integrity": "sha512-3PvUwBerLNVJiIVQdpkWF9F/M0ekgb2NPJWOhsE28RXSQPsY42YSnaJ8d1kZjcAz58TZ/Fk9Tw64xJsENFlJNw==",
|
"integrity": "sha512-3PvUwBerLNVJiIVQdpkWF9F/M0ekgb2NPJWOhsE28RXSQPsY42YSnaJ8d1kZjcAz58TZ/Fk9Tw64xJsENFlJNw==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hapi/node_modules/iron": {
|
||||||
|
"version": "5.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/iron/-/iron-5.0.6.tgz",
|
||||||
|
"integrity": "sha512-zYUMOSkEXGBdwlV/AXF9zJC0aLuTJUKHkGeYS5I2g225M5i6SrxQyGJGhPgOR8BK1omL6N5i6TcwfsXbP8/Exw==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
"node_modules/hapi/node_modules/joi": {
|
"node_modules/hapi/node_modules/joi": {
|
||||||
"version": "14.0.4",
|
"version": "14.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/joi/-/joi-14.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/joi/-/joi-14.0.4.tgz",
|
||||||
"integrity": "sha512-KUXRcinDUMMbtlOk7YLGHQvG73dLyf8bmgE+6sBTkdJbZpeGVGAlPXEHLiQBV7KinD/VLD5OA0EUgoTTfbRAJQ==",
|
"integrity": "sha512-KUXRcinDUMMbtlOk7YLGHQvG73dLyf8bmgE+6sBTkdJbZpeGVGAlPXEHLiQBV7KinD/VLD5OA0EUgoTTfbRAJQ==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hapi/node_modules/mime-db": {
|
||||||
|
"version": "1.37.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
|
||||||
|
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
"node_modules/hapi/node_modules/mimos": {
|
"node_modules/hapi/node_modules/mimos": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/mimos/-/mimos-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mimos/-/mimos-4.0.2.tgz",
|
||||||
"integrity": "sha512-5XBsDqBqzSN88XPPH/TFpOalWOjHJM5Z2d3AMx/30iq+qXvYKd/8MPhqBwZDOLtoaIWInR3nLzMQcxfGK9djXA==",
|
"integrity": "sha512-5XBsDqBqzSN88XPPH/TFpOalWOjHJM5Z2d3AMx/30iq+qXvYKd/8MPhqBwZDOLtoaIWInR3nLzMQcxfGK9djXA==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hapi/node_modules/nigel": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/nigel/-/nigel-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-3SZCCS/duVDGxFpTROHEieC+itDo4UqL9JNUyQJv3rljudQbK6aqus5B4470OxhESPJLN93Qqxg16rH7DUjbfQ==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
|
"node_modules/hapi/node_modules/pez": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/pez/-/pez-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-HvL8uiFIlkXbx/qw4B8jKDCWzo7Pnnd65Uvanf9OOCtb20MRcb9gtTVBf9NCnhETif1/nzbDHIjAWC/sUp7LIQ==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
"node_modules/hapi/node_modules/podium": {
|
"node_modules/hapi/node_modules/podium": {
|
||||||
"version": "3.1.5",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/podium/-/podium-3.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/podium/-/podium-3.1.5.tgz",
|
||||||
|
|
@ -11974,6 +12028,18 @@
|
||||||
"integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==",
|
"integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hapi/node_modules/vise": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vise/-/vise-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-7BJNjsv2o83+E6AHAFSnjQF324UTgypsR/Sw/iFmLvr7RgJrEXF1xNBvb5LJfi+1FvWQXjJK4X41WMuHMeunPQ==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
|
"node_modules/hapi/node_modules/wreck": {
|
||||||
|
"version": "14.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/wreck/-/wreck-14.1.3.tgz",
|
||||||
|
"integrity": "sha512-hb/BUtjX3ObbwO3slCOLCenQ4EP8e+n8j6FmTne3VhEFp5XV1faSJojiyxVSvw34vgdeTG5baLTl4NmjwokLlw==",
|
||||||
|
"extraneous": true
|
||||||
|
},
|
||||||
"node_modules/has": {
|
"node_modules/has": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue