Skip to content

Commit

Permalink
feat: Consider data type to set dimension resolution + do not trim cu…
Browse files Browse the repository at this point in the history
…rrency values

Instead of trimming currency values, we pad if necessary
  • Loading branch information
ptbrowne committed Aug 24, 2022
1 parent ca2323d commit 3b33b06
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 15 deletions.
23 changes: 22 additions & 1 deletion app/configurator/components/ui-helpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ describe("useDimensionFormatters", () => {
currencyExponent: 1,
__typename: "Measure",
} as DimensionMetadataFragment,
{
iri: "iri-currency-int",
isNumerical: true,
isKeyDimension: false,
isCurrency: true,
currencyExponent: 1,
resolution: 0,
__typename: "Measure",
} as DimensionMetadataFragment,
])
);
return { formatters };
Expand All @@ -86,7 +95,19 @@ describe("useDimensionFormatters", () => {

it("should work with currencies", () => {
const { formatters } = setup();
expect(formatters["iri-currency"]("20002.3333")).toEqual("20'002,3");

// Keeps precision if it is over the currencyExponent
expect(formatters["iri-currency"]("20002.3333")).toEqual("20'002,3333");

// Pads with 0 otherwise
expect(formatters["iri-currency"]("20002")).toEqual("20'002,0");
});

it("should work with dimension marked with currency and with datatype integer", () => {
const { formatters } = setup();

// If we have a resolution on the dimension
expect(formatters["iri-currency-int"]("20002")).toEqual("20'002");
});
});

Expand Down
33 changes: 27 additions & 6 deletions app/configurator/components/ui-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,36 @@ const namedNodeFormatter = (d: DimensionMetadataFragment) => {
};
};

const currencyFormatter = (d: Measure) => {
const formatLocale = getD3FormatLocale();
// Use the currency exponent from the dimension, with default 2
return formatLocale.format(`,.${d.currencyExponent || 2}f`);
const currencyFormatter = (d: Measure, locale: string) => {
const formatLocale = getD3FormatLocale(locale);
const minDecimals = d.resolution ?? d.currencyExponent ?? 2;
const maxDecimals = 8;
const baseFormatter = formatLocale.format(`,.${maxDecimals}f`);
return (v: number) => {
const formatted = baseFormatter(v);
const l = formatted.length;

// TODO Decimal separator should be based on locale
const dot = formatted.indexOf(".");

let lastSignificantIndex = formatted.length - maxDecimals + minDecimals - 1;
for (let i = l - maxDecimals + minDecimals; i < l; i++) {
if (formatted[i] !== "0") {
lastSignificantIndex = i;
}
}
return formatted.substring(
0,
lastSignificantIndex +
(minDecimals === 0 || dot === lastSignificantIndex ? 0 : 1)
);
};
};

export const useDimensionFormatters = (
dimensions: DimensionMetadataFragment[]
) => {
const locale = useLocale();
const formatNumber = useFormatNumber() as unknown as (
d: number | string
) => string;
Expand All @@ -169,7 +190,7 @@ export const useDimensionFormatters = (
let formatter: (s: any) => string;
if (d.__typename === "Measure") {
if (d.isCurrency) {
formatter = currencyFormatter(d);
formatter = currencyFormatter(d, locale);
} else {
formatter = formatNumber;
}
Expand All @@ -190,7 +211,7 @@ export const useDimensionFormatters = (
return [d.iri, formatter];
})
);
}, [dimensions, formatNumber, dateFormatters, formatDateAuto]);
}, [locale, dimensions, formatNumber, dateFormatters, formatDateAuto]);
};

export type LocalDateFormatters = ReturnType<typeof getFormattersForLocale>;
Expand Down
1 change: 1 addition & 0 deletions app/graphql/queries/data-cubes.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ fragment dimensionMetadata on Dimension {
... on Measure {
isCurrency
currencyExponent
resolution
}
}

Expand Down
4 changes: 3 additions & 1 deletion app/graphql/query-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ export type Measure = Dimension & {
isKeyDimension: Scalars['Boolean'];
isCurrency?: Maybe<Scalars['Boolean']>;
currencyExponent?: Maybe<Scalars['Int']>;
resolution?: Maybe<Scalars['Int']>;
values: Array<Scalars['DimensionValue']>;
related?: Maybe<Array<RelatedDimension>>;
hierarchy?: Maybe<Array<HierarchyValue>>;
Expand Down Expand Up @@ -455,7 +456,7 @@ type DimensionMetadata_GeoCoordinatesDimension_Fragment = { __typename: 'GeoCoor

type DimensionMetadata_GeoShapesDimension_Fragment = { __typename: 'GeoShapesDimension', iri: string, label: string, isNumerical: boolean, isKeyDimension: boolean, order?: Maybe<number>, values: Array<any>, unit?: Maybe<string>, related?: Maybe<Array<{ __typename: 'RelatedDimension', iri: string, type: string }>> };

type DimensionMetadata_Measure_Fragment = { __typename: 'Measure', isCurrency?: Maybe<boolean>, currencyExponent?: Maybe<number>, iri: string, label: string, isNumerical: boolean, isKeyDimension: boolean, order?: Maybe<number>, values: Array<any>, unit?: Maybe<string>, related?: Maybe<Array<{ __typename: 'RelatedDimension', iri: string, type: string }>> };
type DimensionMetadata_Measure_Fragment = { __typename: 'Measure', isCurrency?: Maybe<boolean>, currencyExponent?: Maybe<number>, resolution?: Maybe<number>, iri: string, label: string, isNumerical: boolean, isKeyDimension: boolean, order?: Maybe<number>, values: Array<any>, unit?: Maybe<string>, related?: Maybe<Array<{ __typename: 'RelatedDimension', iri: string, type: string }>> };

type DimensionMetadata_NominalDimension_Fragment = { __typename: 'NominalDimension', iri: string, label: string, isNumerical: boolean, isKeyDimension: boolean, order?: Maybe<number>, values: Array<any>, unit?: Maybe<string>, related?: Maybe<Array<{ __typename: 'RelatedDimension', iri: string, type: string }>> };

Expand Down Expand Up @@ -854,6 +855,7 @@ export const DimensionMetadataFragmentDoc = gql`
... on Measure {
isCurrency
currencyExponent
resolution
}
}
`;
Expand Down
2 changes: 2 additions & 0 deletions app/graphql/resolver-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ export type Measure = Dimension & {
isKeyDimension: Scalars['Boolean'];
isCurrency?: Maybe<Scalars['Boolean']>;
currencyExponent?: Maybe<Scalars['Int']>;
resolution?: Maybe<Scalars['Int']>;
values: Array<Scalars['DimensionValue']>;
related?: Maybe<Array<RelatedDimension>>;
hierarchy?: Maybe<Array<HierarchyValue>>;
Expand Down Expand Up @@ -714,6 +715,7 @@ export type MeasureResolvers<ContextType = GraphQLContext, ParentType extends Re
isKeyDimension?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
isCurrency?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
currencyExponent?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
resolution?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
values?: Resolver<Array<ResolversTypes['DimensionValue']>, ParentType, ContextType, RequireFields<MeasureValuesArgs, 'sourceType' | 'sourceUrl'>>;
related?: Resolver<Maybe<Array<ResolversTypes['RelatedDimension']>>, ParentType, ContextType>;
hierarchy?: Resolver<Maybe<Array<ResolversTypes['HierarchyValue']>>, ParentType, ContextType, RequireFields<MeasureHierarchyArgs, 'sourceType' | 'sourceUrl'>>;
Expand Down
9 changes: 3 additions & 6 deletions app/graphql/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,8 @@ export const resolvers: Resolvers = {
},
Measure: {
...mkDimensionResolvers("Measure"),
isCurrency: ({ data: { isCurrency } }) => {
return isCurrency;
},
currencyExponent: ({ data: { currencyExponent } }) => {
return currencyExponent || 0;
},
isCurrency: ({ data: { isCurrency } }) => isCurrency,
currencyExponent: ({ data: { currencyExponent } }) => currencyExponent || 0,
resolution: ({ data: { resolution } }) => resolution ?? null,
},
};
1 change: 1 addition & 0 deletions app/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ type Measure implements Dimension {
isKeyDimension: Boolean!
isCurrency: Boolean
currencyExponent: Int
resolution: Int
values(
sourceType: String!
sourceUrl: String!
Expand Down
1 change: 1 addition & 0 deletions app/graphql/shared-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type ResolvedDimension = {
currencyExponent?: number;
hasUndefinedValues: boolean;
unit?: string;
resolution?: number;
dataType?: string;
order?: number;
name: string;
Expand Down
10 changes: 9 additions & 1 deletion app/rdf/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ export const parseCubeDimension = ({
const rawOrder = dim.out(ns.sh.order).value;
const order = rawOrder !== undefined ? parseInt(rawOrder, 10) : undefined;

const name = dim.out(ns.schema.name, outOpts).value ?? dim.path?.value!;
const resolution =
dataType?.equals(ns.xsd.int) || dataType?.equals(ns.xsd.integer)
? 0
: undefined;

console.log({ name, resolution });
return {
cube,
dimension: dim,
Expand All @@ -252,11 +259,12 @@ export const parseCubeDimension = ({
hasUndefinedValues,
unit: dimensionUnitLabel,
dataType: dataType?.value,
resolution,
isCurrency: !!dimensionUnit?.isCurrency?.value,
currencyExponent: dimensionUnit?.currencyExponent?.value
? parseInt(dimensionUnit?.currencyExponent?.value)
: undefined,
name: dim.out(ns.schema.name, outOpts).value ?? dim.path?.value!,
name,
order: order,
dataKind: dataKindTerm?.equals(ns.time.GeneralDateTimeDescription)
? "Time"
Expand Down

0 comments on commit 3b33b06

Please sign in to comment.