orc-shared 5.2.0-dev.1 → 5.3.0-dev.0

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.
@@ -9,7 +9,10 @@ var _reactDatepicker = _interopRequireDefault(require("react-datepicker"));
9
9
  require("react-datepicker/dist/react-datepicker.css");
10
10
  var _TimePicker = _interopRequireDefault(require("./TimePicker"));
11
11
  var _styles = require("@material-ui/core/styles");
12
- var _excluded = ["value", "useTime", "useDate", "onChange", "dateFormat", "showTimeZone", "timeInputLabel", "readOnly", "showTimeSelectOnly", "metadata", "timePickerTimeZone", "error"];
12
+ var _timezoneHelper = require("../../../utils/timezoneHelper");
13
+ var _metadata = require("../../../selectors/metadata");
14
+ var _reactRedux = require("react-redux");
15
+ var _excluded = ["value", "useTime", "useDate", "onChange", "useTimeZone", "dateFormat", "showTimeZone", "timeInputLabel", "readOnly", "showTimeSelectOnly", "metadata", "timePickerTimeZone", "error"];
13
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
17
  (function () {
15
18
  var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
@@ -152,6 +155,8 @@ var WrappedDatePicker = function WrappedDatePicker(_ref) {
152
155
  _ref$useDate = _ref.useDate,
153
156
  useDate = _ref$useDate === void 0 ? true : _ref$useDate,
154
157
  onChange = _ref.onChange,
158
+ _ref$useTimeZone = _ref.useTimeZone,
159
+ useTimeZone = _ref$useTimeZone === void 0 ? false : _ref$useTimeZone,
155
160
  dateFormat = _ref.dateFormat,
156
161
  showTimeZone = _ref.showTimeZone,
157
162
  timeInputLabel = _ref.timeInputLabel,
@@ -164,11 +169,13 @@ var WrappedDatePicker = function WrappedDatePicker(_ref) {
164
169
  var classes = useStyles({
165
170
  readOnly: readOnly
166
171
  });
167
- var startDate = value ? new Date(value) : null;
172
+ var timeZoneName = (0, _timezoneHelper.getTimeZoneByName)(timePickerTimeZone);
173
+ var startDate = value ? timePickerTimeZone && useTimeZone ? (0, _timezoneHelper.convertTimeToLocalTimeZone)(new Date(value), timeZoneName) : new Date(value) : null;
168
174
  var disabledCls = (0, _classnames.default)(_defineProperty({}, classes.disabled, props.disabled));
175
+ var localizedTimeZoneName = (0, _reactRedux.useSelector)((0, _metadata.namedLookupLocalizedSelector)("customer", "TimeZone", timePickerTimeZone));
169
176
  var updateDate = function updateDate(date, metadata) {
170
177
  if (onChange) {
171
- onChange(date, metadata);
178
+ onChange(useTimeZone && timePickerTimeZone ? (0, _timezoneHelper.convertTimeToOtherTimeZone)(date, timeZoneName) : date, metadata);
172
179
  }
173
180
  };
174
181
  return /*#__PURE__*/_react.default.createElement("div", {
@@ -187,7 +194,7 @@ var WrappedDatePicker = function WrappedDatePicker(_ref) {
187
194
  useTime: useTime != null ? useTime : false,
188
195
  customTimeInput: useTime ? /*#__PURE__*/_react.default.createElement(_TimePicker.default, {
189
196
  showTimeZone: showTimeZone,
190
- requestedTimeZone: timePickerTimeZone
197
+ requestedTimeZone: localizedTimeZoneName
191
198
  }) : null,
192
199
  timeInputLabel: timeInputLabel != null ? timeInputLabel : "",
193
200
  readOnly: readOnly,
@@ -201,11 +208,11 @@ var WrappedDatePicker = function WrappedDatePicker(_ref) {
201
208
  className: classes.errorText
202
209
  }, error));
203
210
  };
204
- __signature__(WrappedDatePicker, "useStyles{classes}", function () {
205
- return [useStyles];
211
+ __signature__(WrappedDatePicker, "useStyles{classes}\nuseSelector{localizedTimeZoneName}", function () {
212
+ return [useStyles, _reactRedux.useSelector];
206
213
  });
207
- __signature__(WrappedDatePicker, "useStyles{classes}", function () {
208
- return [useStyles];
214
+ __signature__(WrappedDatePicker, "useStyles{classes}\nuseSelector{localizedTimeZoneName}", function () {
215
+ return [useStyles, _reactRedux.useSelector];
209
216
  });
210
217
  var _default = WrappedDatePicker;
211
218
  var _default2 = _default;
@@ -132,6 +132,7 @@ var InputBase = function InputBase(_ref) {
132
132
  var endAdornment = inputProps == null ? void 0 : inputProps.get(_InputBaseProps.default.propNames.endAdornment);
133
133
  var metadata = inputProps == null ? void 0 : inputProps.get(_InputBaseProps.default.propNames.metadata);
134
134
  var autoComplete = inputProps == null ? void 0 : inputProps.get(_InputBaseProps.default.propNames.autoComplete);
135
+ var timeoutDelay = (inputProps == null ? void 0 : inputProps.get(_InputBaseProps.default.propNames.timeoutDelay)) || 100;
135
136
  var tooltipText = type === "text" ? value : "";
136
137
  var onClick = function onClick(item) {
137
138
  // Fixes FireFox issue, where the input number buttons do not focus on input control,
@@ -162,7 +163,7 @@ var InputBase = function InputBase(_ref) {
162
163
  var updateValue = update(inputText, metadata);
163
164
  setInputText(null);
164
165
  return updateValue;
165
- }, 100);
166
+ }, timeoutDelay);
166
167
  return function () {
167
168
  return clearTimeout(timeOutId);
168
169
  };
@@ -43,6 +43,7 @@ var InputBaseProps = /*#__PURE__*/function (_ComponentProps) {
43
43
  _this.componentProps.set(_this.constructor.propNames.endAdornment, null);
44
44
  _this.componentProps.set(_this.constructor.propNames.metadata, null);
45
45
  _this.componentProps.set(_this.constructor.propNames.autoComplete, null);
46
+ _this.componentProps.set(_this.constructor.propNames.timeoutDelay, null);
46
47
  _this.componentClasses.set(_this.constructor.ruleNames.input, null);
47
48
  _this.componentClasses.set(_this.constructor.ruleNames.errorText, null);
48
49
  _this._isInputProps = true;
@@ -71,7 +72,8 @@ _defineProperty(InputBaseProps, "propNames", {
71
72
  startAdornment: "startAdornment",
72
73
  endAdornment: "endAdornment",
73
74
  metadata: "metadata",
74
- autoComplete: "autoComplete"
75
+ autoComplete: "autoComplete",
76
+ timeoutDelay: "timeoutDelay"
75
77
  });
76
78
  _defineProperty(InputBaseProps, "ruleNames", {
77
79
  input: "input",
@@ -238,6 +238,9 @@ var TimePicker = function TimePicker(_ref4) {
238
238
  _useState2 = _slicedToArray(_useState, 2),
239
239
  time = _useState2[0],
240
240
  setTime = _useState2[1];
241
+ (0, _react.useEffect)(function () {
242
+ setTime(parseTime(value || "00:00"));
243
+ }, [value, setTime]);
241
244
  var userTimeZone = (0, _timezoneHelper.getTimeZoneName)();
242
245
  var localizedTimeZoneName = (0, _reactRedux.useSelector)((0, _metadata.namedLookupLocalizedSelector)("customer", "TimeZone", userTimeZone, null));
243
246
  var onTimeChange = function onTimeChange(datetime) {
@@ -297,10 +300,10 @@ var TimePicker = function TimePicker(_ref4) {
297
300
  className: classes.timeZoneWrapper
298
301
  }, showTimeZone && getTimeZone(requestedTimeZone)));
299
302
  };
300
- __signature__(TimePicker, "useStyles{classes}\nuseState{[time, setTime](parseTime(value || \"00:00\"))}\nuseSelector{localizedTimeZoneName}", function () {
303
+ __signature__(TimePicker, "useStyles{classes}\nuseState{[time, setTime](parseTime(value || \"00:00\"))}\nuseEffect{}\nuseSelector{localizedTimeZoneName}", function () {
301
304
  return [useStyles, _reactRedux.useSelector];
302
305
  });
303
- __signature__(TimePicker, "useStyles{classes}\nuseState{[time, setTime](parseTime(value || \"00:00\"))}\nuseSelector{localizedTimeZoneName}", function () {
306
+ __signature__(TimePicker, "useStyles{classes}\nuseState{[time, setTime](parseTime(value || \"00:00\"))}\nuseEffect{}\nuseSelector{localizedTimeZoneName}", function () {
304
307
  return [useStyles, _reactRedux.useSelector];
305
308
  });
306
309
  var _default = TimePicker;
@@ -46,7 +46,7 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
46
46
  };
47
47
  });
48
48
  var SubPage = exports.SubPage = function SubPage(_ref) {
49
- var _props$title, _props$title2, _props$title3;
49
+ var _props$title, _props$title2, _props$title3, _props$componentProps;
50
50
  var config = _ref.config,
51
51
  match = _ref.match,
52
52
  location = _ref.location,
@@ -94,6 +94,24 @@ var SubPage = exports.SubPage = function SubPage(_ref) {
94
94
  disableElevation: true,
95
95
  onClick: closeSubPage
96
96
  }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, _sharedMessages.default.close)));
97
+ if (((_props$componentProps = props.componentProps) == null || (_props$componentProps = _props$componentProps.actionPanel()) == null ? void 0 : _props$componentProps.length) > 0) {
98
+ var _props$componentProps2;
99
+ actionPanel = /*#__PURE__*/_react.default.createElement("div", {
100
+ className: classes.actionPanel
101
+ }, (_props$componentProps2 = props.componentProps) == null ? void 0 : _props$componentProps2.actionPanel().map(function (action) {
102
+ var _action$label;
103
+ return /*#__PURE__*/_react.default.createElement(_Button.default, {
104
+ key: (_action$label = action.label) == null ? void 0 : _action$label.id,
105
+ variant: action.isPrimary ? "contained" : "outlined",
106
+ color: action.isPrimary ? "primary" : "default",
107
+ disableElevation: action.isPrimary,
108
+ onClick: function onClick(e) {
109
+ action.handler && action.handler(e);
110
+ closeSubPage();
111
+ }
112
+ }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, action.label));
113
+ }));
114
+ }
97
115
  modalProps.set(_modalProps.default.propNames.actionPanel, actionPanel);
98
116
  return /*#__PURE__*/_react.default.createElement(_Modal.default, {
99
117
  message: message,
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <path fill="#333" fill-rule="evenodd" d="M23.5,3 C23.7761424,3 24,3.22385763 24,3.5 L24,3.5 L24,8.5 C24,8.77614237 23.7761424,9 23.5,9 L23.5,9 L23,9 L23,21.5 C23,21.7454599 22.8231248,21.9496084 22.5898756,21.9919443 L22.5,22 L1.5,22 C1.22385763,22 1,21.7761424 1,21.5 L1,21.5 L1,9 L0.5,9 C0.254540111,9 0.0503916296,8.82312484 0.00805566941,8.58987563 L0,8.5 L0,3.5 C0,3.22385763 0.223857625,3 0.5,3 L0.5,3 Z M22,9 L2,9 L2,21 L22,21 L22,9 Z M15.5,11 C15.7761424,11 16,11.2238576 16,11.5 L16,11.5 L16,13.5 C16,13.7761424 15.7761424,14 15.5,14 L15.5,14 L8.5,14 C8.22385763,14 8,13.7761424 8,13.5 L8,13.5 L8,11.5 C8,11.2238576 8.22385763,11 8.5,11 L8.5,11 Z M15,12 L9,12 L9,13 L15,13 L15,12 Z M23,4 L1,4 L1,8 L23,8 L23,4 Z"/>
3
+ </svg>
@@ -8,6 +8,9 @@
8
8
  <symbol id="icon-app-list" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
9
9
  <path stroke="none" fill-rule="evenodd" d="M21,18 C22.7,18 24,19.3 24,21 C24,22.7 22.7,24 21,24 C19.3,24 18,22.7 18,21 C18,19.3 19.3,18 21,18 Z M3,0 C4.7,0 6,1.3 6,3 C6,4.7 4.7,6 3,6 C1.3,6 0,4.7 0,3 C0,1.3 1.3,0 3,0 Z M12,0 C13.7,0 15,1.3 15,3 C15,4.7 13.7,6 12,6 C10.3,6 9,4.7 9,3 C9,1.3 10.3,0 12,0 Z M21,0 C22.7,0 24,1.3 24,3 C24,4.7 22.7,6 21,6 C19.3,6 18,4.7 18,3 C18,1.3 19.3,0 21,0 Z M3,9 C4.7,9 6,10.3 6,12 C6,13.7 4.7,15 3,15 C1.3,15 0,13.7 0,12 C0,10.3 1.3,9 3,9 Z M12,9 C13.7,9 15,10.3 15,12 C15,13.7 13.7,15 12,15 C10.3,15 9,13.7 9,12 C9,10.3 10.3,9 12,9 Z M21,9 C22.7,9 24,10.3 24,12 C24,13.7 22.7,15 21,15 C19.3,15 18,13.7 18,12 C18,10.3 19.3,9 21,9 Z M3,18 C4.7,18 6,19.3 6,21 C6,22.7 4.7,24 3,24 C1.3,24 0,22.7 0,21 C0,19.3 1.3,18 3,18 Z M12,18 C13.7,18 15,19.3 15,21 C15,22.7 13.7,24 12,24 C10.3,24 9,22.7 9,21 C9,19.3 10.3,18 12,18 Z"/>
10
10
  </symbol>
11
+ <symbol id="icon-archives" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
12
+ <path stroke="none" fill-rule="evenodd" d="M23.5,3 C23.7761424,3 24,3.22385763 24,3.5 L24,3.5 L24,8.5 C24,8.77614237 23.7761424,9 23.5,9 L23.5,9 L23,9 L23,21.5 C23,21.7454599 22.8231248,21.9496084 22.5898756,21.9919443 L22.5,22 L1.5,22 C1.22385763,22 1,21.7761424 1,21.5 L1,21.5 L1,9 L0.5,9 C0.254540111,9 0.0503916296,8.82312484 0.00805566941,8.58987563 L0,8.5 L0,3.5 C0,3.22385763 0.223857625,3 0.5,3 L0.5,3 Z M22,9 L2,9 L2,21 L22,21 L22,9 Z M15.5,11 C15.7761424,11 16,11.2238576 16,11.5 L16,11.5 L16,13.5 C16,13.7761424 15.7761424,14 15.5,14 L15.5,14 L8.5,14 C8.22385763,14 8,13.7761424 8,13.5 L8,13.5 L8,11.5 C8,11.2238576 8.22385763,11 8.5,11 L8.5,11 Z M15,12 L9,12 L9,13 L15,13 L15,12 Z M23,4 L1,4 L1,8 L23,8 L23,4 Z"/>
13
+ </symbol>
11
14
  <symbol id="icon-arrow-large-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 21">
12
15
  <path stroke="none" fill-rule="evenodd" d="M8.79069767,17.6511628 C8.69302326,17.6511628 8.59534884,17.6511628 8.49767442,17.5534884 L0.195348837,10.7162791 C0.0976744186,10.6186047 0,10.5209302 0,10.3255814 C0,10.1302326 0.0976744186,10.0325581 0.195348837,9.93488372 L8.49767442,3.09767442 C8.59534884,3 8.79069767,3 8.98604651,3 C9.18139535,3.09767442 9.27906977,3.29302326 9.27906977,3.48837209 L9.27906977,6.90697674 L20.5116279,6.90697674 C20.8046512,6.90697674 21,7.10232558 21,7.39534884 L21,13.255814 C21,13.5488372 20.8046512,13.744186 20.5116279,13.744186 L9.27906977,13.744186 L9.27906977,17.1627907 C9.27906977,17.3581395 9.18139535,17.5534884 8.98604651,17.6511628 C8.88837209,17.6511628 8.88837209,17.6511628 8.79069767,17.6511628 Z M1.26976744,10.3255814 L8.30232558,16.0883721 L8.30232558,13.255814 C8.30232558,12.9627907 8.49767442,12.7674419 8.79069767,12.7674419 L20.0232558,12.7674419 L20.0232558,7.88372093 L8.79069767,7.88372093 C8.49767442,7.88372093 8.30232558,7.68837209 8.30232558,7.39534884 L8.30232558,4.5627907 L1.26976744,10.3255814 Z"/>
13
16
  </symbol>
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.timeZonesList = exports.getTimeZoneName = exports.getTimeZoneByName = exports.getTimeZone = void 0;
4
+ exports.timeZonesList = exports.getTimeZoneName = exports.getTimeZoneByName = exports.getTimeZone = exports.convertTimeToOtherTimeZone = exports.convertTimeToLocalTimeZone = void 0;
5
+ var _momentTimezone = _interopRequireDefault(require("moment-timezone"));
6
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
5
7
  (function () {
6
8
  var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
7
9
  enterModule && enterModule(module);
@@ -41,6 +43,22 @@ var getTimeZoneName = exports.getTimeZoneName = function getTimeZoneName() {
41
43
  var timezoneName = timeZonesList.get(customerTimezone);
42
44
  return timezoneName;
43
45
  };
46
+
47
+ //converting time from other timezone to local
48
+ var convertTimeToLocalTimeZone = exports.convertTimeToLocalTimeZone = function convertTimeToLocalTimeZone(date, timezone) {
49
+ var dateWithoutZone = _momentTimezone.default.tz(date, timezone).format("YYYY-MM-DDTHH:mm:ss.SSS");
50
+ var localZone = (0, _momentTimezone.default)(dateWithoutZone).format("Z");
51
+ var dateWithLocalZone = [dateWithoutZone, localZone].join("");
52
+ return new Date(dateWithLocalZone);
53
+ };
54
+
55
+ //converting time from local timezone to other
56
+ var convertTimeToOtherTimeZone = exports.convertTimeToOtherTimeZone = function convertTimeToOtherTimeZone(date, timezone) {
57
+ var dateWithoutZone = (0, _momentTimezone.default)(date).format("YYYY-MM-DDTHH:mm:ss.SSS");
58
+ var otherZone = _momentTimezone.default.tz(date, timezone).format("Z");
59
+ var dateWithOtherZone = [dateWithoutZone, otherZone].join("");
60
+ return new Date(dateWithOtherZone);
61
+ };
44
62
  var timeZonesList = exports.timeZonesList = new Map([["Africa/Bangui", "W. Central Africa Standard Time"], ["Africa/Cairo", "Egypt Standard Time"], ["Africa/Casablanca", "Morocco Standard Time"], ["Africa/Harare", "South Africa Standard Time"], ["Africa/Johannesburg", "South Africa Standard Time"], ["Africa/Lagos", "W. Central Africa Standard Time"], ["Africa/Monrovia", "Greenwich Standard Time"], ["Africa/Nairobi", "E. Africa Standard Time"], ["Africa/Windhoek", "Namibia Standard Time"], ["America/Anchorage", "Alaskan Standard Time"], ["America/Argentina/San_Juan", "Argentina Standard Time"], ["America/Asuncion", "Paraguay Standard Time"], ["America/Bahia", "Bahia Standard Time"], ["America/Bogota", "SA Pacific Standard Time"], ["America/Buenos_Aires", "Argentina Standard Time"], ["America/Caracas", "Venezuela Standard Time"], ["America/Cayenne", "SA Eastern Standard Time"], ["America/Chicago", "Central Standard Time"], ["America/Chihuahua", "Mountain Standard Time (Mexico)"], ["America/Cuiaba", "Central Brazilian Standard Time"], ["America/Denver", "Mountain Standard Time"], ["America/Fortaleza", "SA Eastern Standard Time"], ["America/Godthab", "Greenland Standard Time"], ["America/Guatemala", "Central America Standard Time"], ["America/Halifax", "Atlantic Standard Time"], ["America/Indianapolis", "US Eastern Standard Time"], ["America/Indiana/Indianapolis", "US Eastern Standard Time"], ["America/La_Paz", "SA Western Standard Time"], ["America/Los_Angeles", "Pacific Standard Time"], ["America/Mexico_City", "Mexico Standard Time"], ["America/Montevideo", "Montevideo Standard Time"], ["America/New_York", "Eastern Standard Time"], ["America/Noronha", "UTC-02"], ["America/Phoenix", "US Mountain Standard Time"], ["America/Regina", "Canada Central Standard Time"], ["America/Santa_Isabel", "Pacific Standard Time (Mexico)"], ["America/Santiago", "Pacific SA Standard Time"], ["America/Sao_Paulo", "E. South America Standard Time"], ["America/St_Johns", "Newfoundland Standard Time"], ["America/Tijuana", "Pacific Standard Time"], ["Antarctica/McMurdo", "New Zealand Standard Time"], ["Atlantic/South_Georgia", "UTC-02"], ["Asia/Almaty", "Central Asia Standard Time"], ["Asia/Amman", "Jordan Standard Time"], ["Asia/Baghdad", "Arabic Standard Time"], ["Asia/Baku", "Azerbaijan Standard Time"], ["Asia/Bangkok", "SE Asia Standard Time"], ["Asia/Beirut", "Middle East Standard Time"], ["Asia/Calcutta", "India Standard Time"], ["Asia/Colombo", "Sri Lanka Standard Time"], ["Asia/Damascus", "Syria Standard Time"], ["Asia/Dhaka", "Bangladesh Standard Time"], ["Asia/Dubai", "Arabian Standard Time"], ["Asia/Irkutsk", "North Asia East Standard Time"], ["Asia/Jerusalem", "Israel Standard Time"], ["Asia/Kabul", "Afghanistan Standard Time"], ["Asia/Kamchatka", "Kamchatka Standard Time"], ["Asia/Karachi", "Pakistan Standard Time"], ["Asia/Katmandu", "Nepal Standard Time"], ["Asia/Kolkata", "India Standard Time"], ["Asia/Krasnoyarsk", "North Asia Standard Time"], ["Asia/Kuala_Lumpur", "Singapore Standard Time"], ["Asia/Kuwait", "Arab Standard Time"], ["Asia/Magadan", "Magadan Standard Time"], ["Asia/Muscat", "Arabian Standard Time"], ["Asia/Novosibirsk", "N. Central Asia Standard Time"], ["Asia/Oral", "West Asia Standard Time"], ["Asia/Rangoon", "Myanmar Standard Time"], ["Asia/Riyadh", "Arab Standard Time"], ["Asia/Seoul", "Korea Standard Time"], ["Asia/Shanghai", "China Standard Time"], ["Asia/Singapore", "Singapore Standard Time"], ["Asia/Taipei", "Taipei Standard Time"], ["Asia/Tashkent", "West Asia Standard Time"], ["Asia/Tbilisi", "Georgian Standard Time"], ["Asia/Tehran", "Iran Standard Time"], ["Asia/Tokyo", "Tokyo Standard Time"], ["Asia/Ulaanbaatar", "Ulaanbaatar Standard Time"], ["Asia/Vladivostok", "Vladivostok Standard Time"], ["Asia/Yakutsk", "Yakutsk Standard Time"], ["Asia/Yekaterinburg", "Ekaterinburg Standard Time"], ["Asia/Yerevan", "Armenian Standard Time"], ["Atlantic/Azores", "Azores Standard Time"], ["Atlantic/Cape_Verde", "Cape Verde Standard Time"], ["Atlantic/Reykjavik", "Greenwich Standard Time"], ["Australia/Adelaide", "Cen. Australia Standard Time"], ["Australia/Brisbane", "E. Australia Standard Time"], ["Australia/Darwin", "AUS Central Standard Time"], ["Australia/Hobart", "Tasmania Standard Time"], ["Australia/Perth", "W. Australia Standard Time"], ["Australia/Sydney", "AUS Eastern Standard Time"], ["UTC", "UTC"], ["Etc/GMT+11", "UTC-11"], ["Etc/GMT+12", "Dateline Standard Time"], ["Etc/GMT+2", "UTC-02"], ["Etc/GMT-12", "UTC+12"], ["Europe/Amsterdam", "W. Europe Standard Time"], ["Europe/Athens", "GTB Standard Time"], ["Europe/Belgrade", "Central Europe Standard Time"], ["Europe/Berlin", "W. Europe Standard Time"], ["Europe/Brussels", "Romance Standard Time"], ["Europe/Budapest", "Central Europe Standard Time"], ["Europe/Dublin", "GMT Standard Time"], ["Europe/Helsinki", "FLE Standard Time"], ["Europe/Istanbul", "GTB Standard Time"], ["Europe/Kiev", "FLE Standard Time"], ["Europe/London", "GMT Standard Time"], ["Europe/Minsk", "E. Europe Standard Time"], ["Europe/Moscow", "Russian Standard Time"], ["Europe/Paris", "Romance Standard Time"], ["Europe/Sarajevo", "Central European Standard Time"], ["Europe/Warsaw", "Central European Standard Time"], ["Indian/Mauritius", "Mauritius Standard Time"], ["Pacific/Apia", "Samoa Standard Time"], ["Pacific/Auckland", "New Zealand Standard Time"], ["Pacific/Fiji", "Fiji Standard Time"], ["Pacific/Guadalcanal", "Central Pacific Standard Time"], ["Pacific/Guam", "West Pacific Standard Time"], ["Pacific/Honolulu", "Hawaiian Standard Time"], ["Pacific/Pago_Pago", "UTC-11"], ["Pacific/Port_Moresby", "West Pacific Standard Time"], ["Pacific/Tongatapu", "Tonga Standard Time"]]);
45
63
  ;
46
64
  (function () {
@@ -51,6 +69,8 @@ var timeZonesList = exports.timeZonesList = new Map([["Africa/Bangui", "W. Centr
51
69
  reactHotLoader.register(getTimeZone, "getTimeZone", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
52
70
  reactHotLoader.register(getTimeZoneByName, "getTimeZoneByName", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
53
71
  reactHotLoader.register(getTimeZoneName, "getTimeZoneName", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
72
+ reactHotLoader.register(convertTimeToLocalTimeZone, "convertTimeToLocalTimeZone", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
73
+ reactHotLoader.register(convertTimeToOtherTimeZone, "convertTimeToOtherTimeZone", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
54
74
  reactHotLoader.register(timeZonesList, "timeZonesList", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
55
75
  })();
56
76
  ;
@@ -67,6 +87,8 @@ var timeZonesList = exports.timeZonesList = new Map([["Africa/Bangui", "W. Centr
67
87
  reactHotLoader.register(getTimeZone, "getTimeZone", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
68
88
  reactHotLoader.register(getTimeZoneByName, "getTimeZoneByName", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
69
89
  reactHotLoader.register(getTimeZoneName, "getTimeZoneName", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
90
+ reactHotLoader.register(convertTimeToLocalTimeZone, "convertTimeToLocalTimeZone", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
91
+ reactHotLoader.register(convertTimeToOtherTimeZone, "convertTimeToOtherTimeZone", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
70
92
  reactHotLoader.register(timeZonesList, "timeZonesList", "/home/vsts/work/1/s/src/utils/timezoneHelper.js");
71
93
  })();
72
94
  ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orc-shared",
3
- "version": "5.2.0-dev.1",
3
+ "version": "5.3.0-dev.0",
4
4
  "description": "Shared code for Orckestra applications",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
@@ -49,7 +49,10 @@
49
49
  ],
50
50
  "devDependencies": {},
51
51
  "peerDependencies": {
52
- "orc-scripts": "1.6.0"
52
+ "orc-scripts": "1.8.0-dev.2"
53
+ },
54
+ "dependencies": {
55
+ "orc-scripts": "1.8.0-dev.2"
53
56
  },
54
57
  "sideEffects": false,
55
58
  "lint-staged": {
@@ -67,8 +70,5 @@
67
70
  "hooks": {
68
71
  "pre-commit": "lint-staged"
69
72
  }
70
- },
71
- "dependencies": {
72
- "orc-scripts": "1.6.0"
73
73
  }
74
74
  }
@@ -59,6 +59,24 @@ describe("InputField", () => {
59
59
  field_fieldName: { wasBlurred: true },
60
60
  activeForm_fieldName: { wasBlurred: true },
61
61
  },
62
+ metadata: {
63
+ lookups: {
64
+ customer: {
65
+ index: {
66
+ TimeZone: {
67
+ values: {
68
+ UTC: {
69
+ value: "UTC",
70
+ displayName: {
71
+ "en-US": "(UTC) Coordinated Universal Time",
72
+ },
73
+ },
74
+ },
75
+ },
76
+ },
77
+ },
78
+ },
79
+ },
62
80
  });
63
81
  store = {
64
82
  subscribe: () => {},
@@ -14,6 +14,24 @@ describe("DateInput", () => {
14
14
  locale: {
15
15
  locale: "en-CA",
16
16
  },
17
+ metadata: {
18
+ lookups: {
19
+ customer: {
20
+ index: {
21
+ TimeZone: {
22
+ values: {
23
+ UTC: {
24
+ value: "UTC",
25
+ displayName: {
26
+ "en-US": "(UTC) Coordinated Universal Time",
27
+ },
28
+ },
29
+ },
30
+ },
31
+ },
32
+ },
33
+ },
34
+ },
17
35
  });
18
36
 
19
37
  store = {
@@ -5,6 +5,13 @@ import DatePicker from "react-datepicker";
5
5
  import "react-datepicker/dist/react-datepicker.css";
6
6
  import TimePicker from "./TimePicker";
7
7
  import { makeStyles } from "@material-ui/core/styles";
8
+ import {
9
+ getTimeZoneByName,
10
+ convertTimeToOtherTimeZone,
11
+ convertTimeToLocalTimeZone,
12
+ } from "../../../utils/timezoneHelper";
13
+ import { namedLookupLocalizedSelector } from "../../../selectors/metadata";
14
+ import { useSelector } from "react-redux";
8
15
 
9
16
  const useStyles = makeStyles(theme => ({
10
17
  container: {
@@ -120,6 +127,7 @@ const WrappedDatePicker = ({
120
127
  useTime,
121
128
  useDate = true,
122
129
  onChange,
130
+ useTimeZone = false,
123
131
  dateFormat,
124
132
  showTimeZone,
125
133
  timeInputLabel,
@@ -131,12 +139,18 @@ const WrappedDatePicker = ({
131
139
  ...props
132
140
  }) => {
133
141
  const classes = useStyles({ readOnly });
134
- const startDate = value ? new Date(value) : null;
142
+ const timeZoneName = getTimeZoneByName(timePickerTimeZone);
143
+ const startDate = value
144
+ ? timePickerTimeZone && useTimeZone
145
+ ? convertTimeToLocalTimeZone(new Date(value), timeZoneName)
146
+ : new Date(value)
147
+ : null;
135
148
  const disabledCls = classNames({ [classes.disabled]: props.disabled });
149
+ const localizedTimeZoneName = useSelector(namedLookupLocalizedSelector("customer", "TimeZone", timePickerTimeZone));
136
150
 
137
151
  const updateDate = (date, metadata) => {
138
152
  if (onChange) {
139
- onChange(date, metadata);
153
+ onChange(useTimeZone && timePickerTimeZone ? convertTimeToOtherTimeZone(date, timeZoneName) : date, metadata);
140
154
  }
141
155
  };
142
156
 
@@ -152,7 +166,7 @@ const WrappedDatePicker = ({
152
166
  showTimeInput={useTime ?? false}
153
167
  useTime={useTime ?? false}
154
168
  customTimeInput={
155
- useTime ? <TimePicker showTimeZone={showTimeZone} requestedTimeZone={timePickerTimeZone} /> : null
169
+ useTime ? <TimePicker showTimeZone={showTimeZone} requestedTimeZone={localizedTimeZoneName} /> : null
156
170
  }
157
171
  timeInputLabel={timeInputLabel ?? ""}
158
172
  readOnly={readOnly}
@@ -15,8 +15,25 @@ describe("DatePicker", () => {
15
15
  locale: {
16
16
  locale: "en-CA",
17
17
  },
18
+ metadata: {
19
+ lookups: {
20
+ customer: {
21
+ index: {
22
+ TimeZone: {
23
+ values: {
24
+ UTC: {
25
+ value: "Eastern Standard Time",
26
+ displayName: {
27
+ "en-US": "Eastern Standard Time",
28
+ },
29
+ },
30
+ },
31
+ },
32
+ },
33
+ },
34
+ },
35
+ },
18
36
  });
19
-
20
37
  store = {
21
38
  subscribe: () => {},
22
39
  dispatch: () => {},
@@ -311,6 +328,131 @@ describe("DatePicker", () => {
311
328
 
312
329
  input.at(0).simulate("change", event);
313
330
  });
331
+
332
+ it("should call onChange prop with timezone", () => {
333
+ const onChangeMock = jest.fn();
334
+ const date = new Date("2020-06-30T00:00:00");
335
+ const event = {
336
+ preventDefault() {},
337
+ target: { value: "" },
338
+ };
339
+ const requestTimeZone = "Eastern Standard Time";
340
+
341
+ const component = (
342
+ <TestWrapper provider={{ store }} intlProvider>
343
+ <DatePicker
344
+ onChange={onChangeMock}
345
+ value={date}
346
+ useTime={true}
347
+ useDate={false}
348
+ showTimeSelectOnly={true}
349
+ timePickerTimeZone={requestTimeZone}
350
+ />
351
+ </TestWrapper>
352
+ );
353
+ const mountedComponent = mount(component);
354
+
355
+ const input = mountedComponent.find("input");
356
+ input.at(0).simulate("change", event);
357
+ expect(onChangeMock.mock.calls.length, "to equal", 1);
358
+ });
359
+
360
+ it("should call onChange prop with null timezone", () => {
361
+ const onChangeMock = jest.fn();
362
+ const date = new Date("2020-06-30T00:00:00");
363
+ const event = {
364
+ preventDefault() {},
365
+ target: { value: "" },
366
+ };
367
+
368
+ const component = (
369
+ <TestWrapper provider={{ store }} intlProvider>
370
+ <DatePicker
371
+ onChange={onChangeMock}
372
+ value={date}
373
+ useTime={true}
374
+ useDate={false}
375
+ showTimeSelectOnly={true}
376
+ timePickerTimeZone={null}
377
+ />
378
+ </TestWrapper>
379
+ );
380
+ const mountedComponent = mount(component);
381
+
382
+ const input = mountedComponent.find("input");
383
+ input.at(0).simulate("change", event);
384
+ expect(onChangeMock.mock.calls.length, "to equal", 1);
385
+ });
386
+
387
+ it("should call onChange prop with timezone without date value", () => {
388
+ const onChangeMock = jest.fn();
389
+ const event = {
390
+ preventDefault() {},
391
+ target: { value: "" },
392
+ };
393
+ const requestTimeZone = "Eastern Standard Time";
394
+ const component = (
395
+ <TestWrapper provider={{ store }} intlProvider>
396
+ <DatePicker
397
+ onChange={onChangeMock}
398
+ useTime={true}
399
+ useDate={false}
400
+ showTimeSelectOnly={true}
401
+ timePickerTimeZone={requestTimeZone}
402
+ />
403
+ </TestWrapper>
404
+ );
405
+ const mountedComponent = mount(component);
406
+
407
+ const input = mountedComponent.find("input");
408
+ input.at(0).simulate("change", event);
409
+ });
410
+
411
+ it("should call onChange prop with timezone and not use time", () => {
412
+ const date = new Date("2020-06-30T00:00:00");
413
+ const event = {
414
+ preventDefault() {},
415
+ target: { value: "" },
416
+ };
417
+ const requestTimeZone = "Eastern Standard Time";
418
+ const component = (
419
+ <TestWrapper provider={{ store }} intlProvider>
420
+ <DatePicker value={date} useDate={false} showTimeSelectOnly={true} timePickerTimeZone={requestTimeZone} />
421
+ </TestWrapper>
422
+ );
423
+ const mountedComponent = mount(component);
424
+
425
+ const input = mountedComponent.find("input");
426
+ input.at(0).simulate("change", event);
427
+ });
428
+
429
+ it("should call onChange prop with useTimeZone", () => {
430
+ const onChangeMock = jest.fn();
431
+ const date = new Date("2020-06-30T00:00:00");
432
+ const event = {
433
+ preventDefault() {},
434
+ target: { value: "" },
435
+ };
436
+ const requestTimeZone = "Eastern Standard Time";
437
+ const component = (
438
+ <TestWrapper provider={{ store }} intlProvider>
439
+ <DatePicker
440
+ onChange={onChangeMock}
441
+ value={date}
442
+ useTime={true}
443
+ useDate={false}
444
+ useTimeZone={true}
445
+ showTimeSelectOnly={true}
446
+ timePickerTimeZone={requestTimeZone}
447
+ />
448
+ </TestWrapper>
449
+ );
450
+ const mountedComponent = mount(component);
451
+
452
+ const input = mountedComponent.find("input");
453
+ input.at(0).simulate("change", event);
454
+ expect(onChangeMock.mock.calls.length, "to equal", 1);
455
+ });
314
456
  });
315
457
 
316
458
  describe("createFormat", () => {
@@ -99,6 +99,7 @@ const InputBase = ({ inputProps }) => {
99
99
  const endAdornment = inputProps?.get(InputBaseProps.propNames.endAdornment);
100
100
  const metadata = inputProps?.get(InputBaseProps.propNames.metadata);
101
101
  const autoComplete = inputProps?.get(InputBaseProps.propNames.autoComplete);
102
+ const timeoutDelay = inputProps?.get(InputBaseProps.propNames.timeoutDelay) || 100;
102
103
 
103
104
  const tooltipText = type === "text" ? value : "";
104
105
 
@@ -133,7 +134,7 @@ const InputBase = ({ inputProps }) => {
133
134
  setInputText(null);
134
135
 
135
136
  return updateValue;
136
- }, 100);
137
+ }, timeoutDelay);
137
138
  return () => clearTimeout(timeOutId);
138
139
  }
139
140
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -17,6 +17,7 @@ class InputBaseProps extends ComponentProps {
17
17
  endAdornment: "endAdornment",
18
18
  metadata: "metadata",
19
19
  autoComplete: "autoComplete",
20
+ timeoutDelay: "timeoutDelay",
20
21
  };
21
22
 
22
23
  static ruleNames = {
@@ -41,6 +42,7 @@ class InputBaseProps extends ComponentProps {
41
42
  this.componentProps.set(this.constructor.propNames.endAdornment, null);
42
43
  this.componentProps.set(this.constructor.propNames.metadata, null);
43
44
  this.componentProps.set(this.constructor.propNames.autoComplete, null);
45
+ this.componentProps.set(this.constructor.propNames.timeoutDelay, null);
44
46
 
45
47
  this.componentClasses.set(this.constructor.ruleNames.input, null);
46
48
  this.componentClasses.set(this.constructor.ruleNames.errorText, null);
@@ -18,6 +18,7 @@ describe("InputBase Props", () => {
18
18
  "endAdornment",
19
19
  "metadata",
20
20
  "autoComplete",
21
+ "timeoutDelay",
21
22
  ];
22
23
 
23
24
  expect(InputBaseProps.propNames, "to have keys", propNames);
@@ -40,6 +41,7 @@ describe("InputBase Props", () => {
40
41
  "endAdornment",
41
42
  "metadata",
42
43
  "autoComplete",
44
+ "timeoutDelay",
43
45
  ];
44
46
 
45
47
  const ruleNames = ["input", "errorText"];
@@ -1,4 +1,4 @@
1
- import React, { useState } from "react";
1
+ import React, { useState, useEffect } from "react";
2
2
  import { makeStyles } from "@material-ui/core/styles";
3
3
  import Select from "./Select";
4
4
  import SelectProps from "./SelectProps";
@@ -180,6 +180,10 @@ const TimePicker = ({ value, onChange, showTimeZone, showAMPM, requestedTimeZone
180
180
  showAMPM = showAMPM ?? isBrowserUsingAMPM();
181
181
  const [time, setTime] = useState(parseTime(value || "00:00"));
182
182
 
183
+ useEffect(() => {
184
+ setTime(parseTime(value || "00:00"));
185
+ }, [value, setTime]);
186
+
183
187
  const userTimeZone = getTimeZoneName();
184
188
  const localizedTimeZoneName = useSelector(namedLookupLocalizedSelector("customer", "TimeZone", userTimeZone, null));
185
189
 
@@ -61,7 +61,7 @@ export const SubPage = ({ config, match, location, history, root, modulePrependP
61
61
  modalProps.set(ModalProps.propNames.type, "fullwidth");
62
62
  modalProps.set(ModalProps.propNames.backdropClickCallback, closeSubPage);
63
63
 
64
- const actionPanel = (
64
+ let actionPanel = (
65
65
  <div className={classes.actionPanel}>
66
66
  <Button variant="contained" color="primary" disableElevation onClick={closeSubPage}>
67
67
  <FormattedMessage {...sharedMessages.close} />
@@ -69,6 +69,27 @@ export const SubPage = ({ config, match, location, history, root, modulePrependP
69
69
  </div>
70
70
  );
71
71
 
72
+ if (props.componentProps?.actionPanel()?.length > 0) {
73
+ actionPanel = (
74
+ <div className={classes.actionPanel}>
75
+ {props.componentProps?.actionPanel().map(action => (
76
+ <Button
77
+ key={action.label?.id}
78
+ variant={action.isPrimary ? "contained" : "outlined"}
79
+ color={action.isPrimary ? "primary" : "default"}
80
+ disableElevation={action.isPrimary}
81
+ onClick={e => {
82
+ action.handler && action.handler(e);
83
+ closeSubPage();
84
+ }}
85
+ >
86
+ <FormattedMessage {...action.label} />
87
+ </Button>
88
+ ))}
89
+ </div>
90
+ );
91
+ }
92
+
72
93
  modalProps.set(ModalProps.propNames.actionPanel, actionPanel);
73
94
 
74
95
  return <Modal message={message} modalProps={modalProps} />;
@@ -11,7 +11,6 @@ import Modal from "../MaterialUI/DataDisplay/Modal";
11
11
  import ModalProps from "../MaterialUI/DataDisplay/modalProps";
12
12
  import Button from "@material-ui/core/Button";
13
13
  import translations from "~/translations/en-US.json";
14
-
15
14
  import { TestWrapper, createMuiTheme } from "../../utils/testUtils";
16
15
  import sharedMessages from "../../sharedMessages";
17
16
 
@@ -181,4 +180,86 @@ describe("SubPage", () => {
181
180
  expect(history.push, "to have calls satisfying", [{ args: ["/foo"] }]);
182
181
  expect(dispatch, "to have calls satisfying", [{ args: [mapHref("/foo", "/foo")] }]);
183
182
  });
183
+
184
+ it("renders action panel passed from props", () => {
185
+ const actions = () => [{ label: sharedMessages.cancel }, { label: sharedMessages.applyChanges }];
186
+
187
+ const component = (
188
+ <TestWrapper provider={{ store }} intlProvider={intlProvider} stylesProvider muiThemeProvider={{ theme }}>
189
+ <div>
190
+ <div id="outer" />
191
+ <Router history={history}>
192
+ <Route
193
+ path="/foo/bar"
194
+ render={route => (
195
+ <SubPage
196
+ config={{
197
+ component: InnerView,
198
+ set: true,
199
+ title: "Item Details",
200
+ componentProps: { actionPanel: actions },
201
+ }}
202
+ root="/foo"
203
+ path="/foo/bar"
204
+ {...route}
205
+ />
206
+ )}
207
+ />
208
+ </Router>
209
+ </div>
210
+ </TestWrapper>
211
+ );
212
+ const mountedComponent = mount(component);
213
+
214
+ const closeButton = mountedComponent.find("button").at(0);
215
+ const applyButton = mountedComponent.find("button").at(1);
216
+
217
+ closeButton.invoke("onClick")();
218
+
219
+ expect(applyButton, "not to be", null);
220
+ expect(history.push, "to have calls satisfying", [{ args: ["/foo"] }]);
221
+ expect(dispatch, "to have calls satisfying", [{ args: [mapHref("/foo", "/foo")] }]);
222
+ });
223
+
224
+ it("Executes handler from button received from props", () => {
225
+ const someEvent = sinon.spy().named("someEvent");
226
+
227
+ const actions = () => [{ label: sharedMessages.applyChanges, isPrimary: true, handler: someEvent }];
228
+
229
+ const component = (
230
+ <TestWrapper provider={{ store }} intlProvider={intlProvider} stylesProvider muiThemeProvider={{ theme }}>
231
+ <div>
232
+ <div id="outer" />
233
+ <Router history={history}>
234
+ <Route
235
+ path="/foo/bar"
236
+ render={route => (
237
+ <SubPage
238
+ config={{
239
+ component: InnerView,
240
+ set: true,
241
+ title: "Item Details",
242
+ componentProps: { actionPanel: actions },
243
+ }}
244
+ root="/foo"
245
+ path="/foo/bar"
246
+ {...route}
247
+ />
248
+ )}
249
+ />
250
+ </Router>
251
+ </div>
252
+ </TestWrapper>
253
+ );
254
+ const mountedComponent = mount(component);
255
+
256
+ const applyButton = mountedComponent.find("button").at(0);
257
+
258
+ applyButton.invoke("onClick")();
259
+
260
+ const applyButtonClassName = applyButton.props().className;
261
+ expect(applyButtonClassName, "to contain", "MuiButton-contained");
262
+ expect(applyButtonClassName, "to contain", "MuiButton-containedPrimary");
263
+ expect(someEvent, "was called");
264
+ });
184
265
  });
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <path fill="#333" fill-rule="evenodd" d="M23.5,3 C23.7761424,3 24,3.22385763 24,3.5 L24,3.5 L24,8.5 C24,8.77614237 23.7761424,9 23.5,9 L23.5,9 L23,9 L23,21.5 C23,21.7454599 22.8231248,21.9496084 22.5898756,21.9919443 L22.5,22 L1.5,22 C1.22385763,22 1,21.7761424 1,21.5 L1,21.5 L1,9 L0.5,9 C0.254540111,9 0.0503916296,8.82312484 0.00805566941,8.58987563 L0,8.5 L0,3.5 C0,3.22385763 0.223857625,3 0.5,3 L0.5,3 Z M22,9 L2,9 L2,21 L22,21 L22,9 Z M15.5,11 C15.7761424,11 16,11.2238576 16,11.5 L16,11.5 L16,13.5 C16,13.7761424 15.7761424,14 15.5,14 L15.5,14 L8.5,14 C8.22385763,14 8,13.7761424 8,13.5 L8,13.5 L8,11.5 C8,11.2238576 8.22385763,11 8.5,11 L8.5,11 Z M15,12 L9,12 L9,13 L15,13 L15,12 Z M23,4 L1,4 L1,8 L23,8 L23,4 Z"/>
3
+ </svg>
@@ -8,6 +8,9 @@
8
8
  <symbol id="icon-app-list" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
9
9
  <path stroke="none" fill-rule="evenodd" d="M21,18 C22.7,18 24,19.3 24,21 C24,22.7 22.7,24 21,24 C19.3,24 18,22.7 18,21 C18,19.3 19.3,18 21,18 Z M3,0 C4.7,0 6,1.3 6,3 C6,4.7 4.7,6 3,6 C1.3,6 0,4.7 0,3 C0,1.3 1.3,0 3,0 Z M12,0 C13.7,0 15,1.3 15,3 C15,4.7 13.7,6 12,6 C10.3,6 9,4.7 9,3 C9,1.3 10.3,0 12,0 Z M21,0 C22.7,0 24,1.3 24,3 C24,4.7 22.7,6 21,6 C19.3,6 18,4.7 18,3 C18,1.3 19.3,0 21,0 Z M3,9 C4.7,9 6,10.3 6,12 C6,13.7 4.7,15 3,15 C1.3,15 0,13.7 0,12 C0,10.3 1.3,9 3,9 Z M12,9 C13.7,9 15,10.3 15,12 C15,13.7 13.7,15 12,15 C10.3,15 9,13.7 9,12 C9,10.3 10.3,9 12,9 Z M21,9 C22.7,9 24,10.3 24,12 C24,13.7 22.7,15 21,15 C19.3,15 18,13.7 18,12 C18,10.3 19.3,9 21,9 Z M3,18 C4.7,18 6,19.3 6,21 C6,22.7 4.7,24 3,24 C1.3,24 0,22.7 0,21 C0,19.3 1.3,18 3,18 Z M12,18 C13.7,18 15,19.3 15,21 C15,22.7 13.7,24 12,24 C10.3,24 9,22.7 9,21 C9,19.3 10.3,18 12,18 Z"/>
10
10
  </symbol>
11
+ <symbol id="icon-archives" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
12
+ <path stroke="none" fill-rule="evenodd" d="M23.5,3 C23.7761424,3 24,3.22385763 24,3.5 L24,3.5 L24,8.5 C24,8.77614237 23.7761424,9 23.5,9 L23.5,9 L23,9 L23,21.5 C23,21.7454599 22.8231248,21.9496084 22.5898756,21.9919443 L22.5,22 L1.5,22 C1.22385763,22 1,21.7761424 1,21.5 L1,21.5 L1,9 L0.5,9 C0.254540111,9 0.0503916296,8.82312484 0.00805566941,8.58987563 L0,8.5 L0,3.5 C0,3.22385763 0.223857625,3 0.5,3 L0.5,3 Z M22,9 L2,9 L2,21 L22,21 L22,9 Z M15.5,11 C15.7761424,11 16,11.2238576 16,11.5 L16,11.5 L16,13.5 C16,13.7761424 15.7761424,14 15.5,14 L15.5,14 L8.5,14 C8.22385763,14 8,13.7761424 8,13.5 L8,13.5 L8,11.5 C8,11.2238576 8.22385763,11 8.5,11 L8.5,11 Z M15,12 L9,12 L9,13 L15,13 L15,12 Z M23,4 L1,4 L1,8 L23,8 L23,4 Z"/>
13
+ </symbol>
11
14
  <symbol id="icon-arrow-large-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 21">
12
15
  <path stroke="none" fill-rule="evenodd" d="M8.79069767,17.6511628 C8.69302326,17.6511628 8.59534884,17.6511628 8.49767442,17.5534884 L0.195348837,10.7162791 C0.0976744186,10.6186047 0,10.5209302 0,10.3255814 C0,10.1302326 0.0976744186,10.0325581 0.195348837,9.93488372 L8.49767442,3.09767442 C8.59534884,3 8.79069767,3 8.98604651,3 C9.18139535,3.09767442 9.27906977,3.29302326 9.27906977,3.48837209 L9.27906977,6.90697674 L20.5116279,6.90697674 C20.8046512,6.90697674 21,7.10232558 21,7.39534884 L21,13.255814 C21,13.5488372 20.8046512,13.744186 20.5116279,13.744186 L9.27906977,13.744186 L9.27906977,17.1627907 C9.27906977,17.3581395 9.18139535,17.5534884 8.98604651,17.6511628 C8.88837209,17.6511628 8.88837209,17.6511628 8.79069767,17.6511628 Z M1.26976744,10.3255814 L8.30232558,16.0883721 L8.30232558,13.255814 C8.30232558,12.9627907 8.49767442,12.7674419 8.79069767,12.7674419 L20.0232558,12.7674419 L20.0232558,7.88372093 L8.79069767,7.88372093 C8.49767442,7.88372093 8.30232558,7.68837209 8.30232558,7.39534884 L8.30232558,4.5627907 L1.26976744,10.3255814 Z"/>
13
16
  </symbol>
@@ -1,3 +1,5 @@
1
+ import moment from "moment-timezone";
2
+
1
3
  export const getTimeZone = () => Intl.DateTimeFormat().resolvedOptions().timeZone;
2
4
 
3
5
  export const getTimeZoneByName = name => {
@@ -14,6 +16,22 @@ export const getTimeZoneName = () => {
14
16
  return timezoneName;
15
17
  };
16
18
 
19
+ //converting time from other timezone to local
20
+ export const convertTimeToLocalTimeZone = (date, timezone) => {
21
+ const dateWithoutZone = moment.tz(date, timezone).format("YYYY-MM-DDTHH:mm:ss.SSS");
22
+ const localZone = moment(dateWithoutZone).format("Z");
23
+ const dateWithLocalZone = [dateWithoutZone, localZone].join("");
24
+ return new Date(dateWithLocalZone);
25
+ };
26
+
27
+ //converting time from local timezone to other
28
+ export const convertTimeToOtherTimeZone = (date, timezone) => {
29
+ const dateWithoutZone = moment(date).format("YYYY-MM-DDTHH:mm:ss.SSS");
30
+ const otherZone = moment.tz(date, timezone).format("Z");
31
+ const dateWithOtherZone = [dateWithoutZone, otherZone].join("");
32
+ return new Date(dateWithOtherZone);
33
+ };
34
+
17
35
  export const timeZonesList = new Map([
18
36
  ["Africa/Bangui", "W. Central Africa Standard Time"],
19
37
  ["Africa/Cairo", "Egypt Standard Time"],
@@ -1,4 +1,10 @@
1
- import { getTimeZone, getTimeZoneByName, getTimeZoneName } from "./timezoneHelper";
1
+ import {
2
+ getTimeZone,
3
+ getTimeZoneByName,
4
+ getTimeZoneName,
5
+ convertTimeToLocalTimeZone,
6
+ convertTimeToOtherTimeZone,
7
+ } from "./timezoneHelper";
2
8
 
3
9
  describe("Timezone Helper", () => {
4
10
  beforeEach(() => {
@@ -30,4 +36,18 @@ describe("Timezone Helper", () => {
30
36
  it("Retrieves user timezone name", () => {
31
37
  expect(getTimeZoneName, "called with", [], "to satisfy", "W. Europe Standard Time");
32
38
  });
39
+
40
+ it("Retrieves user local timezone date", () => {
41
+ const timezoneName = "America/New_York";
42
+ const date = "Mon Apr 04 2022 13:00:00 GMT+0300 (Eastern European Summer Time)";
43
+ const expectedDate = new Date("2022-04-04T09:00:00Z");
44
+ expect(convertTimeToLocalTimeZone, "called with", [date, timezoneName], "to satisfy", expectedDate);
45
+ });
46
+
47
+ it("Retrieves user other timezone date", () => {
48
+ const timezoneName = "America/New_York";
49
+ const date = "Mon Apr 04 2022 03:00:00 GMT+0300 (Eastern European Summer Time)";
50
+ const expectedDate = new Date("2022-04-04T04:00:00Z");
51
+ expect(convertTimeToOtherTimeZone, "called with", [date, timezoneName], "to satisfy", expectedDate);
52
+ });
33
53
  });