From 4697352f60cd65dc43da7db1bf36ccfd9d95e8d0 Mon Sep 17 00:00:00 2001 From: Shefali Joshi Date: Mon, 31 Oct 2022 16:56:52 -0700 Subject: [PATCH] Fix now marker for time system axis in timestrips and plans (#5911) * Ensure the now marker spans the height of the plan. * Set height for timestrip for the now marker * Fix linting issues * Fix failing test --- src/plugins/plan/Plan.vue | 29 ++++++++++++++++++--- src/plugins/timeline/TimelineViewLayout.vue | 28 ++++++++++++++++---- src/plugins/timeline/pluginSpec.js | 13 ++++++--- src/ui/components/TimeSystemAxis.vue | 8 +++--- src/ui/components/timesystem-axis.scss | 4 +++ 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/plugins/plan/Plan.vue b/src/plugins/plan/Plan.vue index 89ad45bdd8..8296b0c711 100644 --- a/src/plugins/plan/Plan.vue +++ b/src/plugins/plan/Plan.vue @@ -129,11 +129,13 @@ export default { this.timeContext.on("timeSystem", this.setScaleAndPlotActivities); this.timeContext.on("bounds", this.updateViewBounds); + this.timeContext.on("clock", this.updateBounds); }, stopFollowingTimeContext() { if (this.timeContext) { this.timeContext.off("timeSystem", this.setScaleAndPlotActivities); this.timeContext.off("bounds", this.updateViewBounds); + this.timeContext.off("clock", this.updateBounds); } }, observeForChanges(mutatedObject) { @@ -142,10 +144,15 @@ export default { }, resize() { let clientWidth = this.getClientWidth(); + let clientHeight = this.getClientHeight(); if (clientWidth !== this.width) { this.setDimensions(); this.updateViewBounds(); } + + if (clientHeight !== this.height) { + this.setDimensions(); + } }, getClientWidth() { let clientWidth = this.$refs.plan.clientWidth; @@ -160,9 +167,27 @@ export default { return clientWidth - 200; }, + getClientHeight() { + let clientHeight = this.$refs.plan.clientHeight; + + if (!clientHeight) { + //this is a hack - need a better way to find the parent of this component + let parent = this.openmct.layout.$refs.browseObject.$el; + if (parent) { + clientHeight = parent.getBoundingClientRect().height; + } + } + + return clientHeight; + }, getPlanData(domainObject) { this.planData = getValidatedData(domainObject); }, + updateBounds(clock) { + if (clock === undefined) { + this.viewBounds = Object.create(this.timeContext.bounds()); + } + }, updateViewBounds(bounds) { if (bounds) { this.viewBounds = Object.create(bounds); @@ -191,10 +216,8 @@ export default { activities.forEach(activity => activity.remove()); }, setDimensions() { - const planHolder = this.$refs.plan; this.width = this.getClientWidth(); - - this.height = Math.round(planHolder.getBoundingClientRect().height); + this.height = this.getClientHeight(); }, setScale(timeSystem) { if (!this.width) { diff --git a/src/plugins/timeline/TimelineViewLayout.vue b/src/plugins/timeline/TimelineViewLayout.vue index c92e4ab739..4a8158ed56 100644 --- a/src/plugins/timeline/TimelineViewLayout.vue +++ b/src/plugins/timeline/TimelineViewLayout.vue @@ -124,12 +124,10 @@ export default { }; this.items.push(item); - this.updateContentHeight(); }, removeItem(identifier) { let index = this.items.findIndex(item => this.openmct.objects.areIdsEqual(identifier, item.domainObject.identifier)); this.items.splice(index, 1); - this.updateContentHeight(); }, reorder(reorderPlan) { let oldItems = this.items.slice(); @@ -138,7 +136,23 @@ export default { }); }, updateContentHeight() { - this.height = Math.round(this.$refs.contentHolder.getBoundingClientRect().height); + const clientHeight = this.getClientHeight(); + if (this.height !== clientHeight) { + this.height = clientHeight; + } + }, + getClientHeight() { + let clientHeight = this.$refs.contentHolder.getBoundingClientRect().height; + + if (!clientHeight) { + //this is a hack - need a better way to find the parent of this component + let parent = this.openmct.layout.$refs.browseObject.$el; + if (parent) { + clientHeight = parent.getBoundingClientRect().height; + } + } + + return clientHeight; }, getTimeSystems() { const timeSystems = this.openmct.time.getAllTimeSystems(); @@ -155,7 +169,9 @@ export default { //TODO: Some kind of translation via an offset? of current bounds to target timeSystem return currentBounds; }, - updateViewBounds(bounds) { + updateViewBounds() { + const bounds = this.timeContext.bounds(); + this.updateContentHeight(); let currentTimeSystem = this.timeSystems.find(item => item.timeSystem.key === this.openmct.time.timeSystem().key); if (currentTimeSystem) { currentTimeSystem.bounds = bounds; @@ -166,12 +182,14 @@ export default { this.timeContext = this.openmct.time.getContextForView(this.objectPath); this.getTimeSystems(); - this.updateViewBounds(this.timeContext.bounds()); + this.updateViewBounds(); this.timeContext.on('bounds', this.updateViewBounds); + this.timeContext.on('clock', this.updateViewBounds); }, stopFollowingTimeContext() { if (this.timeContext) { this.timeContext.off('bounds', this.updateViewBounds); + this.timeContext.off('clock', this.updateViewBounds); } } } diff --git a/src/plugins/timeline/pluginSpec.js b/src/plugins/timeline/pluginSpec.js index 0eb77e193c..fd69419a78 100644 --- a/src/plugins/timeline/pluginSpec.js +++ b/src/plugins/timeline/pluginSpec.js @@ -27,6 +27,7 @@ import EventEmitter from "EventEmitter"; describe('the plugin', function () { let objectDef; + let appHolder; let element; let child; let openmct; @@ -92,6 +93,10 @@ describe('the plugin', function () { }; beforeEach((done) => { + appHolder = document.createElement('div'); + appHolder.style.width = '640px'; + appHolder.style.height = '480px'; + mockObjectPath = [ { name: 'mock folder', @@ -133,7 +138,7 @@ describe('the plugin', function () { element.appendChild(child); openmct.on('start', done); - openmct.startHeadless(); + openmct.start(appHolder); }); afterEach(() => { @@ -167,7 +172,7 @@ describe('the plugin', function () { const applicableViews = openmct.objectViews.get(testViewObject, mockObjectPath); timelineView = applicableViews.find((viewProvider) => viewProvider.key === 'time-strip.view'); - let view = timelineView.view(testViewObject, element); + let view = timelineView.view(testViewObject, mockObjectPath); view.show(child, true); return Vue.nextTick(); @@ -245,7 +250,7 @@ describe('the plugin', function () { beforeEach(done => { const applicableViews = openmct.objectViews.get(testViewObject, mockObjectPath); timelineView = applicableViews.find((viewProvider) => viewProvider.key === 'time-strip.view'); - let view = timelineView.view(testViewObject, element); + let view = timelineView.view(testViewObject, mockObjectPath); view.show(child, true); Vue.nextTick(done); @@ -281,7 +286,7 @@ describe('the plugin', function () { beforeEach((done) => { const applicableViews = openmct.objectViews.get(testViewObject2, mockObjectPath); timelineView = applicableViews.find((viewProvider) => viewProvider.key === 'time-strip.view'); - let view = timelineView.view(testViewObject2, element); + let view = timelineView.view(testViewObject2, mockObjectPath); view.show(child, true); Vue.nextTick(done); diff --git a/src/ui/components/TimeSystemAxis.vue b/src/ui/components/TimeSystemAxis.vue index b8e48d5217..d580b884e6 100644 --- a/src/ui/components/TimeSystemAxis.vue +++ b/src/ui/components/TimeSystemAxis.vue @@ -94,15 +94,13 @@ export default { if (this.openmct.time.clock() === undefined) { let nowMarker = document.querySelector('.nowMarker'); if (nowMarker) { - nowMarker.parentNode.removeChild(nowMarker); + nowMarker.classList.add('hidden'); } } else { let nowMarker = document.querySelector('.nowMarker'); if (nowMarker) { - const svgEl = d3Selection.select(this.svgElement).node(); - let height = svgEl.style('height').replace('px', ''); - height = Number(height) + this.contentHeight; - nowMarker.style.height = height + 'px'; + nowMarker.classList.remove('hidden'); + nowMarker.style.height = this.contentHeight + 'px'; const now = this.xScale(Date.now()); nowMarker.style.left = now + this.offset + 'px'; } diff --git a/src/ui/components/timesystem-axis.scss b/src/ui/components/timesystem-axis.scss index 93b2dbe999..3ad765db04 100644 --- a/src/ui/components/timesystem-axis.scss +++ b/src/ui/components/timesystem-axis.scss @@ -32,6 +32,10 @@ z-index: 10; background: gray; + &.hidden { + display: none; + } + & .icon-arrow-down { font-size: large; position: absolute;