UNPKG

@mongodb-js/charts-embed-dom

Version:

JavaScript library for embedding MongoDB Charts

166 lines (165 loc) 6.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const chatty_1 = require("@looker/chatty"); const dom_1 = require("./dom"); const types_1 = require("./types"); const utils_1 = require("./utils"); const MAX_QUERY_EXECUTION_MS = 10 * 60 * 1000; // 10 minutes class BaseEmbedItem { /** * Renders an embeddable item into the given `container`. * * This method should only be called once, and successive attempts to call `render` * will fail with an error. * * @returns a promise that will resolve once the item has successfully been embedded */ async render(container) { if (this.iframe) { throw new Error(this.ERRORS.IFRAME); } // Create styled container const embedRoot = this._configureEmbedRoot((0, dom_1.createElement)('div', { style: { position: 'relative', overflow: 'hidden', minHeight: Boolean(this.options.height) ? 0 : '15px', width: (0, utils_1.parseCSSMeasurement)(this.options.width) || '100%', height: (0, utils_1.parseCSSMeasurement)(this.options.height) || '100%', }, })); // Create host const host = this._configureHost(chatty_1.Chatty.createHost(this.getEmbedUrl()) .withDefaultTimeout(MAX_QUERY_EXECUTION_MS) .withSandboxAttribute('allow-scripts') .withSandboxAttribute('allow-same-origin') .withSandboxAttribute('allow-popups') .withSandboxAttribute('allow-popups-to-escape-sandbox') .appendTo(embedRoot)).build(); // Customise IFrame styles host.iframe.setAttribute('aria-label', this.name); Object.assign(host.iframe.style, { position: 'absolute', top: 0, left: 0, border: 0, width: '100%', height: '100%', }); // Remove any existing nodes in our target container while (container.firstChild) container.removeChild(container.firstChild); container.appendChild(embedRoot); // connect to iframe this.connection = await host.connect(); this.iframe = host.iframe; this._setBackground(this.options.background, this.options.theme); // configure token if needed await this._retrieveAndSetToken(); } /** * @returns whether auto refreshing is enabled */ async isAutoRefresh() { const [result] = await this._send('get', 'autoRefresh'); // autoRefresh from embed chart may be a number when refreshInterval is set return typeof result === 'number' || typeof result === 'boolean' ? Boolean(result) : Promise.reject('unexpected response received from iframe'); } /** * Enable/Disable auto refreshing. */ async setAutoRefresh(value) { if (typeof value !== 'boolean') { return Promise.reject('autoRefresh property value should be a boolean'); } await this._send('set', 'autoRefresh', value); } /** * @returns the number of seconds before a chart or dashboard's data expires */ async getMaxDataAge() { const [result] = await this._send('get', 'maxDataAge'); return typeof result === 'number' ? result : Promise.reject('unexpected response received from iframe'); } /** * Set the number of seconds a chart or dashboard's data expires. */ async setMaxDataAge(value) { if (typeof value !== 'number') { return Promise.reject('maxDataAge property value should be a number'); } await this._send('set', 'maxDataAge', value); } /** * Sets the color scheme to apply to the chart or dashboard. * * If the theme is set to 'dark' and you have specified a custom background color, you should ensure that your background color has appropriate contrast. */ async setTheme(value) { if (typeof value !== 'string') { return Promise.reject('theme property value should be a string'); } // if invalid theme string is provided, default it to light const newTheme = Object.values(types_1.THEME).includes(value) ? value : types_1.THEME.LIGHT; await this._send('set', 'theme', newTheme); this._setBackground(this.options.background, newTheme); } /** * @returns the current theme applied to the chart or dashboard */ async getTheme() { const [result] = await this._send('get', 'theme'); return typeof result === 'string' ? result : Promise.reject('unexpected response received from iframe'); } _configureHost(hostBuilder) { return hostBuilder.on('refreshToken', () => this._retrieveAndSetToken()); } _configureEmbedRoot(embedRoot) { return embedRoot; } _setBackground(background, theme) { this.iframe.style.backgroundColor = (0, utils_1.getBackground)(background, theme, this.COLOUR.LIGHT, this.COLOUR.DARK); } async _retrieveAndSetToken() { if (this.options.getUserToken) { const token = await this.options.getUserToken(); await this._send('set', 'token', token); } } /** * Send message to embedded app. */ _send(eventName, ...payload) { if (this.connection) { return this.connection.sendAndReceive(eventName, ...payload); } return Promise.reject(this.ERRORS.SEND); } /** * Get the image data of embeded entity in base64 or binary encoding * @param {GetImageOptions} options options for image generation * @returns {string | Blob} image encoded with base64 or binary */ async getImage(options) { const { encoding } = options || {}; if (encoding !== types_1.ENCODING.BASE64 && encoding !== types_1.ENCODING.BINARY) { return Promise.reject('Encoding must be either "base64" or "binary"'); } const [result] = await this._send('get', 'image', { background: this.options.background, encoding, }); return typeof result === 'string' || result instanceof Blob ? result : Promise.reject('unexpected response received from iframe'); } } exports.default = BaseEmbedItem;