Compare commits
8 Commits
try-fix-tr
...
multi-user
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de5914b82d | ||
|
|
41bbbb136b | ||
|
|
0f199b6aff | ||
|
|
95e686038d | ||
|
|
f705bf9a61 | ||
|
|
50559ac502 | ||
|
|
f0ef93dd3f | ||
|
|
3ae14cf786 |
@@ -242,6 +242,10 @@ workflows:
|
||||
name: e2e-stable
|
||||
node-version: lts/hydrogen
|
||||
suite: stable
|
||||
- perf-test:
|
||||
node-version: lts/hydrogen
|
||||
- visual-test:
|
||||
node-version: lts/hydrogen
|
||||
|
||||
the-nightly: #These jobs do not run on PRs, but against master at night
|
||||
jobs:
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
"origin": "http://localhost:8080",
|
||||
"localStorage": [
|
||||
{
|
||||
"name": "mct",
|
||||
"value": "{\"mine\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1689710399654,\"created\":1689710398656,\"persisted\":1689710399654},\"58f55f3a-46d9-4c37-a726-27b5d38b895a\":{\"identifier\":{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"},\"name\":\"Overlay Plot:b0ba67ab-e383-40c1-a181-82b174e8fdf0\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"}],\"configuration\":{\"series\":[{\"identifier\":{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"}}]},\"notes\":\"framework/generateVisualTestData.e2e.spec.js\\nGenerate Visual Test Data @localStorage\\nchrome\",\"modified\":1689710400878,\"location\":\"mine\",\"created\":1689710399651,\"persisted\":1689710400878},\"19f2e461-190e-4662-8d62-251e90bb7aac\":{\"name\":\"Unnamed Sine Wave Generator\",\"type\":\"generator\",\"identifier\":{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"},\"telemetry\":{\"period\":10,\"amplitude\":1,\"offset\":0,\"dataRateInHz\":1,\"phase\":0,\"randomness\":0,\"loadDelay\":\"5000\",\"infinityValues\":false,\"staleness\":false},\"modified\":1689710400433,\"location\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"created\":1689710400433,\"persisted\":1689710400433}}"
|
||||
"name": "tcHistory",
|
||||
"value": "{\"utc\":[{\"start\":1658617611983,\"end\":1658619411983}]}"
|
||||
},
|
||||
{
|
||||
"name": "mct-recent-objects",
|
||||
"value": "[{\"objectPath\":[{\"identifier\":{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"},\"name\":\"Overlay Plot:b0ba67ab-e383-40c1-a181-82b174e8fdf0\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"}],\"configuration\":{\"series\":[]},\"notes\":\"framework/generateVisualTestData.e2e.spec.js\\nGenerate Visual Test Data @localStorage\\nchrome\",\"modified\":1689710400435,\"location\":\"mine\",\"created\":1689710399651,\"persisted\":1689710400436},{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1689710399654,\"created\":1689710398656,\"persisted\":1689710399654},{\"identifier\":{\"key\":\"ROOT\",\"namespace\":\"\"},\"name\":\"Open MCT\",\"type\":\"root\",\"composition\":[{\"key\":\"mine\",\"namespace\":\"\"}]}],\"navigationPath\":\"/browse/mine/58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"domainObject\":{\"identifier\":{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"},\"name\":\"Overlay Plot:b0ba67ab-e383-40c1-a181-82b174e8fdf0\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"}],\"configuration\":{\"series\":[]},\"notes\":\"framework/generateVisualTestData.e2e.spec.js\\nGenerate Visual Test Data @localStorage\\nchrome\",\"modified\":1689710400435,\"location\":\"mine\",\"created\":1689710399651,\"persisted\":1689710400436}},{\"objectPath\":[{\"identifier\":{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"},\"name\":\"Unnamed Sine Wave Generator\",\"type\":\"generator\",\"telemetry\":{\"period\":10,\"amplitude\":1,\"offset\":0,\"dataRateInHz\":1,\"phase\":0,\"randomness\":0,\"loadDelay\":\"5000\",\"infinityValues\":false,\"staleness\":false},\"modified\":1689710400433,\"location\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"created\":1689710400433,\"persisted\":1689710400433},{\"identifier\":{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"},\"name\":\"Overlay Plot:b0ba67ab-e383-40c1-a181-82b174e8fdf0\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"}],\"configuration\":{\"series\":[]},\"notes\":\"framework/generateVisualTestData.e2e.spec.js\\nGenerate Visual Test Data @localStorage\\nchrome\",\"modified\":1689710400435,\"location\":\"mine\",\"created\":1689710399651,\"persisted\":1689710400436},{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1689710399654,\"created\":1689710398656,\"persisted\":1689710399654},{\"identifier\":{\"key\":\"ROOT\",\"namespace\":\"\"},\"name\":\"Open MCT\",\"type\":\"root\",\"composition\":[{\"key\":\"mine\",\"namespace\":\"\"}]}],\"navigationPath\":\"/browse/mine/58f55f3a-46d9-4c37-a726-27b5d38b895a/19f2e461-190e-4662-8d62-251e90bb7aac\",\"domainObject\":{\"identifier\":{\"key\":\"19f2e461-190e-4662-8d62-251e90bb7aac\",\"namespace\":\"\"},\"name\":\"Unnamed Sine Wave Generator\",\"type\":\"generator\",\"telemetry\":{\"period\":10,\"amplitude\":1,\"offset\":0,\"dataRateInHz\":1,\"phase\":0,\"randomness\":0,\"loadDelay\":\"5000\",\"infinityValues\":false,\"staleness\":false},\"modified\":1689710400433,\"location\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"created\":1689710400433,\"persisted\":1689710400433}},{\"objectPath\":[{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1689710399654,\"created\":1689710398656,\"persisted\":1689710399654},{\"identifier\":{\"key\":\"ROOT\",\"namespace\":\"\"},\"name\":\"Open MCT\",\"type\":\"root\",\"composition\":[{\"key\":\"mine\",\"namespace\":\"\"}]}],\"navigationPath\":\"/browse/mine\",\"domainObject\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"58f55f3a-46d9-4c37-a726-27b5d38b895a\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"modified\":1689710399654,\"created\":1689710398656,\"persisted\":1689710399654}}]"
|
||||
"name": "mct",
|
||||
"value": "{\"mine\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"7fa5749b-8969-494c-9d85-c272516d333c\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"persisted\":1658619412848,\"modified\":1658619412848},\"7fa5749b-8969-494c-9d85-c272516d333c\":{\"identifier\":{\"key\":\"7fa5749b-8969-494c-9d85-c272516d333c\",\"namespace\":\"\"},\"name\":\"Unnamed Overlay Plot\",\"type\":\"telemetry.plot.overlay\",\"composition\":[{\"key\":\"67cbb9fc-af46-4148-b9e5-aea11179ae4b\",\"namespace\":\"\"}],\"configuration\":{\"series\":[{\"identifier\":{\"key\":\"67cbb9fc-af46-4148-b9e5-aea11179ae4b\",\"namespace\":\"\"}}]},\"modified\":1658619413566,\"location\":\"mine\",\"persisted\":1658619413567},\"67cbb9fc-af46-4148-b9e5-aea11179ae4b\":{\"name\":\"Unnamed Sine Wave Generator\",\"type\":\"generator\",\"identifier\":{\"key\":\"67cbb9fc-af46-4148-b9e5-aea11179ae4b\",\"namespace\":\"\"},\"telemetry\":{\"period\":10,\"amplitude\":1,\"offset\":0,\"dataRateInHz\":1,\"phase\":0,\"randomness\":0,\"loadDelay\":\"5000\"},\"modified\":1658619413552,\"location\":\"7fa5749b-8969-494c-9d85-c272516d333c\",\"persisted\":1658619413552}}"
|
||||
},
|
||||
{
|
||||
"name": "mct-tree-expanded",
|
||||
"value": "[]"
|
||||
"value": "[\"/browse/mine\"]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,19 +80,21 @@ test.describe('Example Imagery Object', () => {
|
||||
// flip on independent time conductor
|
||||
await page.getByRole('switch', { name: 'Enable Independent Time Conductor' }).click();
|
||||
await page.getByRole('button', { name: 'Independent Time Conductor Settings' }).click();
|
||||
await page.getByRole('textbox', { name: 'Start date' }).click();
|
||||
await page.getByRole('textbox', { name: 'Start date' }).fill('');
|
||||
await page.getByRole('textbox', { name: 'Start date' }).fill('2021-12-30');
|
||||
await page.getByRole('textbox', { name: 'Start time' }).click();
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByRole('textbox', { name: 'Start time' }).fill('');
|
||||
await page.getByRole('textbox', { name: 'Start time' }).fill('01:01:00');
|
||||
await page.getByRole('textbox', { name: 'End date' }).click();
|
||||
await page.getByRole('textbox', { name: 'Start time' }).type('01:01:00');
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByRole('textbox', { name: 'End date' }).fill('');
|
||||
await page.getByRole('textbox', { name: 'End date' }).fill('2021-12-30');
|
||||
await page.getByRole('textbox', { name: 'End time' }).click();
|
||||
await page.getByRole('textbox', { name: 'End date' }).type('2021-12-30');
|
||||
await page.keyboard.press('Tab');
|
||||
await page.getByRole('textbox', { name: 'End time' }).fill('');
|
||||
await page.getByRole('textbox', { name: 'End time' }).fill('01:11:00');
|
||||
await page.getByRole('button', { name: 'Submit time bounds' }).click();
|
||||
await page.getByRole('textbox', { name: 'End time' }).type('01:11:00');
|
||||
await page.keyboard.press('Tab');
|
||||
await page.keyboard.press('Enter');
|
||||
// expect(await page.getByRole('button', { name: 'Submit time bounds' }).isEnabled()).toBe(true);
|
||||
// await page.getByRole('button', { name: 'Submit time bounds' }).click();
|
||||
|
||||
// check image date
|
||||
await expect(page.getByText('2021-12-30 01:11:00.000Z').first()).toBeVisible();
|
||||
|
||||
@@ -52,7 +52,8 @@ test.describe('Visual - addInit', () => {
|
||||
path: path.join(__dirname, '../../helper', './addInitRestrictedNotebook.js')
|
||||
});
|
||||
//Go to baseURL
|
||||
await page.goto('./#/browse/mine?hideTree=true', { waitUntil: 'networkidle' });
|
||||
await page.goto('./#/browse/mine', { waitUntil: 'networkidle' });
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
|
||||
await createDomainObjectWithDefaults(page, { type: CUSTOM_NAME });
|
||||
|
||||
|
||||
@@ -41,7 +41,8 @@ test.describe('Visual - Controlled Clock @localStorage', () => {
|
||||
|
||||
test('Overlay Plot Loading Indicator @localStorage', async ({ page, theme }) => {
|
||||
// Go to baseURL
|
||||
await page.goto('./#/browse/mine?hideTree=true', { waitUntil: 'networkidle' });
|
||||
await page.goto('./#/browse/mine', { waitUntil: 'networkidle' });
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
|
||||
await page.locator('a:has-text("Unnamed Overlay Plot Overlay Plot")').click();
|
||||
//Ensure that we're on the Unnamed Overlay Plot object
|
||||
|
||||
@@ -39,7 +39,8 @@ const { createDomainObjectWithDefaults } = require('../../appActions');
|
||||
test.describe('Visual - Default', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Go to baseURL and Hide Tree
|
||||
await page.goto('./#/browse/mine?hideTree=true', { waitUntil: 'networkidle' });
|
||||
await page.goto('./#/browse/mine', { waitUntil: 'networkidle' });
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
});
|
||||
test.use({
|
||||
clockOptions: {
|
||||
@@ -99,6 +100,8 @@ test.describe('Visual - Default', () => {
|
||||
let endDate = 'xxxx-01-01 02:00:00.000Z';
|
||||
endDate = year + endDate.substring(4);
|
||||
|
||||
await page.getByRole('button', { name: 'Time Conductor Settings' }).click();
|
||||
|
||||
await page.locator('input[type="text"]').nth(1).fill(endDate.toString());
|
||||
await page.locator('input[type="text"]').first().fill(startDate.toString());
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ const percySnapshot = require('@percy/playwright');
|
||||
test.describe('Grand Search', () => {
|
||||
test.beforeEach(async ({ page, theme }) => {
|
||||
//Go to baseURL and Hide Tree
|
||||
await page.goto('./#/browse/mine?hideTree=true', { waitUntil: 'networkidle' });
|
||||
await page.goto('./#/browse/mine', { waitUntil: 'networkidle' });
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
});
|
||||
test.use({
|
||||
clockOptions: {
|
||||
|
||||
@@ -204,7 +204,8 @@ export default class TelemetryAPI {
|
||||
*/
|
||||
standardizeRequestOptions(options = {}) {
|
||||
if (!Object.hasOwn(options, 'start')) {
|
||||
if (options.timeContext?.getBounds()) {
|
||||
const bounds = options.timeContext?.getBounds();
|
||||
if (bounds?.start) {
|
||||
options.start = options.timeContext.getBounds().start;
|
||||
} else {
|
||||
options.start = this.openmct.time.getBounds().start;
|
||||
@@ -212,7 +213,8 @@ export default class TelemetryAPI {
|
||||
}
|
||||
|
||||
if (!Object.hasOwn(options, 'end')) {
|
||||
if (options.timeContext?.getBounds()) {
|
||||
const bounds = options.timeContext?.getBounds();
|
||||
if (bounds?.end) {
|
||||
options.end = options.timeContext.getBounds().end;
|
||||
} else {
|
||||
options.end = this.openmct.time.getBounds().end;
|
||||
|
||||
@@ -71,6 +71,7 @@ export default class TelemetryCollection extends EventEmitter {
|
||||
this.requestAbort = undefined;
|
||||
this.isStrategyLatest = this.options.strategy === 'latest';
|
||||
this.dataOutsideTimeBounds = false;
|
||||
this.modeChanged = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,6 +307,12 @@ export default class TelemetryCollection extends EventEmitter {
|
||||
* @private
|
||||
*/
|
||||
_bounds(bounds, isTick) {
|
||||
if (this.modeChanged) {
|
||||
this.modeChanged = false;
|
||||
this._reset();
|
||||
return;
|
||||
}
|
||||
|
||||
let startChanged = this.lastBounds.start !== bounds.start;
|
||||
let endChanged = this.lastBounds.end !== bounds.end;
|
||||
|
||||
@@ -439,7 +446,8 @@ export default class TelemetryCollection extends EventEmitter {
|
||||
}
|
||||
|
||||
_timeModeChanged() {
|
||||
this._reset();
|
||||
//We're need this so that when the bounds change comes in after this mode change, we can reset and request historic telemetry
|
||||
this.modeChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -101,7 +101,11 @@ export default {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
multiSelect: Boolean
|
||||
multiSelect: Boolean,
|
||||
isEditing: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -114,7 +118,7 @@ export default {
|
||||
showFrameEdit() {
|
||||
let layoutItem = this.selection.length > 0 && this.selection[0][0].context.layoutItem;
|
||||
|
||||
return !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
|
||||
return this.isEditing && !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
|
||||
},
|
||||
position() {
|
||||
let { x, y, x2, y2 } = this.item;
|
||||
|
||||
@@ -209,6 +209,7 @@ import ImageControls from './ImageControls.vue';
|
||||
import ImageThumbnail from './ImageThumbnail.vue';
|
||||
import imageryData from '../../imagery/mixins/imageryData';
|
||||
import AnnotationsCanvas from './AnnotationsCanvas.vue';
|
||||
import { TIME_CONTEXT_EVENTS } from '../../../api/time/constants';
|
||||
|
||||
const REFRESH_CSS_MS = 500;
|
||||
const DURATION_TRACK_MS = 1000;
|
||||
@@ -754,32 +755,28 @@ export default {
|
||||
this.stopFollowingTimeContext();
|
||||
this.timeContext = this.openmct.time.getContextForView(this.objectPath);
|
||||
//listen
|
||||
this.timeContext.on('timeSystem', this.timeContextChanged);
|
||||
this.timeContext.on('clock', this.timeContextChanged);
|
||||
this.timeContextChanged();
|
||||
this.timeContext.on('timeSystem', this.setModeAndTrackDuration);
|
||||
this.timeContext.on(TIME_CONTEXT_EVENTS.clockChanged, this.setModeAndTrackDuration);
|
||||
this.timeContext.on(TIME_CONTEXT_EVENTS.modeChanged, this.setModeAndTrackDuration);
|
||||
this.setModeAndTrackDuration();
|
||||
},
|
||||
stopFollowingTimeContext() {
|
||||
if (this.timeContext) {
|
||||
this.timeContext.off('timeSystem', this.timeContextChanged);
|
||||
this.timeContext.off('clock', this.timeContextChanged);
|
||||
this.timeContext.off('timeSystem', this.setModeAndTrackDuration);
|
||||
this.timeContext.off(TIME_CONTEXT_EVENTS.clockChanged, this.setModeAndTrackDuration);
|
||||
this.timeContext.off(TIME_CONTEXT_EVENTS.modeChanged, this.setModeAndTrackDuration);
|
||||
}
|
||||
},
|
||||
timeContextChanged() {
|
||||
setModeAndTrackDuration() {
|
||||
this.setIsFixed();
|
||||
this.setCanTrackDuration();
|
||||
this.trackDuration();
|
||||
},
|
||||
setIsFixed() {
|
||||
this.isFixed = this.timeContext ? this.timeContext.isFixed() : this.openmct.time.isFixed();
|
||||
this.isFixed = this.timeContext.isRealTime() === false;
|
||||
},
|
||||
setCanTrackDuration() {
|
||||
let isRealTime;
|
||||
if (this.timeContext) {
|
||||
isRealTime = this.timeContext.isRealTime();
|
||||
} else {
|
||||
isRealTime = this.openmct.time.isRealTime();
|
||||
}
|
||||
|
||||
let isRealTime = this.timeContext.isRealTime();
|
||||
this.canTrackDuration = isRealTime && this.timeSystem.isUTCBased;
|
||||
},
|
||||
updateSelection(selection) {
|
||||
@@ -809,13 +806,18 @@ export default {
|
||||
}
|
||||
},
|
||||
async initializeRelatedTelemetry() {
|
||||
this.relatedTelemetry = new RelatedTelemetry(this.openmct, this.domainObject, [
|
||||
...this.spacecraftPositionKeys,
|
||||
...this.spacecraftOrientationKeys,
|
||||
...this.cameraKeys,
|
||||
...this.sunKeys,
|
||||
...this.transformationsKeys
|
||||
]);
|
||||
this.relatedTelemetry = new RelatedTelemetry(
|
||||
this.openmct,
|
||||
this.domainObject,
|
||||
[
|
||||
...this.spacecraftPositionKeys,
|
||||
...this.spacecraftOrientationKeys,
|
||||
...this.cameraKeys,
|
||||
...this.sunKeys,
|
||||
...this.transformationsKeys
|
||||
],
|
||||
this.timeContext
|
||||
);
|
||||
|
||||
if (this.relatedTelemetry.hasRelatedTelemetry) {
|
||||
await this.relatedTelemetry.load();
|
||||
|
||||
@@ -30,9 +30,10 @@ function copyRelatedMetadata(metadata) {
|
||||
|
||||
import IndependentTimeContext from '@/api/time/IndependentTimeContext';
|
||||
export default class RelatedTelemetry {
|
||||
constructor(openmct, domainObject, telemetryKeys) {
|
||||
constructor(openmct, domainObject, telemetryKeys, timeContext) {
|
||||
this._openmct = openmct;
|
||||
this._domainObject = domainObject;
|
||||
this.timeContext = timeContext;
|
||||
|
||||
let metadata = this._openmct.telemetry.getMetadata(this._domainObject);
|
||||
let imageHints = metadata.valuesForHints(['image'])[0];
|
||||
@@ -43,7 +44,7 @@ export default class RelatedTelemetry {
|
||||
this.keys = telemetryKeys;
|
||||
|
||||
this._timeFormatter = undefined;
|
||||
this._timeSystemChange(this._openmct.time.timeSystem());
|
||||
this._timeSystemChange(this.timeContext.timeSystem());
|
||||
|
||||
// grab related telemetry metadata
|
||||
for (let key of this.keys) {
|
||||
@@ -57,7 +58,7 @@ export default class RelatedTelemetry {
|
||||
this._timeSystemChange = this._timeSystemChange.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
|
||||
this._openmct.time.on('timeSystem', this._timeSystemChange);
|
||||
this.timeContext.on('timeSystem', this._timeSystemChange);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +110,7 @@ export default class RelatedTelemetry {
|
||||
// and set bounds.
|
||||
ephemeralContext.resetContext();
|
||||
const newBounds = {
|
||||
start: this._openmct.time.bounds().start,
|
||||
start: this.timeContext.bounds().start,
|
||||
end: this._parseTime(datum)
|
||||
};
|
||||
ephemeralContext.bounds(newBounds);
|
||||
@@ -183,7 +184,7 @@ export default class RelatedTelemetry {
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._openmct.time.off('timeSystem', this._timeSystemChange);
|
||||
this.timeContext.off('timeSystem', this._timeSystemChange);
|
||||
for (let key of this.keys) {
|
||||
if (this[key] && this[key].unsubscribe) {
|
||||
this[key].unsubscribe();
|
||||
|
||||
@@ -42,7 +42,8 @@ import configStore from '../configuration/ConfigStore';
|
||||
import PlotConfigurationModel from '../configuration/PlotConfigurationModel';
|
||||
import LimitLine from './LimitLine.vue';
|
||||
import LimitLabel from './LimitLabel.vue';
|
||||
import Vue from 'vue';
|
||||
import mount from 'utils/mount';
|
||||
import { toRaw } from 'vue';
|
||||
|
||||
const MARKER_SIZE = 6.0;
|
||||
const HIGHLIGHT_SIZE = MARKER_SIZE * 2.0;
|
||||
@@ -315,7 +316,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const elements = this.seriesElements.get(series);
|
||||
const elements = this.seriesElements.get(toRaw(series));
|
||||
elements.lines.forEach(function (line) {
|
||||
this.lines.splice(this.lines.indexOf(line), 1);
|
||||
line.destroy();
|
||||
@@ -333,7 +334,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const elements = this.seriesElements.get(series);
|
||||
const elements = this.seriesElements.get(toRaw(series));
|
||||
if (elements.alarmSet) {
|
||||
elements.alarmSet.destroy();
|
||||
this.alarmSets.splice(this.alarmSets.indexOf(elements.alarmSet), 1);
|
||||
@@ -349,7 +350,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const elements = this.seriesElements.get(series);
|
||||
const elements = this.seriesElements.get(toRaw(series));
|
||||
elements.pointSets.forEach(function (pointSet) {
|
||||
this.pointSets.splice(this.pointSets.indexOf(pointSet), 1);
|
||||
pointSet.destroy();
|
||||
@@ -473,7 +474,7 @@ export default {
|
||||
this.$emit('plotReinitializeCanvas');
|
||||
},
|
||||
removeChartElement(series) {
|
||||
const elements = this.seriesElements.get(series);
|
||||
const elements = this.seriesElements.get(toRaw(series));
|
||||
|
||||
elements.lines.forEach(function (line) {
|
||||
this.lines.splice(this.lines.indexOf(line), 1);
|
||||
@@ -576,7 +577,7 @@ export default {
|
||||
this.seriesLimits.set(series, limitElements);
|
||||
},
|
||||
clearLimitLines(series) {
|
||||
const seriesLimits = this.seriesLimits.get(series);
|
||||
const seriesLimits = this.seriesLimits.get(toRaw(series));
|
||||
|
||||
if (seriesLimits) {
|
||||
seriesLimits.limitLines.forEach(function (line) {
|
||||
@@ -747,16 +748,14 @@ export default {
|
||||
left: 0,
|
||||
top: this.drawAPI.y(limit.point.y)
|
||||
};
|
||||
let LimitLineClass = Vue.extend(LimitLine);
|
||||
const component = new LimitLineClass({
|
||||
propsData: {
|
||||
const { vNode } = mount(LimitLine, {
|
||||
props: {
|
||||
point,
|
||||
limit
|
||||
}
|
||||
});
|
||||
component.$mount();
|
||||
|
||||
return component.$el;
|
||||
return vNode.el;
|
||||
},
|
||||
getLimitOverlap(limit, overlapMap) {
|
||||
//calculate if limit lines are too close to each other
|
||||
@@ -792,16 +791,14 @@ export default {
|
||||
left: 0,
|
||||
top: this.drawAPI.y(limit.point.y)
|
||||
};
|
||||
let LimitLabelClass = Vue.extend(LimitLabel);
|
||||
const component = new LimitLabelClass({
|
||||
propsData: {
|
||||
const { vNode } = mount(LimitLabel, {
|
||||
props: {
|
||||
limit: Object.assign({}, overlap, limit),
|
||||
point
|
||||
}
|
||||
});
|
||||
component.$mount();
|
||||
|
||||
return component.$el;
|
||||
return vNode.el;
|
||||
},
|
||||
drawAlarmPoints(alarmSet) {
|
||||
this.drawAPI.drawLimitPoints(
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
import Timer from './components/Timer.vue';
|
||||
import mount from 'utils/mount';
|
||||
import { markRaw, toRaw } from 'vue';
|
||||
|
||||
export default function TimerViewProvider(openmct) {
|
||||
return {
|
||||
@@ -32,11 +33,12 @@ export default function TimerViewProvider(openmct) {
|
||||
return domainObject.type === 'timer';
|
||||
},
|
||||
|
||||
view: function (domainObject, objectPath) {
|
||||
view(domainObject, objectPath) {
|
||||
let _destroy = null;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
show(element) {
|
||||
const rawDomainObject = markRaw(toRaw(domainObject));
|
||||
const { destroy } = mount(
|
||||
{
|
||||
el: element,
|
||||
@@ -45,11 +47,11 @@ export default function TimerViewProvider(openmct) {
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
domainObject: rawDomainObject,
|
||||
currentView: this
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject,
|
||||
objectPath
|
||||
};
|
||||
},
|
||||
@@ -62,7 +64,7 @@ export default function TimerViewProvider(openmct) {
|
||||
);
|
||||
_destroy = destroy;
|
||||
},
|
||||
destroy: function () {
|
||||
destroy() {
|
||||
if (_destroy) {
|
||||
_destroy();
|
||||
}
|
||||
|
||||
@@ -43,19 +43,17 @@
|
||||
|
||||
<script>
|
||||
import raf from 'utils/raf';
|
||||
import throttle from '../../../utils/throttle';
|
||||
|
||||
const moment = require('moment-timezone');
|
||||
const momentDurationFormatSetup = require('moment-duration-format');
|
||||
const refreshRateSeconds = 2;
|
||||
|
||||
momentDurationFormatSetup(moment);
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'currentView'],
|
||||
inject: ['openmct', 'currentView', 'domainObject'],
|
||||
props: {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
objectPath: {
|
||||
type: Array,
|
||||
required: true
|
||||
@@ -82,6 +80,10 @@ export default {
|
||||
return this.lastTimestamp - this.relativeTimestamp;
|
||||
},
|
||||
timeTextValue() {
|
||||
if(this.timerState !== 'started') {
|
||||
// THIS IS NOT RIGHT!!!
|
||||
return moment.duration(this.lastTimestamp - this.configuration.pausedTime, 'ms').format(this.format, { trim: false });
|
||||
}
|
||||
if (isNaN(this.timeDelta)) {
|
||||
return null;
|
||||
}
|
||||
@@ -178,12 +180,15 @@ export default {
|
||||
this.showOrHideAvailableActions();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.refreshTimerObject = throttle(this.refreshTimerObject, refreshRateSeconds * 1000);
|
||||
},
|
||||
mounted() {
|
||||
this.unobserve = this.openmct.objects.observe(
|
||||
this.domainObject,
|
||||
'configuration',
|
||||
(configuration) => {
|
||||
this.configuration = configuration;
|
||||
'*',
|
||||
(domainObject) => {
|
||||
this.configuration = domainObject.configuration;
|
||||
}
|
||||
);
|
||||
this.$nextTick(() => {
|
||||
@@ -219,6 +224,11 @@ export default {
|
||||
if (this.timerState === 'paused' && !this.lastTimestamp) {
|
||||
this.lastTimestamp = this.pausedTime;
|
||||
}
|
||||
|
||||
this.refreshTimerObject();
|
||||
},
|
||||
refreshTimerObject() {
|
||||
this.openmct.objects.refresh(this.domainObject);
|
||||
},
|
||||
restartTimer() {
|
||||
this.triggerAction('timer.restart');
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
:loading-items="treeItemLoading"
|
||||
:targeted-path="targetedPath"
|
||||
@tree-item-mounted="scrollToCheck($event)"
|
||||
@tree-item-destroyed="removeCompositionListenerFor($event)"
|
||||
@tree-item-action="treeItemAction(treeItem, $event)"
|
||||
@tree-item-selection="treeItemSelection(treeItem)"
|
||||
@targeted-path-animation-end="targetedPathAnimationEnd()"
|
||||
|
||||
@@ -191,7 +191,6 @@ export default {
|
||||
},
|
||||
unmounted() {
|
||||
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
||||
this.$emit('tree-item-destroyed', this.navigationPath);
|
||||
},
|
||||
methods: {
|
||||
targetedPathAnimationEnd($event) {
|
||||
|
||||
34
src/utils/throttle.js
Normal file
34
src/utils/throttle.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Creates a throttled function that only invokes the provided function at most once every
|
||||
* specified number of milliseconds. Subsequent calls within the waiting period will be ignored.
|
||||
* @param {Function} func The function to throttle.
|
||||
* @param {number} wait The number of milliseconds to wait between successive calls to the function.
|
||||
* @return {Function} Returns the new throttled function.
|
||||
*/
|
||||
export default function throttle(func, wait) {
|
||||
let timeout;
|
||||
let result;
|
||||
let previous = 0;
|
||||
|
||||
return function (...args) {
|
||||
const now = new Date().getTime();
|
||||
const remaining = wait - (now - previous);
|
||||
|
||||
if (remaining <= 0 || remaining > wait) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
|
||||
previous = now;
|
||||
result = func(...args);
|
||||
} else if (!timeout) {
|
||||
timeout = setTimeout(() => {
|
||||
previous = new Date().getTime();
|
||||
timeout = null;
|
||||
result = func(...args);
|
||||
}, remaining);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user