Skip to content

Commit

Permalink
#1073 add functionality to select date/time locales and timezones
Browse files Browse the repository at this point in the history
  • Loading branch information
junaidzm13 committed Jan 2, 2024
1 parent 7e0a79c commit 1f7a584
Show file tree
Hide file tree
Showing 19 changed files with 425 additions and 165 deletions.
2 changes: 1 addition & 1 deletion vuu-ui/cypress/pages/ShellWithNewTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class ShellWithNewTheme {
creator: string,
date: Date
) => {
const formattedDate = formatDate({ date: "dd.mm.yyyy" })(date);
const formattedDate = formatDate({ date: "ddmmyyyy" })(date);
const layoutTileName = `${layoutName} ${creator}, ${formattedDate}`;

return cy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class LocalPersistenceManager implements PersistenceManager {
const newMetadata: LayoutMetadata = {
...metadata,
id,
created: formatDate({ date: "dd.mm.yyyy" })(new Date()),
created: formatDate({ date: "ddmmyyyy" })(new Date()),
};

this.saveLayoutsWithMetadata(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const persistenceManager = new LocalPersistenceManager();

const existingId = "existing_id";

const newDate = formatDate({ date: "dd.mm.yyyy" })(new Date());
const newDate = formatDate({ date: "ddmmyyyy" })(new Date());

const existingMetadata: LayoutMetadata = {
id: existingId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import {
FormField,
FormFieldLabel,
Switch,
ToggleButton,
ToggleButtonGroup,
} from "@salt-ds/core";
Expand All @@ -19,61 +20,18 @@ import { FormattingSettingsProps } from "./types";

export const DateTimeFormattingSettings: React.FC<
FormattingSettingsProps<DateTimeColumnDescriptor>
> = (props) => {
const { column, onChangeFormatting: onChange } = props;
> = ({ column, onChangeFormatting: onChange }) => {
const formatting = getTypeFormattingFromColumn(column);
const { pattern = fallbackDateTimePattern } = formatting;
const toggleValue = useMemo(() => getToggleValue(pattern), [pattern]);

const [fallbackState, setFallbackState] = useState<Required<DateTimePattern>>(
{
time: pattern.time ?? defaultPatternsByType.time,
date: pattern.date ?? defaultPatternsByType.date,
}
);

const onPatternChange = useCallback(
(pattern: DateTimePattern) => onChange({ ...formatting, pattern }),
[onChange, formatting]
);

const onDropdownChange = useCallback<
<T extends keyof DateTimePattern>(
key: T
) => SingleSelectionHandler<Required<DateTimePattern>[T]>
>(
(key) => (_, p) => {
const updatedPattern = { ...(pattern ?? {}), [key]: p };
setFallbackState((s) => ({
time: updatedPattern.time ?? s.time,
date: updatedPattern.date ?? s.date,
}));
onPatternChange(updatedPattern);
},
[onPatternChange, pattern]
);

const onToggleChange = useCallback(
(evnt: SyntheticEvent<HTMLButtonElement, Event>) => {
const value = evnt.currentTarget.value as ToggleValue;
switch (value) {
case "time":
return onPatternChange({
[value]: pattern[value] ?? fallbackState[value],
});
case "date":
return onPatternChange({
[value]: pattern[value] ?? fallbackState[value],
});
case "both":
return onPatternChange({
time: pattern.time ?? fallbackState.time,
date: pattern.date ?? fallbackState.date,
});
}
},
[onPatternChange]
);
const { onDropdownChange, onSwitchChange, onToggleChange } =
useDateTimeFormattingSettings({ pattern, onPatternChange });

return (
<>
Expand Down Expand Up @@ -105,14 +63,16 @@ export const DateTimeFormattingSettings: React.FC<
/>
</FormField>
))}

<FormField labelPlacement="left">
<FormFieldLabel>{"Show time-zone"}</FormFieldLabel>
<Switch checked={!!pattern.showTimeZone} onChange={onSwitchChange} />
</FormField>
</>
);
};

const labelByType: Record<keyof DateTimePattern, string> = {
date: "Date",
time: "Time",
};
const labelByType = { date: "Date", time: "Time" } as const;

const toggleValues = ["date", "time", "both"] as const;

Expand All @@ -127,3 +87,71 @@ function getToggleValue(pattern: DateTimePattern): ToggleValue {
? "time"
: "both";
}

type RequiredDateTimePattern = Required<Pick<DateTimePattern, "date" | "time">>;

function useDateTimeFormattingSettings(props: {
pattern: DateTimePattern;
onPatternChange: (p: DateTimePattern) => void;
}) {
const { pattern, onPatternChange } = props;
const [fallbackState, setFallbackState] = useState<RequiredDateTimePattern>({
time: pattern.time ?? defaultPatternsByType.time,
date: pattern.date ?? defaultPatternsByType.date,
});

const onDropdownChange = useCallback<
<T extends keyof RequiredDateTimePattern>(
key: T
) => SingleSelectionHandler<RequiredDateTimePattern[T]>
>(
(key) => (_, p) => {
const updatedPattern = { ...(pattern ?? {}), [key]: p };
setFallbackState((s) => ({
time: updatedPattern.time ?? s.time,
date: updatedPattern.date ?? s.date,
}));
onPatternChange(updatedPattern);
},
[onPatternChange, pattern]
);

const onToggleChange = useCallback(
(evnt: SyntheticEvent<HTMLButtonElement, Event>) => {
const value = evnt.currentTarget.value as ToggleValue;
switch (value) {
case "time":
return onPatternChange({
...pattern,
time: pattern.time ?? fallbackState.time,
date: undefined,
});
case "date":
return onPatternChange({
...pattern,
time: undefined,
date: pattern.date ?? fallbackState.date,
});
case "both":
return onPatternChange({
...pattern,
time: pattern.time ?? fallbackState.time,
date: pattern.date ?? fallbackState.date,
});
}
},
[onPatternChange, pattern, fallbackState]
);

const onSwitchChange = useCallback<
React.ChangeEventHandler<HTMLInputElement>
>(
(e) => {
const { checked: showTimeZone } = e.target;
onPatternChange({ ...pattern, showTimeZone });
},
[onPatternChange, pattern]
);

return { onDropdownChange, onSwitchChange, onToggleChange };
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useMemo } from "react";
import { Dropdown, SingleSelectionHandler } from "@finos/vuu-ui-controls";
import {
Button,
FormField,
Expand All @@ -6,7 +8,15 @@ import {
ToggleButton,
ToggleButtonGroup,
} from "@salt-ds/core";
import { TableSettingsProps } from "@finos/vuu-table-types";
import {
localeOptions,
timeZoneOptions,
getDefaultLocaleAndTimeZone,
} from "@finos/vuu-utils";
import {
DateTimeTableAttributes,
TableSettingsProps,
} from "@finos/vuu-table-types";
import { ColumnList } from "../column-list";
import { useTableSettings } from "./useTableSettings";

Expand All @@ -33,6 +43,7 @@ export const TableSettingsPanel = ({
onChangeColumnLabels,
onChangeTableAttribute,
onColumnChange,
onChangeDateTimeAttribute,
onMoveListItem,
tableConfig,
} = useTableSettings({
Expand Down Expand Up @@ -101,6 +112,12 @@ export const TableSettingsPanel = ({
<Input className="vuuInput" />
</FormField>

<DateTimeAttributesSettings
dateTimeAttrs={tableConfig.dateTime ?? {}}
onLocaleChange={onChangeDateTimeAttribute("locale")}
onTimeZoneChange={onChangeDateTimeAttribute("timeZone")}
/>

<ColumnList
columnItems={columnItems}
onChange={onColumnChange}
Expand All @@ -117,3 +134,47 @@ export const TableSettingsPanel = ({
</div>
);
};

const DateTimeAttributesSettings: React.FC<{
dateTimeAttrs: DateTimeTableAttributes;
onLocaleChange: SingleSelectionHandler<string>;
onTimeZoneChange: SingleSelectionHandler<string>;
}> = ({ dateTimeAttrs, onLocaleChange, onTimeZoneChange }) => {
const { locale: defaultLocale, timeZone: defaultTimeZone } =
getDefaultLocaleAndTimeZone();
const { locale = defaultLocale, timeZone = defaultTimeZone } = dateTimeAttrs;

const localesSource = useMemo(
() => [...new Set([...localeOptions, locale, defaultLocale])].sort(),
[locale, defaultLocale]
);

const timeZonesSource = useMemo(
() => [...new Set([...timeZoneOptions, timeZone, defaultTimeZone])].sort(),
[timeZone, defaultTimeZone]
);

return (
<>
<FormField>
<FormFieldLabel>Date/time locale</FormFieldLabel>
<Dropdown
onSelectionChange={onLocaleChange}
selected={locale}
source={localesSource}
width="100%"
/>
</FormField>

<FormField>
<FormFieldLabel>Time-zone</FormFieldLabel>
<Dropdown
onSelectionChange={onTimeZoneChange}
selected={timeZone}
source={timeZonesSource}
width="100%"
/>
</FormField>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SchemaColumn } from "@finos/vuu-data-types";
import { updateTableConfig } from "@finos/vuu-table";
import {
ColumnDescriptor,
DateTimeTableAttributes,
TableConfig,
TableSettingsProps,
} from "@finos/vuu-table-types";
Expand All @@ -20,6 +21,7 @@ import {
useState,
} from "react";
import { ColumnChangeHandler } from "../column-list";
import { SingleSelectionHandler } from "@finos/vuu-ui-controls";

const sortOrderFromAvailableColumns = (
availableColumns: SchemaColumn[],
Expand Down Expand Up @@ -194,6 +196,23 @@ export const useTableSettings = ({
[]
);

const handleChangeDateTimeAttribute = useCallback<
<T extends keyof DateTimeTableAttributes>(
key: T
) => SingleSelectionHandler<DateTimeTableAttributes[T]>
>(
(key) => (_, value) => {
setColumnState((s) => ({
...s,
tableConfig: {
...s.tableConfig,
dateTime: { ...s.tableConfig.dateTime, [key]: value },
},
}));
},
[]
);

useLayoutEffectSkipFirst(() => {
onConfigChange?.(tableConfig);
}, [onConfigChange, tableConfig]);
Expand All @@ -211,6 +230,7 @@ export const useTableSettings = ({
onChangeColumnLabels: handleChangeColumnLabels,
onChangeTableAttribute: handleChangeTableAttribute,
onColumnChange: handleColumnChange,
onChangeDateTimeAttribute: handleChangeDateTimeAttribute,
onMoveListItem: handleMoveListItem,
tableConfig,
};
Expand Down
6 changes: 6 additions & 0 deletions vuu-ui/packages/vuu-table-types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,19 @@ export interface TableCellRendererProps
onCommit?: DataItemCommitHandler;
}

export declare type DateTimeTableAttributes = {
timeZone?: string;
locale?: string;
};

export interface TableAttributes {
columnDefaultWidth?: number;
columnFormatHeader?: "capitalize" | "uppercase";
columnSeparators?: boolean;
// showHighlightedRow?: boolean;
rowSeparators?: boolean;
zebraStripes?: boolean;
dateTime?: DateTimeTableAttributes;
}

/**
Expand Down
13 changes: 10 additions & 3 deletions vuu-ui/packages/vuu-table/src/useTableModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,11 @@ const columnDescriptorToRuntimeColumDescriptor =
column: ColumnDescriptor & { key?: number },
index: number
): RuntimeColumnDescriptor => {
const { columnDefaultWidth = DEFAULT_COLUMN_WIDTH, columnFormatHeader } =
tableAttributes;
const {
columnDefaultWidth = DEFAULT_COLUMN_WIDTH,
columnFormatHeader,
dateTime: dateTimeTableAttributes,
} = tableAttributes;
const serverDataType = getDataType(column, tableSchema);
const {
align = getDefaultAlignment(serverDataType),
Expand All @@ -314,7 +317,11 @@ const columnDescriptorToRuntimeColumDescriptor =
name,
originalIdx: index,
serverDataType,
valueFormatter: getValueFormatter(column, serverDataType),
valueFormatter: getValueFormatter(
column,
serverDataType,
dateTimeTableAttributes
),
width: width,
};

Expand Down
Loading

0 comments on commit 1f7a584

Please sign in to comment.