@visns-studio/visns-components 1.4.8 → 1.4.10

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.
@@ -12,6 +12,7 @@ import DateFilter from "@inovua/reactdatagrid-community/DateFilter";
12
12
  import ReactDataGrid from "@inovua/reactdatagrid-community";
13
13
  import { confirmAlert } from "react-confirm-alert";
14
14
  import { toast } from "react-toastify";
15
+ import Toggle from "react-toggle";
15
16
  import {
16
17
  Backspace,
17
18
  Check,
@@ -25,11 +26,14 @@ import {
25
26
  Ribbon,
26
27
  Search,
27
28
  ShippingBoxV1,
29
+ ToggleOff,
30
+ ToggleOnFill,
28
31
  TriangleAlert,
29
32
  } from "akar-icons";
30
33
 
31
34
  import "@inovua/reactdatagrid-community/index.css";
32
35
  import "react-confirm-alert/src/react-confirm-alert.css";
36
+ import "react-toggle/style.css";
33
37
 
34
38
  import CustomFetch from "../crm/visns-fetch";
35
39
  import Form from "./visns-form";
@@ -246,7 +250,11 @@ const DataGrid = ({
246
250
  };
247
251
 
248
252
  const handleReload = () => {
249
- setDataReload(dataReload + 1);
253
+ const min = 0;
254
+ const max = 999999999;
255
+ const randomNumber = Math.floor(Math.random() * (max - min + 1) + min);
256
+
257
+ setDataReload(randomNumber);
250
258
  };
251
259
 
252
260
  const onRowClick = useCallback((rowProps, event) => {
@@ -255,30 +263,45 @@ const DataGrid = ({
255
263
  cellElement
256
264
  );
257
265
 
258
- if (
259
- rowProps.columns[columnIndex].link &&
260
- rowProps.columns[columnIndex].link.url
261
- ) {
262
- if (rowProps.columns[columnIndex].link.folder) {
263
- window.location.href =
264
- rowProps.columns[columnIndex].link.url +
265
- rowProps.data[rowProps.columns[columnIndex].link.key] +
266
- "/" +
267
- rowProps.columns[columnIndex].link.folder;
266
+ let proceed = true;
267
+
268
+ columns.forEach((a, b) => {
269
+ if (
270
+ a.id === rowProps.columns[columnIndex].id &&
271
+ a.type === "toggle"
272
+ ) {
273
+ proceed = false;
274
+ }
275
+ });
276
+
277
+ if (proceed) {
278
+ if (
279
+ rowProps.columns[columnIndex].link &&
280
+ rowProps.columns[columnIndex].link.url
281
+ ) {
282
+ if (rowProps.columns[columnIndex].link.folder) {
283
+ window.location.href =
284
+ rowProps.columns[columnIndex].link.url +
285
+ rowProps.data[rowProps.columns[columnIndex].link.key] +
286
+ "/" +
287
+ rowProps.columns[columnIndex].link.folder;
288
+ } else {
289
+ navigate(
290
+ `${rowProps.columns[columnIndex].link.url}${
291
+ rowProps.data[
292
+ rowProps.columns[columnIndex].link.key
293
+ ]
294
+ }`,
295
+ {
296
+ state: {
297
+ form: form,
298
+ },
299
+ }
300
+ );
301
+ }
268
302
  } else {
269
- navigate(
270
- `${rowProps.columns[columnIndex].link.url}${
271
- rowProps.data[rowProps.columns[columnIndex].link.key]
272
- }`,
273
- {
274
- state: {
275
- form: form,
276
- },
277
- }
278
- );
303
+ modalOpen("update", rowProps.data[form.primaryKey]);
279
304
  }
280
- } else {
281
- modalOpen("update", rowProps.data[form.primaryKey]);
282
305
  }
283
306
  }, []);
284
307
 
@@ -544,7 +567,13 @@ const DataGrid = ({
544
567
  filterEditor: filterEditor,
545
568
  filterEditorProps: filterEditorProps,
546
569
  render: ({ data }) => {
547
- if (data && data[column.id]) {
570
+ if (
571
+ data &&
572
+ data[column.id] &&
573
+ moment(data[column.id]).isValid() &&
574
+ moment(data[column.id]).format("YYYY-MM-DD") !==
575
+ "1970-01-01"
576
+ ) {
548
577
  const value = moment(data[column.id]).format(
549
578
  column.format || "DD-MM-YYYY"
550
579
  );
@@ -593,7 +622,13 @@ const DataGrid = ({
593
622
  filterEditor: filterEditor,
594
623
  filterEditorProps: filterEditorProps,
595
624
  render: ({ data }) => {
596
- if (data && data[column.id]) {
625
+ if (
626
+ data &&
627
+ data[column.id] &&
628
+ moment(data[column.id]).isValid() &&
629
+ moment(data[column.id]).format("YYYY-MM-DD") !==
630
+ "1970-01-01"
631
+ ) {
597
632
  data = moment(data[column.id]).format(
598
633
  column.format
599
634
  ? column.format
@@ -986,7 +1021,13 @@ const DataGrid = ({
986
1021
  ...commonProps,
987
1022
  name: column.id,
988
1023
  render: ({ data }) => {
989
- if (data && data[column.id]) {
1024
+ if (
1025
+ data &&
1026
+ data[column.id] &&
1027
+ moment(data[column.id]).isValid() &&
1028
+ moment(data[column.id]).format("YYYY-MM-DD") !==
1029
+ "1970-01-01"
1030
+ ) {
990
1031
  data = moment(data[column.id]).format(
991
1032
  column.format ? column.format : "hh:mm A"
992
1033
  );
@@ -997,6 +1038,40 @@ const DataGrid = ({
997
1038
  }
998
1039
  },
999
1040
  };
1041
+ case "toggle":
1042
+ return {
1043
+ ...commonProps,
1044
+ name: column.id,
1045
+ render: ({ data }) => {
1046
+ return (
1047
+ <Toggle
1048
+ name={column.id}
1049
+ checked={
1050
+ data[column.id] === 1 ? true : false
1051
+ }
1052
+ onChange={() => {
1053
+ CustomFetch(
1054
+ `/ajax/projects/toggleFeature/${data.id}`,
1055
+ "POST",
1056
+ {
1057
+ [column.id]:
1058
+ data[column.id] === 1
1059
+ ? 0
1060
+ : 1,
1061
+ },
1062
+ (res) => {
1063
+ if (res.error === "") {
1064
+ handleReload();
1065
+ } else {
1066
+ toast.error(res.error);
1067
+ }
1068
+ }
1069
+ );
1070
+ }}
1071
+ />
1072
+ );
1073
+ },
1074
+ };
1000
1075
  case "url":
1001
1076
  return {
1002
1077
  ...commonProps,
@@ -13,23 +13,53 @@ import "react-toggle/style.css";
13
13
  import "react-quill/dist/quill.snow.css";
14
14
  import "react-datepicker/dist/react-datepicker.css";
15
15
 
16
- function Field(props) {
16
+ const Field = ({
17
+ settings,
18
+ inputValue,
19
+ inputClass,
20
+ onChange,
21
+ onChangeFile,
22
+ onChangeRicheditor,
23
+ onChangeSelect,
24
+ onChangeToggle,
25
+ setFormData,
26
+ uploadProgress,
27
+ }) => {
28
+ const quillFileInputRef = useRef(null);
29
+ const quillRef = useRef(null);
17
30
  const inputFile = useRef(null);
18
31
  const [options, setOptions] = useState([]);
19
32
  const [dataOptions, setDataOptions] = useState([]);
20
33
  const [formItemStyle, setFormItemStyle] = useState({});
21
34
  const [formItemClass, setFormItemClass] = useState("formItem");
22
- const {
23
- settings,
24
- inputValue,
25
- inputClass,
26
- onChange,
27
- onChangeFile,
28
- onChangeRicheditor,
29
- onChangeSelect,
30
- setFormData,
31
- uploadProgress,
32
- } = props;
35
+ const modules = {
36
+ toolbar: {
37
+ container: [
38
+ [{ header: [1, 2, false] }],
39
+ ["bold", "italic", "underline", "strike", "blockquote"],
40
+ [{ list: "ordered" }, { list: "bullet" }],
41
+ ["link", "image"],
42
+ ["clean"],
43
+ ],
44
+ },
45
+ };
46
+
47
+ const handleImageUpload = async (e) => {
48
+ try {
49
+ const file = e.target.files[0];
50
+ const reader = new FileReader();
51
+
52
+ reader.onload = () => {
53
+ const dataUrl = reader.result;
54
+ const range = quillRef.getEditor().getSelection();
55
+ quillRef.getEditor().insertEmbed(range.index, "image", dataUrl);
56
+ };
57
+
58
+ reader.readAsDataURL(file);
59
+ } catch (error) {
60
+ console.error("Error uploading image:", error);
61
+ }
62
+ };
33
63
 
34
64
  useEffect(() => {
35
65
  switch (settings.type) {
@@ -579,7 +609,7 @@ function Field(props) {
579
609
  ? false
580
610
  : inputValue === "on"
581
611
  ? false
582
- : inputValue
612
+ : Boolean(inputValue)
583
613
  : false
584
614
  }
585
615
  onChange={onChangeToggle}
@@ -593,14 +623,35 @@ function Field(props) {
593
623
  break;
594
624
  case "richeditor":
595
625
  htmlContainer = (
596
- <ReactQuill
597
- theme="snow"
598
- name={settings.id}
599
- onChange={(value) => {
600
- onChangeRicheditor(value, settings.id);
601
- }}
602
- value={inputValue || ""}
603
- />
626
+ <>
627
+ <input
628
+ type="file"
629
+ style={{ display: "none" }}
630
+ ref={quillFileInputRef}
631
+ onChange={handleImageUpload}
632
+ />
633
+ <ReactQuill
634
+ theme="snow"
635
+ name={settings.id}
636
+ onChange={(value) => {
637
+ onChangeRicheditor(value, settings.id);
638
+ }}
639
+ value={inputValue || ""}
640
+ modules={modules}
641
+ formats={[
642
+ "header",
643
+ "bold",
644
+ "italic",
645
+ "underline",
646
+ "strike",
647
+ "blockquote",
648
+ "list",
649
+ "bullet",
650
+ "link",
651
+ "image",
652
+ ]}
653
+ />
654
+ </>
604
655
  );
605
656
  break;
606
657
  case "image":
@@ -668,6 +719,6 @@ function Field(props) {
668
719
  })()}
669
720
  </div>
670
721
  );
671
- }
722
+ };
672
723
 
673
724
  export default Field;
@@ -34,6 +34,17 @@ function Form(props) {
34
34
  [name]: value,
35
35
  }));
36
36
 
37
+ setData((prevState) => ({
38
+ ...prevState,
39
+ slug: slugify(value),
40
+ }));
41
+ break;
42
+ case "name":
43
+ setData((prevState) => ({
44
+ ...prevState,
45
+ [name]: value,
46
+ }));
47
+
37
48
  setData((prevState) => ({
38
49
  ...prevState,
39
50
  slug: slugify(value),
@@ -72,6 +83,19 @@ function Form(props) {
72
83
  }));
73
84
  };
74
85
 
86
+ const handleChangeToggle = (e) => {
87
+ if (!e) {
88
+ return;
89
+ }
90
+
91
+ const { name, checked } = e.target;
92
+
93
+ setData((prevState) => ({
94
+ ...prevState,
95
+ [name]: checked,
96
+ }));
97
+ };
98
+
75
99
  const handleChangeFile = (e) => {
76
100
  if (e) {
77
101
  setData((prevState) => ({
@@ -337,7 +361,13 @@ function Form(props) {
337
361
  <div className="grid">
338
362
  <div className="grid__row">
339
363
  <div className="grid__full cmstitle">
340
- <h1>{data.title ? data.title : form.update.title}</h1>
364
+ <h1>
365
+ {data.title
366
+ ? data.title
367
+ : dataId !== "create"
368
+ ? form.update.title
369
+ : form.create.title}
370
+ </h1>
341
371
  <div className="cmstitle__actions">
342
372
  <button
343
373
  className="btn actionbtn"
@@ -379,6 +409,7 @@ function Form(props) {
379
409
  onChangeFile={handleChangeFile}
380
410
  onChangeRicheditor={handleChangeRicheditor}
381
411
  onChangeSelect={handleChangeSelect}
412
+ onChangeToggle={handleChangeToggle}
382
413
  setFormData={setData}
383
414
  uploadProgress={uploadProgress}
384
415
  />
@@ -4,7 +4,8 @@ import AwesomeDebouncePromise from "awesome-debounce-promise";
4
4
  import { ToggleOffFill, ToggleOnFill } from "akar-icons";
5
5
 
6
6
  const VisnsAutocomplete = (props) => {
7
- const { api, country, onSelect, setFormData, field, inputValue } = props;
7
+ const { api, country, field, inputValue, onSelect, setFormData, style } =
8
+ props;
8
9
  const [search, setSearch] = useState("");
9
10
  const [results, setResults] = useState([]);
10
11
  const [isLoading, setIsLoading] = useState(false);
@@ -18,8 +19,8 @@ const VisnsAutocomplete = (props) => {
18
19
  } else {
19
20
  let url = `https://api.mapbox.com/geocoding/v5/mapbox.places/${value}.json?types=address,poi&access_token=${api}`;
20
21
 
21
- if (import.meta.env.VITE_MAPBOX_COUNTRY) {
22
- url += `&country=${import.meta.env.VITE_MAPBOX_COUNTRY}`;
22
+ if (country) {
23
+ url += `&country=${country}`;
23
24
  }
24
25
 
25
26
  if (import.meta.env.hasOwnProperty("VITE_MAPBOX_PROXIMITY")) {
@@ -95,7 +96,12 @@ const VisnsAutocomplete = (props) => {
95
96
  <div className="AutocompletePlace">
96
97
  <input
97
98
  className="AutocompletePlace-input"
98
- style={{ height: "53px" }}
99
+ style={{
100
+ height:
101
+ style && style.multi_select_height
102
+ ? style.multi_select_height
103
+ : "52px",
104
+ }}
99
105
  type="text"
100
106
  value={search || ""}
101
107
  onChange={handleSearchChange}
@@ -270,7 +270,13 @@ const DataGrid = forwardRef(
270
270
  };
271
271
 
272
272
  const handleReload = () => {
273
- setDataReload(dataReload + 1);
273
+ const min = 0;
274
+ const max = 999999999;
275
+ const randomNumber = Math.floor(
276
+ Math.random() * (max - min + 1) + min
277
+ );
278
+
279
+ setDataReload(randomNumber);
274
280
  };
275
281
 
276
282
  const onRowClick = useCallback((rowProps, event) => {
@@ -429,7 +435,7 @@ const DataGrid = forwardRef(
429
435
  }
430
436
  };
431
437
 
432
- c.config.forEach((config) => {
438
+ c.config.forEach((config, configKey) => {
433
439
  const fieldValue = config.id.reduce((acc, id) => {
434
440
  if (acc === "") {
435
441
  return data[id];
@@ -453,7 +459,7 @@ const DataGrid = forwardRef(
453
459
  iconData.icon ? iconData.icon : null,
454
460
  iconData.alt,
455
461
  iconData.tooltipContent,
456
- `coding-${config.id[0]}`
462
+ `coding-${config.id[0]}-${configKey}`
457
463
  );
458
464
  }
459
465
  });
@@ -609,8 +615,23 @@ const DataGrid = forwardRef(
609
615
  },
610
616
  };
611
617
  case "age":
618
+ if (column.filter && column.filter.type) {
619
+ switch (column.filter.type) {
620
+ case "number":
621
+ filterEditor = NumberFilter;
622
+ break;
623
+ default:
624
+ filterEditor = null;
625
+ break;
626
+ }
627
+ } else {
628
+ filterEditor = null;
629
+ }
630
+
612
631
  return {
613
632
  ...commonProps,
633
+ type: "number",
634
+ filterEditor: filterEditor,
614
635
  name: `${column.type}.${column.id}`,
615
636
  render: ({ data }) => {
616
637
  value = column.id.reduce((acc, id) => {
@@ -655,7 +676,7 @@ const DataGrid = forwardRef(
655
676
  case "coding":
656
677
  return {
657
678
  ...commonProps,
658
- name: "audits.name",
679
+ name: `${column.type}.${column.id}`,
659
680
  sortable: false,
660
681
  render: ({ data }) => {
661
682
  if (data) {
@@ -668,7 +689,7 @@ const DataGrid = forwardRef(
668
689
  case "created_by":
669
690
  return {
670
691
  ...commonProps,
671
- name: "audits.name",
692
+ name: `${column.type}.${column.id}`,
672
693
  sortable: false,
673
694
  render: ({ data }) => {
674
695
  if (
@@ -720,7 +741,14 @@ const DataGrid = forwardRef(
720
741
  filterEditor: filterEditor,
721
742
  filterEditorProps: filterEditorProps,
722
743
  render: ({ data }) => {
723
- if (data && data[column.id]) {
744
+ if (
745
+ data &&
746
+ data[column.id] &&
747
+ moment(data[column.id]).isValid() &&
748
+ moment(data[column.id]).format(
749
+ "YYYY-MM-DD"
750
+ ) !== "1970-01-01"
751
+ ) {
724
752
  const value = moment(
725
753
  data[column.id]
726
754
  ).format(column.format || "DD-MM-YYYY");
@@ -769,7 +797,14 @@ const DataGrid = forwardRef(
769
797
  filterEditor: filterEditor,
770
798
  filterEditorProps: filterEditorProps,
771
799
  render: ({ data }) => {
772
- if (data && data[column.id]) {
800
+ if (
801
+ data &&
802
+ data[column.id] &&
803
+ moment(data[column.id]).isValid() &&
804
+ moment(data[column.id]).format(
805
+ "YYYY-MM-DD"
806
+ ) !== "1970-01-01"
807
+ ) {
773
808
  data = moment(data[column.id]).format(
774
809
  column.format
775
810
  ? column.format
@@ -1186,7 +1221,14 @@ const DataGrid = forwardRef(
1186
1221
  ...commonProps,
1187
1222
  name: column.id,
1188
1223
  render: ({ data }) => {
1189
- if (data && data[column.id]) {
1224
+ if (
1225
+ data &&
1226
+ data[column.id] &&
1227
+ moment(data[column.id]).isValid() &&
1228
+ moment(data[column.id]).format(
1229
+ "YYYY-MM-DD"
1230
+ ) !== "1970-01-01"
1231
+ ) {
1190
1232
  data = moment(data[column.id]).format(
1191
1233
  column.format
1192
1234
  ? column.format
@@ -1445,6 +1487,7 @@ const DataGrid = forwardRef(
1445
1487
  updateForm={setFormData}
1446
1488
  columnId={formId}
1447
1489
  childDropdownCallback={childDropdownCallback}
1490
+ style={style}
1448
1491
  />
1449
1492
  </Popup>
1450
1493
  </>
@@ -15,25 +15,25 @@ import "react-toggle/style.css";
15
15
  import "react-quill/dist/quill.snow.css";
16
16
  import "react-datepicker/dist/react-datepicker.css";
17
17
 
18
- function Field(props) {
18
+ function Field({
19
+ childDropdownCallback,
20
+ inputValue,
21
+ inputClass,
22
+ onChange,
23
+ onChangeDate,
24
+ onChangeSelect,
25
+ onChangeRicheditor,
26
+ onChangeToggle,
27
+ onChangeNumberFormat,
28
+ autocompleteCallback,
29
+ setFormData,
30
+ settings,
31
+ style,
32
+ }) {
19
33
  const [options, setOptions] = useState([]);
20
34
  const [dataOptions, setDataOptions] = useState([]);
21
35
  const [formItemStyle, setFormItemStyle] = useState({});
22
36
  const [formItemClass, setFormItemClass] = useState("formItem");
23
- const {
24
- settings,
25
- inputValue,
26
- inputClass,
27
- childDropdownCallback,
28
- onChange,
29
- onChangeDate,
30
- onChangeSelect,
31
- onChangeRicheditor,
32
- onChangeToggle,
33
- onChangeNumberFormat,
34
- autocompleteCallback,
35
- setFormData,
36
- } = props;
37
37
 
38
38
  useEffect(() => {
39
39
  switch (settings.type) {
@@ -426,14 +426,13 @@ function Field(props) {
426
426
  case "address":
427
427
  htmlContainer = (
428
428
  <VisnsAutocomplete
429
- onSelect={(place) =>
430
- autocompleteCallback(place)
431
- }
432
- field={settings.id}
433
- setFormData={setFormData}
434
429
  api="pk.eyJ1IjoidmlzbnMtc3R1ZGlvIiwiYSI6ImNrbGlraW5vZDBhMDYycHBsdmk5b3ljbGQifQ.ZGUBk0PWac5GahUeVHdTpg"
435
- inputValue={inputValue}
436
430
  country="AU"
431
+ field={settings.id}
432
+ inputValue={inputValue}
433
+ onSelect={autocompleteCallback}
434
+ setFormData={setFormData}
435
+ style={style}
437
436
  />
438
437
  );
439
438
  break;
@@ -481,6 +480,7 @@ function Field(props) {
481
480
  }
482
481
  options={settings.options}
483
482
  dataOptions={dataOptions}
483
+ style={style}
484
484
  />
485
485
  );
486
486
  break;
@@ -500,6 +500,7 @@ function Field(props) {
500
500
  }
501
501
  options={options}
502
502
  dataOptions={dataOptions}
503
+ style={style}
503
504
  />
504
505
  );
505
506
  break;
@@ -612,6 +613,7 @@ function Field(props) {
612
613
  ? settings.format
613
614
  : "dd-MM-yyyy"
614
615
  }
616
+ isClearable
615
617
  className={inputClass[settings.id]}
616
618
  selected={inputValue || ""}
617
619
  showMonthDropdown
@@ -631,6 +633,7 @@ function Field(props) {
631
633
  ? settings.format
632
634
  : "dd-MM-yyyy hh:mm aa"
633
635
  }
636
+ isClearable
634
637
  showTimeSelect
635
638
  className={inputClass[settings.id]}
636
639
  selected={inputValue || null}
@@ -652,6 +655,7 @@ function Field(props) {
652
655
  ? settings.format
653
656
  : "hh:mm aa"
654
657
  }
658
+ isClearable
655
659
  showTimeSelect
656
660
  showTimeSelectOnly
657
661
  timeIntervals={15}