authscape 1.0.468 → 1.0.469

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.
@@ -1,16 +1,38 @@
1
- import { Box, Button } from '@mui/material';
2
- import React, { useEffect, useState, useRef } from 'react';
1
+ import { Box, Button, List, ListItem, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material';
2
+ import React, { useEffect, useState, useRef, useImperativeHandle, forwardRef } from 'react';
3
3
  import { ReactGrid, Column, Row } from "@silevis/reactgrid";
4
+ // import { apiService } from 'authscape';
4
5
  import {isMacOs} from 'react-device-detect';
5
6
  import * as signalR from '@microsoft/signalr';
6
7
  import Avatar from '@mui/material/Avatar';
7
8
  import Stack from '@mui/material/Stack';
8
9
  import Tooltip from '@mui/material/Tooltip';
9
10
 
10
- export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx, onFocusLocationChanged = null, onChange = null, hubUrl = null}) {
11
+ import AppBar from '@mui/material/AppBar';
12
+ import Toolbar from '@mui/material/Toolbar';
13
+ import VisibilityOffRoundedIcon from '@mui/icons-material/VisibilityOffRounded';
14
+ import FilterListRoundedIcon from '@mui/icons-material/FilterListRounded';
15
+ import SwapVertRoundedIcon from '@mui/icons-material/SwapVertRounded';
16
+ import LineWeightRoundedIcon from '@mui/icons-material/LineWeightRounded';
17
+ import PivotTableChartRoundedIcon from '@mui/icons-material/PivotTableChartRounded';
18
+ import ViewWeekRoundedIcon from '@mui/icons-material/ViewWeekRounded';
19
+
20
+ import Dialog from '@mui/material/Dialog';
21
+ import DialogActions from '@mui/material/DialogActions';
22
+ import DialogContent from '@mui/material/DialogContent';
23
+ import DialogContentText from '@mui/material/DialogContentText';
24
+ import DialogTitle from '@mui/material/DialogTitle';
25
+ import TextField from '@mui/material/TextField';
26
+
27
+ import {DndContext} from '@dnd-kit/core';
28
+ import {SortableContext} from '@dnd-kit/sortable';
29
+ // import { SortableColumn } from './Mapping/sortableColumn';
30
+
31
+ const SpreadsheetViewer = forwardRef(({loadedUser, currentUser, documentId, url, sx, hideToolbar = false, onFocusLocationChanged = null, advanceQuery = null, onChange = null, hubUrl = null}, ref) => {
11
32
 
12
33
  const [data, setData] = useState(null);
13
34
  const [rows, setRows] = useState(null);
35
+
14
36
  const [columns, setColumns] = useState(null);
15
37
 
16
38
  const [cellChangesIndex, setCellChangesIndex] = useState(() => -1);
@@ -19,12 +41,36 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
19
41
  const highlightsRef = useRef([]);
20
42
  const userIdRef = useRef(0);
21
43
 
44
+
45
+ const returnedRef = useRef([]);
46
+
47
+
48
+ const [showStickyDialog, setShowStickyDialog] = useState(false);
49
+
50
+ const leftColumnRef = useRef(null);
51
+ const rightColumnRef = useRef(null);
52
+ const topRowRef = useRef(null);
53
+ const bottomRowRef = useRef(null);
54
+
55
+ const [leftColumnSticky, setLeftColumnSticky] = useState(null);
56
+ const [rightColumnSticky, setRightColumnSticky] = useState(null);
57
+ const [topRowSticky, setTopRowSticky] = useState(null);
58
+ const [bottomRowSticky, setBottomRowSticky] = useState(null);
59
+
22
60
  const [highlights, setHighlights] = useState([]);
23
61
  const [sessions, setSessions] = useState([]);
24
62
  const [requestedChanges, setRequestedChanges] = useState([]);
25
63
 
26
64
  const [hubConnection, setHubConnection] = useState(null);
27
65
 
66
+ const getRows = () => {
67
+ return returnedRef.current;
68
+ }
69
+
70
+ useImperativeHandle(ref, () => ({
71
+ getRows
72
+ }));
73
+
28
74
  useEffect(() => {
29
75
 
30
76
  if (requestedChanges != null && requestedChanges.length > 0)
@@ -92,8 +138,27 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
92
138
 
93
139
  }, [requestedChanges]);
94
140
 
141
+
142
+ const validateAllCells = (cells) => {
143
+
144
+ let hasData = false;
145
+ cells.forEach(element => {
146
+
147
+ if (element.text != "" && element.text != null)
148
+ {
149
+ hasData = true;
150
+ }
151
+
152
+ });
153
+
154
+ return hasData
155
+ }
156
+
95
157
  const getSpreadSheetRows = (headerCell, rows) => {
96
158
 
159
+ // returnedRef
160
+ returnedRef.current = [];
161
+
97
162
  let dataRows = [
98
163
  {
99
164
  rowId: "header",
@@ -104,10 +169,60 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
104
169
  for (let index = 0; index < rows.length; index++) {
105
170
  const row = rows[index];
106
171
 
107
- dataRows.push({
108
- rowId: row.rowId,
109
- cells: row.cells
110
- });
172
+ if (rows != null && row.cells.length > 0 && advanceQuery != null && advanceQuery.rules.length > 0)
173
+ {
174
+ row.cells.forEach(element => {
175
+
176
+ advanceQuery.rules.forEach(rule => {
177
+
178
+ if (rule.field == element.columnId)
179
+ {
180
+ if (rule.operator == "contains")
181
+ {
182
+ if (element.text.toLowerCase().includes(rule.value.toLowerCase()))
183
+ {
184
+ if (validateAllCells(row.cells))
185
+ {
186
+ dataRows.push({
187
+ rowId: row.rowId,
188
+ cells: row.cells
189
+ });
190
+
191
+ returnedRef.current.push(row);
192
+ }
193
+ }
194
+ }
195
+ else if (rule.operator == "notContains")
196
+ {
197
+ if (!element.text.toLowerCase().includes(rule.value.toLowerCase()))
198
+ {
199
+ if (validateAllCells(row.cells))
200
+ {
201
+ dataRows.push({
202
+ rowId: row.rowId,
203
+ cells: row.cells
204
+ });
205
+
206
+ returnedRef.current.push(row);
207
+ }
208
+ }
209
+ }
210
+ }
211
+ });
212
+ });
213
+ }
214
+ else
215
+ {
216
+ if (validateAllCells(row.cells))
217
+ {
218
+ dataRows.push({
219
+ rowId: row.rowId,
220
+ cells: row.cells
221
+ });
222
+
223
+ returnedRef.current.push(row);
224
+ }
225
+ }
111
226
  }
112
227
 
113
228
  return dataRows;
@@ -131,8 +246,13 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
131
246
 
132
247
  useEffect(() => {
133
248
 
134
- if (loadedUser)
249
+ if (url)
135
250
  {
251
+ setLeftColumnSticky(parseInt(localStorage.getItem("leftColumn")));
252
+ setRightColumnSticky(parseInt(localStorage.getItem("rightColumn")));
253
+ setTopRowSticky(parseInt(localStorage.getItem("topRow")));
254
+ setBottomRowSticky(parseInt(localStorage.getItem("bottomRow")));
255
+
136
256
  const fetchData = async () => {
137
257
  let response = await apiService().get(url);
138
258
  if (response != null && response.status == 200)
@@ -145,7 +265,54 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
145
265
  fetchData();
146
266
  }
147
267
 
148
- }, [loadedUser]);
268
+ }, [url]);
269
+
270
+
271
+ // useEffect(() => {
272
+
273
+ // if (rows != null && advanceQuery != null)
274
+ // {
275
+ // let newRows = [...rows];
276
+
277
+ // let index = 0;
278
+ // rows.forEach(row => {
279
+
280
+ // row.cells.forEach(element => {
281
+
282
+ // advanceQuery.rules.forEach(rule => {
283
+
284
+ // if (rule.field == element.columnId)
285
+ // {
286
+
287
+ // if (element.text.toLowerCase().includes(rule.value))
288
+ // {
289
+ // newRows.push(element);
290
+ // index++;
291
+ // }
292
+
293
+
294
+ // //alert(rule.field + " - " + rule.operator + " - " + rule.value);
295
+ // }
296
+ // });
297
+
298
+ // });
299
+ // });
300
+
301
+
302
+
303
+
304
+
305
+
306
+ // setRows(newRows);
307
+
308
+ // // newRows.forEach(row => {
309
+ // // alert(JSON.stringify(row));
310
+ // // });
311
+
312
+ // // alert("found " + index + " empty fields")
313
+ // }
314
+
315
+ // }, [advanceQuery]);
149
316
 
150
317
  const getSessions = async () => {
151
318
 
@@ -153,28 +320,32 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
153
320
  var sessionData = response.data;
154
321
 
155
322
  let _sessions = [];
156
- sessionData.forEach((element) => {
157
323
 
158
- if (_sessions.find(s => s.userId == element.userId) == null)
159
- {
160
- if (element.userId == userIdRef.current)
161
- {
162
- _sessions.push({
163
- userId: element.userId,
164
- name: element.name,
165
- borderColor: "#3579f8"
166
- });
167
- }
168
- else
324
+ if (sessionData != null && sessionData.length > 0)
325
+ {
326
+ sessionData.forEach((element) => {
327
+
328
+ if (_sessions.find(s => s.userId == element.userId) == null)
169
329
  {
170
- _sessions.push({
171
- userId: element.userId,
172
- name: element.name,
173
- borderColor: element.borderColor
174
- });
330
+ if (element.userId == userIdRef.current)
331
+ {
332
+ _sessions.push({
333
+ userId: element.userId,
334
+ name: element.name,
335
+ borderColor: "#3579f8"
336
+ });
337
+ }
338
+ else
339
+ {
340
+ _sessions.push({
341
+ userId: element.userId,
342
+ name: element.name,
343
+ borderColor: element.borderColor
344
+ });
345
+ }
175
346
  }
176
- }
177
- });
347
+ });
348
+ }
178
349
 
179
350
  assignHighlights(highlightsRef.current);
180
351
  setSessions(_sessions);
@@ -241,6 +412,11 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
241
412
  {
242
413
  userIdRef.current = currentUser.id;
243
414
 
415
+ if (hubUrl == null)
416
+ {
417
+ return;
418
+ }
419
+
244
420
  const connection = new signalR.HubConnectionBuilder().withUrl(hubUrl).build();
245
421
 
246
422
  connection.on("onUpdateUserSession", () => {
@@ -437,23 +613,66 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
437
613
  children: `${name.split(' ')[0][0]}${name.split(' ')[1][0]}`,
438
614
  };
439
615
  }
440
-
616
+
617
+ const getaListOfColumns = () => {
618
+
619
+ let arrayItem = [];
620
+ for (let index = 0; index < columns.length; index++) {
621
+ const column = columns[index];
622
+ arrayItem.push(column.columnId);
623
+ }
624
+ return arrayItem;
625
+ }
441
626
 
442
627
  return (
443
628
  <Box>
444
- <Box sx={{paddingBottom:2}}>
445
- <Box sx={{paddingBottom:1}}>
446
- Sessions
447
- </Box>
448
- <Stack direction="row" spacing={2}>
449
- {sessions.map((user) => {
450
- return <Tooltip title={user.name}><Avatar {...stringAvatar(user.name, user.borderColor)} alt={user.name}></Avatar></Tooltip>
451
- })}
452
- </Stack>
453
- </Box>
454
- <Box sx={{ ...sx, overflow:"scroll"}}>
629
+ {!hideToolbar &&
630
+ <AppBar position="static" elevation={0} sx={{backgroundColor:"white"}}>
631
+ <Toolbar disableGutters sx={{color:"black"}}>
632
+ <Box sx={{ flexGrow: 1}}>
633
+
634
+ <Button variant={"text"} startIcon={<VisibilityOffRoundedIcon/>} sx={{color:"black"}}>
635
+ Hide Fields
636
+ </Button>
637
+
638
+ <Button variant={"text"} startIcon={<PivotTableChartRoundedIcon/>} sx={{color:"black", paddingLeft:4}} onClick={() => {
639
+ setShowStickyDialog(true);
640
+ }}>
641
+ Sticky
642
+ </Button>
643
+
644
+ <Button variant={"text"} startIcon={<FilterListRoundedIcon/>} sx={{color:"black", paddingLeft:4}}>
645
+ Filter
646
+ </Button>
647
+
648
+ <Button variant={"text"} startIcon={<SwapVertRoundedIcon/>} sx={{color:"black", paddingLeft:4}}>
649
+ Sort
650
+ </Button>
651
+
652
+ <Button variant={"text"} startIcon={<LineWeightRoundedIcon/>} sx={{color:"black", paddingLeft:4}}>
653
+ Row Height
654
+ </Button>
655
+
656
+ <Button variant={"text"} startIcon={<ViewWeekRoundedIcon/>} sx={{color:"black", paddingLeft:4}}>
657
+ Reorder Columns
658
+ </Button>
659
+
660
+ </Box>
661
+ <Box sx={{ flexGrow: 0 }}>
662
+ <Stack direction="row" spacing={2}>
663
+ {sessions.map((user) => {
664
+ return <Tooltip title={user.name}><Avatar {...stringAvatar(user.name, user.borderColor)} alt={user.name}></Avatar></Tooltip>
665
+ })}
666
+ </Stack>
667
+ </Box>
668
+ </Toolbar>
669
+ </AppBar>
670
+ }
671
+
672
+ {(leftColumnSticky != null && rightColumnSticky != null && topRowSticky != null && bottomRowSticky != null && data != null && columns != null) &&
673
+ <Box sx={{ ...sx}}>
455
674
  {(data != null && rows != null) &&
456
- <Box onKeyDown={(e) => {
675
+ <Box className="reactgrid-gold" onKeyDown={(e) => {
457
676
  const isMac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
458
677
 
459
678
  if ((!isMacOs && e.ctrlKey) || e.metaKey) {
@@ -467,10 +686,11 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
467
686
  }
468
687
  }
469
688
  }}>
470
- <ReactGrid
689
+ <ReactGrid
471
690
  rows={getSpreadSheetRows(data.headerCell, rows)}
472
691
  highlights={highlights}
473
692
  columns={columns}
693
+ enableFillHandle={true}
474
694
  onFocusLocationChanged={(location) => {
475
695
 
476
696
  try
@@ -490,11 +710,146 @@ export function SpreadsheetViewer({loadedUser, currentUser, documentId, url, sx,
490
710
  enableRangeSelection={true}
491
711
  //onContextMenu={simpleHandleContextMenu}
492
712
  onColumnResized={handleColumnResize}
493
- stickyTopRows={1}
713
+ stickyTopRows={topRowSticky}
714
+ stickyBottomRows={bottomRowSticky}
715
+ stickyLeftColumns={leftColumnSticky}
716
+ stickyRightColumns={rightColumnSticky}
494
717
  />
495
718
  </Box>
496
719
  }
497
720
  </Box>
721
+ }
722
+
723
+ <Dialog
724
+ open={showStickyDialog}
725
+ onClose={() => {
726
+ setShowStickyDialog(false);
727
+ }}
728
+ aria-labelledby="alert-dialog-title"
729
+ aria-describedby="alert-dialog-description">
730
+ <DialogTitle id="alert-dialog-title">
731
+ {"Sticky"}
732
+ </DialogTitle>
733
+ <DialogContent>
734
+ <DialogContentText id="alert-dialog-description">
735
+ Stick chosen rows and columns at the top or bottom rows or left and right columns. Sticky rows or columns will remain visible at all times.
736
+ </DialogContentText>
737
+
738
+ <TableContainer sx={{paddingTop:4}}>
739
+ <Table aria-label="customized table">
740
+ <TableHead>
741
+ <TableRow>
742
+ <TableCell align="left">Left Column</TableCell>
743
+ <TableCell align="left">Right Column</TableCell>
744
+ <TableCell align="left">Top Row</TableCell>
745
+ <TableCell align="left">Bottom Row</TableCell>
746
+ </TableRow>
747
+ </TableHead>
748
+ <TableBody>
749
+ <TableCell sx={{paddingTop:0}}>
750
+ <TextField inputRef={leftColumnRef} type="number" defaultValue="0" variant="outlined" />
751
+ </TableCell>
752
+ <TableCell sx={{paddingTop:0}}>
753
+ <TextField inputRef={rightColumnRef} type="number" defaultValue="0" variant="outlined" />
754
+ </TableCell>
755
+ <TableCell sx={{paddingTop:0}}>
756
+ <TextField inputRef={topRowRef} type="number" defaultValue="0" variant="outlined" />
757
+ </TableCell>
758
+ <TableCell sx={{paddingTop:0}}>
759
+ <TextField inputRef={bottomRowRef} type="number" defaultValue="0" variant="outlined" />
760
+ </TableCell>
761
+ </TableBody>
762
+ </Table>
763
+ </TableContainer>
764
+
765
+
766
+ </DialogContent>
767
+ <DialogActions>
768
+ <Button onClick={() => {
769
+
770
+ setShowStickyDialog(false);
771
+
772
+ }}>Cancel</Button>
773
+ <Button onClick={() => {
774
+
775
+ localStorage.setItem("leftColumn", leftColumnRef.current.value);
776
+ localStorage.setItem("rightColumn", rightColumnRef.current.value);
777
+ localStorage.setItem("topRow", topRowRef.current.value);
778
+ localStorage.setItem("bottomRow", bottomRowRef.current.value);
779
+
780
+ window.location.reload();
781
+ // setLeftColumnSticky(leftColumnRef.current.value);
782
+ // setRightColumnSticky(rightColumnRef.current.value);
783
+ // setTopRowSticky(topRowRef.current.value);
784
+ // setBottomRowSticky(bottomRowRef.current.value);
785
+
786
+ setShowStickyDialog(false);
787
+
788
+ }} autoFocus>
789
+ Apply
790
+ </Button>
791
+ </DialogActions>
792
+ </Dialog>
793
+
794
+ <Dialog
795
+ open={false}
796
+ onClose={() => {
797
+ setShowStickyDialog(false);
798
+ }}
799
+ aria-labelledby="alert-dialog-title"
800
+ aria-describedby="alert-dialog-description">
801
+ <DialogTitle id="alert-dialog-title">
802
+ {"Reorder Columns"}
803
+ </DialogTitle>
804
+ <DialogContent>
805
+ <DialogContentText id="alert-dialog-description">
806
+ Assign the column order from left to right.
807
+ </DialogContentText>
808
+
809
+
810
+ {columns != null &&
811
+ <List>
812
+ <DndContext onDragEnd={(event) => {
813
+ const {over} = event;
814
+
815
+ alert(over.id);
816
+ // If the item is dropped over a container, set it as the parent
817
+ // otherwise reset the parent to `null`
818
+ //setParent(over ? over.id : null);
819
+ }}>
820
+ <SortableContext items={getaListOfColumns()}>
821
+
822
+ {columns.map((item) => {
823
+ return (
824
+ <SortableColumn key={item.columnId} id={item.columnId} />
825
+ )
826
+ })}
827
+
828
+ </SortableContext>
829
+ </DndContext>
830
+ </List>
831
+ }
832
+
833
+
834
+ </DialogContent>
835
+ <DialogActions>
836
+ <Button onClick={() => {
837
+
838
+ setShowStickyDialog(false);
839
+
840
+ }}>Cancel</Button>
841
+ <Button onClick={() => {
842
+
843
+
844
+
845
+ }} autoFocus>
846
+ Apply
847
+ </Button>
848
+ </DialogActions>
849
+ </Dialog>
850
+
498
851
  </Box>
499
852
  );
500
- }
853
+ });
854
+
855
+ export default SpreadsheetViewer