Skip to content

Commit

Permalink
feat: add safe mode to config
Browse files Browse the repository at this point in the history
  • Loading branch information
FERNman committed Apr 6, 2020
1 parent 8f1f36b commit e11974c
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 47 deletions.
8 changes: 7 additions & 1 deletion docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export class AppModule {}

## Providing a Google Maps API Key

When using GeoCharts, it might be necessary to provide a Maps API Key to access full functionality.
When using Geocharts or Map Charts, it might be necessary to provide a Maps API Key to avoid
the default request throttling of Googles servers.

The Google Maps API Key can be configured using the `mapsApiKey` property in the config.

Expand All @@ -31,3 +32,8 @@ You may want to specify a custom version of Google Charts, e.g. `'upcoming'`.
More information on this can be found in the [official documentation](https://developers.google.com/chart/interactive/docs/basic_load_libs).

The version can be configured using the `version` property in the config.

## Sanitizing unsafe HTML

Since version 47, Google Charts allows you to sanitize generated HTML and will automatically strip unsafe elements.
You can enable this behaviour by setting `safeMode` to true.
17 changes: 9 additions & 8 deletions libs/angular-google-charts/src/lib/google-charts.module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { TestBed } from '@angular/core/testing';

import { GoogleChartsModule } from './google-charts.module';
import { CHART_VERSION, MAPS_API_KEY } from './models/injection-tokens.model';
import { GoogleChartsConfig } from './models/google-charts-config.model';
import { GOOGLE_CHARTS_CONFIG } from './models/injection-tokens.model';
import { ScriptLoaderService } from './script-loader/script-loader.service';

describe('GoogleChartsModule', () => {
Expand All @@ -23,32 +24,32 @@ describe('GoogleChartsModule', () => {
describe('config via forRoot', () => {
const mapsApiKey = 'myMapsApiKey';
const version = '13.5';
const safeMode = false;

it('should provide the given config values', () => {
const config: GoogleChartsConfig = { mapsApiKey, version, safeMode };

TestBed.configureTestingModule({
imports: [GoogleChartsModule.forRoot({ mapsApiKey, version })]
imports: [GoogleChartsModule.forRoot(config)]
});

expect(TestBed.inject(CHART_VERSION)).toBe(version);
expect(TestBed.inject(MAPS_API_KEY)).toBe(mapsApiKey);
expect(TestBed.inject(GOOGLE_CHARTS_CONFIG)).toEqual(config);
});

it('should accept empty config', () => {
TestBed.configureTestingModule({
imports: [GoogleChartsModule.forRoot()]
});

expect(TestBed.inject(CHART_VERSION)).toBeUndefined();
expect(TestBed.inject(MAPS_API_KEY)).toBeUndefined();
expect(TestBed.inject(GOOGLE_CHARTS_CONFIG)).toEqual({});
});

it('should accept a partial config', () => {
TestBed.configureTestingModule({
imports: [GoogleChartsModule.forRoot({ mapsApiKey })]
});

expect(TestBed.inject(CHART_VERSION)).toBeUndefined();
expect(TestBed.inject(MAPS_API_KEY)).toBe(mapsApiKey);
expect(TestBed.inject(GOOGLE_CHARTS_CONFIG)).toMatchObject({ mapsApiKey });
});
});
});
11 changes: 4 additions & 7 deletions libs/angular-google-charts/src/lib/google-charts.module.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import { ModuleWithProviders, NgModule } from '@angular/core';

import { GoogleChartComponent } from './google-chart/google-chart.component';
import { Config } from './models/config.model';
import { CHART_VERSION, MAPS_API_KEY } from './models/injection-tokens.model';
import { GoogleChartsConfig } from './models/google-charts-config.model';
import { GOOGLE_CHARTS_CONFIG } from './models/injection-tokens.model';
import { RawChartComponent } from './raw-chart/raw-chart.component';

@NgModule({
declarations: [GoogleChartComponent, RawChartComponent],
exports: [GoogleChartComponent, RawChartComponent]
})
export class GoogleChartsModule {
public static forRoot({ mapsApiKey, version }: Config = {}): ModuleWithProviders<GoogleChartsModule> {
public static forRoot(config: GoogleChartsConfig = {}): ModuleWithProviders<GoogleChartsModule> {
return {
ngModule: GoogleChartsModule,
providers: [
{ provide: MAPS_API_KEY, useValue: mapsApiKey },
{ provide: CHART_VERSION, useValue: version }
]
providers: [{ provide: GOOGLE_CHARTS_CONFIG, useValue: config }]
};
}
}
15 changes: 0 additions & 15 deletions libs/angular-google-charts/src/lib/models/config.model.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export interface GoogleChartsConfig {
/**
* This setting lets you specify a key that you may use with Geochart and Map Chart.
* You may want to do this rather than use the default behavior which may result in
* occasional throttling of service for your users.
*
* Only available when using Google Charts 45 or higher.
*
* {@link https://developers.google.com/chart/interactive/docs/basic_load_libs#load-settings Parameter documentation }
* {@link https://developers.google.com/chart/interactive/docs/gallery/geochart GeoChart Documentation}
*/
mapsApiKey?: string;

/**
* Which version of Google Charts to use.
*
* Please note that this library does only work with Google Charts 45 or higher.
*
* @description
* Can be either a number specifying a
* {@link https://developers.google.com/chart/interactive/docs/release_notes#current:-january-6,-2020 frozen version } of Google Charts
* or one of the special versions `current` and `upcoming`.
*
* Defaults to `current`.
*
* {@link https://developers.google.com/chart/interactive/docs/basic_load_libs#basic-library-loading Offical Documentation}
*/
version?: string;

/**
* When set to true, all charts and tooltips that generate HTML from user-supplied data will sanitize it
* by stripping out unsafe elements and attributes.
*
* Only available when using GoogleCharts 47 or higher.
*
* {@link https://developers.google.com/chart/interactive/docs/basic_load_libs#load-settings Parameter documentation }
*/
safeMode?: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { InjectionToken } from '@angular/core';

export const CHART_VERSION = new InjectionToken<string>('CHART_VERSION');
export const MAPS_API_KEY = new InjectionToken<string>('MAPS_API_KEY');
import { GoogleChartsConfig } from './google-charts-config.model';

export const GOOGLE_CHARTS_CONFIG = new InjectionToken<GoogleChartsConfig>('GOOGLE_CHARTS_CONFIG');
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TestBed } from '@angular/core/testing';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

import { CHART_VERSION, MAPS_API_KEY } from '../models/injection-tokens.model';
import { GOOGLE_CHARTS_CONFIG } from '../models/injection-tokens.model';

import { ScriptLoaderService } from './script-loader.service';

Expand Down Expand Up @@ -104,10 +104,11 @@ describe('ScriptLoaderService', () => {

service.loadChartPackages(chart).subscribe();

expect(chartsMock.load).toHaveBeenCalledWith('46', {
expect(chartsMock.load).toHaveBeenCalledWith('current', {
packages: [chart],
language: 'en-US',
mapsApiKey: ''
mapsApiKey: '',
safeMode: false
});
});

Expand All @@ -131,14 +132,14 @@ describe('ScriptLoaderService', () => {

const version = 'current';
const mapsApiKey = 'mapsApiKey';
const safeMode = true;
const locale = 'de-DE';

TestBed.configureTestingModule({
providers: [
ScriptLoaderService,
{ provide: LOCALE_ID, useValue: locale },
{ provide: CHART_VERSION, useValue: version },
{ provide: MAPS_API_KEY, useValue: mapsApiKey }
{ provide: GOOGLE_CHARTS_CONFIG, useValue: { version, mapsApiKey, safeMode } }
]
});
service = TestBed.inject(ScriptLoaderService);
Expand All @@ -150,7 +151,8 @@ describe('ScriptLoaderService', () => {
expect(chartsMock.load).toHaveBeenCalledWith(version, {
packages: [chart],
language: locale,
mapsApiKey: mapsApiKey
mapsApiKey,
safeMode
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@ import { Inject, Injectable, LOCALE_ID, Optional } from '@angular/core';
import { Observable, of, Subject } from 'rxjs';
import { switchMap } from 'rxjs/operators';

import { CHART_VERSION, MAPS_API_KEY } from '../models/injection-tokens.model';
import { GoogleChartsConfig } from '../models/google-charts-config.model';
import { GOOGLE_CHARTS_CONFIG } from '../models/injection-tokens.model';

const DEFAULT_CONFIG: GoogleChartsConfig = {
mapsApiKey: '',
version: 'current',
safeMode: false
};

@Injectable({ providedIn: 'root' })
export class ScriptLoaderService {
private readonly scriptSource = 'https://www.gstatic.com/charts/loader.js';
private readonly onLoadSubject = new Subject<void>();

constructor(
@Inject(LOCALE_ID) private localeId: string,
@Inject(MAPS_API_KEY) @Optional() private mapsApiKey?: string,
@Inject(CHART_VERSION) @Optional() private chartVersion?: string
) {}
constructor(@Inject(LOCALE_ID) private localeId: string, @Inject(GOOGLE_CHARTS_CONFIG) @Optional() private config?: GoogleChartsConfig) {
this.config = { ...DEFAULT_CONFIG, ...(config || {}) };
}

/**
* A stream that emits as soon as the google charts script is loaded (i.e. `google.charts` is available).
Expand Down Expand Up @@ -59,10 +64,11 @@ export class ScriptLoaderService {
const config = {
packages,
language: this.localeId,
mapsApiKey: this.mapsApiKey || ''
mapsApiKey: this.config.mapsApiKey,
safeMode: this.config.safeMode
};

google.charts.load(this.chartVersion || '46', config);
google.charts.load(this.config.version, config);
google.charts.setOnLoadCallback(() => {
observer.next();
observer.complete();
Expand Down

0 comments on commit e11974c

Please sign in to comment.