orc-shared 1.1.0-dev.8 → 1.1.1

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.
Files changed (259) hide show
  1. package/dist/actions/applications.js +1 -1
  2. package/dist/actions/authentication.js +1 -1
  3. package/dist/actions/countries.js +1 -1
  4. package/dist/actions/locale.js +1 -1
  5. package/dist/actions/makeApiAction.js +73 -3
  6. package/dist/actions/makeOrcApiAction.js +2 -2
  7. package/dist/actions/metadata.js +295 -31
  8. package/dist/actions/navigation.js +3 -3
  9. package/dist/actions/requestState.js +78 -0
  10. package/dist/actions/requestsApi.js +58 -7
  11. package/dist/actions/scopes.js +1 -1
  12. package/dist/actions/timezones.js +1 -1
  13. package/dist/actions/toasts.js +1 -1
  14. package/dist/actions/versionInfo.js +1 -1
  15. package/dist/actions/view.js +1 -1
  16. package/dist/buildStore.js +7 -4
  17. package/dist/components/AppFrame/About.js +3 -3
  18. package/dist/components/AppFrame/ApplicationSelector/ApplicationDialog.js +115 -62
  19. package/dist/components/AppFrame/ApplicationSelector/index.js +45 -47
  20. package/dist/components/AppFrame/MenuItem.js +1 -1
  21. package/dist/components/AppFrame/Preferences.js +3 -3
  22. package/dist/components/AppFrame/Sidebar.js +1 -1
  23. package/dist/components/AppFrame/Topbar.js +1 -1
  24. package/dist/components/Authenticate.js +1 -1
  25. package/dist/components/CategoryList.js +1 -1
  26. package/dist/components/Checkbox.js +1 -1
  27. package/dist/components/DropMenu/Menu.js +1 -1
  28. package/dist/components/DropMenu/index.js +1 -1
  29. package/dist/components/Form/FieldList.js +3 -3
  30. package/dist/components/Form/Form.js +1 -1
  31. package/dist/components/Form/Inputs/Button.js +1 -1
  32. package/dist/components/Form/Inputs/FieldButtons.js +1 -1
  33. package/dist/components/Form/Inputs/Number.js +1 -1
  34. package/dist/components/Form/Inputs/ReadOnly.js +1 -1
  35. package/dist/components/Form/Inputs/SmallButton.js +1 -1
  36. package/dist/components/Form/Inputs/Text.js +1 -1
  37. package/dist/components/Form/Inputs/Time.js +1 -1
  38. package/dist/components/Form/Inputs/Toggles.js +1 -1
  39. package/dist/components/Form/Inputs/Translation.js +3 -3
  40. package/dist/components/List/HeadCell.js +1 -1
  41. package/dist/components/List/List.js +1 -1
  42. package/dist/components/List/Row.js +1 -1
  43. package/dist/components/List/enhanceColumnDefs.js +2 -2
  44. package/dist/components/MaterialUI/DataDisplay/List.js +1 -1
  45. package/dist/components/MaterialUI/DataDisplay/Notification.js +2 -2
  46. package/dist/components/MaterialUI/DataDisplay/NotificationProps.js +1 -1
  47. package/dist/components/MaterialUI/DataDisplay/PredefinedElements/Translations.js +3 -3
  48. package/dist/components/MaterialUI/DataDisplay/SelectionList.js +19 -6
  49. package/dist/components/MaterialUI/DataDisplay/Table.js +28 -10
  50. package/dist/components/MaterialUI/DataDisplay/TableProps.js +5 -2
  51. package/dist/components/MaterialUI/DataDisplay/TransferList.js +5 -2
  52. package/dist/components/MaterialUI/DataDisplay/chipProps.js +1 -1
  53. package/dist/components/MaterialUI/DataDisplay/collapsableListProps.js +1 -1
  54. package/dist/components/MaterialUI/DataDisplay/dividerProps.js +1 -1
  55. package/dist/components/MaterialUI/DataDisplay/index.js +1 -1
  56. package/dist/components/MaterialUI/DataDisplay/modalProps.js +1 -1
  57. package/dist/components/MaterialUI/DataDisplay/useTableSelection.js +3 -3
  58. package/dist/components/MaterialUI/Feedback/useNotification.js +1 -1
  59. package/dist/components/MaterialUI/Inputs/Autocomplete.js +2 -2
  60. package/dist/components/MaterialUI/Inputs/AutocompleteProps.js +1 -1
  61. package/dist/components/MaterialUI/Inputs/CheckboxGroupProps.js +1 -1
  62. package/dist/components/MaterialUI/Inputs/CheckboxProps.js +1 -1
  63. package/dist/components/MaterialUI/Inputs/DatePicker.js +11 -0
  64. package/dist/components/MaterialUI/Inputs/InputBase.js +3 -2
  65. package/dist/components/MaterialUI/Inputs/InputBaseProps.js +1 -1
  66. package/dist/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +1 -1
  67. package/dist/components/MaterialUI/Inputs/RadioProps.js +1 -1
  68. package/dist/components/MaterialUI/Inputs/Select.js +2 -2
  69. package/dist/components/MaterialUI/Inputs/SelectProps.js +1 -1
  70. package/dist/components/MaterialUI/Inputs/Switch.js +3 -3
  71. package/dist/components/MaterialUI/Inputs/SwitchProps.js +1 -1
  72. package/dist/components/MaterialUI/Inputs/TimePicker.js +19 -8
  73. package/dist/components/MaterialUI/Inputs/createInput.js +3 -3
  74. package/dist/components/MaterialUI/Inputs/index.js +1 -1
  75. package/dist/components/MaterialUI/Inputs/standaloneRadioProps.js +1 -1
  76. package/dist/components/MaterialUI/Navigation/DropDownMenuProps.js +1 -1
  77. package/dist/components/MaterialUI/Navigation/TabBar.js +38 -33
  78. package/dist/components/MaterialUI/ScopeSelector/ScopeSelector.js +6 -4
  79. package/dist/components/MaterialUI/ScopeSelector/ScopeTreeView.js +8 -4
  80. package/dist/components/MaterialUI/ScopeSelector/TreeItem.js +9 -6
  81. package/dist/components/MaterialUI/Surfaces/ExpansionPanel.js +11 -2
  82. package/dist/components/MaterialUI/Surfaces/SectionExpansionPanel.js +10 -2
  83. package/dist/components/MaterialUI/Surfaces/expansionPanelProps.js +5 -2
  84. package/dist/components/MaterialUI/Surfaces/paperProps.js +1 -1
  85. package/dist/components/MaterialUI/muiThemes.js +21 -6
  86. package/dist/components/MaterialUI/textProps.js +1 -1
  87. package/dist/components/Modules.js +24 -2
  88. package/dist/components/MultiSelector.js +1 -1
  89. package/dist/components/Navigation/Bar.js +3 -3
  90. package/dist/components/Navigation/Tab.js +1 -1
  91. package/dist/components/Navigation/useNavigationState.js +30 -4
  92. package/dist/components/Placeholder.js +1 -1
  93. package/dist/components/Routing/FullPage.js +2 -0
  94. package/dist/components/Routing/Segment.js +4 -3
  95. package/dist/components/Routing/SegmentPage.js +24 -11
  96. package/dist/components/Routing/withWaypointing.js +10 -4
  97. package/dist/components/Scope/ScopeNode.js +1 -1
  98. package/dist/components/Scope/Selector.js +1 -1
  99. package/dist/components/Scope/index.js +11 -3
  100. package/dist/components/Scope/useScopeSelect.js +1 -1
  101. package/dist/components/Selector.js +1 -1
  102. package/dist/components/Sidepanel.js +1 -2
  103. package/dist/components/Spritesheet.js +1 -1
  104. package/dist/components/Switch.js +1 -1
  105. package/dist/components/Text.js +1 -1
  106. package/dist/components/ToastList.js +1 -1
  107. package/dist/components/Toolbar.js +1 -1
  108. package/dist/components/Treeview/Label.js +1 -1
  109. package/dist/components/Treeview/Leaf.js +1 -1
  110. package/dist/components/Treeview/Node.js +3 -3
  111. package/dist/components/Treeview/index.js +2 -2
  112. package/dist/components/Treeview/settings.js +1 -1
  113. package/dist/constants.js +26 -1
  114. package/dist/content/icons/html-templates.svg +3 -0
  115. package/dist/content/iconsSheet.svg +3 -0
  116. package/dist/getThemeOverrides.js +2 -2
  117. package/dist/hocs/withInfiniteScroll.js +1 -1
  118. package/dist/hocs/withUpdateHandler.js +2 -2
  119. package/dist/hooks/useDispatchWithModulesData.js +1 -1
  120. package/dist/hooks/useEditState.js +3 -3
  121. package/dist/hooks/useEntityLoader.js +182 -0
  122. package/dist/hooks/useFullEntityEditState.js +3 -3
  123. package/dist/hooks/useInfiniteScroll.js +104 -0
  124. package/dist/hooks/useLabelMessage.js +3 -3
  125. package/dist/hooks/useLoader.js +1 -0
  126. package/dist/hooks/useMultipleFieldEditState.js +2 -2
  127. package/dist/hooks/useNavigationHandler.js +1 -1
  128. package/dist/hooks/useNotificationRequestState.js +159 -0
  129. package/dist/hooks/useRequestState.js +146 -0
  130. package/dist/hooks/useSelectorAndUnwrap.js +1 -1
  131. package/dist/reducers/metadata.js +52 -26
  132. package/dist/reducers/requestStates.js +181 -0
  133. package/dist/schemas/countries.js +1 -1
  134. package/dist/schemas/definitions.js +1 -1
  135. package/dist/schemas/metadata.js +1 -1
  136. package/dist/schemas/productDefinitions.js +1 -1
  137. package/dist/schemas/timezones.js +1 -1
  138. package/dist/selectors/applications.js +1 -1
  139. package/dist/selectors/authentication.js +1 -2
  140. package/dist/selectors/countries.js +1 -1
  141. package/dist/selectors/locale.js +1 -1
  142. package/dist/selectors/metadata.js +117 -17
  143. package/dist/selectors/navigation.js +1 -1
  144. package/dist/selectors/requestStates.js +82 -0
  145. package/dist/selectors/requests.js +1 -1
  146. package/dist/selectors/scope.js +2 -1
  147. package/dist/selectors/versionInfo.js +1 -1
  148. package/dist/selectors/view.js +1 -1
  149. package/dist/sharedMessages.js +44 -0
  150. package/dist/spawnerMiddleware.js +1 -1
  151. package/dist/utils/displayModeHelper.js +1 -1
  152. package/dist/utils/flatten.js +2 -2
  153. package/dist/utils/localizationHelper.js +1 -1
  154. package/dist/utils/mapHelper.js +1 -1
  155. package/dist/utils/modelValidationHelper.js +2 -2
  156. package/dist/utils/parseHelper.js +1 -1
  157. package/dist/utils/propertyHelper.js +2 -2
  158. package/dist/utils/propertyValidator.js +1 -1
  159. package/dist/utils/setTranslation.js +27 -1
  160. package/dist/utils/setTranslationWithFallback.js +33 -3
  161. package/dist/utils/testUtils.js +6 -2
  162. package/dist/utils/timezoneHelper.js +111 -0
  163. package/dist/utils/unwrapImmutable.js +1 -1
  164. package/dist/utils/urlHelper.js +11 -1
  165. package/package.json +3 -7
  166. package/src/actions/makeApiAction.js +24 -1
  167. package/src/actions/makeApiAction.test.js +76 -3
  168. package/src/actions/metadata.js +130 -0
  169. package/src/actions/metadata.test.js +337 -5
  170. package/src/actions/requestState.js +8 -0
  171. package/src/actions/requestState.test.js +14 -0
  172. package/src/actions/requestsApi.js +30 -0
  173. package/src/buildStore.js +2 -0
  174. package/src/components/AppFrame/AppFrame.test.js +6 -16
  175. package/src/components/AppFrame/ApplicationSelector/ApplicationDialog.js +105 -82
  176. package/src/components/AppFrame/ApplicationSelector/ApplicationDialog.test.js +60 -23
  177. package/src/components/AppFrame/ApplicationSelector/ApplicationSelector.test.js +22 -89
  178. package/src/components/AppFrame/ApplicationSelector/index.js +34 -15
  179. package/src/components/AppFrame/Topbar.test.js +2 -4
  180. package/src/components/MaterialUI/DataDisplay/SelectionList.js +14 -6
  181. package/src/components/MaterialUI/DataDisplay/SelectionList.test.js +21 -11
  182. package/src/components/MaterialUI/DataDisplay/Table.js +29 -5
  183. package/src/components/MaterialUI/DataDisplay/Table.test.js +23 -0
  184. package/src/components/MaterialUI/DataDisplay/TableProps.js +2 -0
  185. package/src/components/MaterialUI/DataDisplay/TableProps.test.js +2 -0
  186. package/src/components/MaterialUI/DataDisplay/TransferList.js +3 -0
  187. package/src/components/MaterialUI/Inputs/DatePicker.js +11 -0
  188. package/src/components/MaterialUI/Inputs/InputBase.js +3 -1
  189. package/src/components/MaterialUI/Inputs/InputBase.test.js +38 -0
  190. package/src/components/MaterialUI/Inputs/TimePicker.js +9 -3
  191. package/src/components/MaterialUI/Inputs/TimePicker.test.js +263 -118
  192. package/src/components/MaterialUI/Navigation/TabBar.js +82 -78
  193. package/src/components/MaterialUI/Navigation/TabBar.test.js +129 -3
  194. package/src/components/MaterialUI/ScopeSelector/ScopeSelector.js +4 -2
  195. package/src/components/MaterialUI/ScopeSelector/ScopeSelector.test.js +29 -0
  196. package/src/components/MaterialUI/ScopeSelector/ScopeTreeView.js +4 -1
  197. package/src/components/MaterialUI/ScopeSelector/ScopeTreeView.test.js +52 -0
  198. package/src/components/MaterialUI/ScopeSelector/TreeItem.js +9 -6
  199. package/src/components/MaterialUI/ScopeSelector/TreeItem.test.js +63 -2
  200. package/src/components/MaterialUI/Surfaces/ExpansionPanel.js +14 -1
  201. package/src/components/MaterialUI/Surfaces/ExpansionPanel.test.js +16 -0
  202. package/src/components/MaterialUI/Surfaces/SectionExpansionPanel.js +11 -2
  203. package/src/components/MaterialUI/Surfaces/SectionExpansionPanel.test.js +36 -0
  204. package/src/components/MaterialUI/Surfaces/expansionPanelProps.js +2 -0
  205. package/src/components/MaterialUI/Surfaces/expansionPanelProps.test.js +2 -2
  206. package/src/components/MaterialUI/muiThemes.js +18 -3
  207. package/src/components/Modules.js +13 -1
  208. package/src/components/Modules.test.js +133 -1
  209. package/src/components/Navigation/Navigation.test.js +2 -0
  210. package/src/components/Navigation/useNavigationState.js +21 -1
  211. package/src/components/Navigation/useNavigationState.test.js +10 -0
  212. package/src/components/Routing/FullPage.js +2 -1
  213. package/src/components/Routing/FullPage.test.js +149 -79
  214. package/src/components/Routing/Segment.js +5 -2
  215. package/src/components/Routing/Segment.test.js +22 -1
  216. package/src/components/Routing/SegmentPage.js +19 -9
  217. package/src/components/Routing/SubPage.test.js +1 -1
  218. package/src/components/Routing/withWaypointing.js +19 -17
  219. package/src/components/Routing/withWaypointing.test.js +50 -0
  220. package/src/components/Scope/Scope.test.js +117 -0
  221. package/src/components/Scope/index.js +6 -10
  222. package/src/components/Sidepanel.js +0 -1
  223. package/src/components/Sidepanel.test.js +0 -3
  224. package/src/constants.js +18 -0
  225. package/src/content/icons/html-templates.svg +3 -0
  226. package/src/content/iconsSheet.svg +3 -0
  227. package/src/hooks/useEntityLoader.js +68 -0
  228. package/src/hooks/useEntityLoader.test.js +266 -0
  229. package/src/hooks/useInfiniteScroll.js +25 -0
  230. package/src/hooks/useInfiniteScroll.test.js +87 -0
  231. package/src/hooks/useLoader.js +1 -0
  232. package/src/hooks/useNotificationRequestState.js +78 -0
  233. package/src/hooks/useNotificationRequestState.test.js +264 -0
  234. package/src/hooks/useRequestState.js +57 -0
  235. package/src/hooks/useRequestState.test.js +217 -0
  236. package/src/reducers/metadata.js +76 -16
  237. package/src/reducers/metadata.test.js +458 -4
  238. package/src/reducers/requestStates.js +98 -0
  239. package/src/reducers/requestStates.test.js +399 -0
  240. package/src/selectors/authentication.js +0 -1
  241. package/src/selectors/locale.test.js +0 -2
  242. package/src/selectors/metadata.js +90 -19
  243. package/src/selectors/metadata.test.js +532 -123
  244. package/src/selectors/requestStates.js +12 -0
  245. package/src/selectors/requestStates.test.js +83 -0
  246. package/src/selectors/scope.js +1 -1
  247. package/src/sharedMessages.js +44 -0
  248. package/src/translations/en-US.json +12 -1
  249. package/src/translations/fr-CA.json +13 -2
  250. package/src/utils/modelValidationHelper.js +1 -1
  251. package/src/utils/setTranslation.js +16 -1
  252. package/src/utils/setTranslation.test.js +24 -0
  253. package/src/utils/setTranslationWithFallback.js +19 -2
  254. package/src/utils/setTranslationWithFallback.test.js +104 -6
  255. package/src/utils/testUtils.js +3 -1
  256. package/src/utils/timezoneHelper.js +140 -0
  257. package/src/utils/timezoneHelper.test.js +33 -0
  258. package/src/utils/urlHelper.js +6 -0
  259. package/src/translations/it-IT.json +0 -54
@@ -12,6 +12,7 @@ import { mount } from "enzyme";
12
12
 
13
13
  describe("TreeItem", () => {
14
14
  let store, state;
15
+ const closeSelectorSpy = sinon.spy();
15
16
 
16
17
  beforeEach(() => {
17
18
  state = Immutable.fromJS({
@@ -32,6 +33,10 @@ describe("TreeItem", () => {
32
33
  };
33
34
  });
34
35
 
36
+ afterEach(() => {
37
+ closeSelectorSpy.resetHistory();
38
+ });
39
+
35
40
  const globalScope = {
36
41
  id: "Global",
37
42
  name: "Global",
@@ -59,8 +64,6 @@ describe("TreeItem", () => {
59
64
 
60
65
  const theme = createMuiTheme();
61
66
 
62
- const closeSelectorSpy = sinon.spy();
63
-
64
67
  it("Renders Tree Item correctly for global scope", () => {
65
68
  const expectedGlobalLabel = (
66
69
  <ScopeLabel name={globalScope.name} type={globalScope.type} isRootScope={true} isVirtualScope={false} />
@@ -151,6 +154,64 @@ describe("TreeItem", () => {
151
154
  expect(preventDefaultSpy, "was called once");
152
155
  expect(closeSelectorSpy, "to have no calls satisfying", { args: [event] });
153
156
  });
157
+
158
+ it("Does not calls scope select handler on label click if isScopeSelectable is defined and returns false", () => {
159
+ const isScopeSelectableSpy = sinon.spy(() => false).named("isScopeSelectable");
160
+ const component = (
161
+ <TestWrapper provider={{ store }} memoryRouter stylesProvider muiThemeProvider={{ theme }}>
162
+ <TreeItem
163
+ scope={saleScope}
164
+ rootId={rootId}
165
+ onScopeSelect={closeSelectorSpy}
166
+ isScopeSelectable={isScopeSelectableSpy}
167
+ />
168
+ </TestWrapper>
169
+ );
170
+
171
+ const preventDefaultSpy = sinon.spy();
172
+
173
+ const mountedComponent = mount(component);
174
+
175
+ const saleScopeLabel = mountedComponent.find(TreeItemMui);
176
+
177
+ const event = {
178
+ preventDefault: preventDefaultSpy,
179
+ };
180
+
181
+ saleScopeLabel.invoke("onLabelClick")(event);
182
+
183
+ expect(preventDefaultSpy, "was called");
184
+ expect(closeSelectorSpy, "was not called");
185
+ });
186
+
187
+ it("Calls scope select handler on label click if isScopeSelectable is defined and returns true", () => {
188
+ const isScopeSelectableSpy = sinon.spy(() => true).named("isScopeSelectable");
189
+ const component = (
190
+ <TestWrapper provider={{ store }} memoryRouter stylesProvider muiThemeProvider={{ theme }}>
191
+ <TreeItem
192
+ scope={saleScope}
193
+ rootId={rootId}
194
+ onScopeSelect={closeSelectorSpy}
195
+ isScopeSelectable={isScopeSelectableSpy}
196
+ />
197
+ </TestWrapper>
198
+ );
199
+
200
+ const preventDefaultSpy = sinon.spy();
201
+
202
+ const mountedComponent = mount(component);
203
+
204
+ const saleScopeLabel = mountedComponent.find(TreeItemMui);
205
+
206
+ const event = {
207
+ preventDefault: preventDefaultSpy,
208
+ };
209
+
210
+ saleScopeLabel.invoke("onLabelClick")(event);
211
+
212
+ expect(preventDefaultSpy, "was called");
213
+ expect(closeSelectorSpy, "to have no calls satisfying", { args: [event] });
214
+ });
154
215
  });
155
216
 
156
217
  describe("ScopeLabel", () => {
@@ -29,6 +29,13 @@ const useStyles = makeStyles(theme => ({
29
29
  width: theme.spacing(1),
30
30
  },
31
31
  headerPanelExpanded: {},
32
+ constrainedSummaryRoot: {
33
+ overflowX: "auto",
34
+ overflowY: "hidden",
35
+ },
36
+ constrainedSummaryContent: {
37
+ minWidth: theme.spacing(83),
38
+ },
32
39
  }));
33
40
 
34
41
  const ExpansionPanel = ({ header, content, actions, expansionPanelProps, expansionPanelActionsProps }) => {
@@ -45,6 +52,7 @@ const ExpansionPanel = ({ header, content, actions, expansionPanelProps, expansi
45
52
  // Expansion panel props
46
53
  const disabled = expansionPanelProps?.get(ExpansionPanelProps.propNames.disabled);
47
54
  const defaultExpanded = expansionPanelProps?.get(ExpansionPanelProps.propNames.defaultExpanded) ?? true;
55
+ const constrained = expansionPanelProps?.get(ExpansionPanelProps.propNames.constrained) || false;
48
56
 
49
57
  const [expanded, setExpanded] = React.useState(defaultExpanded);
50
58
 
@@ -76,7 +84,12 @@ const ExpansionPanel = ({ header, content, actions, expansionPanelProps, expansi
76
84
  <AccordionSummary
77
85
  expandIcon={<Icon id="chevron-down" className={classes.expandIcon} />}
78
86
  classes={{
79
- root: classNames(classes.expansionPanelHeader, panelSummaryRootStyle),
87
+ root: classNames(
88
+ classes.expansionPanelHeader,
89
+ panelSummaryRootStyle,
90
+ constrained ? classes.constrainedSummaryRoot : "",
91
+ ),
92
+ content: classNames(constrained ? classes.constrainedSummaryContent : ""),
80
93
  expanded: classNames(classes.headerPanelExpanded, panelSummaryExpandedStyle),
81
94
  }}
82
95
  >
@@ -178,6 +178,22 @@ describe("Expansion Panel", () => {
178
178
  expect(mountedComponent.exists(".MuiAccordionActions-spacing"), "to be truthy");
179
179
  });
180
180
 
181
+ it("Classes are added properly when constrained property of expansionPanelProps is true", () => {
182
+ const expansionPanelProps = new ExpansionPanelProps();
183
+ expansionPanelProps.set(ExpansionPanelProps.propNames.constrained, true);
184
+
185
+ const component = (
186
+ <MuiThemeProvider theme={createMuiTheme()}>
187
+ <ExpansionPanel expansionPanelProps={expansionPanelProps} />
188
+ </MuiThemeProvider>
189
+ );
190
+
191
+ const mountedComponent = mount(component);
192
+
193
+ expect(mountedComponent.exists(".makeStyles-constrainedSummaryRoot-49"), "to be truthy");
194
+ expect(mountedComponent.exists(".makeStyles-constrainedSummaryContent-50"), "to be truthy");
195
+ });
196
+
181
197
  it("DisableSpacing value for disabled property is correct if expansionPanelActionsProps was passed without setting that", () => {
182
198
  const actions = <p>Actions</p>;
183
199
  const expansionPanelActionsProps = new ExpansionPanelActionsProps();
@@ -52,6 +52,13 @@ const useStyles = makeStyles(theme => ({
52
52
  color: theme.palette.grey.darker,
53
53
  minWidth: "auto",
54
54
  },
55
+ constrainedSummaryRoot: {
56
+ overflowX: "auto",
57
+ overflowY: "hidden",
58
+ },
59
+ constrainedSummaryContent: {
60
+ minWidth: theme.spacing(83),
61
+ },
55
62
  }));
56
63
 
57
64
  const SectionExpansionPanel = ({
@@ -97,6 +104,8 @@ const SectionExpansionPanel = ({
97
104
  // Expansion panel actions props
98
105
  const disableSpacing = expansionPanelActionsProps?.get(ExpansionPanelActionsProps.propNames.disableSpacing);
99
106
 
107
+ const constrained = expansionPanelProps?.get(ExpansionPanelProps.propNames.constrained) || false;
108
+
100
109
  return (
101
110
  <Accordion
102
111
  defaultExpanded={defaultExpanded}
@@ -112,9 +121,9 @@ const SectionExpansionPanel = ({
112
121
  expandIcon={<Icon id="dropdown-chevron-down" />}
113
122
  IconButtonProps={defaultSummaryStyles}
114
123
  classes={{
115
- root: classNames(classes.summaryRoot),
124
+ root: classNames(classes.summaryRoot, constrained ? classes.constrainedSummaryRoot : ""),
116
125
  expanded: classNames(classes.panelExpanded),
117
- content: classNames(classes.summaryContent),
126
+ content: classNames(classes.summaryContent, constrained ? classes.constrainedSummaryContent : ""),
118
127
  expandIcon: classNames(classes.summaryExpandIconRoot),
119
128
  }}
120
129
  >
@@ -231,6 +231,42 @@ describe("Section Expansion Panel", () => {
231
231
  expect(mountedComponent.exists(".MuiAccordionActions-spacing"), "to be truthy");
232
232
  });
233
233
 
234
+ it("Uses expansionPanelProps.constrained correctly", () => {
235
+ const expansionPanelProps = new ExpansionPanelProps();
236
+
237
+ expansionPanelProps.set(ExpansionPanelProps.propNames.constrained, true);
238
+
239
+ const component = (
240
+ <Provider store={store(state)}>
241
+ <MuiThemeProvider theme={createMuiTheme()}>
242
+ <SectionExpansionPanel expansionPanelProps={expansionPanelProps} />
243
+ </MuiThemeProvider>
244
+ </Provider>
245
+ );
246
+
247
+ const mountedComponent = mount(component);
248
+
249
+ expect(mountedComponent.exists(".makeStyles-constrainedSummaryRoot-87"), "to be truthy");
250
+ expect(mountedComponent.exists(".makeStyles-constrainedSummaryContent-88"), "to be truthy");
251
+ });
252
+
253
+ it("Default value for constrained property is correct if expansionPanelProps was passed without setting that", () => {
254
+ const expansionPanelProps = new ExpansionPanelProps();
255
+
256
+ const component = (
257
+ <Provider store={store(state)}>
258
+ <MuiThemeProvider theme={createMuiTheme()}>
259
+ <SectionExpansionPanel expansionPanelProps={expansionPanelProps} />
260
+ </MuiThemeProvider>
261
+ </Provider>
262
+ );
263
+
264
+ const mountedComponent = mount(component);
265
+
266
+ expect(mountedComponent.exists(".makeStyles-constrainedSummaryRoot-96"), "to be falsy");
267
+ expect(mountedComponent.exists(".makeStyles-constrainedSummaryContent-97"), "to be falsy");
268
+ });
269
+
234
270
  it("handles internal on change function", () => {
235
271
  const header = <p>Header</p>;
236
272
  const content = <p>Content</p>;
@@ -6,6 +6,7 @@ class ExpansionPanelProps extends ComponentProps {
6
6
  disabled: "disabled",
7
7
  expanded: "expanded",
8
8
  onChange: "onChange",
9
+ constrained: "constrained",
9
10
  };
10
11
 
11
12
  static ruleNames = {
@@ -22,6 +23,7 @@ class ExpansionPanelProps extends ComponentProps {
22
23
  this.componentProps.set(this.constructor.propNames.disabled, null);
23
24
  this.componentProps.set(this.constructor.propNames.expanded, null);
24
25
  this.componentProps.set(this.constructor.propNames.onChange, null);
26
+ this.componentProps.set(this.constructor.propNames.constrained, false);
25
27
 
26
28
  this.componentClasses.set(this.constructor.ruleNames.root, null);
27
29
  this.componentClasses.set(this.constructor.ruleNames.summaryRoot, null);
@@ -7,7 +7,7 @@ import {
7
7
 
8
8
  describe("Expansion Panel Props", () => {
9
9
  it("Contains necessary prop and rule keys", () => {
10
- const propNames = ["defaultExpanded", "disabled", "expanded", "onChange"];
10
+ const propNames = ["defaultExpanded", "disabled", "expanded", "onChange", "constrained"];
11
11
  const rulesNames = ["root", "summaryRoot", "summaryExpanded", "details", "actions"];
12
12
 
13
13
  expect(ExpansionPanelProps.propNames, "to have keys", propNames);
@@ -15,7 +15,7 @@ describe("Expansion Panel Props", () => {
15
15
  });
16
16
 
17
17
  it("Puts keys in component prop and rule maps", () => {
18
- const propNames = ["defaultExpanded", "disabled", "expanded", "onChange"];
18
+ const propNames = ["defaultExpanded", "disabled", "expanded", "onChange", "constrained"];
19
19
  const rulesNames = ["root", "summaryRoot", "summaryExpanded", "details", "actions"];
20
20
 
21
21
  const expansionPanelProps = new ExpansionPanelProps();
@@ -94,6 +94,7 @@ const commonPalette = {
94
94
  default: "#FFF",
95
95
  tabs: "#EFEFEF",
96
96
  app: "#333",
97
+ selectedDate: "#216BA5",
97
98
  },
98
99
  action: {
99
100
  disabledBackground: "#EFEFEF",
@@ -979,9 +980,6 @@ const setThemeOverrides = theme => ({
979
980
  left: theme.spacing(-2.1),
980
981
  width: theme.spacing(2),
981
982
  },
982
- "&.Mui-expanded:before": {
983
- width: theme.spacing(1.5),
984
- },
985
983
  },
986
984
  label: {
987
985
  ...theme.label,
@@ -1027,6 +1025,23 @@ const setThemeOverrides = theme => ({
1027
1025
  "& svg": {
1028
1026
  fontSize: "10px",
1029
1027
  },
1028
+ "&:before": {
1029
+ content: `" "`,
1030
+ position: "absolute",
1031
+ height: theme.spacing(0.1),
1032
+ width: theme.spacing(0.5),
1033
+ left: theme.spacing(-0.5),
1034
+ backgroundColor: theme.palette.grey.light,
1035
+ top: theme.spacing(1.1),
1036
+ },
1037
+ "&:empty": {
1038
+ width: theme.spacing(1),
1039
+ "&:before": {
1040
+ backgroundColor: "transparent",
1041
+ borderTop: `1px solid ${theme.palette.grey.icon}`,
1042
+ width: theme.spacing(1.5),
1043
+ },
1044
+ },
1030
1045
  },
1031
1046
  },
1032
1047
  MuiTimeline: {
@@ -3,7 +3,7 @@ import { useHistory, useLocation } from "react-router-dom";
3
3
  import { useSelector, useDispatch } from "react-redux";
4
4
  import { Route, Switch, Redirect } from "react-router-dom";
5
5
  import withErrorBoundary from "../hocs/withErrorBoundary";
6
- import { getCurrentScope } from "../selectors/navigation";
6
+ import { getCurrentScope, selectRouteHref } from "../selectors/navigation";
7
7
  import { isCurrentScopeAuthorizedSelector } from "../selectors/scope";
8
8
  import Navigation from "./Navigation";
9
9
  import FullPage from "./Routing/FullPage";
@@ -12,6 +12,18 @@ import { setModulesStructure } from "../actions/modules";
12
12
  import { defaultScopeSelector } from "../selectors/settings";
13
13
 
14
14
  export const Module = withErrorBoundary("Module")(({ config, path, error, location, match, modulePrependPath }) => {
15
+ const currentRoute = useSelector(selectRouteHref);
16
+ const history = useHistory();
17
+ let hideSelector = state => (typeof config.hide === "function" ? config.hide(state) : config.hide ?? false);
18
+ const isHidden = useSelector(hideSelector);
19
+
20
+ React.useEffect(() => {
21
+ if (isHidden === true && currentRoute.includes(match.url)) {
22
+ history.push("/");
23
+ }
24
+ // eslint-disable-next-line react-hooks/exhaustive-deps
25
+ }, [isHidden, currentRoute, match.url]);
26
+
15
27
  return (
16
28
  <FullPage path={path} config={config} location={location} match={match} modulePrependPath={modulePrependPath} />
17
29
  );
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import Immutable from "immutable";
3
3
  import { mount } from "unexpected-reaction";
4
4
  import SegmentPage from "./Routing/SegmentPage";
5
- import { Modules } from "./Modules";
5
+ import { Modules, Module } from "./Modules";
6
6
  import TabBar from "./MaterialUI/Navigation/TabBar";
7
7
  import { TestWrapper, createMuiTheme } from "./../utils/testUtils";
8
8
  import sinon from "sinon";
@@ -438,3 +438,135 @@ describe("Modules", () => {
438
438
  });
439
439
  });
440
440
  });
441
+
442
+ 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
+ };
450
+
451
+ let history, pushSpy;
452
+ beforeAll(() => {
453
+ history = createMemoryHistory({ initialEntries: ["/TestScope/demos"] });
454
+ pushSpy = sinon.spy(history, "push");
455
+ history.push.named("history.push");
456
+ });
457
+
458
+ beforeEach(() => {
459
+ config = {
460
+ label: "Module 1",
461
+ icon: "user",
462
+ hide: true,
463
+ segments: {
464
+ "/page1": {
465
+ component: Page1,
466
+ label: "Page 1",
467
+ },
468
+ },
469
+ };
470
+ state = Immutable.fromJS({
471
+ navigation: {
472
+ tabIndex: {},
473
+ moduleTabs: {},
474
+ mappedHrefs: {},
475
+ route: {
476
+ match: match,
477
+ },
478
+ config: { prependPath: "/:scope/", prependHref: "/TestScope/" },
479
+ },
480
+ router: {
481
+ location: {},
482
+ },
483
+ modules: {
484
+ tree: {},
485
+ },
486
+ view: {
487
+ edit: {
488
+ users: {},
489
+ photos: {},
490
+ demos: {},
491
+ },
492
+ },
493
+ requests: {
494
+ logout: false,
495
+ },
496
+ settings: {
497
+ defaultScope: "myScope",
498
+ },
499
+ scopes: {
500
+ TestScope: {
501
+ id: "TestScope",
502
+ name: { "en-CA": "Test 1" },
503
+ foo: false,
504
+ bar: false,
505
+ children: ["test2"],
506
+ isAuthorizedScope: true,
507
+ },
508
+ },
509
+ locale: {
510
+ locale: null,
511
+ supportedLocales: [
512
+ { language: "English", cultureIso: "en-US" },
513
+ { language: "Francais", cultureIso: "fr" },
514
+ ],
515
+ },
516
+ });
517
+ store = {
518
+ subscribe: () => {},
519
+ dispatch: () => {},
520
+ getState: () => state,
521
+ };
522
+ });
523
+
524
+ const theme = createMuiTheme();
525
+
526
+ it("Calls pushes to root when unauthorized user trying to access hidden module", () => {
527
+ //config.hide = false;
528
+ const component = (
529
+ <TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
530
+ <Module config={config} match={match} path={match.path} location={{}} />
531
+ </TestWrapper>
532
+ );
533
+
534
+ mount(component);
535
+
536
+ expect(history.push, "to have calls satisfying", [{ args: ["/"] }]);
537
+
538
+ pushSpy.resetHistory();
539
+ });
540
+
541
+ it("Calls pushes to root when unauthorized user trying to access hidden module and hide property is a function which retrieves false", () => {
542
+ config.hide = () => false;
543
+
544
+ const component = (
545
+ <TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
546
+ <Module config={config} match={match} path={match.path} location={{}} />
547
+ </TestWrapper>
548
+ );
549
+
550
+ mount(component);
551
+
552
+ expect(history.push, "not to have calls satisfying", [{ args: ["/"] }]);
553
+
554
+ pushSpy.resetHistory();
555
+ });
556
+
557
+ it("Calls pushes to root when unauthorized user trying to access hidden module and hide property is a function which retrieves true", () => {
558
+ config.hide = () => true;
559
+
560
+ const component = (
561
+ <TestWrapper provider={{ store }} router={{ history }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
562
+ <Module config={config} match={match} path={match.path} location={{}} />
563
+ </TestWrapper>
564
+ );
565
+
566
+ mount(component);
567
+
568
+ expect(history.push, "to have calls satisfying", [{ args: ["/"] }]);
569
+
570
+ pushSpy.resetHistory();
571
+ });
572
+ });
@@ -113,12 +113,14 @@ describe("Navigation", () => {
113
113
  href: "/TestScope/test/page1",
114
114
  active: true,
115
115
  params: { scope: "TestScope", entityId: "page1" },
116
+ path: "/:scope/test/:entityId",
116
117
  },
117
118
  {
118
119
  label: "Page 2",
119
120
  href: "/TestScope/test/page2",
120
121
  active: false,
121
122
  params: { scope: "TestScope", entityId: "page2" },
123
+ path: "/:scope/test/:entityId",
122
124
  },
123
125
  ];
124
126
 
@@ -25,7 +25,7 @@ const doesRestPathMatchParams = (params, paramPathSplit, restPath) => {
25
25
  };
26
26
 
27
27
  const getPageWithSplitPath = ([pathStep, ...restPath], params, pages) => {
28
- let page = pages[pathStep];
28
+ let page = getPageFromPathSteps(pages, pathStep);
29
29
  if (!page) {
30
30
  const paramPath =
31
31
  // Only one should exist
@@ -62,6 +62,25 @@ const getPageWithSplitPath = ([pathStep, ...restPath], params, pages) => {
62
62
  }
63
63
  };
64
64
 
65
+ const getPageFromPathSteps = (pages, pathStep) => {
66
+ let page = pages[pathStep];
67
+ if (page) {
68
+ return page;
69
+ }
70
+
71
+ const rx = /^\/:[^(]+\(([^/]+?)\)/;
72
+
73
+ for (const key of Object.keys(pages)) {
74
+ const matches = key.match(rx);
75
+ if (matches !== null) {
76
+ if (new RegExp(matches[1]).test(pathStep)) {
77
+ return pages[key];
78
+ }
79
+ }
80
+ }
81
+ return undefined;
82
+ };
83
+
65
84
  const redirectScopeWhenRequired = (isPageTab, pageScopeSelector, rawPage, currentScope, scopeDefinitionGetter) => {
66
85
  const params = rawPage.params || {};
67
86
  const scopeChanged = params.scope && params.scope !== currentScope;
@@ -195,6 +214,7 @@ export const useNavigationState = modules => {
195
214
  outsideScope: isPageTab ? outsideScope : null,
196
215
  scopeNotSupported: isPageTab ? pageScopeSelector != null && outsideScope : null,
197
216
  label,
217
+ entityIdResolver: pageData.entityIdResolver,
198
218
  mustTruncate: pageData.mustTruncate,
199
219
  href,
200
220
  mappedFrom: page.href,
@@ -1339,6 +1339,10 @@ describe("getPageData", () => {
1339
1339
  label: "Page 5",
1340
1340
  component: TestComp9,
1341
1341
  },
1342
+ "/:var3(def\\d{1,3})": {
1343
+ label: "Page 6",
1344
+ component: TestComp7,
1345
+ },
1342
1346
  },
1343
1347
  };
1344
1348
  });
@@ -1374,6 +1378,12 @@ describe("getPageData", () => {
1374
1378
  component: TestComp9,
1375
1379
  }));
1376
1380
 
1381
+ it("handles variable path steps which uses 'path to regex' with multiple pages", () =>
1382
+ expect(getPageData, "when called with", ["/def666", { var3: "def666" }, module3], "to satisfy", {
1383
+ label: "Page 6",
1384
+ component: TestComp7,
1385
+ }));
1386
+
1377
1387
  it("handles multiple variable path steps", () =>
1378
1388
  expect(
1379
1389
  getPageData,
@@ -3,12 +3,13 @@ import Page from "./Page";
3
3
  import SegmentPage from "./SegmentPage";
4
4
 
5
5
  const FullPage = ({ path, config, location, match, modulePrependPath }) => {
6
- const { component, pages = {}, segments, subpages, entityIdResolver } = config;
6
+ const { component, componentProps, pages = {}, segments, subpages, entityIdResolver } = config;
7
7
  if (segments) {
8
8
  return (
9
9
  <SegmentPage
10
10
  path={path}
11
11
  component={component}
12
+ componentProps={componentProps ?? {}}
12
13
  segments={segments}
13
14
  location={location}
14
15
  match={match}