Skip to content

Commit

Permalink
feat: display timezone preference
Browse files Browse the repository at this point in the history
  • Loading branch information
adityathebe committed Feb 14, 2025
1 parent d9051c9 commit 2cb23e3
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 15 deletions.
17 changes: 14 additions & 3 deletions src/components/Configs/Changes/ConfigChangeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useState } from "react";
import ConfigLink from "../ConfigLink/ConfigLink";
import MRTConfigListTagsCell from "../ConfigList/Cells/MRTConfigListTagsCell";
import { ConfigDetailChangeModal } from "./ConfigDetailsChanges/ConfigDetailsChanges";
import { DateTimePreferenceOptions } from "@flanksource-ui/store/preference.state";

export const paramsToReset = {
configChanges: ["pageIndex", "pageSize"]
Expand All @@ -29,7 +30,12 @@ export function ConfigChangeDateCell({
<Age from={dateString} />
{(count || 1) > 1 && (
<span className="inline-block pl-1 text-gray-500">
(x{count} over <Age from={firstObserved} />)
(x{count} over{" "}
<Age
dateTimePreferenceOverride={DateTimePreferenceOptions.Short}
from={firstObserved}
/>
)
</span>
)}
</div>
Expand All @@ -53,10 +59,15 @@ const configChangesColumn: MRT_ColumnDef<ConfigChange>[] = [

return (
<div className="text-xs">
<Age from={dateString} />
<Age from={dateString} suffix={true} />
{(count || 1) > 1 && (
<span className="inline-block pl-1 text-gray-500">
(x{count} over <Age from={firstObserved} />)
(x{count} over{" "}
<Age
dateTimePreferenceOverride={DateTimePreferenceOptions.Short}
from={firstObserved}
/>
)
</span>
)}
</div>
Expand Down
8 changes: 7 additions & 1 deletion src/components/Notifications/NotificationSendHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useSearchParams } from "react-router-dom";
import NotificationDetailsModal from "./NotificationDetailsModal";
import NotificationResourceDisplay from "./NotificationResourceDisplay";
import { NotificationStatusCell } from "./NotificationsStatusCell";
import { DateTimePreferenceOptions } from "@flanksource-ui/store/preference.state";

const notificationSendHistoryColumns: MRT_ColumnDef<NotificationSendHistoryApiResponse>[] =
[
Expand All @@ -23,7 +24,12 @@ const notificationSendHistoryColumns: MRT_ColumnDef<NotificationSendHistoryApiRe
<Age from={dateString} />
{(count || 1) > 1 && (
<span className="inline-block pl-1 text-gray-500">
(x{count} over <Age from={firstObserved} />)
(x{count} over{" "}
<Age
dateTimePreferenceOverride={DateTimePreferenceOptions.Short}
from={firstObserved}
/>
)
</span>
)}
</div>
Expand Down
19 changes: 19 additions & 0 deletions src/store/preference.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ export const datetimePreferenceAtom =
}
);

export enum DisplayTimezonePreference {
Browser = "Browser",
UTC = "UTC",
LosAngeles = "America/Los_Angeles",
SouthAfrica = "Africa/Johannesburg",
India = "Asia/Kolkata",
Nepal = "Asia/Kathmandu"
}

export const displayTimezonePreferenceAtom =
atomWithStorage<DisplayTimezonePreference>(
"display_timezone_preference",
DisplayTimezonePreference.Browser,
undefined,
{
getOnInit: true
}
);

export const cardPreferenceAtom = atomWithStorage<string>(
"topology_card_width",
CardWidth[Size.extra_large],
Expand Down
53 changes: 43 additions & 10 deletions src/ui/Age/Age.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
import clsx from "clsx";
import dayjs from "dayjs";
import LocalizedFormat from "dayjs/plugin/localizedFormat";
import TimezonePlugin from "dayjs/plugin/timezone";
import { Tooltip } from "react-tooltip";
import { isEmpty } from "../../utils/date";
import {
datetimePreferenceAtom,
DateTimePreferenceOptions
displayTimezonePreferenceAtom,
DateTimePreferenceOptions,
DisplayTimezonePreference
} from "@flanksource-ui/store/preference.state";
import { useAtomValue } from "jotai";

dayjs.extend(LocalizedFormat);
dayjs.extend(TimezonePlugin);

type AgeProps = {
className?: string;
from?: Date | string;
to?: Date | string | null;
suffix?: boolean;
dateTimePreferenceOverride?: DateTimePreferenceOptions;
};

export default function Age({
className = "",
from,
to,
suffix = false
suffix = false,
dateTimePreferenceOverride = undefined
}: AgeProps) {
// TODO: Do we need to memoize this ...
const datetimePreference = useAtomValue(datetimePreferenceAtom);
let datetimePreference = useAtomValue(datetimePreferenceAtom);
const displayTimezonePreference = useAtomValue(displayTimezonePreferenceAtom);
if (dateTimePreferenceOverride) {
datetimePreference = dateTimePreferenceOverride;
}

if (isEmpty(from)) {
return null;
Expand All @@ -34,7 +44,12 @@ export default function Age({
const _from = dayjs(from);

if (isEmpty(to)) {
const formattedDate = formatDayjs(_from, datetimePreference, suffix);
const formattedDate = formatDayjs(
_from,
displayTimezonePreference,
datetimePreference,
suffix
);
return (
<>
<span
Expand All @@ -45,7 +60,7 @@ export default function Age({
</span>
<Tooltip
id={`age-tooltip-${_from.local().fromNow(!suffix)}`}
content={formatDateForTooltip(_from)}
content={formatDateForTooltip(_from, displayTimezonePreference)}
/>
</>
);
Expand All @@ -66,7 +81,7 @@ export default function Age({
</span>
<Tooltip
id={`age-tooltip-${duration.asMilliseconds()}`}
content={`${formatDateForTooltip(_from)}`}
content={`${formatDateForTooltip(_from, displayTimezonePreference)}`}
/>
</>
);
Expand All @@ -82,21 +97,36 @@ export default function Age({
</span>
<Tooltip
id={`age-tooltip-${_from.local().to(_to)}`}
content={`${formatDateForTooltip(_from)} - ${formatDateForTooltip(_to)}`}
content={`${formatDateForTooltip(_from, displayTimezonePreference)} - ${formatDateForTooltip(_to, displayTimezonePreference)}`}
/>
</>
);
}

export function formatDateForTooltip(datetime: dayjs.Dayjs) {
return formatDayjs(datetime, DateTimePreferenceOptions.Timestamp, false);
export function formatDateForTooltip(
datetime: dayjs.Dayjs,
displayTimezone: DisplayTimezonePreference = DisplayTimezonePreference.Browser
) {
return formatDayjs(
datetime,
displayTimezone,
DateTimePreferenceOptions.Timestamp,
false
);
}

function formatDayjs(
datetime: dayjs.Dayjs,
displayTimezone: DisplayTimezonePreference,
datetimePreference: DateTimePreferenceOptions,
suffix: boolean
) {
if (displayTimezone === DisplayTimezonePreference.Browser) {
datetime = datetime.local();
} else {
datetime = datetime.tz(displayTimezone);
}

switch (datetimePreference) {
case DateTimePreferenceOptions.Short:
return datetime.fromNow(!suffix);
Expand All @@ -113,7 +143,10 @@ function formatDayjs(
}

case DateTimePreferenceOptions.Full:
return datetime.format("MMM D HH:mm:ss.SSS");
if (datetime.isSame(dayjs(), "year")) {
return datetime.format("MMM D HH:mm");
}
return datetime.format("MMM D YYYY HH:mm:ss.SSS");

case DateTimePreferenceOptions.Timestamp:
return datetime.format("YYYY-MM-DD HH:mm:ss.SSS Z");
Expand Down
61 changes: 60 additions & 1 deletion src/ui/Layout/Preference.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { ClickableSvg } from "../ClickableSvg/ClickableSvg";
import { Toggle } from "@flanksource-ui/components";
import {
datetimePreferenceAtom,
DateTimePreferenceOptions
DateTimePreferenceOptions,
displayTimezonePreferenceAtom,
DisplayTimezonePreference
} from "@flanksource-ui/store/preference.state";
import { useAtom } from "jotai";

Expand Down Expand Up @@ -70,6 +72,10 @@ export const Preference = ({
datetimePreferenceAtom
);

const [displayTimezonePreference, setDisplayTimezonePreference] = useAtom(
displayTimezonePreferenceAtom
);

const {
ref: popoverRef,
isActive: isPopoverActive,
Expand All @@ -79,6 +85,15 @@ export const Preference = ({
const showHiddenComponents =
searchParams.get("showHiddenComponents") !== "no";

// const opt: GroupByOptions[] = Object.entries(DisplayTimezonePreference).map(
// ([_, val]) => {
// return {
// label: val,
// value: val
// };
// }
// );

return (
<>
<style jsx>{`
Expand Down Expand Up @@ -224,6 +239,50 @@ export const Preference = ({
</div>
</div>
</div>

{/* Timezone selection */}
<div className="py-1" role="none">
<div className="px-4 py-4">
<label className="block text-sm font-medium text-gray-700">
Timezone:
</label>
<div className="relative mt-3">
<select
className="w-full appearance-none rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-600 shadow-sm hover:bg-gray-100 focus:border-blue-500 focus:ring focus:ring-blue-200"
onChange={(e) =>
setDisplayTimezonePreference(
e.target.value as DisplayTimezonePreference
)
}
>
{Object.entries(DisplayTimezonePreference).map(([_, val]) => (
<option
key={val}
value={val}
selected={displayTimezonePreference === val}
className="bg-white text-gray-700 hover:bg-blue-700 hover:text-white"
>
{val}
</option>
))}
</select>
</div>
</div>
</div>

{/* <div className="py-1">
<div className="px-4 py-4">
<MultiSelectDropdown
options={opt}
isMulti={false}
label="Timezone"
closeMenuOnSelect={true}
// @ts-ignore
onChange={(value: GroupByOptions) => {}}
className="w-auto max-w-[400px]"
/>
</div>
</div> */}
</div>
</div>
</>
Expand Down

0 comments on commit 2cb23e3

Please sign in to comment.