mirror of
https://github.com/nasa/openmct.git
synced 2025-06-15 21:58:13 +00:00
[Staleness] API and Component Functionality (#6108)
* initial telemetry api updates for staleness support * modifying staleness to a subsription style * fixing variable name * debuggin * put the subscribe in the wrong place * stale class for object views * temp cyan border for testing * added staleness to swg, working on stacked plot staleness * WIP: stacked plot staleness * reverting, going a different route * staleness on stacked plots * plot legend staleness * remove debug code * staleness for alphanumerics * lad table and table set staleness * overlay plot staleness * remove debug code * hardened lad staleness functionality fixed plots without composition bug * adding staleness to gauges * renaming telemetry age check functionality so it does not conflict with new staleness functionality * couple one-off fixes here and there, and WIP for condition sets, moving to telemetry tables to facilitate styling of completed components * small fix on lad tables, added staleness functionality to tables * finishing up condition sets * some cleaning up * adding border to condition sets when an item is stale * fixing dub sub * addressing PR comment, moving repeated code to a function * robustified the SWG stalenes provider, little fixes here and there as far as cleaning up listeners and... whatnot * removing debug code * typo fixes * cleanin up debug code * created a simple stalenes mixin for more basic usage in components * more robustification, if a new staleness subscription happens, will now send the current staleness value if we have it, beefed up example stalenes swg provider * beefed up staleness mixin a bit to give it more use * copyright * cleanin up ladtable code * cleanin up ladtable code * cleaning up lad table sets * some minor updates * Closes #6109 - New staleness glyph and font CSS added. * Closes #6109 - Normalized staleness colors as theme constants. - New mixins for staleness application to view elements. - Applied staleness styling to all relevant view elements. - TODO: smoke-test in Show theme. * adding staleness utils helper, mixin and isStale functionalirty for telemtry api * Closes #6109 - Refined style for Snow theme. * need to have one domainObject per stalenes utility * making sure we handle domains correctly while dealing with staleness * couple fixes * moving abort controller logic to a spot where it makes more sense * added some more info for the StalenesProvider interface docs * returning undefinded for ifStale requests with no provider * debuggin * debuggin * missed "isStale" call in condtioncollections * removing debug code and using mixin unsubscribe in gauge * fixing tests * more targeted tree item click Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com> Co-authored-by: Andrew Henry <akhenry@gmail.com> Co-authored-by: Scott Bell <scott@traclabs.com>
This commit is contained in:
@ -197,11 +197,16 @@ test.describe('Tagging in Notebooks @addInit', () => {
|
|||||||
page.goto('./#/browse/mine?hideTree=false'),
|
page.goto('./#/browse/mine?hideTree=false'),
|
||||||
page.click('.c-disclosure-triangle')
|
page.click('.c-disclosure-triangle')
|
||||||
]);
|
]);
|
||||||
// Click Clock
|
|
||||||
await page.click(`text=${clock.name}`);
|
|
||||||
|
|
||||||
|
const treePane = page.locator('#tree-pane');
|
||||||
|
// Click Clock
|
||||||
|
await treePane.getByRole('treeitem', {
|
||||||
|
name: clock.name
|
||||||
|
}).click();
|
||||||
// Click Notebook
|
// Click Notebook
|
||||||
await page.click(`text=${notebook.name}`);
|
await page.getByRole('treeitem', {
|
||||||
|
name: notebook.name
|
||||||
|
}).click();
|
||||||
|
|
||||||
for (let iteration = 0; iteration < ITERATIONS; iteration++) {
|
for (let iteration = 0; iteration < ITERATIONS; iteration++) {
|
||||||
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
|
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
|
||||||
|
@ -32,7 +32,7 @@ test.use({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('ExportAsJSON', () => {
|
test.fixme('ExportAsJSON', () => {
|
||||||
test('User can set autoscale with a valid range @snapshot', async ({ page, openmctConfig }) => {
|
test('User can set autoscale with a valid range @snapshot', async ({ page, openmctConfig }) => {
|
||||||
const { myItemsFolderName } = openmctConfig;
|
const { myItemsFolderName } = openmctConfig;
|
||||||
|
|
||||||
|
@ -37,8 +37,9 @@ define([
|
|||||||
infinityValues: false
|
infinityValues: false
|
||||||
};
|
};
|
||||||
|
|
||||||
function GeneratorProvider(openmct) {
|
function GeneratorProvider(openmct, StalenessProvider) {
|
||||||
this.workerInterface = new WorkerInterface(openmct);
|
this.openmct = openmct;
|
||||||
|
this.workerInterface = new WorkerInterface(openmct, StalenessProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
GeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
||||||
@ -81,6 +82,7 @@ define([
|
|||||||
workerRequest[prop] = Number(workerRequest[prop]);
|
workerRequest[prop] = Number(workerRequest[prop]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
workerRequest.id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
workerRequest.name = domainObject.name;
|
workerRequest.name = domainObject.name;
|
||||||
|
|
||||||
return workerRequest;
|
return workerRequest;
|
||||||
|
151
example/generator/SinewaveStalenessProvider.js
Normal file
151
example/generator/SinewaveStalenessProvider.js
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import EventEmitter from 'EventEmitter';
|
||||||
|
|
||||||
|
export default class SinewaveLimitProvider extends EventEmitter {
|
||||||
|
|
||||||
|
constructor(openmct) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.openmct = openmct;
|
||||||
|
this.observingStaleness = {};
|
||||||
|
this.watchingTheClock = false;
|
||||||
|
this.isRealTime = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
supportsStaleness(domainObject) {
|
||||||
|
return domainObject.type === 'generator';
|
||||||
|
}
|
||||||
|
|
||||||
|
isStale(domainObject, options) {
|
||||||
|
if (!this.providingStaleness(domainObject)) {
|
||||||
|
return Promise.resolve({
|
||||||
|
isStale: false,
|
||||||
|
utc: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = this.getObjectKeyString(domainObject);
|
||||||
|
|
||||||
|
if (!this.observerExists(id)) {
|
||||||
|
this.createObserver(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(this.observingStaleness[id].isStale);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeToStaleness(domainObject, callback) {
|
||||||
|
const id = this.getObjectKeyString(domainObject);
|
||||||
|
|
||||||
|
if (this.isRealTime === undefined) {
|
||||||
|
this.updateRealTime(this.openmct.time.clock());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handleClockUpdate();
|
||||||
|
|
||||||
|
if (this.observerExists(id)) {
|
||||||
|
this.addCallbackToObserver(id, callback);
|
||||||
|
} else {
|
||||||
|
this.createObserver(id, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
const intervalId = setInterval(() => {
|
||||||
|
if (this.providingStaleness(domainObject)) {
|
||||||
|
this.updateStaleness(id, !this.observingStaleness[id].isStale);
|
||||||
|
}
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(intervalId);
|
||||||
|
this.updateStaleness(id, false);
|
||||||
|
this.handleClockUpdate();
|
||||||
|
this.destroyObserver(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClockUpdate() {
|
||||||
|
let observers = Object.values(this.observingStaleness).length > 0;
|
||||||
|
|
||||||
|
if (observers && !this.watchingTheClock) {
|
||||||
|
this.watchingTheClock = true;
|
||||||
|
this.openmct.time.on('clock', this.updateRealTime, this);
|
||||||
|
} else if (!observers && this.watchingTheClock) {
|
||||||
|
this.watchingTheClock = false;
|
||||||
|
this.openmct.time.off('clock', this.updateRealTime, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRealTime(clock) {
|
||||||
|
this.isRealTime = clock !== undefined;
|
||||||
|
|
||||||
|
if (!this.isRealTime) {
|
||||||
|
Object.keys(this.observingStaleness).forEach((id) => {
|
||||||
|
this.updateStaleness(id, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStaleness(id, isStale) {
|
||||||
|
this.observingStaleness[id].isStale = isStale;
|
||||||
|
this.observingStaleness[id].utc = Date.now();
|
||||||
|
this.observingStaleness[id].callback({
|
||||||
|
isStale: this.observingStaleness[id].isStale,
|
||||||
|
utc: this.observingStaleness[id].utc
|
||||||
|
});
|
||||||
|
this.emit('stalenessEvent', {
|
||||||
|
id,
|
||||||
|
isStale: this.observingStaleness[id].isStale
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createObserver(id, callback) {
|
||||||
|
this.observingStaleness[id] = {
|
||||||
|
isStale: false,
|
||||||
|
utc: Date.now()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
this.addCallbackToObserver(id, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyObserver(id) {
|
||||||
|
delete this.observingStaleness[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
providingStaleness(domainObject) {
|
||||||
|
return domainObject.telemetry?.staleness === true && this.isRealTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
getObjectKeyString(object) {
|
||||||
|
return this.openmct.objects.makeKeyString(object.identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCallbackToObserver(id, callback) {
|
||||||
|
this.observingStaleness[id].callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
observerExists(id) {
|
||||||
|
return this.observingStaleness?.[id];
|
||||||
|
}
|
||||||
|
}
|
@ -25,14 +25,24 @@ define([
|
|||||||
], function (
|
], function (
|
||||||
{ v4: uuid }
|
{ v4: uuid }
|
||||||
) {
|
) {
|
||||||
function WorkerInterface(openmct) {
|
function WorkerInterface(openmct, StalenessProvider) {
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
const workerUrl = `${openmct.getAssetPath()}${__OPENMCT_ROOT_RELATIVE__}generatorWorker.js`;
|
const workerUrl = `${openmct.getAssetPath()}${__OPENMCT_ROOT_RELATIVE__}generatorWorker.js`;
|
||||||
|
this.StalenessProvider = StalenessProvider;
|
||||||
this.worker = new Worker(workerUrl);
|
this.worker = new Worker(workerUrl);
|
||||||
this.worker.onmessage = this.onMessage.bind(this);
|
this.worker.onmessage = this.onMessage.bind(this);
|
||||||
this.callbacks = {};
|
this.callbacks = {};
|
||||||
|
this.staleTelemetryIds = {};
|
||||||
|
|
||||||
|
this.watchStaleness();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorkerInterface.prototype.watchStaleness = function () {
|
||||||
|
this.StalenessProvider.on('stalenessEvent', ({ id, isStale}) => {
|
||||||
|
this.staleTelemetryIds[id] = isStale;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
WorkerInterface.prototype.onMessage = function (message) {
|
WorkerInterface.prototype.onMessage = function (message) {
|
||||||
message = message.data;
|
message = message.data;
|
||||||
var callback = this.callbacks[message.id];
|
var callback = this.callbacks[message.id];
|
||||||
@ -83,11 +93,12 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
WorkerInterface.prototype.subscribe = function (request, cb) {
|
WorkerInterface.prototype.subscribe = function (request, cb) {
|
||||||
function callback(message) {
|
const id = request.id;
|
||||||
|
const messageId = this.dispatch('subscribe', request, (message) => {
|
||||||
|
if (!this.staleTelemetryIds[id]) {
|
||||||
cb(message.data);
|
cb(message.data);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
var messageId = this.dispatch('subscribe', request, callback);
|
|
||||||
|
|
||||||
return function () {
|
return function () {
|
||||||
this.dispatch('unsubscribe', {
|
this.dispatch('unsubscribe', {
|
||||||
|
@ -20,19 +20,13 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
import GeneratorProvider from "./GeneratorProvider";
|
||||||
"./GeneratorProvider",
|
import SinewaveLimitProvider from "./SinewaveLimitProvider";
|
||||||
"./SinewaveLimitProvider",
|
import SinewaveStalenessProvider from "./SinewaveStalenessProvider";
|
||||||
"./StateGeneratorProvider",
|
import StateGeneratorProvider from "./StateGeneratorProvider";
|
||||||
"./GeneratorMetadataProvider"
|
import GeneratorMetadataProvider from "./GeneratorMetadataProvider";
|
||||||
], function (
|
|
||||||
GeneratorProvider,
|
|
||||||
SinewaveLimitProvider,
|
|
||||||
StateGeneratorProvider,
|
|
||||||
GeneratorMetadataProvider
|
|
||||||
) {
|
|
||||||
|
|
||||||
return function (openmct) {
|
export default function (openmct) {
|
||||||
|
|
||||||
openmct.types.addType("example.state-generator", {
|
openmct.types.addType("example.state-generator", {
|
||||||
name: "State Generator",
|
name: "State Generator",
|
||||||
@ -153,6 +147,16 @@ define([
|
|||||||
"telemetry",
|
"telemetry",
|
||||||
"infinityValues"
|
"infinityValues"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Provide Staleness Updates",
|
||||||
|
control: "toggleSwitch",
|
||||||
|
cssClass: "l-input",
|
||||||
|
key: "staleness",
|
||||||
|
property: [
|
||||||
|
"telemetry",
|
||||||
|
"staleness"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
initialize: function (object) {
|
initialize: function (object) {
|
||||||
@ -164,14 +168,15 @@ define([
|
|||||||
phase: 0,
|
phase: 0,
|
||||||
randomness: 0,
|
randomness: 0,
|
||||||
loadDelay: 0,
|
loadDelay: 0,
|
||||||
infinityValues: false
|
infinityValues: false,
|
||||||
|
staleness: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const stalenessProvider = new SinewaveStalenessProvider(openmct);
|
||||||
|
|
||||||
openmct.telemetry.addProvider(new GeneratorProvider(openmct));
|
openmct.telemetry.addProvider(new GeneratorProvider(openmct, stalenessProvider));
|
||||||
openmct.telemetry.addProvider(new GeneratorMetadataProvider());
|
openmct.telemetry.addProvider(new GeneratorMetadataProvider());
|
||||||
openmct.telemetry.addProvider(new SinewaveLimitProvider());
|
openmct.telemetry.addProvider(new SinewaveLimitProvider());
|
||||||
};
|
openmct.telemetry.addProvider(stalenessProvider);
|
||||||
|
}
|
||||||
});
|
|
||||||
|
@ -36,6 +36,7 @@ export default class TelemetryAPI {
|
|||||||
this.formatMapCache = new WeakMap();
|
this.formatMapCache = new WeakMap();
|
||||||
this.formatters = new Map();
|
this.formatters = new Map();
|
||||||
this.limitProviders = [];
|
this.limitProviders = [];
|
||||||
|
this.stalenessProviders = [];
|
||||||
this.metadataCache = new WeakMap();
|
this.metadataCache = new WeakMap();
|
||||||
this.metadataProviders = [new DefaultMetadataProvider(this.openmct)];
|
this.metadataProviders = [new DefaultMetadataProvider(this.openmct)];
|
||||||
this.noRequestProviderForAllObjects = false;
|
this.noRequestProviderForAllObjects = false;
|
||||||
@ -114,6 +115,10 @@ export default class TelemetryAPI {
|
|||||||
if (provider.supportsLimits) {
|
if (provider.supportsLimits) {
|
||||||
this.limitProviders.unshift(provider);
|
this.limitProviders.unshift(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (provider.supportsStaleness) {
|
||||||
|
this.stalenessProviders.unshift(provider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,7 +130,7 @@ export default class TelemetryAPI {
|
|||||||
return provider.supportsSubscribe.apply(provider, args);
|
return provider.supportsSubscribe.apply(provider, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.subscriptionProviders.filter(supportsDomainObject)[0];
|
return this.subscriptionProviders.find(supportsDomainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,25 +143,25 @@ export default class TelemetryAPI {
|
|||||||
return provider.supportsRequest.apply(provider, args);
|
return provider.supportsRequest.apply(provider, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.requestProviders.filter(supportsDomainObject)[0];
|
return this.requestProviders.find(supportsDomainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
#findMetadataProvider(domainObject) {
|
#findMetadataProvider(domainObject) {
|
||||||
return this.metadataProviders.filter(function (p) {
|
return this.metadataProviders.find((provider) => {
|
||||||
return p.supportsMetadata(domainObject);
|
return provider.supportsMetadata(domainObject);
|
||||||
})[0];
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
#findLimitEvaluator(domainObject) {
|
#findLimitEvaluator(domainObject) {
|
||||||
return this.limitProviders.filter(function (p) {
|
return this.limitProviders.find((provider) => {
|
||||||
return p.supportsLimits(domainObject);
|
return provider.supportsLimits(domainObject);
|
||||||
})[0];
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -351,6 +356,101 @@ export default class TelemetryAPI {
|
|||||||
}.bind(this);
|
}.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to staleness updates for a specific domain object.
|
||||||
|
* The callback will be called whenever staleness changes.
|
||||||
|
*
|
||||||
|
* @method subscribeToStaleness
|
||||||
|
* @memberof module:openmct.TelemetryAPI~StalenessProvider#
|
||||||
|
* @param {module:openmct.DomainObject} domainObject the object
|
||||||
|
* to watch for staleness updates
|
||||||
|
* @param {Function} callback the callback to invoke with staleness data,
|
||||||
|
* as it is received: ex.
|
||||||
|
* {
|
||||||
|
* isStale: <Boolean>,
|
||||||
|
* timestamp: <timestamp>
|
||||||
|
* }
|
||||||
|
* @returns {Function} a function which may be called to terminate
|
||||||
|
* the subscription to staleness updates
|
||||||
|
*/
|
||||||
|
subscribeToStaleness(domainObject, callback) {
|
||||||
|
const provider = this.#findStalenessProvider(domainObject);
|
||||||
|
|
||||||
|
if (!this.stalenessSubscriberCache) {
|
||||||
|
this.stalenessSubscriberCache = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyString = objectUtils.makeKeyString(domainObject.identifier);
|
||||||
|
let stalenessSubscriber = this.stalenessSubscriberCache[keyString];
|
||||||
|
|
||||||
|
if (!stalenessSubscriber) {
|
||||||
|
stalenessSubscriber = this.stalenessSubscriberCache[keyString] = {
|
||||||
|
callbacks: [callback]
|
||||||
|
};
|
||||||
|
if (provider) {
|
||||||
|
stalenessSubscriber.unsubscribe = provider
|
||||||
|
.subscribeToStaleness(domainObject, (stalenessResponse) => {
|
||||||
|
stalenessSubscriber.callbacks.forEach((cb) => {
|
||||||
|
cb(stalenessResponse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
stalenessSubscriber.unsubscribe = () => {};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stalenessSubscriber.callbacks.push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function unsubscribe() {
|
||||||
|
stalenessSubscriber.callbacks = stalenessSubscriber.callbacks.filter((cb) => {
|
||||||
|
return cb !== callback;
|
||||||
|
});
|
||||||
|
if (stalenessSubscriber.callbacks.length === 0) {
|
||||||
|
stalenessSubscriber.unsubscribe();
|
||||||
|
delete this.stalenessSubscriberCache[keyString];
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request telemetry staleness for a domain object.
|
||||||
|
*
|
||||||
|
* @method isStale
|
||||||
|
* @memberof module:openmct.TelemetryAPI~StalenessProvider#
|
||||||
|
* @param {module:openmct.DomainObject} domainObject the object
|
||||||
|
* which has associated telemetry staleness
|
||||||
|
* @returns {Promise.<StalenessResponseObject>} a promise for a StalenessResponseObject
|
||||||
|
* or undefined if no provider exists
|
||||||
|
*/
|
||||||
|
async isStale(domainObject) {
|
||||||
|
const provider = this.#findStalenessProvider(domainObject);
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const options = { signal: abortController.signal };
|
||||||
|
this.requestAbortControllers.add(abortController);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const staleness = await provider.isStale(domainObject, options);
|
||||||
|
|
||||||
|
return staleness;
|
||||||
|
} finally {
|
||||||
|
this.requestAbortControllers.delete(abortController);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#findStalenessProvider(domainObject) {
|
||||||
|
return this.stalenessProviders.find((provider) => {
|
||||||
|
return provider.supportsStaleness(domainObject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get telemetry metadata for a given domain object. Returns a telemetry
|
* Get telemetry metadata for a given domain object. Returns a telemetry
|
||||||
* metadata manager which provides methods for interrogating telemetry
|
* metadata manager which provides methods for interrogating telemetry
|
||||||
@ -661,6 +761,29 @@ export default class TelemetryAPI {
|
|||||||
* @memberof module:openmct.TelemetryAPI~
|
* @memberof module:openmct.TelemetryAPI~
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides telemetry staleness data. To subscribe to telemetry stalenes,
|
||||||
|
* new StalenessProvider implementations should be
|
||||||
|
* [registered]{@link module:openmct.TelemetryAPI#addProvider}.
|
||||||
|
*
|
||||||
|
* @interface StalenessProvider
|
||||||
|
* @property {function} supportsStaleness receieves a domainObject and
|
||||||
|
* returns a boolean to indicate it will provide staleness
|
||||||
|
* @property {function} subscribeToStaleness receieves a domainObject to
|
||||||
|
* be subscribed to and a callback to invoke with a StalenessResponseObject
|
||||||
|
* @property {function} isStale an asynchronous method called with a domainObject
|
||||||
|
* and an options object which currently has an abort signal, ex.
|
||||||
|
* { signal: <AbortController.signal> }
|
||||||
|
* this method should return a current StalenessResponseObject
|
||||||
|
* @memberof module:openmct.TelemetryAPI~
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} StalenessResponseObject
|
||||||
|
* @property {Boolean} isStale boolean representing the staleness state
|
||||||
|
* @property {Number} timestamp Unix timestamp in milliseconds
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for retrieving telemetry data associated with a domain
|
* An interface for retrieving telemetry data associated with a domain
|
||||||
* object.
|
* object.
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<td class="js-second-data">{{ formattedTimestamp }}</td>
|
<td class="js-second-data">{{ formattedTimestamp }}</td>
|
||||||
<td
|
<td
|
||||||
class="js-third-data"
|
class="js-third-data"
|
||||||
:class="valueClass"
|
:class="valueClasses"
|
||||||
>{{ value }}</td>
|
>{{ value }}</td>
|
||||||
<td
|
<td
|
||||||
v-if="hasUnits"
|
v-if="hasUnits"
|
||||||
@ -63,6 +63,12 @@ export default {
|
|||||||
hasUnits: {
|
hasUnits: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
requred: true
|
requred: true
|
||||||
|
},
|
||||||
|
isStale: {
|
||||||
|
type: Boolean,
|
||||||
|
default() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -81,14 +87,22 @@ export default {
|
|||||||
|
|
||||||
return this.formats[this.valueKey].format(this.datum);
|
return this.formats[this.valueKey].format(this.datum);
|
||||||
},
|
},
|
||||||
valueClass() {
|
valueClasses() {
|
||||||
if (!this.datum) {
|
let classes = [];
|
||||||
return '';
|
|
||||||
|
if (this.isStale) {
|
||||||
|
classes.push('is-stale');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.datum) {
|
||||||
const limit = this.limitEvaluator.evaluate(this.datum, this.valueMetadata);
|
const limit = this.limitEvaluator.evaluate(this.datum, this.valueMetadata);
|
||||||
|
|
||||||
return limit ? limit.cssClass : '';
|
if (limit) {
|
||||||
|
classes.push(limit.cssClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
|
||||||
},
|
},
|
||||||
formattedTimestamp() {
|
formattedTimestamp() {
|
||||||
|
@ -21,7 +21,10 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="c-lad-table-wrapper u-style-receiver js-style-receiver">
|
<div
|
||||||
|
class="c-lad-table-wrapper u-style-receiver js-style-receiver"
|
||||||
|
:class="staleClass"
|
||||||
|
>
|
||||||
<table class="c-table c-lad-table">
|
<table class="c-table c-lad-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -38,6 +41,7 @@
|
|||||||
:domain-object="ladRow.domainObject"
|
:domain-object="ladRow.domainObject"
|
||||||
:path-to-table="objectPath"
|
:path-to-table="objectPath"
|
||||||
:has-units="hasUnits"
|
:has-units="hasUnits"
|
||||||
|
:is-stale="staleObjects.includes(ladRow.key)"
|
||||||
@rowContextClick="updateViewContext"
|
@rowContextClick="updateViewContext"
|
||||||
/>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -46,7 +50,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import LadRow from './LADRow.vue';
|
import LadRow from './LADRow.vue';
|
||||||
|
import StalenessUtils from '@/utils/staleness';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -66,7 +72,8 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
items: [],
|
items: [],
|
||||||
viewContext: {}
|
viewContext: {},
|
||||||
|
staleObjects: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -80,6 +87,13 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return itemsWithUnits.length !== 0;
|
return itemsWithUnits.length !== 0;
|
||||||
|
},
|
||||||
|
staleClass() {
|
||||||
|
if (this.staleObjects.length !== 0) {
|
||||||
|
return 'is-stale';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -88,11 +102,17 @@ export default {
|
|||||||
this.composition.on('remove', this.removeItem);
|
this.composition.on('remove', this.removeItem);
|
||||||
this.composition.on('reorder', this.reorder);
|
this.composition.on('reorder', this.reorder);
|
||||||
this.composition.load();
|
this.composition.load();
|
||||||
|
this.stalenessSubscription = {};
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.composition.off('add', this.addItem);
|
this.composition.off('add', this.addItem);
|
||||||
this.composition.off('remove', this.removeItem);
|
this.composition.off('remove', this.removeItem);
|
||||||
this.composition.off('reorder', this.reorder);
|
this.composition.off('reorder', this.reorder);
|
||||||
|
|
||||||
|
Object.values(this.stalenessSubscription).forEach(stalenessSubscription => {
|
||||||
|
stalenessSubscription.unsubscribe();
|
||||||
|
stalenessSubscription.stalenessUtils.destroy();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addItem(domainObject) {
|
addItem(domainObject) {
|
||||||
@ -101,23 +121,55 @@ export default {
|
|||||||
item.key = this.openmct.objects.makeKeyString(domainObject.identifier);
|
item.key = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
|
||||||
this.items.push(item);
|
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;
|
||||||
},
|
},
|
||||||
removeItem(identifier) {
|
removeItem(identifier) {
|
||||||
let index = this.items.findIndex(item => this.openmct.objects.makeKeyString(identifier) === item.key);
|
const SKIP_CHECK = true;
|
||||||
|
const keystring = this.openmct.objects.makeKeyString(identifier);
|
||||||
|
const index = this.items.findIndex(item => keystring === item.key);
|
||||||
|
|
||||||
this.items.splice(index, 1);
|
this.items.splice(index, 1);
|
||||||
|
|
||||||
|
this.stalenessSubscription[keystring].unsubscribe();
|
||||||
|
this.handleStaleness(keystring, { isStale: false }, SKIP_CHECK);
|
||||||
},
|
},
|
||||||
reorder(reorderPlan) {
|
reorder(reorderPlan) {
|
||||||
let oldItems = this.items.slice();
|
const oldItems = this.items.slice();
|
||||||
reorderPlan.forEach((reorderEvent) => {
|
reorderPlan.forEach((reorderEvent) => {
|
||||||
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
metadataHasUnits(valueMetadatas) {
|
metadataHasUnits(valueMetadatas) {
|
||||||
let metadataWithUnits = valueMetadatas.filter(metadatum => metadatum.unit);
|
const metadataWithUnits = valueMetadatas.filter(metadatum => metadatum.unit);
|
||||||
|
|
||||||
return metadataWithUnits.length > 0;
|
return metadataWithUnits.length > 0;
|
||||||
},
|
},
|
||||||
|
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) {
|
updateViewContext(rowContext) {
|
||||||
this.viewContext.row = rowContext;
|
this.viewContext.row = rowContext;
|
||||||
},
|
},
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div
|
||||||
|
class="c-lad-table-wrapper u-style-receiver js-style-receiver"
|
||||||
|
:class="staleClass"
|
||||||
|
>
|
||||||
<table class="c-table c-lad-table">
|
<table class="c-table c-lad-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -48,15 +52,19 @@
|
|||||||
:domain-object="ladRow.domainObject"
|
:domain-object="ladRow.domainObject"
|
||||||
:path-to-table="ladTable.objectPath"
|
:path-to-table="ladTable.objectPath"
|
||||||
:has-units="hasUnits"
|
:has-units="hasUnits"
|
||||||
|
:is-stale="staleObjects.includes(ladRow.key)"
|
||||||
@rowContextClick="updateViewContext"
|
@rowContextClick="updateViewContext"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import LadRow from './LADRow.vue';
|
import LadRow from './LADRow.vue';
|
||||||
|
import StalenessUtils from '@/utils/staleness';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -74,7 +82,8 @@ export default {
|
|||||||
ladTableObjects: [],
|
ladTableObjects: [],
|
||||||
ladTelemetryObjects: {},
|
ladTelemetryObjects: {},
|
||||||
compositions: [],
|
compositions: [],
|
||||||
viewContext: {}
|
viewContext: {},
|
||||||
|
staleObjects: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -95,6 +104,13 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
},
|
||||||
|
staleClass() {
|
||||||
|
if (this.staleObjects.length !== 0) {
|
||||||
|
return 'is-stale';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -103,6 +119,8 @@ export default {
|
|||||||
this.composition.on('remove', this.removeLadTable);
|
this.composition.on('remove', this.removeLadTable);
|
||||||
this.composition.on('reorder', this.reorderLadTables);
|
this.composition.on('reorder', this.reorderLadTables);
|
||||||
this.composition.load();
|
this.composition.load();
|
||||||
|
|
||||||
|
this.stalenessSubscription = {};
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.composition.off('add', this.addLadTable);
|
this.composition.off('add', this.addLadTable);
|
||||||
@ -112,6 +130,11 @@ export default {
|
|||||||
c.composition.off('add', c.addCallback);
|
c.composition.off('add', c.addCallback);
|
||||||
c.composition.off('remove', c.removeCallback);
|
c.composition.off('remove', c.removeCallback);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.values(this.stalenessSubscription).forEach(stalenessSubscription => {
|
||||||
|
stalenessSubscription.unsubscribe();
|
||||||
|
stalenessSubscription.stalenessUtils.destroy();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addLadTable(domainObject) {
|
addLadTable(domainObject) {
|
||||||
@ -160,18 +183,57 @@ export default {
|
|||||||
telemetryObjects.push(telemetryObject);
|
telemetryObjects.push(telemetryObject);
|
||||||
|
|
||||||
this.$set(this.ladTelemetryObjects, ladTable.key, telemetryObjects);
|
this.$set(this.ladTelemetryObjects, ladTable.key, telemetryObjects);
|
||||||
|
|
||||||
|
// if tracking already, possibly in another table, return
|
||||||
|
if (this.stalenessSubscription[telemetryObject.key]) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.stalenessSubscription[telemetryObject.key] = {};
|
||||||
|
this.stalenessSubscription[telemetryObject.key].stalenessUtils = new StalenessUtils(this.openmct, domainObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.openmct.telemetry.isStale(domainObject).then((stalenessResponse) => {
|
||||||
|
if (stalenessResponse !== undefined) {
|
||||||
|
this.handleStaleness(telemetryObject.key, stalenessResponse);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(domainObject, (stalenessResponse) => {
|
||||||
|
this.handleStaleness(telemetryObject.key, stalenessResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.stalenessSubscription[telemetryObject.key].unsubscribe = stalenessSubscription;
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
removeTelemetryObject(ladTable) {
|
removeTelemetryObject(ladTable) {
|
||||||
return (identifier) => {
|
return (identifier) => {
|
||||||
|
const SKIP_CHECK = true;
|
||||||
|
const keystring = this.openmct.objects.makeKeyString(identifier);
|
||||||
let telemetryObjects = this.ladTelemetryObjects[ladTable.key];
|
let telemetryObjects = this.ladTelemetryObjects[ladTable.key];
|
||||||
let index = telemetryObjects.findIndex(telemetryObject => this.openmct.objects.makeKeyString(identifier) === telemetryObject.key);
|
let index = telemetryObjects.findIndex(telemetryObject => keystring === telemetryObject.key);
|
||||||
|
|
||||||
telemetryObjects.splice(index, 1);
|
telemetryObjects.splice(index, 1);
|
||||||
|
|
||||||
this.$set(this.ladTelemetryObjects, ladTable.key, telemetryObjects);
|
this.$set(this.ladTelemetryObjects, ladTable.key, telemetryObjects);
|
||||||
|
|
||||||
|
this.stalenessSubscription[keystring].unsubscribe();
|
||||||
|
this.stalenessSubscription[keystring].stalenessUtils.destroy();
|
||||||
|
this.handleStaleness(keystring, { isStale: false }, SKIP_CHECK);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
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) {
|
updateViewContext(rowContext) {
|
||||||
this.viewContext.row = rowContext;
|
this.viewContext.row = rowContext;
|
||||||
},
|
},
|
||||||
|
@ -160,7 +160,8 @@ export default class Condition extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
criterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
criterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
||||||
criterion.on('telemetryIsStale', (obj) => this.handleStaleCriterion(obj));
|
criterion.on('telemetryIsOld', (obj) => this.handleOldTelemetryCriterion(obj));
|
||||||
|
criterion.on('telemetryStaleness', () => this.handleTelemetryStaleness());
|
||||||
if (!this.criteria) {
|
if (!this.criteria) {
|
||||||
this.criteria = [];
|
this.criteria = [];
|
||||||
}
|
}
|
||||||
@ -191,12 +192,14 @@ export default class Condition extends EventEmitter {
|
|||||||
const newCriterionConfiguration = this.generateCriterion(criterionConfiguration);
|
const newCriterionConfiguration = this.generateCriterion(criterionConfiguration);
|
||||||
let newCriterion = new TelemetryCriterion(newCriterionConfiguration, this.openmct);
|
let newCriterion = new TelemetryCriterion(newCriterionConfiguration, this.openmct);
|
||||||
newCriterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
newCriterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
||||||
newCriterion.on('telemetryIsStale', (obj) => this.handleStaleCriterion(obj));
|
newCriterion.on('telemetryIsOld', (obj) => this.handleOldTelemetryCriterion(obj));
|
||||||
|
newCriterion.on('telemetryStaleness', () => this.handleTelemetryStaleness());
|
||||||
|
|
||||||
let criterion = found.item;
|
let criterion = found.item;
|
||||||
criterion.unsubscribe();
|
criterion.unsubscribe();
|
||||||
criterion.off('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
criterion.off('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
||||||
criterion.off('telemetryIsStale', (obj) => this.handleStaleCriterion(obj));
|
criterion.off('telemetryIsOld', (obj) => this.handleOldTelemetryCriterion(obj));
|
||||||
|
newCriterion.off('telemetryStaleness', () => this.handleTelemetryStaleness());
|
||||||
this.criteria.splice(found.index, 1, newCriterion);
|
this.criteria.splice(found.index, 1, newCriterion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,12 +208,9 @@ export default class Condition extends EventEmitter {
|
|||||||
let found = this.findCriterion(id);
|
let found = this.findCriterion(id);
|
||||||
if (found) {
|
if (found) {
|
||||||
let criterion = found.item;
|
let criterion = found.item;
|
||||||
criterion.off('criterionUpdated', (obj) => {
|
criterion.off('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
||||||
this.handleCriterionUpdated(obj);
|
criterion.off('telemetryIsOld', (obj) => this.handleOldTelemetryCriterion(obj));
|
||||||
});
|
criterion.off('telemetryStaleness', () => this.handleTelemetryStaleness());
|
||||||
criterion.off('telemetryIsStale', (obj) => {
|
|
||||||
this.handleStaleCriterion(obj);
|
|
||||||
});
|
|
||||||
criterion.destroy();
|
criterion.destroy();
|
||||||
this.criteria.splice(found.index, 1);
|
this.criteria.splice(found.index, 1);
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ export default class Condition extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStaleCriterion(updatedCriterion) {
|
handleOldTelemetryCriterion(updatedCriterion) {
|
||||||
this.result = evaluateResults(this.criteria.map(criterion => criterion.result), this.trigger);
|
this.result = evaluateResults(this.criteria.map(criterion => criterion.result), this.trigger);
|
||||||
let latestTimestamp = {};
|
let latestTimestamp = {};
|
||||||
latestTimestamp = getLatestTimestamp(
|
latestTimestamp = getLatestTimestamp(
|
||||||
@ -239,6 +239,11 @@ export default class Condition extends EventEmitter {
|
|||||||
this.conditionManager.updateCurrentCondition(latestTimestamp);
|
this.conditionManager.updateCurrentCondition(latestTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTelemetryStaleness() {
|
||||||
|
this.result = evaluateResults(this.criteria.map(criterion => criterion.result), this.trigger);
|
||||||
|
this.conditionManager.updateCurrentCondition();
|
||||||
|
}
|
||||||
|
|
||||||
updateDescription() {
|
updateDescription() {
|
||||||
const triggerDescription = this.getTriggerDescription();
|
const triggerDescription = this.getTriggerDescription();
|
||||||
let description = '';
|
let description = '';
|
||||||
|
@ -82,8 +82,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import Condition from './Condition.vue';
|
import Condition from './Condition.vue';
|
||||||
import ConditionManager from '../ConditionManager';
|
import ConditionManager from '../ConditionManager';
|
||||||
|
import StalenessUtils from '@/utils/staleness';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -139,6 +141,13 @@ export default {
|
|||||||
if (this.stopObservingForChanges) {
|
if (this.stopObservingForChanges) {
|
||||||
this.stopObservingForChanges();
|
this.stopObservingForChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.stalenessSubscription) {
|
||||||
|
Object.values(this.stalenessSubscription).forEach(stalenessSubscription => {
|
||||||
|
stalenessSubscription.unsubscribe();
|
||||||
|
stalenessSubscription.stalenessUtils.destroy();
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.composition = this.openmct.composition.get(this.domainObject);
|
this.composition = this.openmct.composition.get(this.domainObject);
|
||||||
@ -150,6 +159,7 @@ export default {
|
|||||||
this.conditionManager = new ConditionManager(this.domainObject, this.openmct);
|
this.conditionManager = new ConditionManager(this.domainObject, this.openmct);
|
||||||
this.conditionManager.on('conditionSetResultUpdated', this.handleConditionSetResultUpdated);
|
this.conditionManager.on('conditionSetResultUpdated', this.handleConditionSetResultUpdated);
|
||||||
this.updateDefaultCondition();
|
this.updateDefaultCondition();
|
||||||
|
this.stalenessSubscription = {};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleConditionSetResultUpdated(data) {
|
handleConditionSetResultUpdated(data) {
|
||||||
@ -210,19 +220,57 @@ export default {
|
|||||||
return arr;
|
return arr;
|
||||||
},
|
},
|
||||||
addTelemetryObject(domainObject) {
|
addTelemetryObject(domainObject) {
|
||||||
|
const keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
|
||||||
this.telemetryObjs.push(domainObject);
|
this.telemetryObjs.push(domainObject);
|
||||||
this.$emit('telemetryUpdated', this.telemetryObjs);
|
this.$emit('telemetryUpdated', 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) => {
|
||||||
|
this.hanldeStaleness(keyString, stalenessResponse);
|
||||||
|
});
|
||||||
|
const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(domainObject, (stalenessResponse) => {
|
||||||
|
this.hanldeStaleness(keyString, stalenessResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.stalenessSubscription[keyString].unsubscribe = stalenessSubscription;
|
||||||
},
|
},
|
||||||
removeTelemetryObject(identifier) {
|
removeTelemetryObject(identifier) {
|
||||||
let index = this.telemetryObjs.findIndex(obj => {
|
const keyString = this.openmct.objects.makeKeyString(identifier);
|
||||||
|
const index = this.telemetryObjs.findIndex(obj => {
|
||||||
let objId = this.openmct.objects.makeKeyString(obj.identifier);
|
let objId = this.openmct.objects.makeKeyString(obj.identifier);
|
||||||
let id = this.openmct.objects.makeKeyString(identifier);
|
|
||||||
|
|
||||||
return objId === id;
|
return objId === keyString;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
this.telemetryObjs.splice(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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hanldeStaleness(keyString, stalenessResponse) {
|
||||||
|
if (this.stalenessSubscription[keyString].stalenessUtils.shouldUpdateStaleness(stalenessResponse)) {
|
||||||
|
this.emitStaleness({
|
||||||
|
keyString,
|
||||||
|
isStale: stalenessResponse.isStale
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emitStaleness(stalenessObject) {
|
||||||
|
this.$emit('telemetryStaleness', stalenessObject);
|
||||||
},
|
},
|
||||||
addCondition() {
|
addCondition() {
|
||||||
this.conditionManager.addCondition();
|
this.conditionManager.addCondition();
|
||||||
|
@ -21,7 +21,10 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="c-cs">
|
<div
|
||||||
|
class="c-cs"
|
||||||
|
:class="{'is-stale': isStale }"
|
||||||
|
>
|
||||||
<section class="c-cs__current-output c-section">
|
<section class="c-cs__current-output c-section">
|
||||||
<div class="c-cs__content c-cs__current-output-value">
|
<div class="c-cs__content c-cs__current-output-value">
|
||||||
<span class="c-cs__current-output-value__label">Current Output</span>
|
<span class="c-cs__current-output-value__label">Current Output</span>
|
||||||
@ -50,6 +53,7 @@
|
|||||||
@conditionSetResultUpdated="updateCurrentOutput"
|
@conditionSetResultUpdated="updateCurrentOutput"
|
||||||
@updateDefaultOutput="updateDefaultOutput"
|
@updateDefaultOutput="updateDefaultOutput"
|
||||||
@telemetryUpdated="updateTelemetry"
|
@telemetryUpdated="updateTelemetry"
|
||||||
|
@telemetryStaleness="handleStaleness"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -73,9 +77,15 @@ export default {
|
|||||||
currentConditionOutput: '',
|
currentConditionOutput: '',
|
||||||
defaultConditionOutput: '',
|
defaultConditionOutput: '',
|
||||||
telemetryObjs: [],
|
telemetryObjs: [],
|
||||||
testData: {}
|
testData: {},
|
||||||
|
staleObjects: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
isStale() {
|
||||||
|
return this.staleObjects.length !== 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.conditionSetIdentifier = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
this.conditionSetIdentifier = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||||
this.testData = {
|
this.testData = {
|
||||||
@ -95,6 +105,18 @@ export default {
|
|||||||
},
|
},
|
||||||
updateTestData(testData) {
|
updateTestData(testData) {
|
||||||
this.testData = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
>
|
>
|
||||||
<span v-if="inputIndex < inputCount-1">and</span>
|
<span v-if="inputIndex < inputCount-1">and</span>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="criterion.metadata === 'dataReceived'">seconds</span>
|
<span v-if="criterion.metadata === 'dataReceived' && criterion.operation.name === IS_OLD_KEY">seconds</span>
|
||||||
</template>
|
</template>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
<span
|
<span
|
||||||
@ -122,7 +122,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { OPERATIONS, INPUT_TYPES } from '../utils/operations';
|
import { OPERATIONS, INPUT_TYPES } from '../utils/operations';
|
||||||
import {TRIGGER_CONJUNCTION} from "../utils/constants";
|
import { TRIGGER_CONJUNCTION, IS_OLD_KEY, IS_STALE_KEY } from "../utils/constants";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
@ -153,7 +153,8 @@ export default {
|
|||||||
rowLabel: '',
|
rowLabel: '',
|
||||||
operationFormat: '',
|
operationFormat: '',
|
||||||
enumerations: [],
|
enumerations: [],
|
||||||
inputTypes: INPUT_TYPES
|
inputTypes: INPUT_TYPES,
|
||||||
|
IS_OLD_KEY
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -164,7 +165,7 @@ export default {
|
|||||||
},
|
},
|
||||||
filteredOps: function () {
|
filteredOps: function () {
|
||||||
if (this.criterion.metadata === 'dataReceived') {
|
if (this.criterion.metadata === 'dataReceived') {
|
||||||
return this.operations.filter(op => op.name === 'isStale');
|
return this.operations.filter(op => op.name === IS_OLD_KEY || op.name === IS_STALE_KEY);
|
||||||
} else {
|
} else {
|
||||||
return this.operations.filter(op => op.appliesTo.indexOf(this.operationFormat) !== -1);
|
return this.operations.filter(op => op.appliesTo.indexOf(this.operationFormat) !== -1);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,10 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleHolder();
|
||||||
|
}
|
||||||
|
|
||||||
/************************** CONDITION SET LAYOUT */
|
/************************** CONDITION SET LAYOUT */
|
||||||
&__current-output {
|
&__current-output {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
@ -21,8 +21,9 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
import TelemetryCriterion from './TelemetryCriterion';
|
import TelemetryCriterion from './TelemetryCriterion';
|
||||||
|
import StalenessUtils from '@/utils/staleness';
|
||||||
import { evaluateResults } from "../utils/evaluator";
|
import { evaluateResults } from "../utils/evaluator";
|
||||||
import {getLatestTimestamp, subscribeForStaleness} from '../utils/time';
|
import { getLatestTimestamp, checkIfOld } from '../utils/time';
|
||||||
import { getOperatorText } from "@/plugins/condition/utils/operations";
|
import { getOperatorText } from "@/plugins/condition/utils/operations";
|
||||||
|
|
||||||
export default class AllTelemetryCriterion extends TelemetryCriterion {
|
export default class AllTelemetryCriterion extends TelemetryCriterion {
|
||||||
@ -38,13 +39,41 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
|||||||
initialize() {
|
initialize() {
|
||||||
this.telemetryObjects = { ...this.telemetryDomainObjectDefinition.telemetryObjects };
|
this.telemetryObjects = { ...this.telemetryDomainObjectDefinition.telemetryObjects };
|
||||||
this.telemetryDataCache = {};
|
this.telemetryDataCache = {};
|
||||||
if (this.isValid() && this.isStalenessCheck() && this.isValidInput()) {
|
|
||||||
this.subscribeForStaleData(this.telemetryObjects || {});
|
if (this.isValid() && this.isOldCheck() && this.isValidInput()) {
|
||||||
|
this.checkForOldData(this.telemetryObjects || {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isValid() && this.isStalenessCheck()) {
|
||||||
|
this.subscribeToStaleness(this.telemetryObjects || {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeForStaleData(telemetryObjects) {
|
checkForOldData(telemetryObjects) {
|
||||||
|
if (!this.ageCheck) {
|
||||||
|
this.ageCheck = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.values(telemetryObjects).forEach((telemetryObject) => {
|
||||||
|
const id = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||||
|
if (!this.ageCheck[id]) {
|
||||||
|
this.ageCheck[id] = checkIfOld((data) => {
|
||||||
|
this.handleOldTelemetry(id, data);
|
||||||
|
}, this.input[0] * 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOldTelemetry(id, data) {
|
||||||
|
if (this.telemetryDataCache) {
|
||||||
|
this.telemetryDataCache[id] = true;
|
||||||
|
this.result = evaluateResults(Object.values(this.telemetryDataCache), this.telemetry);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emitEvent('telemetryIsOld', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeToStaleness(telemetryObjects) {
|
||||||
if (!this.stalenessSubscription) {
|
if (!this.stalenessSubscription) {
|
||||||
this.stalenessSubscription = {};
|
this.stalenessSubscription = {};
|
||||||
}
|
}
|
||||||
@ -52,20 +81,27 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
|||||||
Object.values(telemetryObjects).forEach((telemetryObject) => {
|
Object.values(telemetryObjects).forEach((telemetryObject) => {
|
||||||
const id = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
const id = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||||
if (!this.stalenessSubscription[id]) {
|
if (!this.stalenessSubscription[id]) {
|
||||||
this.stalenessSubscription[id] = subscribeForStaleness((data) => {
|
this.stalenessSubscription[id] = {};
|
||||||
this.handleStaleTelemetry(id, data);
|
this.stalenessSubscription[id].stalenessUtils = new StalenessUtils(this.openmct, telemetryObject);
|
||||||
}, this.input[0] * 1000);
|
this.stalenessSubscription[id].unsubscribe = this.openmct.telemetry.subscribeToStaleness(
|
||||||
|
telemetryObject,
|
||||||
|
(stalenessResponse) => {
|
||||||
|
this.handleStaleTelemetry(id, stalenessResponse);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStaleTelemetry(id, data) {
|
handleStaleTelemetry(id, stalenessResponse) {
|
||||||
if (this.telemetryDataCache) {
|
if (this.telemetryDataCache) {
|
||||||
this.telemetryDataCache[id] = true;
|
if (this.stalenessSubscription[id].stalenessUtils.shouldUpdateStaleness(stalenessResponse)) {
|
||||||
|
this.telemetryDataCache[id] = stalenessResponse.isStale;
|
||||||
this.result = evaluateResults(Object.values(this.telemetryDataCache), this.telemetry);
|
this.result = evaluateResults(Object.values(this.telemetryDataCache), this.telemetry);
|
||||||
}
|
|
||||||
|
|
||||||
this.emitEvent('telemetryIsStale', data);
|
this.emitEvent('telemetryStaleness');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid() {
|
isValid() {
|
||||||
@ -75,8 +111,13 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
|||||||
updateTelemetryObjects(telemetryObjects) {
|
updateTelemetryObjects(telemetryObjects) {
|
||||||
this.telemetryObjects = { ...telemetryObjects };
|
this.telemetryObjects = { ...telemetryObjects };
|
||||||
this.removeTelemetryDataCache();
|
this.removeTelemetryDataCache();
|
||||||
if (this.isValid() && this.isStalenessCheck() && this.isValidInput()) {
|
|
||||||
this.subscribeForStaleData(this.telemetryObjects || {});
|
if (this.isValid() && this.isOldCheck() && this.isValidInput()) {
|
||||||
|
this.checkForOldData(this.telemetryObjects || {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isValid() && this.isStalenessCheck()) {
|
||||||
|
this.subscribeToStaleness(this.telemetryObjects || {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +132,9 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
|||||||
});
|
});
|
||||||
telemetryCacheIds.forEach(id => {
|
telemetryCacheIds.forEach(id => {
|
||||||
delete (this.telemetryDataCache[id]);
|
delete (this.telemetryDataCache[id]);
|
||||||
|
delete (this.ageCheck[id]);
|
||||||
|
this.stalenessSubscription[id].unsubscribe();
|
||||||
|
this.stalenessSubscription[id].stalenessUtils.destroy();
|
||||||
delete (this.stalenessSubscription[id]);
|
delete (this.stalenessSubscription[id]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -125,10 +169,10 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
|||||||
updateResult(data, telemetryObjects) {
|
updateResult(data, telemetryObjects) {
|
||||||
const validatedData = this.isValid() ? data : {};
|
const validatedData = this.isValid() ? data : {};
|
||||||
|
|
||||||
if (validatedData) {
|
if (validatedData && !this.isStalenessCheck()) {
|
||||||
if (this.isStalenessCheck()) {
|
if (this.isOldCheck()) {
|
||||||
if (this.stalenessSubscription && this.stalenessSubscription[validatedData.id]) {
|
if (this.ageCheck?.[validatedData.id]) {
|
||||||
this.stalenessSubscription[validatedData.id].update(validatedData);
|
this.ageCheck[validatedData.id].update(validatedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.telemetryDataCache[validatedData.id] = false;
|
this.telemetryDataCache[validatedData.id] = false;
|
||||||
@ -226,9 +270,17 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
|||||||
destroy() {
|
destroy() {
|
||||||
delete this.telemetryObjects;
|
delete this.telemetryObjects;
|
||||||
delete this.telemetryDataCache;
|
delete this.telemetryDataCache;
|
||||||
|
|
||||||
|
if (this.ageCheck) {
|
||||||
|
Object.values(this.ageCheck).forEach((subscription) => subscription.clear);
|
||||||
|
delete this.ageCheck;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.stalenessSubscription) {
|
if (this.stalenessSubscription) {
|
||||||
Object.values(this.stalenessSubscription).forEach((subscription) => subscription.clear);
|
Object.values(this.stalenessSubscription).forEach(subscription => {
|
||||||
delete this.stalenessSubscription;
|
subscription.unsubscribe();
|
||||||
|
subscription.stalenessUtils.destroy();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,10 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
import EventEmitter from 'EventEmitter';
|
import EventEmitter from 'EventEmitter';
|
||||||
|
import StalenessUtils from '@/utils/staleness';
|
||||||
|
import { IS_OLD_KEY, IS_STALE_KEY } from '../utils/constants';
|
||||||
import { OPERATIONS, getOperatorText } from '../utils/operations';
|
import { OPERATIONS, getOperatorText } from '../utils/operations';
|
||||||
import { subscribeForStaleness } from "../utils/time";
|
import { checkIfOld } from "../utils/time";
|
||||||
|
|
||||||
export default class TelemetryCriterion extends EventEmitter {
|
export default class TelemetryCriterion extends EventEmitter {
|
||||||
|
|
||||||
@ -44,7 +46,8 @@ export default class TelemetryCriterion extends EventEmitter {
|
|||||||
this.input = telemetryDomainObjectDefinition.input;
|
this.input = telemetryDomainObjectDefinition.input;
|
||||||
this.metadata = telemetryDomainObjectDefinition.metadata;
|
this.metadata = telemetryDomainObjectDefinition.metadata;
|
||||||
this.result = undefined;
|
this.result = undefined;
|
||||||
this.stalenessSubscription = undefined;
|
this.ageCheck = undefined;
|
||||||
|
this.unsubscribeFromStaleness = undefined;
|
||||||
|
|
||||||
this.initialize();
|
this.initialize();
|
||||||
this.emitEvent('criterionUpdated', this);
|
this.emitEvent('criterionUpdated', this);
|
||||||
@ -57,8 +60,13 @@ export default class TelemetryCriterion extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.updateTelemetryObjects(this.telemetryDomainObjectDefinition.telemetryObjects);
|
this.updateTelemetryObjects(this.telemetryDomainObjectDefinition.telemetryObjects);
|
||||||
if (this.isValid() && this.isStalenessCheck() && this.isValidInput()) {
|
|
||||||
this.subscribeForStaleData();
|
if (this.isValid() && this.isOldCheck() && this.isValidInput()) {
|
||||||
|
this.checkForOldData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isValid() && this.isStalenessCheck()) {
|
||||||
|
this.subscribeToStaleness();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,25 +74,52 @@ export default class TelemetryCriterion extends EventEmitter {
|
|||||||
return this.telemetryObjectIdAsString && (this.telemetryObjectIdAsString === id);
|
return this.telemetryObjectIdAsString && (this.telemetryObjectIdAsString === id);
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeForStaleData() {
|
checkForOldData() {
|
||||||
if (this.stalenessSubscription) {
|
if (this.ageCheck) {
|
||||||
this.stalenessSubscription.clear();
|
this.ageCheck.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stalenessSubscription = subscribeForStaleness(this.handleStaleTelemetry.bind(this), this.input[0] * 1000);
|
this.ageCheck = checkIfOld(this.handleOldTelemetry.bind(this), this.input[0] * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStaleTelemetry(data) {
|
handleOldTelemetry(data) {
|
||||||
this.result = true;
|
this.result = true;
|
||||||
this.emitEvent('telemetryIsStale', data);
|
this.emitEvent('telemetryIsOld', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeToStaleness() {
|
||||||
|
if (this.unsubscribeFromStaleness) {
|
||||||
|
this.unsubscribeFromStaleness();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.stalenessUtils) {
|
||||||
|
this.stalenessUtils = new StalenessUtils(this.openmct, this.telemetryObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.openmct.telemetry.isStale(this.telemetryObject).then(this.handleStaleTelemetry.bind(this));
|
||||||
|
this.unsubscribeFromStaleness = this.openmct.telemetry.subscribeToStaleness(
|
||||||
|
this.telemetryObject,
|
||||||
|
this.handleStaleTelemetry.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleStaleTelemetry(stalenessResponse) {
|
||||||
|
if (stalenessResponse !== undefined && this.stalenessUtils.shouldUpdateStaleness(stalenessResponse)) {
|
||||||
|
this.result = stalenessResponse.isStale;
|
||||||
|
this.emitEvent('telemetryStaleness');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid() {
|
isValid() {
|
||||||
return this.telemetryObject && this.metadata && this.operation;
|
return this.telemetryObject && this.metadata && this.operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isOldCheck() {
|
||||||
|
return this.metadata && this.metadata === 'dataReceived' && this.operation === IS_OLD_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
isStalenessCheck() {
|
isStalenessCheck() {
|
||||||
return this.metadata && this.metadata === 'dataReceived';
|
return this.metadata && this.metadata === 'dataReceived' && this.operation === IS_STALE_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidInput() {
|
isValidInput() {
|
||||||
@ -93,8 +128,13 @@ export default class TelemetryCriterion extends EventEmitter {
|
|||||||
|
|
||||||
updateTelemetryObjects(telemetryObjects) {
|
updateTelemetryObjects(telemetryObjects) {
|
||||||
this.telemetryObject = telemetryObjects[this.telemetryObjectIdAsString];
|
this.telemetryObject = telemetryObjects[this.telemetryObjectIdAsString];
|
||||||
if (this.isValid() && this.isStalenessCheck() && this.isValidInput()) {
|
|
||||||
this.subscribeForStaleData();
|
if (this.isValid() && this.isOldCheck() && this.isValidInput()) {
|
||||||
|
this.checkForOldData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isValid() && this.isStalenessCheck()) {
|
||||||
|
this.subscribeToStaleness();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,9 +170,11 @@ export default class TelemetryCriterion extends EventEmitter {
|
|||||||
|
|
||||||
updateResult(data) {
|
updateResult(data) {
|
||||||
const validatedData = this.isValid() ? data : {};
|
const validatedData = this.isValid() ? data : {};
|
||||||
if (this.isStalenessCheck()) {
|
|
||||||
if (this.stalenessSubscription) {
|
if (!this.isStalenessCheck()) {
|
||||||
this.stalenessSubscription.update(validatedData);
|
if (this.isOldCheck()) {
|
||||||
|
if (this.ageCheck) {
|
||||||
|
this.ageCheck.update(validatedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.result = false;
|
this.result = false;
|
||||||
@ -140,6 +182,7 @@ export default class TelemetryCriterion extends EventEmitter {
|
|||||||
this.result = this.computeResult(validatedData);
|
this.result = this.computeResult(validatedData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
requestLAD(telemetryObjects, requestOptions) {
|
requestLAD(telemetryObjects, requestOptions) {
|
||||||
let options = {
|
let options = {
|
||||||
@ -268,8 +311,17 @@ export default class TelemetryCriterion extends EventEmitter {
|
|||||||
destroy() {
|
destroy() {
|
||||||
delete this.telemetryObject;
|
delete this.telemetryObject;
|
||||||
delete this.telemetryObjectIdAsString;
|
delete this.telemetryObjectIdAsString;
|
||||||
if (this.stalenessSubscription) {
|
|
||||||
delete this.stalenessSubscription;
|
if (this.ageCheck) {
|
||||||
|
delete this.ageCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.stalenessUtils) {
|
||||||
|
this.stalenessUtils.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.unsubscribeFromStaleness) {
|
||||||
|
this.unsubscribeFromStaleness();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import Vue from 'vue';
|
|||||||
import {getApplicableStylesForItem} from "./utils/styleUtils";
|
import {getApplicableStylesForItem} from "./utils/styleUtils";
|
||||||
import ConditionManager from "@/plugins/condition/ConditionManager";
|
import ConditionManager from "@/plugins/condition/ConditionManager";
|
||||||
import StyleRuleManager from "./StyleRuleManager";
|
import StyleRuleManager from "./StyleRuleManager";
|
||||||
|
import { IS_OLD_KEY } from "./utils/constants";
|
||||||
|
|
||||||
describe('the plugin', function () {
|
describe('the plugin', function () {
|
||||||
let conditionSetDefinition;
|
let conditionSetDefinition;
|
||||||
@ -642,7 +643,7 @@ describe('the plugin', function () {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('the condition check for staleness', () => {
|
describe('the condition check if old', () => {
|
||||||
let conditionSetDomainObject;
|
let conditionSetDomainObject;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -660,13 +661,13 @@ describe('the plugin', function () {
|
|||||||
"id": "39584410-cbf9-499e-96dc-76f27e69885d",
|
"id": "39584410-cbf9-499e-96dc-76f27e69885d",
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"name": "Unnamed Condition",
|
"name": "Unnamed Condition",
|
||||||
"output": "Any stale telemetry",
|
"output": "Any old telemetry",
|
||||||
"trigger": "all",
|
"trigger": "all",
|
||||||
"criteria": [
|
"criteria": [
|
||||||
{
|
{
|
||||||
"id": "35400132-63b0-425c-ac30-8197df7d5862",
|
"id": "35400132-63b0-425c-ac30-8197df7d5862",
|
||||||
"telemetry": "any",
|
"telemetry": "any",
|
||||||
"operation": "isStale",
|
"operation": IS_OLD_KEY,
|
||||||
"input": [
|
"input": [
|
||||||
"0.2"
|
"0.2"
|
||||||
],
|
],
|
||||||
@ -674,7 +675,7 @@ describe('the plugin', function () {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"summary": "Match if all criteria are met: Any telemetry is stale after 5 seconds"
|
"summary": "Match if all criteria are met: Any telemetry is old after 5 seconds"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"isDefault": true,
|
"isDefault": true,
|
||||||
@ -708,7 +709,7 @@ describe('the plugin', function () {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should evaluate as stale when telemetry is not received in the allotted time', (done) => {
|
it('should evaluate as old when telemetry is not received in the allotted time', (done) => {
|
||||||
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||||
conditionMgr.telemetryObjects = {
|
conditionMgr.telemetryObjects = {
|
||||||
@ -717,7 +718,7 @@ describe('the plugin', function () {
|
|||||||
conditionMgr.updateConditionTelemetryObjects();
|
conditionMgr.updateConditionTelemetryObjects();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(mockListener).toHaveBeenCalledWith({
|
expect(mockListener).toHaveBeenCalledWith({
|
||||||
output: 'Any stale telemetry',
|
output: 'Any old telemetry',
|
||||||
id: {
|
id: {
|
||||||
namespace: '',
|
namespace: '',
|
||||||
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
|
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
|
||||||
@ -729,7 +730,7 @@ describe('the plugin', function () {
|
|||||||
}, 400);
|
}, 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not evaluate as stale when telemetry is received in the allotted time', (done) => {
|
it('should not evaluate as old when telemetry is received in the allotted time', (done) => {
|
||||||
const date = 1;
|
const date = 1;
|
||||||
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["0.4"];
|
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["0.4"];
|
||||||
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||||
|
@ -59,3 +59,6 @@ export const ERROR = {
|
|||||||
errorText: 'Condition not found'
|
errorText: 'Condition not found'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const IS_OLD_KEY = 'isStale';
|
||||||
|
export const IS_STALE_KEY = 'isStale.new';
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import { IS_OLD_KEY, IS_STALE_KEY } from "./constants";
|
||||||
|
|
||||||
function convertToNumbers(input) {
|
function convertToNumbers(input) {
|
||||||
let numberInputs = [];
|
let numberInputs = [];
|
||||||
input.forEach(inputValue => numberInputs.push(Number(inputValue)));
|
input.forEach(inputValue => numberInputs.push(Number(inputValue)));
|
||||||
@ -295,7 +297,7 @@ export const OPERATIONS = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'isStale',
|
name: IS_OLD_KEY,
|
||||||
operation: function () {
|
operation: function () {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
@ -305,6 +307,18 @@ export const OPERATIONS = [
|
|||||||
getDescription: function (values) {
|
getDescription: function (values) {
|
||||||
return ` is older than ${values[0] || ''} seconds`;
|
return ` is older than ${values[0] || ''} seconds`;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: IS_STALE_KEY,
|
||||||
|
operation: function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
text: 'is stale',
|
||||||
|
appliesTo: ["number"],
|
||||||
|
inputCount: 0,
|
||||||
|
getDescription: function () {
|
||||||
|
return ' is stale';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -316,5 +330,5 @@ export const INPUT_TYPES = {
|
|||||||
export function getOperatorText(operationName, values) {
|
export function getOperatorText(operationName, values) {
|
||||||
const found = OPERATIONS.find((operation) => operation.name === operationName);
|
const found = OPERATIONS.find((operation) => operation.name === operationName);
|
||||||
|
|
||||||
return found ? found.getDescription(values) : '';
|
return found?.getDescription(values) ?? '';
|
||||||
}
|
}
|
||||||
|
@ -51,26 +51,26 @@ export function getLatestTimestamp(
|
|||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function subscribeForStaleness(callback, timeout) {
|
export function checkIfOld(callback, timeout) {
|
||||||
let stalenessTimer = setTimeout(() => {
|
let oldCheckTimer = setTimeout(() => {
|
||||||
clearTimeout(stalenessTimer);
|
clearTimeout(oldCheckTimer);
|
||||||
callback();
|
callback();
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
update: (data) => {
|
update: (data) => {
|
||||||
if (stalenessTimer) {
|
if (oldCheckTimer) {
|
||||||
clearTimeout(stalenessTimer);
|
clearTimeout(oldCheckTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
stalenessTimer = setTimeout(() => {
|
oldCheckTimer = setTimeout(() => {
|
||||||
clearTimeout(stalenessTimer);
|
clearTimeout(oldCheckTimer);
|
||||||
callback(data);
|
callback(data);
|
||||||
}, timeout);
|
}, timeout);
|
||||||
},
|
},
|
||||||
clear: () => {
|
clear: () => {
|
||||||
if (stalenessTimer) {
|
if (oldCheckTimer) {
|
||||||
clearTimeout(stalenessTimer);
|
clearTimeout(oldCheckTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
import { subscribeForStaleness } from "./time";
|
import { checkIfOld } from "./time";
|
||||||
|
|
||||||
describe('time related utils', () => {
|
describe('time related utils', () => {
|
||||||
let subscription;
|
let subscription;
|
||||||
@ -27,11 +27,11 @@ describe('time related utils', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockListener = jasmine.createSpy('listener');
|
mockListener = jasmine.createSpy('listener');
|
||||||
subscription = subscribeForStaleness(mockListener, 100);
|
subscription = checkIfOld(mockListener, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('subscribe for staleness', () => {
|
describe('check if old', () => {
|
||||||
it('should call listeners when stale', (done) => {
|
it('should call listeners when old', (done) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(mockListener).toHaveBeenCalled();
|
expect(mockListener).toHaveBeenCalled();
|
||||||
done();
|
done();
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
<div
|
<div
|
||||||
v-if="domainObject"
|
v-if="domainObject"
|
||||||
class="c-telemetry-view u-style-receiver"
|
class="c-telemetry-view u-style-receiver"
|
||||||
:class="[statusClass]"
|
:class="[itemClasses]"
|
||||||
:style="styleObject"
|
:style="styleObject"
|
||||||
:data-font-size="item.fontSize"
|
:data-font-size="item.fontSize"
|
||||||
:data-font="item.font"
|
:data-font="item.font"
|
||||||
@ -73,6 +73,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import LayoutFrame from './LayoutFrame.vue';
|
import LayoutFrame from './LayoutFrame.vue';
|
||||||
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
|
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
|
||||||
|
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||||
import { getDefaultNotebook, getNotebookSectionAndPage } from '@/plugins/notebook/utils/notebook-storage.js';
|
import { getDefaultNotebook, getNotebookSectionAndPage } from '@/plugins/notebook/utils/notebook-storage.js';
|
||||||
|
|
||||||
const DEFAULT_TELEMETRY_DIMENSIONS = [10, 5];
|
const DEFAULT_TELEMETRY_DIMENSIONS = [10, 5];
|
||||||
@ -102,7 +103,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
LayoutFrame
|
LayoutFrame
|
||||||
},
|
},
|
||||||
mixins: [conditionalStylesMixin],
|
mixins: [conditionalStylesMixin, stalenessMixin],
|
||||||
inject: ['openmct', 'objectPath', 'currentView'],
|
inject: ['openmct', 'objectPath', 'currentView'],
|
||||||
props: {
|
props: {
|
||||||
item: {
|
item: {
|
||||||
@ -137,8 +138,18 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
statusClass() {
|
itemClasses() {
|
||||||
return (this.status) ? `is-status--${this.status}` : '';
|
let classes = [];
|
||||||
|
|
||||||
|
if (this.status) {
|
||||||
|
classes.push(`is-status--${this.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isStale) {
|
||||||
|
classes.push('is-stale');
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
},
|
},
|
||||||
showLabel() {
|
showLabel() {
|
||||||
let displayMode = this.item.displayMode;
|
let displayMode = this.item.displayMode;
|
||||||
@ -310,6 +321,7 @@ export default {
|
|||||||
this.removeSelectable = this.openmct.selection.selectable(
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
this.$el, this.context, this.immediatelySelect || this.initSelect);
|
this.$el, this.context, this.immediatelySelect || this.initSelect);
|
||||||
delete this.immediatelySelect;
|
delete this.immediatelySelect;
|
||||||
|
this.subscribeToStaleness(this.domainObject);
|
||||||
},
|
},
|
||||||
updateTelemetryFormat(format) {
|
updateTelemetryFormat(format) {
|
||||||
this.customStringformatter.setFormat(format);
|
this.customStringformatter.setFormat(format);
|
||||||
|
@ -25,6 +25,12 @@
|
|||||||
margin-right: $interiorMargin;
|
margin-right: $interiorMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
.c-telemetry-view__value {
|
||||||
|
@include isStaleElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.c-frame & {
|
.c-frame & {
|
||||||
@include abs();
|
@include abs();
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="c-gauge__wrapper js-gauge-wrapper"
|
class="c-gauge__wrapper js-gauge-wrapper"
|
||||||
:class="`c-gauge--${gaugeType}`"
|
:class="gaugeClasses"
|
||||||
:title="gaugeTitle"
|
:title="gaugeTitle"
|
||||||
>
|
>
|
||||||
<template v-if="typeDial">
|
<template v-if="typeDial">
|
||||||
@ -347,12 +347,14 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { DIAL_VALUE_DEG_OFFSET, getLimitDegree } from '../gauge-limit-util';
|
import { DIAL_VALUE_DEG_OFFSET, getLimitDegree } from '../gauge-limit-util';
|
||||||
|
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||||
|
|
||||||
const LIMIT_PADDING_IN_PERCENT = 10;
|
const LIMIT_PADDING_IN_PERCENT = 10;
|
||||||
const DEFAULT_CURRENT_VALUE = '--';
|
const DEFAULT_CURRENT_VALUE = '--';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Gauge',
|
name: 'Gauge',
|
||||||
|
mixins: [stalenessMixin],
|
||||||
inject: ['openmct', 'domainObject', 'composition'],
|
inject: ['openmct', 'domainObject', 'composition'],
|
||||||
data() {
|
data() {
|
||||||
let gaugeController = this.domainObject.configuration.gaugeController;
|
let gaugeController = this.domainObject.configuration.gaugeController;
|
||||||
@ -403,6 +405,15 @@ export default {
|
|||||||
|
|
||||||
return VIEWBOX_STR.replace('X', this.digits * DIGITS_RATIO);
|
return VIEWBOX_STR.replace('X', this.digits * DIGITS_RATIO);
|
||||||
},
|
},
|
||||||
|
gaugeClasses() {
|
||||||
|
let classes = [`c-gauge--${this.gaugeType}`];
|
||||||
|
|
||||||
|
if (this.isStale) {
|
||||||
|
classes.push('is-stale');
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
},
|
||||||
rangeFontSize() {
|
rangeFontSize() {
|
||||||
const CHAR_THRESHOLD = 3;
|
const CHAR_THRESHOLD = 3;
|
||||||
const START_PERC = 8.5;
|
const START_PERC = 8.5;
|
||||||
@ -553,6 +564,8 @@ export default {
|
|||||||
this.telemetryObject = domainObject;
|
this.telemetryObject = domainObject;
|
||||||
this.request();
|
this.request();
|
||||||
this.subscribe();
|
this.subscribe();
|
||||||
|
|
||||||
|
this.subscribeToStaleness(domainObject);
|
||||||
},
|
},
|
||||||
addedToComposition(domainObject) {
|
addedToComposition(domainObject) {
|
||||||
if (this.telemetryObject) {
|
if (this.telemetryObject) {
|
||||||
@ -611,6 +624,8 @@ export default {
|
|||||||
this.unsubscribe = null;
|
this.unsubscribe = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.triggerUnsubscribeFromStaleness();
|
||||||
|
|
||||||
this.curVal = DEFAULT_CURRENT_VALUE;
|
this.curVal = DEFAULT_CURRENT_VALUE;
|
||||||
this.formats = null;
|
this.formats = null;
|
||||||
this.limitHigh = '';
|
this.limitHigh = '';
|
||||||
|
@ -32,6 +32,15 @@ $meterNeedleBorderRadius: 5px;
|
|||||||
&__wrapper {
|
&__wrapper {
|
||||||
@include abs();
|
@include abs();
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleHolder();
|
||||||
|
|
||||||
|
[class*=__current-value-text] {
|
||||||
|
fill: $colorTelemStale;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__current-value-text-wrapper {
|
&__current-value-text-wrapper {
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<div
|
<div
|
||||||
ref="plotWrapper"
|
ref="plotWrapper"
|
||||||
class="c-plot holder holder-plot has-control-bar"
|
class="c-plot holder holder-plot has-control-bar"
|
||||||
|
:class="staleClass"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
ref="plotContainer"
|
ref="plotContainer"
|
||||||
@ -50,6 +51,7 @@ import eventHelpers from './lib/eventHelpers';
|
|||||||
import ImageExporter from '../../exporters/ImageExporter';
|
import ImageExporter from '../../exporters/ImageExporter';
|
||||||
import MctPlot from './MctPlot.vue';
|
import MctPlot from './MctPlot.vue';
|
||||||
import ProgressBar from "../../ui/components/ProgressBar.vue";
|
import ProgressBar from "../../ui/components/ProgressBar.vue";
|
||||||
|
import StalenessUtils from '@/utils/staleness';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -74,21 +76,95 @@ export default {
|
|||||||
cursorGuide: false,
|
cursorGuide: false,
|
||||||
gridLines: !this.options.compact,
|
gridLines: !this.options.compact,
|
||||||
loading: false,
|
loading: false,
|
||||||
status: ''
|
status: '',
|
||||||
|
staleObjects: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
staleClass() {
|
||||||
|
if (this.staleObjects.length !== 0) {
|
||||||
|
return 'is-stale';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
eventHelpers.extend(this);
|
eventHelpers.extend(this);
|
||||||
this.imageExporter = new ImageExporter(this.openmct);
|
this.imageExporter = new ImageExporter(this.openmct);
|
||||||
|
this.loadComposition();
|
||||||
|
this.stalenessSubscription = {};
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
loadComposition() {
|
||||||
|
this.compositionCollection = this.openmct.composition.get(this.domainObject);
|
||||||
|
|
||||||
|
if (this.compositionCollection) {
|
||||||
|
this.compositionCollection.on('add', this.addItem);
|
||||||
|
this.compositionCollection.on('remove', this.removeItem);
|
||||||
|
this.compositionCollection.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
addItem(object) {
|
||||||
|
const keystring = this.openmct.objects.makeKeyString(object.identifier);
|
||||||
|
|
||||||
|
if (!this.stalenessSubscription[keystring]) {
|
||||||
|
this.stalenessSubscription[keystring] = {};
|
||||||
|
this.stalenessSubscription[keystring].stalenessUtils = new StalenessUtils(this.openmct, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.openmct.telemetry.isStale(object).then((stalenessResponse) => {
|
||||||
|
if (stalenessResponse !== undefined) {
|
||||||
|
this.handleStaleness(keystring, stalenessResponse);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const unsubscribeFromStaleness = this.openmct.telemetry.subscribeToStaleness(object, (stalenessResponse) => {
|
||||||
|
this.handleStaleness(keystring, stalenessResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.stalenessSubscription[keystring].unsubscribe = unsubscribeFromStaleness;
|
||||||
|
},
|
||||||
|
removeItem(object) {
|
||||||
|
const SKIP_CHECK = true;
|
||||||
|
const keystring = this.openmct.objects.makeKeyString(object);
|
||||||
|
this.stalenessSubscription[keystring].unsubscribe();
|
||||||
|
this.stalenessSubscription[keystring].stalenessUtils.destroy();
|
||||||
|
this.handleStaleness(keystring, { isStale: false }, SKIP_CHECK);
|
||||||
|
},
|
||||||
|
handleStaleness(id, stalenessResponse, skipCheck = false) {
|
||||||
|
if (skipCheck || this.stalenessSubscription[id].stalenessUtils.shouldUpdateStaleness(stalenessResponse, id)) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
loadingUpdated(loading) {
|
loadingUpdated(loading) {
|
||||||
this.loading = loading;
|
this.loading = loading;
|
||||||
},
|
},
|
||||||
destroy() {
|
destroy() {
|
||||||
|
if (this.stalenessSubscription) {
|
||||||
|
Object.values(this.stalenessSubscription).forEach(stalenessSubscription => {
|
||||||
|
stalenessSubscription.unsubscribe();
|
||||||
|
stalenessSubscription.stalenessUtils.destroy();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.compositionCollection) {
|
||||||
|
this.compositionCollection.off('add', this.addItem);
|
||||||
|
this.compositionCollection.off('remove', this.removeItem);
|
||||||
|
}
|
||||||
|
|
||||||
this.stopListening();
|
this.stopListening();
|
||||||
},
|
},
|
||||||
exportJPG() {
|
exportJPG() {
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<div
|
<div
|
||||||
class="plot-legend-item"
|
class="plot-legend-item"
|
||||||
:class="{
|
:class="{
|
||||||
|
'is-stale': isStale,
|
||||||
'is-status--missing': isMissing
|
'is-status--missing': isMissing
|
||||||
}"
|
}"
|
||||||
@mouseover="toggleHover(true)"
|
@mouseover="toggleHover(true)"
|
||||||
@ -55,8 +56,10 @@
|
|||||||
|
|
||||||
import {getLimitClass} from "@/plugins/plot/chart/limitUtil";
|
import {getLimitClass} from "@/plugins/plot/chart/limitUtil";
|
||||||
import eventHelpers from "../lib/eventHelpers";
|
import eventHelpers from "../lib/eventHelpers";
|
||||||
|
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [stalenessMixin],
|
||||||
inject: ['openmct', 'domainObject'],
|
inject: ['openmct', 'domainObject'],
|
||||||
props: {
|
props: {
|
||||||
valueToShowWhenCollapsed: {
|
valueToShowWhenCollapsed: {
|
||||||
@ -112,6 +115,7 @@ export default {
|
|||||||
this.listenTo(this.seriesObject, 'change:name', () => {
|
this.listenTo(this.seriesObject, 'change:name', () => {
|
||||||
this.updateName();
|
this.updateName();
|
||||||
}, this);
|
}, this);
|
||||||
|
this.subscribeToStaleness(this.seriesObject.domainObject);
|
||||||
this.initialize();
|
this.initialize();
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
@ -120,6 +124,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
initialize(highlightedObject) {
|
initialize(highlightedObject) {
|
||||||
const seriesObject = highlightedObject ? highlightedObject.series : this.seriesObject;
|
const seriesObject = highlightedObject ? highlightedObject.series : this.seriesObject;
|
||||||
|
|
||||||
this.isMissing = seriesObject.domainObject.status === 'missing';
|
this.isMissing = seriesObject.domainObject.status === 'missing';
|
||||||
this.colorAsHexString = seriesObject.get('color').asHexString();
|
this.colorAsHexString = seriesObject.get('color').asHexString();
|
||||||
this.nameWithUnit = seriesObject.nameWithUnit();
|
this.nameWithUnit = seriesObject.nameWithUnit();
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<tr
|
<tr
|
||||||
class="plot-legend-item"
|
class="plot-legend-item"
|
||||||
:class="{
|
:class="{
|
||||||
|
'is-stale': isStale,
|
||||||
'is-status--missing': isMissing
|
'is-status--missing': isMissing
|
||||||
}"
|
}"
|
||||||
@mouseover="toggleHover(true)"
|
@mouseover="toggleHover(true)"
|
||||||
@ -81,8 +82,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import {getLimitClass} from "@/plugins/plot/chart/limitUtil";
|
import {getLimitClass} from "@/plugins/plot/chart/limitUtil";
|
||||||
import eventHelpers from "@/plugins/plot/lib/eventHelpers";
|
import eventHelpers from "@/plugins/plot/lib/eventHelpers";
|
||||||
|
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [stalenessMixin],
|
||||||
inject: ['openmct', 'domainObject'],
|
inject: ['openmct', 'domainObject'],
|
||||||
props: {
|
props: {
|
||||||
seriesObject: {
|
seriesObject: {
|
||||||
@ -149,6 +152,7 @@ export default {
|
|||||||
this.listenTo(this.seriesObject, 'change:name', () => {
|
this.listenTo(this.seriesObject, 'change:name', () => {
|
||||||
this.updateName();
|
this.updateName();
|
||||||
}, this);
|
}, this);
|
||||||
|
this.subscribeToStaleness(this.seriesObject.domainObject);
|
||||||
this.initialize();
|
this.initialize();
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
@ -27,12 +27,13 @@
|
|||||||
import MctPlot from '../MctPlot.vue';
|
import MctPlot from '../MctPlot.vue';
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import conditionalStylesMixin from "./mixins/objectStyles-mixin";
|
import conditionalStylesMixin from "./mixins/objectStyles-mixin";
|
||||||
|
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||||
import configStore from "@/plugins/plot/configuration/ConfigStore";
|
import configStore from "@/plugins/plot/configuration/ConfigStore";
|
||||||
import PlotConfigurationModel from "@/plugins/plot/configuration/PlotConfigurationModel";
|
import PlotConfigurationModel from "@/plugins/plot/configuration/PlotConfigurationModel";
|
||||||
import ProgressBar from "../../../ui/components/ProgressBar.vue";
|
import ProgressBar from "../../../ui/components/ProgressBar.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [conditionalStylesMixin],
|
mixins: [conditionalStylesMixin, stalenessMixin],
|
||||||
inject: ['openmct', 'domainObject', 'path'],
|
inject: ['openmct', 'domainObject', 'path'],
|
||||||
props: {
|
props: {
|
||||||
childObject: {
|
childObject: {
|
||||||
@ -114,6 +115,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateView() {
|
updateView() {
|
||||||
|
this.isStale = false;
|
||||||
|
|
||||||
|
this.triggerUnsubscribeFromStaleness();
|
||||||
|
|
||||||
if (this.component) {
|
if (this.component) {
|
||||||
this.component.$destroy();
|
this.component.$destroy();
|
||||||
this.component = undefined;
|
this.component = undefined;
|
||||||
@ -139,6 +144,10 @@ export default {
|
|||||||
let viewContainer = document.createElement('div');
|
let viewContainer = document.createElement('div');
|
||||||
this.$el.append(viewContainer);
|
this.$el.append(viewContainer);
|
||||||
|
|
||||||
|
this.subscribeToStaleness(object, (isStale) => {
|
||||||
|
this.updateComponentProp('isStale', isStale);
|
||||||
|
});
|
||||||
|
|
||||||
this.component = new Vue({
|
this.component = new Vue({
|
||||||
el: viewContainer,
|
el: viewContainer,
|
||||||
components: {
|
components: {
|
||||||
@ -169,7 +178,7 @@ export default {
|
|||||||
this.loading = loaded;
|
this.loading = loaded;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: '<div v-if="!isMissing" ref="plotWrapper" class="l-view-section u-style-receiver js-style-receiver" :class="{\'s-status-timeconductor-unsynced\': status && status === \'timeconductor-unsynced\'}"><progress-bar v-show="loading !== false" class="c-telemetry-table__progress-bar" :model="{progressPerc: undefined}" /><mct-plot :init-grid-lines="gridLines" :init-cursor-guide="cursorGuide" :plot-tick-width="plotTickWidth" :limit-line-labels="limitLineLabels" :color-palette="colorPalette" :options="options" @plotTickWidth="onTickWidthChange" @lockHighlightPoint="onLockHighlightPointUpdated" @highlights="onHighlightsUpdated" @configLoaded="onConfigLoaded" @cursorGuide="onCursorGuideChange" @gridLines="onGridLinesChange" @statusUpdated="setStatus" @loadingUpdated="loadingUpdated"/></div>'
|
template: '<div v-if="!isMissing" ref="plotWrapper" class="l-view-section u-style-receiver js-style-receiver" :class="{\'s-status-timeconductor-unsynced\': status && status === \'timeconductor-unsynced\', \'is-stale\': isStale}"><progress-bar v-show="loading !== false" class="c-telemetry-table__progress-bar" :model="{progressPerc: undefined}" /><mct-plot :init-grid-lines="gridLines" :init-cursor-guide="cursorGuide" :plot-tick-width="plotTickWidth" :limit-line-labels="limitLineLabels" :color-palette="colorPalette" :options="options" @plotTickWidth="onTickWidthChange" @lockHighlightPoint="onLockHighlightPointUpdated" @highlights="onHighlightsUpdated" @configLoaded="onConfigLoaded" @cursorGuide="onCursorGuideChange" @gridLines="onGridLinesChange" @statusUpdated="setStatus" @loadingUpdated="loadingUpdated"/></div>'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setSelection();
|
this.setSelection();
|
||||||
@ -215,7 +224,8 @@ export default {
|
|||||||
plotTickWidth: this.plotTickWidth,
|
plotTickWidth: this.plotTickWidth,
|
||||||
options: this.options,
|
options: this.options,
|
||||||
status: this.status,
|
status: this.status,
|
||||||
colorPalette: this.colorPalette
|
colorPalette: this.colorPalette,
|
||||||
|
isStale: this.isStale
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getPlotObject() {
|
getPlotObject() {
|
||||||
|
@ -155,7 +155,7 @@ define([
|
|||||||
plugins.example.ExampleFaultSource = ExampleFaultSource.default;
|
plugins.example.ExampleFaultSource = ExampleFaultSource.default;
|
||||||
plugins.example.EventGeneratorPlugin = EventGeneratorPlugin.default;
|
plugins.example.EventGeneratorPlugin = EventGeneratorPlugin.default;
|
||||||
plugins.example.ExampleTags = ExampleTags.default;
|
plugins.example.ExampleTags = ExampleTags.default;
|
||||||
plugins.example.Generator = () => GeneratorPlugin;
|
plugins.example.Generator = () => GeneratorPlugin.default;
|
||||||
|
|
||||||
plugins.UTCTimeSystem = UTCTimeSystem.default;
|
plugins.UTCTimeSystem = UTCTimeSystem.default;
|
||||||
plugins.LocalTimeSystem = LocalTimeSystem;
|
plugins.LocalTimeSystem = LocalTimeSystem;
|
||||||
|
@ -28,7 +28,8 @@ define([
|
|||||||
'./TelemetryTableNameColumn',
|
'./TelemetryTableNameColumn',
|
||||||
'./TelemetryTableColumn',
|
'./TelemetryTableColumn',
|
||||||
'./TelemetryTableUnitColumn',
|
'./TelemetryTableUnitColumn',
|
||||||
'./TelemetryTableConfiguration'
|
'./TelemetryTableConfiguration',
|
||||||
|
'@/utils/staleness'
|
||||||
], function (
|
], function (
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
_,
|
_,
|
||||||
@ -37,7 +38,8 @@ define([
|
|||||||
TelemetryTableNameColumn,
|
TelemetryTableNameColumn,
|
||||||
TelemetryTableColumn,
|
TelemetryTableColumn,
|
||||||
TelemetryTableUnitColumn,
|
TelemetryTableUnitColumn,
|
||||||
TelemetryTableConfiguration
|
TelemetryTableConfiguration,
|
||||||
|
StalenessUtils
|
||||||
) {
|
) {
|
||||||
class TelemetryTable extends EventEmitter {
|
class TelemetryTable extends EventEmitter {
|
||||||
constructor(domainObject, openmct) {
|
constructor(domainObject, openmct) {
|
||||||
@ -56,6 +58,7 @@ define([
|
|||||||
this.telemetryCollections = {};
|
this.telemetryCollections = {};
|
||||||
this.delayedActions = [];
|
this.delayedActions = [];
|
||||||
this.outstandingRequests = 0;
|
this.outstandingRequests = 0;
|
||||||
|
this.stalenessSubscription = {};
|
||||||
|
|
||||||
this.addTelemetryObject = this.addTelemetryObject.bind(this);
|
this.addTelemetryObject = this.addTelemetryObject.bind(this);
|
||||||
this.removeTelemetryObject = this.removeTelemetryObject.bind(this);
|
this.removeTelemetryObject = this.removeTelemetryObject.bind(this);
|
||||||
@ -155,6 +158,19 @@ define([
|
|||||||
this.telemetryCollections[keyString].on('clear', this.clearData);
|
this.telemetryCollections[keyString].on('clear', this.clearData);
|
||||||
this.telemetryCollections[keyString].load();
|
this.telemetryCollections[keyString].load();
|
||||||
|
|
||||||
|
this.stalenessSubscription[keyString] = {};
|
||||||
|
this.stalenessSubscription[keyString].stalenessUtils = new StalenessUtils.default(this.openmct, telemetryObject);
|
||||||
|
this.openmct.telemetry.isStale(telemetryObject).then(stalenessResponse => {
|
||||||
|
if (stalenessResponse !== undefined) {
|
||||||
|
this.handleStaleness(keyString, stalenessResponse);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(telemetryObject, (stalenessResponse) => {
|
||||||
|
this.handleStaleness(keyString, stalenessResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.stalenessSubscription[keyString].unsubscribe = stalenessSubscription;
|
||||||
|
|
||||||
this.telemetryObjects[keyString] = {
|
this.telemetryObjects[keyString] = {
|
||||||
telemetryObject,
|
telemetryObject,
|
||||||
keyString,
|
keyString,
|
||||||
@ -166,6 +182,15 @@ define([
|
|||||||
this.emit('object-added', telemetryObject);
|
this.emit('object-added', telemetryObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleStaleness(keyString, stalenessResponse, skipCheck = false) {
|
||||||
|
if (skipCheck || this.stalenessSubscription[keyString].stalenessUtils.shouldUpdateStaleness(stalenessResponse, keyString)) {
|
||||||
|
this.emit('telemetry-staleness', {
|
||||||
|
keyString,
|
||||||
|
isStale: stalenessResponse.isStale
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getTelemetryProcessor(keyString, columnMap, limitEvaluator) {
|
getTelemetryProcessor(keyString, columnMap, limitEvaluator) {
|
||||||
return (telemetry) => {
|
return (telemetry) => {
|
||||||
//Check that telemetry object has not been removed since telemetry was requested.
|
//Check that telemetry object has not been removed since telemetry was requested.
|
||||||
@ -255,6 +280,7 @@ define([
|
|||||||
|
|
||||||
removeTelemetryObject(objectIdentifier) {
|
removeTelemetryObject(objectIdentifier) {
|
||||||
const keyString = this.openmct.objects.makeKeyString(objectIdentifier);
|
const keyString = this.openmct.objects.makeKeyString(objectIdentifier);
|
||||||
|
const SKIP_CHECK = true;
|
||||||
|
|
||||||
this.configuration.removeColumnsForObject(objectIdentifier, true);
|
this.configuration.removeColumnsForObject(objectIdentifier, true);
|
||||||
this.tableRows.removeRowsByObject(keyString);
|
this.tableRows.removeRowsByObject(keyString);
|
||||||
@ -263,6 +289,10 @@ define([
|
|||||||
delete this.telemetryObjects[keyString];
|
delete this.telemetryObjects[keyString];
|
||||||
|
|
||||||
this.emit('object-removed', objectIdentifier);
|
this.emit('object-removed', objectIdentifier);
|
||||||
|
|
||||||
|
this.stalenessSubscription[keyString].unsubscribe();
|
||||||
|
this.stalenessSubscription[keyString].stalenessUtils.destroy();
|
||||||
|
this.handleStaleness(keyString, { isStale: false }, SKIP_CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearData() {
|
clearData() {
|
||||||
@ -368,6 +398,11 @@ define([
|
|||||||
this.filterObserver();
|
this.filterObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.values(this.stalenessSubscription).forEach(stalenessSubscription => {
|
||||||
|
stalenessSubscription.unsubscribe();
|
||||||
|
stalenessSubscription.stalenessUtils.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
if (this.tableComposition !== undefined) {
|
if (this.tableComposition !== undefined) {
|
||||||
this.tableComposition.off('add', this.addTelemetryObject);
|
this.tableComposition.off('add', this.addTelemetryObject);
|
||||||
this.tableComposition.off('remove', this.removeTelemetryObject);
|
this.tableComposition.off('remove', this.removeTelemetryObject);
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="c-table-wrapper"
|
class="c-table-wrapper"
|
||||||
:class="{ 'is-paused': paused }"
|
:class="tableClasses"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="enableLegacyToolbar"
|
v-if="enableLegacyToolbar"
|
||||||
@ -381,7 +381,8 @@ export default {
|
|||||||
enableRegexSearch: {},
|
enableRegexSearch: {},
|
||||||
hideHeaders: configuration.hideHeaders,
|
hideHeaders: configuration.hideHeaders,
|
||||||
totalNumberOfRows: 0,
|
totalNumberOfRows: 0,
|
||||||
rowContext: {}
|
rowContext: {},
|
||||||
|
staleObjects: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -416,6 +417,19 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
|
},
|
||||||
|
tableClasses() {
|
||||||
|
let classes = [];
|
||||||
|
|
||||||
|
if (this.paused) {
|
||||||
|
classes.push('is-paused');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.staleObjects.length !== 0) {
|
||||||
|
classes.push('is-stale');
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -488,6 +502,7 @@ export default {
|
|||||||
this.table.on('refresh', this.clearRowsAndRerender);
|
this.table.on('refresh', this.clearRowsAndRerender);
|
||||||
this.table.on('historical-rows-processed', this.checkForMarkedRows);
|
this.table.on('historical-rows-processed', this.checkForMarkedRows);
|
||||||
this.table.on('outstanding-requests', this.outstandingRequests);
|
this.table.on('outstanding-requests', this.outstandingRequests);
|
||||||
|
this.table.on('telemetry-staleness', this.handleStaleness);
|
||||||
|
|
||||||
this.table.tableRows.on('add', this.rowsAdded);
|
this.table.tableRows.on('add', this.rowsAdded);
|
||||||
this.table.tableRows.on('remove', this.rowsRemoved);
|
this.table.tableRows.on('remove', this.rowsRemoved);
|
||||||
@ -516,6 +531,7 @@ export default {
|
|||||||
this.table.off('historical-rows-processed', this.checkForMarkedRows);
|
this.table.off('historical-rows-processed', this.checkForMarkedRows);
|
||||||
this.table.off('refresh', this.clearRowsAndRerender);
|
this.table.off('refresh', this.clearRowsAndRerender);
|
||||||
this.table.off('outstanding-requests', this.outstandingRequests);
|
this.table.off('outstanding-requests', this.outstandingRequests);
|
||||||
|
this.table.off('telemetry-staleness', this.handleStaleness);
|
||||||
|
|
||||||
this.table.tableRows.off('add', this.rowsAdded);
|
this.table.tableRows.off('add', this.rowsAdded);
|
||||||
this.table.tableRows.off('remove', this.rowsRemoved);
|
this.table.tableRows.off('remove', this.rowsRemoved);
|
||||||
@ -726,6 +742,18 @@ export default {
|
|||||||
outstandingRequests(loading) {
|
outstandingRequests(loading) {
|
||||||
this.loading = loading;
|
this.loading = loading;
|
||||||
},
|
},
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
calculateTableSize() {
|
calculateTableSize() {
|
||||||
this.$nextTick().then(this.calculateColumnWidths);
|
this.$nextTick().then(this.calculateColumnWidths);
|
||||||
},
|
},
|
||||||
|
@ -305,8 +305,8 @@ $colorIndicatorMenuFg: $colorHeadFg;
|
|||||||
$colorIndicatorMenuFgHov: pullForward($colorHeadFg, 10%);
|
$colorIndicatorMenuFgHov: pullForward($colorHeadFg, 10%);
|
||||||
|
|
||||||
// Staleness
|
// Staleness
|
||||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
$colorTelemStale: cyan;
|
||||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
$colorTelemStaleFg: #002A2A;
|
||||||
$styleTelemStale: italic;
|
$styleTelemStale: italic;
|
||||||
|
|
||||||
// Limits
|
// Limits
|
||||||
|
@ -309,8 +309,8 @@ $colorIndicatorMenuFg: $colorHeadFg;
|
|||||||
$colorIndicatorMenuFgHov: pullForward($colorHeadFg, 10%);
|
$colorIndicatorMenuFgHov: pullForward($colorHeadFg, 10%);
|
||||||
|
|
||||||
// Staleness
|
// Staleness
|
||||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
$colorTelemStale: cyan;
|
||||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
$colorTelemStaleFg: #002A2A;
|
||||||
$styleTelemStale: italic;
|
$styleTelemStale: italic;
|
||||||
|
|
||||||
// Limits
|
// Limits
|
||||||
|
@ -305,8 +305,8 @@ $colorIndicatorMenuFg: $colorHeadFg;
|
|||||||
$colorIndicatorMenuFgHov: pullForward($colorHeadFg, 10%);
|
$colorIndicatorMenuFgHov: pullForward($colorHeadFg, 10%);
|
||||||
|
|
||||||
// Staleness
|
// Staleness
|
||||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
$colorTelemStale: #00c9c9;
|
||||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
$colorTelemStaleFg: #002A2A;
|
||||||
$styleTelemStale: italic;
|
$styleTelemStale: italic;
|
||||||
|
|
||||||
// Limits
|
// Limits
|
||||||
|
@ -164,6 +164,7 @@ $glyph-icon-status-poll-caution: '\e933';
|
|||||||
$glyph-icon-status-poll-circle-slash: '\e934';
|
$glyph-icon-status-poll-circle-slash: '\e934';
|
||||||
$glyph-icon-status-poll-question-mark: '\e935';
|
$glyph-icon-status-poll-question-mark: '\e935';
|
||||||
$glyph-icon-status-poll-edit: '\e936';
|
$glyph-icon-status-poll-edit: '\e936';
|
||||||
|
$glyph-icon-stale: '\e937';
|
||||||
$glyph-icon-arrows-right-left: '\ea00';
|
$glyph-icon-arrows-right-left: '\ea00';
|
||||||
$glyph-icon-arrows-up-down: '\ea01';
|
$glyph-icon-arrows-up-down: '\ea01';
|
||||||
$glyph-icon-bullet: '\ea02';
|
$glyph-icon-bullet: '\ea02';
|
||||||
|
@ -95,6 +95,7 @@
|
|||||||
.icon-status-poll-circle-slash { @include glyphBefore($glyph-icon-status-poll-circle-slash); }
|
.icon-status-poll-circle-slash { @include glyphBefore($glyph-icon-status-poll-circle-slash); }
|
||||||
.icon-status-poll-question-mark { @include glyphBefore($glyph-icon-status-poll-question-mark); }
|
.icon-status-poll-question-mark { @include glyphBefore($glyph-icon-status-poll-question-mark); }
|
||||||
.icon-status-poll-edit { @include glyphBefore($glyph-icon-status-poll-edit); }
|
.icon-status-poll-edit { @include glyphBefore($glyph-icon-status-poll-edit); }
|
||||||
|
.icon-stale { @include glyphBefore($glyph-icon-stale); }
|
||||||
.icon-arrows-right-left { @include glyphBefore($glyph-icon-arrows-right-left); }
|
.icon-arrows-right-left { @include glyphBefore($glyph-icon-arrows-right-left); }
|
||||||
.icon-arrows-up-down { @include glyphBefore($glyph-icon-arrows-up-down); }
|
.icon-arrows-up-down { @include glyphBefore($glyph-icon-arrows-up-down); }
|
||||||
.icon-bullet { @include glyphBefore($glyph-icon-bullet); }
|
.icon-bullet { @include glyphBefore($glyph-icon-bullet); }
|
||||||
|
@ -81,6 +81,10 @@ mct-plot {
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleHolder();
|
||||||
|
}
|
||||||
|
|
||||||
.c-plot--stacked-container {
|
.c-plot--stacked-container {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -89,6 +93,10 @@ mct-plot {
|
|||||||
min-height: $plotMinH;
|
min-height: $plotMinH;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
.is-stale {
|
||||||
|
@include isStaleHolder();
|
||||||
|
}
|
||||||
|
|
||||||
&[s-selected] {
|
&[s-selected] {
|
||||||
.is-editing & {
|
.is-editing & {
|
||||||
border: $editMarqueeBorder;
|
border: $editMarqueeBorder;
|
||||||
@ -596,6 +604,10 @@ mct-plot {
|
|||||||
margin-left: $interiorMarginSm;
|
margin-left: $interiorMarginSm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleElement();
|
||||||
|
}
|
||||||
|
|
||||||
.plot-series-color-swatch {
|
.plot-series-color-swatch {
|
||||||
@include colorSwatch();
|
@include colorSwatch();
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -649,8 +661,10 @@ mct-plot {
|
|||||||
// .plot-legend-item is a span of spans.
|
// .plot-legend-item is a span of spans.
|
||||||
|
|
||||||
.plot-legend-item {
|
.plot-legend-item {
|
||||||
|
border-radius: $smallCr;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
padding: 1px;
|
||||||
|
|
||||||
.plot-series-swatch-and-name,
|
.plot-series-swatch-and-name,
|
||||||
.plot-series-value {
|
.plot-series-value {
|
||||||
|
@ -153,6 +153,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin isStaleGlyph() {
|
||||||
|
content: $glyph-icon-stale;
|
||||||
|
display: block;
|
||||||
|
font-family: symbolsfont;
|
||||||
|
font-style: normal;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin isStaleHolder() {
|
||||||
|
// Applied to objects that frame content, like Display Layout frames, plots, etc.
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 2px solid rgba($colorTelemStale, 0.8) !important;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
@include isStaleGlyph();
|
||||||
|
color: $colorTelemStale;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
left: 3px;
|
||||||
|
width: 12px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin isStaleElement() {
|
||||||
|
// Applied directly to values, like LAD Table cells, alphanumerics, plot legend items
|
||||||
|
background: $colorTelemStale !important;
|
||||||
|
color: $colorTelemStaleFg !important;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin isLimit() {
|
@mixin isLimit() {
|
||||||
&[class*='is-limit'] {
|
&[class*='is-limit'] {
|
||||||
&:before {
|
&:before {
|
||||||
|
@ -90,6 +90,10 @@ div.c-table {
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleHolder();
|
||||||
|
}
|
||||||
|
|
||||||
.--width-less-than-600 & {
|
.--width-less-than-600 & {
|
||||||
&:not(.is-paused) {
|
&:not(.is-paused) {
|
||||||
.c-table-control-bar {
|
.c-table-control-bar {
|
||||||
@ -179,12 +183,22 @@ div.c-table {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: $mainViewPad;
|
padding: $mainViewPad;
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleHolder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.c-lad-table {
|
.c-lad-table {
|
||||||
th, td {
|
th, td {
|
||||||
width: 33%; // Needed to prevent size jumping as values dynamically update
|
width: 33%; // Needed to prevent size jumping as values dynamically update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************** TABLE AND SUMMARY VIEWS */
|
/************************************** TABLE AND SUMMARY VIEWS */
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "Open MCT Symbols 16px",
|
"name": "Open MCT Symbols 16px",
|
||||||
"lastOpened": 0,
|
"lastOpened": 0,
|
||||||
"created": 1660771219523
|
"created": 1674103729548
|
||||||
},
|
},
|
||||||
"iconSets": [
|
"iconSets": [
|
||||||
{
|
{
|
||||||
@ -447,13 +447,21 @@
|
|||||||
"code": 59702,
|
"code": 59702,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"order": 215,
|
||||||
|
"id": 185,
|
||||||
|
"name": "icon-stale",
|
||||||
|
"prevSize": 16,
|
||||||
|
"code": 59703,
|
||||||
|
"tempChar": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"order": 27,
|
"order": 27,
|
||||||
"id": 105,
|
"id": 105,
|
||||||
"name": "icon-arrows-right-left",
|
"name": "icon-arrows-right-left",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59904,
|
"code": 59904,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 26,
|
"order": 26,
|
||||||
@ -461,7 +469,7 @@
|
|||||||
"name": "icon-arrows-up-down",
|
"name": "icon-arrows-up-down",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59905,
|
"code": 59905,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 68,
|
"order": 68,
|
||||||
@ -469,7 +477,7 @@
|
|||||||
"name": "icon-bullet",
|
"name": "icon-bullet",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59906,
|
"code": 59906,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 150,
|
"order": 150,
|
||||||
@ -477,7 +485,7 @@
|
|||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59907,
|
"code": 59907,
|
||||||
"name": "icon-calendar",
|
"name": "icon-calendar",
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 45,
|
"order": 45,
|
||||||
@ -485,7 +493,7 @@
|
|||||||
"name": "icon-chain-links",
|
"name": "icon-chain-links",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59908,
|
"code": 59908,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 73,
|
"order": 73,
|
||||||
@ -493,7 +501,7 @@
|
|||||||
"name": "icon-download",
|
"name": "icon-download",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59909,
|
"code": 59909,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 39,
|
"order": 39,
|
||||||
@ -501,7 +509,7 @@
|
|||||||
"name": "icon-duplicate",
|
"name": "icon-duplicate",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59910,
|
"code": 59910,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 50,
|
"order": 50,
|
||||||
@ -509,7 +517,7 @@
|
|||||||
"name": "icon-folder-new",
|
"name": "icon-folder-new",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59911,
|
"code": 59911,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 138,
|
"order": 138,
|
||||||
@ -517,7 +525,7 @@
|
|||||||
"name": "icon-fullscreen-collapse",
|
"name": "icon-fullscreen-collapse",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59912,
|
"code": 59912,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 139,
|
"order": 139,
|
||||||
@ -525,7 +533,7 @@
|
|||||||
"name": "icon-fullscreen-expand",
|
"name": "icon-fullscreen-expand",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59913,
|
"code": 59913,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 122,
|
"order": 122,
|
||||||
@ -533,7 +541,7 @@
|
|||||||
"name": "icon-layers",
|
"name": "icon-layers",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59914,
|
"code": 59914,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 151,
|
"order": 151,
|
||||||
@ -541,7 +549,7 @@
|
|||||||
"name": "icon-line-horz",
|
"name": "icon-line-horz",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59915,
|
"code": 59915,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 100,
|
"order": 100,
|
||||||
@ -549,7 +557,7 @@
|
|||||||
"name": "icon-magnify",
|
"name": "icon-magnify",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59916,
|
"code": 59916,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 99,
|
"order": 99,
|
||||||
@ -557,7 +565,7 @@
|
|||||||
"name": "icon-magnify-in",
|
"name": "icon-magnify-in",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59917,
|
"code": 59917,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 101,
|
"order": 101,
|
||||||
@ -565,7 +573,7 @@
|
|||||||
"name": "icon-magnify-out-v2",
|
"name": "icon-magnify-out-v2",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59918,
|
"code": 59918,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 103,
|
"order": 103,
|
||||||
@ -573,7 +581,7 @@
|
|||||||
"name": "icon-menu",
|
"name": "icon-menu",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59919,
|
"code": 59919,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 124,
|
"order": 124,
|
||||||
@ -581,7 +589,7 @@
|
|||||||
"name": "icon-move",
|
"name": "icon-move",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59920,
|
"code": 59920,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 7,
|
"order": 7,
|
||||||
@ -589,7 +597,7 @@
|
|||||||
"name": "icon-new-window",
|
"name": "icon-new-window",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59921,
|
"code": 59921,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 63,
|
"order": 63,
|
||||||
@ -597,7 +605,7 @@
|
|||||||
"name": "icon-paint-bucket-v2",
|
"name": "icon-paint-bucket-v2",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59922,
|
"code": 59922,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 15,
|
"order": 15,
|
||||||
@ -605,7 +613,7 @@
|
|||||||
"name": "icon-pencil",
|
"name": "icon-pencil",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59923,
|
"code": 59923,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 54,
|
"order": 54,
|
||||||
@ -613,7 +621,7 @@
|
|||||||
"name": "icon-pencil-edit-in-place",
|
"name": "icon-pencil-edit-in-place",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59924,
|
"code": 59924,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 40,
|
"order": 40,
|
||||||
@ -621,7 +629,7 @@
|
|||||||
"name": "icon-play",
|
"name": "icon-play",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59925,
|
"code": 59925,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 125,
|
"order": 125,
|
||||||
@ -629,7 +637,7 @@
|
|||||||
"name": "icon-pause",
|
"name": "icon-pause",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59926,
|
"code": 59926,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 119,
|
"order": 119,
|
||||||
@ -637,7 +645,7 @@
|
|||||||
"name": "icon-plot-resource",
|
"name": "icon-plot-resource",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59927,
|
"code": 59927,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 48,
|
"order": 48,
|
||||||
@ -645,7 +653,7 @@
|
|||||||
"name": "icon-pointer-left",
|
"name": "icon-pointer-left",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59928,
|
"code": 59928,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 47,
|
"order": 47,
|
||||||
@ -653,7 +661,7 @@
|
|||||||
"name": "icon-pointer-right",
|
"name": "icon-pointer-right",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59929,
|
"code": 59929,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 85,
|
"order": 85,
|
||||||
@ -661,7 +669,7 @@
|
|||||||
"name": "icon-refresh",
|
"name": "icon-refresh",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59930,
|
"code": 59930,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 55,
|
"order": 55,
|
||||||
@ -669,7 +677,7 @@
|
|||||||
"name": "icon-save",
|
"name": "icon-save",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59931,
|
"code": 59931,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 56,
|
"order": 56,
|
||||||
@ -677,7 +685,7 @@
|
|||||||
"name": "icon-save-as",
|
"name": "icon-save-as",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59932,
|
"code": 59932,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 58,
|
"order": 58,
|
||||||
@ -685,7 +693,7 @@
|
|||||||
"name": "icon-sine",
|
"name": "icon-sine",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59933,
|
"code": 59933,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 113,
|
"order": 113,
|
||||||
@ -693,7 +701,7 @@
|
|||||||
"name": "icon-font",
|
"name": "icon-font",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59934,
|
"code": 59934,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 41,
|
"order": 41,
|
||||||
@ -701,7 +709,7 @@
|
|||||||
"name": "icon-thumbs-strip",
|
"name": "icon-thumbs-strip",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59935,
|
"code": 59935,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 146,
|
"order": 146,
|
||||||
@ -709,7 +717,7 @@
|
|||||||
"name": "icon-two-parts-both",
|
"name": "icon-two-parts-both",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59936,
|
"code": 59936,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 145,
|
"order": 145,
|
||||||
@ -717,7 +725,7 @@
|
|||||||
"name": "icon-two-parts-one-only",
|
"name": "icon-two-parts-one-only",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59937,
|
"code": 59937,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 82,
|
"order": 82,
|
||||||
@ -725,7 +733,7 @@
|
|||||||
"name": "icon-resync",
|
"name": "icon-resync",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59938,
|
"code": 59938,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 86,
|
"order": 86,
|
||||||
@ -733,7 +741,7 @@
|
|||||||
"name": "icon-reset",
|
"name": "icon-reset",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59939,
|
"code": 59939,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 61,
|
"order": 61,
|
||||||
@ -741,7 +749,7 @@
|
|||||||
"name": "icon-x-in-circle",
|
"name": "icon-x-in-circle",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59940,
|
"code": 59940,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 84,
|
"order": 84,
|
||||||
@ -749,7 +757,7 @@
|
|||||||
"name": "icon-brightness",
|
"name": "icon-brightness",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59941,
|
"code": 59941,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 83,
|
"order": 83,
|
||||||
@ -757,7 +765,7 @@
|
|||||||
"name": "icon-contrast",
|
"name": "icon-contrast",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59942,
|
"code": 59942,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 87,
|
"order": 87,
|
||||||
@ -765,7 +773,7 @@
|
|||||||
"name": "icon-expand",
|
"name": "icon-expand",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59943,
|
"code": 59943,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 89,
|
"order": 89,
|
||||||
@ -773,7 +781,7 @@
|
|||||||
"name": "icon-list-view",
|
"name": "icon-list-view",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59944,
|
"code": 59944,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 133,
|
"order": 133,
|
||||||
@ -781,7 +789,7 @@
|
|||||||
"name": "icon-grid-snap-to",
|
"name": "icon-grid-snap-to",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59945,
|
"code": 59945,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 132,
|
"order": 132,
|
||||||
@ -789,7 +797,7 @@
|
|||||||
"name": "icon-grid-snap-no",
|
"name": "icon-grid-snap-no",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59946,
|
"code": 59946,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 94,
|
"order": 94,
|
||||||
@ -797,7 +805,7 @@
|
|||||||
"name": "icon-frame-show",
|
"name": "icon-frame-show",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59947,
|
"code": 59947,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 95,
|
"order": 95,
|
||||||
@ -805,7 +813,7 @@
|
|||||||
"name": "icon-frame-hide",
|
"name": "icon-frame-hide",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59948,
|
"code": 59948,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 97,
|
"order": 97,
|
||||||
@ -813,7 +821,7 @@
|
|||||||
"name": "icon-import",
|
"name": "icon-import",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59949,
|
"code": 59949,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 96,
|
"order": 96,
|
||||||
@ -821,7 +829,7 @@
|
|||||||
"name": "icon-export",
|
"name": "icon-export",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59950,
|
"code": 59950,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 194,
|
"order": 194,
|
||||||
@ -829,7 +837,7 @@
|
|||||||
"name": "icon-font-size",
|
"name": "icon-font-size",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59951,
|
"code": 59951,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 163,
|
"order": 163,
|
||||||
@ -837,7 +845,7 @@
|
|||||||
"name": "icon-clear-data",
|
"name": "icon-clear-data",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59952,
|
"code": 59952,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 173,
|
"order": 173,
|
||||||
@ -845,7 +853,7 @@
|
|||||||
"name": "icon-history",
|
"name": "icon-history",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59953,
|
"code": 59953,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 181,
|
"order": 181,
|
||||||
@ -853,7 +861,7 @@
|
|||||||
"name": "icon-arrow-up-to-parent",
|
"name": "icon-arrow-up-to-parent",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59954,
|
"code": 59954,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 184,
|
"order": 184,
|
||||||
@ -861,7 +869,7 @@
|
|||||||
"name": "icon-crosshair-in-circle",
|
"name": "icon-crosshair-in-circle",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59955,
|
"code": 59955,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 185,
|
"order": 185,
|
||||||
@ -869,7 +877,7 @@
|
|||||||
"name": "icon-target",
|
"name": "icon-target",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59956,
|
"code": 59956,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 187,
|
"order": 187,
|
||||||
@ -877,7 +885,7 @@
|
|||||||
"name": "icon-items-collapse",
|
"name": "icon-items-collapse",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59957,
|
"code": 59957,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 188,
|
"order": 188,
|
||||||
@ -885,7 +893,7 @@
|
|||||||
"name": "icon-items-expand",
|
"name": "icon-items-expand",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59958,
|
"code": 59958,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 190,
|
"order": 190,
|
||||||
@ -893,7 +901,7 @@
|
|||||||
"name": "icon-3-dots",
|
"name": "icon-3-dots",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59959,
|
"code": 59959,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 193,
|
"order": 193,
|
||||||
@ -901,7 +909,7 @@
|
|||||||
"name": "icon-grid-on",
|
"name": "icon-grid-on",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59960,
|
"code": 59960,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 192,
|
"order": 192,
|
||||||
@ -909,7 +917,7 @@
|
|||||||
"name": "icon-grid-off",
|
"name": "icon-grid-off",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59961,
|
"code": 59961,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 191,
|
"order": 191,
|
||||||
@ -917,7 +925,7 @@
|
|||||||
"name": "icon-camera",
|
"name": "icon-camera",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59962,
|
"code": 59962,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 196,
|
"order": 196,
|
||||||
@ -925,7 +933,7 @@
|
|||||||
"name": "icon-folders-collapse",
|
"name": "icon-folders-collapse",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 59963,
|
"code": 59963,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 144,
|
"order": 144,
|
||||||
@ -933,7 +941,7 @@
|
|||||||
"name": "icon-activity",
|
"name": "icon-activity",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60160,
|
"code": 60160,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 104,
|
"order": 104,
|
||||||
@ -941,7 +949,7 @@
|
|||||||
"name": "icon-activity-mode",
|
"name": "icon-activity-mode",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60161,
|
"code": 60161,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 137,
|
"order": 137,
|
||||||
@ -949,7 +957,7 @@
|
|||||||
"name": "icon-autoflow-tabular",
|
"name": "icon-autoflow-tabular",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60162,
|
"code": 60162,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 115,
|
"order": 115,
|
||||||
@ -957,7 +965,7 @@
|
|||||||
"name": "icon-clock",
|
"name": "icon-clock",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60163,
|
"code": 60163,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 2,
|
"order": 2,
|
||||||
@ -965,7 +973,7 @@
|
|||||||
"name": "icon-database",
|
"name": "icon-database",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60164,
|
"code": 60164,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 3,
|
"order": 3,
|
||||||
@ -973,7 +981,7 @@
|
|||||||
"name": "icon-database-query",
|
"name": "icon-database-query",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60165,
|
"code": 60165,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 67,
|
"order": 67,
|
||||||
@ -981,7 +989,7 @@
|
|||||||
"name": "icon-dataset",
|
"name": "icon-dataset",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60166,
|
"code": 60166,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 59,
|
"order": 59,
|
||||||
@ -989,7 +997,7 @@
|
|||||||
"name": "icon-datatable",
|
"name": "icon-datatable",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60167,
|
"code": 60167,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 136,
|
"order": 136,
|
||||||
@ -997,7 +1005,7 @@
|
|||||||
"name": "icon-dictionary",
|
"name": "icon-dictionary",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60168,
|
"code": 60168,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 51,
|
"order": 51,
|
||||||
@ -1005,7 +1013,7 @@
|
|||||||
"name": "icon-folder",
|
"name": "icon-folder",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60169,
|
"code": 60169,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 147,
|
"order": 147,
|
||||||
@ -1013,7 +1021,7 @@
|
|||||||
"name": "icon-image",
|
"name": "icon-image",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60170,
|
"code": 60170,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 4,
|
"order": 4,
|
||||||
@ -1021,7 +1029,7 @@
|
|||||||
"name": "icon-layout",
|
"name": "icon-layout",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60171,
|
"code": 60171,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 24,
|
"order": 24,
|
||||||
@ -1029,7 +1037,7 @@
|
|||||||
"name": "icon-object",
|
"name": "icon-object",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60172,
|
"code": 60172,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 52,
|
"order": 52,
|
||||||
@ -1037,7 +1045,7 @@
|
|||||||
"name": "icon-object-unknown",
|
"name": "icon-object-unknown",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60173,
|
"code": 60173,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 105,
|
"order": 105,
|
||||||
@ -1045,7 +1053,7 @@
|
|||||||
"name": "icon-packet",
|
"name": "icon-packet",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60174,
|
"code": 60174,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 126,
|
"order": 126,
|
||||||
@ -1053,7 +1061,7 @@
|
|||||||
"name": "icon-page",
|
"name": "icon-page",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60175,
|
"code": 60175,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 130,
|
"order": 130,
|
||||||
@ -1061,7 +1069,7 @@
|
|||||||
"name": "icon-plot-overlay",
|
"name": "icon-plot-overlay",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60176,
|
"code": 60176,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 80,
|
"order": 80,
|
||||||
@ -1069,7 +1077,7 @@
|
|||||||
"name": "icon-plot-stacked",
|
"name": "icon-plot-stacked",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60177,
|
"code": 60177,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 134,
|
"order": 134,
|
||||||
@ -1077,7 +1085,7 @@
|
|||||||
"name": "icon-session",
|
"name": "icon-session",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60178,
|
"code": 60178,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 109,
|
"order": 109,
|
||||||
@ -1085,7 +1093,7 @@
|
|||||||
"name": "icon-tabular",
|
"name": "icon-tabular",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60179,
|
"code": 60179,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 107,
|
"order": 107,
|
||||||
@ -1093,7 +1101,7 @@
|
|||||||
"name": "icon-tabular-lad",
|
"name": "icon-tabular-lad",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60180,
|
"code": 60180,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 106,
|
"order": 106,
|
||||||
@ -1101,7 +1109,7 @@
|
|||||||
"name": "icon-tabular-lad-set",
|
"name": "icon-tabular-lad-set",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60181,
|
"code": 60181,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 70,
|
"order": 70,
|
||||||
@ -1109,7 +1117,7 @@
|
|||||||
"name": "icon-tabular-realtime",
|
"name": "icon-tabular-realtime",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60182,
|
"code": 60182,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 60,
|
"order": 60,
|
||||||
@ -1117,7 +1125,7 @@
|
|||||||
"name": "icon-tabular-scrolling",
|
"name": "icon-tabular-scrolling",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60183,
|
"code": 60183,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 131,
|
"order": 131,
|
||||||
@ -1125,7 +1133,7 @@
|
|||||||
"name": "icon-telemetry",
|
"name": "icon-telemetry",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60184,
|
"code": 60184,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 202,
|
"order": 202,
|
||||||
@ -1133,7 +1141,7 @@
|
|||||||
"name": "icon-timeline",
|
"name": "icon-timeline",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60185,
|
"code": 60185,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 81,
|
"order": 81,
|
||||||
@ -1141,7 +1149,7 @@
|
|||||||
"name": "icon-timer",
|
"name": "icon-timer",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60186,
|
"code": 60186,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 69,
|
"order": 69,
|
||||||
@ -1149,7 +1157,7 @@
|
|||||||
"name": "icon-topic",
|
"name": "icon-topic",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60187,
|
"code": 60187,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 79,
|
"order": 79,
|
||||||
@ -1157,7 +1165,7 @@
|
|||||||
"name": "icon-box-with-dashed-lines-v2",
|
"name": "icon-box-with-dashed-lines-v2",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60188,
|
"code": 60188,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 90,
|
"order": 90,
|
||||||
@ -1165,7 +1173,7 @@
|
|||||||
"name": "icon-summary-widget",
|
"name": "icon-summary-widget",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60189,
|
"code": 60189,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 92,
|
"order": 92,
|
||||||
@ -1173,7 +1181,7 @@
|
|||||||
"name": "icon-notebook",
|
"name": "icon-notebook",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60190,
|
"code": 60190,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 168,
|
"order": 168,
|
||||||
@ -1181,7 +1189,7 @@
|
|||||||
"name": "icon-tabs-view",
|
"name": "icon-tabs-view",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60191,
|
"code": 60191,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 117,
|
"order": 117,
|
||||||
@ -1189,7 +1197,7 @@
|
|||||||
"name": "icon-flexible-layout",
|
"name": "icon-flexible-layout",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60192,
|
"code": 60192,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 166,
|
"order": 166,
|
||||||
@ -1197,7 +1205,7 @@
|
|||||||
"name": "icon-generator-sine",
|
"name": "icon-generator-sine",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60193,
|
"code": 60193,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 167,
|
"order": 167,
|
||||||
@ -1205,7 +1213,7 @@
|
|||||||
"name": "icon-generator-event",
|
"name": "icon-generator-event",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60194,
|
"code": 60194,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 165,
|
"order": 165,
|
||||||
@ -1213,7 +1221,7 @@
|
|||||||
"name": "icon-gauge-v2",
|
"name": "icon-gauge-v2",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60195,
|
"code": 60195,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 170,
|
"order": 170,
|
||||||
@ -1221,7 +1229,7 @@
|
|||||||
"name": "icon-spectra",
|
"name": "icon-spectra",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60196,
|
"code": 60196,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 171,
|
"order": 171,
|
||||||
@ -1229,7 +1237,7 @@
|
|||||||
"name": "icon-telemetry-spectra",
|
"name": "icon-telemetry-spectra",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60197,
|
"code": 60197,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 172,
|
"order": 172,
|
||||||
@ -1237,7 +1245,7 @@
|
|||||||
"name": "icon-pushbutton",
|
"name": "icon-pushbutton",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60198,
|
"code": 60198,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 174,
|
"order": 174,
|
||||||
@ -1245,7 +1253,7 @@
|
|||||||
"name": "icon-conditional",
|
"name": "icon-conditional",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60199,
|
"code": 60199,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 178,
|
"order": 178,
|
||||||
@ -1253,7 +1261,7 @@
|
|||||||
"name": "icon-condition-widget",
|
"name": "icon-condition-widget",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60200,
|
"code": 60200,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 180,
|
"order": 180,
|
||||||
@ -1261,7 +1269,7 @@
|
|||||||
"name": "icon-alphanumeric",
|
"name": "icon-alphanumeric",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60201,
|
"code": 60201,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 183,
|
"order": 183,
|
||||||
@ -1269,7 +1277,7 @@
|
|||||||
"name": "icon-image-telemetry",
|
"name": "icon-image-telemetry",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60202,
|
"code": 60202,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 198,
|
"order": 198,
|
||||||
@ -1277,7 +1285,7 @@
|
|||||||
"name": "icon-telemetry-aggregate",
|
"name": "icon-telemetry-aggregate",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60203,
|
"code": 60203,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 199,
|
"order": 199,
|
||||||
@ -1285,7 +1293,7 @@
|
|||||||
"name": "icon-bar-graph",
|
"name": "icon-bar-graph",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60204,
|
"code": 60204,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 200,
|
"order": 200,
|
||||||
@ -1293,7 +1301,7 @@
|
|||||||
"name": "icon-map",
|
"name": "icon-map",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60205,
|
"code": 60205,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 203,
|
"order": 203,
|
||||||
@ -1301,7 +1309,7 @@
|
|||||||
"name": "icon-plan",
|
"name": "icon-plan",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60206,
|
"code": 60206,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"order": 204,
|
"order": 204,
|
||||||
@ -1309,14 +1317,6 @@
|
|||||||
"name": "icon-timelist",
|
"name": "icon-timelist",
|
||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60207,
|
"code": 60207,
|
||||||
"tempChar": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"order": 214,
|
|
||||||
"id": 184,
|
|
||||||
"name": "icon-notebook-restricted",
|
|
||||||
"prevSize": 16,
|
|
||||||
"code": 60209,
|
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1326,6 +1326,14 @@
|
|||||||
"prevSize": 16,
|
"prevSize": 16,
|
||||||
"code": 60208,
|
"code": 60208,
|
||||||
"tempChar": ""
|
"tempChar": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"order": 214,
|
||||||
|
"id": 184,
|
||||||
|
"name": "icon-notebook-restricted",
|
||||||
|
"prevSize": 16,
|
||||||
|
"code": 60209,
|
||||||
|
"tempChar": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"id": 0,
|
"id": 0,
|
||||||
@ -2327,6 +2335,26 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": 186,
|
||||||
|
"paths": [
|
||||||
|
"M832 0h-640c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192h640c105.6 0 192-86.4 192-192v-640c0-105.6-86.4-192-192-192zM681.38 365.14c0.68-20.46-2.22-37.7-8.7-51.68-6.5-13.98-15.7-25.4-27.64-34.28-11.94-8.86-26.1-15.18-42.48-18.94-16.38-3.74-33.78-5.62-52.2-5.62-15.020 0-30.2 1.54-45.54 4.6s-29.16 8.18-41.44 15.36-22.18 16.56-29.68 28.14c-7.52 11.62-11.26 25.94-11.26 42.98s6.66 32.6 19.96 44.52c13.3 11.94 29.34 21.84 48.1 29.68 18.76 7.86 38.020 14 57.82 18.42 19.78 4.44 35.82 8.020 48.1 10.74 28.66 7.52 54.92 16.22 78.8 26.1 23.88 9.9 44.52 22.68 61.92 38.38s30.86 34.8 40.42 57.32c9.54 22.52 14.32 50.16 14.32 82.9 0 43.68-9.040 80.86-27.12 111.56s-41.28 55.62-69.6 74.7c-28.32 19.1-60.22 32.92-95.7 41.44s-70.62 12.8-105.42 12.8c-102.34 0-178.6-20.8-228.74-62.44-50.16-41.6-75.22-107.1-75.22-196.5h152.5c-1.38 25.94 1.7 47.58 9.22 64.98 7.5 17.4 18.42 31.22 32.74 41.44 14.32 10.24 31.38 17.58 51.18 22 19.78 4.44 41.28 6.66 64.48 6.66 16.38 0 32.74-2.040 49.12-6.14s31.22-10.24 44.52-18.42c13.3-8.18 24.22-18.76 32.76-31.72 8.52-12.94 12.8-28.66 12.8-47.080s-5.46-32.24-16.38-43.5c-10.92-11.26-25.080-20.98-42.48-29.16s-37.2-15.36-59.36-21.5c-22.18-6.14-44.52-12.62-67.040-19.44-23.2-6.82-45.72-15-67.54-24.56-21.84-9.54-41.44-21.82-58.84-36.84-17.4-15-31.38-33.42-41.96-55.26-10.58-21.82-15.86-48.44-15.86-79.82 0-40.94 8.52-75.74 25.58-104.4 17.040-28.66 39.22-52.020 66.52-70.1 27.28-18.080 58.16-31.38 92.62-39.92 34.44-8.52 69.42-12.8 104.9-12.8 37.52 0 72.82 4.26 105.92 12.8 33.080 8.54 62.080 22.36 87 41.44 24.9 19.1 44.68 43.5 59.36 73.18 14.66 29.68 22 65.68 22 107.98h-152.5z"
|
||||||
|
],
|
||||||
|
"attrs": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"isMulticolor": false,
|
||||||
|
"isMulticolor2": false,
|
||||||
|
"grid": 16,
|
||||||
|
"tags": [
|
||||||
|
"icon-stale"
|
||||||
|
],
|
||||||
|
"colorPermutations": {
|
||||||
|
"12552552551": [
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": 105,
|
"id": 105,
|
||||||
"paths": [
|
"paths": [
|
||||||
@ -4237,6 +4265,26 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": 185,
|
||||||
|
"paths": [
|
||||||
|
"M192 0c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192h640c105.6 0 192-86.4 192-192v-640c0-105.6-86.4-192-192-192zM128 352c0-53.019 42.981-96 96-96s96 42.981 96 96c0 53.019-42.981 96-96 96v0c-53.019 0-96-42.981-96-96v0zM288 832c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0zM544 640c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0zM544 320c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0zM800 832c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0z"
|
||||||
|
],
|
||||||
|
"attrs": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"isMulticolor": false,
|
||||||
|
"isMulticolor2": false,
|
||||||
|
"grid": 16,
|
||||||
|
"tags": [
|
||||||
|
"icon-plot-scatter"
|
||||||
|
],
|
||||||
|
"colorPermutations": {
|
||||||
|
"12552552551": [
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": 184,
|
"id": 184,
|
||||||
"paths": [
|
"paths": [
|
||||||
@ -4259,26 +4307,6 @@
|
|||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 185,
|
|
||||||
"paths": [
|
|
||||||
"M192 0c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192h640c105.6 0 192-86.4 192-192v-640c0-105.6-86.4-192-192-192zM128 352c0-53.019 42.981-96 96-96s96 42.981 96 96c0 53.019-42.981 96-96 96v0c-53.019 0-96-42.981-96-96v0zM288 832c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0zM544 640c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0zM544 320c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0zM800 832c-53.019 0-96-42.981-96-96s42.981-96 96-96c53.019 0 96 42.981 96 96v0c0 53.019-42.981 96-96 96v0z"
|
|
||||||
],
|
|
||||||
"attrs": [
|
|
||||||
{}
|
|
||||||
],
|
|
||||||
"isMulticolor": false,
|
|
||||||
"isMulticolor2": false,
|
|
||||||
"grid": 16,
|
|
||||||
"tags": [
|
|
||||||
"icon-plot-scatter"
|
|
||||||
],
|
|
||||||
"colorPermutations": {
|
|
||||||
"12552552551": [
|
|
||||||
{}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"invisible": false,
|
"invisible": false,
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
<glyph unicode="" glyph-name="icon-status-poll-circle-slash" d="M391.18 227.3c35.72-22.98 77.32-35.3 120.82-35.3 59.84 0 116.080 23.3 158.4 65.6 42.3 42.3 65.6 98.56 65.6 158.4 0 43.5-12.32 85.080-35.3 120.82l-309.52-309.52zM512 640c-59.84 0-116.080-23.3-158.4-65.6-42.3-42.3-65.6-98.56-65.6-158.4 0-43.5 12.32-85.080 35.3-120.82l309.52 309.52c-35.72 22.98-77.32 35.3-120.82 35.3zM512 896c-282.76 0-512-214.9-512-480 0-92.26 27.8-178.44 75.92-251.6l-75.92-292.4 313.5 101.42c61.040-24.1 128.12-37.42 198.5-37.42 282.76 0 512 214.9 512 480s-229.24 480-512 480zM512 96c-176.74 0-320 143.26-320 320s143.26 320 320 320 320-143.26 320-320-143.26-320-320-320z" />
|
<glyph unicode="" glyph-name="icon-status-poll-circle-slash" d="M391.18 227.3c35.72-22.98 77.32-35.3 120.82-35.3 59.84 0 116.080 23.3 158.4 65.6 42.3 42.3 65.6 98.56 65.6 158.4 0 43.5-12.32 85.080-35.3 120.82l-309.52-309.52zM512 640c-59.84 0-116.080-23.3-158.4-65.6-42.3-42.3-65.6-98.56-65.6-158.4 0-43.5 12.32-85.080 35.3-120.82l309.52 309.52c-35.72 22.98-77.32 35.3-120.82 35.3zM512 896c-282.76 0-512-214.9-512-480 0-92.26 27.8-178.44 75.92-251.6l-75.92-292.4 313.5 101.42c61.040-24.1 128.12-37.42 198.5-37.42 282.76 0 512 214.9 512 480s-229.24 480-512 480zM512 96c-176.74 0-320 143.26-320 320s143.26 320 320 320 320-143.26 320-320-143.26-320-320-320z" />
|
||||||
<glyph unicode="" glyph-name="icon-status-poll-question-mark" d="M512 896c-282.76 0-512-214.9-512-480 0-92.26 27.8-178.44 75.92-251.6l-75.92-292.4 313.5 101.42c61.040-24.1 128.12-37.42 198.5-37.42 282.76 0 512 214.9 512 480s-229.24 480-512 480zM579.020 64h-141.36v136.64h141.36v-136.64zM713.84 462.1c-11.94-17.020-34.9-38.78-68.84-65.24l-33.48-26c-18.24-14.18-30.34-30.74-36.32-49.64-3.78-11.98-5.82-30.58-6.14-55.8h-128.12c1.88 53.26 6.92 90.060 15.080 110.4 8.18 20.34 29.22 43.74 63.16 70.22l34.42 26.94c11.3 8.52 20.42 17.8 27.34 27.9 12.56 17.34 18.86 36.4 18.86 57.2 0 23.94-7 45.78-20.98 65.48-14 19.7-39.54 29.54-76.64 29.54s-62.34-12.14-77.6-36.4c-15.24-24.28-22.88-49.48-22.88-75.64h-136.64c3.78 89.84 35.14 153.5 94.080 191.020 37.18 23.94 82.9 35.94 137.12 35.94 71.22 0 130.42-17.020 177.54-51.060s70.68-84.48 70.68-151.3c0-40.98-10.22-75.5-30.66-103.54z" />
|
<glyph unicode="" glyph-name="icon-status-poll-question-mark" d="M512 896c-282.76 0-512-214.9-512-480 0-92.26 27.8-178.44 75.92-251.6l-75.92-292.4 313.5 101.42c61.040-24.1 128.12-37.42 198.5-37.42 282.76 0 512 214.9 512 480s-229.24 480-512 480zM579.020 64h-141.36v136.64h141.36v-136.64zM713.84 462.1c-11.94-17.020-34.9-38.78-68.84-65.24l-33.48-26c-18.24-14.18-30.34-30.74-36.32-49.64-3.78-11.98-5.82-30.58-6.14-55.8h-128.12c1.88 53.26 6.92 90.060 15.080 110.4 8.18 20.34 29.22 43.74 63.16 70.22l34.42 26.94c11.3 8.52 20.42 17.8 27.34 27.9 12.56 17.34 18.86 36.4 18.86 57.2 0 23.94-7 45.78-20.98 65.48-14 19.7-39.54 29.54-76.64 29.54s-62.34-12.14-77.6-36.4c-15.24-24.28-22.88-49.48-22.88-75.64h-136.64c3.78 89.84 35.14 153.5 94.080 191.020 37.18 23.94 82.9 35.94 137.12 35.94 71.22 0 130.42-17.020 177.54-51.060s70.68-84.48 70.68-151.3c0-40.98-10.22-75.5-30.66-103.54z" />
|
||||||
<glyph unicode="" glyph-name="icon-status-poll-edit" d="M1000.080 561.36l-336.6-336.76-20.52-6.88-450.96-153.72 160.68 471.52 332.34 332.34c-54.040 18.2-112.28 28.14-173.020 28.14-282.76 0-512-214.9-512-480 0-92.26 27.8-178.44 75.92-251.6l-75.92-292.4 313.5 101.42c61.040-24.1 128.12-37.42 198.5-37.42 282.76 0 512 214.9 512 480 0 50.68-8.4 99.5-23.92 145.36zM408.42 500.76l-2.16-6.3-111.7-327.9 334.12 113.86 4.62 4.68 350.28 350.28c6.8 6.78 14.96 19.1 14.96 38.9 0 34.86-26.82 83.28-69.88 126.38-26.54 26.54-55.9 47.6-82.7 59.34-47.34 20.8-72.020 6.24-82.64-4.36l-354.9-354.88zM470.56 474.58h44v-88h88v-44l-4.7-12.72-139.68-47.54-47.94 47.94 47.6 139.72 12.72 4.6z" />
|
<glyph unicode="" glyph-name="icon-status-poll-edit" d="M1000.080 561.36l-336.6-336.76-20.52-6.88-450.96-153.72 160.68 471.52 332.34 332.34c-54.040 18.2-112.28 28.14-173.020 28.14-282.76 0-512-214.9-512-480 0-92.26 27.8-178.44 75.92-251.6l-75.92-292.4 313.5 101.42c61.040-24.1 128.12-37.42 198.5-37.42 282.76 0 512 214.9 512 480 0 50.68-8.4 99.5-23.92 145.36zM408.42 500.76l-2.16-6.3-111.7-327.9 334.12 113.86 4.62 4.68 350.28 350.28c6.8 6.78 14.96 19.1 14.96 38.9 0 34.86-26.82 83.28-69.88 126.38-26.54 26.54-55.9 47.6-82.7 59.34-47.34 20.8-72.020 6.24-82.64-4.36l-354.9-354.88zM470.56 474.58h44v-88h88v-44l-4.7-12.72-139.68-47.54-47.94 47.94 47.6 139.72 12.72 4.6z" />
|
||||||
|
<glyph unicode="" glyph-name="icon-stale" d="M832 896h-640c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM681.38 530.86c0.68 20.46-2.22 37.7-8.7 51.68-6.5 13.98-15.7 25.4-27.64 34.28-11.94 8.86-26.1 15.18-42.48 18.94-16.38 3.74-33.78 5.62-52.2 5.62-15.020 0-30.2-1.54-45.54-4.6s-29.16-8.18-41.44-15.36-22.18-16.56-29.68-28.14c-7.52-11.62-11.26-25.94-11.26-42.98s6.66-32.6 19.96-44.52c13.3-11.94 29.34-21.84 48.1-29.68 18.76-7.86 38.020-14 57.82-18.42 19.78-4.44 35.82-8.020 48.1-10.74 28.66-7.52 54.92-16.22 78.8-26.1 23.88-9.9 44.52-22.68 61.92-38.38s30.86-34.8 40.42-57.32c9.54-22.52 14.32-50.16 14.32-82.9 0-43.68-9.040-80.86-27.12-111.56s-41.28-55.62-69.6-74.7c-28.32-19.1-60.22-32.92-95.7-41.44s-70.62-12.8-105.42-12.8c-102.34 0-178.6 20.8-228.74 62.44-50.16 41.6-75.22 107.1-75.22 196.5h152.5c-1.38-25.94 1.7-47.58 9.22-64.98 7.5-17.4 18.42-31.22 32.74-41.44 14.32-10.24 31.38-17.58 51.18-22 19.78-4.44 41.28-6.66 64.48-6.66 16.38 0 32.74 2.040 49.12 6.14s31.22 10.24 44.52 18.42c13.3 8.18 24.22 18.76 32.76 31.72 8.52 12.94 12.8 28.66 12.8 47.080s-5.46 32.24-16.38 43.5c-10.92 11.26-25.080 20.98-42.48 29.16s-37.2 15.36-59.36 21.5c-22.18 6.14-44.52 12.62-67.040 19.44-23.2 6.82-45.72 15-67.54 24.56-21.84 9.54-41.44 21.82-58.84 36.84-17.4 15-31.38 33.42-41.96 55.26-10.58 21.82-15.86 48.44-15.86 79.82 0 40.94 8.52 75.74 25.58 104.4 17.040 28.66 39.22 52.020 66.52 70.1 27.28 18.080 58.16 31.38 92.62 39.92 34.44 8.52 69.42 12.8 104.9 12.8 37.52 0 72.82-4.26 105.92-12.8 33.080-8.54 62.080-22.36 87-41.44 24.9-19.1 44.68-43.5 59.36-73.18 14.66-29.68 22-65.68 22-107.98h-152.5z" />
|
||||||
<glyph unicode="" glyph-name="icon-arrows-right-left" d="M1024 384l-448-512v1024zM448 896l-448-512 448-512z" />
|
<glyph unicode="" glyph-name="icon-arrows-right-left" d="M1024 384l-448-512v1024zM448 896l-448-512 448-512z" />
|
||||||
<glyph unicode="" glyph-name="icon-arrows-up-down" d="M512 896l512-448h-1024zM0 320l512-448 512 448z" />
|
<glyph unicode="" glyph-name="icon-arrows-up-down" d="M512 896l512-448h-1024zM0 320l512-448 512 448z" />
|
||||||
<glyph unicode="" glyph-name="icon-bullet" d="M832 144c0-44-36-80-80-80h-480c-44 0-80 36-80 80v480c0 44 36 80 80 80h480c44 0 80-36 80-80v-480z" />
|
<glyph unicode="" glyph-name="icon-bullet" d="M832 144c0-44-36-80-80-80h-480c-44 0-80 36-80 80v480c0 44 36 80 80 80h480c44 0 80-36 80-80v-480z" />
|
||||||
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 70 KiB |
Binary file not shown.
Binary file not shown.
@ -14,7 +14,7 @@
|
|||||||
<div
|
<div
|
||||||
ref="objectViewWrapper"
|
ref="objectViewWrapper"
|
||||||
class="c-object-view"
|
class="c-object-view"
|
||||||
:class="objectTypeClass"
|
:class="viewClasses"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -24,6 +24,7 @@ import _ from "lodash";
|
|||||||
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
|
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
|
||||||
import {STYLE_CONSTANTS} from "@/plugins/condition/utils/constants";
|
import {STYLE_CONSTANTS} from "@/plugins/condition/utils/constants";
|
||||||
import IndependentTimeConductor from '@/plugins/timeConductor/independent/IndependentTimeConductor.vue';
|
import IndependentTimeConductor from '@/plugins/timeConductor/independent/IndependentTimeConductor.vue';
|
||||||
|
import stalenessMixin from '@/ui/mixins/staleness-mixin';
|
||||||
|
|
||||||
const SupportedViewTypes = [
|
const SupportedViewTypes = [
|
||||||
'plot-stacked',
|
'plot-stacked',
|
||||||
@ -36,6 +37,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
IndependentTimeConductor
|
IndependentTimeConductor
|
||||||
},
|
},
|
||||||
|
mixins: [stalenessMixin],
|
||||||
inject: ["openmct"],
|
inject: ["openmct"],
|
||||||
props: {
|
props: {
|
||||||
showEditView: Boolean,
|
showEditView: Boolean,
|
||||||
@ -85,8 +87,14 @@ export default {
|
|||||||
|
|
||||||
return this.domainObject && SupportedViewTypes.includes(viewKey);
|
return this.domainObject && SupportedViewTypes.includes(viewKey);
|
||||||
},
|
},
|
||||||
objectTypeClass() {
|
viewClasses() {
|
||||||
return this.domainObject && ('is-object-type-' + this.domainObject.type);
|
let classes;
|
||||||
|
|
||||||
|
if (this.domainObject) {
|
||||||
|
classes = `is-object-type-${this.domainObject.type} ${this.isStale ? 'is-stale' : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
@ -128,6 +136,7 @@ export default {
|
|||||||
if (this.domainObject) {
|
if (this.domainObject) {
|
||||||
//This is to apply styles to subobjects in a layout
|
//This is to apply styles to subobjects in a layout
|
||||||
this.initObjectStyles();
|
this.initObjectStyles();
|
||||||
|
this.triggerStalenessSubscribe(this.domainObject);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -161,6 +170,9 @@ export default {
|
|||||||
this.composition._destroy();
|
this.composition._destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isStale = false;
|
||||||
|
this.triggerUnsubscribeFromStaleness();
|
||||||
|
|
||||||
this.openmct.objectViews.off('clearData', this.clearData);
|
this.openmct.objectViews.off('clearData', this.clearData);
|
||||||
},
|
},
|
||||||
getStyleReceiver() {
|
getStyleReceiver() {
|
||||||
@ -192,6 +204,11 @@ export default {
|
|||||||
this.clear();
|
this.clear();
|
||||||
this.updateView(true);
|
this.updateView(true);
|
||||||
},
|
},
|
||||||
|
triggerStalenessSubscribe(object) {
|
||||||
|
if (this.openmct.telemetry.isTelemetryObject(object)) {
|
||||||
|
this.subscribeToStaleness(object);
|
||||||
|
}
|
||||||
|
},
|
||||||
updateStyle(styleObj) {
|
updateStyle(styleObj) {
|
||||||
let elemToStyle = this.getStyleReceiver();
|
let elemToStyle = this.getStyleReceiver();
|
||||||
|
|
||||||
@ -306,6 +323,7 @@ export default {
|
|||||||
|
|
||||||
this.updateView(immediatelySelect);
|
this.updateView(immediatelySelect);
|
||||||
|
|
||||||
|
this.triggerStalenessSubscribe(this.domainObject);
|
||||||
this.initObjectStyles();
|
this.initObjectStyles();
|
||||||
},
|
},
|
||||||
initObjectStyles() {
|
initObjectStyles() {
|
||||||
|
@ -320,6 +320,10 @@
|
|||||||
display: block;
|
display: block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
|
&.is-stale {
|
||||||
|
@include isStaleHolder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-editing {
|
.is-editing {
|
||||||
|
68
src/ui/mixins/staleness-mixin.js
Normal file
68
src/ui/mixins/staleness-mixin.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import StalenessUtils from '@/utils/staleness';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isStale: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.triggerUnsubscribeFromStaleness();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
subscribeToStaleness(domainObject, callback) {
|
||||||
|
if (!this.stalenessUtils) {
|
||||||
|
this.stalenessUtils = new StalenessUtils(this.openmct, domainObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.requestStaleness(domainObject);
|
||||||
|
this.unsubscribeFromStaleness = this.openmct.telemetry.subscribeToStaleness(domainObject, (stalenessResponse) => {
|
||||||
|
this.handleStalenessResponse(stalenessResponse, callback);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async requestStaleness(domainObject) {
|
||||||
|
const stalenessResponse = await this.openmct.telemetry.isStale(domainObject);
|
||||||
|
if (stalenessResponse !== undefined) {
|
||||||
|
this.handleStalenessResponse(stalenessResponse);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleStalenessResponse(stalenessResponse, callback) {
|
||||||
|
if (this.stalenessUtils.shouldUpdateStaleness(stalenessResponse)) {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback(stalenessResponse.isStale);
|
||||||
|
} else {
|
||||||
|
this.isStale = stalenessResponse.isStale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
triggerUnsubscribeFromStaleness() {
|
||||||
|
if (this.unsubscribeFromStaleness) {
|
||||||
|
this.unsubscribeFromStaleness();
|
||||||
|
delete this.unsubscribeFromStaleness;
|
||||||
|
this.stalenessUtils.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
76
src/utils/staleness.js
Normal file
76
src/utils/staleness.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2022, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
export default class StalenessUtils {
|
||||||
|
constructor(openmct, domainObject) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.metadata = this.openmct.telemetry.getMetadata(domainObject);
|
||||||
|
this.lastStalenessResponseTime = 0;
|
||||||
|
|
||||||
|
this.setTimeSystem(this.openmct.time.timeSystem());
|
||||||
|
this.watchTimeSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldUpdateStaleness(stalenessResponse, id) {
|
||||||
|
const stalenessResponseTime = this.parseTime(stalenessResponse);
|
||||||
|
|
||||||
|
if (stalenessResponseTime > this.lastStalenessResponseTime) {
|
||||||
|
this.lastStalenessResponseTime = stalenessResponseTime;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watchTimeSystem() {
|
||||||
|
this.openmct.time.on('timeSystem', this.setTimeSystem, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
unwatchTimeSystem() {
|
||||||
|
this.openmct.time.off('timeSystem', this.setTimeSystem, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeSystem(timeSystem) {
|
||||||
|
let metadataValue = { format: timeSystem.key };
|
||||||
|
|
||||||
|
if (this.metadata) {
|
||||||
|
metadataValue = this.metadata.value(timeSystem.key) ?? metadataValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueFormatter = this.openmct.telemetry.getValueFormatter(metadataValue);
|
||||||
|
|
||||||
|
this.parseTime = (stalenessResponse) => {
|
||||||
|
const stalenessDatum = {
|
||||||
|
...stalenessResponse,
|
||||||
|
source: stalenessResponse[timeSystem.key]
|
||||||
|
};
|
||||||
|
|
||||||
|
return valueFormatter.parse(stalenessDatum);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.unwatchTimeSystem();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user