authscape 1.0.550 → 1.0.552

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,9 +1,8 @@
1
1
  import React, {useEffect, useState, useRef} from 'react';
2
2
  import { Box } from '@mui/system';
3
3
  import TextField from '@mui/material/TextField';
4
- import { Button, Grid } from '@mui/material';
4
+ import { Autocomplete, Button, Grid } from '@mui/material';
5
5
  import Typography from '@mui/material/Typography';
6
- // import { apiService } from 'authscape';
7
6
  import FormControl from '@mui/material/FormControl';
8
7
  import InputLabel from '@mui/material/InputLabel';
9
8
  import Select from '@mui/material/Select';
@@ -14,6 +13,8 @@ import ListItemText from '@mui/material/ListItemText';
14
13
  import { useForm, Controller } from 'react-hook-form';
15
14
  import FormControlLabel from '@mui/material/FormControlLabel';
16
15
  import Switch from '@mui/material/Switch';
16
+ import { Tab, Tabs } from '@mui/material';
17
+ import { BusinessRounded, PersonRounded } from '@mui/icons-material';
17
18
 
18
19
  export function UserEditor({userId = null, customFields = null, onSaved = null}) {
19
20
 
@@ -22,6 +23,14 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
22
23
  const [selectedRoles, setSelectedRole] = useState([]);
23
24
  const [selectedPermission, setSelectedPermission] = useState([]);
24
25
 
26
+ const [companies, setCompanies] = useState([]);
27
+ const [company, setCompany] = useState(null);
28
+ const [inputCompanyValue, setInputCompanyValue] = useState('');
29
+
30
+ const [locations, setLocations] = useState([]);
31
+ const [location, setLocation] = useState(null);
32
+ const [inputLocationValue, setInputLocationValue] = useState('');
33
+
25
34
  const [roles, setRole] = useState([]);
26
35
  const [permissions, setPermissions] = useState([]);
27
36
 
@@ -38,6 +47,12 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
38
47
  },
39
48
  };
40
49
 
50
+ const [tabValue, setTabValue] = useState(0);
51
+
52
+ const handleTabChange = (event, newValue) => {
53
+ setTabValue(newValue);
54
+ };
55
+
41
56
  useEffect(() => {
42
57
 
43
58
  const fetchData = async () => {
@@ -69,6 +84,16 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
69
84
  {
70
85
  setUser(response.data);
71
86
 
87
+ if (response.data.company != null)
88
+ {
89
+ setCompany(response.data.company);
90
+ }
91
+
92
+ if (response.data.location != null)
93
+ {
94
+ setLocation(response.data.location);
95
+ }
96
+
72
97
  // assign all selected roles
73
98
  if (response.data.roles != null)
74
99
  {
@@ -95,7 +120,12 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
95
120
 
96
121
  }
97
122
  }
98
- fetchData();
123
+
124
+ if (userId != -1)
125
+ {
126
+ fetchData();
127
+ }
128
+
99
129
  }
100
130
 
101
131
  }, [userId])
@@ -103,7 +133,6 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
103
133
  const fields = [
104
134
  "FirstName",
105
135
  "LastName",
106
- "Company",
107
136
  "IsActive",
108
137
  "Email"
109
138
  ]
@@ -148,12 +177,12 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
148
177
 
149
178
  return (
150
179
  <>
151
- {user != null && customFields.map((field) => {
180
+ {(userId != -1 ? user != null : true) && customFields.map((field) => {
152
181
 
153
182
  let result = findCustomFieldValue(field.name);
154
183
 
155
184
  return (
156
- <Box>
185
+ <Grid item xs={6}>
157
186
  <Controller name={field.name}
158
187
  control={control}
159
188
  rules={{
@@ -172,7 +201,7 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
172
201
  }
173
202
  />
174
203
  {errors[field.name] && <Typography color={"red"}>{field.name} is required.</Typography>}
175
- </Box>
204
+ </Grid>
176
205
  )
177
206
 
178
207
  })}
@@ -184,52 +213,52 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
184
213
 
185
214
  return (
186
215
  <>
187
- {user != null && customFields.map((field) => {
216
+ {(userId != -1 ? user != null : true) && customFields.map((field) => {
188
217
 
189
218
  let result = findTheValue(field);
190
219
 
191
220
  return (
192
- <Box>
193
-
194
- {field == "IsActive" &&
195
- <Box>
196
- <Controller name={field}
197
- control={control}
198
- rules={{
199
- required: false,
200
- }}
201
- render={({renderField}) =>
202
- <FormControlLabel control={<Switch defaultChecked={result} />} label={field} {...register(field, { required: false })} {...renderField} />
203
- }
204
- />
205
- {errors[field] && <Typography color={"red"}>{field} is required.</Typography>}
221
+ <Grid item xs={6}>
206
222
 
207
- </Box>
208
- }
223
+ {field == "IsActive" &&
224
+ <Box>
225
+ <Controller name={field}
226
+ control={control}
227
+ rules={{
228
+ required: false,
229
+ }}
230
+ render={({renderField}) =>
231
+ <FormControlLabel control={<Switch defaultChecked={result} />} label={field} {...register(field, { required: false })} {...renderField} />
232
+ }
233
+ />
234
+ {errors[field] && <Typography color={"red"}>{field} is required.</Typography>}
209
235
 
210
- {field != "IsActive" &&
211
- <Box>
212
- <Controller name={field}
213
- control={control}
214
- rules={{
215
- required: true,
216
- }}
217
- render={({renderField}) =>
218
- <TextField
219
- label={field}
220
- variant="outlined"
221
- defaultValue={result}
222
- margin="normal"
223
- fullWidth
224
- {...register(field, { required: true })}
225
- {...renderField}
226
- />
227
- }
228
- />
229
- {errors[field] && <Typography color={"red"}>{field} is required.</Typography>}
230
- </Box>
231
- }
232
- </Box>
236
+ </Box>
237
+ }
238
+
239
+ {field != "IsActive" &&
240
+ <Box>
241
+ <Controller name={field}
242
+ control={control}
243
+ rules={{
244
+ required: true,
245
+ }}
246
+ render={({renderField}) =>
247
+ <TextField
248
+ label={field}
249
+ variant="outlined"
250
+ defaultValue={result}
251
+ margin="normal"
252
+ fullWidth
253
+ {...register(field, { required: true })}
254
+ {...renderField}
255
+ />
256
+ }
257
+ />
258
+ {errors[field] && <Typography color={"red"}>{field} is required.</Typography>}
259
+ </Box>
260
+ }
261
+ </Grid>
233
262
  )
234
263
 
235
264
  })}
@@ -237,12 +266,84 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
237
266
  )
238
267
  }
239
268
 
240
- return (
241
- <Box sx={{paddingTop:0}}>
269
+ function a11yProps(index) {
270
+ return {
271
+ id: `simple-tab-${index}`,
272
+ 'aria-controls': `simple-tabpanel-${index}`
273
+ };
274
+ }
275
+
276
+
277
+
278
+ useEffect(() => {
279
+
280
+ const fetchData = async () => {
281
+
282
+ if (inputCompanyValue == null || inputCompanyValue == "")
283
+ {
284
+ let response = await apiService().get("/UserManagement/GetCompanies");
285
+ if (response != null && response.status == 200)
286
+ {
287
+ setCompanies(response.data);
288
+ }
289
+ }
290
+ else
291
+ {
292
+ let response = await apiService().get("/UserManagement/GetCompanies?name=" + inputCompanyValue);
293
+ if (response != null && response.status == 200)
294
+ {
295
+ setCompanies(response.data);
296
+ }
297
+ }
298
+
299
+ }
300
+
301
+ if (user != null || userId == -1)
302
+ {
303
+ fetchData();
304
+ }
305
+
306
+ }, [user, userId, inputCompanyValue])
307
+
308
+
242
309
 
243
- <Box sx={{paddingBottom:2}}>
244
- Edit Account
245
- </Box>
310
+
311
+
312
+
313
+ useEffect(() => {
314
+
315
+ const fetchData = async () => {
316
+
317
+ if (company != null)
318
+ {
319
+ if (inputLocationValue == null || inputLocationValue == "")
320
+ {
321
+ let response = await apiService().get("/UserManagement/GetLocations?companyId=" + company.id);
322
+ if (response != null && response.status == 200)
323
+ {
324
+ setLocations(response.data);
325
+ }
326
+ }
327
+ else
328
+ {
329
+ let response = await apiService().get("/UserManagement/GetLocations?companyId=" + company.id + "&name=" + inputLocationValue);
330
+ if (response != null && response.status == 200)
331
+ {
332
+ setLocations(response.data);
333
+ }
334
+ }
335
+ }
336
+ }
337
+
338
+ if (user != null || userId == -1)
339
+ {
340
+ fetchData();
341
+ }
342
+
343
+ }, [user, userId, inputLocationValue, company])
344
+
345
+ return (
346
+ <Box sx={{paddingTop:0, minWidth: 600}}>
246
347
 
247
348
  <form onSubmit={handleSubmit(async (data) => {
248
349
 
@@ -260,7 +361,8 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
260
361
  id: userId,
261
362
  firstName: data.FirstName,
262
363
  lastName: data.LastName,
263
- company: data.Company,
364
+ companyId: company != null ? company.id : null,
365
+ locationId: location != null ? location.id : null,
264
366
  email: data.Email,
265
367
  isActive: data.IsActive,
266
368
  roles: selectedRoles != "" ? selectedRoles : null,
@@ -277,99 +379,212 @@ export function UserEditor({userId = null, customFields = null, onSaved = null})
277
379
  }
278
380
 
279
381
  })} noValidate autoComplete="off">
280
- <Grid container spacing={2}>
281
- <Grid item xs={6}>
282
-
283
- <Box>
284
382
 
285
- {renderSystemField(fields)}
383
+ <Box>
384
+ <Box>
385
+ <Tabs value={tabValue} onChange={handleTabChange} variant="fullWidth" aria-label="basic tabs example" centered>
386
+ <Tab label="Information" {...a11yProps(0)} />
387
+ <Tab label="Company / Locations" {...a11yProps(1)} />
388
+ <Tab label="Roles / Permissions" {...a11yProps(2)} />
389
+ {/* <Tab label="Item Three" {...a11yProps(2)} /> */}
390
+ </Tabs>
391
+ </Box>
286
392
 
287
- {renderCustomField(customFields)}
393
+ {tabValue === 0 &&
394
+ <Grid spacing={2} sx={{paddingLeft:2, paddingRight:2, paddingTop:2}}>
288
395
 
289
- </Box>
396
+ {renderSystemField(fields)}
397
+ {renderCustomField(customFields)}
290
398
 
291
399
  </Grid>
400
+ }
292
401
 
293
- <Grid item xs={6}>
402
+ {tabValue === 1 &&
403
+ <Grid spacing={2} sx={{paddingLeft:2, paddingRight:2, paddingTop:2}}>
294
404
 
295
- <Box>
405
+ <Autocomplete
406
+ id="companySelect"
407
+ sx={{paddingTop:2}}
408
+ getOptionLabel={
409
+ (option) => option.title
410
+ }
411
+ filterOptions={(x) => x}
412
+ options={companies != null ? companies : []}
413
+ autoComplete
414
+ includeInputInList
415
+ filterSelectedOptions
416
+ value={company}
417
+ noOptionsText="No locations"
418
+ onChange={(event, newValue) => {
419
+ setCompanies(newValue ? [newValue, ...companies] : companies);
420
+ setCompany(newValue);
421
+ setLocation(null);
422
+ }}
423
+ onInputChange={(event, newInputValue) => {
424
+ setInputCompanyValue(newInputValue);
425
+ }}
426
+ renderInput={(params) => (
427
+ <TextField {...params} label="Company" fullWidth />
428
+ )}
429
+ renderOption={(props, option) => {
430
+ // const matches =
431
+ // option.structured_formatting.main_text_matched_substrings || [];
432
+
433
+ // const parts = parse(
434
+ // option.structured_formatting.main_text,
435
+ // matches.map((match) => [match.offset, match.offset + match.length]),
436
+ // );
437
+
438
+ return (
439
+ <li {...props}>
440
+ <Grid container alignItems="center">
441
+ <Grid item sx={{ display: 'flex', width: 44 }}>
442
+ <BusinessRounded sx={{ color: 'text.secondary' }} />
443
+ </Grid>
444
+ <Grid item sx={{ width: 'calc(100% - 44px)', wordWrap: 'break-word' }}>
445
+ {/* {parts.map((part, index) => (
446
+ <Box
447
+ key={index}
448
+ component="span"
449
+ sx={{ fontWeight: part.highlight ? 'bold' : 'regular' }}
450
+ >
451
+ {part.text}
452
+ </Box>
453
+ ))} */}
454
+ <Typography variant="body2" color="text.secondary">
455
+ {option.title}
456
+ </Typography>
457
+ </Grid>
458
+ </Grid>
459
+ </li>
460
+ );
461
+ }}
462
+ />
296
463
 
297
- <FormControl sx={{ paddingTop:1, m: 1, width: "100%" }}>
298
- <InputLabel id="demo-multiple-checkbox-label">Roles</InputLabel>
299
- <Select
300
- fullWidth={true}
301
- labelId="demo-multiple-checkbox-label"
302
- id="demo-multiple-checkbox"
303
- {...register("roles", { required: false })}
304
- multiple
305
- value={selectedRoles}
306
- onChange={(event) => {
307
-
308
- const {
309
- target: { value },
310
- } = event;
311
- setSelectedRole(
312
- // On autofill we get a stringified value.
313
- typeof value === 'string' ? value.split(',') : value,
314
- );
315
-
316
- }}
317
- input={<OutlinedInput label="Roles" />}
318
- renderValue={(selected) => selected.join(', ')}
319
- MenuProps={MenuProps}>
320
- {roles.map((role) => (
321
- <MenuItem key={role.name} value={role.name}>
322
- <Checkbox checked={selectedRoles.indexOf(role.name) > -1} />
323
- <ListItemText primary={role.name} />
324
- </MenuItem>
325
- ))}
326
- </Select>
327
- </FormControl>
328
- {errors.roles && <Typography color={"red"}>{"roles"} is required.</Typography>}
329
-
330
-
331
- <FormControl sx={{ m: 1, paddingTop:1, width: "100%" }}>
332
- <InputLabel id="demo-multiple-checkbox-label">Permissions</InputLabel>
333
- <Select
334
- fullWidth={true}
335
- labelId="demo-multiple-checkbox-label"
336
- id="demo-multiple-checkbox"
337
- {...register("permissions", { required: false })}
338
- multiple
339
- value={selectedPermission}
340
- onChange={(event) => {
464
+ <Autocomplete
465
+ id="LocationSelect"
466
+ sx={{paddingTop:3}}
467
+ getOptionLabel={
468
+ (option) => option.title
469
+ }
470
+ filterOptions={(x) => x}
471
+ options={locations != null ? locations : []}
472
+ autoComplete
473
+ includeInputInList
474
+ filterSelectedOptions
475
+ value={location}
476
+ noOptionsText="No locations"
477
+ onChange={(event, newValue) => {
478
+ setLocations(newValue ? [newValue, ...locations] : locations);
479
+ setLocation(newValue);
480
+ }}
481
+ onInputChange={(event, newInputValue) => {
482
+ setInputCompanyValue(newInputValue);
483
+ }}
484
+ renderInput={(params) => (
485
+ <TextField {...params} label="Location" fullWidth />
486
+ )}
487
+ renderOption={(props, option) => {
488
+
489
+ return (
490
+ <li {...props}>
491
+ <Grid container alignItems="center">
492
+ <Grid item sx={{ display: 'flex', width: 44 }}>
493
+ <BusinessRounded sx={{ color: 'text.secondary' }} />
494
+ </Grid>
495
+ <Grid item sx={{ width: 'calc(100% - 44px)', wordWrap: 'break-word' }}>
496
+ <Typography variant="body2" color="text.secondary">
497
+ {option.title}
498
+ </Typography>
499
+ </Grid>
500
+ </Grid>
501
+ </li>
502
+ );
503
+ }}
504
+ />
505
+
506
+ </Grid>
507
+ }
508
+
509
+ {tabValue === 2 &&
510
+ <Box sx={{paddingLeft:2, paddingRight:2, paddingTop:2}}>
511
+
512
+ <FormControl sx={{ paddingTop:1, m: 1, width: "100%" }}>
513
+ <InputLabel id="demo-multiple-checkbox-label">Roles</InputLabel>
514
+ <Select
515
+ fullWidth={true}
516
+ labelId="demo-multiple-checkbox-label"
517
+ id="demo-multiple-checkbox"
518
+ {...register("roles", { required: false })}
519
+ multiple
520
+ value={selectedRoles}
521
+ onChange={(event) => {
341
522
 
342
523
  const {
343
- target: { value },
524
+ target: { value },
344
525
  } = event;
345
- setSelectedPermission(
346
- // On autofill we get a stringified value.
347
- typeof value === 'string' ? value.split(',') : value,
526
+ setSelectedRole(
527
+ // On autofill we get a stringified value.
528
+ typeof value === 'string' ? value.split(',') : value,
348
529
  );
530
+
531
+ }}
532
+ input={<OutlinedInput label="Roles" />}
533
+ renderValue={(selected) => selected.join(', ')}
534
+ MenuProps={MenuProps}>
535
+ {roles.map((role) => (
536
+ <MenuItem key={role.name} value={role.name}>
537
+ <Checkbox checked={selectedRoles.indexOf(role.name) > -1} />
538
+ <ListItemText primary={role.name} />
539
+ </MenuItem>
540
+ ))}
541
+ </Select>
542
+ </FormControl>
543
+ {errors.roles && <Typography color={"red"}>{"roles"} is required.</Typography>}
544
+
545
+
546
+ <FormControl sx={{ m: 1, paddingTop:1, width: "100%" }}>
547
+ <InputLabel id="demo-multiple-checkbox-label">Permissions</InputLabel>
548
+ <Select
549
+ fullWidth={true}
550
+ labelId="demo-multiple-checkbox-label"
551
+ id="demo-multiple-checkbox"
552
+ {...register("permissions", { required: false })}
553
+ multiple
554
+ value={selectedPermission}
555
+ onChange={(event) => {
556
+
557
+ const {
558
+ target: { value },
559
+ } = event;
560
+ setSelectedPermission(
561
+ // On autofill we get a stringified value.
562
+ typeof value === 'string' ? value.split(',') : value,
563
+ );
564
+
565
+ }}
566
+ input={<OutlinedInput label="Roles" />}
567
+ renderValue={(selected) => selected.join(', ')}
568
+ MenuProps={MenuProps}>
569
+ {permissions.map((permission) => (
570
+ <MenuItem key={permission.name} value={permission.name}>
571
+ <Checkbox checked={selectedPermission.indexOf(permission.name) > -1} />
572
+ <ListItemText primary={permission.name} />
573
+ </MenuItem>
574
+ ))}
575
+ </Select>
576
+ </FormControl>
577
+ {errors.permissions && <Typography color={"red"}>{"permissions"} is required.</Typography>}
349
578
 
350
- }}
351
- input={<OutlinedInput label="Roles" />}
352
- renderValue={(selected) => selected.join(', ')}
353
- MenuProps={MenuProps}>
354
- {permissions.map((permission) => (
355
- <MenuItem key={permission.name} value={permission.name}>
356
- <Checkbox checked={selectedPermission.indexOf(permission.name) > -1} />
357
- <ListItemText primary={permission.name} />
358
- </MenuItem>
359
- ))}
360
- </Select>
361
- </FormControl>
362
- {errors.permissions && <Typography color={"red"}>{"permissions"} is required.</Typography>}
579
+ </Box>
580
+ }
363
581
 
364
- </Box>
582
+ <Box sx={{paddingTop:1, paddingBottom: 4, paddingLeft: 2}}>
583
+ <Button variant="contained" type="submit">{userId == -1 ? "Create Account" : "Update Account"}</Button>
584
+ </Box>
365
585
 
366
- </Grid>
367
- </Grid>
368
- <Box sx={{paddingTop:2}}>
369
- <Button variant="contained" type="submit">Submit</Button>
370
586
  </Box>
371
587
  </form>
372
-
373
588
  </Box>
374
589
  )
375
590
  }