orc-shared 1.6.0-dev.8 → 1.6.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.
- package/dist/actions/applications.js +1 -1
- package/dist/actions/authentication.js +1 -1
- package/dist/actions/countries.js +1 -1
- package/dist/actions/locale.js +1 -1
- package/dist/actions/makeApiAction.js +3 -3
- package/dist/actions/makeOrcApiAction.js +2 -2
- package/dist/actions/metadata.js +3 -3
- package/dist/actions/navigation.js +2 -2
- package/dist/actions/scopes.js +1 -1
- package/dist/actions/tasks.js +1 -1
- package/dist/actions/timezones.js +1 -1
- package/dist/actions/versionInfo.js +1 -1
- package/dist/buildStore.js +2 -2
- package/dist/components/AppFrame/About.js +3 -3
- package/dist/components/AppFrame/AppFrame.js +1 -1
- package/dist/components/AppFrame/Preferences.js +3 -3
- package/dist/components/ApplicationModuleLoader.js +1 -1
- package/dist/components/CategoryList.js +1 -1
- package/dist/components/DropMenu/index.js +1 -1
- package/dist/components/Form/FieldList.js +2 -2
- package/dist/components/Form/InputField.js +1 -1
- package/dist/components/Form/Inputs/Translation.js +3 -3
- package/dist/components/List/List.js +1 -1
- package/dist/components/List/enhanceColumnDefs.js +2 -2
- package/dist/components/Loader.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/CollapsableList.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/Notification.js +3 -3
- package/dist/components/MaterialUI/DataDisplay/PredefinedElements/GlobalErrorMessages.js +33 -5
- package/dist/components/MaterialUI/DataDisplay/PredefinedElements/LookupDisplayValue.js +12 -7
- package/dist/components/MaterialUI/DataDisplay/PredefinedElements/StepperModal.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/PredefinedElements/Translations.js +2 -2
- package/dist/components/MaterialUI/DataDisplay/SelectionList.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/Table.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/TooltippedElements/MultipleLinesText.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/TransferList.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/tableHelpers.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/useTableSelection.js +3 -3
- package/dist/components/MaterialUI/Feedback/NotificationContext.js +1 -1
- package/dist/components/MaterialUI/Feedback/loadingScreen.js +1 -1
- package/dist/components/MaterialUI/Inputs/Autocomplete.js +2 -2
- package/dist/components/MaterialUI/Inputs/InputBase.js +97 -15
- package/dist/components/MaterialUI/Inputs/InputBaseProps.js +3 -1
- package/dist/components/MaterialUI/Inputs/Select.js +3 -3
- package/dist/components/MaterialUI/Inputs/Switch.js +2 -2
- package/dist/components/MaterialUI/Inputs/TimePicker.js +1 -1
- package/dist/components/MaterialUI/Inputs/createInput.js +2 -2
- package/dist/components/MaterialUI/Navigation/DropDownMenu.js +1 -1
- package/dist/components/MaterialUI/Navigation/TabBar.js +1 -1
- package/dist/components/MaterialUI/Navigation/TabLabel.js +1 -1
- package/dist/components/MaterialUI/ScopeSelector/ScopeTreeView.js +1 -1
- package/dist/components/MaterialUI/Surfaces/ExpansionPanel.js +1 -1
- package/dist/components/MaterialUI/Surfaces/SectionExpansionPanel.js +1 -1
- package/dist/components/MaterialUI/hocs/withDeferredPopper.js +1 -1
- package/dist/components/MaterialUI/hocs/withDeferredTooltip.js +1 -1
- package/dist/components/MaterialUI/muiThemes.js +2 -2
- package/dist/components/Modal/index.js +1 -1
- package/dist/components/Modules.js +1 -1
- package/dist/components/MultiSelector.js +1 -1
- package/dist/components/Navigation/Bar.js +3 -3
- package/dist/components/Navigation/Tab.js +1 -1
- package/dist/components/Navigation/useNavigationState.js +3 -3
- package/dist/components/Routing/Page.js +1 -1
- package/dist/components/Routing/SegmentPage.js +1 -1
- package/dist/components/Routing/withWaypointing.js +2 -2
- package/dist/components/Scope/ScopeNode.js +1 -1
- package/dist/components/Scope/index.js +3 -3
- package/dist/components/Scope/useScopeConfirmationModalState.js +2 -2
- package/dist/components/Selector.js +1 -1
- package/dist/components/Text.js +1 -1
- package/dist/components/Treeview/Node.js +2 -2
- package/dist/components/Treeview/index.js +3 -3
- package/dist/getThemeOverrides.js +2 -2
- package/dist/hocs/withNavigationLink.js +1 -1
- package/dist/hocs/withScopeData.js +1 -1
- package/dist/hocs/withToggle.js +1 -1
- package/dist/hocs/withUpdateHandler.js +2 -2
- package/dist/hocs/withViewState.js +1 -1
- package/dist/hooks/useEditState.js +2 -2
- package/dist/hooks/useEntityLoader.js +3 -3
- package/dist/hooks/useFullEntityEditState.js +3 -3
- package/dist/hooks/useInfiniteScroll.js +1 -1
- package/dist/hooks/useLabelMessage.js +2 -2
- package/dist/hooks/useMultipleFieldEditState.js +2 -2
- package/dist/hooks/useNotificationRequestState.js +2 -2
- package/dist/hooks/useToggle.js +1 -1
- package/dist/reducers/authentication.js +1 -1
- package/dist/reducers/request.js +2 -1
- package/dist/selectors/metadata.js +2 -2
- package/dist/selectors/modules.js +2 -2
- package/dist/utils/buildUrl.js +1 -1
- package/dist/utils/flatten.js +3 -3
- package/dist/utils/testUtils.js +1 -1
- package/dist/utils/timezoneHelper.js +1 -1
- package/package.json +4 -3
- package/src/components/MaterialUI/DataDisplay/PredefinedElements/GlobalErrorMessages.js +16 -1
- package/src/components/MaterialUI/DataDisplay/PredefinedElements/GlobalErrorMessages.test.js +6 -10
- package/src/components/MaterialUI/DataDisplay/PredefinedElements/LookupDisplayValue.js +13 -2
- package/src/components/MaterialUI/DataDisplay/PredefinedElements/LookupDisplayValue.test.js +26 -0
- package/src/components/MaterialUI/Inputs/InputBase.js +96 -14
- package/src/components/MaterialUI/Inputs/InputBase.test.js +337 -1
- package/src/components/MaterialUI/Inputs/InputBaseProps.js +2 -0
- package/src/components/MaterialUI/Inputs/InputBaseProps.test.js +2 -0
- package/src/reducers/request.js +2 -1
- package/src/reducers/request.test.js +23 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useRef } from "react";
|
|
2
2
|
import { makeStyles } from "@material-ui/core/styles";
|
|
3
3
|
import InputBaseMUI from "@material-ui/core/InputBase";
|
|
4
4
|
import InputBaseProps, { isInputProps } from "./InputBaseProps";
|
|
5
5
|
import classNames from "classnames";
|
|
6
|
+
import { NumericFormat, numericFormatter } from "react-number-format";
|
|
6
7
|
|
|
7
8
|
export const useStyles = makeStyles(theme => ({
|
|
8
9
|
container: {
|
|
@@ -79,6 +80,27 @@ export const useStyles = makeStyles(theme => ({
|
|
|
79
80
|
},
|
|
80
81
|
}));
|
|
81
82
|
|
|
83
|
+
export const AdvancedNumericInput = props => {
|
|
84
|
+
const { inputRef, onChange, ...other } = props;
|
|
85
|
+
|
|
86
|
+
// https://github.com/s-yadav/react-number-format
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<NumericFormat
|
|
90
|
+
{...other}
|
|
91
|
+
getInputRef={inputRef}
|
|
92
|
+
onValueChange={values => {
|
|
93
|
+
onChange({
|
|
94
|
+
target: {
|
|
95
|
+
name: props.name,
|
|
96
|
+
value: values.value,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
82
104
|
const InputBase = ({ inputProps }) => {
|
|
83
105
|
if (isInputProps(inputProps) === false) {
|
|
84
106
|
throw new TypeError("inputProps property is not of type InputBaseProps");
|
|
@@ -101,6 +123,19 @@ const InputBase = ({ inputProps }) => {
|
|
|
101
123
|
const autoComplete = inputProps?.get(InputBaseProps.propNames.autoComplete);
|
|
102
124
|
const timeoutDelay = inputProps?.get(InputBaseProps.propNames.timeoutDelay) || 100;
|
|
103
125
|
const rowsProps = inputProps?.get(InputBaseProps.propNames.rows);
|
|
126
|
+
const numericInputProps = inputProps?.get(InputBaseProps.propNames.numericInputProps) || null;
|
|
127
|
+
|
|
128
|
+
const isAdvancedNumericInput = type.toLowerCase() === "advancednumericinput";
|
|
129
|
+
const inputComponent = isAdvancedNumericInput ? AdvancedNumericInput : undefined;
|
|
130
|
+
const inputControlType = isAdvancedNumericInput ? "text" : type;
|
|
131
|
+
|
|
132
|
+
if (isAdvancedNumericInput && numericInputProps) {
|
|
133
|
+
Object.keys(numericInputProps).forEach(key => {
|
|
134
|
+
if (key !== "blurFormattingSkipFixedDecimalScale") {
|
|
135
|
+
inputAttributes[key] = numericInputProps[key];
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
104
139
|
|
|
105
140
|
const defaultRows = 4;
|
|
106
141
|
let rows = rowsProps;
|
|
@@ -116,34 +151,80 @@ const InputBase = ({ inputProps }) => {
|
|
|
116
151
|
const classes = useStyles({ label, errorPosition });
|
|
117
152
|
|
|
118
153
|
const onChangeHandler = event => {
|
|
119
|
-
event.persist
|
|
154
|
+
if (event.persist) {
|
|
155
|
+
event.persist();
|
|
156
|
+
}
|
|
120
157
|
|
|
121
158
|
if (!event.target.value || window.bypassDebounce === true) {
|
|
122
159
|
update(event.target.value, metadata);
|
|
123
160
|
}
|
|
124
|
-
|
|
125
161
|
setInputText(event.target.value);
|
|
126
162
|
};
|
|
127
163
|
|
|
164
|
+
const timerId = useRef(null);
|
|
165
|
+
|
|
166
|
+
React.useEffect(() => {
|
|
167
|
+
return () => {
|
|
168
|
+
clearTimeout(timerId.current);
|
|
169
|
+
timerId.current = null;
|
|
170
|
+
};
|
|
171
|
+
}, []);
|
|
172
|
+
|
|
173
|
+
const onBlurInternal = e => {
|
|
174
|
+
let updateValue = (inputText ?? value).toString(); // value cannot be null as defined above
|
|
175
|
+
|
|
176
|
+
if (timerId.current) {
|
|
177
|
+
clearTimeout(timerId.current);
|
|
178
|
+
timerId.current = null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (isAdvancedNumericInput) {
|
|
182
|
+
const formattingProps = { ...numericInputProps };
|
|
183
|
+
delete formattingProps.blurFormattingSkipFixedDecimalScale;
|
|
184
|
+
|
|
185
|
+
if (numericInputProps?.blurFormattingSkipFixedDecimalScale !== true) {
|
|
186
|
+
formattingProps.fixedDecimalScale = true;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
updateValue = numericFormatter(updateValue, formattingProps);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
update(updateValue, metadata);
|
|
193
|
+
setInputText(null);
|
|
194
|
+
|
|
195
|
+
if (onBlur) {
|
|
196
|
+
onBlur(e);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
128
200
|
const inputBaseInputStyle = inputProps?.getStyle(InputBaseProps.ruleNames.input);
|
|
129
201
|
const errorTextStyle = inputProps?.getStyle(InputBaseProps.ruleNames.errorText);
|
|
130
|
-
|
|
131
202
|
const [inputText, setInputText] = React.useState(null);
|
|
132
|
-
|
|
133
203
|
const textToDisplay = inputText ?? value;
|
|
134
204
|
|
|
135
205
|
React.useEffect(() => {
|
|
136
|
-
if (inputText
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
setInputText(null);
|
|
206
|
+
if (inputText === null || window.bypassDebounce === true) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
140
209
|
|
|
141
|
-
|
|
210
|
+
if (inputText !== value) {
|
|
211
|
+
clearTimeout(timerId.current);
|
|
212
|
+
timerId.current = setTimeout(() => {
|
|
213
|
+
update(inputText, metadata);
|
|
214
|
+
setInputText(null);
|
|
142
215
|
}, timeoutDelay);
|
|
143
|
-
|
|
216
|
+
|
|
217
|
+
return () => {
|
|
218
|
+
clearTimeout(timerId.current);
|
|
219
|
+
timerId.current = null;
|
|
220
|
+
};
|
|
221
|
+
} else {
|
|
222
|
+
setInputText(null);
|
|
223
|
+
clearTimeout(timerId.current);
|
|
144
224
|
}
|
|
225
|
+
|
|
145
226
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
146
|
-
}, [inputText, value]);
|
|
227
|
+
}, [inputText, metadata, timeoutDelay, update, value]);
|
|
147
228
|
|
|
148
229
|
return (
|
|
149
230
|
<div className={classes.container}>
|
|
@@ -157,15 +238,16 @@ const InputBase = ({ inputProps }) => {
|
|
|
157
238
|
multiline: classes.multiline,
|
|
158
239
|
inputMultiline: classes.inputMultiline,
|
|
159
240
|
}}
|
|
160
|
-
onBlur={
|
|
241
|
+
onBlur={onBlurInternal}
|
|
161
242
|
onClick={onClick}
|
|
162
|
-
type={
|
|
243
|
+
type={inputControlType}
|
|
163
244
|
placeholder={placeholder}
|
|
164
245
|
value={textToDisplay}
|
|
165
246
|
fullWidth={true}
|
|
166
247
|
onChange={event => onChangeHandler(event)}
|
|
167
248
|
error={!!error}
|
|
168
249
|
inputProps={inputAttributes}
|
|
250
|
+
inputComponent={inputComponent}
|
|
169
251
|
disabled={disabled}
|
|
170
252
|
multiline={multiline}
|
|
171
253
|
startAdornment={startAdornment}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { mount } from "enzyme";
|
|
3
|
-
import InputBase from "./InputBase";
|
|
3
|
+
import InputBase, { AdvancedNumericInput } from "./InputBase";
|
|
4
4
|
import InputBaseMUI from "@material-ui/core/InputBase";
|
|
5
5
|
import sinon from "sinon";
|
|
6
6
|
import { ignoreConsoleError } from "../../../utils/testUtils";
|
|
7
7
|
import InputBaseProps from "./InputBaseProps";
|
|
8
8
|
import { act } from "unexpected-reaction";
|
|
9
|
+
import { fireEvent, render, getByDisplayValue } from "@testing-library/react";
|
|
9
10
|
|
|
10
11
|
describe("InputBase Component", () => {
|
|
11
12
|
let update, container;
|
|
@@ -285,6 +286,35 @@ describe("InputBase Component", () => {
|
|
|
285
286
|
|
|
286
287
|
expect(mountedComponent.containsMatchingElement(expected), "to be truthy");
|
|
287
288
|
});
|
|
289
|
+
|
|
290
|
+
it("Change value on blur with pending timer", () => {
|
|
291
|
+
window.bypassDebounce = false;
|
|
292
|
+
const inputProps = new InputBaseProps();
|
|
293
|
+
const aLabel = "aLabel";
|
|
294
|
+
const aValue = "12.2";
|
|
295
|
+
const metadata = {
|
|
296
|
+
test: "value",
|
|
297
|
+
};
|
|
298
|
+
const onBlur = sinon.spy().named("blur");
|
|
299
|
+
|
|
300
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
301
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
302
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
303
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
304
|
+
inputProps.set(InputBaseProps.propNames.onBlur, onBlur);
|
|
305
|
+
inputProps.set(InputBaseProps.propNames.timeoutDelay, 1000);
|
|
306
|
+
|
|
307
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
308
|
+
const mountedComponent = mount(component);
|
|
309
|
+
const input = mountedComponent.find("input");
|
|
310
|
+
|
|
311
|
+
input.simulate("change", { target: { value: "13", focus: () => {} } });
|
|
312
|
+
input.simulate("blur", {});
|
|
313
|
+
|
|
314
|
+
expect(onBlur, "was called once");
|
|
315
|
+
expect(update, "not to have calls satisfying", [{ args: [aValue, metadata] }]);
|
|
316
|
+
expect(update, "to have calls satisfying", [{ args: ["13", metadata] }]);
|
|
317
|
+
});
|
|
288
318
|
});
|
|
289
319
|
|
|
290
320
|
describe("InputBase component debouce", () => {
|
|
@@ -350,3 +380,309 @@ describe("InputBase component debouce", () => {
|
|
|
350
380
|
expect(input.get(0).props.value, "to equal", "");
|
|
351
381
|
});
|
|
352
382
|
});
|
|
383
|
+
|
|
384
|
+
describe("AdvancedNumericInput", () => {
|
|
385
|
+
const noop = function () {};
|
|
386
|
+
let update, container;
|
|
387
|
+
beforeEach(() => {
|
|
388
|
+
window.bypassDebounce = true;
|
|
389
|
+
jest.useFakeTimers();
|
|
390
|
+
|
|
391
|
+
container = document.createElement("div");
|
|
392
|
+
document.body.appendChild(container);
|
|
393
|
+
update = sinon.spy().named("update");
|
|
394
|
+
});
|
|
395
|
+
afterEach(() => {
|
|
396
|
+
jest.useRealTimers();
|
|
397
|
+
delete window.bypassDebounce;
|
|
398
|
+
document.body.removeChild(container);
|
|
399
|
+
container = null;
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it("Renders InputBase component as advanced numeric input", () => {
|
|
403
|
+
const inputProps = new InputBaseProps();
|
|
404
|
+
const aLabel = "aLabel";
|
|
405
|
+
const aValue = "value";
|
|
406
|
+
|
|
407
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
408
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
409
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
410
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
411
|
+
|
|
412
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
413
|
+
|
|
414
|
+
const mountedComponent = mount(component);
|
|
415
|
+
const expected = <InputBaseMUI value={aValue} title="" inputComponent={AdvancedNumericInput} />;
|
|
416
|
+
|
|
417
|
+
expect(mountedComponent.containsMatchingElement(expected), "to be truthy");
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it("Renders InputBase component as advanced numeric input with custom numeric props", () => {
|
|
421
|
+
const inputProps = new InputBaseProps();
|
|
422
|
+
const aLabel = "aLabel";
|
|
423
|
+
const aValue = "value";
|
|
424
|
+
|
|
425
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
426
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
427
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
428
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
429
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
430
|
+
|
|
431
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
432
|
+
|
|
433
|
+
const mountedComponent = mount(component);
|
|
434
|
+
|
|
435
|
+
const advInput = mountedComponent.find("AdvancedNumericInput");
|
|
436
|
+
expect(advInput.props().decimalScale, "to be", 2);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it("Change advanced numeric input value", () => {
|
|
440
|
+
const inputProps = new InputBaseProps();
|
|
441
|
+
const aLabel = "aLabel";
|
|
442
|
+
const aValue = "12.2";
|
|
443
|
+
const metadata = {
|
|
444
|
+
test: "value",
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
448
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
449
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
450
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
451
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
452
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
453
|
+
|
|
454
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
455
|
+
const mountedComponent = mount(component);
|
|
456
|
+
const input = mountedComponent.find("input");
|
|
457
|
+
input.simulate("change", { target: { value: "13", focus: noop } });
|
|
458
|
+
|
|
459
|
+
expect(update, "to have calls satisfying", [{ args: ["13", metadata] }]);
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it("Change advanced numeric input on blur without custom blur method", () => {
|
|
463
|
+
const inputProps = new InputBaseProps();
|
|
464
|
+
const aLabel = "aLabel";
|
|
465
|
+
const aValue = "12.2";
|
|
466
|
+
const metadata = {
|
|
467
|
+
test: "value",
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
471
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
472
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
473
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
474
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
475
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
476
|
+
|
|
477
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
478
|
+
const mountedComponent = mount(component);
|
|
479
|
+
const input = mountedComponent.find("input");
|
|
480
|
+
|
|
481
|
+
input.simulate("blur", {});
|
|
482
|
+
|
|
483
|
+
expect(update, "to have calls satisfying", [{ args: ["12.20", metadata] }]);
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
it("Onblur send a formatted string instead of a number", () => {
|
|
487
|
+
const inputProps = new InputBaseProps();
|
|
488
|
+
const aLabel = "aLabel";
|
|
489
|
+
const aValue = 12.2;
|
|
490
|
+
const metadata = {
|
|
491
|
+
test: "value",
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
495
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
496
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
497
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
498
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
499
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
500
|
+
|
|
501
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
502
|
+
const mountedComponent = mount(component);
|
|
503
|
+
const input = mountedComponent.find("input");
|
|
504
|
+
|
|
505
|
+
input.simulate("blur", {});
|
|
506
|
+
|
|
507
|
+
expect(update, "to have calls satisfying", [{ args: ["12.20", metadata] }]);
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
it("Onblur send a formatted string with default numeric input props", () => {
|
|
511
|
+
const inputProps = new InputBaseProps();
|
|
512
|
+
const aLabel = "aLabel";
|
|
513
|
+
const aValue = 12.2;
|
|
514
|
+
const metadata = {
|
|
515
|
+
test: "value",
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
519
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
520
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
521
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
522
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
523
|
+
|
|
524
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
525
|
+
const mountedComponent = mount(component);
|
|
526
|
+
const input = mountedComponent.find("input");
|
|
527
|
+
|
|
528
|
+
input.simulate("blur", {});
|
|
529
|
+
|
|
530
|
+
expect(update, "to have calls satisfying", [{ args: ["12.2", metadata] }]);
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it("Onblur send an unformatted string when blurFormattingSkipFixedDecimalScale is true", () => {
|
|
534
|
+
const inputProps = new InputBaseProps();
|
|
535
|
+
const aLabel = "aLabel";
|
|
536
|
+
const aValue = 12.2;
|
|
537
|
+
const metadata = {
|
|
538
|
+
test: "value",
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
542
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
543
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
544
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
545
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, {
|
|
546
|
+
decimalScale: 2,
|
|
547
|
+
blurFormattingSkipFixedDecimalScale: true,
|
|
548
|
+
});
|
|
549
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
550
|
+
|
|
551
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
552
|
+
const mountedComponent = mount(component);
|
|
553
|
+
const input = mountedComponent.find("input");
|
|
554
|
+
|
|
555
|
+
input.simulate("blur", {});
|
|
556
|
+
|
|
557
|
+
expect(update, "to have calls satisfying", [{ args: ["12.2", metadata] }]);
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
it("Onblur send an empty string when the initial value is empty", () => {
|
|
561
|
+
const inputProps = new InputBaseProps();
|
|
562
|
+
const aLabel = "aLabel";
|
|
563
|
+
const aValue = null;
|
|
564
|
+
const metadata = {
|
|
565
|
+
test: "value",
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
569
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
570
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
571
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
572
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
573
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
574
|
+
|
|
575
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
576
|
+
const mountedComponent = mount(component);
|
|
577
|
+
const input = mountedComponent.find("input");
|
|
578
|
+
|
|
579
|
+
input.simulate("blur", {});
|
|
580
|
+
|
|
581
|
+
expect(update, "to have calls satisfying", [{ args: ["", metadata] }]);
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it("Change advanced numeric input on blur with no pending timer", () => {
|
|
585
|
+
const inputProps = new InputBaseProps();
|
|
586
|
+
const aLabel = "aLabel";
|
|
587
|
+
const aValue = "12.2";
|
|
588
|
+
const metadata = {
|
|
589
|
+
test: "value",
|
|
590
|
+
};
|
|
591
|
+
const onBlur = sinon.spy().named("blur");
|
|
592
|
+
|
|
593
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
594
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
595
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
596
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
597
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
598
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
599
|
+
inputProps.set(InputBaseProps.propNames.onBlur, onBlur);
|
|
600
|
+
|
|
601
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
602
|
+
const mountedComponent = mount(component);
|
|
603
|
+
const input = mountedComponent.find("input");
|
|
604
|
+
|
|
605
|
+
input.simulate("blur", {});
|
|
606
|
+
|
|
607
|
+
expect(onBlur, "was called once");
|
|
608
|
+
expect(update, "to have calls satisfying", [{ args: ["12.20", metadata] }]);
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it("Change advanced numeric input on blur with pending timer", () => {
|
|
612
|
+
window.bypassDebounce = false;
|
|
613
|
+
const inputProps = new InputBaseProps();
|
|
614
|
+
const aLabel = "aLabel";
|
|
615
|
+
const aValue = "12.2";
|
|
616
|
+
const metadata = {
|
|
617
|
+
test: "value",
|
|
618
|
+
};
|
|
619
|
+
const onBlur = sinon.spy().named("blur");
|
|
620
|
+
|
|
621
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
622
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
623
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
624
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
625
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
626
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
627
|
+
inputProps.set(InputBaseProps.propNames.onBlur, onBlur);
|
|
628
|
+
inputProps.set(InputBaseProps.propNames.timeoutDelay, 1000);
|
|
629
|
+
|
|
630
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
631
|
+
const mountedComponent = mount(component);
|
|
632
|
+
const input = mountedComponent.find("input");
|
|
633
|
+
|
|
634
|
+
input.simulate("change", { target: { value: "13", focus: noop } });
|
|
635
|
+
input.simulate("blur", {});
|
|
636
|
+
|
|
637
|
+
expect(onBlur, "was called once");
|
|
638
|
+
expect(update, "not to have calls satisfying", [{ args: [aValue, metadata] }]);
|
|
639
|
+
expect(update, "to have calls satisfying", [{ args: ["13.00", metadata] }]);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
it("Local state is reset when the value props changes for the same value as inputText", () => {
|
|
643
|
+
window.bypassDebounce = false;
|
|
644
|
+
const inputProps = new InputBaseProps();
|
|
645
|
+
const aLabel = "aLabel";
|
|
646
|
+
const aValue = "12.2";
|
|
647
|
+
const metadata = {
|
|
648
|
+
test: "value",
|
|
649
|
+
};
|
|
650
|
+
const onBlur = sinon.spy().named("blur");
|
|
651
|
+
|
|
652
|
+
inputProps.set(InputBaseProps.propNames.update, update);
|
|
653
|
+
inputProps.set(InputBaseProps.propNames.value, aValue);
|
|
654
|
+
inputProps.set(InputBaseProps.propNames.label, aLabel);
|
|
655
|
+
inputProps.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
656
|
+
inputProps.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
657
|
+
inputProps.set(InputBaseProps.propNames.metadata, metadata);
|
|
658
|
+
inputProps.set(InputBaseProps.propNames.onBlur, onBlur);
|
|
659
|
+
inputProps.set(InputBaseProps.propNames.timeoutDelay, 1000);
|
|
660
|
+
|
|
661
|
+
const component = <InputBase inputProps={inputProps} />;
|
|
662
|
+
const { container, rerender } = render(component);
|
|
663
|
+
|
|
664
|
+
const input = getByDisplayValue(container, "12.2");
|
|
665
|
+
|
|
666
|
+
fireEvent.change(input, {
|
|
667
|
+
target: {
|
|
668
|
+
value: "13",
|
|
669
|
+
},
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
const inputProps2 = new InputBaseProps();
|
|
673
|
+
inputProps2.set(InputBaseProps.propNames.update, update);
|
|
674
|
+
inputProps2.set(InputBaseProps.propNames.value, "13");
|
|
675
|
+
inputProps2.set(InputBaseProps.propNames.label, aLabel);
|
|
676
|
+
inputProps2.set(InputBaseProps.propNames.type, "AdvancedNumericInput");
|
|
677
|
+
inputProps2.set(InputBaseProps.propNames.numericInputProps, { decimalScale: 2 });
|
|
678
|
+
inputProps2.set(InputBaseProps.propNames.metadata, metadata);
|
|
679
|
+
inputProps2.set(InputBaseProps.propNames.onBlur, onBlur);
|
|
680
|
+
inputProps2.set(InputBaseProps.propNames.timeoutDelay, 1000);
|
|
681
|
+
|
|
682
|
+
act(() => {
|
|
683
|
+
rerender(<InputBase inputProps={inputProps2} />);
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
// no idea what to assert here, this test is mostly for code coverage
|
|
687
|
+
});
|
|
688
|
+
});
|
|
@@ -19,6 +19,7 @@ class InputBaseProps extends ComponentProps {
|
|
|
19
19
|
autoComplete: "autoComplete",
|
|
20
20
|
timeoutDelay: "timeoutDelay",
|
|
21
21
|
rows: "rows",
|
|
22
|
+
numericInputProps: "numericInputProps",
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
static ruleNames = {
|
|
@@ -45,6 +46,7 @@ class InputBaseProps extends ComponentProps {
|
|
|
45
46
|
this.componentProps.set(this.constructor.propNames.autoComplete, null);
|
|
46
47
|
this.componentProps.set(this.constructor.propNames.timeoutDelay, null);
|
|
47
48
|
this.componentProps.set(this.constructor.propNames.rows, null);
|
|
49
|
+
this.componentProps.set(this.constructor.propNames.numericInputProps, null);
|
|
48
50
|
|
|
49
51
|
this.componentClasses.set(this.constructor.ruleNames.input, null);
|
|
50
52
|
this.componentClasses.set(this.constructor.ruleNames.errorText, null);
|
|
@@ -20,6 +20,7 @@ describe("InputBase Props", () => {
|
|
|
20
20
|
"autoComplete",
|
|
21
21
|
"timeoutDelay",
|
|
22
22
|
"rows",
|
|
23
|
+
"numericInputProps",
|
|
23
24
|
];
|
|
24
25
|
|
|
25
26
|
expect(InputBaseProps.propNames, "to have keys", propNames);
|
|
@@ -44,6 +45,7 @@ describe("InputBase Props", () => {
|
|
|
44
45
|
"autoComplete",
|
|
45
46
|
"timeoutDelay",
|
|
46
47
|
"rows",
|
|
48
|
+
"numericInputProps",
|
|
47
49
|
];
|
|
48
50
|
|
|
49
51
|
const ruleNames = ["input", "errorText"];
|
package/src/reducers/request.js
CHANGED
|
@@ -24,7 +24,8 @@ const requestReducer = (state = initialState, action) => {
|
|
|
24
24
|
}
|
|
25
25
|
if (action.type.endsWith("_FAILURE")) {
|
|
26
26
|
const requestName = action.type.replace(/_FAILURE$/, "");
|
|
27
|
-
|
|
27
|
+
const status = safeGet(action, "payload", "status");
|
|
28
|
+
if (status === 403 || status === 401) {
|
|
28
29
|
return state.deleteIn(["actives", requestName]).set("logout", true);
|
|
29
30
|
} else {
|
|
30
31
|
return state.deleteIn(["actives", requestName]).set("error", Immutable.fromJS(action));
|
|
@@ -125,4 +125,27 @@ describe("Request reducer", () => {
|
|
|
125
125
|
}),
|
|
126
126
|
);
|
|
127
127
|
});
|
|
128
|
+
|
|
129
|
+
it("clears activity flag and sets login flag when a request fails with status 401", () => {
|
|
130
|
+
const oldState = Immutable.fromJS({
|
|
131
|
+
actives: {
|
|
132
|
+
SOME_FLAG: true,
|
|
133
|
+
TEST_THIS: true,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
const action = {
|
|
137
|
+
type: "TEST_THIS_FAILURE",
|
|
138
|
+
payload: { status: 401, message: "UnauthorizedAccessException" },
|
|
139
|
+
};
|
|
140
|
+
const newState = reducer(oldState, action);
|
|
141
|
+
expect(newState, "not to be", oldState).and(
|
|
142
|
+
"to equal",
|
|
143
|
+
Immutable.fromJS({
|
|
144
|
+
actives: {
|
|
145
|
+
SOME_FLAG: true,
|
|
146
|
+
},
|
|
147
|
+
[LOGOUT]: true,
|
|
148
|
+
}),
|
|
149
|
+
);
|
|
150
|
+
});
|
|
128
151
|
});
|