mirror of
https://github.com/nasa/openmct.git
synced 2025-06-24 18:25:19 +00:00
Compare commits
22 Commits
master
...
omm-r5.2.0
Author | SHA1 | Date | |
---|---|---|---|
3d2c9b8787 | |||
3b28dd6238 | |||
cbf52eb7d5 | |||
d65821ca81 | |||
798eb4444d | |||
59ae7cddc5 | |||
321c7a3af5 | |||
609cf72bd1 | |||
a447b0ada8 | |||
5788f4cc69 | |||
f94b4e53c7 | |||
faf71f1e67 | |||
23310f85ae | |||
d80819634b | |||
483b62c152 | |||
1254279635 | |||
c768a71656 | |||
678a92bd29 | |||
34b488944a | |||
4d1dd2f51d | |||
080f7b8f4b | |||
483f2feac8 |
@ -239,9 +239,15 @@ export default class ObjectAPI {
|
||||
|
||||
return domainObject;
|
||||
}).catch((error) => {
|
||||
console.warn(`Failed to retrieve ${keystring}:`, error);
|
||||
let result;
|
||||
|
||||
delete this.cache[keystring];
|
||||
const result = this.applyGetInterceptors(identifier);
|
||||
|
||||
// suppress abort errors
|
||||
if (error.name !== 'AbortError') {
|
||||
console.warn(`Failed to retrieve ${keystring}:`, error);
|
||||
result = this.applyGetInterceptors(identifier);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
@ -55,6 +55,13 @@ define([
|
||||
*/
|
||||
function parseKeyString(keyString) {
|
||||
if (isIdentifier(keyString)) {
|
||||
// TODO REMOVE FOR OMM-RELEASE-5.0
|
||||
if (!keyString.namespace && keyString.key.includes(':')) {
|
||||
console.warn(`smushed key: ${keyString.key}`);
|
||||
|
||||
return parseKeyString(keyString.key);
|
||||
}
|
||||
|
||||
return keyString;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ export default class TelemetryAPI {
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
*/
|
||||
canProvideTelemetry(domainObject) {
|
||||
return Boolean(this.#findSubscriptionProvider(domainObject))
|
||||
return Boolean(this.findSubscriptionProvider(domainObject))
|
||||
|| Boolean(this.findRequestProvider(domainObject));
|
||||
}
|
||||
|
||||
@ -123,9 +123,10 @@ export default class TelemetryAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns a telemetry subscription provider that supports
|
||||
* a given domain object and options.
|
||||
*/
|
||||
#findSubscriptionProvider() {
|
||||
findSubscriptionProvider() {
|
||||
const args = Array.prototype.slice.apply(arguments);
|
||||
function supportsDomainObject(provider) {
|
||||
return provider.supportsSubscribe.apply(provider, args);
|
||||
@ -348,7 +349,7 @@ export default class TelemetryAPI {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
const provider = this.#findSubscriptionProvider(domainObject);
|
||||
const provider = this.findSubscriptionProvider(domainObject);
|
||||
|
||||
if (!this.subscribeCache) {
|
||||
this.subscribeCache = {};
|
||||
|
@ -21,16 +21,18 @@
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="urlDefined ? 'a' : 'span'"
|
||||
<div
|
||||
ref="conditionWidgetElement"
|
||||
class="c-condition-widget u-style-receiver js-style-receiver"
|
||||
:href="url"
|
||||
:target="url ? '_BLANK' : ''"
|
||||
>
|
||||
<div class="c-condition-widget__label">
|
||||
{{ label }}
|
||||
</div>
|
||||
</component>
|
||||
<component
|
||||
:is="urlDefined ? 'a' : 'div'"
|
||||
class="c-condition-widget__label-wrapper"
|
||||
:href="url"
|
||||
>
|
||||
<div class="c-condition-widget__label">{{ label }}</div>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -40,19 +42,26 @@ export default {
|
||||
inject: ['openmct', 'domainObject'],
|
||||
data: function () {
|
||||
return {
|
||||
conditionalLabel: '',
|
||||
conditionSetIdentifier: null,
|
||||
domainObjectLabel: '',
|
||||
url: null,
|
||||
urlDefined: false,
|
||||
useConditionSetOutputAsLabel: false
|
||||
conditionalLabel: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
urlDefined() {
|
||||
return this.domainObject.url?.length > 0;
|
||||
},
|
||||
url() {
|
||||
return this.urlDefined ? sanitizeUrl(this.domainObject.url) : null;
|
||||
},
|
||||
useConditionSetOutputAsLabel() {
|
||||
return this.conditionSetIdentifier && this.domainObject.configuration.useConditionSetOutputAsLabel;
|
||||
},
|
||||
conditionSetIdentifier() {
|
||||
return this.domainObject.configuration?.objectStyles?.conditionSetIdentifier;
|
||||
},
|
||||
label() {
|
||||
return this.useConditionSetOutputAsLabel
|
||||
? this.conditionalLabel
|
||||
: this.domainObjectLabel
|
||||
: this.domainObject.label
|
||||
;
|
||||
}
|
||||
},
|
||||
@ -69,20 +78,11 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.unlisten = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject);
|
||||
|
||||
if (this.domainObject) {
|
||||
this.updateDomainObject(this.domainObject);
|
||||
this.listenToConditionSetChanges();
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.conditionSetIdentifier = null;
|
||||
|
||||
if (this.unlisten) {
|
||||
this.unlisten();
|
||||
}
|
||||
|
||||
this.stopListeningToConditionSetChanges();
|
||||
},
|
||||
methods: {
|
||||
@ -121,31 +121,6 @@ export default {
|
||||
}
|
||||
|
||||
this.conditionalLabel = latestDatum.output || '';
|
||||
},
|
||||
updateDomainObject(domainObject) {
|
||||
if (this.domainObjectLabel !== domainObject.label) {
|
||||
this.domainObjectLabel = domainObject.label;
|
||||
}
|
||||
|
||||
const urlDefined = domainObject.url && domainObject.url.length > 0;
|
||||
if (this.urlDefined !== urlDefined) {
|
||||
this.urlDefined = urlDefined;
|
||||
}
|
||||
|
||||
const url = this.urlDefined ? sanitizeUrl(domainObject.url) : null;
|
||||
if (this.url !== url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
const conditionSetIdentifier = domainObject.configuration?.objectStyles?.conditionSetIdentifier;
|
||||
if (conditionSetIdentifier && this.conditionSetIdentifier !== conditionSetIdentifier) {
|
||||
this.conditionSetIdentifier = conditionSetIdentifier;
|
||||
}
|
||||
|
||||
const useConditionSetOutputAsLabel = this.conditionSetIdentifier && domainObject.configuration.useConditionSetOutputAsLabel;
|
||||
if (this.useConditionSetOutputAsLabel !== useConditionSetOutputAsLabel) {
|
||||
this.useConditionSetOutputAsLabel = useConditionSetOutputAsLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -26,31 +26,35 @@
|
||||
background-color: rgba($colorBodyFg, 0.1); // Give a little presence if the user hasn't defined a fill color
|
||||
border-radius: $basicCr;
|
||||
border: 1px solid transparent;
|
||||
display: inline-block;
|
||||
padding: $interiorMarginLg $interiorMarginLg * 2;
|
||||
display: block;
|
||||
max-width: max-content;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.c-condition-widget__label {
|
||||
padding: $interiorMargin;
|
||||
// Either a <div> or an <a> tag
|
||||
padding: $interiorMargin $interiorMargin * 1.5;
|
||||
text-align: center;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
a.c-condition-widget {
|
||||
// Widget is conditionally made into a <a> when URL property has been defined
|
||||
cursor: pointer !important;
|
||||
pointer-events: inherit;
|
||||
}
|
||||
|
||||
// Make Condition Widget expand when in a hidden frame Layout context
|
||||
// For both static and Flexible Layouts
|
||||
.c-so-view--conditionWidget.c-so-view--no-frame {
|
||||
.c-condition-widget {
|
||||
@include abs();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
max-width: unset;
|
||||
|
||||
&__label-wrapper {
|
||||
@include abs();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.c-so-view__frame-controls { display: none; }
|
||||
|
@ -36,6 +36,7 @@ export default function plugin() {
|
||||
domainObject.configuration = {};
|
||||
domainObject.label = 'Condition Widget';
|
||||
domainObject.conditionalLabel = '';
|
||||
domainObject.url = '';
|
||||
},
|
||||
form: [
|
||||
{
|
||||
|
@ -20,8 +20,6 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import JSONExporter from '/src/exporters/JSONExporter.js';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
export default class ExportAsJSONAction {
|
||||
@ -35,10 +33,9 @@ export default class ExportAsJSONAction {
|
||||
this.group = "json";
|
||||
this.priority = 1;
|
||||
|
||||
this.externalIdentifiers = [];
|
||||
this.tree = {};
|
||||
this.calls = 0;
|
||||
this.idMap = {};
|
||||
this.tree = null;
|
||||
this.calls = null;
|
||||
this.idMap = null;
|
||||
|
||||
this.JSONExportService = new JSONExporter();
|
||||
}
|
||||
@ -60,21 +57,164 @@ export default class ExportAsJSONAction {
|
||||
*/
|
||||
invoke(objectpath) {
|
||||
this.tree = {};
|
||||
this.calls = 0;
|
||||
this.idMap = {};
|
||||
|
||||
const root = objectpath[0];
|
||||
this.root = JSON.parse(JSON.stringify(root));
|
||||
const rootId = this._getId(this.root);
|
||||
this.root = this._copy(root);
|
||||
|
||||
const rootId = this._getKeystring(this.root);
|
||||
this.tree[rootId] = this.root;
|
||||
|
||||
this._write(this.root);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} parent
|
||||
*/
|
||||
async _write(parent) {
|
||||
this.calls++;
|
||||
|
||||
//conditional object styles are not saved on the composition, so we need to check for them
|
||||
const conditionSetIdentifier = this._getConditionSetIdentifier(parent);
|
||||
const hasItemConditionSetIdentifiers = this._hasItemConditionSetIdentifiers(parent);
|
||||
const composition = this.openmct.composition.get(parent);
|
||||
|
||||
if (composition) {
|
||||
const children = await composition.load();
|
||||
|
||||
children.forEach((child) => {
|
||||
this._exportObject(child, parent);
|
||||
});
|
||||
}
|
||||
|
||||
if (!conditionSetIdentifier && !hasItemConditionSetIdentifiers) {
|
||||
this._decrementCallsAndSave();
|
||||
} else {
|
||||
const conditionSetObjects = [];
|
||||
|
||||
// conditionSetIdentifiers directly in objectStyles object
|
||||
if (conditionSetIdentifier) {
|
||||
conditionSetObjects.push(await this.openmct.objects.get(conditionSetIdentifier));
|
||||
}
|
||||
|
||||
// conditionSetIdentifiers stored on item ids in the objectStyles object
|
||||
if (hasItemConditionSetIdentifiers) {
|
||||
const itemConditionSetIdentifiers = this._getItemConditionSetIdentifiers(parent);
|
||||
|
||||
for (const itemConditionSetIdentifier of itemConditionSetIdentifiers) {
|
||||
conditionSetObjects.push(await this.openmct.objects.get(itemConditionSetIdentifier));
|
||||
}
|
||||
}
|
||||
|
||||
for (const conditionSetObject of conditionSetObjects) {
|
||||
this._exportObject(conditionSetObject, parent);
|
||||
}
|
||||
|
||||
this._decrementCallsAndSave();
|
||||
}
|
||||
}
|
||||
|
||||
_exportObject(child, parent) {
|
||||
const originalKeyString = this._getKeystring(child);
|
||||
const createable = this._isCreatableAndPersistable(child);
|
||||
const isNotInfinite = !Object.prototype.hasOwnProperty.call(this.tree, originalKeyString);
|
||||
|
||||
if (createable && isNotInfinite) {
|
||||
// for external or linked objects we generate new keys, if they don't exist already
|
||||
if (this._isLinkedObject(child, parent)) {
|
||||
child = this._rewriteLink(child, parent);
|
||||
} else {
|
||||
this.tree[originalKeyString] = child;
|
||||
}
|
||||
|
||||
this._write(child);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} child
|
||||
* @param {object} parent
|
||||
* @returns {object}
|
||||
*/
|
||||
_rewriteLink(child, parent) {
|
||||
const originalKeyString = this._getKeystring(child);
|
||||
const parentKeyString = this._getKeystring(parent);
|
||||
const conditionSetIdentifier = this._getConditionSetIdentifier(parent);
|
||||
const hasItemConditionSetIdentifiers = this._hasItemConditionSetIdentifiers(parent);
|
||||
const existingMappedKeyString = this.idMap[originalKeyString];
|
||||
let copy;
|
||||
|
||||
if (!existingMappedKeyString) {
|
||||
copy = this._copy(child);
|
||||
copy.identifier.key = uuid();
|
||||
|
||||
if (!conditionSetIdentifier && !hasItemConditionSetIdentifiers) {
|
||||
copy.location = parentKeyString;
|
||||
}
|
||||
|
||||
let newKeyString = this._getKeystring(copy);
|
||||
this.idMap[originalKeyString] = newKeyString;
|
||||
this.tree[newKeyString] = copy;
|
||||
} else {
|
||||
copy = this.tree[existingMappedKeyString];
|
||||
}
|
||||
|
||||
if (conditionSetIdentifier || hasItemConditionSetIdentifiers) {
|
||||
|
||||
// update objectStyle object
|
||||
if (conditionSetIdentifier) {
|
||||
const directObjectStylesIdentifier = this.openmct.objects.areIdsEqual(
|
||||
parent.configuration.objectStyles.conditionSetIdentifier,
|
||||
child.identifier
|
||||
);
|
||||
|
||||
if (directObjectStylesIdentifier) {
|
||||
parent.configuration.objectStyles.conditionSetIdentifier = copy.identifier;
|
||||
this.tree[parentKeyString].configuration.objectStyles.conditionSetIdentifier = copy.identifier;
|
||||
}
|
||||
}
|
||||
|
||||
// update per item id on objectStyle object
|
||||
if (hasItemConditionSetIdentifiers) {
|
||||
for (const itemId in parent.configuration.objectStyles) {
|
||||
if (parent.configuration.objectStyles[itemId]) {
|
||||
const itemConditionSetIdentifier = parent.configuration.objectStyles[itemId].conditionSetIdentifier;
|
||||
|
||||
if (
|
||||
itemConditionSetIdentifier
|
||||
&& this.openmct.objects.areIdsEqual(itemConditionSetIdentifier, child.identifier)
|
||||
) {
|
||||
parent.configuration.objectStyles[itemId].conditionSetIdentifier = copy.identifier;
|
||||
this.tree[parentKeyString].configuration.objectStyles[itemId].conditionSetIdentifier = copy.identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// just update parent
|
||||
const index = parent.composition.findIndex(identifier => {
|
||||
return this.openmct.objects.areIdsEqual(child.identifier, identifier);
|
||||
});
|
||||
|
||||
parent.composition[index] = copy.identifier;
|
||||
this.tree[parentKeyString].composition[index] = copy.identifier;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} domainObject
|
||||
* @returns {string} A string representation of the given identifier, including namespace and key
|
||||
*/
|
||||
_getId(domainObject) {
|
||||
_getKeystring(domainObject) {
|
||||
return this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} domainObject
|
||||
@ -86,6 +226,7 @@ export default class ExportAsJSONAction {
|
||||
|
||||
return type && type.definition.creatable && isPersistable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} child
|
||||
@ -93,74 +234,80 @@ export default class ExportAsJSONAction {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_isLinkedObject(child, parent) {
|
||||
if (child.location !== this._getId(parent)
|
||||
&& !Object.keys(this.tree).includes(child.location)
|
||||
&& this._getId(child) !== this._getId(this.root)
|
||||
|| this.externalIdentifiers.includes(this._getId(child))) {
|
||||
const rootKeyString = this._getKeystring(this.root);
|
||||
const childKeyString = this._getKeystring(child);
|
||||
const parentKeyString = this._getKeystring(parent);
|
||||
|
||||
return true;
|
||||
return (child.location !== parentKeyString
|
||||
&& !Object.keys(this.tree).includes(child.location)
|
||||
&& childKeyString !== rootKeyString)
|
||||
|| this.idMap[childKeyString] !== undefined;
|
||||
}
|
||||
|
||||
_getConditionSetIdentifier(object) {
|
||||
return object.configuration?.objectStyles?.conditionSetIdentifier;
|
||||
}
|
||||
|
||||
_hasItemConditionSetIdentifiers(parent) {
|
||||
const objectStyles = parent.configuration?.objectStyles;
|
||||
|
||||
for (const itemId in objectStyles) {
|
||||
if (Object.prototype.hasOwnProperty.call(objectStyles[itemId], 'conditionSetIdentifier')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
* @param {object} child
|
||||
* @param {object} parent
|
||||
* @returns {object}
|
||||
*/
|
||||
_rewriteLink(child, parent) {
|
||||
this.externalIdentifiers.push(this._getId(child));
|
||||
const index = parent.composition.findIndex(id => {
|
||||
return _.isEqual(child.identifier, id);
|
||||
});
|
||||
const copyOfChild = JSON.parse(JSON.stringify(child));
|
||||
|
||||
copyOfChild.identifier.key = uuid();
|
||||
const newIdString = this._getId(copyOfChild);
|
||||
const parentId = this._getId(parent);
|
||||
_getItemConditionSetIdentifiers(parent) {
|
||||
const objectStyles = parent.configuration?.objectStyles;
|
||||
let identifiers = new Set();
|
||||
|
||||
this.idMap[this._getId(child)] = newIdString;
|
||||
copyOfChild.location = parentId;
|
||||
parent.composition[index] = copyOfChild.identifier;
|
||||
this.tree[newIdString] = copyOfChild;
|
||||
this.tree[parentId].composition[index] = copyOfChild.identifier;
|
||||
if (objectStyles) {
|
||||
Object.keys(objectStyles).forEach(itemId => {
|
||||
if (objectStyles[itemId].conditionSetIdentifier) {
|
||||
identifiers.add(objectStyles[itemId].conditionSetIdentifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return copyOfChild;
|
||||
return Array.from(identifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} child
|
||||
* @param {object} parent
|
||||
* @returns {object}
|
||||
*/
|
||||
_rewriteLinkForReference(child, parent) {
|
||||
const childId = this._getId(child);
|
||||
this.externalIdentifiers.push(childId);
|
||||
const copyOfChild = JSON.parse(JSON.stringify(child));
|
||||
|
||||
copyOfChild.identifier.key = uuid();
|
||||
const newIdString = this._getId(copyOfChild);
|
||||
const parentId = this._getId(parent);
|
||||
|
||||
this.idMap[childId] = newIdString;
|
||||
copyOfChild.location = null;
|
||||
parent.configuration.objectStyles.conditionSetIdentifier = copyOfChild.identifier;
|
||||
this.tree[newIdString] = copyOfChild;
|
||||
this.tree[parentId].configuration.objectStyles.conditionSetIdentifier = copyOfChild.identifier;
|
||||
|
||||
return copyOfChild;
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_rewriteReferences() {
|
||||
const oldKeyStrings = Object.keys(this.idMap);
|
||||
let treeString = JSON.stringify(this.tree);
|
||||
Object.keys(this.idMap).forEach(function (oldId) {
|
||||
const newId = this.idMap[oldId];
|
||||
treeString = treeString.split(oldId).join(newId);
|
||||
}.bind(this));
|
||||
|
||||
oldKeyStrings.forEach((oldKeyString) => {
|
||||
// this will cover keyStrings, identifiers and identifiers created
|
||||
// by hand that may be structured differently from those created with 'makeKeyString'
|
||||
const newKeyString = this.idMap[oldKeyString];
|
||||
const newIdentifier = JSON.stringify(this.openmct.objects.parseKeyString(newKeyString));
|
||||
const oldIdentifier = this.openmct.objects.parseKeyString(oldKeyString);
|
||||
const oldIdentifierNamespaceFirst = JSON.stringify(oldIdentifier);
|
||||
const oldIdentifierKeyFirst = JSON.stringify({
|
||||
key: oldIdentifier.key,
|
||||
namespace: oldIdentifier.namespace
|
||||
});
|
||||
|
||||
// replace keyStrings
|
||||
treeString = treeString.split(oldKeyString).join(newKeyString);
|
||||
|
||||
// check for namespace first identifiers, replace if necessary
|
||||
if (treeString.includes(oldIdentifierNamespaceFirst)) {
|
||||
treeString = treeString.split(oldIdentifierNamespaceFirst).join(newIdentifier);
|
||||
}
|
||||
|
||||
// check for key first identifiers, replace if necessary
|
||||
if (treeString.includes(oldIdentifierKeyFirst)) {
|
||||
treeString = treeString.split(oldIdentifierKeyFirst).join(newIdentifier);
|
||||
}
|
||||
|
||||
});
|
||||
this.tree = JSON.parse(treeString);
|
||||
}
|
||||
/**
|
||||
@ -180,70 +327,10 @@ export default class ExportAsJSONAction {
|
||||
_wrapTree() {
|
||||
return {
|
||||
"openmct": this.tree,
|
||||
"rootId": this._getId(this.root)
|
||||
"rootId": this._getKeystring(this.root)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {object} parent
|
||||
*/
|
||||
_write(parent) {
|
||||
this.calls++;
|
||||
//conditional object styles are not saved on the composition, so we need to check for them
|
||||
let childObjectReferenceId = parent.configuration?.objectStyles?.conditionSetIdentifier;
|
||||
|
||||
const composition = this.openmct.composition.get(parent);
|
||||
if (composition !== undefined) {
|
||||
composition.load()
|
||||
.then((children) => {
|
||||
children.forEach((child, index) => {
|
||||
// Only export if object is creatable
|
||||
if (this._isCreatableAndPersistable(child)) {
|
||||
// Prevents infinite export of self-contained objs
|
||||
if (!Object.prototype.hasOwnProperty.call(this.tree, this._getId(child))) {
|
||||
// If object is a link to something absent from
|
||||
// tree, generate new id and treat as new object
|
||||
if (this._isLinkedObject(child, parent)) {
|
||||
child = this._rewriteLink(child, parent);
|
||||
} else {
|
||||
this.tree[this._getId(child)] = child;
|
||||
}
|
||||
|
||||
this._write(child);
|
||||
}
|
||||
}
|
||||
});
|
||||
this._decrementCallsAndSave();
|
||||
});
|
||||
} else if (!childObjectReferenceId) {
|
||||
this._decrementCallsAndSave();
|
||||
}
|
||||
|
||||
if (childObjectReferenceId) {
|
||||
this.openmct.objects.get(childObjectReferenceId)
|
||||
.then((child) => {
|
||||
// Only export if object is creatable
|
||||
if (this._isCreatableAndPersistable(child)) {
|
||||
// Prevents infinite export of self-contained objs
|
||||
if (!Object.prototype.hasOwnProperty.call(this.tree, this._getId(child))) {
|
||||
// If object is a link to something absent from
|
||||
// tree, generate new id and treat as new object
|
||||
if (this._isLinkedObject(child, parent)) {
|
||||
child = this._rewriteLinkForReference(child, parent);
|
||||
} else {
|
||||
this.tree[this._getId(child)] = child;
|
||||
}
|
||||
|
||||
this._write(child);
|
||||
}
|
||||
}
|
||||
|
||||
this._decrementCallsAndSave();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_decrementCallsAndSave() {
|
||||
this.calls--;
|
||||
if (this.calls === 0) {
|
||||
@ -251,4 +338,8 @@ export default class ExportAsJSONAction {
|
||||
this._saveAs(this._wrapTree());
|
||||
}
|
||||
}
|
||||
|
||||
_copy(object) {
|
||||
return JSON.parse(JSON.stringify(object));
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,10 @@ define([
|
||||
});
|
||||
},
|
||||
showTab: function (isEditing) {
|
||||
if (isEditing) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hasPersistedFilters = Boolean(domainObject?.configuration?.filters);
|
||||
const hasGlobalFilters = Boolean(domainObject?.configuration?.globalFilters);
|
||||
|
||||
|
@ -154,8 +154,11 @@ export default {
|
||||
let originalClassName = this.dragGhost.classList[0];
|
||||
this.dragGhost.className = '';
|
||||
this.dragGhost.classList.add(originalClassName, iconClass);
|
||||
this.dragGhost.textContent = '';
|
||||
const span = document.createElement('span');
|
||||
span.textContent = this.domainObject.name;
|
||||
this.dragGhost.appendChild(span);
|
||||
|
||||
this.dragGhost.innerHTML = `<span>${this.domainObject.name}</span>`;
|
||||
event.dataTransfer.setDragImage(this.dragGhost, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,11 @@ export default class CreateAction extends PropertiesAction {
|
||||
|
||||
const parentDomainObject = this.openmct.objects.toMutable(parentDomainObjectPath[0]);
|
||||
|
||||
// TODO REMOVE FOR OMM-RELEASE-5.0
|
||||
if (!parentDomainObject.identifier.namespace && parentDomainObject.key) {
|
||||
console.error(`parent namespace in key: ${parentDomainObject.key}`);
|
||||
}
|
||||
|
||||
this.domainObject.modified = Date.now();
|
||||
this.domainObject.location = this.openmct.objects.makeKeyString(parentDomainObject.identifier);
|
||||
this.domainObject.identifier.namespace = parentDomainObject.identifier.namespace;
|
||||
|
@ -31,6 +31,7 @@ export default class ImportAsJSONAction {
|
||||
this.cssClass = "icon-import";
|
||||
this.group = "json";
|
||||
this.priority = 2;
|
||||
this.newObjects = [];
|
||||
|
||||
this.openmct = openmct;
|
||||
}
|
||||
@ -85,22 +86,25 @@ export default class ImportAsJSONAction {
|
||||
let objectIdentifiers = this._getObjectReferenceIds(parent);
|
||||
|
||||
if (objectIdentifiers.length) {
|
||||
let newObj;
|
||||
const parentId = this.openmct.objects.makeKeyString(parent.identifier);
|
||||
seen.push(parentId);
|
||||
|
||||
seen.push(parent.id);
|
||||
|
||||
objectIdentifiers.forEach(async (childId) => {
|
||||
for (const childId of objectIdentifiers) {
|
||||
const keystring = this.openmct.objects.makeKeyString(childId);
|
||||
if (!tree[keystring] || seen.includes(keystring)) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
const newModel = tree[keystring];
|
||||
delete newModel.persisted;
|
||||
|
||||
newObj = await this._instantiate(newModel);
|
||||
this._deepInstantiate(newObj, tree, seen);
|
||||
}, this);
|
||||
this.newObjects.push(newModel);
|
||||
|
||||
// make sure there weren't any errors saving
|
||||
if (newModel) {
|
||||
this._deepInstantiate(newModel, tree, seen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -110,19 +114,32 @@ export default class ImportAsJSONAction {
|
||||
*/
|
||||
_getObjectReferenceIds(parent) {
|
||||
let objectIdentifiers = [];
|
||||
let itemObjectReferences = [];
|
||||
const objectStyles = parent?.configuration?.objectStyles;
|
||||
const parentComposition = this.openmct.composition.get(parent);
|
||||
|
||||
let parentComposition = this.openmct.composition.get(parent);
|
||||
if (parentComposition) {
|
||||
objectIdentifiers = Array.from(parentComposition.domainObject.composition);
|
||||
objectIdentifiers = Array.from(parent.composition);
|
||||
}
|
||||
|
||||
//conditional object styles are not saved on the composition, so we need to check for them
|
||||
let parentObjectReference = parent.configuration?.objectStyles?.conditionSetIdentifier;
|
||||
if (parentObjectReference) {
|
||||
objectIdentifiers.push(parentObjectReference);
|
||||
if (objectStyles) {
|
||||
const parentObjectReference = objectStyles.conditionSetIdentifier;
|
||||
|
||||
if (parentObjectReference) {
|
||||
objectIdentifiers.push(parentObjectReference);
|
||||
}
|
||||
|
||||
function hasConditionSetIdentifier(item) {
|
||||
return Boolean(item.conditionSetIdentifier);
|
||||
}
|
||||
|
||||
itemObjectReferences = Object.values(objectStyles)
|
||||
.filter(hasConditionSetIdentifier)
|
||||
.map(item => item.conditionSetIdentifier);
|
||||
}
|
||||
|
||||
return objectIdentifiers;
|
||||
return Array.from(new Set([...objectIdentifiers, ...itemObjectReferences]));
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
@ -155,13 +172,21 @@ export default class ImportAsJSONAction {
|
||||
const tree = this._generateNewIdentifiers(objTree, namespace);
|
||||
const rootId = tree.rootId;
|
||||
|
||||
const rootModel = tree.openmct[rootId];
|
||||
delete rootModel.persisted;
|
||||
const rootObj = tree.openmct[rootId];
|
||||
delete rootObj.persisted;
|
||||
this.newObjects.push(rootObj);
|
||||
|
||||
const rootObj = await this._instantiate(rootModel);
|
||||
if (this.openmct.composition.checkPolicy(domainObject, rootObj)) {
|
||||
this._deepInstantiate(rootObj, tree.openmct, []);
|
||||
|
||||
try {
|
||||
await Promise.all(this.newObjects.map(this._instantiate, this));
|
||||
} catch (error) {
|
||||
this.openmct.notifications.error('Error saving objects');
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
const compositionCollection = this.openmct.composition.get(domainObject);
|
||||
let domainObjectKeyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
this.openmct.objects.mutate(rootObj, 'location', domainObjectKeyString);
|
||||
@ -184,16 +209,11 @@ export default class ImportAsJSONAction {
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
* @param {object} rootModel
|
||||
* @param {object} model
|
||||
* @returns {object}
|
||||
*/
|
||||
async _instantiate(rootModel) {
|
||||
const success = await this.openmct.objects.save(rootModel);
|
||||
if (success) {
|
||||
return rootModel;
|
||||
}
|
||||
|
||||
this.openmct.notifications.error('Error saving objects');
|
||||
_instantiate(model) {
|
||||
return this.openmct.objects.save(model);
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
|
@ -19,7 +19,7 @@
|
||||
class="c-icon-button c-button--menu icon-font"
|
||||
@click.prevent.stop="showFontMenu"
|
||||
>
|
||||
<span class="c-button__label">{{ fontTypeLable }}</span>
|
||||
<span class="c-button__label">{{ fontTypeLabel }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -43,7 +43,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fontTypeLable() {
|
||||
fontTypeLabel() {
|
||||
const fontType = FONTS.find(f => f.value === this.fontStyle.font);
|
||||
if (!fontType) {
|
||||
return '??';
|
||||
|
@ -20,12 +20,10 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
|
||||
<template>
|
||||
<div class="gl-plot-chart-area">
|
||||
<span v-html="canvasTemplate"></span>
|
||||
<span v-html="canvasTemplate"></span>
|
||||
<canvas :style="canvasStyle"></canvas>
|
||||
<canvas :style="canvasStyle"></canvas>
|
||||
<div
|
||||
ref="limitArea"
|
||||
class="js-limit-area"
|
||||
@ -132,10 +130,15 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
canvasTemplate: '<canvas style="position: absolute; background: none; width: 100%; height: 100%;"></canvas>'
|
||||
};
|
||||
computed: {
|
||||
canvasStyle() {
|
||||
return {
|
||||
position: 'absolute',
|
||||
background: 'none',
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
highlights() {
|
||||
@ -418,7 +421,10 @@ export default {
|
||||
// Have to throw away the old canvas elements and replace with new
|
||||
// canvas elements in order to get new drawing contexts.
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = this.canvasTemplate + this.canvasTemplate;
|
||||
div.innerHTML = `
|
||||
<canvas style="position: absolute; background: none; width: 100%; height: 100%;"></canvas>
|
||||
<canvas style="position: absolute; background: none; width: 100%; height: 100%;"></canvas>
|
||||
`;
|
||||
const mainCanvas = div.querySelectorAll("canvas")[1];
|
||||
const overlayCanvas = div.querySelectorAll("canvas")[0];
|
||||
this.canvas.parentNode.replaceChild(mainCanvas, this.canvas);
|
||||
|
@ -63,6 +63,10 @@ import { symlog } from '../mathUtils';
|
||||
*
|
||||
* @extends {Model<PlotSeriesModelType, PlotSeriesModelOptions>}
|
||||
*/
|
||||
|
||||
const FLOAT32_MAX = 3.4e38;
|
||||
const FLOAT32_MIN = -3.4e38;
|
||||
|
||||
export default class PlotSeries extends Model {
|
||||
logMode = false;
|
||||
|
||||
@ -357,7 +361,7 @@ export default class PlotSeries extends Model {
|
||||
let stats = this.get('stats');
|
||||
let changed = false;
|
||||
if (!stats) {
|
||||
if ([Infinity, -Infinity].includes(value)) {
|
||||
if ([Infinity, -Infinity].includes(value) || !this.isValidFloat32(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -369,13 +373,13 @@ export default class PlotSeries extends Model {
|
||||
};
|
||||
changed = true;
|
||||
} else {
|
||||
if (stats.maxValue < value && value !== Infinity) {
|
||||
if (stats.maxValue < value && value !== Infinity && this.isValidFloat32(value)) {
|
||||
stats.maxValue = value;
|
||||
stats.maxPoint = point;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (stats.minValue > value && value !== -Infinity) {
|
||||
if (stats.minValue > value && value !== -Infinity && this.isValidFloat32(value)) {
|
||||
stats.minValue = value;
|
||||
stats.minPoint = point;
|
||||
changed = true;
|
||||
@ -411,7 +415,7 @@ export default class PlotSeries extends Model {
|
||||
const lastYVal = this.getYVal(data[insertIndex - 1]);
|
||||
|
||||
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
|
||||
console.warn('[Plot] Invalid Y Values detected');
|
||||
console.warn(`[Plot] Invalid Y Values detected: ${currentYVal} ${lastYVal}`);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -439,7 +443,15 @@ export default class PlotSeries extends Model {
|
||||
* @private
|
||||
*/
|
||||
isValueInvalid(val) {
|
||||
return Number.isNaN(val) || this.unPlottableValues.includes(val);
|
||||
return Number.isNaN(val) || this.unPlottableValues.includes(val) || !this.isValidFloat32(val);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
isValidFloat32(val) {
|
||||
return val < FLOAT32_MAX && val > FLOAT32_MIN;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -194,7 +194,7 @@ define([
|
||||
const options = this.generateSelectOptions();
|
||||
|
||||
newInput = document.createElement("select");
|
||||
newInput.innerHTML = options;
|
||||
newInput.appendChild(options);
|
||||
|
||||
emitChange = true;
|
||||
} else {
|
||||
@ -224,12 +224,15 @@ define([
|
||||
|
||||
Condition.prototype.generateSelectOptions = function () {
|
||||
let telemetryMetadata = this.conditionManager.getTelemetryMetadata(this.config.object);
|
||||
let options = '';
|
||||
let fragment = document.createDocumentFragment();
|
||||
telemetryMetadata[this.config.key].enumerations.forEach(enumeration => {
|
||||
options += '<option value="' + enumeration.value + '">' + enumeration.string + '</option>';
|
||||
const option = document.createElement('option');
|
||||
option.value = enumeration.value;
|
||||
option.textContent = enumeration.string;
|
||||
fragment.appendChild(option);
|
||||
});
|
||||
|
||||
return options;
|
||||
return fragment;
|
||||
};
|
||||
|
||||
return Condition;
|
||||
|
@ -165,7 +165,8 @@ define([
|
||||
document.querySelectorAll('.t-drag-indicator').forEach(indicator => {
|
||||
// eslint-disable-next-line no-invalid-this
|
||||
const ruleHeader = self.domElement.querySelectorAll('.widget-rule-header')[0].cloneNode(true);
|
||||
indicator.innerHTML = ruleHeader;
|
||||
indicator.textContent = '';
|
||||
indicator.appendChild(ruleHeader);
|
||||
});
|
||||
self.widgetDnD.setDragImage(self.domElement.querySelectorAll('.widget-rule-header')[0].cloneNode(true));
|
||||
self.widgetDnD.dragStart(self.config.id);
|
||||
@ -235,8 +236,8 @@ define([
|
||||
this.listenTo(this.toggleConfigButton, 'click', toggleConfig);
|
||||
this.listenTo(this.trigger, 'change', onTriggerInput);
|
||||
|
||||
this.title.innerHTML = self.config.name;
|
||||
this.description.innerHTML = self.config.description;
|
||||
this.title.innerText = self.config.name;
|
||||
this.description.innerText = self.config.description;
|
||||
this.trigger.value = self.config.trigger;
|
||||
|
||||
this.listenTo(this.grippy, 'mousedown', onDragStart);
|
||||
@ -445,7 +446,7 @@ define([
|
||||
const lastOfType = self.conditionArea.querySelector('li:last-of-type');
|
||||
lastOfType.parentNode.insertBefore($condition, lastOfType);
|
||||
if (loopCnt > 0) {
|
||||
$condition.querySelector('.t-condition-context').innerHTML = triggerContextStr + ' when';
|
||||
$condition.querySelector('.t-condition-context').innerText = triggerContextStr + ' when';
|
||||
}
|
||||
|
||||
loopCnt++;
|
||||
@ -517,7 +518,7 @@ define([
|
||||
}
|
||||
|
||||
description = (description === '' ? this.config.description : description);
|
||||
this.description.innerHTML = self.config.description;
|
||||
this.description.innerText = self.config.description;
|
||||
this.config.description = description;
|
||||
};
|
||||
|
||||
|
@ -229,9 +229,10 @@ define([
|
||||
SummaryWidget.prototype.updateWidget = function () {
|
||||
const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
const activeRule = this.rulesById[this.activeId];
|
||||
|
||||
this.applyStyle(this.domElement.querySelector('#widget'), activeRule.getProperty('style'));
|
||||
this.domElement.querySelector('#widget').title = activeRule.getProperty('message');
|
||||
this.domElement.querySelector('#widgetLabel').innerHTML = activeRule.getProperty('label');
|
||||
this.domElement.querySelector('#widgetLabel').textContent = activeRule.getProperty('label');
|
||||
this.domElement.querySelector('#widgetIcon').classList = WIDGET_ICON_CLASS + ' ' + activeRule.getProperty('icon');
|
||||
};
|
||||
|
||||
|
@ -49,11 +49,12 @@ define([
|
||||
self.setNullOption(this.nullOption);
|
||||
|
||||
self.items.forEach(function (item) {
|
||||
const itemElement = `<div class = "c-palette__item ${item}" data-item = "${item}"></div>`;
|
||||
const temp = document.createElement('div');
|
||||
temp.innerHTML = itemElement;
|
||||
self.itemElements[item] = temp.firstChild;
|
||||
self.domElement.querySelector('.c-palette__items').appendChild(temp.firstChild);
|
||||
const itemElement = document.createElement('div');
|
||||
itemElement.className = 'c-palette__item ' + item;
|
||||
itemElement.setAttribute('data-item', item);
|
||||
|
||||
self.itemElements[item] = itemElement;
|
||||
self.domElement.querySelector('.c-palette__items').appendChild(itemElement);
|
||||
});
|
||||
|
||||
self.domElement.querySelector('.c-menu').style.display = 'none';
|
||||
|
@ -1,38 +1,60 @@
|
||||
define([
|
||||
'./summary-widget.html',
|
||||
'@braintree/sanitize-url'
|
||||
], function (
|
||||
summaryWidgetTemplate,
|
||||
urlSanitizeLib
|
||||
) {
|
||||
const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
import * as urlSanitizeLib from '@braintree/sanitize-url';
|
||||
|
||||
function SummaryWidgetView(domainObject, openmct) {
|
||||
const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
|
||||
class SummaryWidgetView {
|
||||
#createSummaryWidgetTemplate() {
|
||||
const anchor = document.createElement('a');
|
||||
anchor.classList.add(
|
||||
't-summary-widget',
|
||||
'c-summary-widget',
|
||||
'js-sw',
|
||||
'u-links',
|
||||
'u-fills-container'
|
||||
);
|
||||
|
||||
const widgetIcon = document.createElement('div');
|
||||
widgetIcon.id = 'widgetIcon';
|
||||
widgetIcon.classList.add('c-sw__icon', 'js-sw__icon');
|
||||
anchor.appendChild(widgetIcon);
|
||||
|
||||
const widgetLabel = document.createElement('div');
|
||||
widgetLabel.id = 'widgetLabel';
|
||||
widgetLabel.classList.add('c-sw__label', 'js-sw__label');
|
||||
widgetLabel.textContent = 'Loading...';
|
||||
anchor.appendChild(widgetLabel);
|
||||
|
||||
return anchor;
|
||||
}
|
||||
|
||||
constructor(domainObject, openmct) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.hasUpdated = false;
|
||||
this.render = this.render.bind(this);
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.updateState = function (datum) {
|
||||
updateState(datum) {
|
||||
this.hasUpdated = true;
|
||||
this.widget.style.color = datum.textColor;
|
||||
this.widget.style.backgroundColor = datum.backgroundColor;
|
||||
this.widget.style.borderColor = datum.borderColor;
|
||||
this.widget.title = datum.message;
|
||||
this.label.title = datum.message;
|
||||
this.label.innerHTML = datum.ruleLabel;
|
||||
this.label.textContent = datum.ruleLabel;
|
||||
this.icon.className = WIDGET_ICON_CLASS + ' ' + datum.icon;
|
||||
};
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.render = function () {
|
||||
render() {
|
||||
if (this.unsubscribe) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
|
||||
this.hasUpdated = false;
|
||||
|
||||
this.container.innerHTML = summaryWidgetTemplate;
|
||||
const anchor = this.#createSummaryWidgetTemplate();
|
||||
this.container.appendChild(anchor);
|
||||
|
||||
this.widget = this.container.querySelector('a');
|
||||
this.icon = this.container.querySelector('#widgetIcon');
|
||||
this.label = this.container.querySelector('.js-sw__label');
|
||||
@ -52,26 +74,32 @@ define([
|
||||
|
||||
const renderTracker = {};
|
||||
this.renderTracker = renderTracker;
|
||||
this.openmct.telemetry.request(this.domainObject, {
|
||||
strategy: 'latest',
|
||||
size: 1
|
||||
}).then(function (results) {
|
||||
if (this.destroyed
|
||||
|| this.hasUpdated
|
||||
|| this.renderTracker !== renderTracker
|
||||
|| results.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateState(results[results.length - 1]);
|
||||
}.bind(this));
|
||||
this.openmct.telemetry
|
||||
.request(this.domainObject, {
|
||||
strategy: 'latest',
|
||||
size: 1
|
||||
})
|
||||
.then((results) => {
|
||||
if (
|
||||
this.destroyed ||
|
||||
this.hasUpdated ||
|
||||
this.renderTracker !== renderTracker ||
|
||||
results.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.unsubscribe = this.openmct
|
||||
.telemetry
|
||||
.subscribe(this.domainObject, this.updateState.bind(this));
|
||||
};
|
||||
this.updateState(results[results.length - 1]);
|
||||
});
|
||||
|
||||
SummaryWidgetView.prototype.show = function (container) {
|
||||
this.unsubscribe = this.openmct.telemetry.subscribe(
|
||||
this.domainObject,
|
||||
this.updateState.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
show(container) {
|
||||
this.container = container;
|
||||
this.render();
|
||||
this.removeMutationListener = this.openmct.objects.observe(
|
||||
@ -80,14 +108,14 @@ define([
|
||||
this.onMutation.bind(this)
|
||||
);
|
||||
this.openmct.time.on('timeSystem', this.render);
|
||||
};
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.onMutation = function (domainObject) {
|
||||
onMutation(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
this.render();
|
||||
};
|
||||
}
|
||||
|
||||
SummaryWidgetView.prototype.destroy = function (container) {
|
||||
destroy() {
|
||||
this.unsubscribe();
|
||||
this.removeMutationListener();
|
||||
this.openmct.time.off('timeSystem', this.render);
|
||||
@ -96,8 +124,7 @@ define([
|
||||
delete this.label;
|
||||
delete this.openmct;
|
||||
delete this.domainObject;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return SummaryWidgetView;
|
||||
|
||||
});
|
||||
export default SummaryWidgetView;
|
||||
|
@ -1,4 +0,0 @@
|
||||
<a class="t-summary-widget c-summary-widget js-sw u-links u-fills-container">
|
||||
<div id="widgetIcon" class="c-sw__icon js-sw__icon"></div>
|
||||
<div id="widgetLabel" class="c-sw__label js-sw__label">Loading...</div>
|
||||
</a>
|
@ -35,7 +35,7 @@ define([
|
||||
function TableConfigurationViewProvider(openmct) {
|
||||
return {
|
||||
key: 'table-configuration',
|
||||
name: 'Configuration',
|
||||
name: 'Config',
|
||||
canView: function (selection) {
|
||||
if (selection.length !== 1 || selection[0].length === 0) {
|
||||
return false;
|
||||
|
@ -88,7 +88,7 @@ define([], function () {
|
||||
}
|
||||
|
||||
getContextMenuActions() {
|
||||
return ['viewDatumAction'];
|
||||
return ['viewDatumAction', 'viewHistoricalData'];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,14 +175,22 @@ export default {
|
||||
getDatum() {
|
||||
return this.row.fullDatum;
|
||||
},
|
||||
showContextMenu: function (event) {
|
||||
showContextMenu: async function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.updateViewContext();
|
||||
this.markRow(event);
|
||||
|
||||
const contextualDomainObject = await this.row.getContextualDomainObject?.(this.openmct, this.row.objectKeyString);
|
||||
|
||||
let objectPath = this.objectPath;
|
||||
if (contextualDomainObject) {
|
||||
objectPath = objectPath.slice();
|
||||
objectPath.unshift(contextualDomainObject);
|
||||
}
|
||||
|
||||
const actions = this.row.getContextMenuActions().map(key => this.openmct.actions.getAction(key));
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(actions, this.objectPath, this.currentView);
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(actions, objectPath, this.currentView);
|
||||
if (menuItems.length) {
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ export default {
|
||||
return this.domainObject && (this.currentObjectPath || this.objectPath);
|
||||
},
|
||||
objectFontStyle() {
|
||||
return this.domainObject && this.domainObject.configuration && this.domainObject.configuration.fontStyle;
|
||||
return this.domainObject?.configuration?.fontStyle;
|
||||
},
|
||||
fontSize() {
|
||||
return this.objectFontStyle ? this.objectFontStyle.fontSize : this.layoutFontSize;
|
||||
@ -287,6 +287,8 @@ export default {
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.updateStyle(this.styleRuleManager?.currentStyle);
|
||||
this.setFontSize(this.fontSize);
|
||||
this.setFont(this.font);
|
||||
this.getActionCollection();
|
||||
});
|
||||
},
|
||||
@ -329,9 +331,9 @@ export default {
|
||||
},
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager((this.domainObject.configuration && this.domainObject.configuration.objectStyles), this.openmct, this.updateStyle.bind(this), true);
|
||||
this.styleRuleManager = new StyleRuleManager((this.domainObject.configuration?.objectStyles), this.openmct, this.updateStyle.bind(this), true);
|
||||
} else {
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.domainObject.configuration && this.domainObject.configuration.objectStyles);
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.domainObject.configuration?.objectStyles);
|
||||
}
|
||||
|
||||
if (this.stopListeningStyles) {
|
||||
@ -343,9 +345,6 @@ export default {
|
||||
this.styleRuleManager.updateObjectStyleConfig(newObjectStyle);
|
||||
});
|
||||
|
||||
this.setFontSize(this.fontSize);
|
||||
this.setFont(this.font);
|
||||
|
||||
this.stopListeningFontStyles = this.openmct.objects.observe(this.domainObject, 'configuration.fontStyle', (newFontStyle) => {
|
||||
this.setFontSize(newFontStyle.fontSize);
|
||||
this.setFont(newFontStyle.font);
|
||||
|
@ -6,11 +6,12 @@
|
||||
<input
|
||||
class="c-search__input"
|
||||
aria-label="Search Input"
|
||||
tabindex="10000"
|
||||
tabindex="0"
|
||||
type="search"
|
||||
v-bind="$attrs"
|
||||
:value="value"
|
||||
v-on="inputListeners"
|
||||
@click="() => $emit('click')"
|
||||
@input="($event) => $emit('input', $event.target.value)"
|
||||
>
|
||||
<a
|
||||
class="c-search__clear-input icon-x-in-circle"
|
||||
@ -35,27 +36,11 @@ export default {
|
||||
active: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
inputListeners: function () {
|
||||
let vm = this;
|
||||
|
||||
return Object.assign({},
|
||||
this.$listeners,
|
||||
{
|
||||
input: function (event) {
|
||||
vm.$emit('input', event.target.value);
|
||||
vm.active = (event.target.value.length > 0);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(inputValue) {
|
||||
if (!inputValue.length) {
|
||||
this.clearInput();
|
||||
}
|
||||
this.active = inputValue.length > 0;
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
clearInput() {
|
||||
@ -65,4 +50,4 @@ export default {
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
@ -322,10 +322,14 @@ export default {
|
||||
},
|
||||
async openTreeItem(parentItem) {
|
||||
const parentPath = parentItem.navigationPath;
|
||||
const abortSignal = this.startItemLoad(parentPath);
|
||||
|
||||
this.startItemLoad(parentPath);
|
||||
// pass in abort signal when functional
|
||||
const childrenItems = await this.loadAndBuildTreeItemsFor(parentItem.object.identifier, parentItem.objectPath);
|
||||
const childrenItems = await this.loadAndBuildTreeItemsFor(
|
||||
parentItem.object.identifier,
|
||||
parentItem.objectPath,
|
||||
abortSignal
|
||||
);
|
||||
const parentIndex = this.treeItems.indexOf(parentItem);
|
||||
|
||||
// if it's not loading, it was aborted
|
||||
|
@ -1,8 +1,17 @@
|
||||
export function convertTemplateToHTML(templateString) {
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = templateString;
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(templateString, 'text/html');
|
||||
|
||||
return template.content.cloneNode(true).children;
|
||||
// Create a document fragment to hold the parsed content
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
// Append nodes from the parsed content to the fragment
|
||||
while (doc.body.firstChild) {
|
||||
fragment.appendChild(doc.body.firstChild);
|
||||
}
|
||||
|
||||
// Convert children of the fragment to an array and return
|
||||
return Array.from(fragment.children);
|
||||
}
|
||||
|
||||
export function toggleClass(element, className) {
|
||||
|
Reference in New Issue
Block a user