UNPKG

@fleetbase/ember-core

Version:

Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.

174 lines (160 loc) 5.34 kB
import BaseContract from './base-contract'; /** * Represents a lazy-loadable component from an engine * * This contract defines a component that will be loaded on-demand from an engine, * preserving lazy loading capabilities while allowing cross-engine component usage. * * @class ExtensionComponent * @extends BaseContract * * @example * // Simple usage * new ExtensionComponent('@fleetbase/fleetops-engine', 'components/admin/navigator-app') * * @example * // With options * new ExtensionComponent('@fleetbase/fleetops-engine', { * path: 'components/admin/navigator-app', * loadingComponent: 'loading-spinner', * errorComponent: 'error-display' * }) * * @example * // With method chaining * new ExtensionComponent('@fleetbase/fleetops-engine', 'components/widget/metrics') * .withLoadingComponent('skeletons/widget') * .withErrorComponent('error-boundary') * .withData({ refreshInterval: 5000 }) */ export default class ExtensionComponent extends BaseContract { /** * Create a new ExtensionComponent * * @constructor * @param {String} engineName The name of the engine (e.g., '@fleetbase/fleetops-engine') * @param {String|Function|Object} pathClassOrOptions Component path, component class, or options object */ constructor(engineName, pathClassOrOptions = {}) { // Handle component class if (typeof pathClassOrOptions === 'function' && pathClassOrOptions.prototype) { const componentClass = pathClassOrOptions; super({ engine: engineName, class: componentClass, name: componentClass.name, }); this.engine = engineName; this.class = componentClass; this.name = componentClass.name; this.path = null; // No path for classes this.isClass = true; this.loadingComponent = null; this.errorComponent = null; return; } // Handle string path or options object const options = typeof pathClassOrOptions === 'string' ? { path: pathClassOrOptions } : pathClassOrOptions; super({ engine: engineName, ...options, }); this.engine = engineName; this.path = options.path; this.name = options.path; // Add name for parity this.class = null; this.isClass = false; this.loadingComponent = options.loadingComponent || null; this.errorComponent = options.errorComponent || null; } /** * Validate the component definition * * @method validate * @throws {Error} If engine name or path/class is missing */ validate() { if (!this.engine) { throw new Error('ExtensionComponent requires an engine name'); } if (!this.path && !this.class) { throw new Error('ExtensionComponent requires a component path or class'); } } /** * Set a custom loading component to display while the engine loads * * @method withLoadingComponent * @param {String} componentName Name of the loading component * @returns {ExtensionComponent} This instance for chaining */ withLoadingComponent(componentName) { this.loadingComponent = componentName; this._options.loadingComponent = componentName; return this; } /** * Set a custom error component to display if loading fails * * @method withErrorComponent * @param {String} componentName Name of the error component * @returns {ExtensionComponent} This instance for chaining */ withErrorComponent(componentName) { this.errorComponent = componentName; this._options.errorComponent = componentName; return this; } /** * Add custom data to pass to the component when it renders * * @method withData * @param {Object} data Custom data object * @returns {ExtensionComponent} This instance for chaining */ withData(data) { this._options.data = data; return this; } /** * Set a timeout for loading the component * * @method withTimeout * @param {Number} milliseconds Timeout in milliseconds * @returns {ExtensionComponent} This instance for chaining */ withTimeout(milliseconds) { this._options.timeout = milliseconds; return this; } /** * Get the plain object representation * * @method toObject * @returns {Object} Plain object with all component definition properties */ toObject() { return { engine: this.engine, path: this.path, name: this.name, class: this.class, isClass: this.isClass, loadingComponent: this.loadingComponent, errorComponent: this.errorComponent, ...this._options, }; } /** * Get the string representation * * @method toString * @returns {String} Plain string component definition properties */ toString() { if (this.isClass) { return `#extension-component:${this.engine}:${this.name}`; } return `#extension-component:${this.engine}:${this.path}`; } }