Compare commits
36 Commits
v3.1.0
...
table-pagi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e10e836796 | ||
|
|
ba688e667a | ||
|
|
9f309388fd | ||
|
|
c0ccc05361 | ||
|
|
e03683e11a | ||
|
|
fde676a807 | ||
|
|
7e8917c959 | ||
|
|
b0aa36b0e3 | ||
|
|
112ac74cfb | ||
|
|
635c725573 | ||
|
|
a0fd1f0171 | ||
|
|
c7fd584b58 | ||
|
|
16ca994cfa | ||
|
|
ebe5323f82 | ||
|
|
7a8a6d3649 | ||
|
|
25e7a16c77 | ||
|
|
141939295a | ||
|
|
2c1040c7c0 | ||
|
|
d94fe8806b | ||
|
|
7bf983210c | ||
|
|
8f92cd4206 | ||
|
|
13311b9fc8 | ||
|
|
2daec448da | ||
|
|
5bd8d17592 | ||
|
|
954c72b100 | ||
|
|
43338f3980 | ||
|
|
1414f54c17 | ||
|
|
9849e0398e | ||
|
|
76889cf60d | ||
|
|
26d3bd1e69 | ||
|
|
a16a1d35b6 | ||
|
|
97b2ebc0bb | ||
|
|
6b32c63039 | ||
|
|
084784a409 | ||
|
|
734a8dd592 | ||
|
|
5eed5de3bb |
@@ -483,7 +483,11 @@
|
||||
"websockets",
|
||||
"swgs",
|
||||
"memlab",
|
||||
"devmode"
|
||||
"devmode",
|
||||
"blockquote",
|
||||
"blockquotes",
|
||||
"Blockquote",
|
||||
"Blockquotes"
|
||||
],
|
||||
"dictionaries": ["npm", "softwareTerms", "node", "html", "css", "bash", "en_US"],
|
||||
"ignorePaths": [
|
||||
|
||||
20
.eslintrc.js
20
.eslintrc.js
@@ -15,7 +15,8 @@ module.exports = {
|
||||
'plugin:compat/recommended',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:you-dont-need-lodash-underscore/compatible',
|
||||
'plugin:prettier/recommended'
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:no-unsanitized/DOM'
|
||||
],
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
@@ -145,29 +146,26 @@ module.exports = {
|
||||
'no-implicit-coercion': 'error',
|
||||
//https://eslint.org/docs/rules/no-unneeded-ternary
|
||||
'no-unneeded-ternary': 'error',
|
||||
"unicorn/filename-case": [
|
||||
"error",
|
||||
'unicorn/filename-case': [
|
||||
'error',
|
||||
{
|
||||
"cases": {
|
||||
"pascalCase": true
|
||||
cases: {
|
||||
pascalCase: true
|
||||
},
|
||||
"ignore": [
|
||||
"^.*\\.js$"
|
||||
]
|
||||
ignore: ['^.*\\.js$']
|
||||
}
|
||||
],
|
||||
'vue/first-attribute-linebreak': 'error',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/multi-word-component-names': 'off', // TODO enable, align with conventions
|
||||
'vue/no-mutating-props': 'off'
|
||||
'vue/no-mutating-props': 'off' // TODO: Remove this rule and fix resulting errors
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: LEGACY_FILES,
|
||||
rules: {
|
||||
'no-unused-vars': [
|
||||
'warn',
|
||||
'error',
|
||||
{
|
||||
vars: 'all',
|
||||
args: 'none',
|
||||
|
||||
2
.github/workflows/e2e-couchdb.yml
vendored
2
.github/workflows/e2e-couchdb.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'lts/hydrogen'
|
||||
|
||||
|
||||
2
.github/workflows/e2e-pr.yml
vendored
2
.github/workflows/e2e-pr.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
- windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'lts/hydrogen'
|
||||
|
||||
|
||||
4
.github/workflows/npm-prerelease.yml
vendored
4
.github/workflows/npm-prerelease.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/hydrogen
|
||||
- run: npm install
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/hydrogen
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
2
.github/workflows/pr-platform.yml
vendored
2
.github/workflows/pr-platform.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
architecture: ${{ matrix.architecture }}
|
||||
|
||||
@@ -77,8 +77,7 @@ const config = {
|
||||
MCT: path.join(projectRootDir, 'src/MCT'),
|
||||
testUtils: path.join(projectRootDir, 'src/utils/testUtils.js'),
|
||||
objectUtils: path.join(projectRootDir, 'src/api/objects/object-utils.js'),
|
||||
utils: path.join(projectRootDir, 'src/utils'),
|
||||
vue: path.join(projectRootDir, 'node_modules/@vue/compat/dist/vue.esm-bundler.js'),
|
||||
utils: path.join(projectRootDir, 'src/utils')
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
@@ -86,7 +85,9 @@ const config = {
|
||||
__OPENMCT_VERSION__: `'${packageDefinition.version}'`,
|
||||
__OPENMCT_BUILD_DATE__: `'${new Date()}'`,
|
||||
__OPENMCT_REVISION__: `'${gitRevision}'`,
|
||||
__OPENMCT_BUILD_BRANCH__: `'${gitBranch}'`
|
||||
__OPENMCT_BUILD_BRANCH__: `'${gitBranch}'`,
|
||||
__VUE_OPTIONS_API__: true, // enable/disable Options API support, default: true
|
||||
__VUE_PROD_DEVTOOLS__: false // enable/disable devtools support in production, default: false
|
||||
}),
|
||||
new VueLoaderPlugin(),
|
||||
new CopyWebpackPlugin({
|
||||
@@ -115,7 +116,7 @@ const config = {
|
||||
new webpack.BannerPlugin({
|
||||
test: /.*Theme\.css$/,
|
||||
raw: true,
|
||||
banner: '@charset "UTF-8";',
|
||||
banner: '@charset "UTF-8";'
|
||||
})
|
||||
],
|
||||
module: {
|
||||
@@ -142,10 +143,7 @@ const config = {
|
||||
options: {
|
||||
compilerOptions: {
|
||||
hoistStatic: false,
|
||||
whitespace: 'preserve',
|
||||
compatConfig: {
|
||||
MODE: 2
|
||||
}
|
||||
whitespace: 'preserve'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -34,7 +34,6 @@ async function enterTextEntry(page, text) {
|
||||
await page.locator(NOTEBOOK_DROP_AREA).click();
|
||||
|
||||
// enter text
|
||||
await page.getByLabel('Notebook Entry Display').last().click();
|
||||
await page.getByLabel('Notebook Entry Input').last().fill(text);
|
||||
await commitEntry(page);
|
||||
}
|
||||
@@ -53,6 +52,7 @@ async function dragAndDropEmbed(page, notebookObject) {
|
||||
await page.click('button[title="Show selected item in tree"]');
|
||||
// Drag and drop the SWG into the notebook
|
||||
await page.dragAndDrop(`text=${swg.name}`, NOTEBOOK_DROP_AREA);
|
||||
await commitEntry(page);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
59
e2e/tests/functional/clearDataAction.e2e.spec.js
Normal file
59
e2e/tests/functional/clearDataAction.e2e.spec.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2023, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
Verify that the "Clear Data" menu action performs as expected for various object types.
|
||||
*/
|
||||
|
||||
const { test, expect } = require('../../pluginFixtures.js');
|
||||
const { createDomainObjectWithDefaults } = require('../../appActions.js');
|
||||
|
||||
const backgroundImageSelector = '.c-imagery__main-image__background-image';
|
||||
|
||||
test.describe('Clear Data Action', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Go to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create a default 'Example Imagery' object
|
||||
const exampleImagery = await createDomainObjectWithDefaults(page, { type: 'Example Imagery' });
|
||||
|
||||
// Verify that the created object is focused
|
||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText(exampleImagery.name);
|
||||
await page.locator('.c-imagery__main-image__bg').hover({ trial: true });
|
||||
await expect(page.locator(backgroundImageSelector)).toBeVisible();
|
||||
});
|
||||
test('works as expected with Example Imagery', async ({ page }) => {
|
||||
await expect(await page.locator('.c-thumb__image').count()).toBeGreaterThan(0);
|
||||
// Click the "Clear Data" menu action
|
||||
await page.getByTitle('More options').click();
|
||||
const clearDataMenuItem = page.getByRole('menuitem', {
|
||||
name: 'Clear Data'
|
||||
});
|
||||
await expect(clearDataMenuItem).toBeEnabled();
|
||||
await clearDataMenuItem.click();
|
||||
|
||||
// Verify that the background image is no longer visible
|
||||
await expect(page.locator(backgroundImageSelector)).toBeHidden();
|
||||
await expect(await page.locator('.c-thumb__image').count()).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -40,7 +40,7 @@ test.describe('The Fault Management Plugin using example faults', () => {
|
||||
}) => {
|
||||
await utils.selectFaultItem(page, 1);
|
||||
|
||||
await page.getByRole('tab', { name: 'Fault Management Configuration' }).click();
|
||||
await page.getByRole('tab', { name: 'Config' }).click();
|
||||
const selectedFaultName = await page
|
||||
.locator('.c-fault-mgmt__list.is-selected .c-fault-mgmt__list-faultname')
|
||||
.textContent();
|
||||
@@ -65,7 +65,7 @@ test.describe('The Fault Management Plugin using example faults', () => {
|
||||
);
|
||||
expect.soft(await selectedRows.count()).toEqual(2);
|
||||
|
||||
await page.getByRole('tab', { name: 'Fault Management Configuration' }).click();
|
||||
await page.getByRole('tab', { name: 'Config' }).click();
|
||||
const firstSelectedFaultName = await selectedRows.nth(0).textContent();
|
||||
const secondSelectedFaultName = await selectedRows.nth(1).textContent();
|
||||
const firstNameInInspectorCount = await page
|
||||
|
||||
@@ -209,7 +209,6 @@ test.describe('Example Imagery Object', () => {
|
||||
const canvasBoundingBox = await canvas.boundingBox();
|
||||
const canvasCenterX = canvasBoundingBox.x + canvasBoundingBox.width / 2;
|
||||
const canvasCenterY = canvasBoundingBox.y + canvasBoundingBox.height / 2;
|
||||
|
||||
await Promise.all(tagHotkey.map((x) => page.keyboard.down(x)));
|
||||
await page.mouse.down();
|
||||
// steps not working for me here
|
||||
@@ -222,7 +221,7 @@ test.describe('Example Imagery Object', () => {
|
||||
await expect(page.locator('[role="toolbar"][aria-label="Image controls"]')).toBeVisible();
|
||||
await Promise.all(tagHotkey.map((x) => page.keyboard.up(x)));
|
||||
|
||||
//Wait for canvas to stabilize.
|
||||
// Wait for canvas to stabilize.
|
||||
await canvas.hover({ trial: true });
|
||||
|
||||
// add some tags
|
||||
@@ -234,6 +233,20 @@ test.describe('Example Imagery Object', () => {
|
||||
await page.getByRole('button', { name: /Add Tag/ }).click();
|
||||
await page.getByPlaceholder('Type to select tag').click();
|
||||
await page.getByText('Science').click();
|
||||
|
||||
// click on a separate part of the canvas to ensure no tags appear
|
||||
await page.mouse.click(canvasCenterX + 10, canvasCenterY + 10);
|
||||
await expect(page.getByText('Driving')).toBeHidden();
|
||||
await expect(page.getByText('Science')).toBeHidden();
|
||||
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/nasa/openmct/issues/7083'
|
||||
});
|
||||
// click on annotation again and expect tags to appear
|
||||
await page.mouse.click(canvasCenterX - 50, canvasCenterY - 50);
|
||||
await expect(page.getByText('Driving')).toBeVisible();
|
||||
await expect(page.getByText('Science')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Can use + - buttons to zoom on the image @unstable', async ({ page }) => {
|
||||
|
||||
@@ -279,7 +279,7 @@ test.describe('Notebook entry tests', () => {
|
||||
|
||||
// Click .c-notebook__drag-area
|
||||
await page.locator('.c-notebook__drag-area').click();
|
||||
await expect(page.getByLabel('Notebook Entry Display')).toBeVisible();
|
||||
await expect(page.getByLabel('Notebook Entry Input')).toBeVisible();
|
||||
await expect(page.getByLabel('Notebook Entry', { exact: true })).toHaveClass(/is-selected/);
|
||||
});
|
||||
test('When an object is dropped into a notebook, a new entry is created and it should be focused @unstable', async ({
|
||||
@@ -514,10 +514,23 @@ test.describe('Notebook entry tests', () => {
|
||||
const childItem = page.locator('li:has-text("List Item 2") ol li:has-text("Order 2")');
|
||||
await expect(childItem).toBeVisible();
|
||||
|
||||
// Blocks
|
||||
const blockTest = '```javascript\nconst foo = "bar";\nconst bar = "foo";\n```';
|
||||
await nbUtils.enterTextEntry(page, blockTest);
|
||||
// Code Blocks
|
||||
const codeblockTest = '```javascript\nconst foo = "bar";\nconst bar = "foo";\n```';
|
||||
await nbUtils.enterTextEntry(page, codeblockTest);
|
||||
const codeBlock = page.locator('code.language-javascript:has-text("const foo = \\"bar\\";")');
|
||||
await expect(codeBlock).toBeVisible();
|
||||
|
||||
// Blockquotes
|
||||
const blockquoteTest =
|
||||
'This is a quote by Mark Twain:\n> "The man with a new idea is a crank\n>until the idea succeeds."';
|
||||
await nbUtils.enterTextEntry(page, blockquoteTest);
|
||||
const firstLineOfBlockquoteText = page.locator(
|
||||
'blockquote:has-text("The man with a new idea is a crank")'
|
||||
);
|
||||
await expect(firstLineOfBlockquoteText).toBeVisible();
|
||||
const secondLineOfBlockquoteText = page.locator(
|
||||
'blockquote:has-text("until the idea succeeds")'
|
||||
);
|
||||
await expect(secondLineOfBlockquoteText).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -188,12 +188,11 @@ test.describe('Snapshot image tests', () => {
|
||||
}, fileData);
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: dropTransfer });
|
||||
|
||||
await page.locator('.c-ne__save-button > button').click();
|
||||
// be sure that entry was created
|
||||
await expect(page.getByText('favicon-96x96.png')).toBeVisible();
|
||||
|
||||
await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).click();
|
||||
|
||||
// expect large image to be displayed
|
||||
await expect(page.getByRole('dialog').getByText('favicon-96x96.png')).toBeVisible();
|
||||
|
||||
@@ -215,3 +214,59 @@ test.describe('Snapshot image tests', () => {
|
||||
expect(await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).count()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Snapshot image failure tests', () => {
|
||||
test.use({ failOnConsoleError: false });
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
});
|
||||
|
||||
test('Get an error notification when dropping unknown file onto notebook entry', async ({
|
||||
page
|
||||
}) => {
|
||||
// fill Uint8Array array with some garbage data
|
||||
const garbageData = new Uint8Array(100);
|
||||
const fileData = Array.from(garbageData);
|
||||
|
||||
const dropTransfer = await page.evaluateHandle((data) => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([new Uint8Array(data)], 'someGarbage.foo', { type: 'unknown/garbage' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
}, fileData);
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: dropTransfer });
|
||||
|
||||
// should have gotten a notification from OpenMCT that we couldn't add it
|
||||
await expect(page.getByText('Unknown object(s) dropped and cannot embed')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Get an error notification when dropping big files onto notebook entry', async ({
|
||||
page
|
||||
}) => {
|
||||
const garbageSize = 15 * 1024 * 1024; // 15 megabytes
|
||||
|
||||
await page.addScriptTag({
|
||||
// make the garbage client side
|
||||
content: `window.bigGarbageData = new Uint8Array(${garbageSize})`
|
||||
});
|
||||
|
||||
const bigDropTransfer = await page.evaluateHandle(() => {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const file = new File([window.bigGarbageData], 'bigBoy.png', { type: 'image/png' });
|
||||
dataTransfer.items.add(file);
|
||||
return dataTransfer;
|
||||
});
|
||||
|
||||
await page.dispatchEvent('.c-notebook__drag-area', 'drop', { dataTransfer: bigDropTransfer });
|
||||
|
||||
// should have gotten a notification from OpenMCT that we couldn't add it as it's too big
|
||||
await expect(page.getByText('unable to embed')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,7 +150,6 @@ test.describe('Tagging in Notebooks @addInit', () => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
|
||||
await page.locator('text=To start a new entry, click here or drag and drop any object').click();
|
||||
await page.getByLabel('Notebook Entry Display').last().click();
|
||||
await page.getByLabel('Notebook Entry Input').fill(`An entry without tags`);
|
||||
await page.locator('.c-ne__save-button > button').click();
|
||||
|
||||
|
||||
@@ -77,11 +77,11 @@ test.describe('Grand Search', () => {
|
||||
|
||||
// Click [aria-label="OpenMCT Search"] a >> nth=0
|
||||
await page.locator('[aria-label="Search Result"] >> nth=0').click();
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeInViewport();
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeHidden();
|
||||
|
||||
// Fill [aria-label="OpenMCT Search"] input[type="search"]
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('foo');
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).not.toBeInViewport();
|
||||
await expect(page.locator('[aria-label="Search Result"] >> nth=0')).toBeHidden();
|
||||
|
||||
// Click text=Snapshot Save and Finish Editing Save and Continue Editing >> button >> nth=1
|
||||
await page
|
||||
|
||||
@@ -89,20 +89,6 @@ test.describe('Verify tooltips', () => {
|
||||
await expandEntireTree(page);
|
||||
});
|
||||
|
||||
// LAD Tables - DONE
|
||||
// Expanded collapsed plot legend - DONE
|
||||
// Object Labels - DONE
|
||||
// Display Layout headers - DONE
|
||||
// Flexible Layout headers - DONE
|
||||
// Tab View layout headers - DONE
|
||||
// Search - DONE
|
||||
// Gauge -
|
||||
// Notebook Embed - DONE
|
||||
// Telemetry Table -
|
||||
// Timeline Objects
|
||||
// Tree - DONE
|
||||
// Recent Objects
|
||||
|
||||
test('display correct paths for LAD tables', async ({ page, openmctConfig }) => {
|
||||
// Create LAD table
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
@@ -254,13 +240,13 @@ test.describe('Verify tooltips', () => {
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe('My Items / Test Overlay Plot');
|
||||
|
||||
// await page.keyboard.up('Control');
|
||||
// await page.locator('.c-plot-legend__view-control >> nth=0').click();
|
||||
// await page.keyboard.down('Control');
|
||||
// await page.locator('.plot-wrapper-expanded-legend .plot-series-name').first().hover();
|
||||
// tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
// tooltipText = tooltipText.replace('\n', '').trim();
|
||||
// expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
await page.keyboard.up('Control');
|
||||
await page.locator('.c-plot-legend__view-control >> nth=0').click();
|
||||
await page.keyboard.down('Control');
|
||||
await page.locator('.plot-wrapper-expanded-legend .plot-series-name').first().hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
|
||||
await page.getByText('Test Stacked Plot').nth(2).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
@@ -345,18 +331,18 @@ test.describe('Verify tooltips', () => {
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
|
||||
test('display path for source telemetry when hovering over gauge', ({ page }) => {
|
||||
expect(true).toBe(true);
|
||||
// await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Gauge',
|
||||
// name: 'Test Gauge'
|
||||
// });
|
||||
// await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-gauge__wrapper');
|
||||
// await page.keyboard.down('Control');
|
||||
// await page.locator('.c-gauge__current-value-text-wrapper').hover();
|
||||
// let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
// tooltipText = tooltipText.replace('\n', '').trim();
|
||||
// expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
test('display path for source telemetry when hovering over gauge', async ({ page }) => {
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Gauge',
|
||||
name: 'Test Gauge'
|
||||
});
|
||||
await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-gauge__wrapper');
|
||||
await page.keyboard.down('Control');
|
||||
// eslint-disable-next-line playwright/no-force-option
|
||||
await page.locator('.c-gauge.c-dial').hover({ position: { x: 0, y: 0 }, force: true });
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
|
||||
test('display tooltip path for notebook embeds', async ({ page }) => {
|
||||
@@ -373,26 +359,105 @@ test.describe('Verify tooltips', () => {
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
|
||||
// test('display tooltip path for telemetry table names', async ({ page }) => {
|
||||
// await setEndOffset(page, { secs: '10' });
|
||||
// await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Telemetry Table',
|
||||
// name: 'Test Telemetry Table'
|
||||
// });
|
||||
test('display tooltip path for telemetry table names', async ({ page }) => {
|
||||
// set endBound to 10 seconds after start bound
|
||||
const url = await page.url();
|
||||
const parsedUrl = new URL(url.replace('#', '!'));
|
||||
const startBound = Number(parsedUrl.searchParams.get('tc.startBound'));
|
||||
const tenSecondsInMilliseconds = 10 * 1000;
|
||||
const endBound = startBound + tenSecondsInMilliseconds;
|
||||
parsedUrl.searchParams.set('tc.endBound', endBound);
|
||||
await page.goto(parsedUrl.href.replace('!', '#'));
|
||||
|
||||
// await page.dragAndDrop(`text=${sineWaveObject1.name}`, '.c-telemetry-table');
|
||||
// await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-telemetry-table');
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Telemetry Table',
|
||||
name: 'Test Telemetry Table'
|
||||
});
|
||||
|
||||
// await page.locator('button[title="Save"]').click();
|
||||
// await page.locator('text=Save and Finish Editing').click();
|
||||
await page.dragAndDrop(`text=${sineWaveObject1.name}`, '.c-telemetry-table');
|
||||
await page.dragAndDrop(`text=${sineWaveObject3.name}`, '.c-telemetry-table');
|
||||
|
||||
// // .c-telemetry-table__body
|
||||
await page.locator('button[title="Save"]').click();
|
||||
await page.locator('text=Save and Finish Editing').click();
|
||||
await page.keyboard.down('Control');
|
||||
|
||||
// await page.keyboard.down('Control');
|
||||
await page.locator('.noselect > [title="SWG 3"]').first().hover();
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
|
||||
// await page.locator('.noselect > [title="SWG 3"]').first().hover();
|
||||
// let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
// tooltipText = tooltipText.replace('\n', '').trim();
|
||||
// expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
// });
|
||||
await page.locator('.noselect > [title="SWG 1"]').first().hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
});
|
||||
|
||||
test('display tooltip path for recently viewed items', async ({ page }) => {
|
||||
// drag up Recently Viewed pane
|
||||
await page
|
||||
.locator('.l-pane.l-pane--vertical-handle-before', {
|
||||
hasText: 'Recently Viewed'
|
||||
})
|
||||
.locator('.l-pane__handle')
|
||||
.hover();
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(0, 300);
|
||||
await page.mouse.up();
|
||||
|
||||
await page.keyboard.down('Control');
|
||||
await page.getByLabel('Recent Objects').getByText(sineWaveObject3.name).hover();
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
|
||||
await page.getByLabel('Recent Objects').getByText(sineWaveObject2.name).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject2.path);
|
||||
|
||||
await page.getByLabel('Recent Objects').getByText(sineWaveObject1.name).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
});
|
||||
|
||||
test('display tooltip path for time strips', async ({ page }) => {
|
||||
// Create Time Strip
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Time Strip',
|
||||
name: 'Test Time Strip'
|
||||
});
|
||||
// Edit Overlay Plot
|
||||
await page.locator('[title="Edit"]').click();
|
||||
await page.dragAndDrop(
|
||||
`text=${sineWaveObject1.name}`,
|
||||
'.c-object-view.is-object-type-time-strip'
|
||||
);
|
||||
await page.dragAndDrop(
|
||||
`text=${sineWaveObject2.name}`,
|
||||
'.c-object-view.is-object-type-time-strip'
|
||||
);
|
||||
await page.dragAndDrop(
|
||||
`text=${sineWaveObject3.name}`,
|
||||
'.c-object-view.is-object-type-time-strip'
|
||||
);
|
||||
await page.locator('button[title="Save"]').click();
|
||||
await page.locator('text=Save and Finish Editing').click();
|
||||
|
||||
await page.keyboard.down('Control');
|
||||
await page.getByText(sineWaveObject1.name).nth(2).hover();
|
||||
let tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject1.path);
|
||||
|
||||
await page.getByText(sineWaveObject2.name).nth(2).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject2.path);
|
||||
|
||||
await page.getByText(sineWaveObject3.name).nth(2).hover();
|
||||
tooltipText = await page.locator('.c-tooltip').textContent();
|
||||
tooltipText = tooltipText.replace('\n', '').trim();
|
||||
expect(tooltipText).toBe(sineWaveObject3.path);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -131,7 +131,6 @@ test.describe('Performance tests', () => {
|
||||
await page.evaluate(() => window.performance.mark('new-notebook-entry-created'));
|
||||
|
||||
// Enter Notebook Entry text
|
||||
await page.getByLabel('Notebook Entry').last().click();
|
||||
await page.getByLabel('Notebook Entry Input').last().fill('New Entry');
|
||||
await page.locator('.c-ne__save-button').click();
|
||||
await page.evaluate(() => window.performance.mark('new-notebook-entry-filled'));
|
||||
|
||||
@@ -29,7 +29,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
|
||||
randomness: 0,
|
||||
phase: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false
|
||||
infinityValues: false,
|
||||
exceedFloat32: false
|
||||
};
|
||||
|
||||
function GeneratorProvider(openmct, StalenessProvider) {
|
||||
@@ -53,7 +54,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
|
||||
'randomness',
|
||||
'phase',
|
||||
'loadDelay',
|
||||
'infinityValues'
|
||||
'infinityValues',
|
||||
'exceedFloat32'
|
||||
];
|
||||
|
||||
request = request || {};
|
||||
|
||||
@@ -85,7 +85,8 @@
|
||||
data.offset,
|
||||
data.phase,
|
||||
data.randomness,
|
||||
data.infinityValues
|
||||
data.infinityValues,
|
||||
data.exceedFloat32
|
||||
),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
@@ -96,7 +97,8 @@
|
||||
data.offset,
|
||||
data.phase,
|
||||
data.randomness,
|
||||
data.infinityValues
|
||||
data.infinityValues,
|
||||
data.exceedFloat32
|
||||
)
|
||||
}
|
||||
});
|
||||
@@ -136,6 +138,7 @@
|
||||
var randomness = request.randomness;
|
||||
var loadDelay = Math.max(request.loadDelay, 0);
|
||||
var infinityValues = request.infinityValues;
|
||||
var exceedFloat32 = request.exceedFloat32;
|
||||
|
||||
var step = 1000 / dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
@@ -146,10 +149,28 @@
|
||||
data.push({
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, period, amplitude, offset, phase, randomness, infinityValues),
|
||||
sin: sin(
|
||||
nextStep,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
cos: cos(nextStep, period, amplitude, offset, phase, randomness, infinityValues)
|
||||
cos: cos(
|
||||
nextStep,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -176,9 +197,26 @@
|
||||
});
|
||||
}
|
||||
|
||||
function cos(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
|
||||
if (infinityValues && Math.random() > 0.5) {
|
||||
function cos(
|
||||
timestamp,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
) {
|
||||
if (infinityValues && exceedFloat32) {
|
||||
if (Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
} else if (infinityValues && Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (exceedFloat32 && Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -188,9 +226,26 @@
|
||||
);
|
||||
}
|
||||
|
||||
function sin(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
|
||||
if (infinityValues && Math.random() > 0.5) {
|
||||
function sin(
|
||||
timestamp,
|
||||
period,
|
||||
amplitude,
|
||||
offset,
|
||||
phase,
|
||||
randomness,
|
||||
infinityValues,
|
||||
exceedFloat32
|
||||
) {
|
||||
if (infinityValues && exceedFloat32) {
|
||||
if (Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
} else if (infinityValues && Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
} else if (exceedFloat32 && Math.random() < 0.01) {
|
||||
return getRandomFloat32OverflowValue();
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -200,6 +255,13 @@
|
||||
);
|
||||
}
|
||||
|
||||
// Values exceeding float32 range (Positive: 3.4+38, Negative: -3.4+38)
|
||||
function getRandomFloat32OverflowValue() {
|
||||
const sign = Math.random() > 0.5 ? 1 : -1;
|
||||
|
||||
return sign * 3.4e39;
|
||||
}
|
||||
|
||||
function wavelengths() {
|
||||
let values = [];
|
||||
while (values.length < 5) {
|
||||
|
||||
@@ -122,6 +122,13 @@ export default function (openmct) {
|
||||
key: 'infinityValues',
|
||||
property: ['telemetry', 'infinityValues']
|
||||
},
|
||||
{
|
||||
name: 'Exceed Float32 Limits',
|
||||
control: 'toggleSwitch',
|
||||
cssClass: 'l-input',
|
||||
key: 'exceedFloat32',
|
||||
property: ['telemetry', 'exceedFloat32']
|
||||
},
|
||||
{
|
||||
name: 'Provide Staleness Updates',
|
||||
control: 'toggleSwitch',
|
||||
@@ -140,6 +147,7 @@ export default function (openmct) {
|
||||
randomness: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false,
|
||||
exceedFloat32: false,
|
||||
staleness: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<div class="example">{{ msg }}</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
msg: 'Hello world!'
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.example {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
@@ -1,36 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
import HelloWorld from './HelloWorld.vue';
|
||||
|
||||
function SimpleVuePlugin() {
|
||||
return function install(openmct) {
|
||||
openmct.types.addType('hello-world', {
|
||||
name: 'Hello World',
|
||||
description: 'An introduction object',
|
||||
creatable: true
|
||||
});
|
||||
openmct.objectViews.addProvider({
|
||||
name: 'demo-provider',
|
||||
key: 'hello-world',
|
||||
cssClass: 'icon-packet',
|
||||
canView: function (d) {
|
||||
return d.type === 'hello-world';
|
||||
},
|
||||
view: function (domainObject) {
|
||||
var vm;
|
||||
|
||||
return {
|
||||
show: function (container) {
|
||||
vm = new Vue(HelloWorld);
|
||||
container.appendChild(vm.$mount().$el);
|
||||
},
|
||||
destroy: function (container) {
|
||||
//vm.$destroy();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default SimpleVuePlugin;
|
||||
29
package.json
29
package.json
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "openmct",
|
||||
"version": "3.1.0-next",
|
||||
"version": "3.2.0-next",
|
||||
"description": "The Open MCT core platform",
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "7.22.5",
|
||||
"@braintree/sanitize-url": "6.0.2",
|
||||
"@braintree/sanitize-url": "6.0.4",
|
||||
"@deploysentinel/playwright": "0.3.4",
|
||||
"@percy/cli": "1.26.0",
|
||||
"@percy/playwright": "1.0.4",
|
||||
@@ -12,14 +12,13 @@
|
||||
"@types/eventemitter3": "1.2.0",
|
||||
"@types/jasmine": "4.3.4",
|
||||
"@types/lodash": "4.14.192",
|
||||
"@vue/compat": "3.3.4",
|
||||
"@vue/compiler-sfc": "3.3.4",
|
||||
"babel-loader": "9.1.0",
|
||||
"babel-plugin-istanbul": "6.1.1",
|
||||
"codecov": "3.8.3",
|
||||
"comma-separated-values": "3.6.4",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"cspell": "7.3.6",
|
||||
"cspell": "7.3.8",
|
||||
"css-loader": "6.8.1",
|
||||
"d3-axis": "3.0.0",
|
||||
"d3-scale": "3.3.0",
|
||||
@@ -27,11 +26,12 @@
|
||||
"eslint": "8.48.0",
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint-plugin-compat": "4.2.0",
|
||||
"eslint-plugin-no-unsanitized": "4.0.2",
|
||||
"eslint-plugin-playwright": "0.12.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"eslint-plugin-simple-import-sort": "10.0.0",
|
||||
"eslint-plugin-unicorn": "44.0.2",
|
||||
"eslint-plugin-vue": "9.15.0",
|
||||
"eslint-plugin-unicorn": "48.0.1",
|
||||
"eslint-plugin-vue": "9.17.0",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "6.12.0",
|
||||
"eventemitter3": "1.2.0",
|
||||
"file-saver": "2.0.5",
|
||||
@@ -39,7 +39,7 @@
|
||||
"git-rev-sync": "3.0.2",
|
||||
"html2canvas": "1.4.1",
|
||||
"imports-loader": "4.0.1",
|
||||
"jasmine-core": "5.0.0",
|
||||
"jasmine-core": "5.1.1",
|
||||
"karma": "6.4.2",
|
||||
"karma-chrome-launcher": "3.2.0",
|
||||
"karma-cli": "2.0.0",
|
||||
@@ -59,21 +59,22 @@
|
||||
"moment-timezone": "0.5.41",
|
||||
"npm-run-all2": "6.0.6",
|
||||
"nyc": "15.1.0",
|
||||
"painterro": "1.2.78",
|
||||
"painterro": "1.2.87",
|
||||
"plotly.js-basic-dist": "2.20.0",
|
||||
"plotly.js-gl2d-dist": "2.20.0",
|
||||
"prettier": "2.8.7",
|
||||
"printj": "1.3.1",
|
||||
"resolve-url-loader": "5.0.0",
|
||||
"sanitize-html": "2.11.0",
|
||||
"sass": "1.63.4",
|
||||
"sass": "1.68.0",
|
||||
"sass-loader": "13.3.2",
|
||||
"sinon": "15.1.0",
|
||||
"sinon": "17.0.0",
|
||||
"style-loader": "3.3.3",
|
||||
"tiny-emitter": "2.1.0",
|
||||
"typescript": "5.2.2",
|
||||
"uuid": "9.0.0",
|
||||
"vue": "3.3.4",
|
||||
"vue-eslint-parser": "9.3.1",
|
||||
"vue-eslint-parser": "9.3.2",
|
||||
"vue-loader": "16.8.3",
|
||||
"webpack": "5.88.0",
|
||||
"webpack-cli": "5.1.1",
|
||||
@@ -85,9 +86,9 @@
|
||||
"start": "npx webpack serve --config ./.webpack/webpack.dev.js",
|
||||
"start:prod": "npx webpack serve --config ./.webpack/webpack.prod.js",
|
||||
"start:coverage": "npx webpack serve --config ./.webpack/webpack.coverage.js",
|
||||
"lint:js": "eslint example src e2e --ext .js openmct.js --max-warnings=0",
|
||||
"lint:vue": "eslint example src --ext .vue",
|
||||
"lint:spelling": "cspell \"**/*.{js,md,vue}\" --show-context --gitignore",
|
||||
"lint:js": "eslint \"example/**/*.js\" \"src/**/*.js\" \"e2e/**/*.js\" \"openmct.js\" --max-warnings=0",
|
||||
"lint:vue": "eslint \"src/**/*.vue\"",
|
||||
"lint:spelling": "cspell \"**/*.{js,md,vue}\" --show-context --gitignore --quiet",
|
||||
"lint": "run-p \"lint:js -- {1}\" \"lint:vue -- {1}\" \"lint:spelling -- {1}\" --",
|
||||
"lint:fix": "eslint example src e2e --ext .js,.vue openmct.js --fix",
|
||||
"build:prod": "webpack --config ./.webpack/webpack.prod.js",
|
||||
|
||||
@@ -33,7 +33,7 @@ define([
|
||||
'./ui/registries/ToolbarRegistry',
|
||||
'./ui/router/ApplicationRouter',
|
||||
'./ui/router/Browse',
|
||||
'./ui/layout/Layout.vue',
|
||||
'./ui/layout/AppLayout.vue',
|
||||
'./ui/preview/plugin',
|
||||
'./api/Branding',
|
||||
'./plugins/licenses/plugin',
|
||||
|
||||
@@ -3,9 +3,9 @@ import mount from 'utils/mount';
|
||||
import AutoCompleteField from './components/controls/AutoCompleteField.vue';
|
||||
import CheckBoxField from './components/controls/CheckBoxField.vue';
|
||||
import ClockDisplayFormatField from './components/controls/ClockDisplayFormatField.vue';
|
||||
import Datetime from './components/controls/Datetime.vue';
|
||||
import Datetime from './components/controls/DatetimeField.vue';
|
||||
import FileInput from './components/controls/FileInput.vue';
|
||||
import Locator from './components/controls/Locator.vue';
|
||||
import Locator from './components/controls/LocatorField.vue';
|
||||
import NumberField from './components/controls/NumberField.vue';
|
||||
import SelectField from './components/controls/SelectField.vue';
|
||||
import TextAreaField from './components/controls/TextAreaField.vue';
|
||||
@@ -87,7 +87,7 @@ export default class FormControl {
|
||||
onChange
|
||||
};
|
||||
},
|
||||
template: `<FormControlComponent :model="model" @onChange="onChange"></FormControlComponent>`
|
||||
template: `<FormControlComponent :model="model" @on-change="onChange"></FormControlComponent>`
|
||||
},
|
||||
{
|
||||
element,
|
||||
|
||||
@@ -171,7 +171,7 @@ export default class FormsAPI {
|
||||
};
|
||||
},
|
||||
template:
|
||||
'<FormProperties :model="formStructure" @onChange="onChange" @onCancel="onCancel" @onSave="onSave"></FormProperties>'
|
||||
'<FormProperties :model="formStructure" @on-change="onChange" @on-cancel="onCancel" @on-save="onSave"></FormProperties>'
|
||||
},
|
||||
{
|
||||
element,
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
:css-class="row.cssClass"
|
||||
:first="index < 1"
|
||||
:row="row"
|
||||
@onChange="onChange"
|
||||
@on-change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
@@ -94,6 +94,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['on-change', 'on-save', 'on-cancel'],
|
||||
data() {
|
||||
return {
|
||||
invalidProperties: {},
|
||||
@@ -144,13 +145,13 @@ export default {
|
||||
onChange(data) {
|
||||
this.invalidProperties[data.model.key] = data.invalid;
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
},
|
||||
onCancel() {
|
||||
this.$emit('onCancel');
|
||||
this.$emit('on-cancel');
|
||||
},
|
||||
onSave() {
|
||||
this.$emit('onSave');
|
||||
this.$emit('on-save');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-row c-form__row" :class="[{ first: first }, cssClass]" @onChange="onChange">
|
||||
<div class="form-row c-form__row" :class="[{ first: first }, cssClass]" @on-change="onChange">
|
||||
<label class="c-form-row__label" :title="row.description" :for="`form-${row.key}`">
|
||||
{{ row.name }}
|
||||
</label>
|
||||
@@ -51,6 +51,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
formControl: this.openmct.forms.getFormControl(this.row.control),
|
||||
@@ -101,7 +102,7 @@ export default {
|
||||
this.valid = this.validateRow(data);
|
||||
data.invalid = !this.valid;
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
},
|
||||
validateRow(data) {
|
||||
let valid = true;
|
||||
|
||||
@@ -88,6 +88,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
hideOptions: true,
|
||||
@@ -138,7 +139,7 @@ export default {
|
||||
value: newValue
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
},
|
||||
hideOptions(newValue) {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<template>
|
||||
<div class="c-form-control--clock-display-format-fields">
|
||||
<SelectField v-for="item in items" :key="item.key" :model="item" @onChange="onChange" />
|
||||
<SelectField v-for="item in items" :key="item.key" :model="item" @on-change="onChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -39,6 +39,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
items: []
|
||||
@@ -55,7 +56,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onChange(data) {
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
:first="index < 1"
|
||||
:value="JSON.stringify(model.value[index])"
|
||||
:item="item"
|
||||
@onChange="onChange"
|
||||
@on-change="onChange"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
@@ -46,12 +46,13 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
mounted() {
|
||||
this.model.items.forEach((item, index) => (item.key = `${this.model.key}.${index}`));
|
||||
},
|
||||
methods: {
|
||||
onChange(data) {
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<template>
|
||||
<div :class="compositeCssClass">
|
||||
<FormRow :css-class="item.cssClass" :first="first" :row="row" @onChange="onChange" />
|
||||
<FormRow :css-class="item.cssClass" :first="first" :row="row" @on-change="onChange" />
|
||||
<span class="composite-control-label">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
@@ -50,6 +50,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
computed: {
|
||||
compositeCssClass() {
|
||||
return `l-composite-control l-${this.item.control}`;
|
||||
@@ -63,7 +64,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onChange(data) {
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -85,6 +85,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
format: DATE_FORMAT,
|
||||
@@ -139,7 +140,7 @@ export default {
|
||||
value: new Date(timestamp).toISOString()
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
},
|
||||
resetValues() {
|
||||
this.setDatetime();
|
||||
@@ -52,6 +52,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
fileInfo: undefined
|
||||
@@ -101,7 +102,7 @@ export default {
|
||||
model: self.model,
|
||||
value: fileInfo
|
||||
};
|
||||
self.$emit('onChange', data);
|
||||
self.$emit('on-change', data);
|
||||
};
|
||||
|
||||
fileReader.onerror = function (error) {
|
||||
@@ -123,7 +124,7 @@ export default {
|
||||
value: fileInfo
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
},
|
||||
selectFile() {
|
||||
this.$refs.fileInput.click();
|
||||
@@ -135,7 +136,7 @@ export default {
|
||||
model: this.model,
|
||||
value: undefined
|
||||
};
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,6 +42,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
methods: {
|
||||
handleItemSelection(item) {
|
||||
const data = {
|
||||
@@ -49,7 +50,7 @@ export default {
|
||||
value: item.objectPath
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -46,6 +46,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
field: this.model.value
|
||||
@@ -61,7 +62,7 @@ export default {
|
||||
value: this.field
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
selected: this.model.value
|
||||
@@ -56,7 +57,7 @@ export default {
|
||||
value: this.selected
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
field: this.model.value
|
||||
@@ -60,7 +61,7 @@ export default {
|
||||
value: this.field
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
field: this.model.value
|
||||
@@ -60,7 +61,7 @@ export default {
|
||||
value: this.field
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export default {
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
isChecked: false
|
||||
@@ -13,7 +14,7 @@ export default {
|
||||
value: this.isChecked
|
||||
};
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { createMouseEvent, createOpenMct, resetApplicationState } from '../../utils/testing';
|
||||
import Menu from './menu';
|
||||
@@ -186,7 +186,7 @@ describe('The Menu API', () => {
|
||||
superMenuItem.dispatchEvent(mouseOverEvent);
|
||||
const itemDescription = document.querySelector('.l-item-description__description');
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(menuElement).not.toBeNull();
|
||||
expect(itemDescription.innerText).toEqual(actionsArray[0].description);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import EventEmitter from 'EventEmitter';
|
||||
import mount from 'utils/mount';
|
||||
import { h } from 'vue';
|
||||
|
||||
import MenuComponent from './components/Menu.vue';
|
||||
import MenuComponent from './components/MenuComponent.vue';
|
||||
import SuperMenuComponent from './components/SuperMenu.vue';
|
||||
|
||||
export const MENU_PLACEMENT = {
|
||||
@@ -71,11 +71,6 @@ class Menu extends EventEmitter {
|
||||
},
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
// TODO: Remove this exception upon full migration to Vue 3
|
||||
// https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#render-function-argument
|
||||
compatConfig: {
|
||||
RENDER_FUNCTION: false
|
||||
}
|
||||
});
|
||||
|
||||
@@ -98,11 +93,6 @@ class Menu extends EventEmitter {
|
||||
},
|
||||
provide: {
|
||||
options: this.options
|
||||
},
|
||||
// TODO: Remove this exception upon full migration to Vue 3
|
||||
// https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#render-function-argument
|
||||
compatConfig: {
|
||||
RENDER_FUNCTION: false
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ export default class ObjectAPI {
|
||||
const provider = this.getProvider(identifier);
|
||||
|
||||
if (!provider) {
|
||||
throw new Error(`No Provider Matched for keyString "${this.makeKeyString(identifier)}}"`);
|
||||
throw new Error(`No Provider Matched for keyString "${this.makeKeyString(identifier)}"`);
|
||||
}
|
||||
|
||||
if (!provider.get) {
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
<script>
|
||||
export default {
|
||||
inject: ['dismiss', 'element', 'buttons', 'dismissable'],
|
||||
emits: ['destroy'],
|
||||
data: function () {
|
||||
return {
|
||||
focusIndex: -1
|
||||
|
||||
@@ -181,6 +181,10 @@ export default class TelemetryCollection extends EventEmitter {
|
||||
this.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.options.paging) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.unsubscribe = this.openmct.telemetry.subscribe(
|
||||
this.domainObject,
|
||||
(datum) => this._processNewTelemetry(datum),
|
||||
@@ -188,6 +192,10 @@ export default class TelemetryCollection extends EventEmitter {
|
||||
);
|
||||
}
|
||||
|
||||
getLastTelemetryDatum() {
|
||||
return this.boundedTelemetry[this.boundedTelemetry.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter any new telemetry (add/page, historical, subscription) based on
|
||||
* time bounds and dupes
|
||||
@@ -218,7 +226,9 @@ export default class TelemetryCollection extends EventEmitter {
|
||||
|
||||
if (
|
||||
!afterEndOfBounds &&
|
||||
(!beforeStartOfBounds || (this.isStrategyLatest && this.openmct.telemetry.greedyLAD()))
|
||||
(!beforeStartOfBounds ||
|
||||
(beforeStartOfBounds && this.options.paging) ||
|
||||
(this.isStrategyLatest && this.openmct.telemetry.greedyLAD()))
|
||||
) {
|
||||
let isDuplicate = false;
|
||||
let startIndex = this._sortedIndex(datum);
|
||||
@@ -314,6 +324,10 @@ export default class TelemetryCollection extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.options.paging) {
|
||||
return;
|
||||
}
|
||||
|
||||
let startChanged = this.lastBounds.start !== bounds.start;
|
||||
let endChanged = this.lastBounds.end !== bounds.end;
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['row-context-click'],
|
||||
data() {
|
||||
return {
|
||||
datum: undefined,
|
||||
@@ -232,7 +233,7 @@ export default {
|
||||
this.timestampKey = timeSystem.key;
|
||||
},
|
||||
updateViewContext() {
|
||||
this.$emit('rowContextClick', {
|
||||
this.$emit('row-context-click', {
|
||||
viewHistoricalData: true,
|
||||
viewDatumAction: true,
|
||||
getDatum: () => {
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
:has-units="hasUnits"
|
||||
:is-stale="staleObjects.includes(ladRow.key)"
|
||||
:configuration="configuration"
|
||||
@rowContextClick="updateViewContext"
|
||||
@row-context-click="updateViewContext"
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -49,9 +49,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue, { toRaw } from 'vue';
|
||||
import { nextTick, toRaw } from 'vue';
|
||||
|
||||
import StalenessUtils from '@/utils/staleness';
|
||||
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||
|
||||
import LadRow from './LadRow.vue';
|
||||
|
||||
@@ -59,6 +59,7 @@ export default {
|
||||
components: {
|
||||
LadRow
|
||||
},
|
||||
mixins: [stalenessMixin],
|
||||
inject: ['openmct', 'currentView', 'ladTableConfiguration'],
|
||||
props: {
|
||||
domainObject: {
|
||||
@@ -74,7 +75,6 @@ export default {
|
||||
return {
|
||||
items: [],
|
||||
viewContext: {},
|
||||
staleObjects: [],
|
||||
configuration: this.ladTableConfiguration.getConfiguration()
|
||||
};
|
||||
},
|
||||
@@ -96,11 +96,7 @@ export default {
|
||||
return !this.configuration?.hiddenColumns?.type;
|
||||
},
|
||||
staleClass() {
|
||||
if (this.staleObjects.length !== 0) {
|
||||
return 'is-stale';
|
||||
}
|
||||
|
||||
return '';
|
||||
return this.isStale ? 'is-stale' : '';
|
||||
},
|
||||
applyLayoutClass() {
|
||||
if (this.configuration.isFixedLayout) {
|
||||
@@ -133,12 +129,16 @@ export default {
|
||||
this.composition.on('remove', this.removeItem);
|
||||
this.composition.on('reorder', this.reorder);
|
||||
this.composition.load();
|
||||
this.stalenessSubscription = {};
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
this.viewActionsCollection = this.openmct.actions.getActionsCollection(
|
||||
this.objectPath,
|
||||
this.currentView
|
||||
);
|
||||
this.setupClockChangedEvent((domainObject) => {
|
||||
this.triggerUnsubscribeFromStaleness(domainObject);
|
||||
this.subscribeToStaleness(domainObject);
|
||||
});
|
||||
|
||||
this.initializeViewActions();
|
||||
},
|
||||
unmounted() {
|
||||
@@ -147,11 +147,6 @@ export default {
|
||||
this.composition.off('add', this.addItem);
|
||||
this.composition.off('remove', this.removeItem);
|
||||
this.composition.off('reorder', this.reorder);
|
||||
|
||||
Object.values(this.stalenessSubscription).forEach((stalenessSubscription) => {
|
||||
stalenessSubscription.unsubscribe();
|
||||
stalenessSubscription.stalenessUtils.destroy();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
addItem(domainObject) {
|
||||
@@ -160,35 +155,16 @@ export default {
|
||||
item.key = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
|
||||
this.items.push(item);
|
||||
|
||||
this.stalenessSubscription[item.key] = {};
|
||||
this.stalenessSubscription[item.key].stalenessUtils = new StalenessUtils(
|
||||
this.openmct,
|
||||
domainObject
|
||||
);
|
||||
this.openmct.telemetry.isStale(domainObject).then((stalenessResponse) => {
|
||||
if (stalenessResponse !== undefined) {
|
||||
this.handleStaleness(item.key, stalenessResponse);
|
||||
}
|
||||
});
|
||||
const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(
|
||||
domainObject,
|
||||
(stalenessResponse) => {
|
||||
this.handleStaleness(item.key, stalenessResponse);
|
||||
}
|
||||
);
|
||||
|
||||
this.stalenessSubscription[item.key].unsubscribe = stalenessSubscription;
|
||||
this.subscribeToStaleness(domainObject);
|
||||
},
|
||||
removeItem(identifier) {
|
||||
const SKIP_CHECK = true;
|
||||
const keystring = this.openmct.objects.makeKeyString(identifier);
|
||||
const index = this.items.findIndex((item) => keystring === item.key);
|
||||
|
||||
const index = this.items.findIndex((item) => keystring === item.key);
|
||||
this.items.splice(index, 1);
|
||||
|
||||
this.stalenessSubscription[keystring].unsubscribe();
|
||||
this.handleStaleness(keystring, { isStale: false }, SKIP_CHECK);
|
||||
const domainObject = this.openmct.objects.get(keystring);
|
||||
this.triggerUnsubscribeFromStaleness(domainObject);
|
||||
},
|
||||
reorder(reorderPlan) {
|
||||
const oldItems = this.items.slice();
|
||||
@@ -204,23 +180,6 @@ export default {
|
||||
handleConfigurationChange(configuration) {
|
||||
this.configuration = configuration;
|
||||
},
|
||||
handleStaleness(id, stalenessResponse, skipCheck = false) {
|
||||
if (
|
||||
skipCheck ||
|
||||
this.stalenessSubscription[id].stalenessUtils.shouldUpdateStaleness(stalenessResponse)
|
||||
) {
|
||||
const index = this.staleObjects.indexOf(id);
|
||||
if (stalenessResponse.isStale) {
|
||||
if (index === -1) {
|
||||
this.staleObjects.push(id);
|
||||
}
|
||||
} else {
|
||||
if (index !== -1) {
|
||||
this.staleObjects.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
updateViewContext(rowContext) {
|
||||
this.viewContext.row = rowContext;
|
||||
},
|
||||
|
||||
@@ -45,9 +45,9 @@
|
||||
:domain-object="ladRow.domainObject"
|
||||
:path-to-table="ladTable.objectPath"
|
||||
:has-units="hasUnits"
|
||||
:is-stale="staleObjects.includes(combineKeys(ladTable.key, ladRow.key))"
|
||||
:is-stale="staleObjects.includes(ladRow.key)"
|
||||
:configuration="configuration"
|
||||
@rowContextClick="updateViewContext"
|
||||
@row-context-click="updateViewContext"
|
||||
/>
|
||||
</template>
|
||||
</tbody>
|
||||
@@ -56,7 +56,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StalenessUtils from '@/utils/staleness';
|
||||
import { toRaw } from 'vue';
|
||||
|
||||
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||
|
||||
import LadRow from './LadRow.vue';
|
||||
|
||||
@@ -64,6 +66,7 @@ export default {
|
||||
components: {
|
||||
LadRow
|
||||
},
|
||||
mixins: [stalenessMixin],
|
||||
inject: ['openmct', 'objectPath', 'currentView', 'ladTableConfiguration'],
|
||||
props: {
|
||||
domainObject: {
|
||||
@@ -76,8 +79,8 @@ export default {
|
||||
ladTableObjects: [],
|
||||
ladTelemetryObjects: {},
|
||||
viewContext: {},
|
||||
staleObjects: [],
|
||||
configuration: this.ladTableConfiguration.getConfiguration()
|
||||
configuration: this.ladTableConfiguration.getConfiguration(),
|
||||
subscribedObjects: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -108,11 +111,7 @@ export default {
|
||||
return !this.configuration?.hiddenColumns?.type;
|
||||
},
|
||||
staleClass() {
|
||||
if (this.staleObjects.length !== 0) {
|
||||
return 'is-stale';
|
||||
}
|
||||
|
||||
return '';
|
||||
return this.isStale ? 'is-stale' : '';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -125,8 +124,10 @@ export default {
|
||||
this.composition.on('remove', this.removeLadTable);
|
||||
this.composition.on('reorder', this.reorderLadTables);
|
||||
this.composition.load();
|
||||
|
||||
this.stalenessSubscription = {};
|
||||
this.setupClockChangedEvent((domainObject) => {
|
||||
this.triggerUnsubscribeFromStaleness(domainObject);
|
||||
this.subscribeToStaleness(domainObject);
|
||||
});
|
||||
},
|
||||
unmounted() {
|
||||
this.ladTableConfiguration.off('change', this.handleConfigurationChange);
|
||||
@@ -137,11 +138,6 @@ export default {
|
||||
c.composition.off('add', c.addCallback);
|
||||
c.composition.off('remove', c.removeCallback);
|
||||
});
|
||||
|
||||
Object.values(this.stalenessSubscription).forEach((stalenessSubscription) => {
|
||||
stalenessSubscription.unsubscribe();
|
||||
stalenessSubscription.stalenessUtils.destroy();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
addLadTable(domainObject) {
|
||||
@@ -176,9 +172,18 @@ export default {
|
||||
);
|
||||
let ladTable = this.ladTableObjects[index];
|
||||
|
||||
this.ladTelemetryObjects[ladTable.key].forEach((telemetryObject) => {
|
||||
let combinedKey = this.combineKeys(ladTable.key, telemetryObject.key);
|
||||
this.unwatchStaleness(combinedKey);
|
||||
ladTable?.domainObject?.composition.forEach((telemetryObject) => {
|
||||
const telemetryKey = this.openmct.objects.makeKeyString(telemetryObject);
|
||||
if (!this.subscribedObjects?.[telemetryKey]) {
|
||||
return;
|
||||
}
|
||||
let subscribedObject = toRaw(this.subscribedObjects[telemetryKey]);
|
||||
if (subscribedObject?.count > 1) {
|
||||
subscribedObject.count -= 1;
|
||||
} else if (subscribedObject?.count === 1) {
|
||||
this.triggerUnsubscribeFromStaleness(subscribedObject.domainObject);
|
||||
delete this.subscribedObjects[telemetryKey];
|
||||
}
|
||||
});
|
||||
|
||||
delete this.ladTelemetryObjects[ladTable.key];
|
||||
@@ -187,11 +192,7 @@ export default {
|
||||
reorderLadTables(reorderPlan) {
|
||||
let oldComposition = this.ladTableObjects.slice();
|
||||
reorderPlan.forEach((reorderEvent) => {
|
||||
this.$set(
|
||||
this.ladTableObjects,
|
||||
reorderEvent.newIndex,
|
||||
oldComposition[reorderEvent.oldIndex]
|
||||
);
|
||||
this.ladTableObjects[reorderEvent.newIndex] = oldComposition[reorderEvent.oldIndex];
|
||||
});
|
||||
},
|
||||
addTelemetryObject(ladTable) {
|
||||
@@ -199,77 +200,35 @@ export default {
|
||||
let telemetryObject = {};
|
||||
telemetryObject.key = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
telemetryObject.domainObject = domainObject;
|
||||
const combinedKey = this.combineKeys(ladTable.key, telemetryObject.key);
|
||||
|
||||
const telemetryObjects = this.ladTelemetryObjects[ladTable.key];
|
||||
telemetryObjects.push(telemetryObject);
|
||||
|
||||
this.ladTelemetryObjects[ladTable.key] = telemetryObjects;
|
||||
|
||||
this.stalenessSubscription[combinedKey] = {};
|
||||
this.stalenessSubscription[combinedKey].stalenessUtils = new StalenessUtils(
|
||||
this.openmct,
|
||||
domainObject
|
||||
);
|
||||
|
||||
this.openmct.telemetry.isStale(domainObject).then((stalenessResponse) => {
|
||||
if (stalenessResponse !== undefined) {
|
||||
this.handleStaleness(combinedKey, stalenessResponse);
|
||||
}
|
||||
});
|
||||
const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(
|
||||
domainObject,
|
||||
(stalenessResponse) => {
|
||||
this.handleStaleness(combinedKey, stalenessResponse);
|
||||
}
|
||||
);
|
||||
|
||||
this.stalenessSubscription[combinedKey].unsubscribe = stalenessSubscription;
|
||||
if (!this.subscribedObjects[telemetryObject?.key]) {
|
||||
this.subscribeToStaleness(domainObject);
|
||||
this.subscribedObjects[telemetryObject?.key] = { count: 1, domainObject };
|
||||
} else if (this.subscribedObjects?.[telemetryObject?.key]?.count) {
|
||||
this.subscribedObjects[telemetryObject?.key].count += 1;
|
||||
}
|
||||
};
|
||||
},
|
||||
removeTelemetryObject(ladTable) {
|
||||
return (identifier) => {
|
||||
const keystring = this.openmct.objects.makeKeyString(identifier);
|
||||
const telemetryObjects = this.ladTelemetryObjects[ladTable.key];
|
||||
const combinedKey = this.combineKeys(ladTable.key, keystring);
|
||||
let index = telemetryObjects.findIndex(
|
||||
(telemetryObject) => keystring === telemetryObject.key
|
||||
);
|
||||
|
||||
this.unwatchStaleness(combinedKey);
|
||||
|
||||
telemetryObjects.splice(index, 1);
|
||||
this.ladTelemetryObjects[ladTable.key] = telemetryObjects;
|
||||
};
|
||||
},
|
||||
unwatchStaleness(combinedKey) {
|
||||
const SKIP_CHECK = true;
|
||||
|
||||
this.stalenessSubscription[combinedKey].unsubscribe();
|
||||
this.stalenessSubscription[combinedKey].stalenessUtils.destroy();
|
||||
this.handleStaleness(combinedKey, { isStale: false }, SKIP_CHECK);
|
||||
|
||||
delete this.stalenessSubscription[combinedKey];
|
||||
},
|
||||
handleConfigurationChange(configuration) {
|
||||
this.configuration = configuration;
|
||||
},
|
||||
handleStaleness(combinedKey, stalenessResponse, skipCheck = false) {
|
||||
if (
|
||||
skipCheck ||
|
||||
this.stalenessSubscription[combinedKey].stalenessUtils.shouldUpdateStaleness(
|
||||
stalenessResponse
|
||||
)
|
||||
) {
|
||||
const index = this.staleObjects.indexOf(combinedKey);
|
||||
const foundStaleObject = index > -1;
|
||||
if (stalenessResponse.isStale && !foundStaleObject) {
|
||||
this.staleObjects.push(combinedKey);
|
||||
} else if (!stalenessResponse.isStale && foundStaleObject) {
|
||||
this.staleObjects.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
updateViewContext(rowContext) {
|
||||
this.viewContext.row = rowContext;
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
resetApplicationState,
|
||||
spyOnBuiltins
|
||||
} from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import LadPlugin from './plugin.js';
|
||||
|
||||
@@ -233,7 +233,7 @@ describe('The LAD Table', () => {
|
||||
anotherTelemetryObjectPromise,
|
||||
aggregateTelemetryObjectResolve
|
||||
]);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('should show one row per object in the composition', () => {
|
||||
@@ -244,7 +244,7 @@ describe('The LAD Table', () => {
|
||||
it('should show the most recent datum from the telemetry producing object', async () => {
|
||||
const latestDatum = getLatestTelemetry(mockTelemetry, { timeFormat });
|
||||
const expectedDate = utcTimeFormat(latestDatum[timeFormat]);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const latestDate = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText;
|
||||
expect(latestDate).toBe(expectedDate);
|
||||
const dataType = parent
|
||||
@@ -254,7 +254,7 @@ describe('The LAD Table', () => {
|
||||
});
|
||||
|
||||
it('should show aggregate telemetry type with blank data', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const latestData = parent
|
||||
.querySelectorAll(TABLE_BODY_ROWS)[1]
|
||||
.querySelectorAll('td')[2].innerText;
|
||||
@@ -282,7 +282,7 @@ describe('The LAD Table', () => {
|
||||
const mostRecentTelemetry = getLatestTelemetry(mockTelemetry, { timeFormat });
|
||||
const rangeValue = mostRecentTelemetry[range];
|
||||
const domainValue = utcTimeFormat(mostRecentTelemetry[domain]);
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const actualDomainValue = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText;
|
||||
const actualRangeValue = parent.querySelector(TABLE_BODY_FIRST_ROW_THIRD_DATA).innerText;
|
||||
expect(actualRangeValue).toBe(rangeValue);
|
||||
@@ -424,7 +424,7 @@ describe('The LAD Table Set', () => {
|
||||
ladTableSetView = ladTableSetViewProvider.view(mockObj.ladTableSet, [mockObj.ladTableSet]);
|
||||
ladTableSetView.show(child);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('should show one row per lad table object in the composition', () => {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import { createOpenMct, resetApplicationState, spyOnBuiltins } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import AutoflowTabularConstants from './AutoflowTabularConstants';
|
||||
import AutoflowTabularPlugin from './AutoflowTabularPlugin';
|
||||
@@ -175,7 +175,7 @@ xdescribe('AutoflowTabularPlugin', () => {
|
||||
view = provider.view(testObject, [testObject]);
|
||||
view.show(testContainer);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -67,6 +67,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['subscribe', 'unsubscribe'],
|
||||
data() {
|
||||
return {
|
||||
isZoomed: false,
|
||||
|
||||
@@ -6,7 +6,7 @@ import BarGraphOptions from './BarGraphOptions.vue';
|
||||
export default function BarGraphInspectorViewProvider(openmct) {
|
||||
return {
|
||||
key: BAR_GRAPH_INSPECTOR_KEY,
|
||||
name: 'Bar Graph Configuration',
|
||||
name: 'Config',
|
||||
canView: function (selection) {
|
||||
if (selection.length === 0 || selection[0].length === 0) {
|
||||
return false;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
edit-title="Manually set the color for this bar graph series."
|
||||
view-title="The color for this bar graph series."
|
||||
short-label="Color"
|
||||
@colorSet="setColor"
|
||||
@color-set="setColor"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
// import BarGraph from './BarGraphPlot.vue';
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { BAR_GRAPH_KEY, BAR_GRAPH_VIEW } from './BarGraphConstants';
|
||||
import { BAR_GRAPH_INSPECTOR_KEY, BAR_GRAPH_KEY, BAR_GRAPH_VIEW } from './BarGraphConstants';
|
||||
import BarGraphPlugin from './plugin';
|
||||
|
||||
describe('the plugin', function () {
|
||||
@@ -153,7 +153,7 @@ describe('the plugin', function () {
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('provides a bar graph view', () => {
|
||||
@@ -254,7 +254,7 @@ describe('the plugin', function () {
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('Renders spectral plots', async () => {
|
||||
@@ -305,8 +305,8 @@ describe('the plugin', function () {
|
||||
barGraphView.show(child, true);
|
||||
mockComposition.emit('add', dotFullTelemetryObject);
|
||||
|
||||
await Vue.nextTick();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
|
||||
const plotElement = element.querySelector('.cartesianlayer .scatterlayer .trace .lines');
|
||||
expect(plotElement).not.toBeNull();
|
||||
@@ -578,12 +578,10 @@ describe('the plugin', function () {
|
||||
child.append(viewContainer);
|
||||
|
||||
const applicableViews = openmct.inspectorViews.get(selection);
|
||||
plotInspectorView = applicableViews.filter(
|
||||
(view) => view.name === 'Bar Graph Configuration'
|
||||
)[0];
|
||||
plotInspectorView = applicableViews.filter((view) => view.key === BAR_GRAPH_INSPECTOR_KEY)[0];
|
||||
plotInspectorView.show(viewContainer);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
optionsElement = element.querySelector('.c-bar-graph-options');
|
||||
});
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['on-change'],
|
||||
data() {
|
||||
return {
|
||||
rangeMax: this.model.value.rangeMax,
|
||||
@@ -119,7 +120,7 @@ export default {
|
||||
this.model.validate(data);
|
||||
}
|
||||
|
||||
this.$emit('onChange', data);
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,6 +71,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['subscribe', 'unsubscribe'],
|
||||
data() {
|
||||
return {
|
||||
isZoomed: false,
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
edit-title="Manually set the line and marker color for this plot."
|
||||
view-title="The line and marker color for this plot."
|
||||
short-label="Color"
|
||||
@colorSet="setColor"
|
||||
@color-set="setColor"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -118,7 +118,7 @@ export default function () {
|
||||
onChange
|
||||
};
|
||||
},
|
||||
template: `<scatter-plot-form :model="model" @onChange="onChange"></scatter-plot-form>`
|
||||
template: `<scatter-plot-form :model="model" @on-change="onChange"></scatter-plot-form>`
|
||||
},
|
||||
{
|
||||
app: openmct.app,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ScatterPlotPlugin from './plugin';
|
||||
import { SCATTER_PLOT_KEY, SCATTER_PLOT_VIEW } from './scatterPlotConstants';
|
||||
@@ -178,7 +178,7 @@ describe('the plugin', function () {
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('provides a scatter plot view', () => {
|
||||
@@ -406,7 +406,7 @@ describe('the plugin', function () {
|
||||
plotInspectorView = applicableViews[0];
|
||||
plotInspectorView.show(viewContainer);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
optionsElement = element.querySelector('.c-scatter-plot-options');
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createMouseEvent, createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ClearDataPlugin from './plugin.js';
|
||||
|
||||
@@ -213,7 +213,7 @@ describe('The Clear Data Plugin:', () => {
|
||||
});
|
||||
|
||||
it('renders its major elements', async () => {
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
const indicatorClass = appHolder.querySelector('.c-indicator');
|
||||
const iconClass = appHolder.querySelector('.icon-clear-data');
|
||||
const indicatorLabel = appHolder.querySelector('.c-indicator__label');
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import mount from 'utils/mount';
|
||||
|
||||
import Clock from './components/Clock.vue';
|
||||
import Clock from './components/ClockComponent.vue';
|
||||
|
||||
export default function ClockViewProvider(openmct) {
|
||||
return {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import clockPlugin from './plugin';
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('Clock plugin:', () => {
|
||||
clockView = clockViewProvider.view(mutableClockObject);
|
||||
clockView.show(child);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
});
|
||||
|
||||
@@ -232,7 +232,7 @@ describe('Clock plugin:', () => {
|
||||
it('contains text', async () => {
|
||||
await setupClock(true);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
|
||||
clockIndicator = openmct.indicators.indicatorObjects.find(
|
||||
|
||||
@@ -97,8 +97,10 @@ describe('The condition', function () {
|
||||
mockTimeSystems = {
|
||||
key: 'utc'
|
||||
};
|
||||
openmct.time = jasmine.createSpyObj('time', ['getAllTimeSystems']);
|
||||
openmct.time = jasmine.createSpyObj('time', ['getAllTimeSystems', 'on', 'off']);
|
||||
openmct.time.getAllTimeSystems.and.returnValue([mockTimeSystems]);
|
||||
openmct.time.on.and.returnValue(() => {});
|
||||
openmct.time.off.and.returnValue(() => {});
|
||||
|
||||
testConditionDefinition = {
|
||||
id: '123-456',
|
||||
|
||||
@@ -66,12 +66,12 @@
|
||||
:is-editing="isEditing"
|
||||
:move-index="moveIndex"
|
||||
:is-dragging="isDragging"
|
||||
@updateCondition="updateCondition"
|
||||
@removeCondition="removeCondition"
|
||||
@cloneCondition="cloneCondition"
|
||||
@setMoveIndex="setMoveIndex"
|
||||
@dragComplete="dragComplete"
|
||||
@dropCondition="dropCondition"
|
||||
@update-condition="updateCondition"
|
||||
@remove-condition="removeCondition"
|
||||
@clone-condition="cloneCondition"
|
||||
@set-move-index="setMoveIndex"
|
||||
@drag-complete="dragComplete"
|
||||
@drop-condition="dropCondition"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,15 +79,16 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StalenessUtils from '@/utils/staleness';
|
||||
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||
|
||||
import ConditionManager from '../ConditionManager';
|
||||
import Condition from './Condition.vue';
|
||||
import Condition from './ConditionItem.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Condition
|
||||
},
|
||||
mixins: [stalenessMixin],
|
||||
inject: ['openmct', 'domainObject'],
|
||||
props: {
|
||||
isEditing: Boolean,
|
||||
@@ -102,6 +103,12 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
'condition-set-result-updated',
|
||||
'no-telemetry-objects',
|
||||
'telemetry-updated',
|
||||
'telemetry-staleness'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
expanded: true,
|
||||
@@ -135,13 +142,6 @@ export default {
|
||||
if (this.stopObservingForChanges) {
|
||||
this.stopObservingForChanges();
|
||||
}
|
||||
|
||||
if (this.stalenessSubscription) {
|
||||
Object.values(this.stalenessSubscription).forEach((stalenessSubscription) => {
|
||||
stalenessSubscription.unsubscribe();
|
||||
stalenessSubscription.stalenessUtils.destroy();
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
@@ -153,16 +153,29 @@ export default {
|
||||
this.conditionManager = new ConditionManager(this.domainObject, this.openmct);
|
||||
this.conditionManager.on('conditionSetResultUpdated', this.handleConditionSetResultUpdated);
|
||||
this.conditionManager.on('noTelemetryObjects', this.emitNoTelemetryObjectEvent);
|
||||
this.stalenessSubscription = {};
|
||||
this.setupClockChangedEvent((domainObject) => {
|
||||
this.triggerUnsubscribeFromStaleness(domainObject, () => {
|
||||
this.emitStaleness({
|
||||
keyString: domainObject.identifier,
|
||||
stalenessResponse: { isStale: false }
|
||||
});
|
||||
});
|
||||
this.subscribeToStaleness(domainObject, (stalenessResponse) => {
|
||||
this.emitStaleness({
|
||||
keyString: domainObject.identifier,
|
||||
stalenessResponse: stalenessResponse
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
handleConditionSetResultUpdated(data) {
|
||||
this.currentConditionId = data.conditionId;
|
||||
this.$emit('conditionSetResultUpdated', data);
|
||||
this.$emit('condition-set-result-updated', data);
|
||||
},
|
||||
emitNoTelemetryObjectEvent(data) {
|
||||
this.currentConditionId = '';
|
||||
this.$emit('noTelemetryObjects');
|
||||
this.$emit('no-telemetry-objects');
|
||||
},
|
||||
observeForChanges() {
|
||||
this.stopObservingForChanges = this.openmct.objects.observe(
|
||||
@@ -219,30 +232,14 @@ export default {
|
||||
const keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
|
||||
this.telemetryObjs.push(domainObject);
|
||||
this.$emit('telemetryUpdated', this.telemetryObjs);
|
||||
this.$emit('telemetry-updated', this.telemetryObjs);
|
||||
|
||||
if (!this.stalenessSubscription[keyString]) {
|
||||
this.stalenessSubscription[keyString] = {};
|
||||
}
|
||||
|
||||
this.stalenessSubscription[keyString].stalenessUtils = new StalenessUtils(
|
||||
this.openmct,
|
||||
domainObject
|
||||
);
|
||||
|
||||
this.openmct.telemetry.isStale(domainObject).then((stalenessResponse) => {
|
||||
if (stalenessResponse !== undefined) {
|
||||
this.handleStaleness(keyString, stalenessResponse);
|
||||
}
|
||||
this.subscribeToStaleness(domainObject, (stalenessResponse) => {
|
||||
this.emitStaleness({
|
||||
keyString,
|
||||
stalenessResponse: stalenessResponse
|
||||
});
|
||||
});
|
||||
const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(
|
||||
domainObject,
|
||||
(stalenessResponse) => {
|
||||
this.handleStaleness(keyString, stalenessResponse);
|
||||
}
|
||||
);
|
||||
|
||||
this.stalenessSubscription[keyString].unsubscribe = stalenessSubscription;
|
||||
},
|
||||
removeTelemetryObject(identifier) {
|
||||
const keyString = this.openmct.objects.makeKeyString(identifier);
|
||||
@@ -252,34 +249,20 @@ export default {
|
||||
return objId === keyString;
|
||||
});
|
||||
|
||||
const domainObject = this.telemetryObjs[index];
|
||||
this.triggerUnsubscribeFromStaleness(domainObject, () => {
|
||||
this.emitStaleness({
|
||||
keyString,
|
||||
stalenessResponse: { isStale: false }
|
||||
});
|
||||
});
|
||||
|
||||
if (index > -1) {
|
||||
this.telemetryObjs.splice(index, 1);
|
||||
}
|
||||
|
||||
if (this.stalenessSubscription[keyString]) {
|
||||
this.stalenessSubscription[keyString].unsubscribe();
|
||||
this.stalenessSubscription[keyString].stalenessUtils.destroy();
|
||||
this.emitStaleness({
|
||||
keyString,
|
||||
isStale: false
|
||||
});
|
||||
delete this.stalenessSubscription[keyString];
|
||||
}
|
||||
},
|
||||
handleStaleness(keyString, stalenessResponse) {
|
||||
if (
|
||||
this.stalenessSubscription[keyString].stalenessUtils.shouldUpdateStaleness(
|
||||
stalenessResponse
|
||||
)
|
||||
) {
|
||||
this.emitStaleness({
|
||||
keyString,
|
||||
isStale: stalenessResponse.isStale
|
||||
});
|
||||
}
|
||||
},
|
||||
emitStaleness(stalenessObject) {
|
||||
this.$emit('telemetryStaleness', stalenessObject);
|
||||
this.$emit('telemetry-staleness', stalenessObject);
|
||||
},
|
||||
addCondition() {
|
||||
this.conditionManager.addCondition();
|
||||
|
||||
@@ -189,7 +189,7 @@ import { v4 as uuid } from 'uuid';
|
||||
import { TRIGGER, TRIGGER_LABEL } from '@/plugins/condition/utils/constants';
|
||||
|
||||
import ConditionDescription from './ConditionDescription.vue';
|
||||
import Criterion from './Criterion.vue';
|
||||
import Criterion from './CriterionItem.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -229,6 +229,14 @@ export default {
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
'set-move-index',
|
||||
'drag-complete',
|
||||
'drop-condition',
|
||||
'remove-condition',
|
||||
'clone-condition',
|
||||
'update-condition'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
currentCriteria: this.currentCriteria,
|
||||
@@ -313,11 +321,11 @@ export default {
|
||||
event.dataTransfer.setData('dragging', event.target); // required for FF to initiate drag
|
||||
event.dataTransfer.effectAllowed = 'copyMove';
|
||||
event.dataTransfer.setDragImage(event.target.closest('.c-condition-h'), 0, 0);
|
||||
this.$emit('setMoveIndex', this.conditionIndex);
|
||||
this.$emit('set-move-index', this.conditionIndex);
|
||||
},
|
||||
dragEnd() {
|
||||
this.dragStarted = false;
|
||||
this.$emit('dragComplete');
|
||||
this.$emit('drag-complete');
|
||||
},
|
||||
dropCondition(event, targetIndex) {
|
||||
if (!this.isDragging) {
|
||||
@@ -331,7 +339,7 @@ export default {
|
||||
if (this.isValidTarget(targetIndex)) {
|
||||
this.dragElement = undefined;
|
||||
this.draggingOver = false;
|
||||
this.$emit('dropCondition', targetIndex);
|
||||
this.$emit('drop-condition', targetIndex);
|
||||
}
|
||||
},
|
||||
dragEnter(event, targetIndex) {
|
||||
@@ -359,10 +367,10 @@ export default {
|
||||
},
|
||||
destroy() {},
|
||||
removeCondition() {
|
||||
this.$emit('removeCondition', this.condition.id);
|
||||
this.$emit('remove-condition', this.condition.id);
|
||||
},
|
||||
cloneCondition() {
|
||||
this.$emit('cloneCondition', {
|
||||
this.$emit('clone-condition', {
|
||||
condition: this.condition,
|
||||
index: this.conditionIndex
|
||||
});
|
||||
@@ -380,7 +388,7 @@ export default {
|
||||
this.persist();
|
||||
},
|
||||
persist() {
|
||||
this.$emit('updateCondition', {
|
||||
this.$emit('update-condition', {
|
||||
condition: this.condition
|
||||
});
|
||||
},
|
||||
@@ -39,22 +39,24 @@
|
||||
:is-editing="isEditing"
|
||||
:test-data="testData"
|
||||
:telemetry="telemetryObjs"
|
||||
@updateTestData="updateTestData"
|
||||
@update-test-data="updateTestData"
|
||||
/>
|
||||
<ConditionCollection
|
||||
class="c-cs__conditions"
|
||||
:is-editing="isEditing"
|
||||
:test-data="testData"
|
||||
@conditionSetResultUpdated="updateCurrentOutput"
|
||||
@noTelemetryObjects="updateCurrentOutput('---')"
|
||||
@telemetryUpdated="updateTelemetry"
|
||||
@telemetryStaleness="handleStaleness"
|
||||
@condition-set-result-updated="updateCurrentOutput"
|
||||
@no-telemetry-objects="updateCurrentOutput('---')"
|
||||
@telemetry-updated="updateTelemetry"
|
||||
@telemetry-staleness="handleStaleness"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||
|
||||
import ConditionCollection from './ConditionCollection.vue';
|
||||
import TestData from './TestData.vue';
|
||||
|
||||
@@ -63,6 +65,7 @@ export default {
|
||||
TestData,
|
||||
ConditionCollection
|
||||
},
|
||||
mixins: [stalenessMixin],
|
||||
inject: ['openmct', 'domainObject'],
|
||||
props: {
|
||||
isEditing: Boolean
|
||||
@@ -71,15 +74,9 @@ export default {
|
||||
return {
|
||||
currentConditionOutput: '',
|
||||
telemetryObjs: [],
|
||||
testData: {},
|
||||
staleObjects: []
|
||||
testData: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isStale() {
|
||||
return this.staleObjects.length !== 0;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.conditionSetIdentifier = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||
this.testData = {
|
||||
@@ -100,17 +97,8 @@ export default {
|
||||
updateTestData(testData) {
|
||||
this.testData = testData;
|
||||
},
|
||||
handleStaleness({ keyString, isStale }) {
|
||||
const index = this.staleObjects.indexOf(keyString);
|
||||
if (isStale) {
|
||||
if (index === -1) {
|
||||
this.staleObjects.push(keyString);
|
||||
}
|
||||
} else {
|
||||
if (index !== -1) {
|
||||
this.staleObjects.splice(index, 1);
|
||||
}
|
||||
}
|
||||
handleStaleness({ keyString, stalenessResponse }) {
|
||||
this.addOrRemoveStaleObject(keyString, stalenessResponse);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -136,6 +136,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['persist'],
|
||||
data() {
|
||||
return {
|
||||
telemetryMetadataOptions: [],
|
||||
@@ -127,6 +127,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['update-test-data'],
|
||||
data() {
|
||||
return {
|
||||
expanded: true,
|
||||
@@ -225,7 +226,7 @@ export default {
|
||||
this.updateTestData();
|
||||
},
|
||||
updateTestData() {
|
||||
this.$emit('updateTestData', {
|
||||
this.$emit('update-test-data', {
|
||||
applied: this.isApplied,
|
||||
conditionTestInputs: this.testInputs
|
||||
});
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
<!-- Save Styles -->
|
||||
<toolbar-button
|
||||
v-if="canSaveStyle"
|
||||
ref="saveStyleButton"
|
||||
class="c-style__toolbar-button--save c-local-controls--show-on-hover c-icon-button c-icon-button--major"
|
||||
:options="saveOptions"
|
||||
@click="saveItemStyle()"
|
||||
@@ -120,6 +121,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['persist', 'save-style'],
|
||||
computed: {
|
||||
itemStyle() {
|
||||
return getStylesWithoutNoneValue(this.styleItem.style);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
<div class="c-inspect-styles__content">
|
||||
<div v-if="staticStyle" class="c-inspect-styles__style">
|
||||
<StyleEditor
|
||||
ref="styleEditor"
|
||||
class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="allowEditing"
|
||||
|
||||
@@ -52,6 +52,8 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
|
||||
this.initialize();
|
||||
this.emitEvent('criterionUpdated', this);
|
||||
|
||||
this.openmct.time.on('clockChanged', this.subscribeToStaleness);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
@@ -95,6 +97,10 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
this.unsubscribeFromStaleness();
|
||||
}
|
||||
|
||||
if (!this.telemetryObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.stalenessUtils) {
|
||||
this.stalenessUtils = new StalenessUtils(this.openmct, this.telemetryObject);
|
||||
}
|
||||
@@ -333,6 +339,8 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
delete this.ageCheck;
|
||||
}
|
||||
|
||||
this.openmct.time.off('clockChanged', this.subscribeToStaleness);
|
||||
|
||||
if (this.stalenessUtils) {
|
||||
this.stalenessUtils.destroy();
|
||||
}
|
||||
|
||||
@@ -88,7 +88,9 @@ describe('The telemetry criterion', function () {
|
||||
'timeSystem',
|
||||
'bounds',
|
||||
'getAllTimeSystems',
|
||||
'getContextForView'
|
||||
'getContextForView',
|
||||
'on',
|
||||
'off'
|
||||
]);
|
||||
openmct.time.timeSystem.and.returnValue({ key: 'system' });
|
||||
openmct.time.bounds.and.returnValue({
|
||||
@@ -97,6 +99,8 @@ describe('The telemetry criterion', function () {
|
||||
});
|
||||
openmct.time.getAllTimeSystems.and.returnValue([{ key: 'system' }]);
|
||||
openmct.time.getContextForView.and.returnValue({});
|
||||
openmct.time.on.and.returnValue(() => {});
|
||||
openmct.time.off.and.returnValue(() => {});
|
||||
|
||||
testCriterionDefinition = {
|
||||
id: 'test-criterion-id',
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import mount from 'utils/mount';
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ConditionManager from '@/plugins/condition/ConditionManager';
|
||||
|
||||
@@ -142,6 +143,7 @@ describe('the plugin', function () {
|
||||
let conditionWidgetItem;
|
||||
let selection;
|
||||
let component;
|
||||
let _destroy;
|
||||
let styleViewComponentObject;
|
||||
const conditionSetDomainObject = {
|
||||
configuration: {
|
||||
@@ -238,8 +240,7 @@ describe('the plugin', function () {
|
||||
];
|
||||
let viewContainer = document.createElement('div');
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
const { vNode, destroy } = mount({
|
||||
components: {
|
||||
StylesView
|
||||
},
|
||||
@@ -248,17 +249,20 @@ describe('the plugin', function () {
|
||||
selection: selection,
|
||||
stylesManager
|
||||
},
|
||||
template: '<styles-view/>'
|
||||
template: '<styles-view ref="root"/>'
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
styleViewComponentObject = component.$root.$children[0];
|
||||
component = vNode.componentInstance;
|
||||
_destroy = destroy;
|
||||
|
||||
return nextTick().then(() => {
|
||||
styleViewComponentObject = component.$refs.root;
|
||||
styleViewComponentObject.setEditState(true);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
component.$destroy();
|
||||
_destroy();
|
||||
});
|
||||
|
||||
it('does not include the output label when the flag is disabled', () => {
|
||||
@@ -267,7 +271,7 @@ describe('the plugin', function () {
|
||||
styleViewComponentObject.initializeConditionalStyles();
|
||||
expect(styleViewComponentObject.conditionalStyles.length).toBe(2);
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
const hasNoOutput =
|
||||
styleViewComponentObject.domainObject.configuration.objectStyles.styles.every((style) => {
|
||||
return style.style.output === '' || style.style.output === undefined;
|
||||
@@ -286,7 +290,7 @@ describe('the plugin', function () {
|
||||
styleViewComponentObject.useConditionSetOutputAsLabel = true;
|
||||
styleViewComponentObject.persistLabelConfiguration();
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
const outputs = styleViewComponentObject.domainObject.configuration.objectStyles.styles.map(
|
||||
(style) => {
|
||||
return style.style.output;
|
||||
@@ -306,6 +310,7 @@ describe('the plugin', function () {
|
||||
let selection;
|
||||
let component;
|
||||
let styleViewComponentObject;
|
||||
let _destroy;
|
||||
const conditionSetDomainObject = {
|
||||
configuration: {
|
||||
conditionTestData: [
|
||||
@@ -560,8 +565,7 @@ describe('the plugin', function () {
|
||||
];
|
||||
let viewContainer = document.createElement('div');
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
const { vNode, destroy } = mount({
|
||||
components: {
|
||||
StylesView
|
||||
},
|
||||
@@ -570,15 +574,22 @@ describe('the plugin', function () {
|
||||
selection: selection,
|
||||
stylesManager
|
||||
},
|
||||
template: '<styles-view/>'
|
||||
template: '<styles-view ref="root"/>'
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
styleViewComponentObject = component.$root.$children[0];
|
||||
component = vNode.componentInstance;
|
||||
_destroy = destroy;
|
||||
|
||||
return nextTick().then(() => {
|
||||
styleViewComponentObject = component.$refs.root;
|
||||
styleViewComponentObject.setEditState(true);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
_destroy();
|
||||
});
|
||||
|
||||
it('initializes the items in the view', () => {
|
||||
expect(styleViewComponentObject.items.length).toBe(3);
|
||||
});
|
||||
@@ -597,7 +608,7 @@ describe('the plugin', function () {
|
||||
expect(styleViewComponentObject.conditionalStyles.length).toBe(2);
|
||||
styleViewComponentObject.updateConditionalStyle(conditionalStyle, 'border');
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(styleViewComponentObject.domainObject.configuration.objectStyles).toBeDefined();
|
||||
[boxLayoutItem, lineLayoutItem, notCreatableObjectItem].forEach((item) => {
|
||||
const itemStyles =
|
||||
@@ -627,7 +638,7 @@ describe('the plugin', function () {
|
||||
it('updates applicable static styles', () => {
|
||||
styleViewComponentObject.updateStaticStyle(staticStyle, 'border');
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
return nextTick().then(() => {
|
||||
expect(styleViewComponentObject.domainObject.configuration.objectStyles).toBeDefined();
|
||||
[boxLayoutItem, lineLayoutItem, notCreatableObjectItem].forEach((item) => {
|
||||
const itemStyle =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import ConditionWidgetPlugin from './plugin';
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('the plugin', function () {
|
||||
let view = conditionWidgetView.view(testViewObject, element);
|
||||
view.show(child, true);
|
||||
|
||||
return Vue.nextTick();
|
||||
return nextTick();
|
||||
});
|
||||
|
||||
it('provides a view', () => {
|
||||
@@ -184,7 +184,7 @@ describe('the plugin', function () {
|
||||
);
|
||||
conditionWidgetView.show(urlChild);
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
const domainUrl = mockConditionObject[CONDITION_WIDGET_KEY].url;
|
||||
expect(urlParent.innerHTML).toContain(
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@end-move="endMove"
|
||||
>
|
||||
<template #content>
|
||||
<div
|
||||
@@ -78,6 +78,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move'],
|
||||
computed: {
|
||||
style() {
|
||||
if (this.itemStyle) {
|
||||
@@ -127,7 +128,7 @@ export default {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,17 +57,17 @@
|
||||
:index="index"
|
||||
:multi-select="selectedLayoutItems.length > 1 || null"
|
||||
:is-editing="isEditing"
|
||||
@contextClick="updateViewContext"
|
||||
@context-click="updateViewContext"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@endLineResize="endLineResize"
|
||||
@formatChanged="updateTelemetryFormat"
|
||||
@end-move="endMove"
|
||||
@end-line-resize="endLineResize"
|
||||
@format-changed="updateTelemetryFormat"
|
||||
/>
|
||||
<edit-marquee
|
||||
v-if="showMarquee"
|
||||
:grid-size="gridSize"
|
||||
:selected-layout-items="selectedLayoutItems"
|
||||
@endResize="endResize"
|
||||
@end-resize="endResize"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -58,6 +58,7 @@ export default {
|
||||
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
|
||||
}
|
||||
},
|
||||
emits: ['end-resize'],
|
||||
data() {
|
||||
return {
|
||||
dragPosition: undefined
|
||||
@@ -182,7 +183,7 @@ export default {
|
||||
y: marqueeEnd.y - marqueeStart.y
|
||||
};
|
||||
|
||||
this.$emit('endResize', scaleWidth, scaleHeight, marqueeStart, marqueeOffset);
|
||||
this.$emit('end-resize', scaleWidth, scaleHeight, marqueeStart, marqueeOffset);
|
||||
this.dragPosition = undefined;
|
||||
this.initialPosition = undefined;
|
||||
this.marqueeStartPosition = undefined;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@end-move="endMove"
|
||||
>
|
||||
<template #content>
|
||||
<div
|
||||
@@ -78,6 +78,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move'],
|
||||
computed: {
|
||||
style() {
|
||||
if (this.itemStyle) {
|
||||
@@ -127,7 +128,7 @@ export default {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@end-move="endMove"
|
||||
>
|
||||
<template #content>
|
||||
<div class="c-image-view" :style="style"></div>
|
||||
@@ -74,6 +74,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move'],
|
||||
computed: {
|
||||
style() {
|
||||
let backgroundImage = 'url(' + this.item.url + ')';
|
||||
@@ -130,7 +131,7 @@ export default {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -56,6 +56,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move'],
|
||||
computed: {
|
||||
size() {
|
||||
let { width, height } = this.item;
|
||||
@@ -119,7 +120,7 @@ export default {
|
||||
document.body.removeEventListener('mousemove', this.continueMove);
|
||||
document.body.removeEventListener('mouseup', this.endMove);
|
||||
this.continueMove(event);
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
this.dragPosition = undefined;
|
||||
this.initialPosition = undefined;
|
||||
this.delta = undefined;
|
||||
|
||||
@@ -108,6 +108,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move', 'end-line-resize'],
|
||||
data() {
|
||||
return {
|
||||
dragPosition: undefined,
|
||||
@@ -318,9 +319,9 @@ export default {
|
||||
document.body.removeEventListener('mouseup', this.endDrag);
|
||||
let { x, y, x2, y2 } = this.dragPosition;
|
||||
if (!this.dragging) {
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
} else {
|
||||
this.$emit('endLineResize', this.item, {
|
||||
this.$emit('end-line-resize', this.item, {
|
||||
x,
|
||||
y,
|
||||
x2,
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@end-move="endMove"
|
||||
>
|
||||
<template #content>
|
||||
<ObjectFrame
|
||||
@@ -103,6 +103,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move'],
|
||||
data() {
|
||||
return {
|
||||
domainObject: undefined,
|
||||
@@ -174,7 +175,7 @@ export default {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@end-move="endMove"
|
||||
>
|
||||
<template #content>
|
||||
<div
|
||||
@@ -126,6 +126,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move', 'format-changed', 'context-click'],
|
||||
data() {
|
||||
return {
|
||||
currentObjectPath: undefined,
|
||||
@@ -240,6 +241,11 @@ export default {
|
||||
|
||||
this.status = this.openmct.status.get(this.item.identifier);
|
||||
this.removeStatusListener = this.openmct.status.observe(this.item.identifier, this.setStatus);
|
||||
|
||||
this.setupClockChangedEvent((domainObject) => {
|
||||
this.triggerUnsubscribeFromStaleness(domainObject);
|
||||
this.subscribeToStaleness(domainObject);
|
||||
});
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.removeStatusListener();
|
||||
@@ -339,10 +345,10 @@ export default {
|
||||
updateTelemetryFormat(format) {
|
||||
this.customStringformatter.setFormat(format);
|
||||
|
||||
this.$emit('formatChanged', this.item, format);
|
||||
this.$emit('format-changed', this.item, format);
|
||||
},
|
||||
updateViewContext() {
|
||||
this.$emit('contextClick', {
|
||||
this.$emit('context-click', {
|
||||
viewHistoricalData: true,
|
||||
formattedValueForCopy: this.formattedValueForCopy
|
||||
});
|
||||
@@ -395,7 +401,7 @@ export default {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
:grid-size="gridSize"
|
||||
:is-editing="isEditing"
|
||||
@move="move"
|
||||
@endMove="endMove"
|
||||
@end-move="endMove"
|
||||
>
|
||||
<template #content>
|
||||
<div
|
||||
@@ -86,6 +86,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['move', 'end-move'],
|
||||
computed: {
|
||||
style() {
|
||||
let size;
|
||||
@@ -139,7 +140,7 @@ export default {
|
||||
this.$emit('move', gridDelta);
|
||||
},
|
||||
endMove() {
|
||||
this.$emit('endMove');
|
||||
this.$emit('end-move');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import DisplayLayoutPlugin from './plugin';
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('the plugin', function () {
|
||||
const view = displayLayoutViewProvider.view(displayLayoutItem, displayLayoutItem);
|
||||
view.show(child, false);
|
||||
|
||||
Vue.nextTick(done);
|
||||
nextTick(done);
|
||||
});
|
||||
|
||||
it('will sync composition and layout items', () => {
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function FaultManagementInspectorViewProvider(openmct) {
|
||||
return {
|
||||
openmct: openmct,
|
||||
key: FAULT_MANAGEMENT_INSPECTOR,
|
||||
name: 'Fault Management Configuration',
|
||||
name: 'Config',
|
||||
canView: (selection) => {
|
||||
if (selection.length !== 1 || selection[0].length === 0) {
|
||||
return false;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
class="c-fault-mgmt-viewButton"
|
||||
title="Sort By"
|
||||
:model="model"
|
||||
@onChange="onChange"
|
||||
@on-change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,6 +74,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['sort-changed', 'select-all'],
|
||||
data() {
|
||||
return {
|
||||
model: {}
|
||||
@@ -93,10 +94,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onChange(data) {
|
||||
this.$emit('sortChanged', data);
|
||||
this.$emit('sort-changed', data);
|
||||
},
|
||||
selectAll(e) {
|
||||
this.$emit('selectAll', e.target.checked);
|
||||
this.$emit('select-all', e.target.checked);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -90,6 +90,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['acknowledge-selected', 'shelve-selected', 'toggle-selected'],
|
||||
computed: {
|
||||
classesFromState() {
|
||||
const exclusiveStates = [
|
||||
@@ -169,7 +170,7 @@ export default {
|
||||
name: 'Acknowledge',
|
||||
description: '',
|
||||
onItemClicked: (e) => {
|
||||
this.$emit('acknowledgeSelected', [this.fault]);
|
||||
this.$emit('acknowledge-selected', [this.fault]);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -177,7 +178,7 @@ export default {
|
||||
name: 'Shelve',
|
||||
description: '',
|
||||
onItemClicked: () => {
|
||||
this.$emit('shelveSelected', [this.fault], { shelved: true });
|
||||
this.$emit('shelve-selected', [this.fault], { shelved: true });
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -186,7 +187,7 @@ export default {
|
||||
name: 'Unshelve',
|
||||
description: '',
|
||||
onItemClicked: () => {
|
||||
this.$emit('shelveSelected', [this.fault], { shelved: false });
|
||||
this.$emit('shelve-selected', [this.fault], { shelved: false });
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -199,7 +200,7 @@ export default {
|
||||
selected: event.target.checked
|
||||
};
|
||||
|
||||
this.$emit('toggleSelected', faultData);
|
||||
this.$emit('toggle-selected', faultData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
<div class="c-faults-list-view">
|
||||
<FaultManagementSearch
|
||||
:search-term="searchTerm"
|
||||
@filterChanged="updateFilter"
|
||||
@updateSearchTerm="updateSearchTerm"
|
||||
@filter-changed="updateFilter"
|
||||
@update-search-term="updateSearchTerm"
|
||||
/>
|
||||
|
||||
<FaultManagementToolbar
|
||||
v-if="showToolbar"
|
||||
:selected-faults="selectedFaults"
|
||||
@acknowledgeSelected="toggleAcknowledgeSelected"
|
||||
@shelveSelected="toggleShelveSelected"
|
||||
@acknowledge-selected="toggleAcknowledgeSelected"
|
||||
@shelve-selected="toggleShelveSelected"
|
||||
/>
|
||||
|
||||
<div class="c-faults-list-view-header-item-container-wrapper">
|
||||
@@ -41,8 +41,8 @@
|
||||
class="header"
|
||||
:selected-faults="Object.values(selectedFaults)"
|
||||
:total-faults-count="filteredFaultsList.length"
|
||||
@selectAll="selectAll"
|
||||
@sortChanged="sortChanged"
|
||||
@select-all="selectAll"
|
||||
@sort-changed="sortChanged"
|
||||
/>
|
||||
|
||||
<div class="c-faults-list-view-item-body">
|
||||
@@ -52,9 +52,9 @@
|
||||
:key="fault.id"
|
||||
:fault="fault"
|
||||
:is-selected="isSelected(fault)"
|
||||
@toggleSelected="toggleSelected"
|
||||
@acknowledgeSelected="toggleAcknowledgeSelected"
|
||||
@shelveSelected="toggleShelveSelected"
|
||||
@toggle-selected="toggleSelected"
|
||||
@acknowledge-selected="toggleAcknowledgeSelected"
|
||||
@shelve-selected="toggleShelveSelected"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -33,14 +33,14 @@
|
||||
class="c-fault-mgmt-viewButton"
|
||||
title="View Filter"
|
||||
:model="model"
|
||||
@onChange="onChange"
|
||||
@on-change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectField from '@/api/forms/components/controls/SelectField.vue';
|
||||
import Search from '@/ui/components/Search.vue';
|
||||
import Search from '@/ui/components/SearchComponent.vue';
|
||||
|
||||
import { FILTER_ITEMS } from './constants';
|
||||
|
||||
@@ -56,6 +56,7 @@ export default {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
emits: ['filter-changed', 'update-search-term'],
|
||||
data() {
|
||||
return {
|
||||
items: []
|
||||
@@ -79,10 +80,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onChange(data) {
|
||||
this.$emit('filterChanged', data);
|
||||
this.$emit('filter-changed', data);
|
||||
},
|
||||
updateSearchTerm(searchTerm) {
|
||||
this.$emit('updateSearchTerm', searchTerm);
|
||||
this.$emit('update-search-term', searchTerm);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,6 +53,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['acknowledge-selected', 'shelve-selected'],
|
||||
data() {
|
||||
return {
|
||||
disableAcknowledge: true,
|
||||
@@ -82,10 +83,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
acknowledgeSelected() {
|
||||
this.$emit('acknowledgeSelected');
|
||||
this.$emit('acknowledge-selected');
|
||||
},
|
||||
shelveSelected() {
|
||||
this.$emit('shelveSelected');
|
||||
this.$emit('shelve-selected');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
import { createOpenMct, resetApplicationState } from '../../utils/testing';
|
||||
import {
|
||||
FAULT_MANAGEMENT_INSPECTOR,
|
||||
FAULT_MANAGEMENT_NAMESPACE,
|
||||
FAULT_MANAGEMENT_TYPE,
|
||||
FAULT_MANAGEMENT_VIEW
|
||||
@@ -86,7 +87,7 @@ describe('The Fault Management Plugin', () => {
|
||||
];
|
||||
const applicableInspectorViews = openmct.inspectorViews.get(faultDomainObjectSelection);
|
||||
const faultManagementInspectorView = applicableInspectorViews.filter(
|
||||
(view) => view.name === 'Fault Management Configuration'
|
||||
(view) => view.key === FAULT_MANAGEMENT_INSPECTOR
|
||||
);
|
||||
|
||||
expect(faultManagementInspectorView.length).toEqual(1);
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
type="text"
|
||||
:aria-label="label"
|
||||
:disabled="useGlobal"
|
||||
:value="persistedValue(filter)"
|
||||
@change="updateFilterValueFromString($event, filter)"
|
||||
:value="persistedValue(filter.comparator)"
|
||||
@change="updateFilterValueFromString($event, filter.comparator)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -125,6 +125,12 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
'filter-text-value-changed',
|
||||
'filter-selected',
|
||||
'clear-filters',
|
||||
'filter-single-selected'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
isEditing: this.openmct.editor.isEditing()
|
||||
@@ -151,16 +157,16 @@ export default {
|
||||
return this.persistedFilters && this.persistedFilters[comparator];
|
||||
},
|
||||
updateFilterValueFromString(event, comparator) {
|
||||
this.$emit('filterTextValueChanged', this.filterField.key, comparator, event.target.value);
|
||||
this.$emit('filter-text-value-changed', this.filterField.key, comparator, event.target.value);
|
||||
},
|
||||
updateFilterValueFromCheckbox(event, comparator, value) {
|
||||
this.$emit('filterSelected', this.filterField.key, comparator, value, event.target.checked);
|
||||
this.$emit('filter-selected', this.filterField.key, comparator, value, event.target.checked);
|
||||
},
|
||||
updateFilterValueFromDropdown(event, comparator, value) {
|
||||
if (value === 'NONE') {
|
||||
this.$emit('clearFilters', this.filterField.key);
|
||||
this.$emit('clear-filters', this.filterField.key);
|
||||
} else {
|
||||
this.$emit('filterSingleSelected', this.filterField.key, comparator, value);
|
||||
this.$emit('filter-single-selected', this.filterField.key, comparator, value);
|
||||
}
|
||||
},
|
||||
getFilterLabels(filter) {
|
||||
|
||||
@@ -64,10 +64,10 @@
|
||||
:use-global="persistedFilters.useGlobal"
|
||||
:persisted-filters="updatedFilters[metadatum.key]"
|
||||
label="Specific Filter"
|
||||
@filterSelected="updateMultipleFiltersWithSelectedValue"
|
||||
@filterTextValueChanged="updateFiltersWithTextValue"
|
||||
@filterSingleSelected="updateSingleSelection"
|
||||
@clearFilters="clearFilters"
|
||||
@filter-selected="updateMultipleFiltersWithSelectedValue"
|
||||
@filter-text-value-changed="updateFiltersWithTextValue"
|
||||
@filter-single-selected="updateSingleSelection"
|
||||
@clear-filters="clearFilters"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -98,6 +98,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['update-filters'],
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
@@ -161,11 +162,11 @@ export default {
|
||||
this.updatedFilters[key][comparator] = [valueName];
|
||||
}
|
||||
|
||||
this.$emit('updateFilters', this.keyString, this.updatedFilters);
|
||||
this.$emit('update-filters', this.keyString, this.updatedFilters);
|
||||
},
|
||||
clearFilters(key) {
|
||||
this.updatedFilters[key] = {};
|
||||
this.$emit('updateFilters', this.keyString, this.updatedFilters);
|
||||
this.$emit('update-filters', this.keyString, this.updatedFilters);
|
||||
},
|
||||
updateFiltersWithTextValue(key, comparator, value) {
|
||||
if (value.trim() === '') {
|
||||
@@ -174,15 +175,15 @@ export default {
|
||||
this.updatedFilters[key][comparator] = value;
|
||||
}
|
||||
|
||||
this.$emit('updateFilters', this.keyString, this.updatedFilters);
|
||||
this.$emit('update-filters', this.keyString, this.updatedFilters);
|
||||
},
|
||||
updateSingleSelection(key, comparator, value) {
|
||||
this.updatedFilters[key][comparator] = [value];
|
||||
this.$emit('updateFilters', this.keyString, this.updatedFilters);
|
||||
this.$emit('update-filters', this.keyString, this.updatedFilters);
|
||||
},
|
||||
useGlobalFilter(checked) {
|
||||
this.updatedFilters.useGlobal = checked;
|
||||
this.$emit('updateFilters', this.keyString, this.updatedFilters, checked);
|
||||
this.$emit('update-filters', this.keyString, this.updatedFilters, checked);
|
||||
},
|
||||
toggleIsEditing(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
|
||||
@@ -28,20 +28,21 @@
|
||||
<global-filters
|
||||
:global-filters="globalFilters"
|
||||
:global-metadata="globalMetadata"
|
||||
@persistGlobalFilters="persistGlobalFilters"
|
||||
@persist-global-filters="persistGlobalFilters"
|
||||
/>
|
||||
<filter-object
|
||||
v-for="(child, key) in children"
|
||||
:key="key"
|
||||
:filter-object="child"
|
||||
:persisted-filters="persistedFilters[key]"
|
||||
@updateFilters="persistFilters"
|
||||
@update-filters="persistFilters"
|
||||
/>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
import { toRaw } from 'vue';
|
||||
|
||||
import FilterObject from './FilterObject.vue';
|
||||
import GlobalFilters from './GlobalFilters.vue';
|
||||
@@ -155,11 +156,7 @@ export default {
|
||||
mutateFilters = true;
|
||||
}
|
||||
|
||||
this.$set(
|
||||
this.persistedFilters[keyString],
|
||||
metadatum.key,
|
||||
this.globalFilters[metadatum.key]
|
||||
);
|
||||
this.persistedFilters[keyString][metadatum.key] = this.globalFilters[metadatum.key];
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -271,14 +268,14 @@ export default {
|
||||
this.openmct.objects.mutate(
|
||||
this.providedObject,
|
||||
'configuration.filters',
|
||||
this.persistedFilters
|
||||
toRaw(this.persistedFilters)
|
||||
);
|
||||
},
|
||||
mutateConfigurationGlobalFilters() {
|
||||
this.openmct.objects.mutate(
|
||||
this.providedObject,
|
||||
'configuration.globalFilters',
|
||||
this.globalFilters
|
||||
toRaw(this.globalFilters)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
:filter-field="metadatum"
|
||||
:persisted-filters="updatedFilters[metadatum.key]"
|
||||
label="Global Filter"
|
||||
@filterSelected="updateFiltersWithSelectedValue"
|
||||
@filterTextValueChanged="updateFiltersWithTextValue"
|
||||
@filterSingleSelected="updateSingleSelection"
|
||||
@clearFilters="clearFilters"
|
||||
@filter-selected="updateFiltersWithSelectedValue"
|
||||
@filter-text-value-changed="updateFiltersWithTextValue"
|
||||
@filter-single-selected="updateSingleSelection"
|
||||
@clear-filters="clearFilters"
|
||||
/>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -73,6 +73,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['persist-global-filters'],
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
@@ -102,7 +103,7 @@ export default {
|
||||
},
|
||||
clearFilters(key) {
|
||||
this.updatedFilters[key] = {};
|
||||
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
||||
this.$emit('persist-global-filters', key, this.updatedFilters);
|
||||
},
|
||||
updateFiltersWithSelectedValue(key, comparator, valueName, value) {
|
||||
let filterValue = this.updatedFilters[key];
|
||||
@@ -121,11 +122,11 @@ export default {
|
||||
this.updatedFilters[key][comparator] = [valueName];
|
||||
}
|
||||
|
||||
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
||||
this.$emit('persist-global-filters', key, this.updatedFilters);
|
||||
},
|
||||
updateSingleSelection(key, comparator, value) {
|
||||
this.updatedFilters[key][comparator] = [value];
|
||||
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
||||
this.$emit('persist-global-filters', key, this.updatedFilters);
|
||||
},
|
||||
updateFiltersWithTextValue(key, comparator, value) {
|
||||
if (value.trim() === '') {
|
||||
@@ -134,7 +135,7 @@ export default {
|
||||
this.updatedFilters[key][comparator] = value;
|
||||
}
|
||||
|
||||
this.$emit('persistGlobalFilters', key, this.updatedFilters);
|
||||
this.$emit('persist-global-filters', key, this.updatedFilters);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
<script>
|
||||
import DropHint from './DropHint.vue';
|
||||
import FrameComponent from './Frame.vue';
|
||||
import FrameComponent from './FrameComponent.vue';
|
||||
import ResizeHandle from './ResizeHandle.vue';
|
||||
|
||||
const MIN_FRAME_SIZE = 5;
|
||||
@@ -111,6 +111,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['new-frame', 'move-frame', 'persist'],
|
||||
computed: {
|
||||
frames() {
|
||||
return this.container.frames;
|
||||
@@ -45,6 +45,7 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['object-drop-to'],
|
||||
data() {
|
||||
return {
|
||||
isMouseOver: false,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user