Skip to content

Commit

Permalink
Add scatterplot scaffold (#827)
Browse files Browse the repository at this point in the history
Enable choosing scatterplot in menu
  • Loading branch information
kzadurska authored Feb 8, 2022
1 parent 8626e55 commit 488da60
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"tsc:watch": "tsc -p tsconfig.json -w --pretty",
"lint": "npm-run-all -p lint:*",
"lint:ts": "tslint -p . --format verbose",
"lint:ts:fix":"tslint -p . --fix",
"lint:sass": "sass-lint -v",
"e2e": "start-server-and-test start:examples http://localhost:9090/health/ready 'cypress run'",
"e2e:dev": "cypress open",
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/vis-selector/vis-selector-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export class VisSelectorMenu extends React.Component<VisSelectorMenuProps, VisSe
case "line-chart":
const LineChartSettingsComponent = settingsComponent(visualization.name);
return <LineChartSettingsComponent onChange={this.changeSettings} settings={visualizationSettings as ImmutableRecord<LineChartSettings>}/>;
case "scatterplot":
return null;
}
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/client/visualization-settings/settings-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface SettingsComponents {
"heatmap": null;
"grid": null;
"totals": null;
"scatterplot": null;
}

const Components: SettingsComponents = {
Expand All @@ -33,7 +34,8 @@ const Components: SettingsComponents = {
"heatmap": null,
"grid": null,
"totals": null,
"table": TableSettingsComponent
"table": TableSettingsComponent,
"scatterplot": null
};

export function settingsComponent<T extends Visualization>(visualization: T): SettingsComponents[T] {
Expand Down
4 changes: 3 additions & 1 deletion src/client/visualizations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { BarChartVisualization } from "./bar-chart/bar-chart";
import { GridVisualization } from "./grid/grid";
import { HeatMapVisualization } from "./heat-map/heat-map";
import { LineChartVisualization } from "./line-chart/line-chart";
import { ScatterplotVisualization } from "./scatterplot/scatterplot";
import { TableVisualization } from "./table/table";
import { TotalsVisualization } from "./totals/totals";

Expand All @@ -29,7 +30,8 @@ const VISUALIZATIONS = {
"line-chart": LineChartVisualization,
"bar-chart": BarChartVisualization,
"heatmap": HeatMapVisualization,
"grid": GridVisualization
"grid": GridVisualization,
"scatterplot": ScatterplotVisualization
};

export function getVisualizationComponent({ name }: VisualizationManifest) {
Expand Down
23 changes: 23 additions & 0 deletions src/client/visualizations/scatterplot/scatterplot.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2017-2022 Allegro.pl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.scatterplot {
.scatterplot-container {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
}
39 changes: 39 additions & 0 deletions src/client/visualizations/scatterplot/scatterplot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2017-2022 Allegro.pl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as React from "react";

import { ChartProps } from "../../../common/models/chart-props/chart-props";
import makeQuery from "../../../common/utils/query/visualization-query";
import {
ChartPanel,
DefaultVisualizationControls,
VisualizationProps
} from "../../views/cube-view/center-panel/center-panel";

import "./scatterplot.scss";

const Scatterplot: React.SFC<ChartProps> = () => {
return <div className="scatterplot-container">
<h2>Scatterplot will be here</h2>
</div>;
};

export function ScatterplotVisualization(props: VisualizationProps) {
return <React.Fragment>
<DefaultVisualizationControls {...props} />
<ChartPanel {...props} queryFactory={makeQuery} chartComponent={Scatterplot}/>
</React.Fragment>;
}
8 changes: 8 additions & 0 deletions src/common/models/series-list/series-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,18 @@ export class SeriesList extends Record<SeriesListValue>(defaultSeriesList) {
return this.updateSeries(series => series.take(1));
}

public takeNFirst(number: number) {
return this.updateSeries(series => series.take(number));
}

public getExpressionSeriesFor(reference: string): List<ExpressionSeries> {
return this.series.filter(series =>
series.reference === reference && series instanceof ExpressionSeries) as List<ExpressionSeries>;
}

public getSeriesKeys(): List<string> {
return this.series.map(series => series.key());
}
}

export const EMPTY_SERIES = new SeriesList({ series: List([]) });
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class Resolve {
}
}

export type Visualization = "heatmap" | "table" | "totals" | "bar-chart" | "line-chart" | "grid";
export type Visualization = "heatmap" | "table" | "totals" | "bar-chart" | "line-chart" | "grid" | "scatterplot";

export class VisualizationManifest<T extends object = {}> {
constructor(
Expand Down
4 changes: 3 additions & 1 deletion src/common/visualization-manifests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { BAR_CHART_MANIFEST } from "./bar-chart/bar-chart";
import { GRID_MANIFEST } from "./grid/grid";
import { HEAT_MAP_MANIFEST } from "./heat-map/heat-map";
import { LINE_CHART_MANIFEST } from "./line-chart/line-chart";
import { SCATTERPLOT_MANIFEST } from "./scatterplot/scatterplot";
import { TABLE_MANIFEST } from "./table/table";
import { TOTALS_MANIFEST } from "./totals/totals";

Expand All @@ -30,7 +31,8 @@ export const MANIFESTS: VisualizationManifest[] = [
LINE_CHART_MANIFEST,
BAR_CHART_MANIFEST,
HEAT_MAP_MANIFEST,
TABLE_MANIFEST
TABLE_MANIFEST,
SCATTERPLOT_MANIFEST
];

export function manifestByName(visualizationName: string): VisualizationManifest {
Expand Down
95 changes: 95 additions & 0 deletions src/common/visualization-manifests/scatterplot/scatterplot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright 2017-2022 Allegro.pl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { allDimensions } from "../../models/dimension/dimensions";
import { allMeasures } from "../../models/measure/measures";
import { MeasureSeries } from "../../models/series/measure-series";
import { Split } from "../../models/split/split";
import { Resolve, VisualizationManifest } from "../../models/visualization-manifest/visualization-manifest";
import { emptySettingsConfig } from "../../models/visualization-settings/empty-settings-config";
import { Predicates } from "../../utils/rules/predicates";
import {
ActionVariables,
visualizationDependentEvaluatorBuilder
} from "../../utils/rules/visualization-dependent-evaluator";

// FIXME: Update conditions and tests in EssenceProps src/common/models/essence/essence.mocha.ts
const rulesEvaluator = visualizationDependentEvaluatorBuilder
.when(Predicates.numberOfSplitsIsNot(1))
.then(variables => Resolve.manual(
3,
"Scatterplot needs exactly 1 split",
variables.splits.length() > 1 ? suggestRemovingSplits(variables) : suggestAddingSplits(variables)
))
.when(Predicates.numberOfSeriesIsNot(2))
.then(variables => Resolve.manual(
3,
"Scatterplot needs exactly 2 measures",
variables.series.series.size < 2 ? suggestAddingMeasure(variables) : suggestRemovingMeasures(variables)
))
.otherwise(({ isSelectedVisualization }) =>
Resolve.ready(isSelectedVisualization ? 10 : 3)
)
.build();

const suggestRemovingSplits = ({ splits }: ActionVariables) => [{
description: splits.length() === 2 ? "Remove last split" : `Remove last ${splits.length() - 1} splits`,
adjustment: { splits: splits.slice(0, 1) }
}];

const suggestAddingSplits = ({ dataCube, splits }: ActionVariables) =>
allDimensions(dataCube.dimensions)
.filter(dimension => !splits.hasSplitOn(dimension))
.slice(0, 2)
.map(dimension => ({
description: `Add ${dimension.title} split`,
adjustment: {
splits: splits.addSplit(Split.fromDimension(dimension))
}
}));

const suggestAddingMeasure = ({ dataCube, series }: ActionVariables) => {
const firstSeriesKey = series.getSeriesKeys().first();
const notUsedMeasures = allMeasures(dataCube.measures).filter(measure => measure.name !== firstSeriesKey);

if (notUsedMeasures.length > 0) {
const firstMeasure = notUsedMeasures[0];
return [{
description: `Add measure ${firstMeasure.title}`,
adjustment: {
series: series.addSeries(MeasureSeries.fromMeasure(firstMeasure))
}
}];
}

return [{
description: "Second measure needed",
adjustment: null
}];
};

const suggestRemovingMeasures = ({ series }: ActionVariables) => [{
description: series.count() === 3 ? "Remove last measure" : "Use first two measures",
adjustment: {
series: series.takeNFirst(2)
}
}];

export const SCATTERPLOT_MANIFEST = new VisualizationManifest(
"scatterplot",
"Scatterplot",
rulesEvaluator,
emptySettingsConfig
);

0 comments on commit 488da60

Please sign in to comment.