@singularsystems/neo-react 0.10.57 → 0.10.61
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.
- package/dist/ReactComponents/DropDown/AutoCompleteDropDown.d.ts +9 -1
- package/dist/ReactComponents/DropDown/AutoCompleteDropDown.js +36 -12
- package/dist/ReactComponents/DropDown/DropDown.js +6 -2
- package/dist/ReactComponents/DropDown/DropDownBase.d.ts +2 -1
- package/dist/ReactComponents/DropDown/DropDownBase.js +12 -13
- package/dist/ReactComponents/Form.js +1 -1
- package/dist/ReactComponents/Grid/Column.js +3 -3
- package/dist/ReactComponents/NumberInput.d.ts +7 -3
- package/dist/ReactComponents/NumberInput.js +25 -13
- package/dist/Routing/ViewParameter.d.ts +20 -0
- package/dist/Routing/ViewParameter.js +11 -3
- package/dist/Routing/ViewParameterList.js +16 -0
- package/dist/Views/ViewBase.d.ts +1 -1
- package/dist/Views/ViewBase.js +16 -5
- package/package.json +3 -3
- package/styles/DatePicker.scss +2 -2
- package/styles/Forms.scss +5 -0
|
@@ -67,7 +67,12 @@ export interface IAutoCompleteMultiSelectProps<T> extends IAutoCompleteCommonPro
|
|
|
67
67
|
/**
|
|
68
68
|
* Optional list of ids. This will be kept in sync with the bindItems prop.
|
|
69
69
|
*/
|
|
70
|
-
bindIds?: (string | number)[]
|
|
70
|
+
bindIds?: (string | number)[] | Model.IPropertyInstance<number[]>;
|
|
71
|
+
/**
|
|
72
|
+
* The max no of items to record in the field info if bound to a field info class. (Defaults to 5)
|
|
73
|
+
* If the selected items exceeds this limit, the field info will be recorded as "x items selected".
|
|
74
|
+
*/
|
|
75
|
+
fieldInfoLimit?: number;
|
|
71
76
|
}
|
|
72
77
|
export default class AutoCompleteDropDown<T> extends DropDownBase<T, IAutoCompleteProps<T> | IAutoCompleteMultiSelectProps<T>> {
|
|
73
78
|
static contextType: React.Context<import("../FormContext").FormContextParams>;
|
|
@@ -75,6 +80,9 @@ export default class AutoCompleteDropDown<T> extends DropDownBase<T, IAutoComple
|
|
|
75
80
|
private asyncSelectImplementation;
|
|
76
81
|
private selectImplementation;
|
|
77
82
|
constructor(props: IAutoCompleteProps<T> | IAutoCompleteMultiSelectProps<T>);
|
|
83
|
+
private bindProperty;
|
|
84
|
+
private bindIdsList?;
|
|
85
|
+
private bindIdsProperty?;
|
|
78
86
|
static getBindProp<T>(props: IAutoCompleteProps<T> | IAutoCompleteMultiSelectProps<T>): any;
|
|
79
87
|
private onKeyPress;
|
|
80
88
|
private mapTArrayToOptions;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __assign, __decorate, __extends, __metadata, __rest } from "tslib";
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { EnumHelper, Misc, Utils } from '@singularsystems/neo-core';
|
|
3
|
+
import { EnumHelper, Misc, Model, Utils } from '@singularsystems/neo-core';
|
|
4
4
|
import { observer } from 'mobx-react';
|
|
5
5
|
import { DropDownBase } from './DropDownBase';
|
|
6
6
|
import { BindPropsHelper } from '../PropTypes';
|
|
@@ -11,11 +11,27 @@ import { NeoReactTypes } from '../../Modules/Types';
|
|
|
11
11
|
var AutoCompleteDropDown = /** @class */ (function (_super) {
|
|
12
12
|
__extends(AutoCompleteDropDown, _super);
|
|
13
13
|
function AutoCompleteDropDown(props) {
|
|
14
|
+
var _a;
|
|
14
15
|
var _this = _super.call(this, props) || this;
|
|
15
16
|
_this.asyncSelectImplementation = Misc.Globals.appService.get(NeoReactTypes.Components.AsyncSelect);
|
|
16
17
|
_this.selectImplementation = Misc.Globals.appService.get(NeoReactTypes.Components.ReactSelect);
|
|
17
18
|
_this.onKeyPress = _this.onKeyPress.bind(_this);
|
|
18
19
|
_this.onItemSelected = _this.onItemSelected.bind(_this);
|
|
20
|
+
_this.bindProperty = (_a = _this.props.bind, (_a !== null && _a !== void 0 ? _a : _this.props.bindItems));
|
|
21
|
+
_this.fieldInfoContainer = Model.ModelFieldInfo.asModelFieldInfoContainer(_this.bindProperty.attachedTo);
|
|
22
|
+
if (_this.props.bindIds) {
|
|
23
|
+
if (_this.props.bindIds.propertyInfo) {
|
|
24
|
+
_this.bindIdsProperty = _this.props.bindIds;
|
|
25
|
+
_this.bindIdsList = _this.props.bindIds.value;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
_this.bindIdsList = _this.props.bindIds;
|
|
29
|
+
if (_this.fieldInfoContainer) {
|
|
30
|
+
console.error("Warning: Pass a property instance as 'bindIds', otherwise the display values will not be captured.");
|
|
31
|
+
_this.fieldInfoContainer = null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
19
35
|
return _this;
|
|
20
36
|
}
|
|
21
37
|
AutoCompleteDropDown.getBindProp = function (props) {
|
|
@@ -58,11 +74,10 @@ var AutoCompleteDropDown = /** @class */ (function (_super) {
|
|
|
58
74
|
var itemsProperty = this.props.bindItems;
|
|
59
75
|
// Multi select
|
|
60
76
|
var itemList = itemsProperty.value;
|
|
61
|
-
var bindIdsList = this.props.bindIds;
|
|
62
77
|
if (action.action === "select-option") {
|
|
63
78
|
itemList.push({ id: action.option.value, display: action.option.label });
|
|
64
|
-
if (bindIdsList) {
|
|
65
|
-
bindIdsList.push(action.option.value);
|
|
79
|
+
if (this.bindIdsList) {
|
|
80
|
+
this.bindIdsList.push(action.option.value);
|
|
66
81
|
}
|
|
67
82
|
if (onItemSelected) {
|
|
68
83
|
onItemSelected((_a = action.option) === null || _a === void 0 ? void 0 : _a.item);
|
|
@@ -72,8 +87,8 @@ var AutoCompleteDropDown = /** @class */ (function (_super) {
|
|
|
72
87
|
var removeItem = itemList.find(function (c) { return c.id === action.removedValue.value; });
|
|
73
88
|
if (removeItem) {
|
|
74
89
|
itemList.remove(removeItem);
|
|
75
|
-
if (bindIdsList) {
|
|
76
|
-
bindIdsList.remove(removeItem.id);
|
|
90
|
+
if (this.bindIdsList) {
|
|
91
|
+
this.bindIdsList.remove(removeItem.id);
|
|
77
92
|
}
|
|
78
93
|
}
|
|
79
94
|
if (onItemSelected) {
|
|
@@ -82,8 +97,8 @@ var AutoCompleteDropDown = /** @class */ (function (_super) {
|
|
|
82
97
|
}
|
|
83
98
|
else if (action.action === "clear") {
|
|
84
99
|
itemList.length = 0;
|
|
85
|
-
if (bindIdsList) {
|
|
86
|
-
bindIdsList.length = 0;
|
|
100
|
+
if (this.bindIdsList) {
|
|
101
|
+
this.bindIdsList.length = 0;
|
|
87
102
|
}
|
|
88
103
|
if (onItemSelected) {
|
|
89
104
|
onItemSelected(undefined);
|
|
@@ -105,15 +120,14 @@ var AutoCompleteDropDown = /** @class */ (function (_super) {
|
|
|
105
120
|
AutoCompleteDropDown.prototype.render = function () {
|
|
106
121
|
var _this = this;
|
|
107
122
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
108
|
-
var _m = this.props, bind = _m.bind, bindDisplay = _m.bindDisplay, bindItems = _m.bindItems, bindIds = _m.bindIds, itemSource = _m.itemSource, items = _m.items, displayMember = _m.displayMember, valueMember = _m.valueMember, descriptionMember = _m.descriptionMember, option = _m.option, noRecordsPrompt = _m.noRecordsPrompt, typeToSearchPrompt = _m.typeToSearchPrompt, delayMs = _m.delayMs, minCharacters = _m.minCharacters, onItemSelected = _m.onItemSelected, otherProps = __rest(_m, ["bind", "bindDisplay", "bindItems", "bindIds", "itemSource", "items", "displayMember", "valueMember", "descriptionMember", "option", "noRecordsPrompt", "typeToSearchPrompt", "delayMs", "minCharacters", "onItemSelected"]);
|
|
123
|
+
var _m = this.props, bind = _m.bind, bindDisplay = _m.bindDisplay, bindItems = _m.bindItems, bindIds = _m.bindIds, itemSource = _m.itemSource, items = _m.items, displayMember = _m.displayMember, valueMember = _m.valueMember, descriptionMember = _m.descriptionMember, option = _m.option, noRecordsPrompt = _m.noRecordsPrompt, typeToSearchPrompt = _m.typeToSearchPrompt, delayMs = _m.delayMs, minCharacters = _m.minCharacters, onItemSelected = _m.onItemSelected, fieldInfoLimit = _m.fieldInfoLimit, otherProps = __rest(_m, ["bind", "bindDisplay", "bindItems", "bindIds", "itemSource", "items", "displayMember", "valueMember", "descriptionMember", "option", "noRecordsPrompt", "typeToSearchPrompt", "delayMs", "minCharacters", "onItemSelected", "fieldInfoLimit"]);
|
|
109
124
|
var splitProps = BindPropsHelper.splitCommonEditorProps(otherProps);
|
|
110
125
|
var nativeProps = splitProps.rest;
|
|
111
126
|
var bindItemsProperty = bindItems;
|
|
112
127
|
var itemList = (_a = bindItemsProperty) === null || _a === void 0 ? void 0 : _a.value;
|
|
113
128
|
var bindValue = bind;
|
|
114
129
|
var bindDisplayProperty = bindDisplay;
|
|
115
|
-
var
|
|
116
|
-
var displayInfo = bindProperty.validator.getDisplayState(this.context.validationDisplayMode);
|
|
130
|
+
var displayInfo = this.bindProperty.validator.getDisplayState(this.context.validationDisplayMode);
|
|
117
131
|
displayInfo.applyToDom(nativeProps, this.context.parentType !== EditorParentType.FormGroup);
|
|
118
132
|
this.displayMember = (_b = this.props.displayMember, (_b !== null && _b !== void 0 ? _b : ""));
|
|
119
133
|
this.valueMember = (_c = this.props.valueMember, (_c !== null && _c !== void 0 ? _c : ""));
|
|
@@ -130,6 +144,16 @@ var AutoCompleteDropDown = /** @class */ (function (_super) {
|
|
|
130
144
|
var value = null;
|
|
131
145
|
if (bindItems) {
|
|
132
146
|
value = itemList.map(function (c) { return ({ value: c.id, label: c.display }); });
|
|
147
|
+
if (this.fieldInfoContainer && this.bindIdsProperty) {
|
|
148
|
+
var itemListString = "";
|
|
149
|
+
if (value.length > ((fieldInfoLimit !== null && fieldInfoLimit !== void 0 ? fieldInfoLimit : 5))) {
|
|
150
|
+
itemListString = value.length + " items selected";
|
|
151
|
+
}
|
|
152
|
+
else if (value.length > 0) {
|
|
153
|
+
itemListString = value.map(function (c) { return c.label; }).join(", ");
|
|
154
|
+
}
|
|
155
|
+
this.setFieldInfo(this.bindIdsProperty, itemListString, bindItemsProperty.propertyInfo.readableName);
|
|
156
|
+
}
|
|
133
157
|
}
|
|
134
158
|
else {
|
|
135
159
|
if (bindValue.value !== null) {
|
|
@@ -170,7 +194,7 @@ var AutoCompleteDropDown = /** @class */ (function (_super) {
|
|
|
170
194
|
}
|
|
171
195
|
var userOnBlur = nativeProps.onBlur;
|
|
172
196
|
nativeProps.onBlur = function (e) {
|
|
173
|
-
bindProperty.validator.hasBlurred = true;
|
|
197
|
+
_this.bindProperty.validator.hasBlurred = true;
|
|
174
198
|
if (userOnBlur !== undefined) {
|
|
175
199
|
userOnBlur(e);
|
|
176
200
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __assign, __decorate, __extends, __metadata } from "tslib";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { BindPropsHelper } from '../PropTypes';
|
|
4
|
-
import { Utils } from '@singularsystems/neo-core';
|
|
4
|
+
import { Model, Utils } from '@singularsystems/neo-core';
|
|
5
5
|
import { observer } from 'mobx-react';
|
|
6
6
|
import { InputHelpers } from '../InputHelpers';
|
|
7
7
|
import { DropDownBase } from './DropDownBase';
|
|
@@ -12,6 +12,7 @@ var DropDown = /** @class */ (function (_super) {
|
|
|
12
12
|
var _this = _super.call(this, props) || this;
|
|
13
13
|
_this.listIndexSymbol = Symbol("ValueIndex");
|
|
14
14
|
_this.onItemSelected = _this.onItemSelected.bind(_this);
|
|
15
|
+
_this.fieldInfoContainer = Model.ModelFieldInfo.asModelFieldInfoContainer(_this.props.bind.attachedTo);
|
|
15
16
|
return _this;
|
|
16
17
|
}
|
|
17
18
|
Object.defineProperty(DropDown.prototype, "items", {
|
|
@@ -117,9 +118,12 @@ var DropDown = /** @class */ (function (_super) {
|
|
|
117
118
|
}
|
|
118
119
|
var valueIsBlank = value === undefined || value === null;
|
|
119
120
|
var nullText = (valueIsBlank || ((_d = splitProps.select) === null || _d === void 0 ? void 0 : _d.deSelectText) === undefined) ? (_e = splitProps.select) === null || _e === void 0 ? void 0 : _e.nullText : (_f = splitProps.select) === null || _f === void 0 ? void 0 : _f.deSelectText;
|
|
121
|
+
if (valueIsBlank) {
|
|
122
|
+
domProps.className = Utils.joinWithSpaces(domProps.className, "select-no-value");
|
|
123
|
+
}
|
|
120
124
|
control =
|
|
121
125
|
React.createElement("select", __assign({ value: valueIsBlank ? "" : value, onChange: this.onItemSelected, ref: splitProps.editor.inputElement }, domProps),
|
|
122
|
-
addBlankItem && React.createElement("option",
|
|
126
|
+
addBlankItem && React.createElement("option", { className: "option-default" }, nullText),
|
|
123
127
|
items.map(function (item) { return (React.createElement("option", { value: item[_this.valueMember], key: item[_this.valueMember] }, item[_this.displayMember])); }));
|
|
124
128
|
}
|
|
125
129
|
return (InputHelpers.surroundWithInputGroup(control, splitProps.editor));
|
|
@@ -8,8 +8,9 @@ export declare abstract class DropDownBase<T, TProps> extends ComponentBase<TPro
|
|
|
8
8
|
protected isLoading: boolean;
|
|
9
9
|
protected dataSource: Data.IAsyncDataSource<T[]> | null;
|
|
10
10
|
protected cachedDataSource: Data.IDataCacheEntry | null;
|
|
11
|
+
protected fieldInfoContainer: Model.IModelFieldInfoContainer | null;
|
|
11
12
|
protected getItems(itemSource: ItemSource<T>): T[];
|
|
12
13
|
afterRender(): Promise<void>;
|
|
13
14
|
private fieldDisplayInfo;
|
|
14
|
-
protected setFieldInfo(bindProperty: Model.IPropertyInstance, displayValue: string): void;
|
|
15
|
+
protected setFieldInfo(bindProperty: Model.IPropertyInstance, displayValue: string, readableName?: string): void;
|
|
15
16
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __awaiter, __extends, __generator } from "tslib";
|
|
2
|
-
import { Data
|
|
2
|
+
import { Data } from '@singularsystems/neo-core';
|
|
3
3
|
import ComponentBase from '../ComponentBase';
|
|
4
4
|
import LookupHelper from './LookupHelper';
|
|
5
5
|
var DropDownBase = /** @class */ (function (_super) {
|
|
@@ -9,6 +9,7 @@ var DropDownBase = /** @class */ (function (_super) {
|
|
|
9
9
|
_this.isLoading = false;
|
|
10
10
|
_this.dataSource = null;
|
|
11
11
|
_this.cachedDataSource = null;
|
|
12
|
+
_this.fieldInfoContainer = null;
|
|
12
13
|
_this.fieldDisplayInfo = null;
|
|
13
14
|
return _this;
|
|
14
15
|
}
|
|
@@ -53,7 +54,7 @@ var DropDownBase = /** @class */ (function (_super) {
|
|
|
53
54
|
};
|
|
54
55
|
DropDownBase.prototype.afterRender = function () {
|
|
55
56
|
return __awaiter(this, void 0, void 0, function () {
|
|
56
|
-
var _a, bindProperty, displayValue, fieldInfo;
|
|
57
|
+
var _a, bindProperty, displayValue, readableName, fieldInfo;
|
|
57
58
|
return __generator(this, function (_b) {
|
|
58
59
|
if (this.cachedDataSource) {
|
|
59
60
|
this.dataSource = this.cachedDataSource.get();
|
|
@@ -62,16 +63,12 @@ var DropDownBase = /** @class */ (function (_super) {
|
|
|
62
63
|
this.dataSource.fetchInitial();
|
|
63
64
|
}
|
|
64
65
|
if (this.fieldDisplayInfo) {
|
|
65
|
-
_a = this.fieldDisplayInfo, bindProperty = _a.bindProperty, displayValue = _a.displayValue;
|
|
66
|
+
_a = this.fieldDisplayInfo, bindProperty = _a.bindProperty, displayValue = _a.displayValue, readableName = _a.readableName;
|
|
66
67
|
this.fieldDisplayInfo = null;
|
|
67
|
-
if (
|
|
68
|
-
fieldInfo =
|
|
69
|
-
if (
|
|
70
|
-
fieldInfo =
|
|
71
|
-
bindProperty.attachedTo.fieldInfo[bindProperty.propertyInfo.propertyName] = fieldInfo;
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
fieldInfo.valueString = displayValue;
|
|
68
|
+
if (this.fieldInfoContainer) {
|
|
69
|
+
fieldInfo = this.fieldInfoContainer.setModelFieldInfo(bindProperty.propertyInfo, displayValue);
|
|
70
|
+
if (readableName) {
|
|
71
|
+
fieldInfo.displayName = readableName;
|
|
75
72
|
}
|
|
76
73
|
}
|
|
77
74
|
}
|
|
@@ -79,8 +76,10 @@ var DropDownBase = /** @class */ (function (_super) {
|
|
|
79
76
|
});
|
|
80
77
|
});
|
|
81
78
|
};
|
|
82
|
-
DropDownBase.prototype.setFieldInfo = function (bindProperty, displayValue) {
|
|
83
|
-
this.
|
|
79
|
+
DropDownBase.prototype.setFieldInfo = function (bindProperty, displayValue, readableName) {
|
|
80
|
+
if (this.fieldInfoContainer) {
|
|
81
|
+
this.fieldDisplayInfo = { bindProperty: bindProperty, displayValue: displayValue, readableName: readableName };
|
|
82
|
+
}
|
|
84
83
|
};
|
|
85
84
|
return DropDownBase;
|
|
86
85
|
}(ComponentBase));
|
|
@@ -40,7 +40,7 @@ var Form = /** @class */ (function (_super) {
|
|
|
40
40
|
var onClose = this.disposeReaction.bind(this);
|
|
41
41
|
var codeModal_1 = ModalUtils.showModal(this.props.invalidSummaryTitle || "Invalid data", React.createElement(Observer, null, function () {
|
|
42
42
|
return React.createElement("div", null,
|
|
43
|
-
_this.props.invalidSummaryText || "Cannot continue due to the following
|
|
43
|
+
_this.props.invalidSummaryText || "Cannot continue due to the following issues:",
|
|
44
44
|
React.createElement(ValidationSummary, { graph: Validation.getValidationSummary(model), hideTopLevelTitle: !(model instanceof Array) }));
|
|
45
45
|
}), { onClose: onClose, closeButton: { text: "Ok", onClick: onClose } });
|
|
46
46
|
// Listen for when isValid changes to true, in case there is an async rule running.
|
|
@@ -143,7 +143,7 @@ var Column = /** @class */ (function (_super) {
|
|
|
143
143
|
if (sortProperty && !this.suppressSort) {
|
|
144
144
|
var sortInfo = this.context.dataView.sortInfo.find(function (c) { return c.column === sortProperty.propertyInfo; });
|
|
145
145
|
if (sortInfo) {
|
|
146
|
-
sortIcon = sortInfo.sortAscending ?
|
|
146
|
+
sortIcon = sortInfo.sortAscending ? Misc.Settings.icons.sortAsc : Misc.Settings.icons.sortDesc;
|
|
147
147
|
domProps.className = Utils.joinWithSpaces(domProps.className, "column-is-sorted");
|
|
148
148
|
}
|
|
149
149
|
domProps.className = Utils.joinWithSpaces(domProps.className, "column-sortable");
|
|
@@ -163,7 +163,7 @@ var Column = /** @class */ (function (_super) {
|
|
|
163
163
|
if (editorProps.isReadOnly && !editorProps.requiresGroup) {
|
|
164
164
|
var rawValue = editorProps.bind.value;
|
|
165
165
|
if (this.controlType == ControlType.Number) {
|
|
166
|
-
displayValue = this.numFormatState(editorProps.bind.propertyInfo.propertyType, props.numProps).getFormattedValue(rawValue);
|
|
166
|
+
displayValue = this.numFormatState(editorProps.bind.propertyInfo, editorProps.bind.propertyInfo.propertyType, props.numProps).getFormattedValue(rawValue);
|
|
167
167
|
}
|
|
168
168
|
else if (this.controlType == ControlType.Date) {
|
|
169
169
|
displayValue = DateUtils.format(rawValue, props.dateProps ? props.dateProps.formatString : undefined);
|
|
@@ -197,7 +197,7 @@ var Column = /** @class */ (function (_super) {
|
|
|
197
197
|
var hasSummary = (colProps.sum && !!props.bind) || colProps.footerContent;
|
|
198
198
|
return (React.createElement("th", __assign({}, domProps), hasSummary &&
|
|
199
199
|
React.createElement(Observer, null, function () { return colProps.footerContent ? colProps.footerContent(_this.context.dataView.filteredItems) :
|
|
200
|
-
_this.numFormatState(props.bind.propertyInfo.propertyType, props.numProps).getFormattedValue(_this.context.dataView.filteredItems.sum(props.bind.propertyInfo)); })));
|
|
200
|
+
_this.numFormatState(props.bind.propertyInfo, props.bind.propertyInfo.propertyType, props.numProps).getFormattedValue(_this.context.dataView.filteredItems.sum(props.bind.propertyInfo)); })));
|
|
201
201
|
};
|
|
202
202
|
Column.isColumnComponent = true;
|
|
203
203
|
Column.contextType = GridContext;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { IBindableEditorProps } from './PropTypes';
|
|
3
3
|
import { FormContext } from './FormContext';
|
|
4
|
-
import { Misc } from '@singularsystems/neo-core';
|
|
4
|
+
import { Misc, Model } from '@singularsystems/neo-core';
|
|
5
5
|
import Decimal from 'decimal.js-light';
|
|
6
6
|
import ComponentBase from './ComponentBase';
|
|
7
7
|
export interface INumberInputSpecificProps {
|
|
@@ -25,10 +25,14 @@ export declare class FormatState {
|
|
|
25
25
|
isPercent: boolean;
|
|
26
26
|
hasExternalPercentSymbol: boolean;
|
|
27
27
|
formatString: string;
|
|
28
|
+
/** How many decimals the value is allowed. */
|
|
29
|
+
allowedDecimals: number;
|
|
28
30
|
zeroText?: string | undefined;
|
|
29
31
|
useNative?: boolean | undefined;
|
|
30
|
-
constructor(isPercent: boolean, hasExternalPercentSymbol: boolean, formatString: string,
|
|
31
|
-
|
|
32
|
+
constructor(isPercent: boolean, hasExternalPercentSymbol: boolean, formatString: string,
|
|
33
|
+
/** How many decimals the value is allowed. */
|
|
34
|
+
allowedDecimals: number, zeroText?: string | undefined, useNative?: boolean | undefined);
|
|
35
|
+
static create(propertyInfo: Model.PropertyInfo, numericType: Misc.DataType, numProps?: INumberInputSpecificProps, appendText?: string): FormatState;
|
|
32
36
|
getFormattedValue(value?: number | Decimal | null): string;
|
|
33
37
|
}
|
|
34
38
|
export default class NumberInput extends ComponentBase<INumberInputProps> {
|
|
@@ -9,37 +9,49 @@ import { observer } from 'mobx-react';
|
|
|
9
9
|
import memoize from 'memoize-one';
|
|
10
10
|
import ComponentBase from './ComponentBase';
|
|
11
11
|
var FormatState = /** @class */ (function () {
|
|
12
|
-
function FormatState(isPercent, hasExternalPercentSymbol, formatString,
|
|
12
|
+
function FormatState(isPercent, hasExternalPercentSymbol, formatString,
|
|
13
|
+
/** How many decimals the value is allowed. */
|
|
14
|
+
allowedDecimals, zeroText, useNative) {
|
|
13
15
|
this.isPercent = isPercent;
|
|
14
16
|
this.hasExternalPercentSymbol = hasExternalPercentSymbol;
|
|
15
17
|
this.formatString = formatString;
|
|
18
|
+
this.allowedDecimals = allowedDecimals;
|
|
16
19
|
this.zeroText = zeroText;
|
|
17
20
|
this.useNative = useNative;
|
|
18
21
|
}
|
|
19
|
-
FormatState.create = function (numericType, numProps, appendText) {
|
|
20
|
-
var _a, _b, _c, _d;
|
|
22
|
+
FormatState.create = function (propertyInfo, numericType, numProps, appendText) {
|
|
23
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
21
24
|
var isPercent = false;
|
|
22
25
|
var hasExternalPercentSymbol = false;
|
|
23
26
|
var formatString = numProps ? numProps.formatString : "";
|
|
27
|
+
var displayDecimals = 2;
|
|
28
|
+
if ((formatString && formatString.indexOf("%") >= 0)
|
|
29
|
+
|| appendText === "%"
|
|
30
|
+
|| ((_a = numProps) === null || _a === void 0 ? void 0 : _a.format) === Misc.NumberFormat.PercentDecimals || ((_b = numProps) === null || _b === void 0 ? void 0 : _b.format) === Misc.NumberFormat.PercentNoDecimals) {
|
|
31
|
+
isPercent = true;
|
|
32
|
+
}
|
|
33
|
+
if (propertyInfo.allowedDecimals !== undefined) {
|
|
34
|
+
displayDecimals = propertyInfo.allowedDecimals - (isPercent ? 2 : 0);
|
|
35
|
+
}
|
|
36
|
+
else if ((_c = numProps) === null || _c === void 0 ? void 0 : _c.formatString) {
|
|
37
|
+
displayDecimals = NumberUtils.getDecimalPlaces(numProps.formatString);
|
|
38
|
+
}
|
|
24
39
|
if (!formatString) {
|
|
25
40
|
if (numProps && numProps.format) {
|
|
26
|
-
formatString = NumberUtils.getFormatString(numProps.format, numProps.currencySymbol);
|
|
41
|
+
formatString = NumberUtils.getFormatString(numProps.format, numProps.currencySymbol, displayDecimals);
|
|
27
42
|
}
|
|
28
43
|
else {
|
|
29
44
|
var hasDecimals = numericType === Misc.DataType.Float || numericType === Misc.DataType.Decimal;
|
|
30
|
-
var format = ((
|
|
45
|
+
var format = ((_d = numProps) === null || _d === void 0 ? void 0 : _d.currencySymbol) ?
|
|
31
46
|
(hasDecimals ? Misc.NumberFormat.CurrencyDecimals : Misc.NumberFormat.CurrencyNoDecimals) :
|
|
32
47
|
(hasDecimals ? Misc.NumberFormat.Decimals : Misc.NumberFormat.NoDecimals);
|
|
33
|
-
formatString = NumberUtils.getFormatString(format, (
|
|
48
|
+
formatString = NumberUtils.getFormatString(format, (_e = numProps) === null || _e === void 0 ? void 0 : _e.currencySymbol, displayDecimals);
|
|
34
49
|
}
|
|
35
50
|
}
|
|
36
51
|
if (formatString.indexOf("%") < 0 && appendText === "%") {
|
|
37
52
|
hasExternalPercentSymbol = true;
|
|
38
53
|
}
|
|
39
|
-
|
|
40
|
-
isPercent = true;
|
|
41
|
-
}
|
|
42
|
-
return new FormatState(isPercent, hasExternalPercentSymbol, formatString, (_c = numProps) === null || _c === void 0 ? void 0 : _c.zeroText, (_d = numProps) === null || _d === void 0 ? void 0 : _d.native);
|
|
54
|
+
return new FormatState(isPercent, hasExternalPercentSymbol, formatString, displayDecimals + (isPercent ? 2 : 0), (_f = numProps) === null || _f === void 0 ? void 0 : _f.zeroText, (_g = numProps) === null || _g === void 0 ? void 0 : _g.native);
|
|
43
55
|
};
|
|
44
56
|
FormatState.prototype.getFormattedValue = function (value) {
|
|
45
57
|
if (!value && this.zeroText !== undefined) {
|
|
@@ -112,7 +124,7 @@ var NumberInput = /** @class */ (function (_super) {
|
|
|
112
124
|
}
|
|
113
125
|
else {
|
|
114
126
|
if (!this.props.numProps || this.props.numProps.autoRound !== false) {
|
|
115
|
-
newValue = NumberUtils.
|
|
127
|
+
newValue = NumberUtils.round(newValue, this.formatState.allowedDecimals);
|
|
116
128
|
}
|
|
117
129
|
if (this.numericType === Misc.DataType.Decimal) {
|
|
118
130
|
this.props.bind.value = newValue;
|
|
@@ -147,7 +159,7 @@ var NumberInput = /** @class */ (function (_super) {
|
|
|
147
159
|
}
|
|
148
160
|
else {
|
|
149
161
|
if (element.readOnly || !this.props.numProps || this.props.numProps.autoRound !== false) {
|
|
150
|
-
stringValue = NumberUtils.formatRaw(numberValue, this.formatState.formatString, this.formatState.hasExternalPercentSymbol);
|
|
162
|
+
stringValue = NumberUtils.formatRaw(numberValue, this.formatState.formatString, this.formatState.hasExternalPercentSymbol, this.formatState.allowedDecimals);
|
|
151
163
|
}
|
|
152
164
|
else {
|
|
153
165
|
if (this.formatState.isPercent && NumberUtils.transformPercent) {
|
|
@@ -222,7 +234,7 @@ var NumberInput = /** @class */ (function (_super) {
|
|
|
222
234
|
var useNative = (_a = splitProps.numProps) === null || _a === void 0 ? void 0 : _a.native;
|
|
223
235
|
var displayInfo = this.props.bind.validator.getDisplayState(this.context.validationDisplayMode);
|
|
224
236
|
displayInfo.applyToDom(domProps, !splitProps.inGroup);
|
|
225
|
-
this.formatState = this.recalcFormatState(this.numericType, splitProps.numProps, editorProps.appendText);
|
|
237
|
+
this.formatState = this.recalcFormatState(this.props.bind.propertyInfo, this.numericType, splitProps.numProps, editorProps.appendText);
|
|
226
238
|
this.isReadOnly = domProps.readOnly === true;
|
|
227
239
|
if (editorProps.inputElement) {
|
|
228
240
|
this.inputElement = editorProps.inputElement;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { IRouteParameter } from './IRouteParameter';
|
|
2
3
|
import { IViewParameterListInternal } from './ViewParameterList';
|
|
3
4
|
import { Model } from '@singularsystems/neo-core';
|
|
@@ -16,6 +17,12 @@ export interface IViewParameter {
|
|
|
16
17
|
* Used by the breadcrumb.
|
|
17
18
|
*/
|
|
18
19
|
description: string;
|
|
20
|
+
/**
|
|
21
|
+
* Sets the description, and an optional list of prefixes.
|
|
22
|
+
* @param description Description of the current value.
|
|
23
|
+
* @param prefixes Function that returns prefixes for this breadcrumb item. The previous prefixes are passed into the function.
|
|
24
|
+
*/
|
|
25
|
+
setDescription(description: string, getPrefixes?: (currentPrefixes: IViewParameterPrefix[]) => IViewParameterPrefix[]): void;
|
|
19
26
|
/**
|
|
20
27
|
* Returns value as a nullable int.
|
|
21
28
|
*/
|
|
@@ -41,6 +48,7 @@ export declare class ViewParameter implements IViewParameter {
|
|
|
41
48
|
private hasPendingValue;
|
|
42
49
|
private pendingValue;
|
|
43
50
|
private _value;
|
|
51
|
+
prefixes: IViewParameterPrefix[];
|
|
44
52
|
constructor(parent: IViewParameterListInternal, name: string, routeParameter: IRouteParameter);
|
|
45
53
|
bindTo(propertyOrCallback: Model.IPropertyInstance | (() => (string | number | null | undefined))): void;
|
|
46
54
|
get value(): number | string | null;
|
|
@@ -49,6 +57,7 @@ export declare class ViewParameter implements IViewParameter {
|
|
|
49
57
|
_description: string;
|
|
50
58
|
get description(): string;
|
|
51
59
|
set description(value: string);
|
|
60
|
+
setDescription(description: string, getPrefixes?: (currentPrefixes: IViewParameterPrefix[]) => IViewParameterPrefix[]): void;
|
|
52
61
|
asNullableInt(): number | null;
|
|
53
62
|
asString(): string;
|
|
54
63
|
/** Updates the current value, and returns true if the value changed. */
|
|
@@ -58,3 +67,14 @@ export declare class ViewParameter implements IViewParameter {
|
|
|
58
67
|
}): string;
|
|
59
68
|
get latestValue(): string | null;
|
|
60
69
|
}
|
|
70
|
+
interface IViewParameterPrefix {
|
|
71
|
+
/** Label to show on breadcrumb. */
|
|
72
|
+
label: string;
|
|
73
|
+
/** Value to use in the breadcrumb link. Clicking on the link will set the view parameter to this value. */
|
|
74
|
+
value?: number | string | null;
|
|
75
|
+
/** Custom link to use in the breadcrumb. */
|
|
76
|
+
link?: string;
|
|
77
|
+
/** Click event for the breadcrumb. */
|
|
78
|
+
onClick?: (e: React.MouseEvent) => void;
|
|
79
|
+
}
|
|
80
|
+
export {};
|
|
@@ -8,6 +8,7 @@ var ViewParameter = /** @class */ (function () {
|
|
|
8
8
|
this.hasPendingValue = false;
|
|
9
9
|
this.pendingValue = null;
|
|
10
10
|
this._value = null;
|
|
11
|
+
this.prefixes = [];
|
|
11
12
|
this._description = "";
|
|
12
13
|
}
|
|
13
14
|
ViewParameter.prototype.bindTo = function (propertyOrCallback) {
|
|
@@ -28,7 +29,6 @@ var ViewParameter = /** @class */ (function () {
|
|
|
28
29
|
if (stringValue !== this._value) {
|
|
29
30
|
this.hasPendingValue = true;
|
|
30
31
|
this.pendingValue = stringValue;
|
|
31
|
-
this._description = "";
|
|
32
32
|
this.parent.setUrl(this);
|
|
33
33
|
}
|
|
34
34
|
},
|
|
@@ -55,6 +55,10 @@ var ViewParameter = /** @class */ (function () {
|
|
|
55
55
|
enumerable: true,
|
|
56
56
|
configurable: true
|
|
57
57
|
});
|
|
58
|
+
ViewParameter.prototype.setDescription = function (description, getPrefixes) {
|
|
59
|
+
this.prefixes = getPrefixes ? getPrefixes(this.prefixes) : [];
|
|
60
|
+
this.description = description;
|
|
61
|
+
};
|
|
58
62
|
ViewParameter.prototype.asNullableInt = function () {
|
|
59
63
|
if (this._value) {
|
|
60
64
|
return parseInt(this._value, 10);
|
|
@@ -66,13 +70,17 @@ var ViewParameter = /** @class */ (function () {
|
|
|
66
70
|
};
|
|
67
71
|
/** Updates the current value, and returns true if the value changed. */
|
|
68
72
|
ViewParameter.prototype.update = function (value) {
|
|
69
|
-
if (value)
|
|
73
|
+
if (value) {
|
|
70
74
|
value = decodeURIComponent(value);
|
|
75
|
+
}
|
|
71
76
|
if (value != this._value) {
|
|
72
77
|
this.hasPendingValue = false;
|
|
73
78
|
this.pendingValue = value;
|
|
74
|
-
this._description = "";
|
|
75
79
|
this._value = value;
|
|
80
|
+
if (!value) {
|
|
81
|
+
this._description = "";
|
|
82
|
+
this.prefixes = [];
|
|
83
|
+
}
|
|
76
84
|
return true;
|
|
77
85
|
}
|
|
78
86
|
return false;
|
|
@@ -28,6 +28,22 @@ var ViewParameterList = /** @class */ (function () {
|
|
|
28
28
|
for (var _i = 0, _b = this.params; _i < _b.length; _i++) {
|
|
29
29
|
var viewParam = _b[_i];
|
|
30
30
|
if (!viewParam.routeParameter.isQuery) {
|
|
31
|
+
if (!upTo) {
|
|
32
|
+
for (var _c = 0, _d = viewParam.prefixes; _c < _d.length; _c++) {
|
|
33
|
+
var prefix = _d[_c];
|
|
34
|
+
var breadcrumbItem = new BreadCrumbItem(prefix.label);
|
|
35
|
+
if (prefix.onClick) {
|
|
36
|
+
breadcrumbItem.onClick = prefix.onClick;
|
|
37
|
+
}
|
|
38
|
+
else if (prefix.link) {
|
|
39
|
+
breadcrumbItem.link = prefix.link;
|
|
40
|
+
}
|
|
41
|
+
else if (prefix.value) {
|
|
42
|
+
breadcrumbItem.link = paramPath + "/" + prefix.value;
|
|
43
|
+
}
|
|
44
|
+
breadCrumbs.push(breadcrumbItem);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
31
47
|
paramPath += viewParam.getParamString(state);
|
|
32
48
|
if ((_a = viewParam.routeParameter.selection, (_a !== null && _a !== void 0 ? _a : BreadCrumbSelectMode.Default)) === BreadCrumbSelectMode.Default) {
|
|
33
49
|
selectablePath = paramPath;
|
package/dist/Views/ViewBase.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export default abstract class ViewBase<TViewModel extends IViewModel = EmptyView
|
|
|
46
46
|
/**
|
|
47
47
|
* viewParamsUpdated() is called when the component is mounted, and whenever a route parameter or query parameter gets a changed value.
|
|
48
48
|
*/
|
|
49
|
-
protected viewParamsUpdated(): void
|
|
49
|
+
protected viewParamsUpdated(): void | Promise<void>;
|
|
50
50
|
/** Gets the parent breadcrumbs, and the breadcrumb for this view. */
|
|
51
51
|
protected getBreadCrumbStart(): BreadCrumbItem[];
|
|
52
52
|
/**
|
package/dist/Views/ViewBase.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { __decorate, __extends, __metadata } from "tslib";
|
|
1
|
+
import { __awaiter, __decorate, __extends, __generator, __metadata } from "tslib";
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { observable } from 'mobx';
|
|
3
|
+
import { observable, runInAction } from 'mobx';
|
|
4
4
|
import { Misc } from '@singularsystems/neo-core';
|
|
5
5
|
import { ViewParameterList } from '../Routing/ViewParameterList';
|
|
6
6
|
import { ViewState } from './ViewState';
|
|
@@ -79,9 +79,20 @@ var ViewBase = /** @class */ (function (_super) {
|
|
|
79
79
|
this.disposeViewModel();
|
|
80
80
|
};
|
|
81
81
|
ViewBase.prototype.updateViewParams = function (match) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
var _this = this;
|
|
83
|
+
runInAction(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
84
|
+
return __generator(this, function (_a) {
|
|
85
|
+
switch (_a.label) {
|
|
86
|
+
case 0:
|
|
87
|
+
if (!this.viewState.viewParams.update(match)) return [3 /*break*/, 2];
|
|
88
|
+
return [4 /*yield*/, Promise.resolve(this.viewParamsUpdated())];
|
|
89
|
+
case 1:
|
|
90
|
+
_a.sent();
|
|
91
|
+
_a.label = 2;
|
|
92
|
+
case 2: return [2 /*return*/];
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}); });
|
|
85
96
|
};
|
|
86
97
|
/**
|
|
87
98
|
* viewParamsUpdated() is called when the component is mounted, and whenever a route parameter or query parameter gets a changed value.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singularsystems/neo-react",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.61",
|
|
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",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@types/rc-slider": "^8.6.5",
|
|
34
34
|
"@types/react-color": "^3.0.1",
|
|
35
35
|
"@types/react-select": "3.1.0",
|
|
36
|
-
"@singularsystems/neo-core": "^0.10.
|
|
36
|
+
"@singularsystems/neo-core": "^0.10.63",
|
|
37
37
|
"axios": "^0.21.1",
|
|
38
38
|
"decimal.js-light": "2.5.1",
|
|
39
39
|
"history": "4.10.1",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"react-router-dom": "5.1.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@singularsystems/neo-core": ">=0.10.
|
|
50
|
+
"@singularsystems/neo-core": ">=0.10.69",
|
|
51
51
|
"axios": ">=0.21.1",
|
|
52
52
|
"inversify": ">=5.0.1",
|
|
53
53
|
"react": ">=16.13.1",
|
package/styles/DatePicker.scss
CHANGED
package/styles/Forms.scss
CHANGED
|
@@ -131,6 +131,11 @@ div.neo-form-group-floating {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
.react-select-bs {
|
|
135
|
+
.react-select-bs__menu {
|
|
136
|
+
z-index: 2; /* Without this, checkboxes appear in front of the drop down menu. */
|
|
137
|
+
}
|
|
138
|
+
}
|
|
134
139
|
.react-select-row {
|
|
135
140
|
padding: 0.15rem 1rem 0.25rem 1rem;
|
|
136
141
|
display: flex;
|