orc-shared 1.5.0-dev.12 → 1.5.0-dev.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.
- package/dist/actions/navigation.js +16 -1
- package/dist/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +36 -48
- package/dist/reducers/navigation.js +16 -0
- package/package.json +1 -1
- package/src/actions/navigation.js +7 -0
- package/src/actions/navigation.test.js +12 -0
- package/src/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +33 -30
- package/src/components/MaterialUI/Inputs/PredefinedElements/SearchControl.test.js +39 -74
- package/src/reducers/navigation.js +24 -0
- package/src/reducers/navigation.test.js +38 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.setRoute = exports.setHrefConfig = exports.setCurrentPrependPath = exports.setClosingTabHandlerActions = exports.removeTab = exports.mapHref = exports.SET_ROUTE = exports.SET_HREF_CONFIG = exports.SET_CURRENT_PREPEND_PATH = exports.SET_CLOSING_TAB_HANDLER_ACTIONS = exports.REMOVE_TAB = exports.MAP_HREF = void 0;
|
|
4
|
+
exports.setRoute = exports.setHrefConfig = exports.setCurrentPrependPath = exports.setClosingTabHandlerActions = exports.removeTab = exports.removeModuleTabs = exports.mapHref = exports.SET_ROUTE = exports.SET_HREF_CONFIG = exports.SET_CURRENT_PREPEND_PATH = exports.SET_CLOSING_TAB_HANDLER_ACTIONS = exports.REMOVE_TAB = exports.REMOVE_MODULE_TABS = exports.MAP_HREF = void 0;
|
|
5
5
|
(function () {
|
|
6
6
|
var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
|
|
7
7
|
enterModule && enterModule(module);
|
|
@@ -57,6 +57,17 @@ var removeTab = function removeTab(module, path) {
|
|
|
57
57
|
};
|
|
58
58
|
};
|
|
59
59
|
exports.removeTab = removeTab;
|
|
60
|
+
var REMOVE_MODULE_TABS = "REMOVE_MODULE_TABS";
|
|
61
|
+
exports.REMOVE_MODULE_TABS = REMOVE_MODULE_TABS;
|
|
62
|
+
var removeModuleTabs = function removeModuleTabs(module) {
|
|
63
|
+
return {
|
|
64
|
+
type: REMOVE_MODULE_TABS,
|
|
65
|
+
payload: {
|
|
66
|
+
module: module
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
exports.removeModuleTabs = removeModuleTabs;
|
|
60
71
|
var SET_HREF_CONFIG = "SET_HREF_CONFIG";
|
|
61
72
|
exports.SET_HREF_CONFIG = SET_HREF_CONFIG;
|
|
62
73
|
var setHrefConfig = function setHrefConfig(prependPath, prependHref, otherConfigs) {
|
|
@@ -105,6 +116,8 @@ exports.setClosingTabHandlerActions = setClosingTabHandlerActions;
|
|
|
105
116
|
reactHotLoader.register(mapHref, "mapHref", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
106
117
|
reactHotLoader.register(REMOVE_TAB, "REMOVE_TAB", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
107
118
|
reactHotLoader.register(removeTab, "removeTab", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
119
|
+
reactHotLoader.register(REMOVE_MODULE_TABS, "REMOVE_MODULE_TABS", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
120
|
+
reactHotLoader.register(removeModuleTabs, "removeModuleTabs", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
108
121
|
reactHotLoader.register(SET_HREF_CONFIG, "SET_HREF_CONFIG", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
109
122
|
reactHotLoader.register(setHrefConfig, "setHrefConfig", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
110
123
|
reactHotLoader.register(SET_CURRENT_PREPEND_PATH, "SET_CURRENT_PREPEND_PATH", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
@@ -129,6 +142,8 @@ exports.setClosingTabHandlerActions = setClosingTabHandlerActions;
|
|
|
129
142
|
reactHotLoader.register(mapHref, "mapHref", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
130
143
|
reactHotLoader.register(REMOVE_TAB, "REMOVE_TAB", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
131
144
|
reactHotLoader.register(removeTab, "removeTab", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
145
|
+
reactHotLoader.register(REMOVE_MODULE_TABS, "REMOVE_MODULE_TABS", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
146
|
+
reactHotLoader.register(removeModuleTabs, "removeModuleTabs", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
132
147
|
reactHotLoader.register(SET_HREF_CONFIG, "SET_HREF_CONFIG", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
133
148
|
reactHotLoader.register(setHrefConfig, "setHrefConfig", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
134
149
|
reactHotLoader.register(SET_CURRENT_PREPEND_PATH, "SET_CURRENT_PREPEND_PATH", "/home/vsts/work/1/s/src/actions/navigation.js");
|
|
@@ -21,12 +21,6 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
21
21
|
var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
|
|
22
22
|
enterModule && enterModule(module);
|
|
23
23
|
})();
|
|
24
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
25
|
-
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
26
|
-
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
27
|
-
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
28
|
-
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
|
|
29
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
30
24
|
var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
|
|
31
25
|
return a;
|
|
32
26
|
};
|
|
@@ -107,15 +101,9 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
|
|
|
107
101
|
},
|
|
108
102
|
parentInput: {
|
|
109
103
|
flex: "13 0 0",
|
|
110
|
-
zIndex:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
border: function border(props) {
|
|
114
|
-
return props.focused ? "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.focus) : "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.grey.borders);
|
|
115
|
-
},
|
|
116
|
-
boxShadow: function boxShadow(props) {
|
|
117
|
-
return props.focused ? "0 0 4px ".concat(theme.palette.focus) : "none";
|
|
118
|
-
},
|
|
104
|
+
zIndex: 1,
|
|
105
|
+
border: "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.grey.borders),
|
|
106
|
+
boxShadow: "none",
|
|
119
107
|
width: "100%",
|
|
120
108
|
display: "inherit",
|
|
121
109
|
marginLeft: theme.spacing(-0.1),
|
|
@@ -133,6 +121,11 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
|
|
|
133
121
|
borderTopLeftRadius: 0,
|
|
134
122
|
borderBottomLeftRadius: 0
|
|
135
123
|
}
|
|
124
|
+
},
|
|
125
|
+
"&:focus-within": {
|
|
126
|
+
zIndex: 99,
|
|
127
|
+
border: "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.focus),
|
|
128
|
+
boxShadow: "0 0 4px ".concat(theme.palette.focus)
|
|
136
129
|
}
|
|
137
130
|
},
|
|
138
131
|
selectRoot: {
|
|
@@ -184,19 +177,27 @@ var SearchControl = function SearchControl(_ref) {
|
|
|
184
177
|
onSearch = _ref$onSearch === void 0 ? function () {} : _ref$onSearch,
|
|
185
178
|
disabled = _ref.disabled,
|
|
186
179
|
_ref$focusAndSelectSe = _ref.focusAndSelectSearchFieldOnLoad,
|
|
187
|
-
focusAndSelectSearchFieldOnLoad = _ref$focusAndSelectSe === void 0 ? true : _ref$focusAndSelectSe
|
|
180
|
+
focusAndSelectSearchFieldOnLoad = _ref$focusAndSelectSe === void 0 ? true : _ref$focusAndSelectSe,
|
|
181
|
+
_ref$focusSearchOnSea = _ref.focusSearchOnSearchOptionChange,
|
|
182
|
+
focusSearchOnSearchOptionChange = _ref$focusSearchOnSea === void 0 ? false : _ref$focusSearchOnSea;
|
|
188
183
|
searchOptions = !((_searchOptions = searchOptions) != null && _searchOptions.length) ? null : searchOptions;
|
|
189
184
|
searchOption = getSearchOptionValue(searchOptions, searchOption);
|
|
190
|
-
var
|
|
191
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
192
|
-
inputFocused = _useState2[0],
|
|
193
|
-
setInputFocused = _useState2[1];
|
|
194
|
-
var classes = useStyles({
|
|
195
|
-
focused: inputFocused
|
|
196
|
-
});
|
|
185
|
+
var classes = useStyles();
|
|
197
186
|
var inputRef = (0, _react.useRef)();
|
|
198
187
|
var update = function update(value) {
|
|
199
|
-
|
|
188
|
+
if (focusSearchOnSearchOptionChange && inputRef.current) {
|
|
189
|
+
onSearch(value, "");
|
|
190
|
+
setTimeout(function () {
|
|
191
|
+
/* istanbul ignore next */
|
|
192
|
+
if (inputRef.current) {
|
|
193
|
+
inputRef.current.value = "";
|
|
194
|
+
inputRef.current.focus();
|
|
195
|
+
inputRef.current.select();
|
|
196
|
+
}
|
|
197
|
+
}, 0);
|
|
198
|
+
} else {
|
|
199
|
+
onSearch(value, defaultValue);
|
|
200
|
+
}
|
|
200
201
|
};
|
|
201
202
|
var selectProps = new _SelectProps.default();
|
|
202
203
|
selectProps.set(_SelectProps.default.propNames.update, update);
|
|
@@ -213,23 +214,11 @@ var SearchControl = function SearchControl(_ref) {
|
|
|
213
214
|
});
|
|
214
215
|
selectProps.setStyle(_SelectProps.default.ruleNames.root, classes.selectRoot);
|
|
215
216
|
selectProps.setStyle(_SelectProps.default.ruleNames.paper, classes.selectPaper);
|
|
216
|
-
var handleKeyDown = function handleKeyDown(e) {
|
|
217
|
-
if (e.key === "Enter") {
|
|
218
|
-
onSearch(searchOption, e.target.value);
|
|
219
|
-
e.preventDefault();
|
|
220
|
-
e.stopPropagation();
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
var onFocusedEvent = function onFocusedEvent(event, focused) {
|
|
224
|
-
setInputFocused(focused);
|
|
225
|
-
event.preventDefault();
|
|
226
|
-
event.stopPropagation();
|
|
227
|
-
};
|
|
228
217
|
(0, _react.useEffect)(function () {
|
|
218
|
+
/* istanbul ignore next */
|
|
229
219
|
if (focusAndSelectSearchFieldOnLoad && inputRef.current) {
|
|
230
220
|
inputRef.current.focus();
|
|
231
221
|
inputRef.current.select();
|
|
232
|
-
setInputFocused(true);
|
|
233
222
|
}
|
|
234
223
|
}, [focusAndSelectSearchFieldOnLoad]);
|
|
235
224
|
var SelectSection = function SelectSection() {
|
|
@@ -239,13 +228,19 @@ var SearchControl = function SearchControl(_ref) {
|
|
|
239
228
|
selectProps: selectProps
|
|
240
229
|
});
|
|
241
230
|
};
|
|
231
|
+
var onSubmit = function onSubmit(event) {
|
|
232
|
+
var _inputRef$current;
|
|
233
|
+
// using form submit instead of a keydown (with key=enter) to allow the 'enter key' event to be canceled elsewhere to avoid the submit event
|
|
234
|
+
onSearch(searchOption, (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.value);
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
};
|
|
242
237
|
var inputSection = /*#__PURE__*/_react.default.createElement("div", {
|
|
243
238
|
"data-qa": "searchInput",
|
|
244
|
-
"data-qa-is-focused": inputFocused,
|
|
245
239
|
className: classes.parentInput
|
|
246
240
|
}, /*#__PURE__*/_react.default.createElement("form", {
|
|
247
241
|
"data-qa": "searchForm",
|
|
248
|
-
className: classes.fullWidth
|
|
242
|
+
className: classes.fullWidth,
|
|
243
|
+
onSubmitCapture: onSubmit
|
|
249
244
|
}, /*#__PURE__*/_react.default.createElement(_Input.default, {
|
|
250
245
|
placeholder: placeholder,
|
|
251
246
|
defaultValue: defaultValue,
|
|
@@ -255,14 +250,7 @@ var SearchControl = function SearchControl(_ref) {
|
|
|
255
250
|
classes: {
|
|
256
251
|
input: classes.controlInput
|
|
257
252
|
},
|
|
258
|
-
onKeyDown: handleKeyDown,
|
|
259
253
|
disableUnderline: true,
|
|
260
|
-
onFocus: function onFocus(e) {
|
|
261
|
-
return onFocusedEvent(e, true);
|
|
262
|
-
},
|
|
263
|
-
onBlur: function onBlur(e) {
|
|
264
|
-
return onFocusedEvent(e, false);
|
|
265
|
-
},
|
|
266
254
|
endAdornment: /*#__PURE__*/_react.default.createElement(_InputAdornment.default, {
|
|
267
255
|
position: "start"
|
|
268
256
|
}, /*#__PURE__*/_react.default.createElement(_IconButton.default, {
|
|
@@ -296,10 +284,10 @@ var SearchControl = function SearchControl(_ref) {
|
|
|
296
284
|
className: classes.container
|
|
297
285
|
}, /*#__PURE__*/_react.default.createElement(SelectSection, null), inputSection, searchSection);
|
|
298
286
|
};
|
|
299
|
-
__signature__(SearchControl, "
|
|
287
|
+
__signature__(SearchControl, "useStyles{classes}\nuseRef{inputRef}\nuseEffect{}", function () {
|
|
300
288
|
return [useStyles];
|
|
301
289
|
});
|
|
302
|
-
__signature__(SearchControl, "
|
|
290
|
+
__signature__(SearchControl, "useStyles{classes}\nuseRef{inputRef}\nuseEffect{}", function () {
|
|
303
291
|
return [useStyles];
|
|
304
292
|
});
|
|
305
293
|
var _default = SearchControl;
|
|
@@ -83,6 +83,22 @@ var navigationReducer = function navigationReducer(state, action) {
|
|
|
83
83
|
s.deleteIn(["tabIndex", remainingSection]);
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
|
+
case _navigation.REMOVE_MODULE_TABS:
|
|
87
|
+
return state.withMutations(function (s) {
|
|
88
|
+
var module = action.payload.module;
|
|
89
|
+
s.deleteIn(["moduleTabs", module]);
|
|
90
|
+
s.deleteIn(["closingTabsHandlerActions", module]);
|
|
91
|
+
s.get("tabIndex").keySeq().forEach(function (key) {
|
|
92
|
+
if (key.startsWith(module)) {
|
|
93
|
+
s.deleteIn(["tabIndex", key]);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
s.get("mappedHrefs").keySeq().forEach(function (key) {
|
|
97
|
+
if (key.startsWith(module)) {
|
|
98
|
+
s.deleteIn(["mappedHrefs", key]);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
86
102
|
case _navigation.SET_HREF_CONFIG:
|
|
87
103
|
return state.set("config", _immutable.default.fromJS(action.payload));
|
|
88
104
|
case _navigation.SET_CURRENT_PREPEND_PATH:
|
package/package.json
CHANGED
|
@@ -25,6 +25,13 @@ export const removeTab = (module, path) => ({
|
|
|
25
25
|
payload: { module, path },
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
export const REMOVE_MODULE_TABS = "REMOVE_MODULE_TABS";
|
|
29
|
+
|
|
30
|
+
export const removeModuleTabs = module => ({
|
|
31
|
+
type: REMOVE_MODULE_TABS,
|
|
32
|
+
payload: { module },
|
|
33
|
+
});
|
|
34
|
+
|
|
28
35
|
export const SET_HREF_CONFIG = "SET_HREF_CONFIG";
|
|
29
36
|
|
|
30
37
|
export const setHrefConfig = (prependPath, prependHref, otherConfigs = {}) => ({
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
SET_HREF_CONFIG,
|
|
6
6
|
setClosingTabHandlerActions,
|
|
7
7
|
SET_CLOSING_TAB_HANDLER_ACTIONS,
|
|
8
|
+
removeModuleTabs,
|
|
9
|
+
REMOVE_MODULE_TABS,
|
|
8
10
|
} from "./navigation";
|
|
9
11
|
|
|
10
12
|
describe("removeTab", () => {
|
|
@@ -18,6 +20,16 @@ describe("removeTab", () => {
|
|
|
18
20
|
}));
|
|
19
21
|
});
|
|
20
22
|
|
|
23
|
+
describe("removeModuleTabs", () => {
|
|
24
|
+
it("creates a remove module tabs action", () =>
|
|
25
|
+
expect(removeModuleTabs, "when called with", ["module"], "to equal", {
|
|
26
|
+
type: REMOVE_MODULE_TABS,
|
|
27
|
+
payload: {
|
|
28
|
+
module: "module",
|
|
29
|
+
},
|
|
30
|
+
}));
|
|
31
|
+
});
|
|
32
|
+
|
|
21
33
|
describe("setHrefConfig", () => {
|
|
22
34
|
it("set href config action", () =>
|
|
23
35
|
expect(setHrefConfig, "when called with", ["/:scope/", "/scope/"], "to equal", {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useRef, useEffect } from "react";
|
|
2
2
|
import { makeStyles } from "@material-ui/core/styles";
|
|
3
3
|
import SelectProps from "../SelectProps";
|
|
4
4
|
import Icon from "../../DataDisplay/Icon";
|
|
@@ -80,12 +80,9 @@ export const useStyles = makeStyles(theme => ({
|
|
|
80
80
|
},
|
|
81
81
|
parentInput: {
|
|
82
82
|
flex: "13 0 0",
|
|
83
|
-
zIndex:
|
|
84
|
-
border:
|
|
85
|
-
|
|
86
|
-
? `${theme.spacing(0.1)} solid ${theme.palette.focus}`
|
|
87
|
-
: `${theme.spacing(0.1)} solid ${theme.palette.grey.borders}`,
|
|
88
|
-
boxShadow: props => (props.focused ? `0 0 4px ${theme.palette.focus}` : "none"),
|
|
83
|
+
zIndex: 1,
|
|
84
|
+
border: `${theme.spacing(0.1)} solid ${theme.palette.grey.borders}`,
|
|
85
|
+
boxShadow: "none",
|
|
89
86
|
width: "100%",
|
|
90
87
|
display: "inherit",
|
|
91
88
|
marginLeft: theme.spacing(-0.1),
|
|
@@ -104,6 +101,11 @@ export const useStyles = makeStyles(theme => ({
|
|
|
104
101
|
borderBottomLeftRadius: 0,
|
|
105
102
|
},
|
|
106
103
|
},
|
|
104
|
+
"&:focus-within": {
|
|
105
|
+
zIndex: 99,
|
|
106
|
+
border: `${theme.spacing(0.1)} solid ${theme.palette.focus}`,
|
|
107
|
+
boxShadow: `0 0 4px ${theme.palette.focus}`,
|
|
108
|
+
},
|
|
107
109
|
},
|
|
108
110
|
selectRoot: {
|
|
109
111
|
zIndex: 10,
|
|
@@ -150,17 +152,29 @@ const SearchControl = ({
|
|
|
150
152
|
onSearch = () => {},
|
|
151
153
|
disabled,
|
|
152
154
|
focusAndSelectSearchFieldOnLoad = true,
|
|
155
|
+
focusSearchOnSearchOptionChange = false,
|
|
153
156
|
}) => {
|
|
154
157
|
searchOptions = !searchOptions?.length ? null : searchOptions;
|
|
155
158
|
searchOption = getSearchOptionValue(searchOptions, searchOption);
|
|
156
|
-
const [inputFocused, setInputFocused] = useState(false);
|
|
157
159
|
|
|
158
|
-
const classes = useStyles(
|
|
160
|
+
const classes = useStyles();
|
|
159
161
|
|
|
160
162
|
const inputRef = useRef();
|
|
161
163
|
|
|
162
164
|
const update = value => {
|
|
163
|
-
|
|
165
|
+
if (focusSearchOnSearchOptionChange && inputRef.current) {
|
|
166
|
+
onSearch(value, "");
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
/* istanbul ignore next */
|
|
169
|
+
if (inputRef.current) {
|
|
170
|
+
inputRef.current.value = "";
|
|
171
|
+
inputRef.current.focus();
|
|
172
|
+
inputRef.current.select();
|
|
173
|
+
}
|
|
174
|
+
}, 0);
|
|
175
|
+
} else {
|
|
176
|
+
onSearch(value, defaultValue);
|
|
177
|
+
}
|
|
164
178
|
};
|
|
165
179
|
|
|
166
180
|
const selectProps = new SelectProps();
|
|
@@ -179,25 +193,11 @@ const SearchControl = ({
|
|
|
179
193
|
selectProps.setStyle(SelectProps.ruleNames.root, classes.selectRoot);
|
|
180
194
|
selectProps.setStyle(SelectProps.ruleNames.paper, classes.selectPaper);
|
|
181
195
|
|
|
182
|
-
const handleKeyDown = e => {
|
|
183
|
-
if (e.key === "Enter") {
|
|
184
|
-
onSearch(searchOption, e.target.value);
|
|
185
|
-
e.preventDefault();
|
|
186
|
-
e.stopPropagation();
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const onFocusedEvent = (event, focused) => {
|
|
191
|
-
setInputFocused(focused);
|
|
192
|
-
event.preventDefault();
|
|
193
|
-
event.stopPropagation();
|
|
194
|
-
};
|
|
195
|
-
|
|
196
196
|
useEffect(() => {
|
|
197
|
+
/* istanbul ignore next */
|
|
197
198
|
if (focusAndSelectSearchFieldOnLoad && inputRef.current) {
|
|
198
199
|
inputRef.current.focus();
|
|
199
200
|
inputRef.current.select();
|
|
200
|
-
setInputFocused(true);
|
|
201
201
|
}
|
|
202
202
|
}, [focusAndSelectSearchFieldOnLoad]);
|
|
203
203
|
|
|
@@ -206,9 +206,15 @@ const SearchControl = ({
|
|
|
206
206
|
else return <Select className={classes.selectInput} options={searchOptions} selectProps={selectProps} />;
|
|
207
207
|
};
|
|
208
208
|
|
|
209
|
+
const onSubmit = event => {
|
|
210
|
+
// using form submit instead of a keydown (with key=enter) to allow the 'enter key' event to be canceled elsewhere to avoid the submit event
|
|
211
|
+
onSearch(searchOption, inputRef.current?.value);
|
|
212
|
+
event.preventDefault();
|
|
213
|
+
};
|
|
214
|
+
|
|
209
215
|
const inputSection = (
|
|
210
|
-
<div data-qa="searchInput"
|
|
211
|
-
<form data-qa="searchForm" className={classes.fullWidth}>
|
|
216
|
+
<div data-qa="searchInput" className={classes.parentInput}>
|
|
217
|
+
<form data-qa="searchForm" className={classes.fullWidth} onSubmitCapture={onSubmit}>
|
|
212
218
|
<Input
|
|
213
219
|
placeholder={placeholder}
|
|
214
220
|
defaultValue={defaultValue}
|
|
@@ -216,10 +222,7 @@ const SearchControl = ({
|
|
|
216
222
|
type="text"
|
|
217
223
|
disabled={disabled}
|
|
218
224
|
classes={{ input: classes.controlInput }}
|
|
219
|
-
onKeyDown={handleKeyDown}
|
|
220
225
|
disableUnderline={true}
|
|
221
|
-
onFocus={e => onFocusedEvent(e, true)}
|
|
222
|
-
onBlur={e => onFocusedEvent(e, false)}
|
|
223
226
|
endAdornment={
|
|
224
227
|
<InputAdornment position="start">
|
|
225
228
|
<IconButton
|
|
@@ -53,10 +53,11 @@ describe("useStyles", () => {
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
describe("SearchControl Component", () => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
jest.useFakeTimers();
|
|
58
|
+
});
|
|
59
59
|
afterEach(() => {
|
|
60
|
+
jest.useRealTimers();
|
|
60
61
|
jest.clearAllMocks();
|
|
61
62
|
});
|
|
62
63
|
|
|
@@ -232,8 +233,7 @@ describe("SearchControl Component", () => {
|
|
|
232
233
|
expect(searchInput.length, "to be", 1);
|
|
233
234
|
|
|
234
235
|
searchInput.instance().value = "abc";
|
|
235
|
-
|
|
236
|
-
searchInput.simulate("keydown", { key: "Enter" });
|
|
236
|
+
mountedComponent.find("form").simulate("submit", { preventDefault: () => {} });
|
|
237
237
|
|
|
238
238
|
expect(onSearchEvent, "to have calls satisfying", [{ args: ["aValue", "abc"] }]);
|
|
239
239
|
});
|
|
@@ -371,7 +371,7 @@ describe("SearchControl Component", () => {
|
|
|
371
371
|
expect(onSearchEvent, "to have calls satisfying", [{ args: ["anotherValue", "abcdef123"] }]);
|
|
372
372
|
});
|
|
373
373
|
|
|
374
|
-
it("Search Control should
|
|
374
|
+
it("Search Control should clear the search when changing the option", () => {
|
|
375
375
|
const options = [
|
|
376
376
|
{ value: "aValue", label: "aLabel" },
|
|
377
377
|
{ value: "anotherValue", label: "anotherLabel" },
|
|
@@ -385,8 +385,8 @@ describe("SearchControl Component", () => {
|
|
|
385
385
|
placeholder="placeHolderTest"
|
|
386
386
|
defaultValue={"abcdef123"}
|
|
387
387
|
searchOptions={options}
|
|
388
|
-
searchOption={"anotherValue"}
|
|
389
388
|
onSearch={onSearchEvent}
|
|
389
|
+
focusSearchOnSearchOptionChange={true}
|
|
390
390
|
/>
|
|
391
391
|
</TestWrapper>
|
|
392
392
|
);
|
|
@@ -395,48 +395,53 @@ describe("SearchControl Component", () => {
|
|
|
395
395
|
|
|
396
396
|
const selectMui = mountedComponent.find(SelectMUI);
|
|
397
397
|
|
|
398
|
-
|
|
399
|
-
|
|
398
|
+
const event = {
|
|
399
|
+
target: {
|
|
400
|
+
value: "anotherValue",
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
onSearchEvent.resetHistory();
|
|
405
|
+
|
|
406
|
+
selectMui.invoke("onChange")(event);
|
|
407
|
+
|
|
408
|
+
expect(onSearchEvent.callCount, "to equal", 1);
|
|
409
|
+
expect(onSearchEvent, "to have calls satisfying", [{ args: ["anotherValue", ""] }]);
|
|
410
|
+
|
|
411
|
+
const allInputs = mountedComponent.find("input");
|
|
412
|
+
const searchInput = allInputs.find("[placeholder='placeHolderTest']");
|
|
413
|
+
expect(searchInput.length, "to be", 1);
|
|
400
414
|
|
|
401
|
-
|
|
402
|
-
jest.
|
|
415
|
+
expect(searchInput.instance().value, "to be", "abcdef123");
|
|
416
|
+
jest.runOnlyPendingTimers();
|
|
417
|
+
expect(searchInput.instance().value, "to be", "");
|
|
418
|
+
});
|
|
403
419
|
|
|
420
|
+
it("Search Control should render with the 2nd value", () => {
|
|
404
421
|
const options = [
|
|
405
422
|
{ value: "aValue", label: "aLabel" },
|
|
406
423
|
{ value: "anotherValue", label: "anotherLabel" },
|
|
407
424
|
];
|
|
408
425
|
|
|
426
|
+
const onSearchEvent = sinon.spy().named("search");
|
|
427
|
+
|
|
409
428
|
const component = (
|
|
410
429
|
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
411
|
-
<SearchControl
|
|
430
|
+
<SearchControl
|
|
431
|
+
placeholder="placeHolderTest"
|
|
432
|
+
defaultValue={"abcdef123"}
|
|
433
|
+
searchOptions={options}
|
|
434
|
+
searchOption={"anotherValue"}
|
|
435
|
+
onSearch={onSearchEvent}
|
|
436
|
+
/>
|
|
412
437
|
</TestWrapper>
|
|
413
438
|
);
|
|
414
439
|
|
|
415
440
|
const mountedComponent = mount(component);
|
|
416
441
|
|
|
417
|
-
const
|
|
418
|
-
const searchInput = allInputs.find("[placeholder='placeHolderTest']");
|
|
419
|
-
expect(searchInput.length, "to be", 1);
|
|
420
|
-
|
|
421
|
-
let searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
|
|
422
|
-
expect(searchEditParent.length, "to be", 1);
|
|
423
|
-
|
|
424
|
-
expect(searchEditParent.props()["data-qa-is-focused"], "to be", false);
|
|
425
|
-
|
|
426
|
-
const event = {
|
|
427
|
-
preventDefault: () => {},
|
|
428
|
-
stopPropagation: () => {},
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
searchInput.invoke("onFocus")(event);
|
|
432
|
-
|
|
433
|
-
searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
|
|
434
|
-
expect(searchEditParent.props()["data-qa-is-focused"], "to be", true);
|
|
435
|
-
|
|
436
|
-
searchInput.invoke("onBlur")(event);
|
|
442
|
+
const selectMui = mountedComponent.find(SelectMUI);
|
|
437
443
|
|
|
438
|
-
|
|
439
|
-
expect(searchEditParent.props()["data-qa-is-focused"], "to be", false);
|
|
444
|
+
expect(selectMui.props().value, "to equal", "anotherValue");
|
|
440
445
|
});
|
|
441
446
|
|
|
442
447
|
it("Renders Search Control component without errors when disabled", () => {
|
|
@@ -484,46 +489,6 @@ describe("SearchControl Component", () => {
|
|
|
484
489
|
|
|
485
490
|
expect(component, "when mounted", "to satisfy", expected);
|
|
486
491
|
});
|
|
487
|
-
|
|
488
|
-
it("focusAndSelectSearchFieldOnLoad set to true gives focus to control", () => {
|
|
489
|
-
jest.spyOn(React, "useState").mockImplementation(useStateMock);
|
|
490
|
-
|
|
491
|
-
const options = [
|
|
492
|
-
{ value: "aValue", label: "aLabel" },
|
|
493
|
-
{ value: "anotherValue", label: "anotherLabel" },
|
|
494
|
-
];
|
|
495
|
-
|
|
496
|
-
const component = (
|
|
497
|
-
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
498
|
-
<SearchControl placeholder="placeHolderTest" searchOptions={options} focusAndSelectSearchFieldOnLoad={true} />
|
|
499
|
-
</TestWrapper>
|
|
500
|
-
);
|
|
501
|
-
|
|
502
|
-
const mountedComponent = mount(component);
|
|
503
|
-
const searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
|
|
504
|
-
|
|
505
|
-
expect(searchEditParent.props()["data-qa-is-focused"], "to be", true);
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
it("focusAndSelectSearchFieldOnLoad set to false does not give focus to control", () => {
|
|
509
|
-
jest.spyOn(React, "useState").mockImplementation(useStateMock);
|
|
510
|
-
|
|
511
|
-
const options = [
|
|
512
|
-
{ value: "aValue", label: "aLabel" },
|
|
513
|
-
{ value: "anotherValue", label: "anotherLabel" },
|
|
514
|
-
];
|
|
515
|
-
|
|
516
|
-
const component = (
|
|
517
|
-
<TestWrapper stylesProvider muiThemeProvider={{ theme }}>
|
|
518
|
-
<SearchControl placeholder="placeHolderTest" searchOptions={options} focusAndSelectSearchFieldOnLoad={false} />
|
|
519
|
-
</TestWrapper>
|
|
520
|
-
);
|
|
521
|
-
|
|
522
|
-
const mountedComponent = mount(component);
|
|
523
|
-
const searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
|
|
524
|
-
|
|
525
|
-
expect(searchEditParent.props()["data-qa-is-focused"], "to be", false);
|
|
526
|
-
});
|
|
527
492
|
});
|
|
528
493
|
|
|
529
494
|
describe("getSearchOptionValue function", () => {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
SET_HREF_CONFIG,
|
|
7
7
|
SET_CURRENT_PREPEND_PATH,
|
|
8
8
|
SET_CLOSING_TAB_HANDLER_ACTIONS,
|
|
9
|
+
REMOVE_MODULE_TABS,
|
|
9
10
|
} from "../actions/navigation";
|
|
10
11
|
import { getAllAfterPrependHref } from "../utils/parseHelper";
|
|
11
12
|
import { APPLICATION_SCOPE_HAS_CHANGED } from "../actions/scopes";
|
|
@@ -73,6 +74,29 @@ const navigationReducer = (state = initialState, action) => {
|
|
|
73
74
|
s.deleteIn(["tabIndex", remainingSection]);
|
|
74
75
|
}
|
|
75
76
|
});
|
|
77
|
+
case REMOVE_MODULE_TABS:
|
|
78
|
+
return state.withMutations(s => {
|
|
79
|
+
const { module } = action.payload;
|
|
80
|
+
|
|
81
|
+
s.deleteIn(["moduleTabs", module]);
|
|
82
|
+
s.deleteIn(["closingTabsHandlerActions", module]);
|
|
83
|
+
|
|
84
|
+
s.get("tabIndex")
|
|
85
|
+
.keySeq()
|
|
86
|
+
.forEach(key => {
|
|
87
|
+
if (key.startsWith(module)) {
|
|
88
|
+
s.deleteIn(["tabIndex", key]);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
s.get("mappedHrefs")
|
|
93
|
+
.keySeq()
|
|
94
|
+
.forEach(key => {
|
|
95
|
+
if (key.startsWith(module)) {
|
|
96
|
+
s.deleteIn(["mappedHrefs", key]);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
76
100
|
case SET_HREF_CONFIG:
|
|
77
101
|
return state.set("config", Immutable.fromJS(action.payload));
|
|
78
102
|
case SET_CURRENT_PREPEND_PATH:
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
setHrefConfig,
|
|
7
7
|
setCurrentPrependPath,
|
|
8
8
|
setClosingTabHandlerActions,
|
|
9
|
+
removeModuleTabs,
|
|
9
10
|
} from "../actions/navigation";
|
|
10
11
|
import reducer from "./navigation";
|
|
11
12
|
import { applicationScopeHasChanged } from "../actions/scopes";
|
|
@@ -295,6 +296,43 @@ describe("Navigation reducer", () => {
|
|
|
295
296
|
});
|
|
296
297
|
});
|
|
297
298
|
|
|
299
|
+
describe("REMOVE_MODULE_TABS", () => {
|
|
300
|
+
it("can remove module tabs", () => {
|
|
301
|
+
const oldState = Immutable.fromJS({
|
|
302
|
+
moduleTabs: { test: ["test/new", "test/old"], another: [1, 2, 3] },
|
|
303
|
+
closingTabsHandlerActions: { test: [0, 1, 2], another: [] },
|
|
304
|
+
tabIndex: { "test/old": {}, "test/new": {}, test: {}, another: {} },
|
|
305
|
+
mappedHrefs: { "test/old": {}, "test/new": {}, test: {}, another2: {} },
|
|
306
|
+
config: { prependPath: "/:scope/" },
|
|
307
|
+
});
|
|
308
|
+
const action = removeModuleTabs("test");
|
|
309
|
+
const newState = reducer(oldState, action);
|
|
310
|
+
return expect(newState, "not to be", oldState).and(
|
|
311
|
+
"to equal",
|
|
312
|
+
Immutable.fromJS({
|
|
313
|
+
moduleTabs: { another: [1, 2, 3] },
|
|
314
|
+
closingTabsHandlerActions: { another: [] },
|
|
315
|
+
tabIndex: { another: {} },
|
|
316
|
+
mappedHrefs: { another2: {} },
|
|
317
|
+
config: { prependPath: "/:scope/" },
|
|
318
|
+
}),
|
|
319
|
+
);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("does nothing if the module to remove is not found", () => {
|
|
323
|
+
const oldState = Immutable.fromJS({
|
|
324
|
+
moduleTabs: { test: ["test/new", "test/old"], another: [1, 2, 3] },
|
|
325
|
+
closingTabsHandlerActions: { test: [0, 1, 2], another: [] },
|
|
326
|
+
tabIndex: { "test/old": {}, "test/new": {}, test: {}, another: {} },
|
|
327
|
+
mappedHrefs: { "test/old": {}, "test/new": {}, test: {}, another2: {} },
|
|
328
|
+
config: { prependPath: "/:scope/" },
|
|
329
|
+
});
|
|
330
|
+
const action = removeModuleTabs("unknown");
|
|
331
|
+
const newState = reducer(oldState, action);
|
|
332
|
+
return expect(newState, "to be", oldState);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
298
336
|
describe("SET_HREF_CONFIG", () => {
|
|
299
337
|
it("update href config in navigation state", () => {
|
|
300
338
|
const oldState = Immutable.fromJS({
|