UNPKG

@highcharts/dashboards

Version:
270 lines (269 loc) 8.18 kB
/* * * * (c) 2009-2025 Highsoft AS * * License: www.highcharts.com/license * * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! * * Authors: * - Dawid Dragula * * */ import Cell from '../Layout/Cell.js'; import Globals from '../Globals.js'; /* * * * Class * * */ /** * A class that handles the connection between the component and the data * connector. */ class ConnectorHandler { /* * * * Constructor * * */ /** * Creates an object that manages the data layer for the component. * * @param component * The component that the connector is tied to. * * @param options * The options for the connector. * */ constructor(component, options) { /** * Event listeners tied to the current DataTable. Used for rerendering the * component on data changes. * * @internal */ this.tableEvents = []; this.component = component; this.options = options; } /* * * * Functions * * */ /** * Inits connectors for the component and rerenders it. * * @returns * Promise resolving to the component. */ async initConnector() { const component = this.component; const connectorId = this.options.id; const dataPool = this.component.board.dataPool; if (connectorId && (this.connectorId !== connectorId || dataPool.isNewConnector(connectorId))) { if (Cell.isCell(component.cell)) { component.cell.setLoadingState(); } const connector = await dataPool.getConnector(connectorId); // The connector shouldn't be set if the handler was destroyed // during its creation. if (!this.destroyed) { this.setConnector(connector); } } return component; } /** * Sets the data table settings and events. * * @param table * The data table instance for settings and events. */ setTable(table) { // Set up event listeners this.clearTableListeners(table); this.setupTableListeners(table); // Re-setup if modifier changes table.on('setModifier', () => this.clearTableListeners(table)); table.on('afterSetModifier', (e) => { if (e.type === 'afterSetModifier' && e.modified) { this.setupTableListeners(e.modified); this.component.emit({ type: 'tableChanged', connector: this.connector }); } }); if (this.presentationModifier) { this.presentationTable = this.presentationModifier.modifyTable(table.modified.clone()).modified; } else { this.presentationTable = table; } } /** * Sets the connector for the component connector handler. * * @param connector * The connector to set. */ setConnector(connector) { // Clean up old event listeners while (this.tableEvents.length) { const eventCallback = this.tableEvents.pop(); if (typeof eventCallback === 'function') { eventCallback(); } } this.connector = connector; if (connector) { const dataTableKey = this.component.dataTableKey; const dataTables = connector.dataTables; if (dataTableKey) { // Match a data table used in this component. this.setTable(dataTables[dataTableKey]); // Take the first connector data table if id not provided. } else { this.setTable(Object.values(dataTables)[0]); } } this.addConnectorAssignment(); return this.component; } /** * Adds event listeners to data table. * @param table * Data table that is source of data. * @internal */ setupTableListeners(table) { const connector = this.connector; if (connector) { if (table) { [ 'afterDeleteRows', 'afterSetCell', 'afterSetColumns', 'afterSetRows' ].forEach((event) => { this.tableEvents.push(table.on(event, (e) => { clearTimeout(this.tableEventTimeout); this.tableEventTimeout = Globals.win.setTimeout(() => { this.component.emit({ ...e, type: 'tableChanged', targetConnector: connector }); this.tableEventTimeout = void 0; }); })); }); } } } /** * Remove event listeners in data table. * * @param table * The connector data table (data source). * * @internal */ clearTableListeners(table) { const connector = this.connector; const tableEvents = this.tableEvents; this.removeTableEvents(); if (connector) { tableEvents.push(table.on('afterSetModifier', (e) => { if (e.type === 'afterSetModifier') { clearTimeout(this.tableEventTimeout); this.tableEventTimeout = Globals.win.setTimeout(() => { connector.emit({ ...e, type: 'tableChanged', targetConnector: connector }); this.tableEventTimeout = void 0; }); } })); } } /** * Adds the component to the provided connector. * Starts the connector polling if inactive and one component is provided. */ addConnectorAssignment() { const { connector } = this; if (!connector) { return; } if (!connector.components) { connector.components = []; } if (!connector.components.includes(this.component)) { const options = connector.options; // Add the component assignment. connector.components.push(this.component); // Start the connector polling. if ('enablePolling' in options && options.enablePolling && !connector.polling && connector.components.length === 1 && 'dataRefreshRate' in options) { connector.startPolling(Math.max(options.dataRefreshRate || 0, 1) * 1000); } } } /** * Removes the component instance from the provided connector. * Stops the connector polling if the last element is removed. */ removeConnectorAssignment() { const { connector } = this; if (!connector?.components) { return; } const index = connector.components.indexOf(this.component); if (index > -1) { connector.components.splice(index, 1); if (!connector.components.length) { connector.stopPolling(); delete connector.components; } } } /** * Clears all event listeners in the table. */ removeTableEvents() { this.tableEvents.forEach((clearEvent) => clearEvent()); this.tableEvents.length = 0; } /** * Updates the options for the connector handler. * * @param newOptions * The new options to update. */ updateOptions(newOptions) { this.options = newOptions; } /** * Destroys the connector handler. * @internal */ destroy() { this.destroyed = true; this.removeConnectorAssignment(); this.removeTableEvents(); } } export default ConnectorHandler;