From 74b8f1d73113ea339e93bfab64961a83092ab673 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 10 Sep 2024 11:12:12 +0200 Subject: [PATCH] ui: fix default timezone conversion via luxon global settings --- .../DateRangeDropdown/DateRangePopup.js | 136 ------------------ .../DateRangeDropdown/DateRangePopup.tsx | 128 +++++++++++++++++ .../SelectDateRange/SelectDateRange.tsx | 1 - .../components/DefaultTimezone.tsx | 4 +- frontend/app/mstore/types/sessionSettings.ts | 12 +- frontend/app/types/app/period.js | 10 +- 6 files changed, 146 insertions(+), 145 deletions(-) delete mode 100644 frontend/app/components/shared/DateRangeDropdown/DateRangePopup.js create mode 100644 frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx diff --git a/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.js b/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.js deleted file mode 100644 index 6520ccb2d..000000000 --- a/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.js +++ /dev/null @@ -1,136 +0,0 @@ -import { Button } from 'antd'; -import React from 'react'; -import DateRangePicker from '@wojtekmaj/react-daterange-picker'; -import '@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css'; -import 'react-calendar/dist/Calendar.css'; - -import { TimePicker } from 'App/components/shared/DatePicker'; -import { - CUSTOM_RANGE, - DATE_RANGE_VALUES, - dateRangeValues, - getDateRangeFromValue, - getDateRangeLabel, -} from 'App/dateRange'; -import { DateTime, Interval } from 'luxon'; - -import styles from './dateRangePopup.module.css'; - -export default class DateRangePopup extends React.PureComponent { - state = { - range: this.props.selectedDateRange || Interval.fromDateTimes(DateTime.now(), DateTime.now()), - value: null, - }; - - selectCustomRange = (range) => { - console.log(range) - const updatedRange = Interval.fromDateTimes(DateTime.fromJSDate(range[0]), DateTime.fromJSDate(range[1])); - this.setState({ - range: updatedRange, - value: CUSTOM_RANGE, - }); - }; - - setRangeTimeStart = (value) => { - if (value > this.state.range.end) { - return; - } - this.setState({ - range: Interval.fromDateTimes(value, this.state.range.end), - value: CUSTOM_RANGE, - }); - }; - - setRangeTimeEnd = (value) => { - if (value && value < this.state.range.start) { - return; - } - this.setState({ - range: Interval.fromDateTimes(this.state.range.start, value), - value: CUSTOM_RANGE, - }); - }; - - selectValue = (value) => { - const range = getDateRangeFromValue(value); - this.setState({ range, value }); - }; - - onApply = () => this.props.onApply(this.state.range, this.state.value); - - render() { - const { onCancel, onApply } = this.props; - const { range } = this.state; - const rangeForDisplay = [range.start.startOf('day').ts, range.end.startOf('day').ts] - - return ( -
-
-
- {dateRangeValues - .filter( - (value) => - value !== CUSTOM_RANGE && - value !== DATE_RANGE_VALUES.LAST_30_MINUTES - ) - .map((value) => ( -
this.selectValue(value)}> - {getDateRangeLabel(value)} -
- ))} -
-
- onChange - // numberOfCalendars={2} - // selectionType="range" - // maximumDate={new Date()} - // singleDateRange={true} - onChange={this.selectCustomRange} - shouldCloseCalendar={() => false} - isOpen - maxDate={new Date()} - value={rangeForDisplay} - /> -
-
-
-
- - {range.start.toFormat('dd/MM')} - - - {range.end.toFormat('dd/MM')} - -
-
- - -
-
-
- ); - } -} diff --git a/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx b/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx new file mode 100644 index 000000000..772186cc3 --- /dev/null +++ b/frontend/app/components/shared/DateRangeDropdown/DateRangePopup.tsx @@ -0,0 +1,128 @@ +import { Button } from 'antd'; +import React from 'react'; +import DateRangePicker from '@wojtekmaj/react-daterange-picker'; +import '@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css'; +import 'react-calendar/dist/Calendar.css'; + +import { TimePicker } from 'App/components/shared/DatePicker'; +import { + CUSTOM_RANGE, + DATE_RANGE_VALUES, + dateRangeValues, + getDateRangeFromValue, + getDateRangeLabel, +} from 'App/dateRange'; +import { DateTime, Interval } from 'luxon'; + +import styles from './dateRangePopup.module.css'; + +function DateRangePopup(props: any) { + const [range, setRange] = React.useState(props.selectedDateRange || Interval.fromDateTimes(DateTime.now(), DateTime.now())); + const [value, setValue] = React.useState(null); + + const selectCustomRange = (range) => { + const updatedRange = Interval.fromDateTimes(DateTime.fromJSDate(range[0]), DateTime.fromJSDate(range[1])); + setRange(updatedRange); + setValue(CUSTOM_RANGE); + }; + + const setRangeTimeStart = (value: DateTime) => { + if (!range.end || value > range.end) { + return; + } + setRange(Interval.fromDateTimes(value, range.end)); + setValue(CUSTOM_RANGE); + }; + + const setRangeTimeEnd = (value: DateTime) => { + if (!range.start || (value && value < range.start)) { + return; + } + setRange(Interval.fromDateTimes(range.start, value)); + setValue(CUSTOM_RANGE); + }; + + const selectValue = (value: string) => { + const range = getDateRangeFromValue(value); + setRange(range); + setValue(value); + }; + + const onApply = () => { + props.onApply(range, value); + }; + + const { onCancel } = props; + const rangeForDisplay = [range.start!.startOf('day').ts, range.end!.startOf('day').ts] + return ( +
+
+
+ {dateRangeValues + .filter( + (value) => + value !== CUSTOM_RANGE && + value !== DATE_RANGE_VALUES.LAST_30_MINUTES + ) + .map((value) => ( +
selectValue(value)}> + {getDateRangeLabel(value)} +
+ ))} +
+
+ onChange + // numberOfCalendars={2} + // selectionType="range" + // maximumDate={new Date()} + // singleDateRange={true} + onChange={selectCustomRange} + shouldCloseCalendar={() => false} + isOpen + maxDate={new Date()} + value={rangeForDisplay} + /> +
+
+
+
+ + {range.start.toFormat("dd/MM")} + + + {range.end.toFormat("dd/MM")} + +
+
+ + +
+
+
+ ); +} + +export default DateRangePopup; \ No newline at end of file diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index ebdbcf5c2..42bb062f7 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -5,7 +5,6 @@ import cn from 'classnames'; import { observer } from 'mobx-react-lite'; import React from 'react'; import { components } from 'react-select'; - import { CUSTOM_RANGE, DATE_RANGE_OPTIONS } from 'App/dateRange'; import DateRangePopup from 'Shared/DateRangeDropdown/DateRangePopup'; diff --git a/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx b/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx index 539254964..891cc2206 100644 --- a/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx +++ b/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx @@ -48,7 +48,7 @@ function DefaultTimezone() { const selectedTimezone = getCurrentTimezone(); if (selectedTimezone) { setTimezone(selectedTimezone); - sessionSettings.updateKey('timezone', selectedTimezone); + sessionSettings.updateTimezone(selectedTimezone); toast.success('Default timezone saved successfully'); } }; @@ -60,7 +60,7 @@ function DefaultTimezone() { const onTimezoneSave = () => { setChanged(false); - sessionSettings.updateKey('timezone', timezone); + sessionSettings.updateTimezone(timezone); toast.success('Default timezone saved successfully'); }; diff --git a/frontend/app/mstore/types/sessionSettings.ts b/frontend/app/mstore/types/sessionSettings.ts index 5e6cb8891..6bc54c26a 100644 --- a/frontend/app/mstore/types/sessionSettings.ts +++ b/frontend/app/mstore/types/sessionSettings.ts @@ -1,6 +1,6 @@ import { makeAutoObservable, runInAction } from 'mobx'; import { SKIP_TO_ISSUE, TIMEZONE, SHOWN_TIMEZONE, DURATION_FILTER, MOUSE_TRAIL } from 'App/constants/storageKeys'; -import { DateTime } from 'luxon' +import { DateTime, Settings } from 'luxon' export type Timezone = { label: string; @@ -81,9 +81,10 @@ export default class SessionSettings { tz.value.includes('UTC' + userTimezoneOffset.slice(0, 3)) ) || { label: 'Local', value: `UTC${userTimezoneOffset}` }; - const savedTz = localStorage.getItem(TIMEZONE) this.timezone = savedTz ? JSON.parse(savedTz) : defaultTimezone; + // @ts-ignore + Settings.defaultZoneName = this.timezone.value; if (localStorage.getItem(MOUSE_TRAIL) === null) { localStorage.setItem(MOUSE_TRAIL, 'true'); } @@ -110,6 +111,13 @@ export default class SessionSettings { this.conditionalCapture = all; }; + updateTimezone = (value: Timezone) => { + this.timezone = value; + // @ts-ignore + Settings.defaultZoneName = value.value; + localStorage.setItem(`__$session-timezone$__`, JSON.stringify(value)); + } + updateKey = (key: string, value: any) => { runInAction(() => { // @ts-ignore diff --git a/frontend/app/types/app/period.js b/frontend/app/types/app/period.js index 3166027af..01c2e9d01 100644 --- a/frontend/app/types/app/period.js +++ b/frontend/app/types/app/period.js @@ -1,4 +1,4 @@ -import { DateTime, Interval } from "luxon"; +import { DateTime, Interval, Settings } from "luxon"; import Record from "Types/Record"; export const LAST_30_MINUTES = "LAST_30_MINUTES"; @@ -61,11 +61,13 @@ export default Record( }, { fromJS: (period) => { - const offset = period.timezoneOffset || 'local'; + const offset = period.timezoneOffset || DateTime.now().offset; if (!period.rangeName || period.rangeName === CUSTOM_RANGE) { const isLuxon = DateTime.isDateTime(period.start); - const start = isLuxon ? period.start : DateTime.fromMillis(period.start || 0); - const end = isLuxon ? period.end : DateTime.fromMillis(period.end || 0); + const start = isLuxon + ? period.start : DateTime.fromMillis(period.start || 0, { zone: Settings.defaultZone }); + const end = isLuxon + ? period.end : DateTime.fromMillis(period.end || 0, { zone: Settings.defaultZone }); const range = Interval.fromDateTimes(start, end); return { ...period,