@mongodb-js/charts-embed-dom
Version:
JavaScript library for embedding MongoDB Charts
157 lines (156 loc) • 6.28 kB
JavaScript
import BaseEmbedItem from './base-embed-item';
import { EventSource } from './mixins/event-source';
import { Refreshable } from './mixins/refreshable';
import { CommonChart } from './mixins/common-chart';
import { Filterable } from './mixins/filterable';
import { getChartUrl, getSharedEmbedOptions, isPlainObject } from './utils';
const getChartOptions = (options) => {
if (typeof options !== 'object' || options === null) {
throw new Error('Options argument must be an object');
}
const sharedEmbedOptions = getSharedEmbedOptions(options);
const { chartId, refreshInterval, renderingSpec } = options;
// Verify chart embed options
if (typeof chartId !== 'string' || chartId.length === 0) {
throw new Error('chartId must be specified');
}
if (refreshInterval !== undefined && typeof refreshInterval !== 'number') {
throw new Error('refreshInterval interval must be a number if specified');
}
if (renderingSpec !== undefined && !isPlainObject(renderingSpec)) {
throw new Error('renderingSpec must be an object if specified');
}
if (renderingSpec !== undefined && !renderingSpec.version) {
throw new Error('renderingSpec must contain a version key');
}
return {
...sharedEmbedOptions,
chartId,
refreshInterval,
renderingSpec,
};
};
class ChartEventSender extends BaseEmbedItem {
/** @ignore */
constructor(options) {
super();
this.name = 'Embedded Chart';
this.ERRORS = {
SEND: 'Chart has not been rendered. Ensure that you wait for the promise returned by `chart.render()` before trying to manipulate a chart.',
IFRAME: 'A chart can only be rendered into a container once',
};
this.COLOUR = {
LIGHT: '#FFFFFF',
DARK: '#21313C',
};
this.options = getChartOptions(options);
}
getEmbedUrl() {
return getChartUrl(this.options);
}
}
/**
* # Chart
*
* Allows you to interact and embed charts into your application.
*
* ```js
* const sdk = new EmbedSDK({ ... });
* const chart = sdk.createChart({ ... });
*
* // renders a chart
* chart.render(document.getElementById('embed-chart'));
*
* // dynamically set a filter
* chart.setFilter({ age: { $gt: 50 } });
* ```
*/
class Chart extends CommonChart(Filterable(Refreshable(EventSource(ChartEventSender)))) {
/**
* Sends the `ready` event to Charts to render the embedded chart in the component
* @param container where the chart will render
*/
async render(container) {
await super.render(container);
const renderingSpec = this.options.renderingSpec;
const initialState = renderingSpec ? { renderingSpec } : {};
// Ready to actually render Embedded Chart
await this._send('ready', initialState);
if (initialState.renderingSpec) {
// store users rendering spec
this.renderingSpec = initialState.renderingSpec;
}
}
/**
* @returns the number of seconds a chart will wait before refreshing
* @deprecated This method is deprecated. Please use the 'autoRefresh' option with the 'maxDataAge' option to configure how often the chart refreshes.
*/
async getRefreshInterval() {
const [result] = await this._send('get', 'autorefresh');
console.warn("The 'getRefreshInterval' method is deprecated. Please use the 'autoRefresh' option with the 'maxDataAge' option to configure how often the chart refreshes.");
return typeof result === 'number'
? result
: Promise.reject('unexpected response received from iframe');
}
/**
* Set the number of seconds a chart will wait before refreshing.
*
* The minimum refresh interval is 10 seconds. To disable, set the refresh interval to 0.
* @deprecated This method is deprecated. Please use the 'autoRefresh' option with the 'maxDataAge' option to configure how often the chart refreshes.
*/
async setRefreshInterval(value) {
if (typeof value !== 'number') {
return Promise.reject('refreshInterval property value should be a number');
}
console.warn("The 'setRefreshInterval' method is deprecated. Please use the 'autoRefresh' option with the 'maxDataAge' option to configure how often the chart refreshes.");
await this._send('set', 'autorefresh', value);
}
_configureHost(hostBuilder) {
return super
._configureHost(hostBuilder)
.on('event', this._handleEvent.bind(this));
}
/**
* Sets a set of customizations on the rendered chart
* @param value customization settings and values
* @returns a promise that resolves once the rendering spec is saved and the component rerendered
*/
async setRenderingSpecOverride(value) {
if (!isPlainObject(value)) {
return Promise.reject('renderingSpec property value should be an object');
}
if (!value.version) {
return Promise.reject('renderingSpec should contain a "version" key');
}
await this._send('set', 'renderingSpec', value);
this.renderingSpec = value;
}
/**
* Get the channel data from the current chart
* @returns a promise that resolves to the channel data on the current chart
*/
async getChannels() {
const [result] = await this._send('get', 'channels');
return !!result && typeof result === 'object'
? result
: Promise.reject('Unexpected response from iframe');
}
/**
* Get the customizable axes data from the current chart
* @returns a promise that resolves to the axis data on the current chart
*/
async getCustomizableAxes() {
const [result] = await this._send('get', 'axes');
return !!result && typeof result === 'object'
? result
: Promise.reject('Unexpected response from iframe');
}
/**
* Gets the customizations applied to a chart after initial render
* @returns the customized rendering spec or undefined.
*/
getRenderingSpecOverride() {
return this.renderingSpec;
}
}
export default Chart;