mirror of
https://github.com/nasa/openmct.git
synced 2024-12-20 21:53:08 +00:00
Merge branch 'master' into telemetry-comps
This commit is contained in:
commit
e02217ad63
22
e2e/test-data/condition_set_storage.json
Normal file
22
e2e/test-data/condition_set_storage.json
Normal file
File diff suppressed because one or more lines are too long
@ -286,6 +286,55 @@ test.describe('Generate Visual Test Data @localStorage @generatedata @clock', ()
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Generate Conditional Styling Data @localStorage @generatedata', () => {
|
||||
test('Generate basic condition set', async ({ page, context }) => {
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
// Create a Condition Set
|
||||
const conditionSet = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Condition Set',
|
||||
name: 'Test Condition Set'
|
||||
});
|
||||
|
||||
// Create a Telemetry Object (Sine Wave Generator)
|
||||
const swg = await createExampleTelemetryObject(page, conditionSet.uuid);
|
||||
|
||||
// Edit the Telemetry Object to have a 10hz data rate (Gotta go fast!)
|
||||
await page.goto(swg.url);
|
||||
await page.getByLabel('More actions').click();
|
||||
await page.getByRole('menuitem', { name: 'Edit Properties...' }).click();
|
||||
await page.getByLabel('Period', { exact: true }).fill('5');
|
||||
await page.getByLabel('Save').click();
|
||||
|
||||
// Edit the Condition Set
|
||||
await page.goto(conditionSet.url);
|
||||
await page.getByLabel('Edit Object').click();
|
||||
|
||||
// Add a Condition to the Condition Set
|
||||
await page.getByLabel('Add Condition').click();
|
||||
await page.getByLabel('Condition Name Input').first().fill('Test Condition');
|
||||
await page.getByLabel('Condition Output Type').first().selectOption('String');
|
||||
await page.getByLabel('Condition Output String').first().fill('Test Condition Met');
|
||||
|
||||
// Condition: True if sine value > 0 (half the time)
|
||||
await page.getByLabel('Criterion Telemetry Selection').selectOption(swg.name);
|
||||
await page.getByLabel('Criterion Metadata Selection').selectOption('Sine');
|
||||
await page.getByLabel('Criterion Comparison Selection').selectOption('is greater than');
|
||||
await page.getByLabel('Criterion Input').first().fill('0');
|
||||
|
||||
// Rename default condition
|
||||
await page.getByLabel('Condition Output String').nth(1).fill('Test Condition Unmet');
|
||||
await page.getByLabel('Save').click();
|
||||
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
|
||||
|
||||
// Save localStorage for future test execution
|
||||
await context.storageState({
|
||||
path: fileURLToPath(
|
||||
new URL('../../../e2e/test-data/condition_set_storage.json', import.meta.url)
|
||||
)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Validate Overlay Plot with Telemetry Object @localStorage @generatedata', () => {
|
||||
test.use({
|
||||
storageState: fileURLToPath(
|
||||
|
@ -0,0 +1,114 @@
|
||||
/*****************************************************************************
|
||||
* 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 { fileURLToPath } from 'url';
|
||||
|
||||
import {
|
||||
createDomainObjectWithDefaults,
|
||||
navigateToObjectWithRealTime
|
||||
} from '../../../../../appActions.js';
|
||||
import { expect, test } from '../../../../../pluginFixtures.js';
|
||||
|
||||
const TINY_IMAGE_BASE64 =
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII';
|
||||
|
||||
test.describe('Display Layout Conditional Styling', () => {
|
||||
test.use({
|
||||
storageState: fileURLToPath(
|
||||
new URL('../../../../../test-data/condition_set_storage.json', import.meta.url)
|
||||
)
|
||||
});
|
||||
|
||||
let displayLayout;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
displayLayout = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout',
|
||||
name: 'Test Display Layout'
|
||||
});
|
||||
});
|
||||
|
||||
test('Image Drawing Object can have visibility toggled conditionally', async ({ page }) => {
|
||||
await page.getByLabel('Edit Object').click();
|
||||
|
||||
// Add Image Drawing Object to the layout
|
||||
await page.getByLabel('Add Drawing Object').click();
|
||||
await page.getByLabel('Image').click();
|
||||
await page.getByLabel('Image URL').fill(TINY_IMAGE_BASE64);
|
||||
await page.getByText('Ok').click();
|
||||
|
||||
// Use the "Test Condition Set" for conditional styling on the image
|
||||
await page.getByRole('tab', { name: 'Styles' }).click();
|
||||
await page.getByRole('button', { name: 'Use Conditional Styling...' }).click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel('Expand My Items folder').click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel('Preview Test Condition Set').click();
|
||||
await page.getByText('Ok').click();
|
||||
|
||||
// Set the image to be hidden when the condition is met
|
||||
await page.getByTitle('Visible').first().click();
|
||||
await page.getByLabel('Save Style').first().click();
|
||||
await page.getByLabel('Save', { exact: true }).click();
|
||||
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
|
||||
|
||||
// Switch to real-time mode and verify that the image toggles visibility
|
||||
await navigateToObjectWithRealTime(page, displayLayout.url);
|
||||
await expect(page.getByLabel('Image View')).toBeVisible();
|
||||
await expect(page.getByLabel('Image View')).toBeHidden();
|
||||
|
||||
// Reload the page and verify that the image toggles visibility
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await expect(page.getByLabel('Image View')).toBeVisible();
|
||||
await expect(page.getByLabel('Image View')).toBeHidden();
|
||||
});
|
||||
|
||||
test('Alphanumeric object can have visibility toggled conditionally', async ({ page }) => {
|
||||
await page.getByLabel('Edit Object').click();
|
||||
|
||||
// Add Alphanumeric Object to the layout
|
||||
await page.getByLabel('Expand My Items folder').click();
|
||||
await page.getByLabel('Expand Test Condition Set').click();
|
||||
await page.getByLabel('Preview VIPER Rover Heading').dragTo(page.getByLabel('Layout Grid'));
|
||||
|
||||
// Use the "Test Condition Set" for conditional styling on the alphanumeric
|
||||
await page.getByRole('tab', { name: 'Styles' }).click();
|
||||
await page.getByRole('button', { name: 'Use Conditional Styling...' }).click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel('Expand My Items folder').click();
|
||||
await page.getByLabel('Modal Overlay').getByLabel('Preview Test Condition Set').click();
|
||||
await page.getByText('Ok').click();
|
||||
|
||||
// Set the alphanumeric to be hidden when the condition is met
|
||||
await page.getByTitle('Visible').first().click();
|
||||
await page.getByLabel('Save Style').first().click();
|
||||
await page.getByLabel('Save', { exact: true }).click();
|
||||
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
|
||||
|
||||
// Switch to real-time mode and verify that the image toggles visibility
|
||||
await navigateToObjectWithRealTime(page, displayLayout.url);
|
||||
await expect(page.getByLabel('Alpha-numeric telemetry', { exact: true })).toBeVisible();
|
||||
await expect(page.getByLabel('Alpha-numeric telemetry', { exact: true })).toBeHidden();
|
||||
|
||||
// Reload the page and verify that the alphanumeric toggles visibility
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await expect(page.getByLabel('Alpha-numeric telemetry', { exact: true })).toBeVisible();
|
||||
await expect(page.getByLabel('Alpha-numeric telemetry', { exact: true })).toBeHidden();
|
||||
});
|
||||
});
|
@ -27,14 +27,16 @@
|
||||
aria-label="Condition Set Condition Collection"
|
||||
>
|
||||
<div class="c-cs__header c-section__header">
|
||||
<span
|
||||
<button
|
||||
class="c-disclosure-triangle c-tree__item__view-control is-enabled"
|
||||
:class="{ 'c-disclosure-triangle--expanded': expanded }"
|
||||
@click="expanded = !expanded"
|
||||
></span>
|
||||
:aria-expanded="expanded"
|
||||
aria-controls="conditionContent"
|
||||
@click="toggleExpanded"
|
||||
></button>
|
||||
<div class="c-cs__header-label c-section__label">Conditions</div>
|
||||
</div>
|
||||
<div v-if="expanded" class="c-cs__content">
|
||||
<div v-if="expanded" id="conditionContent" class="c-cs__content">
|
||||
<div
|
||||
v-show="isEditing"
|
||||
class="hint"
|
||||
@ -54,9 +56,10 @@
|
||||
v-show="isEditing"
|
||||
id="addCondition"
|
||||
class="c-button c-button--major icon-plus labeled"
|
||||
aria-labelledby="addConditionButtonLabel"
|
||||
@click="addCondition"
|
||||
>
|
||||
<span class="c-cs-button__label">Add Condition</span>
|
||||
<span id="addConditionButtonLabel" class="c-cs-button__label">Add Condition</span>
|
||||
</button>
|
||||
|
||||
<div class="c-cs__conditions-h" :class="{ 'is-active-dragging': isDragging }">
|
||||
|
@ -29,7 +29,7 @@
|
||||
@end-move="endMove"
|
||||
>
|
||||
<template #content>
|
||||
<div class="c-image-view" :style="style"></div>
|
||||
<div v-show="showImage" aria-label="Image View" class="c-image-view" :style="style"></div>
|
||||
</template>
|
||||
</LayoutFrame>
|
||||
</template>
|
||||
@ -76,6 +76,9 @@ export default {
|
||||
},
|
||||
emits: ['move', 'end-move'],
|
||||
computed: {
|
||||
showImage() {
|
||||
return this.isEditing || !this.itemStyle?.isStyleInvisible;
|
||||
},
|
||||
style() {
|
||||
let backgroundImage = 'url(' + this.item.url + ')';
|
||||
let border = '1px solid ' + this.item.stroke;
|
||||
|
@ -31,9 +31,10 @@
|
||||
<template #content>
|
||||
<div
|
||||
v-if="domainObject"
|
||||
v-show="showTelemetry"
|
||||
ref="telemetryViewWrapper"
|
||||
class="c-telemetry-view u-style-receiver"
|
||||
:class="[itemClasses]"
|
||||
:class="classNames"
|
||||
:style="styleObject"
|
||||
:data-font-size="item.fontSize"
|
||||
:data-font="item.font"
|
||||
@ -151,7 +152,10 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
itemClasses() {
|
||||
showTelemetry() {
|
||||
return this.isEditing || !this.itemStyle?.isStyleInvisible;
|
||||
},
|
||||
classNames() {
|
||||
let classes = [];
|
||||
|
||||
if (this.status) {
|
||||
|
@ -25,6 +25,7 @@ import _ from 'lodash';
|
||||
|
||||
import StalenessUtils from '../../utils/staleness.js';
|
||||
import TableRowCollection from './collections/TableRowCollection.js';
|
||||
import { MODE, ORDER } from './constants.js';
|
||||
import TelemetryTableColumn from './TelemetryTableColumn.js';
|
||||
import TelemetryTableConfiguration from './TelemetryTableConfiguration.js';
|
||||
import TelemetryTableNameColumn from './TelemetryTableNameColumn.js';
|
||||
@ -119,7 +120,7 @@ export default class TelemetryTable extends EventEmitter {
|
||||
this.rowLimit = rowLimit;
|
||||
}
|
||||
|
||||
if (this.telemetryMode === 'performance') {
|
||||
if (this.telemetryMode === MODE.PERFORMANCE) {
|
||||
this.tableRows.setLimit(this.rowLimit);
|
||||
} else {
|
||||
this.tableRows.removeLimit();
|
||||
@ -135,7 +136,7 @@ export default class TelemetryTable extends EventEmitter {
|
||||
//If no persisted sort order, default to sorting by time system, descending.
|
||||
sortOptions = sortOptions || {
|
||||
key: this.openmct.time.getTimeSystem().key,
|
||||
direction: 'desc'
|
||||
direction: ORDER.DESCENDING
|
||||
};
|
||||
|
||||
this.updateRowLimit();
|
||||
@ -172,10 +173,9 @@ export default class TelemetryTable extends EventEmitter {
|
||||
this.removeTelemetryCollection(keyString);
|
||||
|
||||
let sortOptions = this.configuration.getConfiguration().sortOptions;
|
||||
requestOptions.order =
|
||||
sortOptions?.direction ?? (this.telemetryMode === 'performance' ? 'desc' : 'asc');
|
||||
requestOptions.order = sortOptions?.direction ?? ORDER.DESCENDING; // default to descending
|
||||
|
||||
if (this.telemetryMode === 'performance') {
|
||||
if (this.telemetryMode === MODE.PERFORMANCE) {
|
||||
requestOptions.size = this.rowLimit;
|
||||
requestOptions.enforceSize = true;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import { MODE } from './constants.js';
|
||||
|
||||
export default function getTelemetryTableType(options) {
|
||||
let { telemetryMode, persistModeChange, rowLimit } = options;
|
||||
|
||||
@ -36,11 +38,11 @@ export default function getTelemetryTableType(options) {
|
||||
control: 'select',
|
||||
options: [
|
||||
{
|
||||
value: 'performance',
|
||||
value: MODE.PERFORMANCE,
|
||||
name: 'Limited (Performance) Mode'
|
||||
},
|
||||
{
|
||||
value: 'unlimited',
|
||||
value: MODE.UNLIMITED,
|
||||
name: 'Unlimited Mode'
|
||||
}
|
||||
],
|
||||
|
@ -22,6 +22,7 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { ORDER } from '../constants.js';
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
@ -208,7 +209,7 @@ export default class TableRowCollection extends EventEmitter {
|
||||
const val1 = this.getValueForSortColumn(row1);
|
||||
const val2 = this.getValueForSortColumn(row2);
|
||||
|
||||
if (this.sortOptions.direction === 'asc') {
|
||||
if (this.sortOptions.direction === ORDER.ASCENDING) {
|
||||
return val1 <= val2 ? row1 : row2;
|
||||
} else {
|
||||
return val1 >= val2 ? row1 : row2;
|
||||
@ -373,7 +374,7 @@ export default class TableRowCollection extends EventEmitter {
|
||||
|
||||
getRows() {
|
||||
if (this.rowLimit && this.rows.length > this.rowLimit) {
|
||||
if (this.sortOptions.direction === 'desc') {
|
||||
if (this.sortOptions.direction === ORDER.DESCENDING) {
|
||||
return this.rows.slice(0, this.rowLimit);
|
||||
} else {
|
||||
return this.rows.slice(-this.rowLimit);
|
||||
|
@ -296,6 +296,7 @@ import ProgressBar from '../../../ui/components/ProgressBar.vue';
|
||||
import Search from '../../../ui/components/SearchComponent.vue';
|
||||
import ToggleSwitch from '../../../ui/components/ToggleSwitch.vue';
|
||||
import { useResizeObserver } from '../../../ui/composables/resize.js';
|
||||
import { MODE, ORDER } from '../constants.js';
|
||||
import SizingRow from './SizingRow.vue';
|
||||
import TableColumnHeader from './TableColumnHeader.vue';
|
||||
import TableFooterIndicator from './TableFooterIndicator.vue';
|
||||
@ -713,7 +714,7 @@ export default {
|
||||
sortBy(columnKey) {
|
||||
let timeSystemKey = this.openmct.time.getTimeSystem().key;
|
||||
|
||||
if (this.telemetryMode === 'performance' && columnKey !== timeSystemKey) {
|
||||
if (this.telemetryMode === MODE.PERFORMANCE && columnKey !== timeSystemKey) {
|
||||
this.confirmUnlimitedMode('Switch to Unlimited Telemetry and Sort', () => {
|
||||
this.initiateSort(columnKey);
|
||||
});
|
||||
@ -724,15 +725,15 @@ export default {
|
||||
initiateSort(columnKey) {
|
||||
// If sorting by the same column, flip the sort direction.
|
||||
if (this.sortOptions.key === columnKey) {
|
||||
if (this.sortOptions.direction === 'asc') {
|
||||
this.sortOptions.direction = 'desc';
|
||||
if (this.sortOptions.direction === ORDER.ASCENDING) {
|
||||
this.sortOptions.direction = ORDER.DESCENDING;
|
||||
} else {
|
||||
this.sortOptions.direction = 'asc';
|
||||
this.sortOptions.direction = ORDER.ASCENDING;
|
||||
}
|
||||
} else {
|
||||
this.sortOptions = {
|
||||
key: columnKey,
|
||||
direction: 'desc'
|
||||
direction: ORDER.DESCENDING
|
||||
};
|
||||
}
|
||||
|
||||
@ -751,7 +752,7 @@ export default {
|
||||
}
|
||||
},
|
||||
shouldAutoScroll() {
|
||||
if (this.sortOptions.direction === 'desc') {
|
||||
if (this.sortOptions.direction === ORDER.DESCENDING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -844,7 +845,7 @@ export default {
|
||||
return justTheData;
|
||||
},
|
||||
exportAllDataAsCSV() {
|
||||
if (this.telemetryMode === 'performance') {
|
||||
if (this.telemetryMode === MODE.PERFORMANCE) {
|
||||
this.confirmUnlimitedMode('Switch to Unlimited Telemetry and Export', () => {
|
||||
const data = this.getTableRowData();
|
||||
|
||||
@ -1226,7 +1227,8 @@ export default {
|
||||
});
|
||||
},
|
||||
updateTelemetryMode() {
|
||||
this.telemetryMode = this.telemetryMode === 'unlimited' ? 'performance' : 'unlimited';
|
||||
this.telemetryMode =
|
||||
this.telemetryMode === MODE.UNLIMITED ? MODE.PERFORMANCE : MODE.UNLIMITED;
|
||||
|
||||
if (this.persistModeChange) {
|
||||
this.table.configuration.setTelemetryMode(this.telemetryMode);
|
||||
@ -1236,7 +1238,7 @@ export default {
|
||||
|
||||
const timeSystemKey = this.openmct.time.getTimeSystem().key;
|
||||
|
||||
if (this.telemetryMode === 'performance' && this.sortOptions.key !== timeSystemKey) {
|
||||
if (this.telemetryMode === MODE.PERFORMANCE && this.sortOptions.key !== timeSystemKey) {
|
||||
this.openmct.notifications.info(
|
||||
'Switched to Performance Mode: Table now sorted by time for optimized efficiency.'
|
||||
);
|
||||
|
@ -62,6 +62,8 @@
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
|
||||
import { MODE } from '../constants.js';
|
||||
|
||||
const FILTER_INDICATOR_LABEL = 'Filters:';
|
||||
const FILTER_INDICATOR_LABEL_MIXED = 'Mixed Filters:';
|
||||
const FILTER_INDICATOR_TITLE = 'Data filters are being applied to this view.';
|
||||
@ -81,7 +83,7 @@ export default {
|
||||
},
|
||||
telemetryMode: {
|
||||
type: String,
|
||||
default: 'performance'
|
||||
default: MODE.PERFORMANCE
|
||||
}
|
||||
},
|
||||
emits: ['telemetry-mode-change'],
|
||||
@ -103,7 +105,7 @@ export default {
|
||||
});
|
||||
},
|
||||
isUnlimitedMode() {
|
||||
return this.telemetryMode === 'unlimited';
|
||||
return this.telemetryMode === MODE.UNLIMITED;
|
||||
},
|
||||
label() {
|
||||
if (this.hasMixedFilters) {
|
||||
|
11
src/plugins/telemetryTable/constants.js
Normal file
11
src/plugins/telemetryTable/constants.js
Normal file
@ -0,0 +1,11 @@
|
||||
const ORDER = {
|
||||
ASCENDING: 'asc',
|
||||
DESCENDING: 'desc'
|
||||
};
|
||||
|
||||
const MODE = {
|
||||
PERFORMANCE: 'performance',
|
||||
UNLIMITED: 'unlimited'
|
||||
};
|
||||
|
||||
export { MODE, ORDER };
|
@ -20,13 +20,14 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import { MODE } from './constants.js';
|
||||
import TableConfigurationViewProvider from './TableConfigurationViewProvider.js';
|
||||
import getTelemetryTableType from './TelemetryTableType.js';
|
||||
import TelemetryTableViewProvider from './TelemetryTableViewProvider.js';
|
||||
import TelemetryTableViewActions from './ViewActions.js';
|
||||
|
||||
export default function plugin(
|
||||
options = { telemetryMode: 'performance', persistModeChange: true, rowLimit: 50 }
|
||||
options = { telemetryMode: MODE.PERFORMANCE, persistModeChange: true, rowLimit: 50 }
|
||||
) {
|
||||
return function install(openmct) {
|
||||
openmct.objectViews.addProvider(new TelemetryTableViewProvider(openmct, options));
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
} from 'utils/testing';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { MODE } from './constants.js';
|
||||
import TablePlugin from './plugin.js';
|
||||
|
||||
class MockDataTransfer {
|
||||
@ -198,7 +199,7 @@ describe('the plugin', () => {
|
||||
},
|
||||
persistModeChange: true,
|
||||
rowLimit: 50,
|
||||
telemetryMode: 'performance'
|
||||
telemetryMode: MODE.PERFORMANCE
|
||||
}
|
||||
};
|
||||
const testTelemetry = [
|
||||
|
@ -25,65 +25,67 @@
|
||||
*
|
||||
* @interface ToolbarRegistry
|
||||
*/
|
||||
export default function ToolbarRegistry() {
|
||||
this.providers = {};
|
||||
export default class ToolbarRegistry {
|
||||
constructor() {
|
||||
this.providers = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets toolbar controls from providers which can provide a toolbar for this selection.
|
||||
*
|
||||
* @param {Object} selection the selection object
|
||||
* @returns {Object[]} an array of objects defining controls for the toolbar
|
||||
* @private for platform-internal use
|
||||
*/
|
||||
get(selection) {
|
||||
const providers = this.getAllProviders().filter(function (provider) {
|
||||
return provider.forSelection(selection);
|
||||
});
|
||||
|
||||
const structure = [];
|
||||
|
||||
providers.forEach((provider) => {
|
||||
provider.toolbar(selection).forEach((item) => structure.push(item));
|
||||
});
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
getAllProviders() {
|
||||
return Object.values(this.providers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
getByProviderKey(key) {
|
||||
return this.providers[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new type of toolbar.
|
||||
*
|
||||
* @param {module:openmct.ToolbarRegistry} provider the provider for this toolbar
|
||||
* @method addProvider
|
||||
*/
|
||||
addProvider(provider) {
|
||||
const key = provider.key;
|
||||
|
||||
if (key === undefined) {
|
||||
throw "Toolbar providers must have a unique 'key' property defined.";
|
||||
}
|
||||
|
||||
if (this.providers[key] !== undefined) {
|
||||
console.warn("Provider already defined for key '%s'. Provider keys must be unique.", key);
|
||||
}
|
||||
|
||||
this.providers[key] = provider;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets toolbar controls from providers which can provide a toolbar for this selection.
|
||||
*
|
||||
* @param {Object} selection the selection object
|
||||
* @returns {Object[]} an array of objects defining controls for the toolbar
|
||||
* @private for platform-internal use
|
||||
*/
|
||||
ToolbarRegistry.prototype.get = function (selection) {
|
||||
const providers = this.getAllProviders().filter(function (provider) {
|
||||
return provider.forSelection(selection);
|
||||
});
|
||||
|
||||
const structure = [];
|
||||
|
||||
providers.forEach((provider) => {
|
||||
provider.toolbar(selection).forEach((item) => structure.push(item));
|
||||
});
|
||||
|
||||
return structure;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ToolbarRegistry.prototype.getAllProviders = function () {
|
||||
return Object.values(this.providers);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ToolbarRegistry.prototype.getByProviderKey = function (key) {
|
||||
return this.providers[key];
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a new type of toolbar.
|
||||
*
|
||||
* @param {module:openmct.ToolbarRegistry} provider the provider for this toolbar
|
||||
* @method addProvider
|
||||
*/
|
||||
ToolbarRegistry.prototype.addProvider = function (provider) {
|
||||
const key = provider.key;
|
||||
|
||||
if (key === undefined) {
|
||||
throw "Toolbar providers must have a unique 'key' property defined.";
|
||||
}
|
||||
|
||||
if (this.providers[key] !== undefined) {
|
||||
console.warn("Provider already defined for key '%s'. Provider keys must be unique.", key);
|
||||
}
|
||||
|
||||
this.providers[key] = provider;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exposes types of toolbars in Open MCT.
|
||||
*
|
||||
|
@ -34,9 +34,9 @@
|
||||
}"
|
||||
@click="onClick"
|
||||
>
|
||||
<div v-if="options.label" class="c-icon-button__label">
|
||||
<span v-if="options.label" class="c-icon-button__label">
|
||||
{{ options.label }}
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -25,11 +25,13 @@
|
||||
class="c-icon-button c-icon-button--menu"
|
||||
:class="options.icon"
|
||||
:title="options.title"
|
||||
:aria-label="options.label"
|
||||
role="button"
|
||||
@click="toggle"
|
||||
>
|
||||
<div v-if="options.label" class="c-icon-button__label">
|
||||
<span v-if="options.label" class="c-icon-button__label">
|
||||
{{ options.label }}
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="open" class="c-menu" role="menu">
|
||||
<ul>
|
||||
|
Loading…
Reference in New Issue
Block a user