orc-shared 1.1.0-dev.9 → 1.2.0-dev.10

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 (309) 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/modules.js +63 -1
  9. package/dist/actions/navigation.js +3 -3
  10. package/dist/actions/requestState.js +78 -0
  11. package/dist/actions/requestsApi.js +58 -7
  12. package/dist/actions/scopes.js +59 -22
  13. package/dist/actions/timezones.js +1 -1
  14. package/dist/actions/toasts.js +1 -1
  15. package/dist/actions/versionInfo.js +1 -1
  16. package/dist/actions/view.js +1 -1
  17. package/dist/buildStore.js +7 -4
  18. package/dist/components/AppFrame/About.js +6 -5
  19. package/dist/components/AppFrame/ApplicationSelector/ApplicationDialog.js +115 -62
  20. package/dist/components/AppFrame/ApplicationSelector/index.js +45 -47
  21. package/dist/components/AppFrame/MenuItem.js +6 -15
  22. package/dist/components/AppFrame/Preferences.js +3 -3
  23. package/dist/components/AppFrame/Sidebar.js +20 -9
  24. package/dist/components/AppFrame/Topbar.js +1 -1
  25. package/dist/components/ApplicationModuleLoader.js +143 -0
  26. package/dist/components/Authenticate.js +13 -13
  27. package/dist/components/CategoryList.js +1 -1
  28. package/dist/components/Checkbox.js +1 -1
  29. package/dist/components/DropMenu/Menu.js +1 -1
  30. package/dist/components/DropMenu/index.js +1 -1
  31. package/dist/components/Form/FieldList.js +3 -3
  32. package/dist/components/Form/Form.js +1 -1
  33. package/dist/components/Form/Inputs/Button.js +1 -1
  34. package/dist/components/Form/Inputs/FieldButtons.js +1 -1
  35. package/dist/components/Form/Inputs/Number.js +1 -1
  36. package/dist/components/Form/Inputs/ReadOnly.js +1 -1
  37. package/dist/components/Form/Inputs/SmallButton.js +1 -1
  38. package/dist/components/Form/Inputs/Text.js +1 -1
  39. package/dist/components/Form/Inputs/Time.js +1 -1
  40. package/dist/components/Form/Inputs/Toggles.js +1 -1
  41. package/dist/components/Form/Inputs/Translation.js +3 -3
  42. package/dist/components/List/HeadCell.js +1 -1
  43. package/dist/components/List/List.js +1 -1
  44. package/dist/components/List/Row.js +1 -1
  45. package/dist/components/List/enhanceColumnDefs.js +2 -2
  46. package/dist/components/MaterialUI/DataDisplay/List.js +1 -1
  47. package/dist/components/MaterialUI/DataDisplay/Notification.js +2 -2
  48. package/dist/components/MaterialUI/DataDisplay/NotificationProps.js +1 -1
  49. package/dist/components/MaterialUI/DataDisplay/PredefinedElements/Translations.js +3 -3
  50. package/dist/components/MaterialUI/DataDisplay/SelectionList.js +19 -6
  51. package/dist/components/MaterialUI/DataDisplay/Table.js +28 -10
  52. package/dist/components/MaterialUI/DataDisplay/TableProps.js +5 -2
  53. package/dist/components/MaterialUI/DataDisplay/TransferList.js +5 -2
  54. package/dist/components/MaterialUI/DataDisplay/chipProps.js +1 -1
  55. package/dist/components/MaterialUI/DataDisplay/collapsableListProps.js +1 -1
  56. package/dist/components/MaterialUI/DataDisplay/dividerProps.js +1 -1
  57. package/dist/components/MaterialUI/DataDisplay/index.js +1 -1
  58. package/dist/components/MaterialUI/DataDisplay/modalProps.js +1 -1
  59. package/dist/components/MaterialUI/DataDisplay/useTableSelection.js +3 -3
  60. package/dist/components/MaterialUI/Feedback/useNotification.js +1 -1
  61. package/dist/components/MaterialUI/Inputs/Autocomplete.js +2 -2
  62. package/dist/components/MaterialUI/Inputs/AutocompleteProps.js +1 -1
  63. package/dist/components/MaterialUI/Inputs/CheckboxGroupProps.js +1 -1
  64. package/dist/components/MaterialUI/Inputs/CheckboxProps.js +1 -1
  65. package/dist/components/MaterialUI/Inputs/DatePicker.js +11 -0
  66. package/dist/components/MaterialUI/Inputs/InputBase.js +3 -2
  67. package/dist/components/MaterialUI/Inputs/InputBaseProps.js +1 -1
  68. package/dist/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +1 -1
  69. package/dist/components/MaterialUI/Inputs/RadioProps.js +1 -1
  70. package/dist/components/MaterialUI/Inputs/Select.js +2 -2
  71. package/dist/components/MaterialUI/Inputs/SelectProps.js +1 -1
  72. package/dist/components/MaterialUI/Inputs/Switch.js +3 -3
  73. package/dist/components/MaterialUI/Inputs/SwitchProps.js +1 -1
  74. package/dist/components/MaterialUI/Inputs/TimePicker.js +19 -8
  75. package/dist/components/MaterialUI/Inputs/createInput.js +3 -3
  76. package/dist/components/MaterialUI/Inputs/index.js +1 -1
  77. package/dist/components/MaterialUI/Inputs/standaloneRadioProps.js +1 -1
  78. package/dist/components/MaterialUI/Navigation/DropDownMenuProps.js +1 -1
  79. package/dist/components/MaterialUI/Navigation/ExternalLink.js +113 -0
  80. package/dist/components/MaterialUI/Navigation/TabBar.js +38 -33
  81. package/dist/components/MaterialUI/ScopeSelector/ScopeSelector.js +6 -4
  82. package/dist/components/MaterialUI/ScopeSelector/ScopeTreeView.js +8 -4
  83. package/dist/components/MaterialUI/ScopeSelector/TreeItem.js +9 -6
  84. package/dist/components/MaterialUI/Surfaces/ExpansionPanel.js +11 -2
  85. package/dist/components/MaterialUI/Surfaces/SectionExpansionPanel.js +10 -2
  86. package/dist/components/MaterialUI/Surfaces/expansionPanelProps.js +5 -2
  87. package/dist/components/MaterialUI/Surfaces/paperProps.js +1 -1
  88. package/dist/components/MaterialUI/muiThemes.js +26 -6
  89. package/dist/components/MaterialUI/textProps.js +1 -1
  90. package/dist/components/Modules.js +132 -25
  91. package/dist/components/MultiSelector.js +1 -1
  92. package/dist/components/Navigation/Bar.js +3 -3
  93. package/dist/components/Navigation/Tab.js +1 -1
  94. package/dist/components/Navigation/useNavigationState.js +30 -4
  95. package/dist/components/Placeholder.js +1 -1
  96. package/dist/components/Routing/FullPage.js +5 -1
  97. package/dist/components/Routing/Page.js +5 -3
  98. package/dist/components/Routing/Segment.js +4 -3
  99. package/dist/components/Routing/SegmentPage.js +8 -6
  100. package/dist/components/Routing/withWaypointing.js +14 -4
  101. package/dist/components/Scope/ScopeNode.js +1 -1
  102. package/dist/components/Scope/Selector.js +1 -1
  103. package/dist/components/Scope/index.js +11 -3
  104. package/dist/components/Scope/useScopeConfirmationModalState.js +7 -16
  105. package/dist/components/Scope/useScopeData.js +4 -13
  106. package/dist/components/Scope/useScopeSelect.js +1 -1
  107. package/dist/components/Selector.js +1 -1
  108. package/dist/components/Sidepanel.js +1 -2
  109. package/dist/components/Spritesheet.js +1 -1
  110. package/dist/components/Switch.js +1 -1
  111. package/dist/components/Text.js +1 -1
  112. package/dist/components/ToastList.js +1 -1
  113. package/dist/components/Toolbar.js +1 -1
  114. package/dist/components/Treeview/Label.js +1 -1
  115. package/dist/components/Treeview/Leaf.js +1 -1
  116. package/dist/components/Treeview/Node.js +3 -3
  117. package/dist/components/Treeview/index.js +2 -2
  118. package/dist/components/Treeview/settings.js +1 -1
  119. package/dist/constants.js +44 -2
  120. package/dist/content/icons/html-templates.svg +3 -0
  121. package/dist/content/icons/lock.svg +3 -0
  122. package/dist/content/icons/orckestra-icon.svg +5 -0
  123. package/dist/content/icons/unlock.svg +3 -0
  124. package/dist/content/iconsSheet.svg +14 -0
  125. package/dist/content/orckestra-logo-white.png +0 -0
  126. package/dist/getThemeOverrides.js +2 -2
  127. package/dist/hocs/withInfiniteScroll.js +1 -1
  128. package/dist/hocs/withUpdateHandler.js +2 -2
  129. package/dist/hooks/useDispatchWithModulesData.js +1 -1
  130. package/dist/hooks/useEditState.js +3 -3
  131. package/dist/hooks/useEntityLoader.js +182 -0
  132. package/dist/hooks/useFullEntityEditState.js +3 -3
  133. package/dist/hooks/useInfiniteScroll.js +104 -0
  134. package/dist/hooks/useLabelMessage.js +3 -3
  135. package/dist/hooks/useLoader.js +1 -0
  136. package/dist/hooks/useMultipleFieldEditState.js +2 -2
  137. package/dist/hooks/useNavigationHandler.js +1 -1
  138. package/dist/hooks/useNotificationRequestState.js +159 -0
  139. package/dist/hooks/useRequestState.js +146 -0
  140. package/dist/hooks/useSelectorAndUnwrap.js +1 -1
  141. package/dist/reducers/metadata.js +52 -26
  142. package/dist/reducers/modules.js +39 -1
  143. package/dist/reducers/requestStates.js +181 -0
  144. package/dist/reducers/scopes.js +27 -0
  145. package/dist/reducers/settings.js +31 -2
  146. package/dist/schemas/countries.js +1 -1
  147. package/dist/schemas/definitions.js +1 -1
  148. package/dist/schemas/metadata.js +1 -1
  149. package/dist/schemas/productDefinitions.js +1 -1
  150. package/dist/schemas/timezones.js +1 -1
  151. package/dist/selectors/applications.js +1 -1
  152. package/dist/selectors/authentication.js +57 -19
  153. package/dist/selectors/countries.js +1 -1
  154. package/dist/selectors/locale.js +1 -1
  155. package/dist/selectors/metadata.js +104 -14
  156. package/dist/selectors/modules.js +15 -1
  157. package/dist/selectors/navigation.js +1 -1
  158. package/dist/selectors/requestStates.js +82 -0
  159. package/dist/selectors/requests.js +1 -1
  160. package/dist/selectors/scope.js +7 -1
  161. package/dist/selectors/settings.js +13 -1
  162. package/dist/selectors/versionInfo.js +1 -1
  163. package/dist/selectors/view.js +1 -1
  164. package/dist/sharedMessages.js +44 -0
  165. package/dist/spawnerMiddleware.js +1 -1
  166. package/dist/utils/displayModeHelper.js +1 -1
  167. package/dist/utils/flatten.js +2 -2
  168. package/dist/utils/localizationHelper.js +1 -1
  169. package/dist/utils/mapHelper.js +1 -1
  170. package/dist/utils/modelValidationHelper.js +2 -2
  171. package/dist/utils/parseHelper.js +1 -1
  172. package/dist/utils/propertyHelper.js +2 -2
  173. package/dist/utils/propertyValidator.js +1 -1
  174. package/dist/utils/setTranslationWithFallback.js +3 -2
  175. package/dist/utils/testUtils.js +6 -2
  176. package/dist/utils/timezoneHelper.js +111 -0
  177. package/dist/utils/unwrapImmutable.js +1 -1
  178. package/dist/utils/urlHelper.js +11 -1
  179. package/package.json +6 -9
  180. package/src/actions/makeApiAction.js +24 -1
  181. package/src/actions/makeApiAction.test.js +76 -3
  182. package/src/actions/metadata.js +130 -0
  183. package/src/actions/metadata.test.js +337 -5
  184. package/src/actions/modules.js +30 -0
  185. package/src/actions/modules.test.js +50 -1
  186. package/src/actions/requestState.js +8 -0
  187. package/src/actions/requestState.test.js +14 -0
  188. package/src/actions/requestsApi.js +30 -0
  189. package/src/actions/scopes.js +33 -7
  190. package/src/actions/scopes.test.js +84 -14
  191. package/src/buildStore.js +2 -0
  192. package/src/components/AppFrame/About.js +2 -2
  193. package/src/components/AppFrame/AppFrame.test.js +15 -16
  194. package/src/components/AppFrame/ApplicationSelector/ApplicationDialog.js +105 -82
  195. package/src/components/AppFrame/ApplicationSelector/ApplicationDialog.test.js +60 -23
  196. package/src/components/AppFrame/ApplicationSelector/ApplicationSelector.test.js +22 -89
  197. package/src/components/AppFrame/ApplicationSelector/index.js +34 -15
  198. package/src/components/AppFrame/MenuItem.js +3 -5
  199. package/src/components/AppFrame/MenuItem.test.js +2 -24
  200. package/src/components/AppFrame/Sidebar.js +11 -12
  201. package/src/components/AppFrame/Sidebar.test.js +18 -0
  202. package/src/components/AppFrame/Topbar.test.js +2 -4
  203. package/src/components/ApplicationModuleLoader.js +52 -0
  204. package/src/components/ApplicationModuleLoader.test.js +149 -0
  205. package/src/components/Authenticate.js +5 -4
  206. package/src/components/Authenticate.test.js +23 -4
  207. package/src/components/MaterialUI/DataDisplay/SelectionList.js +14 -6
  208. package/src/components/MaterialUI/DataDisplay/SelectionList.test.js +21 -11
  209. package/src/components/MaterialUI/DataDisplay/Table.js +29 -5
  210. package/src/components/MaterialUI/DataDisplay/Table.test.js +23 -0
  211. package/src/components/MaterialUI/DataDisplay/TableProps.js +2 -0
  212. package/src/components/MaterialUI/DataDisplay/TableProps.test.js +2 -0
  213. package/src/components/MaterialUI/DataDisplay/TransferList.js +3 -0
  214. package/src/components/MaterialUI/Inputs/DatePicker.js +11 -0
  215. package/src/components/MaterialUI/Inputs/InputBase.js +3 -1
  216. package/src/components/MaterialUI/Inputs/InputBase.test.js +38 -0
  217. package/src/components/MaterialUI/Inputs/TimePicker.js +9 -3
  218. package/src/components/MaterialUI/Inputs/TimePicker.test.js +263 -118
  219. package/src/components/MaterialUI/Navigation/ExternalLink.js +25 -0
  220. package/src/components/MaterialUI/Navigation/ExternalLink.test.js +26 -0
  221. package/src/components/MaterialUI/Navigation/TabBar.js +82 -78
  222. package/src/components/MaterialUI/Navigation/TabBar.test.js +129 -3
  223. package/src/components/MaterialUI/ScopeSelector/ScopeSelector.js +4 -2
  224. package/src/components/MaterialUI/ScopeSelector/ScopeSelector.test.js +29 -0
  225. package/src/components/MaterialUI/ScopeSelector/ScopeTreeView.js +4 -1
  226. package/src/components/MaterialUI/ScopeSelector/ScopeTreeView.test.js +52 -0
  227. package/src/components/MaterialUI/ScopeSelector/TreeItem.js +9 -6
  228. package/src/components/MaterialUI/ScopeSelector/TreeItem.test.js +63 -2
  229. package/src/components/MaterialUI/Surfaces/ExpansionPanel.js +14 -1
  230. package/src/components/MaterialUI/Surfaces/ExpansionPanel.test.js +16 -0
  231. package/src/components/MaterialUI/Surfaces/SectionExpansionPanel.js +11 -2
  232. package/src/components/MaterialUI/Surfaces/SectionExpansionPanel.test.js +36 -0
  233. package/src/components/MaterialUI/Surfaces/expansionPanelProps.js +2 -0
  234. package/src/components/MaterialUI/Surfaces/expansionPanelProps.test.js +2 -2
  235. package/src/components/MaterialUI/muiThemes.js +23 -3
  236. package/src/components/Modules.js +108 -13
  237. package/src/components/Modules.test.js +431 -12
  238. package/src/components/Navigation/Navigation.test.js +2 -0
  239. package/src/components/Navigation/useNavigationState.js +21 -1
  240. package/src/components/Navigation/useNavigationState.test.js +10 -0
  241. package/src/components/Provision.test.js +34 -0
  242. package/src/components/Routing/FullPage.js +4 -2
  243. package/src/components/Routing/FullPage.test.js +75 -0
  244. package/src/components/Routing/Page.js +2 -2
  245. package/src/components/Routing/Page.test.js +20 -0
  246. package/src/components/Routing/Segment.js +5 -2
  247. package/src/components/Routing/Segment.test.js +22 -1
  248. package/src/components/Routing/SegmentPage.js +12 -4
  249. package/src/components/Routing/SubPage.test.js +1 -1
  250. package/src/components/Routing/withWaypointing.js +19 -17
  251. package/src/components/Routing/withWaypointing.test.js +81 -3
  252. package/src/components/Scope/Scope.test.js +117 -0
  253. package/src/components/Scope/index.js +6 -10
  254. package/src/components/Scope/useScopeConfirmationModalState.js +5 -16
  255. package/src/components/Scope/useScopeConfirmationModalState.test.js +39 -13
  256. package/src/components/Scope/useScopeData.js +0 -3
  257. package/src/components/Scope/useScopeData.test.js +0 -27
  258. package/src/components/Sidepanel.js +0 -1
  259. package/src/components/Sidepanel.test.js +0 -3
  260. package/src/constants.js +33 -0
  261. package/src/content/icons/html-templates.svg +3 -0
  262. package/src/content/icons/lock.svg +3 -0
  263. package/src/content/icons/orckestra-icon.svg +5 -0
  264. package/src/content/icons/unlock.svg +3 -0
  265. package/src/content/iconsSheet.svg +14 -0
  266. package/src/content/orckestra-logo-white.png +0 -0
  267. package/src/hocs/withScopeData.test.js +0 -31
  268. package/src/hooks/useEntityLoader.js +68 -0
  269. package/src/hooks/useEntityLoader.test.js +266 -0
  270. package/src/hooks/useInfiniteScroll.js +25 -0
  271. package/src/hooks/useInfiniteScroll.test.js +87 -0
  272. package/src/hooks/useLoader.js +1 -0
  273. package/src/hooks/useNotificationRequestState.js +78 -0
  274. package/src/hooks/useNotificationRequestState.test.js +264 -0
  275. package/src/hooks/useRequestState.js +57 -0
  276. package/src/hooks/useRequestState.test.js +217 -0
  277. package/src/reducers/metadata.js +76 -16
  278. package/src/reducers/metadata.test.js +458 -4
  279. package/src/reducers/modules.js +48 -2
  280. package/src/reducers/modules.test.js +117 -2
  281. package/src/reducers/requestStates.js +98 -0
  282. package/src/reducers/requestStates.test.js +399 -0
  283. package/src/reducers/scopes.js +30 -0
  284. package/src/reducers/scopes.test.js +45 -1
  285. package/src/reducers/settings.js +26 -2
  286. package/src/reducers/settings.test.js +74 -6
  287. package/src/selectors/authentication.js +53 -28
  288. package/src/selectors/authentication.test.js +600 -12
  289. package/src/selectors/locale.test.js +0 -2
  290. package/src/selectors/metadata.js +73 -13
  291. package/src/selectors/metadata.test.js +479 -8
  292. package/src/selectors/modules.js +7 -0
  293. package/src/selectors/modules.test.js +16 -1
  294. package/src/selectors/requestStates.js +12 -0
  295. package/src/selectors/requestStates.test.js +83 -0
  296. package/src/selectors/scope.js +2 -0
  297. package/src/selectors/scope.test.js +5 -0
  298. package/src/selectors/settings.js +6 -0
  299. package/src/sharedMessages.js +44 -0
  300. package/src/translations/en-US.json +12 -1
  301. package/src/translations/fr-CA.json +13 -2
  302. package/src/utils/modelValidationHelper.js +1 -1
  303. package/src/utils/setTranslationWithFallback.js +1 -1
  304. package/src/utils/setTranslationWithFallback.test.js +4 -14
  305. package/src/utils/testUtils.js +3 -1
  306. package/src/utils/timezoneHelper.js +140 -0
  307. package/src/utils/timezoneHelper.test.js +33 -0
  308. package/src/utils/urlHelper.js +6 -0
  309. package/src/translations/it-IT.json +0 -54
@@ -1,10 +1,16 @@
1
1
  import React from "react";
2
- import ApplicationSelector, { getAnchor, getDialog } from "./index";
3
- import Header, { MenuIcon, Wrapper } from "./Header";
4
- import ApplicationDialog, { List, Block, Link, Logo, Label, Indicator } from "./ApplicationDialog";
2
+ import { extractMessages, TestWrapper, createMuiTheme } from "../../../utils/testUtils";
3
+ import ApplicationSelector from "./index";
4
+ import PopperedIcon from "../../MaterialUI/DataDisplay/PopperedElements/PopperedIcon";
5
+ import ApplicationDialog from "./ApplicationDialog";
6
+ import sharedMessages from "~/sharedMessages";
7
+
8
+ const messages = extractMessages(sharedMessages);
5
9
 
6
10
  describe("ApplicationSelector", () => {
7
- let props, applications, thisApp, modalRoot;
11
+ const theme = createMuiTheme();
12
+
13
+ let props, applications, thisApp;
8
14
  beforeEach(() => {
9
15
  thisApp = {
10
16
  name: "current",
@@ -26,92 +32,19 @@ describe("ApplicationSelector", () => {
26
32
  applications,
27
33
  applicationId: "current",
28
34
  };
29
- modalRoot = document.createElement("div");
30
- modalRoot.id = "modal";
31
- document.body.appendChild(modalRoot);
32
- });
33
- afterEach(() => {
34
- document.body.removeChild(modalRoot);
35
35
  });
36
36
 
37
- it("renders a modal application selector dialog", () =>
38
- expect(
39
- <ApplicationSelector {...props} />,
40
- "when mounted",
41
- "with event",
42
- "click",
43
- "to satisfy",
44
- <Wrapper>
45
- <MenuIcon />
46
- </Wrapper>,
47
- ).then(() =>
48
- expect(
49
- modalRoot,
50
- "to contain",
51
- <List>
52
- <Block key="current">
53
- <Link href="/test/url">
54
- <Logo src="/url/to/img1.png" />
55
- </Link>
56
- <Label>Test label</Label>
57
- <Indicator />
58
- </Block>
59
- <Block key="other">
60
- <Link href="/test/elsewhere">
61
- <Logo src="/url/to/img2.png" />
62
- </Link>
63
- <Label>Test again</Label>
64
- </Block>
65
- </List>,
66
- ),
67
- ));
68
-
69
- describe("getAnchor", () => {
70
- let toggle;
71
- beforeEach(() => {
72
- toggle = () => {};
73
- });
74
-
75
- it("takes props and returns a header render function", () =>
76
- expect(
77
- getAnchor,
78
- "when called with",
79
- ["foo", props],
80
- "when called with",
81
- [toggle],
82
- "to equal",
83
- <Header className="foo" open application={thisApp} toggle={toggle} />,
84
- ));
85
-
86
- it("handles a missing app list", () => {
87
- delete props.applications;
88
- return expect(
89
- getAnchor,
90
- "when called with",
91
- ["foo", props],
92
- "when called with",
93
- [toggle],
94
- "to equal",
95
- <Header className="foo" open toggle={toggle} />,
96
- );
97
- });
98
- });
99
-
100
- describe("getDialog", () => {
101
- let toggle;
102
- beforeEach(() => {
103
- toggle = () => {};
104
- });
105
-
106
- it("takes props and returns a header render function", () =>
107
- expect(
108
- getDialog,
109
- "when called with",
110
- [props],
111
- "when called with",
112
- [toggle],
113
- "to equal",
114
- <ApplicationDialog open applications={applications} applicationId={props.applicationId} toggle={toggle} />,
115
- ));
37
+ it("renders a poppered application selector dialog", () => {
38
+ const component = (
39
+ <TestWrapper intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
40
+ <ApplicationSelector {...props} />
41
+ </TestWrapper>
42
+ );
43
+ const expected = (
44
+ <TestWrapper intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
45
+ <PopperedIcon popperValue={<ApplicationDialog {...props} />} id="app-list" placement="bottom-start" />
46
+ </TestWrapper>
47
+ );
48
+ expect(component, "when mounted", "to satisfy", expected);
116
49
  });
117
50
  });
@@ -1,24 +1,43 @@
1
1
  import React from "react";
2
- import Header from "./Header";
3
2
  import ApplicationDialog from "./ApplicationDialog";
4
- import Modal from "../../Modal";
3
+ import PopperedIcon from "../../MaterialUI/DataDisplay/PopperedElements/PopperedIcon";
4
+ import { makeStyles } from "@material-ui/core/styles";
5
5
 
6
- const getApp = (apps = [], id) => apps.filter(app => app.name === id)[0];
6
+ const useStyles = makeStyles(theme => ({
7
+ popperContainer: {
8
+ cursor: "pointer",
9
+ position: "relative",
10
+ fontSize: theme.spacing(2.4),
11
+ padding: theme.spacing(0.5, 1.3),
12
+ "& svg": {
13
+ color: theme.palette.grey.icon,
14
+ },
15
+ },
16
+ arrow: {
17
+ top: 0,
18
+ left: theme.spacing(1),
19
+ width: theme.spacing(1),
20
+ height: theme.spacing(1),
21
+ transform: "translateX(-50%) rotate(45deg)",
22
+ marginTop: theme.spacing(-1.5),
23
+ backgroundColor: theme.palette.grey.lighter,
24
+ border: "1px solid",
25
+ borderColor: `${theme.palette.grey.borders} transparent transparent ${theme.palette.grey.borders}`,
26
+ zIndex: 2000,
27
+ position: "absolute",
28
+ },
29
+ }));
7
30
 
8
- export const getAnchor = (className, props) => toggle =>
9
- (
10
- <Header
11
- className={className}
12
- open={props.open}
13
- application={getApp(props.applications, props.applicationId)}
14
- toggle={toggle}
31
+ const ApplicationSelector = ({ className, ...props }) => {
32
+ const classes = useStyles();
33
+ return (
34
+ <PopperedIcon
35
+ popperValue={<ApplicationDialog {...props} />}
36
+ id="app-list"
37
+ classprop={classes}
38
+ placement="bottom-start"
15
39
  />
16
40
  );
17
-
18
- export const getDialog = props => toggle => <ApplicationDialog {...props} toggle={toggle} />;
19
-
20
- const ApplicationSelector = ({ className, ...props }) => {
21
- return <Modal anchor={getAnchor(className, props)} content={getDialog(props)} look="dark" />;
22
41
  };
23
42
 
24
43
  export default ApplicationSelector;
@@ -1,5 +1,4 @@
1
1
  import React, { useRef } from "react";
2
- import { useSelector } from "react-redux";
3
2
  import styled, { css } from "styled-components";
4
3
  import transition from "styled-transition-group";
5
4
  import { Link } from "react-router-dom";
@@ -124,13 +123,11 @@ const MenuItem = ({
124
123
  alert,
125
124
  pageScopeSelector,
126
125
  closingTabHandler,
127
- hide,
126
+ hide, // This props is not used in the component, but we need to destructure it so props can be used in ItemWrapper
127
+ isHidden = false,
128
128
  href,
129
129
  ...props
130
130
  }) => {
131
- let hideSelector = state => (typeof hide === "function" ? hide(state) : hide ?? false);
132
- const isHidden = useSelector(hideSelector);
133
-
134
131
  let ItemWrapper = Block;
135
132
  if (props.menuToggle) {
136
133
  ItemWrapper = BlockWithA;
@@ -139,6 +136,7 @@ const MenuItem = ({
139
136
  if (alert && alert.message) {
140
137
  alertMessage.current = alert.message;
141
138
  }
139
+
142
140
  return (
143
141
  !isHidden && (
144
142
  <ItemWrapper to={href} {...props}>
@@ -168,7 +168,7 @@ describe("MenuItem", () => {
168
168
  </MemoryRouter>,
169
169
  ));
170
170
 
171
- it("shows nothing if hide is true", () => {
171
+ it("shows nothing if isHidden is true", () => {
172
172
  expect(
173
173
  <Provider store={store}>
174
174
  <MemoryRouter>
@@ -178,29 +178,7 @@ describe("MenuItem", () => {
178
178
  icon="cake"
179
179
  label="Test"
180
180
  alert={{ message: "Test message", type: "warn" }}
181
- hide={true}
182
- />
183
- </MemoryRouter>
184
- </Provider>,
185
- "when mounted",
186
- "to equal",
187
- null,
188
- );
189
- });
190
-
191
- it("shows nothing if hide selector returns true", () => {
192
- const hide = state => true;
193
-
194
- expect(
195
- <Provider store={store}>
196
- <MemoryRouter>
197
- <MenuItem
198
- id="test"
199
- href="/foo/test"
200
- icon="cake"
201
- label="Test"
202
- alert={{ message: "Test message", type: "warn" }}
203
- hide={hide}
181
+ isHidden={true}
204
182
  />
205
183
  </MemoryRouter>
206
184
  </Provider>,
@@ -5,6 +5,7 @@ import { useLocation } from "react-router-dom";
5
5
  import { getThemeProp } from "../../utils";
6
6
  import { selectPrependHrefConfig } from "../../selectors/navigation";
7
7
  import MenuItem from "./MenuItem";
8
+ import { getScopeModuleInformationSelector } from "../../selectors/modules";
8
9
 
9
10
  export const Bar = styled.div`
10
11
  box-sizing: border-box;
@@ -40,7 +41,13 @@ const useEnhancement = id => {
40
41
  };
41
42
  };
42
43
 
43
- export const EnhancedMenuItem = ({ id, ...props }) => <MenuItem {...props} {...useEnhancement(id)} />;
44
+ export const EnhancedMenuItem = ({ id, ...props }) => {
45
+ const defaultModule = useSelector(getScopeModuleInformationSelector);
46
+
47
+ const isHidden = !defaultModule.visibleModules.includes(id);
48
+
49
+ return <MenuItem {...props} {...useEnhancement(id)} isHidden={isHidden} />;
50
+ };
44
51
 
45
52
  const LogoSvg = styled.svg`
46
53
  flex: 0 0 auto;
@@ -53,17 +60,9 @@ const LogoSvg = styled.svg`
53
60
  `;
54
61
 
55
62
  export const Logo = () => (
56
- <LogoSvg>
57
- <path
58
- id="orckestra-logo"
59
- d="M10.3,3.8c-1.7,0-3.5,0.7-4.7,1.9L2.8,3c1.9-1.9,4.6-3,7.5-3c0.6,0,1.3,0.1,1.9,0.2
60
- l-0.9,3.7C11,3.8,10.6,3.8,10.3,3.8L10.3,3.8z M16.1,7.5c-1.4-1.4-3.2-2.1-5.1-2.1c-2,0-3.9,0.8-5.3,2.3c-1.2,1.2-1.9,2.8-2,4.5H0
61
- c0.1-2.7,1-4.9,3-7c0.2-0.2,0.5-0.5,0.7-0.7l1.8,1.8l0.1-0.1c1.2-1.2,2.9-1.9,4.6-1.9c0.4,0,0.8,0,1.2,0.1l0.2,0l0.6-2.5
62
- c2.3,0.3,4.3,1.2,6,2.8l0.3,0.3c2,1.9,3.1,4.5,3.3,7.3h-3.6C18.1,10.4,17.3,8.7,16.1,7.5L16.1,7.5z M19.8,3.3
63
- c2.9,2.8,4.4,6.8,4,10.8c-0.3,2.8-1.5,5.4-3.4,7.6L17,19.1c0.4-0.4,0.7-0.8,1-1.2c0.9-1.2,1.4-2.7,1.6-4.2c0-0.4,0.1-0.7,0-1.1h2.7
64
- l0-0.2c-0.1-3-1.4-5.7-3.5-7.8l-0.2-0.2L19.8,3.3L19.8,3.3z M16.5,18.9l-0.2,0.2l2.6,2c-2.3,2.6-5.6,4-9.1,3.8l0-4
65
- c0.2,0,0.4,0,0.6,0h0c2.6,0,5-1.4,6.4-3.6l0.7,0.5C17.2,18.2,16.9,18.6,16.5,18.9L16.5,18.9z"
66
- />
63
+ <LogoSvg viewBox="0 0 260 260">
64
+ <path d="M1.11,125.62C1.11,74.94,40.22,39,93.72,39S186,74.94,186,125.62s-38.79,86.66-92.29,86.66S1.11,176.3,1.11,125.62Zm135.47,0c0-29.1-18.46-46.62-42.86-46.62S50.54,96.52,50.54,125.62s18.77,46.62,43.18,46.62S136.58,154.72,136.58,125.62Z" />
65
+ <circle cx="227.6" cy="181.13" r="31.29" />
67
66
  </LogoSvg>
68
67
  );
69
68
 
@@ -24,6 +24,15 @@ describe("Sidebar", () => {
24
24
  state = Immutable.fromJS({
25
25
  navigation: { route: { match: { params: { scope: "Global" } } }, config: { prependHref: "/Global/" } },
26
26
  settings: { defaultScope: "myScope" },
27
+ modules: {
28
+ tree: "modulesTree",
29
+ visibleModules: ["a", "module123"],
30
+ lastScopeAndModuleSelection: {
31
+ scope: "Norway",
32
+ moduleName: "Profiles",
33
+ routingPerformed: false,
34
+ },
35
+ },
27
36
  });
28
37
  store = {
29
38
  subscribe: () => {},
@@ -153,6 +162,15 @@ describe("EnhancedMenuItem", () => {
153
162
  },
154
163
  config: { prependHref: "/Global/" },
155
164
  },
165
+ modules: {
166
+ tree: "modulesTree",
167
+ visibleModules: ["route"],
168
+ lastScopeAndModuleSelection: {
169
+ scope: "Norway",
170
+ moduleName: "Profiles",
171
+ routingPerformed: false,
172
+ },
173
+ },
156
174
  settings: { defaultScope: "myScope" },
157
175
  }),
158
176
  };
@@ -9,7 +9,7 @@ import { VIEW_STATE_SET_FIELD } from "../../actions/view";
9
9
  import { SIGN_OUT_REQUEST, SIGN_OUT_SUCCESS, SIGN_OUT_FAILURE } from "../../actions/authentication";
10
10
  import { PREFS_NAME } from "./Preferences";
11
11
  import { ABOUT_NAME } from "./About";
12
- import { Wrapper as AppSelWrapper, MenuIcon } from "./ApplicationSelector/Header";
12
+ import ApplicationSelector from "./ApplicationSelector";
13
13
  import { Wrapper as MenuWrapper } from "../DropMenu";
14
14
  import Topbar, { Wrapper, AppBox, CurrentApp, AppLabel, AppLogo, useMenuProps } from "./Topbar";
15
15
  import { HelpLink } from "./Help";
@@ -79,9 +79,7 @@ describe("Topbar", () => {
79
79
  "to satisfy",
80
80
  <Wrapper onClick={clicker}>
81
81
  <AppBox>
82
- <AppSelWrapper>
83
- <MenuIcon />
84
- </AppSelWrapper>
82
+ <ApplicationSelector {...props} />
85
83
  <AppLabel>
86
84
  <AppLogo src="/test/url" />
87
85
  Test label
@@ -0,0 +1,52 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { useDispatch, useSelector } from "react-redux";
3
+ import { getDefaultScope, getScopes } from "../actions/scopes";
4
+ import {
5
+ defaultScopeSelector,
6
+ getApplicationModulesSelector,
7
+ getLoadedModulesScopeSelector,
8
+ } from "../selectors/settings";
9
+ import { Loader } from "./Authenticate";
10
+ import { overtureModule, scopeTypes } from "../constants";
11
+ import { initializeFirstModuleScope } from "../actions/modules";
12
+
13
+ const ApplicationModuleLoader = ({ children }) => {
14
+ const dispatch = useDispatch();
15
+
16
+ const [scopesLoaded, setScopesLoaded] = useState(false);
17
+
18
+ const loadedModules = useSelector(getLoadedModulesScopeSelector);
19
+ const applicationModules = useSelector(getApplicationModulesSelector);
20
+ const defaultScope = useSelector(defaultScopeSelector);
21
+
22
+ useEffect(() => {
23
+ if (applicationModules.length > 0 && scopesLoaded === false) {
24
+ if (applicationModules.includes(overtureModule.System)) {
25
+ dispatch(initializeFirstModuleScope(scopeTypes.global));
26
+ }
27
+
28
+ applicationModules.forEach(x => {
29
+ // For the default scope, the latest that will be returned will be the chosen one
30
+ dispatch(getDefaultScope(x));
31
+ // For scopes, they need to be merged
32
+ dispatch(getScopes(x));
33
+ });
34
+
35
+ setScopesLoaded(true);
36
+ }
37
+ }, [dispatch, applicationModules, scopesLoaded]);
38
+
39
+ const scopeLoadedFromAllModules =
40
+ applicationModules.length > 0 &&
41
+ applicationModules.reduce((prev, current) => prev && loadedModules.includes(current), true);
42
+
43
+ const applicationModuleReady = scopeLoadedFromAllModules && defaultScope != null;
44
+
45
+ if (!applicationModuleReady) {
46
+ return <Loader />;
47
+ }
48
+
49
+ return React.Children.only(children);
50
+ };
51
+
52
+ export default ApplicationModuleLoader;
@@ -0,0 +1,149 @@
1
+ import React from "react";
2
+ import Immutable from "immutable";
3
+ import { Provider } from "react-redux";
4
+ import { ThemeProvider } from "styled-components";
5
+ import { Loader } from "./Authenticate";
6
+ import ApplicationModuleLoader from "./ApplicationModuleLoader";
7
+ import { mount } from "enzyme";
8
+ import { getDefaultScope, getScopes } from "../actions/scopes";
9
+ import sinon from "sinon";
10
+ import { initializeFirstModuleScope } from "../actions/modules";
11
+ import { scopeTypes } from "../constants";
12
+
13
+ const TestComp = () => {
14
+ return <div className="test" />;
15
+ };
16
+
17
+ jest.mock("../utils/buildUrl", () => {
18
+ const modExport = {};
19
+ modExport.loadConfig = () => Promise.resolve({});
20
+ modExport.buildUrl = (path = [], params = "") => "URL: " + path.join("/") + " " + JSON.stringify(params);
21
+ return modExport;
22
+ });
23
+
24
+ describe("ApplicationModuleLoader", () => {
25
+ let state, store;
26
+
27
+ beforeEach(() => {
28
+ state = Immutable.fromJS({
29
+ requests: {},
30
+ scopes: {
31
+ test1: {
32
+ id: "test1",
33
+ name: { "en-CA": "Test 1", "en-US": "Test 1" },
34
+ children: ["test2"],
35
+ },
36
+ },
37
+ authentication: {
38
+ name: "foo@bar.com",
39
+ },
40
+ settings: {
41
+ defaultScope: "aDefaultScope",
42
+ loadedModulesScope: ["moduleA", "moduleB"],
43
+ modules: ["moduleA", "moduleB"],
44
+ },
45
+ });
46
+ store = state => ({
47
+ subscribe: () => {},
48
+ getState: () => state,
49
+ dispatch: sinon.spy().named("dispatch"),
50
+ });
51
+ });
52
+
53
+ it("shows the component when scopes configuration are all loaded", () =>
54
+ expect(
55
+ <Provider store={store(state)}>
56
+ <ApplicationModuleLoader>
57
+ <TestComp />
58
+ </ApplicationModuleLoader>
59
+ </Provider>,
60
+ "when mounted",
61
+ "to exhaustively satisfy",
62
+ <TestComp />,
63
+ ));
64
+
65
+ it("shows a load indicator component when default scope is still unknown", () => {
66
+ state = state.setIn(["settings", "defaultScope"], null);
67
+ return expect(
68
+ <Provider store={store(state)}>
69
+ <ThemeProvider theme={{}}>
70
+ <ApplicationModuleLoader>
71
+ <TestComp />
72
+ </ApplicationModuleLoader>
73
+ </ThemeProvider>
74
+ </Provider>,
75
+ "when mounted",
76
+ "to exhaustively satisfy",
77
+ <ThemeProvider theme={{}}>
78
+ <Loader />
79
+ </ThemeProvider>,
80
+ );
81
+ });
82
+
83
+ it("shows a load indicator component when scopes trees are not loaded for all modules", () => {
84
+ state = state.setIn(["settings", "loadedModulesScope"], Immutable.fromJS(["moduleA"]));
85
+ return expect(
86
+ <Provider store={store(state)}>
87
+ <ThemeProvider theme={{}}>
88
+ <ApplicationModuleLoader>
89
+ <TestComp />
90
+ </ApplicationModuleLoader>
91
+ </ThemeProvider>
92
+ </Provider>,
93
+ "when mounted",
94
+ "to exhaustively satisfy",
95
+ <ThemeProvider theme={{}}>
96
+ <Loader />
97
+ </ThemeProvider>,
98
+ );
99
+ });
100
+
101
+ it("scopes tree and default scope should be loaded when rendering the component", () => {
102
+ const theStore = store(state);
103
+
104
+ const component = (
105
+ <Provider store={theStore}>
106
+ <ThemeProvider theme={{}}>
107
+ <ApplicationModuleLoader>
108
+ <TestComp />
109
+ </ApplicationModuleLoader>
110
+ </ThemeProvider>
111
+ </Provider>
112
+ );
113
+
114
+ mount(component);
115
+
116
+ expect(theStore.dispatch, "to have calls satisfying", [
117
+ { args: [getDefaultScope("moduleA")] },
118
+ { args: [getScopes("moduleA")] },
119
+ { args: [getDefaultScope("moduleB")] },
120
+ { args: [getScopes("moduleB")] },
121
+ ]);
122
+ });
123
+
124
+ it("First module scope should be initialized when System is part application modules", () => {
125
+ state = state.setIn(["settings", "modules"], Immutable.fromJS(["moduleA", "System"]));
126
+
127
+ const theStore = store(state);
128
+
129
+ const component = (
130
+ <Provider store={theStore}>
131
+ <ThemeProvider theme={{}}>
132
+ <ApplicationModuleLoader>
133
+ <TestComp />
134
+ </ApplicationModuleLoader>
135
+ </ThemeProvider>
136
+ </Provider>
137
+ );
138
+
139
+ mount(component);
140
+
141
+ expect(theStore.dispatch, "to have calls satisfying", [
142
+ { args: [initializeFirstModuleScope(scopeTypes.global)] },
143
+ { args: [getDefaultScope("moduleA")] },
144
+ { args: [getScopes("moduleA")] },
145
+ { args: [getDefaultScope("System")] },
146
+ { args: [getScopes("System")] },
147
+ ]);
148
+ });
149
+ });
@@ -6,10 +6,10 @@ import { useSelector } from "react-redux";
6
6
  import { unwrapImmutable } from "../utils";
7
7
  import { GET_AUTHENTICATION_PROFILE } from "../actions/authentication";
8
8
  import { ERROR, LOGOUT } from "../reducers/request";
9
+ import ApplicationModuleLoader from "./ApplicationModuleLoader";
9
10
 
10
11
  export const useAuthenticationData = () => ({
11
12
  loading: useSelector(state => state.getIn(["requests", "actives", GET_AUTHENTICATION_PROFILE])),
12
- defaultScope: useSelector(state => state.getIn(["settings", "defaultScope"])) || null,
13
13
  authedUser: useSelector(state => state.getIn(["authentication", "name"])),
14
14
  requestError: unwrapImmutable(useSelector(state => state.getIn(["requests", ERROR]) || null)),
15
15
  needLogin: useSelector(state => state.getIn(["requests", LOGOUT])),
@@ -47,14 +47,15 @@ export const Error = ({ requestError, needLogin }) => {
47
47
  };
48
48
 
49
49
  const Authenticate = ({ children }) => {
50
- const { loading, defaultScope, authedUser, requestError, needLogin } = useAuthenticationData();
51
- if (loading || defaultScope === null) {
50
+ const { loading, authedUser, requestError, needLogin } = useAuthenticationData();
51
+
52
+ if (loading) {
52
53
  return <Loader />;
53
54
  }
54
55
  if (!authedUser) {
55
56
  return <Error {...{ requestError, needLogin }} />;
56
57
  } else {
57
- return React.Children.only(children);
58
+ return <ApplicationModuleLoader children={children} />;
58
59
  }
59
60
  };
60
61
 
@@ -7,19 +7,36 @@ import { ERROR, LOGOUT } from "../reducers/request";
7
7
  import { GET_AUTHENTICATION_PROFILE } from "../actions/authentication";
8
8
 
9
9
  const TestComp = () => {
10
- return <div className="test"></div>;
10
+ return <div className="test" />;
11
11
  };
12
12
 
13
+ jest.mock("../utils/buildUrl", () => {
14
+ const modExport = {};
15
+ modExport.loadConfig = () => Promise.resolve({});
16
+ modExport.buildUrl = () => "URL";
17
+ return modExport;
18
+ });
19
+
13
20
  describe("Authenticate", () => {
14
21
  let state, store;
22
+
15
23
  beforeEach(() => {
16
24
  state = Immutable.fromJS({
17
25
  requests: {},
26
+ scopes: {
27
+ test1: {
28
+ id: "test1",
29
+ name: { "en-CA": "Test 1", "en-US": "Test 1" },
30
+ children: ["test2"],
31
+ },
32
+ },
18
33
  authentication: {
19
34
  name: "foo@bar.com",
20
35
  },
21
36
  settings: {
22
37
  defaultScope: "aDefaultScope",
38
+ loadedModulesScope: ["moduleA", "moduleB"],
39
+ modules: ["moduleA", "moduleB"],
23
40
  },
24
41
  });
25
42
  store = state => ({
@@ -38,7 +55,9 @@ describe("Authenticate", () => {
38
55
  </Provider>,
39
56
  "when mounted",
40
57
  "to exhaustively satisfy",
41
- <TestComp />,
58
+ <Provider store={store(state)}>
59
+ <TestComp />
60
+ </Provider>,
42
61
  ));
43
62
 
44
63
  it("shows a load indicator component if authentication is ongoing", () => {
@@ -59,12 +78,12 @@ describe("Authenticate", () => {
59
78
  );
60
79
  });
61
80
 
62
- it("shows a load indicator component if default scope is unknown", () => {
81
+ it("shows a load indicator component when application modules not ready", () => {
63
82
  state = state.setIn(["settings", "defaultScope"], null);
64
83
  return expect(
65
84
  <Provider store={store(state)}>
66
85
  <ThemeProvider theme={{}}>
67
- <Authenticate>
86
+ <Authenticate applicationModuleReady={false}>
68
87
  <TestComp />
69
88
  </Authenticate>
70
89
  </ThemeProvider>