orc-shared 1.2.0-dev.10 → 1.2.0-dev.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/dist/components/AppFrame/About.js +5 -1
  4. package/dist/components/AppFrame/AppFrame.js +14 -4
  5. package/dist/components/AppFrame/MenuItem.js +1 -4
  6. package/dist/components/MaterialUI/Inputs/InputBase.js +41 -4
  7. package/dist/components/MaterialUI/ScopeSelector/ScopeSelector.js +8 -2
  8. package/dist/components/Routing/FullPage.js +6 -3
  9. package/dist/selectors/metadata.js +13 -3
  10. package/dist/selectors/scope.js +2 -1
  11. package/dist/utils/setTranslation.js +27 -1
  12. package/dist/utils/setTranslationWithFallback.js +30 -1
  13. package/package.json +1 -1
  14. package/src/components/AppFrame/About.js +8 -1
  15. package/src/components/AppFrame/AppFrame.js +13 -2
  16. package/src/components/AppFrame/AppFrame.test.js +53 -0
  17. package/src/components/AppFrame/MenuItem.js +1 -12
  18. package/src/components/MaterialUI/DataDisplay/PredefinedElements/Translations.test.js +7 -1
  19. package/src/components/MaterialUI/Inputs/InputBase.js +19 -2
  20. package/src/components/MaterialUI/Inputs/InputBase.test.js +68 -0
  21. package/src/components/MaterialUI/ScopeSelector/ScopeSelector.js +5 -1
  22. package/src/components/Routing/FullPage.js +12 -4
  23. package/src/components/Routing/FullPage.test.js +24 -0
  24. package/src/components/Scope/Scope.test.js +4 -0
  25. package/src/selectors/metadata.js +18 -7
  26. package/src/selectors/metadata.test.js +221 -283
  27. package/src/selectors/scope.js +1 -1
  28. package/src/translations/en-US.json +1 -1
  29. package/src/translations/fr-CA.json +1 -1
  30. package/src/utils/setTranslation.js +16 -1
  31. package/src/utils/setTranslation.test.js +24 -0
  32. package/src/utils/setTranslationWithFallback.js +18 -1
  33. package/src/utils/setTranslationWithFallback.test.js +108 -0
@@ -5,15 +5,19 @@ import InputBaseMUI from "@material-ui/core/InputBase";
5
5
  import sinon from "sinon";
6
6
  import { ignoreConsoleError } from "../../../utils/testUtils";
7
7
  import InputBaseProps from "./InputBaseProps";
8
+ import { act } from "unexpected-reaction";
8
9
 
9
10
  describe("InputBase Component", () => {
10
11
  let update, container;
11
12
  beforeEach(() => {
13
+ window.bypassDebounce = true;
14
+
12
15
  container = document.createElement("div");
13
16
  document.body.appendChild(container);
14
17
  update = sinon.spy().named("update");
15
18
  });
16
19
  afterEach(() => {
20
+ delete window.bypassDebounce;
17
21
  document.body.removeChild(container);
18
22
  container = null;
19
23
  });
@@ -243,3 +247,67 @@ describe("InputBase Component", () => {
243
247
  expect(mountedComponent.containsMatchingElement(expected), "to be truthy");
244
248
  });
245
249
  });
250
+
251
+ describe("InputBase component debouce", () => {
252
+ const clock = sinon.useFakeTimers();
253
+ let update, container;
254
+
255
+ beforeEach(() => {
256
+ container = document.createElement("div");
257
+ document.body.appendChild(container);
258
+ update = sinon.spy().named("update");
259
+ });
260
+
261
+ afterEach(() => {
262
+ clock.restore();
263
+ });
264
+
265
+ it("InputBase component updates when debounced update", async () => {
266
+ const inputProps = new InputBaseProps();
267
+ const aLabel = "aLabel";
268
+ const aValue = "value";
269
+
270
+ const metadata = {
271
+ test: "value",
272
+ };
273
+
274
+ inputProps.set(InputBaseProps.propNames.value, "");
275
+ inputProps.set(InputBaseProps.propNames.update, update);
276
+ inputProps.set(InputBaseProps.propNames.label, aLabel);
277
+ inputProps.set(InputBaseProps.propNames.metadata, metadata);
278
+
279
+ const component = <InputBase inputProps={inputProps} />;
280
+ const mountedComponent = mount(component);
281
+
282
+ const input = mountedComponent.find("input");
283
+ input.simulate("change", { target: { value: aValue } });
284
+
285
+ act(() => {
286
+ clock.tick(200);
287
+ });
288
+
289
+ input.simulate("change", { target: { value: "differentValue" } });
290
+ expect(update, "to have calls satisfying", [{ args: [aValue, metadata] }]);
291
+ });
292
+
293
+ it("InputBase component update to empty when text to display is null", async () => {
294
+ const inputProps = new InputBaseProps();
295
+ const aLabel = "aLabel";
296
+
297
+ const metadata = {
298
+ test: "value",
299
+ };
300
+
301
+ inputProps.set(InputBaseProps.propNames.value, null);
302
+ inputProps.set(InputBaseProps.propNames.update, update);
303
+ inputProps.set(InputBaseProps.propNames.label, aLabel);
304
+ inputProps.set(InputBaseProps.propNames.metadata, metadata);
305
+
306
+ const component = <InputBase inputProps={inputProps} />;
307
+ const mountedComponent = mount(component);
308
+
309
+ const input = mountedComponent.find("input");
310
+ input.simulate("change", { target: { value: null } });
311
+ expect(input.get(0).props.value, "to equal", "");
312
+ });
313
+ });
@@ -16,6 +16,10 @@ const useStyles = makeStyles(theme => ({
16
16
  border: `1px solid ${theme.palette.grey.borders}`,
17
17
  boxShadow: "0 2px 4px rgba(0,0,0,0.5)",
18
18
  width: theme.spacing(50),
19
+ display: "flex",
20
+ },
21
+ scopeContainer: {
22
+ width: "100%",
19
23
  },
20
24
  scopeSelector: {
21
25
  display: "flex",
@@ -64,7 +68,7 @@ const ScopeSelector = ({ show, getScope, selectedScope, closeSelector, filter, u
64
68
  <Sidepanel className={classes.container} in={show} timeout={300}>
65
69
  <ClickAwayListener onClickAway={e => closeSelector(e)}>
66
70
  {/* this div is required since ClickAwayListener child element should be able to hold ref */}
67
- <div>{show ? scopeSelectorContent : null}</div>
71
+ <div className={classes.scopeContainer}>{show ? scopeSelectorContent : null}</div>
68
72
  </ClickAwayListener>
69
73
  </Sidepanel>
70
74
  );
@@ -2,8 +2,16 @@ import React from "react";
2
2
  import Page from "./Page";
3
3
  import SegmentPage from "./SegmentPage";
4
4
 
5
- const FullPage = ({ path, config, location, match, modulePrependPath, isVisible }) => {
6
- const { component, componentProps, pages = {}, segments, subpages, entityIdResolver } = config;
5
+ const FullPage = ({ path, config, location, match, modulePrependPath, isVisible = true }) => {
6
+ const {
7
+ component,
8
+ routerComponent = null,
9
+ componentProps,
10
+ pages = {},
11
+ segments,
12
+ subpages,
13
+ entityIdResolver,
14
+ } = config;
7
15
  if (segments) {
8
16
  return (
9
17
  <SegmentPage
@@ -21,12 +29,12 @@ const FullPage = ({ path, config, location, match, modulePrependPath, isVisible
21
29
  return (
22
30
  <Page
23
31
  path={path}
24
- component={component}
32
+ component={component ?? routerComponent}
25
33
  pages={pages}
26
34
  subpages={subpages}
27
35
  location={location}
28
36
  match={match}
29
- isVisible={isVisible}
37
+ isVisible={isVisible === true || routerComponent != null}
30
38
  modulePrependPath={modulePrependPath}
31
39
  />
32
40
  );
@@ -86,6 +86,30 @@ describe("Fullpage", () => {
86
86
  <View2 />,
87
87
  ));
88
88
 
89
+ it("shows a page when there is a router component no matter how visible is set", () =>
90
+ expect(
91
+ <TestWrapper
92
+ provider={{ store }}
93
+ memoryRouter={{ initialEntries: ["/meep/snap/stuff"] }}
94
+ stylesProvider
95
+ muiThemeProvider={{ theme }}
96
+ >
97
+ <FullPage
98
+ path="/meep/snap"
99
+ config={{
100
+ routerComponent: View1,
101
+ pages: { "/stuff": { component: View2 } },
102
+ }}
103
+ location={{ location: true }}
104
+ match={{ match: true }}
105
+ isVisible={false}
106
+ />
107
+ </TestWrapper>,
108
+ "when mounted",
109
+ "to satisfy",
110
+ <View2 />,
111
+ ));
112
+
89
113
  it("does not show a page when not visible", () =>
90
114
  expect(
91
115
  <TestWrapper
@@ -204,10 +204,14 @@ describe("ScopeBar", () => {
204
204
  describe("Scope", () => {
205
205
  let nodeState;
206
206
  beforeEach(() => {
207
+ window.bypassDebounce = true;
208
+
207
209
  nodeState = { foo: true, bar: false };
208
210
  state = state.setIn(["view", "scopeSelector", "nodeState"], Immutable.fromJS(nodeState));
209
211
  });
210
212
 
213
+ afterEach(() => delete window.bypassDebounce);
214
+
211
215
  it("renders a scope bar, selector panel with handlers, and viewport", () => {
212
216
  const scopes = [
213
217
  {
@@ -46,8 +46,10 @@ export const namedLookupSelector = memoize((moduleName, lookupName) =>
46
46
  );
47
47
 
48
48
  export const namedLookupValuesSelector = memoize((moduleName, lookupName) =>
49
- createSelector(namedLookupSelector(moduleName, lookupName), currentLocaleOrDefault, (statuses, locale) =>
50
- (statuses.get("values") || Immutable.Map()).map(status => setTranslation(locale, status, "displayName")),
49
+ createSelector(namedLookupSelector(moduleName, lookupName), currentLocaleOrDefault, (lookup, locale) =>
50
+ (lookup.get("values") || Immutable.Map()).map(lookupValue =>
51
+ setTranslationWithFallbackField(locale, lookupValue, "name", "displayName"),
52
+ ),
51
53
  ),
52
54
  );
53
55
 
@@ -157,7 +159,8 @@ const definitionEntityAttributes = memoize((moduleName, entityName) =>
157
159
  ),
158
160
  );
159
161
 
160
- const filterIsBuiltInAttributes = isBuiltIn => attributes => attributes.filter(a => a.get("isBuiltIn") === isBuiltIn);
162
+ const filterIsBuiltInAttributes = isBuiltIn => attributes =>
163
+ attributes.filter(a => a.get("isBuiltIn") === isBuiltIn).sortBy(x => x.get("displayOrder"));
161
164
 
162
165
  export const definitionEntityCustomAttributesSelector = memoize((moduleName, entityName) =>
163
166
  createSelector(definitionEntityAttributes(moduleName, entityName), filterIsBuiltInAttributes(false)),
@@ -204,11 +207,15 @@ export const groupedCustomAttributesDefinitionSelector = memoize((moduleName, en
204
207
  })
205
208
  .set(
206
209
  "baseAttributes",
207
- group.filter(i => i.get("dataType") !== attributeDataType.entityReference),
210
+ group
211
+ .filter(i => i.get("dataType") !== attributeDataType.entityReference)
212
+ .sortBy(x => x.get("displayOrder")),
208
213
  )
209
214
  .set(
210
215
  "profileAttributes",
211
- group.filter(i => i.get("dataType") === attributeDataType.entityReference),
216
+ group
217
+ .filter(i => i.get("dataType") === attributeDataType.entityReference)
218
+ .sortBy(x => x.get("displayOrder")),
212
219
  );
213
220
  })
214
221
  .sortBy(x => x.get("displayOrder")),
@@ -220,8 +227,12 @@ export const customAttributesDefinitionSelector = memoize((moduleName, profileEn
220
227
  mappedDefinitionEntity(moduleName, profileEntityName),
221
228
  customAttributesSelector(moduleName, profileEntityName),
222
229
  (definition, attributes) => {
223
- const profileAttributes = attributes?.filter(a => a.get("dataType") === attributeDataType.entityReference);
224
- const baseAttributes = attributes?.filter(a => a.get("dataType") !== attributeDataType.entityReference);
230
+ const profileAttributes = attributes
231
+ ?.filter(a => a.get("dataType") === attributeDataType.entityReference)
232
+ .sortBy(x => x.get("displayOrder"));
233
+ const baseAttributes = attributes
234
+ ?.filter(a => a.get("dataType") !== attributeDataType.entityReference)
235
+ .sortBy(x => x.get("displayOrder"));
225
236
  return definition.set("baseAttributes", baseAttributes).set("profileAttributes", profileAttributes);
226
237
  },
227
238
  ),