config-editor-base 3.1.3 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
3
3
  import classNames from 'classnames';
4
4
  import validator from '@rjsf/validator-ajv6';
5
5
  import Form from '@rjsf/core';
6
- import saveAs from 'file-saver';
6
+ import saveAs, { saveAs as saveAs$1 } from 'file-saver';
7
7
  import Select from 'react-select';
8
8
  import Files from 'react-files';
9
9
  import applyNav, { GENERIC_NAV } from 'rjsf-tabs';
@@ -147,7 +147,7 @@ var loadFile = function loadFile(fileName) {
147
147
  var _require = require('detect-browser'),
148
148
  detect = _require.detect;
149
149
  var browser = detect();
150
- var crcBrowserSupport = ['chrome', 'firefox', 'opera', 'safari', 'edge'].includes(browser.name);
150
+ var crcBrowserSupport = ['chrome', 'firefox', 'opera', 'safari', 'edge'].includes(browser && browser.name);
151
151
 
152
152
  var SET_SCHEMA_LIST = "editor/SET_SCHEMA_LIST";
153
153
  var SET_CONFIG_LIST = "editor/SET_CONFIG_LIST";
@@ -1291,6 +1291,19 @@ var runConfigurationWarningChecks = function runConfigurationWarningChecks(conte
1291
1291
  dispatch(checkCANmodMonitoringMode(content));
1292
1292
  };
1293
1293
  };
1294
+ var collectConfigurationWarnings = function collectConfigurationWarnings(content) {
1295
+ var messages = [];
1296
+ var _capture = function capture(action) {
1297
+ if (typeof action === "function") return action(_capture, function () {
1298
+ return {};
1299
+ });
1300
+ if (action && action.type === "alert/SET" && action.alert && action.alert.type === "warning") {
1301
+ messages.push(action.alert.message);
1302
+ }
1303
+ };
1304
+ _capture(runConfigurationWarningChecks(content));
1305
+ return messages;
1306
+ };
1294
1307
  var checkCANmodMonitoringMode = function checkCANmodMonitoringMode(content) {
1295
1308
  return function (dispatch) {
1296
1309
  var _content$phy, _content$phy$can, _content$phy$can$phy;
@@ -1430,6 +1443,7 @@ var actions = {
1430
1443
  checkFileSplitValue: checkFileSplitValue,
1431
1444
  checkGNSSEstimate: checkGNSSEstimate,
1432
1445
  runConfigurationWarningChecks: runConfigurationWarningChecks,
1446
+ collectConfigurationWarnings: collectConfigurationWarnings,
1433
1447
  checkCANmodMonitoringMode: checkCANmodMonitoringMode,
1434
1448
  saveUpdatedConfiguration: saveUpdatedConfiguration,
1435
1449
  setUpdatedFormData: setUpdatedFormData,
@@ -18935,11 +18949,9 @@ var PartialConfigLoader = /*#__PURE__*/function (_React$Component) {
18935
18949
  var _this$props = this.props,
18936
18950
  formData = _this$props.formData,
18937
18951
  schemaContent = _this$props.schemaContent;
18938
- return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h4", null, "Partial config loader"), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
18952
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h4", null, "Partial config loader"), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
18939
18953
  className: "form-group pl0 field-string"
18940
18954
  }, /*#__PURE__*/React.createElement("p", {
18941
- className: "reduced-margin"
18942
- }, "Upload partial Configuration File"), /*#__PURE__*/React.createElement("p", {
18943
18955
  className: "field-description field-description-shift"
18944
18956
  }, "Select a JSON file containing a partial Configuration File. This lets you e.g. load a list of transmit messages or filters. The loaded JSON is validated vs. the Rule Schema, after which it can be merged into the editor Configuration File (even if it is not valid)")), /*#__PURE__*/React.createElement("div", null, formData ? /*#__PURE__*/React.createElement("div", {
18945
18957
  className: "text-area-wrapper row no-gutters reduced-margin"
@@ -18958,10 +18970,13 @@ var PartialConfigLoader = /*#__PURE__*/function (_React$Component) {
18958
18970
  minFileSize: 0,
18959
18971
  clickable: true
18960
18972
  }, /*#__PURE__*/React.createElement("button", {
18961
- className: "btn btn-primary"
18973
+ className: "btn btn-primary",
18974
+ title: "Upload a partial Configuration File to merge it"
18962
18975
  }, "Load JSON file"), /*#__PURE__*/React.createElement("div", {
18963
18976
  className: "browse-file-name"
18964
- }, jsonFileName))), Object.keys(jsonFile).length ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("pre", {
18977
+ }, jsonFileName))), Object.keys(jsonFile).length ? /*#__PURE__*/React.createElement("div", {
18978
+ className: "text-area-wrapper row no-gutters"
18979
+ }, /*#__PURE__*/React.createElement("pre", {
18965
18980
  className: "browse-file-preview"
18966
18981
  }, JSON.stringify(jsonFile, null, 2)), formData ? /*#__PURE__*/React.createElement("div", null, mergedConfigValid ? /*#__PURE__*/React.createElement("div", {
18967
18982
  className: "btn-highlight",
@@ -19156,6 +19171,57 @@ function ArrayFieldTemplate(props) {
19156
19171
  }), " "))));
19157
19172
  }
19158
19173
 
19174
+ var isPlainObject = function isPlainObject(value) {
19175
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
19176
+ };
19177
+ var jsonEqual = function jsonEqual(a, b) {
19178
+ return JSON.stringify(a) === JSON.stringify(b);
19179
+ };
19180
+ var clone = function clone(value) {
19181
+ return JSON.parse(JSON.stringify(value));
19182
+ };
19183
+ var computeConfigDelta = function computeConfigDelta(past, current) {
19184
+ var deletions = [];
19185
+ if (!isPlainObject(past) || !isPlainObject(current)) {
19186
+ return {
19187
+ partial: isPlainObject(current) ? clone(current) : {},
19188
+ deletions: deletions
19189
+ };
19190
+ }
19191
+ var _walk = function walk(pastNode, currentNode, path) {
19192
+ var partialNode = {};
19193
+ Object.keys(currentNode).forEach(function (key) {
19194
+ var childPath = path ? path + '.' + key : key;
19195
+ var pastValue = pastNode[key];
19196
+ var currentValue = currentNode[key];
19197
+ if (!(key in pastNode)) {
19198
+ partialNode[key] = clone(currentValue);
19199
+ } else if (isPlainObject(pastValue) && isPlainObject(currentValue)) {
19200
+ var childPartial = _walk(pastValue, currentValue, childPath);
19201
+ if (Object.keys(childPartial).length) {
19202
+ partialNode[key] = childPartial;
19203
+ }
19204
+ } else if (!jsonEqual(pastValue, currentValue)) {
19205
+ if (Array.isArray(pastValue) && isPlainObject(currentValue)) {
19206
+ deletions.push(childPath);
19207
+ } else {
19208
+ partialNode[key] = clone(currentValue);
19209
+ }
19210
+ }
19211
+ });
19212
+ Object.keys(pastNode).forEach(function (key) {
19213
+ if (!(key in currentNode)) {
19214
+ deletions.push(path ? path + '.' + key : key);
19215
+ }
19216
+ });
19217
+ return partialNode;
19218
+ };
19219
+ return {
19220
+ partial: _walk(past, current, ''),
19221
+ deletions: deletions
19222
+ };
19223
+ };
19224
+
19159
19225
  var selectOptions$1 = function selectOptions(Files) {
19160
19226
  Files = lodash.orderBy(Files, ["name"], ["desc"]);
19161
19227
  return [].concat(Files, [{
@@ -19171,7 +19237,7 @@ var pastCrc32 = "N/A";
19171
19237
  var _require$1 = require("detect-browser"),
19172
19238
  detect$1 = _require$1.detect;
19173
19239
  var browser$1 = detect$1();
19174
- var crcBrowserSupport$1 = ["chrome", "firefox", "opera", "safari", "edge"].includes(browser$1.name);
19240
+ var crcBrowserSupport$1 = ["chrome", "firefox", "opera", "safari", "edge"].includes(browser$1 && browser$1.name);
19175
19241
  var EditorChangesComparison = /*#__PURE__*/function (_React$Component) {
19176
19242
  function EditorChangesComparison(props) {
19177
19243
  var _this;
@@ -19184,6 +19250,68 @@ var EditorChangesComparison = /*#__PURE__*/function (_React$Component) {
19184
19250
  _this.handleSelectChange = function (selectedValue) {
19185
19251
  _this.props.handleDropdownChange(selectedValue.value, "Previous Configuration File");
19186
19252
  };
19253
+ _this.getPartialDelta = function () {
19254
+ var _this$props = _this.props,
19255
+ past = _this$props.past,
19256
+ current = _this$props.current,
19257
+ showAlert = _this$props.showAlert;
19258
+ var pastObj = null;
19259
+ try {
19260
+ pastObj = JSON.parse(past);
19261
+ } catch (e) {
19262
+ pastObj = null;
19263
+ }
19264
+ if (!pastObj || typeof pastObj !== "object") {
19265
+ if (showAlert) {
19266
+ showAlert("info", "Select a Previous Configuration File first");
19267
+ }
19268
+ return null;
19269
+ }
19270
+ var _computeConfigDelta = computeConfigDelta(pastObj, current),
19271
+ partial = _computeConfigDelta.partial,
19272
+ deletions = _computeConfigDelta.deletions;
19273
+ if (!Object.keys(partial).length) {
19274
+ if (showAlert) {
19275
+ showAlert("info", "No changes detected vs. the Previous Configuration File");
19276
+ }
19277
+ return null;
19278
+ }
19279
+ if (deletions.length && showAlert) {
19280
+ showAlert("warning", deletions.length + " deleted setting(s) cannot be expressed in a partial config and were excluded: " + deletions.join(", "));
19281
+ }
19282
+ return {
19283
+ partial: partial,
19284
+ deletions: deletions
19285
+ };
19286
+ };
19287
+ _this.onDownloadPartial = function () {
19288
+ var delta = _this.getPartialDelta();
19289
+ if (!delta) {
19290
+ return;
19291
+ }
19292
+ var revisedConfigFile = _this.props.revisedConfigFile;
19293
+ var fileName = "partial-" + (revisedConfigFile && revisedConfigFile.value || "config.json");
19294
+ var blob = new Blob([JSON.stringify(delta.partial, null, 2)], {
19295
+ type: "text/json"
19296
+ });
19297
+ saveAs$1(blob, fileName);
19298
+ };
19299
+ _this.onTransferClick = function () {
19300
+ var delta = _this.getPartialDelta();
19301
+ if (!delta) {
19302
+ return;
19303
+ }
19304
+ var _this$props2 = _this.props,
19305
+ onTransferPartial = _this$props2.onTransferPartial,
19306
+ closeChangesModal = _this$props2.closeChangesModal,
19307
+ revisedConfigFile = _this$props2.revisedConfigFile;
19308
+ closeChangesModal();
19309
+ onTransferPartial({
19310
+ partial: delta.partial,
19311
+ deletions: delta.deletions,
19312
+ configName: revisedConfigFile && revisedConfigFile.value || null
19313
+ });
19314
+ };
19187
19315
  _this.toggleCheckbox = _this.toggleCheckbox.bind(_this);
19188
19316
  _this.handleSelectChange = _this.handleSelectChange.bind(_this);
19189
19317
  _this.state = {
@@ -19194,17 +19322,17 @@ var EditorChangesComparison = /*#__PURE__*/function (_React$Component) {
19194
19322
  _inheritsLoose(EditorChangesComparison, _React$Component);
19195
19323
  var _proto = EditorChangesComparison.prototype;
19196
19324
  _proto.render = function render() {
19197
- var _this$props = this.props,
19198
- options = _this$props.options,
19199
- selected = _this$props.selected,
19200
- past = _this$props.past,
19201
- current = _this$props.current,
19202
- closeChangesModal = _this$props.closeChangesModal,
19203
- revisedConfigFile = _this$props.revisedConfigFile,
19204
- crc32EditorLive = _this$props.crc32EditorLive,
19205
- isCompareChanges = _this$props.isCompareChanges,
19206
- enableDownload = _this$props.enableDownload,
19207
- externalSubmit = _this$props.externalSubmit;
19325
+ var _this$props3 = this.props,
19326
+ options = _this$props3.options,
19327
+ selected = _this$props3.selected,
19328
+ past = _this$props3.past,
19329
+ current = _this$props3.current,
19330
+ closeChangesModal = _this$props3.closeChangesModal,
19331
+ revisedConfigFile = _this$props3.revisedConfigFile,
19332
+ crc32EditorLive = _this$props3.crc32EditorLive,
19333
+ isCompareChanges = _this$props3.isCompareChanges,
19334
+ enableDownload = _this$props3.enableDownload,
19335
+ externalSubmit = _this$props3.externalSubmit;
19208
19336
  var pastCleaned = past && Object.keys(past).length ? JSON.stringify(JSON.parse(past), null, 2) : "";
19209
19337
  if (crcBrowserSupport$1 == 1 && past && Object.keys(past).length) {
19210
19338
  var _require2 = require("crc"),
@@ -19213,6 +19341,15 @@ var EditorChangesComparison = /*#__PURE__*/function (_React$Component) {
19213
19341
  } else {
19214
19342
  pastCrc32 = "N/A";
19215
19343
  }
19344
+ var partialAvailable = false;
19345
+ try {
19346
+ var pastObj = past ? JSON.parse(past) : null;
19347
+ if (pastObj && typeof pastObj === "object") {
19348
+ partialAvailable = Object.keys(computeConfigDelta(pastObj, current).partial).length > 0;
19349
+ }
19350
+ } catch (e) {
19351
+ partialAvailable = false;
19352
+ }
19216
19353
  return /*#__PURE__*/React.createElement("div", {
19217
19354
  className: isCompareChanges ? "show modal-custom-wrapper" : "hidden modal-custom-wrapper"
19218
19355
  }, /*#__PURE__*/React.createElement("div", {
@@ -19289,7 +19426,19 @@ var EditorChangesComparison = /*#__PURE__*/function (_React$Component) {
19289
19426
  type: "submit",
19290
19427
  onClick: enableDownload,
19291
19428
  className: "btn btn-primary ml15"
19292
- }, " ", "Download to disk", " "))));
19429
+ }, " ", "Download to disk", " "), /*#__PURE__*/React.createElement("button", {
19430
+ type: "button",
19431
+ onClick: this.onDownloadPartial,
19432
+ className: "btn btn-white ml15",
19433
+ disabled: !partialAvailable,
19434
+ title: "Download the delta changes as a partial config JSON e.g. for application across multiple devices"
19435
+ }, " ", "Download partial JSON to disk", " "), typeof this.props.onTransferPartial === "function" ? /*#__PURE__*/React.createElement("button", {
19436
+ type: "button",
19437
+ onClick: this.onTransferClick,
19438
+ className: "btn btn-white ml15",
19439
+ disabled: !partialAvailable,
19440
+ title: "Transfer the delta changes as a partial config JSON to the OTA batch manager for application across multiple devices"
19441
+ }, " ", "Transfer to OTA batch manager", " ") : null)));
19293
19442
  };
19294
19443
  return EditorChangesComparison;
19295
19444
  }(React.Component);
@@ -19624,7 +19773,9 @@ var EditorSection = /*#__PURE__*/function (_React$Component) {
19624
19773
  handleDropdownChange: this.handleDropdownChange,
19625
19774
  closeChangesModal: this.closeChangesModal,
19626
19775
  enableDownload: this.enableDownload.bind(this),
19627
- externalSubmit: this.props.fetchFileContentExt ? true : false
19776
+ externalSubmit: this.props.fetchFileContentExt ? true : false,
19777
+ showAlert: this.props.showAlert,
19778
+ onTransferPartial: this.props.onTransferPartial
19628
19779
  }), /*#__PURE__*/React.createElement("div", {
19629
19780
  className: classNames({
19630
19781
  'config-bar': true,
@@ -24914,7 +25065,7 @@ var FilterBuilderTool = /*#__PURE__*/function (_React$Component) {
24914
25065
  style: {
24915
25066
  width: barWidth + "px",
24916
25067
  height: "10px",
24917
- backgroundColor: "#4a90d9",
25068
+ backgroundColor: "#46a5e0",
24918
25069
  borderRadius: "2px",
24919
25070
  display: "inline-block"
24920
25071
  }
@@ -25380,7 +25531,7 @@ var FilterBuilderTool = /*#__PURE__*/function (_React$Component) {
25380
25531
  }
25381
25532
  }, "Select: "), /*#__PURE__*/React.createElement("span", {
25382
25533
  style: {
25383
- color: "#337ab7",
25534
+ color: "#46a5e0",
25384
25535
  cursor: "pointer",
25385
25536
  marginLeft: "4px"
25386
25537
  },
@@ -25394,7 +25545,7 @@ var FilterBuilderTool = /*#__PURE__*/function (_React$Component) {
25394
25545
  }
25395
25546
  }, "|"), /*#__PURE__*/React.createElement("span", {
25396
25547
  style: {
25397
- color: "#337ab7",
25548
+ color: "#46a5e0",
25398
25549
  cursor: "pointer"
25399
25550
  },
25400
25551
  onClick: function onClick() {
@@ -25407,7 +25558,7 @@ var FilterBuilderTool = /*#__PURE__*/function (_React$Component) {
25407
25558
  }
25408
25559
  }, "|"), /*#__PURE__*/React.createElement("span", {
25409
25560
  style: {
25410
- color: "#337ab7",
25561
+ color: "#46a5e0",
25411
25562
  cursor: "pointer"
25412
25563
  },
25413
25564
  onClick: function onClick() {
@@ -25420,7 +25571,7 @@ var FilterBuilderTool = /*#__PURE__*/function (_React$Component) {
25420
25571
  }
25421
25572
  }, "|"), /*#__PURE__*/React.createElement("span", {
25422
25573
  style: {
25423
- color: "#337ab7",
25574
+ color: "#46a5e0",
25424
25575
  cursor: "pointer"
25425
25576
  },
25426
25577
  onClick: function onClick() {
@@ -25745,5 +25896,5 @@ var mapDispatchToProps$4 = function mapDispatchToProps(dispatch) {
25745
25896
  };
25746
25897
  var FilterBuilderTool$1 = connect(mapStateToProps$4, mapDispatchToProps$4)(FilterBuilderTool);
25747
25898
 
25748
- export { EditorSection$1 as EditorSection, FilterBuilderTool$1 as FilterBuilderTool, OBDTool$1 as OBDTool, reducer as editor, actions as editorActions };
25899
+ export { EditorSection$1 as EditorSection, FilterBuilderTool$1 as FilterBuilderTool, OBDTool$1 as OBDTool, computeConfigDelta, reducer as editor, actions as editorActions };
25749
25900
  //# sourceMappingURL=index.modern.js.map