openmct/src/MCT.js
2024-08-01 17:27:12 +02:00

416 lines
13 KiB
JavaScript

/*****************************************************************************
* Open MCT, Copyright (c) 2014-2024, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import { EventEmitter } from 'eventemitter3';
import { createApp, markRaw } from 'vue';
import ActionsAPI from './api/actions/ActionsAPI.js';
import AnnotationAPI from './api/annotation/AnnotationAPI.js';
import BrandingAPI from './api/Branding.js';
import CompositionAPI from './api/composition/CompositionAPI.js';
import EditorAPI from './api/Editor.js';
import FaultManagementAPI from './api/faultmanagement/FaultManagementAPI.js';
import FormsAPI from './api/forms/FormsAPI.js';
import IndicatorAPI from './api/indicators/IndicatorAPI.js';
import MenuAPI from './api/menu/MenuAPI.js';
import NotificationAPI from './api/notifications/NotificationAPI.js';
import ObjectAPI from './api/objects/ObjectAPI.js';
import OverlayAPI from './api/overlays/OverlayAPI.js';
import PriorityAPI from './api/priority/PriorityAPI.js';
import StatusAPI from './api/status/StatusAPI.js';
import TelemetryAPI from './api/telemetry/TelemetryAPI.js';
import TimeAPI from './api/time/TimeAPI.js';
import ToolTipAPI from './api/tooltips/ToolTipAPI.js';
import TypeRegistry from './api/types/TypeRegistry.js';
import UserAPI from './api/user/UserAPI.js';
import DuplicateActionPlugin from './plugins/duplicate/plugin.js';
import ExportAsJSONAction from './plugins/exportAsJSONAction/plugin.js';
import ImageryPlugin from './plugins/imagery/plugin.js';
import ImportFromJSONAction from './plugins/importFromJSONAction/plugin.js';
import LicensesPlugin from './plugins/licenses/plugin.js';
import LinkActionPlugin from './plugins/linkAction/plugin.js';
import MoveActionPlugin from './plugins/move/plugin.js';
import plugins from './plugins/plugins.js';
import RemoveActionPlugin from './plugins/remove/plugin.js';
import Selection from './selection/Selection.js';
import Layout from './ui/layout/AppLayout.vue';
import PreviewPlugin from './ui/preview/plugin.js';
import InspectorViewRegistry from './ui/registries/InspectorViewRegistry.js';
import ToolbarRegistry from './ui/registries/ToolbarRegistry.js';
import ViewRegistry from './ui/registries/ViewRegistry.js';
import ApplicationRouter from './ui/router/ApplicationRouter.js';
import Browse from './ui/router/Browse.js';
/**
* Open MCT is an extensible web application for building mission
* control user interfaces. This module is itself an instance of
* [MCT]{@link module:openmct.MCT}, which provides an interface for
* configuring and executing the application.
*
* @exports openmct
*/
/**
* The Open MCT application. This may be configured by installing plugins
* or registering extensions before the application is started.
* @constructor
*/
export class MCT extends EventEmitter {
/**
* @type {import('openmct.js').BuildInfo}
*/
buildInfo;
/**
* @type {string}
*/
defaultClock;
/**
* @type {Record<string, OpenMCTPlugin>}
*/
plugins;
/**
* Tracks current selection state of the application.
* @type {Selection}
*/
selection;
constructor() {
super();
this.buildInfo = {
version: __OPENMCT_VERSION__,
buildDate: __OPENMCT_BUILD_DATE__,
revision: __OPENMCT_REVISION__,
branch: __OPENMCT_BUILD_BRANCH__
};
this.destroy = this.destroy.bind(this);
this.defaultClock = 'local';
this.plugins = plugins;
this.selection = new Selection(this);
/**
* @type {TimeAPI}
*/
this.time = new TimeAPI(this);
/**
* An interface for interacting with the composition of domain objects.
* The composition of a domain object is the list of other domain
* objects it "contains" (for instance, that should be displayed
* beneath it in the tree.)
*
* `composition` may be called as a function, in which case it acts
* as [`composition.get`]{@link module:openmct.CompositionAPI#get}.
*
* @type {CompositionAPI}
*/
this.composition = new CompositionAPI(this);
/**
* Registry for views of domain objects which should appear in the
* main viewing area.
*
* @type {ViewRegistry}
*/
this.objectViews = new ViewRegistry();
/**
* Registry for views which should appear in the Inspector area.
* These views will be chosen based on the selection state.
*
* @type {InspectorViewRegistry}
*/
this.inspectorViews = new InspectorViewRegistry();
/**
* Registry for views which should appear in Edit Properties
* dialogs, and similar user interface elements used for
* modifying domain objects external to its regular views.
*
* @type {ViewRegistry}
*/
this.propertyEditors = new ViewRegistry();
/**
* Registry for views which should appear in the toolbar area while
* editing. These views will be chosen based on the selection state.
*
* @type {ToolbarRegistry}
*/
this.toolbars = new ToolbarRegistry();
/**
* Registry for domain object types which may exist within this
* instance of Open MCT.
*
* @type {TypeRegistry}
*/
this.types = new TypeRegistry();
/**
* An interface for interacting with domain objects and the domain
* object hierarchy.
*
* @type {ObjectAPI}
*/
this.objects = new ObjectAPI(this.types, this);
/**
* An interface for retrieving and interpreting telemetry data associated
* with a domain object.
*
* @type {TelemetryAPI}
*/
this.telemetry = new TelemetryAPI(this);
/**
* An interface for creating new indicators and changing them dynamically.
*
* @type {IndicatorAPI}
*/
this.indicators = new IndicatorAPI(this);
/**
* MCT's user awareness management, to enable user and
* role specific functionality.
* @type {UserAPI}
*/
this.user = new UserAPI(this);
/**
* An interface for managing notifications and alerts.
* @type {NotificationAPI}
*/
this.notifications = new NotificationAPI();
/**
* An interface for editing domain objects.
* @type {EditorAPI}
*/
this.editor = new EditorAPI(this);
/**
* An interface for managing overlays.
* @type {OverlayAPI}
*/
this.overlays = new OverlayAPI();
/**
* An interface for managing tooltips.
* @type {ToolTipAPI}
*/
this.tooltips = new ToolTipAPI();
/**
* An interface for managing menus.
* @type {MenuAPI}
*/
this.menus = new MenuAPI(this);
/**
* An interface for managing menu actions.
* @type {ActionsAPI}
*/
this.actions = new ActionsAPI(this);
/**
* An interface for managing statuses.
* @type {StatusAPI}
*/
this.status = new StatusAPI(this);
/**
* An object defining constants for priority levels.
* @type {PriorityAPI}
*/
this.priority = PriorityAPI;
/**
* An interface for routing application traffic.
* @type {ApplicationRouter}
*/
this.router = new ApplicationRouter(this);
/**
* An interface for managing faults.
* @type {FaultManagementAPI}
*/
this.faults = new FaultManagementAPI(this);
/**
* An interface for managing forms.
* @type {FormsAPI}
*/
this.forms = new FormsAPI(this);
/**
* An interface for branding the application.
* @type {BrandingAPI}
*/
this.branding = BrandingAPI;
/**
* MCT's annotation API that enables
* human-created comments and categorization linked to data products
* @type {AnnotationAPI}
*/
this.annotation = new AnnotationAPI(this);
// Plugins that are installed by default
this.install(this.plugins.Plot());
this.install(this.plugins.TelemetryTable());
this.install(PreviewPlugin());
this.install(LicensesPlugin());
this.install(RemoveActionPlugin());
this.install(MoveActionPlugin());
this.install(LinkActionPlugin());
this.install(DuplicateActionPlugin());
this.install(ExportAsJSONAction());
this.install(ImportFromJSONAction());
this.install(this.plugins.FormActions());
this.install(this.plugins.FolderView());
this.install(this.plugins.Tabs());
this.install(ImageryPlugin());
this.install(this.plugins.FlexibleLayout());
this.install(this.plugins.GoToOriginalAction());
this.install(this.plugins.OpenInNewTabAction());
this.install(this.plugins.ReloadAction());
this.install(this.plugins.WebPage());
this.install(this.plugins.Condition());
this.install(this.plugins.ConditionWidget());
this.install(this.plugins.URLTimeSettingsSynchronizer());
this.install(this.plugins.NotificationIndicator());
this.install(this.plugins.NewFolderAction());
this.install(this.plugins.ViewDatumAction());
this.install(this.plugins.ViewLargeAction());
this.install(this.plugins.ObjectInterceptors());
this.install(this.plugins.DeviceClassifier());
this.install(this.plugins.UserIndicator());
this.install(this.plugins.Gauge());
this.install(this.plugins.InspectorViews());
this.install(this.plugins.Comps());
}
/**
* Set path to where assets are hosted. This should be the path to main.js.
* @method setAssetPath
*/
setAssetPath(assetPath) {
this._assetPath = assetPath;
}
/**
* Get path to where assets are hosted.
* @method getAssetPath
*/
getAssetPath() {
const assetPathLength = this._assetPath && this._assetPath.length;
if (!assetPathLength) {
return '/';
}
if (this._assetPath[assetPathLength - 1] !== '/') {
return this._assetPath + '/';
}
return this._assetPath;
}
/**
* Start running Open MCT. This should be called only after any plugins
* have been installed.
* @fires module:openmct.MCT~start
* @method start
* @param {Element?} domElement the DOM element in which to run
* MCT; if undefined, MCT will be run in the body of the document
*/
start(domElement = document.body.firstElementChild, isHeadlessMode = false) {
// Create element to mount Layout if it doesn't exist
if (domElement === null) {
domElement = document.createElement('div');
document.body.appendChild(domElement);
}
domElement.id = 'openmct-app';
if (this.types.get('layout') === undefined) {
this.install(
this.plugins.DisplayLayout({
showAsView: ['summary-widget']
})
);
}
this.element = domElement;
if (!this.time.getClock()) {
this.time.setClock(this.defaultClock);
}
this.router.route(/^\/$/, () => {
this.router.setPath('/browse/');
});
/**
* Fired by [MCT]{@link module:openmct.MCT} when the application
* is started.
* @event start
*/
if (!isHeadlessMode) {
const appLayout = createApp(Layout);
appLayout.provide('openmct', markRaw(this));
const component = appLayout.mount(domElement);
component.$nextTick(() => {
this.layout = component;
this.app = appLayout;
this.browseRoutes = new Browse(this);
window.addEventListener('beforeunload', this.destroy);
this.router.start();
this.emit('start');
});
} else {
window.addEventListener('beforeunload', this.destroy);
this.router.start();
this.emit('start');
}
}
startHeadless() {
let unreachableNode = document.createElement('div');
return this.start(unreachableNode, true);
}
/**
* Install a plugin in MCT.
*
* @param {Function} plugin a plugin install function which will be
* invoked with the mct instance.
*/
install(plugin) {
plugin(this);
}
destroy() {
window.removeEventListener('beforeunload', this.destroy);
this.emit('destroy');
}
}
/**
* @typedef {import('../openmct.js').OpenMCTPlugin} OpenMCTPlugin
*/