ui: fix default timezone conversion via luxon global settings
This commit is contained in:
parent
d65ecacb18
commit
74b8f1d731
6 changed files with 146 additions and 145 deletions
|
|
@ -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 (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={`${styles.body} h-fit`}>
|
||||
<div className={styles.preSelections}>
|
||||
{dateRangeValues
|
||||
.filter(
|
||||
(value) =>
|
||||
value !== CUSTOM_RANGE &&
|
||||
value !== DATE_RANGE_VALUES.LAST_30_MINUTES
|
||||
)
|
||||
.map((value) => (
|
||||
<div key={value} onClick={() => this.selectValue(value)}>
|
||||
{getDateRangeLabel(value)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className='flex justify-center h-fit dateRangeContainer'>
|
||||
<DateRangePicker
|
||||
name="dateRangePicker"
|
||||
// onSelect={this.selectCustomRange} -> onChange
|
||||
// numberOfCalendars={2}
|
||||
// selectionType="range"
|
||||
// maximumDate={new Date()}
|
||||
// singleDateRange={true}
|
||||
onChange={this.selectCustomRange}
|
||||
shouldCloseCalendar={() => false}
|
||||
isOpen
|
||||
maxDate={new Date()}
|
||||
value={rangeForDisplay}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between py-2 px-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<label>From: </label>
|
||||
<span>{range.start.toFormat('dd/MM')} </span>
|
||||
<TimePicker
|
||||
format={'HH:mm'}
|
||||
defaultValue={range.start}
|
||||
className="w-24"
|
||||
onChange={this.setRangeTimeStart}
|
||||
needConfirm={false}
|
||||
showNow={false}
|
||||
/>
|
||||
<label>To: </label>
|
||||
<span>{range.end.toFormat('dd/MM')} </span>
|
||||
<TimePicker
|
||||
format={'HH:mm'}
|
||||
defaultValue={range.end}
|
||||
onChange={this.setRangeTimeEnd}
|
||||
className="w-24"
|
||||
needConfirm={false}
|
||||
showNow={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Button onClick={onCancel}>{'Cancel'}</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
className="ml-2"
|
||||
onClick={this.onApply}
|
||||
disabled={!range}
|
||||
>
|
||||
{'Apply'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<string | null>(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 (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={`${styles.body} h-fit`}>
|
||||
<div className={styles.preSelections}>
|
||||
{dateRangeValues
|
||||
.filter(
|
||||
(value) =>
|
||||
value !== CUSTOM_RANGE &&
|
||||
value !== DATE_RANGE_VALUES.LAST_30_MINUTES
|
||||
)
|
||||
.map((value) => (
|
||||
<div key={value} onClick={() => selectValue(value)}>
|
||||
{getDateRangeLabel(value)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-center h-fit dateRangeContainer">
|
||||
<DateRangePicker
|
||||
name="dateRangePicker"
|
||||
// onSelect={this.selectCustomRange} -> onChange
|
||||
// numberOfCalendars={2}
|
||||
// selectionType="range"
|
||||
// maximumDate={new Date()}
|
||||
// singleDateRange={true}
|
||||
onChange={selectCustomRange}
|
||||
shouldCloseCalendar={() => false}
|
||||
isOpen
|
||||
maxDate={new Date()}
|
||||
value={rangeForDisplay}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between py-2 px-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<label>From: </label>
|
||||
<span>{range.start.toFormat("dd/MM")} </span>
|
||||
<TimePicker
|
||||
format={"HH:mm"}
|
||||
value={range.start}
|
||||
className="w-24"
|
||||
onChange={setRangeTimeStart}
|
||||
needConfirm={false}
|
||||
showNow={false}
|
||||
/>
|
||||
<label>To: </label>
|
||||
<span>{range.end.toFormat("dd/MM")} </span>
|
||||
<TimePicker
|
||||
format={"HH:mm"}
|
||||
value={range.end}
|
||||
onChange={setRangeTimeEnd}
|
||||
className="w-24"
|
||||
needConfirm={false}
|
||||
showNow={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Button onClick={onCancel}>{"Cancel"}</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
className="ml-2"
|
||||
onClick={onApply}
|
||||
disabled={!range}
|
||||
>
|
||||
{"Apply"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default DateRangePopup;
|
||||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue