orc-shared 1.2.0-dev.1 → 1.2.0-dev.13
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/LICENSE +1 -1
- package/README.md +1 -1
- 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/modules.js +63 -1
- package/dist/actions/navigation.js +3 -3
- 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 +3 -3
- package/dist/components/AppFrame/About.js +11 -6
- package/dist/components/AppFrame/MenuItem.js +6 -15
- package/dist/components/AppFrame/Preferences.js +3 -3
- 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 +3 -3
- 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 +3 -3
- 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/List/enhanceColumnDefs.js +2 -2
- package/dist/components/MaterialUI/DataDisplay/List.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/Notification.js +2 -2
- package/dist/components/MaterialUI/DataDisplay/NotificationProps.js +1 -1
- package/dist/components/MaterialUI/DataDisplay/PredefinedElements/Translations.js +3 -3
- 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 +3 -3
- package/dist/components/MaterialUI/Feedback/useNotification.js +1 -1
- package/dist/components/MaterialUI/Inputs/Autocomplete.js +2 -2
- 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 +42 -5
- 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/Select.js +2 -2
- package/dist/components/MaterialUI/Inputs/SelectProps.js +1 -1
- package/dist/components/MaterialUI/Inputs/Switch.js +3 -3
- 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 +3 -3
- 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/ScopeSelector/ScopeSelector.js +8 -2
- package/dist/components/MaterialUI/Surfaces/expansionPanelProps.js +1 -1
- package/dist/components/MaterialUI/Surfaces/paperProps.js +1 -1
- package/dist/components/MaterialUI/muiThemes.js +7 -2
- 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 +3 -3
- package/dist/components/Navigation/Tab.js +1 -1
- package/dist/components/Navigation/useNavigationState.js +3 -3
- 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 +8 -4
- package/dist/components/Scope/ScopeNode.js +1 -1
- package/dist/components/Scope/Selector.js +1 -1
- package/dist/components/Scope/index.js +3 -3
- 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 +3 -3
- package/dist/components/Treeview/index.js +2 -2
- package/dist/components/Treeview/settings.js +1 -1
- package/dist/constants.js +19 -2
- package/dist/content/icons/lock.svg +3 -0
- package/dist/content/icons/orckestra-icon.svg +5 -0
- package/dist/content/icons/unlock.svg +3 -0
- package/dist/content/iconsSheet.svg +11 -0
- package/dist/content/orckestra-logo-white.png +0 -0
- package/dist/getThemeOverrides.js +2 -2
- package/dist/hocs/withInfiniteScroll.js +1 -1
- package/dist/hocs/withUpdateHandler.js +2 -2
- package/dist/hooks/useDispatchWithModulesData.js +1 -1
- package/dist/hooks/useEditState.js +3 -3
- package/dist/hooks/useEntityLoader.js +2 -2
- package/dist/hooks/useFullEntityEditState.js +3 -3
- package/dist/hooks/useLabelMessage.js +3 -3
- package/dist/hooks/useMultipleFieldEditState.js +2 -2
- package/dist/hooks/useNavigationHandler.js +1 -1
- package/dist/hooks/useNotificationRequestState.js +2 -2
- 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 +16 -6
- 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 +8 -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/flatten.js +2 -2
- 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/setTranslation.js +27 -1
- package/dist/utils/setTranslationWithFallback.js +31 -2
- 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 +10 -3
- 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/DataDisplay/PredefinedElements/Translations.test.js +7 -1
- package/src/components/MaterialUI/Inputs/InputBase.js +19 -2
- package/src/components/MaterialUI/Inputs/InputBase.test.js +68 -0
- package/src/components/MaterialUI/Navigation/ExternalLink.js +25 -0
- package/src/components/MaterialUI/Navigation/ExternalLink.test.js +26 -0
- package/src/components/MaterialUI/ScopeSelector/ScopeSelector.js +5 -1
- 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/Scope.test.js +4 -0
- 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/lock.svg +3 -0
- package/src/content/icons/orckestra-icon.svg +5 -0
- package/src/content/icons/unlock.svg +3 -0
- package/src/content/iconsSheet.svg +11 -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/metadata.js +18 -7
- package/src/selectors/metadata.test.js +221 -283
- package/src/selectors/modules.js +7 -0
- package/src/selectors/modules.test.js +16 -1
- package/src/selectors/scope.js +3 -1
- package/src/selectors/scope.test.js +5 -0
- package/src/selectors/settings.js +6 -0
- package/src/translations/en-US.json +1 -1
- package/src/translations/fr-CA.json +1 -1
- package/src/utils/setTranslation.js +16 -1
- package/src/utils/setTranslation.test.js +24 -0
- package/src/utils/setTranslationWithFallback.js +18 -1
- package/src/utils/setTranslationWithFallback.test.js +108 -0
package/src/reducers/modules.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import Immutable from "immutable";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
INITIALIZE_FIRST_MODULE_SCOPE,
|
|
4
|
+
SET_MODULE_AS_VISIBLE,
|
|
5
|
+
SET_MODULES_STRUCTURE,
|
|
6
|
+
SET_NEW_SCOPE_AND_MODULE_NAME,
|
|
7
|
+
SET_ROUTING_PERFORMED,
|
|
8
|
+
} from "../actions/modules";
|
|
3
9
|
import { infoBar } from "./../constants";
|
|
4
10
|
|
|
5
|
-
const initialState = Immutable.
|
|
11
|
+
const initialState = Immutable.fromJS({
|
|
12
|
+
tree: {},
|
|
13
|
+
visibleModules: [],
|
|
14
|
+
lastScopeAndModuleSelection: {
|
|
15
|
+
scope: null,
|
|
16
|
+
moduleName: null,
|
|
17
|
+
routingPerformed: true,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
6
20
|
|
|
7
21
|
const viewStateReducer = (state = initialState, action) => {
|
|
8
22
|
switch (action.type) {
|
|
@@ -32,6 +46,38 @@ const viewStateReducer = (state = initialState, action) => {
|
|
|
32
46
|
|
|
33
47
|
return state.set("tree", Immutable.fromJS(modulesTree));
|
|
34
48
|
}
|
|
49
|
+
|
|
50
|
+
case INITIALIZE_FIRST_MODULE_SCOPE: {
|
|
51
|
+
return state.setIn(["lastScopeAndModuleSelection", "scope"], action.payload);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
case SET_MODULE_AS_VISIBLE: {
|
|
55
|
+
const visibleModules = state.get("visibleModules").toJS();
|
|
56
|
+
visibleModules.push(action.payload);
|
|
57
|
+
|
|
58
|
+
return state.set("visibleModules", Immutable.fromJS(visibleModules));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
case SET_NEW_SCOPE_AND_MODULE_NAME: {
|
|
62
|
+
const lastScopeAndModuleSelection = state.get("lastScopeAndModuleSelection").toJS();
|
|
63
|
+
|
|
64
|
+
if (action.payload.scope !== lastScopeAndModuleSelection.scope) {
|
|
65
|
+
state = state.set("visibleModules", Immutable.fromJS([]));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return state.set(
|
|
69
|
+
"lastScopeAndModuleSelection",
|
|
70
|
+
Immutable.fromJS({
|
|
71
|
+
moduleName: action.payload.moduleName,
|
|
72
|
+
scope: action.payload.scope,
|
|
73
|
+
routingPerformed: false,
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
case SET_ROUTING_PERFORMED:
|
|
79
|
+
return state.setIn(["lastScopeAndModuleSelection", "routingPerformed"], true);
|
|
80
|
+
|
|
35
81
|
default:
|
|
36
82
|
return state;
|
|
37
83
|
}
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
import Immutable from "immutable";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
initializeFirstModuleScope,
|
|
4
|
+
setModuleAsVisible,
|
|
5
|
+
setModulesStructure,
|
|
6
|
+
setNewScopeAndModuleName,
|
|
7
|
+
setRoutingPerformed,
|
|
8
|
+
} from "../actions/modules";
|
|
3
9
|
import modulesReducer from "./modules";
|
|
4
10
|
|
|
5
11
|
describe("View state reducer", () => {
|
|
6
|
-
|
|
12
|
+
const initialState = {
|
|
13
|
+
tree: {},
|
|
14
|
+
visibleModules: [],
|
|
15
|
+
lastScopeAndModuleSelection: {
|
|
16
|
+
scope: null,
|
|
17
|
+
moduleName: null,
|
|
18
|
+
routingPerformed: true,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
it("behaves as a reducer should", () => expect(modulesReducer, "to be a reducer with initial state", initialState));
|
|
7
23
|
|
|
8
24
|
it("Sets module structure correctly", () => {
|
|
9
25
|
const oldState = Immutable.Map({});
|
|
@@ -92,4 +108,103 @@ describe("View state reducer", () => {
|
|
|
92
108
|
const newState = modulesReducer(oldState, action);
|
|
93
109
|
return expect(newState, "not to be", oldState).and("to equal", Immutable.fromJS({ tree: modules }));
|
|
94
110
|
});
|
|
111
|
+
|
|
112
|
+
it("Initialize first scope", () => {
|
|
113
|
+
const oldState = Immutable.fromJS(initialState);
|
|
114
|
+
|
|
115
|
+
const expected = {
|
|
116
|
+
...initialState,
|
|
117
|
+
lastScopeAndModuleSelection: {
|
|
118
|
+
...initialState.lastScopeAndModuleSelection,
|
|
119
|
+
scope: "firstScope",
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const action = initializeFirstModuleScope("firstScope");
|
|
124
|
+
const newState = modulesReducer(oldState, action);
|
|
125
|
+
return expect(newState, "not to be", oldState).and("to equal", Immutable.fromJS(expected));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("Add a visible module into the array", () => {
|
|
129
|
+
const oldState = Immutable.fromJS({
|
|
130
|
+
...initialState,
|
|
131
|
+
visibleModules: ["moduleReality"],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const expected = {
|
|
135
|
+
...initialState,
|
|
136
|
+
visibleModules: ["moduleReality", "moduleMatrix"],
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const action = setModuleAsVisible("moduleMatrix");
|
|
140
|
+
const newState = modulesReducer(oldState, action);
|
|
141
|
+
return expect(newState, "not to be", oldState).and("to equal", Immutable.fromJS(expected));
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("set a new scope and module for eventual redirection", () => {
|
|
145
|
+
const oldState = Immutable.fromJS({
|
|
146
|
+
...initialState,
|
|
147
|
+
lastScopeAndModuleSelection: {
|
|
148
|
+
scope: "aScope",
|
|
149
|
+
moduleName: null,
|
|
150
|
+
routingPerformed: true,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const expected = {
|
|
155
|
+
...initialState,
|
|
156
|
+
lastScopeAndModuleSelection: {
|
|
157
|
+
scope: "aScope",
|
|
158
|
+
moduleName: "moduleMatrix",
|
|
159
|
+
routingPerformed: false,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const action = setNewScopeAndModuleName("aScope", "moduleMatrix");
|
|
164
|
+
const newState = modulesReducer(oldState, action);
|
|
165
|
+
return expect(newState, "not to be", oldState).and("to equal", Immutable.fromJS(expected));
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("set a new scope and module for eventual redirection and reinitialize visible modules", () => {
|
|
169
|
+
const oldState = Immutable.fromJS({
|
|
170
|
+
...initialState,
|
|
171
|
+
visibleModules: ["moduleReality"],
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const expected = {
|
|
175
|
+
...initialState,
|
|
176
|
+
lastScopeAndModuleSelection: {
|
|
177
|
+
scope: "newScope",
|
|
178
|
+
moduleName: "moduleMatrix",
|
|
179
|
+
routingPerformed: false,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const action = setNewScopeAndModuleName("newScope", "moduleMatrix");
|
|
184
|
+
const newState = modulesReducer(oldState, action);
|
|
185
|
+
return expect(newState, "not to be", oldState).and("to equal", Immutable.fromJS(expected));
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("set routing was perform on scope and module", () => {
|
|
189
|
+
const oldState = Immutable.fromJS({
|
|
190
|
+
...initialState,
|
|
191
|
+
lastScopeAndModuleSelection: {
|
|
192
|
+
scope: "aScope",
|
|
193
|
+
moduleName: "aModule",
|
|
194
|
+
routingPerformed: false,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
const expected = {
|
|
198
|
+
...initialState,
|
|
199
|
+
lastScopeAndModuleSelection: {
|
|
200
|
+
scope: "aScope",
|
|
201
|
+
moduleName: "aModule",
|
|
202
|
+
routingPerformed: true,
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const action = setRoutingPerformed();
|
|
207
|
+
const newState = modulesReducer(oldState, action);
|
|
208
|
+
return expect(newState, "not to be", oldState).and("to equal", Immutable.fromJS(expected));
|
|
209
|
+
});
|
|
95
210
|
});
|
package/src/reducers/scopes.js
CHANGED
|
@@ -8,7 +8,37 @@ const initialState = Immutable.fromJS({});
|
|
|
8
8
|
const scopeReducer = (state = initialState, action) => {
|
|
9
9
|
switch (action.type) {
|
|
10
10
|
case GET_SCOPES_SUCCESS: {
|
|
11
|
+
const loadedScopes = state.toJS();
|
|
11
12
|
const normalizedScopes = normalize(action.payload, scopeSchema);
|
|
13
|
+
|
|
14
|
+
if (Object.keys(loadedScopes).length > 0) {
|
|
15
|
+
const addedScope = {};
|
|
16
|
+
|
|
17
|
+
Object.values(normalizedScopes.entities.scopes).forEach(scope => {
|
|
18
|
+
if (!loadedScopes[scope.id]) {
|
|
19
|
+
loadedScopes[scope.id] = scope;
|
|
20
|
+
addedScope[scope.id] = scope;
|
|
21
|
+
} else if (scope.isAuthorizedScope) {
|
|
22
|
+
loadedScopes[scope.id] = scope;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
Object.values(addedScope).forEach(scope => {
|
|
27
|
+
const parentScope = loadedScopes[scope.parentScopeId];
|
|
28
|
+
|
|
29
|
+
if (parentScope) {
|
|
30
|
+
if (!parentScope.children.includes(scope.id)) {
|
|
31
|
+
parentScope.children.push(scope.id);
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
// Should not happen, but for safety
|
|
35
|
+
delete loadedScopes[scope.id];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return state.merge(Immutable.fromJS(loadedScopes));
|
|
40
|
+
}
|
|
41
|
+
|
|
12
42
|
return state.merge(Immutable.fromJS(normalizedScopes.entities.scopes));
|
|
13
43
|
}
|
|
14
44
|
default:
|
|
@@ -6,7 +6,7 @@ describe("scopes", () => {
|
|
|
6
6
|
it("behaves as a reducer should", () => expect(reducer, "to be a reducer with initial state", {}));
|
|
7
7
|
|
|
8
8
|
it("saves a normalized index of scopes with child lists, keys all lower case", () => {
|
|
9
|
-
const oldState = Immutable.Map({
|
|
9
|
+
const oldState = Immutable.Map({});
|
|
10
10
|
const action = {
|
|
11
11
|
type: GET_SCOPES_SUCCESS,
|
|
12
12
|
payload: {
|
|
@@ -47,4 +47,48 @@ describe("scopes", () => {
|
|
|
47
47
|
}),
|
|
48
48
|
);
|
|
49
49
|
});
|
|
50
|
+
|
|
51
|
+
it("updates a normalized index of scopes with child lists, keys all lower case", () => {
|
|
52
|
+
const oldState = Immutable.Map({
|
|
53
|
+
Global: {
|
|
54
|
+
id: "Global",
|
|
55
|
+
isAuthorizedScope: false,
|
|
56
|
+
children: ["Child1", "Child2", "Child3"],
|
|
57
|
+
scopePath: ["Global"],
|
|
58
|
+
},
|
|
59
|
+
Child1: { id: "Child1", isAuthorizedScope: true, scopePath: ["Global", "Child1"], children: [] },
|
|
60
|
+
Child2: { id: "Child2", isAuthorizedScope: false, scopePath: ["Global", "Child2"], children: [] },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const action = {
|
|
64
|
+
type: GET_SCOPES_SUCCESS,
|
|
65
|
+
payload: {
|
|
66
|
+
id: "Global",
|
|
67
|
+
isAuthorized: false,
|
|
68
|
+
children: [
|
|
69
|
+
{ id: "Child1", isAuthorizedScope: false, children: [], parentScopeId: "Global" },
|
|
70
|
+
{ id: "Child2", isAuthorizedScope: true, children: [], parentScopeId: "Global" },
|
|
71
|
+
{ id: "Child3", isAuthorizedScope: false, children: [], parentScopeId: "Global" },
|
|
72
|
+
{ id: "Child4", isAuthorizedScope: true, children: [], parentScopeId: "Global" },
|
|
73
|
+
{ id: "Child5", isAuthorizedScope: true, children: [], parentScopeId: "UnknownParent" },
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const newState = reducer(oldState, action);
|
|
78
|
+
return expect(newState, "not to be", oldState).and(
|
|
79
|
+
"to satisfy",
|
|
80
|
+
Immutable.fromJS({
|
|
81
|
+
Global: {
|
|
82
|
+
id: "Global",
|
|
83
|
+
isAuthorizedScope: false,
|
|
84
|
+
children: ["Child1", "Child2", "Child3", "Child4"],
|
|
85
|
+
scopePath: ["Global"],
|
|
86
|
+
},
|
|
87
|
+
Child1: { id: "Child1", isAuthorizedScope: true, scopePath: ["Global", "Child1"], children: [] },
|
|
88
|
+
Child2: { id: "Child2", isAuthorizedScope: true, scopePath: ["Global", "Child2"], children: [] },
|
|
89
|
+
Child3: { id: "Child3", isAuthorizedScope: false, scopePath: ["Global", "Child3"], children: [] },
|
|
90
|
+
Child4: { id: "Child4", isAuthorizedScope: true, scopePath: ["Global", "Child4"], children: [] },
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
93
|
+
});
|
|
50
94
|
});
|
package/src/reducers/settings.js
CHANGED
|
@@ -3,19 +3,43 @@ import addSpawner from "../spawnerMiddleware";
|
|
|
3
3
|
import { changeLocale } from "../actions/locale";
|
|
4
4
|
import { GET_MY_CULTURE_SUCCESS } from "../actions/locale";
|
|
5
5
|
import { GET_MY_APPLICATION_SUCCESS, SET_MY_APPLICATION_SUCCESS } from "../actions/applications";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
GET_APPLICATION_MODULES_SUCCESS,
|
|
8
|
+
GET_MY_SCOPE_SUCCESS,
|
|
9
|
+
GET_SCOPES_FAILURE,
|
|
10
|
+
GET_SCOPES_SUCCESS,
|
|
11
|
+
} from "../actions/scopes";
|
|
12
|
+
import { overtureModule } from "../constants";
|
|
7
13
|
|
|
8
|
-
const initialState = Immutable.
|
|
14
|
+
const initialState = Immutable.fromJS({
|
|
9
15
|
defaultApp: 0,
|
|
10
16
|
defaultScope: null,
|
|
17
|
+
loadedModulesScope: [],
|
|
18
|
+
modules: [],
|
|
11
19
|
});
|
|
12
20
|
|
|
21
|
+
const setLoadedModulesScope = (state, module) => {
|
|
22
|
+
const loadedModulesScope = state.get("loadedModulesScope").toJS();
|
|
23
|
+
loadedModulesScope.push(module);
|
|
24
|
+
return state.set("loadedModulesScope", Immutable.fromJS(loadedModulesScope));
|
|
25
|
+
};
|
|
26
|
+
|
|
13
27
|
const settingsReducer = (state = initialState, action) => {
|
|
14
28
|
switch (action.type) {
|
|
29
|
+
case GET_APPLICATION_MODULES_SUCCESS:
|
|
30
|
+
return state.set("modules", Immutable.fromJS(action.payload.map(x => overtureModule[x.name])));
|
|
15
31
|
case GET_MY_APPLICATION_SUCCESS:
|
|
16
32
|
return state.set("defaultApp", action.payload.id);
|
|
17
33
|
case SET_MY_APPLICATION_SUCCESS:
|
|
18
34
|
return state.set("defaultApp", action.meta.appId);
|
|
35
|
+
case GET_SCOPES_SUCCESS:
|
|
36
|
+
return setLoadedModulesScope(state, action.meta.module);
|
|
37
|
+
case GET_SCOPES_FAILURE: {
|
|
38
|
+
if (action.payload.status === 500) {
|
|
39
|
+
state = setLoadedModulesScope(state, action.meta.module);
|
|
40
|
+
}
|
|
41
|
+
return state;
|
|
42
|
+
}
|
|
19
43
|
case GET_MY_SCOPE_SUCCESS:
|
|
20
44
|
return state.set("defaultScope", action.payload.id);
|
|
21
45
|
default:
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import Immutable from "immutable";
|
|
2
2
|
import reducer from "./settings";
|
|
3
3
|
import { GET_MY_APPLICATION_SUCCESS, SET_MY_APPLICATION_SUCCESS } from "../actions/applications";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
GET_APPLICATION_MODULES_SUCCESS,
|
|
6
|
+
GET_MY_SCOPE_SUCCESS,
|
|
7
|
+
GET_SCOPES_FAILURE,
|
|
8
|
+
GET_SCOPES_SUCCESS,
|
|
9
|
+
} from "../actions/scopes";
|
|
5
10
|
|
|
6
11
|
describe("settings", () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
const initialState = Immutable.fromJS({
|
|
13
|
+
defaultApp: 0,
|
|
14
|
+
defaultScope: null,
|
|
15
|
+
loadedModulesScope: [],
|
|
16
|
+
modules: [],
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("behaves as a reducer should", () => expect(reducer, "to be a reducer with initial state", initialState));
|
|
12
20
|
|
|
13
21
|
it("stores results of getting your personal default application", () => {
|
|
14
22
|
const oldState = Immutable.fromJS({
|
|
@@ -65,4 +73,64 @@ describe("settings", () => {
|
|
|
65
73
|
defaultScope: "aScope",
|
|
66
74
|
});
|
|
67
75
|
});
|
|
76
|
+
|
|
77
|
+
it("stores modules for the application", () => {
|
|
78
|
+
const oldState = Immutable.fromJS({
|
|
79
|
+
modules: [],
|
|
80
|
+
});
|
|
81
|
+
const action = {
|
|
82
|
+
type: GET_APPLICATION_MODULES_SUCCESS,
|
|
83
|
+
payload: [{ name: "Customers" }, { name: "Orders" }, { name: "Administration" }],
|
|
84
|
+
};
|
|
85
|
+
const newState = reducer(oldState, action);
|
|
86
|
+
expect(newState, "not to be", oldState).and("to satisfy", {
|
|
87
|
+
modules: ["Customer", "Order", "Administration"],
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("stores module as loaded when it is a success", () => {
|
|
92
|
+
const oldState = Immutable.fromJS({
|
|
93
|
+
loadedModulesScope: [],
|
|
94
|
+
});
|
|
95
|
+
const action = {
|
|
96
|
+
type: GET_SCOPES_SUCCESS,
|
|
97
|
+
meta: { module: "Order" },
|
|
98
|
+
};
|
|
99
|
+
const newState = reducer(oldState, action);
|
|
100
|
+
expect(newState, "not to be", oldState).and("to satisfy", {
|
|
101
|
+
loadedModulesScope: ["Order"],
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("stores module as loaded when it is a failure with status 500", () => {
|
|
106
|
+
const oldState = Immutable.fromJS({
|
|
107
|
+
loadedModulesScope: [],
|
|
108
|
+
});
|
|
109
|
+
const action = {
|
|
110
|
+
type: GET_SCOPES_FAILURE,
|
|
111
|
+
payload: {
|
|
112
|
+
status: 500,
|
|
113
|
+
},
|
|
114
|
+
meta: { module: "Order" },
|
|
115
|
+
};
|
|
116
|
+
const newState = reducer(oldState, action);
|
|
117
|
+
expect(newState, "not to be", oldState).and("to satisfy", {
|
|
118
|
+
loadedModulesScope: ["Order"],
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("does not store module as loaded when it is a failure with other errors", () => {
|
|
123
|
+
const oldState = Immutable.fromJS({
|
|
124
|
+
loadedModulesScope: [],
|
|
125
|
+
});
|
|
126
|
+
const action = {
|
|
127
|
+
type: GET_SCOPES_FAILURE,
|
|
128
|
+
payload: {
|
|
129
|
+
status: 404,
|
|
130
|
+
},
|
|
131
|
+
meta: { module: "Order" },
|
|
132
|
+
};
|
|
133
|
+
const newState = reducer(oldState, action);
|
|
134
|
+
expect(newState, "to be", oldState);
|
|
135
|
+
});
|
|
68
136
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createSelector } from "reselect";
|
|
2
2
|
import { platformRoles } from "./../constants";
|
|
3
3
|
import { getCurrentScope } from "./navigation";
|
|
4
|
+
import { getScopesSelector } from "./scope";
|
|
4
5
|
|
|
5
6
|
const authData = state => state.get("authentication");
|
|
6
7
|
|
|
@@ -11,35 +12,60 @@ export const selectRolesClaims = createSelector(authData, data => data.get("role
|
|
|
11
12
|
export const selectGroupRolesClaims = roleGroup =>
|
|
12
13
|
createSelector(selectRolesClaims, rolesClaims => rolesClaims.get(roleGroup) || null);
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
const hasRolePermissions = (appRolesClaims, scopeId, role, scopes) => {
|
|
16
|
+
if (appRolesClaims != null && scopeId != null) {
|
|
17
|
+
const allowed = !!appRolesClaims.getIn(["*", role]) || !!appRolesClaims.getIn([scopeId, role]);
|
|
18
|
+
|
|
19
|
+
if (!allowed) {
|
|
20
|
+
const parentScopeId = scopes.get(scopeId)?.toJS()?.parentScopeId ?? null;
|
|
21
|
+
|
|
22
|
+
return hasRolePermissions(appRolesClaims, parentScopeId, role, scopes);
|
|
21
23
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
return allowed;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return false;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const hasEditorPermissions = roleGroup =>
|
|
32
|
+
createSelector(
|
|
33
|
+
selectGroupRolesClaims(roleGroup),
|
|
34
|
+
getCurrentScope,
|
|
35
|
+
getScopesSelector,
|
|
36
|
+
(appRolesClaims, currentScope, scopes) =>
|
|
37
|
+
hasRolePermissions(appRolesClaims, currentScope, platformRoles.Editor, scopes),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
export const hasEditorPermissionsForScope = (scope, roleGroup) =>
|
|
41
|
+
createSelector(selectGroupRolesClaims(roleGroup), getScopesSelector, (appRolesClaims, scopes) =>
|
|
42
|
+
hasRolePermissions(appRolesClaims, scope, platformRoles.Editor, scopes),
|
|
43
|
+
);
|
|
24
44
|
|
|
25
45
|
export const hasAdministratorPermissions = roleGroup =>
|
|
26
|
-
createSelector(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
createSelector(
|
|
47
|
+
selectGroupRolesClaims(roleGroup),
|
|
48
|
+
getCurrentScope,
|
|
49
|
+
getScopesSelector,
|
|
50
|
+
(appRolesClaims, currentScope, scopes) =>
|
|
51
|
+
hasRolePermissions(appRolesClaims, currentScope, platformRoles.Administrator, scopes),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
export const hasAdministratorPermissionsForScope = (scope, roleGroup) =>
|
|
55
|
+
createSelector(selectGroupRolesClaims(roleGroup), getScopesSelector, (appRolesClaims, scopes) =>
|
|
56
|
+
hasRolePermissions(appRolesClaims, scope, platformRoles.Administrator, scopes),
|
|
57
|
+
);
|
|
35
58
|
|
|
36
59
|
export const hasReaderPermissions = roleGroup =>
|
|
37
|
-
createSelector(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
createSelector(
|
|
61
|
+
selectGroupRolesClaims(roleGroup),
|
|
62
|
+
getCurrentScope,
|
|
63
|
+
getScopesSelector,
|
|
64
|
+
(appRolesClaims, currentScope, scopes) =>
|
|
65
|
+
hasRolePermissions(appRolesClaims, currentScope, platformRoles.Reader, scopes),
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
export const hasReaderPermissionsForScope = (scope, roleGroup) =>
|
|
69
|
+
createSelector(selectGroupRolesClaims(roleGroup), getScopesSelector, (appRolesClaims, scopes) =>
|
|
70
|
+
hasRolePermissions(appRolesClaims, scope, platformRoles.Reader, scopes),
|
|
71
|
+
);
|