mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57:53 +00:00
Merge branch '7936-add-discrete-event-visualization' of github.com:nasa/openmct into 7936-add-discrete-event-visualization
This commit is contained in:
commit
68fc3172a0
@ -74,7 +74,7 @@ test.describe('Event Timeline View', () => {
|
|||||||
|
|
||||||
// count the event lines
|
// count the event lines
|
||||||
const eventWrappersContainer = page.locator('.c-events-tsv__container');
|
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;
|
const expectedEventWrappersCount = 25;
|
||||||
await expect(eventWrappers).toHaveCount(expectedEventWrappersCount);
|
await expect(eventWrappers).toHaveCount(expectedEventWrappersCount);
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ test.describe('Event Timeline View', () => {
|
|||||||
|
|
||||||
// count the extended lines
|
// count the extended lines
|
||||||
const overlayLinesContainer = page.locator('.c-timeline__overlay-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;
|
const expectedCount = 25;
|
||||||
await expect(extendedLines).toHaveCount(expectedCount);
|
await expect(extendedLines).toHaveCount(expectedCount);
|
||||||
});
|
});
|
||||||
|
@ -25,7 +25,7 @@ export const SEVERITY_CSS = {
|
|||||||
WARNING: 'is-event--yellow',
|
WARNING: 'is-event--yellow',
|
||||||
DISTRESS: 'is-event--red',
|
DISTRESS: 'is-event--red',
|
||||||
CRITICAL: 'is-event--red',
|
CRITICAL: 'is-event--red',
|
||||||
SEVERE: 'is-event--red'
|
SEVERE: 'is-event--purple'
|
||||||
};
|
};
|
||||||
|
|
||||||
const NOMINAL_SEVERITY = {
|
const NOMINAL_SEVERITY = {
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
import { SEVERITY_CSS } from './EventLimitProvider.js';
|
import { SEVERITY_CSS } from './EventLimitProvider.js';
|
||||||
import messages from './transcript.json';
|
import messages from './transcript.json';
|
||||||
|
|
||||||
|
const DUR_MIN = 1000;
|
||||||
|
const DUR_MAX = 10000;
|
||||||
class EventTelemetryProvider {
|
class EventTelemetryProvider {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.defaultSize = 25;
|
this.defaultSize = 25;
|
||||||
@ -34,12 +36,17 @@ class EventTelemetryProvider {
|
|||||||
|
|
||||||
generateData(firstObservedTime, count, startTime, duration, name) {
|
generateData(firstObservedTime, count, startTime, duration, name) {
|
||||||
const millisecondsSinceStart = startTime - firstObservedTime;
|
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 ind = count % messages.length;
|
||||||
const message = messages[ind] + ' - [' + millisecondsSinceStart + ']';
|
const message = messages[ind] + ' - [' + millisecondsSinceStart + ']';
|
||||||
// pick a random severity level + 1 for an undefined level so we can do nominal
|
// pick a random severity level + 1 for an undefined level so we can do nominal
|
||||||
const severity =
|
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 {
|
return {
|
||||||
name,
|
name,
|
||||||
@ -58,7 +65,7 @@ class EventTelemetryProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
subscribe(domainObject, callback) {
|
subscribe(domainObject, callback) {
|
||||||
const duration = domainObject.telemetry.duration * 1000;
|
const duration = domainObject.telemetry.duration * DUR_MIN;
|
||||||
const firstObservedTime = Date.now();
|
const firstObservedTime = Date.now();
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
@ -83,7 +90,7 @@ class EventTelemetryProvider {
|
|||||||
request(domainObject, options) {
|
request(domainObject, options) {
|
||||||
let start = options.start;
|
let start = options.start;
|
||||||
const end = Math.min(Date.now(), options.end); // no future values
|
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 size = options.size ? options.size : this.defaultSize;
|
||||||
const data = [];
|
const data = [];
|
||||||
const firstObservedTime = options.start;
|
const firstObservedTime = options.start;
|
||||||
|
@ -38,7 +38,7 @@ import eventData from '../mixins/eventData.js';
|
|||||||
const PADDING = 1;
|
const PADDING = 1;
|
||||||
const CONTAINER_CLASS = 'c-events-tsv__container';
|
const CONTAINER_CLASS = 'c-events-tsv__container';
|
||||||
const NO_ITEMS_CLASS = 'c-events-tsv__no-items';
|
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 ID_PREFIX = 'wrapper-';
|
||||||
const AXES_PADDING = 20;
|
const AXES_PADDING = 20;
|
||||||
|
|
||||||
@ -403,6 +403,10 @@ export default {
|
|||||||
}
|
}
|
||||||
this.openmct.selection.select(selection, true);
|
this.openmct.selection.select(selection, true);
|
||||||
},
|
},
|
||||||
|
getLimitClass(event) {
|
||||||
|
const limitEvaluation = this.limitEvaluator.evaluate(event, this.valueMetadata);
|
||||||
|
return limitEvaluation?.cssClass;
|
||||||
|
},
|
||||||
createEventWrapper(event) {
|
createEventWrapper(event) {
|
||||||
const id = `${ID_PREFIX}${event.time}`;
|
const id = `${ID_PREFIX}${event.time}`;
|
||||||
const eventWrapper = document.createElement('div');
|
const eventWrapper = document.createElement('div');
|
||||||
@ -413,7 +417,7 @@ export default {
|
|||||||
const textToShow = event[this.titleKey];
|
const textToShow = event[this.titleKey];
|
||||||
eventWrapper.ariaLabel = textToShow;
|
eventWrapper.ariaLabel = textToShow;
|
||||||
eventWrapper.addEventListener('mouseover', () => {
|
eventWrapper.addEventListener('mouseover', () => {
|
||||||
this.showToolTip(textToShow, eventWrapper);
|
this.showToolTip(textToShow, eventWrapper, event);
|
||||||
this.extendedLinesBus.updateHoverExtendEventLine(this.keyString, event.time);
|
this.extendedLinesBus.updateHoverExtendEventLine(this.keyString, event.time);
|
||||||
});
|
});
|
||||||
eventWrapper.addEventListener('mouseleave', () => {
|
eventWrapper.addEventListener('mouseleave', () => {
|
||||||
@ -421,8 +425,7 @@ export default {
|
|||||||
this.extendedLinesBus.updateHoverExtendEventLine(this.keyString, null);
|
this.extendedLinesBus.updateHoverExtendEventLine(this.keyString, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const limitEvaluation = this.limitEvaluator.evaluate(event, this.valueMetadata);
|
const limitClass = this.getLimitClass(event);
|
||||||
const limitClass = limitEvaluation?.cssClass;
|
|
||||||
if (limitClass) {
|
if (limitClass) {
|
||||||
eventWrapper.classList.add(limitClass);
|
eventWrapper.classList.add(limitClass);
|
||||||
event.limitClass = 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({
|
this.tooltip = this.openmct.tooltips.tooltip({
|
||||||
toolTipText: textToShow,
|
toolTipText: textToShow,
|
||||||
toolTipLocation: this.openmct.tooltips.TOOLTIP_LOCATIONS.RIGHT,
|
toolTipLocation: this.openmct.tooltips.TOOLTIP_LOCATIONS.RIGHT,
|
||||||
parentElement: referenceElement,
|
parentElement: referenceElement,
|
||||||
cssClasses: ['c-timeline-event-tooltip']
|
cssClasses: [aClasses.join(' ')]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
.c-events-tsv {
|
||||||
$m: $interiorMargin;
|
$m: $interiorMargin;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -11,21 +24,37 @@
|
|||||||
top: $m; right: 0; bottom: $m; left: 0;
|
top: $m; right: 0; bottom: $m; left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__event-wrapper {
|
&__event-line {
|
||||||
// Wraps an individual event line
|
// Wraps an individual event line
|
||||||
// Also holds the hover flyout element
|
// Also holds the hover flyout element
|
||||||
$c: $colorEventLine;
|
$c: $colorEventLine;
|
||||||
$lineW: $eventLineW;
|
$lineW: $eventLineW;
|
||||||
$hitAreaW: 7px;
|
$hitAreaW: 7px;
|
||||||
$m: $interiorMarginSm;
|
$m: $interiorMarginSm;
|
||||||
background-color: rgba($c, 0.6);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex;
|
display: flex;
|
||||||
top: $m; bottom: $m;
|
top: $m; bottom: $m;
|
||||||
|
transition: box-shadow 250ms ease-out;
|
||||||
width: $lineW;
|
width: $lineW;
|
||||||
z-index: 1;
|
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 {
|
&:before {
|
||||||
// Extend hit area
|
// Extend hit area
|
||||||
content: '';
|
content: '';
|
||||||
@ -36,17 +65,6 @@
|
|||||||
width: $hitAreaW;
|
width: $hitAreaW;
|
||||||
transform: translateX(($hitAreaW - $lineW) * -0.5);
|
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 {
|
&__no-items {
|
||||||
@ -64,3 +82,38 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
z-index: 2;
|
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);
|
||||||
|
}
|
||||||
|
@ -24,18 +24,17 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(lines, key) in extendedLinesPerKey"
|
v-for="(lines, key) in extendedLinesPerKey"
|
||||||
:key="key"
|
:key="key"
|
||||||
class="c-timeline__extended-line-container"
|
class="c-timeline__event-line--extended-container"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(line, index) in lines"
|
v-for="(line, index) in lines"
|
||||||
:id="line.id"
|
:id="line.id"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="c-timeline__extended-line"
|
class="c-timeline__event-line--extended"
|
||||||
:class="[
|
:class="[
|
||||||
line.limitClass,
|
line.limitClass,
|
||||||
{
|
{
|
||||||
'c-timeline__extended-line-hovered':
|
'--hilite': hoveredLineId && hoveredKeyString === key && line.id === hoveredLineId
|
||||||
hoveredLineId && hoveredKeyString === key && line.id === hoveredLineId
|
|
||||||
}
|
}
|
||||||
]"
|
]"
|
||||||
:style="{ left: `${line.x + leftOffset}px`, height: `${height}px` }"
|
:style="{ left: `${line.x + leftOffset}px`, height: `${height}px` }"
|
||||||
|
@ -51,10 +51,4 @@
|
|||||||
pointer-events: none; // Allows clicks to pass through
|
pointer-events: none; // Allows clicks to pass through
|
||||||
z-index: 10; // Ensure it sits atop swimlanes
|
z-index: 10; // Ensure it sits atop swimlanes
|
||||||
}
|
}
|
||||||
|
|
||||||
&__extended-line {
|
|
||||||
position: absolute;
|
|
||||||
width: $eventLineW;
|
|
||||||
background-color: $colorEventLineExtended;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -443,6 +443,10 @@ $colorEventPurpleBg: #31204a;
|
|||||||
$colorEventRedBg: #3c1616;
|
$colorEventRedBg: #3c1616;
|
||||||
$colorEventOrangeBg: #3e2a13;
|
$colorEventOrangeBg: #3e2a13;
|
||||||
$colorEventYellowBg: #3e3316;
|
$colorEventYellowBg: #3e3316;
|
||||||
|
$colorEventPurpleLine: #9e36ff;
|
||||||
|
$colorEventRedLine: #ff2525;
|
||||||
|
$colorEventOrangeLine: #ff8800;
|
||||||
|
$colorEventYellowLine: #fdce22;
|
||||||
|
|
||||||
// Bubble colors
|
// Bubble colors
|
||||||
$colorInfoBubbleBg: #dddddd;
|
$colorInfoBubbleBg: #dddddd;
|
||||||
|
@ -412,6 +412,10 @@ $colorEventPurpleBg: #31204a;
|
|||||||
$colorEventRedBg: #3c1616;
|
$colorEventRedBg: #3c1616;
|
||||||
$colorEventOrangeBg: #3e2a13;
|
$colorEventOrangeBg: #3e2a13;
|
||||||
$colorEventYellowBg: #3e3316;
|
$colorEventYellowBg: #3e3316;
|
||||||
|
$colorEventPurpleLine: #9e36ff;
|
||||||
|
$colorEventRedLine: #ff2525;
|
||||||
|
$colorEventOrangeLine: #ff8800;
|
||||||
|
$colorEventYellowLine: #fdce22;
|
||||||
|
|
||||||
// Bubble colors
|
// Bubble colors
|
||||||
$colorInfoBubbleBg: #dddddd;
|
$colorInfoBubbleBg: #dddddd;
|
||||||
|
@ -428,6 +428,10 @@ $colorEventPurpleBg: #31204a;
|
|||||||
$colorEventRedBg: #3c1616;
|
$colorEventRedBg: #3c1616;
|
||||||
$colorEventOrangeBg: #3e2a13;
|
$colorEventOrangeBg: #3e2a13;
|
||||||
$colorEventYellowBg: #3e3316;
|
$colorEventYellowBg: #3e3316;
|
||||||
|
$colorEventPurpleLine: #9e36ff;
|
||||||
|
$colorEventRedLine: #ff2525;
|
||||||
|
$colorEventOrangeLine: #ff8800;
|
||||||
|
$colorEventYellowLine: #fdce22;
|
||||||
|
|
||||||
// Bubble colors
|
// Bubble colors
|
||||||
$colorInfoBubbleBg: #dddddd;
|
$colorInfoBubbleBg: #dddddd;
|
||||||
|
@ -403,14 +403,18 @@ $colorLimitCyanFg: #d3faff;
|
|||||||
$colorLimitCyanIc: #1795c0;
|
$colorLimitCyanIc: #1795c0;
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
$colorEventPurpleFg: #6433ff;
|
$colorEventPurpleFg: #6f07ed;
|
||||||
$colorEventRedFg: #aa0000;
|
$colorEventRedFg: #aa0000;
|
||||||
$colorEventOrangeFg: #b84900;
|
$colorEventOrangeFg: #b84900;
|
||||||
$colorEventYellowFg: #867109;
|
$colorEventYellowFg: #a98c04;
|
||||||
$colorEventPurpleBg: #ebe7fb;
|
$colorEventPurpleBg: #ebe7fb;
|
||||||
$colorEventRedBg: #fcefef;
|
$colorEventRedBg: #fcefef;
|
||||||
$colorEventOrangeBg: #ffece3;
|
$colorEventOrangeBg: #ffece3;
|
||||||
$colorEventYellowBg: #fdf8eb;
|
$colorEventYellowBg: #fdf8eb;
|
||||||
|
$colorEventPurpleLine: $colorEventPurpleFg;
|
||||||
|
$colorEventRedLine: $colorEventRedFg;
|
||||||
|
$colorEventOrangeLine: $colorEventOrangeFg;
|
||||||
|
$colorEventYellowLine: $colorEventYellowFg;
|
||||||
|
|
||||||
// Bubble colors
|
// Bubble colors
|
||||||
$colorInfoBubbleBg: $colorMenuBg;
|
$colorInfoBubbleBg: $colorMenuBg;
|
||||||
|
@ -252,8 +252,6 @@ tr {
|
|||||||
background-color: $colorEventYellowBg !important;
|
background-color: $colorEventYellowBg !important;
|
||||||
color: $colorEventYellowFg !important;
|
color: $colorEventYellowFg !important;
|
||||||
}
|
}
|
||||||
&--no-style {
|
|
||||||
background-color: $colorBodyBg !important;
|
|
||||||
color: $colorBodyFg !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user