@deviceinsight/ng-ui-components 6.25.0 → 6.27.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.
Files changed (31) hide show
  1. package/lib/cjs/components/input/DateInput.d.ts +3 -1
  2. package/lib/cjs/components/input/DateInput.d.ts.map +1 -1
  3. package/lib/cjs/components/input/DateInput.js +37 -16
  4. package/lib/cjs/components/input/DateTimeInput.d.ts.map +1 -1
  5. package/lib/cjs/components/input/DateTimeInput.js +16 -44
  6. package/lib/cjs/components/input/__tests__/DateInput.spec.js +7 -21
  7. package/lib/cjs/components/periodpicker/components/Inputs.d.ts.map +1 -1
  8. package/lib/cjs/components/periodpicker/components/Inputs.js +11 -4
  9. package/lib/cjs/components/reactable/helpers/ReactableTableFilterRow.d.ts.map +1 -1
  10. package/lib/cjs/components/reactable/helpers/ReactableTableFilterRow.js +17 -8
  11. package/lib/esm/components/input/DateInput.d.ts +3 -1
  12. package/lib/esm/components/input/DateInput.d.ts.map +1 -1
  13. package/lib/esm/components/input/DateInput.js +37 -16
  14. package/lib/esm/components/input/DateTimeInput.d.ts.map +1 -1
  15. package/lib/esm/components/input/DateTimeInput.js +16 -44
  16. package/lib/esm/components/input/__tests__/DateInput.spec.js +7 -21
  17. package/lib/esm/components/periodpicker/components/Inputs.d.ts.map +1 -1
  18. package/lib/esm/components/periodpicker/components/Inputs.js +11 -4
  19. package/lib/esm/components/reactable/helpers/ReactableTableFilterRow.d.ts.map +1 -1
  20. package/lib/esm/components/reactable/helpers/ReactableTableFilterRow.js +17 -8
  21. package/lib/esm/src/components/input/DateInput.d.ts +3 -1
  22. package/lib/esm/src/components/input/DateInput.d.ts.map +1 -1
  23. package/lib/esm/src/components/input/DateInput.js +37 -16
  24. package/lib/esm/src/components/input/DateTimeInput.d.ts.map +1 -1
  25. package/lib/esm/src/components/input/DateTimeInput.js +16 -44
  26. package/lib/esm/src/components/input/__tests__/DateInput.spec.js +7 -21
  27. package/lib/esm/src/components/periodpicker/components/Inputs.d.ts.map +1 -1
  28. package/lib/esm/src/components/periodpicker/components/Inputs.js +11 -4
  29. package/lib/esm/src/components/reactable/helpers/ReactableTableFilterRow.d.ts.map +1 -1
  30. package/lib/esm/src/components/reactable/helpers/ReactableTableFilterRow.js +17 -8
  31. package/package.json +2 -2
@@ -1,69 +1,41 @@
1
1
  import dayjs from 'dayjs';
2
2
  import React, { useEffect, useState } from 'react';
3
- import { dayjsTz } from '../periodpicker/periods';
4
3
  import DateInput from './DateInput';
5
4
  import ValidatedTextInput from './ValidatedTextInput';
6
- import { toInteger } from 'lodash';
7
- const extractTime = (timezone, date) => {
5
+ const formatTime = (timezone, date) => {
8
6
  try {
9
- return dayjsTz(timezone, date).format('HH:mm');
7
+ return dayjs.tz(date, timezone).format('HH:mm');
10
8
  }
11
9
  catch (error) {
12
10
  console.error('DateTimeInput: Error while extracting time from date', error);
13
11
  return '00:00';
14
12
  }
15
13
  };
16
- const extractDate = (timezone, date) => {
17
- try {
18
- return dayjs(dayjsTz(timezone, date).format('YYYY-MM-DD'));
19
- }
20
- catch (error) {
21
- console.error('DateTimeInput: Error while extracting time from date', error);
22
- return dayjs(new Date());
23
- }
24
- };
25
14
  /**
26
15
  * Extends DateInput but also displaying the current time.
27
16
  * Usually the user's locale is used for displaying the correct date format.
28
17
  */
29
18
  export default function DateTimeInput({ timestamp, timezone, warning, readOnly = false, onChange, ...otherProps }) {
30
- const [time, setTime] = useState(extractTime(timezone, timestamp));
31
- const timeValue = time == null ? extractTime(timezone, timestamp) : time;
19
+ const [time, setTime] = useState(formatTime(timezone, timestamp));
20
+ const timeValue = time == null ? formatTime(timezone, timestamp) : time;
32
21
  useEffect(() => {
33
- setTime(extractTime(timezone, timestamp));
22
+ setTime(formatTime(timezone, timestamp));
34
23
  }, [timezone, timestamp]);
35
24
  function handleChangeDate(date, fromTextField) {
36
- const oldDate = dayjsTz(timezone, timestamp);
37
- const dateFix = dayjs(date);
38
- let newDate = dayjsTz(timezone, date)
39
- .set('day', dateFix.day())
40
- .set('month', dateFix.month())
41
- .set('year', dateFix.year())
42
- .set('hour', toInteger(oldDate.hour()))
43
- .set('minute', toInteger(oldDate.minute()));
44
- const dstOffset = getLocalDstOffset(newDate);
45
- newDate = newDate.subtract(dstOffset, 'minutes');
25
+ const currentDate = dayjs.tz(timestamp, timezone);
26
+ const newDate = dayjs
27
+ .tz(date, timezone)
28
+ .set('hour', currentDate.hour())
29
+ .set('minute', currentDate.minute())
30
+ .set('second', currentDate.second())
31
+ .set('millisecond', currentDate.millisecond());
46
32
  onChange(newDate.valueOf(), fromTextField);
47
33
  }
48
- function getMaxUtcOffset(year) {
49
- const jan = new Date(`${year}-01-01`).getTimezoneOffset();
50
- const jul = new Date(`${year}-07-01`).getTimezoneOffset();
51
- return Math.min(jan, jul);
52
- }
53
- function getLocalDstOffset(newDate) {
54
- return newDate.toDate().getTimezoneOffset() - getMaxUtcOffset(newDate.year());
55
- }
56
34
  function handleChangeTime(time, valid) {
57
35
  if (valid) {
58
- const [hours, minutes] = time.split(':');
59
- const date = extractDate(timezone, timestamp);
60
- const dateTime = dayjsTz(timezone, timestamp)
61
- .set('date', date.date())
62
- .set('hour', parseInt(hours, 10))
63
- .set('minute', parseInt(minutes, 10))
64
- .set('second', 0)
65
- .set('millisecond', 0);
66
- onChange(dateTime.valueOf());
36
+ const [hours, minutes] = time.split(':').map(Number);
37
+ const newDate = dayjs.tz(timestamp, timezone).set('hours', hours).set('minutes', minutes);
38
+ onChange(newDate.valueOf(), true);
67
39
  }
68
40
  setTime(time);
69
41
  }
@@ -73,7 +45,7 @@ export default function DateTimeInput({ timestamp, timezone, warning, readOnly =
73
45
  }
74
46
  }
75
47
  return (React.createElement("span", { className: `di date-time-input ${warning ? 'with-warning' : ''}` },
76
- React.createElement(DateInput, { ...otherProps, value: extractDate(timezone, timestamp).valueOf(), onChange: handleChangeDate, readOnly: readOnly }),
48
+ React.createElement(DateInput, { ...otherProps, value: timestamp, timezone: timezone, onChange: handleChangeDate, readOnly: readOnly }),
77
49
  React.createElement(ValidatedTextInput, { "data-testid": "time-input", value: timeValue, onChange: handleChangeTime, pattern: /^(([01][0-9])|2[0-3]):[0-5][0-9]$/, required: true, invalidStyle: {
78
50
  borderColor: 'red'
79
51
  }, placeholder: "00:00", className: "time", onBlur: tryFixTime, disabled: readOnly })));
@@ -16,9 +16,7 @@ describe('DateInput.js', () => {
16
16
  });
17
17
  describe('Changing values via text input', () => {
18
18
  it('should render correct date typed into text input without "invalid" class', async () => {
19
- await act(async () => {
20
- render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
21
- });
19
+ render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
22
20
  await act(async () => {
23
21
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.2019' } });
24
22
  });
@@ -26,9 +24,7 @@ describe('DateInput.js', () => {
26
24
  expect(screen.getByTestId('date-input')).not.toHaveClass('invalid');
27
25
  });
28
26
  it('should render incorrect date typed into text input with "invalid" class', async () => {
29
- await act(async () => {
30
- render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
31
- });
27
+ render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
32
28
  await act(async () => {
33
29
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.201' } });
34
30
  });
@@ -36,9 +32,7 @@ describe('DateInput.js', () => {
36
32
  });
37
33
  it('should call onChange callback with parsed value of the input during the input is being changed when the value is valid', async () => {
38
34
  const onChange = vi.fn();
39
- await act(async () => {
40
- render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
41
- });
35
+ render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
42
36
  await act(async () => {
43
37
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.2019' } });
44
38
  });
@@ -47,18 +41,14 @@ describe('DateInput.js', () => {
47
41
  });
48
42
  it('should not call onChange callback while editing the input when the input value is invalid', async () => {
49
43
  const onChange = vi.fn();
50
- await act(async () => {
51
- render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
52
- });
44
+ render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
53
45
  await act(async () => {
54
46
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.201' } });
55
47
  });
56
48
  expect(onChange).not.toHaveBeenCalled();
57
49
  });
58
50
  it('should display the current value in the input field if the input value is invalid and the input became blurred', async () => {
59
- await act(async () => {
60
- render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
61
- });
51
+ render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
62
52
  await act(async () => {
63
53
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.201' } });
64
54
  fireEvent.blur(screen.getByTestId('date-input'));
@@ -66,16 +56,12 @@ describe('DateInput.js', () => {
66
56
  expect(screen.getByTestId('date-input')).toHaveValue('01.02.2019');
67
57
  });
68
58
  it('should display invalid date text in the input when the value is NaN', async () => {
69
- await act(async () => {
70
- render(React.createElement(DateInput, { value: NaN, onChange: () => { } }));
71
- });
59
+ render(React.createElement(DateInput, { value: NaN, onChange: () => { } }));
72
60
  expect(screen.getByTestId('date-input')).toHaveValue('dateInput.invalidDate');
73
61
  });
74
62
  it('should call onChange callback with [null, true] when empty string is set to input field', async () => {
75
63
  const onChange = vi.fn();
76
- await act(async () => {
77
- render(React.createElement(DateInput, { value: Date.now(), onChange: onChange }));
78
- });
64
+ render(React.createElement(DateInput, { value: Date.now(), onChange: onChange }));
79
65
  await act(async () => {
80
66
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '' } });
81
67
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Inputs.d.ts","sourceRoot":"","sources":["../../../../../src/components/periodpicker/components/Inputs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyB,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAMhC,aAAK,KAAK,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAC,EAAE,KAAK,qBA2FnF"}
1
+ {"version":3,"file":"Inputs.d.ts","sourceRoot":"","sources":["../../../../../src/components/periodpicker/components/Inputs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyB,MAAM,OAAO,CAAC;AAG9C,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAMhC,aAAK,KAAK,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAC,EAAE,KAAK,qBAiGnF"}
@@ -1,4 +1,5 @@
1
1
  import React, { useRef, useState } from 'react';
2
+ import { isEqual } from 'lodash';
2
3
  import DateTimeInput from '../../input/DateTimeInput';
3
4
  const ONE_HOUR = 60 * 60 * 1000;
4
5
  const TOGGLE_TIMEOUT = 300;
@@ -25,10 +26,13 @@ export default function Inputs({ period, onChange, readOnly, locale, timezone })
25
26
  if (timestamp) {
26
27
  const incorrect = period.tsEnd && timestamp > period.tsEnd;
27
28
  const tsEnd = incorrect ? timestamp + ONE_HOUR : period.tsEnd;
28
- onChange({
29
+ const newPeriod = {
29
30
  tsStart: timestamp,
30
31
  tsEnd
31
- });
32
+ };
33
+ if (!isEqual(newPeriod, period)) {
34
+ onChange(newPeriod);
35
+ }
32
36
  if (!fromTextField) {
33
37
  openEndDate();
34
38
  }
@@ -41,10 +45,13 @@ export default function Inputs({ period, onChange, readOnly, locale, timezone })
41
45
  if (timestamp) {
42
46
  const incorrect = period.tsStart && timestamp < period.tsStart;
43
47
  const tsStart = incorrect ? timestamp - ONE_HOUR : period.tsStart;
44
- onChange({
48
+ const newPeriod = {
45
49
  tsStart,
46
50
  tsEnd: timestamp
47
- });
51
+ };
52
+ if (!isEqual(newPeriod, period)) {
53
+ onChange(newPeriod);
54
+ }
48
55
  if (incorrect) {
49
56
  showWarning('date-from');
50
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAuF5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA+F5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -6,14 +6,23 @@ const ReactableTableFilterRow = ({ columnDefs, onFilter, tableName }) => {
6
6
  const { t } = useTranslation();
7
7
  const [state, setState] = useState({});
8
8
  useEffect(() => {
9
- const initialFilters = columnDefs.reduce((acc, columnDef) => ({
10
- ...acc,
11
- [columnDef.name]: columnDef.filterable?.initialValue ?? ''
12
- }), {});
13
- setState(initialFilters);
14
- if (Object.values(initialFilters).some((value) => value)) {
15
- onFilter(initialFilters);
16
- }
9
+ setState((prev) => {
10
+ const merged = {};
11
+ for (const cd of columnDefs) {
12
+ merged[cd.name] = prev[cd.name] !== undefined ? prev[cd.name] : cd.filterable?.initialValue ?? '';
13
+ }
14
+ const prevKeys = Object.keys(prev);
15
+ const mergedKeys = Object.keys(merged);
16
+ const sameKeys = mergedKeys.length === prevKeys.length && mergedKeys.every((k) => prevKeys.includes(k));
17
+ const sameValues = sameKeys && mergedKeys.every((k) => merged[k] === prev[k]);
18
+ if (sameKeys && sameValues) {
19
+ return prev; // no change
20
+ }
21
+ if (Object.values(merged).some((v) => v)) {
22
+ onFilter(merged);
23
+ }
24
+ return merged;
25
+ });
17
26
  }, [columnDefs, onFilter]);
18
27
  const changeFilter = (columnName, value) => {
19
28
  const newState = { ...state, [columnName]: value };
@@ -5,6 +5,8 @@ import '../../assets/react-datepicker-custom.css';
5
5
  declare type DateInputProps = {
6
6
  /** the current value (millis since 1970-01-01 or formatted string) */
7
7
  value: number | string | null | undefined;
8
+ /** (optional) timezone */
9
+ timezone?: string;
8
10
  /** callback function that is executed when the user picks a date */
9
11
  onChange: (date: number | null | undefined, fromTextField?: boolean) => void;
10
12
  /** makes the input field clearable */
@@ -23,6 +25,6 @@ export declare type Props = Omit<ReactDatePickerProps, keyof DateInputProps> & D
23
25
  * DateInput is used to let users set a date conveniently.
24
26
  * Usually the user's locale is used for displaying the correct date format.
25
27
  */
26
- export default function DateInput({ value, clearable, inline, readOnly, wrapperClassName, onChange, locale, ...otherProps }: Props): React.JSX.Element;
28
+ export default function DateInput({ value, clearable, inline, readOnly, wrapperClassName, onChange, locale, timezone, ...otherProps }: Props): React.JSX.Element;
27
29
  export {};
28
30
  //# sourceMappingURL=DateInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DateInput.d.ts","sourceRoot":"","sources":["../../../../../src/components/input/DateInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AACvE,OAAmB,EAAC,oBAAoB,EAAiB,MAAM,kBAAkB,CAAC;AAalF,OAAO,4CAA4C,CAAC;AACpD,OAAO,0CAA0C,CAAC;AAwClD,aAAK,cAAc,GAAG;IACrB,sEAAsE;IACtE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAE1C,oEAAoE;IACpE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAE7E,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,oBAAY,KAAK,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,cAAc,CAAC,GAAG,cAAc,CAAC;AAqBtF;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EACjC,KAAK,EACL,SAAS,EACT,MAAM,EACN,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,MAAM,EACN,GAAG,UAAU,EACb,EAAE,KAAK,qBAmKP"}
1
+ {"version":3,"file":"DateInput.d.ts","sourceRoot":"","sources":["../../../../../src/components/input/DateInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAGvE,OAAmB,EAAC,oBAAoB,EAAiB,MAAM,kBAAkB,CAAC;AAalF,OAAO,4CAA4C,CAAC;AACpD,OAAO,0CAA0C,CAAC;AA0ClD,aAAK,cAAc,GAAG;IACrB,sEAAsE;IACtE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAE1C,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oEAAoE;IACpE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAE7E,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,oBAAY,KAAK,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,cAAc,CAAC,GAAG,cAAc,CAAC;AA2CtF;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EACjC,KAAK,EACL,SAAS,EACT,MAAM,EACN,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,GAAG,UAAU,EACb,EAAE,KAAK,qBAyKP"}
@@ -1,4 +1,6 @@
1
1
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import timezone from 'dayjs/plugin/timezone';
3
+ import utc from 'dayjs/plugin/utc';
2
4
  import DatePicker, { registerLocale } from 'react-datepicker';
3
5
  import { debounce } from 'lodash';
4
6
  import dayjs from 'dayjs';
@@ -13,6 +15,8 @@ import { Button, Icon, Popup } from '@deviceinsight/ng-ui-basic-components';
13
15
  import 'react-datepicker/dist/react-datepicker.css';
14
16
  import '../../assets/react-datepicker-custom.css';
15
17
  import { isLocaleSupported } from '../../utils/dayjsLocales';
18
+ dayjs.extend(utc);
19
+ dayjs.extend(timezone);
16
20
  dayjs.extend(localeData);
17
21
  dayjs.extend(localizedFormat);
18
22
  dayjs.extend(customParseFormat);
@@ -48,29 +52,40 @@ async function changeDayjsLocale(locale) {
48
52
  }
49
53
  }
50
54
  function isInputValid(value, pattern) {
51
- if (value == null || (typeof value === 'number' && !isNaN(value)) || value == '') {
55
+ if (value == null || value === '') {
52
56
  return true;
53
57
  }
58
+ if (typeof value === 'number') {
59
+ return !isNaN(value);
60
+ }
54
61
  if (typeof value === 'string') {
55
62
  return dayjs(value, pattern, true).isValid();
56
63
  }
57
64
  return false;
58
65
  }
59
- function inputToDate(value, pattern) {
60
- if (value == null || value === '' || !isInputValid(value, pattern))
61
- return null;
66
+ function inputToDate(value, pattern, timezone) {
62
67
  if (typeof value === 'number') {
63
68
  return new Date(value);
64
69
  }
65
- else {
66
- return dayjs(value, pattern, true).toDate();
70
+ if (typeof value === 'string' && dayjs(value, pattern, true).isValid()) {
71
+ return dayjs.tz(value, pattern, timezone).toDate();
72
+ }
73
+ return null;
74
+ }
75
+ function inputToTzDate(value, pattern, timezone) {
76
+ if (typeof value === 'number') {
77
+ return dayjs.tz(value, timezone);
78
+ }
79
+ if (typeof value === 'string' && dayjs(value, pattern, true).isValid()) {
80
+ return dayjs.tz(value, pattern, timezone);
67
81
  }
82
+ return null;
68
83
  }
69
84
  /**
70
85
  * DateInput is used to let users set a date conveniently.
71
86
  * Usually the user's locale is used for displaying the correct date format.
72
87
  */
73
- export default function DateInput({ value, clearable, inline, readOnly, wrapperClassName, onChange, locale, ...otherProps }) {
88
+ export default function DateInput({ value, clearable, inline, readOnly, wrapperClassName, onChange, locale, timezone, ...otherProps }) {
74
89
  const [pattern, setPattern] = useState(dayjs.localeData().longDateFormat('L'));
75
90
  const { t } = useTranslation();
76
91
  const [valid, setValid] = useState(false);
@@ -94,10 +109,9 @@ export default function DateInput({ value, clearable, inline, readOnly, wrapperC
94
109
  });
95
110
  }
96
111
  else {
97
- const date = typeof value === 'number' ? dayjs(value) : dayjs(value, pattern, true);
98
- return date.format(pattern);
112
+ return typeof value === 'number' ? dayjs.tz(value, timezone).format(pattern) : value;
99
113
  }
100
- }, [pattern, t]);
114
+ }, [pattern, t, timezone]);
101
115
  useEffect(() => {
102
116
  if (value == null) {
103
117
  setInputText('');
@@ -116,10 +130,17 @@ export default function DateInput({ value, clearable, inline, readOnly, wrapperC
116
130
  const handleInputTextChange = (text) => {
117
131
  setInputText(text);
118
132
  if (text) {
119
- const date = dayjs(text, pattern, true);
120
- const valid = date.isValid();
133
+ const valid = dayjs(text, pattern, true).isValid();
121
134
  if (valid) {
122
- onChange(date.valueOf(), true);
135
+ const prevDate = inputToTzDate(value, pattern, timezone);
136
+ const newDate = dayjs.tz(text, pattern, timezone ?? dayjs.tz.guess());
137
+ if (prevDate) {
138
+ newDate.set('hour', prevDate.hour());
139
+ newDate.set('minute', prevDate.minute());
140
+ newDate.set('second', prevDate.second());
141
+ newDate.set('millisecond', prevDate.millisecond());
142
+ }
143
+ onChange(newDate.valueOf(), true);
123
144
  }
124
145
  setValid(valid);
125
146
  }
@@ -137,10 +158,10 @@ export default function DateInput({ value, clearable, inline, readOnly, wrapperC
137
158
  const handlePopupHide = () => setPopupActive(false);
138
159
  const handleClear = () => handleInputTextChange('');
139
160
  if (inline) {
140
- return (React.createElement(DatePicker, { ...otherProps, onChange: handlePickerChange, selected: inputToDate(value, pattern), locale: locale ?? i18n.language, isClearable: clearable, placeholderText: pattern, className: cx('date', { invalid: !valid }), inline: true }));
161
+ return (React.createElement(DatePicker, { ...otherProps, onChange: handlePickerChange, selected: inputToDate(value, pattern, timezone), locale: locale ?? i18n.language, isClearable: clearable, placeholderText: pattern, className: cx('date', { invalid: !valid }), inline: true }));
141
162
  }
142
163
  if (readOnly) {
143
- return (React.createElement(DatePicker, { ...otherProps, onChange: () => { }, selected: inputToDate(value, pattern), locale: locale ?? i18n.language, customInput: React.createElement("span", null,
164
+ return (React.createElement(DatePicker, { ...otherProps, onChange: () => { }, selected: inputToDate(value, pattern, timezone), locale: locale ?? i18n.language, customInput: React.createElement("span", null,
144
165
  React.createElement("input", { type: "text", value: formattedDate(value), readOnly: true })), placeholderText: pattern, readOnly: true }));
145
166
  }
146
167
  return (React.createElement(Popup, { handler: React.createElement("span", { className: "di date-input-wrapper" },
@@ -153,5 +174,5 @@ export default function DateInput({ value, clearable, inline, readOnly, wrapperC
153
174
  React.createElement("div", { className: "di date-picker-popup-wrapper", tabIndex: 0, onFocus: () => {
154
175
  debouncedSetPopupActive(true);
155
176
  } },
156
- React.createElement(DatePicker, { ...otherProps, selected: inputToDate(value, pattern), onChange: handlePickerChange, locale: locale ?? i18n.language, isClearable: clearable, placeholderText: pattern, className: cx('date', { invalid: !valid }), inline: true }))));
177
+ React.createElement(DatePicker, { ...otherProps, selected: inputToDate(value, pattern, timezone), onChange: handlePickerChange, locale: locale ?? i18n.language, isClearable: clearable, placeholderText: pattern, className: cx('date', { invalid: !valid }), inline: true }))));
157
178
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../../../../src/components/input/DateTimeInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAwBjD,oBAAY,KAAK,GAAG;IACnB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAElB,oEAAoE;IACpE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAE7E,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CAAC;IAEf,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACrC,SAAS,EACT,QAAQ,EACR,OAAO,EACP,QAAgB,EAChB,QAAQ,EACR,GAAG,UAAU,EACb,EAAE,KAAK,qBAgFP"}
1
+ {"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../../../../src/components/input/DateTimeInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAcjD,oBAAY,KAAK,GAAG;IACnB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAElB,oEAAoE;IACpE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAE7E,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CAAC;IAEf,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACrC,SAAS,EACT,QAAQ,EACR,OAAO,EACP,QAAgB,EAChB,QAAQ,EACR,GAAG,UAAU,EACb,EAAE,KAAK,qBA4DP"}
@@ -1,69 +1,41 @@
1
1
  import dayjs from 'dayjs';
2
2
  import React, { useEffect, useState } from 'react';
3
- import { dayjsTz } from '../periodpicker/periods';
4
3
  import DateInput from './DateInput';
5
4
  import ValidatedTextInput from './ValidatedTextInput';
6
- import { toInteger } from 'lodash';
7
- const extractTime = (timezone, date) => {
5
+ const formatTime = (timezone, date) => {
8
6
  try {
9
- return dayjsTz(timezone, date).format('HH:mm');
7
+ return dayjs.tz(date, timezone).format('HH:mm');
10
8
  }
11
9
  catch (error) {
12
10
  console.error('DateTimeInput: Error while extracting time from date', error);
13
11
  return '00:00';
14
12
  }
15
13
  };
16
- const extractDate = (timezone, date) => {
17
- try {
18
- return dayjs(dayjsTz(timezone, date).format('YYYY-MM-DD'));
19
- }
20
- catch (error) {
21
- console.error('DateTimeInput: Error while extracting time from date', error);
22
- return dayjs(new Date());
23
- }
24
- };
25
14
  /**
26
15
  * Extends DateInput but also displaying the current time.
27
16
  * Usually the user's locale is used for displaying the correct date format.
28
17
  */
29
18
  export default function DateTimeInput({ timestamp, timezone, warning, readOnly = false, onChange, ...otherProps }) {
30
- const [time, setTime] = useState(extractTime(timezone, timestamp));
31
- const timeValue = time == null ? extractTime(timezone, timestamp) : time;
19
+ const [time, setTime] = useState(formatTime(timezone, timestamp));
20
+ const timeValue = time == null ? formatTime(timezone, timestamp) : time;
32
21
  useEffect(() => {
33
- setTime(extractTime(timezone, timestamp));
22
+ setTime(formatTime(timezone, timestamp));
34
23
  }, [timezone, timestamp]);
35
24
  function handleChangeDate(date, fromTextField) {
36
- const oldDate = dayjsTz(timezone, timestamp);
37
- const dateFix = dayjs(date);
38
- let newDate = dayjsTz(timezone, date)
39
- .set('day', dateFix.day())
40
- .set('month', dateFix.month())
41
- .set('year', dateFix.year())
42
- .set('hour', toInteger(oldDate.hour()))
43
- .set('minute', toInteger(oldDate.minute()));
44
- const dstOffset = getLocalDstOffset(newDate);
45
- newDate = newDate.subtract(dstOffset, 'minutes');
25
+ const currentDate = dayjs.tz(timestamp, timezone);
26
+ const newDate = dayjs
27
+ .tz(date, timezone)
28
+ .set('hour', currentDate.hour())
29
+ .set('minute', currentDate.minute())
30
+ .set('second', currentDate.second())
31
+ .set('millisecond', currentDate.millisecond());
46
32
  onChange(newDate.valueOf(), fromTextField);
47
33
  }
48
- function getMaxUtcOffset(year) {
49
- const jan = new Date(`${year}-01-01`).getTimezoneOffset();
50
- const jul = new Date(`${year}-07-01`).getTimezoneOffset();
51
- return Math.min(jan, jul);
52
- }
53
- function getLocalDstOffset(newDate) {
54
- return newDate.toDate().getTimezoneOffset() - getMaxUtcOffset(newDate.year());
55
- }
56
34
  function handleChangeTime(time, valid) {
57
35
  if (valid) {
58
- const [hours, minutes] = time.split(':');
59
- const date = extractDate(timezone, timestamp);
60
- const dateTime = dayjsTz(timezone, timestamp)
61
- .set('date', date.date())
62
- .set('hour', parseInt(hours, 10))
63
- .set('minute', parseInt(minutes, 10))
64
- .set('second', 0)
65
- .set('millisecond', 0);
66
- onChange(dateTime.valueOf());
36
+ const [hours, minutes] = time.split(':').map(Number);
37
+ const newDate = dayjs.tz(timestamp, timezone).set('hours', hours).set('minutes', minutes);
38
+ onChange(newDate.valueOf(), true);
67
39
  }
68
40
  setTime(time);
69
41
  }
@@ -73,7 +45,7 @@ export default function DateTimeInput({ timestamp, timezone, warning, readOnly =
73
45
  }
74
46
  }
75
47
  return (React.createElement("span", { className: `di date-time-input ${warning ? 'with-warning' : ''}` },
76
- React.createElement(DateInput, { ...otherProps, value: extractDate(timezone, timestamp).valueOf(), onChange: handleChangeDate, readOnly: readOnly }),
48
+ React.createElement(DateInput, { ...otherProps, value: timestamp, timezone: timezone, onChange: handleChangeDate, readOnly: readOnly }),
77
49
  React.createElement(ValidatedTextInput, { "data-testid": "time-input", value: timeValue, onChange: handleChangeTime, pattern: /^(([01][0-9])|2[0-3]):[0-5][0-9]$/, required: true, invalidStyle: {
78
50
  borderColor: 'red'
79
51
  }, placeholder: "00:00", className: "time", onBlur: tryFixTime, disabled: readOnly })));
@@ -16,9 +16,7 @@ describe('DateInput.js', () => {
16
16
  });
17
17
  describe('Changing values via text input', () => {
18
18
  it('should render correct date typed into text input without "invalid" class', async () => {
19
- await act(async () => {
20
- render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
21
- });
19
+ render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
22
20
  await act(async () => {
23
21
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.2019' } });
24
22
  });
@@ -26,9 +24,7 @@ describe('DateInput.js', () => {
26
24
  expect(screen.getByTestId('date-input')).not.toHaveClass('invalid');
27
25
  });
28
26
  it('should render incorrect date typed into text input with "invalid" class', async () => {
29
- await act(async () => {
30
- render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
31
- });
27
+ render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
32
28
  await act(async () => {
33
29
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.201' } });
34
30
  });
@@ -36,9 +32,7 @@ describe('DateInput.js', () => {
36
32
  });
37
33
  it('should call onChange callback with parsed value of the input during the input is being changed when the value is valid', async () => {
38
34
  const onChange = vi.fn();
39
- await act(async () => {
40
- render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
41
- });
35
+ render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
42
36
  await act(async () => {
43
37
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.2019' } });
44
38
  });
@@ -47,18 +41,14 @@ describe('DateInput.js', () => {
47
41
  });
48
42
  it('should not call onChange callback while editing the input when the input value is invalid', async () => {
49
43
  const onChange = vi.fn();
50
- await act(async () => {
51
- render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
52
- });
44
+ render(React.createElement(DateInput, { value: new Date('2019-02-01').getTime(), onChange: onChange }));
53
45
  await act(async () => {
54
46
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.201' } });
55
47
  });
56
48
  expect(onChange).not.toHaveBeenCalled();
57
49
  });
58
50
  it('should display the current value in the input field if the input value is invalid and the input became blurred', async () => {
59
- await act(async () => {
60
- render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
61
- });
51
+ render(React.createElement(DateStateProvider, { initialValue: new Date('2019-02-01').getTime() }, (date, setDate) => React.createElement(DateInput, { value: date, onChange: (date) => setDate(date) })));
62
52
  await act(async () => {
63
53
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '02.02.201' } });
64
54
  fireEvent.blur(screen.getByTestId('date-input'));
@@ -66,16 +56,12 @@ describe('DateInput.js', () => {
66
56
  expect(screen.getByTestId('date-input')).toHaveValue('01.02.2019');
67
57
  });
68
58
  it('should display invalid date text in the input when the value is NaN', async () => {
69
- await act(async () => {
70
- render(React.createElement(DateInput, { value: NaN, onChange: () => { } }));
71
- });
59
+ render(React.createElement(DateInput, { value: NaN, onChange: () => { } }));
72
60
  expect(screen.getByTestId('date-input')).toHaveValue('dateInput.invalidDate');
73
61
  });
74
62
  it('should call onChange callback with [null, true] when empty string is set to input field', async () => {
75
63
  const onChange = vi.fn();
76
- await act(async () => {
77
- render(React.createElement(DateInput, { value: Date.now(), onChange: onChange }));
78
- });
64
+ render(React.createElement(DateInput, { value: Date.now(), onChange: onChange }));
79
65
  await act(async () => {
80
66
  fireEvent.change(screen.getByTestId('date-input'), { target: { value: '' } });
81
67
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Inputs.d.ts","sourceRoot":"","sources":["../../../../../../src/components/periodpicker/components/Inputs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyB,MAAM,OAAO,CAAC;AAE9C,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAMhC,aAAK,KAAK,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAC,EAAE,KAAK,qBA2FnF"}
1
+ {"version":3,"file":"Inputs.d.ts","sourceRoot":"","sources":["../../../../../../src/components/periodpicker/components/Inputs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyB,MAAM,OAAO,CAAC;AAG9C,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAMhC,aAAK,KAAK,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAC,EAAE,KAAK,qBAiGnF"}
@@ -1,4 +1,5 @@
1
1
  import React, { useRef, useState } from 'react';
2
+ import { isEqual } from 'lodash';
2
3
  import DateTimeInput from '../../input/DateTimeInput';
3
4
  const ONE_HOUR = 60 * 60 * 1000;
4
5
  const TOGGLE_TIMEOUT = 300;
@@ -25,10 +26,13 @@ export default function Inputs({ period, onChange, readOnly, locale, timezone })
25
26
  if (timestamp) {
26
27
  const incorrect = period.tsEnd && timestamp > period.tsEnd;
27
28
  const tsEnd = incorrect ? timestamp + ONE_HOUR : period.tsEnd;
28
- onChange({
29
+ const newPeriod = {
29
30
  tsStart: timestamp,
30
31
  tsEnd
31
- });
32
+ };
33
+ if (!isEqual(newPeriod, period)) {
34
+ onChange(newPeriod);
35
+ }
32
36
  if (!fromTextField) {
33
37
  openEndDate();
34
38
  }
@@ -41,10 +45,13 @@ export default function Inputs({ period, onChange, readOnly, locale, timezone })
41
45
  if (timestamp) {
42
46
  const incorrect = period.tsStart && timestamp < period.tsStart;
43
47
  const tsStart = incorrect ? timestamp - ONE_HOUR : period.tsStart;
44
- onChange({
48
+ const newPeriod = {
45
49
  tsStart,
46
50
  tsEnd: timestamp
47
- });
51
+ };
52
+ if (!isEqual(newPeriod, period)) {
53
+ onChange(newPeriod);
54
+ }
48
55
  if (incorrect) {
49
56
  showWarning('date-from');
50
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAuF5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA+F5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}