authscape 1.0.245 → 1.0.248
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/package.json +1 -1
- package/src/components/DocumentManager +423 -0
package/package.json
CHANGED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { AppBar, Box, Button, Toolbar, Typography, Grid, Paper } from '@mui/material';
|
|
2
|
+
import React, {useEffect, useState, useRef} from 'react';
|
|
3
|
+
import AddRoundedIcon from '@mui/icons-material/AddRounded';
|
|
4
|
+
import DeleteRoundedIcon from '@mui/icons-material/DeleteRounded';
|
|
5
|
+
import FolderIcon from '@mui/icons-material/Folder';
|
|
6
|
+
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
|
|
7
|
+
import { styled, alpha } from '@mui/material/styles';
|
|
8
|
+
import Menu from '@mui/material/Menu';
|
|
9
|
+
import MenuItem from '@mui/material/MenuItem';
|
|
10
|
+
import Divider from '@mui/material/Divider';
|
|
11
|
+
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
|
12
|
+
import InsertDriveFileOutlinedIcon from '@mui/icons-material/InsertDriveFileOutlined';
|
|
13
|
+
import Breadcrumbs from '@mui/material/Breadcrumbs';
|
|
14
|
+
import Link from '@mui/material/Link';
|
|
15
|
+
import PublishRoundedIcon from '@mui/icons-material/PublishRounded';
|
|
16
|
+
import Dialog from '@mui/material/Dialog';
|
|
17
|
+
import DialogActions from '@mui/material/DialogActions';
|
|
18
|
+
import DialogContent from '@mui/material/DialogContent';
|
|
19
|
+
import DialogContentText from '@mui/material/DialogContentText';
|
|
20
|
+
import DialogTitle from '@mui/material/DialogTitle';
|
|
21
|
+
import LockRoundedIcon from '@mui/icons-material/LockRounded';
|
|
22
|
+
import Tooltip from '@mui/material/Tooltip';
|
|
23
|
+
|
|
24
|
+
export function DocumentManager({loadedUser, setIsLoading, viewDocumentType = 1, apiDownloadEnforced = false, overrideLockMessage = "The directory cannot be removed."}) {
|
|
25
|
+
|
|
26
|
+
const fileUploaderRef = useRef();
|
|
27
|
+
const [files, setFiles] = useState(null);
|
|
28
|
+
const [update, setUpdate] = useState(false);
|
|
29
|
+
const [folderParent, setFolderParent] = useState(null);
|
|
30
|
+
const [breadCrumb, setBreadCrumb] = useState([]);
|
|
31
|
+
|
|
32
|
+
const [contextMenu, setContextMenu] = useState(null);
|
|
33
|
+
const [contextFile, setContextFile] = useState(null);
|
|
34
|
+
|
|
35
|
+
const [dialogDelete, setDialogDelete] = useState(false);
|
|
36
|
+
|
|
37
|
+
const handleContextMenu = (event, file) => {
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
|
|
40
|
+
setContextFile(file);
|
|
41
|
+
|
|
42
|
+
if (!file.isLocked)
|
|
43
|
+
{
|
|
44
|
+
setContextMenu(
|
|
45
|
+
contextMenu === null
|
|
46
|
+
? {
|
|
47
|
+
mouseX: event.clientX + 2,
|
|
48
|
+
mouseY: event.clientY - 6,
|
|
49
|
+
}
|
|
50
|
+
: // repeated contextmenu when it is already open closes it with Chrome 84 on Ubuntu
|
|
51
|
+
// Other native context menus might behave different.
|
|
52
|
+
// With this behavior we prevent contextmenu from the backdrop to re-locale existing context menus.
|
|
53
|
+
null,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
|
|
61
|
+
if (loadedUser)
|
|
62
|
+
{
|
|
63
|
+
const fetchDocuments = async () => {
|
|
64
|
+
|
|
65
|
+
if (folderParent != null)
|
|
66
|
+
{
|
|
67
|
+
let response = await apiService().get("/Document/GetDocumentsAndFiles?parentFolderId=" + folderParent.id + "&ViewDocumentType=" + viewDocumentType);
|
|
68
|
+
if (response != null && response.status == 200)
|
|
69
|
+
{
|
|
70
|
+
setFiles(response.data);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else
|
|
74
|
+
{
|
|
75
|
+
let response = await apiService().get("/Document/GetDocumentsAndFiles?ViewDocumentType=" + viewDocumentType);
|
|
76
|
+
if (response != null && response.status == 200)
|
|
77
|
+
{
|
|
78
|
+
setFiles(response.data);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
};
|
|
83
|
+
fetchDocuments();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}, [loadedUser, folderParent, update])
|
|
87
|
+
|
|
88
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
89
|
+
const open = Boolean(anchorEl);
|
|
90
|
+
const handleClick = (event) => {
|
|
91
|
+
setAnchorEl(event.currentTarget);
|
|
92
|
+
};
|
|
93
|
+
const handleClose = () => {
|
|
94
|
+
setAnchorEl(null);
|
|
95
|
+
setContextMenu(null);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const StyledMenu = styled((props) => (
|
|
99
|
+
<Menu
|
|
100
|
+
elevation={0}
|
|
101
|
+
anchorOrigin={{
|
|
102
|
+
vertical: 'bottom',
|
|
103
|
+
horizontal: 'right',
|
|
104
|
+
}}
|
|
105
|
+
transformOrigin={{
|
|
106
|
+
vertical: 'top',
|
|
107
|
+
horizontal: 'right',
|
|
108
|
+
}}
|
|
109
|
+
{...props}
|
|
110
|
+
/>
|
|
111
|
+
))(({ theme }) => ({
|
|
112
|
+
'& .MuiPaper-root': {
|
|
113
|
+
borderRadius: 6,
|
|
114
|
+
marginTop: theme.spacing(1),
|
|
115
|
+
minWidth: 180,
|
|
116
|
+
color:
|
|
117
|
+
theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[300],
|
|
118
|
+
boxShadow:
|
|
119
|
+
'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px',
|
|
120
|
+
'& .MuiMenu-list': {
|
|
121
|
+
padding: '4px 0',
|
|
122
|
+
},
|
|
123
|
+
'& .MuiMenuItem-root': {
|
|
124
|
+
'& .MuiSvgIcon-root': {
|
|
125
|
+
fontSize: 18,
|
|
126
|
+
color: theme.palette.text.secondary,
|
|
127
|
+
marginRight: theme.spacing(1.5),
|
|
128
|
+
},
|
|
129
|
+
'&:active': {
|
|
130
|
+
backgroundColor: alpha(
|
|
131
|
+
theme.palette.primary.main,
|
|
132
|
+
theme.palette.action.selectedOpacity,
|
|
133
|
+
),
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
}));
|
|
138
|
+
|
|
139
|
+
const handleFileClick = async (file, addToBread = true) => {
|
|
140
|
+
|
|
141
|
+
if (file.type == "folder")
|
|
142
|
+
{
|
|
143
|
+
setFolderParent(file);
|
|
144
|
+
|
|
145
|
+
if (addToBread)
|
|
146
|
+
{
|
|
147
|
+
let newBC = [...breadCrumb];
|
|
148
|
+
newBC.push(file);
|
|
149
|
+
setBreadCrumb(newBC);
|
|
150
|
+
}
|
|
151
|
+
else
|
|
152
|
+
{
|
|
153
|
+
let newList = [];
|
|
154
|
+
let hasBeenFound = false;
|
|
155
|
+
for (let index = 0; index < breadCrumb.length; index++) {
|
|
156
|
+
|
|
157
|
+
const element = breadCrumb[index];
|
|
158
|
+
if (element.id == file.id)
|
|
159
|
+
{
|
|
160
|
+
hasBeenFound = true;
|
|
161
|
+
newList.push(element);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!hasBeenFound)
|
|
166
|
+
{
|
|
167
|
+
newList.push(element);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
setBreadCrumb(newList);
|
|
173
|
+
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
else
|
|
178
|
+
{
|
|
179
|
+
setIsLoading(true);
|
|
180
|
+
|
|
181
|
+
await apiService().DownloadFile("/Document/DownloadDocument?documentId=" + file.id + "&ViewDocumentType=" + viewDocumentType, file.name, () => {
|
|
182
|
+
setIsLoading(false);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const dialogDeleteClosed = () => {
|
|
189
|
+
setContextFile(null);
|
|
190
|
+
setContextMenu(null);
|
|
191
|
+
setDialogDelete(false);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<>
|
|
196
|
+
<Box sx={{ flexGrow: 1 }}>
|
|
197
|
+
<AppBar position="static" color='inherit' elevation={0}>
|
|
198
|
+
<Toolbar>
|
|
199
|
+
<Box>
|
|
200
|
+
<Button
|
|
201
|
+
id="demo-customized-button"
|
|
202
|
+
aria-controls={open ? 'demo-customized-menu' : undefined}
|
|
203
|
+
aria-haspopup="true"
|
|
204
|
+
aria-expanded={open ? 'true' : undefined}
|
|
205
|
+
variant="contained"
|
|
206
|
+
disableElevation
|
|
207
|
+
onClick={handleClick}
|
|
208
|
+
startIcon={<AddRoundedIcon />}
|
|
209
|
+
endIcon={<KeyboardArrowDownIcon />}
|
|
210
|
+
>
|
|
211
|
+
New
|
|
212
|
+
</Button>
|
|
213
|
+
<StyledMenu
|
|
214
|
+
id="demo-customized-menu"
|
|
215
|
+
MenuListProps={{
|
|
216
|
+
'aria-labelledby': 'demo-customized-button',
|
|
217
|
+
}}
|
|
218
|
+
anchorEl={anchorEl}
|
|
219
|
+
open={open}
|
|
220
|
+
onClose={handleClose}
|
|
221
|
+
>
|
|
222
|
+
<MenuItem onClick={async () => {
|
|
223
|
+
|
|
224
|
+
let newDocumentName = prompt("New folder name");
|
|
225
|
+
if (newDocumentName != null && newDocumentName != "")
|
|
226
|
+
{
|
|
227
|
+
let response = await apiService().post("/Document/CreateFolder", {
|
|
228
|
+
folderName: newDocumentName,
|
|
229
|
+
parentFolderId: folderParent != null ? folderParent.id : null,
|
|
230
|
+
viewDocumentType: viewDocumentType
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
if (response != null && response.status == 200)
|
|
234
|
+
{
|
|
235
|
+
// refresh
|
|
236
|
+
setUpdate(!update);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
handleClose();
|
|
242
|
+
}} disableRipple>
|
|
243
|
+
<InsertDriveFileIcon />
|
|
244
|
+
New Folder
|
|
245
|
+
</MenuItem>
|
|
246
|
+
</StyledMenu>
|
|
247
|
+
</Box>
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
<FileUploader refOveride={fileUploaderRef} url={"/Document/UploadFile"} params={{
|
|
251
|
+
parentFolderId: (folderParent != null ? folderParent.id : null),
|
|
252
|
+
viewDocumentType: viewDocumentType
|
|
253
|
+
|
|
254
|
+
}} multiple={true} variant='custom' onUploadCompleted={() => {
|
|
255
|
+
setUpdate(!update);
|
|
256
|
+
handleClose();
|
|
257
|
+
}}>
|
|
258
|
+
|
|
259
|
+
<Button
|
|
260
|
+
id="FileUploader"
|
|
261
|
+
aria-controls={open ? 'demo-customized-menu' : undefined}
|
|
262
|
+
aria-haspopup="true"
|
|
263
|
+
aria-expanded={open ? 'true' : undefined}
|
|
264
|
+
variant="text"
|
|
265
|
+
disableElevation
|
|
266
|
+
startIcon={<PublishRoundedIcon />}
|
|
267
|
+
sx={{marginLeft:1}}>
|
|
268
|
+
Upload File(s)
|
|
269
|
+
</Button>
|
|
270
|
+
|
|
271
|
+
</FileUploader>
|
|
272
|
+
</Toolbar>
|
|
273
|
+
</AppBar>
|
|
274
|
+
|
|
275
|
+
<Divider />
|
|
276
|
+
|
|
277
|
+
<Breadcrumbs aria-label="breadcrumb" separator={">"} sx={{marginLeft:1, marginBottom:2, marginTop:2}}>
|
|
278
|
+
<Link underline="hover" color="inherit" sx={{cursor:"pointer", fontWeight:"bold"}} onClick={() => {
|
|
279
|
+
|
|
280
|
+
setFolderParent(null);
|
|
281
|
+
setBreadCrumb([]);
|
|
282
|
+
|
|
283
|
+
}}>
|
|
284
|
+
My Files
|
|
285
|
+
</Link>
|
|
286
|
+
{breadCrumb.map((bread, index) => {
|
|
287
|
+
return (
|
|
288
|
+
<Link
|
|
289
|
+
key={index}
|
|
290
|
+
underline="hover"
|
|
291
|
+
sx={{cursor:"pointer"}}
|
|
292
|
+
color="inherit" onClick={() => {
|
|
293
|
+
handleFileClick(bread, false);
|
|
294
|
+
}}>
|
|
295
|
+
{bread.name}
|
|
296
|
+
</Link>
|
|
297
|
+
)
|
|
298
|
+
})}
|
|
299
|
+
</Breadcrumbs>
|
|
300
|
+
</Box>
|
|
301
|
+
|
|
302
|
+
<Box sx={{height: "85vh", width: '100%' }}>
|
|
303
|
+
<Grid container spacing={2}>
|
|
304
|
+
{files != null && files.map((file, index) => (
|
|
305
|
+
|
|
306
|
+
<Grid onContextMenu={(event) => {
|
|
307
|
+
handleContextMenu(event, file);
|
|
308
|
+
}} item key={index} xs={12} sm={6} md={4} lg={2} onClick={() => handleFileClick(file)}>
|
|
309
|
+
<Paper
|
|
310
|
+
sx={{
|
|
311
|
+
padding: 2,
|
|
312
|
+
display: 'flex',
|
|
313
|
+
flexDirection: 'column',
|
|
314
|
+
alignItems: 'center',
|
|
315
|
+
cursor: 'pointer',
|
|
316
|
+
position:"relative",
|
|
317
|
+
'&:hover': {
|
|
318
|
+
backgroundColor: '#F5F5F5'
|
|
319
|
+
}
|
|
320
|
+
}}>
|
|
321
|
+
|
|
322
|
+
{file.type === 'folder' &&
|
|
323
|
+
<Box sx={{position:"absolute", top:45, color:"white"}}>
|
|
324
|
+
{file.count}
|
|
325
|
+
</Box>}
|
|
326
|
+
|
|
327
|
+
{file.isLocked &&
|
|
328
|
+
<Box sx={{position:"absolute", top:10, right: 10, color:"black"}}>
|
|
329
|
+
<Tooltip title={overrideLockMessage}>
|
|
330
|
+
<LockRoundedIcon />
|
|
331
|
+
</Tooltip>
|
|
332
|
+
</Box>
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
{file.type === 'folder' ? (
|
|
336
|
+
<FolderIcon sx={{ fontSize: 80, color:"orange" }} />
|
|
337
|
+
) : (
|
|
338
|
+
|
|
339
|
+
file.documentFileExtentionType == 0 || apiDownloadEnforced ? <InsertDriveFileOutlinedIcon sx={{ fontSize: 60 }} /> : <NextImage src={file.uri} alt={"Image"} width={80} height={80} />
|
|
340
|
+
|
|
341
|
+
)}
|
|
342
|
+
<Typography variant="subtitle1" sx={{paddingTop:1}}>{file.name}</Typography>
|
|
343
|
+
<Typography variant="subtitle2" sx={{paddingTop:0, fontSize:11}}>{file.lastUpdated}</Typography>
|
|
344
|
+
</Paper>
|
|
345
|
+
</Grid>
|
|
346
|
+
|
|
347
|
+
))}
|
|
348
|
+
</Grid>
|
|
349
|
+
|
|
350
|
+
<Menu
|
|
351
|
+
open={contextMenu !== null}
|
|
352
|
+
onClose={handleClose}
|
|
353
|
+
anchorReference="anchorPosition"
|
|
354
|
+
anchorPosition={
|
|
355
|
+
contextMenu !== null
|
|
356
|
+
? { top: contextMenu.mouseY, left: contextMenu.mouseX }
|
|
357
|
+
: undefined
|
|
358
|
+
}>
|
|
359
|
+
{/* <MenuItem onClick={handleClose}>Move</MenuItem>
|
|
360
|
+
<MenuItem onClick={handleClose}>Copy</MenuItem>
|
|
361
|
+
<Divider /> */}
|
|
362
|
+
<MenuItem startIcon={<DeleteRoundedIcon />} onClick={() => {
|
|
363
|
+
|
|
364
|
+
setDialogDelete(true);
|
|
365
|
+
handleClose();
|
|
366
|
+
|
|
367
|
+
}}>Delete</MenuItem>
|
|
368
|
+
</Menu>
|
|
369
|
+
</Box>
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
<Dialog
|
|
373
|
+
open={dialogDelete}
|
|
374
|
+
onClose={() => {
|
|
375
|
+
dialogDeleteClosed();
|
|
376
|
+
}}
|
|
377
|
+
aria-labelledby="alert-dialog-title"
|
|
378
|
+
aria-describedby="alert-dialog-description">
|
|
379
|
+
<DialogTitle id="alert-dialog-title">
|
|
380
|
+
Are you sure you wan to delete {contextFile != null ? contextFile.name : ""}?
|
|
381
|
+
</DialogTitle>
|
|
382
|
+
<DialogContent>
|
|
383
|
+
<DialogContentText id="alert-dialog-description">
|
|
384
|
+
|
|
385
|
+
{(contextFile != null && contextFile.type != null && contextFile.type == 'folder') &&
|
|
386
|
+
<>
|
|
387
|
+
If you delete {contextFile != null ? contextFile.name : ""}, you will delete all files and folders within {contextFile != null ? contextFile.name : ""}.
|
|
388
|
+
</>
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
{(contextFile != null && contextFile.type != null && contextFile.type != 'folder') &&
|
|
392
|
+
<>
|
|
393
|
+
If you delete {contextFile != null ? contextFile.name : ""} this file will be gone forever.
|
|
394
|
+
</>
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
</DialogContentText>
|
|
399
|
+
</DialogContent>
|
|
400
|
+
<DialogActions>
|
|
401
|
+
<Button onClick={() => {
|
|
402
|
+
|
|
403
|
+
dialogDeleteClosed();
|
|
404
|
+
|
|
405
|
+
}}>Cancel</Button>
|
|
406
|
+
<Button onClick={async () => {
|
|
407
|
+
dialogDeleteClosed();
|
|
408
|
+
|
|
409
|
+
let response = await apiService().delete("/Document/DeleteFolder?documentId=" + contextFile.id);
|
|
410
|
+
if (response != null && response.status == 200)
|
|
411
|
+
{
|
|
412
|
+
setUpdate(!update);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
}} autoFocus>
|
|
416
|
+
Delete
|
|
417
|
+
</Button>
|
|
418
|
+
</DialogActions>
|
|
419
|
+
</Dialog>
|
|
420
|
+
</>
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
};
|