Skip to content

Commit

Permalink
Feature/custom limits (#758)
Browse files Browse the repository at this point in the history
* Dimension has now limits property

* Handle limits property in url decoders

* Hardcode small limit in resolvers. To be fixed in #756

* Use limits in Split menu

* Name expression for brevity

* Filter early faulty definitions in view definition converter
  • Loading branch information
adrianmroz-allegro authored Jun 9, 2021
1 parent 0901435 commit c2057ba
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 43 deletions.
17 changes: 9 additions & 8 deletions src/client/components/split-menu/limit-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

import * as React from "react";
import { AVAILABLE_LIMITS } from "../../../common/limit/limit";
import { Unary } from "../../../common/utils/functional/functional";
import { STRINGS } from "../../config/constants";
import { Dropdown } from "../dropdown/dropdown";
Expand All @@ -24,22 +23,24 @@ function formatLimit(limit: number): string {
return limit === null ? "None" : String(limit);
}

function calculateLimits(includeNone: boolean) {
if (!includeNone) return AVAILABLE_LIMITS;
return [...AVAILABLE_LIMITS, null];
// TODO: Review again when fixing time split menu in #756
function calculateLimits(limits: number[], includeNone: boolean) {
if (!includeNone) return limits;
return [...limits, null];
}

export interface LimitDropdownProps {
limit: number;
selectedLimit: number;
limits: number[];
includeNone: boolean;
onLimitSelect: Unary<number, void>;
}

export const LimitDropdown: React.SFC<LimitDropdownProps> = ({ onLimitSelect, limit, includeNone }) => {
export const LimitDropdown: React.SFC<LimitDropdownProps> = ({ onLimitSelect, limits, selectedLimit, includeNone }) => {
return <Dropdown<number | string>
label={STRINGS.limit}
items={calculateLimits(includeNone)}
selectedItem={limit}
items={calculateLimits(limits, includeNone)}
selectedItem={selectedLimit}
renderItem={formatLimit}
onSelect={onLimitSelect}
/>;
Expand Down
5 changes: 3 additions & 2 deletions src/client/components/split-menu/split-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ export class SplitMenu extends React.Component<SplitMenuProps, SplitMenuState> {
{this.renderSortDropdown()}
<LimitDropdown
onLimitSelect={this.saveLimit}
limit={limit}
includeNone={isContinuous(dimension)} />
selectedLimit={limit}
includeNone={isContinuous(dimension)}
limits={dimension.limits}/>
<div className="button-bar">
<Button className="ok" type="primary" disabled={!this.validate()} onClick={this.onOkClick} title={STRINGS.ok} />
<Button type="secondary" onClick={this.onCancelClick} title={STRINGS.cancel} />
Expand Down
6 changes: 5 additions & 1 deletion src/client/deserializers/dimension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { bucketingStrategies, ClientDimension, SerializedDimension } from "../..
import { TimeShift } from "../../common/models/time-shift/time-shift";

export function deserialize(dimension: SerializedDimension): ClientDimension {
const { description, url, name, title, expression, sortStrategy } = dimension;
const { description, url, name, title, expression, limits, sortStrategy } = dimension;

switch (dimension.kind) {
case "string": {
Expand All @@ -30,6 +30,7 @@ export function deserialize(dimension: SerializedDimension): ClientDimension {
url,
name,
title,
limits,
sortStrategy,
expression: Expression.fromJS(expression),
multiValue: dimension.multiValue
Expand All @@ -42,6 +43,7 @@ export function deserialize(dimension: SerializedDimension): ClientDimension {
url,
name,
title,
limits,
sortStrategy,
expression: Expression.fromJS(expression)
};
Expand All @@ -53,6 +55,7 @@ export function deserialize(dimension: SerializedDimension): ClientDimension {
url,
name,
title,
limits,
sortStrategy,
expression: Expression.fromJS(expression),
granularities,
Expand All @@ -68,6 +71,7 @@ export function deserialize(dimension: SerializedDimension): ClientDimension {
url,
name,
title,
limits,
sortStrategy,
expression: Expression.fromJS(expression),
bucketedBy: bucketedBy && Duration.fromJS(bucketedBy),
Expand Down
2 changes: 1 addition & 1 deletion src/common/limit/limit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
* limitations under the License.
*/

export const AVAILABLE_LIMITS = [5, 10, 25, 50, 100];
export const DEFAULT_LIMITS = [5, 10, 25, 50, 100];
30 changes: 29 additions & 1 deletion src/common/models/dimension/dimension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
DEFAULT_LATEST_PERIOD_DURATIONS,
DEFAULT_TIME_SHIFT_DURATIONS
} from "../../../client/components/filter-menu/time-filter-menu/presets";
import { DEFAULT_LIMITS } from "../../limit/limit";
import { makeTitle, verifyUrlSafeName } from "../../utils/general/general";
import { GranularityJS } from "../granularity/granularity";
import { Bucket } from "../split/split";
Expand All @@ -37,6 +38,7 @@ interface BaseDimension {
title: string;
description?: string;
expression: Expression;
limits: number[];
url?: string;
sortStrategy?: string;
}
Expand Down Expand Up @@ -99,6 +101,7 @@ export interface DimensionJS {
granularities?: GranularityJS[];
timeShiftDurations?: string[];
latestPeriodDurations?: string[];
limits?: number[];
bucketedBy?: GranularityJS;
bucketingStrategy?: BucketingStrategy;
sortStrategy?: string;
Expand All @@ -121,6 +124,7 @@ export function fromConfig(config: DimensionJS & LegacyDimension): Dimension {
const kind = rawKind ? readKind(rawKind) : typeToKind(config.type);
const expression = readExpression(config);
const title = rawTitle || makeTitle(name);
const limits = readLimits(config);
switch (kind) {
case "string": {
const { multiValue } = config;
Expand All @@ -130,6 +134,7 @@ export function fromConfig(config: DimensionJS & LegacyDimension): Dimension {
name,
title,
expression,
limits,
multiValue: Boolean(multiValue),
sortStrategy,
kind
Expand All @@ -142,6 +147,7 @@ export function fromConfig(config: DimensionJS & LegacyDimension): Dimension {
name,
title,
expression,
limits,
sortStrategy,
kind
};
Expand All @@ -159,6 +165,7 @@ export function fromConfig(config: DimensionJS & LegacyDimension): Dimension {
url,
description,
expression,
limits,
bucketedBy: bucketedBy && Duration.fromJS(bucketedBy as string),
bucketingStrategy: bucketingStrategy && bucketingStrategies[bucketingStrategy],
granularities: readGranularities(config, "time"),
Expand All @@ -180,6 +187,7 @@ export function fromConfig(config: DimensionJS & LegacyDimension): Dimension {
url,
description,
expression,
limits,
bucketedBy: bucketedBy && Number(bucketedBy),
bucketingStrategy: bucketingStrategy && bucketingStrategies[bucketingStrategy],
granularities: readGranularities(config, "number")
Expand All @@ -188,6 +196,14 @@ export function fromConfig(config: DimensionJS & LegacyDimension): Dimension {
}
}

function readLimits({ name, limits }: DimensionJS): number[] {
if (!limits) return DEFAULT_LIMITS;
if (!Array.isArray(limits)) {
throw new Error(`must have list of valid limits in dimension '${name}'`);
}
return limits;
}

function readLatestPeriodDurations({ name, latestPeriodDurations }: DimensionJS): Duration[] {
if (!latestPeriodDurations) return DEFAULT_LATEST_PERIODS;
if (!Array.isArray(latestPeriodDurations) || latestPeriodDurations.length !== 5) {
Expand Down Expand Up @@ -226,6 +242,7 @@ interface SerializedStringDimension {
title: string;
description?: string;
expression: ExpressionJS;
limits: number[];
url?: string;
sortStrategy?: string;
multiValue: boolean;
Expand All @@ -237,6 +254,7 @@ interface SerializedBooleanDimension {
title: string;
description?: string;
expression: ExpressionJS;
limits: number[];
url?: string;
sortStrategy?: string;
}
Expand All @@ -247,6 +265,7 @@ interface SerializedNumberDimension {
title: string;
description?: string;
expression: ExpressionJS;
limits: number[];
url?: string;
sortStrategy?: string;
granularities?: number[];
Expand All @@ -260,6 +279,7 @@ interface SerializedTimeDimension {
title: string;
description?: string;
expression: ExpressionJS;
limits: number[];
url?: string;
sortStrategy?: string;
granularities?: string[];
Expand All @@ -276,7 +296,7 @@ export type SerializedDimension =
| SerializedTimeDimension;

export function serialize(dimension: Dimension): SerializedDimension {
const { name, description, expression, title, sortStrategy, url } = dimension;
const { name, description, expression, title, sortStrategy, url, limits } = dimension;

// NOTE: If we move kind to destructuring above, typescript would not infer proper Dimension variant
switch (dimension.kind) {
Expand All @@ -288,6 +308,7 @@ export function serialize(dimension: Dimension): SerializedDimension {
name,
title,
expression: expression.toJS(),
limits,
multiValue,
sortStrategy,
kind: dimension.kind
Expand All @@ -300,6 +321,7 @@ export function serialize(dimension: Dimension): SerializedDimension {
name,
title,
expression: expression.toJS(),
limits,
sortStrategy,
kind: dimension.kind
};
Expand All @@ -311,6 +333,7 @@ export function serialize(dimension: Dimension): SerializedDimension {
name,
title,
expression: expression.toJS(),
limits,
sortStrategy,
bucketingStrategy,
bucketedBy: bucketedBy && bucketedBy.toJS(),
Expand All @@ -328,6 +351,7 @@ export function serialize(dimension: Dimension): SerializedDimension {
name,
title,
expression: expression.toJS(),
limits,
sortStrategy,
bucketingStrategy,
bucketedBy,
Expand Down Expand Up @@ -357,13 +381,15 @@ export function createDimension(kind: DimensionKind, name: string, expression: E
name,
title: makeTitle(name),
expression,
limits: DEFAULT_LIMITS,
multiValue: Boolean(multiValue)
};
case "boolean":
return {
kind,
name,
title: makeTitle(name),
limits: DEFAULT_LIMITS,
expression
};
case "time":
Expand All @@ -372,13 +398,15 @@ export function createDimension(kind: DimensionKind, name: string, expression: E
timeShiftDurations: DEFAULT_TIME_SHIFTS,
kind,
name,
limits: DEFAULT_LIMITS,
title: makeTitle(name),
expression
};
case "number":
return {
kind,
name,
limits: DEFAULT_LIMITS,
title: makeTitle(name),
expression
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class ViewDefinitionConverter3 implements ViewDefinitionConverter<ViewDef
const filter = Filter.fromClauses(definition.filters.map(fc => filterDefinitionConverter.toFilterClause(fc, dataCube)));

const splitDefinitions = List(definition.splits);
const splits = new Splits({ splits: splitDefinitions.map(splitConverter.toSplitCombine) });
const splits = new Splits({ splits: splitDefinitions.map(sd => splitConverter.toSplitCombine(sd, dataCube)) });

const pinnedDimensions = OrderedSet(definition.pinnedDimensions || []);
const pinnedSort = definition.pinnedSort;
Expand Down
Loading

0 comments on commit c2057ba

Please sign in to comment.