diff --git a/e2e/tests/functional/plugins/event/eventTimelineView.e2e.spec.js b/e2e/tests/functional/plugins/event/eventTimelineView.e2e.spec.js index 689870cb46..99f5e5aad7 100644 --- a/e2e/tests/functional/plugins/event/eventTimelineView.e2e.spec.js +++ b/e2e/tests/functional/plugins/event/eventTimelineView.e2e.spec.js @@ -74,7 +74,7 @@ test.describe('Event Timeline View', () => { // count the event lines const eventWrappersContainer = page.locator('.c-events-tsv__container'); - const eventWrappers = eventWrappersContainer.locator('.c-events-tsv__event-wrapper'); + const eventWrappers = eventWrappersContainer.locator('.c-events-tsv__event-line'); const expectedEventWrappersCount = 25; await expect(eventWrappers).toHaveCount(expectedEventWrappersCount); @@ -104,7 +104,7 @@ test.describe('Event Timeline View', () => { // count the extended lines const overlayLinesContainer = page.locator('.c-timeline__overlay-lines'); - const extendedLines = overlayLinesContainer.locator('.c-timeline__extended-line'); + const extendedLines = overlayLinesContainer.locator('.c-timeline__event-line--extended'); const expectedCount = 25; await expect(extendedLines).toHaveCount(expectedCount); }); diff --git a/example/eventGenerator/EventLimitProvider.js b/example/eventGenerator/EventLimitProvider.js index cd6d765097..6a72bd533c 100644 --- a/example/eventGenerator/EventLimitProvider.js +++ b/example/eventGenerator/EventLimitProvider.js @@ -25,7 +25,7 @@ export const SEVERITY_CSS = { WARNING: 'is-event--yellow', DISTRESS: 'is-event--red', CRITICAL: 'is-event--red', - SEVERE: 'is-event--red' + SEVERE: 'is-event--purple' }; const NOMINAL_SEVERITY = { diff --git a/example/eventGenerator/EventTelemetryProvider.js b/example/eventGenerator/EventTelemetryProvider.js index b952b8358a..faccc68b4e 100644 --- a/example/eventGenerator/EventTelemetryProvider.js +++ b/example/eventGenerator/EventTelemetryProvider.js @@ -27,6 +27,8 @@ import { SEVERITY_CSS } from './EventLimitProvider.js'; import messages from './transcript.json'; +const DUR_MIN = 1000; +const DUR_MAX = 10000; class EventTelemetryProvider { constructor() { this.defaultSize = 25; @@ -34,12 +36,17 @@ class EventTelemetryProvider { generateData(firstObservedTime, count, startTime, duration, name) { const millisecondsSinceStart = startTime - firstObservedTime; - const utc = startTime + count * duration; + const randStartDelay = Math.max(DUR_MIN, Math.random() * DUR_MAX); + const utc = startTime + randStartDelay + count * duration; const ind = count % messages.length; const message = messages[ind] + ' - [' + millisecondsSinceStart + ']'; // pick a random severity level + 1 for an undefined level so we can do nominal const severity = - Object.keys(SEVERITY_CSS)[Math.floor(Math.random() * Object.keys(SEVERITY_CSS).length + 1)]; + Math.random() > 0.4 + ? Object.keys(SEVERITY_CSS)[ + Math.floor(Math.random() * Object.keys(SEVERITY_CSS).length + 1) + ] + : undefined; return { name, @@ -58,7 +65,7 @@ class EventTelemetryProvider { } subscribe(domainObject, callback) { - const duration = domainObject.telemetry.duration * 1000; + const duration = domainObject.telemetry.duration * DUR_MIN; const firstObservedTime = Date.now(); let count = 0; @@ -83,7 +90,7 @@ class EventTelemetryProvider { request(domainObject, options) { let start = options.start; const end = Math.min(Date.now(), options.end); // no future values - const duration = domainObject.telemetry.duration * 1000; + const duration = domainObject.telemetry.duration * DUR_MIN; const size = options.size ? options.size : this.defaultSize; const data = []; const firstObservedTime = options.start; diff --git a/src/plugins/events/components/EventTimelineView.vue b/src/plugins/events/components/EventTimelineView.vue index c99c18d99a..e2718cf7c6 100644 --- a/src/plugins/events/components/EventTimelineView.vue +++ b/src/plugins/events/components/EventTimelineView.vue @@ -38,7 +38,7 @@ import eventData from '../mixins/eventData.js'; const PADDING = 1; const CONTAINER_CLASS = 'c-events-tsv__container'; const NO_ITEMS_CLASS = 'c-events-tsv__no-items'; -const EVENT_WRAPPER_CLASS = 'c-events-tsv__event-wrapper'; +const EVENT_WRAPPER_CLASS = 'c-events-tsv__event-line'; const ID_PREFIX = 'wrapper-'; const AXES_PADDING = 20; @@ -403,6 +403,10 @@ export default { } this.openmct.selection.select(selection, true); }, + getLimitClass(event) { + const limitEvaluation = this.limitEvaluator.evaluate(event, this.valueMetadata); + return limitEvaluation?.cssClass; + }, createEventWrapper(event) { const id = `${ID_PREFIX}${event.time}`; const eventWrapper = document.createElement('div'); @@ -413,7 +417,7 @@ export default { const textToShow = event[this.titleKey]; eventWrapper.ariaLabel = textToShow; eventWrapper.addEventListener('mouseover', () => { - this.showToolTip(textToShow, eventWrapper); + this.showToolTip(textToShow, eventWrapper, event); this.extendedLinesBus.updateHoverExtendEventLine(this.keyString, event.time); }); eventWrapper.addEventListener('mouseleave', () => { @@ -421,8 +425,7 @@ export default { this.extendedLinesBus.updateHoverExtendEventLine(this.keyString, null); }); } - const limitEvaluation = this.limitEvaluator.evaluate(event, this.valueMetadata); - const limitClass = limitEvaluation?.cssClass; + const limitClass = this.getLimitClass(event); if (limitClass) { eventWrapper.classList.add(limitClass); event.limitClass = limitClass; @@ -451,12 +454,22 @@ export default { }); } }, - showToolTip(textToShow, referenceElement) { + showToolTip(textToShow, referenceElement, event) { + const aClasses = ['c-events-tooltip']; + const limitClass = this.getLimitClass(event); + if (limitClass) { + aClasses.push(limitClass); + } + const showToLeft = false; // Temp, stubbed in + if (showToLeft) { + aClasses.push('--left'); + } + this.tooltip = this.openmct.tooltips.tooltip({ toolTipText: textToShow, toolTipLocation: this.openmct.tooltips.TOOLTIP_LOCATIONS.RIGHT, parentElement: referenceElement, - cssClasses: ['c-timeline-event-tooltip'] + cssClasses: [aClasses.join(' ')] }); } } diff --git a/src/plugins/events/components/events-view.scss b/src/plugins/events/components/events-view.scss index fec35d46e5..f48edbab52 100644 --- a/src/plugins/events/components/events-view.scss +++ b/src/plugins/events/components/events-view.scss @@ -1,3 +1,16 @@ +@mixin styleEventLine($colorConst) { + background-color: $colorConst !important; + &:hover, + &[s-selected] { + box-shadow: rgba($colorConst, 0.5) 0 0 0px 4px; + transition: none; + z-index: 2; + } +} +@mixin styleEventLineExtended($colorConst) { + background-color: $colorConst !important; +} + .c-events-tsv { $m: $interiorMargin; overflow: hidden; @@ -11,21 +24,37 @@ top: $m; right: 0; bottom: $m; left: 0; } - &__event-wrapper { + &__event-line { // Wraps an individual event line // Also holds the hover flyout element $c: $colorEventLine; $lineW: $eventLineW; $hitAreaW: 7px; $m: $interiorMarginSm; - background-color: rgba($c, 0.6); cursor: pointer; position: absolute; display: flex; top: $m; bottom: $m; + transition: box-shadow 250ms ease-out; width: $lineW; z-index: 1; + @include styleEventLine($colorEventLine); + &.is-event { + &--purple { + @include styleEventLine($colorEventPurpleLine); + } + &--red { + @include styleEventLine($colorEventRedLine); + } + &--orange { + @include styleEventLine($colorEventOrangeLine); + } + &--yellow { + @include styleEventLine($colorEventYellowLine); + } + } + &:before { // Extend hit area content: ''; @@ -36,17 +65,6 @@ width: $hitAreaW; transform: translateX(($hitAreaW - $lineW) * -0.5); } - - &.is-selected, // TODO: temp, remove this once we set selection correctly - &[s-selected], - &:hover { - z-index: 2; - background-color: $c; - - &:before { - background-color: rgba($c, 0.4); - } - } } &__no-items { @@ -64,3 +82,38 @@ top: 0; z-index: 2; } + +// Extended event lines +.c-timeline__event-line--extended { + @include abs(); + transition: opacity 250ms ease-out; + width: $eventLineW; + opacity: 0.4; + + &.--hilite { + opacity: 0.8; + transition: none; + } + + @include styleEventLineExtended($colorEventLine); + &.is-event { + &--purple { + @include styleEventLineExtended($colorEventPurpleLine); + } + &--red { + @include styleEventLineExtended($colorEventRedLine); + } + &--orange { + @include styleEventLineExtended($colorEventOrangeLine); + } + &--yellow { + @include styleEventLineExtended($colorEventYellowLine); + } + } +} + +.c-events-tooltip { + // Default to right of event line + border-radius: 0 !important; + //transform: translate(0, $interiorMargin); +} diff --git a/src/plugins/timeline/ExtendedLinesOverlay.vue b/src/plugins/timeline/ExtendedLinesOverlay.vue index b9a06ed64d..dfb16fc87e 100644 --- a/src/plugins/timeline/ExtendedLinesOverlay.vue +++ b/src/plugins/timeline/ExtendedLinesOverlay.vue @@ -24,18 +24,17 @@