docs: better docs and types for the API (#7796)

* docs: fix type imports in openmct.js

* docs: fix type imports

* docs: fix types for eventHelpers

* docs: types for TypeRegistry

* docs: types for StatusAPI

* docs: fix ObjectAPI types and docs

* docs: more types

* docs: improved types for main entry

* docs: improved types

* fix: unbreak the linting

* chore: remove EventEmitter webpack alias as it hide types

* fix: return type

* fix: parameter type

* fix: types for composables

* chore: add webpack consts to eslintrc

* fix: remove usage of deprecated timeAPI methods and add a ton of docs and types

* docs: update README.md

* lint: clean up API.md

* chore: upgrade eventemitter to v5.0.2

* refactor: update imports for EventEmitter to remove alias

* format: lint

* docs: update types for Views and ViewProviders

* docs: expose common types at the base import level

* docs(types): remove unnecessary tsconfig options

* docs: ActionAPI

* docs: AnnotationAPI

* docs: import common types from the same origin

* docs: FormsAPI & TelemetryAPI types

* docs: FormController, IndicatorAPI

* docs: MenuAPI, ActionsAPI

* docs: `@memberof` is not supported by `tsc` and JSDoc generation so remove it

* docs: RootRegistry and RootObjectProvider

* docs: Transaction + Overlay

* lint: words for the word god

* fix: review comments
This commit is contained in:
Jesse Mazzella 2024-07-31 10:46:16 -07:00 committed by GitHub
parent e3fcbe1a35
commit 4ee68cccd6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
117 changed files with 1494 additions and 1089 deletions

View File

@ -481,9 +481,20 @@
"specced",
"composables",
"countup",
"darkmatter"
"darkmatter",
"Undeletes"
],
"dictionaries": [
"npm",
"softwareTerms",
"node",
"html",
"css",
"bash",
"en_US",
"en-gb",
"misc"
],
"dictionaries": ["npm", "softwareTerms", "node", "html", "css", "bash", "en_US", "en-gb", "misc"],
"ignorePaths": [
"package.json",
"dist/**",

View File

@ -10,7 +10,12 @@ const config = {
serviceworker: true
},
globals: {
_: 'readonly'
_: 'readonly',
__webpack_public_path__: 'writeable',
__OPENMCT_VERSION__: 'readonly',
__OPENMCT_BUILD_DATE__: 'readonly',
__OPENMCT_REVISION__: 'readonly',
__OPENMCT_BUILD_BRANCH__: 'readonly'
},
plugins: ['prettier', 'unicorn', 'simple-import-sort'],
extends: [

View File

@ -70,7 +70,6 @@ const config = {
'@': path.join(projectRootDir, 'src'),
legacyRegistry: path.join(projectRootDir, 'src/legacyRegistry'),
csv: 'comma-separated-values',
EventEmitter: 'eventemitter3',
bourbon: 'bourbon.scss',
'plotly-basic': 'plotly.js-basic-dist-min',
'plotly-gl2d': 'plotly.js-gl2d-dist-min',

33
API.md
View File

@ -381,6 +381,7 @@ openmct.composition.addProvider({
The `addProvider` function accepts a Composition Provider object as its sole
argument. A Composition Provider is a javascript object exposing two functions:
- `appliesTo`: A `function` that accepts a `domainObject` argument, and returns
a `boolean` value indicating whether this composition provider applies to the
given object.
@ -621,6 +622,7 @@ Open MCT on its own defines a handful of built-in formats:
###### **Number Format (default):**
Applied to data with `format: 'number'`
```js
valueMetadata = {
format: 'number'
@ -635,15 +637,18 @@ interface NumberFormatter extends Formatter {
validate: (value: any) => boolean;
}
```
###### **String Format**:
###### **String Format**
Applied to data with `format: 'string'`
```js
valueMetadata = {
format: 'string'
// ...
};
```
```ts
interface StringFormatter extends Formatter {
parse: (value: any) => string;
@ -652,8 +657,10 @@ interface StringFormatter extends Formatter {
}
```
###### **Enum Format**:
###### **Enum Format**
Applied to data with `format: 'enum'`
```js
valueMetadata = {
format: 'enum',
@ -676,6 +683,7 @@ valueMetadata = {
Creates a two-way mapping between enum string and value to be used in the `parse` and `format` methods.
Ex:
- `formatter.parse('APPLE') === 1;`
- `formatter.format(1) === 'APPLE';`
@ -691,7 +699,6 @@ interface EnumFormatter extends Formatter {
Formats implement the following interface (provided here as TypeScript for simplicity):
Formats are registered with the Telemetry API using the `addFormat` function. eg.
```javascript
@ -841,10 +848,9 @@ Setting the active time system will trigger a [`'timeSystemChanged'`](#time-even
event. If you supplied bounds, a [`'boundsChanged'`](#time-events) event will be triggered afterwards with your newly supplied bounds.
> ⚠️ **Deprecated**
>
> - The method `timeSystem()` is deprecated. Please use `getTimeSystem()` and `setTimeSystem()` as a replacement.
#### Time Bounds
The TimeAPI provides a getter and setter for querying and setting time bounds. Time
@ -875,6 +881,7 @@ To respond to bounds change events, listen for the [`'boundsChanged'`](#time-eve
event.
> ⚠️ **Deprecated**
>
> - The method `bounds()` is deprecated and will be removed in a future release. Please use `getBounds()` and `setBounds()` as a replacement.
### Clocks
@ -972,6 +979,7 @@ openmct.time.getClock();
```
> ⚠️ **Deprecated**
>
> - The method `clock()` is deprecated and will be removed in a future release. Please use `getClock()` and `setClock()` as a replacement.
#### ⚠️ [DEPRECATED] Stopping an active clock
@ -986,6 +994,7 @@ openmct.time.stopClock();
```
> ⚠️ **Deprecated**
>
> - The method `stopClock()` is deprecated and will be removed in a future release.
#### Clock Offsets
@ -1026,6 +1035,7 @@ new bounds will be calculated based on the `currentValue()` of the active clock.
Clock offsets are only relevant when in Real-time [mode](#time-modes).
> ⚠️ **Deprecated**
>
> - The method `clockOffsets()` is deprecated and will be removed in a future release. Please use `getClockOffsets()` and `setClockOffsets()` as a replacement.
### Time Modes
@ -1120,6 +1130,7 @@ The events emitted by the Time API are:
- `mode`: A string representation of the current time mode, either `'realtime'` or `'fixed'`.
> ⚠️ **Deprecated Events** (These will be removed in a future release):
>
> - `bounds``boundsChanged`
> - `timeSystem``timeSystemChanged`
> - `clock``clockChanged`
@ -1262,7 +1273,7 @@ Returns the currently set text as a `string`.
[the built-in glyphs](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home/glyphs?view=styleguide.glyphs)
may be used here, or a custom CSS class can be provided. Returns the currently defined CSS
class as a `string`.
- `.statusClass([className])`: Gets or sets the CSS class used to determine status. Accepts an __optional__
- `.statusClass([className])`: Gets or sets the CSS class used to determine status. Accepts an **optional**
`string` parameter to be used to set a status class applied to the indicator. May be used to apply
different colors to indicate status.
@ -1335,10 +1346,10 @@ Heres the signature for the show function:
`show(element, isEditing, viewOptions)`
* `element` (HTMLElement) - The DOM element where the view should be rendered.
* `isEditing` (boolean) - Indicates whether the view is in editing mode.
* `viewOptions` (Object) - An object with configuration options for the view, including:
* `renderWhenVisible` (Function) - This function wraps the `requestAnimationFrame` and only triggers the provided render logic when the view is visible in the viewport.
- `element` (HTMLElement) - The DOM element where the view should be rendered.
- `isEditing` (boolean) - Indicates whether the view is in editing mode.
- `viewOptions` (Object) - An object with configuration options for the view, including:
- `renderWhenVisible` (Function) - This function wraps the `requestAnimationFrame` and only triggers the provided render logic when the view is visible in the viewport.
### Example
@ -1367,8 +1378,6 @@ const myViewProvider = {
};
```
Note that `renderWhenVisible` defers rendering while the view is not visible and caters to the latest execution call. This provides responsiveness for dynamic content while ensuring performance optimizations.
Ensure your view logic is prepared to handle potentially multiple deferrals if using this API, as only the last call to renderWhenVisible will be queued for execution upon the view becoming visible.

View File

@ -5,12 +5,10 @@ Open MCT (Open Mission Control Technologies) is a next-generation mission contro
> [!NOTE]
> Please visit our [Official Site](https://nasa.github.io/openmct/) and [Getting Started Guide](https://nasa.github.io/openmct/getting-started/)
Once you've created something amazing with Open MCT, showcase your work in our GitHub Discussions [Show and Tell](https://github.com/nasa/openmct/discussions/categories/show-and-tell) section. We love seeing unique and wonderful implementations of Open MCT!
![Screen Shot 2022-11-23 at 9 51 36 AM](https://user-images.githubusercontent.com/4215777/203617422-4d912bfc-766f-4074-8324-409d9bbe7c05.png)
## Building and Running Open MCT Locally
Building and running Open MCT in your local dev environment is very easy. Be sure you have [Git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/) installed, then follow the directions below. Need additional information? Check out the [Getting Started](https://nasa.github.io/openmct/getting-started/) page on our website.
@ -18,19 +16,19 @@ Building and running Open MCT in your local dev environment is very easy. Be sur
1. Clone the source code:
```
```sh
git clone https://github.com/nasa/openmct.git
```
2. (Optional) Install the correct node version using [nvm](https://github.com/nvm-sh/nvm):
```
```sh
nvm install
```
3. Install development dependencies (Note: Check the `package.json` engine for our tested and supported node versions):
```
```sh
npm install
```
@ -68,11 +66,11 @@ For more on developing with Open MCT, see our documentation for a guide on [Deve
## Compatibility
This is a fast moving project and we do our best to test and support the widest possible range of browsers, operating systems, and nodejs APIs. We have a published list of support available in our package.json's `browserslist` key.
This is a fast moving project and we do our best to test and support the widest possible range of browsers, operating systems, and NodeJS APIs. We have a published list of support available in our package.json's `browserslist` key.
The project uses `nvm` to ensure the node and npm version used, is coherent in all projects. Install nvm (non-windows), [here](https://github.com/nvm-sh/nvm) or the windows equivalent [here](https://github.com/coreybutler/nvm-windows)
The project utilizes `nvm` to maintain consistent node and npm versions across all projects. For UNIX, MacOS, Windows WSL, and other POSIX-compliant shell environments, click [here](https://github.com/nvm-sh/nvm). For Windows, check out [nvm-windows](https://github.com/coreybutler/nvm-windows).
If you encounter an issue with a particular browser, OS, or nodejs API, please file a [GitHub issue](https://github.com/nasa/openmct/issues/new/choose)
If you encounter an issue with a particular browser, OS, or NodeJS API, please [file an issue](https://github.com/nasa/openmct/issues/new/choose).
## Plugins
@ -90,6 +88,7 @@ For information on writing plugins, please see [our API documentation](./API.md#
Our automated test coverage comes in the form of unit, e2e, visual, performance, and security tests.
### Unit Tests
Unit Tests are written for [Jasmine](https://jasmine.github.io/api/edge/global)
and run by [Karma](http://karma-runner.github.io). To run:
@ -101,24 +100,34 @@ in the `src` hierarchy. Full configuration details are found in
alongside the units that they test; for example, `src/foo/Bar.js` would be
tested by `src/foo/BarSpec.js`.
### e2e, Visual, and Performance tests
The e2e, Visual, and Performance tests are written for playwright and run by playwright's new test runner [@playwright/test](https://playwright.dev/).
### e2e, Visual, and Performance Testing
To run the e2e tests which are part of every commit:
Our e2e (end-to-end), Visual, and Performance tests leverage the Playwright framework and are executed using Playwright's test runner, [@playwright/test](https://playwright.dev/).
`npm run test:e2e:stable`
#### How to Run Tests
To run the visual test suite:
- **e2e Tests**: These tests are run on every commit. To run the tests locally, use:
`npm run test:e2e:visual`
```sh
npm run test:e2e:stable
```
To run the performance tests:
- **Visual Tests**: For running the visual test suite, use:
`npm run test:perf`
```sh
npm run test:e2e:visual
```
The test suite is configured to all tests located in `e2e/tests/` ending in `*.e2e.spec.js`. For more about the e2e test suite, please see the [README](./e2e/README.md)
- **Performance Tests**: To initiate the performance tests, enter:
```sh
npm run test:perf
```
All tests are located within the `e2e/tests/` directory and are identified by the `*.e2e.spec.js` filename pattern. For more information about the e2e test suite, refer to the [README](./e2e/README.md).
### Security Tests
Each commit is analyzed for known security vulnerabilities using [CodeQL](https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-javascript/). The list of CWE coverage items is available in the [CodeQL docs](https://codeql.github.com/codeql-query-help/javascript-cwe/). The CodeQL workflow is specified in the [CodeQL analysis file](./.github/workflows/codeql-analysis.yml) and the custom [CodeQL config](./.github/codeql/codeql-config.yml).
### Test Reporting and Code Coverage
@ -129,60 +138,41 @@ Our code coverage is generated during the runtime of our unit, e2e, and visual t
For more on the specifics of our code coverage setup, [see](TESTING.md#code-coverage)
# Glossary
## Glossary
Certain terms are used throughout Open MCT with consistent meanings
or conventions. Any deviations from the below are issues and should be
addressed (either by updating this glossary or changing code to reflect
correct usage.) Other developer documentation, particularly in-line
documentation, may presume an understanding of these terms.
* _plugin_: A plugin is a removable, reusable grouping of software elements.
The application is composed of plugins.
* _composition_: In the context of a domain object, this refers to the set of
other domain objects that compose or are contained by that object. A domain
object's composition is the set of domain objects that should appear
immediately beneath it in a tree hierarchy. A domain object's composition is
described in its model as an array of id's; its composition capability
provides a means to retrieve the actual domain object instances associated
with these identifiers asynchronously.
* _description_: When used as an object property, this refers to the human-readable
description of a thing; usually a single sentence or short paragraph.
(Most often used in the context of extensions, domain
object models, or other similar application-specific objects.)
* _domain object_: A meaningful object to the user; a distinct thing in
the work support by Open MCT. Anything that appears in the left-hand
tree is a domain object.
* _identifier_: A tuple consisting of a namespace and a key, which together uniquely
identifies a domain object.
* _model_: The persistent state associated with a domain object. A domain
object's model is a JavaScript object which can be converted to JSON
without losing information (that is, it contains no methods.)
* _name_: When used as an object property, this refers to the human-readable
name for a thing. (Most often used in the context of extensions, domain
object models, or other similar application-specific objects.)
* _navigation_: Refers to the current state of the application with respect
to the user's expressed interest in a specific domain object; e.g. when
a user clicks on a domain object in the tree, they are _navigating_ to
it, and it is thereafter considered the _navigated_ object (until the
user makes another such choice.)
* _namespace_: A name used to identify a persistence store. A running open MCT
application could potentially use multiple persistence stores, with the
| Term | Definition |
|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| _plugin_ | A removable, reusable grouping of software elements. The application is composed of plugins. |
| _composition_ | In the context of a domain object, this term refers to the set of other domain objects that compose or are contained by that object. A domain object's composition is the set of domain objects that should appear immediately beneath it in a tree hierarchy. It is described in its model as an array of ids, providing a means to asynchronously retrieve the actual domain object instances associated with these identifiers. |
| _description_ | When used as an object property, this term refers to the human-readable description of a thing, usually a single sentence or short paragraph. It is most often used in the context of extensions, domain object models, or other similar application-specific objects. |
| _domain object_ | A meaningful object to the user and a distinct thing in the work supported by Open MCT. Anything that appears in the left-hand tree is a domain object. |
| _identifier_ | A tuple consisting of a namespace and a key, which together uniquely identifies a domain object. |
| _model_ | The persistent state associated with a domain object. A domain object's model is a JavaScript object that can be converted to JSON without losing information, meaning it contains no methods. |
| _name_ | When used as an object property, this term refers to the human-readable name for a thing. It is most often used in the context of extensions, domain object models, or other similar application-specific objects. |
| _navigation_ | This term refers to the current state of the application with respect to the user's expressed interest in a specific domain object. For example, when a user clicks on a domain object in the tree, they are navigating to it, and it is thereafter considered the navigated object until the user makes another such choice. |
| _namespace_ | A name used to identify a persistence store. A running Open MCT application could potentially use multiple persistence stores. |
## Open MCT v2.0.0
Support for our legacy bundle-based API, and the libraries that it was built on (like Angular 1.x), have now been removed entirely from this repository.
For now if you have an Open MCT application that makes use of the legacy API, [a plugin](https://github.com/nasa/openmct-legacy-plugin) is provided that bootstraps the legacy bundling mechanism and API. This plugin will not be maintained over the long term however, and the legacy support plugin will not be tested for compatibility with future versions of Open MCT. It is provided for convenience only.
### How do I know if I am using legacy API?
You might still be using legacy API if your source code
* Contains files named bundle.js, or bundle.json,
* Makes calls to `openmct.$injector()`, or `openmct.$angular`,
* Makes calls to `openmct.legacyRegistry`, `openmct.legacyExtension`, or `openmct.legacyBundle`.
- Contains files named bundle.js, or bundle.json,
- Makes calls to `openmct.$injector()`, or `openmct.$angular`,
- Makes calls to `openmct.legacyRegistry`, `openmct.legacyExtension`, or `openmct.legacyBundle`.
### What should I do if I am using legacy API?
Please refer to [the modern Open MCT API](https://nasa.github.io/openmct/documentation/). Post any questions to the [Discussions section](https://github.com/nasa/openmct/discussions) of the Open MCT GitHub repository.
## Related Repos

View File

@ -15,12 +15,12 @@
## Sections
* The [API](api/) uses inline documentation
* The [API](api/) uses inline documentation.
using [TypeScript](https://www.typescriptlang.org) and some legacy [JSDoc](https://jsdoc.app/). It describes the JavaScript objects and
functions that make up the software platform.
* The [Development Process](process/) document describes the
* The [Development Process](process/) document describes the
Open MCT software development cycle.
* The [Tutorials](https://github.com/nasa/openmct-tutorial) give examples of extending the platform to add
functionality, and integrate with data sources.
* The [tutorial](https://github.com/nasa/openmct-tutorial) and [plugin template](https://github.com/nasa/openmct-hello) give examples of extending the platform to add
functionality and integrate with data sources.

View File

@ -35,7 +35,7 @@
* @property {string} type the type of domain object to create (e.g.: "Sine Wave Generator").
* @property {string} [name] the desired name of the created domain object.
* @property {string | import('../src/api/objects/ObjectAPI').Identifier} [parent] the Identifier or uuid of the parent object.
* @property {Object<string, string>} [customParameters] any additional parameters to be passed to the domain object's form. E.g. '[aria-label="Data Rate (hz)"]': {'0.1'}
* @property {Record<string, string>} [customParameters] any additional parameters to be passed to the domain object's form. E.g. '[aria-label="Data Rate (hz)"]': {'0.1'}
*/
/**

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { v4 as uuid } from 'uuid';
import createExampleUser from './exampleUserCreator.js';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
export default class SinewaveLimitProvider extends EventEmitter {
#openmct;

View File

@ -22,13 +22,38 @@
const matcher = /\/openmct.js$/;
if (document.currentScript) {
// @ts-ignore
let src = document.currentScript.src;
if (src && matcher.test(src)) {
// eslint-disable-next-line no-undef
// @ts-ignore
__webpack_public_path__ = src.replace(matcher, '') + '/';
}
}
import { MCT } from './src/MCT.js';
const openmct = new MCT();
export default openmct;
/**
* @typedef {MCT} OpenMCT
* @typedef {import('./src/api/objects/ObjectAPI.js').DomainObject} DomainObject
* @typedef {import('./src/api/objects/ObjectAPI.js').Identifier} Identifier
* @typedef {import('./src/api/objects/Transaction.js').default} Transaction
* @typedef {import('./src/api/actions/ActionsAPI.js').Action} Action
* @typedef {import('./src/api/actions/ActionCollection.js').default} ActionCollection
* @typedef {import('./src/api/composition/CompositionCollection.js').default} CompositionCollection
* @typedef {import('./src/api/composition/CompositionProvider.js').default} CompositionProvider
* @typedef {import('./src/ui/registries/ViewRegistry.js').ViewProvider} ViewProvider
* @typedef {import('./src/ui/registries/ViewRegistry.js').View} View
*
* @typedef {DomainObject[]} ObjectPath
* @typedef {(...args: any[]) => (openmct: OpenMCT) => void} OpenMCTPlugin
* An OpenMCT Plugin returns a function that receives an instance of
* the OpenMCT API and uses it to install itself.
*/
/**
* @typedef {Object} BuildInfo
* @property {string} version
@ -36,46 +61,3 @@ if (document.currentScript) {
* @property {string} revision
* @property {string} branch
*/
/**
* @typedef {Object} OpenMCT
* @property {BuildInfo} buildInfo
* @property {import('./src/selection/Selection').default} selection
* @property {import('./src/api/time/TimeAPI').default} time
* @property {import('./src/api/composition/CompositionAPI').default} composition
* @property {import('./src/ui/registries/ViewRegistry').default} objectViews
* @property {import('./src/ui/registries/InspectorViewRegistry').default} inspectorViews
* @property {import('./src/ui/registries/ViewRegistry').default} propertyEditors
* @property {import('./src/ui/registries/ToolbarRegistry').default} toolbars
* @property {import('./src/api/types/TypeRegistry').default} types
* @property {import('./src/api/objects/ObjectAPI').default} objects
* @property {import('./src/api/telemetry/TelemetryAPI').default} telemetry
* @property {import('./src/api/indicators/IndicatorAPI').default} indicators
* @property {import('./src/api/user/UserAPI').default} user
* @property {import('./src/api/notifications/NotificationAPI').default} notifications
* @property {import('./src/api/Editor').default} editor
* @property {import('./src/api/overlays/OverlayAPI')} overlays
* @property {import('./src/api/tooltips/ToolTipAPI')} tooltips
* @property {import('./src/api/menu/MenuAPI').default} menus
* @property {import('./src/api/actions/ActionsAPI').default} actions
* @property {import('./src/api/status/StatusAPI').default} status
* @property {import('./src/api/priority/PriorityAPI').default} priority
* @property {import('./src/ui/router/ApplicationRouter')} router
* @property {import('./src/api/faultmanagement/FaultManagementAPI').default} faults
* @property {import('./src/api/forms/FormsAPI').default} forms
* @property {import('./src/api/Branding').default} branding
* @property {import('./src/api/annotation/AnnotationAPI').default} annotation
* @property {{(plugin: OpenMCTPlugin) => void}} install
* @property {{() => string}} getAssetPath
* @property {{(assetPath: string) => void}} setAssetPath
* @property {{(domElement: HTMLElement, isHeadlessMode: boolean) => void}} start
* @property {{() => void}} startHeadless
* @property {{() => void}} destroy
* @property {OpenMCTPlugin[]} plugins
* @property {OpenMCTComponent[]} components
*/
import { MCT } from './src/MCT.js';
/** @type {OpenMCT} */
const openmct = new MCT();
export default openmct;

View File

@ -19,8 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/* eslint-disable no-undef */
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { createApp, markRaw } from 'vue';
import ActionsAPI from './api/actions/ActionsAPI.js';
@ -73,10 +72,25 @@ import Browse from './ui/router/Browse.js';
* The Open MCT application. This may be configured by installing plugins
* or registering extensions before the application is started.
* @constructor
* @memberof module:openmct
* @extends EventEmitter
*/
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();
@ -89,21 +103,11 @@ export class MCT extends EventEmitter {
this.destroy = this.destroy.bind(this);
this.defaultClock = 'local';
this.plugins = plugins;
/**
* Tracks current selection state of the application.
* @private
*/
this.selection = new Selection(this);
/**
* MCT's time conductor, which may be used to synchronize view contents
* for telemetry- or time-based views.
* @type {module:openmct.TimeConductor}
* @memberof module:openmct.MCT#
* @name conductor
* @type {TimeAPI}
*/
this.time = new TimeAPI(this);
@ -116,9 +120,7 @@ export class MCT extends EventEmitter {
* `composition` may be called as a function, in which case it acts
* as [`composition.get`]{@link module:openmct.CompositionAPI#get}.
*
* @type {module:openmct.CompositionAPI}
* @memberof module:openmct.MCT#
* @name composition
* @type {CompositionAPI}
*/
this.composition = new CompositionAPI(this);
@ -126,9 +128,7 @@ export class MCT extends EventEmitter {
* Registry for views of domain objects which should appear in the
* main viewing area.
*
* @type {module:openmct.ViewRegistry}
* @memberof module:openmct.MCT#
* @name objectViews
* @type {ViewRegistry}
*/
this.objectViews = new ViewRegistry();
@ -136,9 +136,7 @@ export class MCT extends EventEmitter {
* Registry for views which should appear in the Inspector area.
* These views will be chosen based on the selection state.
*
* @type {module:openmct.InspectorViewRegistry}
* @memberof module:openmct.MCT#
* @name inspectorViews
* @type {InspectorViewRegistry}
*/
this.inspectorViews = new InspectorViewRegistry();
@ -147,9 +145,7 @@ export class MCT extends EventEmitter {
* dialogs, and similar user interface elements used for
* modifying domain objects external to its regular views.
*
* @type {module:openmct.ViewRegistry}
* @memberof module:openmct.MCT#
* @name propertyEditors
* @type {ViewRegistry}
*/
this.propertyEditors = new ViewRegistry();
@ -157,9 +153,7 @@ export class MCT extends EventEmitter {
* Registry for views which should appear in the toolbar area while
* editing. These views will be chosen based on the selection state.
*
* @type {module:openmct.ToolbarRegistry}
* @memberof module:openmct.MCT#
* @name toolbars
* @type {ToolbarRegistry}
*/
this.toolbars = new ToolbarRegistry();
@ -167,9 +161,7 @@ export class MCT extends EventEmitter {
* Registry for domain object types which may exist within this
* instance of Open MCT.
*
* @type {module:openmct.TypeRegistry}
* @memberof module:openmct.MCT#
* @name types
* @type {TypeRegistry}
*/
this.types = new TypeRegistry();
@ -177,9 +169,7 @@ export class MCT extends EventEmitter {
* An interface for interacting with domain objects and the domain
* object hierarchy.
*
* @type {module:openmct.ObjectAPI}
* @memberof module:openmct.MCT#
* @name objects
* @type {ObjectAPI}
*/
this.objects = new ObjectAPI(this.types, this);
@ -187,49 +177,100 @@ export class MCT extends EventEmitter {
* An interface for retrieving and interpreting telemetry data associated
* with a domain object.
*
* @type {module:openmct.TelemetryAPI}
* @memberof module:openmct.MCT#
* @name telemetry
* @type {TelemetryAPI}
*/
this.telemetry = new TelemetryAPI(this);
/**
* An interface for creating new indicators and changing them dynamically.
*
* @type {module:openmct.IndicatorAPI}
* @memberof module:openmct.MCT#
* @name indicators
* @type {IndicatorAPI}
*/
this.indicators = new IndicatorAPI(this);
/**
* MCT's user awareness management, to enable user and
* role specific functionality.
* @type {module:openmct.UserAPI}
* @memberof module:openmct.MCT#
* @name user
* @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 {module:openmct.AnnotationAPI}
* @memberof module:openmct.MCT#
* @name annotation
* @type {AnnotationAPI}
*/
this.annotation = new AnnotationAPI(this);
@ -268,7 +309,6 @@ export class MCT extends EventEmitter {
}
/**
* Set path to where assets are hosted. This should be the path to main.js.
* @memberof module:openmct.MCT#
* @method setAssetPath
*/
setAssetPath(assetPath) {
@ -276,7 +316,6 @@ export class MCT extends EventEmitter {
}
/**
* Get path to where assets are hosted.
* @memberof module:openmct.MCT#
* @method getAssetPath
*/
getAssetPath() {
@ -295,9 +334,8 @@ export class MCT extends EventEmitter {
* Start running Open MCT. This should be called only after any plugins
* have been installed.
* @fires module:openmct.MCT~start
* @memberof module:openmct.MCT#
* @method start
* @param {HTMLElement} [domElement] the DOM element in which to run
* @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) {
@ -330,7 +368,6 @@ export class MCT extends EventEmitter {
* Fired by [MCT]{@link module:openmct.MCT} when the application
* is started.
* @event start
* @memberof module:openmct.MCT~
*/
if (!isHeadlessMode) {
const appLayout = createApp(Layout);
@ -361,7 +398,6 @@ export class MCT extends EventEmitter {
*
* @param {Function} plugin a plugin install function which will be
* invoked with the mct instance.
* @memberof module:openmct.MCT#
*/
install(plugin) {
plugin(this);
@ -372,3 +408,7 @@ export class MCT extends EventEmitter {
this.emit('destroy');
}
}
/**
* @typedef {import('../openmct.js').OpenMCTPlugin} OpenMCTPlugin
*/

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
export default class Editor extends EventEmitter {
constructor(openmct) {

View File

@ -20,10 +20,22 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
/**
* A collection of actions applicable to a domain object.
* @extends EventEmitter
*/
class ActionCollection extends EventEmitter {
/**
* Creates an instance of ActionCollection.
* @param {Object.<string, Action>} applicableActions - The actions applicable to the domain object.
* @param {import('openmct').ObjectPath} objectPath - The path to the domain object.
* @param {import('openmct').View} view - The view displaying the domain object.
* @param {import('openmct').OpenMCT} openmct - The Open MCT API.
* @param {boolean} skipEnvironmentObservers - Whether to skip setting up environment observers.
*/
constructor(applicableActions, objectPath, view, openmct, skipEnvironmentObservers) {
super();
@ -48,6 +60,10 @@ class ActionCollection extends EventEmitter {
}
}
/**
* Disables the specified actions.
* @param {string[]} actionKeys - The keys of the actions to disable.
*/
disable(actionKeys) {
actionKeys.forEach((actionKey) => {
if (this.applicableActions[actionKey]) {
@ -57,6 +73,10 @@ class ActionCollection extends EventEmitter {
this._update();
}
/**
* Enables the specified actions.
* @param {string[]} actionKeys - The keys of the actions to enable.
*/
enable(actionKeys) {
actionKeys.forEach((actionKey) => {
if (this.applicableActions[actionKey]) {
@ -66,6 +86,10 @@ class ActionCollection extends EventEmitter {
this._update();
}
/**
* Hides the specified actions.
* @param {string[]} actionKeys - The keys of the actions to hide.
*/
hide(actionKeys) {
actionKeys.forEach((actionKey) => {
if (this.applicableActions[actionKey]) {
@ -75,6 +99,10 @@ class ActionCollection extends EventEmitter {
this._update();
}
/**
* Shows the specified actions.
* @param {string[]} actionKeys - The keys of the actions to show.
*/
show(actionKeys) {
actionKeys.forEach((actionKey) => {
if (this.applicableActions[actionKey]) {
@ -84,6 +112,9 @@ class ActionCollection extends EventEmitter {
this._update();
}
/**
* Destroys the action collection, removing all listeners and observers.
*/
destroy() {
if (!this.skipEnvironmentObservers) {
this.objectUnsubscribes.forEach((unsubscribe) => {
@ -97,6 +128,10 @@ class ActionCollection extends EventEmitter {
this.removeAllListeners();
}
/**
* Gets all visible actions.
* @returns {Action[]} An array of visible actions.
*/
getVisibleActions() {
let actionsArray = Object.keys(this.applicableActions);
let visibleActions = [];
@ -112,6 +147,10 @@ class ActionCollection extends EventEmitter {
return visibleActions;
}
/**
* Gets all actions that should be shown in the status bar.
* @returns {Action[]} An array of status bar actions.
*/
getStatusBarActions() {
let actionsArray = Object.keys(this.applicableActions);
let statusBarActions = [];
@ -127,17 +166,34 @@ class ActionCollection extends EventEmitter {
return statusBarActions;
}
/**
* Gets the object containing all applicable actions.
* @returns {Object.<string, Action>} The object of applicable actions.
*/
getActionsObject() {
return this.applicableActions;
}
/**
* Emits an update event with the current applicable actions.
* @private
*/
_update() {
this.emit('update', this.applicableActions);
}
/**
* Sets up observers for the object path.
* @private
*/
_observeObjectPath() {
let actionCollection = this;
/**
* Updates an object with new properties.
* @param {Object} oldObject - The object to update.
* @param {Object} newObject - The object containing new properties.
*/
function updateObject(oldObject, newObject) {
Object.assign(oldObject, newObject);
@ -157,6 +213,10 @@ class ActionCollection extends EventEmitter {
});
}
/**
* Updates the applicable actions.
* @private
*/
_updateActions() {
let newApplicableActions = this.openmct.actions._applicableActions(this.objectPath, this.view);
@ -167,6 +227,13 @@ class ActionCollection extends EventEmitter {
this._update();
}
/**
* Merges old and new actions, preserving existing action states.
* @param {Object.<string, Action>} oldActions - The existing actions.
* @param {Object.<string, Action>} newActions - The new actions.
* @returns {Object.<string, Action>} The merged actions.
* @private
*/
_mergeOldAndNewActions(oldActions, newActions) {
let mergedActions = {};
Object.keys(newActions).forEach((key) => {
@ -182,3 +249,7 @@ class ActionCollection extends EventEmitter {
}
export default ActionCollection;
/**
* @typedef {import('openmct').Action} Action
*/

View File

@ -19,19 +19,30 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import ActionCollection from './ActionCollection.js';
/**
* The ActionsAPI manages the registration and retrieval of actions in Open MCT.
* @extends EventEmitter
*/
class ActionsAPI extends EventEmitter {
/**
* @param {import('openmct').OpenMCT} openmct - The Open MCT instance
*/
constructor(openmct) {
super();
/** @type {Object<string, Action>} */
this._allActions = {};
/** @type {WeakMap<Object, ActionCollection>} */
this._actionCollections = new WeakMap();
/** @type {import('openmct').OpenMCT} */
this._openmct = openmct;
/** @type {string[]} */
this._groupOrder = ['windowing', 'undefined', 'view', 'action', 'export', 'import'];
this.register = this.register.bind(this);
@ -40,14 +51,29 @@ class ActionsAPI extends EventEmitter {
this._updateCachedActionCollections = this._updateCachedActionCollections.bind(this);
}
/**
* Register an action with the API.
* @param {Action} actionDefinition - The definition of the action to register
*/
register(actionDefinition) {
this._allActions[actionDefinition.key] = actionDefinition;
}
/**
* Get an action by its key.
* @param {string} key - The key of the action to retrieve
* @returns {Action|undefined} The action definition, or undefined if not found
*/
getAction(key) {
return this._allActions[key];
}
/**
* Get or create an ActionCollection for a given object path and view.
* @param {import('openmct').ObjectPath} objectPath - The path of the object
* @param {import('openmct').View} [view] - The view object
* @returns {ActionCollection} The ActionCollection for the given object path and view
*/
getActionsCollection(objectPath, view) {
if (view) {
return (
@ -59,14 +85,31 @@ class ActionsAPI extends EventEmitter {
}
}
/**
* Update the order in which action groups are displayed.
* @param {string[]} groupArray - An array of group names in the desired order
*/
updateGroupOrder(groupArray) {
this._groupOrder = groupArray;
}
/**
* Get a cached ActionCollection for a given view.
* @param {import('openmct').ObjectPath} objectPath - The path of the object
* @param {Object} view - The view object
* @returns {ActionCollection|undefined} The cached ActionCollection, or undefined if not found
*/
_getCachedActionCollection(objectPath, view) {
return this._actionCollections.get(view);
}
/**
* Create a new ActionCollection.
* @param {import('openmct').ObjectPath} objectPath - The path of the object
* @param {import('openmct').View} [view] - The view object
* @param {boolean} skipEnvironmentObservers - Whether to skip environment observers
* @returns {ActionCollection} The new ActionCollection
*/
_newActionCollection(objectPath, view, skipEnvironmentObservers) {
let applicableActions = this._applicableActions(objectPath, view);
@ -84,20 +127,35 @@ class ActionsAPI extends EventEmitter {
return actionCollection;
}
/**
* Cache an ActionCollection for a given view.
* @param {import('openmct').View} view - The view object
* @param {ActionCollection} actionCollection - The ActionCollection to cache
*/
_cacheActionCollection(view, actionCollection) {
this._actionCollections.set(view, actionCollection);
actionCollection.on('destroy', this._updateCachedActionCollections);
}
_updateCachedActionCollections(key) {
if (this._actionCollections.has(key)) {
let actionCollection = this._actionCollections.get(key);
/**
* Update cached ActionCollections when destroyed.
* @param {import('openmct').View} view - The key (View object)of the destroyed ActionCollection
*/
_updateCachedActionCollections(view) {
if (this._actionCollections.has(view)) {
let actionCollection = this._actionCollections.get(view);
actionCollection.off('destroy', this._updateCachedActionCollections);
delete actionCollection.applicableActions;
this._actionCollections.delete(key);
this._actionCollections.delete(view);
}
}
/**
* Get applicable actions for a given object path and view.
* @param {import('openmct').ObjectPath} objectPath - The path of the object
* @param {import('openmct').View} [view] - The view object
* @returns {Object<string, Action>} A dictionary of applicable actions keyed by action key
*/
_applicableActions(objectPath, view) {
let actionsObject = {};
@ -120,6 +178,11 @@ class ActionsAPI extends EventEmitter {
return actionsObject;
}
/**
* Group and sort actions based on their group and priority.
* @param {Action[]|Object<string, Action>} actionsArray - An array or object of actions to group and sort
* @returns {Action[][]} An array of grouped and sorted action arrays
*/
_groupAndSortActions(actionsArray = []) {
if (!Array.isArray(actionsArray) && typeof actionsArray === 'object') {
actionsArray = Object.keys(actionsArray).map((key) => actionsArray[key]);
@ -153,3 +216,19 @@ class ActionsAPI extends EventEmitter {
}
export default ActionsAPI;
/**
* @typedef {Object} Action
* @property {string} name - The display name of the action.
* @property {string} key - A unique identifier for the action.
* @property {string} description - A brief description of what the action does.
* @property {string} cssClass - The CSS class for the action's icon.
* @property {string} [group] - The group this action belongs to (e.g., 'action', 'import').
* @property {number} [priority] - The priority of the action within its group (controls the order of the actions in the menu).
* @property {boolean} [isHidden] - Whether the action should be hidden from menus.
* @property {(objectPath: ObjectPath, view: View) => void} invoke - Executes the action.
* @property {(objectPath: ObjectPath, view: View) => boolean} appliesTo - Determines if the action is applicable to the given object path.
*/
/** @typedef {import('openmct').ObjectPath} ObjectPath */
/** @typedef {import('openmct').View} View */

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import { v4 as uuid } from 'uuid';
@ -41,8 +41,14 @@ const ANNOTATION_TYPES = Object.freeze({
PLOT_SPATIAL: 'PLOT_SPATIAL'
});
/**
* @type {string}
*/
const ANNOTATION_TYPE = 'annotation';
/**
* @type {string}
*/
const ANNOTATION_LAST_CREATED = 'annotationLastCreated';
/**
@ -53,15 +59,15 @@ const ANNOTATION_LAST_CREATED = 'annotationLastCreated';
*/
/**
* @typedef {import('../objects/ObjectAPI').DomainObject} DomainObject
* @typedef {import('openmct').DomainObject} DomainObject
*/
/**
* @typedef {import('../objects/ObjectAPI').Identifier} Identifier
* @typedef {import('openmct').Identifier} Identifier
*/
/**
* @typedef {import('../../../openmct').OpenMCT} OpenMCT
* @typedef {import('openmct').OpenMCT} OpenMCT
*/
/**
@ -73,7 +79,8 @@ const ANNOTATION_LAST_CREATED = 'annotationLastCreated';
* about rationals behind why the robot has taken a certain path.
* Annotations are discoverable using search, and are typically rendered in OpenMCT views to bring attention
* to other users.
* @constructor
* @class AnnotationAPI
* @extends {EventEmitter}
*/
export default class AnnotationAPI extends EventEmitter {
/** @type {Map<ANNOTATION_TYPES, Array<(a, b) => boolean >>} */
@ -120,10 +127,9 @@ export default class AnnotationAPI extends EventEmitter {
* @property {Array<Object>} targets The targets ID keystrings and their specific properties.
* For plots, this will be a bounding box, e.g.: {keyString: "d8385009-789d-457b-acc7-d50ba2fd55ea", maxY: 100, minY: 0, maxX: 100, minX: 0}
* For notebooks, this will be an entry ID, e.g.: {entryId: "entry-ecb158f5-d23c-45e1-a704-649b382622ba"}
* @property {DomainObject>[]} targetDomainObjects the domain objects this annotation points to (e.g., telemetry objects for a plot)
* @property {DomainObject[]} targetDomainObjects the domain objects this annotation points to (e.g., telemetry objects for a plot)
*/
/**
* @method create
* @param {CreateAnnotationOptions} options
* @returns {Promise<DomainObject>} a promise which will resolve when the domain object
* has been created, or be rejected if it cannot be saved
@ -195,6 +201,10 @@ export default class AnnotationAPI extends EventEmitter {
}
}
/**
* Updates the annotation modified timestamp for a target domain object
* @param {DomainObject} targetDomainObject The target domain object to update
*/
#updateAnnotationModified(targetDomainObject) {
// As certain telemetry objects are immutable, we'll need to check here first
// to see if we can add the annotation last created property.
@ -207,8 +217,8 @@ export default class AnnotationAPI extends EventEmitter {
}
/**
* @method defineTag
* @param {string} key a unique identifier for the tag
* Defines a new tag
* @param {string} tagKey a unique identifier for the tag
* @param {Tag} tagsDefinition the definition of the tag to add
*/
defineTag(tagKey, tagsDefinition) {
@ -216,7 +226,7 @@ export default class AnnotationAPI extends EventEmitter {
}
/**
* @method setNamespaceToSaveAnnotations
* Sets the namespace to save new annotations to
* @param {string} namespace the namespace to save new annotations to
*/
setNamespaceToSaveAnnotations(namespace) {
@ -224,7 +234,7 @@ export default class AnnotationAPI extends EventEmitter {
}
/**
* @method isAnnotation
* Checks if a domain object is an annotation
* @param {DomainObject} domainObject the domainObject in question
* @returns {boolean} Returns true if the domain object is an annotation
*/
@ -233,7 +243,7 @@ export default class AnnotationAPI extends EventEmitter {
}
/**
* @method getAvailableTags
* Gets the available tags that have been loaded
* @returns {Tag[]} Returns an array of the available tags that have been loaded
*/
getAvailableTags() {
@ -252,10 +262,10 @@ export default class AnnotationAPI extends EventEmitter {
}
/**
* @method getAnnotations
* Gets annotations for a given domain object identifier
* @param {Identifier} domainObjectIdentifier - The domain object identifier to use to search for annotations. For example, a telemetry object identifier.
* @param {AbortSignal} abortSignal - An abort signal to cancel the search
* @returns {DomainObject[]} Returns an array of annotations that match the search query
* @param {AbortSignal} [abortSignal] - An abort signal to cancel the search
* @returns {Promise<DomainObject[]>} Returns a promise that resolves to an array of annotations that match the search query
*/
async getAnnotations(domainObjectIdentifier, abortSignal = null) {
const keyStringQuery = this.openmct.objects.makeKeyString(domainObjectIdentifier);
@ -273,8 +283,8 @@ export default class AnnotationAPI extends EventEmitter {
}
/**
* @method deleteAnnotations
* @param {DomainObject[]} existingAnnotation - An array of annotations to delete (set _deleted to true)
* Deletes (marks as deleted) the given annotations
* @param {DomainObject[]} annotations - An array of annotations to delete (set _deleted to true)
*/
deleteAnnotations(annotations) {
if (!annotations) {
@ -289,7 +299,7 @@ export default class AnnotationAPI extends EventEmitter {
}
/**
* @method deleteAnnotations
* Undeletes (marks as not deleted) the given annotation
* @param {DomainObject} annotation - An annotation to undelete (set _deleted to false)
*/
unDeleteAnnotation(annotation) {
@ -300,6 +310,12 @@ export default class AnnotationAPI extends EventEmitter {
this.openmct.objects.mutate(annotation, '_deleted', false);
}
/**
* Gets tags from the given annotations
* @param {DomainObject[]} annotations - The annotations to get tags from
* @param {boolean} [filterDuplicates=true] - Whether to filter out duplicate tags
* @returns {Tag[]} An array of tags from the given annotations
*/
getTagsFromAnnotations(annotations, filterDuplicates = true) {
if (!annotations) {
return [];
@ -324,6 +340,11 @@ export default class AnnotationAPI extends EventEmitter {
return fullTagModels;
}
/**
* Adds meta information to the given tags
* @param {string[]} tags - The tags to add meta information to
* @returns {Tag[]} An array of tags with meta information added
*/
#addTagMetaInformationToTags(tags) {
// Convert to Set and back to Array to remove duplicates
const uniqueTags = [...new Set(tags)];
@ -336,6 +357,11 @@ export default class AnnotationAPI extends EventEmitter {
});
}
/**
* Gets tags that match the given query
* @param {string} query - The query to match tags against
* @returns {string[]} An array of tag keys that match the query
*/
#getMatchingTags(query) {
if (!query) {
return [];
@ -352,6 +378,88 @@ export default class AnnotationAPI extends EventEmitter {
return matchingTags;
}
/**
* @typedef {Object} AnnotationTarget
* @property {string} keyString - The key string of the target
* @property {*} [additionalProperties] - Additional properties depending on the annotation type
*/
/**
* @typedef {Object} TargetModel
* @property {import('openmct').DomainObject[]} originalPath - The original path of the target object
* @property {*} [additionalProperties] - Additional properties of the target domain object
*/
/**
* @typedef {Object} AnnotationResult
* @property {string} name - The name of the annotation
* @property {string} type - The type of the object (always 'annotation')
* @property {{key: string, namespace: string}} identifier - The identifier of the annotation
* @property {string[]} tags - Array of tag keys associated with the annotation
* @property {boolean} _deleted - Whether the annotation is marked as deleted
* @property {ANNOTATION_TYPES} annotationType - The type of the annotation
* @property {string} contentText - The text content of the annotation
* @property {string} originalContextPath - The original context path of the annotation
* @property {AnnotationTarget[]} targets - Array of targets for the annotation
* @property {Tag[]} fullTagModels - Full tag models including metadata
* @property {string[]} matchingTagKeys - Array of tag keys that matched the search query
* @property {TargetModel[]} targetModels - Array of target models with additional information
*/
/**
* Combines annotations with the same targets
* @param {AnnotationResult[]} results - The results to combine
* @returns {AnnotationResult[]} The combined results
*/
#combineSameTargets(results) {
const combinedResults = [];
results.forEach((currentAnnotation) => {
const existingAnnotation = combinedResults.find((annotationToFind) => {
const { annotationType, targets } = currentAnnotation;
return this.areAnnotationTargetsEqual(annotationType, targets, annotationToFind.targets);
});
if (!existingAnnotation) {
combinedResults.push(currentAnnotation);
} else {
existingAnnotation.tags.push(...currentAnnotation.tags);
}
});
return combinedResults;
}
/**
* Breaks apart annotations with multiple targets into separate results
* @param {AnnotationResult[]} results - The results to break apart
* @returns {AnnotationResult[]} The separated results
*/
#breakApartSeparateTargets(results) {
const separateResults = [];
results.forEach((result) => {
result.targets.forEach((target) => {
const targetID = target.keyString;
const separatedResult = {
...result
};
separatedResult.targets = [target];
separatedResult.targetModels = result.targetModels.filter((targetModel) => {
const targetKeyString = this.openmct.objects.makeKeyString(targetModel.identifier);
return targetKeyString === targetID;
});
separateResults.push(separatedResult);
});
});
return separateResults;
}
/**
* Adds tag meta information to the given results
* @param {AnnotationResult[]} results - The results to add tag meta information to
* @param {string[]} matchingTagKeys - The matching tag keys
* @returns {AnnotationResult[]} The results with tag meta information added
*/
#addTagMetaInformationToResults(results, matchingTagKeys) {
const tagsAddedToResults = results.map((result) => {
const fullTagModels = this.#addTagMetaInformationToTags(result.tags);
@ -366,6 +474,12 @@ export default class AnnotationAPI extends EventEmitter {
return tagsAddedToResults;
}
/**
* Adds target models to the results
* @param {AnnotationResult[]} results - The results to add target models to
* @param {AbortSignal} abortSignal - The abort signal
* @returns {Promise<AnnotationResult[]>} The results with target models added
*/
async #addTargetModelsToResults(results, abortSignal) {
const modelAddedToResults = await Promise.all(
results.map(async (result) => {
@ -397,54 +511,11 @@ export default class AnnotationAPI extends EventEmitter {
return modelAddedToResults;
}
#combineSameTargets(results) {
const combinedResults = [];
results.forEach((currentAnnotation) => {
const existingAnnotation = combinedResults.find((annotationToFind) => {
const { annotationType, targets } = currentAnnotation;
return this.areAnnotationTargetsEqual(annotationType, targets, annotationToFind.targets);
});
if (!existingAnnotation) {
combinedResults.push(currentAnnotation);
} else {
existingAnnotation.tags.push(...currentAnnotation.tags);
}
});
return combinedResults;
}
/**
* @method #breakApartSeparateTargets
* @param {Array} results A set of search results that could have the multiple targets for the same result
* @returns {Array} The same set of results, but with each target separated out into its own result
*/
#breakApartSeparateTargets(results) {
const separateResults = [];
results.forEach((result) => {
result.targets.forEach((target) => {
const targetID = target.keyString;
const separatedResult = {
...result
};
separatedResult.targets = [target];
separatedResult.targetModels = result.targetModels.filter((targetModel) => {
const targetKeyString = this.openmct.objects.makeKeyString(targetModel.identifier);
return targetKeyString === targetID;
});
separateResults.push(separatedResult);
});
});
return separateResults;
}
/**
* @method searchForTags
* @param {string} query A query to match against tags. E.g., "dr" will match the tags "drilling" and "driving"
* @param {Object} [abortController] An optional abort method to stop the query
* @returns {Promise} returns a model of matching tags with their target domain objects attached
* Searches for tags matching the given query
* @param {string} query - A query to match against tags
* @param {AbortSignal} [abortSignal] - An optional abort signal to stop the query
* @returns {Promise<AnnotationResult[]>} A promise that resolves to an array of matching annotation results
*/
async searchForTags(query, abortSignal) {
const matchingTagKeys = this.#getMatchingTags(query);

View File

@ -28,7 +28,7 @@ import DefaultCompositionProvider from './DefaultCompositionProvider.js';
*/
/**
* @typedef {import('../objects/ObjectAPI').DomainObject} DomainObject
* @typedef {import('openmct').DomainObject} DomainObject
*/
/**
@ -72,7 +72,7 @@ export default class CompositionAPI {
*
* @method get
* @param {DomainObject} domainObject
* @returns {CompositionCollection}
* @returns {CompositionCollection | undefined}
*/
get(domainObject) {
const provider = this.registry.find((p) => {

View File

@ -21,7 +21,7 @@
*****************************************************************************/
/**
* @typedef {import('../objects/ObjectAPI').DomainObject} DomainObject
* @typedef {import('openmct').DomainObject} DomainObject
*/
/**
@ -200,10 +200,9 @@ export default class CompositionCollection {
/**
* Load the domain objects in this composition.
*
* @param {AbortSignal} abortSignal
* @param {AbortSignal} [abortSignal]
* @returns {Promise.<Array.<DomainObject>>} a promise for
* the domain objects in this composition
* @memberof {module:openmct.CompositionCollection#}
* @name load
*/
async load(abortSignal) {
@ -280,7 +279,7 @@ export default class CompositionCollection {
/**
* Handle adds from provider.
* @private
* @param {import('../objects/ObjectAPI').Identifier} childId
* @param {import('openmct').Identifier} childId
* @returns {DomainObject}
*/
#onProviderAdd(childId) {

View File

@ -24,11 +24,11 @@ import _ from 'lodash';
import { makeKeyString, parseKeyString } from '../objects/object-utils.js';
/**
* @typedef {import('../objects/ObjectAPI').DomainObject} DomainObject
* @typedef {import('openmct').DomainObject} DomainObject
*/
/**
* @typedef {import('../objects/ObjectAPI').Identifier} Identifier
* @typedef {import('openmct').Identifier} Identifier
*/
/**
@ -36,7 +36,7 @@ import { makeKeyString, parseKeyString } from '../objects/object-utils.js';
*/
/**
* @typedef {import('../../../openmct').OpenMCT} OpenMCT
* @typedef {import('openmct').OpenMCT} OpenMCT
*/
/**
@ -84,7 +84,7 @@ export default class CompositionProvider {
* Check if this provider should be used to load composition for a
* particular domain object.
* @method appliesTo
* @param {import('../objects/ObjectAPI').DomainObject} domainObject the domain object
* @param {DomainObject} domainObject the domain object
* to check
* @returns {boolean} true if this provider can provide composition for a given domain object
*/
@ -98,7 +98,6 @@ export default class CompositionProvider {
* for which to load composition
* @returns {Promise<Identifier[]>} a promise for
* the Identifiers in this composition
* @method load
*/
load(domainObject) {
throw new Error('This method must be implemented by a subclass.');
@ -137,7 +136,6 @@ export default class CompositionProvider {
* @param {DomainObject} domainObject the domain object
* which should have its composition modified
* @param {Identifier} childId the domain object to remove
* @method remove
*/
remove(domainObject, childId) {
throw new Error('This method must be implemented by a subclass.');
@ -151,7 +149,6 @@ export default class CompositionProvider {
* @param {DomainObject} parent the domain object
* which should have its composition modified
* @param {Identifier} childId the domain object to add
* @method add
*/
add(parent, childId) {
throw new Error('This method must be implemented by a subclass.');
@ -179,7 +176,6 @@ export default class CompositionProvider {
/**
* Listens on general mutation topic, using injector to fetch to avoid
* circular dependencies.
* @private
*/
#establishTopicListener() {
if (this.topicListener) {
@ -194,7 +190,6 @@ export default class CompositionProvider {
}
/**
* @private
* @param {DomainObject} parent
* @param {DomainObject} child
* @returns {boolean}
@ -207,7 +202,6 @@ export default class CompositionProvider {
}
/**
* @private
* @param {DomainObject} parent
* @returns {boolean}
*/
@ -219,7 +213,6 @@ export default class CompositionProvider {
* Handles mutation events. If there are active listeners for the mutated
* object, detects changes to composition and triggers necessary events.
*
* @private
* @param {DomainObject} oldDomainObject
*/
#onMutation(newDomainObject, oldDomainObject) {
@ -230,6 +223,10 @@ export default class CompositionProvider {
return;
}
if (oldDomainObject.composition === undefined || newDomainObject.composition === undefined) {
return;
}
const oldComposition = oldDomainObject.composition.map(makeKeyString);
const newComposition = newDomainObject.composition.map(makeKeyString);

View File

@ -25,11 +25,11 @@ import { makeKeyString } from '../objects/object-utils.js';
import CompositionProvider from './CompositionProvider.js';
/**
* @typedef {import('../objects/ObjectAPI').DomainObject} DomainObject
* @typedef {import('openmct').DomainObject} DomainObject
*/
/**
* @typedef {import('../objects/ObjectAPI').Identifier} Identifier
* @typedef {import('openmct').Identifier} Identifier
*/
/**

View File

@ -45,7 +45,7 @@ export default class FaultManagementAPI {
}
/**
* @param {import("../objects/ObjectAPI").DomainObject} domainObject
* @param {import('openmct').DomainObject} domainObject
* @returns {Promise.<FaultAPIResponse[]>}
*/
request(domainObject) {
@ -57,7 +57,7 @@ export default class FaultManagementAPI {
}
/**
* @param {import("../objects/ObjectAPI").DomainObject} domainObject
* @param {import('openmct').DomainObject} domainObject
* @param {Function} callback
* @returns {Function} unsubscribe
*/

View File

@ -1,3 +1,25 @@
/*****************************************************************************
* 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 mount from 'utils/mount';
import AutoCompleteField from './components/controls/AutoCompleteField.vue';
@ -11,6 +33,8 @@ import SelectField from './components/controls/SelectField.vue';
import TextAreaField from './components/controls/TextAreaField.vue';
import TextField from './components/controls/TextField.vue';
import ToggleSwitchField from './components/controls/ToggleSwitchField.vue';
/** @type {Record<string, import('vue').Component>} */
export const DEFAULT_CONTROLS_MAP = {
autocomplete: AutoCompleteField,
checkbox: CheckBoxField,
@ -26,6 +50,12 @@ export const DEFAULT_CONTROLS_MAP = {
};
export default class FormControl {
/** @type {Record<string, ControlViewProvider>} */
controls;
/**
* @param {OpenMCT} openmct
*/
constructor(openmct) {
this.openmct = openmct;
this.controls = {};
@ -33,6 +63,10 @@ export default class FormControl {
this._addDefaultFormControls();
}
/**
* @param {string} controlName
* @param {ControlViewProvider} controlViewProvider
*/
addControl(controlName, controlViewProvider) {
const control = this.controls[controlName];
if (control) {
@ -44,6 +78,10 @@ export default class FormControl {
this.controls[controlName] = controlViewProvider;
}
/**
* @param {string} controlName
* @returns {ControlViewProvider | undefined}
*/
getControl(controlName) {
const control = this.controls[controlName];
if (!control) {
@ -65,6 +103,8 @@ export default class FormControl {
/**
* @private
* @param {string} control
* @returns {ControlViewProvider}
*/
_getControlViewProvider(control) {
const self = this;
@ -106,3 +146,13 @@ export default class FormControl {
};
}
}
/**
* @typedef {import('openmct')} OpenMCT
*/
/**
* @typedef {Object} ControlViewProvider
* @property {(element: HTMLElement, model: any, onChange: Function) => any} show
* @property {() => void} destroy
*/

View File

@ -26,7 +26,14 @@ import mount from 'utils/mount';
import FormProperties from './components/FormProperties.vue';
import FormController from './FormController.js';
/**
* The FormsAPI provides methods for creating and managing forms in Open MCT.
*/
export default class FormsAPI {
/**
* Creates an instance of FormsAPI.
* @param {import('openmct').OpenMCT} openmct - The Open MCT API
*/
constructor(openmct) {
this.openmct = openmct;
this.formController = new FormController(openmct);
@ -47,7 +54,6 @@ export default class FormsAPI {
* Create a new form control definition with a formControlViewProvider
* this formControlViewProvider is used inside form overlay to show/render a form row
*
* @public
* @param {string} controlName a form structure, array of section
* @param {ControlViewProvider} controlViewProvider
*/
@ -58,7 +64,6 @@ export default class FormsAPI {
/**
* Get a ControlViewProvider for a given/stored form controlName
*
* @public
* @param {string} controlName a form structure, array of section
* @return {ControlViewProvider}
*/
@ -80,20 +85,20 @@ export default class FormsAPI {
* @property {string} control represents type of row to render
* eg:autocomplete,composite,datetime,file-input,locator,numberfield,select,textarea,textfield
* @property {string} cssClass class name for styling this row
* @property {module:openmct.DomainObject} domainObject object to be used by row
* @property {import('openmct').DomainObject} domainObject object to be used by row
* @property {string} key id for this row
* @property {string} name Name of the row to display on Form
* @property {module:openmct.DomainObject} parent parent object to be used by row
* @property {import('openmct').DomainObject} parent parent object to be used by row
* @property {boolean} required is this row mandatory
* @property {function} validate a function to validate this row on any changes
*/
/**
* Show form inside an Overlay dialog with given form structure
* @public
* @param {Array<Section>} formStructure a form structure, array of section
* @param {Object} options
* @property {function} onChange a callback function when any changes detected
* @param {() => void} [options.onChange] a callback function when any changes detected
* @returns {Promise<Object>} A promise that resolves with the form data when saved, or rejects when cancelled
*/
showForm(formStructure, { onChange } = {}) {
let overlay;
@ -134,11 +139,11 @@ export default class FormsAPI {
/**
* Show form as a child of the element provided with given form structure
*
* @public
* @param {Array<Section>} formStructure a form structure, array of section
* @param {Object} options
* @property {HTMLElement} element Parent Element to render a Form
* @property {function} onChange a callback function when any changes detected
* @param {HTMLElement} options.element Parent Element to render a Form
* @param {() => void} [options.onChange] a callback function when any changes detected
* @returns {Promise<Object>} A promise that resolves with the form data when saved, or rejects when cancelled
*/
showCustomForm(formStructure, { element, onChange } = {}) {
if (element === undefined) {
@ -179,6 +184,10 @@ export default class FormsAPI {
}
);
/**
* Handles form property changes
* @param {Object} data - The changed form data
*/
function onFormPropertyChange(data) {
if (onChange) {
onChange(data);
@ -196,6 +205,11 @@ export default class FormsAPI {
}
}
/**
* Creates a form action handler
* @param {() => void} callback - The callback to be called when the form action is triggered
* @returns {(...args: any[]) => void} The form action handler
*/
function onFormAction(callback) {
return () => {
destroy();

View File

@ -1,3 +1,25 @@
/*****************************************************************************
* 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.
*****************************************************************************/
export default {
emits: ['on-change'],
data() {

View File

@ -20,11 +20,18 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import vueWrapHtmlElement from '../../utils/vueWrapHtmlElement.js';
import SimpleIndicator from './SimpleIndicator.js';
/**
* The Indicator API is used to add indicators to the Open MCT UI.
* An indicator appears in the top navigation bar and can be used to
* display information or trigger actions.
*
* @extends EventEmitter
*/
class IndicatorAPI extends EventEmitter {
/** @type {import('../../../openmct.js').OpenMCT} */
openmct;
@ -51,38 +58,39 @@ class IndicatorAPI extends EventEmitter {
/**
* @typedef {Object} Indicator
* @property {HTMLElement} [element]
* @property {VueComponent|Promise<VueComponent>} [vueComponent]
* @property {string} key
* @property {number} priority
* @property {HTMLElement} [element] - The HTML element of the indicator. Optional if using vueComponent.
* @property {VueComponent|Promise<VueComponent>} [vueComponent] - The Vue component for the indicator. Optional if using element.
* @property {string} key - The unique key for the indicator.
* @property {number} priority - The priority of the indicator (default: -1).
*/
/**
* Accepts an indicator object, which is a simple object
* with a two attributes: 'element' which has an HTMLElement
* as its value, and 'priority' with an integer that specifies its order in the layout.
* The lower the priority, the further to the right the element is placed.
* If undefined, the priority will be assigned -1.
* Adds an indicator to the API.
*
* We provide .simpleIndicator() as a convenience function
* which will create a default Open MCT indicator that can
* be passed to .add(indicator). This indicator also exposes
* functions for changing its appearance to support customization
* and dynamic behavior.
* @param {Indicator} indicator - The indicator object to add.
*
* Eg.
* @description
* The indicator object is a simple object with two main attributes:
* - 'element': An HTMLElement (optional if using vueComponent).
* - 'priority': An integer specifying its order in the layout. Lower priority
* places the element further to the right. If undefined, defaults to -1.
*
* A convenience function `.simpleIndicator()` is provided to create a default
* Open MCT indicator that can be passed to `.add(indicator)`. This indicator
* exposes functions for customizing its appearance and behavior.
*
* Example usage:
* ```
* const myIndicator = openmct.indicators.simpleIndicator();
* openmct.indicators.add(myIndicator);
*
* myIndicator.text("Hello World!");
* myIndicator.iconClass("icon-info");
* ```
*
* If you would like to use a Vue component, you can pass it in
* directly as the 'vueComponent' attribute of the indicator object.
* This accepts a Vue component or a promise that resolves to a Vue component (for asynchronous
* rendering).
*
* @param {Indicator} indicator
* For Vue components, pass the component directly as the 'vueComponent'
* attribute. This can be a Vue component or a promise resolving to a
* Vue component for asynchronous rendering.
*/
add(indicator) {
if (!indicator.priority) {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { convertTemplateToHTML } from '@/utils/template/templateHelpers';

View File

@ -22,32 +22,14 @@
import Menu, { MENU_PLACEMENT } from './menu.js';
/**
* Popup Menu options
* @typedef {Object} MenuOptions
* @property {string} menuClass Class for popup menu
* @property {MENU_PLACEMENT} placement Placement for menu relative to click
* @property {Function} onDestroy callback function: invoked when menu is destroyed
*/
/**
* Popup Menu Item/action
* @typedef {Object} Action
* @property {string} cssClass Class for menu item
* @property {boolean} isDisabled adds disable class if true
* @property {string} name Menu item text
* @property {string} description Menu item description
* @property {Function} onItemClicked callback function: invoked when item is clicked
*/
/**
* The MenuAPI allows the addition of new context menu actions, and for the context menu to be launched from
* custom HTML elements.
* @interface MenuAPI
* @memberof module:openmct
*/
class MenuAPI {
/**
* @param {import('openmct').OpenMCT} openmct
*/
constructor(openmct) {
this.openmct = openmct;
@ -61,10 +43,10 @@ class MenuAPI {
/**
* Show popup menu
* @param {number} x x-coordinates for popup
* @param {number} y x-coordinates for popup
* @param {Array.<Action>|Array.<Array.<Action>>} actions collection of actions{@link Action} or collection of groups of actions {@link Action}
* @param {MenuOptions} [menuOptions] [Optional] The {@link MenuOptions} options for Menu
* @param {number} x - x-coordinates for popup
* @param {number} y - y-coordinates for popup
* @param {Action[]|Action[][]} items - collection of actions or collection of groups of actions
* @param {MenuOptions} [menuOptions] - The options for Menu
*/
showMenu(x, y, items, menuOptions) {
this._createMenuComponent(x, y, items, menuOptions);
@ -72,6 +54,13 @@ class MenuAPI {
this.menuComponent.showMenu();
}
/**
* Convert actions to menu items
* @param {Action[]} actions - collection of actions
* @param {import('openmct').ObjectPath} objectPath - The object path
* @param {import('openmct').ViewProvider} view - The view provider
* @returns {Action[]}
*/
actionsToMenuItems(actions, objectPath, view) {
return actions.map((action) => {
const isActionGroup = Array.isArray(action);
@ -87,10 +76,10 @@ class MenuAPI {
/**
* Show popup menu with description of item on hover
* @param {number} x x-coordinates for popup
* @param {number} y x-coordinates for popup
* @param {Array.<Action>|Array.<Array.<Action>>} actions collection of actions {@link Action} or collection of groups of actions {@link Action}
* @param {MenuOptions} [menuOptions] [Optional] The {@link MenuOptions} options for Menu
* @param {number} x - x-coordinates for popup
* @param {number} y - y-coordinates for popup
* @param {Action[]|Action[][]} actions - collection of actions or collection of groups of actions
* @param {MenuOptions} [menuOptions] - The options for Menu
*/
showSuperMenu(x, y, actions, menuOptions) {
this._createMenuComponent(x, y, actions, menuOptions);
@ -98,11 +87,23 @@ class MenuAPI {
this.menuComponent.showSuperMenu();
}
/**
* Clear the menu component
* @private
*/
_clearMenuComponent() {
this.menuComponent = undefined;
delete this.menuComponent;
}
/**
* Create a menu component
* @param {number} x - x-coordinates for popup
* @param {number} y - y-coordinates for popup
* @param {Action[]|Action[][]} actions - collection of actions or collection of groups of actions
* @param {MenuOptions} menuOptions - The options for Menu
* @private
*/
_createMenuComponent(x, y, actions, menuOptions = {}) {
if (this.menuComponent) {
this.menuComponent.dismiss();
@ -119,6 +120,14 @@ class MenuAPI {
this.menuComponent.once('destroy', this._clearMenuComponent);
}
/**
* Show object menu
* @param {import('openmct').ObjectPath} objectPath - The object path
* @param {number} x - x-coordinates for popup
* @param {number} y - y-coordinates for popup
* @param {string[]} actionsToBeIncluded - Actions to be included in the menu
* @private
*/
_showObjectMenu(objectPath, x, y, actionsToBeIncluded) {
let applicableActions = this.openmct.actions._groupedAndSortedObjectActions(
objectPath,
@ -129,3 +138,14 @@ class MenuAPI {
}
}
export default MenuAPI;
/**
* @typedef {Object} MenuOptions
* @property {string} [menuClass] - Class for popup menu
* @property {MENU_PLACEMENT} [placement] - Placement for menu relative to click
* @property {() => void} [onDestroy] - callback function: invoked when menu is destroyed
*/
/**
* @typedef {import('openmct').Action} Action
*/

View File

@ -19,13 +19,18 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import mount from 'utils/mount';
import { h } from 'vue';
import MenuComponent from './components/MenuComponent.vue';
import SuperMenuComponent from './components/SuperMenu.vue';
/**
* Enum for menu placement options.
* @readonly
* @enum {string}
*/
export const MENU_PLACEMENT = {
TOP: 'top',
TOP_LEFT: 'top-left',
@ -37,7 +42,15 @@ export const MENU_PLACEMENT = {
RIGHT: 'right'
};
/**
* Class representing a menu.
* @extends EventEmitter
*/
class Menu extends EventEmitter {
/**
* Create a menu.
* @param {MenuOptions} options - The options for the menu.
*/
constructor(options) {
super();
@ -52,6 +65,9 @@ class Menu extends EventEmitter {
this.showSuperMenu = this.showSuperMenu.bind(this);
}
/**
* Dismiss the menu.
*/
dismiss() {
if (this.destroy) {
this.destroy();
@ -61,6 +77,9 @@ class Menu extends EventEmitter {
this.emit('destroy');
}
/**
* Show the menu component.
*/
showMenu() {
if (this.destroy) {
return;
@ -80,6 +99,9 @@ class Menu extends EventEmitter {
this.show();
}
/**
* Show the super menu component.
*/
showSuperMenu() {
const { vNode, destroy } = mount({
data() {
@ -102,6 +124,9 @@ class Menu extends EventEmitter {
this.show();
}
/**
* Show the menu.
*/
show() {
document.body.appendChild(this.el);
document.addEventListener('click', this.dismiss);
@ -109,3 +134,8 @@ class Menu extends EventEmitter {
}
export default Menu;
/**
* @typedef {Object} MenuOptions
* @property {() => void} [onDestroy] - Callback function to be called when the menu is destroyed.
*/

View File

@ -27,65 +27,22 @@
* much as possible, notifications share a model with blocking
* dialogs so that the same information can be provided in a dialog
* and then minimized to a banner notification if needed.
*
* @namespace platform/api/notifications
*/
import EventEmitter from 'eventemitter3';
import { EventEmitter } from 'eventemitter3';
import moment from 'moment';
/**
* @typedef {Object} NotificationProperties
* @property {function} dismiss Dismiss the notification
* @property {NotificationModel} model The Notification model
* @property {(progressPerc: number, progressText: string) => void} [progress] Update the progress of the notification
*/
/**
* @typedef {EventEmitter & NotificationProperties} Notification
*/
/**
* @typedef {Object} NotificationLink
* @property {function} onClick The function to be called when the link is clicked
* @property {string} cssClass A CSS class name to style the link
* @property {string} text The text to be displayed for the link
*/
/**
* @typedef {Object} NotificationOptions
* @property {number} [autoDismissTimeout] Milliseconds to wait before automatically dismissing the notification
* @property {boolean} [minimized] Allows for a notification to be minimized into the indicator by default
* @property {NotificationLink} [link] A link for the notification
*/
/**
* A representation of a banner notification. Banner notifications
* are used to inform users of events in a non-intrusive way. As
* much as possible, notifications share a model with blocking
* dialogs so that the same information can be provided in a dialog
* and then minimized to a banner notification if needed, or vice-versa.
*
* @see DialogModel
* @typedef {Object} NotificationModel
* @property {string} message The message to be displayed by the notification
* @property {number | 'unknown'} [progress] The progress of some ongoing task. Should be a number between 0 and 100, or
* with the string literal 'unknown'.
* @property {string} [progressText] A message conveying progress of some ongoing task.
* @property {string} [severity] The severity of the notification. Should be one of 'info', 'alert', or 'error'.
* @property {string} [timestamp] The time at which the notification was created. Should be a string in ISO 8601 format.
* @property {boolean} [minimized] Whether or not the notification has been minimized
* @property {boolean} [autoDismiss] Whether the notification should be automatically dismissed after a short period of time.
* @property {NotificationOptions} options The notification options
*/
const DEFAULT_AUTO_DISMISS_TIMEOUT = 3000;
const MINIMIZE_ANIMATION_TIMEOUT = 300;
/**
* The notification service is responsible for informing the user of
* events via the use of banner notifications.
* @extends EventEmitter
*/
export default class NotificationAPI extends EventEmitter {
/**
* @constructor
*/
constructor() {
super();
/** @type {Notification[]} */
@ -123,12 +80,7 @@ export default class NotificationAPI extends EventEmitter {
/**
* Present an alert to the user.
* @param {string} message The message to display to the user.
* @param {NotificationOptions} [options] object with following properties
* autoDismissTimeout: {number} in milliseconds to automatically dismisses notification
* link: {Object} Add a link to notifications for navigation
* onClick: callback function
* cssClass: css class name to add style on link
* text: text to display for link
* @param {NotificationOptions} [options] The notification options
* @returns {Notification}
*/
alert(message, options = {}) {
@ -143,13 +95,8 @@ export default class NotificationAPI extends EventEmitter {
/**
* Present an error message to the user
* @param {string} message
* @param {Object} [options] object with following properties
* autoDismissTimeout: {number} in milliseconds to automatically dismisses notification
* link: {Object} Add a link to notifications for navigation
* onClick: callback function
* cssClass: css class name to add style on link
* text: text to display for link
* @param {string} message The error message to display
* @param {NotificationOptions} [options] The notification options
* @returns {Notification}
*/
error(message, options = {}) {
@ -164,9 +111,10 @@ export default class NotificationAPI extends EventEmitter {
/**
* Create a new progress notification. These notifications will contain a progress bar.
* @param {string} message
* @param {string} message The message to display
* @param {number | null} progressPerc A value between 0 and 100, or null.
* @param {string} [progressText] Text description of progress (eg. "10 of 20 objects copied").
* @returns {Notification}
*/
progress(message, progressPerc, progressText) {
let notificationModel = {
@ -180,6 +128,9 @@ export default class NotificationAPI extends EventEmitter {
return this._notify(notificationModel);
}
/**
* Dismiss all active notifications.
*/
dismissAllNotifications() {
this.notifications = [];
this.emit('dismiss-all');
@ -192,7 +143,7 @@ export default class NotificationAPI extends EventEmitter {
* dismissed.
*
* @private
* @param {Notification | undefined} notification
* @param {Notification | undefined} notification The notification to minimize
*/
_minimize(notification) {
if (!notification) {
@ -204,13 +155,13 @@ export default class NotificationAPI extends EventEmitter {
if (this.activeTimeout) {
/*
Method can be called manually (clicking dismiss) or
automatically from an auto-timeout. this.activeTimeout
acts as a semaphore to prevent race conditions. Cancel any
timeout in progress (for the case where a manual dismiss
has shortcut an active auto-dismiss), and clear the
semaphore.
*/
* Method can be called manually (clicking dismiss) or
* automatically from an auto-timeout. this.activeTimeout
* acts as a semaphore to prevent race conditions. Cancel any
* timeout in progress (for the case where a manual dismiss
* has shortcut an active auto-dismiss), and clear the
* semaphore.
*/
clearTimeout(this.activeTimeout);
delete this.activeTimeout;
}
@ -232,11 +183,10 @@ export default class NotificationAPI extends EventEmitter {
* message banner and remove it from the list of notifications.
* Typically only notifications with a severity of info should be
* dismissed. If you're not sure whether to dismiss or minimize a
* notification, use {@link Notification#dismissOrMinimize}.
* dismiss
* notification, use {@link NotificationAPI#_dismissOrMinimize}.
*
* @private
* @param {Notification | undefined} notification
* @param {Notification | undefined} notification The notification to dismiss
*/
_dismiss(notification) {
if (!notification) {
@ -247,14 +197,14 @@ export default class NotificationAPI extends EventEmitter {
let index = this.notifications.indexOf(notification);
if (this.activeTimeout) {
/* Method can be called manually (clicking dismiss) or
/*
* Method can be called manually (clicking dismiss) or
* automatically from an auto-timeout. this.activeTimeout
* acts as a semaphore to prevent race conditions. Cancel any
* timeout in progress (for the case where a manual dismiss
* has shortcut an active auto-dismiss), and clear the
* semaphore.
*/
clearTimeout(this.activeTimeout);
delete this.activeTimeout;
}
@ -273,7 +223,7 @@ export default class NotificationAPI extends EventEmitter {
* dismiss or minimize where appropriate.
*
* @private
* @param {Notification | undefined} notification
* @param {Notification | undefined} notification The notification to dismiss or minimize
*/
_dismissOrMinimize(notification) {
let model = notification?.model;
@ -285,6 +235,7 @@ export default class NotificationAPI extends EventEmitter {
}
/**
* Sets the highest severity notification.
* @private
*/
_setHighestSeverity() {
@ -308,10 +259,10 @@ export default class NotificationAPI extends EventEmitter {
* already active, then it will be dismissed or minimized automatically,
* and the provided notification displayed in its place.
*
* @param {NotificationModel} notificationModel The notification to
* display
* @private
* @param {NotificationModel} notificationModel The notification to display
* @returns {Notification} the provided notification decorated with
* functions to {@link Notification#dismiss} or {@link Notification#minimize}
* functions to dismiss or minimize
*/
_notify(notificationModel) {
let notification;
@ -326,21 +277,21 @@ export default class NotificationAPI extends EventEmitter {
this._setHighestSeverity();
/*
Check if there is already an active (ie. visible) notification
*/
* Check if there is already an active (ie. visible) notification
*/
if (!this.activeNotification && !notification?.model?.options?.minimized) {
this._setActiveNotification(notification);
} else if (!this.activeTimeout) {
/*
If there is already an active notification, time it out. If it's
already got a timeout in progress (either because it has had
timeout forced because of a queue of messages, or it had an
autodismiss specified), leave it to run. Otherwise force a
timeout.
This notification has been added to queue and will be
serviced as soon as possible.
*/
* If there is already an active notification, time it out. If it's
* already got a timeout in progress (either because it has had
* timeout forced because of a queue of messages, or it had an
* autodismiss specified), leave it to run. Otherwise force a
* timeout.
*
* This notification has been added to queue and will be
* serviced as soon as possible.
*/
this.activeTimeout = setTimeout(() => {
this._dismissOrMinimize(activeNotification);
}, DEFAULT_AUTO_DISMISS_TIMEOUT);
@ -350,8 +301,9 @@ export default class NotificationAPI extends EventEmitter {
}
/**
* Creates a new notification object.
* @private
* @param {NotificationModel} notificationModel
* @param {NotificationModel} notificationModel The model for the notification
* @returns {Notification}
*/
_createNotification(notificationModel) {
@ -374,8 +326,9 @@ export default class NotificationAPI extends EventEmitter {
}
/**
* Sets the active notification.
* @private
* @param {Notification | undefined} notification
* @param {Notification | undefined} notification The notification to set as active
*/
_setActiveNotification(notification) {
this.activeNotification = notification;
@ -400,18 +353,18 @@ export default class NotificationAPI extends EventEmitter {
}
/**
* Used internally by the NotificationService
*
* Selects the next notification to be displayed.
* @private
* @returns {Notification | undefined}
*/
_selectNextNotification() {
let notification;
let i = 0;
/*
Loop through the notifications queue and find the first one that
has not already been minimized (manually or otherwise).
*/
* Loop through the notifications queue and find the first one that
* has not already been minimized (manually or otherwise).
*/
for (; i < this.notifications.length; i++) {
notification = this.notifications[i];
@ -424,3 +377,41 @@ export default class NotificationAPI extends EventEmitter {
}
}
}
/**
* @typedef {Object} NotificationProperties
* @property {() => void} dismiss Dismiss the notification
* @property {NotificationModel} model The Notification model
* @property {(progressPerc: number, progressText: string) => void} [progress] Update the progress of the notification
*/
/**
* @typedef {EventEmitter & NotificationProperties} Notification
*/
/**
* @typedef {Object} NotificationLink
* @property {() => void} onClick The function to be called when the link is clicked
* @property {string} cssClass A CSS class name to style the link
* @property {string} text The text to be displayed for the link
*/
/**
* @typedef {Object} NotificationOptions
* @property {number} [autoDismissTimeout] Milliseconds to wait before automatically dismissing the notification
* @property {boolean} [minimized] Allows for a notification to be minimized into the indicator by default
* @property {NotificationLink} [link] A link for the notification
*/
/**
* A representation of a banner notification.
* @typedef {Object} NotificationModel
* @property {string} message The message to be displayed by the notification
* @property {number | 'unknown'} [progress] The progress of some ongoing task. Should be a number between 0 and 100, or 'unknown'.
* @property {string} [progressText] A message conveying progress of some ongoing task.
* @property {'info' | 'alert' | 'error'} [severity] The severity of the notification.
* @property {string} [timestamp] The time at which the notification was created. Should be a string in ISO 8601 format.
* @property {boolean} [minimized] Whether or not the notification has been minimized
* @property {boolean} [autoDismiss] Whether the notification should be automatically dismissed after a short period of time.
* @property {NotificationOptions} options The notification options
*/

View File

@ -1 +1,28 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/**
* Represents an error that occurs when there is a conflict (409) while trying to
* persist an object.
* This class extends the built-in Error class.
*/
export default class ConflictError extends Error {}

View File

@ -24,7 +24,6 @@ export default class InterceptorRegistry {
/**
* A InterceptorRegistry maintains the definitions for different interceptors that may be invoked on domain objects.
* @interface InterceptorRegistry
* @memberof module:openmct
*/
constructor() {
this.interceptors = [];
@ -35,7 +34,6 @@ export default class InterceptorRegistry {
* @property {function} appliesTo function that determines if this interceptor should be called for the given identifier/object
* @property {function} invoke function that transforms the provided domain object and returns the transformed domain object
* @property {function} priority the priority for this interceptor. A higher number returned has more weight than a lower number
* @memberof module:openmct InterceptorRegistry#
*/
/**
@ -43,7 +41,6 @@ export default class InterceptorRegistry {
*
* @param {module:openmct.InterceptorDef} interceptorDef the interceptor to add
* @method addInterceptor
* @memberof module:openmct.InterceptorRegistry#
*/
addInterceptor(interceptorDef) {
this.interceptors.push(interceptorDef);
@ -53,7 +50,6 @@ export default class InterceptorRegistry {
* Retrieve all interceptors applicable to a domain object.
* @method getInterceptors
* @returns [module:openmct.InterceptorDef] the registered interceptors for this identifier/object
* @memberof module:openmct.InterceptorRegistry#
*/
getInterceptors(identifier, object) {
function byPriority(interceptorA, interceptorB) {

View File

@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import { makeKeyString, refresh } from './object-utils.js';
@ -38,7 +38,6 @@ const ANY_OBJECT_EVENT = 'mutation';
* (via openmct.objects.destroy) when you're done with it.
*
* @typedef MutableDomainObject
* @memberof module:openmct
*/
class MutableDomainObject {
constructor(eventEmitter) {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { identifierEquals, makeKeyString, parseKeyString, refresh } from 'objectUtils';
import ConflictError from './ConflictError.js';
@ -33,39 +33,21 @@ import Transaction from './Transaction.js';
/**
* Uniquely identifies a domain object.
*
* @typedef {Object} Identifier
* @property {string} namespace the namespace to/from which this domain
* object should be loaded/stored.
* @property {string} key a unique identifier for the domain object
* within that namespace
* @memberof module:openmct.ObjectAPI~
* @property {string} namespace the namespace to/from which this domain object should be loaded/stored.
* @property {string} key a unique identifier for the domain object within that namespace
*/
/**
* A domain object is an entity of relevance to a user's workflow, that
* should appear as a distinct and meaningful object within the user
* interface. Examples of domain objects are folders, telemetry sensors,
* and so forth.
*
* A few common properties are defined for domain objects. Beyond these,
* individual types of domain objects may add more as they see fit.
*
* A domain object is an entity of relevance to a user's workflow, that should appear as a distinct and meaningful object within the user interface.
* @typedef {Object} DomainObject
* @property {Identifier} identifier a key/namespace pair which
* uniquely identifies this domain object
* @property {Identifier} identifier a key/namespace pair which uniquely identifies this domain object
* @property {string} type the type of domain object
* @property {string} name the human-readable name for this domain object
* @property {string} [creator] the user name of the creator of this domain
* object
* @property {number} [modified] the time, in milliseconds since the UNIX
* epoch, at which this domain object was last modified
* @property {Identifier[]} [composition] if
* present, this will be used by the default composition provider
* to load domain objects
* @property {Object.<string, any>} [configuration] A key-value map containing configuration
* settings for this domain object.
* @memberof module:openmct.ObjectAPI~
* @property {string} [creator] the user name of the creator of this domain object
* @property {number} [modified] the time, in milliseconds since the UNIX epoch, at which this domain object was last modified
* @property {Identifier[]} [composition] if present, this will be used by the default composition provider to load domain objects
* @property {Record<string, any>} [configuration] A key-value map containing configuration settings for this domain object.
*/
/**
@ -78,8 +60,6 @@ import Transaction from './Transaction.js';
/**
* Utilities for loading, saving, and manipulating domain objects.
* @interface ObjectAPI
* @memberof module:openmct
*/
export default class ObjectAPI {
#makeKeyString;
@ -88,6 +68,10 @@ export default class ObjectAPI {
#refresh;
#openmct;
/**
* @param {any} typeRegistry
* @param {any} openmct
*/
constructor(typeRegistry, openmct) {
this.#makeKeyString = makeKeyString;
this.#parseKeyString = parseKeyString;
@ -125,6 +109,8 @@ export default class ObjectAPI {
/**
* Retrieve the provider for a given identifier.
* @param {Identifier} identifier
* @returns {ObjectProvider | RootObjectProvider}
*/
getProvider(identifier) {
if (identifier.key === 'ROOT') {
@ -144,7 +130,7 @@ export default class ObjectAPI {
/**
* Get the root-level object.
* @returns {Promise.<DomainObject>} a promise for the root object
* @returns {Promise<DomainObject>} a promise for the root object
*/
getRoot() {
return this.rootProvider.get();
@ -154,63 +140,17 @@ export default class ObjectAPI {
* Register a new object provider for a particular namespace.
*
* @param {string} namespace the namespace for which to provide objects
* @param {module:openmct.ObjectProvider} provider the provider which
* will handle loading domain objects from this namespace
* @memberof {module:openmct.ObjectAPI#}
* @name addProvider
* @param {ObjectProvider} provider the provider which will handle loading domain objects from this namespace
*/
addProvider(namespace, provider) {
this.providers[namespace] = provider;
}
/**
* Provides the ability to read, write, and delete domain objects.
*
* When registering a new object provider, all methods on this interface
* are optional.
*
* @interface ObjectProvider
* @memberof module:openmct
*/
/**
* Create the given domain object in the corresponding persistence store
*
* @method create
* @memberof module:openmct.ObjectProvider#
* @param {module:openmct.DomainObject} domainObject the domain object to
* create
* @returns {Promise} a promise which will resolve when the domain object
* has been created, or be rejected if it cannot be saved
*/
/**
* Update this domain object in its persistence store
*
* @method update
* @memberof module:openmct.ObjectProvider#
* @param {module:openmct.DomainObject} domainObject the domain object to
* update
* @returns {Promise} a promise which will resolve when the domain object
* has been updated, or be rejected if it cannot be saved
*/
/**
* Delete this domain object.
*
* @method delete
* @memberof module:openmct.ObjectProvider#
* @param {module:openmct.DomainObject} domainObject the domain object to
* delete
* @returns {Promise} a promise which will resolve when the domain object
* has been deleted, or be rejected if it cannot be deleted
*/
/**
* Get a domain object.
*
* @param {string} key the key for the domain object to load
* @param {AbortSignal} abortSignal (optional) signal to abort fetch requests
* @param {Identifier | string} identifier the identifier for the domain object to load
* @param {AbortSignal} [abortSignal] (optional) signal to abort fetch requests
* @param {boolean} [forceRemote=false] defaults to false. If true, will skip cached and
* dirty/in-transaction objects use and the provider.get method
* @returns {Promise<DomainObject>} a promise which will resolve when the domain object
@ -289,14 +229,10 @@ export default class ObjectAPI {
* and will be searched using the fallback in-memory search.
* Search results are asynchronous and resolve in parallel.
*
* @method search
* @memberof module:openmct.ObjectAPI#
* @param {string} query the term to search for
* @param {AbortController.signal} abortSignal (optional) signal to cancel downstream fetch requests
* @param {string} searchType the type of search as defined by SEARCH_TYPES
* @returns {Array.<Promise.<module:openmct.DomainObject>>}
* an array of promises returned from each object provider's search function
* each resolving to domain objects matching provided search query and options.
* @param {AbortController.signal} [abortSignal] (optional) signal to cancel downstream fetch requests
* @param {string} [searchType=this.SEARCH_TYPES.OBJECTS] the type of search as defined by SEARCH_TYPES
* @returns {Promise<DomainObject>[]} an array of promises returned from each object provider's search function, each resolving to domain objects matching the provided search query and options
*/
search(query, abortSignal, searchType = this.SEARCH_TYPES.OBJECTS) {
if (!Object.keys(this.SEARCH_TYPES).includes(searchType.toUpperCase())) {
@ -330,9 +266,8 @@ export default class ObjectAPI {
* platform will manage the lifecycle of any mutable objects that it provides. If you use `getMutable` you are
* committing to managing that lifecycle yourself. `.destroy` should be called when the object is no longer needed.
*
* @memberof {module:openmct.ObjectAPI#}
* @returns {Promise.<MutableDomainObject>} a promise that will resolve with a MutableDomainObject if
* the object can be mutated.
* @param {Identifier} identifier the identifier of the object to fetch
* @returns {Promise<MutableDomainObject>} a promise that will resolve with a MutableDomainObject if the object can be mutated
*/
getMutable(identifier) {
if (!this.supportsMutation(identifier)) {
@ -348,7 +283,7 @@ export default class ObjectAPI {
* This function is for cleaning up a mutable domain object when you're done with it.
* You only need to use this if you retrieved the object using `getMutable()`. If the object was provided by the
* platform (eg. passed into a `view()` function) then the platform is responsible for its lifecycle.
* @param {MutableDomainObject} domainObject
* @param {MutableDomainObject} domainObject the mutable domain object to destroy
*/
destroyMutable(domainObject) {
if (domainObject.isMutable) {
@ -382,11 +317,8 @@ export default class ObjectAPI {
/**
* Save this domain object in its current state.
*
* @memberof module:openmct.ObjectAPI#
* @param {module:openmct.DomainObject} domainObject the domain object to
* save
* @returns {Promise} a promise which will resolve when the domain object
* has been saved, or be rejected if it cannot be saved
* @param {DomainObject} domainObject the domain object to save
* @returns {Promise} a promise which will resolve when the domain object has been saved, or be rejected if it cannot be saved
*/
async save(domainObject) {
const provider = this.getProvider(domainObject.identifier);
@ -517,7 +449,6 @@ export default class ObjectAPI {
* this item(s) position in the root object's composition (example: order in object tree).
* For arrays, they are treated as blocks.
* @method addRoot
* @memberof module:openmct.ObjectAPI#
*/
addRoot(identifier, priority) {
this.rootRegistry.addRoot(identifier, priority);
@ -530,7 +461,6 @@ export default class ObjectAPI {
*
* @param {module:openmct.InterceptorDef} interceptorDef the interceptor definition to add
* @method addGetInterceptor
* @memberof module:openmct.InterceptorRegistry#
*/
addGetInterceptor(interceptorDef) {
this.interceptorRegistry.addInterceptor(interceptorDef);
@ -538,7 +468,6 @@ export default class ObjectAPI {
/**
* Retrieve the interceptors for a given domain object.
* @private
*/
#listGetInterceptors(identifier, object) {
return this.interceptorRegistry.getInterceptors(identifier, object);
@ -560,7 +489,7 @@ export default class ObjectAPI {
/**
* Return relative url path from a given object path
* eg: #/browse/mine/cb56f6bf-c900-43b7-b923-2e3b64b412db/6e89e858-77ce-46e4-a1ad-749240286497/....
* @param {Array} objectPath
* @param {Array<DomainObject>} objectPath
* @returns {string} relative url for object
*/
getRelativePath(objectPath) {
@ -612,13 +541,10 @@ export default class ObjectAPI {
/**
* Modify a domain object. Internal to ObjectAPI, won't call save after.
* @private
*
* @param {module:openmct.DomainObject} object the object to mutate
* @param {DomainObject} domainObject the object to mutate
* @param {string} path the property to modify
* @param {*} value the new value for this property
* @method mutate
* @memberof module:openmct.ObjectAPI#
*/
#mutate(domainObject, path, value) {
if (!this.supportsMutation(domainObject.identifier)) {
@ -628,28 +554,26 @@ export default class ObjectAPI {
if (domainObject.isMutable) {
domainObject.$set(path, value);
} else {
//Creating a temporary mutable domain object allows other mutable instances of the
//object to be kept in sync.
// Creating a temporary mutable domain object allows other mutable instances of the
// object to be kept in sync.
let mutableDomainObject = this.toMutable(domainObject);
//Mutate original object
// Mutate original object
MutableDomainObject.mutateObject(domainObject, path, value);
//Mutate temporary mutable object, in the process informing any other mutable instances
// Mutate temporary mutable object, in the process informing any other mutable instances
mutableDomainObject.$set(path, value);
//Destroy temporary mutable object
// Destroy temporary mutable object
this.destroyMutable(mutableDomainObject);
}
}
/**
* Modify a domain object and save.
* @param {module:openmct.DomainObject} object the object to mutate
* @param {DomainObject} domainObject the object to mutate
* @param {string} path the property to modify
* @param {*} value the new value for this property
* @method mutate
* @memberof module:openmct.ObjectAPI#
*/
mutate(domainObject, path, value) {
this.#mutate(domainObject, path, value);
@ -662,11 +586,9 @@ export default class ObjectAPI {
}
/**
* Create a mutable domain object from an existing domain object
* @param {module:openmct.DomainObject} domainObject the object to make mutable
* Create a mutable domain object from an existing domain object.
* @param {DomainObject} domainObject the object to make mutable
* @returns {MutableDomainObject} a mutable domain object that will automatically sync
* @method toMutable
* @memberof module:openmct.ObjectAPI#
*/
toMutable(domainObject) {
let mutableObject;
@ -689,8 +611,8 @@ export default class ObjectAPI {
// modified can sometimes be undefined, so make it 0 in this case
const mutableObjectModification = mutableObject.modified ?? Number.MIN_SAFE_INTEGER;
if (updatedModel.persisted > mutableObjectModification) {
//Don't replace with a stale model. This can happen on slow connections when multiple mutations happen
//in rapid succession and intermediate persistence states are returned by the observe function.
// Don't replace with a stale model. This can happen on slow connections when multiple mutations happen
// in rapid succession and intermediate persistence states are returned by the observe function.
updatedModel = this.applyGetInterceptors(identifier, updatedModel);
mutableObject.$refresh(updatedModel);
}
@ -706,10 +628,10 @@ export default class ObjectAPI {
/**
* Updates a domain object based on its latest persisted state. Note that this will mutate the provided object.
* @param {module:openmct.DomainObject} domainObject an object to refresh from its persistence store
* @param {DomainObject} domainObject an object to refresh from its persistence store
* @param {boolean} [forceRemote=false] defaults to false. If true, will skip cached and
* dirty/in-transaction objects use and the provider.get method
* @returns {Promise} the provided object, updated to reflect the latest persisted state of the object.
* @returns {Promise<DomainObject>} the provided object, updated to reflect the latest persisted state of the object.
*/
async refresh(domainObject, forceRemote = false) {
const refreshedObject = await this.get(domainObject.identifier, null, forceRemote);
@ -724,7 +646,8 @@ export default class ObjectAPI {
}
/**
* @param module:openmct.ObjectAPI~Identifier identifier An object identifier
* Determine if the object can be mutated.
* @param {Identifier} identifier An object identifier
* @returns {boolean} true if the object can be mutated, otherwise returns false
*/
supportsMutation(identifier) {
@ -733,12 +656,10 @@ export default class ObjectAPI {
/**
* Observe changes to a domain object.
* @param {module:openmct.DomainObject} object the object to observe
* @param {DomainObject} domainObject the object to observe
* @param {string} path the property to observe
* @param {Function} callback a callback to invoke when new values for
* this property are observed.
* @method observe
* @memberof module:openmct.ObjectAPI#
* @param {Function} callback a callback to invoke when new values for this property are observed.
* @returns {() => void} a function to unsubscribe from the updates
*/
observe(domainObject, path, callback) {
if (domainObject.isMutable) {
@ -785,7 +706,7 @@ export default class ObjectAPI {
/**
* Given an original path check if the path is reachable via root
* @param {Array<Object>} originalPath an array of path objects to check
* @param {Array<DomainObject>} originalPath an array of path objects to check
* @returns {boolean} whether the domain object is reachable
*/
isReachable(originalPath) {
@ -796,6 +717,12 @@ export default class ObjectAPI {
return false;
}
/**
* Check if a path contains a domain object with a given key string
* @param {string} keyStringToCheck the keystring to check for
* @param {Array<DomainObject>} path the path to check
* @returns {boolean} true if the path contains a DomainObject with the given keystring, otherwise false
*/
#pathContainsDomainObject(keyStringToCheck, path) {
if (!keyStringToCheck) {
return false;
@ -810,10 +737,10 @@ export default class ObjectAPI {
/**
* Given an identifier, constructs the original path by walking up its parents
* @param {module:openmct.ObjectAPI~Identifier} identifier
* @param {Array<module:openmct.DomainObject>} path an array of path objects
* @param {Identifier} identifier
* @param {Array<DomainObject>} path an array of path objects
* @param {AbortSignal} abortSignal (optional) signal to abort fetch requests
* @returns {Promise<Array<module:openmct.DomainObject>>} a promise containing an array of domain objects
* @returns {Promise<Array<DomainObject>>} a promise containing an array of domain objects
*/
async getOriginalPath(identifier, path = [], abortSignal = null) {
const domainObject = await this.get(identifier, abortSignal);
@ -873,6 +800,12 @@ export default class ObjectAPI {
return objectPath;
}
/**
* Check if the object is a link based on its path
* @param {DomainObject} domainObject the DomainObject to check
* @param {Array<DomainObject>} objectPath the object path to check
* @returns {boolean} true if the object path is a link, otherwise false
*/
isObjectPathToALink(domainObject, objectPath) {
return (
objectPath !== undefined &&
@ -881,10 +814,19 @@ export default class ObjectAPI {
);
}
/**
* Check if a transaction is active
* @returns {boolean} true if a transaction is active, otherwise false
*/
isTransactionActive() {
return this.transaction !== undefined && this.transaction !== null;
}
/**
* Check if a domain object has already been persisted
* @param {DomainObject} domainObject the domain object to check
* @returns {boolean} true if the domain object has already been persisted, otherwise false
*/
#hasAlreadyBeenPersisted(domainObject) {
// modified can sometimes be undefined, so make it 0 in this case
const modified = domainObject.modified ?? Number.MIN_SAFE_INTEGER;

View File

@ -20,7 +20,13 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* Provides the root object for the Open MCT application.
*/
class RootObjectProvider {
/**
* @param {RootRegistry} rootRegistry - The registry containing root objects.
*/
constructor(rootRegistry) {
if (!RootObjectProvider.instance) {
this.rootRegistry = rootRegistry;
@ -42,10 +48,18 @@ class RootObjectProvider {
return RootObjectProvider.instance; // eslint-disable-line no-constructor-return
}
/**
* Updates the name of the root object.
* @param {string} name - The new name for the root object.
*/
updateName(name) {
this.rootObject.name = name;
}
/**
* Retrieves the root object with updated composition.
* @returns {Promise<RootObject>} A promise that resolves to the root object.
*/
async get() {
let roots = await this.rootRegistry.getRoots();
this.rootObject.composition = roots;
@ -54,8 +68,30 @@ class RootObjectProvider {
}
}
/**
* Creates or returns an instance of RootObjectProvider.
* @param {RootRegistry} rootRegistry - The registry containing root objects.
* @returns {RootObjectProvider} An instance of RootObjectProvider.
*/
function instance(rootRegistry) {
return new RootObjectProvider(rootRegistry);
}
export default instance;
/**
* @typedef {import('openmct').Identifier} Identifier
*/
/**
* @typedef {Object} RootObject
* @property {Identifier} identifier - The identifier of the root object.
* @property {string} name - The name of the root object.
* @property {string} type - The type of the root object.
* @property {Identifier[]} composition - The composition of the root object.
*/
/**
* @typedef {Object} RootRegistry
* @property {() => Promise<Identifier[]>} getRoots - A method that returns a promise resolving to an array of root identifiers.
*/

View File

@ -22,12 +22,24 @@
import { isIdentifier } from './object-utils.js';
/**
* Registry for managing root items in Open MCT.
*/
export default class RootRegistry {
/**
* @param {OpenMCT} openmct - The Open MCT instance.
*/
constructor(openmct) {
/** @type {Array<RootItemEntry>} */
this._rootItems = [];
/** @type {OpenMCT} */
this._openmct = openmct;
}
/**
* Get all registered root items.
* @returns {Promise<Array<Identifier>>} A promise that resolves to an array of root item identifiers.
*/
getRoots() {
const sortedItems = this._rootItems.sort((a, b) => b.priority - a.priority);
const promises = sortedItems.map((rootItem) => rootItem.provider());
@ -35,6 +47,11 @@ export default class RootRegistry {
return Promise.all(promises).then((rootItems) => rootItems.flat());
}
/**
* Add a root item to the registry.
* @param {RootItemInput} rootItem - The root item to add.
* @param {number} [priority] - The priority of the root item.
*/
addRoot(rootItem, priority) {
if (!this._isValid(rootItem)) {
return;
@ -46,6 +63,12 @@ export default class RootRegistry {
});
}
/**
* Validate a root item.
* @param {RootItemInput} rootItem - The root item to validate.
* @returns {boolean} True if the root item is valid, false otherwise.
* @private
*/
_isValid(rootItem) {
if (isIdentifier(rootItem) || typeof rootItem === 'function') {
return true;
@ -58,3 +81,15 @@ export default class RootRegistry {
return false;
}
}
/**
* @typedef {Object} RootItemEntry
* @property {number} priority - The priority of the root item.
* @property {() => Promise<Identifier | Identifier[]>} provider - A function that returns a promise resolving to a root item or an array of root items.
*/
/**
* @typedef {import('openmct').Identifier} Identifier
* @typedef {Identifier | Identifier[] | (() => Promise<Identifier | Identifier[]>)} RootItemInput
* @typedef {import('openmct').OpenMCT} OpenMCT
*/

View File

@ -20,22 +20,42 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* Represents a transaction for managing changes to domain objects.
*/
export default class Transaction {
/**
* @param {import('./ObjectAPI').default} objectAPI - The object API instance.
*/
constructor(objectAPI) {
/** @type {Record<string, DomainObject>} */
this.dirtyObjects = {};
/** @type {import('./ObjectAPI').default} */
this.objectAPI = objectAPI;
}
/**
* Adds an object to the transaction.
* @param {DomainObject} object - The object to add.
*/
add(object) {
const key = this.objectAPI.makeKeyString(object.identifier);
this.dirtyObjects[key] = object;
}
/**
* Cancels the transaction and reverts changes.
* @returns {Promise<void[]>}
*/
cancel() {
return this._clear();
}
/**
* Commits the transaction and saves changes.
* @returns {Promise<void[]>}
*/
commit() {
const promiseArray = [];
const save = this.objectAPI.save.bind(this.objectAPI);
@ -47,6 +67,14 @@ export default class Transaction {
return Promise.all(promiseArray);
}
/**
* Creates a promise for handling a dirty object.
* @template T
* @param {DomainObject} object - The dirty object.
* @param {(object: DomainObject, ...args: any[]) => Promise<T>} action - The action to perform.
* @param {...any} args - Additional arguments for the action.
* @returns {Promise<T>}
*/
createDirtyObjectPromise(object, action, ...args) {
return new Promise((resolve, reject) => {
action(object, ...args)
@ -60,6 +88,11 @@ export default class Transaction {
});
}
/**
* Retrieves a dirty object by its identifier.
* @param {Identifier} identifier - The object identifier.
* @returns {DomainObject | undefined}
*/
getDirtyObject(identifier) {
let dirtyObject;
@ -73,6 +106,11 @@ export default class Transaction {
return dirtyObject;
}
/**
* Clears the transaction and refreshes objects.
* @returns {Promise<void[]>}
* @private
*/
_clear() {
const promiseArray = [];
const action = (obj) => this.objectAPI.refresh(obj, true);
@ -84,3 +122,8 @@ export default class Transaction {
return Promise.all(promiseArray);
}
}
/**
* @typedef {import('openmct').DomainObject} DomainObject
* @typedef {import('openmct').Identifier} Identifier
*/

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import mount from 'utils/mount';
import OverlayComponent from './components/OverlayComponent.vue';

View File

@ -29,11 +29,7 @@ import Selection from './Selection.js';
* The OverlayAPI is responsible for pre-pending templates to
* the body of the document, which is useful for displaying templates
* which need to block the full screen.
*
* @memberof api/overlays
* @constructor
*/
class OverlayAPI {
constructor() {
this.activeOverlays = [];
@ -48,7 +44,9 @@ class OverlayAPI {
}
/**
* private
* Shows an overlay
* @private
* @param {Overlay} overlay - The overlay to show
*/
showOverlay(overlay) {
if (this.activeOverlays.length) {
@ -72,7 +70,8 @@ class OverlayAPI {
}
/**
* private
* Dismisses the last overlay
* @private
*/
dismissLastOverlay() {
let lastOverlay = this.activeOverlays[this.activeOverlays.length - 1];
@ -83,14 +82,6 @@ class OverlayAPI {
/**
* Creates and displays an overlay with the specified options.
*
* @typedef {Object} OverlayOptions
* @property {HTMLElement} element The DOM Element to be inserted or shown in the overlay.
* @property {'large'|'small'|'fit'} size The preferred size of the overlay.
* @property {Array<{label: string, callback: Function}>} [buttons] Optional array of button objects, each with 'label' and 'callback' properties.
* @property {Function} onDestroy Callback to be called when the overlay is destroyed.
* @property {boolean} [dismissible=true] Whether the overlay can be dismissed by pressing 'esc' or clicking outside of it. Defaults to true.
*
* @param {OverlayOptions} options - The configuration options for the overlay.
* @returns {Overlay} An instance of the Overlay class.
*/
@ -104,23 +95,9 @@ class OverlayAPI {
/**
* Displays a blocking (modal) dialog. This dialog can be used for
* displaying messages that require the user's
* immediate attention.
* @param {model} options defines options for the dialog
* @returns {Object} with an object with a dismiss function that can be called from the calling code
* to dismiss/destroy the dialog
*
* A description of the model options that may be passed to the
* dialog method. Note that the DialogModel described
* here is shared with the Notifications framework.
* @see NotificationService
*
* @typedef options
* @property {string} title the title to use for the dialog
* @property {string} iconClass class to apply to icon that is shown on dialog
* @property {string} message text that indicates a current message,
* @property {buttons[]} buttons a list of buttons with title and callback properties that will
* be added to the dialog.
* displaying messages that require the user's immediate attention.
* @param {DialogOptions} options - Defines options for the dialog
* @returns {Dialog} An object with a dismiss function that can be called from the calling code to dismiss/destroy the dialog
*/
dialog(options) {
let dialog = new Dialog(options);
@ -133,21 +110,10 @@ class OverlayAPI {
/**
* Displays a blocking (modal) progress dialog. This dialog can be used for
* displaying messages that require the user's attention, and show progress
* @param {model} options defines options for the dialog
* @returns {Object} with an object with a dismiss function that can be called from the calling code
* @param {ProgressDialogOptions} options - Defines options for the dialog
* @returns {ProgressDialog} An object with a dismiss function that can be called from the calling code
* to dismiss/destroy the dialog and an updateProgress function that takes progressPercentage(Number 0-100)
* and progressText (string)
*
* A description of the model options that may be passed to the
* dialog method. Note that the DialogModel described
* here is shared with the Notifications framework.
* @see NotificationService
*
* @typedef options
* @property {number | null} progressPerc the initial progress value (0-100) or null for anonymous progress
* @property {string} progressText the initial text to be shown under the progress bar
* @property {buttons[]} buttons a list of buttons with title and callback properties that will
* be added to the dialog.
*/
progressDialog(options) {
let progressDialog = new ProgressDialog(options);
@ -157,6 +123,11 @@ class OverlayAPI {
return progressDialog;
}
/**
* Creates and displays a selection overlay
* @param {SelectionOptions} options - The options for the selection overlay
* @returns {Selection} The created Selection instance
*/
selection(options) {
let selection = new Selection(options);
this.showOverlay(selection);
@ -166,3 +137,32 @@ class OverlayAPI {
}
export default OverlayAPI;
/**
* @typedef {Object} OverlayOptions
* @property {HTMLElement} element - The DOM Element to be inserted or shown in the overlay.
* @property {'large'|'small'|'fit'} size - The preferred size of the overlay.
* @property {Array<{label: string, callback: Function}>} [buttons] - Optional array of button objects, each with 'label' and 'callback' properties.
* @property {Function} onDestroy - Callback to be called when the overlay is destroyed.
* @property {boolean} [dismissible=true] - Whether the overlay can be dismissed by pressing 'esc' or clicking outside of it. Defaults to true.
*/
/**
* @typedef {Object} DialogOptions
* @property {string} title - The title to use for the dialog
* @property {string} iconClass - Class to apply to icon that is shown on dialog
* @property {string} message - Text that indicates a current message
* @property {Array<{label: string, callback: Function}>} buttons - A list of buttons with label and callback properties that will be added to the dialog.
*/
/**
* @typedef {Object} ProgressDialogOptions
* @property {number | null} progressPerc - The initial progress value (0-100) or null for anonymous progress
* @property {string} progressText - The initial text to be shown under the progress bar
* @property {Array<{label: string, callback: Function}>} buttons - A list of buttons with label and callback properties that will be added to the dialog.
*/
/**
* @typedef {Object} SelectionOptions
* @property {any} options - The options for the selection overlay
*/

View File

@ -20,13 +20,29 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
/**
* @typedef {import('openmct').OpenMCT} OpenMCT
* @typedef {import('openmct').Identifier} Identifier
* @typedef {string} Status
*/
import { EventEmitter } from 'eventemitter3';
/**
* Get, set, and observe statuses for Open MCT objects. A status is a string
* that represents the current state of an object.
*
* @extends EventEmitter
*/
export default class StatusAPI extends EventEmitter {
/**
* Constructs a new instance of the StatusAPI class.
* @param {OpenMCT} openmct - The Open MCT application instance.
*/
constructor(openmct) {
super();
this._openmct = openmct;
/** @type {Record<string, Status>} */
this._statusCache = {};
this.get = this.get.bind(this);
@ -34,19 +50,33 @@ export default class StatusAPI extends EventEmitter {
this.observe = this.observe.bind(this);
}
/**
* Retrieves the status of the object with the given identifier.
* @param {Identifier} identifier - The identifier of the object.
* @returns {Status | undefined} The status of the object, or undefined if the object's status is not cached.
*/
get(identifier) {
let keyString = this._openmct.objects.makeKeyString(identifier);
return this._statusCache[keyString];
}
set(identifier, value) {
/**
* Sets the status of the object with the given identifier.
* @param {Identifier} identifier - The identifier of the object.
* @param {Status} status - The new status value for the object.
*/
set(identifier, status) {
let keyString = this._openmct.objects.makeKeyString(identifier);
this._statusCache[keyString] = value;
this.emit(keyString, value);
this._statusCache[keyString] = status;
this.emit(keyString, status);
}
/**
* Deletes the status of the object with the given identifier.
* @param {Identifier} identifier - The identifier of the object.
*/
delete(identifier) {
let keyString = this._openmct.objects.makeKeyString(identifier);
@ -55,6 +85,13 @@ export default class StatusAPI extends EventEmitter {
delete this._statusCache[keyString];
}
/**
* Observes the status of the object with the given identifier, and calls the provided callback
* function whenever the status changes.
* @param {Identifier} identifier - The identifier of the object.
* @param {(value: any) => void} callback - The function to be called whenever the status changes.
* @returns {() => void} A function that can be called to stop observing the status.
*/
observe(identifier, callback) {
let key = this._openmct.objects.makeKeyString(identifier);

View File

@ -48,7 +48,6 @@ import installWorker from './WebSocketWorker.js';
* concerns are not handled on the main event loop. This allows for performant receipt
* and batching of messages without blocking either the UI or server.
*
* @memberof module:openmct.telemetry
*/
// Shim for Internet Explorer, I mean Safari. It doesn't support requestIdleCallback, but it's in a tech preview, so it will be dropping soon.
const requestIdleCallback =

View File

@ -52,7 +52,6 @@ import TelemetryValueFormatter from './TelemetryValueFormatter.js';
* to cancel a telemetry request
* @property {string} [domain] the domain key of the request
* @property {TimeContext} [timeContext] the time context to use for this request
* @memberof module:openmct.TelemetryAPI~
*/
/**
@ -69,7 +68,6 @@ import TelemetryValueFormatter from './TelemetryValueFormatter.js';
* rendering a telemetry plot or table. If `batch` is specified, the subscription
* callback will be invoked with an Array.
*
* @memberof module:openmct.TelemetryAPI~
*/
const SUBSCRIBE_STRATEGY = {
@ -80,7 +78,6 @@ const SUBSCRIBE_STRATEGY = {
/**
* Utilities for telemetry
* @interface TelemetryAPI
* @memberof module:openmct
*/
export default class TelemetryAPI {
#isGreedyLAD;
@ -133,7 +130,7 @@ export default class TelemetryAPI {
* object is any object which has telemetry metadata-- regardless of whether
* the telemetry object has an available telemetry provider.
*
* @param {module:openmct.DomainObject} domainObject
* @param {import('openmct').DomainObject} domainObject
* @returns {boolean} true if the object is a telemetry object.
*/
isTelemetryObject(domainObject) {
@ -145,10 +142,9 @@ export default class TelemetryAPI {
* this domain object.
*
* @method canProvideTelemetry
* @param {module:openmct.DomainObject} domainObject the object for
* @param {import('openmct').DomainObject} domainObject the object for
* which telemetry would be provided
* @returns {boolean} true if telemetry can be provided
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
canProvideTelemetry(domainObject) {
return (
@ -161,7 +157,6 @@ export default class TelemetryAPI {
* Register a telemetry provider with the telemetry service. This
* allows you to connect alternative telemetry sources.
* @method addProvider
* @memberof module:openmct.TelemetryAPI#
* @param {module:openmct.TelemetryAPI~TelemetryProvider} provider the new
* telemetry provider
*/
@ -268,7 +263,6 @@ export default class TelemetryAPI {
*
* @param {module:openmct.RequestInterceptorDef} requestInterceptorDef the request interceptor definition to add
* @method addRequestInterceptor
* @memberof module:openmct.TelemetryRequestInterceptorRegistry#
*/
addRequestInterceptor(requestInterceptorDef) {
this.requestInterceptorRegistry.addInterceptor(requestInterceptorDef);
@ -312,7 +306,6 @@ export default class TelemetryAPI {
*
* @method greedyLAD
* @returns {boolean} if greedyLAD is active or not
* @memberof module:openmct.TelemetryAPI#
*/
greedyLAD(isGreedy) {
if (arguments.length > 0) {
@ -333,8 +326,7 @@ export default class TelemetryAPI {
* telemetry (aggregation, latest available, etc.).
*
* @method requestCollection
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
* @param {module:openmct.DomainObject} domainObject the object
* @param {import('openmct').DomainObject} domainObject the object
* which has associated telemetry
* @param {TelemetryRequestOptions} options
* options for this telemetry collection request
@ -351,8 +343,7 @@ export default class TelemetryAPI {
* telemetry (aggregation, latest available, etc.).
*
* @method request
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
* @param {module:openmct.DomainObject} domainObject the object
* @param {import('openmct').DomainObject} domainObject the object
* which has associated telemetry
* @param {TelemetryRequestOptions} options
* options for this historical request
@ -410,8 +401,7 @@ export default class TelemetryAPI {
* realtime provider.
*
* @method subscribe
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
* @param {module:openmct.DomainObject} domainObject the object
* @param {import('openmct').DomainObject} domainObject the object
* which has associated telemetry
* @param {TelemetrySubscriptionOptions} options configuration items for subscription
* @param {Function} callback the callback to invoke with new data, as
@ -527,8 +517,7 @@ export default class TelemetryAPI {
* The callback will be called whenever staleness changes.
*
* @method subscribeToStaleness
* @memberof module:openmct.TelemetryAPI~StalenessProvider#
* @param {module:openmct.DomainObject} domainObject the object
* @param {import('openmct').DomainObject} domainObject the object
* to watch for staleness updates
* @param {Function} callback the callback to invoke with staleness data,
* as it is received: ex.
@ -586,8 +575,7 @@ export default class TelemetryAPI {
* limit provider.
*
* @method subscribeToLimits
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
* @param {module:openmct.DomainObject} domainObject the object
* @param {import('openmct').DomainObject} domainObject the object
* which has associated limits
* @param {Function} callback the callback to invoke with new data, as
* it becomes available
@ -640,8 +628,7 @@ export default class TelemetryAPI {
* Request telemetry staleness for a domain object.
*
* @method isStale
* @memberof module:openmct.TelemetryAPI~StalenessProvider#
* @param {module:openmct.DomainObject} domainObject the object
* @param {import('openmct').DomainObject} domainObject the object
* which has associated telemetry staleness
* @returns {Promise.<StalenessResponseObject>} a promise for a StalenessResponseObject
* or undefined if no provider exists
@ -727,7 +714,7 @@ export default class TelemetryAPI {
* Get a format map of all value formatters for a given piece of telemetry
* metadata.
*
* @returns {Object<String, {TelemetryValueFormatter}>}
* @returns {Record<string, TelemetryValueFormatter>}
*/
getFormatMap(metadata) {
if (!metadata) {
@ -801,11 +788,10 @@ export default class TelemetryAPI {
* If a provider does not implement this method, it is presumed
* that no limits are defined for this domain object's telemetry.
*
* @param {module:openmct.DomainObject} domainObject the domain
* @param {import('openmct').DomainObject} domainObject the domain
* object for which to evaluate limits
* @returns {module:openmct.TelemetryAPI~LimitEvaluator}
* @method limitEvaluator
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
limitEvaluator(domainObject) {
return this.getLimitEvaluator(domainObject);
@ -821,11 +807,10 @@ export default class TelemetryAPI {
* If a provider does not implement this method, it is presumed
* that no limits are defined for this domain object's telemetry.
*
* @param {module:openmct.DomainObject} domainObject the domain
* @param {import('openmct').DomainObject} domainObject the domain
* object for which to get limits
* @returns {LimitsResponseObject}
* @method limits
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
limitDefinition(domainObject) {
return this.getLimits(domainObject);
@ -841,11 +826,10 @@ export default class TelemetryAPI {
* If a provider does not implement this method, it is presumed
* that no limits are defined for this domain object's telemetry.
*
* @param {module:openmct.DomainObject} domainObject the domain
* @param {import('openmct').DomainObject} domainObject the domain
* object for which to evaluate limits
* @returns {module:openmct.TelemetryAPI~LimitEvaluator}
* @method limitEvaluator
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
getLimitEvaluator(domainObject) {
const provider = this.#findLimitEvaluator(domainObject);
@ -868,12 +852,11 @@ export default class TelemetryAPI {
* If a provider does not implement this method, it is presumed
* that no limits are defined for this domain object's telemetry.
*
* @param {module:openmct.DomainObject} domainObject the domain
* @param {import('openmct').DomainObject} domainObject the domain
* object for which to display limits
* @returns {LimitsResponseObject}
* @method limits returns a limits object of type {LimitsResponseObject}
* supported colors are purple, red, orange, yellow and cyan
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
getLimits(domainObject) {
const provider = this.#findLimitEvaluator(domainObject);
@ -911,7 +894,6 @@ export default class TelemetryAPI {
* have exceeded nominal conditions.
*
* @interface LimitEvaluator
* @memberof module:openmct.TelemetryAPI~
*/
/**
@ -919,7 +901,6 @@ export default class TelemetryAPI {
* @method evaluate
* @param {*} datum the telemetry datum to evaluate
* @param {TelemetryProperty} the property to check for limit violations
* @memberof module:openmct.TelemetryAPI~LimitEvaluator
* @returns {LimitViolation} metadata about
* the limit violation, or undefined if a value is within limits
*/
@ -927,7 +908,6 @@ export default class TelemetryAPI {
/**
* A violation of limits defined for a telemetry property.
* @typedef LimitViolation
* @memberof {module:openmct.TelemetryAPI~}
* @property {string} cssClass the class (or space-separated classes) to
* apply to display elements for values which violate this limit
* @property {string} name the human-readable name for the limit violation
@ -937,7 +917,6 @@ export default class TelemetryAPI {
/**
* @typedef {Object} LimitsResponseObject
* @memberof {module:openmct.TelemetryAPI~}
* @property {LimitDefinition} limitLevel the level name and it's limit definition
* @example {
* [limitLevel]: {
@ -956,7 +935,6 @@ export default class TelemetryAPI {
/**
* Limit defined for a telemetry property.
* @typedef LimitDefinition
* @memberof {module:openmct.TelemetryAPI~}
* @property {LimitDefinitionValue} low a lower limit
* @property {LimitDefinitionValue} high a higher limit
*/
@ -964,7 +942,6 @@ export default class TelemetryAPI {
/**
* Limit definition for a Limit of a telemetry property.
* @typedef LimitDefinitionValue
* @memberof {module:openmct.TelemetryAPI~}
* @property {string} color color to represent this limit
* @property {number} value the limit value
*/
@ -974,7 +951,6 @@ export default class TelemetryAPI {
* display as text.
*
* @interface TelemetryFormatter
* @memberof module:openmct.TelemetryAPI~
*/
/**
@ -982,7 +958,6 @@ export default class TelemetryAPI {
* telemetry metadata in domain object.
*
* @method format
* @memberof module:openmct.TelemetryAPI~TelemetryFormatter#
*/
/**
@ -990,7 +965,6 @@ export default class TelemetryAPI {
* associated with a particular domain object.
*
* @typedef TelemetryProperty
* @memberof module:openmct.TelemetryAPI~
* @property {string} key the name of the property in the datum which
* contains this telemetry value
* @property {string} name the human-readable name for this property
@ -1010,7 +984,6 @@ export default class TelemetryAPI {
* Describes and bounds requests for telemetry data.
*
* @typedef TelemetryRequest
* @memberof module:openmct.TelemetryAPI~
* @property {string} sort the key of the property to sort by. This may
* be prefixed with a "+" or a "-" sign to sort in ascending
* or descending order respectively. If no prefix is present,
@ -1029,7 +1002,6 @@ export default class TelemetryAPI {
* [registered]{@link module:openmct.TelemetryAPI#addProvider}.
*
* @interface TelemetryProvider
* @memberof module:openmct.TelemetryAPI~
*/
/**
@ -1046,7 +1018,6 @@ export default class TelemetryAPI {
* and an options object which currently has an abort signal, ex.
* { signal: <AbortController.signal> }
* this method should return a current StalenessResponseObject
* @memberof module:openmct.TelemetryAPI~
*/
/**
@ -1061,5 +1032,4 @@ export default class TelemetryAPI {
*
* @interface TelemetryAPI
* @augments module:openmct.TelemetryAPI~TelemetryProvider
* @memberof module:openmct
*/

View File

@ -20,14 +20,14 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import { TIME_CONTEXT_EVENTS } from '../time/constants.js';
import { LOADED_ERROR, TIMESYSTEM_KEY_NOTIFICATION, TIMESYSTEM_KEY_WARNING } from './constants.js';
/**
* @typedef {import('../objects/ObjectAPI').DomainObject} DomainObject
* @typedef {import('openmct').DomainObject} DomainObject
*/
/**

View File

@ -25,7 +25,6 @@ export default class TelemetryRequestInterceptorRegistry {
* A TelemetryRequestInterceptorRegistry maintains the definitions for different interceptors that may be invoked on telemetry
* requests.
* @interface TelemetryRequestInterceptorRegistry
* @memberof module:openmct
*/
constructor() {
this.interceptors = [];
@ -36,7 +35,6 @@ export default class TelemetryRequestInterceptorRegistry {
* @property {function} appliesTo function that determines if this interceptor should be called for the given identifier/request
* @property {function} invoke function that transforms the provided request and returns the transformed request
* @property {function} priority the priority for this interceptor. A higher number returned has more weight than a lower number
* @memberof module:openmct TelemetryRequestInterceptorRegistry#
*/
/**
@ -44,7 +42,6 @@ export default class TelemetryRequestInterceptorRegistry {
*
* @param {module:openmct.RequestInterceptorDef} requestInterceptorDef the interceptor to add
* @method addInterceptor
* @memberof module:openmct.TelemetryRequestInterceptorRegistry#
*/
addInterceptor(interceptorDef) {
//TODO: sort by priority
@ -55,7 +52,6 @@ export default class TelemetryRequestInterceptorRegistry {
* Retrieve all interceptors applicable to a domain object/request.
* @method getInterceptors
* @returns [module:openmct.RequestInterceptorDef] the registered interceptors for this identifier/request
* @memberof module:openmct.TelemetryRequestInterceptorRegistry#
*/
getInterceptors(identifier, request) {
return this.interceptors.filter((interceptor) => {

View File

@ -165,7 +165,6 @@ class IndependentTimeContext extends TimeContext {
/**
* Get the time system of the TimeAPI.
* @returns {TimeSystem} The currently applied time system
* @memberof module:openmct.TimeAPI#
* @method getTimeSystem
* @override
*/
@ -214,7 +213,6 @@ class IndependentTimeContext extends TimeContext {
/**
* The active clock has changed.
* @event clock
* @memberof module:openmct.TimeAPI~
* @property {Clock} clock The newly activated clock, or undefined
* if the system is no longer following a clock source
*/
@ -286,7 +284,6 @@ class IndependentTimeContext extends TimeContext {
/**
* The active clock has changed.
* @event clock
* @memberof module:openmct.TimeAPI~
* @property {Clock} clock The newly activated clock, or undefined
* if the system is no longer following a clock source
*/
@ -333,7 +330,6 @@ class IndependentTimeContext extends TimeContext {
/**
* The active mode has changed.
* @event modeChanged
* @memberof module:openmct.TimeAPI~
* @property {Mode} mode The newly activated mode
*/
this.emit(TIME_CONTEXT_EVENTS.modeChanged, this.#copy(this.mode));

View File

@ -107,7 +107,6 @@ class TimeAPI extends GlobalTimeContext {
* automatically update the time bounds of the data displayed in Open MCT.
*
* @typedef {Object} Clock
* @memberof openmct.timeAPI
* @property {string} key A unique identifier
* @property {string} name A human-readable name. The name will be used to
* represent this clock in the Time Conductor UI

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'eventemitter3';
import { EventEmitter } from 'eventemitter3';
import { FIXED_MODE_KEY, MODES, REALTIME_MODE_KEY, TIME_CONTEXT_EVENTS } from './constants.js';
@ -34,7 +34,7 @@ import { FIXED_MODE_KEY, MODES, REALTIME_MODE_KEY, TIME_CONTEXT_EVENTS } from '.
/**
* @typedef {Object} TimeConductorBounds
* @property {number} start The start time displayed by the time conductor
* @property {number } start The start time displayed by the time conductor
* in ms since epoch. Epoch determined by currently active time system
* @property {number} end The end time displayed by the time conductor in ms
* since epoch.
@ -301,7 +301,6 @@ class TimeContext extends EventEmitter {
/**
* Event that is triggered when clock offsets change.
* @event clockOffsets
* @memberof module:openmct.TimeAPI~
* @property {ClockOffsets} clockOffsets The newly activated clock
* offsets.
*/
@ -426,8 +425,8 @@ class TimeContext extends EventEmitter {
/**
* Set the time system of the TimeAPI.
* Emits a "timeSystem" event with the new time system.
* @param {TimeSystem | string} timeSystemOrKey The time system to set, or its key
* @param {TimeConductorBounds} [bounds] Optional bounds to set
* @param {TimeSystem | string} timeSystemOrKey
* @param {TimeConductorBounds} bounds
*/
setTimeSystem(timeSystemOrKey, bounds) {
if (timeSystemOrKey === undefined) {
@ -546,7 +545,6 @@ class TimeContext extends EventEmitter {
/**
* The active clock has changed.
* @event clock
* @memberof module:openmct.TimeAPI~
* @property {TimeContext} clock The newly activated clock, or undefined
* if the system is no longer following a clock source
*/

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import mount from 'utils/mount';
import TooltipComponent from './components/TooltipComponent.vue';

View File

@ -43,7 +43,6 @@ const TOOLTIP_LOCATIONS = Object.freeze({
* The TooltipAPI is responsible for adding custom tooltips to
* the desired elements on the screen
*
* @memberof api/tooltips
* @constructor
*/

View File

@ -23,12 +23,11 @@
/**
* A Type describes a kind of domain object that may appear or be
* created within Open MCT.
*
* @param {module:openmct.TypeRegistry~TypeDefinition} definition
* @class Type
* @memberof module:openmct
*/
export default class Type {
/**
* @param {TypeDefinition} definition
*/
constructor(definition) {
this.definition = definition;
if (definition.key) {
@ -36,7 +35,9 @@ export default class Type {
}
}
/**
* Create a type definition from a legacy definition.
* Convert a legacy type definition to the new format.
* @param {LegacyTypeDefinition} legacyDefinition
* @returns {TypeDefinition}
*/
static definitionFromLegacyDefinition(legacyDefinition) {
let definition = {};
@ -86,10 +87,8 @@ export default class Type {
}
/**
* Check if a domain object is an instance of this type.
* @param domainObject
* @param {DomainObject} domainObject
* @returns {boolean} true if the domain object is of this type
* @memberof module:openmct.Type#
* @method check
*/
check(domainObject) {
// Depends on assignment from MCT.
@ -119,3 +118,19 @@ export default class Type {
return def;
}
}
/**
* @typedef {Object} TypeDefinition
* @property {string} [key]
* @property {string} name
* @property {string} cssClass
* @property {string} description
* @property {Form} form
* @property {Telemetry} telemetry
* @property {function(Object): void} initialize
* @property {boolean} creatable
*/
/**
* @typedef {import('openmct').DomainObject} DomainObject
*/

View File

@ -29,12 +29,11 @@ const UNKNOWN_TYPE = new Type({
/**
* @typedef TypeDefinition
* @memberof module:openmct.TypeRegistry~
* @property {string} label the name for this type of object
* @property {string} description a longer-form description of this type
* @property {function (object)} [initialize] a function which initializes
* @property {function(domainObject:DomainObject): void} [initialize] a function which initializes
* the model for new domain objects of this type
* @property {boolean} [creatable] true if users should be allowed to
* @property {boolean} [creatable=false] true if users should be allowed to
* create this type (default: false)
* @property {string} [cssClass] the CSS class to apply for icons
*/
@ -43,19 +42,19 @@ const UNKNOWN_TYPE = new Type({
* A TypeRegistry maintains the definitions for different types
* that domain objects may have.
* @interface TypeRegistry
* @memberof module:openmct
*/
export default class TypeRegistry {
constructor() {
/**
* @type {Record<string, Type>}
*/
this.types = {};
}
/**
* Register a new object type.
*
* @param {string} typeKey a string identifier for this type
* @param {module:openmct.Type} type the type to add
* @method addType
* @memberof module:openmct.TypeRegistry#
* @param {TypeDefinition} typeDef the type to add
*/
addType(typeKey, typeDef) {
this.standardizeType(typeDef);
@ -77,8 +76,6 @@ export default class TypeRegistry {
}
/**
* List keys for all registered types.
* @method listKeys
* @memberof module:openmct.TypeRegistry#
* @returns {string[]} all registered type keys
*/
listKeys() {
@ -86,10 +83,8 @@ export default class TypeRegistry {
}
/**
* Retrieve a registered type by its key.
* @method get
* @param {string} typeKey the key for this type
* @memberof module:openmct.TypeRegistry#
* @returns {module:openmct.Type} the registered type
* @returns {Type} the registered type
*/
get(typeKey) {
return this.types[typeKey] || UNKNOWN_TYPE;

View File

@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
/**
* The StatusAPI is used to get and set various statuses linked to the current logged in user.

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { MULTIPLE_PROVIDER_ERROR, NO_PROVIDER_ERROR } from './constants.js';
import StatusAPI from './StatusAPI.js';
@ -28,27 +28,27 @@ import StoragePersistence from './StoragePersistence.js';
import User from './User.js';
class UserAPI extends EventEmitter {
/** @type {OpenMCT} */
/**
* @type {OpenMCT}
*/
#openmct;
/**
* @param {OpenMCT} openmct
* @param {UserAPIConfiguration} config
*/
constructor(openmct, config) {
constructor(openmct) {
super();
this.#openmct = openmct;
this._provider = undefined;
this.User = User;
this.status = new StatusAPI(this, openmct, config);
this.status = new StatusAPI(this, openmct);
}
/**
* Set the user provider for the user API. This allows you
* to specify ONE user provider to be used with Open MCT.
* @method setProvider
* @memberof module:openmct.UserAPI#
* @param {module:openmct.UserAPI~UserProvider} provider the new
* user provider
*/
@ -68,7 +68,6 @@ class UserAPI extends EventEmitter {
/**
* Return true if the user provider has been set.
*
* @memberof module:openmct.UserAPI#
* @returns {boolean} true if the user provider exists
*/
hasProvider() {
@ -79,7 +78,6 @@ class UserAPI extends EventEmitter {
* If a user provider is set, it will return a copy of a user object from
* the provider. If the user is not logged in, it will return undefined;
*
* @memberof module:openmct.UserAPI#
* @returns {Function|Promise} user provider 'getCurrentUser' method
* @throws Will throw an error if no user provider is set
*/
@ -93,7 +91,6 @@ class UserAPI extends EventEmitter {
/**
* If a user provider is set, it will return an array of possible roles
* that can be selected by the current user
* @memberof module:openmct.UserAPI#
* @returns {Array}
* @throws Will throw an error if no user provider is set
*/
@ -106,7 +103,6 @@ class UserAPI extends EventEmitter {
}
/**
* If a user provider is set, it will return the active role or null
* @memberof module:openmct.UserAPI#
* @returns {string|null}
*/
getActiveRole() {
@ -121,7 +117,6 @@ class UserAPI extends EventEmitter {
}
/**
* Set the active role in session storage
* @memberof module:openmct.UserAPI#
* @returns {undefined}
*/
setActiveRole(role) {
@ -135,7 +130,6 @@ class UserAPI extends EventEmitter {
/**
* Will return if a role can provide a operator status response
* @memberof module:openmct.UserApi#
* @returns {boolean}
*/
canProvideStatusForRole() {
@ -151,7 +145,6 @@ class UserAPI extends EventEmitter {
* If a user provider is set, it will return the user provider's
* 'isLoggedIn' method
*
* @memberof module:openmct.UserAPI#
* @returns {Function|Boolean} user provider 'isLoggedIn' method
* @throws Will throw an error if no user provider is set
*/
@ -167,7 +160,6 @@ class UserAPI extends EventEmitter {
* If a user provider is set, it will return a call to it's
* 'hasRole' method
*
* @memberof module:openmct.UserAPI#
* @returns {Function|boolean} user provider 'isLoggedIn' method
* @param {string} roleId id of role to check for
* @throws Will throw an error if no user provider is set
@ -206,14 +198,9 @@ export default UserAPI;
/**
* @typedef {string} Role
*/
/**
* @typedef {import('../../../openmct.js').OpenMCT} OpenMCT
*/
/**
* @typedef {{statusStyles: Object.<string, StatusStyleDefinition>}} UserAPIConfiguration
* @typedef {import('../../MCT.js').MCT} OpenMCT
* @typedef {{statusStyles: Record<string, StatusStyleDefinition>}} UserAPIConfiguration
* @typedef {Object} UserProvider
*/
/**
@ -224,7 +211,3 @@ export default UserAPI;
* @property {string} statusBgColor The background color to apply in the status summary section of the poll question popup for this status eg."#9900cc"
* @property {string} statusFgColor The foreground color to apply in the status summary section of the poll question popup for this status eg. "#fff"
*/
/**
* @typedef {Object} UserProvider
*/

View File

@ -28,7 +28,6 @@
*
* For internal use by the mobile support bundle.
*
* @memberof src/plugins/DeviceClassifier
* @private
*/

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { markRaw } from 'vue';
export default class LADTableConfiguration extends EventEmitter {
constructor(domainObject, openmct) {

View File

@ -24,7 +24,7 @@ import { ACTIVITY_STATES_KEY } from './createActivityStatesIdentifier.js';
/**
* @typedef {Object} ActivityStatesInterceptorOptions
* @property {import('../../api/objects/ObjectAPI').Identifier} identifier the {namespace, key} to use for the activity states object.
* @property {import('openmct').Identifier} identifier the {namespace, key} to use for the activity states object.
* @property {string} name The name of the activity states model.
* @property {number} priority the priority of the interceptor. By default, it is low.
*/

View File

@ -21,7 +21,7 @@
*****************************************************************************/
// import BarGraph from './BarGraphPlot.vue';
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { createOpenMct, resetApplicationState } from 'utils/testing';
import { nextTick } from 'vue';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { createOpenMct, resetApplicationState } from 'utils/testing';
import { nextTick } from 'vue';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { createOpenMct, resetApplicationState } from 'utils/testing';
import { nextTick } from 'vue';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { v4 as uuid } from 'uuid';
import AllTelemetryCriterion from './criterion/AllTelemetryCriterion.js';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { v4 as uuid } from 'uuid';
import Condition from './Condition.js';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
export default class StyleRuleManager extends EventEmitter {
constructor(styleConfiguration, openmct, callback, suppressSubscriptionOnEdit) {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import StalenessUtils from '@/utils/staleness';

View File

@ -45,7 +45,6 @@
* @param {number[]} dimFactor the dimensions factor
* @param {number[]} the size of each grid element, in pixels
* @constructor
* @memberof platform/features/layout
*/
export default function LayoutDrag(rawPosition, posFactor, dimFactor, gridSize) {
this.rawPosition = rawPosition;

View File

@ -108,7 +108,7 @@ class ExportAsJSONAction {
/**
* @private
* @param {import('../../api/objects/ObjectAPI').DomainObject} parent
* @param {import('openmct').DomainObject} parent
*/
async #write(parent) {
this.totalToExport++;

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { createOpenMct, resetApplicationState } from 'utils/testing';
import { nextTick } from 'vue';

View File

@ -20,6 +20,9 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* @type {EventHelpers}
*/
const helperFunctions = {
listenTo: function (object, event, callback, context) {
if (!this._listeningTo) {
@ -95,3 +98,8 @@ const helperFunctions = {
};
export default helperFunctions;
/**
* @typedef {Object} EventHelpers
* @property {(object: any, event: string, callback: Function, context?: any) => void} listenTo
* @property {(object: any, event?: string, callback?: Function, context?: any) => void} stopListening
*/

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
const LOCAL_STORAGE_KEY = 'mct-saved-styles';
const LIMIT = 20;

View File

@ -38,7 +38,6 @@ const DATE_FORMATS = [DATE_FORMAT, 'YYYY-MM-DD h:mm:ss a', 'YYYY-MM-DD h:mm a',
*
* @implements {Format}
* @constructor
* @memberof platform/commonUI/formats
*/
export default function LocalTimeFormat() {
this.key = 'local-format';

View File

@ -61,7 +61,7 @@ describe('The local time', () => {
});
it('can be set to be the main time system', () => {
expect(openmct.time.timeSystem().key).toBe(LOCAL_SYSTEM_KEY);
expect(openmct.time.getTimeSystem().key).toBe(LOCAL_SYSTEM_KEY);
});
it('uses the local-format time format', () => {

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { EVENT_SNAPSHOTS_UPDATED } from './notebook-constants.js';
const NOTEBOOK_SNAPSHOT_STORAGE = 'notebook-snapshot-storage';

View File

@ -27,7 +27,6 @@
* metadata field which contains a subset of information found
* in the model itself (to support search optimization with
* CouchDB views.)
* @memberof platform/persistence/couch
* @constructor
* @param {string} id the id under which to store this mode
* @param {Object} model the model to store

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
export const DEFAULT_CONFIGURATION = {
clipActivityNames: false,

View File

@ -77,7 +77,7 @@ export default {
inject: ['openmct'],
data() {
const selection = this.openmct.selection.get();
/** @type {import('../../../api/objects/ObjectAPI').DomainObject} */
/** @type {import('openmct').DomainObject} */
const domainObject = selection[0][0].context.item;
const planViewConfiguration = markRaw(new PlanViewConfiguration(domainObject, this.openmct));

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'eventemitter3';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import eventHelpers from '../lib/eventHelpers.js';

View File

@ -126,7 +126,7 @@ export default class PlotConfigurationModel extends Model {
}
/**
* Retrieve the persisted series config for a given identifier.
* @param {import('./PlotSeries').Identifier} identifier
* @param {import('openmct').Identifier} identifier
* @returns {import('./PlotSeries').PlotSeriesModelType=}
*/
getPersistedSeriesConfig(identifier) {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import eventHelpers from '../lib/eventHelpers.js';
import { MARKER_SHAPES } from './MarkerShapes.js';
@ -138,5 +138,4 @@ class Draw2D extends EventEmitter {
}
}
}
export default Draw2D;

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import eventHelpers from '../lib/eventHelpers.js';
import { MARKER_SHAPES } from './MarkerShapes.js';
@ -297,5 +297,4 @@ class DrawWebGL extends EventEmitter {
}
}
}
export default DrawWebGL;

View File

@ -19,8 +19,10 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*jscs:disable disallowDanglingUnderscores */
/**
* @type {EventHelpers}
*/
const helperFunctions = {
listenTo: function (object, event, callback, context) {
if (!this._listeningTo) {
@ -94,7 +96,7 @@ export default helperFunctions;
/**
@typedef {{
listenTo: (object: any, event: any, callback: any, context: any) => void
listenTo: (object: any, event: any, callback: any, context: any) => void,
stopListening: (object: any, event: any, callback: any, context: any) => void
}} EventHelpers
*/

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import mount from 'utils/mount';
import {
createMouseEvent,

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import mount from 'utils/mount';
import {
createMouseEvent,

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import mount from 'utils/mount';
import {
createMouseEvent,

View File

@ -87,6 +87,9 @@ import ViewDatumAction from './viewDatumAction/plugin.js';
import ViewLargeAction from './viewLargeAction/plugin.js';
import WebPagePlugin from './webPage/plugin.js';
/**
* @type {Object}
*/
const plugins = {};
plugins.example = {};

View File

@ -149,8 +149,6 @@ export default class RemoteClock extends DefaultClock {
/**
* Waits for the clock to have a non-default tick value.
*
* @private
*/
#waitForReady() {
const waitForInitialTick = (resolve) => {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import * as templateHelpers from '../../../utils/template/templateHelpers.js';
import conditionTemplate from '../res/conditionTemplate.html';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import { makeKeyString } from 'objectUtils';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import * as templateHelpers from '../../../utils/template/templateHelpers.js';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import * as templateHelpers from '../../../utils/template/templateHelpers.js';
import itemTemplate from '../res/testDataItemTemplate.html';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import * as templateHelpers from '../../../utils/template/templateHelpers.js';
import ruleImageTemplate from '../res/ruleImageTemplate.html';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import * as templateHelpers from '../../../../utils/template/templateHelpers.js';
import paletteTemplate from '../../res/input/paletteTemplate.html';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import * as templateHelpers from '../../../../utils/template/templateHelpers.js';
import selectTemplate from '../../res/input/selectTemplate.html';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { createOpenMct, resetApplicationState } from 'utils/testing';
import { nextTick } from 'vue';

View File

@ -611,7 +611,7 @@ describe('The Mean Telemetry Provider', function () {
}
function createMockTimeApi() {
return jasmine.createSpyObj('timeApi', ['getTimeSystem']);
return jasmine.createSpyObj('timeApi', ['getTimeSystem', 'setTimeSystem']);
}
function setTimeSystemTo(timeSystemKey) {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
import StalenessUtils from '../../utils/staleness.js';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
export default class TelemetryTableConfiguration extends EventEmitter {

View File

@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
/**

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { nextTick } from 'vue';
import { createOpenMct, resetApplicationState } from '@/utils/testing';

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import { createOpenMct, resetApplicationState } from 'utils/testing';
import { nextTick } from 'vue';

View File

@ -26,6 +26,7 @@ import StartTimerAction from './actions/StartTimerAction.js';
import StopTimerAction from './actions/StopTimerAction.js';
import TimerViewProvider from './TimerViewProvider.js';
/** @type {OpenMCTPlugin} */
export default function TimerPlugin() {
return function install(openmct) {
openmct.types.addType('timer', {

View File

@ -12,7 +12,6 @@ const DATE_FORMATS = [DATE_FORMAT];
*
* @implements {Format}
* @constructor
* @memberof platform/commonUI/formats
*/
class DurationFormat {
constructor() {

View File

@ -28,7 +28,6 @@ import moment from 'moment';
*
* @implements {Format}
* @constructor
* @memberof platform/commonUI/formats
*/
export default class UTCTimeFormat {
constructor() {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import EventEmitter from 'EventEmitter';
import { EventEmitter } from 'eventemitter3';
import _ from 'lodash';
/**
@ -30,12 +30,13 @@ import _ from 'lodash';
*/
/**
* @typedef {import('../../openmct').OpenMCT} OpenMCT
* @typedef {import('../../src/MCT').MCT} OpenMCT
*/
/**
* Manages selection state for Open MCT
* @private
* @constructor
* @extends EventEmitter
*/
export default class Selection extends EventEmitter {
/**

Some files were not shown because too many files have changed in this diff Show More