orc-shared 5.9.0-dev.8 → 5.9.0

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.
@@ -116,6 +116,16 @@ var useStyles = exports.useStyles = (0, _styles.makeStyles)(function (theme) {
116
116
  "& + $track": {
117
117
  backgroundColor: "".concat(theme.palette.grey.borders, " !important")
118
118
  }
119
+ },
120
+ container: {
121
+ display: "flex",
122
+ flexDirection: "column"
123
+ },
124
+ errorText: {
125
+ marginTop: theme.spacing(0.5),
126
+ color: theme.palette.error.main,
127
+ fontSize: theme.typography.fieldLabelSize,
128
+ float: "left"
119
129
  }
120
130
  };
121
131
  });
@@ -130,6 +140,7 @@ var Switch = function Switch(_ref) {
130
140
  var value = (switchProps == null ? void 0 : switchProps.get(_SwitchProps.default.propNames.value)) || false;
131
141
  var onCaption = switchProps == null ? void 0 : switchProps.get(_SwitchProps.default.propNames.onCaption);
132
142
  var offCaption = switchProps == null ? void 0 : switchProps.get(_SwitchProps.default.propNames.offCaption);
143
+ var error = switchProps == null ? void 0 : switchProps.get(_SwitchProps.default.propNames.error);
133
144
  var disabled = (switchProps == null ? void 0 : switchProps.get(_SwitchProps.default.propNames.disabled)) || false;
134
145
  var readOnly = switchProps == null ? void 0 : switchProps.get(_SwitchProps.default.propNames.readOnly);
135
146
  var className = (switchProps == null ? void 0 : switchProps.get(_SwitchProps.default.propNames.className)) || "";
@@ -149,7 +160,7 @@ var Switch = function Switch(_ref) {
149
160
  checked: classes.checked,
150
161
  disabled: classes.disabled
151
162
  }, className);
152
- return /*#__PURE__*/_react.default.createElement(_Switch.default, {
163
+ var switchComponent = /*#__PURE__*/_react.default.createElement(_Switch.default, {
153
164
  disabled: disabled,
154
165
  classes: switchClasses,
155
166
  checked: value,
@@ -158,6 +169,11 @@ var Switch = function Switch(_ref) {
158
169
  },
159
170
  color: "primary"
160
171
  });
172
+ return error && /*#__PURE__*/_react.default.createElement("div", {
173
+ className: classes.container
174
+ }, switchComponent, /*#__PURE__*/_react.default.createElement("div", {
175
+ className: (0, _classnames.default)(classes.errorText)
176
+ }, error)) || switchComponent;
161
177
  };
162
178
  __signature__(Switch, "useIntl{{ formatMessage }}\nuseStyles{classes}", function () {
163
179
  return [_reactIntl.useIntl, useStyles];
@@ -35,6 +35,7 @@ var SwitchProps = /*#__PURE__*/function (_ComponentProps) {
35
35
  _this.componentProps.set(_this.constructor.propNames.readOnly, null);
36
36
  _this.componentProps.set(_this.constructor.propNames.className, null);
37
37
  _this.componentProps.set(_this.constructor.propNames.id, null);
38
+ _this.componentProps.set(_this.constructor.propNames.error, null);
38
39
  _this.componentProps.set(_this.constructor.propNames.metadata, null);
39
40
  _this._isSwitchProps = true;
40
41
  return _this;
@@ -57,6 +58,7 @@ _defineProperty(SwitchProps, "propNames", {
57
58
  readOnly: "readOnly",
58
59
  className: "className",
59
60
  id: "id",
61
+ error: "error",
60
62
  metadata: "metadata"
61
63
  });
62
64
  var isSwitchProps = exports.isSwitchProps = function isSwitchProps(value) {
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _react = _interopRequireDefault(require("react"));
6
+ var _styles = require("@material-ui/core/styles");
7
+ var _Menu = _interopRequireDefault(require("@material-ui/core/Menu"));
8
+ var _MenuItem = _interopRequireDefault(require("@material-ui/core/MenuItem"));
9
+ var _Divider = _interopRequireDefault(require("./DataDisplay/Divider"));
10
+ var _dividerProps = _interopRequireDefault(require("./DataDisplay/dividerProps"));
11
+ var _Icon = _interopRequireDefault(require("./DataDisplay/Icon"));
12
+ var _Button = _interopRequireDefault(require("@material-ui/core/Button"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ (function () {
15
+ var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
16
+ enterModule && enterModule(module);
17
+ })();
18
+ (function () {
19
+ var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
20
+ enterModule && enterModule(module);
21
+ })();
22
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
23
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
24
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
25
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
26
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
27
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
28
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
29
+ var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
30
+ return a;
31
+ };
32
+ var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
33
+ return a;
34
+ };
35
+ var useMenuStyles = (0, _styles.makeStyles)(function (theme) {
36
+ return {
37
+ menuItem: {
38
+ fontFamily: theme.typography.fontFamily,
39
+ textTransform: "none",
40
+ color: theme.palette.text.primary,
41
+ borderRadius: 0,
42
+ "&:hover": {
43
+ borderRadius: 0,
44
+ boxShadow: "none",
45
+ backgroundColor: theme.palette.primary.light
46
+ },
47
+ "&:focus, &:active, &.Mui-focusVisible": {
48
+ borderRadius: 0,
49
+ boxShadow: "none",
50
+ outline: "none"
51
+ }
52
+ },
53
+ menu: {
54
+ border: "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.primary.main)
55
+ },
56
+ arrowIcon: {
57
+ width: theme.spacing(1),
58
+ height: theme.spacing(1)
59
+ }
60
+ };
61
+ });
62
+ var StyledMenu = function StyledMenu(props) {
63
+ var classes = useMenuStyles();
64
+ return /*#__PURE__*/_react.default.createElement(_Menu.default, _extends({
65
+ elevation: 0,
66
+ getContentAnchorEl: null,
67
+ anchorOrigin: {
68
+ vertical: "bottom",
69
+ horizontal: "left"
70
+ },
71
+ transformOrigin: {
72
+ vertical: "top",
73
+ horizontal: "left"
74
+ },
75
+ classes: {
76
+ paper: classes.menu
77
+ }
78
+ }, props));
79
+ };
80
+ __signature__(StyledMenu, "useMenuStyles{classes}", function () {
81
+ return [useMenuStyles];
82
+ });
83
+ __signature__(StyledMenu, "useMenuStyles{classes}", function () {
84
+ return [useMenuStyles];
85
+ });
86
+ var MenuButton = function MenuButton(_ref) {
87
+ var _options$every;
88
+ var options = _ref.options,
89
+ label = _ref.label;
90
+ var _React$useState = _react.default.useState(null),
91
+ _React$useState2 = _slicedToArray(_React$useState, 2),
92
+ anchorEl = _React$useState2[0],
93
+ setAnchorEl = _React$useState2[1];
94
+ var classes = useMenuStyles();
95
+ var handleClick = function handleClick(event) {
96
+ setAnchorEl(event.currentTarget);
97
+ };
98
+ var handleClose = function handleClose() {
99
+ setAnchorEl(null);
100
+ };
101
+ var dividerProps = new _dividerProps.default();
102
+ dividerProps.set(_dividerProps.default.propNames.light, true);
103
+ dividerProps.set(_dividerProps.default.propNames.variant, "middle");
104
+ var allDisabled = (_options$every = options == null ? void 0 : options.every(function (o) {
105
+ return o.disabled;
106
+ })) != null ? _options$every : true;
107
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Button.default, {
108
+ "aria-haspopup": "true",
109
+ variant: "outlined",
110
+ color: "primary",
111
+ disabled: allDisabled,
112
+ onClick: handleClick,
113
+ endIcon: /*#__PURE__*/_react.default.createElement(_Icon.default, {
114
+ id: "chevron-down",
115
+ className: classes.arrowIcon
116
+ })
117
+ }, label), /*#__PURE__*/_react.default.createElement(StyledMenu, {
118
+ anchorEl: anchorEl,
119
+ open: Boolean(anchorEl),
120
+ onClose: handleClose
121
+ }, options == null ? void 0 : options.map(function (_ref2, index) {
122
+ var key = _ref2.key,
123
+ component = _ref2.component,
124
+ disabled = _ref2.disabled,
125
+ action = _ref2.action;
126
+ return /*#__PURE__*/_react.default.createElement("div", {
127
+ key: key
128
+ }, /*#__PURE__*/_react.default.createElement(_MenuItem.default, {
129
+ onClick: function onClick() {
130
+ handleClose();
131
+ action == null || action();
132
+ },
133
+ disabled: disabled,
134
+ classes: {
135
+ root: classes.menuItem
136
+ }
137
+ }, component), index < options.length - 1 && /*#__PURE__*/_react.default.createElement(_Divider.default, {
138
+ dividerProps: dividerProps
139
+ }));
140
+ })));
141
+ };
142
+ __signature__(MenuButton, "useState{[anchorEl, setAnchorEl](null)}\nuseMenuStyles{classes}", function () {
143
+ return [useMenuStyles];
144
+ });
145
+ __signature__(MenuButton, "useState{[anchorEl, setAnchorEl](null)}\nuseMenuStyles{classes}", function () {
146
+ return [useMenuStyles];
147
+ });
148
+ var _default = MenuButton;
149
+ var _default2 = _default;
150
+ var _default3 = exports.default = _default2;
151
+ ;
152
+ (function () {
153
+ var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined;
154
+ if (!reactHotLoader) {
155
+ return;
156
+ }
157
+ reactHotLoader.register(useMenuStyles, "useMenuStyles", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
158
+ reactHotLoader.register(StyledMenu, "StyledMenu", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
159
+ reactHotLoader.register(MenuButton, "MenuButton", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
160
+ reactHotLoader.register(_default, "default", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
161
+ })();
162
+ ;
163
+ (function () {
164
+ var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined;
165
+ leaveModule && leaveModule(module);
166
+ })();
167
+ ;
168
+ (function () {
169
+ var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined;
170
+ if (!reactHotLoader) {
171
+ return;
172
+ }
173
+ reactHotLoader.register(useMenuStyles, "useMenuStyles", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
174
+ reactHotLoader.register(StyledMenu, "StyledMenu", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
175
+ reactHotLoader.register(MenuButton, "MenuButton", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
176
+ reactHotLoader.register(_default2, "default", "/home/vsts/work/1/s/src/components/MaterialUI/MenuButtons.js");
177
+ })();
178
+ ;
179
+ (function () {
180
+ var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined;
181
+ leaveModule && leaveModule(module);
182
+ })();
@@ -78,6 +78,13 @@ var DropDownMenu = function DropDownMenu(_ref) {
78
78
  event.stopPropagation();
79
79
  setAnchorEl(null);
80
80
  };
81
+
82
+ // Even though we do nothing, we need to avoid mouse event propagation when the mouse
83
+ // button is released after hovering out the menu
84
+ var onMainMenuClick = function onMainMenuClick(event) {
85
+ event.preventDefault();
86
+ event.stopPropagation();
87
+ };
81
88
  var onMenuItemClick = function onMenuItemClick(action, itemContext) {
82
89
  return function (event) {
83
90
  onClose(event);
@@ -110,6 +117,7 @@ var DropDownMenu = function DropDownMenu(_ref) {
110
117
  },
111
118
  id: "scope-menu",
112
119
  open: isOpened,
120
+ onClick: onMainMenuClick,
113
121
  onClose: onClose,
114
122
  autoFocus: autoFocus,
115
123
  anchorEl: anchorEl
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _react = _interopRequireDefault(require("react"));
6
+ var _InformationItem = _interopRequireDefault(require("./MaterialUI/DataDisplay/PredefinedElements/InformationItem"));
7
+ var _sharedMessages = _interopRequireDefault(require("../sharedMessages"));
8
+ var _reactIntl = require("react-intl");
9
+ var _Box = _interopRequireDefault(require("@material-ui/core/Box"));
10
+ var _styles = require("@material-ui/core/styles");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ (function () {
13
+ var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
14
+ enterModule && enterModule(module);
15
+ })();
16
+ (function () {
17
+ var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
18
+ enterModule && enterModule(module);
19
+ })();
20
+ var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
21
+ return a;
22
+ };
23
+ var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
24
+ return a;
25
+ };
26
+ var useStyles = (0, _styles.makeStyles)(function (theme) {
27
+ return {
28
+ registry: {
29
+ "& > div + div": {
30
+ marginTop: theme.spacing(2)
31
+ }
32
+ }
33
+ };
34
+ });
35
+ var Registry = function Registry(_ref) {
36
+ var dateCreated = _ref.dateCreated,
37
+ createdBy = _ref.createdBy,
38
+ lastModifiedDate = _ref.lastModifiedDate,
39
+ lastModifiedBy = _ref.lastModifiedBy,
40
+ _ref$additionalConten = _ref.additionalContent,
41
+ additionalContent = _ref$additionalConten === void 0 ? [] : _ref$additionalConten;
42
+ var _useIntl = (0, _reactIntl.useIntl)(),
43
+ formatDate = _useIntl.formatDate;
44
+ var classes = useStyles();
45
+ var created = formatDate(dateCreated);
46
+ var lastModified = formatDate(lastModifiedDate);
47
+ 0;
48
+ var registry = /*#__PURE__*/_react.default.createElement(_Box.default, {
49
+ className: classes.registry,
50
+ display: "flex",
51
+ flexDirection: "column"
52
+ }, dateCreated !== undefined && /*#__PURE__*/_react.default.createElement(_InformationItem.default, {
53
+ label: _sharedMessages.default.created,
54
+ children: created
55
+ }), createdBy !== undefined && /*#__PURE__*/_react.default.createElement(_InformationItem.default, {
56
+ label: _sharedMessages.default.createdBy,
57
+ children: createdBy
58
+ }), lastModifiedDate !== undefined && /*#__PURE__*/_react.default.createElement(_InformationItem.default, {
59
+ label: _sharedMessages.default.lastModified,
60
+ children: lastModified
61
+ }), lastModifiedBy !== undefined && /*#__PURE__*/_react.default.createElement(_InformationItem.default, {
62
+ label: _sharedMessages.default.lastModifiedBy,
63
+ children: lastModifiedBy
64
+ }), additionalContent.map(function (c, index) {
65
+ return /*#__PURE__*/_react.default.createElement(_InformationItem.default, {
66
+ key: "additional" + index,
67
+ label: c.label,
68
+ children: c.content
69
+ });
70
+ }));
71
+ return registry;
72
+ };
73
+ __signature__(Registry, "useIntl{{ formatDate }}\nuseStyles{classes}", function () {
74
+ return [_reactIntl.useIntl, useStyles];
75
+ });
76
+ __signature__(Registry, "useIntl{{ formatDate }}\nuseStyles{classes}", function () {
77
+ return [_reactIntl.useIntl, useStyles];
78
+ });
79
+ var _default = Registry;
80
+ var _default2 = _default;
81
+ var _default3 = exports.default = _default2;
82
+ ;
83
+ (function () {
84
+ var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined;
85
+ if (!reactHotLoader) {
86
+ return;
87
+ }
88
+ reactHotLoader.register(useStyles, "useStyles", "/home/vsts/work/1/s/src/components/Registry.js");
89
+ reactHotLoader.register(Registry, "Registry", "/home/vsts/work/1/s/src/components/Registry.js");
90
+ reactHotLoader.register(_default, "default", "/home/vsts/work/1/s/src/components/Registry.js");
91
+ })();
92
+ ;
93
+ (function () {
94
+ var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined;
95
+ leaveModule && leaveModule(module);
96
+ })();
97
+ ;
98
+ (function () {
99
+ var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined;
100
+ if (!reactHotLoader) {
101
+ return;
102
+ }
103
+ reactHotLoader.register(useStyles, "useStyles", "/home/vsts/work/1/s/src/components/Registry.js");
104
+ reactHotLoader.register(Registry, "Registry", "/home/vsts/work/1/s/src/components/Registry.js");
105
+ reactHotLoader.register(_default2, "default", "/home/vsts/work/1/s/src/components/Registry.js");
106
+ })();
107
+ ;
108
+ (function () {
109
+ var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined;
110
+ leaveModule && leaveModule(module);
111
+ })();
@@ -49,11 +49,14 @@ var useMultipleFieldEditState = function useMultipleFieldEditState(entityId, sec
49
49
  var dispatch = (0, _useDispatchWithModulesData.useDispatchWithModulesData)();
50
50
  var mergedValidationRules = _objectSpread(_objectSpread({}, _modelValidationHelper.validationRules), extendedValidationRules);
51
51
  var modifiedStates = (0, _reactRedux.useSelector)((0, _view.getModifiedModels)(entityId))[sectionName] || {};
52
- var useDynamicFieldState = function useDynamicFieldState(id, fieldName, errorTypes) {
52
+ var useDynamicFieldState = function useDynamicFieldState(id, fieldName, errorTypes, fieldDependencies) {
53
53
  var _initialValues$id$fie, _initialValues$id, _modifiedStates$id$fi, _modifiedStates$id, _editState$value;
54
54
  if (errorTypes === void 0) {
55
55
  errorTypes = [];
56
56
  }
57
+ if (fieldDependencies === void 0) {
58
+ fieldDependencies = {};
59
+ }
57
60
  var keys = [id, fieldName];
58
61
  var initialValue = (_initialValues$id$fie = (_initialValues$id = initialValues[id]) == null ? void 0 : _initialValues$id[fieldName]) != null ? _initialValues$id$fie : "";
59
62
  var editState = (_modifiedStates$id$fi = (_modifiedStates$id = modifiedStates[id]) == null ? void 0 : _modifiedStates$id[fieldName]) != null ? _modifiedStates$id$fi : {};
@@ -65,17 +68,23 @@ var useMultipleFieldEditState = function useMultipleFieldEditState(entityId, sec
65
68
  var resetEditState = function resetEditState() {
66
69
  dispatch(_view2.setEditModelField, [keys, initialValue, initialValue, entityId, sectionName]);
67
70
  };
68
- var isEditStateValid = function isEditStateValid(value) {
71
+ var isEditStateValid = function isEditStateValid(value, dependencies) {
72
+ if (dependencies === void 0) {
73
+ dependencies = {};
74
+ }
69
75
  var valueToValidate = value != null ? value : editState.value;
70
76
  var hasAnyValidationErrors = false;
71
77
  errorTypes.forEach(function (errorType) {
72
- var isValid = mergedValidationRules[errorType](valueToValidate, id, fieldName);
78
+ var isValid = mergedValidationRules[errorType](valueToValidate, id, fieldName, _objectSpread(_objectSpread({}, fieldDependencies), dependencies));
73
79
  if (isValid === false) {
74
80
  dispatch(_view2.setEditModelFieldError, [keys, errorType, entityId, sectionName]);
75
81
  hasAnyValidationErrors = true;
76
82
  return;
77
83
  }
78
84
  });
85
+ if (!hasAnyValidationErrors) {
86
+ dispatch(_view2.removeEditModelFieldError, [keys, entityId, sectionName]);
87
+ }
79
88
  return !hasAnyValidationErrors;
80
89
  };
81
90
  return {
@@ -293,6 +293,26 @@ var sharedMessages = (0, _reactIntl.defineMessages)({
293
293
  valueTypeWrapperFalse: {
294
294
  id: "orc-shared.valueTypeWrapperFalse",
295
295
  defaultMessage: "False"
296
+ },
297
+ registry: {
298
+ id: "orc-shared.registry",
299
+ defaultMessage: "Registry"
300
+ },
301
+ created: {
302
+ id: "orc-shared.created",
303
+ defaultMessage: "Date Created"
304
+ },
305
+ createdBy: {
306
+ id: "orc-shared.createdBy",
307
+ defaultMessage: "Created By"
308
+ },
309
+ lastModified: {
310
+ id: "orc-shared.lastModified",
311
+ defaultMessage: "Last Modified"
312
+ },
313
+ lastModifiedBy: {
314
+ id: "orc-shared.lastModifiedBy",
315
+ defaultMessage: "Last Modified By"
296
316
  }
297
317
  });
298
318
  var _default = sharedMessages;
@@ -29,7 +29,9 @@ var customDataType = exports.customDataType = {
29
29
  password: "Password",
30
30
  carrierProviderSelector: "CarrierProviderSelector",
31
31
  routingProviderSelector: "RoutingProviderSelector",
32
- multipleCarrierProvidersSelector: "MultipleCarrierProvidersSelector"
32
+ multipleCarrierProvidersSelector: "MultipleCarrierProvidersSelector",
33
+ serviceLevelSelector: "ServiceLevelSelector",
34
+ percentageDecimal: "PercentageDecimal"
33
35
  };
34
36
  var tieredAttributeTypes = [customDataType.priceTieredRateTable, customDataType.quantityTieredRateTable];
35
37
  var isTieredAttribute = exports.isTieredAttribute = function isTieredAttribute(attribute) {
@@ -77,15 +79,16 @@ var toJsonCargo = exports.toJsonCargo = function toJsonCargo(attribute, value) {
77
79
  case customDataType.money:
78
80
  return createJsonCargo(_constants.jsonCargoType.double, Number(formatNumber(value, 2)));
79
81
  case customDataType.moneyDecimal:
82
+ case customDataType.percentageDecimal:
80
83
  return createJsonCargo(_constants.jsonCargoType.decimal, Number(formatNumber(value, 2)));
81
84
  case customDataType.priceTieredRateTable:
82
85
  case customDataType.quantityTieredRateTable:
83
86
  return createTieredTableJsonCargo(value);
84
87
  case customDataType.password:
85
- case customDataType.carrierProviderSelector: // To be properly handled when user story 61801 will be addressed
86
- case customDataType.routingProviderSelector: // To be properly handled when user story 61801 will be addressed
88
+ case customDataType.carrierProviderSelector:
89
+ case customDataType.routingProviderSelector:
87
90
  case customDataType.multipleCarrierProvidersSelector:
88
- // To be properly handled when user story 61801 will be addressed
91
+ case customDataType.serviceLevelSelector:
89
92
  return value;
90
93
  default:
91
94
  throw new Error("toJsonCargo: attribute.customDataType ".concat(attribute.customDataType, " is not implemented"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orc-shared",
3
- "version": "5.9.0-dev.8",
3
+ "version": "5.9.0",
4
4
  "description": "Shared code for Orckestra applications",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
@@ -55,7 +55,7 @@
55
55
  "@testing-library/react": "^10.4.9"
56
56
  },
57
57
  "dependencies": {
58
- "orc-scripts": "^4.0.3",
58
+ "orc-scripts": "4.0.4",
59
59
  "react-number-format": "^5.3.0"
60
60
  },
61
61
  "sideEffects": false,
@@ -87,6 +87,16 @@ export const useStyles = makeStyles(theme => ({
87
87
  backgroundColor: `${theme.palette.grey.borders} !important`,
88
88
  },
89
89
  },
90
+ container: {
91
+ display: "flex",
92
+ flexDirection: "column",
93
+ },
94
+ errorText: {
95
+ marginTop: theme.spacing(0.5),
96
+ color: theme.palette.error.main,
97
+ fontSize: theme.typography.fieldLabelSize,
98
+ float: "left",
99
+ },
90
100
  }));
91
101
 
92
102
  const Switch = ({ switchProps }) => {
@@ -100,6 +110,7 @@ const Switch = ({ switchProps }) => {
100
110
  const value = switchProps?.get(SwitchProps.propNames.value) || false;
101
111
  const onCaption = switchProps?.get(SwitchProps.propNames.onCaption);
102
112
  const offCaption = switchProps?.get(SwitchProps.propNames.offCaption);
113
+ const error = switchProps?.get(SwitchProps.propNames.error);
103
114
  const disabled = switchProps?.get(SwitchProps.propNames.disabled) || false;
104
115
  const readOnly = switchProps?.get(SwitchProps.propNames.readOnly);
105
116
  const className = switchProps?.get(SwitchProps.propNames.className) || "";
@@ -120,7 +131,7 @@ const Switch = ({ switchProps }) => {
120
131
  ...className,
121
132
  };
122
133
 
123
- return (
134
+ const switchComponent = (
124
135
  <SwitchMui
125
136
  disabled={disabled}
126
137
  classes={switchClasses}
@@ -129,6 +140,16 @@ const Switch = ({ switchProps }) => {
129
140
  color={"primary"}
130
141
  />
131
142
  );
143
+
144
+ return (
145
+ (error && (
146
+ <div className={classes.container}>
147
+ {switchComponent}
148
+ <div className={classNames(classes.errorText)}>{error}</div>
149
+ </div>
150
+ )) ||
151
+ switchComponent
152
+ );
132
153
  };
133
154
 
134
155
  export default Switch;
@@ -60,6 +60,29 @@ describe("Switch Component", () => {
60
60
  expect(mountedComponent.containsMatchingElement(expected), "to be truthy");
61
61
  });
62
62
 
63
+ it("Renders Switch component with an error", () => {
64
+ const switchProps = new SwitchProps();
65
+
66
+ switchProps.set(SwitchProps.propNames.update, update);
67
+ switchProps.set(SwitchProps.propNames.value, true);
68
+ switchProps.set(SwitchProps.propNames.error, "an error");
69
+ switchProps.set(SwitchProps.propNames.onCaption, { id: "captionOn" });
70
+ switchProps.set(SwitchProps.propNames.offCaption, { id: "captionOff" });
71
+
72
+ const component = (
73
+ <IntlProvider messages={messages} locale="en-US">
74
+ <Switch switchProps={switchProps} />
75
+ </IntlProvider>
76
+ );
77
+
78
+ const mountedComponent = mount(component);
79
+ const expectedSwitch = <SwitchMUI checked={true} />;
80
+ const expectedError = <div>an error</div>;
81
+
82
+ expect(mountedComponent.containsMatchingElement(expectedSwitch), "to be truthy");
83
+ expect(mountedComponent.containsMatchingElement(expectedError), "to be truthy");
84
+ });
85
+
63
86
  it("Checkbox component handles check", () => {
64
87
  const switchProps = new SwitchProps();
65
88
 
@@ -10,6 +10,7 @@ class SwitchProps extends ComponentProps {
10
10
  readOnly: "readOnly",
11
11
  className: "className",
12
12
  id: "id",
13
+ error: "error",
13
14
  metadata: "metadata",
14
15
  };
15
16
 
@@ -23,6 +24,7 @@ class SwitchProps extends ComponentProps {
23
24
  this.componentProps.set(this.constructor.propNames.readOnly, null);
24
25
  this.componentProps.set(this.constructor.propNames.className, null);
25
26
  this.componentProps.set(this.constructor.propNames.id, null);
27
+ this.componentProps.set(this.constructor.propNames.error, null);
26
28
  this.componentProps.set(this.constructor.propNames.metadata, null);
27
29
 
28
30
  this._isSwitchProps = true;
@@ -11,6 +11,7 @@ describe("Switch Props", () => {
11
11
  "readOnly",
12
12
  "className",
13
13
  "id",
14
+ "error",
14
15
  "metadata",
15
16
  ];
16
17
 
@@ -27,6 +28,7 @@ describe("Switch Props", () => {
27
28
  "readOnly",
28
29
  "className",
29
30
  "id",
31
+ "error",
30
32
  "metadata",
31
33
  ];
32
34
 
@@ -0,0 +1,106 @@
1
+ import React from "react";
2
+ import { makeStyles } from "@material-ui/core/styles";
3
+ import Menu from "@material-ui/core/Menu";
4
+ import MenuItem from "@material-ui/core/MenuItem";
5
+ import Divider from "./DataDisplay/Divider";
6
+ import DividerProps from "./DataDisplay/dividerProps";
7
+ import Icon from "./DataDisplay/Icon";
8
+ import Button from "@material-ui/core/Button";
9
+
10
+ const useMenuStyles = makeStyles(theme => ({
11
+ menuItem: {
12
+ fontFamily: theme.typography.fontFamily,
13
+ textTransform: "none",
14
+ color: theme.palette.text.primary,
15
+ borderRadius: 0,
16
+ "&:hover": {
17
+ borderRadius: 0,
18
+ boxShadow: "none",
19
+ backgroundColor: theme.palette.primary.light,
20
+ },
21
+ "&:focus, &:active, &.Mui-focusVisible": {
22
+ borderRadius: 0,
23
+ boxShadow: "none",
24
+ outline: "none",
25
+ },
26
+ },
27
+ menu: {
28
+ border: `${theme.spacing(0.1)} solid ${theme.palette.primary.main}`,
29
+ },
30
+ arrowIcon: {
31
+ width: theme.spacing(1),
32
+ height: theme.spacing(1),
33
+ },
34
+ }));
35
+
36
+ const StyledMenu = props => {
37
+ const classes = useMenuStyles();
38
+
39
+ return (
40
+ <Menu
41
+ elevation={0}
42
+ getContentAnchorEl={null}
43
+ anchorOrigin={{
44
+ vertical: "bottom",
45
+ horizontal: "left",
46
+ }}
47
+ transformOrigin={{
48
+ vertical: "top",
49
+ horizontal: "left",
50
+ }}
51
+ classes={{ paper: classes.menu }}
52
+ {...props}
53
+ />
54
+ );
55
+ };
56
+
57
+ const MenuButton = ({ options, label }) => {
58
+ const [anchorEl, setAnchorEl] = React.useState(null);
59
+ const classes = useMenuStyles();
60
+
61
+ const handleClick = event => {
62
+ setAnchorEl(event.currentTarget);
63
+ };
64
+
65
+ const handleClose = () => {
66
+ setAnchorEl(null);
67
+ };
68
+
69
+ const dividerProps = new DividerProps();
70
+ dividerProps.set(DividerProps.propNames.light, true);
71
+ dividerProps.set(DividerProps.propNames.variant, "middle");
72
+ const allDisabled = options?.every(o => o.disabled) ?? true;
73
+ return (
74
+ <>
75
+ <Button
76
+ aria-haspopup="true"
77
+ variant="outlined"
78
+ color="primary"
79
+ disabled={allDisabled}
80
+ onClick={handleClick}
81
+ endIcon={<Icon id="chevron-down" className={classes.arrowIcon} />}
82
+ >
83
+ {label}
84
+ </Button>
85
+ <StyledMenu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}>
86
+ {options?.map(({ key, component, disabled, action }, index) => (
87
+ <div key={key}>
88
+ <MenuItem
89
+ onClick={() => {
90
+ handleClose();
91
+ action?.();
92
+ }}
93
+ disabled={disabled}
94
+ classes={{ root: classes.menuItem }}
95
+ >
96
+ {component}
97
+ </MenuItem>
98
+ {index < options.length - 1 && <Divider dividerProps={dividerProps} />}
99
+ </div>
100
+ ))}
101
+ </StyledMenu>
102
+ </>
103
+ );
104
+ };
105
+
106
+ export default MenuButton;
@@ -0,0 +1,74 @@
1
+ import React from "react";
2
+ import MenuButton from "./MenuButtons";
3
+ import Button from "@material-ui/core/Button";
4
+ import Menu from "@material-ui/core/Menu";
5
+ import Icon from "./DataDisplay/Icon";
6
+ import sinon from "sinon";
7
+ import ReactDOM from "react-dom";
8
+
9
+ describe("MenuButton", () => {
10
+ it("Renders MenuButton with no options", () => {
11
+ const menuItems = [
12
+ {
13
+ disabled: true,
14
+ },
15
+ {
16
+ disabled: true,
17
+ },
18
+ ];
19
+
20
+ const component = <MenuButton label={<p>Label</p>} options={menuItems} />;
21
+
22
+ const expected = (
23
+ <>
24
+ <Button disabled={true} variant="outlined" color="primary" endIcon={<Icon id="chevron-down" />}>
25
+ <p>Label</p>
26
+ </Button>
27
+ <Menu open={false}></Menu>
28
+ </>
29
+ );
30
+
31
+ expect(component, "when mounted", "to satisfy", expected);
32
+ });
33
+
34
+ it("Renders MenuButton with all options disabled", () => {
35
+ const component = <MenuButton label={<p>Label</p>} />;
36
+
37
+ const expected = (
38
+ <>
39
+ <Button disabled={true} variant="outlined" color="primary" endIcon={<Icon id="chevron-down" />}>
40
+ <p>Label</p>
41
+ </Button>
42
+ <Menu open={false}></Menu>
43
+ </>
44
+ );
45
+
46
+ expect(component, "when mounted", "to satisfy", expected);
47
+ });
48
+
49
+ it("Call option set in menu item", () => {
50
+ const menuItems = [
51
+ {
52
+ action: sinon.spy().named("action"),
53
+ },
54
+ ];
55
+
56
+ const container = document.createElement("div");
57
+ document.body.appendChild(container);
58
+ ReactDOM.render(<MenuButton options={menuItems} />, container);
59
+
60
+ const clickEvent = new MouseEvent("click", {
61
+ bubbles: true,
62
+ cancelable: false,
63
+ });
64
+
65
+ const button = container.querySelector("button");
66
+ button.dispatchEvent(clickEvent);
67
+
68
+ const items = document.querySelectorAll(".MuiListItem-root");
69
+ expect(items, "to have length", 1);
70
+
71
+ items[0].dispatchEvent(clickEvent);
72
+ expect(menuItems[0].action, "was called");
73
+ });
74
+ });
@@ -47,6 +47,13 @@ const DropDownMenu = ({ payload, menuItems, children, dropDownMenuProps = new Dr
47
47
  setAnchorEl(null);
48
48
  };
49
49
 
50
+ // Even though we do nothing, we need to avoid mouse event propagation when the mouse
51
+ // button is released after hovering out the menu
52
+ const onMainMenuClick = event => {
53
+ event.preventDefault();
54
+ event.stopPropagation();
55
+ };
56
+
50
57
  const onMenuItemClick = (action, itemContext) => event => {
51
58
  onClose(event);
52
59
  action(payload, itemContext);
@@ -76,6 +83,7 @@ const DropDownMenu = ({ payload, menuItems, children, dropDownMenuProps = new Dr
76
83
  classes={{ paper: classes.menu }}
77
84
  id="scope-menu"
78
85
  open={isOpened}
86
+ onClick={onMainMenuClick}
79
87
  onClose={onClose}
80
88
  autoFocus={autoFocus}
81
89
  anchorEl={anchorEl}
@@ -8,6 +8,7 @@ import Icon from "../DataDisplay/Icon";
8
8
  import DropDownMenu from "./DropDownMenu";
9
9
  import { ignoreConsoleError } from "../../../utils/testUtils";
10
10
  import { TestWrapper, createMuiTheme } from "./../../../utils/testUtils";
11
+ import Menu from "@material-ui/core/Menu";
11
12
 
12
13
  describe("DropDownMenu", () => {
13
14
  let store, menuItems, container;
@@ -92,4 +93,27 @@ describe("DropDownMenu", () => {
92
93
  expect(menuItems[0].action, "to have calls satisfying", [{ args: [payload, "aContext"] }]);
93
94
  expect(menuItems[1].action, "to have calls satisfying", [{ args: [payload, "myContext"] }]);
94
95
  });
96
+
97
+ it("should handle onClick event on the menu", () => {
98
+ const payload = "payload";
99
+
100
+ const component = (
101
+ <Provider store={store}>
102
+ <DropDownMenu payload={payload} menuItems={menuItems} />
103
+ </Provider>
104
+ );
105
+
106
+ const mountedComponent = mount(component);
107
+
108
+ const event = {
109
+ preventDefault: sinon.spy().named("preventDefault"),
110
+ stopPropagation: sinon.spy().named("stopPropagation"),
111
+ };
112
+
113
+ const dropDownMenu = mountedComponent.find(Menu).at(0);
114
+ dropDownMenu.invoke("onClick")(event);
115
+
116
+ expect(event.preventDefault, "was called");
117
+ expect(event.stopPropagation, "was called");
118
+ });
95
119
  });
@@ -0,0 +1,42 @@
1
+ import React from "react";
2
+ import InformationItem from "./MaterialUI/DataDisplay/PredefinedElements/InformationItem";
3
+ import sharedMessages from "../sharedMessages";
4
+ import { useIntl } from "react-intl";
5
+ import Box from "@material-ui/core/Box";
6
+ import { makeStyles } from "@material-ui/core/styles";
7
+
8
+ const useStyles = makeStyles(theme => ({
9
+ registry: {
10
+ "& > div + div": {
11
+ marginTop: theme.spacing(2),
12
+ },
13
+ },
14
+ }));
15
+
16
+ const Registry = ({ dateCreated, createdBy, lastModifiedDate, lastModifiedBy, additionalContent = [] }) => {
17
+ const { formatDate } = useIntl();
18
+ const classes = useStyles();
19
+
20
+ const created = formatDate(dateCreated);
21
+ const lastModified = formatDate(lastModifiedDate);
22
+ 0;
23
+ const registry = (
24
+ <Box className={classes.registry} display="flex" flexDirection="column">
25
+ {dateCreated !== undefined && <InformationItem label={sharedMessages.created} children={created} />}
26
+ {createdBy !== undefined && <InformationItem label={sharedMessages.createdBy} children={createdBy} />}
27
+ {lastModifiedDate !== undefined && (
28
+ <InformationItem label={sharedMessages.lastModified} children={lastModified} />
29
+ )}
30
+ {lastModifiedBy !== undefined && (
31
+ <InformationItem label={sharedMessages.lastModifiedBy} children={lastModifiedBy} />
32
+ )}
33
+ {additionalContent.map((c, index) => (
34
+ <InformationItem key={"additional" + index} label={c.label} children={c.content} />
35
+ ))}
36
+ </Box>
37
+ );
38
+
39
+ return registry;
40
+ };
41
+
42
+ export default Registry;
@@ -0,0 +1,85 @@
1
+ import React from "react";
2
+ import InformationItem from "./MaterialUI/DataDisplay/PredefinedElements/InformationItem";
3
+ import sharedMessages from "~/sharedMessages";
4
+ import Box from "@material-ui/core/Box";
5
+ import Registry from "./Registry";
6
+ import { TestWrapper, createMuiTheme, extractMessages } from "../utils/testUtils";
7
+
8
+ const messages = extractMessages(sharedMessages);
9
+ const theme = createMuiTheme();
10
+
11
+ describe("Registry", () => {
12
+ it("Renders Registry correctly", () => {
13
+ const created = "2020-10-06T16:21:55.5700000Z";
14
+ const createdBy = "Somebody";
15
+ const lastModified = "2020-10-06T16:21:55.5700000Z";
16
+ const lastModifiedBy = "OOE@oco";
17
+
18
+ const component = (
19
+ <TestWrapper intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
20
+ <Registry
21
+ dateCreated={created}
22
+ createdBy={createdBy}
23
+ lastModifiedDate={lastModified}
24
+ lastModifiedBy={lastModifiedBy}
25
+ />
26
+ </TestWrapper>
27
+ );
28
+
29
+ const expected = (
30
+ <TestWrapper intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
31
+ <Box display="flex" flexDirection="column">
32
+ <InformationItem label={sharedMessages.created} children="10/6/2020" />
33
+ <InformationItem label={sharedMessages.createdBy} children={createdBy} />
34
+ <InformationItem label={sharedMessages.lastModified} children="10/6/2020" />
35
+ <InformationItem label={sharedMessages.lastModifiedBy} children={lastModifiedBy} />
36
+ </Box>
37
+ </TestWrapper>
38
+ );
39
+
40
+ expect(component, "when mounted", "to satisfy", expected);
41
+ });
42
+
43
+ it("Renders Registry correctly with additional content", () => {
44
+ const created = "2020-10-06T16:21:55.5700000Z";
45
+ const createdBy = "Somebody";
46
+ const lastModified = "2020-10-06T16:21:55.5700000Z";
47
+ const lastModifiedBy = "OOE@oco";
48
+
49
+ const component = (
50
+ <TestWrapper intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
51
+ <Registry
52
+ dateCreated={created}
53
+ createdBy={createdBy}
54
+ lastModifiedDate={lastModified}
55
+ lastModifiedBy={lastModifiedBy}
56
+ additionalContent={[
57
+ {
58
+ label: sharedMessages.about,
59
+ content: "some date",
60
+ },
61
+ {
62
+ label: sharedMessages.help,
63
+ content: "Hugh Mann",
64
+ },
65
+ ]}
66
+ />
67
+ </TestWrapper>
68
+ );
69
+
70
+ const expected = (
71
+ <TestWrapper intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
72
+ <Box display="flex" flexDirection="column">
73
+ <InformationItem label={sharedMessages.created} children="10/6/2020" />
74
+ <InformationItem label={sharedMessages.createdBy} children={createdBy} />
75
+ <InformationItem label={sharedMessages.lastModified} children="10/6/2020" />
76
+ <InformationItem label={sharedMessages.lastModifiedBy} children={lastModifiedBy} />
77
+ <InformationItem label={sharedMessages.about} children={"some date"} />
78
+ <InformationItem label={sharedMessages.help} children={"Hugh Mann"} />
79
+ </Box>
80
+ </TestWrapper>
81
+ );
82
+
83
+ expect(component, "when mounted", "to satisfy", expected);
84
+ });
85
+ });
@@ -1,7 +1,7 @@
1
1
  import { useSelector } from "react-redux";
2
2
  import { validationRules } from "../utils/modelValidationHelper";
3
3
  import { getModifiedModels } from "../selectors/view";
4
- import { setEditModelField, setEditModelFieldError } from "../actions/view";
4
+ import { setEditModelField, setEditModelFieldError, removeEditModelFieldError } from "../actions/view";
5
5
  import { useDispatchWithModulesData } from "./../hooks/useDispatchWithModulesData";
6
6
 
7
7
  /* This hook is used when a component has a dynamic number of fields that can be edited (e.g.: Orders' Custom Configuration Parameters).
@@ -25,7 +25,7 @@ const useMultipleFieldEditState = (entityId, sectionName, initialValues, extende
25
25
  const mergedValidationRules = { ...validationRules, ...extendedValidationRules };
26
26
  const modifiedStates = useSelector(getModifiedModels(entityId))[sectionName] || {};
27
27
 
28
- const useDynamicFieldState = (id, fieldName, errorTypes = []) => {
28
+ const useDynamicFieldState = (id, fieldName, errorTypes = [], fieldDependencies = {}) => {
29
29
  const keys = [id, fieldName];
30
30
 
31
31
  const initialValue = initialValues[id]?.[fieldName] ?? "";
@@ -42,12 +42,15 @@ const useMultipleFieldEditState = (entityId, sectionName, initialValues, extende
42
42
  dispatch(setEditModelField, [keys, initialValue, initialValue, entityId, sectionName]);
43
43
  };
44
44
 
45
- const isEditStateValid = value => {
45
+ const isEditStateValid = (value, dependencies = {}) => {
46
46
  const valueToValidate = value ?? editState.value;
47
47
 
48
48
  let hasAnyValidationErrors = false;
49
49
  errorTypes.forEach(errorType => {
50
- const isValid = mergedValidationRules[errorType](valueToValidate, id, fieldName);
50
+ const isValid = mergedValidationRules[errorType](valueToValidate, id, fieldName, {
51
+ ...fieldDependencies,
52
+ ...dependencies,
53
+ });
51
54
 
52
55
  if (isValid === false) {
53
56
  dispatch(setEditModelFieldError, [keys, errorType, entityId, sectionName]);
@@ -57,6 +60,10 @@ const useMultipleFieldEditState = (entityId, sectionName, initialValues, extende
57
60
  }
58
61
  });
59
62
 
63
+ if (!hasAnyValidationErrors) {
64
+ dispatch(removeEditModelFieldError, [keys, entityId, sectionName]);
65
+ }
66
+
60
67
  return !hasAnyValidationErrors;
61
68
  };
62
69
 
@@ -5,7 +5,7 @@ import Immutable from "immutable";
5
5
  import sinon from "sinon";
6
6
  import { mount } from "enzyme";
7
7
  import * as useDispatchWithModulesDataMock from "./useDispatchWithModulesData";
8
- import { setEditModelField, setEditModelFieldError } from "./../actions/view";
8
+ import { removeEditModelFieldError, setEditModelField, setEditModelFieldError } from "./../actions/view";
9
9
  import { validationErrorTypes } from "./../constants";
10
10
  import _ from "lodash";
11
11
 
@@ -404,6 +404,54 @@ describe("useMultipleFieldEditState", () => {
404
404
  }
405
405
  });
406
406
 
407
+ it("Updates edit view value and reset error correctly with custom validation rules when validation was passed", () => {
408
+ const useDispatchWithModulesDataSpy = sinon.spy();
409
+ const useDispatchWithModulesDataStub = sinon
410
+ .stub(useDispatchWithModulesDataMock, "useDispatchWithModulesData")
411
+ .returns(useDispatchWithModulesDataSpy);
412
+
413
+ try {
414
+ // TODOJOC
415
+ const mountedComponent = mountComponent();
416
+
417
+ const fieldComponent = mountedComponent.find(`#id1-prop1-update`);
418
+
419
+ const event = {
420
+ target: {
421
+ value: "anotherValue",
422
+ },
423
+ };
424
+
425
+ fieldComponent.invoke("onClick")(event);
426
+
427
+ const resetEvent = {
428
+ target: {
429
+ value: "custom",
430
+ },
431
+ };
432
+
433
+ fieldComponent.invoke("onClick")(resetEvent);
434
+
435
+ const id = "id1";
436
+ const fieldName = "prop1";
437
+ const initialFieldValue = fieldInitialValues[id][fieldName];
438
+
439
+ expect(useDispatchWithModulesDataSpy, "to have a call satisfying", {
440
+ args: [setEditModelField, [[id, fieldName], "anotherValue", initialFieldValue, entityId, sectionName]],
441
+ });
442
+
443
+ expect(useDispatchWithModulesDataSpy, "to have a call satisfying", {
444
+ args: [setEditModelFieldError, [[id, fieldName], "customRule", entityId, sectionName]],
445
+ });
446
+
447
+ expect(useDispatchWithModulesDataSpy, "to have a call satisfying", {
448
+ args: [removeEditModelFieldError, [[id, fieldName], entityId, sectionName]],
449
+ });
450
+ } finally {
451
+ useDispatchWithModulesDataStub.restore();
452
+ }
453
+ });
454
+
407
455
  it.each([
408
456
  ["id1", "prop1"],
409
457
  ["id1", "prop2"],
@@ -279,6 +279,26 @@ const sharedMessages = defineMessages({
279
279
  id: "orc-shared.valueTypeWrapperFalse",
280
280
  defaultMessage: "False",
281
281
  },
282
+ registry: {
283
+ id: "orc-shared.registry",
284
+ defaultMessage: "Registry",
285
+ },
286
+ created: {
287
+ id: "orc-shared.created",
288
+ defaultMessage: "Date Created",
289
+ },
290
+ createdBy: {
291
+ id: "orc-shared.createdBy",
292
+ defaultMessage: "Created By",
293
+ },
294
+ lastModified: {
295
+ id: "orc-shared.lastModified",
296
+ defaultMessage: "Last Modified",
297
+ },
298
+ lastModifiedBy: {
299
+ id: "orc-shared.lastModifiedBy",
300
+ defaultMessage: "Last Modified By",
301
+ },
282
302
  });
283
303
 
284
304
  export default sharedMessages;
@@ -14,6 +14,8 @@
14
14
  "orc-shared.confirmation": "Confirmation",
15
15
  "orc-shared.copyright": "© {year} Orckestra Technologies Inc.",
16
16
  "orc-shared.copyrightTermsNotice": "This computer program is protected by copyright laws and international treaties. Unauthorized reproduction or redistribution of this program, or any portion of it, may result in severe civil and criminal penalties, and will be prosecuted to the maximum extent possible under the law. Orckestra is a trademark of Orckestra Technologies Inc. All other trademarks are property of the respective owners.",
17
+ "orc-shared.created": "Date Created",
18
+ "orc-shared.createdBy": "Created By",
17
19
  "orc-shared.dataTypeBoolean": "Yes/No Choice",
18
20
  "orc-shared.dataTypeDate": "Date/Calendar",
19
21
  "orc-shared.dataTypeDecimal": "Decimal Number",
@@ -37,6 +39,8 @@
37
39
  "orc-shared.inactive": "Inactive",
38
40
  "orc-shared.internetExplorerWarningContent": "You are using a browser that we no longer support. For a better experience with our HTML web applications, we recommend you to use the latest version of one of the following browsers:",
39
41
  "orc-shared.internetExplorerWarningTitle": "Improve your experience",
42
+ "orc-shared.lastModified": "Last Modified",
43
+ "orc-shared.lastModifiedBy": "Last Modified By",
40
44
  "orc-shared.needToRefresh": "You are not authorized to execute a request. Click refresh to reload the application.",
41
45
  "orc-shared.next": "Next",
42
46
  "orc-shared.no": "No",
@@ -46,6 +50,7 @@
46
50
  "orc-shared.orcSharedVersion": "Orc-Shared Framework {version}",
47
51
  "orc-shared.preferences": "Preferences",
48
52
  "orc-shared.refresh": "Refresh",
53
+ "orc-shared.registry": "Registry",
49
54
  "orc-shared.remove": "Remove",
50
55
  "orc-shared.save": "Save",
51
56
  "orc-shared.scopeChangeWithOpenedTabsConfirmation": "One or more entities opened will be closed. Would you like to change scope now?",
@@ -14,6 +14,8 @@
14
14
  "orc-shared.confirmation": "Confirmation",
15
15
  "orc-shared.copyright": "© {year} Technologies Orckestra Inc.",
16
16
  "orc-shared.copyrightTermsNotice": "Avertissement: Ce programme est protégé par la loi relative au droit d'auteur et par les conventions internationales. Toute reproduction ou distribution partielle ou totale du logiciel, par quelque moyen que ce soit, est strictement interdite. Toute personne ne respectant pas ces dispositions se rendra coupable du délit de contrefaçon et sera passible des sanctions pénales prévues par la loi. Orckestra est une marque de commerce déposée et détenue par Technologies Orckestra Inc. Toutes les autres marques de commerce sont la propriété de leurs détenteurs respectifs.",
17
+ "orc-shared.created": "Date de création",
18
+ "orc-shared.createdBy": "Créé par",
17
19
  "orc-shared.dataTypeBoolean": "Choix Oui/Non",
18
20
  "orc-shared.dataTypeDate": "Date/Calendrier",
19
21
  "orc-shared.dataTypeDecimal": "Nombre décimal",
@@ -37,6 +39,8 @@
37
39
  "orc-shared.inactive": "Inactif",
38
40
  "orc-shared.internetExplorerWarningContent": "Vous utilisez un navigateur qui n'est plus supporté. Pour assurer une expérience optimale de nos applications web HTML, nous vous recommendons d'utiliser la dernière version des navigateurs suivants:",
39
41
  "orc-shared.internetExplorerWarningTitle": "Améliorez votre expérience",
42
+ "orc-shared.lastModified": "Dernière date de modification",
43
+ "orc-shared.lastModifiedBy": "Modifié par",
40
44
  "orc-shared.needToRefresh": "Vous n'êtes pas autorisé à effectuer une requête. Veuillez cliquer sur Rafraîchir pour rafraîchir l’application.",
41
45
  "orc-shared.next": "Suivant",
42
46
  "orc-shared.no": "Non",
@@ -46,6 +50,7 @@
46
50
  "orc-shared.orcSharedVersion": "Infrastructure Orc-Shared {version}",
47
51
  "orc-shared.preferences": "Préférences",
48
52
  "orc-shared.refresh": "Rafraîchir",
53
+ "orc-shared.registry": "Régistre",
49
54
  "orc-shared.remove": "Retirer",
50
55
  "orc-shared.save": "Sauvegarder",
51
56
  "orc-shared.scopeChangeWithOpenedTabsConfirmation": "Une ou plusieurs entités ouvertes seront fermées. Voulez-vous vraiment changer de Scope?",
@@ -18,6 +18,8 @@ export const customDataType = {
18
18
  carrierProviderSelector: "CarrierProviderSelector",
19
19
  routingProviderSelector: "RoutingProviderSelector",
20
20
  multipleCarrierProvidersSelector: "MultipleCarrierProvidersSelector",
21
+ serviceLevelSelector: "ServiceLevelSelector",
22
+ percentageDecimal: "PercentageDecimal",
21
23
  };
22
24
 
23
25
  const tieredAttributeTypes = [customDataType.priceTieredRateTable, customDataType.quantityTieredRateTable];
@@ -72,14 +74,16 @@ export const toJsonCargo = (attribute, value) => {
72
74
  case customDataType.money:
73
75
  return createJsonCargo(jsonCargoType.double, Number(formatNumber(value, 2)));
74
76
  case customDataType.moneyDecimal:
77
+ case customDataType.percentageDecimal:
75
78
  return createJsonCargo(jsonCargoType.decimal, Number(formatNumber(value, 2)));
76
79
  case customDataType.priceTieredRateTable:
77
80
  case customDataType.quantityTieredRateTable:
78
81
  return createTieredTableJsonCargo(value);
79
82
  case customDataType.password:
80
- case customDataType.carrierProviderSelector: // To be properly handled when user story 61801 will be addressed
81
- case customDataType.routingProviderSelector: // To be properly handled when user story 61801 will be addressed
82
- case customDataType.multipleCarrierProvidersSelector: // To be properly handled when user story 61801 will be addressed
83
+ case customDataType.carrierProviderSelector:
84
+ case customDataType.routingProviderSelector:
85
+ case customDataType.multipleCarrierProvidersSelector:
86
+ case customDataType.serviceLevelSelector:
83
87
  return value;
84
88
  default:
85
89
  throw new Error(`toJsonCargo: attribute.customDataType ${attribute.customDataType} is not implemented`);