Skip to content

Commit d9bf977

Browse files
Sankey diagram (#1912)
* Add Sankey diagram * Update demo data * Update demo * Clean up * Fix tests
1 parent 2d72326 commit d9bf977

File tree

15 files changed

+501
-4
lines changed

15 files changed

+501
-4
lines changed

package-lock.json

Lines changed: 73 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"d3-format": "^3.1.0",
5151
"d3-hierarchy": "^3.1.0",
5252
"d3-interpolate": "^3.0.1",
53+
"d3-sankey": "^0.12.3",
5354
"d3-scale": "^4.0.2",
5455
"d3-selection": "^3.0.0",
5556
"d3-shape": "^3.2.0",

projects/swimlane/ngx-charts/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"d3-format": "^3.1.0",
5353
"d3-hierarchy": "^3.1.0",
5454
"d3-interpolate": "^3.0.1",
55+
"d3-sankey": "^0.12.3",
5556
"d3-scale": "^4.0.2",
5657
"d3-selection": "^3.0.0",
5758
"d3-shape": "^3.2.0",

projects/swimlane/ngx-charts/src/lib/common/base-chart.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@
2121
.circle,
2222
.cell,
2323
.bar,
24+
.node,
25+
.link,
2426
.arc {
2527
cursor: pointer;
2628
}
2729

2830
.bar,
2931
.cell,
3032
.arc,
33+
.node,
34+
.link,
3135
.card {
3236
&.active,
3337
&:hover {

projects/swimlane/ngx-charts/src/lib/common/base-chart.component.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,11 @@ export class BaseChartComponent implements OnChanges, AfterViewInit, OnDestroy,
184184
const results = [];
185185

186186
for (const item of data) {
187-
const copy = {
188-
name: item['name']
189-
};
187+
const copy = {};
188+
189+
if (item['name'] !== undefined) {
190+
copy['name'] = item['name'];
191+
}
190192

191193
if (item['value'] !== undefined) {
192194
copy['value'] = item['value'];
@@ -204,6 +206,14 @@ export class BaseChartComponent implements OnChanges, AfterViewInit, OnDestroy,
204206
copy['extra'] = JSON.parse(JSON.stringify(item['extra']));
205207
}
206208

209+
if (item['source'] !== undefined) {
210+
copy['source'] = item['source'];
211+
}
212+
213+
if (item['target'] !== undefined) {
214+
copy['target'] = item['target'];
215+
}
216+
207217
results.push(copy);
208218
}
209219

projects/swimlane/ngx-charts/src/lib/models/chart-data.model.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ export interface TreeMapDataItem {
7070

7171
export interface TreeMapData extends Array<TreeMapDataItem> {}
7272

73+
export interface SankeyObject {
74+
source: string;
75+
target: string;
76+
value: number;
77+
}
78+
79+
export interface SankeyData extends Array<SankeyObject> {}
80+
7381
export interface BoxChartSeries {
7482
name: StringOrNumberOrDate;
7583
series: DataItem[];

projects/swimlane/ngx-charts/src/lib/ngx-charts.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { PieChartModule } from './pie-chart/pie-chart.module';
1212
import { TreeMapModule } from './tree-map/tree-map.module';
1313
import { GaugeModule } from './gauge/gauge.module';
1414
import { ngxChartsPolyfills } from './polyfills';
15+
import { SankeyModule } from './sankey/sankey.module';
1516

1617
@NgModule({
1718
exports: [
@@ -21,6 +22,7 @@ import { ngxChartsPolyfills } from './polyfills';
2122
BoxChartModule,
2223
BubbleChartModule,
2324
HeatMapModule,
25+
SankeyModule,
2426
LineChartModule,
2527
PolarChartModule,
2628
NumberCardModule,
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { TestBed } from '@angular/core/testing';
2+
import { Component } from '@angular/core';
3+
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
4+
5+
import { APP_BASE_HREF } from '@angular/common';
6+
7+
import { SankeyModule } from './sankey.module';
8+
9+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
10+
11+
@Component({
12+
selector: 'test-component',
13+
template: ''
14+
})
15+
class TestComponent {
16+
colorScheme = {
17+
domain: ['#5AA454', '#A10A28', '#C7B42C', '#AAAAAA']
18+
};
19+
}
20+
21+
describe('<ngx-charts-sankey>', () => {
22+
beforeEach(() => {
23+
TestBed.configureTestingModule({
24+
declarations: [TestComponent],
25+
imports: [NoopAnimationsModule, SankeyModule],
26+
providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
27+
});
28+
});
29+
30+
describe('basic setup', () => {
31+
beforeEach(() => {
32+
TestBed.overrideComponent(TestComponent, {
33+
set: {
34+
template: `
35+
<ngx-charts-sankey
36+
[animations]="false"
37+
[view]="[400,800]"
38+
[scheme]="colorScheme"
39+
[results]="[
40+
{ source: 'United States Of America', target: 'Japan', value: 50 },
41+
{ source: 'Germany', target: 'Japan', value: 80 },
42+
{ source: 'Germany', target: 'South Korea', value: 25 },
43+
{ source: 'France', target: 'South Korea', value: 30 },
44+
{ source: 'France', target: 'Italy', value: 10 },
45+
{ source: 'France', target: 'North Macedonia', value: 15 },
46+
{ source: 'India', target: 'Japan', value: 10 },
47+
{ source: 'Japan', target: 'UK', value: 60 },
48+
{ source: 'Japan', target: 'UK', value: 10 },
49+
{ source: 'Japan', target: 'Democratic Republic of São Tomé and Príncipe', value: 50 },
50+
{ source: 'Japan', target: 'Republic of Equatorial Guinea', value: 20 },
51+
{ source: 'South Korea', target: 'UK', value: 55 },
52+
{ source: 'Italy', target: 'UK', value: 10 },
53+
{ source: 'North Macedonia', target: 'Republic of Equatorial Guinea', value: 15 },
54+
{ source: 'UK', target: 'Independent and the Sovereign Republic of Kiribati', value: 10 },
55+
{ source: 'UK', target: 'Commonwealth of the Northern Mariana Islands', value: 60 },
56+
{ source: 'UK', target: 'Bosnia and Herzegovina', value: 25 },
57+
{ source: 'UK', target: 'Spain', value: 20 },
58+
{ source: 'UK', target: 'Bosnia and Herzegovina', value: 20 },
59+
{ source: 'Republic of Equatorial Guinea', target: 'Republic of Costa Rica', value: 30 },
60+
{ source: 'Republic of Equatorial Guinea', target: 'Portugal', value: 5 }
61+
]">
62+
</ngx-charts-sankey>`
63+
}
64+
}).compileComponents();
65+
});
66+
67+
it('should set the svg width and height', () => {
68+
const fixture = TestBed.createComponent(TestComponent);
69+
fixture.detectChanges();
70+
71+
const svg = fixture.debugElement.nativeElement.querySelector('svg');
72+
73+
expect(svg.getAttribute('width')).toBe('400');
74+
expect(svg.getAttribute('height')).toBe('800');
75+
});
76+
});
77+
});

0 commit comments

Comments
 (0)