Add data structures for chart plugin system (#6028)

* add unit tests

* add test structure

* add unit tests for Registry

* add LoaderRegistry unit test

* add unit test for makeSingleton

* add type check

* add plugin data structures

* simplify API

* add preset tests

* update test message

* fix lint

* update makeSingleton

* update Plugin, Preset and unit test

* revise Registry code

* update unit test, add remove function

* update test

* update unit test

* update plugin unit test

* add .keys(), .entries() and .entriesAsPromise()

* update test description
This commit is contained in:
Krist Wongsuphasawat
2018-10-09 11:47:16 -07:00
committed by Chris Williams
parent 395359f5ad
commit cd2c46a5ed
16 changed files with 602 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
export default class ChartMetadata {
constructor({
name,
description,
thumbnail,
show = true,
}) {
this.name = name;
this.description = description;
this.thumbnail = thumbnail;
this.show = show;
}
}

View File

@@ -0,0 +1,43 @@
import Plugin from './Plugin';
import isRequired from '../../../utils/isRequired';
import getChartMetadataRegistry from '../registries/ChartMetadataRegistrySingleton';
import getChartComponentRegistry from '../registries/ChartComponentRegistrySingleton';
import getChartTransformPropsRegistry from '../registries/ChartTransformPropsRegistrySingleton';
const IDENTITY = x => x;
export default class ChartPlugin extends Plugin {
constructor({
metadata = isRequired('metadata'),
// use transformProps for immediate value
transformProps = IDENTITY,
// use loadTransformProps for dynamic import (lazy-loading)
loadTransformProps,
// use Chart for immediate value
Chart,
// use loadChart for dynamic import (lazy-loading)
loadChart,
} = {}) {
super();
this.metadata = metadata;
this.loadTransformProps = loadTransformProps || (() => transformProps);
if (loadChart) {
this.loadChart = loadChart;
} else if (Chart) {
this.loadChart = () => Chart;
} else {
throw new Error('Chart or loadChart is required');
}
}
register() {
const { key = isRequired('config.key') } = this.config;
getChartMetadataRegistry().registerValue(key, this.metadata);
getChartComponentRegistry().registerLoader(key, this.loadChart);
getChartTransformPropsRegistry().registerLoader(key, this.loadTransformProps);
return this;
}
}

View File

@@ -0,0 +1,25 @@
export default class Plugin {
constructor() {
this.resetConfig();
}
resetConfig() {
// The child class can set default config
// by overriding this function.
this.config = {};
return this;
}
configure(config, replace = false) {
if (replace) {
this.config = config;
} else {
this.config = { ...this.config, ...config };
}
return this;
}
register() {
return this;
}
}

View File

@@ -0,0 +1,23 @@
export default class Preset {
constructor({
name = '',
description = '',
presets = [],
plugins = [],
} = {}) {
this.name = name;
this.description = description;
this.presets = presets;
this.plugins = plugins;
}
register() {
this.presets.forEach((preset) => {
preset.register();
});
this.plugins.forEach((plugin) => {
plugin.register();
});
return this;
}
}

View File

@@ -0,0 +1,12 @@
import Registry from '../../../modules/Registry';
import makeSingleton from '../../../utils/makeSingleton';
class ChartComponentRegistry extends Registry {
constructor() {
super('ChartComponent');
}
}
const getInstance = makeSingleton(ChartComponentRegistry);
export default getInstance;

View File

@@ -0,0 +1,12 @@
import Registry from '../../../modules/Registry';
import makeSingleton from '../../../utils/makeSingleton';
class ChartMetadataRegistry extends Registry {
constructor() {
super('ChartMetadata');
}
}
const getInstance = makeSingleton(ChartMetadataRegistry);
export default getInstance;

View File

@@ -0,0 +1,12 @@
import Registry from '../../../modules/Registry';
import makeSingleton from '../../../utils/makeSingleton';
class ChartTransformPropsRegistry extends Registry {
constructor() {
super('ChartTransformProps');
}
}
const getInstance = makeSingleton(ChartTransformPropsRegistry);
export default getInstance;