add facility to send action to mounted component regarding extending lines

This commit is contained in:
Scott Bell 2024-12-12 14:05:14 +01:00
parent 3b236cc33b
commit 0db301dea8
11 changed files with 162 additions and 49 deletions

View File

@ -235,7 +235,7 @@
openmct.install(openmct.plugins.Timelist());
openmct.install(openmct.plugins.BarChart());
openmct.install(openmct.plugins.ScatterPlot());
openmct.install(openmct.plugins.EventTimestripPlugin(timeLinePlugin.eventBus));
openmct.install(openmct.plugins.EventTimestripPlugin(timeLinePlugin.extendedLinesBus));
document.addEventListener('DOMContentLoaded', function () {
openmct.start();
});

View File

@ -23,7 +23,7 @@ import mount from 'utils/mount';
import EventTimelineView from './components/EventTimelineView.vue';
export default function EventTimestripViewProvider(openmct, timelineEventBus) {
export default function EventTimestripViewProvider(openmct, extendedLinesBus) {
const type = 'event.time-line.view';
function hasEventTelemetry(domainObject) {
@ -66,7 +66,7 @@ export default function EventTimestripViewProvider(openmct, timelineEventBus) {
openmct: openmct,
domainObject: domainObject,
objectPath: objectPath,
timelineEventBus
extendedLinesBus
},
template: '<event-timeline-view ref="root"></event-timeline-view>'
},

View File

@ -44,7 +44,7 @@ const ID_PREFIX = 'wrapper-';
export default {
mixins: [eventData],
inject: ['openmct', 'domainObject', 'objectPath', 'timelineEventBus'],
inject: ['openmct', 'domainObject', 'objectPath', 'extendedLinesBus'],
data() {
const timeSystem = this.openmct.time.getTimeSystem();
this.metadata = {};
@ -78,6 +78,7 @@ export default {
this.setTimeContext();
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(this.domainObject);
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
const metadata = this.openmct.telemetry.getMetadata(this.domainObject);
if (metadata) {
this.valueMetadata =
@ -90,6 +91,8 @@ export default {
this.eventStripResizeObserver.observe(this.$refs.events);
this.unlisten = this.openmct.objects.observe(this.domainObject, '*', this.observeForChanges);
this.extendedLinesBus.on('disable-extended-lines', this.disableExtendEventLines);
this.extendedLinesBus.on('enable-extended-lines', this.enableExtendEventLines);
},
beforeUnmount() {
if (this.eventStripResizeObserver) {
@ -103,6 +106,9 @@ export default {
if (this.destroyEventContainer) {
this.destroyEventContainer();
}
this.extendedLinesBus.off('disable-extended-lines', this.disableExtendEventLines);
this.extendedLinesBus.off('enable-extended-lines', this.enableExtendEventLines);
},
methods: {
setTimeContext() {
@ -111,6 +117,16 @@ export default {
this.timeContext.on('timeSystem', this.setScaleAndPlotEvents);
this.timeContext.on('boundsChanged', this.updateViewBounds);
},
enableExtendEventLines(keyStringToEnable) {
if (this.keyString === keyStringToEnable) {
this.extendLines = true;
}
},
disableExtendEventLines(keyStringToDisable) {
if (this.keyString === keyStringToDisable) {
this.extendLines = false;
}
},
firstNonDomainAttribute(metadata) {
return metadata
.values()
@ -409,7 +425,10 @@ export default {
const lines = this.eventHistory
.filter((e) => this.isEventInBounds(e))
.map((e) => ({ x: this.xScale(e.time) }));
this.timelineEventBus.emit('update-extended-lines', lines);
this.timelineEventBus.emit('update-extended-lines', {
lines,
keyString: this.keyString
});
}
}
};

View File

@ -23,9 +23,9 @@
import EventInspectorViewProvider from './EventInspectorViewProvider.js';
import EventTimelineViewProvider from './EventTimelineViewProvider.js';
export default function plugin(timelineEventBus) {
export default function plugin(extendedLinesBus) {
return function install(openmct) {
openmct.objectViews.addProvider(new EventTimelineViewProvider(openmct, timelineEventBus));
openmct.objectViews.addProvider(new EventTimelineViewProvider(openmct, extendedLinesBus));
openmct.inspectorViews.addProvider(new EventInspectorViewProvider(openmct));
};
}

View File

@ -21,8 +21,17 @@
*****************************************************************************/
import { EventEmitter } from 'eventemitter3';
export default class EventBusAPI extends EventEmitter {
updateExtendedLine(lineData) {
this.emit('update-extended-lines', lineData);
export default class ExtendedLinesBus extends EventEmitter {
updateExtendedLines(keyString, lineData) {
console.debug('🍯 ExtendedLines#updateExtendedLines');
this.emit('update-extended-lines', { lineData, keyString });
}
disableExtendEventLines(keyString) {
console.debug('🍯 ExtendedLines#disableExtendedLines');
this.emit('disable-extended-lines', keyString);
}
enableExtendEventLines(keyString) {
console.debug('🍯 ExtendedLines#enableExtendedLines');
this.emit('enable-extended-lines', keyString);
}
}

View File

@ -37,7 +37,7 @@ export default {
props: {
extendedLines: {
type: Array,
default: () => []
default: () => {}
},
height: {
type: Number,

View File

@ -28,6 +28,11 @@
:show-ucontents="isPlanLikeObject(item.domainObject)"
:span-rows-count="item.rowCount"
:domain-object="item.domainObject"
button-title="Toggle event lines"
button-icon="icon-timeline"
:hide-button="!hasEventTelemetry()"
:button-click-on="enableExtendEventLines"
:button-click-off="disableExtendEventLines"
>
<template #label>
{{ item.domainObject.name }}
@ -58,12 +63,16 @@ export default {
item: {
type: Object,
required: true
},
extendedLinesBus: {
type: Object,
required: true
}
},
data() {
return {
domainObject: undefined,
mutablePromise: undefined,
domainObject: null,
mutablePromise: null,
status: ''
};
},
@ -103,33 +112,54 @@ export default {
}
},
methods: {
setObject(domainObject) {
async setObject(domainObject) {
this.domainObject = domainObject;
this.mutablePromise = undefined;
this.$nextTick(() => {
let reference = this.$refs.objectView;
this.mutablePromise = null;
await this.$nextTick();
let reference = this.$refs.objectView;
if (reference) {
let childContext = this.$refs.objectView.getSelectionContext();
childContext.item = domainObject;
this.context = childContext;
if (this.removeSelectable) {
this.removeSelectable();
}
this.removeSelectable = this.openmct.selection.selectable(this.$el, this.context);
if (reference) {
let childContext = this.$refs.objectView.getSelectionContext();
childContext.item = domainObject;
this.context = childContext;
if (this.removeSelectable) {
this.removeSelectable();
}
if (this.removeStatusListener) {
this.removeStatusListener();
}
this.removeSelectable = this.openmct.selection.selectable(this.$el, this.context);
}
this.removeStatusListener = this.openmct.status.observe(
this.domainObject.identifier,
this.setStatus
);
this.status = this.openmct.status.get(this.domainObject.identifier);
});
if (this.removeStatusListener) {
this.removeStatusListener();
}
this.removeStatusListener = this.openmct.status.observe(
this.domainObject.identifier,
this.setStatus
);
this.status = this.openmct.status.get(this.domainObject.identifier);
},
enableExtendEventLines() {
console.debug('🚄 extending event lines');
const keyString = this.openmct.objects.makeKeyString(this.item.domainObject.identifier);
this.extendedLinesBus.enableExtendEventLines(keyString);
},
disableExtendEventLines() {
console.debug('🚄 disabling extended event lines');
const keyString = this.openmct.objects.makeKeyString(this.item.domainObject.identifier);
this.extendedLinesBus.disableExtendEventLines(keyString);
},
hasEventTelemetry() {
const metadata = this.openmct.telemetry.getMetadata(this.item.domainObject);
if (!metadata) {
return false;
}
const hasDomain = metadata.valuesForHints(['domain']).length > 0;
const hasNoRange = !metadata.valuesForHints(['range'])?.length;
// for the moment, let's also exclude telemetry with images
const hasNoImages = !metadata.valuesForHints(['image']).length;
return hasDomain && hasNoRange && hasNoImages;
},
setActionCollection(actionCollection) {
this.openmct.menus.actionsToMenuItems(

View File

@ -42,6 +42,7 @@
:key="item.keyString"
class="c-timeline__content js-timeline__content"
:item="item"
:extended-lines-bus
/>
</div>
@ -75,7 +76,7 @@ export default {
SwimLane,
ExtendedLinesOverlay
},
inject: ['openmct', 'domainObject', 'path', 'composition', 'eventsBus'],
inject: ['openmct', 'domainObject', 'path', 'composition', 'extendedLinesBus'],
setup() {
const domainObject = inject('domainObject');
const path = inject('path');
@ -93,9 +94,9 @@ export default {
items: [],
timeSystems: [],
height: 0,
extendedLines: [],
useIndependentTime: this.domainObject.configuration.useIndependentTime === true,
timeOptions: this.domainObject.configuration.timeOptions
timeOptions: this.domainObject.configuration.timeOptions,
extendedLines: []
};
},
beforeUnmount() {
@ -106,13 +107,13 @@ export default {
this.stopFollowingTimeContext();
this.handleContentResize.cancel();
this.contentResizeObserver.disconnect();
this.eventsBus.off('update-extended-lines', this.updateExtendedLines);
this.extendedLinesBus.off('update-extended-lines', this.updateExtendedLines);
},
mounted() {
this.items = [];
this.setTimeContext();
this.eventsBus.on('update-extended-lines', this.updateExtendedLines);
this.extendedLinesBus.on('update-extended-lines', this.updateExtendedLines);
if (this.composition) {
this.composition.on('add', this.addItem);
@ -136,6 +137,8 @@ export default {
rowCount = getValidatedGroups(domainObject, planData).length;
} else if (domainObject.type === 'gantt-chart') {
rowCount = Object.keys(domainObject.configuration.swimlaneVisibility).length;
} else if (domainObject.type === 'telemetry.plot.stacked') {
rowCount = domainObject.composition.length;
}
let height =

View File

@ -24,7 +24,7 @@ import mount from 'utils/mount';
import TimelineViewLayout from './TimelineViewLayout.vue';
export default function TimelineViewProvider(openmct, eventsBus) {
export default function TimelineViewProvider(openmct, extendedLinesBus) {
return {
key: 'time-strip.view',
name: 'TimeStrip',
@ -53,7 +53,7 @@ export default function TimelineViewProvider(openmct, eventsBus) {
domainObject,
path: objectPath,
composition: openmct.composition.get(domainObject),
eventsBus
extendedLinesBus
},
template: '<timeline-view-layout></timeline-view-layout>'
},

View File

@ -25,9 +25,9 @@ import TimelineCompositionPolicy from './TimelineCompositionPolicy.js';
import timelineInterceptor from './timelineInterceptor.js';
import TimelineViewProvider from './TimelineViewProvider.js';
const eventsBus = new ExtendedLinesBus();
const extendedLinesBus = new ExtendedLinesBus();
export { eventsBus };
export { extendedLinesBus };
export default function () {
function install(openmct) {
@ -48,10 +48,10 @@ export default function () {
timelineInterceptor(openmct);
openmct.composition.addPolicy(new TimelineCompositionPolicy(openmct).allow);
openmct.objectViews.addProvider(new TimelineViewProvider(openmct, eventsBus));
openmct.objectViews.addProvider(new TimelineViewProvider(openmct, extendedLinesBus));
}
install.eventBus = eventsBus;
install.extendedLinesBus = extendedLinesBus;
return install;
}

View File

@ -34,6 +34,10 @@
:class="[swimlaneClass, statusClass]"
:style="gridRowSpan"
>
<div class="c-object-label__name">
<slot name="label"></slot>
</div>
<div v-if="iconClass" class="c-object-label__type-icon" :class="iconClass">
<span
v-if="status"
@ -42,9 +46,14 @@
:title="`This item is ${status}`"
></span>
</div>
<div class="c-object-label__name">
<slot name="label"></slot>
<div class="c-notebook__toggle-nav-button c-icon-button c-icon-button--major">
<button
v-if="!hideButton"
class="c-button"
:class="[buttonIcon, buttonPressed ? 'is-active' : '']"
:title="buttonTitle"
@click="pressOnButton"
/>
</div>
</div>
<div
@ -115,8 +124,43 @@ export default {
domainObject: {
type: Object,
default: undefined
},
hideButton: {
type: Boolean,
default() {
return false;
}
},
buttonTitle: {
type: String,
default() {
return '';
}
},
buttonIcon: {
type: String,
default() {
return '';
}
},
buttonClickOn: {
type: Function,
default() {
return () => {};
}
},
buttonClickOff: {
type: Function,
default() {
return () => {};
}
}
},
data() {
return {
buttonPressed: false
};
},
computed: {
gridRowSpan() {
if (this.spanRowsCount) {
@ -142,6 +186,14 @@ export default {
async showToolTip() {
const { BELOW } = this.openmct.tooltips.TOOLTIP_LOCATIONS;
this.buildToolTip(await this.getObjectPath(), BELOW, 'swimLane');
},
pressOnButton() {
this.buttonPressed = !this.buttonPressed;
if (this.buttonPressed) {
this.buttonClickOn();
} else {
this.buttonClickOff();
}
}
}
};