Compare commits

...

11 Commits

Author SHA1 Message Date
faf71f1e67 omm-cherry-pick(#6602) : [ExportAsJson] Multiple Aliases in Export an… (#6662)
omm-cherry-pick(#6602) : [ExportAsJson] Multiple Aliases in Export and Conditional Styles Fixes (#6602)

Fixes issues that prevent import and export from being completed successfully. Specifically:

* if multiple aliases are detected, the first is created as a new object and and added to it's parent's composition, any subsequent aliases of the same object will not be recreated, but the originally created one will be added to the current parent's composition, creating an alias.

* Also, there are cases were conditionSetIdentifiers are stored in an object keyed by an item id in the configuration.objectstyles object, this fix will handle these as well.

* Replaces an errant `return` statement with a `continue` statement to prevent early exit from a recursive function.

---------

Co-authored-by: Andrew Henry <akhenry@gmail.com>
2023-05-15 13:12:37 -07:00
23310f85ae cherry pick retain styles on url change 2023-05-02 13:38:13 -07:00
d80819634b revert opening in new tab 2023-04-12 15:01:53 -07:00
483b62c152 Only decrement and save if there is composition but no child object reference 2023-04-07 14:08:58 -07:00
1254279635 Fix ExportAsJSONAction to not lose layout configurations on linked objects (#6562) 2023-04-05 23:05:27 -07:00
c768a71656 free findSubscriptionProvider 2023-03-31 15:50:38 -07:00
678a92bd29 Revert "enable source maps in prod"
This reverts commit 34b488944a.
2023-03-31 14:43:02 -07:00
34b488944a enable source maps in prod 2023-03-31 14:42:39 -07:00
4d1dd2f51d add temporary debugging 2023-03-31 12:23:23 -07:00
080f7b8f4b pass openmct and object key to function
re-enable historical row action
2023-03-29 17:09:35 -07:00
483f2feac8 allow contextual domain objects to row actions 2023-03-29 16:58:51 -07:00
12 changed files with 334 additions and 225 deletions

View File

@ -55,6 +55,11 @@ define([
*/
function parseKeyString(keyString) {
if (isIdentifier(keyString)) {
// TODO REMOVE FOR OMM-RELEASE-5.0
if (!keyString.namespace && keyString.key.includes(':')) {
console.error(`smushed key: ${keyString.key}`);
}
return keyString;
}

View File

@ -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 = {};

View File

@ -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;
}
}
}
};

View File

@ -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; }

View File

@ -36,6 +36,7 @@ export default function plugin() {
domainObject.configuration = {};
domainObject.label = 'Condition Widget';
domainObject.conditionalLabel = '';
domainObject.url = '';
},
form: [
{

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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

View File

@ -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 '??';

View File

@ -88,7 +88,7 @@ define([], function () {
}
getContextMenuActions() {
return ['viewDatumAction'];
return ['viewDatumAction', 'viewHistoricalData'];
}
}

View File

@ -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);
}

View File

@ -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);