@singularsystems/neo-react 1.0.12 → 1.0.14

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.
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import ComponentBase from './ComponentBase';
3
3
  import { Components } from '@singularsystems/neo-core';
4
- type IButtonProps = Components.IButtonOptions & Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & React.RefAttributes<Button>;
4
+ type IButtonProps = Components.IButtonOptions & Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref" | "onClick"> & React.RefAttributes<Button>;
5
5
  interface IButtonState {
6
6
  isExpanded: boolean;
7
7
  }
@@ -10,7 +10,7 @@ export declare abstract class DropDownBase<T, TProps> extends ComponentBase<TPro
10
10
  protected cachedDataSource: Data.IDataCacheEntry | null;
11
11
  protected fieldInfoContainer: Model.IModelFieldInfoContainer | null;
12
12
  protected getItems(itemSource: ItemSource<T>): T[];
13
- afterRender(): Promise<void>;
13
+ afterRender(isInitial: boolean): Promise<void>;
14
14
  private fieldDisplayInfo;
15
15
  protected setFieldInfo(bindProperty: Model.IPropertyInstance, displayValue: string, readableName?: string): void;
16
16
  }
@@ -52,12 +52,12 @@ var DropDownBase = /** @class */ (function (_super) {
52
52
  }
53
53
  return items;
54
54
  };
55
- DropDownBase.prototype.afterRender = function () {
55
+ DropDownBase.prototype.afterRender = function (isInitial) {
56
56
  return __awaiter(this, void 0, void 0, function () {
57
57
  var _a, bindProperty, displayValue, readableName, fieldInfo;
58
58
  return __generator(this, function (_b) {
59
59
  if (this.cachedDataSource) {
60
- this.dataSource = this.cachedDataSource.get();
60
+ this.dataSource = this.cachedDataSource.get(isInitial);
61
61
  }
62
62
  else if (this.dataSource) {
63
63
  this.dataSource.fetchInitial();
@@ -3,15 +3,17 @@ import { Components, Model } from '@singularsystems/neo-core';
3
3
  interface IFormProps<T extends Model.IModelBase> extends Omit<React.FormHTMLAttributes<HTMLElement>, "children">, Components.IFormOptions<T> {
4
4
  /**
5
5
  * Called when the form is submitted, but the model is not valid.
6
- * The justValidated parameter will be true if the validationDisplayMode is 'AfterSubmit', and this is the first submit attempt.
6
+ * The firstSubmit parameter will be true if this is the first submit attempt for the model.
7
7
  */
8
- onInvalid?: (e: React.FormEvent, justValidated?: boolean) => void;
8
+ onInvalid?: (e?: React.FormEvent, firstSubmit?: boolean) => void;
9
9
  children: React.ReactNode | ((item: T, meta: Model.TransformMetaType<T>) => React.ReactNode);
10
10
  }
11
11
  export default class Form<T extends Model.IModelBase> extends React.Component<IFormProps<T>> {
12
12
  private reactionDisposer?;
13
- private firstSubmit;
13
+ private getModelOrModels;
14
14
  private onSubmit;
15
+ /** Checks if the model is valid, waiting for any async rules to complete. Returns true if the model is valid. */
16
+ validateAsync(): Promise<boolean>;
15
17
  private disposeReaction;
16
18
  componentWillUnmount(): void;
17
19
  render(): React.JSX.Element;
@@ -1,4 +1,4 @@
1
- import { __assign, __decorate, __extends, __rest } from "tslib";
1
+ import { __assign, __awaiter, __decorate, __extends, __generator, __rest } from "tslib";
2
2
  import * as React from 'react';
3
3
  import { observer, Observer } from 'mobx-react';
4
4
  import { Validation, Model, ModalUtils, Misc } from '@singularsystems/neo-core';
@@ -8,59 +8,100 @@ import { FormContextProvider } from './FormContext';
8
8
  var Form = /** @class */ (function (_super) {
9
9
  __extends(Form, _super);
10
10
  function Form() {
11
- var _this = _super !== null && _super.apply(this, arguments) || this;
12
- _this.firstSubmit = true;
13
- return _this;
11
+ return _super !== null && _super.apply(this, arguments) || this;
14
12
  }
15
- Form.prototype.onSubmit = function (e, model) {
16
- var _this = this;
17
- var _a;
18
- e.preventDefault();
19
- e.stopPropagation();
20
- this.disposeReaction();
21
- var canSubmit = true;
22
- // TODO: if the model and none of its children have blurred, justValidated should be true
23
- var justValidated = this.props.validationDisplayMode === Validation.DisplayMode.AfterSubmit && this.firstSubmit;
24
- this.firstSubmit = false;
13
+ Form.prototype.getModelOrModels = function () {
14
+ var model = this.props.model;
25
15
  if (model) {
26
- if (!model.isValid) {
27
- canSubmit = false;
28
- var container = void 0;
29
- if (model instanceof Array) {
30
- container = model;
31
- }
32
- else {
33
- container = [model];
16
+ // Allow binding to ObservableProperty
17
+ if (model.attachedTo && !(model instanceof Array)) {
18
+ return model.attachedTo;
19
+ }
20
+ else {
21
+ return model;
22
+ }
23
+ }
24
+ return undefined;
25
+ };
26
+ Form.prototype.onSubmit = function (e) {
27
+ return __awaiter(this, void 0, void 0, function () {
28
+ var models, isFirstSubmit, isValid;
29
+ return __generator(this, function (_a) {
30
+ switch (_a.label) {
31
+ case 0:
32
+ e.preventDefault();
33
+ e.stopPropagation();
34
+ models = this.getModelOrModels();
35
+ isFirstSubmit = true;
36
+ if (models) {
37
+ Model.GraphTraverser.traverseItems(models, new Model.GraphTraverser.RecursionState(), function (item, state) {
38
+ if (item.validator.forceShowErrors) {
39
+ isFirstSubmit = false;
40
+ }
41
+ else {
42
+ item.validator.forceShowErrors = true;
43
+ }
44
+ });
45
+ }
46
+ return [4 /*yield*/, this.validateAsync()];
47
+ case 1:
48
+ isValid = _a.sent();
49
+ if (isValid) {
50
+ if (this.props.onSubmit)
51
+ this.props.onSubmit(e);
52
+ }
53
+ else {
54
+ if (this.props.onInvalid)
55
+ this.props.onInvalid(e, isFirstSubmit);
56
+ }
57
+ return [2 /*return*/];
34
58
  }
35
- Model.GraphTraverser.traverseItems(container, new Model.GraphTraverser.RecursionState(), function (item, state) {
36
- item.validator.forceShowErrors = true;
37
- });
38
- if (this.props.onInvalid)
39
- this.props.onInvalid(e, justValidated);
40
- if (this.props.showSummaryModal || this.props.invalidSummaryText || this.props.invalidSummaryTitle) {
41
- var onClose = this.disposeReaction.bind(this);
42
- var closeButton = (_a = Misc.Settings.form.validationModalCloseButton) !== null && _a !== void 0 ? _a : { text: "Ok" };
43
- if (closeButton) {
44
- closeButton.onClick = onClose;
59
+ });
60
+ });
61
+ };
62
+ /** Checks if the model is valid, waiting for any async rules to complete. Returns true if the model is valid. */
63
+ Form.prototype.validateAsync = function () {
64
+ var _this = this;
65
+ return new Promise(function (resolve, reject) {
66
+ var _a;
67
+ _this.disposeReaction();
68
+ var isValid = true;
69
+ var modelOrModels = _this.getModelOrModels();
70
+ var models = modelOrModels === undefined ? [] : (modelOrModels instanceof Array ? modelOrModels : [modelOrModels]);
71
+ if (models) {
72
+ var allValid_1 = function () { return models.every(function (c) { return c.isValid; }); };
73
+ var someBusy = function () { return models.some(function (c) { return c.validator.isBusy; }); };
74
+ if (!allValid_1()) {
75
+ isValid = false;
76
+ var codeModal_1 = null;
77
+ if (_this.props.showSummaryModal || _this.props.invalidSummaryText || _this.props.invalidSummaryTitle) {
78
+ var onClose = _this.disposeReaction.bind(_this);
79
+ var closeButton = (_a = Misc.Settings.form.validationModalCloseButton) !== null && _a !== void 0 ? _a : { text: "Ok" };
80
+ if (closeButton) {
81
+ closeButton.onClick = onClose;
82
+ }
83
+ codeModal_1 = ModalUtils.showModal(_this.props.invalidSummaryTitle || "Invalid data", React.createElement(Observer, null, function () {
84
+ return React.createElement("div", null,
85
+ _this.props.invalidSummaryText || "Cannot continue due to the following issues:",
86
+ React.createElement(ValidationSummary, { graph: Validation.getValidationSummary(modelOrModels), hideTopLevelTitle: !(modelOrModels instanceof Array) }));
87
+ }), { onClose: onClose, closeButton: closeButton });
88
+ }
89
+ if (someBusy()) {
90
+ // Async rule is busy, listen for when isBusy changes to false.
91
+ _this.reactionDisposer = reaction(someBusy, function () {
92
+ _this.disposeReaction();
93
+ isValid = allValid_1();
94
+ if (codeModal_1 !== null && isValid) {
95
+ codeModal_1.close();
96
+ }
97
+ resolve(isValid);
98
+ });
99
+ return;
45
100
  }
46
- var codeModal_1 = ModalUtils.showModal(this.props.invalidSummaryTitle || "Invalid data", React.createElement(Observer, null, function () {
47
- return React.createElement("div", null,
48
- _this.props.invalidSummaryText || "Cannot continue due to the following issues:",
49
- React.createElement(ValidationSummary, { graph: Validation.getValidationSummary(model), hideTopLevelTitle: !(model instanceof Array) }));
50
- }), { onClose: onClose, closeButton: closeButton });
51
- // Listen for when isValid changes to true, in case there is an async rule running.
52
- this.reactionDisposer = reaction(function () { return model.isValid; }, function () {
53
- _this.disposeReaction();
54
- codeModal_1.close();
55
- if (model.isValid && _this.props.onSubmit)
56
- _this.props.onSubmit(e);
57
- });
58
101
  }
59
102
  }
60
- }
61
- if (canSubmit && this.props.onSubmit) {
62
- this.props.onSubmit(e);
63
- }
103
+ resolve(isValid);
104
+ });
64
105
  };
65
106
  Form.prototype.disposeReaction = function () {
66
107
  if (this.reactionDisposer) {
@@ -74,17 +115,7 @@ var Form = /** @class */ (function (_super) {
74
115
  Form.prototype.render = function () {
75
116
  var _this = this;
76
117
  var _a = this.props, validationDisplayMode = _a.validationDisplayMode, allReadOnly = _a.allReadOnly, allDisabled = _a.allDisabled, model = _a.model, showSummaryModal = _a.showSummaryModal, invalidSummaryTitle = _a.invalidSummaryTitle, invalidSummaryText = _a.invalidSummaryText, native = __rest(_a, ["validationDisplayMode", "allReadOnly", "allDisabled", "model", "showSummaryModal", "invalidSummaryTitle", "invalidSummaryText"]);
77
- var formModel;
78
- if (model) {
79
- // Allow binding to ObservableProperty
80
- if (model.attachedTo && !(model instanceof Array)) {
81
- formModel = model.attachedTo;
82
- }
83
- else {
84
- formModel = model;
85
- }
86
- }
87
- return (React.createElement("form", __assign({}, native, { onSubmit: function (e) { return _this.onSubmit(e, formModel); } }),
118
+ return (React.createElement("form", __assign({}, native, { onSubmit: function (e) { return _this.onSubmit(e); } }),
88
119
  React.createElement(FormContextProvider, { validationDisplayMode: validationDisplayMode !== null && validationDisplayMode !== void 0 ? validationDisplayMode : Misc.Settings.form.validationDisplayMode, allReadOnly: allReadOnly, allDisabled: allDisabled }, (this.props.children instanceof Function) ? this.props.children(model, model.meta) : this.props.children)));
89
120
  };
90
121
  Form = __decorate([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singularsystems/neo-react",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "React application logic and components for the Neo client library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,7 +31,7 @@
31
31
  "typescript": "5.4.2"
32
32
  },
33
33
  "dependencies": {
34
- "@singularsystems/neo-core": "1.0.9",
34
+ "@singularsystems/neo-core": "1.0.11",
35
35
  "@types/rc-slider": "^8.6.5",
36
36
  "@types/react-color": "^3.0.1",
37
37
  "axios": "1.6.7",
@@ -49,7 +49,7 @@
49
49
  "tslib": "2.5.0"
50
50
  },
51
51
  "peerDependencies": {
52
- "@singularsystems/neo-core": ">=1.0.9",
52
+ "@singularsystems/neo-core": ">=1.0.11",
53
53
  "axios": ">=1.6.2",
54
54
  "inversify": ">=5.0.1",
55
55
  "mobx": ">=6.9.0",