Skip to content

Commit 575eb29

Browse files
committed
Creating the PlotlyThemeLoaderService
1 parent 20ef1fe commit 575eb29

15 files changed

+138
-5
lines changed

projects/plotly/src/lib/plotly.component.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,30 @@ describe('PlotlyComponent', () => {
216216

217217
expect(PlotlyJS.Plots.resize).not.toHaveBeenCalled();
218218
});
219+
220+
it('should load a theme', async () => {
221+
spyOn(component, 'loadTheme').and.callThrough();
222+
spyOn(component.themeLoader, 'load').and.callThrough();
223+
224+
component.theme = 'plotly_dark';
225+
226+
component.ngOnInit();
227+
await fixture.whenStable();
228+
229+
expect(component.loadTheme).toHaveBeenCalled();
230+
expect(component.themeLoader.load).toHaveBeenCalledOnceWith('plotly_dark');
231+
});
232+
233+
it('should load NOT a theme', async () => {
234+
spyOn(component, 'loadTheme').and.callThrough();
235+
spyOn(component.themeLoader, 'load').and.callThrough();
236+
237+
component.theme = 'none';
238+
239+
component.ngOnInit();
240+
await fixture.whenStable();
241+
242+
expect(component.loadTheme).not.toHaveBeenCalled();
243+
expect(component.themeLoader.load).not.toHaveBeenCalledOnceWith('plotly_dark');
244+
});
219245
});

projects/plotly/src/lib/plotly.component.ts

+14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
} from '@angular/core';
2121

2222
import { PlotlyService } from './plotly.service';
23+
import { PlotlyThemeLoaderService, PlotlyTheme } from './plotly.theme-loader.service';
2324
import { Plotly } from './plotly.interface';
2425

2526
// @dynamic
@@ -45,6 +46,7 @@ export class PlotlyComponent implements OnInit, OnChanges, OnDestroy, DoCheck {
4546
@Input() config?: Partial<Plotly.Config>;
4647
@Input() frames?: Partial<Plotly.Config>[];
4748
@Input() style?: { [key: string]: string };
49+
@Input() theme: PlotlyTheme = "none";
4850

4951
@Input() divId?: string;
5052
@Input() revision = 0;
@@ -115,6 +117,7 @@ export class PlotlyComponent implements OnInit, OnChanges, OnDestroy, DoCheck {
115117

116118
constructor(
117119
public plotly: PlotlyService,
120+
public themeLoader: PlotlyThemeLoaderService,
118121
public iterableDiffers: IterableDiffers,
119122
public keyValueDiffers: KeyValueDiffers,
120123
) { }
@@ -130,6 +133,8 @@ export class PlotlyComponent implements OnInit, OnChanges, OnDestroy, DoCheck {
130133
+ 'Please check https://github.com/plotly/angular-plotly.js#FAQ';
131134
console.error(msg);
132135
}
136+
137+
if (this.theme != 'none') this.loadTheme();
133138
}
134139

135140
ngOnDestroy(): void {
@@ -291,4 +296,13 @@ export class PlotlyComponent implements OnInit, OnChanges, OnDestroy, DoCheck {
291296
const obj = Object.assign({}, item, { uid: '' });
292297
return JSON.stringify(obj);
293298
}
299+
300+
loadTheme() {
301+
if (this.layout !== undefined) {
302+
const msg = 'You fulfill both `theme` and `layout` properties. This will overwrite the `layout` data with the `theme` data.';
303+
console.warn(msg);
304+
}
305+
306+
this.themeLoader.load(this.theme).then(theme => this.layout = theme);
307+
}
294308
}

projects/plotly/src/lib/plotly.service.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -84,25 +84,25 @@ export class PlotlyService {
8484
await this.waitFor(() => this._getPlotly() !== 'waiting');
8585

8686
if (frames) {
87-
const obj = {data, layout, config, frames};
87+
const obj = { data, layout, config, frames };
8888
return this._getPlotly().newPlot(div, obj).then(() => PlotlyService.insert(div as any)) as Promise<any>;
8989
}
9090

9191
return this._getPlotly().newPlot(div, data, layout, config).then(() => PlotlyService.insert(div as any)) as Promise<any>;
9292
}
9393

94-
public plot(div: Plotly.PlotlyHTMLElement, data: Plotly.Data[], layout?: Partial<Plotly.Layout>, config?: Partial<Plotly.Config>, frames?: Partial<Plotly.Config>[]): Promise<any> {
94+
public plot(div: Plotly.PlotlyHTMLElement, data: Plotly.Data[], layout?: Partial<Plotly.Layout>, config?: Partial<Plotly.Config>, frames?: Partial<Plotly.Config>[]): Promise<any> {
9595
if (frames) {
96-
const obj = {data, layout, config, frames};
96+
const obj = { data, layout, config, frames };
9797
return this._getPlotly().newPlot(div, obj) as Promise<any>;
9898
}
9999

100100
return this._getPlotly().newPlot(div, data, layout, config) as Promise<any>;
101101
}
102102

103-
public update(div: Plotly.PlotlyHTMLElement, data: Plotly.Data[], layout?: Partial<Plotly.Layout>, config?: Partial<Plotly.Config>, frames?: Partial<Plotly.Config>[]): Promise<any> {
103+
public update(div: Plotly.PlotlyHTMLElement, data: Plotly.Data[], layout?: Partial<Plotly.Layout>, config?: Partial<Plotly.Config>, frames?: Partial<Plotly.Config>[]): Promise<any> {
104104
if (frames) {
105-
const obj = {data, layout, config, frames};
105+
const obj = { data, layout, config, frames };
106106
return this._getPlotly().react(div, obj) as Promise<any>;
107107
}
108108

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { TestBed, inject } from '@angular/core/testing';
2+
import { PlotlyThemeLoaderService } from './plotly.theme-loader.service';
3+
4+
5+
describe('PlotlyThemeLoaderService', () => {
6+
beforeEach(() => {
7+
TestBed.configureTestingModule({
8+
providers: [PlotlyThemeLoaderService]
9+
});
10+
});
11+
12+
it("should load the ggplot2 theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
13+
var json: any = await service.load('ggplot2');
14+
expect(json.geo.lakecolor).toBe("white");
15+
}));
16+
17+
it("should load the gridon theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
18+
var json: any = await service.load('gridon');
19+
expect(json.xaxis.title.standoff).toBe(15);
20+
}));
21+
22+
it("should load the plotly_dark theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
23+
var json: any = await service.load('plotly_dark');
24+
expect(json.mapbox.style).toBe("dark");
25+
}));
26+
27+
it("should load the plotly_white theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
28+
var json: any = await service.load('plotly_white');
29+
expect(json.mapbox.style).toBe("light");
30+
}));
31+
32+
it("should load the plotly theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
33+
var json: any = await service.load('plotly');
34+
expect(json.mapbox.style).toBe("light");
35+
}));
36+
37+
it("should load the presentation theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
38+
var json: any = await service.load('presentation');
39+
expect(json.xaxis.title.standoff).toBe(15);
40+
}));
41+
42+
it("should load the seaborn theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
43+
var json: any = await service.load('seaborn');
44+
expect(json.colorway[2]).toBe('rgb(85,168,104)');
45+
}));
46+
47+
it("should load the simple_white theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
48+
var json: any = await service.load('simple_white');
49+
expect(json.colorway[1]).toBe("#FF7F0E");
50+
}));
51+
52+
it("should load the xgridoff theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
53+
var json: any = await service.load('xgridoff');
54+
expect(json.xaxis.title.standoff).toBe(15);
55+
}));
56+
57+
it("should load the ygridoff theme", inject([PlotlyThemeLoaderService], async (service: PlotlyThemeLoaderService) => {
58+
var json: any = await service.load('ygridoff');
59+
expect(json.yaxis.showgrid).toBe(false);
60+
}));
61+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Injectable } from '@angular/core';
2+
3+
export type PlotlyTheme = 'ggplot2' | 'seaborn' | 'simple_white' | 'plotly' | 'plotly_white' | 'plotly_dark' | 'presentation' | 'xgridoff' | 'ygridoff' | 'gridon' | 'none';
4+
5+
@Injectable({
6+
providedIn: 'root'
7+
})
8+
export class PlotlyThemeLoaderService {
9+
10+
public get isLoading() { return this._isLoading; }
11+
private _isLoading: boolean = false;
12+
13+
public load(themeName: PlotlyTheme): Promise<any> {
14+
this._isLoading = true;
15+
return new Promise(resolve => {
16+
import(`./themes/${themeName}.json`).then(data => {
17+
resolve(data);
18+
this._isLoading = false;
19+
});
20+
});
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"autotypenumbers":"strict","colorway":["#F8766D","#A3A500","#00BF7D","#00B0F6","#E76BF3"],"font":{"color":"rgb(51,51,51)"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"rgb(237,237,237)","polar":{"bgcolor":"rgb(237,237,237)","angularaxis":{"gridcolor":"white","linecolor":"white","showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside"},"radialaxis":{"gridcolor":"white","linecolor":"white","showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside"}},"ternary":{"bgcolor":"rgb(237,237,237)","aaxis":{"gridcolor":"white","linecolor":"white","showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside"},"baxis":{"gridcolor":"white","linecolor":"white","showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside"},"caxis":{"gridcolor":"white","linecolor":"white","showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside"}},"coloraxis":{"colorbar":{"outlinewidth":0,"tickcolor":"rgb(237,237,237)","ticklen":6,"ticks":"inside"}},"colorscale":{"sequential":[[0,"rgb(20,44,66)"],[1,"rgb(90,179,244)"]],"sequentialminus":[[0,"rgb(20,44,66)"],[1,"rgb(90,179,244)"]]},"xaxis":{"gridcolor":"white","linecolor":"white","showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside","title":{"standoff":15},"zerolinecolor":"white","automargin":true},"yaxis":{"gridcolor":"white","linecolor":"white","showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside","title":{"standoff":15},"zerolinecolor":"white","automargin":true},"scene":{"xaxis":{"backgroundcolor":"rgb(237,237,237)","gridcolor":"white","linecolor":"white","showbackground":true,"showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"rgb(237,237,237)","gridcolor":"white","linecolor":"white","showbackground":true,"showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"rgb(237,237,237)","gridcolor":"white","linecolor":"white","showbackground":true,"showgrid":true,"tickcolor":"rgb(51,51,51)","ticks":"outside","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"fillcolor":"black","line":{"width":0},"opacity":0.3},"annotationdefaults":{"arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"rgb(237,237,237)","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"xaxis":{"showgrid":true,"title":{"standoff":15}},"yaxis":{"showgrid":true,"title":{"standoff":15}}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"sequentialminus":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"mapbox":{"style":"light"}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#f2f5fa"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"rgb(17,17,17)","plot_bgcolor":"rgb(17,17,17)","polar":{"bgcolor":"rgb(17,17,17)","angularaxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""},"radialaxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""}},"ternary":{"bgcolor":"rgb(17,17,17)","aaxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""},"baxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""},"caxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"sequentialminus":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"#283442","linecolor":"#506784","ticks":"","title":{"standoff":15},"zerolinecolor":"#283442","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"#283442","linecolor":"#506784","ticks":"","title":{"standoff":15},"zerolinecolor":"#283442","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"rgb(17,17,17)","gridcolor":"#506784","linecolor":"#506784","showbackground":true,"ticks":"","zerolinecolor":"#C8D4E3","gridwidth":2},"yaxis":{"backgroundcolor":"rgb(17,17,17)","gridcolor":"#506784","linecolor":"#506784","showbackground":true,"ticks":"","zerolinecolor":"#C8D4E3","gridwidth":2},"zaxis":{"backgroundcolor":"rgb(17,17,17)","gridcolor":"#506784","linecolor":"#506784","showbackground":true,"ticks":"","zerolinecolor":"#C8D4E3","gridwidth":2}},"shapedefaults":{"line":{"color":"#f2f5fa"}},"annotationdefaults":{"arrowcolor":"#f2f5fa","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"rgb(17,17,17)","landcolor":"rgb(17,17,17)","subunitcolor":"#506784","showland":true,"showlakes":true,"lakecolor":"rgb(17,17,17)"},"title":{"x":0.05},"updatemenudefaults":{"bgcolor":"#506784","borderwidth":0},"sliderdefaults":{"bgcolor":"#C8D4E3","borderwidth":1,"bordercolor":"rgb(17,17,17)","tickwidth":0},"mapbox":{"style":"dark"}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"white","polar":{"bgcolor":"white","angularaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""},"radialaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":""}},"ternary":{"bgcolor":"white","aaxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"baxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""},"caxis":{"gridcolor":"#DFE8F3","linecolor":"#A2B1C6","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"sequentialminus":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"#EBF0F8","linecolor":"#EBF0F8","ticks":"","title":{"standoff":15},"zerolinecolor":"#EBF0F8","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8","gridwidth":2},"yaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8","gridwidth":2},"zaxis":{"backgroundcolor":"white","gridcolor":"#DFE8F3","linecolor":"#EBF0F8","showbackground":true,"ticks":"","zerolinecolor":"#EBF0F8","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"white","subunitcolor":"#C8D4E3","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"mapbox":{"style":"light"}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"xaxis":{"title":{"standoff":15}},"yaxis":{"title":{"standoff":15}},"font":{"size":18}}

0 commit comments

Comments
 (0)