orc-shared 5.10.0-dev.20 → 5.10.0-dev.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orc-shared",
3
- "version": "5.10.0-dev.20",
3
+ "version": "5.10.0-dev.21",
4
4
  "description": "Shared code for Orckestra applications",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
@@ -25,7 +25,8 @@
25
25
  "prepublishOnly": "npm run build:clean --",
26
26
  "icons": "orc-scripts buildIconsSheet",
27
27
  "extract": "orc-scripts extract-messages",
28
- "generateApi": "orc-scripts generateApi --outputFile src/actions/requestsApi.js --requestsFile ./src/requests"
28
+ "generateApi": "orc-scripts generateApi --outputFile src/actions/requestsApi.js --requestsFile ./src/requests",
29
+ "generateWindowsZone": "orc-scripts generateWindowsZone --outputFile src/timezones.json"
29
30
  },
30
31
  "files": [
31
32
  "src",
@@ -55,7 +56,7 @@
55
56
  "@testing-library/react": "^10.4.9"
56
57
  },
57
58
  "dependencies": {
58
- "orc-scripts": "4.0.5",
59
+ "orc-scripts": "4.0.7",
59
60
  "react-number-format": "^5.3.0"
60
61
  },
61
62
  "sideEffects": false,
@@ -1,23 +1,33 @@
1
- import React from "react";
2
- import { useMemo } from "react";
3
- import { useSelector } from "react-redux";
4
- import { currentLocaleOrDefault } from "../selectors/locale";
1
+ import React, { useMemo } from "react";
2
+ import { useIntl } from "react-intl";
5
3
  import { registerLocale, setDefaultLocale } from "react-datepicker";
6
4
  import * as date_fns_locale from "date-fns/locale";
7
5
  import { findCorrespondingLocale } from "../utils/localizationHelper";
6
+ import useDaysAndMonthsLocalization from "../hooks/useDaysAndMonthsLocalization";
7
+
8
+ export let customFnsLocale = null;
8
9
 
9
10
  const Culture = () => {
10
- const locale = useSelector(currentLocaleOrDefault);
11
- const language = navigator.language ?? locale;
11
+ const { locale } = useIntl();
12
+ const daysAndMonthsLocalization = useDaysAndMonthsLocalization();
12
13
 
13
14
  useMemo(() => {
14
- const fnsLocale = findCorrespondingLocale(date_fns_locale, language);
15
+ const fnsLocale = findCorrespondingLocale(date_fns_locale, locale);
15
16
 
16
17
  if (fnsLocale != null) {
17
- registerLocale(language, fnsLocale);
18
- setDefaultLocale(language);
18
+ customFnsLocale = {
19
+ ...fnsLocale,
20
+ localize: {
21
+ ...fnsLocale.localize,
22
+ day: n => daysAndMonthsLocalization.weekdaysMin[n],
23
+ month: n => daysAndMonthsLocalization.months[n],
24
+ },
25
+ };
26
+
27
+ registerLocale(locale, customFnsLocale);
28
+ setDefaultLocale(locale);
19
29
  }
20
- }, [language]);
30
+ }, [locale, daysAndMonthsLocalization]);
21
31
 
22
32
  return <React.Fragment />;
23
33
  };
@@ -1,21 +1,24 @@
1
1
  import React from "react";
2
2
  import Immutable from "immutable";
3
- import { Provider } from "react-redux";
4
3
  import { getDefaultLocale } from "react-datepicker";
5
- import Culture from "./Culture";
4
+ import Culture, { customFnsLocale } from "./Culture";
5
+ import { extractMessages, TestWrapper } from "../utils/testUtils";
6
+ import sharedMessages from "../sharedMessages";
7
+ import { mount } from "enzyme";
8
+
9
+ const messages = extractMessages(sharedMessages);
6
10
 
7
11
  describe("Culture", () => {
8
- let state, store, languageGetter;
12
+ let state, store;
9
13
 
10
14
  beforeEach(() => {
11
- languageGetter = jest.spyOn(window.navigator, "language", "get");
12
-
13
15
  state = Immutable.fromJS({
14
16
  requests: {},
15
17
  settings: {
16
18
  defaultScope: "aDefaultScope",
17
19
  },
18
20
  locale: {
21
+ locale: "en-US",
19
22
  supportedLocales: [
20
23
  { language: "English", cultureIso: "en" },
21
24
  { language: "Français", cultureIso: "fr" },
@@ -30,17 +33,14 @@ describe("Culture", () => {
30
33
  });
31
34
 
32
35
  afterEach(() => {
33
- languageGetter.mockReset();
34
36
  jest.clearAllMocks();
35
37
  });
36
38
 
37
39
  it("shows the wrapped component if authenticated and default scope is known", () => {
38
- languageGetter.mockReturnValue(null);
39
-
40
40
  const component = (
41
- <Provider store={store}>
41
+ <TestWrapper provider={{ store }} intlProvider={{ messages, locale: "zz-ZZ" }}>
42
42
  <Culture />
43
- </Provider>
43
+ </TestWrapper>
44
44
  );
45
45
 
46
46
  expect(component, "when mounted", "to satisfy", null);
@@ -50,12 +50,11 @@ describe("Culture", () => {
50
50
 
51
51
  it("shows the wrapped component if authenticated and default scope is known 222", () => {
52
52
  state = state.setIn(["locale", "supportedLocales"], [{ language: "English", cultureIso: "en" }]);
53
- languageGetter.mockReturnValue("en-GB");
54
53
 
55
54
  const component = (
56
- <Provider store={store}>
55
+ <TestWrapper provider={{ store }} intlProvider={{ messages, locale: "en-GB" }}>
57
56
  <Culture />
58
- </Provider>
57
+ </TestWrapper>
59
58
  );
60
59
 
61
60
  expect(component, "when mounted", "to satisfy", null);
@@ -71,16 +70,28 @@ describe("Culture", () => {
71
70
  { language: "EnglishMy", cultureIso: "enMy" },
72
71
  ],
73
72
  );
74
- languageGetter.mockReturnValue("fr-FR");
75
73
 
76
74
  const component = (
77
- <Provider store={store}>
75
+ <TestWrapper provider={{ store }} intlProvider={{ messages, locale: "fr-FR" }}>
78
76
  <Culture />
79
- </Provider>
77
+ </TestWrapper>
80
78
  );
81
79
 
82
80
  expect(component, "when mounted", "to satisfy", null);
83
81
 
84
82
  expect(getDefaultLocale(), "to equal", "fr-FR");
85
83
  });
84
+
85
+ it("computes right localized day and month with Italian culture ", () => {
86
+ const component = (
87
+ <TestWrapper provider={{ store }} intlProvider={{ messages, locale: "it-IT" }}>
88
+ <Culture />
89
+ </TestWrapper>
90
+ );
91
+
92
+ mount(component);
93
+
94
+ expect(customFnsLocale.localize.day(1), "to equal", "Mo");
95
+ expect(customFnsLocale.localize.month(6), "to equal", "July");
96
+ });
86
97
  });
@@ -6,12 +6,10 @@ import "react-datepicker/dist/react-datepicker.css";
6
6
  import TimePicker from "./TimePicker";
7
7
  import { makeStyles } from "@material-ui/core/styles";
8
8
  import {
9
- getTimeZoneByName,
10
- convertTimeToOtherTimeZone,
9
+ getIanaTimeZoneFromWindowsName,
11
10
  convertTimeToLocalTimeZone,
11
+ getWindowsTimeZone,
12
12
  } from "../../../utils/timezoneHelper";
13
- import { namedLookupLocalizedSelector } from "../../../selectors/metadata";
14
- import { useSelector } from "react-redux";
15
13
 
16
14
  const useStyles = makeStyles(theme => ({
17
15
  container: {
@@ -139,24 +137,31 @@ const WrappedDatePicker = ({
139
137
  readOnly,
140
138
  showTimeSelectOnly,
141
139
  metadata,
142
- timePickerTimeZone,
140
+ timePickerWindowsTimeZone,
143
141
  error,
144
142
  timeOption,
145
143
  ...props
146
144
  }) => {
147
145
  const classes = useStyles({ readOnly });
148
- const timeZoneName = getTimeZoneByName(timePickerTimeZone);
149
- const startDate = value
150
- ? timePickerTimeZone && useTimeZone
151
- ? convertTimeToLocalTimeZone(new Date(value), timeZoneName)
152
- : new Date(value)
153
- : null;
146
+
147
+ const ianaTimeZone =
148
+ useTimeZone && timePickerWindowsTimeZone ? getIanaTimeZoneFromWindowsName(timePickerWindowsTimeZone) : null;
149
+
150
+ const computeDateWithTimezone = React.useCallback(
151
+ date => {
152
+ return date ? (ianaTimeZone ? convertTimeToLocalTimeZone(new Date(date), ianaTimeZone) : new Date(date)) : null;
153
+ },
154
+ [ianaTimeZone],
155
+ );
156
+
157
+ const startDate = computeDateWithTimezone(value);
154
158
  const disabledCls = classNames({ [classes.disabled]: props.disabled });
155
- const localizedTimeZoneName = useSelector(namedLookupLocalizedSelector("customer", "TimeZone", timePickerTimeZone));
159
+
160
+ const windowsTimeZoneName = useTime && showTimeZone ? (timePickerWindowsTimeZone ?? getWindowsTimeZone()) : null;
156
161
 
157
162
  const updateDate = (date, metadata) => {
158
163
  if (onChange) {
159
- onChange(useTimeZone && timePickerTimeZone ? convertTimeToOtherTimeZone(date, timeZoneName) : date, metadata);
164
+ onChange(computeDateWithTimezone(date), metadata);
160
165
  }
161
166
  };
162
167
 
@@ -179,13 +184,7 @@ const WrappedDatePicker = ({
179
184
  showTimeInput={useTime ?? false}
180
185
  useTime={useTime ?? false}
181
186
  customTimeInput={
182
- useTime ? (
183
- <TimePicker
184
- showTimeZone={showTimeZone}
185
- requestedTimeZone={localizedTimeZoneName}
186
- timeOption={timeOption}
187
- />
188
- ) : null
187
+ useTime ? <TimePicker windowsTimeZone={windowsTimeZoneName} timeOption={timeOption} /> : null
189
188
  }
190
189
  timeInputLabel={timeInputLabel ?? ""}
191
190
  readOnly={readOnly}
@@ -269,7 +269,7 @@ describe("DatePicker", () => {
269
269
  const expectedDate = "06/30/2020 12:00 AM";
270
270
  expect(
271
271
  <TestWrapper provider={{ store }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
272
- <DatePicker useTime={true} readOnly={true} onChange={updater} value={date} />
272
+ <DatePicker useTime={true} readOnly={true} onChange={updater} value={date} showTimeZone={true} />
273
273
  </TestWrapper>,
274
274
  "when mounted",
275
275
  "to satisfy",
@@ -348,7 +348,7 @@ describe("DatePicker", () => {
348
348
  useTime={true}
349
349
  useDate={false}
350
350
  showTimeSelectOnly={true}
351
- timePickerTimeZone={requestTimeZone}
351
+ timePickerWindowsTimeZone={requestTimeZone}
352
352
  />
353
353
  </TestWrapper>
354
354
  );
@@ -375,7 +375,7 @@ describe("DatePicker", () => {
375
375
  useTime={true}
376
376
  useDate={false}
377
377
  showTimeSelectOnly={true}
378
- timePickerTimeZone={null}
378
+ timePickerWindowsTimeZone={null}
379
379
  />
380
380
  </TestWrapper>
381
381
  );
@@ -400,7 +400,7 @@ describe("DatePicker", () => {
400
400
  useTime={true}
401
401
  useDate={false}
402
402
  showTimeSelectOnly={true}
403
- timePickerTimeZone={requestTimeZone}
403
+ timePickerWindowsTimeZone={requestTimeZone}
404
404
  />
405
405
  </TestWrapper>
406
406
  );
@@ -419,7 +419,12 @@ describe("DatePicker", () => {
419
419
  const requestTimeZone = "Eastern Standard Time";
420
420
  const component = (
421
421
  <TestWrapper provider={{ store }} intlProvider>
422
- <DatePicker value={date} useDate={false} showTimeSelectOnly={true} timePickerTimeZone={requestTimeZone} />
422
+ <DatePicker
423
+ value={date}
424
+ useDate={false}
425
+ showTimeSelectOnly={true}
426
+ timePickerWindowsTimeZone={requestTimeZone}
427
+ />
423
428
  </TestWrapper>
424
429
  );
425
430
  const mountedComponent = mount(component);
@@ -477,7 +482,7 @@ describe("DatePicker", () => {
477
482
  useDate={false}
478
483
  useTimeZone={true}
479
484
  showTimeSelectOnly={true}
480
- timePickerTimeZone={requestTimeZone}
485
+ timePickerWindowsTimeZone={requestTimeZone}
481
486
  />
482
487
  </TestWrapper>
483
488
  );
@@ -1,8 +1,9 @@
1
1
  import React, { useState, useEffect } from "react";
2
+ import { useIntl } from "react-intl";
2
3
  import { makeStyles } from "@material-ui/core/styles";
3
4
  import Select from "./Select";
4
5
  import SelectProps from "./SelectProps";
5
- import { getTimeZoneName } from "../../../utils/timezoneHelper";
6
+ import { getWindowsTimeZone } from "../../../utils/timezoneHelper";
6
7
  import { namedLookupLocalizedSelector } from "../../../selectors/metadata";
7
8
  import { useSelector } from "react-redux";
8
9
 
@@ -65,8 +66,8 @@ const ampmOptions = [
65
66
  { value: "PM", label: "PM" },
66
67
  ];
67
68
 
68
- const isBrowserUsingAMPM = () =>
69
- !!new Date(Date.UTC(2020, 7, 30, 3, 0, 0)).toLocaleTimeString().match(/am|a.m|pm|p.m/i);
69
+ const isBrowserUsingAMPM = locale =>
70
+ !!new Date(Date.UTC(2020, 7, 30, 3, 0, 0)).toLocaleTimeString(locale).match(/am|a.m|pm|p.m/i);
70
71
 
71
72
  export const parseTime = timeStr => {
72
73
  var time = timeStr.match(/(\d+)(?::(\d\d))?\s*(p?)/i);
@@ -184,17 +185,18 @@ export const MinsSelect = ({ updateTimeOptions, time, values = minOptions }) =>
184
185
  );
185
186
  };
186
187
 
187
- const TimePicker = ({ value, onChange, showTimeZone, showAMPM, requestedTimeZone, timeOption }) => {
188
+ const TimePicker = ({ value, onChange, showTimeZone, windowsTimeZone, timeOption }) => {
188
189
  const classes = useStyles();
189
- showAMPM = showAMPM ?? isBrowserUsingAMPM();
190
+ const { locale } = useIntl();
191
+ const showAMPM = isBrowserUsingAMPM(locale);
190
192
  const [time, setTime] = useState(parseTime(value || "00:00"));
191
193
 
192
194
  useEffect(() => {
193
195
  setTime(parseTime(value || "00:00"));
194
196
  }, [value, setTime]);
195
197
 
196
- const userTimeZone = getTimeZoneName();
197
- const localizedTimeZoneName = useSelector(namedLookupLocalizedSelector("customer", "TimeZone", userTimeZone, null));
198
+ const timeZone = windowsTimeZone ?? getWindowsTimeZone();
199
+ const localizedTimeZone = useSelector(namedLookupLocalizedSelector("customer", "TimeZone", timeZone));
198
200
 
199
201
  const onTimeChange = datetime => {
200
202
  if (onChange) {
@@ -227,15 +229,6 @@ const TimePicker = ({ value, onChange, showTimeZone, showAMPM, requestedTimeZone
227
229
  onTimeChange(time);
228
230
  };
229
231
 
230
- const getTimeZone = requestedTimeZone => {
231
- if (requestedTimeZone) return requestedTimeZone;
232
- if (!localizedTimeZoneName) {
233
- var timezone = new Date().toString().match(/GMT(\S+) \(([^)]+)\)/i);
234
- return `${timezone[2]} (GMT${timezone[1]})`;
235
- }
236
- return localizedTimeZoneName;
237
- };
238
-
239
232
  return (
240
233
  <div className={classes.timeWrapper}>
241
234
  <span className={classes.timePickerWrapper}>
@@ -244,9 +237,7 @@ const TimePicker = ({ value, onChange, showTimeZone, showAMPM, requestedTimeZone
244
237
  <MinsSelect updateTimeOptions={updateTimeOptions} time={time} values={timeOption?.minutes} />
245
238
  <AMPMSelect showAMPM={showAMPM} updateTimeOptions={updateTimeOptions} time={time} />
246
239
  </span>
247
- {showTimeZone && (
248
- <label className={classes.timeZoneWrapper}>{showTimeZone && getTimeZone(requestedTimeZone)}</label>
249
- )}
240
+ {showTimeZone && <label className={classes.timeZoneWrapper}>{localizedTimeZone}</label>}
250
241
  </div>
251
242
  );
252
243
  };