From ccf485a653ad333a25176858909680dfa59fed71 Mon Sep 17 00:00:00 2001 From: Adrian Mroz Date: Tue, 22 Feb 2022 21:29:50 +0100 Subject: [PATCH] Replace raw property access with proper Split utils --- .../splits/flattened-split-columns.tsx | 2 +- .../improved-bar-chart/bar/single-bar.tsx | 8 +++---- .../bar/single-time-shift-bar.tsx | 8 +++---- .../improved-bar-chart/bar/stacked-bar.tsx | 11 ++++----- .../bar/stacked-time-shift-bar.tsx | 13 ++++------- .../bars/bars-container.tsx | 6 +---- .../improved-bar-chart/bars/bars.tsx | 14 ++++------- .../foreground/foreground.tsx | 14 ++++------- .../foreground/highlight-modal.tsx | 16 +++++-------- .../foreground/highlight-overlay.tsx | 11 ++++----- .../hover-tooltip/hover-tooltip.tsx | 10 +++----- .../hover-tooltip/tooltip-content.tsx | 3 +-- .../interactions/interaction-controller.tsx | 5 ++-- .../utils/bar-chart-model.ts | 3 +-- .../utils/transpose-dataset.ts | 23 ++++++++++--------- .../improved-bar-chart/utils/x-domain.ts | 3 +-- .../improved-bar-chart/utils/x-scale.mocha.ts | 9 +------- .../improved-bar-chart/utils/x-scale.ts | 6 +---- .../charts/charts-per-series/series-chart.tsx | 4 ++-- .../series-hover-content.tsx | 4 ++-- .../charts/charts-per-split/label.tsx | 7 +++--- .../charts-per-split/nominal-value-key.ts | 8 +++---- .../charts/charts-per-split/split-chart.tsx | 2 +- .../interactions/find-closest-datum.ts | 18 +++++++-------- .../line-chart/legend/split-legend.tsx | 2 +- .../line-chart/utils/x-scale.ts | 10 ++++---- 26 files changed, 88 insertions(+), 132 deletions(-) diff --git a/src/client/components/tabular-scroller/splits/flattened-split-columns.tsx b/src/client/components/tabular-scroller/splits/flattened-split-columns.tsx index cbb9aa0a6..7ee6da422 100644 --- a/src/client/components/tabular-scroller/splits/flattened-split-columns.tsx +++ b/src/client/components/tabular-scroller/splits/flattened-split-columns.tsx @@ -32,7 +32,7 @@ export const FlattenedSplitColumns: React.SFC = ({ s {splits.map(split => { const { reference } = split; - const value = datum[reference]; + const value = split.selectValue(datum); return
{formatSegment(value, timezone)}
; })}
; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-bar.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-bar.tsx index a5d1fa46d..77d7ae4e0 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-bar.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-bar.tsx @@ -17,8 +17,8 @@ import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries } from "../../../../../common/models/series/concrete-series"; -import { Unary } from "../../../../../common/utils/functional/functional"; import { LinearScale } from "../../../../utils/linear-scale/linear-scale"; +import { BaseBarChartModel } from "../utils/bar-chart-model"; import { DomainValue } from "../utils/x-domain"; import { XScale } from "../utils/x-scale"; import { SIDE_PADDING } from "./padding"; @@ -28,13 +28,13 @@ interface SingleBarProps { yScale: LinearScale; xScale: XScale; series: ConcreteSeries; - getX: Unary; + model: BaseBarChartModel; } export const SingleBar: React.SFC = props => { - const { datum, xScale, yScale, getX, series } = props; + const { datum, xScale, yScale, model: { continuousSplit }, series } = props; const [maxHeight] = yScale.range(); - const x = getX(datum); + const x = continuousSplit.selectValue(datum); const xPos = xScale.calculate(x) + SIDE_PADDING; const width = xScale.rangeBand() - (2 * SIDE_PADDING); const y = series.selectValue(datum); diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-time-shift-bar.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-time-shift-bar.tsx index 150272f35..e3ea1b898 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-time-shift-bar.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/bar/single-time-shift-bar.tsx @@ -17,8 +17,8 @@ import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries, SeriesDerivation } from "../../../../../common/models/series/concrete-series"; -import { Unary } from "../../../../../common/utils/functional/functional"; import { LinearScale } from "../../../../utils/linear-scale/linear-scale"; +import { BaseBarChartModel } from "../utils/bar-chart-model"; import { DomainValue } from "../utils/x-domain"; import { XScale } from "../utils/x-scale"; import { SIDE_PADDING } from "./padding"; @@ -28,13 +28,13 @@ interface SingleTimeShiftBar { yScale: LinearScale; xScale: XScale; series: ConcreteSeries; - getX: Unary; + model: BaseBarChartModel; } export const SingleTimeShiftBar: React.SFC = props => { - const { datum, xScale, yScale, getX, series } = props; + const { datum, xScale, yScale, model: { continuousSplit }, series } = props; const [maxHeight] = yScale.range(); - const x = getX(datum); + const x = continuousSplit.selectValue(datum); const xStart = xScale.calculate(x); const rangeBand = xScale.rangeBand(); const fullWidth = rangeBand - 2 * SIDE_PADDING; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-bar.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-bar.tsx index c7c493392..c4c79b7aa 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-bar.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-bar.tsx @@ -17,7 +17,6 @@ import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries } from "../../../../../common/models/series/concrete-series"; -import { Unary } from "../../../../../common/utils/functional/functional"; import { selectSplitDatums } from "../../../../utils/dataset/selectors/selectors"; import { LinearScale } from "../../../../utils/linear-scale/linear-scale"; import { StackedBarChartModel } from "../utils/bar-chart-model"; @@ -32,21 +31,19 @@ interface StackedBarProps { yScale: LinearScale; xScale: XScale; series: ConcreteSeries; - getX: Unary; } export const StackedBar: React.SFC = props => { - const { datum, xScale, yScale, getX, series, model } = props; - const ref = model.nominalSplit.reference; + const { datum, xScale, yScale, series, model: { colors, continuousSplit, nominalSplit } } = props; const datums = selectSplitDatums(datum); - const x = getX(datum); + const x = continuousSplit.selectValue(datum); const xPos = xScale.calculate(x) + SIDE_PADDING; const width = xScale.rangeBand() - (2 * SIDE_PADDING); - const color = (d: Datum) => model.colors.get(String(d[ref])); + const color = (d: Datum) => colors.get(String(nominalSplit.selectValue(d))); return {datums.map(datum => { - const key = datum[ref]; + const key = String(nominalSplit.selectValue(datum)); const y = series.selectValue(datum); const y0 = selectBase(datum, series); const yPos = yScale(y + y0); diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-time-shift-bar.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-time-shift-bar.tsx index 79689513e..14efb9e27 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-time-shift-bar.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/bar/stacked-time-shift-bar.tsx @@ -18,7 +18,6 @@ import * as d3 from "d3"; import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries, SeriesDerivation } from "../../../../../common/models/series/concrete-series"; -import { Unary } from "../../../../../common/utils/functional/functional"; import { selectSplitDatums } from "../../../../utils/dataset/selectors/selectors"; import { LinearScale } from "../../../../utils/linear-scale/linear-scale"; import { StackedBarChartModel } from "../utils/bar-chart-model"; @@ -33,24 +32,22 @@ interface StackedTimeShiftBarProps { yScale: LinearScale; xScale: XScale; series: ConcreteSeries; - getX: Unary; } export const StackedTimeShiftBar: React.SFC = props => { - const { datum, xScale, yScale, getX, series, model } = props; - const { reference: nominalReference } = model.nominalSplit; + const { datum, xScale, yScale, series, model: { nominalSplit, continuousSplit, colors } } = props; const datums = selectSplitDatums(datum); - const x = getX(datum); + const x = continuousSplit.selectValue(datum); const xStart = xScale.calculate(x); const rangeBand = xScale.rangeBand(); const fullWidth = rangeBand - 2 * SIDE_PADDING; const barWidth = fullWidth * 2 / 3; - const color = (d: Datum) => model.colors.get(String(d[nominalReference])); + const color = (d: Datum) => colors.get(String(nominalSplit.selectValue(d))); return {datums.map(datum => { - const key = `${datum[nominalReference]}--previous`; + const key = `${nominalSplit.selectValue(datum)}--previous`; const yPrevious = series.selectValue(datum, SeriesDerivation.PREVIOUS); const yPreviousBase = selectBase(datum, series, SeriesDerivation.PREVIOUS); const yPreviousPos = yScale(yPrevious + yPreviousBase); @@ -70,7 +67,7 @@ export const StackedTimeShiftBar: React.SFC = props => />; })} {datums.map(datum => { - const key = `${datum[nominalReference]}--current`; + const key = `${nominalSplit.selectValue(datum)}--current`; const yCurrent = series.selectValue(datum); const yCurrentBase = selectBase(datum, series); const yCurrentPos = yScale(yCurrent + yCurrentBase); diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars-container.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars-container.tsx index b18f5a20a..8102474bd 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars-container.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars-container.tsx @@ -25,7 +25,7 @@ import { Foreground } from "../foreground/foreground"; import { Interaction } from "../interactions/interaction"; import { BarChartModel } from "../utils/bar-chart-model"; import { calculateChartStage } from "../utils/layout"; -import { xGetter, XScale } from "../utils/x-scale"; +import { XScale } from "../utils/x-scale"; import { yExtent } from "../utils/y-extent"; import { Bars } from "./bars"; import "./bars.scss"; @@ -53,8 +53,6 @@ export class BarsContainer extends React.Component { const { dropHighlight, acceptHighlight, interaction, model, stage, scrollLeft, series, totals, datums, xScale } = this.props; const hasComparison = model.hasComparison; const chartStage = calculateChartStage(stage); - const { reference: continuousReference } = model.continuousSplit; - const getX = xGetter(continuousReference); const extent = yExtent(datums, series, hasComparison); const yScale = getScale(extent, chartStage.height); @@ -73,7 +71,6 @@ export class BarsContainer extends React.Component { model={model} stage={chartStage} xScale={xScale} - getX={getX} series={series} datums={datums} /> {interaction && { model={model} xScale={xScale} series={series} - getX={getX} yScale={yScale} />} ; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars.tsx index f0809cfa0..5f4583c92 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/bars/bars.tsx @@ -18,14 +18,12 @@ import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries } from "../../../../../common/models/series/concrete-series"; import { Stage } from "../../../../../common/models/stage/stage"; -import { Unary } from "../../../../../common/utils/functional/functional"; import getScale, { LinearScale } from "../../../../utils/linear-scale/linear-scale"; import { SingleBar } from "../bar/single-bar"; import { SingleTimeShiftBar } from "../bar/single-time-shift-bar"; import { StackedBar } from "../bar/stacked-bar"; import { StackedTimeShiftBar } from "../bar/stacked-time-shift-bar"; -import { BarChartModel, isStacked, StackedBarChartModel } from "../utils/bar-chart-model"; -import { DomainValue } from "../utils/x-domain"; +import { BarChartModel, isStacked } from "../utils/bar-chart-model"; import { XScale } from "../utils/x-scale"; import { yExtent } from "../utils/y-extent"; import { Background } from "./background"; @@ -36,7 +34,6 @@ interface BarProps { yScale: LinearScale; xScale: XScale; series: ConcreteSeries; - getX: Unary; } const Bar: React.SFC = props => { @@ -48,21 +45,20 @@ const Bar: React.SFC = props => { : ; } return showPrevious - ? - : ; + ? + : ; }; interface BarsProps { model: BarChartModel; stage: Stage; xScale: XScale; - getX: Unary; series: ConcreteSeries; datums: Datum[]; } export const Bars: React.SFC = props => { - const { model, stage, getX, xScale, series, datums } = props; + const { model, stage, xScale, series, datums } = props; const extent = yExtent(datums, series, model.hasComparison); const yScale = getScale(extent, stage.height); if (!yScale) return null; @@ -77,7 +73,7 @@ export const Bars: React.SFC = props => { yScale={yScale} xScale={xScale} series={series} - getX={getX} />)} + />)} ; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/foreground/foreground.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/foreground/foreground.tsx index f98e4cf66..ce5ef5a39 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/foreground/foreground.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/foreground/foreground.tsx @@ -14,16 +14,14 @@ * limitations under the License. */ -import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries } from "../../../../../common/models/series/concrete-series"; import { Stage } from "../../../../../common/models/stage/stage"; -import { Nullary, Unary } from "../../../../../common/utils/functional/functional"; +import { Nullary } from "../../../../../common/utils/functional/functional"; import { LinearScale } from "../../../../utils/linear-scale/linear-scale"; import { HoverTooltip } from "../hover-tooltip/hover-tooltip"; import { Interaction, isHighlight, isHover } from "../interactions/interaction"; import { BarChartModel } from "../utils/bar-chart-model"; -import { DomainValue } from "../utils/x-domain"; import { XScale } from "../utils/x-scale"; import { HighlightModal } from "./highlight-modal"; import { HighlightOverlay } from "./highlight-overlay"; @@ -36,13 +34,12 @@ interface ForegroundProps { xScale: XScale; yScale: LinearScale; series: ConcreteSeries; - getX: Unary; model: BarChartModel; stage: Stage; } export const Foreground: React.SFC = props => { - const { stage, dropHighlight, acceptHighlight, container, getX, model, series, xScale, yScale, interaction } = props; + const { stage, dropHighlight, acceptHighlight, container, model, series, xScale, yScale, interaction } = props; const rect = container.current.getBoundingClientRect(); return {isHighlight(interaction) && @@ -50,27 +47,24 @@ export const Foreground: React.SFC = props => { interaction={interaction} dropHighlight={dropHighlight} acceptHighlight={acceptHighlight} - timezone={model.timezone} xScale={xScale} yScale={yScale} - getX={getX} + model={model} series={series} rect={rect} /> + model={model} /> } {isHover(interaction) && } ; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/foreground/highlight-modal.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/foreground/highlight-modal.tsx index 6e155edd0..7c5640751 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/foreground/highlight-modal.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/foreground/highlight-modal.tsx @@ -14,15 +14,13 @@ * limitations under the License. */ -import { Timezone } from "chronoshift"; -import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries } from "../../../../../common/models/series/concrete-series"; -import { formatValue } from "../../../../../common/utils/formatter/formatter"; -import { Nullary, Unary } from "../../../../../common/utils/functional/functional"; +import { Nullary } from "../../../../../common/utils/functional/functional"; import { HighlightModal as BaseHighlightModal } from "../../../../components/highlight-modal/highlight-modal"; import { LinearScale } from "../../../../utils/linear-scale/linear-scale"; import { Highlight } from "../interactions/interaction"; +import { BarChartModel } from "../utils/bar-chart-model"; import { DomainValue } from "../utils/x-domain"; import { XScale } from "../utils/x-scale"; @@ -30,31 +28,29 @@ interface HighlightModalProps { interaction: Highlight; dropHighlight: Nullary; acceptHighlight: Nullary; - timezone: Timezone; xScale: XScale; yScale: LinearScale; series: ConcreteSeries; - getX: Unary; + model: BarChartModel; rect: ClientRect | DOMRect; } export const HighlightModal: React.SFC = props => { const { - timezone, + model: { timezone, continuousSplit }, rect: { left, top }, interaction: { datum }, dropHighlight, acceptHighlight, yScale, - getX, series, xScale } = props; - const xValue = getX(datum); + const xValue = continuousSplit.selectValue(datum); const x = xScale.calculate(xValue) + (xScale.rangeBand() / 2); const yValue = series.selectValue(datum); const y = yScale(yValue); return ; stage: Stage; - showPrevious: boolean; + model: BarChartModel; } function getYValue(datum: Datum, series: ConcreteSeries, includePrevious: boolean): number { @@ -44,11 +43,11 @@ function getYValue(datum: Datum, series: ConcreteSeries, includePrevious: boolea } export const HighlightOverlay: React.SFC = props => { - const { stage, yScale, series, xScale, showPrevious, interaction: { datum }, getX } = props; - const xValue = getX(datum); + const { stage, yScale, series, xScale, model: { hasComparison, continuousSplit }, interaction: { datum } } = props; + const xValue = continuousSplit.selectValue(datum); const left = xScale.calculate(xValue); const right = left + xScale.rangeBand(); - const yValue = getYValue(datum, series, showPrevious); + const yValue = getYValue(datum, series, hasComparison); const top = yScale(yValue) + stage.y - TOP_PADDING; return ; }; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/hover-tooltip.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/hover-tooltip.tsx index c74cd83ce..6b4cc0764 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/hover-tooltip.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/hover-tooltip.tsx @@ -14,11 +14,8 @@ * limitations under the License. */ -import { Datum } from "plywood"; import * as React from "react"; import { ConcreteSeries } from "../../../../../common/models/series/concrete-series"; -import { formatValue } from "../../../../../common/utils/formatter/formatter"; -import { Unary } from "../../../../../common/utils/functional/functional"; import { SegmentBubble } from "../../../../components/segment-bubble/segment-bubble"; import { LinearScale } from "../../../../utils/linear-scale/linear-scale"; import { Hover } from "../interactions/interaction"; @@ -32,7 +29,6 @@ interface HoverTooltipProps { xScale: XScale; yScale: LinearScale; series: ConcreteSeries; - getX: Unary; model: BarChartModel; rect: ClientRect | DOMRect; } @@ -42,17 +38,17 @@ export const HoverTooltip: React.SFC = props => { model, rect: { left, top }, interaction: { datum }, - getX, series, xScale, yScale } = props; + const { continuousSplit, timezone } = model; const y = yScale(series.selectValue(datum)); - const xValue = getX(datum); + const xValue = continuousSplit.selectValue(datum); const x = xScale.calculate(xValue) + (xScale.rangeBand() / 2); return } />; }; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/tooltip-content.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/tooltip-content.tsx index c2a5a56b5..a89346628 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/tooltip-content.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/hover-tooltip/tooltip-content.tsx @@ -31,11 +31,10 @@ interface ContentProps { function colorEntries(datum: Datum, series: ConcreteSeries, model: StackedBarChartModel) { const { nominalSplit, colors, hasComparison } = model; - const { reference } = nominalSplit; const datums = selectSplitDatums(datum); const colorEntries = colors.entrySeq().toArray(); return colorEntries.map(([name, color]) => { - const datum = datums.find(d => String(d[reference]) === name); + const datum = datums.find(d => String(nominalSplit.selectValue(d)) === name); if (!datum) { return { color, name, value: "-" }; diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/interactions/interaction-controller.tsx b/src/client/visualizations/bar-chart/improved-bar-chart/interactions/interaction-controller.tsx index ba11b399e..ef1d2d9e9 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/interactions/interaction-controller.tsx +++ b/src/client/visualizations/bar-chart/improved-bar-chart/interactions/interaction-controller.tsx @@ -110,9 +110,8 @@ export class InteractionController extends React.Component safeEquals(value, datum[reference])); + const { model: { continuousSplit }, datums } = this.props; + return datums.find(datum => safeEquals(value, continuousSplit.selectValue(datum))); } getSeriesFromEvent(y: number, part: ScrollerPart): ConcreteSeries | null { diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/utils/bar-chart-model.ts b/src/client/visualizations/bar-chart/improved-bar-chart/utils/bar-chart-model.ts index f5b3d9bbb..ba1c141cd 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/utils/bar-chart-model.ts +++ b/src/client/visualizations/bar-chart/improved-bar-chart/utils/bar-chart-model.ts @@ -71,10 +71,9 @@ function readCommons(essence: Essence): Omit { } function createColorMap(nominalSplit: Split, dataset: Dataset): ColorMap { - const { reference } = nominalSplit; const datums = selectFirstSplitDatums(dataset); return datums.reduce((map: ColorMap, datum: Datum, i: number) => { - const key = String(datum[reference]); + const key = String(nominalSplit.selectValue(datum)); const colorIndex = i % NORMAL_COLORS.length; const color = NORMAL_COLORS[colorIndex]; return map.set(key, color); diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/utils/transpose-dataset.ts b/src/client/visualizations/bar-chart/improved-bar-chart/utils/transpose-dataset.ts index 81066227f..78bbd4643 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/utils/transpose-dataset.ts +++ b/src/client/visualizations/bar-chart/improved-bar-chart/utils/transpose-dataset.ts @@ -15,23 +15,24 @@ */ import { Dataset, Datum, TimeRange } from "plywood"; +import { Split } from "../../../../../common/models/split/split"; import { Binary, cons, replaceAt, Unary } from "../../../../../common/utils/functional/functional"; import { SPLIT } from "../../../../config/constants"; import { selectFirstSplitDatums, selectSplitDatums } from "../../../../utils/dataset/selectors/selectors"; import { BarChartModel, isStacked } from "./bar-chart-model"; -function rangeComparator(continuousRef: string): Binary { +function rangeComparator(continuousSplit: Split): Binary { return (a: Datum, b: Datum) => { - const aRange = a[continuousRef] as TimeRange; - const bRange = b[continuousRef] as TimeRange; + const aRange = continuousSplit.selectValue(a); + const bRange = continuousSplit.selectValue(b); return aRange.compare(bRange); }; } -function equalBy(continuousRef: string, datum: Datum): Unary { - const value = datum[continuousRef]; +function equalBy(split: Split, datum: Datum): Unary { + const value = split.selectValue(datum); return (d: Datum) => { - const range = d[continuousRef]; + const range = split.selectValue(d); return TimeRange.isTimeRange(value) && TimeRange.isTimeRange(range) && value.equals(range); }; } @@ -57,19 +58,19 @@ function mergeDatums(continuousRef: string, datum: Datum, newDatum: Datum): Datu export function transposeDataset(dataset: Dataset, model: BarChartModel): Datum[] { if (!isStacked(model)) return selectFirstSplitDatums(dataset); - const { reference } = model.continuousSplit; + const { continuousSplit } = model; const { data } = dataset.flatten(); const result = data.reduce((coll: Datum[], currentDatum: Datum) => { - const idx = coll.findIndex(equalBy(reference, currentDatum)); + const idx = coll.findIndex(equalBy(continuousSplit, currentDatum)); const notFound = idx === -1; if (notFound) { - return cons(coll, createInnerDatum(reference, currentDatum)); + return cons(coll, createInnerDatum(continuousSplit.reference, currentDatum)); } - return replaceAt(coll, idx, mergeDatums(reference, coll[idx], currentDatum)); + return replaceAt(coll, idx, mergeDatums(continuousSplit.reference, coll[idx], currentDatum)); }, []); - return result.sort(rangeComparator(reference)); + return result.sort(rangeComparator(continuousSplit)); } diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-domain.ts b/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-domain.ts index 6d6212a51..d91e50638 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-domain.ts +++ b/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-domain.ts @@ -22,6 +22,5 @@ export type DomainValue = boolean | number | string | Date | NumberRange | TimeR export type XDomain = DomainValue[]; export function getXDomain(datums: Datum[], { continuousSplit }: BarChartModel): XDomain { - const { reference: continuousReference } = continuousSplit; - return datums.map(datum => datum[continuousReference] as DomainValue); + return datums.map(datum => continuousSplit.selectValue(datum)); } diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.mocha.ts b/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.mocha.ts index eb48c21c3..0d12e0cba 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.mocha.ts +++ b/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.mocha.ts @@ -18,7 +18,7 @@ import { expect, use } from "chai"; import { TimeRange } from "plywood"; import { january } from "../../../../utils/dataset/selectors/dataset-fixtures"; import equivalent from "../../../../utils/test-utils/equivalent"; -import { createXScale, xGetter } from "./x-scale"; +import { createXScale } from "./x-scale"; use(equivalent); @@ -28,13 +28,6 @@ const januaryDateAsRange = (date: number) => new TimeRange({ }); describe("x-scale", () => { - describe("xGetter", () => { - it("should return function that picks defined prop", () => { - const getDummy = xGetter("dummy"); - expect(getDummy({ dummy: "foo" })).to.be.equal("foo"); - }); - }); - describe("createXScale", () => { describe("TimeRange", () => { const domain = [ diff --git a/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.ts b/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.ts index 9f625123d..c41de9d7b 100644 --- a/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.ts +++ b/src/client/visualizations/bar-chart/improved-bar-chart/utils/x-scale.ts @@ -15,8 +15,7 @@ */ import * as d3 from "d3"; -import { Datum, NumberRange, TimeRange } from "plywood"; -import { Unary } from "../../../../../common/utils/functional/functional"; +import { NumberRange, TimeRange } from "plywood"; import { DomainValue, XDomain } from "./x-domain"; export interface XScale { @@ -44,9 +43,6 @@ export function createXScale(domain: XDomain, width: number): XScale { }; } -export const xGetter = (reference: string): Unary => - datum => (datum[reference] as DomainValue); - function formatDomainValue(value: DomainValue): string { if (TimeRange.isTimeRange(value)) { const { start } = value; diff --git a/src/client/visualizations/line-chart/charts/charts-per-series/series-chart.tsx b/src/client/visualizations/line-chart/charts/charts-per-series/series-chart.tsx index 529e2de7e..a11194159 100644 --- a/src/client/visualizations/line-chart/charts/charts-per-series/series-chart.tsx +++ b/src/client/visualizations/line-chart/charts/charts-per-series/series-chart.tsx @@ -63,7 +63,7 @@ export const SeriesChart: React.SFC = props => { showPrevious={hasComparison} />; const continuousSplit = getContinuousSplit(essence); - const getX = (d: Datum) => d[continuousSplit.reference] as (TimeRange | NumberRange); + const getX = (d: Datum) => continuousSplit.selectValue(d); const domain = extentAcrossSplits(continuousSplitDataset, essence, series); @@ -83,7 +83,7 @@ export const SeriesChart: React.SFC = props => { yDomain={domain}> {({ yScale, lineStage }) => {continuousSplitDataset.data.map((datum, index) => { - const splitKey = datum[nominalSplit.reference]; + const splitKey = nominalSplit.selectValue(datum); const color = NORMAL_COLORS[index]; return { - const name = String(datum[nominalRef]); + const name = String(nominalSplit.selectValue(datum)); const color = NORMAL_COLORS[i]; const hoverDatum = findSplitDatumByAttribute(datum, continuousRef, range); diff --git a/src/client/visualizations/line-chart/charts/charts-per-split/label.tsx b/src/client/visualizations/line-chart/charts/charts-per-split/label.tsx index 9c7231134..5d8795f16 100644 --- a/src/client/visualizations/line-chart/charts/charts-per-split/label.tsx +++ b/src/client/visualizations/line-chart/charts/charts-per-split/label.tsx @@ -14,11 +14,11 @@ * limitations under the License. */ -import { Datum, PlywoodValue } from "plywood"; +import { Datum } from "plywood"; import * as React from "react"; import { Essence } from "../../../../../common/models/essence/essence"; import { formatSegment } from "../../../../../common/utils/formatter/formatter"; -import { getNominalDimension, hasNominalSplit } from "../../utils/splits"; +import { getNominalDimension, getNominalSplit, hasNominalSplit } from "../../utils/splits"; import "./label.scss"; interface LabelProps { @@ -29,8 +29,9 @@ interface LabelProps { export const Label: React.SFC = props => { const { essence, datum } = props; if (hasNominalSplit(essence)) { + const nominalSplit = getNominalSplit(essence); const nominalDimension = getNominalDimension(essence); - const splitValue = datum[nominalDimension.name] as PlywoodValue; + const splitValue = nominalSplit.selectValue(datum); return
{nominalDimension.title} diff --git a/src/client/visualizations/line-chart/charts/charts-per-split/nominal-value-key.ts b/src/client/visualizations/line-chart/charts/charts-per-split/nominal-value-key.ts index 40607b153..3be6597ee 100644 --- a/src/client/visualizations/line-chart/charts/charts-per-split/nominal-value-key.ts +++ b/src/client/visualizations/line-chart/charts/charts-per-split/nominal-value-key.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { Datum, PlywoodValue } from "plywood"; +import { Datum } from "plywood"; import { Essence } from "../../../../../common/models/essence/essence"; import { formatSegment } from "../../../../../common/utils/formatter/formatter"; -import { getNominalDimension, hasNominalSplit } from "../../utils/splits"; +import { getNominalSplit, hasNominalSplit } from "../../utils/splits"; export function nominalValueKey(datum: Datum, essence: Essence): string { if (!hasNominalSplit(essence)) return "no-nominal-split"; - const nominalDimension = getNominalDimension(essence); - const splitValue = datum[nominalDimension.name] as PlywoodValue; + const nominalSplit = getNominalSplit(essence); + const splitValue = nominalSplit.selectValue(datum); return formatSegment(splitValue, essence.timezone); } diff --git a/src/client/visualizations/line-chart/charts/charts-per-split/split-chart.tsx b/src/client/visualizations/line-chart/charts/charts-per-split/split-chart.tsx index fab3ba5c2..3d84ca75b 100644 --- a/src/client/visualizations/line-chart/charts/charts-per-split/split-chart.tsx +++ b/src/client/visualizations/line-chart/charts/charts-per-split/split-chart.tsx @@ -61,7 +61,7 @@ export const SplitChart: React.SFC = props => { dataset={splitDataset} />; const continuousSplit = getContinuousSplit(essence); - const getX = (d: Datum) => d[continuousSplit.reference] as (TimeRange | NumberRange); + const getX = (d: Datum) => continuousSplit.selectValue(d); const domain = extentAcrossSeries(splitDataset, essence); if (series.count() === 1) { diff --git a/src/client/visualizations/line-chart/interactions/find-closest-datum.ts b/src/client/visualizations/line-chart/interactions/find-closest-datum.ts index 049a36ee5..396925b44 100644 --- a/src/client/visualizations/line-chart/interactions/find-closest-datum.ts +++ b/src/client/visualizations/line-chart/interactions/find-closest-datum.ts @@ -14,20 +14,20 @@ * limitations under the License. */ -const MAX_HOVER_DIST = 50; - import { Dataset, Datum, NumberRange, Range, TimeRange } from "plywood"; -import { Dimension } from "../../../../common/models/dimension/dimension"; import { Essence } from "../../../../common/models/essence/essence"; +import { Split } from "../../../../common/models/split/split"; import { selectFirstSplitDataset, selectFirstSplitDatums } from "../../../utils/dataset/selectors/selectors"; import { ContinuousScale, ContinuousValue } from "../utils/continuous-types"; -import { getContinuousDimension, hasNominalSplit } from "../utils/splits"; +import { getContinuousSplit, hasNominalSplit } from "../utils/splits"; + +const MAX_HOVER_DIST = 50; -function findClosest(data: Datum[], value: ContinuousValue, scaleX: ContinuousScale, continuousDimension: Dimension): Datum | null { +function findClosest(data: Datum[], value: ContinuousValue, scaleX: ContinuousScale, continuousSplit: Split): Datum | null { let closestDatum: Datum = null; let minDist = Infinity; for (const datum of data) { - const continuousSegmentValue = datum[continuousDimension.name] as (TimeRange | NumberRange); + const continuousSegmentValue = continuousSplit.selectValue(datum); if (!continuousSegmentValue || !Range.isRange(continuousSegmentValue)) continue; // !Range.isRange => temp solution for non-bucketed reaching here const mid = continuousSegmentValue.midpoint(); const dist = Math.abs(mid.valueOf() - value.valueOf()); @@ -41,10 +41,10 @@ function findClosest(data: Datum[], value: ContinuousValue, scaleX: ContinuousSc } export function findClosestDatum(value: ContinuousValue, essence: Essence, dataset: Dataset, xScale: ContinuousScale): Datum | null { - const continuousDimension = getContinuousDimension(essence); + const continuousSplit = getContinuousSplit(essence); if (hasNominalSplit(essence)) { const flattened = selectFirstSplitDataset(dataset).flatten(); - return findClosest(flattened.data, value, xScale, continuousDimension); + return findClosest(flattened.data, value, xScale, continuousSplit); } - return findClosest(selectFirstSplitDatums(dataset), value, xScale, continuousDimension); + return findClosest(selectFirstSplitDatums(dataset), value, xScale, continuousSplit); } diff --git a/src/client/visualizations/line-chart/legend/split-legend.tsx b/src/client/visualizations/line-chart/legend/split-legend.tsx index bc598dce3..8dd867c07 100644 --- a/src/client/visualizations/line-chart/legend/split-legend.tsx +++ b/src/client/visualizations/line-chart/legend/split-legend.tsx @@ -34,7 +34,7 @@ export const SplitLegend: React.SFC = props => { const title = legendSplit.getTitle(legendDimension); const nestedDataset = selectFirstSplitDatums(dataset); - const values = nestedDataset.map(datum => String(datum[legendSplit.reference])); + const values = nestedDataset.map(datum => String(legendSplit.selectValue(datum))); return datum[continuousDimensionKey] as PlywoodRange) + .map(datum => continuousSplit.selectValue(datum) as PlywoodRange) .reduce(safeRangeSum, null); } export function calculateXRange(essence: Essence, timekeeper: Timekeeper, dataset: Dataset): ContinuousRange | null { - const continuousDimension = getContinuousDimension(essence); + const continuousSplit = getContinuousSplit(essence); const filterRange = getFilterRange(essence, timekeeper); - const datasetRange = getDatasetXRange(dataset, continuousDimension); + const datasetRange = getDatasetXRange(dataset, continuousSplit); return union(filterRange, datasetRange) as ContinuousRange; }