orc-shared 1.2.0-dev.1 → 1.2.0-dev.5
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 +1 -1
- package/dist/actions/metadata.js +1 -1
- package/dist/actions/modules.js +63 -1
- package/dist/actions/navigation.js +1 -1
- package/dist/actions/requestsApi.js +8 -8
- package/dist/actions/scopes.js +59 -22
- package/dist/actions/timezones.js +1 -1
- package/dist/actions/toasts.js +1 -1
- package/dist/actions/versionInfo.js +1 -1
- package/dist/actions/view.js +1 -1
- package/dist/buildStore.js +1 -1
- package/dist/components/AppFrame/About.js +4 -3
- package/dist/components/AppFrame/MenuItem.js +6 -15
- package/dist/components/AppFrame/Preferences.js +1 -1
- package/dist/components/AppFrame/Sidebar.js +20 -9
- package/dist/components/AppFrame/Topbar.js +1 -1
- package/dist/components/ApplicationModuleLoader.js +143 -0
- package/dist/components/Authenticate.js +13 -13
- package/dist/components/CategoryList.js +1 -1
- package/dist/components/Checkbox.js +1 -1
- package/dist/components/DropMenu/Menu.js +1 -1
- package/dist/components/DropMenu/index.js +1 -1
- package/dist/components/Form/FieldList.js +1 -1
- package/dist/components/Form/Form.js +1 -1
- package/dist/components/Form/Inputs/Button.js +1 -1
- package/dist/components/Form/Inputs/FieldButtons.js +1 -1
- package/dist/components/Form/Inputs/Number.js +1 -1
- package/dist/components/Form/Inputs/ReadOnly.js +1 -1
- package/dist/components/Form/Inputs/SmallButton.js +1 -1
- package/dist/components/Form/Inputs/Text.js +1 -1
- package/dist/components/Form/Inputs/Time.js +1 -1
- package/dist/components/Form/Inputs/Toggles.js +1 -1
- package/dist/components/Form/Inputs/Translation.js +1 -1
- package/dist/components/List/HeadCell.js +1 -1
- package/dist/components/List/List.js +1 -1
- package/dist/components/List/Row.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/List.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/NotificationProps.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/PredefinedElements/Translations.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/Table.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/TableProps.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/TransferList.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/chipProps.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/collapsableListProps.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/dividerProps.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/index.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/modalProps.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/useTableSelection.js +1 -1
- package/dist/components/MaterialUI/Feedback/useNotification.js +1 -1
- package/dist/components/MaterialUI/Inputs/AutocompleteProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/CheckboxGroupProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/CheckboxProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/InputBase.js +1 -1
- package/dist/components/MaterialUI/Inputs/InputBaseProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +1 -1
- package/dist/components/MaterialUI/Inputs/RadioProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/SelectProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/Switch.js +1 -1
- package/dist/components/MaterialUI/Inputs/SwitchProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/TimePicker.js +1 -1
- package/dist/components/MaterialUI/Inputs/createInput.js +1 -1
- package/dist/components/MaterialUI/Inputs/index.js +1 -1
- package/dist/components/MaterialUI/Inputs/standaloneRadioProps.js +1 -1
- package/dist/components/MaterialUI/Navigation/DropDownMenuProps.js +1 -1
- package/dist/components/MaterialUI/Navigation/ExternalLink.js +113 -0
- package/dist/components/MaterialUI/Surfaces/expansionPanelProps.js +1 -1
- package/dist/components/MaterialUI/Surfaces/paperProps.js +1 -1
- package/dist/components/MaterialUI/muiThemes.js +5 -0
- package/dist/components/MaterialUI/textProps.js +1 -1
- package/dist/components/Modules.js +126 -41
- package/dist/components/MultiSelector.js +1 -1
- package/dist/components/Navigation/Bar.js +1 -1
- package/dist/components/Navigation/Tab.js +1 -1
- package/dist/components/Navigation/useNavigationState.js +1 -1
- package/dist/components/Placeholder.js +1 -1
- package/dist/components/Routing/FullPage.js +3 -1
- package/dist/components/Routing/Page.js +5 -3
- package/dist/components/Routing/Segment.js +1 -1
- package/dist/components/Routing/SegmentPage.js +1 -1
- package/dist/components/Routing/withWaypointing.js +6 -2
- package/dist/components/Scope/ScopeNode.js +1 -1
- package/dist/components/Scope/Selector.js +1 -1
- package/dist/components/Scope/index.js +1 -1
- package/dist/components/Scope/useScopeConfirmationModalState.js +7 -16
- package/dist/components/Scope/useScopeData.js +4 -13
- package/dist/components/Scope/useScopeSelect.js +1 -1
- package/dist/components/Selector.js +1 -1
- package/dist/components/Spritesheet.js +1 -1
- package/dist/components/Switch.js +1 -1
- package/dist/components/Text.js +1 -1
- package/dist/components/ToastList.js +1 -1
- package/dist/components/Toolbar.js +1 -1
- package/dist/components/Treeview/Label.js +1 -1
- package/dist/components/Treeview/Leaf.js +1 -1
- package/dist/components/Treeview/Node.js +1 -1
- package/dist/components/Treeview/settings.js +1 -1
- package/dist/constants.js +19 -2
- package/dist/content/icons/orckestra-icon.svg +5 -0
- package/dist/content/iconsSheet.svg +8 -0
- package/dist/content/orckestra-logo-white.png +0 -0
- package/dist/hocs/withInfiniteScroll.js +1 -1
- package/dist/hooks/useDispatchWithModulesData.js +1 -1
- package/dist/hooks/useEditState.js +1 -1
- package/dist/hooks/useFullEntityEditState.js +1 -1
- package/dist/hooks/useLabelMessage.js +1 -1
- package/dist/hooks/useNavigationHandler.js +1 -1
- package/dist/hooks/useSelectorAndUnwrap.js +1 -1
- package/dist/reducers/metadata.js +1 -1
- package/dist/reducers/modules.js +39 -1
- package/dist/reducers/scopes.js +27 -0
- package/dist/reducers/settings.js +31 -2
- package/dist/schemas/countries.js +1 -1
- package/dist/schemas/definitions.js +1 -1
- package/dist/schemas/metadata.js +1 -1
- package/dist/schemas/productDefinitions.js +1 -1
- package/dist/schemas/timezones.js +1 -1
- package/dist/selectors/applications.js +1 -1
- package/dist/selectors/authentication.js +57 -18
- package/dist/selectors/countries.js +1 -1
- package/dist/selectors/locale.js +1 -1
- package/dist/selectors/metadata.js +1 -1
- package/dist/selectors/modules.js +15 -1
- package/dist/selectors/navigation.js +1 -1
- package/dist/selectors/requests.js +1 -1
- package/dist/selectors/scope.js +7 -1
- package/dist/selectors/settings.js +13 -1
- package/dist/selectors/versionInfo.js +1 -1
- package/dist/selectors/view.js +1 -1
- package/dist/spawnerMiddleware.js +1 -1
- package/dist/utils/displayModeHelper.js +1 -1
- package/dist/utils/localizationHelper.js +1 -1
- package/dist/utils/mapHelper.js +1 -1
- package/dist/utils/modelValidationHelper.js +1 -1
- package/dist/utils/parseHelper.js +1 -1
- package/dist/utils/propertyHelper.js +2 -2
- package/dist/utils/propertyValidator.js +1 -1
- package/dist/utils/setTranslationWithFallback.js +1 -1
- package/dist/utils/testUtils.js +2 -1
- package/dist/utils/unwrapImmutable.js +1 -1
- package/dist/utils/urlHelper.js +1 -1
- package/package.json +6 -5
- package/src/actions/modules.js +30 -0
- package/src/actions/modules.test.js +50 -1
- package/src/actions/scopes.js +33 -7
- package/src/actions/scopes.test.js +84 -14
- package/src/components/AppFrame/About.js +2 -2
- package/src/components/AppFrame/AppFrame.test.js +9 -0
- package/src/components/AppFrame/MenuItem.js +3 -5
- package/src/components/AppFrame/MenuItem.test.js +2 -24
- package/src/components/AppFrame/Sidebar.js +11 -12
- package/src/components/AppFrame/Sidebar.test.js +18 -0
- package/src/components/ApplicationModuleLoader.js +52 -0
- package/src/components/ApplicationModuleLoader.test.js +149 -0
- package/src/components/Authenticate.js +5 -4
- package/src/components/Authenticate.test.js +23 -4
- package/src/components/MaterialUI/Navigation/ExternalLink.js +25 -0
- package/src/components/MaterialUI/Navigation/ExternalLink.test.js +26 -0
- package/src/components/MaterialUI/muiThemes.js +5 -0
- package/src/components/Modules.js +103 -20
- package/src/components/Modules.test.js +315 -28
- package/src/components/Provision.test.js +34 -0
- package/src/components/Routing/FullPage.js +2 -1
- package/src/components/Routing/FullPage.test.js +23 -0
- package/src/components/Routing/Page.js +2 -2
- package/src/components/Routing/Page.test.js +20 -0
- package/src/components/Routing/Segment.js +1 -1
- package/src/components/Routing/withWaypointing.js +2 -2
- package/src/components/Routing/withWaypointing.test.js +33 -5
- package/src/components/Scope/useScopeConfirmationModalState.js +5 -16
- package/src/components/Scope/useScopeConfirmationModalState.test.js +39 -13
- package/src/components/Scope/useScopeData.js +0 -3
- package/src/components/Scope/useScopeData.test.js +0 -27
- package/src/constants.js +15 -0
- package/src/content/icons/orckestra-icon.svg +5 -0
- package/src/content/iconsSheet.svg +8 -0
- package/src/content/orckestra-logo-white.png +0 -0
- package/src/hocs/withScopeData.test.js +0 -31
- package/src/reducers/modules.js +48 -2
- package/src/reducers/modules.test.js +117 -2
- package/src/reducers/scopes.js +30 -0
- package/src/reducers/scopes.test.js +45 -1
- package/src/reducers/settings.js +26 -2
- package/src/reducers/settings.test.js +74 -6
- package/src/selectors/authentication.js +53 -27
- package/src/selectors/authentication.test.js +600 -12
- package/src/selectors/modules.js +7 -0
- package/src/selectors/modules.test.js +16 -1
- package/src/selectors/scope.js +2 -0
- package/src/selectors/scope.test.js +5 -0
- package/src/selectors/settings.js +6 -0
|
@@ -7,17 +7,21 @@ import TabBar from "./MaterialUI/Navigation/TabBar";
|
|
|
7
7
|
import { TestWrapper, createMuiTheme } from "./../utils/testUtils";
|
|
8
8
|
import sinon from "sinon";
|
|
9
9
|
import { createMemoryHistory } from "history";
|
|
10
|
+
import { INITIALIZE_FIRST_MODULE_SCOPE, SET_MODULE_AS_VISIBLE, SET_ROUTING_PERFORMED } from "../actions/modules";
|
|
11
|
+
import { resetLastScope } from "../selectors/navigation";
|
|
10
12
|
|
|
11
13
|
describe("Modules", () => {
|
|
12
|
-
let modules, Mod2, Mod3, Page1, Page2, Page3, store, state;
|
|
13
|
-
|
|
14
|
-
const match = {
|
|
15
|
-
url: "/TestScope/users/page1",
|
|
16
|
-
path: "/:scope/users/page1",
|
|
17
|
-
params: { scope: "TestScope" },
|
|
18
|
-
};
|
|
14
|
+
let modules, Mod2, Mod3, Page1, Page2, Page3, store, state, match;
|
|
19
15
|
|
|
20
16
|
beforeEach(() => {
|
|
17
|
+
resetLastScope();
|
|
18
|
+
|
|
19
|
+
match = {
|
|
20
|
+
url: "/TestScope/users/page1",
|
|
21
|
+
path: "/:scope/users/page1",
|
|
22
|
+
params: { scope: "TestScope" },
|
|
23
|
+
};
|
|
24
|
+
|
|
21
25
|
Mod2 = () => <div id="Mod2" />;
|
|
22
26
|
Mod3 = () => <div id="Mod3" />;
|
|
23
27
|
Page1 = () => <div id="Page1" />;
|
|
@@ -68,9 +72,6 @@ describe("Modules", () => {
|
|
|
68
72
|
router: {
|
|
69
73
|
location: {},
|
|
70
74
|
},
|
|
71
|
-
modules: {
|
|
72
|
-
tree: {},
|
|
73
|
-
},
|
|
74
75
|
view: {
|
|
75
76
|
edit: {
|
|
76
77
|
users: {},
|
|
@@ -83,6 +84,7 @@ describe("Modules", () => {
|
|
|
83
84
|
},
|
|
84
85
|
settings: {
|
|
85
86
|
defaultScope: "myScope",
|
|
87
|
+
modules: ["users", "demos", "photos"],
|
|
86
88
|
},
|
|
87
89
|
scopes: {
|
|
88
90
|
TestScope: {
|
|
@@ -93,6 +95,23 @@ describe("Modules", () => {
|
|
|
93
95
|
children: ["test2"],
|
|
94
96
|
isAuthorizedScope: true,
|
|
95
97
|
},
|
|
98
|
+
TestScope1: {
|
|
99
|
+
id: "TestScope1",
|
|
100
|
+
name: { "en-CA": "Test 1" },
|
|
101
|
+
foo: false,
|
|
102
|
+
bar: false,
|
|
103
|
+
children: ["test2"],
|
|
104
|
+
isAuthorizedScope: false,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
modules: {
|
|
108
|
+
tree: {},
|
|
109
|
+
visibleModules: ["users", "demos", "photos"],
|
|
110
|
+
lastScopeAndModuleSelection: {
|
|
111
|
+
scope: "TestScope",
|
|
112
|
+
moduleName: null,
|
|
113
|
+
routingPerformed: false,
|
|
114
|
+
},
|
|
96
115
|
},
|
|
97
116
|
locale: {
|
|
98
117
|
locale: null,
|
|
@@ -104,7 +123,7 @@ describe("Modules", () => {
|
|
|
104
123
|
});
|
|
105
124
|
store = {
|
|
106
125
|
subscribe: () => {},
|
|
107
|
-
dispatch: ()
|
|
126
|
+
dispatch: sinon.spy().named("dispatch"),
|
|
108
127
|
getState: () => state,
|
|
109
128
|
};
|
|
110
129
|
});
|
|
@@ -148,6 +167,144 @@ describe("Modules", () => {
|
|
|
148
167
|
expect(mount(component).childNodes, "to satisfy", expected);
|
|
149
168
|
});
|
|
150
169
|
|
|
170
|
+
it("renders a module table when routing is required for photos", () => {
|
|
171
|
+
const history = createMemoryHistory({ initialEntries: ["/TestScope/demos?arg=data"] });
|
|
172
|
+
const mockHistoryPush = sinon.spy(history, "push");
|
|
173
|
+
|
|
174
|
+
const component = (
|
|
175
|
+
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
176
|
+
<Modules modules={modules} scope="TestScope" />
|
|
177
|
+
</TestWrapper>
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "moduleName"], "photos");
|
|
181
|
+
|
|
182
|
+
const module = {
|
|
183
|
+
icon: "image",
|
|
184
|
+
label: "Module 2",
|
|
185
|
+
href: "/TestScope/photos",
|
|
186
|
+
mappedFrom: "/TestScope/photos",
|
|
187
|
+
active: true,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const expected = [
|
|
191
|
+
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
192
|
+
<TabBar module={module} pages={[]} />
|
|
193
|
+
</TestWrapper>,
|
|
194
|
+
<Mod2 />,
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
expect(mount(component).childNodes, "to satisfy", expected);
|
|
198
|
+
|
|
199
|
+
expect(mockHistoryPush, "to have calls satisfying", [{ args: ["/TestScope/photos"] }]);
|
|
200
|
+
|
|
201
|
+
expect(store.dispatch, "to have a call satisfying", { args: [{ type: SET_ROUTING_PERFORMED }] });
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("renders a module table when routing is required for photos when already set correctly", () => {
|
|
205
|
+
match.url = "/TestScope/demos";
|
|
206
|
+
match.path = "/:scope/demos";
|
|
207
|
+
|
|
208
|
+
const component = (
|
|
209
|
+
<TestWrapper
|
|
210
|
+
provider={{ store }}
|
|
211
|
+
memoryRouter={{ initialEntries: ["/TestScope/demos"] }}
|
|
212
|
+
intlProvider
|
|
213
|
+
stylesProvider
|
|
214
|
+
muiThemeProvider={{ theme }}
|
|
215
|
+
>
|
|
216
|
+
<Modules modules={modules} scope="TestScope" />
|
|
217
|
+
</TestWrapper>
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "routingPerformed"], true);
|
|
221
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "moduleName"], "demos");
|
|
222
|
+
|
|
223
|
+
const module = {
|
|
224
|
+
icon: "cloud",
|
|
225
|
+
label: "Module 3",
|
|
226
|
+
href: "/TestScope/demos",
|
|
227
|
+
mappedFrom: "/TestScope/demos",
|
|
228
|
+
active: true,
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const expected = [
|
|
232
|
+
<TestWrapper
|
|
233
|
+
provider={{ store }}
|
|
234
|
+
memoryRouter={{ initialEntries: ["/TestScope/demos"] }}
|
|
235
|
+
intlProvider
|
|
236
|
+
stylesProvider
|
|
237
|
+
muiThemeProvider={{ theme }}
|
|
238
|
+
>
|
|
239
|
+
<TabBar module={module} pages={[]} />
|
|
240
|
+
</TestWrapper>,
|
|
241
|
+
<Mod3 />,
|
|
242
|
+
];
|
|
243
|
+
|
|
244
|
+
expect(mount(component).childNodes, "to satisfy", expected);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("renders a module table on first available module if requested one not visible", () => {
|
|
248
|
+
const history = createMemoryHistory({ initialEntries: ["/TestScope/demos?arg=data"] });
|
|
249
|
+
const mockHistoryPush = sinon.spy(history, "push");
|
|
250
|
+
|
|
251
|
+
const component = (
|
|
252
|
+
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
253
|
+
<Modules modules={modules} scope="TestScope" />
|
|
254
|
+
</TestWrapper>
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
state = state.setIn(["modules", "visibleModules"], Immutable.fromJS(["demos", "users"]));
|
|
258
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "moduleName"], "photos");
|
|
259
|
+
|
|
260
|
+
const module = {
|
|
261
|
+
icon: "cloud",
|
|
262
|
+
label: "Module 3",
|
|
263
|
+
href: "/TestScope/demos",
|
|
264
|
+
mappedFrom: "/TestScope/demos",
|
|
265
|
+
active: true,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const expected = [
|
|
269
|
+
<TestWrapper
|
|
270
|
+
provider={{ store }}
|
|
271
|
+
memoryRouter={{ initialEntries: ["/TestScope/demos"] }}
|
|
272
|
+
intlProvider
|
|
273
|
+
stylesProvider
|
|
274
|
+
muiThemeProvider={{ theme }}
|
|
275
|
+
>
|
|
276
|
+
<TabBar module={module} pages={[]} />
|
|
277
|
+
</TestWrapper>,
|
|
278
|
+
<Mod3 />,
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
expect(mount(component).childNodes, "to satisfy", expected);
|
|
282
|
+
|
|
283
|
+
expect(mockHistoryPush, "to have calls satisfying", [{ args: ["/TestScope/demos"] }]);
|
|
284
|
+
|
|
285
|
+
expect(store.dispatch, "to have a call satisfying", { args: [{ type: SET_ROUTING_PERFORMED }] });
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("renders a module table when routing cannot be performed without visible modules", () => {
|
|
289
|
+
const history = createMemoryHistory({ initialEntries: ["/TestScope/demos?arg=data"] });
|
|
290
|
+
const mockHistoryPush = sinon.spy(history, "push");
|
|
291
|
+
|
|
292
|
+
const component = (
|
|
293
|
+
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
294
|
+
<Modules modules={modules} scope="TestScope" />
|
|
295
|
+
</TestWrapper>
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
state = state.setIn(["modules", "visibleModules"], Immutable.fromJS([]));
|
|
299
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "moduleName"], "photos");
|
|
300
|
+
|
|
301
|
+
mount(component);
|
|
302
|
+
|
|
303
|
+
expect(mockHistoryPush, "not to have calls satisfying", [{ args: ["/TestScope/photos"] }]);
|
|
304
|
+
|
|
305
|
+
expect(store.dispatch, "not to have calls satisfying", [{ args: [{ type: SET_ROUTING_PERFORMED }] }]);
|
|
306
|
+
});
|
|
307
|
+
|
|
151
308
|
it("renders a module table as a routing system (user route)", () => {
|
|
152
309
|
const module = {
|
|
153
310
|
icon: "user",
|
|
@@ -270,6 +427,80 @@ describe("Modules", () => {
|
|
|
270
427
|
);
|
|
271
428
|
});
|
|
272
429
|
|
|
430
|
+
it("properly sets visible modules and scope when not already set", () => {
|
|
431
|
+
modules.users.hide = () => () => true;
|
|
432
|
+
modules.demos.hide = false;
|
|
433
|
+
|
|
434
|
+
const component = (
|
|
435
|
+
<TestWrapper
|
|
436
|
+
provider={{ store }}
|
|
437
|
+
memoryRouter={{ initialEntries: ["/TestScope/demos"] }}
|
|
438
|
+
intlProvider
|
|
439
|
+
stylesProvider
|
|
440
|
+
muiThemeProvider={{ theme }}
|
|
441
|
+
>
|
|
442
|
+
<Modules modules={modules} scope="TestScope" />
|
|
443
|
+
</TestWrapper>
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
state = state.setIn(["modules", "visibleModules"], Immutable.fromJS([]));
|
|
447
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "moduleName"], null);
|
|
448
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "scope"], null);
|
|
449
|
+
|
|
450
|
+
mount(component);
|
|
451
|
+
|
|
452
|
+
expect(store.dispatch, "to have a call satisfying", { args: [{ type: SET_MODULE_AS_VISIBLE, payload: "demos" }] });
|
|
453
|
+
|
|
454
|
+
expect(store.dispatch, "to have a call satisfying", { args: [{ type: SET_MODULE_AS_VISIBLE, payload: "photos" }] });
|
|
455
|
+
|
|
456
|
+
expect(store.dispatch, "not to have calls satisfying", [
|
|
457
|
+
{ args: [{ type: SET_MODULE_AS_VISIBLE, payload: "users" }] },
|
|
458
|
+
]);
|
|
459
|
+
|
|
460
|
+
expect(store.dispatch, "to have a call satisfying", {
|
|
461
|
+
args: [{ type: INITIALIZE_FIRST_MODULE_SCOPE, payload: "TestScope" }],
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
it("Does not set visible modules and scope when route is not yet initialized", () => {
|
|
466
|
+
modules.users.hide = () => () => true;
|
|
467
|
+
modules.demos.hide = false;
|
|
468
|
+
|
|
469
|
+
state = state.setIn(["navigation", "route", "match", "params", "scope"], null);
|
|
470
|
+
|
|
471
|
+
state = state.setIn(["modules", "visibleModules"], Immutable.fromJS([]));
|
|
472
|
+
|
|
473
|
+
const component = (
|
|
474
|
+
<TestWrapper
|
|
475
|
+
provider={{ store }}
|
|
476
|
+
memoryRouter={{ initialEntries: ["/TestScope/demos"] }}
|
|
477
|
+
intlProvider
|
|
478
|
+
stylesProvider
|
|
479
|
+
muiThemeProvider={{ theme }}
|
|
480
|
+
>
|
|
481
|
+
<Modules modules={modules} scope="TestScope" />
|
|
482
|
+
</TestWrapper>
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
mount(component);
|
|
486
|
+
|
|
487
|
+
expect(store.dispatch, "not to have calls satisfying", [
|
|
488
|
+
{ args: [{ type: SET_MODULE_AS_VISIBLE, payload: "demos" }] },
|
|
489
|
+
]);
|
|
490
|
+
|
|
491
|
+
expect(store.dispatch, "not to have calls satisfying", [
|
|
492
|
+
{ args: [{ type: SET_MODULE_AS_VISIBLE, payload: "photos" }] },
|
|
493
|
+
]);
|
|
494
|
+
|
|
495
|
+
expect(store.dispatch, "not to have calls satisfying", [
|
|
496
|
+
{ args: [{ type: SET_MODULE_AS_VISIBLE, payload: "users" }] },
|
|
497
|
+
]);
|
|
498
|
+
|
|
499
|
+
expect(store.dispatch, "not to have calls satisfying", [
|
|
500
|
+
{ args: [{ type: INITIALIZE_FIRST_MODULE_SCOPE, payload: "TestScope" }] },
|
|
501
|
+
]);
|
|
502
|
+
});
|
|
503
|
+
|
|
273
504
|
describe("with custom href", () => {
|
|
274
505
|
beforeEach(() => {
|
|
275
506
|
state = Immutable.fromJS({
|
|
@@ -286,9 +517,16 @@ describe("Modules", () => {
|
|
|
286
517
|
},
|
|
287
518
|
settings: {
|
|
288
519
|
defaultScope: "myScope",
|
|
520
|
+
modules: ["users", "demos", "photos"],
|
|
289
521
|
},
|
|
290
522
|
modules: {
|
|
291
523
|
tree: {},
|
|
524
|
+
visibleModules: ["users", "demos", "photos"],
|
|
525
|
+
lastScopeAndModuleSelection: {
|
|
526
|
+
scope: "TestScope",
|
|
527
|
+
moduleName: null,
|
|
528
|
+
routingPerformed: false,
|
|
529
|
+
},
|
|
292
530
|
},
|
|
293
531
|
view: {
|
|
294
532
|
edit: {
|
|
@@ -387,9 +625,16 @@ describe("Modules", () => {
|
|
|
387
625
|
},
|
|
388
626
|
settings: {
|
|
389
627
|
defaultScope: "TestScope2",
|
|
628
|
+
modules: ["users", "demos", "photos"],
|
|
390
629
|
},
|
|
391
630
|
modules: {
|
|
392
631
|
tree: {},
|
|
632
|
+
visibleModules: ["users", "demos", "photos"],
|
|
633
|
+
lastScopeAndModuleSelection: {
|
|
634
|
+
scope: "TestScope",
|
|
635
|
+
moduleName: null,
|
|
636
|
+
routingPerformed: false,
|
|
637
|
+
},
|
|
393
638
|
},
|
|
394
639
|
view: {
|
|
395
640
|
edit: {
|
|
@@ -440,13 +685,7 @@ describe("Modules", () => {
|
|
|
440
685
|
});
|
|
441
686
|
|
|
442
687
|
describe("Module", () => {
|
|
443
|
-
let config, Page1, store, state;
|
|
444
|
-
|
|
445
|
-
const match = {
|
|
446
|
-
url: "/TestScope/users/page1",
|
|
447
|
-
path: "/:scope/users/page1",
|
|
448
|
-
params: { scope: "TestScope" },
|
|
449
|
-
};
|
|
688
|
+
let config, Page1, store, state, match;
|
|
450
689
|
|
|
451
690
|
let history, pushSpy;
|
|
452
691
|
beforeAll(() => {
|
|
@@ -456,6 +695,12 @@ describe("Module", () => {
|
|
|
456
695
|
});
|
|
457
696
|
|
|
458
697
|
beforeEach(() => {
|
|
698
|
+
match = {
|
|
699
|
+
url: "/TestScope/users/page1",
|
|
700
|
+
path: "/:scope/users/page1",
|
|
701
|
+
params: { scope: "TestScope" },
|
|
702
|
+
};
|
|
703
|
+
|
|
459
704
|
config = {
|
|
460
705
|
label: "Module 1",
|
|
461
706
|
icon: "user",
|
|
@@ -482,6 +727,12 @@ describe("Module", () => {
|
|
|
482
727
|
},
|
|
483
728
|
modules: {
|
|
484
729
|
tree: {},
|
|
730
|
+
visibleModules: ["firstModule", "module123"],
|
|
731
|
+
lastScopeAndModuleSelection: {
|
|
732
|
+
scope: "TestScope",
|
|
733
|
+
moduleName: "Profiles",
|
|
734
|
+
routingPerformed: true,
|
|
735
|
+
},
|
|
485
736
|
},
|
|
486
737
|
view: {
|
|
487
738
|
edit: {
|
|
@@ -523,49 +774,85 @@ describe("Module", () => {
|
|
|
523
774
|
|
|
524
775
|
const theme = createMuiTheme();
|
|
525
776
|
|
|
526
|
-
it("Calls pushes to
|
|
527
|
-
//config.hide = false;
|
|
777
|
+
it("Calls pushes to first module when unauthorized user trying to access hidden module", () => {
|
|
528
778
|
const component = (
|
|
529
779
|
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
530
|
-
<Module config={config} match={match} path={match.path} location={{}} />
|
|
780
|
+
<Module id="notVisibleModule" config={config} match={match} path={match.path} location={{}} />
|
|
531
781
|
</TestWrapper>
|
|
532
782
|
);
|
|
533
783
|
|
|
534
784
|
mount(component);
|
|
535
785
|
|
|
536
|
-
expect(history.push, "to have calls satisfying", [{ args: ["/"] }]);
|
|
786
|
+
expect(history.push, "to have calls satisfying", [{ args: ["/TestScope/firstModule"] }]);
|
|
537
787
|
|
|
538
788
|
pushSpy.resetHistory();
|
|
539
789
|
});
|
|
540
790
|
|
|
541
|
-
it("
|
|
791
|
+
it("Does not call pushes to first module when unauthorized user trying to access hidden module and hide property is a function which retrieves false", () => {
|
|
542
792
|
config.hide = () => false;
|
|
543
793
|
|
|
544
794
|
const component = (
|
|
545
795
|
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
546
|
-
<Module config={config} match={match} path={match.path} location={{}} />
|
|
796
|
+
<Module id="firstModule" config={config} match={match} path={match.path} location={{}} />
|
|
547
797
|
</TestWrapper>
|
|
548
798
|
);
|
|
549
799
|
|
|
550
800
|
mount(component);
|
|
551
801
|
|
|
552
|
-
expect(history.push, "not to have calls satisfying", [{ args: ["/"] }]);
|
|
802
|
+
expect(history.push, "not to have calls satisfying", [{ args: ["/TestScope/firstModule"] }]);
|
|
553
803
|
|
|
554
804
|
pushSpy.resetHistory();
|
|
555
805
|
});
|
|
556
806
|
|
|
557
|
-
it("Calls pushes to
|
|
807
|
+
it("Calls pushes to first module when unauthorized user trying to access hidden module and hide property is a function which retrieves true", () => {
|
|
808
|
+
config.hide = () => true;
|
|
809
|
+
|
|
810
|
+
const component = (
|
|
811
|
+
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
812
|
+
<Module id="notVisibleModule" config={config} match={match} path={match.path} location={{}} />
|
|
813
|
+
</TestWrapper>
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
mount(component);
|
|
817
|
+
|
|
818
|
+
expect(history.push, "to have calls satisfying", [{ args: ["/TestScope/firstModule"] }]);
|
|
819
|
+
|
|
820
|
+
pushSpy.resetHistory();
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
it("Does not call pushes to first module when already set to that location", () => {
|
|
824
|
+
state = state.setIn(["navigation", "route", "match", "url"], "/TestScope/firstModule");
|
|
825
|
+
state = state.setIn(["navigation", "route", "match", "path"], "/:scope/firstModule");
|
|
826
|
+
|
|
827
|
+
config.hide = () => true;
|
|
828
|
+
|
|
829
|
+
const component = (
|
|
830
|
+
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
831
|
+
<Module id="notVisibleModule" config={config} match={match} path={match.path} location={{}} />
|
|
832
|
+
</TestWrapper>
|
|
833
|
+
);
|
|
834
|
+
|
|
835
|
+
mount(component);
|
|
836
|
+
|
|
837
|
+
expect(history.push, "not to have calls satisfying", [{ args: ["/TestScope/firstModule"] }]);
|
|
838
|
+
|
|
839
|
+
pushSpy.resetHistory();
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
it("Does not call pushes to first module when redirection is not yet completed to new scope", () => {
|
|
843
|
+
state = state.setIn(["modules", "lastScopeAndModuleSelection", "scope"], "newScope");
|
|
844
|
+
|
|
558
845
|
config.hide = () => true;
|
|
559
846
|
|
|
560
847
|
const component = (
|
|
561
848
|
<TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
562
|
-
<Module config={config} match={match} path={match.path} location={{}} />
|
|
849
|
+
<Module id="notVisibleModule" config={config} match={match} path={match.path} location={{}} />
|
|
563
850
|
</TestWrapper>
|
|
564
851
|
);
|
|
565
852
|
|
|
566
853
|
mount(component);
|
|
567
854
|
|
|
568
|
-
expect(history.push, "to have calls satisfying", [{ args: ["/"] }]);
|
|
855
|
+
expect(history.push, "not to have calls satisfying", [{ args: ["/TestScope/firstModule"] }]);
|
|
569
856
|
|
|
570
857
|
pushSpy.resetHistory();
|
|
571
858
|
});
|
|
@@ -6,6 +6,13 @@ import { spyOnConsole } from "../utils/testUtils";
|
|
|
6
6
|
import Provision from "./Provision";
|
|
7
7
|
import { createTheme } from "@material-ui/core/styles";
|
|
8
8
|
|
|
9
|
+
jest.mock("../utils/buildUrl", () => {
|
|
10
|
+
const modExport = {};
|
|
11
|
+
modExport.loadConfig = () => Promise.resolve({});
|
|
12
|
+
modExport.buildUrl = () => "URL";
|
|
13
|
+
return modExport;
|
|
14
|
+
});
|
|
15
|
+
|
|
9
16
|
const fakeStore = {
|
|
10
17
|
subscribe: listener => () => {},
|
|
11
18
|
dispatch: action => action,
|
|
@@ -17,8 +24,35 @@ const fakeStore = {
|
|
|
17
24
|
authentication: {
|
|
18
25
|
name: "foo@bar.com",
|
|
19
26
|
},
|
|
27
|
+
scopes: {
|
|
28
|
+
Global: {
|
|
29
|
+
name: { en: "Global", fr: "Global" },
|
|
30
|
+
id: "Global",
|
|
31
|
+
children: ["MyScope"],
|
|
32
|
+
currency: {
|
|
33
|
+
displayName: {
|
|
34
|
+
en: "Euro",
|
|
35
|
+
fr: "Euro",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
defaultCulture: "en-US",
|
|
39
|
+
},
|
|
40
|
+
MyScope: {
|
|
41
|
+
name: { en: "First child", fr: "Premier fils" },
|
|
42
|
+
id: "FirstChild",
|
|
43
|
+
children: ["ChildScope"],
|
|
44
|
+
parentScopeId: "Global",
|
|
45
|
+
},
|
|
46
|
+
ChildScope: {
|
|
47
|
+
name: { en: "First grandchild", fr: "Premier petit-fils" },
|
|
48
|
+
id: "FirstGrandchild",
|
|
49
|
+
parentScopeId: "MyScope",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
20
52
|
settings: {
|
|
21
53
|
defaultScope: "myScope",
|
|
54
|
+
loadedModulesScope: ["moduleA", "moduleB"],
|
|
55
|
+
modules: ["moduleA", "moduleB"],
|
|
22
56
|
},
|
|
23
57
|
}),
|
|
24
58
|
replaceReducer: () => {},
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import Page from "./Page";
|
|
3
3
|
import SegmentPage from "./SegmentPage";
|
|
4
4
|
|
|
5
|
-
const FullPage = ({ path, config, location, match, modulePrependPath }) => {
|
|
5
|
+
const FullPage = ({ path, config, location, match, modulePrependPath, isVisible }) => {
|
|
6
6
|
const { component, componentProps, pages = {}, segments, subpages, entityIdResolver } = config;
|
|
7
7
|
if (segments) {
|
|
8
8
|
return (
|
|
@@ -26,6 +26,7 @@ const FullPage = ({ path, config, location, match, modulePrependPath }) => {
|
|
|
26
26
|
subpages={subpages}
|
|
27
27
|
location={location}
|
|
28
28
|
match={match}
|
|
29
|
+
isVisible={isVisible}
|
|
29
30
|
modulePrependPath={modulePrependPath}
|
|
30
31
|
/>
|
|
31
32
|
);
|
|
@@ -86,6 +86,29 @@ describe("Fullpage", () => {
|
|
|
86
86
|
<View2 />,
|
|
87
87
|
));
|
|
88
88
|
|
|
89
|
+
it("does not show a page when not visible", () =>
|
|
90
|
+
expect(
|
|
91
|
+
<TestWrapper
|
|
92
|
+
provider={{ store }}
|
|
93
|
+
memoryRouter={{ initialEntries: ["/meep/snap/stuff"] }}
|
|
94
|
+
stylesProvider
|
|
95
|
+
muiThemeProvider={{ theme }}
|
|
96
|
+
>
|
|
97
|
+
<FullPage
|
|
98
|
+
path="/meep/snap"
|
|
99
|
+
config={{
|
|
100
|
+
component: View1,
|
|
101
|
+
}}
|
|
102
|
+
isVisible={false}
|
|
103
|
+
location={{ location: true }}
|
|
104
|
+
match={{ match: true }}
|
|
105
|
+
/>
|
|
106
|
+
</TestWrapper>,
|
|
107
|
+
"when mounted",
|
|
108
|
+
"to be",
|
|
109
|
+
null,
|
|
110
|
+
));
|
|
111
|
+
|
|
89
112
|
it("shows a segment page if segments", () => {
|
|
90
113
|
const location = {
|
|
91
114
|
pathname: "/meep/snap/stuff",
|
|
@@ -5,8 +5,8 @@ import FullPage from "./FullPage";
|
|
|
5
5
|
import SubPage from "./SubPage";
|
|
6
6
|
import withWaypointing from "./withWaypointing";
|
|
7
7
|
|
|
8
|
-
const Page = ({ component: View, path, pages = {}, subpages = {}, modulePrependPath }) => {
|
|
9
|
-
const WrappedView = useMemo(() => withErrorBoundary(path)(withWaypointing(View)), [path, View]);
|
|
8
|
+
const Page = ({ component: View, path, pages = {}, subpages = {}, modulePrependPath, isVisible = true }) => {
|
|
9
|
+
const WrappedView = useMemo(() => withErrorBoundary(path)(withWaypointing(View, isVisible)), [path, View, isVisible]);
|
|
10
10
|
return (
|
|
11
11
|
<React.Fragment>
|
|
12
12
|
<Switch>
|
|
@@ -70,6 +70,26 @@ describe("Page", () => {
|
|
|
70
70
|
</TestWrapper>,
|
|
71
71
|
));
|
|
72
72
|
|
|
73
|
+
it("Does not show the page view when its path is matched but not visible", () =>
|
|
74
|
+
expect(
|
|
75
|
+
<TestWrapper provider={{ store }} intlProvider={intlProvider} stylesProvider muiThemeProvider={{ theme }}>
|
|
76
|
+
<MemoryRouter initialEntries={["/nabble"]}>
|
|
77
|
+
<Page
|
|
78
|
+
component={View}
|
|
79
|
+
path="/nabble"
|
|
80
|
+
isVisible={false}
|
|
81
|
+
pages={{
|
|
82
|
+
"/foo": { component: Sub1 },
|
|
83
|
+
"/bar": { component: Sub2 },
|
|
84
|
+
}}
|
|
85
|
+
/>
|
|
86
|
+
</MemoryRouter>
|
|
87
|
+
</TestWrapper>,
|
|
88
|
+
"when mounted",
|
|
89
|
+
"to equal",
|
|
90
|
+
null,
|
|
91
|
+
));
|
|
92
|
+
|
|
73
93
|
it("shows nested page when its path is matched", () =>
|
|
74
94
|
expect(
|
|
75
95
|
<TestWrapper provider={{ store }} intlProvider={intlProvider} stylesProvider muiThemeProvider={{ theme }}>
|
|
@@ -6,7 +6,7 @@ const Segment = ({ location, match, config, root, modulePrependPath }) => {
|
|
|
6
6
|
const { component, componentProps } = config;
|
|
7
7
|
const path = location.pathname;
|
|
8
8
|
const View = useMemo(
|
|
9
|
-
() => withErrorBoundary(path)(withWaypointing(component, componentProps)),
|
|
9
|
+
() => withErrorBoundary(path)(withWaypointing(component, true, componentProps)),
|
|
10
10
|
[path, component, componentProps],
|
|
11
11
|
);
|
|
12
12
|
return <View location={location} match={match} mapFrom={root} modulePrependPath={modulePrependPath} />;
|
|
@@ -6,7 +6,7 @@ import { setRoute, mapHref, setCurrentPrependPath } from "../../actions/navigati
|
|
|
6
6
|
import useLoader from "../../hooks/useLoader";
|
|
7
7
|
|
|
8
8
|
const withWaypointing =
|
|
9
|
-
(Comp, componentProps = {}) =>
|
|
9
|
+
(Comp, isVisible = true, componentProps = {}) =>
|
|
10
10
|
props => {
|
|
11
11
|
const { match, mapFrom, modulePrependPath } = props;
|
|
12
12
|
const location = useLocation();
|
|
@@ -24,7 +24,7 @@ const withWaypointing =
|
|
|
24
24
|
}
|
|
25
25
|
const cutout = state => selectRouteHref(state) === location.pathname;
|
|
26
26
|
useLoader(loadActions, cutout);
|
|
27
|
-
return <Comp {...props} {...componentProps}
|
|
27
|
+
return isVisible ? <Comp {...props} {...componentProps} /> : null;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export default withWaypointing;
|