Skip to content

Commit

Permalink
finos#1073 first cut
Browse files Browse the repository at this point in the history
  • Loading branch information
junaidzm13 committed Dec 27, 2023
1 parent 76e6a46 commit 02e4567
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import React, { useCallback } from "react";
import { Dropdown, SingleSelectionHandler } from "@finos/vuu-ui-controls";
import {
DateTimePattern,
defaultDateTimePatterns,
getTypeFormattingFromColumn,
isTypeDescriptor,
supportedDateTimePatterns,
} from "@finos/vuu-utils";
import { FormField, FormFieldLabel } from "@salt-ds/core";
Expand All @@ -20,23 +18,37 @@ export const DateTimeFormattingSettings: React.FC<
> = (props) => {
const { column, onChange } = props;
const formatting = getTypeFormattingFromColumn(column);
const type = isTypeDescriptor(column.type) ? column.type.name : column.type;
const { pattern = {} } = formatting;

const handleOnChange = useCallback<SingleSelectionHandler<DateTimePattern>>(
(_, pattern) => onChange({ ...formatting, pattern }),
const handleOnChange = useCallback<
<T extends keyof DateTimePattern>(
key: T
) => SingleSelectionHandler<Required<DateTimePattern>[T] | "None">
>(
(key) => (_, pattern) => {
const updatedFormatting = {
...formatting,
pattern: { [key]: pattern === "None" ? undefined : pattern },
};
onChange(updatedFormatting);
},
[onChange, formatting]
);

return (
<FormField>
<FormFieldLabel>{`${labelByType[type]} format`}</FormFieldLabel>
<Dropdown<DateTimePattern>
onSelectionChange={handleOnChange}
selected={formatting.pattern ?? defaultDateTimePatterns[type]}
source={supportedDateTimePatterns[type]}
width="100%"
/>
</FormField>
<>
{(["date", "time"] as const).map((v) => (
<FormField>
<FormFieldLabel>{`${labelByType[v]} pattern`}</FormFieldLabel>
<Dropdown<Required<DateTimePattern>[typeof v] | "None">
onSelectionChange={handleOnChange(v)}
selected={pattern[v] ?? "None"}
source={["None", ...supportedDateTimePatterns[v]]}
width="100%"
/>
</FormField>
))}
</>
);
};

Expand Down
43 changes: 31 additions & 12 deletions vuu-ui/packages/vuu-utils/src/date/formatter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isNotNullOrUndefined } from "../ts-utils";
import { DatePattern, DateTimePattern, TimePattern } from "./types";

type DateTimeFormatConfig = {
Expand Down Expand Up @@ -55,19 +56,37 @@ const formatConfigByDatePatterns: Record<DatePattern, DateTimeFormatConfig> = {
},
};

const formatConfigByDateTimePatterns: Record<
DateTimePattern,
DateTimeFormatConfig
> = { ...formatConfigByDatePatterns, ...formatConfigByTimePatterns };
function getFormatConfigs(pattern: DateTimePattern) {
return [
isNotNullOrUndefined(pattern["date"])
? formatConfigByDatePatterns[pattern["date"]]
: null,
isNotNullOrUndefined(pattern["time"])
? formatConfigByTimePatterns[pattern["time"]]
: null,
];
}

function applyFormatting(
d: Date,
opts: { dateTimeFormat: Intl.DateTimeFormat } & Pick<
DateTimeFormatConfig,
"postProcessor"
>
): string {
const { dateTimeFormat, postProcessor } = opts;
const dateStr = dateTimeFormat.format(d);
return postProcessor ? postProcessor(dateStr) : dateStr;
}

export function formatDate(pattern: DateTimePattern): (d: Date) => string {
const { locale, options, postProcessor } =
formatConfigByDateTimePatterns[pattern];
const dateTimeFormat = Intl.DateTimeFormat(locale, options);
const formattingOpts = getFormatConfigs(pattern)
.filter(isNotNullOrUndefined)
.map((c) => ({
dateTimeFormat: Intl.DateTimeFormat(c.locale, c.options),
postProcessor: c.postProcessor,
}));

return (d) => {
const dateStr = dateTimeFormat.format(d);
console.log({ dateStr });
return postProcessor ? postProcessor(dateStr) : dateStr;
};
return (d) =>
formattingOpts.map((opts) => applyFormatting(d, opts)).join(" ");
}
19 changes: 7 additions & 12 deletions vuu-ui/packages/vuu-utils/src/date/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import {
DateTimeColumnTypeSimple,
DateTimeColumnDescriptor,
} from "@finos/vuu-table-types";
import { DateTimeColumnDescriptor } from "@finos/vuu-table-types";
import { isTypeDescriptor } from "../column-utils";
import { DateTimePattern, isDateTimePattern } from "./types";

export const defaultDateTimePatterns: Record<
DateTimeColumnTypeSimple,
DateTimePattern
> = { time: "hh:mm:ss", date: "dd.mm.yyyy" };
export const defaultDateTimePattern = {
time: "hh:mm:ss",
date: "dd.mm.yyyy",
} as const;

export function dateTimePattern(
type: DateTimeColumnDescriptor["type"]
Expand All @@ -17,9 +14,7 @@ export function dateTimePattern(
if (type.formatting && isDateTimePattern(type.formatting.pattern)) {
return type.formatting.pattern;
}

return defaultDateTimePatterns[type.name];
} else {
return defaultDateTimePatterns[type];
}

return defaultDateTimePattern;
}
1 change: 0 additions & 1 deletion vuu-ui/packages/vuu-utils/src/date/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ export {
type DateTimePattern,
supportedDateTimePatterns,
} from "./types";
export { defaultDateTimePatterns } from "./helpers";
21 changes: 11 additions & 10 deletions vuu-ui/packages/vuu-utils/src/date/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DateTimeColumnTypeSimple } from "packages/vuu-table-types";
import { ColumnTypeFormatting } from "@finos/vuu-table-types";
import { isNotNullOrUndefined } from "../ts-utils";

const supportedDatePatterns = [
"dd.mm.yyyy",
Expand All @@ -12,17 +13,15 @@ const supportedDatePatterns = [

const supportedTimePatterns = ["hh:mm:ss", "hh:mm:ss a"] as const;

export const supportedDateTimePatterns: Record<
DateTimeColumnTypeSimple,
Array<DateTimePattern>
> = {
date: [...supportedDatePatterns],
time: [...supportedTimePatterns],
export const supportedDateTimePatterns = {
date: supportedDatePatterns,
time: supportedTimePatterns,
};

export type DatePattern = (typeof supportedDatePatterns)[number];
export type TimePattern = (typeof supportedTimePatterns)[number];
export type DateTimePattern = DatePattern | TimePattern;

export type DateTimePattern = { date?: DatePattern; time?: TimePattern };

const isDatePattern = (pattern: string): pattern is DatePattern =>
supportedDatePatterns.includes(pattern as DatePattern);
Expand All @@ -31,6 +30,8 @@ const isTimePattern = (pattern: string): pattern is TimePattern =>
supportedTimePatterns.includes(pattern as TimePattern);

export const isDateTimePattern = (
pattern?: string
pattern?: ColumnTypeFormatting["pattern"]
): pattern is DateTimePattern =>
pattern !== undefined && (isDatePattern(pattern) || isTimePattern(pattern));
isNotNullOrUndefined(pattern) &&
((isNotNullOrUndefined(pattern.date) && isDatePattern(pattern.date)) ||
(isNotNullOrUndefined(pattern.time) && isTimePattern(pattern.time)));
2 changes: 1 addition & 1 deletion vuu-ui/packages/vuu-utils/src/formatting-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import {
ColumnDescriptor,
ColumnTypeValueMap,
ColumnTypeFormatting,
DateTimeColumnDescriptor,
} from "@finos/vuu-table-types";
import { roundDecimal } from "./round-decimal";
import {
isDateTimeColumn,
isTypeDescriptor,
isMappedValueTypeRenderer,
DateTimeColumnDescriptor,
} from "./column-utils";
import { formatDate } from "./date";
import { dateTimePattern } from "./date/helpers";
Expand Down
1 change: 1 addition & 0 deletions vuu-ui/packages/vuu-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ export * from "./row-utils";
export * from "./selection-utils";
export * from "./sort-utils";
export * from "./text-utils";
export * from "./ts-utils";
export * from "./url-utils";
export * from "./screenshot-utils";
5 changes: 5 additions & 0 deletions vuu-ui/packages/vuu-utils/src/ts-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function isNotNullOrUndefined<T extends any>(
value: T | undefined | null
): value is NonNullable<T> {
return value !== undefined && value !== null;
}
26 changes: 17 additions & 9 deletions vuu-ui/packages/vuu-utils/test/date/formatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ const testDate = new Date(2010, 5, 12, 15, 50, 37);

describe("formatDate", () => {
it.each<{ pattern: DateTimePattern; expected: string }>([
{ pattern: "dd.mm.yyyy", expected: "12.06.2010" },
{ pattern: "dd/mm/yyyy", expected: "12/06/2010" },
{ pattern: "dd MMM yyyy", expected: "12 Jun 2010" },
{ pattern: "dd MMMM yyyy", expected: "12 June 2010" },
{ pattern: "mm/dd/yyyy", expected: "06/12/2010" },
{ pattern: "MMM dd, yyyy", expected: "Jun 12, 2010" },
{ pattern: "MMMM dd, yyyy", expected: "June 12, 2010" },
{ pattern: "hh:mm:ss", expected: "15:50:37" },
{ pattern: "hh:mm:ss a", expected: "03:50:37 pm" },
{ pattern: { date: "dd.mm.yyyy" }, expected: "12.06.2010" },
{ pattern: { date: "dd/mm/yyyy" }, expected: "12/06/2010" },
{ pattern: { date: "dd MMM yyyy" }, expected: "12 Jun 2010" },
{ pattern: { date: "dd MMMM yyyy" }, expected: "12 June 2010" },
{ pattern: { date: "mm/dd/yyyy" }, expected: "06/12/2010" },
{ pattern: { date: "MMM dd, yyyy" }, expected: "Jun 12, 2010" },
{ pattern: { date: "MMMM dd, yyyy" }, expected: "June 12, 2010" },
{ pattern: { time: "hh:mm:ss" }, expected: "15:50:37" },
{ pattern: { time: "hh:mm:ss a" }, expected: "03:50:37 pm" },
{
pattern: { date: "dd.mm.yyyy", time: "hh:mm:ss a" },
expected: "12.06.2010 03:50:37 pm",
},
{
pattern: { date: "MMMM dd, yyyy", time: "hh:mm:ss a" },
expected: "June 12, 2010 03:50:37 pm",
},
])(
"can correctly format date with the given pattern $pattern",
({ pattern, expected }) => {
Expand Down
8 changes: 4 additions & 4 deletions vuu-ui/packages/vuu-utils/test/date/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { describe, expect, it } from "vitest";
import {
dateTimePattern,
defaultDateTimePatterns,
defaultDateTimePattern,
} from "../../src/date/helpers";
import { DateTimePattern } from "../../src/date/types";

const testPattern: DateTimePattern = "mm/dd/yyyy";
const testPattern: DateTimePattern = { date: "mm/dd/yyyy" };

describe("dateTimePattern", () => {
it("returns exact pattern when found in descriptor type", () => {
Expand All @@ -20,12 +20,12 @@ describe("dateTimePattern", () => {
it("falls back to default when pattern not found in descriptor type", () => {
const type = { name: "time" as const, formatting: {} };
const actualPattern = dateTimePattern(type);
expect(actualPattern).toEqual(defaultDateTimePatterns["time"]);
expect(actualPattern).toEqual(defaultDateTimePattern);
});

it("falls back to default when simple type", () => {
const type = "date";
const actualPattern = dateTimePattern(type);
expect(actualPattern).toEqual(defaultDateTimePatterns["date"]);
expect(actualPattern).toEqual(defaultDateTimePattern);
});
});

0 comments on commit 02e4567

Please sign in to comment.