@visns-studio/visns-components 4.10.48 → 5.0.1-8.1
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 +29 -29
- package/src/components/cms/Field.jsx +39 -63
- package/src/components/crm/AsyncSelect.jsx +121 -15
- package/src/components/crm/Breadcrumb.jsx +2 -18
- package/src/components/crm/DataGrid.jsx +51 -424
- package/src/components/crm/Field.jsx +185 -358
- package/src/components/crm/Form.jsx +104 -92
- package/src/components/crm/MultiSelect.jsx +66 -45
- package/src/components/crm/Navigation.jsx +9 -92
- package/src/components/crm/QuickAction.jsx +1 -0
- package/src/components/crm/auth/Login.jsx +9 -1
- package/src/components/crm/auth/Profile.jsx +4 -2
- package/src/components/crm/auth/styles/Login.module.scss +52 -82
- package/src/components/crm/auth/styles/Profile.module.scss +150 -44
- package/src/components/crm/auth/styles/Reset.module.scss +55 -37
- package/src/components/crm/auth/styles/Verify.module.scss +55 -76
- package/src/components/crm/generic/GenericAuth.jsx +12 -5
- package/src/components/crm/generic/GenericDashboard.jsx +30 -340
- package/src/components/crm/generic/GenericDetail.jsx +534 -86
- package/src/components/crm/generic/GenericDynamic.jsx +76 -94
- package/src/components/crm/generic/GenericEditableTable.jsx +407 -0
- package/src/components/crm/generic/GenericFormBuilder.jsx +19 -79
- package/src/components/crm/generic/GenericIndex.jsx +1 -2
- package/src/components/crm/generic/styles/AuditLog.module.scss +4 -37
- package/src/components/crm/generic/styles/AuditLogs.module.scss +0 -51
- package/src/components/crm/generic/styles/GenericDetail.module.scss +263 -244
- package/src/components/crm/generic/styles/GenericDynamic.module.scss +100 -198
- package/src/components/crm/generic/styles/GenericEditableTable.module.scss +178 -0
- package/src/components/crm/generic/styles/GenericFormBuilder.module.scss +63 -101
- package/src/components/crm/generic/styles/GenericIndex.module.scss +46 -66
- package/src/components/crm/generic/styles/GenericMain.module.scss +7 -7
- package/src/components/crm/generic/styles/GenericSort.module.scss +0 -36
- package/src/components/crm/generic/styles/NotificationList.module.scss +1 -32
- package/src/components/crm/styles/Autocomplete.module.scss +12 -20
- package/src/components/crm/styles/DataGrid.module.scss +28 -86
- package/src/components/crm/styles/Field.module.scss +72 -252
- package/src/components/crm/styles/Form.module.scss +141 -450
- package/src/components/crm/styles/Navigation.module.scss +356 -507
- package/src/components/crm/styles/Notification.module.scss +1 -0
- package/src/components/crm/styles/QrCode.module.scss +4 -18
- package/src/components/crm/styles/SwitchAccount.module.scss +0 -1
- package/src/components/crm/styles/TableFilter.module.scss +2 -1
- package/src/components/styles/global.css +164 -34
- package/src/index.js +0 -8
- package/src/components/crm/generic/styles/GenericDashboard.module.scss +0 -325
- package/src/components/crm/sketch/SketchField.jsx +0 -395
- package/src/components/crm/sketch/arrow.jsx +0 -108
- package/src/components/crm/sketch/circle.jsx +0 -75
- package/src/components/crm/sketch/default-tool.jsx +0 -16
- package/src/components/crm/sketch/fabrictool.jsx +0 -22
- package/src/components/crm/sketch/history.jsx +0 -144
- package/src/components/crm/sketch/json/config.json +0 -14
- package/src/components/crm/sketch/line.jsx +0 -64
- package/src/components/crm/sketch/pan.jsx +0 -48
- package/src/components/crm/sketch/pencil.jsx +0 -36
- package/src/components/crm/sketch/rectangle-label-object.jsx +0 -69
- package/src/components/crm/sketch/rectangle-label.jsx +0 -93
- package/src/components/crm/sketch/rectangle.jsx +0 -76
- package/src/components/crm/sketch/select.jsx +0 -16
- package/src/components/crm/sketch/tools.jsx +0 -11
- package/src/components/crm/sketch/utils.jsx +0 -67
|
@@ -151,8 +151,6 @@ function Form({
|
|
|
151
151
|
}
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
-
const handleChangeCanvas = (id, value) => {};
|
|
155
|
-
|
|
156
154
|
const handleChangeCheckbox = (e) => {
|
|
157
155
|
const { checked, name, value } = e.target;
|
|
158
156
|
|
|
@@ -217,15 +215,12 @@ function Form({
|
|
|
217
215
|
const handleSelectOption = () => {
|
|
218
216
|
updateFormData({ [id]: inputValue });
|
|
219
217
|
|
|
220
|
-
// Update any matching form data properties
|
|
221
|
-
Object.keys(inputValue)
|
|
222
|
-
.
|
|
223
|
-
(key)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
key !== 'label'
|
|
227
|
-
)
|
|
228
|
-
.forEach((key) => updateFormData({ [key]: inputValue[key] }));
|
|
218
|
+
// Update any matching form data properties except for the second item
|
|
219
|
+
Object.keys(inputValue).forEach((key, index) => {
|
|
220
|
+
if (index !== 1 && formData.hasOwnProperty(key)) {
|
|
221
|
+
updateFormData({ [key]: inputValue[key] });
|
|
222
|
+
}
|
|
223
|
+
});
|
|
229
224
|
|
|
230
225
|
formSettings.fields.forEach((field) => {
|
|
231
226
|
if (field.id === id && field.trigger) {
|
|
@@ -272,28 +267,12 @@ function Form({
|
|
|
272
267
|
let contentValue = inputValue[field.trigger.key];
|
|
273
268
|
|
|
274
269
|
if (field.trigger.url && field.trigger.payload) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
[field.trigger.payload.
|
|
280
|
-
|
|
281
|
-
[field.trigger.payload.key.content]:
|
|
282
|
-
inputValue[field.trigger.payload.value.content],
|
|
283
|
-
};
|
|
284
|
-
} else {
|
|
285
|
-
setContentPayload = {
|
|
286
|
-
formData: formData,
|
|
287
|
-
[field.trigger.payload.key.content]:
|
|
288
|
-
inputValue[field.trigger.payload.value.content],
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const res = await CustomFetch(
|
|
293
|
-
field.trigger.url,
|
|
294
|
-
'POST',
|
|
295
|
-
setContentPayload
|
|
296
|
-
);
|
|
270
|
+
const res = await CustomFetch(field.trigger.url, 'POST', {
|
|
271
|
+
[field.trigger.payload.key.id]:
|
|
272
|
+
inputValue[field.trigger.payload.value.id],
|
|
273
|
+
[field.trigger.payload.key.content]:
|
|
274
|
+
inputValue[field.trigger.payload.value.content],
|
|
275
|
+
});
|
|
297
276
|
|
|
298
277
|
if (res.data.content) {
|
|
299
278
|
contentValue = res.data.content;
|
|
@@ -308,6 +287,7 @@ function Form({
|
|
|
308
287
|
// Switch cases to handle different actions
|
|
309
288
|
switch (action.action) {
|
|
310
289
|
case 'select-option':
|
|
290
|
+
case 'create-option': // New case to handle create-option
|
|
311
291
|
handleSelectOption();
|
|
312
292
|
break;
|
|
313
293
|
case 'clear':
|
|
@@ -605,17 +585,17 @@ function Form({
|
|
|
605
585
|
|
|
606
586
|
if (['create', 'update'].includes(formType)) {
|
|
607
587
|
fields.forEach((item) => {
|
|
588
|
+
// Skip createOnly fields if formType is 'update'
|
|
608
589
|
if (formType === 'update' && item.createOnly) {
|
|
609
590
|
return;
|
|
610
591
|
}
|
|
611
592
|
|
|
593
|
+
// Check if the item is required
|
|
612
594
|
if (item.required) {
|
|
613
|
-
if
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
) {
|
|
595
|
+
// Check if formData[item.id] is null, undefined, or an empty string
|
|
596
|
+
if (!formData[item.id]) {
|
|
597
|
+
// Check for required_check dependency
|
|
617
598
|
if (
|
|
618
|
-
item.hasOwnProperty('required_check') &&
|
|
619
599
|
item.required_check &&
|
|
620
600
|
!formData[item.required_check]
|
|
621
601
|
) {
|
|
@@ -626,19 +606,18 @@ function Form({
|
|
|
626
606
|
_inputClass[item.id] = styles.inputError;
|
|
627
607
|
}
|
|
628
608
|
} else {
|
|
629
|
-
_inputClass[item.id] = '';
|
|
609
|
+
_inputClass[item.id] = ''; // Clear error class if valid
|
|
630
610
|
}
|
|
631
611
|
} else if (
|
|
632
|
-
item.hasOwnProperty('required_rely') &&
|
|
633
612
|
item.required_rely &&
|
|
634
613
|
formData[item.required_rely] &&
|
|
635
|
-
|
|
636
|
-
formData[item.id] === '')
|
|
614
|
+
!formData[item.id]
|
|
637
615
|
) {
|
|
616
|
+
// Check if the dependent required field is empty when it should be filled
|
|
638
617
|
validation += `${item.label} is a required field.<br/>`;
|
|
639
618
|
_inputClass[item.id] = styles.inputError;
|
|
640
619
|
} else {
|
|
641
|
-
_inputClass[item.id] = '';
|
|
620
|
+
_inputClass[item.id] = ''; // Clear error class if not required
|
|
642
621
|
}
|
|
643
622
|
});
|
|
644
623
|
|
|
@@ -713,55 +692,87 @@ function Form({
|
|
|
713
692
|
});
|
|
714
693
|
}
|
|
715
694
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
695
|
+
if (fileUpload && formData[fileKey]) {
|
|
696
|
+
if (Array.isArray(formData[fileKey])) {
|
|
697
|
+
const uploadPromises = formData[fileKey].map(
|
|
698
|
+
async (file) => {
|
|
699
|
+
const toastId = toast.info(
|
|
700
|
+
`Uploading ${file.name}`,
|
|
701
|
+
{
|
|
702
|
+
progress: 0,
|
|
703
|
+
autoClose: false,
|
|
704
|
+
}
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
const fileRes = await Vapor.store(file, {
|
|
708
|
+
progress: (progress) => {
|
|
709
|
+
setUploadProgress(progress * 100);
|
|
710
|
+
toast.update(toastId, {
|
|
711
|
+
progress,
|
|
712
|
+
});
|
|
713
|
+
},
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
toast.update(toastId, {
|
|
717
|
+
render: `${file.name} uploaded successfully!`,
|
|
718
|
+
type: 'success',
|
|
719
|
+
autoClose: 3000,
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
return {
|
|
723
|
+
uuid: fileRes.uuid,
|
|
724
|
+
key: fileRes.key,
|
|
725
|
+
bucket: fileRes.bucket,
|
|
726
|
+
filename: file.name,
|
|
727
|
+
filesize: file.size,
|
|
728
|
+
extension: fileRes.extension,
|
|
729
|
+
file_relationship: fileKey,
|
|
730
|
+
fileable_field:
|
|
731
|
+
fileFieldSetting.fileable_field,
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
);
|
|
719
735
|
|
|
720
|
-
|
|
721
|
-
|
|
736
|
+
formData['uploadedFiles'] = await Promise.all(
|
|
737
|
+
uploadPromises
|
|
738
|
+
);
|
|
739
|
+
} else {
|
|
722
740
|
const toastId = toast.info(
|
|
723
|
-
`Uploading ${
|
|
741
|
+
`Uploading ${formData[fileKey].name}`,
|
|
724
742
|
{
|
|
725
743
|
progress: 0,
|
|
726
744
|
autoClose: false,
|
|
727
745
|
}
|
|
728
746
|
);
|
|
729
747
|
|
|
730
|
-
const fileRes = await Vapor.store(
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
748
|
+
const fileRes = await Vapor.store(
|
|
749
|
+
formData[fileKey],
|
|
750
|
+
{
|
|
751
|
+
progress: (progress) => {
|
|
752
|
+
setUploadProgress(progress * 100);
|
|
753
|
+
toast.update(toastId, {
|
|
754
|
+
progress,
|
|
755
|
+
});
|
|
756
|
+
},
|
|
757
|
+
}
|
|
758
|
+
);
|
|
736
759
|
|
|
737
760
|
toast.update(toastId, {
|
|
738
|
-
render: `${
|
|
761
|
+
render: `${formData[fileKey].name} uploaded successfully!`,
|
|
739
762
|
type: 'success',
|
|
740
763
|
autoClose: 3000,
|
|
741
764
|
});
|
|
742
765
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
fileable_field
|
|
752
|
-
|
|
753
|
-
fileFieldSetting.id,
|
|
754
|
-
};
|
|
755
|
-
});
|
|
756
|
-
|
|
757
|
-
// Wait for all uploads to complete
|
|
758
|
-
const uploadedFiles = await Promise.all(uploadPromises);
|
|
759
|
-
|
|
760
|
-
// If there are multiple files, store them as an array, otherwise as a single object
|
|
761
|
-
formData['uploadedFiles'] =
|
|
762
|
-
uploadedFiles.length > 1
|
|
763
|
-
? uploadedFiles
|
|
764
|
-
: uploadedFiles[0];
|
|
766
|
+
formData['uuid'] = fileRes.uuid;
|
|
767
|
+
formData['key'] = fileRes.key;
|
|
768
|
+
formData['bucket'] = fileRes.bucket;
|
|
769
|
+
formData['filename'] = formData[fileKey].name;
|
|
770
|
+
formData['filesize'] = formData[fileKey].size;
|
|
771
|
+
formData['extension'] = fileRes.extension;
|
|
772
|
+
formData['file_relationship'] = fileKey;
|
|
773
|
+
formData['fileable_field'] =
|
|
774
|
+
fileFieldSetting.fileable_field;
|
|
775
|
+
}
|
|
765
776
|
}
|
|
766
777
|
|
|
767
778
|
// Transform keys with dots into nested objects
|
|
@@ -879,23 +890,25 @@ function Form({
|
|
|
879
890
|
method,
|
|
880
891
|
payload = {};
|
|
881
892
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
893
|
+
if (ajaxSetting?.where) {
|
|
894
|
+
const getDataId = () => {
|
|
895
|
+
for (const item of ajaxSetting.where) {
|
|
896
|
+
if (
|
|
897
|
+
item.hasOwnProperty('urlParam') &&
|
|
898
|
+
item.urlParam === 'dataId'
|
|
899
|
+
) {
|
|
900
|
+
return item.value;
|
|
901
|
+
}
|
|
889
902
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
}
|
|
903
|
+
return 0;
|
|
904
|
+
};
|
|
905
|
+
}
|
|
893
906
|
|
|
894
907
|
if (
|
|
895
908
|
formSettings.hasOwnProperty('json') &&
|
|
896
909
|
formSettings.json === true
|
|
897
910
|
) {
|
|
898
|
-
let dataId = getDataId();
|
|
911
|
+
let dataId = paramValue || getDataId();
|
|
899
912
|
|
|
900
913
|
urlSuffix = '/json/get';
|
|
901
914
|
method = 'POST';
|
|
@@ -1364,7 +1377,7 @@ function Form({
|
|
|
1364
1377
|
);
|
|
1365
1378
|
} else {
|
|
1366
1379
|
return (
|
|
1367
|
-
<div className={
|
|
1380
|
+
<div className={styles.modalwrap}>
|
|
1368
1381
|
<div className={styles.modal}>
|
|
1369
1382
|
<div className={styles.modal__header}>
|
|
1370
1383
|
<h1>{formSettings[formType]?.title}</h1>
|
|
@@ -1372,7 +1385,7 @@ function Form({
|
|
|
1372
1385
|
className={styles.modal__close}
|
|
1373
1386
|
onClick={closeModal}
|
|
1374
1387
|
>
|
|
1375
|
-
<CircleX strokeWidth={
|
|
1388
|
+
<CircleX strokeWidth={2} size={24} />
|
|
1376
1389
|
</button>
|
|
1377
1390
|
</div>
|
|
1378
1391
|
<div className={styles.modal__content}>
|
|
@@ -1426,7 +1439,6 @@ function Form({
|
|
|
1426
1439
|
}
|
|
1427
1440
|
mapbox={mapbox}
|
|
1428
1441
|
onChange={handleChange}
|
|
1429
|
-
onChangeCanvas={handleChangeCanvas}
|
|
1430
1442
|
onChangeCheckbox={
|
|
1431
1443
|
handleChangeCheckbox
|
|
1432
1444
|
}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import CustomFetch from './Fetch';
|
|
3
|
-
import
|
|
4
|
-
import Select, { createFilter } from 'react-select';
|
|
3
|
+
import Select, { createFilter, components } from 'react-select';
|
|
5
4
|
import CreatableSelect from 'react-select/creatable';
|
|
6
5
|
import styles from './styles/AsyncSelect.module.scss';
|
|
7
6
|
|
|
7
|
+
const CustomOption = (props) => (
|
|
8
|
+
<components.Option {...props}>
|
|
9
|
+
<div>
|
|
10
|
+
{props.data.label}
|
|
11
|
+
{props.data.description && props.data.description !== '' && (
|
|
12
|
+
<div style={{ fontSize: '0.85em', color: '#888' }}>
|
|
13
|
+
{props.data.description}
|
|
14
|
+
</div>
|
|
15
|
+
)}
|
|
16
|
+
</div>
|
|
17
|
+
</components.Option>
|
|
18
|
+
);
|
|
19
|
+
|
|
8
20
|
function MultiSelect({
|
|
9
21
|
className,
|
|
10
|
-
inputValue = [],
|
|
22
|
+
inputValue = [],
|
|
11
23
|
multi,
|
|
12
24
|
onChange,
|
|
13
|
-
options = [],
|
|
25
|
+
options = [],
|
|
14
26
|
placeholder,
|
|
15
27
|
settings,
|
|
16
28
|
style,
|
|
@@ -19,49 +31,49 @@ function MultiSelect({
|
|
|
19
31
|
}) {
|
|
20
32
|
const [selectOptions, setSelectOptions] = useState([]);
|
|
21
33
|
const [selectValue, setSelectValue] = useState([]);
|
|
22
|
-
const prevInputValueRef = useRef();
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
// Memoize transformed options
|
|
36
|
+
const memoizedOptions = useMemo(() => {
|
|
37
|
+
return options
|
|
38
|
+
.filter((a) => a?.label || a?.name || a?.description) // Filter out options with no label, name, or description
|
|
39
|
+
.map((a) => ({
|
|
40
|
+
value: a?.id,
|
|
41
|
+
label: a?.label || a?.name || a?.description || 'Unknown',
|
|
42
|
+
description: a?.description || '',
|
|
43
|
+
...a,
|
|
44
|
+
}));
|
|
33
45
|
}, [options]);
|
|
34
46
|
|
|
47
|
+
// Memoize transformed input values
|
|
48
|
+
const memoizedInputValue = useMemo(() => {
|
|
49
|
+
const normalizeInputValue = (value) =>
|
|
50
|
+
Array.isArray(value) ? value : value ? [value] : [];
|
|
51
|
+
|
|
52
|
+
return normalizeInputValue(inputValue)
|
|
53
|
+
.filter((a) => a?.label || a?.name || a?.description) // Filter out values with no label, name, or description
|
|
54
|
+
.map((a) => ({
|
|
55
|
+
value: a?.id,
|
|
56
|
+
label: a?.label || a?.name || a?.description || 'Unknown',
|
|
57
|
+
description: a?.description || '',
|
|
58
|
+
...a,
|
|
59
|
+
}));
|
|
60
|
+
}, [inputValue]);
|
|
61
|
+
|
|
62
|
+
// Set options when memoizedOptions changes
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (JSON.stringify(selectOptions) !== JSON.stringify(memoizedOptions)) {
|
|
65
|
+
setSelectOptions(memoizedOptions);
|
|
66
|
+
}
|
|
67
|
+
}, [memoizedOptions, selectOptions]);
|
|
68
|
+
|
|
69
|
+
// Set value when memoizedInputValue changes
|
|
35
70
|
useEffect(() => {
|
|
36
|
-
// Only update if `inputValue` content has changed
|
|
37
71
|
if (
|
|
38
|
-
JSON.stringify(
|
|
39
|
-
JSON.stringify(inputValue)
|
|
72
|
+
JSON.stringify(selectValue) !== JSON.stringify(memoizedInputValue)
|
|
40
73
|
) {
|
|
41
|
-
|
|
42
|
-
? inputValue.map((a) => ({
|
|
43
|
-
value: a.id,
|
|
44
|
-
label: a.label || a.name || a.description || 'Unknown',
|
|
45
|
-
...a,
|
|
46
|
-
}))
|
|
47
|
-
: inputValue && typeof inputValue === 'object'
|
|
48
|
-
? [
|
|
49
|
-
{
|
|
50
|
-
value: inputValue.id,
|
|
51
|
-
label:
|
|
52
|
-
inputValue.label ||
|
|
53
|
-
inputValue.name ||
|
|
54
|
-
inputValue.description ||
|
|
55
|
-
'Unknown',
|
|
56
|
-
...inputValue,
|
|
57
|
-
},
|
|
58
|
-
]
|
|
59
|
-
: [];
|
|
60
|
-
|
|
61
|
-
setSelectValue(_values);
|
|
62
|
-
prevInputValueRef.current = inputValue;
|
|
74
|
+
setSelectValue(memoizedInputValue);
|
|
63
75
|
}
|
|
64
|
-
}, [
|
|
76
|
+
}, [memoizedInputValue, selectValue]);
|
|
65
77
|
|
|
66
78
|
const handleCreate = async (inputValue) => {
|
|
67
79
|
if (creatableConfig.url && creatableConfig.method) {
|
|
@@ -75,11 +87,20 @@ function MultiSelect({
|
|
|
75
87
|
const newOption = {
|
|
76
88
|
value: res.data.id,
|
|
77
89
|
label: res.data.label || inputValue,
|
|
90
|
+
description: res.data.description || 'Newly created item',
|
|
78
91
|
...res.data,
|
|
79
92
|
};
|
|
80
93
|
|
|
81
94
|
setSelectOptions((prevOptions) => [...prevOptions, newOption]);
|
|
82
|
-
setSelectValue((prevValues) =>
|
|
95
|
+
setSelectValue((prevValues) =>
|
|
96
|
+
multi ? [...prevValues, newOption] : [newOption]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
onChange(
|
|
100
|
+
multi ? [...selectValue, newOption] : newOption,
|
|
101
|
+
{ action: 'create-option' },
|
|
102
|
+
settings.id
|
|
103
|
+
);
|
|
83
104
|
}
|
|
84
105
|
}
|
|
85
106
|
};
|
|
@@ -93,7 +114,7 @@ function MultiSelect({
|
|
|
93
114
|
isSearchable
|
|
94
115
|
isMulti={multi}
|
|
95
116
|
filterOption={createFilter({ ignoreAccents: false })}
|
|
96
|
-
components={{
|
|
117
|
+
components={{ Option: CustomOption }}
|
|
97
118
|
options={selectOptions}
|
|
98
119
|
onChange={(inputValue, action) => {
|
|
99
120
|
onChange(inputValue, action, settings.id);
|
|
@@ -115,8 +136,8 @@ function MultiSelect({
|
|
|
115
136
|
}),
|
|
116
137
|
}}
|
|
117
138
|
value={selectValue}
|
|
118
|
-
onCreateOption={handleCreate}
|
|
119
|
-
placeholder={placeholder
|
|
139
|
+
onCreateOption={isCreatable ? handleCreate : undefined}
|
|
140
|
+
placeholder={placeholder || 'Select...'}
|
|
120
141
|
/>
|
|
121
142
|
);
|
|
122
143
|
}
|
|
@@ -1,46 +1,13 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState, useCallback } from 'react';
|
|
2
2
|
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
|
3
3
|
import {
|
|
4
|
-
ArrowCycle,
|
|
5
|
-
BookClose,
|
|
6
|
-
BookOpen,
|
|
7
|
-
Briefcase,
|
|
8
4
|
Bug,
|
|
9
5
|
Calendar,
|
|
10
|
-
ChatDots,
|
|
11
|
-
Clipboard,
|
|
12
|
-
CloudUpload,
|
|
13
|
-
DoubleSword,
|
|
14
6
|
Draft,
|
|
15
|
-
Envelope,
|
|
16
|
-
File,
|
|
17
|
-
Folder,
|
|
18
|
-
FolderAdd,
|
|
19
|
-
Gear,
|
|
20
|
-
Grid,
|
|
21
|
-
Home,
|
|
22
|
-
HomeAlt1,
|
|
23
|
-
Inbox,
|
|
24
|
-
Info,
|
|
25
|
-
LightBulb,
|
|
26
|
-
Microphone,
|
|
27
|
-
Money,
|
|
28
|
-
Newspaper,
|
|
29
|
-
Paper,
|
|
30
|
-
PeopleGroup,
|
|
31
|
-
PeopleMultiple,
|
|
32
7
|
Person,
|
|
33
|
-
Question,
|
|
34
|
-
QuestionFill,
|
|
35
8
|
Search,
|
|
36
|
-
SettingsVertical,
|
|
37
|
-
ShippingBoxV1,
|
|
38
9
|
SignOut,
|
|
39
10
|
Shield,
|
|
40
|
-
StatisticUp,
|
|
41
|
-
TextAlignLeft,
|
|
42
|
-
Ticket,
|
|
43
|
-
Utensils,
|
|
44
11
|
} from 'akar-icons';
|
|
45
12
|
import CustomFetch from './Fetch';
|
|
46
13
|
import Notification from './Notification';
|
|
@@ -236,8 +203,6 @@ function Navigation({
|
|
|
236
203
|
};
|
|
237
204
|
|
|
238
205
|
const renderSetting = (n) => {
|
|
239
|
-
const isActive = location.pathname === n.url; // Check if current path matches setting URL
|
|
240
|
-
|
|
241
206
|
const iconComponents = {
|
|
242
207
|
bug: Bug,
|
|
243
208
|
calendar: Calendar,
|
|
@@ -247,18 +212,15 @@ function Navigation({
|
|
|
247
212
|
signOut: SignOut,
|
|
248
213
|
};
|
|
249
214
|
|
|
250
|
-
const IconComponent = iconComponents[n.icon];
|
|
251
|
-
const settingClasses = isActive ? `${styles.active}` : ''; // Add active class if URLs match
|
|
252
|
-
|
|
253
215
|
if (n.id === 'notifications') {
|
|
254
216
|
return (
|
|
255
|
-
<li
|
|
217
|
+
<li>
|
|
256
218
|
<Notification setSystemAuth={setSystemAuth} />
|
|
257
219
|
</li>
|
|
258
220
|
);
|
|
259
221
|
} else if (n.id === 'switchAccount') {
|
|
260
222
|
return (
|
|
261
|
-
<li
|
|
223
|
+
<li>
|
|
262
224
|
<SwitchAccount
|
|
263
225
|
setSystemAuth={setSystemAuth}
|
|
264
226
|
setting={n}
|
|
@@ -267,8 +229,9 @@ function Navigation({
|
|
|
267
229
|
</li>
|
|
268
230
|
);
|
|
269
231
|
} else if (n.id === 'logout') {
|
|
232
|
+
const IconComponent = iconComponents[n.icon];
|
|
270
233
|
return (
|
|
271
|
-
<li
|
|
234
|
+
<li>
|
|
272
235
|
<button
|
|
273
236
|
title={n.label}
|
|
274
237
|
data-tooltip-id="system-tooltip"
|
|
@@ -280,8 +243,10 @@ function Navigation({
|
|
|
280
243
|
</li>
|
|
281
244
|
);
|
|
282
245
|
} else {
|
|
246
|
+
const IconComponent = iconComponents[n.icon];
|
|
247
|
+
|
|
283
248
|
return (
|
|
284
|
-
<li
|
|
249
|
+
<li>
|
|
285
250
|
<Link
|
|
286
251
|
to={n.url}
|
|
287
252
|
data-tooltip-id="system-tooltip"
|
|
@@ -297,48 +262,6 @@ function Navigation({
|
|
|
297
262
|
};
|
|
298
263
|
|
|
299
264
|
const renderNav = (n) => {
|
|
300
|
-
const iconComponents = {
|
|
301
|
-
arrowCycle: ArrowCycle,
|
|
302
|
-
bookClose: BookClose,
|
|
303
|
-
bookOpen: BookOpen,
|
|
304
|
-
briefcase: Briefcase,
|
|
305
|
-
calendar: Calendar,
|
|
306
|
-
chatDots: ChatDots,
|
|
307
|
-
clipboard: Clipboard,
|
|
308
|
-
cloudUpload: CloudUpload,
|
|
309
|
-
doubleSword: DoubleSword,
|
|
310
|
-
draft: Draft,
|
|
311
|
-
envelope: Envelope,
|
|
312
|
-
file: File,
|
|
313
|
-
folder: Folder,
|
|
314
|
-
folderAdd: FolderAdd,
|
|
315
|
-
gear: Gear,
|
|
316
|
-
grid: Grid,
|
|
317
|
-
home: Home,
|
|
318
|
-
homeAlt1: HomeAlt1,
|
|
319
|
-
inbox: Inbox,
|
|
320
|
-
info: Info,
|
|
321
|
-
lightBulb: LightBulb,
|
|
322
|
-
microphone: Microphone,
|
|
323
|
-
money: Money,
|
|
324
|
-
newspaper: Newspaper,
|
|
325
|
-
paper: Paper,
|
|
326
|
-
peopleGroup: PeopleGroup,
|
|
327
|
-
peopleMultiple: PeopleMultiple,
|
|
328
|
-
question: Question,
|
|
329
|
-
questionFill: QuestionFill,
|
|
330
|
-
search: Search,
|
|
331
|
-
settingsVertical: SettingsVertical,
|
|
332
|
-
signOut: SignOut,
|
|
333
|
-
shippingBoxV1: ShippingBoxV1,
|
|
334
|
-
statisticUp: StatisticUp,
|
|
335
|
-
textAlignLeft: TextAlignLeft,
|
|
336
|
-
ticket: Ticket,
|
|
337
|
-
utensils: Utensils,
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
const IconComponent = iconComponents[n.icon];
|
|
341
|
-
|
|
342
265
|
let navItemClasses;
|
|
343
266
|
|
|
344
267
|
if (n.class.includes('active')) {
|
|
@@ -379,15 +302,9 @@ function Navigation({
|
|
|
379
302
|
return (
|
|
380
303
|
<li className={navItemClasses}>
|
|
381
304
|
{n.url ? (
|
|
382
|
-
<Link to={n.url}>
|
|
383
|
-
<IconComponent strokeWidth={2} size={18} />
|
|
384
|
-
{n.label}
|
|
385
|
-
</Link>
|
|
305
|
+
<Link to={n.url}>{n.label}</Link>
|
|
386
306
|
) : (
|
|
387
|
-
<span title={n.label}>
|
|
388
|
-
<IconComponent strokeWidth={2} size={18} />
|
|
389
|
-
{n.label}
|
|
390
|
-
</span>
|
|
307
|
+
<span title={n.label}>{n.label}</span>
|
|
391
308
|
)}
|
|
392
309
|
{renderChildren()}
|
|
393
310
|
</li>
|
|
@@ -28,7 +28,15 @@ const Login = ({ logo, providers, setSystemAuth, setUserProfile }) => {
|
|
|
28
28
|
let content =
|
|
29
29
|
providers && providers.length > 0 ? (
|
|
30
30
|
<div className="formItem fwItem lastItem forgotten">
|
|
31
|
-
<span
|
|
31
|
+
<span
|
|
32
|
+
style={{
|
|
33
|
+
display: 'block',
|
|
34
|
+
textAlign: 'center',
|
|
35
|
+
width: '100%',
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
OR
|
|
39
|
+
</span>
|
|
32
40
|
</div>
|
|
33
41
|
) : null;
|
|
34
42
|
|
|
@@ -101,10 +101,12 @@ const Profile = ({ userProfile, setUserProfile }) => {
|
|
|
101
101
|
payload
|
|
102
102
|
);
|
|
103
103
|
|
|
104
|
+
const updatedUserData = res.data.user ? res.data.user : res.data;
|
|
105
|
+
|
|
104
106
|
setUserProfile((prevState) => ({
|
|
105
107
|
...prevState,
|
|
106
|
-
name:
|
|
107
|
-
signature:
|
|
108
|
+
name: updatedUserData.name,
|
|
109
|
+
signature: updatedUserData.signature,
|
|
108
110
|
}));
|
|
109
111
|
toast.success('Your profile has been successfully updated.');
|
|
110
112
|
} catch (err) {
|