mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 21:27:52 +00:00
Styling for plot limits (#3917)
* Styling for plot limits and colors * Updates to limit provider and css * Change limits related CSS "*--upper" and "*--lower" to "*--upr" and "*--lwr" for better parity with legacy naming; * Refactor limit class to util * Use new classes for sine wave generator for red-low and yellow-high * Added modifier classes for right and below-aligned labels; * Prevent label overlap of limits as much as possible * Add border colors to limit labels for better visual ties to their lines * Add documentation for limit level specification API change Co-authored-by: Shefali Joshi <simplyrender@gmail.com> Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
d56d176aac
commit
2889e88a97
14
API.md
14
API.md
@ -595,9 +595,17 @@ section.
|
||||
|
||||
#### Limit Evaluators **draft**
|
||||
|
||||
Limit evaluators allow a telemetry integrator to define how limits should be
|
||||
applied to telemetry from a given domain object. For an example of a limit
|
||||
evaluator, take a look at `examples/generator/SinewaveLimitProvider.js`.
|
||||
Limit evaluators allow a telemetry integrator to define which limits exist for a
|
||||
telemetry endpoint and how limits should be applied to telemetry from a given domain object.
|
||||
|
||||
A limit evaluator can implement the `evalute` method which is used to define how limits
|
||||
should be applied to telemetry and the `getLimits` method which is used to specify
|
||||
what the limit values are for different limit levels.
|
||||
|
||||
Limit levels can be mapped to one of 5 colors for visualization:
|
||||
`purple`, `red`, `orange`, `yellow` and `cyan`.
|
||||
|
||||
For an example of a limit evaluator, take a look at `examples/generator/SinewaveLimitProvider.js`.
|
||||
|
||||
### Telemetry Consumer APIs **draft**
|
||||
|
||||
|
@ -26,14 +26,26 @@ define([
|
||||
|
||||
) {
|
||||
|
||||
var RED = {
|
||||
var PURPLE = {
|
||||
sin: 2.2,
|
||||
cos: 2.2
|
||||
},
|
||||
RED = {
|
||||
sin: 0.9,
|
||||
cos: 0.9
|
||||
},
|
||||
ORANGE = {
|
||||
sin: 0.7,
|
||||
cos: 0.7
|
||||
},
|
||||
YELLOW = {
|
||||
sin: 0.5,
|
||||
cos: 0.5
|
||||
},
|
||||
CYAN = {
|
||||
sin: 0.45,
|
||||
cos: 0.45
|
||||
},
|
||||
LIMITS = {
|
||||
rh: {
|
||||
cssClass: "is-limit--upr is-limit--red",
|
||||
@ -94,32 +106,66 @@ define([
|
||||
};
|
||||
|
||||
SinewaveLimitProvider.prototype.getLimits = function (domainObject) {
|
||||
|
||||
return {
|
||||
limits: function () {
|
||||
return {
|
||||
return Promise.resolve({
|
||||
WATCH: {
|
||||
low: {
|
||||
color: "cyan",
|
||||
sin: -CYAN.sin,
|
||||
cos: -CYAN.cos
|
||||
},
|
||||
high: {
|
||||
color: "cyan",
|
||||
...CYAN
|
||||
}
|
||||
},
|
||||
WARNING: {
|
||||
low: {
|
||||
cssClass: "is-limit--lwr is-limit--yellow",
|
||||
color: "yellow",
|
||||
sin: -YELLOW.sin,
|
||||
cos: -YELLOW.cos
|
||||
},
|
||||
high: {
|
||||
cssClass: "is-limit--upr is-limit--yellow",
|
||||
color: "yellow",
|
||||
...YELLOW
|
||||
}
|
||||
},
|
||||
DISTRESS: {
|
||||
low: {
|
||||
cssClass: "is-limit--lwr is-limit--red",
|
||||
color: "orange",
|
||||
sin: -ORANGE.sin,
|
||||
cos: -ORANGE.cos
|
||||
},
|
||||
high: {
|
||||
color: "orange",
|
||||
...ORANGE
|
||||
}
|
||||
},
|
||||
CRITICAL: {
|
||||
low: {
|
||||
color: "red",
|
||||
sin: -RED.sin,
|
||||
cos: -RED.cos
|
||||
},
|
||||
high: {
|
||||
cssClass: "is-limit--upr is-limit--red",
|
||||
color: "red",
|
||||
...RED
|
||||
}
|
||||
},
|
||||
SEVERE: {
|
||||
low: {
|
||||
color: "purple",
|
||||
sin: -PURPLE.sin,
|
||||
cos: -PURPLE.cos
|
||||
},
|
||||
high: {
|
||||
color: "purple",
|
||||
...PURPLE
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -567,21 +567,24 @@ define([
|
||||
* @method limits returns a limits object of
|
||||
* type {
|
||||
* level1: {
|
||||
* low: { key1: value1, key2: value2 },
|
||||
* high: { key1: value1, key2: value2 }
|
||||
* low: { key1: value1, key2: value2, color: <supportedColor> },
|
||||
* high: { key1: value1, key2: value2, color: <supportedColor> }
|
||||
* },
|
||||
* level2: {
|
||||
* low: { key1: value1, key2: value2 },
|
||||
* high: { key1: value1, key2: value2 }
|
||||
* }
|
||||
* }
|
||||
* supported colors are purple, red, orange, yellow and cyan
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
*/
|
||||
TelemetryAPI.prototype.getLimits = function (domainObject) {
|
||||
const provider = this.findLimitEvaluator(domainObject);
|
||||
if (!provider || !provider.getLimits) {
|
||||
return {
|
||||
limits: function () {}
|
||||
limits: function () {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
|
||||
&__value {
|
||||
@include isLimit();
|
||||
}
|
||||
|
||||
.c-frame & {
|
||||
@include abs();
|
||||
border: 1px solid transparent;
|
||||
|
@ -1,17 +1,23 @@
|
||||
<template>
|
||||
<div class="plot-series-limit-label"
|
||||
<div class="c-plot-limit"
|
||||
:style="styleObj"
|
||||
:class="limit.cssClass"
|
||||
:class="limitClass"
|
||||
>
|
||||
<span class="plot-series-limit-value">{{ limit.value }}</span>
|
||||
<span class="plot-series-color-swatch"
|
||||
:style="{ 'background-color': limit.color }"
|
||||
></span>
|
||||
<span class="plot-series-name">{{ limit.name }}</span>
|
||||
<div class="c-plot-limit__label">
|
||||
<span class="c-plot-limit__direction-icon"></span>
|
||||
<span class="c-plot-limit__severity-icon"></span>
|
||||
<span class="c-plot-limit__limit-value">{{ limit.value }}</span>
|
||||
<span class="c-plot-limit__series-color-swatch"
|
||||
:style="{ 'background-color': limit.seriesColor }"
|
||||
></span>
|
||||
<span class="c-plot-limit__series-name">{{ limit.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getLimitClass } from "./limitUtil";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
limit: {
|
||||
@ -31,15 +37,14 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
styleObj() {
|
||||
const top = `${this.point.top - 10}px`;
|
||||
const left = `${this.point.left + 5}px`;
|
||||
const top = `${this.point.top}px`;
|
||||
|
||||
return {
|
||||
'position': 'absolute',
|
||||
'top': top,
|
||||
'left': left,
|
||||
'color': '#fff'
|
||||
'top': top
|
||||
};
|
||||
},
|
||||
limitClass() {
|
||||
return getLimitClass(this.limit, 'c-plot-limit--');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,10 +1,13 @@
|
||||
<template>
|
||||
<hr :style="styleObj"
|
||||
:class="cssWithoutUprLwr"
|
||||
>
|
||||
<div :style="styleObj"
|
||||
class="c-plot-limit-line js-limit-line"
|
||||
:class="limitClass"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getLimitClass } from "./limitUtil";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
point: {
|
||||
@ -14,30 +17,23 @@ export default {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
cssClass: {
|
||||
type: String,
|
||||
limit: {
|
||||
type: Object,
|
||||
default() {
|
||||
return '';
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
styleObj() {
|
||||
const top = `${this.point.top}px`;
|
||||
const left = `${this.point.left}px`;
|
||||
|
||||
return {
|
||||
'position': 'absolute',
|
||||
'width': '100%',
|
||||
'top': top,
|
||||
'left': left
|
||||
'top': top
|
||||
};
|
||||
},
|
||||
cssWithoutUprLwr() {
|
||||
let cssClass = this.cssClass.replace(/is-limit--upr/gi, 'is-limit--line');
|
||||
cssClass = cssClass.replace(/is-limit--lwr/gi, 'is-limit--line');
|
||||
|
||||
return cssClass;
|
||||
limitClass() {
|
||||
return getLimitClass(this.limit, 'c-plot-limit-line--');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -32,6 +32,7 @@ export default class MCTChartAlarmLineSet {
|
||||
|
||||
eventHelpers.extend(this);
|
||||
this.listenTo(series, 'limitBounds', this.updateBounds, this);
|
||||
this.listenTo(series, 'limits', this.getLimitPoints, this);
|
||||
this.listenTo(series, 'change:xKey', this.getLimitPoints, this);
|
||||
|
||||
if (series.limits) {
|
||||
@ -69,26 +70,28 @@ export default class MCTChartAlarmLineSet {
|
||||
Object.keys(series.limits).forEach((key) => {
|
||||
const limitForLevel = series.limits[key];
|
||||
if (limitForLevel.high) {
|
||||
const point = this.makePoint(Object.assign({ [xKey]: this.bounds.start }, limitForLevel.high), series);
|
||||
this.limits.push({
|
||||
seriesKey: series.keyString,
|
||||
value: series.getYVal(limitForLevel.high),
|
||||
color: this.color().asHexString(),
|
||||
level: key.toLowerCase(),
|
||||
name: this.name(),
|
||||
point,
|
||||
cssClass: limitForLevel.high.cssClass
|
||||
seriesColor: series.get('color').asHexString(),
|
||||
point: this.makePoint(Object.assign({ [xKey]: this.bounds.start }, limitForLevel.high), series),
|
||||
value: series.getYVal(limitForLevel.high),
|
||||
color: limitForLevel.high.color,
|
||||
isUpper: true
|
||||
});
|
||||
}
|
||||
|
||||
if (limitForLevel.low) {
|
||||
const point = this.makePoint(Object.assign({ [xKey]: this.bounds.start }, limitForLevel.low), series);
|
||||
this.limits.push({
|
||||
seriesKey: series.keyString,
|
||||
value: series.getYVal(limitForLevel.low),
|
||||
color: this.color().asHexString(),
|
||||
level: key.toLowerCase(),
|
||||
name: this.name(),
|
||||
point,
|
||||
cssClass: limitForLevel.low.cssClass
|
||||
seriesColor: series.get('color').asHexString(),
|
||||
point: this.makePoint(Object.assign({ [xKey]: this.bounds.start }, limitForLevel.low), series),
|
||||
value: series.getYVal(limitForLevel.low),
|
||||
color: limitForLevel.low.color,
|
||||
isUpper: false
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
|
@ -46,6 +46,7 @@ import Vue from 'vue';
|
||||
|
||||
const MARKER_SIZE = 6.0;
|
||||
const HIGHLIGHT_SIZE = MARKER_SIZE * 2.0;
|
||||
const CLEARANCE = 15;
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'domainObject'],
|
||||
@ -472,13 +473,15 @@ export default {
|
||||
}
|
||||
|
||||
Array.from(this.$refs.limitArea.children).forEach((el) => el.remove());
|
||||
|
||||
let limitPointOverlap = [];
|
||||
this.limitLines.forEach((limitLine) => {
|
||||
let limitContainerEl = this.$refs.limitArea;
|
||||
limitLine.limits.forEach((limit) => {
|
||||
const showLabels = this.showLabels(limit.seriesKey);
|
||||
if (showLabels) {
|
||||
let limitLabelEl = this.getLimitLabel(limit);
|
||||
const overlap = this.getLimitOverlap(limit, limitPointOverlap);
|
||||
limitPointOverlap.push(overlap);
|
||||
let limitLabelEl = this.getLimitLabel(limit, overlap);
|
||||
limitContainerEl.appendChild(limitLabelEl);
|
||||
}
|
||||
|
||||
@ -502,14 +505,41 @@ export default {
|
||||
const component = new LimitLineClass({
|
||||
propsData: {
|
||||
point,
|
||||
cssClass: limit.cssClass
|
||||
limit
|
||||
}
|
||||
});
|
||||
component.$mount();
|
||||
|
||||
return component.$el;
|
||||
},
|
||||
getLimitLabel(limit) {
|
||||
getLimitOverlap(limit, overlapMap) {
|
||||
//calculate if limit lines are too close to each other
|
||||
let limitTop = this.drawAPI.y(limit.point.y);
|
||||
const needsVerticalAdjustment = limitTop - CLEARANCE <= 0;
|
||||
let needsHorizontalAdjustment = false;
|
||||
overlapMap.forEach(value => {
|
||||
let diffTop;
|
||||
if (limitTop > value.overlapTop) {
|
||||
diffTop = limitTop - value.overlapTop;
|
||||
} else {
|
||||
diffTop = value.overlapTop - limitTop;
|
||||
}
|
||||
|
||||
//need to compare +ves to +ves and -ves to -ves
|
||||
if (!needsHorizontalAdjustment
|
||||
&& Math.abs(diffTop) <= CLEARANCE
|
||||
&& value.needsHorizontalAdjustment !== true) {
|
||||
needsHorizontalAdjustment = true;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
needsHorizontalAdjustment,
|
||||
needsVerticalAdjustment,
|
||||
overlapTop: limitTop
|
||||
};
|
||||
},
|
||||
getLimitLabel(limit, overlap) {
|
||||
let point = {
|
||||
left: 0,
|
||||
top: this.drawAPI.y(limit.point.y)
|
||||
@ -517,7 +547,7 @@ export default {
|
||||
let LimitLabelClass = Vue.extend(LimitLabel);
|
||||
const component = new LimitLabelClass({
|
||||
propsData: {
|
||||
limit,
|
||||
limit: Object.assign({}, overlap, limit),
|
||||
point
|
||||
}
|
||||
});
|
||||
|
32
src/plugins/plot/chart/limitUtil.js
Normal file
32
src/plugins/plot/chart/limitUtil.js
Normal file
@ -0,0 +1,32 @@
|
||||
export function getLimitClass(limit, prefix) {
|
||||
let cssClass = '';
|
||||
//If color exists then use it, fall back to the cssClass
|
||||
if (limit.color) {
|
||||
cssClass = `${cssClass} ${prefix}${limit.color}`;
|
||||
} else if (limit.cssClass) {
|
||||
cssClass = `${cssClass}${limit.cssClass}`;
|
||||
}
|
||||
|
||||
// If we applied the cssClass then skip these classes
|
||||
if (limit.cssClass === undefined) {
|
||||
if (limit.isUpper) {
|
||||
cssClass = `${cssClass} ${prefix}upr`;
|
||||
} else {
|
||||
cssClass = `${cssClass} ${prefix}lwr`;
|
||||
}
|
||||
|
||||
if (limit.level) {
|
||||
cssClass = `${cssClass} ${prefix}${limit.level}`;
|
||||
}
|
||||
|
||||
if (limit.needsHorizontalAdjustment) {
|
||||
cssClass = `${cssClass} --align-label-right`;
|
||||
}
|
||||
|
||||
if (limit.needsVerticalAdjustment) {
|
||||
cssClass = `${cssClass} --align-label-below`;
|
||||
}
|
||||
}
|
||||
|
||||
return cssClass;
|
||||
}
|
@ -117,7 +117,17 @@ export default class PlotSeries extends Model {
|
||||
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(options.domainObject);
|
||||
this.limitDefinition = this.openmct.telemetry.limitDefinition(options.domainObject);
|
||||
this.limits = this.limitDefinition.limits();
|
||||
this.limits = [];
|
||||
this.limitDefinition.limits().then(response => {
|
||||
this.limits = [];
|
||||
|
||||
if (response) {
|
||||
this.limits = response;
|
||||
}
|
||||
|
||||
this.emit('limits', this);
|
||||
|
||||
});
|
||||
this.openmct.time.on('bounds', this.updateLimits);
|
||||
this.on('destroy', this.onDestroy, this);
|
||||
}
|
||||
|
@ -49,6 +49,8 @@
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import {getLimitClass} from "@/plugins/plot/chart/limitUtil";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
valueToShowWhenCollapsed: {
|
||||
@ -110,7 +112,7 @@ export default {
|
||||
if (closest) {
|
||||
this.formattedYValue = seriesObject.formatY(closest);
|
||||
this.formattedXValue = seriesObject.formatX(closest);
|
||||
this.mctLimitStateClass = closest.mctLimitState ? `${closest.mctLimitState.cssClass}` : '';
|
||||
this.mctLimitStateClass = closest.mctLimitState ? getLimitClass(closest.mctLimitState, 'c-plot-limit--') : '';
|
||||
} else {
|
||||
this.formattedYValue = '';
|
||||
this.formattedXValue = '';
|
||||
|
@ -74,6 +74,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getLimitClass} from "@/plugins/plot/chart/limitUtil";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
seriesObject: {
|
||||
@ -147,7 +149,7 @@ export default {
|
||||
if (closest) {
|
||||
this.formattedYValue = seriesObject.formatY(closest);
|
||||
this.formattedXValue = seriesObject.formatX(closest);
|
||||
this.mctLimitStateClass = seriesObject.closest.mctLimitState ? seriesObject.closest.mctLimitState.cssClass : '';
|
||||
this.mctLimitStateClass = seriesObject.closest.mctLimitState ? getLimitClass(seriesObject.closest.mctLimitState, 'c-plot-limit--') : '';
|
||||
} else {
|
||||
this.formattedYValue = '';
|
||||
this.formattedXValue = '';
|
||||
|
@ -21,36 +21,36 @@
|
||||
*****************************************************************************/
|
||||
|
||||
export const COLOR_PALETTE = [
|
||||
[0x20, 0xB2, 0xAA],
|
||||
[0x9A, 0xCD, 0x32],
|
||||
[0xFF, 0x8C, 0x00],
|
||||
[0xD2, 0xB4, 0x8C],
|
||||
[0x40, 0xE0, 0xD0],
|
||||
[0x41, 0x69, 0xFF],
|
||||
[0xFF, 0xD7, 0x00],
|
||||
[0x6A, 0x5A, 0xCD],
|
||||
[0xEE, 0x82, 0xEE],
|
||||
[0xCC, 0x99, 0x66],
|
||||
[0x99, 0xCC, 0xCC],
|
||||
[0x66, 0xCC, 0x33],
|
||||
[0xFF, 0xCC, 0x00],
|
||||
[0xFF, 0x66, 0x33],
|
||||
[0xCC, 0x66, 0xFF],
|
||||
[0xFF, 0x00, 0x66],
|
||||
[0xFF, 0xFF, 0x00],
|
||||
[0x80, 0x00, 0x80],
|
||||
[0x00, 0x86, 0x8B],
|
||||
[0x00, 0x8A, 0x00],
|
||||
[0xFF, 0x00, 0x00],
|
||||
[0x00, 0x00, 0xFF],
|
||||
[0xF5, 0xDE, 0xB3],
|
||||
[0xBC, 0x8F, 0x8F],
|
||||
[0x46, 0x82, 0xB4],
|
||||
[0xFF, 0xAF, 0xAF],
|
||||
[0x43, 0xCD, 0x80],
|
||||
[0xCD, 0xC1, 0xC5],
|
||||
[0xA0, 0x52, 0x2D],
|
||||
[0x64, 0x95, 0xED]
|
||||
[0x00, 0x37, 0xFF],
|
||||
[0xF0, 0x60, 0x00],
|
||||
[0x00, 0x70, 0x40],
|
||||
[0xFB, 0x49, 0x49],
|
||||
[0xC8, 0x00, 0xCF],
|
||||
[0x55, 0x77, 0xF2],
|
||||
[0xFF, 0xA6, 0x3D],
|
||||
[0x05, 0xA3, 0x00],
|
||||
[0xF0, 0x00, 0x6C],
|
||||
[0x77, 0x17, 0x7A],
|
||||
[0x23, 0xA9, 0xDB],
|
||||
[0xFA, 0xF0, 0x6F],
|
||||
[0x4E, 0xF0, 0x48],
|
||||
[0xAD, 0x50, 0x72],
|
||||
[0x94, 0x25, 0xEA],
|
||||
[0x21, 0x87, 0x82],
|
||||
[0x8F, 0x6E, 0x47],
|
||||
[0xf0, 0x59, 0xcb],
|
||||
[0x34, 0xB6, 0x7D],
|
||||
[0x6A, 0x36, 0xFF],
|
||||
[0x56, 0xF0, 0xE8],
|
||||
[0xA1, 0x8C, 0x1C],
|
||||
[0xCB, 0xE1, 0x44],
|
||||
[0xFF, 0x84, 0x9E],
|
||||
[0xB7, 0x79, 0xE7],
|
||||
[0x8C, 0xC9, 0xFD],
|
||||
[0xDB, 0xAA, 0x6E],
|
||||
[0xB8, 0xDF, 0x97],
|
||||
[0xFF, 0xBC, 0xDA],
|
||||
[0xD3, 0xB6, 0xDE]
|
||||
];
|
||||
|
||||
export function isDefaultColor(color) {
|
||||
|
@ -97,7 +97,7 @@ describe("the plugin", function () {
|
||||
telemetrylimitProvider.supportsLimits.and.returnValue(true);
|
||||
telemetrylimitProvider.getLimits.and.returnValue({
|
||||
limits: function () {
|
||||
return {
|
||||
return Promise.resolve({
|
||||
WARNING: {
|
||||
low: {
|
||||
cssClass: "is-limit--lwr is-limit--yellow",
|
||||
@ -118,7 +118,7 @@ describe("the plugin", function () {
|
||||
'some-key': 0.9
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
telemetrylimitProvider.getLimitEvaluator.and.returnValue({
|
||||
@ -709,7 +709,7 @@ describe("the plugin", function () {
|
||||
config.series.models[0].set('limitLines', true);
|
||||
|
||||
Vue.nextTick(() => {
|
||||
let limitEl = element.querySelectorAll(".js-limit-area hr");
|
||||
let limitEl = element.querySelectorAll(".js-limit-area .js-limit-line");
|
||||
expect(limitEl.length).toBe(4);
|
||||
done();
|
||||
});
|
||||
|
@ -190,6 +190,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
// All tables
|
||||
td {
|
||||
@include isLimit();
|
||||
}
|
||||
|
||||
/******************************* SPECIFIC CASE WRAPPERS */
|
||||
.is-editing {
|
||||
.c-telemetry-table__headers__labels {
|
||||
|
@ -10,6 +10,7 @@
|
||||
@import "../../styles/glyphs";
|
||||
@import "../../styles/global";
|
||||
@import "../../styles/status";
|
||||
@import "../../styles/limits";
|
||||
@import "../../styles/controls";
|
||||
@import "../../styles/forms";
|
||||
@import "../../styles/table";
|
||||
|
@ -10,6 +10,7 @@
|
||||
@import "../../styles/glyphs";
|
||||
@import "../../styles/global";
|
||||
@import "../../styles/status";
|
||||
@import "../../styles/limits";
|
||||
@import "../../styles/controls";
|
||||
@import "../../styles/forms";
|
||||
@import "../../styles/table";
|
||||
|
@ -10,6 +10,7 @@
|
||||
@import "../../styles/glyphs";
|
||||
@import "../../styles/global";
|
||||
@import "../../styles/status";
|
||||
@import "../../styles/limits";
|
||||
@import "../../styles/controls";
|
||||
@import "../../styles/forms";
|
||||
@import "../../styles/table";
|
||||
|
@ -314,12 +314,21 @@ $colorTelemStale: pushBack($colorBodyFg, 20%);
|
||||
$styleTelemStale: italic;
|
||||
|
||||
// Limits
|
||||
$colorLimitYellowBg: #ac7300;
|
||||
$colorLimitYellowFg: #ffe64d;
|
||||
$colorLimitYellowIc: #ffb607;
|
||||
$colorLimitYellowBg: #B18B05;
|
||||
$colorLimitYellowFg: #FEEEB5;
|
||||
$colorLimitYellowIc: #FDC707;
|
||||
$colorLimitOrangeBg: #B36B00;
|
||||
$colorLimitOrangeFg: #FFE0B2;
|
||||
$colorLimitOrangeIc: #ff9900;
|
||||
$colorLimitRedBg: #940000;
|
||||
$colorLimitRedFg: #ffa489;
|
||||
$colorLimitRedIc: #ff4222;
|
||||
$colorLimitPurpleBg: #891BB3;
|
||||
$colorLimitPurpleFg: #EDBEFF;
|
||||
$colorLimitPurpleIc: #c327ff;
|
||||
$colorLimitCyanBg: #4BA6B3;
|
||||
$colorLimitCyanFg: #D3FAFF;
|
||||
$colorLimitCyanIc: #6BEDFF;
|
||||
|
||||
// Bubble colors
|
||||
$colorInfoBubbleBg: #dddddd;
|
||||
@ -359,6 +368,7 @@ $colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
$legendHoverValueBg: rgba($colorBodyFg, 0.2);
|
||||
$legendTableHeadBg: $colorTabHeaderBg;
|
||||
$colorPlotLimitLineBg: rgba($colorBodyBg, 0.2);
|
||||
|
||||
// Tree
|
||||
$colorTreeBg: transparent;
|
||||
|
@ -318,12 +318,21 @@ $colorTelemStale: pushBack($colorBodyFg, 20%);
|
||||
$styleTelemStale: italic;
|
||||
|
||||
// Limits
|
||||
$colorLimitYellowBg: #ac7300;
|
||||
$colorLimitYellowFg: #ffe64d;
|
||||
$colorLimitYellowIc: #ffb607;
|
||||
$colorLimitYellowBg: #B18B05;
|
||||
$colorLimitYellowFg: #FEEEB5;
|
||||
$colorLimitYellowIc: #FDC707;
|
||||
$colorLimitOrangeBg: #B36B00;
|
||||
$colorLimitOrangeFg: #FFE0B2;
|
||||
$colorLimitOrangeIc: #ff9900;
|
||||
$colorLimitRedBg: #940000;
|
||||
$colorLimitRedFg: #ffa489;
|
||||
$colorLimitRedIc: #ff4222;
|
||||
$colorLimitPurpleBg: #891BB3;
|
||||
$colorLimitPurpleFg: #EDBEFF;
|
||||
$colorLimitPurpleIc: #c327ff;
|
||||
$colorLimitCyanBg: #4BA6B3;
|
||||
$colorLimitCyanFg: #D3FAFF;
|
||||
$colorLimitCyanIc: #6BEDFF;
|
||||
|
||||
// Bubble colors
|
||||
$colorInfoBubbleBg: #dddddd;
|
||||
@ -363,6 +372,7 @@ $colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
$legendHoverValueBg: rgba($colorBodyFg, 0.2);
|
||||
$legendTableHeadBg: rgba($colorBodyFg, 0.15);
|
||||
$colorPlotLimitLineBg: rgba($colorBodyBg, 0.2);
|
||||
|
||||
// Tree
|
||||
$colorTreeBg: transparent;
|
||||
|
@ -317,9 +317,18 @@ $styleTelemStale: italic;
|
||||
$colorLimitYellowBg: #ffe64d;
|
||||
$colorLimitYellowFg: #7f4f20;
|
||||
$colorLimitYellowIc: #e7a115;
|
||||
$colorLimitOrangeBg: #B36B00;
|
||||
$colorLimitOrangeFg: #FFE0B2;
|
||||
$colorLimitOrangeIc: #ff9900;
|
||||
$colorLimitRedBg: #ff0000;
|
||||
$colorLimitRedFg: #fff;
|
||||
$colorLimitRedIc: #ffa99a;
|
||||
$colorLimitPurpleBg: #891BB3;
|
||||
$colorLimitPurpleFg: #EDBEFF;
|
||||
$colorLimitPurpleIc: #c327ff;
|
||||
$colorLimitCyanBg: #4BA6B3;
|
||||
$colorLimitCyanFg: #D3FAFF;
|
||||
$colorLimitCyanIc: #1795c0;
|
||||
|
||||
// Bubble colors
|
||||
$colorInfoBubbleBg: $colorMenuBg;
|
||||
@ -359,6 +368,7 @@ $colorPlotAreaBorder: $colorInteriorBorder;
|
||||
$colorPlotLabelFg: pushBack($colorPlotFg, 20%);
|
||||
$legendHoverValueBg: rgba($colorBodyFg, 0.2);
|
||||
$legendTableHeadBg: rgba($colorBodyFg, 0.15);
|
||||
$colorPlotLimitLineBg: rgba($colorBodyBg, 0.4);
|
||||
|
||||
// Tree
|
||||
$colorTreeBg: transparent;
|
||||
|
@ -136,6 +136,7 @@ mct-plot {
|
||||
left: nth($plotDisplayArea, 4);
|
||||
|
||||
.gl-plot-display-area {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@ -538,12 +539,9 @@ mct-plot {
|
||||
}
|
||||
|
||||
.plot-series-color-swatch {
|
||||
border-radius: 30%; //$smallCr;
|
||||
border: 1px solid $colorBodyBg;
|
||||
@include colorSwatch();
|
||||
display: inline-block;
|
||||
flex: 0 0 auto;
|
||||
height: $plotSwatchD;
|
||||
width: $plotSwatchD;
|
||||
}
|
||||
.plot-series-name {
|
||||
display: inline;
|
||||
@ -552,6 +550,7 @@ mct-plot {
|
||||
|
||||
.plot-series-value {
|
||||
@include ellipsize();
|
||||
@include isLimit();
|
||||
}
|
||||
}
|
||||
|
||||
|
270
src/styles/_limits.scss
Normal file
270
src/styles/_limits.scss
Normal file
@ -0,0 +1,270 @@
|
||||
$plotLimitLineSize: 1px;
|
||||
$plotLimitDashWidthOffset: 10px;
|
||||
$lineBlocker: $colorPlotLimitLineBg;
|
||||
$plotLimitDashWidthSeverity: 50px;
|
||||
$plotLimitDashWidthCritical: $plotLimitDashWidthSeverity - $plotLimitDashWidthOffset;
|
||||
$plotLimitDashWidthDistress: $plotLimitDashWidthCritical - $plotLimitDashWidthOffset;
|
||||
$plotLimitDashWidthWarning: $plotLimitDashWidthDistress - $plotLimitDashWidthOffset;
|
||||
$plotLimitDashWidthWatch: $plotLimitDashWidthWarning - $plotLimitDashWidthOffset;
|
||||
|
||||
@mixin plotLimitLine($c, $breakPerc) {
|
||||
background: $lineBlocker linear-gradient(
|
||||
90deg,
|
||||
$c $breakPerc,
|
||||
transparent $breakPerc,
|
||||
transparent 100%
|
||||
) repeat-x;
|
||||
}
|
||||
|
||||
@mixin plotLimitDirectionGradient($c, $deg: 0deg) {
|
||||
background: linear-gradient(
|
||||
$deg,
|
||||
$c,
|
||||
transparent
|
||||
)
|
||||
}
|
||||
|
||||
@mixin plotLimitLineUpper($c) {
|
||||
$breakPerc: 80%;
|
||||
@include plotLimitLine($c: $c, $breakPerc: $breakPerc);
|
||||
}
|
||||
|
||||
@mixin plotLimitLineLower($c) {
|
||||
$breakPerc: 30%;
|
||||
@include plotLimitLine($c: $c, $breakPerc: $breakPerc);
|
||||
}
|
||||
|
||||
.c-plot-limit-line {
|
||||
box-shadow: $lineBlocker 0 0 0 2px;
|
||||
height: $plotLimitLineSize;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
|
||||
// Colors and directions
|
||||
&--purple.c-plot-limit-line--upr {
|
||||
@include plotLimitLineUpper($colorLimitPurpleIc);
|
||||
}
|
||||
|
||||
&--purple.c-plot-limit-line--lwr {
|
||||
@include plotLimitLineLower($colorLimitPurpleIc);
|
||||
}
|
||||
|
||||
&--red.c-plot-limit-line--upr {
|
||||
@include plotLimitLineUpper($colorLimitRedIc);
|
||||
}
|
||||
|
||||
&--red.c-plot-limit-line--lwr {
|
||||
@include plotLimitLineLower($colorLimitRedIc);
|
||||
}
|
||||
|
||||
&--orange.c-plot-limit-line--upr {
|
||||
@include plotLimitLineUpper($colorLimitOrangeIc);
|
||||
}
|
||||
|
||||
&--orange.c-plot-limit-line--lwr {
|
||||
@include plotLimitLineLower($colorLimitOrangeIc);
|
||||
}
|
||||
|
||||
&--yellow.c-plot-limit-line--upr {
|
||||
@include plotLimitLineUpper($colorLimitYellowIc);
|
||||
}
|
||||
|
||||
&--yellow.c-plot-limit-line--lwr {
|
||||
@include plotLimitLineLower($colorLimitYellowIc);
|
||||
}
|
||||
|
||||
&--cyan.c-plot-limit-line--upr {
|
||||
@include plotLimitLineUpper($colorLimitCyanIc);
|
||||
}
|
||||
|
||||
&--cyan.c-plot-limit-line--lwr {
|
||||
@include plotLimitLineLower($colorLimitCyanIc);
|
||||
}
|
||||
|
||||
// Severities
|
||||
&--severe {
|
||||
background-size: $plotLimitDashWidthSeverity 100% !important;
|
||||
}
|
||||
|
||||
&--critical {
|
||||
background-size: $plotLimitDashWidthCritical 100% !important;
|
||||
}
|
||||
|
||||
&--distress {
|
||||
background-size: $plotLimitDashWidthDistress 100% !important;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
background-size: $plotLimitDashWidthWarning 100% !important;
|
||||
}
|
||||
|
||||
&--watch {
|
||||
background-size: $plotLimitDashWidthWatch 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.c-plot-limit {
|
||||
// Holds both label and directional gradient
|
||||
$labelCr: $basicCr;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
|
||||
&__label {
|
||||
border-width: 1px 1px 0 0;
|
||||
border-style: solid;
|
||||
border-radius: 0 $labelCr 0 0;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
padding: 2px 4px;
|
||||
transform: translateY(-100%);
|
||||
|
||||
> * + * {
|
||||
margin-left: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
|
||||
&.--align-label-right {
|
||||
justify-content: flex-end;
|
||||
.c-plot-limit__label {
|
||||
border-radius: $labelCr 0 0 0;
|
||||
border-width: 1px 0 0 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&.--align-label-below {
|
||||
.c-plot-limit__label {
|
||||
border-radius: 0 0 $labelCr 0;
|
||||
border-width: 0 1px 1px 0;
|
||||
transform: translateY(0);
|
||||
}
|
||||
&.--align-label-right {
|
||||
.c-plot-limit__label {
|
||||
border-radius: 0 0 0 $labelCr;
|
||||
border-width: 0 0 1px 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[class*='icon'] {
|
||||
&:before {
|
||||
display: block;
|
||||
font-family: symbolsfont;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
&__series-color-swatch {
|
||||
@include colorSwatch();
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
&:before {
|
||||
// Direction gradient
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
&--upr:before {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
&--lwr:before {
|
||||
transform: scaleY(-1); // This inverts the gradient direction
|
||||
}
|
||||
|
||||
// Label styling
|
||||
&--purple [class*='label'] {
|
||||
background-color: $colorLimitPurpleBg;
|
||||
border-color: $colorLimitPurpleIc;
|
||||
color: $colorLimitPurpleFg;
|
||||
}
|
||||
|
||||
&--red [class*='label'] {
|
||||
background-color: $colorLimitRedBg;
|
||||
border-color: $colorLimitRedIc;
|
||||
color: $colorLimitRedFg;
|
||||
}
|
||||
|
||||
&--orange [class*='label'] {
|
||||
background-color: $colorLimitOrangeBg;
|
||||
border-color: $colorLimitOrangeIc;
|
||||
color: $colorLimitOrangeFg;
|
||||
}
|
||||
|
||||
&--yellow [class*='label'] {
|
||||
background-color: $colorLimitYellowBg;
|
||||
border-color: $colorLimitYellowIc;
|
||||
color: $colorLimitYellowFg;
|
||||
}
|
||||
|
||||
&--cyan [class*='label'] {
|
||||
background-color: $colorLimitCyanBg;
|
||||
border-color: $colorLimitCyanIc;
|
||||
color: $colorLimitCyanFg;
|
||||
}
|
||||
|
||||
// Directional gradients
|
||||
&--purple:before {
|
||||
@include plotLimitDirectionGradient($c: $colorLimitPurpleIc);
|
||||
}
|
||||
|
||||
&--red:before {
|
||||
@include plotLimitDirectionGradient($c: $colorLimitRedIc);
|
||||
}
|
||||
|
||||
&--orange:before {
|
||||
@include plotLimitDirectionGradient($c: $colorLimitOrangeIc);
|
||||
}
|
||||
|
||||
&--yellow:before {
|
||||
@include plotLimitDirectionGradient($c: $colorLimitYellowIc);
|
||||
}
|
||||
|
||||
&--cyan:before {
|
||||
@include plotLimitDirectionGradient($c: $colorLimitCyanIc);
|
||||
}
|
||||
}
|
||||
|
||||
// Severity icons
|
||||
.c-plot-limit__label .c-plot-limit__severity-icon:before {
|
||||
.c-plot-limit--severe & {
|
||||
content: $glyph-icon-alert-triangle;
|
||||
}
|
||||
|
||||
.c-plot-limit--critical & {
|
||||
content: $glyph-icon-alert-rect;
|
||||
}
|
||||
|
||||
.c-plot-limit--distress & {
|
||||
content: $glyph-icon-bell;
|
||||
}
|
||||
|
||||
.c-plot-limit--warning & {
|
||||
content: $glyph-icon-asterisk;
|
||||
}
|
||||
|
||||
.c-plot-limit--watch & {
|
||||
content: $glyph-icon-eye-open;
|
||||
}
|
||||
}
|
||||
|
||||
// Direction icons
|
||||
.c-plot-limit__label .c-plot-limit__direction-icon:before {
|
||||
.c-plot-limit--upr & {
|
||||
content: $glyph-icon-arrow-up;
|
||||
}
|
||||
|
||||
.c-plot-limit--lwr & {
|
||||
content: $glyph-icon-arrow-down;
|
||||
}
|
||||
}
|
@ -151,6 +151,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
@mixin isLimit() {
|
||||
&[class*='is-limit'] {
|
||||
&:before {
|
||||
display: inline-block;
|
||||
font-family: symbolsfont;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-limit--lwr:before { content: $glyph-icon-arrow-down; }
|
||||
&.is-limit--upr:before { content: $glyph-icon-arrow-up; }
|
||||
|
||||
&.is-limit--purple { background: $colorLimitPurpleBg !important; color: $colorLimitPurpleFg !important; }
|
||||
&.is-limit--red { background: $colorLimitRedBg !important; color: $colorLimitRedFg !important; }
|
||||
&.is-limit--orange { background: $colorLimitOrangeBg !important; color: $colorLimitOrangeFg !important; }
|
||||
&.is-limit--yellow { background: $colorLimitYellowBg !important; color: $colorLimitYellowFg !important; }
|
||||
&.is-limit--cyan { background: $colorLimitCyanBg !important; color: $colorLimitCyanFg !important; }
|
||||
}
|
||||
|
||||
@mixin bgDiagonalStripes($c: yellow, $a: 0.1, $d: 40px) {
|
||||
background-image: linear-gradient(-45deg,
|
||||
rgba($c, $a) 25%, transparent 25%,
|
||||
@ -222,6 +241,13 @@
|
||||
background-size: $bgSize;
|
||||
}
|
||||
|
||||
@mixin colorSwatch() {
|
||||
border-radius: 30%;
|
||||
border: 1px solid $colorBodyBg;
|
||||
height: $plotSwatchD;
|
||||
width: $plotSwatchD;
|
||||
}
|
||||
|
||||
@mixin noColor() {
|
||||
// A "no fill/stroke" selection option. Used in palettes.
|
||||
$c: red;
|
||||
|
@ -65,15 +65,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@mixin andUprLwr {
|
||||
&.is-limit--upr:before { content: $glyph-icon-arrow-up !important; }
|
||||
&.is-limit--lwr:before { content: $glyph-icon-arrow-down !important; }
|
||||
}
|
||||
|
||||
@mixin andLine {
|
||||
&.is-limit--line:before { content: '' !important; }
|
||||
}
|
||||
|
||||
@mixin uIndicator($bg, $fg, $glyph) {
|
||||
background: $bg;
|
||||
color: $fg;
|
||||
@ -95,26 +86,9 @@
|
||||
display: inline-block;
|
||||
padding: 2px $interiorMargin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*************************************************** STYLES */
|
||||
*:not(tr) {
|
||||
&.is-limit--yellow {
|
||||
@include statusStyle($colorLimitYellowBg, $colorLimitYellowFg, true);
|
||||
@include statusIcon($colorLimitYellowIc, $glyph-icon-alert-rect);
|
||||
@include andUprLwr();
|
||||
@include andLine();
|
||||
}
|
||||
|
||||
&.is-limit--red {
|
||||
@include statusStyle($colorLimitRedBg, $colorLimitRedFg, true);
|
||||
@include statusIcon($colorLimitRedIc, $glyph-icon-alert-triangle);
|
||||
@include andUprLwr();
|
||||
@include andLine();
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
&.is-limit--yellow {
|
||||
@include statusStyle($colorLimitYellowBg, $colorLimitYellowFg);
|
||||
|
Loading…
Reference in New Issue
Block a user