authscape-tickets 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +3 -0
- package/dist/Container.module.css +103 -0
- package/dist/Item.module.css +135 -0
- package/index.js +1092 -0
- package/package.json +26 -0
- package/readme.md +1 -0
- package/src/comments.js +149 -0
- package/src/ticketDetail.js +406 -0
- package/src/tickets.js +225 -0
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "authscape-tickets",
|
|
3
|
+
"version": "1.0.14",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"build": "npx babel src --out-file index.js"
|
|
9
|
+
},
|
|
10
|
+
"author": "zuechb",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"peerDependencies": {
|
|
13
|
+
"react-dom": "^18.2.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@babel/cli": "^7.21.5",
|
|
17
|
+
"@babel/core": "^7.22.1",
|
|
18
|
+
"@babel/preset-env": "^7.22.2",
|
|
19
|
+
"@babel/preset-react": "^7.0.0",
|
|
20
|
+
"react-dom": "^18.2.0"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"eslint-config-next": "^14.1.0",
|
|
24
|
+
"react": "^18.2.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Working on docs...
|
package/src/comments.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import React, { useEffect, useState, useRef } from 'react';
|
|
2
|
+
import { Box, Paper } from '@mui/material';
|
|
3
|
+
import InputBase from '@mui/material/InputBase';
|
|
4
|
+
import IconButton from '@mui/material/IconButton';
|
|
5
|
+
import QuestionAnswerOutlinedIcon from '@mui/icons-material/QuestionAnswerOutlined';
|
|
6
|
+
import Typography from '@mui/material/Typography';
|
|
7
|
+
import Grid from '@mui/material/Grid';
|
|
8
|
+
import List from '@mui/material/List';
|
|
9
|
+
import ListItem from '@mui/material/ListItem';
|
|
10
|
+
import Avatar from '@mui/material/Avatar';
|
|
11
|
+
import SendRoundedIcon from '@mui/icons-material/SendRounded';
|
|
12
|
+
import scrollIntoView from 'scroll-into-view-if-needed'
|
|
13
|
+
import Stack from '@mui/material/Stack';
|
|
14
|
+
import { apiService } from 'authscape';
|
|
15
|
+
|
|
16
|
+
export function Comments({ticketId, isNote, isDisabled, currentUser}) {
|
|
17
|
+
|
|
18
|
+
const [comments, setComments] = useState([]);
|
|
19
|
+
const [message, setMessage] = useState("");
|
|
20
|
+
// const [messageDialogOpen, setMessageDialogOpen] = useState(false);
|
|
21
|
+
|
|
22
|
+
const reloadMessages = async () => {
|
|
23
|
+
|
|
24
|
+
// setIsLoading(true);
|
|
25
|
+
|
|
26
|
+
let response = await apiService().get("/Ticket/GetMessages?TicketId=" + ticketId + "&isNote=" + isNote);
|
|
27
|
+
if (response != null && response.status == 200)
|
|
28
|
+
{
|
|
29
|
+
setComments(response.data);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const node = document.getElementById('messages');
|
|
33
|
+
if (node != null)
|
|
34
|
+
{
|
|
35
|
+
scrollIntoView(node, { behavior: 'smooth', scrollMode: 'if-needed' })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// setIsLoading(false);
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
|
|
44
|
+
if (ticketId != null)
|
|
45
|
+
{
|
|
46
|
+
const asyncPush = async () => {
|
|
47
|
+
await reloadMessages();
|
|
48
|
+
}
|
|
49
|
+
asyncPush();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
}, [ticketId]);
|
|
53
|
+
|
|
54
|
+
const SendMessage = async () => {
|
|
55
|
+
|
|
56
|
+
if (message !== "")
|
|
57
|
+
{
|
|
58
|
+
let response = await apiService().post("/Ticket/CreateMessage", {
|
|
59
|
+
ticketId: ticketId,
|
|
60
|
+
name: currentUser.firstName,
|
|
61
|
+
message: message,
|
|
62
|
+
isNote: isNote
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (response != null && response.status == 200)
|
|
66
|
+
{
|
|
67
|
+
await reloadMessages();
|
|
68
|
+
// messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
69
|
+
// let messages = comments.slice();
|
|
70
|
+
// messages.push(message);
|
|
71
|
+
// setComments(messages);
|
|
72
|
+
setMessage("");
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Box sx={{display:"flex", flexDirection:"column", height:"100%"}}>
|
|
79
|
+
<Box sx={{backgroundColor:"#F3F5F7", overflow:"auto", flex: "1 1 auto"}}>
|
|
80
|
+
<Box>
|
|
81
|
+
{comments.length == 0 &&
|
|
82
|
+
<Box sx={{paddingLeft:4}}>
|
|
83
|
+
<QuestionAnswerOutlinedIcon sx={{fill:"gray", position:"relative", top:"4px", marginRight:2}} fontSize={"2px"} />
|
|
84
|
+
<Typography variant="subtitle2" color="text.secondary" component="span" sx={{marginTop:1}}>
|
|
85
|
+
Add your first {isNote ? "note" : "message" }. {isNote ? "Your notes" : "The conversation history" } will appear here
|
|
86
|
+
</Typography>
|
|
87
|
+
</Box>
|
|
88
|
+
}
|
|
89
|
+
<Box sx={{overflow:"scroll", height:"300px"}}>
|
|
90
|
+
<Grid container>
|
|
91
|
+
<Grid item xs={12}>
|
|
92
|
+
<List>
|
|
93
|
+
{comments != null && comments.map((comment, index) => {
|
|
94
|
+
return (
|
|
95
|
+
<ListItem key={index} sx={{marginTop:1}}>
|
|
96
|
+
<Grid container>
|
|
97
|
+
<Grid item xs={1}>
|
|
98
|
+
<Avatar />
|
|
99
|
+
</Grid>
|
|
100
|
+
<Grid item xs={11}>
|
|
101
|
+
<Stack direction="row" spacing={1}>
|
|
102
|
+
<Box sx={{fontSize:12}}>{comment.firstName}</Box>
|
|
103
|
+
<Box sx={{fontSize:12}}>{comment.created}</Box>
|
|
104
|
+
</Stack>
|
|
105
|
+
<Box sx={{fontSize:16}}>{comment.message}</Box>
|
|
106
|
+
</Grid>
|
|
107
|
+
</Grid>
|
|
108
|
+
</ListItem>
|
|
109
|
+
)
|
|
110
|
+
})}
|
|
111
|
+
|
|
112
|
+
<ListItem>
|
|
113
|
+
<div id={"messages"}></div>
|
|
114
|
+
</ListItem>
|
|
115
|
+
</List>
|
|
116
|
+
</Grid>
|
|
117
|
+
</Grid>
|
|
118
|
+
</Box>
|
|
119
|
+
</Box>
|
|
120
|
+
</Box>
|
|
121
|
+
|
|
122
|
+
<Box sx={{flex: "0 1 40px"}}>
|
|
123
|
+
<Paper
|
|
124
|
+
sx={{ p: '2px 4px', display: 'flex', alignItems: 'center'}}>
|
|
125
|
+
<InputBase
|
|
126
|
+
sx={{ ml: 1, flex: 1 }}
|
|
127
|
+
disabled={isDisabled}
|
|
128
|
+
onKeyUp={(event) => {
|
|
129
|
+
if (event.key == "Enter")
|
|
130
|
+
{
|
|
131
|
+
SendMessage();
|
|
132
|
+
}
|
|
133
|
+
}}
|
|
134
|
+
placeholder={!isNote ? "Write your message here..." : "Write your notes here..."}
|
|
135
|
+
value={message}
|
|
136
|
+
onChange={(value) => {
|
|
137
|
+
setMessage(value.target.value);
|
|
138
|
+
}}
|
|
139
|
+
/>
|
|
140
|
+
<IconButton disabled={isDisabled} type="button" sx={{ p: '10px' }} aria-label="search" onClick={() => {
|
|
141
|
+
SendMessage();
|
|
142
|
+
}}>
|
|
143
|
+
<SendRoundedIcon />
|
|
144
|
+
</IconButton>
|
|
145
|
+
</Paper>
|
|
146
|
+
</Box>
|
|
147
|
+
</Box>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import React, {useEffect, useState} from 'react';
|
|
2
|
+
import { Box } from '@mui/system';
|
|
3
|
+
import Grid from '@mui/material/Grid';
|
|
4
|
+
import Tabs from '@mui/material/Tabs';
|
|
5
|
+
import Tab from '@mui/material/Tab';
|
|
6
|
+
import Typography from '@mui/material/Typography';
|
|
7
|
+
import InputLabel from '@mui/material/InputLabel';
|
|
8
|
+
import MenuItem from '@mui/material/MenuItem';
|
|
9
|
+
import FormControl from '@mui/material/FormControl';
|
|
10
|
+
import Select from '@mui/material/Select';
|
|
11
|
+
import TextField from '@mui/material/TextField';
|
|
12
|
+
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
|
|
13
|
+
import { Button, Card, CardActions, CardContent, CardMedia, Stack } from "@mui/material";
|
|
14
|
+
import InsertDriveFileRoundedIcon from '@mui/icons-material/InsertDriveFileRounded';
|
|
15
|
+
import ArrowBackIosRoundedIcon from '@mui/icons-material/ArrowBackIosRounded';
|
|
16
|
+
import { apiService } from 'authscape';
|
|
17
|
+
import IconButton from '@mui/material/IconButton';
|
|
18
|
+
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
//import {Comments} from './comments';
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export const TicketDetail = ({ticketId, setIsLoading, currentUser, GoBackToViewTickets = null, customTabName = null, customTabElement = null}) => {
|
|
25
|
+
|
|
26
|
+
const [value, setValue] = useState(0);
|
|
27
|
+
const [status, setStatus] = useState(null);
|
|
28
|
+
const [ticketType, setTicketType] = useState(null);
|
|
29
|
+
const [ticket, setTicket] = useState(null);
|
|
30
|
+
const [priorty, setPriority] = useState(0);
|
|
31
|
+
const [participants, setParticipants] = useState([]);
|
|
32
|
+
const [ticketAttachments, setTicketAttachments] = useState([]);
|
|
33
|
+
const [customTabPayload, setCustomTabPayload] = useState(null);
|
|
34
|
+
|
|
35
|
+
const [ticketDescription, setTicketDescription] = useState(null);
|
|
36
|
+
|
|
37
|
+
const [createdByList, setCreatedByList] = useState([]);
|
|
38
|
+
const [selectedCreatedBy, setSelectedCreatedBy] = useState(null);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
|
|
42
|
+
const fetchData = async () => {
|
|
43
|
+
setIsLoading(true);
|
|
44
|
+
let response = await apiService().get("/Ticket/GetTicket?ticketId=" + ticketId);
|
|
45
|
+
if (response != null && response.status == 200)
|
|
46
|
+
{
|
|
47
|
+
setTicket(response.data);
|
|
48
|
+
|
|
49
|
+
setIsLoading(false);
|
|
50
|
+
setStatus(response.data.selectedTicketStatusId);
|
|
51
|
+
setTicketType(response.data.selectedTicketTypeId);
|
|
52
|
+
setPriority(response.data.selectedPriortyId);
|
|
53
|
+
setSelectedCreatedBy(response.data.selectedCreatedBy);
|
|
54
|
+
setParticipants(response.data.participants);
|
|
55
|
+
setTicketAttachments(response.data.attachments);
|
|
56
|
+
setCustomTabPayload(response.data.customTabPayload);
|
|
57
|
+
setTicketDescription(response.data.description);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (ticketId != null)
|
|
62
|
+
{
|
|
63
|
+
fetchData();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}, [ticketId]);
|
|
67
|
+
|
|
68
|
+
function TabPanel(props) {
|
|
69
|
+
const { children, value, index, ...other } = props;
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div
|
|
73
|
+
role="tabpanel"
|
|
74
|
+
hidden={value !== index}
|
|
75
|
+
id={`simple-tabpanel-${index}`}
|
|
76
|
+
aria-labelledby={`simple-tab-${index}`}
|
|
77
|
+
{...other}
|
|
78
|
+
>
|
|
79
|
+
{value === index && (
|
|
80
|
+
<Box sx={{ p: 3 }}>
|
|
81
|
+
<Typography>{children}</Typography>
|
|
82
|
+
</Box>
|
|
83
|
+
)}
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function a11yProps(index) {
|
|
89
|
+
return {
|
|
90
|
+
id: `simple-tab-${index}`,
|
|
91
|
+
'aria-controls': `simple-tabpanel-${index}`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const handleChange = (event, newValue) => {
|
|
96
|
+
setValue(newValue);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const refreshCreatedByList = async (query) => {
|
|
100
|
+
|
|
101
|
+
let response = await apiService().get("/ticket/findUser?query=" + query);
|
|
102
|
+
if (response != null && response.status == 200)
|
|
103
|
+
{
|
|
104
|
+
setCreatedByList(response.data);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const DownloadFile = ({fileName, uri}) => {
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<Card
|
|
112
|
+
sx={{
|
|
113
|
+
border: "1px solid black",
|
|
114
|
+
padding: "10px",
|
|
115
|
+
margin: "10px",
|
|
116
|
+
width: "200px",
|
|
117
|
+
textAlign:"center",
|
|
118
|
+
// display: "flex",
|
|
119
|
+
// alignItems: "center",
|
|
120
|
+
justifyContent: "space-between",
|
|
121
|
+
}}>
|
|
122
|
+
<Stack spacing={2}>
|
|
123
|
+
<Box sx={{textAlign:"center"}}>
|
|
124
|
+
<InsertDriveFileRoundedIcon sx={{fontSize:50}} />
|
|
125
|
+
</Box>
|
|
126
|
+
<Typography variant="h6" component="div">
|
|
127
|
+
{fileName}
|
|
128
|
+
</Typography>
|
|
129
|
+
<Button variant="contained" color="primary" onClick={() => {
|
|
130
|
+
window.open(uri);
|
|
131
|
+
}}>
|
|
132
|
+
Download
|
|
133
|
+
</Button>
|
|
134
|
+
</Stack>
|
|
135
|
+
</Card>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<div>
|
|
143
|
+
|
|
144
|
+
<Box sx={{width: '100%' }}>
|
|
145
|
+
|
|
146
|
+
<IconButton aria-label="delete" size="small" sx={{position:"absolute", right: 20, top: 20}} onClick={() => {
|
|
147
|
+
|
|
148
|
+
if (GoBackToViewTickets != null)
|
|
149
|
+
{
|
|
150
|
+
GoBackToViewTickets();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}}>
|
|
154
|
+
<CloseRoundedIcon fontSize="inherit" sx={{width:40, height:40}} />
|
|
155
|
+
</IconButton>
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
<Box>
|
|
159
|
+
<h2>{ticket != null && ticket.name}</h2>
|
|
160
|
+
</Box>
|
|
161
|
+
|
|
162
|
+
<Grid container spacing={2}>
|
|
163
|
+
<Grid item xs={4}>
|
|
164
|
+
|
|
165
|
+
<Box sx={{ minWidth: 120 }}>
|
|
166
|
+
<Box>
|
|
167
|
+
Status:
|
|
168
|
+
</Box>
|
|
169
|
+
<FormControl fullWidth>
|
|
170
|
+
<Select
|
|
171
|
+
labelId="demo-simple-select-label"
|
|
172
|
+
id="demo-simple-select"
|
|
173
|
+
value={status}
|
|
174
|
+
displayEmpty
|
|
175
|
+
inputProps={{ 'aria-label': 'Without label' }}
|
|
176
|
+
InputLabelProps={{ shrink: true }}
|
|
177
|
+
onChange={async (val) =>{
|
|
178
|
+
setStatus(val.target.value);
|
|
179
|
+
|
|
180
|
+
await apiService().put("/ticket/UpdateStatus", {
|
|
181
|
+
id: ticket.id,
|
|
182
|
+
ticketStatusId: val.target.value
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
}}>
|
|
186
|
+
|
|
187
|
+
{ticket != null && ticket.ticketStatuses.map((status, index) => {
|
|
188
|
+
return (
|
|
189
|
+
<MenuItem key={index} value={status.id}>{status.name}</MenuItem>
|
|
190
|
+
)
|
|
191
|
+
})}
|
|
192
|
+
|
|
193
|
+
</Select>
|
|
194
|
+
</FormControl>
|
|
195
|
+
</Box>
|
|
196
|
+
|
|
197
|
+
<Box sx={{paddingTop:2}}>
|
|
198
|
+
<Box>
|
|
199
|
+
Assigned to:
|
|
200
|
+
</Box>
|
|
201
|
+
|
|
202
|
+
{selectedCreatedBy != null &&
|
|
203
|
+
<Autocomplete
|
|
204
|
+
disablePortal
|
|
205
|
+
options={createdByList}
|
|
206
|
+
value={selectedCreatedBy}
|
|
207
|
+
onChange={async (event, newValue) => {
|
|
208
|
+
setSelectedCreatedBy(newValue.id);
|
|
209
|
+
}}
|
|
210
|
+
renderInput={(params) => <TextField {...params} label={""} onChange={(val) => {
|
|
211
|
+
refreshCreatedByList(val.currentTarget.value);
|
|
212
|
+
}} />}
|
|
213
|
+
/>
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
{ticket != null &&
|
|
217
|
+
<>
|
|
218
|
+
<Box sx={{paddingTop:1, fontSize:18}}>
|
|
219
|
+
{ticket.assignedFirstName + " " + ticket.assignedLastName} ({ticket.assignedEmail})
|
|
220
|
+
</Box>
|
|
221
|
+
</>
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
</Box>
|
|
225
|
+
|
|
226
|
+
{/* <Box>
|
|
227
|
+
Company
|
|
228
|
+
</Box> */}
|
|
229
|
+
|
|
230
|
+
<Box sx={{paddingTop:2}}>
|
|
231
|
+
<Box sx={{ minWidth: 120 }}>
|
|
232
|
+
<Box>
|
|
233
|
+
Priority:
|
|
234
|
+
</Box>
|
|
235
|
+
<FormControl fullWidth>
|
|
236
|
+
<InputLabel id="demo-simple-select-label"></InputLabel>
|
|
237
|
+
<Select
|
|
238
|
+
labelId="demo-simple-select-label"
|
|
239
|
+
id="demo-simple-select"
|
|
240
|
+
value={priorty}
|
|
241
|
+
label=""
|
|
242
|
+
onChange={async (val) =>{
|
|
243
|
+
setPriority(val.target.value);
|
|
244
|
+
|
|
245
|
+
await apiService().put("/ticket/UpdateTicketPriority", {
|
|
246
|
+
id: ticket.id,
|
|
247
|
+
priorityLevel: val.target.value
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
}}>
|
|
251
|
+
<MenuItem value={0}>None</MenuItem>
|
|
252
|
+
<MenuItem value={1}>Low</MenuItem>
|
|
253
|
+
<MenuItem value={2}>Medium</MenuItem>
|
|
254
|
+
<MenuItem value={3}>High</MenuItem>
|
|
255
|
+
<MenuItem value={4}>Urgent</MenuItem>
|
|
256
|
+
</Select>
|
|
257
|
+
</FormControl>
|
|
258
|
+
</Box>
|
|
259
|
+
</Box>
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
</Grid>
|
|
263
|
+
<Grid item xs={4}>
|
|
264
|
+
|
|
265
|
+
<Box sx={{ minWidth: 120 }}>
|
|
266
|
+
<Box>
|
|
267
|
+
Ticket Type:
|
|
268
|
+
</Box>
|
|
269
|
+
<FormControl fullWidth>
|
|
270
|
+
<InputLabel id="demo-simple-select-label"></InputLabel>
|
|
271
|
+
<Select
|
|
272
|
+
labelId="demo-simple-select-label"
|
|
273
|
+
id="ticketType"
|
|
274
|
+
value={ticketType}
|
|
275
|
+
label=""
|
|
276
|
+
onChange={async (val) =>{
|
|
277
|
+
setTicketType(val.target.value);
|
|
278
|
+
|
|
279
|
+
await apiService().put("/ticket/UpdateTicketType", {
|
|
280
|
+
id: ticket.id,
|
|
281
|
+
TicketTypeId: val.target.value
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
}}>
|
|
285
|
+
{ticket != null && ticket.ticketTypes.map((status, index) => {
|
|
286
|
+
return (
|
|
287
|
+
<MenuItem key={index} value={status.id}>{status.name}</MenuItem>
|
|
288
|
+
)
|
|
289
|
+
})}
|
|
290
|
+
|
|
291
|
+
</Select>
|
|
292
|
+
</FormControl>
|
|
293
|
+
</Box>
|
|
294
|
+
|
|
295
|
+
<Box sx={{paddingTop:2}}>
|
|
296
|
+
|
|
297
|
+
<Box>
|
|
298
|
+
Participants:
|
|
299
|
+
</Box>
|
|
300
|
+
<Autocomplete
|
|
301
|
+
multiple={true}
|
|
302
|
+
disablePortal
|
|
303
|
+
value={participants}
|
|
304
|
+
options={createdByList}
|
|
305
|
+
onChange={async (event, newValue) => {
|
|
306
|
+
|
|
307
|
+
// alert(JSON.stringify(newValue));
|
|
308
|
+
|
|
309
|
+
await apiService().put("/ticket/UpdateParticipants", {
|
|
310
|
+
ticketId: ticketId,
|
|
311
|
+
participants: newValue
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
setParticipants(newValue);
|
|
315
|
+
}}
|
|
316
|
+
renderInput={(params) => <TextField {...params} label={""} onChange={(val) => {
|
|
317
|
+
refreshCreatedByList(val.currentTarget.value);
|
|
318
|
+
}} />}
|
|
319
|
+
/>
|
|
320
|
+
{/* <TextField id="lastUpdated" fullWidth={true} InputLabelProps={{ shrink: true }} disabled={true} label="Participants" variant="outlined" autoFocus={true} value={(ticket != null ? ticket.lastUpdated : "")} /> */}
|
|
321
|
+
</Box>
|
|
322
|
+
</Grid>
|
|
323
|
+
<Grid item xs={4}>
|
|
324
|
+
<Box>
|
|
325
|
+
<Box>
|
|
326
|
+
Created:
|
|
327
|
+
</Box>
|
|
328
|
+
<TextField id="created" fullWidth={true} InputLabelProps={{ shrink: true }} disabled={true} label="" variant="outlined" autoFocus={true} value={(ticket != null ? ticket.created : "")} />
|
|
329
|
+
</Box>
|
|
330
|
+
<Box sx={{paddingTop:2}}>
|
|
331
|
+
<Box>
|
|
332
|
+
Last Updated:
|
|
333
|
+
</Box>
|
|
334
|
+
<TextField id="lastUpdated" fullWidth={true} InputLabelProps={{ shrink: true }} disabled={true} label="" variant="outlined" autoFocus={true} value={(ticket != null ? ticket.lastUpdated : "")} />
|
|
335
|
+
</Box>
|
|
336
|
+
</Grid>
|
|
337
|
+
</Grid>
|
|
338
|
+
</Box>
|
|
339
|
+
|
|
340
|
+
<Box sx={{ width: '100%', marginTop:2 }}>
|
|
341
|
+
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
|
342
|
+
<Tabs value={value} onChange={handleChange} aria-label="basic tabs example">
|
|
343
|
+
<Tab label="Description" {...a11yProps(0)} />
|
|
344
|
+
<Tab label="Chat" {...a11yProps(1)} />
|
|
345
|
+
<Tab label="Notes" {...a11yProps(2)} />
|
|
346
|
+
<Tab label="Attachments" {...a11yProps(3)} />
|
|
347
|
+
|
|
348
|
+
{customTabName != null &&
|
|
349
|
+
<Tab label={customTabName} {...a11yProps(4)} />
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
</Tabs>
|
|
353
|
+
</Box>
|
|
354
|
+
<TabPanel value={value} index={0}>
|
|
355
|
+
|
|
356
|
+
<Box sx={{whiteSpace:"pre-wrap"}}>
|
|
357
|
+
<Box dangerouslySetInnerHTML={{
|
|
358
|
+
__html: ticketDescription,
|
|
359
|
+
}}>
|
|
360
|
+
</Box>
|
|
361
|
+
</Box>
|
|
362
|
+
|
|
363
|
+
</TabPanel>
|
|
364
|
+
|
|
365
|
+
<TabPanel value={value} index={1}>
|
|
366
|
+
|
|
367
|
+
{ticket != null &&
|
|
368
|
+
<Comments ticketId={ticket.id} isDisabled={false} isNote={false} currentUser={currentUser} />
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
</TabPanel>
|
|
372
|
+
<TabPanel value={value} index={2}>
|
|
373
|
+
{ticket != null &&
|
|
374
|
+
<Comments ticketId={ticket.id} isDisabled={false} isNote={true} currentUser={currentUser} />
|
|
375
|
+
}
|
|
376
|
+
</TabPanel>
|
|
377
|
+
<TabPanel value={value} index={3}>
|
|
378
|
+
{ticket != null &&
|
|
379
|
+
<>
|
|
380
|
+
{ticketAttachments.map((attachment) => {
|
|
381
|
+
return (
|
|
382
|
+
<DownloadFile fileName={attachment.name} uri={attachment.url} />
|
|
383
|
+
)
|
|
384
|
+
})}
|
|
385
|
+
|
|
386
|
+
{ticketAttachments.length == 0 &&
|
|
387
|
+
<Box>
|
|
388
|
+
There are no attachments
|
|
389
|
+
</Box>
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
</>
|
|
393
|
+
}
|
|
394
|
+
</TabPanel>
|
|
395
|
+
|
|
396
|
+
{customTabName != null &&
|
|
397
|
+
<TabPanel value={value} index={4}>
|
|
398
|
+
{customTabElement(customTabPayload)}
|
|
399
|
+
</TabPanel>
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
</Box>
|
|
403
|
+
|
|
404
|
+
</div>
|
|
405
|
+
)
|
|
406
|
+
}
|