Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a3be401
feat: toggle able legend for cartesian chart
itssharmasandeep Nov 18, 2021
1fe78fe
fix: add test cases
itssharmasandeep Nov 18, 2021
1fbd6c9
Merge remote-tracking branch 'origin/main' into cartesian-toggle-legend
itssharmasandeep Nov 19, 2021
b53fe40
fix: addressing review comments
itssharmasandeep Nov 19, 2021
747556e
fix: addressing review comments
itssharmasandeep Nov 22, 2021
09513b3
fix: addressing review comments
itssharmasandeep Nov 22, 2021
1781dee
Merge remote-tracking branch 'origin/main' into cartesian-toggle-legend
itssharmasandeep Nov 25, 2021
a33b271
feat: grouped cartesian legend
itssharmasandeep Nov 26, 2021
805d7e1
fix: some style changes
itssharmasandeep Nov 26, 2021
7da7be2
Merge branch cartesian-toggle-legend into grouped-legend
itssharmasandeep Nov 26, 2021
0244802
fix: code refactoring and lint fixes
itssharmasandeep Nov 26, 2021
458fa52
fix: test cases
itssharmasandeep Nov 26, 2021
43c206e
fix: adding tests
itssharmasandeep Nov 26, 2021
0d2b82e
fix: adding test for coverage
itssharmasandeep Nov 26, 2021
c9df216
Merge remote-tracking branch 'origin/main' into cartesian-toggle-legend
itssharmasandeep Nov 30, 2021
9f5f84b
Merge remote-tracking branch 'origin/main' into cartesian-toggle-legend
itssharmasandeep Nov 30, 2021
408b490
Merge branch 'cartesian-toggle-legend' into grouped-legend
itssharmasandeep Nov 30, 2021
af35f00
fix: addressing review comments
itssharmasandeep Nov 30, 2021
967346e
fix: test cases
itssharmasandeep Nov 30, 2021
d9be399
fix: addressing review comments
itssharmasandeep Dec 1, 2021
53e46bd
Merge branch cartesian-toggle-legend into grouped-legend
itssharmasandeep Dec 1, 2021
72d2af7
fix: addressing review comments
itssharmasandeep Dec 1, 2021
863d65d
fix: test cases
itssharmasandeep Dec 1, 2021
902c0d8
fix: test cases
itssharmasandeep Dec 1, 2021
a9b166b
fix: suggested changes
itssharmasandeep Dec 1, 2021
c78844b
fix: lint fixes
itssharmasandeep Dec 1, 2021
c2f177b
fix: addressing review comments
itssharmasandeep Dec 2, 2021
2669bb7
Merge branch cartesian-toggle-legend into grouped-legend
itssharmasandeep Dec 2, 2021
8ef7d2e
fix: legend text name
itssharmasandeep Dec 2, 2021
316f563
Merge remote-tracking branch origin/main into grouped-legend
itssharmasandeep Dec 6, 2021
6b39400
Merge remote-tracking branch 'origin/main' into grouped-legend
itssharmasandeep Dec 13, 2021
5c57a97
Merge remote-tracking branch 'origin/main' into grouped-legend
itssharmasandeep Dec 14, 2021
5f5aafe
fix: addressing review comments
itssharmasandeep Dec 14, 2021
3572db1
fix: some test cases
itssharmasandeep Dec 14, 2021
a469833
fix: bug
itssharmasandeep Dec 14, 2021
3387b08
fix: test cases
itssharmasandeep Dec 14, 2021
37efef0
fix: remove unwanted code
itssharmasandeep Dec 14, 2021
f8b591a
Merge remote-tracking branch 'origin/main' into grouped-legend
itssharmasandeep Dec 17, 2021
f243622
fix: addressing review comments
itssharmasandeep Dec 17, 2021
3d585ba
fix: test cases
itssharmasandeep Dec 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
width: 100%;
position: absolute;
min-height: 48px;
padding-bottom: 20px;

&.position-none {
display: none;
Expand Down Expand Up @@ -118,9 +119,70 @@
}

.legend-text {
fill: $gray-5;
font-size: 14px;
padding-left: 2px;
cursor: pointer;

&.default {
color: $gray-9;
}

&.active {
color: $blue-4;
}

&.inactive {
color: $gray-5;
}
}
}
}

.reset {
@include font-title($blue-4);
cursor: pointer;
position: absolute;
bottom: 0;
right: 0;

&.hidden {
display: none;
}

&:hover {
color: $blue-6;
}
}

&.grouped {
flex-direction: column;
gap: 12px;

.legend-entries {
flex-direction: row;
display: grid;
grid-template-columns: 200px auto;
gap: 20px;
border: 1px solid $gray-2;
border-radius: 8px;
padding: 8px 20px;

&.active {
border-color: $blue-5;
}

.legend-entries-title {
@include body-1-regular($gray-5);
cursor: pointer;

&.active {
color: $blue-5;
}
}

.legend-entry-values {
display: flex;
flex-wrap: wrap;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,70 @@ describe('Cartesian Chart component', () => {
expect(chart.queryAll(CartesianLegend.CSS_SELECTOR, { root: true }).length).toBe(1);
}));

test('should have correct active series', fakeAsync(() => {
const chart = createHost(`<ht-cartesian-chart [series]="series" [legend]="legend"></ht-cartesian-chart>`, {
hostProps: {
series: [],
legend: undefined
}
});
chart.setHostInput({
series: [
{
data: [[1, 2]],
name: 'test series 1',
color: 'blue',
type: CartesianSeriesVisualizationType.Column,
assignedGroup: {
id: 1,
groupName: 'first'
},
stacking: true
},
{
data: [[1, 6]],
name: 'test series 2',
color: 'red',
type: CartesianSeriesVisualizationType.Column,
assignedGroup: {
id: 1,
groupName: 'first'
},
stacking: true
}
],
legend: LegendPosition.Bottom
});
tick();
expect(chart.queryAll(CartesianLegend.CSS_SELECTOR, { root: true }).length).toBe(1);
expect(chart.queryAll('.legend-entry').length).toBe(2);
expect(chart.query('.group-1')).toExist();
expect(chart.query('.reset.hidden')).toExist();

const legendEntriesTitleElement = chart.query('.legend-entries-title') as Element;
chart.click(legendEntriesTitleElement);
tick();
expect(chart.queryAll('.legend-text.active').length).toBe(2);

chart.click(legendEntriesTitleElement);
tick();
expect(chart.queryAll('.legend-text.active').length).toBe(0);

const legendEntryTexts = chart.queryAll('.legend-text');
chart.click(legendEntryTexts[0]);
tick();
expect(chart.queryAll('.legend-text.active').length).toBe(1);
expect(chart.query('.reset.hidden')).not.toExist();

chart.click(chart.query('.reset') as Element);
tick();
expect(chart.query('.reset.hidden')).toExist();

chart.click(legendEntryTexts[0]);
tick();
expect(chart.queryAll('.legend-text.active').length).toBe(1);
}));

test('should render column chart', fakeAsync(() => {
const chart = createHost(`<ht-cartesian-chart [series]="series"></ht-cartesian-chart>`, {
hostProps: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,19 @@ export interface Series<TInterval> {
// Override the default color string using a method that takes data point as input
getColor?(datum?: TInterval): string;
name: string;
assignedGroup?: AssignedGroup;
symbol?: SeriesSymbol;
type: CartesianSeriesVisualizationType;
stacking?: boolean;
hide?: boolean;
getTooltipTitle?(datum: TInterval): string;
}

export interface AssignedGroup {
id: number;
groupName: string;
}

export interface Band<TInterval> {
upper: Series<TInterval>;
lower: Series<TInterval>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Injector, Renderer2 } from '@angular/core';
import { TimeRange } from '@hypertrace/common';
import { ContainerElement, mouse, select } from 'd3-selection';
import { Subscription } from 'rxjs';
import { LegendPosition } from '../../../legend/legend.component';
import { ChartTooltipRef } from '../../../utils/chart-tooltip/chart-tooltip-popover';
import { D3UtilService } from '../../../utils/d3/d3-util.service';
Expand Down Expand Up @@ -35,6 +36,7 @@ import { CartesianScaleBuilder } from '../scale/cartesian-scale-builder';
// tslint:disable:max-file-line-count
export class DefaultCartesianChart<TData> implements CartesianChart<TData> {
public static DATA_SERIES_CLASS: string = 'data-series';
public static CHART_VISUALIZATION_CLASS: string = 'chart-visualization';

protected readonly margin: number = 16;
protected readonly axisHeight: number = 16;
Expand Down Expand Up @@ -65,6 +67,9 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {
onEvent: ChartEventListener<TData>;
}[] = [];

private activeSeriesSubscription?: Subscription;
private activeSeries: Series<TData>[] = [];

public constructor(
protected readonly hostElement: Element,
protected readonly injector: Injector,
Expand All @@ -80,6 +85,10 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {
this.tooltip && this.tooltip.destroy();
this.legend && this.legend.destroy();

if (this.activeSeriesSubscription) {
this.activeSeriesSubscription.unsubscribe();
}

return this;
}

Expand All @@ -104,6 +113,7 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {
public withSeries(...series: Series<TData>[]): this {
this.series.length = 0;
this.series.push(...series);
this.activeSeries = [...series];

this.seriesSummaries.length = 0;
this.seriesSummaries.push(
Expand Down Expand Up @@ -271,8 +281,10 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {
}
}

private updateData(): void {
this.drawLegend();
private updateData(withLegend: boolean = true): void {
if (withLegend) {
this.drawLegend();
}
this.buildVisualizations();
this.drawChartBackground();
this.drawAxes();
Expand All @@ -283,6 +295,16 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {
this.setupEventListeners();
}

private redrawVisualization(): void {
const chartViz = select(this.chartContainerElement!).selectAll(
`.${DefaultCartesianChart.CHART_VISUALIZATION_CLASS}`
);
if (chartViz.nodes().length > 0) {
chartViz.remove();
this.updateData(false);
}
}

private moveDataOnTopOfAxes(): void {
if (!this.dataElement) {
return;
Expand Down Expand Up @@ -338,16 +360,23 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {
return;
}

new CartesianNoDataMessage(this.chartBackgroundSvgElement, this.series).updateMessage();
new CartesianNoDataMessage(this.chartBackgroundSvgElement, this.activeSeries).updateMessage();
}

private drawLegend(): void {
if (this.chartContainerElement) {
if (this.legendPosition !== undefined && this.legendPosition !== LegendPosition.None) {
this.legend = new CartesianLegend(this.series, this.injector, this.intervalData, this.seriesSummaries).draw(
this.chartContainerElement,
this.legendPosition
);
this.legend = new CartesianLegend(
this.activeSeries,
this.injector,
this.intervalData,
this.seriesSummaries
).draw(this.chartContainerElement, this.legendPosition);
this.activeSeriesSubscription?.unsubscribe();
this.activeSeriesSubscription = this.legend.activeSeries$.subscribe(activeSeries => {
this.activeSeries = activeSeries as Series<TData>[];
this.redrawVisualization();
});
} else {
// The legend also contains the interval selector, so even without a legend we need to create an element for that
this.legend = new CartesianLegend([], this.injector, this.intervalData, this.seriesSummaries).draw(
Expand All @@ -370,6 +399,7 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {

this.chartBackgroundSvgElement = select(this.chartContainerElement)
.append('svg')
.classed(DefaultCartesianChart.CHART_VISUALIZATION_CLASS, true)
.style('position', 'absolute')
.attr('width', `${chartBox.width}px`)
.attr('height', `${chartBox.height}px`)
Expand Down Expand Up @@ -430,7 +460,7 @@ export class DefaultCartesianChart<TData> implements CartesianChart<TData> {

private buildVisualizations(): void {
this.allSeriesData = [
...this.series.map(series => this.getChartSeriesVisualization(series)),
...this.activeSeries.map(series => this.getChartSeriesVisualization(series)),
...this.bands.flatMap(band => [
// Need to add bands as series to get tooltips
this.getChartSeriesVisualization(band.upper),
Expand Down
Loading