aefis-core-ui 2.2.1-rc1 → 2.2.1-rc3

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.
@@ -67,13 +67,13 @@ import 'lodash/camelCase';
67
67
  import debounce from 'lodash/debounce';
68
68
  import StepConnector, { stepConnectorClasses } from '@mui/material/StepConnector';
69
69
  import { MuiForm5 } from '@rjsf/material-ui';
70
+ import isEmpty from 'lodash/isEmpty';
70
71
  import compose from 'lodash/fp/compose';
71
72
  import Chip$2 from '@mui/material/Chip';
72
73
  import TextField$2 from '@mui/material/TextField';
73
74
  import { useFormControl } from '@mui/material/FormControl';
74
75
  import get$1 from 'lodash/get';
75
76
  import isPlainObject from 'lodash/isPlainObject';
76
- import isEmpty from 'lodash/isEmpty';
77
77
  import ToggleButton$1 from '@mui/material/ToggleButton';
78
78
  import { parse as parse$1, format as format$1, setDate, setMonth } from 'date-fns';
79
79
  import { MobileDatePicker as MobileDatePicker$1 } from '@mui/x-date-pickers/MobileDatePicker';
@@ -727,7 +727,7 @@ const DismissableAlert = props => {
727
727
  const [open, setOpen] = useState(true);
728
728
  const handleClick = () => {
729
729
  setOpen(false);
730
- props.onDismiss && props.onDismiss();
730
+ props.onDismiss == null ? void 0 : props.onDismiss();
731
731
  };
732
732
  return /*#__PURE__*/jsx(Collapse, {
733
733
  in: open,
@@ -747,7 +747,12 @@ const DismissableAlert = props => {
747
747
  }),
748
748
  children: [props.title && /*#__PURE__*/jsx(AlertTitle, {
749
749
  children: props.title
750
- }), props.description]
750
+ }), /*#__PURE__*/jsx(Box$1, {
751
+ sx: {
752
+ paddingRight: 0.5
753
+ },
754
+ children: props.description
755
+ })]
751
756
  }))
752
757
  });
753
758
  };
@@ -807,7 +812,12 @@ const Alert = /*#__PURE__*/forwardRef(function Alert(props, ref) {
807
812
  role: props.role,
808
813
  children: [props.title && /*#__PURE__*/jsx(AlertTitle, {
809
814
  children: props.title
810
- }), props.description]
815
+ }), /*#__PURE__*/jsx(Box$1, {
816
+ sx: {
817
+ paddingRight: 0.5
818
+ },
819
+ children: props.description
820
+ })]
811
821
  }))
812
822
  });
813
823
  });
@@ -8085,30 +8095,35 @@ const FilterChips = ({
8085
8095
  if (_filters.length === 0 && _sort.length === 0) return /*#__PURE__*/jsx("div", {
8086
8096
  children: "No filters or sorting criteria selected"
8087
8097
  });
8088
- const Filters = useMemo(() => /*#__PURE__*/jsx(Fragment, {
8089
- children: _filters.map(filter => /*#__PURE__*/jsx(Grow, {
8090
- in: true,
8091
- children: /*#__PURE__*/jsx("div", {
8092
- style: {
8093
- margin: 2,
8094
- display: "inline-flex"
8095
- },
8096
- children: /*#__PURE__*/jsx(BusinessObject, {
8097
- variant: "chip",
8098
- size: "small",
8099
- displayOptions: {
8100
- hasIcon: filter.type !== "keyword"
8098
+ const Filters = useMemo(() => {
8099
+ return /*#__PURE__*/jsx(Box$1, {
8100
+ sx: {
8101
+ display: "flex"
8102
+ },
8103
+ children: _filters.map(filter => /*#__PURE__*/jsx(Grow, {
8104
+ in: true,
8105
+ children: /*#__PURE__*/jsx("div", {
8106
+ style: {
8107
+ margin: 2,
8108
+ display: "inline-flex"
8101
8109
  },
8102
- type: filter.type || "businessObject",
8103
- template: filter.template,
8104
- data: filter.data,
8105
- onDelete: () => {
8106
- onFilterDelete(filter);
8107
- }
8108
- }, filter.data.id)
8109
- })
8110
- }, `filterPanelFilter-${filter.index}-${filter.id}`))
8111
- }), [_filters]);
8110
+ children: /*#__PURE__*/jsx(BusinessObject, {
8111
+ variant: "chip",
8112
+ size: "small",
8113
+ displayOptions: {
8114
+ hasIcon: filter.type !== "keyword"
8115
+ },
8116
+ type: "businessObject",
8117
+ template: filter.template,
8118
+ data: filter.data,
8119
+ onDelete: () => {
8120
+ onFilterDelete(filter);
8121
+ }
8122
+ }, filter.data.id)
8123
+ })
8124
+ }, `filterPanelFilter-${filter.index}-${filter.id}`))
8125
+ });
8126
+ }, [_filters]);
8112
8127
  const SortItems = useMemo(() => /*#__PURE__*/jsx(Fragment, {
8113
8128
  children: _sort.map(sortItem => /*#__PURE__*/jsx(Grow, {
8114
8129
  in: true,
@@ -8195,7 +8210,7 @@ const FilterSelection = ({
8195
8210
  children: "Apply All Filters"
8196
8211
  }), /*#__PURE__*/jsx(Button, {
8197
8212
  name: "reset all filters",
8198
- disabled: !(filters.length > 0),
8213
+ disabled: !(filters.length > 0 || sort.length > 0),
8199
8214
  variant: "contained",
8200
8215
  color: "grey",
8201
8216
  onClick: onResetFilters,
@@ -8377,6 +8392,7 @@ const FilterPanel = props => {
8377
8392
  const [menuPosition, setMenuPosition] = useState(null);
8378
8393
  const [filters, setFilters] = useState([]);
8379
8394
  const [sort, setSort] = useState(sortProp || []);
8395
+ const [panelSearch, setPanelSearch] = useState([]);
8380
8396
  const [pickerFilters, setPickerFilters] = useState([]);
8381
8397
  useEffect(() => {
8382
8398
  const formattedFilters = formatFilters(filtersProp, configuration);
@@ -8408,6 +8424,7 @@ const FilterPanel = props => {
8408
8424
  }
8409
8425
  }, [filters, sort]);
8410
8426
  const removeFilter = filter => {
8427
+ console.log("remove filter ", filter);
8411
8428
  const newFilterArray = filters == null ? void 0 : filters.filter(i => i.index !== filter.index || filter.id !== i.id);
8412
8429
  setFilters(newFilterArray);
8413
8430
  if (!onApplyFilters) {
@@ -8528,6 +8545,8 @@ const FilterPanel = props => {
8528
8545
  const handleResetFilters = () => {
8529
8546
  setPickerFilters([]);
8530
8547
  setFilters([]);
8548
+ setSort([]);
8549
+ setPanelSearch([]);
8531
8550
  if (!onChange && onApplyFilters) {
8532
8551
  onApplyFilters({}, []);
8533
8552
  }
@@ -8536,6 +8555,8 @@ const FilterPanel = props => {
8536
8555
  }
8537
8556
  };
8538
8557
  const handleSearchChange = keyword => {
8558
+ if (panelSearch.includes(keyword)) return;
8559
+ setPanelSearch([...panelSearch, keyword]);
8539
8560
  addFilter({
8540
8561
  index: -1,
8541
8562
  type: "keyword",
@@ -10469,6 +10490,15 @@ const useIsError = status => {
10469
10490
  }, [status]);
10470
10491
  return isError;
10471
10492
  };
10493
+ const initialFilterState = {
10494
+ filter: {},
10495
+ searchText: "",
10496
+ filterArray: [],
10497
+ filterCount: 0,
10498
+ sort: [],
10499
+ sortCount: 0,
10500
+ sortQueryParams: null
10501
+ };
10472
10502
  const RichDataTable = /*#__PURE__*/forwardRef(function RichDatatable(props, ref) {
10473
10503
  var _props$filterPanelCon, _props$rowActions, _props$dataTableProps, _props$dataTableProps2;
10474
10504
  const didMount = useDidMount();
@@ -10494,15 +10524,8 @@ const RichDataTable = /*#__PURE__*/forwardRef(function RichDatatable(props, ref)
10494
10524
  const [formatDrawerContent, setFormatDrawerContent] = useState(false);
10495
10525
  const [enableTableRowAction, setEnableTableRowAction] = useState(false);
10496
10526
  const [selectedRowCount, setSelectedRowCount] = useState(0);
10497
- const [filterPanelState, setFilterPanelState] = useState({
10498
- filter: {},
10499
- searchText: "",
10500
- filterArray: [],
10501
- filterCount: 0,
10502
- sort: [],
10503
- sortCount: 0,
10504
- sortQueryParams: null
10505
- });
10527
+ const [filterPanelState, setFilterPanelState] = useState(initialFilterState);
10528
+ console.log("filterPanelState ", filterPanelState);
10506
10529
  const {
10507
10530
  info,
10508
10531
  error
@@ -10625,6 +10648,15 @@ const RichDataTable = /*#__PURE__*/forwardRef(function RichDatatable(props, ref)
10625
10648
  };
10626
10649
  const handleFilterChange = (filters, newFilterArray) => {
10627
10650
  props == null ? void 0 : props.onFilterChange == null ? void 0 : props.onFilterChange(filters);
10651
+
10652
+ // TODO: apply better approach by gathering handling of all search and
10653
+ // filter changes with onChange; also send operation type to onChange
10654
+ // events
10655
+ const isReset = newFilterArray.length === 0;
10656
+ if (isReset) {
10657
+ setFilterPanelState(() => _extends({}, initialFilterState));
10658
+ return;
10659
+ }
10628
10660
  setFilterPanelState(prev => _extends({}, prev, {
10629
10661
  filterCount: Object.keys(filters).length,
10630
10662
  filter: filters,
@@ -10719,7 +10751,7 @@ const RichDataTable = /*#__PURE__*/forwardRef(function RichDatatable(props, ref)
10719
10751
  exportOptions: props.exportOptions,
10720
10752
  actions: props.actions && props.actions.length > 0 || props.addAction ? updateActions(props.actions, handleDrawerOpen, enableTableRowAction, selectedRowCount, Add) : undefined,
10721
10753
  onFilterClick: isFilterPanelEnabled ? handleFilterClick : undefined,
10722
- hasFilters: filterPanelState.filterCount > 0 || filterPanelState.sortCount > 0,
10754
+ hasFilters: filterPanelState.filterCount > 0 || filterPanelState.sortCount > 0 || filterPanelState.searchText,
10723
10755
  disableFilterButton: isFetching
10724
10756
  }, props.titleAndActionHeaderProps)), /*#__PURE__*/jsx(DataTable, _extends({}, props, {
10725
10757
  tableRef: DataTableRef,
@@ -11122,6 +11154,7 @@ const BusinessObjectPicker = _ref => {
11122
11154
  pageSize,
11123
11155
  idTemplate,
11124
11156
  shouldResetOnParametersChange,
11157
+ // TODO: replace this implementation with getNextPageParam function prop
11125
11158
  queryParamNames,
11126
11159
  enableInfinteScroll,
11127
11160
  renderAddItemForm,
@@ -11369,7 +11402,12 @@ const BusinessObjectPicker = _ref => {
11369
11402
  loading: status === "loading",
11370
11403
  options: props.data || _flatData,
11371
11404
  onChange: handleChange,
11372
- onInputChange: (event, value, reason) => reason === "reset" && setQ(""),
11405
+ onInputChange: (event, value, reason) => reason === "reset" && setQ("")
11406
+ // CAVEAT: changing this to getOptionLabel will create
11407
+ // problem when there are items with same label even though
11408
+ // they have different keys (ids).
11409
+ // getOptionLabel={getKey}
11410
+ ,
11373
11411
  getOptionLabel: getOptionLabel || getLabel,
11374
11412
  size: props.size,
11375
11413
  value: value,
@@ -14280,9 +14318,20 @@ TitleAndDescription.propTypes = {
14280
14318
  gutterBottom: PropTypes.bool
14281
14319
  };
14282
14320
 
14321
+ /**
14322
+ * Avoid using this hook as it mutates ref during render. using useState might
14323
+ * better option. https://beta.reactjs.org/learn/you-might-not-need-an-effect
14324
+ *
14325
+ * const useComponentWillMount = (callback) => { //
14326
+ * const [isMounted, setIsMounted] = useState(false); //
14327
+ * if (!isMounted) { callback(); setIsMounted(true); } //
14328
+ * };
14329
+ *
14330
+ * @param {function} callback
14331
+ */
14283
14332
  const useComponentWillMount = callback => {
14284
14333
  const willMount = useRef(true);
14285
- if (willMount.current) callback == null ? void 0 : callback();
14334
+ if (willMount.current) callback();
14286
14335
  willMount.current = false;
14287
14336
  };
14288
14337
 
@@ -15231,50 +15280,68 @@ RubricDistributionChart.propTypes = {
15231
15280
  titleComponent: PropTypes.oneOf(["h1", "h2", "h3", "h4", "div", "p"])
15232
15281
  };
15233
15282
 
15234
- const moreThan = ruleValue => fieldValue => {
15283
+ const moreThan = ruleValue => ({
15284
+ fieldValue
15285
+ }) => {
15235
15286
  const isValid = fieldValue > ruleValue;
15236
15287
  if (!isValid) return `should be more than ${ruleValue}`;
15237
15288
  };
15238
- const moreThanOrEqual = ruleValue => fieldValue => {
15289
+ const moreThanOrEqual = ruleValue => ({
15290
+ fieldValue
15291
+ }) => {
15239
15292
  const isValid = fieldValue >= ruleValue;
15240
15293
  if (!isValid) return `should be more than to ${ruleValue}`;
15241
15294
  };
15242
- const lessThan = ruleValue => fieldValue => {
15295
+ const lessThan = ruleValue => ({
15296
+ fieldValue
15297
+ }) => {
15243
15298
  const isValid = fieldValue < ruleValue;
15244
15299
  if (!isValid) return `should be less than ${ruleValue}`;
15245
15300
  };
15246
- const lessThanOrEqual = ruleValue => fieldValue => {
15301
+ const lessThanOrEqual = ruleValue => ({
15302
+ fieldValue
15303
+ }) => {
15247
15304
  const isValid = fieldValue <= ruleValue;
15248
15305
  if (!isValid) return `should be less than or equal to ${ruleValue}`;
15249
15306
  };
15250
- const notEqual = ruleValue => fieldValue => {
15307
+ const notEqual = ruleValue => ({
15308
+ fieldValue
15309
+ }) => {
15251
15310
  const isValid = ruleValue.toString() !== (fieldValue == null ? void 0 : fieldValue.toString == null ? void 0 : fieldValue.toString());
15252
15311
  if (!isValid) return `should NOT be ${ruleValue}`;
15253
15312
  };
15254
- const url = () => fieldValue => {
15313
+ const url = () => ({
15314
+ fieldValue
15315
+ }) => {
15255
15316
  const UrlRegEx = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/;
15256
15317
  const isValid = UrlRegEx.test(fieldValue);
15257
15318
  if (!isValid) return `is NOT a valid URL`;
15258
15319
  };
15259
- const email = () => fieldValue => {
15320
+ const email = () => ({
15321
+ fieldValue
15322
+ }) => {
15260
15323
  const EmailRegEx = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
15261
15324
  const isValid = EmailRegEx.test(fieldValue);
15262
15325
  if (!isValid) return `is NOT a valid email address`;
15263
15326
  };
15264
- const isInvalidDate = () => fieldValue => {
15327
+ const isInvalidDate = () => ({
15328
+ fieldValue
15329
+ }) => {
15265
15330
  const isValid = fieldValue !== "Invalid Date";
15266
15331
  if (!isValid) return "is invalid date";
15267
15332
  };
15268
- const required = () => fieldValue => {
15333
+ const required = () => ({
15334
+ fieldValue,
15335
+ schema
15336
+ }) => {
15269
15337
  const message = "is required";
15270
- if (Array.isArray(fieldValue) && fieldValue.length === 0) {
15271
- return message;
15272
- }
15273
- if (fieldValue == undefined || fieldValue == "") {
15274
- return message;
15275
- }
15338
+ if (schema.type.includes("array") && Array.isArray(fieldValue) && fieldValue.length === 0) return message;
15339
+ if (schema.type.includes("object") && isEmpty(fieldValue)) return message;
15340
+ if (fieldValue === null || fieldValue === undefined || fieldValue == "") return message;
15276
15341
  };
15277
- const isNumber = () => fieldValue => {
15342
+ const isNumber = () => ({
15343
+ fieldValue
15344
+ }) => {
15278
15345
  const message = "should be number";
15279
15346
  const isValid = !isNaN(fieldValue) &&
15280
15347
  // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
@@ -15282,7 +15349,9 @@ const isNumber = () => fieldValue => {
15282
15349
 
15283
15350
  if (!isValid) return message;
15284
15351
  };
15285
- const isNotNegativeNumber = () => fieldValue => {
15352
+ const isNotNegativeNumber = () => ({
15353
+ fieldValue
15354
+ }) => {
15286
15355
  const isValid = !isNaN(fieldValue) &&
15287
15356
  // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
15288
15357
  !isNaN(parseFloat(fieldValue)); // ...and ensure strings of whitespace fail
@@ -15290,21 +15359,49 @@ const isNotNegativeNumber = () => fieldValue => {
15290
15359
  if (isValid && parseFloat(fieldValue) < 0) return "should be positive number";
15291
15360
  if (!isValid) return "should be number";
15292
15361
  };
15293
- const characterLimitLessThan = ruleValue => fieldValue => {
15294
- // INFO: fasly values ("", undefined, null) are assumed to be to be 0
15295
- if (!fieldValue) return;
15296
- const isValid = fieldValue.length < ruleValue;
15297
- if (!isValid) return `should not exceed ${ruleValue - 1} characters`;
15362
+ const characterLimitLessThan = ruleValue => ({
15363
+ fieldValue
15364
+ }) => {
15365
+ // INFO: null and undefined are casted to empty string(""), number
15366
+ // values are casted to string
15367
+ const value = (fieldValue != null ? fieldValue : "").toString();
15368
+ const message = `should not exceed ${ruleValue - 1} characters`;
15369
+ const isValid = value.length < ruleValue;
15370
+ if (!isValid) return message;
15371
+ };
15372
+ const characterLimitMoreThan = ruleValue => ({
15373
+ fieldValue
15374
+ }) => {
15375
+ // INFO: null and undefined are casted to empty string(""), number
15376
+ // values are casted to string
15377
+ const value = (fieldValue != null ? fieldValue : "").toString();
15378
+ const message = `should not be less than ${ruleValue + 1} characters`;
15379
+ const isValid = value.length > ruleValue;
15380
+ if (!isValid) return message;
15298
15381
  };
15299
- const characterLimitMoreThan = ruleValue => fieldValue => {
15300
- const message = `should be more than ${ruleValue} characters`;
15301
-
15302
- // INFO: fasly values ("", undefined, null) are assumed to be to be 0
15303
- if (!fieldValue) return message;
15304
- const isValid = fieldValue.length > ruleValue;
15382
+ const maxLength = ruleValue => ({
15383
+ fieldValue
15384
+ }) => {
15385
+ // INFO: null and undefined are casted to empty string(""), number values
15386
+ // are casted to string
15387
+ const value = (fieldValue != null ? fieldValue : "").toString();
15388
+ const message = `should not exceed ${ruleValue} characters`;
15389
+ const isValid = value.length <= ruleValue;
15390
+ if (!isValid) return message;
15391
+ };
15392
+ const minLength = ruleValue => ({
15393
+ fieldValue
15394
+ }) => {
15395
+ // INFO: null and undefined are casted to empty string(""), number values
15396
+ // are casted to string
15397
+ const value = (fieldValue != null ? fieldValue : "").toString();
15398
+ const message = `should not be less than ${ruleValue} characters`;
15399
+ const isValid = value.length >= ruleValue;
15305
15400
  if (!isValid) return message;
15306
15401
  };
15307
15402
  const Rules = {
15403
+ maxLength,
15404
+ minLength,
15308
15405
  moreThan,
15309
15406
  moreThanOrEqual,
15310
15407
  lessThan,
@@ -15334,6 +15431,14 @@ const {
15334
15431
  formData: {}
15335
15432
  });
15336
15433
 
15434
+ const useSubmitted = () => {
15435
+ const [submitted, setSubmitted] = useState(false);
15436
+ useSubmitListener(() => {
15437
+ setSubmitted(true);
15438
+ });
15439
+ return submitted;
15440
+ };
15441
+
15337
15442
  const useStyles$3 = makeStyles(theme => ({
15338
15443
  button: {
15339
15444
  margin: theme.spacing(1)
@@ -15349,10 +15454,10 @@ const FormButtons = ({
15349
15454
  showCancelButton: _showCancelButton = false,
15350
15455
  showResetButton: _showResetButton = false,
15351
15456
  showDeleteButton: _showDeleteButton = false,
15352
- saveLabel,
15353
- cancelLabel,
15354
- resetLabel,
15355
- deleteLabel,
15457
+ saveLabel: _saveLabel = "Save",
15458
+ cancelLabel: _cancelLabel = "Cancel",
15459
+ resetLabel: _resetLabel = "Reset",
15460
+ deleteLabel: _deleteLabel = "Delete",
15356
15461
  hidden,
15357
15462
  submitStatus,
15358
15463
  onCancel,
@@ -15361,13 +15466,15 @@ const FormButtons = ({
15361
15466
  }) => {
15362
15467
  const classes = useStyles$3();
15363
15468
  const setFormState = useSetFormState();
15469
+ const customErrorMapping = useSelectFormState(formState => formState.customErrorMapping);
15470
+ const submitted = useSubmitted();
15364
15471
  let renderSaveButton = () => /*#__PURE__*/jsx(Button, {
15365
15472
  variant: "contained",
15366
15473
  color: "primary",
15367
15474
  type: "submit",
15368
- name: saveLabel,
15475
+ name: _saveLabel,
15369
15476
  className: classes.button,
15370
- children: saveLabel
15477
+ children: _saveLabel
15371
15478
  });
15372
15479
  if (submitStatus === "loading") {
15373
15480
  renderSaveButton = () => {
@@ -15377,7 +15484,7 @@ const FormButtons = ({
15377
15484
  type: "submit",
15378
15485
  className: classes.button,
15379
15486
  disabled: true,
15380
- name: saveLabel,
15487
+ name: _saveLabel,
15381
15488
  endIcon: /*#__PURE__*/jsx(CircularProgress, {
15382
15489
  color: "grey",
15383
15490
  size: 15
@@ -15386,18 +15493,19 @@ const FormButtons = ({
15386
15493
  });
15387
15494
  };
15388
15495
  }
15389
- if (submitStatus === "error") {
15496
+ const submitBlockedByCustomError = Object.values(customErrorMapping).findIndex(Boolean) !== -1;
15497
+ if (submitted && (submitStatus === "error" || submitBlockedByCustomError)) {
15390
15498
  renderSaveButton = () => {
15391
15499
  return /*#__PURE__*/jsx(Button, {
15392
15500
  variant: "contained",
15393
15501
  color: "primary",
15394
15502
  type: "submit",
15395
- name: saveLabel,
15503
+ name: _saveLabel,
15396
15504
  className: classes.button,
15397
15505
  endIcon: /*#__PURE__*/jsx(Error$1, {
15398
15506
  size: 15
15399
15507
  }),
15400
- children: saveLabel
15508
+ children: _saveLabel
15401
15509
  });
15402
15510
  };
15403
15511
  }
@@ -15410,7 +15518,7 @@ const FormButtons = ({
15410
15518
  }, {
15411
15519
  children: [_showResetButton && /*#__PURE__*/jsx(Button, {
15412
15520
  className: classes.button,
15413
- name: resetLabel,
15521
+ name: _resetLabel,
15414
15522
  onClick: () => {
15415
15523
  onReset == null ? void 0 : onReset();
15416
15524
  setFormState(prevState => _extends({}, prevState, {
@@ -15418,26 +15526,20 @@ const FormButtons = ({
15418
15526
  key: +new Date()
15419
15527
  }));
15420
15528
  },
15421
- children: resetLabel
15529
+ children: _resetLabel
15422
15530
  }), _showCancelButton && /*#__PURE__*/jsx(Button, {
15423
- name: cancelLabel,
15531
+ name: _cancelLabel,
15424
15532
  onClick: onCancel,
15425
15533
  className: classes.button,
15426
- children: cancelLabel
15534
+ children: _cancelLabel
15427
15535
  }), _showDeleteButton && /*#__PURE__*/jsx(Button, {
15428
- name: deleteLabel,
15536
+ name: _deleteLabel,
15429
15537
  onClick: onDelete,
15430
15538
  className: classes.button,
15431
- children: deleteLabel
15539
+ children: _deleteLabel
15432
15540
  }), !disabled && renderSaveButton()]
15433
15541
  }));
15434
15542
  };
15435
- FormButtons.defaultProps = {
15436
- saveLabel: "Submit",
15437
- cancelLabel: "Cancel",
15438
- resetLabel: "Reset",
15439
- deleteLabel: "Delete"
15440
- };
15441
15543
  FormButtons.propTypes = {
15442
15544
  cancelLabel: PropTypes.string,
15443
15545
  disabled: PropTypes.any,
@@ -15509,51 +15611,6 @@ const withEmptyValue = Component => {
15509
15611
  });
15510
15612
  };
15511
15613
 
15512
- const windowKeys = Object.keys(window).filter(key => {
15513
- try {
15514
- Function.apply(null, [key, "return;"]);
15515
- return true;
15516
- } catch (e) {
15517
- return false;
15518
- }
15519
- });
15520
-
15521
- /**
15522
- * evaluates
15523
- * @param {string} code
15524
- * @param {object} context
15525
- * @param {object} options
15526
- * @param {function} options.falbback
15527
- *
15528
- * @returns
15529
- */
15530
- const safeEval = (code, context, options) => {
15531
- const keys = Object.keys(context);
15532
-
15533
- // TODO: optimize
15534
- const allParams = keys.concat(windowKeys, [`"use strict"; return ${code}`]);
15535
- try {
15536
- const fn = Function.apply(null, allParams);
15537
- const params = keys.map(key => context[key]);
15538
- const res = fn.apply(null, params);
15539
- return res;
15540
- } catch (e) {
15541
- (options == null ? void 0 : options.fallback == null ? void 0 : options.fallback(e)) || console.log("Eval Error : ", e, {
15542
- code,
15543
- context,
15544
- options
15545
- });
15546
- }
15547
- };
15548
- const lazyEval = (code, context) => {
15549
- return new Promise((resolve, reject) => {
15550
- const result = safeEval(code, context, {
15551
- fallback: reject
15552
- });
15553
- resolve(result);
15554
- });
15555
- };
15556
-
15557
15614
  const {
15558
15615
  useSelectState: useSelectFieldState,
15559
15616
  useSetState: useSetFieldState,
@@ -15672,14 +15729,113 @@ CustomFieldTemplate.propTypes = {
15672
15729
  };
15673
15730
  var CustomFieldTemplate$1 = /*#__PURE__*/React.memo(withFieldStore(CustomFieldTemplate));
15674
15731
 
15732
+ /**
15733
+ * Simple memoize function. Check Stackoverflow topic for better implementation:
15734
+ * https://stackoverflow.com/questions/61402804/what-memoization-libraries-are-available-for-javascript
15735
+ *
15736
+ * @param {functionp} passedFunc
15737
+ * @returns function
15738
+ */
15739
+ const memoize = function memoize(passedFunc) {
15740
+ const cache = {};
15741
+ return function (x) {
15742
+ if (x in cache) return cache[x];
15743
+ cache[x] = passedFunc(x);
15744
+ return cache[x];
15745
+ };
15746
+ };
15747
+
15748
+ const windowKeys = Object.keys(window).filter(key => {
15749
+ try {
15750
+ Function.apply(null, [key, "return;"]);
15751
+ return true;
15752
+ } catch (e) {
15753
+ return false;
15754
+ }
15755
+ });
15756
+ const createScopedEval = (scopeMap, options) => {
15757
+ const keys = Object.keys(scopeMap);
15758
+ const createFunction = code => {
15759
+ const allParams = keys.concat(windowKeys, [`"use strict"; return ${code}`]);
15760
+ return Function.apply(null, allParams);
15761
+ };
15762
+ const memoizedCreateFunction = memoize(createFunction);
15763
+ const scopedEval = (code, scope) => {
15764
+ try {
15765
+ const fn = memoizedCreateFunction(code);
15766
+ const params = keys.map(key => scope[key]);
15767
+ const res = fn.apply(null, params);
15768
+ return res;
15769
+ } catch (e) {
15770
+ (options == null ? void 0 : options.fallback == null ? void 0 : options.fallback(e)) || console.log("Eval Error : ", e, {
15771
+ code,
15772
+ scope,
15773
+ options
15774
+ });
15775
+ }
15776
+ };
15777
+ return scopedEval;
15778
+ };
15779
+
15780
+ /**
15781
+ * evaluates
15782
+ * @param {string} code
15783
+ * @param {object} scope
15784
+ * @param {object} options
15785
+ * @param {function} options.falbback
15786
+ *
15787
+ * @returns
15788
+ */
15789
+ const scopedEval = (code, scope, options) => {
15790
+ const keys = Object.keys(scope);
15791
+
15792
+ // TODO: optimize
15793
+ const allParams = keys.concat(windowKeys, [`"use strict"; return ${code}`]);
15794
+ try {
15795
+ const fn = Function.apply(null, allParams);
15796
+ const params = keys.map(key => scope[key]);
15797
+ const res = fn.apply(null, params);
15798
+ return res;
15799
+ } catch (e) {
15800
+ (options == null ? void 0 : options.fallback == null ? void 0 : options.fallback(e)) || console.log("Eval Error : ", e, {
15801
+ code,
15802
+ scope,
15803
+ options
15804
+ });
15805
+ }
15806
+ };
15807
+ const lazyEval = (code, scope) => {
15808
+ return new Promise((resolve, reject) => {
15809
+ const result = safeEval(code, scope, {
15810
+ fallback: reject
15811
+ });
15812
+ resolve(result);
15813
+ });
15814
+ };
15815
+ const useScopedEval = scopeMap => useMemo(() => createScopedEval(scopeMap), []);
15816
+
15675
15817
  const withValidate = Component => {
15676
15818
  const MemoizedComponent = /*#__PURE__*/React.memo(Component);
15677
15819
  return /*#__PURE__*/forwardRef((props, ref) => {
15678
- var _props$uiSchema;
15679
- const rules = ((_props$uiSchema = props.uiSchema) == null ? void 0 : _props$uiSchema["rules"]) || [];
15680
- const isWidget = !!props.id;
15681
- const formItemValue = isWidget ? props.value : props.formData;
15820
+ const {
15821
+ id,
15822
+ name,
15823
+ value,
15824
+ formData,
15825
+ uiSchema,
15826
+ schema,
15827
+ formContext
15828
+ } = props;
15829
+ const rules = uiSchema["rules"] || [];
15830
+ const isWidget = !!id;
15831
+ const formItemValue = isWidget ? value : formData;
15832
+
15833
+ // CAVEAT: This cleans the idPrefix if widget (not field). Custom
15834
+ // idPrefix defination might effect here. It should be tested and
15835
+ // updated accordingly
15836
+ const fieldName = isWidget ? id.slice(5) : name;
15682
15837
  const Rules = useSelectFormState(state => state.rules);
15838
+ const scopedEval = useScopedEval(_extends({}, Rules));
15683
15839
  const setFieldState = useSetFieldState();
15684
15840
  const setFormState = useSetFormState();
15685
15841
  const [submitted, setSubmitted] = useState(false);
@@ -15689,13 +15845,13 @@ const withValidate = Component => {
15689
15845
  if (!rules) return [];
15690
15846
  const evaluatedRules = rules.map(rule => {
15691
15847
  const isFunctionCall = rule.slice(-1) === ")";
15692
- const ruleFn = safeEval(rule, Rules);
15848
+ const ruleFn = scopedEval(rule, Rules);
15693
15849
  return isFunctionCall ? ruleFn : ruleFn();
15694
15850
  });
15695
15851
 
15696
15852
  // TODO: this is bad practise, implementation should be moved to
15697
15853
  // inside widget/field when withValidate replaced with custom hook
15698
- if (props.uiSchema["ui:widget"] === "DateWidget" || props.uiSchema["ui:field"] === "DateSelect") {
15854
+ if (uiSchema["ui:widget"] === "DateWidget" || uiSchema["ui:field"] === "DateSelect") {
15699
15855
  evaluatedRules.push(Rules.isInvalidDate());
15700
15856
  }
15701
15857
  return evaluatedRules;
@@ -15712,25 +15868,33 @@ const withValidate = Component => {
15712
15868
  if (!rules) return;
15713
15869
  const isEmpty = formItemValue == undefined || formItemValue === "";
15714
15870
  const skipValidationOnEmptyValue = isEmpty && !isRequired;
15715
- const message = !skipValidationOnEmptyValue && evalRuleArray(formItemValue)(ruleArray);
15871
+ const message = !skipValidationOnEmptyValue && evalRuleArray({
15872
+ fieldValue: formItemValue,
15873
+ formContext,
15874
+ formData,
15875
+ uiSchema,
15876
+ schema
15877
+ })(ruleArray);
15716
15878
  setFieldState(state => _extends({}, state, {
15717
15879
  errorMessage: message
15718
15880
  }));
15719
15881
 
15720
- // TODO: cleans the idPrefix if widget (not field). Custom idPrefix
15721
- // defination might effect here. It should be tested and updated
15722
- // accordingly
15723
- const fieldName = isWidget ? props.id.slice(5) : props.name;
15724
-
15725
15882
  // INFO: Adding item to array template does not work without
15726
15883
  // setFormState wrapped with setTimeout
15727
15884
  setTimeout(() => {
15728
- setFormState(state => _extends({}, state, {
15729
- customErrorMapping: _extends({}, state.customErrorMapping, {
15730
- [fieldName]: !!message
15731
- })
15732
- }));
15885
+ // TODO: This setFormState create so much re-render on top
15886
+ // level. For now, leaving this optimization to React 18
15887
+ // debounced rendering. It can also be solved by creating
15888
+ // seperate state for customErrorMapping.
15889
+ setFormState(state => {
15890
+ return _extends({}, state, {
15891
+ customErrorMapping: _extends({}, state.customErrorMapping, {
15892
+ [fieldName]: message
15893
+ })
15894
+ });
15895
+ });
15733
15896
  });
15897
+ // TODO: add other dependecies
15734
15898
  }, [formItemValue]);
15735
15899
  const handleOnchange = (...args) => {
15736
15900
  setTouched(true);
@@ -15743,13 +15907,31 @@ const withValidate = Component => {
15743
15907
  }));
15744
15908
  });
15745
15909
  };
15746
- const evalRuleArray = fieldValue => rules => {
15910
+ const evalRuleArray = ({
15911
+ fieldValue,
15912
+ schema,
15913
+ uiSchema,
15914
+ formContext,
15915
+ formData
15916
+ }) => rules => {
15747
15917
  for (let rule of rules) {
15748
- const message = rule(fieldValue);
15918
+ const message = rule({
15919
+ fieldValue,
15920
+ schema,
15921
+ uiSchema,
15922
+ formContext,
15923
+ formData
15924
+ });
15749
15925
  if (message != undefined) return message;
15750
15926
  }
15751
15927
  };
15752
15928
 
15929
+ /**
15930
+ * TODO:
15931
+ * - do two version of it seperately for widget and field eg. withValidate (for field) and withValidateWidget
15932
+ *
15933
+ */
15934
+
15753
15935
  const commonWidgetHOCs = [withValidate, withEmptyValue];
15754
15936
  const commonFieldHOCs = [withValidate, withEmptyValue];
15755
15937
 
@@ -16389,12 +16571,7 @@ const ReadOnlyView = ({
16389
16571
  sx: {
16390
16572
  fontStyle: "italic"
16391
16573
  },
16392
- description: /*#__PURE__*/jsx(Box$2, {
16393
- sx: {
16394
- paddingRight: 0.5
16395
- },
16396
- children: _emptyViewText
16397
- }),
16574
+ description: _emptyViewText,
16398
16575
  showIcon: false
16399
16576
  });
16400
16577
  }
@@ -16717,7 +16894,9 @@ const useReadOnly = uiSchema => {
16717
16894
  const selector = useCallback(state => {
16718
16895
  const defaultValue = state.readonly || state.schema.readonly;
16719
16896
  if (!code) return defaultValue;
16720
- const evaluatedReadyOnly = safeEval(code, state);
16897
+
16898
+ // TODO: change it with useScopedEval
16899
+ const evaluatedReadyOnly = scopedEval(code, state);
16721
16900
  return defaultValue || evaluatedReadyOnly;
16722
16901
  }, [code]);
16723
16902
  const evaluatedReadyOnly = useSelectFormState(selector);
@@ -16806,13 +16985,11 @@ const dateInputStyles = {
16806
16985
  const DateSelect = props => {
16807
16986
  var _useSelector, _useSelector2;
16808
16987
  const {
16809
- id,
16810
16988
  required,
16811
16989
  schema,
16812
16990
  formData,
16813
16991
  onChange,
16814
16992
  rawErrors,
16815
- options,
16816
16993
  disabled
16817
16994
  } = props;
16818
16995
  const [selectedDate, setSelectedDate] = useState(null);
@@ -16866,7 +17043,10 @@ const DateSelect = props => {
16866
17043
  const maxDateRaw = (_useSelector2 = useSelector(props.uiSchema["select::maxDate"])) == null ? void 0 : _useSelector2.date;
16867
17044
  const maxDate = maxDateRaw ? parse$1(maxDateRaw, "MM-dd-yyyy", new Date()) : undefined;
16868
17045
  const isReadOnly = useReadOnly(props.uiSchema);
16869
- if (isReadOnly) return /*#__PURE__*/jsx(DateSelectReadOnly$1, _extends({}, props));
17046
+ if (isReadOnly) return /*#__PURE__*/jsx(DateSelectReadOnly$1, {
17047
+ formData: formData,
17048
+ schema: schema
17049
+ });
16870
17050
  return /*#__PURE__*/jsxs(FormControl, {
16871
17051
  disabled: disabled || schema.disabled,
16872
17052
  required: required,
@@ -16924,7 +17104,6 @@ const DateSelect = props => {
16924
17104
  value: typeof selectedDate === "undefined" ? null : selectedDate,
16925
17105
  onChange: handleDateChange,
16926
17106
  disabled: disabled,
16927
- inputLabe: true,
16928
17107
  renderInput: params => /*#__PURE__*/jsx(TextField, _extends({}, params, {
16929
17108
  inputProps: _extends({}, params.inputProps, {
16930
17109
  type: "text"
@@ -17540,8 +17719,8 @@ const withEvalDisable = () => Component => {
17540
17719
  const code = (_props$uiSchema = props.uiSchema) == null ? void 0 : _props$uiSchema["ui:disabled"];
17541
17720
  if (!code) return props.disabled;
17542
17721
 
17543
- // TODO: use lazyEval
17544
- return safeEval(code, formState);
17722
+ // TODO: replace with useScopedEval
17723
+ return scopedEval(code, formState);
17545
17724
  }, [formState.formData, formState.formContext, props.disabled]);
17546
17725
  return /*#__PURE__*/jsx(MemoizedComponent, _extends({}, props, {
17547
17726
  disabled: isDisabled
@@ -17856,7 +18035,10 @@ var SelectField$1 = compose(HOCs$8)(SelectField);
17856
18035
  // check this topic to catch consistant view with autocmplete
17857
18036
  // https://stackoverflow.com/questions/63047684/material-ui-select-menu-with-end-adornment
17858
18037
 
18038
+ const useFormStateScopedEval = () => useScopedEval(formStateScopeMap);
18039
+
17859
18040
  const useProcessCondition = formState => {
18041
+ const safeEval = useFormStateScopedEval();
17860
18042
  const conditions = useMemo(() => {
17861
18043
  const {
17862
18044
  schema,
@@ -17882,47 +18064,48 @@ const useProcessCondition = formState => {
17882
18064
  const newFormState = useMemo(() => {
17883
18065
  const {
17884
18066
  schema,
17885
- formData
18067
+ formData,
18068
+ customErrorMapping
17886
18069
  } = formState;
17887
- let changed = false;
17888
- let newRequired = schema.required ? [...schema.required] : [];
18070
+ let newRequiredItemList = schema.required ? [...schema.required] : [];
17889
18071
  let newProperties = _extends({}, schema.properties);
18072
+ let newCustomErrorMapping = _extends({}, customErrorMapping);
17890
18073
  let newFormData = formData ? _extends({}, formData) : {};
17891
18074
  conditions.forEach(item => {
17892
- const nextOperation = safeEval(item.condition, formState) ? "added" : "deleted";
17893
- if (item.lastOperation !== nextOperation) {
17894
- changed = true;
17895
- }
17896
- if (nextOperation === "added") {
17897
- item.lastOperation = nextOperation;
18075
+ const nextOperation = safeEval(item.condition, formState) ? "add" : "delete";
18076
+ if (nextOperation === "add") {
17898
18077
  if (item.isRequired) {
17899
- newRequired.indexOf(item.key) === -1 && newRequired.push(item.key);
18078
+ newRequiredItemList.indexOf(item.key) === -1 && newRequired.push(item.key);
17900
18079
  }
17901
18080
  newProperties[item.key] = item.schema;
17902
- } else {
17903
- item.lastOperation = nextOperation;
18081
+ }
18082
+ if (nextOperation === "delete") {
17904
18083
  if (item.isRequired) {
17905
- newRequired = newRequired.filter(key => key !== item.key);
18084
+ newRequiredItemList = newRequiredItemList.filter(key => key !== item.key);
17906
18085
  }
17907
18086
  delete newProperties[item.key];
17908
18087
  delete newFormData[item.key];
18088
+ delete customErrorMapping[item.key];
17909
18089
  }
17910
18090
  });
17911
- if (changed) {
17912
- const newSchema = _extends({}, schema, {
17913
- properties: _extends({}, newProperties),
17914
- required: [...newRequired]
17915
- });
17916
- return _extends({}, formState, {
17917
- schema: newSchema,
17918
- formData: newFormData
17919
- });
17920
- }
17921
- return formState;
17922
- }, [formState.formData]);
18091
+ const newSchema = _extends({}, schema, {
18092
+ properties: _extends({}, newProperties),
18093
+ required: [...newRequiredItemList]
18094
+ });
18095
+ return _extends({}, formState, {
18096
+ schema: newSchema,
18097
+ formData: newFormData,
18098
+ customErrorMapping: newCustomErrorMapping
18099
+ });
18100
+ }, [formState]);
17923
18101
  return newFormState;
17924
18102
  };
17925
18103
 
18104
+ /**
18105
+ * TODO:
18106
+ * remove required list field
18107
+ */
18108
+
17926
18109
  const useStyles$1 = makeStyles$1(theme => ({
17927
18110
  fab: {
17928
18111
  margin: theme.spacing(1)
@@ -19467,7 +19650,7 @@ TextWidgetBase.propTypes = {
19467
19650
  };
19468
19651
 
19469
19652
  const _excluded = ["onChange"];
19470
- const TextWidgetReadOnly$1 = props => {
19653
+ const TextWidgetReadOnly$1 = function TextWidgetReadOnly(props) {
19471
19654
  const {
19472
19655
  options: {
19473
19656
  prefix = "$",
@@ -19496,7 +19679,15 @@ const TextWidgetReadOnly$1 = props => {
19496
19679
  });
19497
19680
  };
19498
19681
  TextWidgetReadOnly$1.propTypes = {
19499
- schema: PropTypes.any,
19682
+ options: PropTypes.shape({
19683
+ prefix: PropTypes.string,
19684
+ decimalScale: PropTypes.number,
19685
+ fixedDecimalScale: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
19686
+ thousandSeparator: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
19687
+ decimalSeparator: PropTypes.string,
19688
+ allowNegative: PropTypes.bool
19689
+ }),
19690
+ schema: PropTypes.object,
19500
19691
  value: PropTypes.any
19501
19692
  };
19502
19693
  const CurrencyWidget = props => {
@@ -19697,7 +19888,6 @@ SelectWidget.propTypes = {
19697
19888
  id: PropTypes.any,
19698
19889
  onChange: PropTypes.func,
19699
19890
  options: PropTypes.any,
19700
- rawErrors: PropTypes.array,
19701
19891
  required: PropTypes.any,
19702
19892
  schema: PropTypes.shape({
19703
19893
  disabled: PropTypes.any,
@@ -19881,6 +20071,8 @@ ValidateWidget.propTypes = {
19881
20071
  };
19882
20072
  var ValidateWidget$1 = withReadyOnly(ValidateWidget);
19883
20073
 
20074
+ const humanReadableList = a => [a.slice(0, -1).join(", "), a.slice(-1)[0]].join(a.length < 2 ? "" : " and ");
20075
+
19884
20076
  const {
19885
20077
  useDispatcher: useSubmitDispatcher,
19886
20078
  useListener: useSubmitListener,
@@ -19921,27 +20113,43 @@ const defaultFields = {
19921
20113
  */
19922
20114
  };
19923
20115
 
20116
+ const useProcessedFormState = () => {
20117
+ const formState = useSelectFormState();
20118
+ return useProcessCondition(formState);
20119
+ };
19924
20120
  const defaultTemplates = {
19925
20121
  ArrayFieldTemplate: ArrayFieldTemplate$1
19926
20122
  };
20123
+ const fn = () => {};
20124
+ const formStateScopeMap = {
20125
+ schema: {},
20126
+ uiSchema: {},
20127
+ initialFormData: {},
20128
+ formData: {},
20129
+ formContext: {},
20130
+ readonly: false,
20131
+ dataSources: {},
20132
+ customErrorMapping: {},
20133
+ rules: {}
20134
+ };
19927
20135
  const DynamicForm = ({
19928
- schema,
19929
- uiSchema,
19930
- saveButtonText,
19931
- cancelButtonText,
19932
- resetButtonText,
19933
- deleteButtonText,
19934
- formData: initialFormData,
20136
+ schema: _schema = {},
20137
+ uiSchema: _uiSchema = {},
20138
+ saveButtonText: _saveButtonText = "Save",
20139
+ cancelButtonText: _cancelButtonText = "Cancel",
20140
+ resetButtonText: _resetButtonText = "Reset",
20141
+ deleteButtonText: _deleteButtonText = "Delete",
20142
+ formData: initialFormData = {},
19935
20143
  widgets: widgetsProp,
19936
20144
  fields: fieldsProp,
19937
20145
  templates: templatesProp,
19938
- onChange,
19939
- actionUrls,
20146
+ onChange: _onChange = fn,
20147
+ onError: _onError = fn,
20148
+ onSubmit: _onSubmit = fn,
19940
20149
  dataSources: _dataSources = [],
19941
20150
  formContext: formContextProp,
19942
20151
  initialFormContext,
19943
- onSubmit,
19944
- disableSubmit,
20152
+ disableSubmit: _disableSubmit = false,
19945
20153
  readonly,
19946
20154
  formDataStatus,
19947
20155
  submitStatus,
@@ -19958,33 +20166,40 @@ const DynamicForm = ({
19958
20166
  renderBottom
19959
20167
  }) => {
19960
20168
  const setFormState = useSetFormState();
20169
+ const {
20170
+ error
20171
+ } = useNotify();
19961
20172
  useComponentWillMount(() => {
19962
- setFormState(prev => _extends({}, prev, {
19963
- schema,
19964
- uiSchema,
20173
+ const initialState = {
20174
+ schema: _schema,
20175
+ uiSchema: _uiSchema,
19965
20176
  initialFormData: initialFormData,
19966
20177
  formData: initialFormData,
19967
- actionUrls,
19968
20178
  formContext: initialFormContext || formContextProp,
19969
20179
  readonly,
19970
20180
  dataSources: _dataSources,
19971
20181
  customErrorMapping: {},
19972
20182
  rules: _extends({}, _rules, Rules)
19973
- }));
20183
+ };
20184
+ setFormState(() => initialState);
19974
20185
  });
19975
- const formState = useSelectFormState();
20186
+ const formState = useProcessedFormState();
20187
+
20188
+ // useDependencyChange(() => {}, [processedState]);
20189
+
19976
20190
  const widgets = _extends({}, defaultWidgets, widgetsProp);
19977
20191
  const fields = _extends({}, defaultFields, fieldsProp);
19978
20192
  const templates = _extends({}, defaultTemplates, templatesProp);
19979
20193
  const dispatchSubmitEvent = useSubmitDispatcher();
19980
- const newFormState = useProcessCondition(formState);
19981
20194
  useComponentWillMount(() => {
19982
20195
  const configs = getConfigurationParameters();
19983
20196
  registerDataSources(_dataSources, configs);
19984
20197
  });
19985
- useEffect(() => {
19986
- setFormState(prev => _extends({}, prev, newFormState));
19987
- }, [newFormState]);
20198
+
20199
+ // useEffect(() => {
20200
+ // setFormState((prev) => ({ ...prev, ...newFormState }));
20201
+ // }, [newFormState]);
20202
+
19988
20203
  useEffect(() => {
19989
20204
  setFormState(prev => _extends({}, prev, {
19990
20205
  formContext: formContextProp
@@ -20001,19 +20216,35 @@ const DynamicForm = ({
20001
20216
  const [{
20002
20217
  formData
20003
20218
  }] = args;
20004
- setFormState(prevState => _extends({}, prevState, {
20005
- formData
20006
- }));
20007
- onChange == null ? void 0 : onChange(...args);
20219
+ setFormState(prevState => {
20220
+ return _extends({}, prevState, {
20221
+ formData
20222
+ });
20223
+ });
20224
+ _onChange == null ? void 0 : _onChange(...args);
20008
20225
  };
20009
20226
  const handleSubmit = (...args) => {
20010
- if (disableSubmit) {
20011
- return;
20012
- }
20227
+ if (_disableSubmit) return;
20013
20228
  dispatchSubmitEvent(...args);
20014
20229
  const submitBlockedByCustomError = Object.values(formState.customErrorMapping).findIndex(Boolean) !== -1;
20015
- if (submitBlockedByCustomError) return;
20016
- onSubmit(...args);
20230
+ if (submitBlockedByCustomError) {
20231
+ let errorFields = [];
20232
+ for (const [field, _message] of Object.entries(formState.customErrorMapping)) {
20233
+ if (!!_message) {
20234
+ errorFields.push(_schema.properties[field].title);
20235
+ }
20236
+ }
20237
+ const pluralSuffix = errorFields.length > 1 ? "s" : "";
20238
+ const fields = humanReadableList(errorFields);
20239
+ const message = `Please resolve issue${pluralSuffix} on following field${pluralSuffix}: ${fields}`;
20240
+ error(message);
20241
+ _onError({
20242
+ errors: formState.customErrorMapping,
20243
+ message
20244
+ });
20245
+ return;
20246
+ }
20247
+ _onSubmit(...args);
20017
20248
  };
20018
20249
  const handleError = (...args) => {
20019
20250
  dispatchSubmitEvent();
@@ -20043,27 +20274,21 @@ const DynamicForm = ({
20043
20274
  validate: validate,
20044
20275
  transformErrors: transformErrorsProps || transformErrors,
20045
20276
  children: [renderBottom == null ? void 0 : renderBottom(), /*#__PURE__*/jsx(FormButtons, {
20046
- hidden: readonly || schema.readonly,
20047
- saveLabel: saveButtonText,
20277
+ hidden: readonly || _schema.readonly,
20278
+ saveLabel: _saveButtonText,
20048
20279
  submitStatus: submitStatus,
20049
20280
  showResetButton: showResetButton,
20050
- resetLabel: resetButtonText,
20281
+ resetLabel: _resetButtonText,
20051
20282
  onReset: onReset,
20052
20283
  showCancelButton: showCancelButton,
20053
- cancelLabel: cancelButtonText,
20284
+ cancelLabel: _cancelButtonText,
20054
20285
  onCancel: onCancel,
20055
20286
  showDeleteButton: showDeleteButton,
20056
- deleteLabel: deleteButtonText,
20287
+ deleteLabel: _deleteButtonText,
20057
20288
  onDelete: onDelete
20058
20289
  })]
20059
20290
  }, formState.key);
20060
20291
  };
20061
- DynamicForm.defaultProps = {
20062
- saveButtonText: "Submit",
20063
- cancelButtonText: "Cancel",
20064
- resetButtonText: "Reset",
20065
- disableSubmitButton: false
20066
- };
20067
20292
  DynamicForm.propTypes = {
20068
20293
  /** JSON based schema definition for the form. */
20069
20294
  schema: PropTypes.object.isRequired,
@@ -20077,8 +20302,6 @@ DynamicForm.propTypes = {
20077
20302
  onSubmit: PropTypes.func,
20078
20303
  /** Error handler. */
20079
20304
  onError: PropTypes.func,
20080
- /** Urls to be used for templates of dataSource */
20081
- actionUrls: PropTypes.object,
20082
20305
  /** Additional data form custom fields can be passed as formContext */
20083
20306
  formContext: PropTypes.object,
20084
20307
  /** Shows reset button */