chore: add prettier (2/3): apply formatting, re-enable lint ci step (#6682)

* style: apply prettier formatting

* fix: re-enable lint ci check
This commit is contained in:
Jesse Mazzella
2023-05-18 14:54:46 -07:00
committed by GitHub
parent 172e0b23fd
commit caa7bc6fae
976 changed files with 115922 additions and 114693 deletions

View File

@ -25,74 +25,76 @@ import AlphanumericFormat from './components/AlphanumericFormat.vue';
import Vue from 'vue';
class AlphanumericFormatView {
constructor(openmct, domainObject, objectPath) {
this.openmct = openmct;
this.domainObject = domainObject;
this.objectPath = objectPath;
this.component = undefined;
constructor(openmct, domainObject, objectPath) {
this.openmct = openmct;
this.domainObject = domainObject;
this.objectPath = objectPath;
this.component = undefined;
}
show(element) {
this.component = new Vue({
el: element,
name: 'AlphanumericFormat',
components: {
AlphanumericFormat
},
provide: {
openmct: this.openmct,
objectPath: this.objectPath,
currentView: this
},
template: '<alphanumeric-format ref="alphanumericFormat"></alphanumeric-format>'
});
}
getViewContext() {
if (this.component) {
return {};
}
show(element) {
this.component = new Vue({
el: element,
name: 'AlphanumericFormat',
components: {
AlphanumericFormat
},
provide: {
openmct: this.openmct,
objectPath: this.objectPath,
currentView: this
},
template: '<alphanumeric-format ref="alphanumericFormat"></alphanumeric-format>'
});
}
return this.component.$refs.alphanumericFormat.getViewContext();
}
getViewContext() {
if (this.component) {
return {};
}
priority() {
return 1;
}
return this.component.$refs.alphanumericFormat.getViewContext();
}
priority() {
return 1;
}
destroy() {
this.component.$destroy();
this.component = undefined;
}
destroy() {
this.component.$destroy();
this.component = undefined;
}
}
export default function AlphanumericFormatViewProvider(openmct, options) {
function isTelemetryObject(selectionPath) {
let selectedObject = selectionPath[0].context.item;
let parentObject = selectionPath[1].context.item;
let selectedLayoutItem = selectionPath[0].context.layoutItem;
function isTelemetryObject(selectionPath) {
let selectedObject = selectionPath[0].context.item;
let parentObject = selectionPath[1].context.item;
let selectedLayoutItem = selectionPath[0].context.layoutItem;
return parentObject
&& parentObject.type === 'layout'
&& selectedObject
&& selectedLayoutItem
&& selectedLayoutItem.type === 'telemetry-view'
&& openmct.telemetry.isTelemetryObject(selectedObject)
&& !options.showAsView.includes(selectedObject.type);
return (
parentObject &&
parentObject.type === 'layout' &&
selectedObject &&
selectedLayoutItem &&
selectedLayoutItem.type === 'telemetry-view' &&
openmct.telemetry.isTelemetryObject(selectedObject) &&
!options.showAsView.includes(selectedObject.type)
);
}
return {
key: 'alphanumeric-format',
name: 'Format',
canView: function (selection) {
if (selection.length === 0 || selection[0].length === 1) {
return false;
}
return selection.every(isTelemetryObject);
},
view: function (domainObject, objectPath) {
return new AlphanumericFormatView(openmct, domainObject, objectPath);
}
return {
key: 'alphanumeric-format',
name: 'Format',
canView: function (selection) {
if (selection.length === 0 || selection[0].length === 1) {
return false;
}
return selection.every(isTelemetryObject);
},
view: function (domainObject, objectPath) {
return new AlphanumericFormatView(openmct, domainObject, objectPath);
}
};
};
}

View File

@ -1,38 +1,38 @@
import printj from 'printj';
export default class CustomStringFormatter {
constructor(openmct, valueMetadata, itemFormat) {
this.openmct = openmct;
constructor(openmct, valueMetadata, itemFormat) {
this.openmct = openmct;
this.itemFormat = itemFormat;
this.valueMetadata = valueMetadata;
this.itemFormat = itemFormat;
this.valueMetadata = valueMetadata;
}
format(datum) {
if (!this.itemFormat) {
return;
}
format(datum) {
if (!this.itemFormat) {
return;
}
if (!this.itemFormat.startsWith('&')) {
return printj.sprintf(this.itemFormat, datum[this.valueMetadata.key]);
}
try {
const key = this.itemFormat.slice(1);
const customFormatter = this.openmct.telemetry.getFormatter(key);
if (!customFormatter) {
throw new Error('Custom Formatter not found');
}
return customFormatter.format(datum[this.valueMetadata.key]);
} catch (e) {
console.error(e);
return datum[this.valueMetadata.key];
}
if (!this.itemFormat.startsWith('&')) {
return printj.sprintf(this.itemFormat, datum[this.valueMetadata.key]);
}
setFormat(itemFormat) {
this.itemFormat = itemFormat;
try {
const key = this.itemFormat.slice(1);
const customFormatter = this.openmct.telemetry.getFormatter(key);
if (!customFormatter) {
throw new Error('Custom Formatter not found');
}
return customFormatter.format(datum[this.valueMetadata.key]);
} catch (e) {
console.error(e);
return datum[this.valueMetadata.key];
}
}
setFormat(itemFormat) {
this.itemFormat = itemFormat;
}
}

View File

@ -2,80 +2,80 @@ import CustomStringFormatter from './CustomStringFormatter';
import { createOpenMct, resetApplicationState } from 'utils/testing';
const CUSTOM_FORMATS = [
{
key: 'sclk',
format: (value) => 2 * value
},
{
key: 'lts',
format: (value) => 3 * value
}
{
key: 'sclk',
format: (value) => 2 * value
},
{
key: 'lts',
format: (value) => 3 * value
}
];
const valueMetadata = {
key: "sin",
name: "Sine",
unit: "Hz",
formatString: "%0.2f",
hints: {
range: 1,
priority: 3
},
source: "sin"
key: 'sin',
name: 'Sine',
unit: 'Hz',
formatString: '%0.2f',
hints: {
range: 1,
priority: 3
},
source: 'sin'
};
const datum = {
name: "1 Sine Wave Generator",
utc: 1603930354000,
yesterday: 1603843954000,
sin: 0.587785209686822,
cos: -0.8090170253297632
name: '1 Sine Wave Generator',
utc: 1603930354000,
yesterday: 1603843954000,
sin: 0.587785209686822,
cos: -0.8090170253297632
};
describe('CustomStringFormatter', function () {
let element;
let child;
let openmct;
let customStringFormatter;
let element;
let child;
let openmct;
let customStringFormatter;
beforeEach((done) => {
openmct = createOpenMct();
beforeEach((done) => {
openmct = createOpenMct();
element = document.createElement('div');
child = document.createElement('div');
element.appendChild(child);
CUSTOM_FORMATS.forEach((formatter) => {
openmct.telemetry.addFormat(formatter);
});
openmct.on('start', done);
openmct.startHeadless();
customStringFormatter = new CustomStringFormatter(openmct, valueMetadata);
element = document.createElement('div');
child = document.createElement('div');
element.appendChild(child);
CUSTOM_FORMATS.forEach((formatter) => {
openmct.telemetry.addFormat(formatter);
});
openmct.on('start', done);
openmct.startHeadless();
afterEach(() => {
return resetApplicationState(openmct);
});
customStringFormatter = new CustomStringFormatter(openmct, valueMetadata);
});
it('adds custom format sclk', () => {
const format = openmct.telemetry.getFormatter('sclk');
expect(format.key).toEqual('sclk');
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('adds custom format lts', () => {
const format = openmct.telemetry.getFormatter('lts');
expect(format.key).toEqual('lts');
});
it('adds custom format sclk', () => {
const format = openmct.telemetry.getFormatter('sclk');
expect(format.key).toEqual('sclk');
});
it('returns correct value for custom format sclk', () => {
customStringFormatter.setFormat('&sclk');
const value = customStringFormatter.format(datum, valueMetadata);
expect(datum.sin * 2).toEqual(value);
});
it('adds custom format lts', () => {
const format = openmct.telemetry.getFormatter('lts');
expect(format.key).toEqual('lts');
});
it('returns correct value for custom format lts', () => {
customStringFormatter.setFormat('&lts');
const value = customStringFormatter.format(datum, valueMetadata);
expect(datum.sin * 3).toEqual(value);
});
it('returns correct value for custom format sclk', () => {
customStringFormatter.setFormat('&sclk');
const value = customStringFormatter.format(datum, valueMetadata);
expect(datum.sin * 2).toEqual(value);
});
it('returns correct value for custom format lts', () => {
customStringFormatter.setFormat('&lts');
const value = customStringFormatter.format(datum, valueMetadata);
expect(datum.sin * 3).toEqual(value);
});
});

File diff suppressed because it is too large Load Diff

View File

@ -21,67 +21,52 @@
*****************************************************************************/
define(function () {
function DisplayLayoutType() {
return {
name: "Display Layout",
creatable: true,
description: 'Assemble other objects and components together into a reusable screen layout. Simply drag in the objects you want, position and size them. Save your design and view or edit it at any time.',
cssClass: 'icon-layout',
initialize(domainObject) {
domainObject.composition = [];
domainObject.configuration = {
items: [],
layoutGrid: [10, 10]
};
},
form: [
{
name: "Horizontal grid (px)",
control: "numberfield",
cssClass: "l-input-sm l-numeric",
property: [
"configuration",
"layoutGrid",
0
],
required: true
},
{
name: "Vertical grid (px)",
control: "numberfield",
cssClass: "l-input-sm l-numeric",
property: [
"configuration",
"layoutGrid",
1
],
required: true
},
{
name: "Horizontal size (px)",
control: "numberfield",
cssClass: "l-input-sm l-numeric",
property: [
"configuration",
"layoutDimensions",
0
],
required: false
},
{
name: "Vertical size (px)",
control: "numberfield",
cssClass: "l-input-sm l-numeric",
property: [
"configuration",
"layoutDimensions",
1
],
required: false
}
]
function DisplayLayoutType() {
return {
name: 'Display Layout',
creatable: true,
description:
'Assemble other objects and components together into a reusable screen layout. Simply drag in the objects you want, position and size them. Save your design and view or edit it at any time.',
cssClass: 'icon-layout',
initialize(domainObject) {
domainObject.composition = [];
domainObject.configuration = {
items: [],
layoutGrid: [10, 10]
};
}
},
form: [
{
name: 'Horizontal grid (px)',
control: 'numberfield',
cssClass: 'l-input-sm l-numeric',
property: ['configuration', 'layoutGrid', 0],
required: true
},
{
name: 'Vertical grid (px)',
control: 'numberfield',
cssClass: 'l-input-sm l-numeric',
property: ['configuration', 'layoutGrid', 1],
required: true
},
{
name: 'Horizontal size (px)',
control: 'numberfield',
cssClass: 'l-input-sm l-numeric',
property: ['configuration', 'layoutDimensions', 0],
required: false
},
{
name: 'Vertical size (px)',
control: 'numberfield',
cssClass: 'l-input-sm l-numeric',
property: ['configuration', 'layoutDimensions', 1],
required: false
}
]
};
}
return DisplayLayoutType;
return DisplayLayoutType;
});

View File

@ -1,34 +1,34 @@
const displayLayoutDrawingObjectTypes = {
'box-view': {
name: "Box",
creatable: false,
description: 'A rectangle shape.',
cssClass: 'icon-box-round-corners'
},
'ellipse-view': {
name: "Ellipse",
creatable: false,
description: 'A ellipse shape.',
cssClass: 'icon-circle'
},
'line-view': {
name: "Line",
creatable: false,
description: 'A line.',
cssClass: 'icon-line-horz'
},
'text-view': {
name: "Text",
creatable: false,
description: 'An editable text box.',
cssClass: 'icon-font'
},
'image-view': {
name: "Image",
creatable: false,
description: 'An image.',
cssClass: 'icon-image'
}
'box-view': {
name: 'Box',
creatable: false,
description: 'A rectangle shape.',
cssClass: 'icon-box-round-corners'
},
'ellipse-view': {
name: 'Ellipse',
creatable: false,
description: 'A ellipse shape.',
cssClass: 'icon-circle'
},
'line-view': {
name: 'Line',
creatable: false,
description: 'A line.',
cssClass: 'icon-line-horz'
},
'text-view': {
name: 'Text',
creatable: false,
description: 'An editable text box.',
cssClass: 'icon-font'
},
'image-view': {
name: 'Image',
creatable: false,
description: 'An image.',
cssClass: 'icon-image'
}
};
export default displayLayoutDrawingObjectTypes;

View File

@ -20,107 +20,93 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[],
function () {
define([], function () {
/**
* Handles drag interactions on frames in layouts. This will
* provides new positions/dimensions for frames based on
* relative pixel positions provided; these will take into account
* the grid size (in a snap-to sense) and will enforce some minimums
* on both position and dimensions.
*
* The provided position and dimensions factors will determine
* whether this is a move or a resize, and what type of resize it
* will be. For instance, a position factor of [1, 1]
* will move a frame along with the mouse as the drag
* proceeds, while a dimension factor of [0, 0] will leave
* dimensions unchanged. Combining these in different
* ways results in different handles; a position factor of
* [1, 0] and a dimensions factor of [-1, 0] will implement
* a left-edge resize, as the horizontal position will move
* with the mouse while the horizontal dimensions shrink in
* kind (and vertical properties remain unmodified.)
*
* @param {object} rawPosition the initial position/dimensions
* of the frame being interacted with
* @param {number[]} posFactor the position factor
* @param {number[]} dimFactor the dimensions factor
* @param {number[]} the size of each grid element, in pixels
* @constructor
* @memberof platform/features/layout
*/
function LayoutDrag(rawPosition, posFactor, dimFactor, gridSize) {
this.rawPosition = rawPosition;
this.posFactor = posFactor;
this.dimFactor = dimFactor;
this.gridSize = gridSize;
}
/**
* Handles drag interactions on frames in layouts. This will
* provides new positions/dimensions for frames based on
* relative pixel positions provided; these will take into account
* the grid size (in a snap-to sense) and will enforce some minimums
* on both position and dimensions.
*
* The provided position and dimensions factors will determine
* whether this is a move or a resize, and what type of resize it
* will be. For instance, a position factor of [1, 1]
* will move a frame along with the mouse as the drag
* proceeds, while a dimension factor of [0, 0] will leave
* dimensions unchanged. Combining these in different
* ways results in different handles; a position factor of
* [1, 0] and a dimensions factor of [-1, 0] will implement
* a left-edge resize, as the horizontal position will move
* with the mouse while the horizontal dimensions shrink in
* kind (and vertical properties remain unmodified.)
*
* @param {object} rawPosition the initial position/dimensions
* of the frame being interacted with
* @param {number[]} posFactor the position factor
* @param {number[]} dimFactor the dimensions factor
* @param {number[]} the size of each grid element, in pixels
* @constructor
* @memberof platform/features/layout
*/
function LayoutDrag(rawPosition, posFactor, dimFactor, gridSize) {
this.rawPosition = rawPosition;
this.posFactor = posFactor;
this.dimFactor = dimFactor;
this.gridSize = gridSize;
}
// Convert a delta from pixel coordinates to grid coordinates,
// rounding to whole-number grid coordinates.
function toGridDelta(gridSize, pixelDelta) {
return pixelDelta.map(function (v, i) {
return Math.round(v / gridSize[i]);
});
}
// Convert a delta from pixel coordinates to grid coordinates,
// rounding to whole-number grid coordinates.
function toGridDelta(gridSize, pixelDelta) {
return pixelDelta.map(function (v, i) {
return Math.round(v / gridSize[i]);
});
}
// Utility function to perform element-by-element multiplication
function multiply(array, factors) {
return array.map(function (v, i) {
return v * factors[i];
});
}
// Utility function to perform element-by-element multiplication
function multiply(array, factors) {
return array.map(function (v, i) {
return v * factors[i];
});
}
// Utility function to perform element-by-element addition
function add(array, other) {
return array.map(function (v, i) {
return v + other[i];
});
}
// Utility function to perform element-by-element addition
function add(array, other) {
return array.map(function (v, i) {
return v + other[i];
});
}
// Utility function to perform element-by-element max-choosing
function max(array, other) {
return array.map(function (v, i) {
return Math.max(v, other[i]);
});
}
// Utility function to perform element-by-element max-choosing
function max(array, other) {
return array.map(function (v, i) {
return Math.max(v, other[i]);
});
}
/**
* Get a new position object in grid coordinates, with
* position and dimensions both offset appropriately
* according to the factors supplied in the constructor.
* @param {number[]} pixelDelta the offset from the
* original position, in pixels
*/
LayoutDrag.prototype.getAdjustedPositionAndDimensions = function (pixelDelta) {
const gridDelta = toGridDelta(this.gridSize, pixelDelta);
/**
* Get a new position object in grid coordinates, with
* position and dimensions both offset appropriately
* according to the factors supplied in the constructor.
* @param {number[]} pixelDelta the offset from the
* original position, in pixels
*/
LayoutDrag.prototype.getAdjustedPositionAndDimensions = function (pixelDelta) {
const gridDelta = toGridDelta(this.gridSize, pixelDelta);
return {
position: max(add(this.rawPosition.position, multiply(gridDelta, this.posFactor)), [0, 0]),
dimensions: max(add(this.rawPosition.dimensions, multiply(gridDelta, this.dimFactor)), [1, 1])
};
};
return {
position: max(add(
this.rawPosition.position,
multiply(gridDelta, this.posFactor)
), [0, 0]),
dimensions: max(add(
this.rawPosition.dimensions,
multiply(gridDelta, this.dimFactor)
), [1, 1])
};
};
LayoutDrag.prototype.getAdjustedPosition = function (pixelDelta) {
const gridDelta = toGridDelta(this.gridSize, pixelDelta);
LayoutDrag.prototype.getAdjustedPosition = function (pixelDelta) {
const gridDelta = toGridDelta(this.gridSize, pixelDelta);
return {
position: max(add(this.rawPosition.position, multiply(gridDelta, this.posFactor)), [0, 0])
};
};
return {
position: max(add(
this.rawPosition.position,
multiply(gridDelta, this.posFactor)
), [0, 0])
};
};
return LayoutDrag;
}
);
return LayoutDrag;
});

View File

@ -1,38 +1,38 @@
import clipboard from '@/utils/clipboard';
export default class CopyToClipboardAction {
constructor(openmct) {
this.openmct = openmct;
constructor(openmct) {
this.openmct = openmct;
this.cssClass = 'icon-duplicate';
this.description = 'Copy value to clipboard';
this.group = "action";
this.key = 'copyToClipboard';
this.name = 'Copy to Clipboard';
this.priority = 1;
this.cssClass = 'icon-duplicate';
this.description = 'Copy value to clipboard';
this.group = 'action';
this.key = 'copyToClipboard';
this.name = 'Copy to Clipboard';
this.priority = 1;
}
invoke(objectPath, view = {}) {
const viewContext = view.getViewContext && view.getViewContext();
const formattedValue = viewContext.row.formattedValueForCopy();
clipboard
.updateClipboard(formattedValue)
.then(() => {
this.openmct.notifications.info(`Success : copied '${formattedValue}' to clipboard `);
})
.catch(() => {
this.openmct.notifications.error(`Failed : to copy '${formattedValue}' to clipboard `);
});
}
appliesTo(objectPath, view = {}) {
const viewContext = view.getViewContext && view.getViewContext();
const row = viewContext && viewContext.row;
if (!row) {
return false;
}
invoke(objectPath, view = {}) {
const viewContext = view.getViewContext && view.getViewContext();
const formattedValue = viewContext.row.formattedValueForCopy();
clipboard.updateClipboard(formattedValue)
.then(() => {
this.openmct.notifications.info(`Success : copied '${formattedValue}' to clipboard `);
})
.catch(() => {
this.openmct.notifications.error(`Failed : to copy '${formattedValue}' to clipboard `);
});
}
appliesTo(objectPath, view = {}) {
const viewContext = view.getViewContext && view.getViewContext();
const row = viewContext && viewContext.row;
if (!row) {
return false;
}
return row.formattedValueForCopy
&& typeof row.formattedValueForCopy === 'function';
}
return row.formattedValueForCopy && typeof row.formattedValueForCopy === 'function';
}
}

View File

@ -21,82 +21,79 @@
-->
<template>
<div
class="c-inspect-properties"
>
<div class="c-inspect-properties">
<ul class="c-inspect-properties__section">
<li class="c-inspect-properties__row">
<div
class="c-inspect-properties__label"
title="Printf formatting for the selected telemetry"
>
<label for="telemetryPrintfFormat">Format</label>
</div>
<div class="c-inspect-properties__value">
<input
id="telemetryPrintfFormat"
type="text"
:disabled="!isEditing"
:value="telemetryFormat"
:placeholder="nonMixedFormat ? '' : 'Mixed'"
@change="formatTelemetry"
>
</div>
</li>
<li class="c-inspect-properties__row">
<div
class="c-inspect-properties__label"
title="Printf formatting for the selected telemetry"
>
<label for="telemetryPrintfFormat">Format</label>
</div>
<div class="c-inspect-properties__value">
<input
id="telemetryPrintfFormat"
type="text"
:disabled="!isEditing"
:value="telemetryFormat"
:placeholder="nonMixedFormat ? '' : 'Mixed'"
@change="formatTelemetry"
/>
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'AlphanumericFormat',
inject: ['openmct', 'objectPath'],
data() {
return {
isEditing: this.openmct.editor.isEditing(),
telemetryFormat: undefined,
nonMixedFormat: false
};
name: 'AlphanumericFormat',
inject: ['openmct', 'objectPath'],
data() {
return {
isEditing: this.openmct.editor.isEditing(),
telemetryFormat: undefined,
nonMixedFormat: false
};
},
mounted() {
this.openmct.editor.on('isEditing', this.toggleEdit);
this.openmct.selection.on('change', this.handleSelection);
this.handleSelection(this.openmct.selection.get());
},
destroyed() {
this.openmct.editor.off('isEditing', this.toggleEdit);
this.openmct.selection.off('change', this.handleSelection);
},
methods: {
toggleEdit(isEditing) {
this.isEditing = isEditing;
},
mounted() {
this.openmct.editor.on('isEditing', this.toggleEdit);
this.openmct.selection.on('change', this.handleSelection);
this.handleSelection(this.openmct.selection.get());
formatTelemetry(event) {
const newFormat = event.currentTarget.value;
this.openmct.selection.get().forEach((selectionPath) => {
selectionPath[0].context.updateTelemetryFormat(newFormat);
});
this.telemetryFormat = newFormat;
},
destroyed() {
this.openmct.editor.off('isEditing', this.toggleEdit);
this.openmct.selection.off('change', this.handleSelection);
},
methods: {
toggleEdit(isEditing) {
this.isEditing = isEditing;
},
formatTelemetry(event) {
const newFormat = event.currentTarget.value;
this.openmct.selection.get().forEach(selectionPath => {
selectionPath[0].context.updateTelemetryFormat(newFormat);
});
this.telemetryFormat = newFormat;
},
handleSelection(selection) {
if (selection.length === 0 || selection[0].length < 2) {
return;
}
handleSelection(selection) {
if (selection.length === 0 || selection[0].length < 2) {
return;
}
let layoutItem = selection[0][0].context.layoutItem;
let layoutItem = selection[0][0].context.layoutItem;
if (!layoutItem) {
return;
}
if (!layoutItem) {
return;
}
let format = layoutItem.format;
this.nonMixedFormat = selection.every(selectionPath => {
return selectionPath[0].context.layoutItem.format === format;
});
let format = layoutItem.format;
this.nonMixedFormat = selection.every((selectionPath) => {
return selectionPath[0].context.layoutItem.format === format;
});
this.telemetryFormat = this.nonMixedFormat ? format : '';
}
this.telemetryFormat = this.nonMixedFormat ? format : '';
}
}
};
</script>

View File

@ -21,19 +21,19 @@
-->
<template>
<layout-frame
<layout-frame
:item="item"
:grid-size="gridSize"
:is-editing="isEditing"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')"
>
>
<div
class="c-box-view u-style-receiver js-style-receiver"
:class="[styleClass]"
:style="style"
class="c-box-view u-style-receiver js-style-receiver"
:class="[styleClass]"
:style="style"
></div>
</layout-frame>
</layout-frame>
</template>
<script>
@ -41,82 +41,84 @@ import LayoutFrame from './LayoutFrame.vue';
import conditionalStylesMixin from '../mixins/objectStyles-mixin';
export default {
makeDefinition() {
return {
fill: '#666666',
stroke: '',
x: 1,
y: 1,
width: 10,
height: 5
};
makeDefinition() {
return {
fill: '#666666',
stroke: '',
x: 1,
y: 1,
width: 10,
height: 5
};
},
components: {
LayoutFrame
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
components: {
LayoutFrame
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
index: {
type: Number,
required: true
},
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
index: {
type: Number,
required: true
},
computed: {
style() {
if (this.itemStyle) {
return this.itemStyle;
} else {
return {
backgroundColor: this.item.fill,
border: this.item.stroke ? '1px solid ' + this.item.stroke : ''
};
}
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el, this.context, this.initSelect);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
},
computed: {
style() {
if (this.itemStyle) {
return this.itemStyle;
} else {
return {
backgroundColor: this.item.fill,
border: this.item.stroke ? '1px solid ' + this.item.stroke : ''
};
}
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el,
this.context,
this.initSelect
);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
}
};
</script>

File diff suppressed because it is too large Load Diff

View File

@ -20,42 +20,49 @@
at runtime from the About dialog for additional information.
-->
<template>
<div
class="l-layout__grid-holder"
:class="{ 'c-grid': showGrid }"
>
<div class="l-layout__grid-holder" :class="{ 'c-grid': showGrid }">
<div
v-if="gridSize[0] >= 3"
class="c-grid__x l-grid l-grid-x"
:style="[{ backgroundSize: gridSize[0] + 'px 100%', width: gridDimensions[0] +'px', height: gridDimensions[1] +'px' }]"
v-if="gridSize[0] >= 3"
class="c-grid__x l-grid l-grid-x"
:style="[
{
backgroundSize: gridSize[0] + 'px 100%',
width: gridDimensions[0] + 'px',
height: gridDimensions[1] + 'px'
}
]"
></div>
<div
v-if="gridSize[1] >= 3"
class="c-grid__y l-grid l-grid-y"
:style="[{ backgroundSize: '100%' + gridSize[1] + 'px', width: gridDimensions[0] +'px', height: gridDimensions[1] +'px' }]"
v-if="gridSize[1] >= 3"
class="c-grid__y l-grid l-grid-y"
:style="[
{
backgroundSize: '100%' + gridSize[1] + 'px',
width: gridDimensions[0] + 'px',
height: gridDimensions[1] + 'px'
}
]"
></div>
</div>
</div>
</template>
<script>
export default {
props: {
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
showGrid: {
type: Boolean,
required: true
},
gridDimensions: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
}
props: {
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
showGrid: {
type: Boolean,
required: true
},
gridDimensions: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
}
}
};
</script>

View File

@ -21,171 +21,174 @@
-->
<template>
<!-- Resize handles -->
<div
class="c-frame-edit"
:style="marqueeStyle"
>
<!-- Resize handles -->
<div class="c-frame-edit" :style="marqueeStyle">
<div
class="c-frame-edit__handle c-frame-edit__handle--nw"
@mousedown.left="startResize([1,1], [-1,-1], $event)"
class="c-frame-edit__handle c-frame-edit__handle--nw"
@mousedown.left="startResize([1, 1], [-1, -1], $event)"
></div>
<div
class="c-frame-edit__handle c-frame-edit__handle--ne"
@mousedown.left="startResize([0,1], [1,-1], $event)"
class="c-frame-edit__handle c-frame-edit__handle--ne"
@mousedown.left="startResize([0, 1], [1, -1], $event)"
></div>
<div
class="c-frame-edit__handle c-frame-edit__handle--sw"
@mousedown.left="startResize([1,0], [-1,1], $event)"
class="c-frame-edit__handle c-frame-edit__handle--sw"
@mousedown.left="startResize([1, 0], [-1, 1], $event)"
></div>
<div
class="c-frame-edit__handle c-frame-edit__handle--se"
@mousedown.left="startResize([0,0], [1,1], $event)"
class="c-frame-edit__handle c-frame-edit__handle--se"
@mousedown.left="startResize([0, 0], [1, 1], $event)"
></div>
</div>
</div>
</template>
<script>
import LayoutDrag from './../LayoutDrag';
export default {
inject: ['openmct'],
props: {
selectedLayoutItems: {
type: Array,
default: undefined
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
}
inject: ['openmct'],
props: {
selectedLayoutItems: {
type: Array,
default: undefined
},
data() {
return {
dragPosition: undefined
};
},
computed: {
marqueePosition() {
let x = Number.POSITIVE_INFINITY;
let y = Number.POSITIVE_INFINITY;
let width = Number.NEGATIVE_INFINITY;
let height = Number.NEGATIVE_INFINITY;
this.selectedLayoutItems.forEach(item => {
if (item.x2 !== undefined) {
let lineWidth = Math.abs(item.x - item.x2);
let lineMinX = Math.min(item.x, item.x2);
x = Math.min(lineMinX, x);
width = Math.max(lineWidth + lineMinX, width);
} else {
x = Math.min(item.x, x);
width = Math.max(item.width + item.x, width);
}
if (item.y2 !== undefined) {
let lineHeight = Math.abs(item.y - item.y2);
let lineMinY = Math.min(item.y, item.y2);
y = Math.min(lineMinY, y);
height = Math.max(lineHeight + lineMinY, height);
} else {
y = Math.min(item.y, y);
height = Math.max(item.height + item.y, height);
}
});
if (this.dragPosition) {
[x, y] = this.dragPosition.position;
[width, height] = this.dragPosition.dimensions;
} else {
width = width - x;
height = height - y;
}
return {
x: x,
y: y,
width: width,
height: height
};
},
marqueeStyle() {
return {
left: (this.gridSize[0] * this.marqueePosition.x) + 'px',
top: (this.gridSize[1] * this.marqueePosition.y) + 'px',
width: (this.gridSize[0] * this.marqueePosition.width) + 'px',
height: (this.gridSize[1] * this.marqueePosition.height) + 'px'
};
}
},
methods: {
updatePosition(event) {
let currentPosition = [event.pageX, event.pageY];
this.initialPosition = this.initialPosition || currentPosition;
this.delta = currentPosition.map(function (value, index) {
return value - this.initialPosition[index];
}.bind(this));
},
startResize(posFactor, dimFactor, event) {
document.body.addEventListener('mousemove', this.continueResize);
document.body.addEventListener('mouseup', this.endResize);
this.marqueeStartPosition = {
position: [this.marqueePosition.x, this.marqueePosition.y],
dimensions: [this.marqueePosition.width, this.marqueePosition.height]
};
this.updatePosition(event);
this.activeDrag = new LayoutDrag(this.marqueeStartPosition, posFactor, dimFactor, this.gridSize);
event.preventDefault();
},
continueResize(event) {
event.preventDefault();
this.updatePosition(event);
this.dragPosition = this.activeDrag.getAdjustedPositionAndDimensions(this.delta);
},
endResize(event) {
document.body.removeEventListener('mousemove', this.continueResize);
document.body.removeEventListener('mouseup', this.endResize);
this.continueResize(event);
let marqueeStartWidth = this.marqueeStartPosition.dimensions[0];
let marqueeStartHeight = this.marqueeStartPosition.dimensions[1];
let marqueeStartX = this.marqueeStartPosition.position[0];
let marqueeStartY = this.marqueeStartPosition.position[1];
let marqueeEndX = this.dragPosition.position[0];
let marqueeEndY = this.dragPosition.position[1];
let marqueeEndWidth = this.dragPosition.dimensions[0];
let marqueeEndHeight = this.dragPosition.dimensions[1];
let scaleWidth = marqueeEndWidth / marqueeStartWidth;
let scaleHeight = marqueeEndHeight / marqueeStartHeight;
let marqueeStart = {
x: marqueeStartX,
y: marqueeStartY,
height: marqueeStartWidth,
width: marqueeStartHeight
};
let marqueeEnd = {
x: marqueeEndX,
y: marqueeEndY,
width: marqueeEndWidth,
height: marqueeEndHeight
};
let marqueeOffset = {
x: marqueeEnd.x - marqueeStart.x,
y: marqueeEnd.y - marqueeStart.y
};
this.$emit('endResize', scaleWidth, scaleHeight, marqueeStart, marqueeOffset);
this.dragPosition = undefined;
this.initialPosition = undefined;
this.marqueeStartPosition = undefined;
this.delta = undefined;
event.preventDefault();
}
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
}
},
data() {
return {
dragPosition: undefined
};
},
computed: {
marqueePosition() {
let x = Number.POSITIVE_INFINITY;
let y = Number.POSITIVE_INFINITY;
let width = Number.NEGATIVE_INFINITY;
let height = Number.NEGATIVE_INFINITY;
this.selectedLayoutItems.forEach((item) => {
if (item.x2 !== undefined) {
let lineWidth = Math.abs(item.x - item.x2);
let lineMinX = Math.min(item.x, item.x2);
x = Math.min(lineMinX, x);
width = Math.max(lineWidth + lineMinX, width);
} else {
x = Math.min(item.x, x);
width = Math.max(item.width + item.x, width);
}
if (item.y2 !== undefined) {
let lineHeight = Math.abs(item.y - item.y2);
let lineMinY = Math.min(item.y, item.y2);
y = Math.min(lineMinY, y);
height = Math.max(lineHeight + lineMinY, height);
} else {
y = Math.min(item.y, y);
height = Math.max(item.height + item.y, height);
}
});
if (this.dragPosition) {
[x, y] = this.dragPosition.position;
[width, height] = this.dragPosition.dimensions;
} else {
width = width - x;
height = height - y;
}
return {
x: x,
y: y,
width: width,
height: height
};
},
marqueeStyle() {
return {
left: this.gridSize[0] * this.marqueePosition.x + 'px',
top: this.gridSize[1] * this.marqueePosition.y + 'px',
width: this.gridSize[0] * this.marqueePosition.width + 'px',
height: this.gridSize[1] * this.marqueePosition.height + 'px'
};
}
},
methods: {
updatePosition(event) {
let currentPosition = [event.pageX, event.pageY];
this.initialPosition = this.initialPosition || currentPosition;
this.delta = currentPosition.map(
function (value, index) {
return value - this.initialPosition[index];
}.bind(this)
);
},
startResize(posFactor, dimFactor, event) {
document.body.addEventListener('mousemove', this.continueResize);
document.body.addEventListener('mouseup', this.endResize);
this.marqueeStartPosition = {
position: [this.marqueePosition.x, this.marqueePosition.y],
dimensions: [this.marqueePosition.width, this.marqueePosition.height]
};
this.updatePosition(event);
this.activeDrag = new LayoutDrag(
this.marqueeStartPosition,
posFactor,
dimFactor,
this.gridSize
);
event.preventDefault();
},
continueResize(event) {
event.preventDefault();
this.updatePosition(event);
this.dragPosition = this.activeDrag.getAdjustedPositionAndDimensions(this.delta);
},
endResize(event) {
document.body.removeEventListener('mousemove', this.continueResize);
document.body.removeEventListener('mouseup', this.endResize);
this.continueResize(event);
let marqueeStartWidth = this.marqueeStartPosition.dimensions[0];
let marqueeStartHeight = this.marqueeStartPosition.dimensions[1];
let marqueeStartX = this.marqueeStartPosition.position[0];
let marqueeStartY = this.marqueeStartPosition.position[1];
let marqueeEndX = this.dragPosition.position[0];
let marqueeEndY = this.dragPosition.position[1];
let marqueeEndWidth = this.dragPosition.dimensions[0];
let marqueeEndHeight = this.dragPosition.dimensions[1];
let scaleWidth = marqueeEndWidth / marqueeStartWidth;
let scaleHeight = marqueeEndHeight / marqueeStartHeight;
let marqueeStart = {
x: marqueeStartX,
y: marqueeStartY,
height: marqueeStartWidth,
width: marqueeStartHeight
};
let marqueeEnd = {
x: marqueeEndX,
y: marqueeEndY,
width: marqueeEndWidth,
height: marqueeEndHeight
};
let marqueeOffset = {
x: marqueeEnd.x - marqueeStart.x,
y: marqueeEnd.y - marqueeStart.y
};
this.$emit('endResize', scaleWidth, scaleHeight, marqueeStart, marqueeOffset);
this.dragPosition = undefined;
this.initialPosition = undefined;
this.marqueeStartPosition = undefined;
this.delta = undefined;
event.preventDefault();
}
}
};
</script>

View File

@ -21,19 +21,19 @@
-->
<template>
<layout-frame
<layout-frame
:item="item"
:grid-size="gridSize"
:is-editing="isEditing"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')"
>
>
<div
class="c-ellipse-view u-style-receiver js-style-receiver"
:class="[styleClass]"
:style="style"
class="c-ellipse-view u-style-receiver js-style-receiver"
:class="[styleClass]"
:style="style"
></div>
</layout-frame>
</layout-frame>
</template>
<script>
@ -41,82 +41,84 @@ import LayoutFrame from './LayoutFrame.vue';
import conditionalStylesMixin from '../mixins/objectStyles-mixin';
export default {
makeDefinition() {
return {
fill: '#666666',
stroke: '',
x: 1,
y: 1,
width: 10,
height: 10
};
makeDefinition() {
return {
fill: '#666666',
stroke: '',
x: 1,
y: 1,
width: 10,
height: 10
};
},
components: {
LayoutFrame
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
components: {
LayoutFrame
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
index: {
type: Number,
required: true
},
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
index: {
type: Number,
required: true
},
computed: {
style() {
if (this.itemStyle) {
return this.itemStyle;
} else {
return {
backgroundColor: this.item.fill,
border: this.item.stroke ? '1px solid ' + this.item.stroke : ''
};
}
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el, this.context, this.initSelect);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
},
computed: {
style() {
if (this.itemStyle) {
return this.itemStyle;
} else {
return {
backgroundColor: this.item.fill,
border: this.item.stroke ? '1px solid ' + this.item.stroke : ''
};
}
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el,
this.context,
this.initSelect
);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
}
};
</script>

View File

@ -21,109 +21,107 @@
-->
<template>
<layout-frame
<layout-frame
:item="item"
:grid-size="gridSize"
:is-editing="isEditing"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')"
>
<div
class="c-image-view"
:class="[styleClass]"
:style="style"
></div>
</layout-frame>
>
<div class="c-image-view" :class="[styleClass]" :style="style"></div>
</layout-frame>
</template>
<script>
import LayoutFrame from './LayoutFrame.vue';
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
import conditionalStylesMixin from '../mixins/objectStyles-mixin';
export default {
makeDefinition(openmct, gridSize, element) {
return {
stroke: 'transparent',
x: 1,
y: 1,
width: 10,
height: 5,
url: element.url
};
makeDefinition(openmct, gridSize, element) {
return {
stroke: 'transparent',
x: 1,
y: 1,
width: 10,
height: 5,
url: element.url
};
},
components: {
LayoutFrame
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
components: {
LayoutFrame
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
index: {
type: Number,
required: true
},
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
index: {
type: Number,
required: true
},
computed: {
style() {
let backgroundImage = 'url(' + this.item.url + ')';
let border = '1px solid ' + this.item.stroke;
if (this.itemStyle) {
if (this.itemStyle.imageUrl !== undefined) {
backgroundImage = 'url(' + this.itemStyle.imageUrl + ')';
}
border = this.itemStyle.border;
}
return {
backgroundImage,
border
};
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el, this.context, this.initSelect);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
},
computed: {
style() {
let backgroundImage = 'url(' + this.item.url + ')';
let border = '1px solid ' + this.item.stroke;
if (this.itemStyle) {
if (this.itemStyle.imageUrl !== undefined) {
backgroundImage = 'url(' + this.itemStyle.imageUrl + ')';
}
border = this.itemStyle.border;
}
return {
backgroundImage,
border
};
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el,
this.context,
this.initSelect
);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
}
};
</script>

View File

@ -21,20 +21,17 @@
-->
<template>
<div
<div
class="l-layout__frame c-frame"
:class="{
'no-frame': !item.hasFrame,
'u-inspectable': inspectable
'no-frame': !item.hasFrame,
'u-inspectable': inspectable
}"
:style="style"
>
>
<slot></slot>
<div
class="c-frame__move-bar"
@mousedown.left="startMove($event)"
></div>
</div>
<div class="c-frame__move-bar" @mousedown.left="startMove($event)"></div>
</div>
</template>
<script>
@ -42,95 +39,96 @@ import LayoutDrag from './../LayoutDrag';
import _ from 'lodash';
export default {
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
isEditing: {
type: Boolean,
required: true
}
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
computed: {
size() {
let {width, height} = this.item;
return {
width: (this.gridSize[0] * width),
height: (this.gridSize[1] * height)
};
},
style() {
let {x, y, width, height} = this.item;
return {
left: (this.gridSize[0] * x) + 'px',
top: (this.gridSize[1] * y) + 'px',
width: (this.gridSize[0] * width) + 'px',
height: (this.gridSize[1] * height) + 'px',
minWidth: (this.gridSize[0] * width) + 'px',
minHeight: (this.gridSize[1] * height) + 'px'
};
},
inspectable() {
return this.item.type === 'subobject-view' || this.item.type === 'telemetry-view';
}
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
methods: {
updatePosition(event) {
let currentPosition = [event.pageX, event.pageY];
this.initialPosition = this.initialPosition || currentPosition;
this.delta = currentPosition.map(function (value, index) {
return value - this.initialPosition[index];
}.bind(this));
},
startMove(event, posFactor = [1, 1], dimFactor = [0, 0]) {
if (!this.isEditing) {
return;
}
document.body.addEventListener('mousemove', this.continueMove);
document.body.addEventListener('mouseup', this.endMove);
this.dragPosition = {
position: [this.item.x, this.item.y]
};
this.updatePosition(event);
this.activeDrag = new LayoutDrag(this.dragPosition, posFactor, dimFactor, this.gridSize);
event.preventDefault();
},
continueMove(event) {
event.preventDefault();
this.updatePosition(event);
let newPosition = this.activeDrag.getAdjustedPosition(this.delta);
if (!_.isEqual(newPosition, this.dragPosition)) {
this.dragPosition = newPosition;
this.$emit('move', this.toGridDelta(this.delta));
}
},
endMove(event) {
document.body.removeEventListener('mousemove', this.continueMove);
document.body.removeEventListener('mouseup', this.endMove);
this.continueMove(event);
this.$emit('endMove');
this.dragPosition = undefined;
this.initialPosition = undefined;
this.delta = undefined;
event.preventDefault();
},
toGridDelta(pixelDelta) {
return pixelDelta.map((v, i) => {
return Math.round(v / this.gridSize[i]);
});
}
isEditing: {
type: Boolean,
required: true
}
},
computed: {
size() {
let { width, height } = this.item;
return {
width: this.gridSize[0] * width,
height: this.gridSize[1] * height
};
},
style() {
let { x, y, width, height } = this.item;
return {
left: this.gridSize[0] * x + 'px',
top: this.gridSize[1] * y + 'px',
width: this.gridSize[0] * width + 'px',
height: this.gridSize[1] * height + 'px',
minWidth: this.gridSize[0] * width + 'px',
minHeight: this.gridSize[1] * height + 'px'
};
},
inspectable() {
return this.item.type === 'subobject-view' || this.item.type === 'telemetry-view';
}
},
methods: {
updatePosition(event) {
let currentPosition = [event.pageX, event.pageY];
this.initialPosition = this.initialPosition || currentPosition;
this.delta = currentPosition.map(
function (value, index) {
return value - this.initialPosition[index];
}.bind(this)
);
},
startMove(event, posFactor = [1, 1], dimFactor = [0, 0]) {
if (!this.isEditing) {
return;
}
document.body.addEventListener('mousemove', this.continueMove);
document.body.addEventListener('mouseup', this.endMove);
this.dragPosition = {
position: [this.item.x, this.item.y]
};
this.updatePosition(event);
this.activeDrag = new LayoutDrag(this.dragPosition, posFactor, dimFactor, this.gridSize);
event.preventDefault();
},
continueMove(event) {
event.preventDefault();
this.updatePosition(event);
let newPosition = this.activeDrag.getAdjustedPosition(this.delta);
if (!_.isEqual(newPosition, this.dragPosition)) {
this.dragPosition = newPosition;
this.$emit('move', this.toGridDelta(this.delta));
}
},
endMove(event) {
document.body.removeEventListener('mousemove', this.continueMove);
document.body.removeEventListener('mouseup', this.endMove);
this.continueMove(event);
this.$emit('endMove');
this.dragPosition = undefined;
this.initialPosition = undefined;
this.delta = undefined;
event.preventDefault();
},
toGridDelta(pixelDelta) {
return pixelDelta.map((v, i) => {
return Math.round(v / this.gridSize[i]);
});
}
}
};
</script>

View File

@ -21,356 +21,347 @@
-->
<template>
<div
class="l-layout__frame c-frame no-frame c-line-view"
:class="[styleClass]"
:style="style"
>
<svg
width="100%"
height="100%"
>
<line
class="c-line-view__hover-indicator"
v-bind="linePosition"
vector-effect="non-scaling-stroke"
/>
<line
class="c-line-view__line"
v-bind="linePosition"
:stroke="stroke"
vector-effect="non-scaling-stroke"
/>
<div class="l-layout__frame c-frame no-frame c-line-view" :class="[styleClass]" :style="style">
<svg width="100%" height="100%">
<line
class="c-line-view__hover-indicator"
v-bind="linePosition"
vector-effect="non-scaling-stroke"
/>
<line
class="c-line-view__line"
v-bind="linePosition"
:stroke="stroke"
vector-effect="non-scaling-stroke"
/>
</svg>
<div
class="c-frame__move-bar"
@mousedown.left="startDrag($event)"
></div>
<div
v-if="showFrameEdit"
class="c-frame-edit"
>
<div
class="c-frame-edit__handle"
:class="startHandleClass"
@mousedown="startDrag($event, 'start')"
>
</div>
<div
class="c-frame-edit__handle"
:class="endHandleClass"
@mousedown="startDrag($event, 'end')"
></div>
<div class="c-frame__move-bar" @mousedown.left="startDrag($event)"></div>
<div v-if="showFrameEdit" class="c-frame-edit">
<div
class="c-frame-edit__handle"
:class="startHandleClass"
@mousedown="startDrag($event, 'start')"
></div>
<div
class="c-frame-edit__handle"
:class="endHandleClass"
@mousedown="startDrag($event, 'end')"
></div>
</div>
</div>
</div>
</template>
<script>
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
import conditionalStylesMixin from '../mixins/objectStyles-mixin';
import _ from 'lodash';
const START_HANDLE_QUADRANTS = {
1: 'c-frame-edit__handle--sw',
2: 'c-frame-edit__handle--se',
3: 'c-frame-edit__handle--ne',
4: 'c-frame-edit__handle--nw',
5: 'c-frame-edit__handle--nw',
6: 'c-frame-edit__handle--ne'
1: 'c-frame-edit__handle--sw',
2: 'c-frame-edit__handle--se',
3: 'c-frame-edit__handle--ne',
4: 'c-frame-edit__handle--nw',
5: 'c-frame-edit__handle--nw',
6: 'c-frame-edit__handle--ne'
};
const END_HANDLE_QUADRANTS = {
1: 'c-frame-edit__handle--ne',
2: 'c-frame-edit__handle--nw',
3: 'c-frame-edit__handle--sw',
4: 'c-frame-edit__handle--se',
5: 'c-frame-edit__handle--sw',
6: 'c-frame-edit__handle--nw'
1: 'c-frame-edit__handle--ne',
2: 'c-frame-edit__handle--nw',
3: 'c-frame-edit__handle--sw',
4: 'c-frame-edit__handle--se',
5: 'c-frame-edit__handle--sw',
6: 'c-frame-edit__handle--nw'
};
export default {
makeDefinition() {
return {
x: 5,
y: 10,
x2: 10,
y2: 5,
stroke: '#666666'
};
makeDefinition() {
return {
x: 5,
y: 10,
x2: 10,
y2: 5,
stroke: '#666666'
};
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
initSelect: Boolean,
index: {
type: Number,
required: true
},
multiSelect: Boolean
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
data() {
return {
dragPosition: undefined,
dragging: undefined,
selection: []
};
initSelect: Boolean,
index: {
type: Number,
required: true
},
computed: {
showFrameEdit() {
let layoutItem = this.selection.length > 0 && this.selection[0][0].context.layoutItem;
multiSelect: Boolean
},
data() {
return {
dragPosition: undefined,
dragging: undefined,
selection: []
};
},
computed: {
showFrameEdit() {
let layoutItem = this.selection.length > 0 && this.selection[0][0].context.layoutItem;
return !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
},
position() {
let {x, y, x2, y2} = this.item;
if (this.dragging && this.dragPosition) {
({x, y, x2, y2} = this.dragPosition);
}
return {
x,
y,
x2,
y2
};
},
stroke() {
if (this.itemStyle) {
if (this.itemStyle.border) {
return this.itemStyle.border.replace('1px solid ', '');
}
return '';
} else {
return this.item.stroke;
}
},
style() {
let {x, y, x2, y2} = this.position;
let width = Math.max(this.gridSize[0] * Math.abs(x - x2), 1);
let height = Math.max(this.gridSize[1] * Math.abs(y - y2), 1);
let left = this.gridSize[0] * Math.min(x, x2);
let top = this.gridSize[1] * Math.min(y, y2);
return {
left: `${left}px`,
top: `${top}px`,
width: `${width}px`,
height: `${height}px`
};
},
startHandleClass() {
return START_HANDLE_QUADRANTS[this.vectorQuadrant];
},
endHandleClass() {
return END_HANDLE_QUADRANTS[this.vectorQuadrant];
},
vectorQuadrant() {
let {x, y, x2, y2} = this.position;
if (x2 === x) {
return 5; // Vertical line
}
if (y2 === y) {
return 6; // Horizontal line
}
if (x2 > x) {
if (y2 < y) {
return 1;
}
return 4;
}
if (y2 < y) {
return 2;
}
return 3;
},
linePosition() {
let pos = {};
switch (this.vectorQuadrant) {
case 1:
case 3:
// slopes up
pos = {
x1: '0%',
y1: '100%',
x2: '100%',
y2: '0%'
};
break;
case 5:
// vertical
pos = {
x1: '0%',
y1: '0%',
x2: '0%',
y2: '100%'
};
break;
case 6:
// horizontal
pos = {
x1: '0%',
y1: '0%',
x2: '100%',
y2: '0%'
};
break;
default:
// slopes down
pos = {
x1: '0%',
y1: '0%',
x2: '100%',
y2: '100%'
};
break;
}
return pos;
}
return !this.multiSelect && layoutItem && layoutItem.id === this.item.id;
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
position() {
let { x, y, x2, y2 } = this.item;
if (this.dragging && this.dragPosition) {
({ x, y, x2, y2 } = this.dragPosition);
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
return {
x,
y,
x2,
y2
};
},
mounted() {
this.openmct.selection.on('change', this.setSelection);
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(this.$el, this.context, this.initSelect);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
stroke() {
if (this.itemStyle) {
if (this.itemStyle.border) {
return this.itemStyle.border.replace('1px solid ', '');
}
this.openmct.selection.off('change', this.setSelection);
return '';
} else {
return this.item.stroke;
}
},
methods: {
startDrag(event, position) {
this.dragging = position;
document.body.addEventListener('mousemove', this.continueDrag);
document.body.addEventListener('mouseup', this.endDrag);
this.startPosition = [event.pageX, event.pageY];
let {x, y, x2, y2} = this.item;
this.dragPosition = {
x,
y,
x2,
y2
};
if (x === x2 || y === y2) {
if (y > y2 || x < x2) {
if (this.dragging === 'start') {
this.dragging = 'end';
} else if (this.dragging === 'end') {
this.dragging = 'start';
}
}
}
style() {
let { x, y, x2, y2 } = this.position;
let width = Math.max(this.gridSize[0] * Math.abs(x - x2), 1);
let height = Math.max(this.gridSize[1] * Math.abs(y - y2), 1);
let left = this.gridSize[0] * Math.min(x, x2);
let top = this.gridSize[1] * Math.min(y, y2);
event.preventDefault();
},
continueDrag(event) {
event.preventDefault();
let pxDeltaX = this.startPosition[0] - event.pageX;
let pxDeltaY = this.startPosition[1] - event.pageY;
let newPosition = this.calculateDragPosition(pxDeltaX, pxDeltaY);
return {
left: `${left}px`,
top: `${top}px`,
width: `${width}px`,
height: `${height}px`
};
},
startHandleClass() {
return START_HANDLE_QUADRANTS[this.vectorQuadrant];
},
endHandleClass() {
return END_HANDLE_QUADRANTS[this.vectorQuadrant];
},
vectorQuadrant() {
let { x, y, x2, y2 } = this.position;
if (x2 === x) {
return 5; // Vertical line
}
if (!this.dragging) {
if (!_.isEqual(newPosition, this.dragPosition)) {
let gridDelta = [event.pageX - this.startPosition[0], event.pageY - this.startPosition[1]];
this.dragPosition = newPosition;
this.$emit('move', this.toGridDelta(gridDelta));
}
} else {
this.dragPosition = newPosition;
}
},
endDrag(event) {
document.body.removeEventListener('mousemove', this.continueDrag);
document.body.removeEventListener('mouseup', this.endDrag);
let {x, y, x2, y2} = this.dragPosition;
if (!this.dragging) {
this.$emit('endMove');
} else {
this.$emit('endLineResize', this.item, {
x,
y,
x2,
y2
});
}
if (y2 === y) {
return 6; // Horizontal line
}
this.dragPosition = undefined;
this.dragging = undefined;
event.preventDefault();
},
calculateDragPosition(pxDeltaX, pxDeltaY) {
let gridDeltaX = Math.round(pxDeltaX / this.gridSize[0]);
let gridDeltaY = Math.round(pxDeltaY / this.gridSize[1]);
let {x, y, x2, y2} = this.item;
let dragPosition = {
x,
y,
x2,
y2
};
if (this.dragging === 'start') {
dragPosition.x -= gridDeltaX;
dragPosition.y -= gridDeltaY;
} else if (this.dragging === 'end') {
dragPosition.x2 -= gridDeltaX;
dragPosition.y2 -= gridDeltaY;
} else {
// dragging entire line.
dragPosition.x -= gridDeltaX;
dragPosition.y -= gridDeltaY;
dragPosition.x2 -= gridDeltaX;
dragPosition.y2 -= gridDeltaY;
}
return dragPosition;
},
setSelection(selection) {
this.selection = selection;
},
toGridDelta(pixelDelta) {
return pixelDelta.map((v, i) => {
return Math.round(v / this.gridSize[i]);
});
if (x2 > x) {
if (y2 < y) {
return 1;
}
return 4;
}
if (y2 < y) {
return 2;
}
return 3;
},
linePosition() {
let pos = {};
switch (this.vectorQuadrant) {
case 1:
case 3:
// slopes up
pos = {
x1: '0%',
y1: '100%',
x2: '100%',
y2: '0%'
};
break;
case 5:
// vertical
pos = {
x1: '0%',
y1: '0%',
x2: '0%',
y2: '100%'
};
break;
case 6:
// horizontal
pos = {
x1: '0%',
y1: '0%',
x2: '100%',
y2: '0%'
};
break;
default:
// slopes down
pos = {
x1: '0%',
y1: '0%',
x2: '100%',
y2: '100%'
};
break;
}
return pos;
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.openmct.selection.on('change', this.setSelection);
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el,
this.context,
this.initSelect
);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
this.openmct.selection.off('change', this.setSelection);
},
methods: {
startDrag(event, position) {
this.dragging = position;
document.body.addEventListener('mousemove', this.continueDrag);
document.body.addEventListener('mouseup', this.endDrag);
this.startPosition = [event.pageX, event.pageY];
let { x, y, x2, y2 } = this.item;
this.dragPosition = {
x,
y,
x2,
y2
};
if (x === x2 || y === y2) {
if (y > y2 || x < x2) {
if (this.dragging === 'start') {
this.dragging = 'end';
} else if (this.dragging === 'end') {
this.dragging = 'start';
}
}
}
event.preventDefault();
},
continueDrag(event) {
event.preventDefault();
let pxDeltaX = this.startPosition[0] - event.pageX;
let pxDeltaY = this.startPosition[1] - event.pageY;
let newPosition = this.calculateDragPosition(pxDeltaX, pxDeltaY);
if (!this.dragging) {
if (!_.isEqual(newPosition, this.dragPosition)) {
let gridDelta = [
event.pageX - this.startPosition[0],
event.pageY - this.startPosition[1]
];
this.dragPosition = newPosition;
this.$emit('move', this.toGridDelta(gridDelta));
}
} else {
this.dragPosition = newPosition;
}
},
endDrag(event) {
document.body.removeEventListener('mousemove', this.continueDrag);
document.body.removeEventListener('mouseup', this.endDrag);
let { x, y, x2, y2 } = this.dragPosition;
if (!this.dragging) {
this.$emit('endMove');
} else {
this.$emit('endLineResize', this.item, {
x,
y,
x2,
y2
});
}
this.dragPosition = undefined;
this.dragging = undefined;
event.preventDefault();
},
calculateDragPosition(pxDeltaX, pxDeltaY) {
let gridDeltaX = Math.round(pxDeltaX / this.gridSize[0]);
let gridDeltaY = Math.round(pxDeltaY / this.gridSize[1]);
let { x, y, x2, y2 } = this.item;
let dragPosition = {
x,
y,
x2,
y2
};
if (this.dragging === 'start') {
dragPosition.x -= gridDeltaX;
dragPosition.y -= gridDeltaY;
} else if (this.dragging === 'end') {
dragPosition.x2 -= gridDeltaX;
dragPosition.y2 -= gridDeltaY;
} else {
// dragging entire line.
dragPosition.x -= gridDeltaX;
dragPosition.y -= gridDeltaY;
dragPosition.x2 -= gridDeltaX;
dragPosition.y2 -= gridDeltaY;
}
return dragPosition;
},
setSelection(selection) {
this.selection = selection;
},
toGridDelta(pixelDelta) {
return pixelDelta.map((v, i) => {
return Math.round(v / this.gridSize[i]);
});
}
}
};
</script>

View File

@ -20,25 +20,25 @@
at runtime from the About dialog for additional information.
-->
<template>
<layout-frame
<layout-frame
:item="item"
:grid-size="gridSize"
:title="domainObject && domainObject.name"
:is-editing="isEditing"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')"
>
>
<object-frame
v-if="domainObject"
ref="objectFrame"
:domain-object="domainObject"
:object-path="currentObjectPath"
:has-frame="item.hasFrame"
:show-edit-view="false"
:layout-font-size="item.fontSize"
:layout-font="item.font"
v-if="domainObject"
ref="objectFrame"
:domain-object="domainObject"
:object-path="currentObjectPath"
:has-frame="item.hasFrame"
:show-edit-view="false"
:layout-font-size="item.fontSize"
:layout-font="item.font"
/>
</layout-frame>
</layout-frame>
</template>
<script>
@ -51,126 +51,125 @@ const DEFAULT_POSITION = [1, 1];
const DEFAULT_HIDDEN_FRAME_TYPES = ['hyperlink', 'summary-widget', 'conditionWidget'];
function getDefaultDimensions(gridSize) {
return MINIMUM_FRAME_SIZE.map((min, index) => {
return Math.max(
Math.ceil(min / gridSize[index]),
DEFAULT_DIMENSIONS[index]
);
});
return MINIMUM_FRAME_SIZE.map((min, index) => {
return Math.max(Math.ceil(min / gridSize[index]), DEFAULT_DIMENSIONS[index]);
});
}
function hasFrameByDefault(type) {
return DEFAULT_HIDDEN_FRAME_TYPES.indexOf(type) === -1;
return DEFAULT_HIDDEN_FRAME_TYPES.indexOf(type) === -1;
}
export default {
makeDefinition(openmct, gridSize, domainObject, position, viewKey) {
let defaultDimensions = getDefaultDimensions(gridSize);
position = position || DEFAULT_POSITION;
makeDefinition(openmct, gridSize, domainObject, position, viewKey) {
let defaultDimensions = getDefaultDimensions(gridSize);
position = position || DEFAULT_POSITION;
return {
width: defaultDimensions[0],
height: defaultDimensions[1],
x: position[0],
y: position[1],
identifier: domainObject.identifier,
hasFrame: hasFrameByDefault(domainObject.type),
fontSize: 'default',
font: 'default',
viewKey
};
return {
width: defaultDimensions[0],
height: defaultDimensions[1],
x: position[0],
y: position[1],
identifier: domainObject.identifier,
hasFrame: hasFrameByDefault(domainObject.type),
fontSize: 'default',
font: 'default',
viewKey
};
},
components: {
ObjectFrame,
LayoutFrame
},
inject: ['openmct', 'objectPath'],
props: {
item: {
type: Object,
required: true
},
components: {
ObjectFrame,
LayoutFrame
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
inject: ['openmct', 'objectPath'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
initSelect: Boolean,
index: {
type: Number,
required: true
},
isEditing: {
type: Boolean,
required: true
}
initSelect: Boolean,
index: {
type: Number,
required: true
},
data() {
return {
domainObject: undefined,
currentObjectPath: [],
mutablePromise: undefined
};
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
if (this.openmct.objects.supportsMutation(this.item.identifier)) {
this.mutablePromise = this.openmct.objects.getMutable(this.item.identifier)
.then(this.setObject);
} else {
this.openmct.objects.get(this.item.identifier)
.then(this.setObject);
}
},
beforeDestroy() {
if (this.removeSelectable) {
this.removeSelectable();
}
if (this.mutablePromise) {
this.mutablePromise.then(() => {
this.openmct.objects.destroyMutable(this.domainObject);
});
} else if (this?.domainObject?.isMutable) {
this.openmct.objects.destroyMutable(this.domainObject);
}
},
methods: {
setObject(domainObject) {
this.domainObject = domainObject;
this.mutablePromise = undefined;
this.currentObjectPath = [this.domainObject].concat(this.objectPath.slice());
this.$nextTick(() => {
let reference = this.$refs.objectFrame;
if (reference) {
let childContext = this.$refs.objectFrame.getSelectionContext();
childContext.item = domainObject;
childContext.layoutItem = this.item;
childContext.index = this.index;
this.context = childContext;
this.removeSelectable = this.openmct.selection.selectable(
this.$el, this.context, this.immediatelySelect || this.initSelect);
delete this.immediatelySelect;
}
});
}
isEditing: {
type: Boolean,
required: true
}
},
data() {
return {
domainObject: undefined,
currentObjectPath: [],
mutablePromise: undefined
};
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
if (this.openmct.objects.supportsMutation(this.item.identifier)) {
this.mutablePromise = this.openmct.objects
.getMutable(this.item.identifier)
.then(this.setObject);
} else {
this.openmct.objects.get(this.item.identifier).then(this.setObject);
}
},
beforeDestroy() {
if (this.removeSelectable) {
this.removeSelectable();
}
if (this.mutablePromise) {
this.mutablePromise.then(() => {
this.openmct.objects.destroyMutable(this.domainObject);
});
} else if (this?.domainObject?.isMutable) {
this.openmct.objects.destroyMutable(this.domainObject);
}
},
methods: {
setObject(domainObject) {
this.domainObject = domainObject;
this.mutablePromise = undefined;
this.currentObjectPath = [this.domainObject].concat(this.objectPath.slice());
this.$nextTick(() => {
let reference = this.$refs.objectFrame;
if (reference) {
let childContext = this.$refs.objectFrame.getSelectionContext();
childContext.item = domainObject;
childContext.layoutItem = this.item;
childContext.index = this.index;
this.context = childContext;
this.removeSelectable = this.openmct.selection.selectable(
this.$el,
this.context,
this.immediatelySelect || this.initSelect
);
delete this.immediatelySelect;
}
});
}
}
};
</script>

View File

@ -21,353 +21,365 @@
-->
<template>
<layout-frame
<layout-frame
:item="item"
:grid-size="gridSize"
:is-editing="isEditing"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')"
>
>
<div
v-if="domainObject"
class="c-telemetry-view u-style-receiver"
:class="[itemClasses]"
:style="styleObject"
:data-font-size="item.fontSize"
:data-font="item.font"
@contextmenu.prevent="showContextMenu"
v-if="domainObject"
class="c-telemetry-view u-style-receiver"
:class="[itemClasses]"
:style="styleObject"
:data-font-size="item.fontSize"
:data-font="item.font"
@contextmenu.prevent="showContextMenu"
>
<div
class="is-status__indicator"
:title="`This item is ${status}`"
></div>
<div
v-if="showLabel"
class="c-telemetry-view__label"
>
<div class="c-telemetry-view__label-text">
{{ domainObject.name }}
</div>
<div class="is-status__indicator" :title="`This item is ${status}`"></div>
<div v-if="showLabel" class="c-telemetry-view__label">
<div class="c-telemetry-view__label-text">
{{ domainObject.name }}
</div>
</div>
<div
v-if="showValue"
:title="fieldName"
class="c-telemetry-view__value"
:class="[telemetryClass]"
>
<div class="c-telemetry-view__value-text">
{{ telemetryValue }}
<span
v-if="unit && item.showUnits"
class="c-telemetry-view__value-text__unit"
>
{{ unit }}
</span>
</div>
<div
v-if="showValue"
:title="fieldName"
class="c-telemetry-view__value"
:class="[telemetryClass]"
>
<div class="c-telemetry-view__value-text">
{{ telemetryValue }}
<span v-if="unit && item.showUnits" class="c-telemetry-view__value-text__unit">
{{ unit }}
</span>
</div>
</div>
</div>
</layout-frame>
</layout-frame>
</template>
<script>
import LayoutFrame from './LayoutFrame.vue';
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
import conditionalStylesMixin from '../mixins/objectStyles-mixin';
import stalenessMixin from '@/ui/mixins/staleness-mixin';
import { getDefaultNotebook, getNotebookSectionAndPage } from '@/plugins/notebook/utils/notebook-storage.js';
import {
getDefaultNotebook,
getNotebookSectionAndPage
} from '@/plugins/notebook/utils/notebook-storage.js';
const DEFAULT_TELEMETRY_DIMENSIONS = [10, 5];
const DEFAULT_POSITION = [1, 1];
const CONTEXT_MENU_ACTIONS = ['copyToClipboard', 'copyToNotebook', 'viewHistoricalData'];
export default {
makeDefinition(openmct, gridSize, domainObject, position) {
let metadata = openmct.telemetry.getMetadata(domainObject);
position = position || DEFAULT_POSITION;
makeDefinition(openmct, gridSize, domainObject, position) {
let metadata = openmct.telemetry.getMetadata(domainObject);
position = position || DEFAULT_POSITION;
return {
identifier: domainObject.identifier,
x: position[0],
y: position[1],
width: DEFAULT_TELEMETRY_DIMENSIONS[0],
height: DEFAULT_TELEMETRY_DIMENSIONS[1],
displayMode: 'all',
value: metadata.getDefaultDisplayValue()?.key,
stroke: "",
fill: "",
color: "",
fontSize: 'default',
font: 'default'
};
return {
identifier: domainObject.identifier,
x: position[0],
y: position[1],
width: DEFAULT_TELEMETRY_DIMENSIONS[0],
height: DEFAULT_TELEMETRY_DIMENSIONS[1],
displayMode: 'all',
value: metadata.getDefaultDisplayValue()?.key,
stroke: '',
fill: '',
color: '',
fontSize: 'default',
font: 'default'
};
},
components: {
LayoutFrame
},
mixins: [conditionalStylesMixin, stalenessMixin],
inject: ['openmct', 'objectPath', 'currentView'],
props: {
item: {
type: Object,
required: true
},
components: {
LayoutFrame
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
mixins: [conditionalStylesMixin, stalenessMixin],
inject: ['openmct', 'objectPath', 'currentView'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
initSelect: Boolean,
index: {
type: Number,
required: true
},
isEditing: {
type: Boolean,
required: true
}
initSelect: Boolean,
index: {
type: Number,
required: true
},
data() {
return {
currentObjectPath: undefined,
datum: undefined,
domainObject: undefined,
formats: undefined,
viewKey: `alphanumeric-format-${Math.random()}`,
status: '',
mutablePromise: undefined
};
},
computed: {
itemClasses() {
let classes = [];
if (this.status) {
classes.push(`is-status--${this.status}`);
}
if (this.isStale) {
classes.push('is-stale');
}
return classes;
},
showLabel() {
let displayMode = this.item.displayMode;
return displayMode === 'all' || displayMode === 'label';
},
showValue() {
let displayMode = this.item.displayMode;
return displayMode === 'all' || displayMode === 'value';
},
unit() {
let value = this.item.value;
let unit = this.metadata ? this.metadata.value(value).unit : '';
return unit;
},
styleObject() {
let size;
//for legacy size support
if (!this.item.fontSize) {
size = this.item.size;
}
return Object.assign({}, {
size
}, this.itemStyle);
},
fieldName() {
return this.valueMetadata && this.valueMetadata.name;
},
valueMetadata() {
return this.datum && this.metadata.value(this.item.value);
},
formatter() {
if (this.item.format) {
return this.customStringformatter;
}
return this.formats[this.item.value];
},
telemetryValue() {
if (!this.datum) {
return '---';
}
return this.formatter && this.formatter.format(this.datum);
},
telemetryClass() {
if (!this.datum) {
return;
}
let alarm = this.limitEvaluator && this.limitEvaluator.evaluate(this.datum, this.valueMetadata);
return alarm && alarm.cssClass;
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
if (this.openmct.objects.supportsMutation(this.item.identifier)) {
this.mutablePromise = this.openmct.objects.getMutable(this.item.identifier)
.then(this.setObject);
} else {
this.openmct.objects.get(this.item.identifier)
.then(this.setObject);
}
this.status = this.openmct.status.get(this.item.identifier);
this.removeStatusListener = this.openmct.status.observe(this.item.identifier, this.setStatus);
},
beforeDestroy() {
this.removeStatusListener();
if (this.removeSelectable) {
this.removeSelectable();
}
if (this.telemetryCollection) {
this.telemetryCollection.off('add', this.setLatestValues);
this.telemetryCollection.off('clear', this.refreshData);
this.telemetryCollection.destroy();
}
if (this.mutablePromise) {
this.mutablePromise.then(() => {
this.openmct.objects.destroyMutable(this.domainObject);
});
} else if (this?.domainObject?.isMutable) {
this.openmct.objects.destroyMutable(this.domainObject);
}
},
methods: {
formattedValueForCopy() {
const timeFormatterKey = this.openmct.time.timeSystem().key;
const timeFormatter = this.formats[timeFormatterKey];
const unit = this.unit ? ` ${this.unit}` : '';
return `At ${timeFormatter.format(this.datum)} ${this.domainObject.name} had a value of ${this.telemetryValue}${unit}`;
},
setLatestValues(data) {
this.latestDatum = data[data.length - 1];
this.updateView();
},
updateView() {
if (!this.updatingView) {
this.updatingView = true;
requestAnimationFrame(() => {
this.datum = this.latestDatum;
this.updatingView = false;
});
}
},
refreshData(bounds, isTick) {
if (!isTick) {
this.latestDatum = undefined;
this.updateView();
}
},
setObject(domainObject) {
this.domainObject = domainObject;
this.mutablePromise = undefined;
this.keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(this.domainObject);
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
this.timeContext = this.openmct.time.getContextForView(this.objectPath);
const valueMetadata = this.metadata ? this.metadata.value(this.item.value) : {};
this.customStringformatter = this.openmct.telemetry.customStringFormatter(valueMetadata, this.item.format);
this.telemetryCollection = this.openmct.telemetry.requestCollection(this.domainObject, {
size: 1,
strategy: 'latest',
timeContext: this.timeContext
});
this.telemetryCollection.on('add', this.setLatestValues);
this.telemetryCollection.on('clear', this.refreshData);
this.telemetryCollection.load();
this.currentObjectPath = this.objectPath.slice();
this.currentObjectPath.unshift(this.domainObject);
this.context = {
item: domainObject,
layoutItem: this.item,
index: this.index,
updateTelemetryFormat: this.updateTelemetryFormat,
toggleUnits: this.toggleUnits,
showUnits: this.showUnits
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el, this.context, this.immediatelySelect || this.initSelect);
delete this.immediatelySelect;
this.subscribeToStaleness(this.domainObject);
},
updateTelemetryFormat(format) {
this.customStringformatter.setFormat(format);
this.$emit('formatChanged', this.item, format);
},
updateViewContext() {
this.$emit('contextClick', {
viewHistoricalData: true,
formattedValueForCopy: this.formattedValueForCopy
});
},
async getContextMenuActions() {
const defaultNotebook = getDefaultNotebook();
let defaultNotebookName;
if (defaultNotebook) {
const domainObject = await this.openmct.objects.get(defaultNotebook.identifier);
const { section, page } = getNotebookSectionAndPage(domainObject, defaultNotebook.defaultSectionId, defaultNotebook.defaultPageId);
if (section && page) {
const defaultPath = domainObject && `${domainObject.name} - ${section.name} - ${page.name}`;
defaultNotebookName = `Copy to Notebook ${defaultPath}`;
}
}
return CONTEXT_MENU_ACTIONS
.map(actionKey => {
const action = this.openmct.actions.getAction(actionKey);
if (action.key === 'copyToNotebook') {
action.name = defaultNotebookName;
}
return action;
})
.filter(action => action.name !== undefined);
},
async showContextMenu(event) {
this.updateViewContext();
const contextMenuActions = await this.getContextMenuActions();
const menuItems = this.openmct.menus.actionsToMenuItems(contextMenuActions, this.currentObjectPath, this.currentView);
this.openmct.menus.showMenu(event.x, event.y, menuItems);
},
setStatus(status) {
this.status = status;
}
isEditing: {
type: Boolean,
required: true
}
};
},
data() {
return {
currentObjectPath: undefined,
datum: undefined,
domainObject: undefined,
formats: undefined,
viewKey: `alphanumeric-format-${Math.random()}`,
status: '',
mutablePromise: undefined
};
},
computed: {
itemClasses() {
let classes = [];
if (this.status) {
classes.push(`is-status--${this.status}`);
}
if (this.isStale) {
classes.push('is-stale');
}
return classes;
},
showLabel() {
let displayMode = this.item.displayMode;
return displayMode === 'all' || displayMode === 'label';
},
showValue() {
let displayMode = this.item.displayMode;
return displayMode === 'all' || displayMode === 'value';
},
unit() {
let value = this.item.value;
let unit = this.metadata ? this.metadata.value(value).unit : '';
return unit;
},
styleObject() {
let size;
//for legacy size support
if (!this.item.fontSize) {
size = this.item.size;
}
return Object.assign(
{},
{
size
},
this.itemStyle
);
},
fieldName() {
return this.valueMetadata && this.valueMetadata.name;
},
valueMetadata() {
return this.datum && this.metadata.value(this.item.value);
},
formatter() {
if (this.item.format) {
return this.customStringformatter;
}
return this.formats[this.item.value];
},
telemetryValue() {
if (!this.datum) {
return '---';
}
return this.formatter && this.formatter.format(this.datum);
},
telemetryClass() {
if (!this.datum) {
return;
}
let alarm =
this.limitEvaluator && this.limitEvaluator.evaluate(this.datum, this.valueMetadata);
return alarm && alarm.cssClass;
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
if (this.openmct.objects.supportsMutation(this.item.identifier)) {
this.mutablePromise = this.openmct.objects
.getMutable(this.item.identifier)
.then(this.setObject);
} else {
this.openmct.objects.get(this.item.identifier).then(this.setObject);
}
this.status = this.openmct.status.get(this.item.identifier);
this.removeStatusListener = this.openmct.status.observe(this.item.identifier, this.setStatus);
},
beforeDestroy() {
this.removeStatusListener();
if (this.removeSelectable) {
this.removeSelectable();
}
if (this.telemetryCollection) {
this.telemetryCollection.off('add', this.setLatestValues);
this.telemetryCollection.off('clear', this.refreshData);
this.telemetryCollection.destroy();
}
if (this.mutablePromise) {
this.mutablePromise.then(() => {
this.openmct.objects.destroyMutable(this.domainObject);
});
} else if (this?.domainObject?.isMutable) {
this.openmct.objects.destroyMutable(this.domainObject);
}
},
methods: {
formattedValueForCopy() {
const timeFormatterKey = this.openmct.time.timeSystem().key;
const timeFormatter = this.formats[timeFormatterKey];
const unit = this.unit ? ` ${this.unit}` : '';
return `At ${timeFormatter.format(this.datum)} ${this.domainObject.name} had a value of ${
this.telemetryValue
}${unit}`;
},
setLatestValues(data) {
this.latestDatum = data[data.length - 1];
this.updateView();
},
updateView() {
if (!this.updatingView) {
this.updatingView = true;
requestAnimationFrame(() => {
this.datum = this.latestDatum;
this.updatingView = false;
});
}
},
refreshData(bounds, isTick) {
if (!isTick) {
this.latestDatum = undefined;
this.updateView();
}
},
setObject(domainObject) {
this.domainObject = domainObject;
this.mutablePromise = undefined;
this.keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(this.domainObject);
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
this.timeContext = this.openmct.time.getContextForView(this.objectPath);
const valueMetadata = this.metadata ? this.metadata.value(this.item.value) : {};
this.customStringformatter = this.openmct.telemetry.customStringFormatter(
valueMetadata,
this.item.format
);
this.telemetryCollection = this.openmct.telemetry.requestCollection(this.domainObject, {
size: 1,
strategy: 'latest',
timeContext: this.timeContext
});
this.telemetryCollection.on('add', this.setLatestValues);
this.telemetryCollection.on('clear', this.refreshData);
this.telemetryCollection.load();
this.currentObjectPath = this.objectPath.slice();
this.currentObjectPath.unshift(this.domainObject);
this.context = {
item: domainObject,
layoutItem: this.item,
index: this.index,
updateTelemetryFormat: this.updateTelemetryFormat,
toggleUnits: this.toggleUnits,
showUnits: this.showUnits
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el,
this.context,
this.immediatelySelect || this.initSelect
);
delete this.immediatelySelect;
this.subscribeToStaleness(this.domainObject);
},
updateTelemetryFormat(format) {
this.customStringformatter.setFormat(format);
this.$emit('formatChanged', this.item, format);
},
updateViewContext() {
this.$emit('contextClick', {
viewHistoricalData: true,
formattedValueForCopy: this.formattedValueForCopy
});
},
async getContextMenuActions() {
const defaultNotebook = getDefaultNotebook();
let defaultNotebookName;
if (defaultNotebook) {
const domainObject = await this.openmct.objects.get(defaultNotebook.identifier);
const { section, page } = getNotebookSectionAndPage(
domainObject,
defaultNotebook.defaultSectionId,
defaultNotebook.defaultPageId
);
if (section && page) {
const defaultPath =
domainObject && `${domainObject.name} - ${section.name} - ${page.name}`;
defaultNotebookName = `Copy to Notebook ${defaultPath}`;
}
}
return CONTEXT_MENU_ACTIONS.map((actionKey) => {
const action = this.openmct.actions.getAction(actionKey);
if (action.key === 'copyToNotebook') {
action.name = defaultNotebookName;
}
return action;
}).filter((action) => action.name !== undefined);
},
async showContextMenu(event) {
this.updateViewContext();
const contextMenuActions = await this.getContextMenuActions();
const menuItems = this.openmct.menus.actionsToMenuItems(
contextMenuActions,
this.currentObjectPath,
this.currentView
);
this.openmct.menus.showMenu(event.x, event.y, menuItems);
},
setStatus(status) {
this.status = status;
}
}
};
</script>

View File

@ -21,111 +21,116 @@
-->
<template>
<layout-frame
<layout-frame
:item="item"
:grid-size="gridSize"
:is-editing="isEditing"
@move="(gridDelta) => $emit('move', gridDelta)"
@endMove="() => $emit('endMove')"
>
>
<div
class="c-text-view u-style-receiver js-style-receiver"
:data-font-size="item.fontSize"
:data-font="item.font"
:class="[styleClass]"
:style="style"
class="c-text-view u-style-receiver js-style-receiver"
:data-font-size="item.fontSize"
:data-font="item.font"
:class="[styleClass]"
:style="style"
>
<div class="c-text-view__text">{{ item.text }}</div>
<div class="c-text-view__text">{{ item.text }}</div>
</div>
</layout-frame>
</layout-frame>
</template>
<script>
import LayoutFrame from './LayoutFrame.vue';
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
import conditionalStylesMixin from '../mixins/objectStyles-mixin';
export default {
makeDefinition(openmct, gridSize, element) {
return {
fill: '',
stroke: '',
color: '',
x: 1,
y: 1,
width: 10,
height: 5,
text: element.text,
fontSize: 'default',
font: 'default'
};
makeDefinition(openmct, gridSize, element) {
return {
fill: '',
stroke: '',
color: '',
x: 1,
y: 1,
width: 10,
height: 5,
text: element.text,
fontSize: 'default',
font: 'default'
};
},
components: {
LayoutFrame
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
components: {
LayoutFrame
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2 && arr.every((el) => typeof el === 'number')
},
mixins: [conditionalStylesMixin],
inject: ['openmct'],
props: {
item: {
type: Object,
required: true
},
gridSize: {
type: Array,
required: true,
validator: (arr) => arr && arr.length === 2
&& arr.every(el => typeof el === 'number')
},
index: {
type: Number,
required: true
},
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
index: {
type: Number,
required: true
},
computed: {
style() {
let size;
//legacy size support
if (!this.item.fontSize) {
size = this.item.size;
}
return Object.assign({
size
}, this.itemStyle);
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el, this.context, this.initSelect);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
initSelect: Boolean,
isEditing: {
type: Boolean,
required: true
}
},
computed: {
style() {
let size;
//legacy size support
if (!this.item.fontSize) {
size = this.item.size;
}
return Object.assign(
{
size
},
this.itemStyle
);
}
},
watch: {
index(newIndex) {
if (!this.context) {
return;
}
this.context.index = newIndex;
},
item(newItem) {
if (!this.context) {
return;
}
this.context.layoutItem = newItem;
}
},
mounted() {
this.context = {
layoutItem: this.item,
index: this.index
};
this.removeSelectable = this.openmct.selection.selectable(
this.$el,
this.context,
this.initSelect
);
},
destroyed() {
if (this.removeSelectable) {
this.removeSelectable();
}
}
};
</script>

View File

@ -1,65 +1,66 @@
.c-box-view,
.c-ellipse-view {
border-width: $drawingObjBorderW !important;
display: flex;
align-items: stretch;
border-width: $drawingObjBorderW !important;
display: flex;
align-items: stretch;
.c-frame & {
@include abs();
}
.c-frame & {
@include abs();
}
}
.c-ellipse-view {
border-radius: 50%;
border-radius: 50%;
}
.c-line-view {
&.c-frame {
box-shadow: none !important;
}
&.c-frame {
box-shadow: none !important;
}
.c-frame-edit {
border: none;
}
.c-frame-edit {
border: none;
}
.c-handle-info {
background: rgba(#999, 0.2);
padding: 2px;
position: absolute;
top: 5px; left: 5px;
white-space: nowrap;
}
.c-handle-info {
background: rgba(#999, 0.2);
padding: 2px;
position: absolute;
top: 5px;
left: 5px;
white-space: nowrap;
}
svg {
// Prevent clipping when line is horizontal and vertical
min-height: 1px;
min-width: 1px;
// Must use !important to counteract setting in normalize.min.css
overflow: visible;
}
svg {
// Prevent clipping when line is horizontal and vertical
min-height: 1px;
min-width: 1px;
// Must use !important to counteract setting in normalize.min.css
overflow: visible;
}
&__line {
stroke-linecap: round;
stroke-width: $drawingObjBorderW;
}
&__line {
stroke-linecap: round;
stroke-width: $drawingObjBorderW;
}
&__hover-indicator {
display: none;
opacity: 0.5;
stroke: $editFrameColorHov;
stroke-width: $drawingObjBorderW + 4;
}
&__hover-indicator {
display: none;
opacity: 0.5;
stroke: $editFrameColorHov;
stroke-width: $drawingObjBorderW + 4;
}
.is-editing & {
// Needed to allow line to be moved
$w: 4px;
min-width: $w;
min-height: $w;
.is-editing & {
// Needed to allow line to be moved
$w: 4px;
min-width: $w;
min-height: $w;
&:hover {
[class*='__hover-indicator'] {
display: inline;
}
}
&:hover {
[class*='__hover-indicator'] {
display: inline;
}
}
}
}

View File

@ -1,96 +1,97 @@
@mixin displayMarquee($c) {
> .c-frame-edit {
// All other frames
//@include test($c, 0.4);
display: block;
}
> .c-frame > .c-frame-edit {
// Line object frame
//@include test($c, 0.4);
display: block;
}
> .c-frame-edit {
// All other frames
//@include test($c, 0.4);
display: block;
}
> .c-frame > .c-frame-edit {
// Line object frame
//@include test($c, 0.4);
display: block;
}
}
.l-layout {
@include abs();
display: flex;
flex-direction: column;
overflow: auto;
@include abs();
display: flex;
flex-direction: column;
overflow: auto;
&__grid-holder,
&__dimensions {
display: none;
&__grid-holder,
&__dimensions {
display: none;
}
&__dimensions {
$b: 1px dashed $editDimensionsColor;
border-right: $b;
border-bottom: $b;
pointer-events: none;
position: absolute;
&-vals {
$p: 2px;
color: $editDimensionsColor;
display: inline-block;
font-style: italic;
position: absolute;
bottom: $p;
right: $p;
opacity: 0.7;
}
}
&__dimensions {
$b: 1px dashed $editDimensionsColor;
border-right: $b;
border-bottom: $b;
pointer-events: none;
position: absolute;
&-vals {
$p: 2px;
color: $editDimensionsColor;
display: inline-block;
font-style: italic;
position: absolute;
bottom: $p; right: $p;
opacity: 0.7;
}
}
&__frame {
position: absolute;
}
&__frame {
position: absolute;
}
}
.is-editing {
.l-shell__main-container {
[s-selected],
[s-selected-parent] {
// Display grid and allow edit marquee to display in main layout holder when editing
> .l-layout {
background: $editUIGridColorBg;
.l-shell__main-container {
[s-selected],
[s-selected-parent] {
// Display grid and allow edit marquee to display in main layout holder when editing
> .l-layout {
background: $editUIGridColorBg;
> [class*="__dimensions"] {
display: block;
}
> [class*="__grid-holder"] {
display: block;
}
}
> [class*='__dimensions'] {
display: block;
}
> [class*='__grid-holder'] {
display: block;
}
}
}
}
.l-layout__frame {
&[s-selected]:not([multi-select="true"]),
&[s-selected-parent] {
// Display grid and allow edit marquee to display in nested layouts when editing
> * > * > .l-layout.allow-editing {
box-shadow: inset $editUIGridColorFg 0 0 2px 1px;
.l-layout__frame {
&[s-selected]:not([multi-select='true']),
&[s-selected-parent] {
// Display grid and allow edit marquee to display in nested layouts when editing
> * > * > .l-layout.allow-editing {
box-shadow: inset $editUIGridColorFg 0 0 2px 1px;
> [class*="__dimensions"] {
display: block;
}
> [class*='grid-holder'] {
display: block;
}
}
> [class*='__dimensions'] {
display: block;
}
> [class*='grid-holder'] {
display: block;
}
}
}
}
/*********************** EDIT MARQUEE CONTROL */
*[s-selected-parent] {
> .l-layout {
// When main shell layout is the parent
@include displayMarquee(deeppink); // TEMP
}
> * > * > * {
// When a sub-layout is the parent
@include displayMarquee(blue);
}
/*********************** EDIT MARQUEE CONTROL */
*[s-selected-parent] {
> .l-layout {
// When main shell layout is the parent
@include displayMarquee(deeppink); // TEMP
}
> * > * > * {
// When a sub-layout is the parent
@include displayMarquee(blue);
}
}
}

View File

@ -1,54 +1,62 @@
.c-frame-edit {
// In Layouts, this is the editing rect and handles
display: none; // Set to display: block in DisplayLayout.vue
pointer-events: none;
@include abs();
border: $editMarqueeBorder;
// In Layouts, this is the editing rect and handles
display: none; // Set to display: block in DisplayLayout.vue
pointer-events: none;
@include abs();
border: $editMarqueeBorder;
&__handle {
$d: 6px;
$o: floor($d * -0.5);
background: $editFrameColorHandleFg;
box-shadow: $editFrameColorHandleBg 0 0 0 2px;
pointer-events: all;
position: absolute;
width: $d; height: $d;
top: auto; right: auto; bottom: auto; left: auto;
&__handle {
$d: 6px;
$o: floor($d * -0.5);
background: $editFrameColorHandleFg;
box-shadow: $editFrameColorHandleBg 0 0 0 2px;
pointer-events: all;
position: absolute;
width: $d;
height: $d;
top: auto;
right: auto;
bottom: auto;
left: auto;
&:before {
// Extended hit area
@include abs(-10px);
content: '';
display: block;
z-index: 0;
}
&:hover {
background: $editUIColor;
}
&--nwse {
cursor: nwse-resize;
}
&--nw {
cursor: nw-resize;
left: $o; top: $o;
}
&--ne {
cursor: ne-resize;
right: $o; top: $o;
}
&--se {
cursor: se-resize;
right: $o; bottom: $o;
}
&--sw {
cursor: sw-resize;
left: $o; bottom: $o;
}
&:before {
// Extended hit area
@include abs(-10px);
content: '';
display: block;
z-index: 0;
}
&:hover {
background: $editUIColor;
}
&--nwse {
cursor: nwse-resize;
}
&--nw {
cursor: nw-resize;
left: $o;
top: $o;
}
&--ne {
cursor: ne-resize;
right: $o;
top: $o;
}
&--se {
cursor: se-resize;
right: $o;
bottom: $o;
}
&--sw {
cursor: sw-resize;
left: $o;
bottom: $o;
}
}
}

View File

@ -1,10 +1,10 @@
.c-image-view {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
.c-frame & {
@include abs();
border: 1px solid transparent;
}
.c-frame & {
@include abs();
border: 1px solid transparent;
}
}

View File

@ -2,134 +2,134 @@
/******************* FRAME */
.c-frame {
display: flex;
flex-direction: column;
display: flex;
flex-direction: column;
// Whatever is placed into the slot, make it fill the entirety of the space, obeying padding
> *:first-child {
flex: 1 1 auto;
}
// Whatever is placed into the slot, make it fill the entirety of the space, obeying padding
> *:first-child {
flex: 1 1 auto;
}
}
.c-frame__move-bar {
display: none;
display: none;
}
.is-editing {
/******************* STYLES FOR C-FRAME WHILE EDITING */
.c-frame {
border: 1px solid rgba($editFrameColorHov, 0.3);
/******************* STYLES FOR C-FRAME WHILE EDITING */
.c-frame {
border: 1px solid rgba($editFrameColorHov, 0.3);
&:not([s-selected]) {
&:hover {
border: $editFrameBorderHov;
}
}
&[s-selected] {
// All frames selected while editing
box-shadow: $editFrameSelectedShdw;
.c-frame__move-bar {
cursor: move;
}
}
&:not([s-selected]) {
&:hover {
border: $editFrameBorderHov;
}
}
/******************* DEFAULT STYLES FOR -EDIT__MOVE */
// All object types
.c-frame__move-bar {
@include abs();
display: block;
&[s-selected] {
// All frames selected while editing
box-shadow: $editFrameSelectedShdw;
.c-frame__move-bar {
cursor: move;
}
}
}
/******************* DEFAULT STYLES FOR -EDIT__MOVE */
// All object types
.c-frame__move-bar {
@include abs();
display: block;
}
// Has-complex-content objects
.c-so-view.has-complex-content {
@include transition($prop: transform, $dur: $transOutTime, $delay: $moveBarOutDelay);
> .c-so-view__local-controls {
@include transition($prop: transform, $dur: 250ms, $delay: $moveBarOutDelay);
}
// Has-complex-content objects
.c-so-view.has-complex-content {
@include transition($prop: transform, $dur: $transOutTime, $delay: $moveBarOutDelay);
+ .c-frame__move-bar {
display: none;
}
}
> .c-so-view__local-controls {
@include transition($prop: transform, $dur: 250ms, $delay: $moveBarOutDelay);
.l-layout {
/******************* 0 - 1 ITEM SELECTED */
&:not(.is-multi-selected) {
> .l-layout__frame {
> .c-so-view.has-complex-content {
> .c-so-view__local-controls {
@include transition($prop: transform, $dur: $transOutTime, $delay: $moveBarOutDelay);
}
+ .c-frame__move-bar {
@include transition($prop: height, $delay: $moveBarOutDelay);
@include userSelectNone();
background: $editFrameMovebarColorBg;
box-shadow: rgba(black, 0.3) 0 2px;
bottom: auto;
display: block;
height: 0; // Height is set on hover below
opacity: 0.9;
max-height: 100%;
overflow: hidden;
text-align: center;
z-index: 10;
&:before {
// Grippy
$h: 4px;
$tbOffset: math.div($editFrameMovebarH - $h, 2);
$lrOffset: 25%;
@include grippy($editFrameMovebarColorFg);
content: '';
display: none;
position: absolute;
top: $tbOffset;
right: $lrOffset;
bottom: $tbOffset;
left: $lrOffset;
}
}
}
+ .c-frame__move-bar {
display: none;
&:hover {
> .c-so-view.has-complex-content {
transition: $transInTransform;
transition-delay: 0s;
> .c-so-view__local-controls {
transform: translateY($editFrameMovebarH);
@include transition(height, $transOutTime);
transition-delay: 0s;
}
+ .c-frame__move-bar {
@include transition(height);
height: $editFrameMovebarH;
}
}
}
}
> .l-layout__frame[s-selected] {
> .c-so-view.has-complex-content {
+ .c-frame__move-bar:before {
display: block;
}
}
}
}
.l-layout {
/******************* 0 - 1 ITEM SELECTED */
&:not(.is-multi-selected) {
> .l-layout__frame {
> .c-so-view.has-complex-content {
> .c-so-view__local-controls {
@include transition($prop: transform, $dur: $transOutTime, $delay: $moveBarOutDelay);
}
+ .c-frame__move-bar {
@include transition($prop: height, $delay: $moveBarOutDelay);
@include userSelectNone();
background: $editFrameMovebarColorBg;
box-shadow: rgba(black, 0.3) 0 2px;
bottom: auto;
display: block;
height: 0; // Height is set on hover below
opacity: 0.9;
max-height: 100%;
overflow: hidden;
text-align: center;
z-index: 10;
&:before {
// Grippy
$h: 4px;
$tbOffset: math.div($editFrameMovebarH - $h, 2);
$lrOffset: 25%;
@include grippy($editFrameMovebarColorFg);
content: '';
display: none;
position: absolute;
top: $tbOffset;
right: $lrOffset;
bottom: $tbOffset;
left: $lrOffset;
}
}
}
&:hover {
> .c-so-view.has-complex-content {
transition: $transInTransform;
transition-delay: 0s;
> .c-so-view__local-controls {
transform: translateY($editFrameMovebarH);
@include transition(height, $transOutTime);
transition-delay: 0s;
}
+ .c-frame__move-bar {
@include transition(height);
height: $editFrameMovebarH;
}
}
}
}
> .l-layout__frame[s-selected] {
> .c-so-view.has-complex-content {
+ .c-frame__move-bar:before {
display: block;
}
}
}
}
/******************* > 1 ITEMS SELECTED */
&.is-multi-selected {
.l-layout__frame[s-selected] {
> .c-so-view.has-complex-content + .c-frame__move-bar {
display: block;
}
}
/******************* > 1 ITEMS SELECTED */
&.is-multi-selected {
.l-layout__frame[s-selected] {
> .c-so-view.has-complex-content + .c-frame__move-bar {
display: block;
}
}
}
}
}

View File

@ -1,48 +1,48 @@
.c-telemetry-view {
display: flex;
align-items: stretch;
> * {
// Label and value holders
flex: 1 1 50%;
display: flex;
align-items: stretch;
flex-direction: row;
align-items: center;
overflow: hidden;
padding: $interiorMargin;
> * {
// Label and value holders
flex: 1 1 50%;
display: flex;
flex-direction: row;
align-items: center;
overflow: hidden;
padding: $interiorMargin;
> * {
// Text elements
@include ellipsize();
}
// Text elements
@include ellipsize();
}
}
&__value {
@include isLimit();
}
&__value {
@include isLimit();
}
&__label {
margin-right: $interiorMargin;
}
&__label {
margin-right: $interiorMargin;
}
&.is-stale {
.c-telemetry-view__value {
@include isStaleElement();
}
&.is-stale {
.c-telemetry-view__value {
@include isStaleElement();
}
}
.c-frame & {
@include abs();
border: 1px solid transparent;
}
.c-frame & {
@include abs();
border: 1px solid transparent;
}
.is-status__indicator {
position: absolute;
top: 0;
left: 0;
}
.is-status__indicator {
position: absolute;
top: 0;
left: 0;
}
&[class*='is-status'] {
border: $borderMissing;
}
&[class*='is-status'] {
border: $borderMissing;
}
}

View File

@ -1,11 +1,11 @@
.c-text-view {
display: flex;
align-items: center; // Vertically center text
overflow: hidden;
padding: $interiorMargin;
display: flex;
align-items: center; // Vertically center text
overflow: hidden;
padding: $interiorMargin;
.c-frame & {
@include abs();
border: 1px solid transparent;
}
.c-frame & {
@include abs();
border: 1px solid transparent;
}
}

View File

@ -20,64 +20,75 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
import {getStylesWithoutNoneValue} from "@/plugins/condition/utils/styleUtils";
import StyleRuleManager from '@/plugins/condition/StyleRuleManager';
import { getStylesWithoutNoneValue } from '@/plugins/condition/utils/styleUtils';
export default {
inject: ['openmct'],
data() {
return {
objectStyle: undefined,
itemStyle: undefined,
styleClass: ''
};
},
mounted() {
this.parentDomainObject = this.$parent.domainObject;
this.itemId = this.item.id;
this.objectStyle = this.getObjectStyleForItem(this.parentDomainObject.configuration.objectStyles);
this.initObjectStyles();
},
beforeDestroy() {
if (this.stopListeningObjectStyles) {
this.stopListeningObjectStyles();
}
if (this.styleRuleManager) {
this.styleRuleManager.destroy();
}
},
methods: {
getObjectStyleForItem(objectStyle) {
if (objectStyle) {
return objectStyle[this.itemId] ? Object.assign({}, objectStyle[this.itemId]) : undefined;
} else {
return undefined;
}
},
initObjectStyles() {
if (!this.styleRuleManager) {
this.styleRuleManager = new StyleRuleManager(this.objectStyle, this.openmct, this.updateStyle.bind(this), true);
} else {
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
}
if (this.stopListeningObjectStyles) {
this.stopListeningObjectStyles();
}
this.stopListeningObjectStyles = this.openmct.objects.observe(this.parentDomainObject, 'configuration.objectStyles', (newObjectStyle) => {
//Updating object styles in the inspector view will trigger this so that the changes are reflected immediately
let newItemObjectStyle = this.getObjectStyleForItem(newObjectStyle);
if (this.objectStyle !== newItemObjectStyle) {
this.objectStyle = newItemObjectStyle;
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
}
});
},
updateStyle(style) {
this.itemStyle = getStylesWithoutNoneValue(style);
this.styleClass = this.itemStyle && this.itemStyle.isStyleInvisible;
}
inject: ['openmct'],
data() {
return {
objectStyle: undefined,
itemStyle: undefined,
styleClass: ''
};
},
mounted() {
this.parentDomainObject = this.$parent.domainObject;
this.itemId = this.item.id;
this.objectStyle = this.getObjectStyleForItem(
this.parentDomainObject.configuration.objectStyles
);
this.initObjectStyles();
},
beforeDestroy() {
if (this.stopListeningObjectStyles) {
this.stopListeningObjectStyles();
}
if (this.styleRuleManager) {
this.styleRuleManager.destroy();
}
},
methods: {
getObjectStyleForItem(objectStyle) {
if (objectStyle) {
return objectStyle[this.itemId] ? Object.assign({}, objectStyle[this.itemId]) : undefined;
} else {
return undefined;
}
},
initObjectStyles() {
if (!this.styleRuleManager) {
this.styleRuleManager = new StyleRuleManager(
this.objectStyle,
this.openmct,
this.updateStyle.bind(this),
true
);
} else {
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
}
if (this.stopListeningObjectStyles) {
this.stopListeningObjectStyles();
}
this.stopListeningObjectStyles = this.openmct.objects.observe(
this.parentDomainObject,
'configuration.objectStyles',
(newObjectStyle) => {
//Updating object styles in the inspector view will trigger this so that the changes are reflected immediately
let newItemObjectStyle = this.getObjectStyleForItem(newObjectStyle);
if (this.objectStyle !== newItemObjectStyle) {
this.objectStyle = newItemObjectStyle;
this.styleRuleManager.updateObjectStyleConfig(this.objectStyle);
}
}
);
},
updateStyle(style) {
this.itemStyle = getStylesWithoutNoneValue(style);
this.styleClass = this.itemStyle && this.itemStyle.isStyleInvisible;
}
}
};

View File

@ -32,105 +32,108 @@ import objectUtils from 'objectUtils';
import Vue from 'vue';
class DisplayLayoutView {
constructor(openmct, domainObject, objectPath, options) {
this.openmct = openmct;
this.domainObject = domainObject;
this.objectPath = objectPath;
this.options = options;
constructor(openmct, domainObject, objectPath, options) {
this.openmct = openmct;
this.domainObject = domainObject;
this.objectPath = objectPath;
this.options = options;
this.component = undefined;
}
this.component = undefined;
}
show(container, isEditing) {
this.component = new Vue({
el: container,
components: {
DisplayLayout
},
provide: {
openmct: this.openmct,
objectPath: this.objectPath,
options: this.options,
objectUtils,
currentView: this
},
data: () => {
return {
domainObject: this.domainObject,
isEditing
};
},
template: '<display-layout ref="displayLayout" :domain-object="domainObject" :is-editing="isEditing"></display-layout>'
});
}
getViewContext() {
if (!this.component) {
return {};
}
return this.component.$refs.displayLayout.getViewContext();
}
getSelectionContext() {
show(container, isEditing) {
this.component = new Vue({
el: container,
components: {
DisplayLayout
},
provide: {
openmct: this.openmct,
objectPath: this.objectPath,
options: this.options,
objectUtils,
currentView: this
},
data: () => {
return {
item: this.domainObject,
supportsMultiSelect: true,
addElement: this.component && this.component.$refs.displayLayout.addElement,
removeItem: this.component && this.component.$refs.displayLayout.removeItem,
orderItem: this.component && this.component.$refs.displayLayout.orderItem,
duplicateItem: this.component && this.component.$refs.displayLayout.duplicateItem,
switchViewType: this.component && this.component.$refs.displayLayout.switchViewType,
mergeMultipleTelemetryViews: this.component && this.component.$refs.displayLayout.mergeMultipleTelemetryViews,
mergeMultipleOverlayPlots: this.component && this.component.$refs.displayLayout.mergeMultipleOverlayPlots,
toggleGrid: this.component && this.component.$refs.displayLayout.toggleGrid
domainObject: this.domainObject,
isEditing
};
},
template:
'<display-layout ref="displayLayout" :domain-object="domainObject" :is-editing="isEditing"></display-layout>'
});
}
getViewContext() {
if (!this.component) {
return {};
}
onEditModeChange(isEditing) {
this.component.isEditing = isEditing;
}
return this.component.$refs.displayLayout.getViewContext();
}
destroy() {
this.component.$destroy();
this.component = undefined;
}
getSelectionContext() {
return {
item: this.domainObject,
supportsMultiSelect: true,
addElement: this.component && this.component.$refs.displayLayout.addElement,
removeItem: this.component && this.component.$refs.displayLayout.removeItem,
orderItem: this.component && this.component.$refs.displayLayout.orderItem,
duplicateItem: this.component && this.component.$refs.displayLayout.duplicateItem,
switchViewType: this.component && this.component.$refs.displayLayout.switchViewType,
mergeMultipleTelemetryViews:
this.component && this.component.$refs.displayLayout.mergeMultipleTelemetryViews,
mergeMultipleOverlayPlots:
this.component && this.component.$refs.displayLayout.mergeMultipleOverlayPlots,
toggleGrid: this.component && this.component.$refs.displayLayout.toggleGrid
};
}
onEditModeChange(isEditing) {
this.component.isEditing = isEditing;
}
destroy() {
this.component.$destroy();
this.component = undefined;
}
}
export default function DisplayLayoutPlugin(options) {
return function (openmct) {
openmct.actions.register(new CopyToClipboardAction(openmct));
return function (openmct) {
openmct.actions.register(new CopyToClipboardAction(openmct));
openmct.objectViews.addProvider({
key: 'layout.view',
canView: function (domainObject) {
return domainObject.type === 'layout';
},
canEdit: function (domainObject) {
return domainObject.type === 'layout';
},
view: function (domainObject, objectPath) {
return new DisplayLayoutView(openmct, domainObject, objectPath, options);
},
priority() {
return 100;
}
});
openmct.types.addType('layout', DisplayLayoutType());
openmct.toolbars.addProvider(new DisplayLayoutToolbar(openmct));
openmct.inspectorViews.addProvider(new AlphaNumericFormatViewProvider(openmct, options));
openmct.composition.addPolicy((parent, child) => {
if (parent.type === 'layout' && child.type === 'folder') {
return false;
} else {
return true;
}
});
openmct.objectViews.addProvider({
key: 'layout.view',
canView: function (domainObject) {
return domainObject.type === 'layout';
},
canEdit: function (domainObject) {
return domainObject.type === 'layout';
},
view: function (domainObject, objectPath) {
return new DisplayLayoutView(openmct, domainObject, objectPath, options);
},
priority() {
return 100;
}
});
openmct.types.addType('layout', DisplayLayoutType());
openmct.toolbars.addProvider(new DisplayLayoutToolbar(openmct));
openmct.inspectorViews.addProvider(new AlphaNumericFormatViewProvider(openmct, options));
openmct.composition.addPolicy((parent, child) => {
if (parent.type === 'layout' && child.type === 'folder') {
return false;
} else {
return true;
}
});
for (const [type, definition] of Object.entries(DisplayLayoutDrawingObjectTypes)) {
openmct.types.addType(type, definition);
}
for (const [type, definition] of Object.entries(DisplayLayoutDrawingObjectTypes)) {
openmct.types.addType(type, definition);
}
DisplayLayoutPlugin._installed = true;
};
DisplayLayoutPlugin._installed = true;
};
}

View File

@ -25,416 +25,407 @@ import Vue from 'vue';
import DisplayLayoutPlugin from './plugin';
describe('the plugin', function () {
let element;
let child;
let openmct;
let displayLayoutDefinition;
let element;
let child;
let openmct;
let displayLayoutDefinition;
beforeEach((done) => {
openmct = createOpenMct();
openmct.install(
new DisplayLayoutPlugin({
showAsView: []
})
);
displayLayoutDefinition = openmct.types.get('layout');
element = document.createElement('div');
child = document.createElement('div');
element.appendChild(child);
openmct.on('start', done);
openmct.start(child);
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('defines a display layout object type with the correct key', () => {
expect(displayLayoutDefinition.definition.name).toEqual('Display Layout');
});
it('provides a view', () => {
const testViewObject = {
id: 'test-object',
type: 'layout',
configuration: {
items: [
{
identifier: {
namespace: '',
key: '55122607-e65e-44d5-9c9d-9c31a914ca89'
},
x: 8,
y: 3,
width: 10,
height: 5,
displayMode: 'all',
value: 'sin',
stroke: '',
fill: '',
color: '',
size: '13px',
type: 'telemetry-view',
id: 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
}
],
layoutGrid: [10, 10]
}
};
const applicableViews = openmct.objectViews.get(testViewObject, []);
let displayLayoutViewProvider = applicableViews.find(
(viewProvider) => viewProvider.key === 'layout.view'
);
expect(displayLayoutViewProvider).toBeDefined();
});
it('renders a display layout view without errors', () => {
const testViewObject = {
identifier: {
namespace: 'test-namespace',
key: 'test-key'
},
type: 'layout',
configuration: {
items: [],
layoutGrid: [10, 10]
},
composition: []
};
const applicableViews = openmct.objectViews.get(testViewObject, []);
let displayLayoutViewProvider = applicableViews.find(
(viewProvider) => viewProvider.key === 'layout.view'
);
let view = displayLayoutViewProvider.view(testViewObject);
let error;
try {
view.show(child, false);
} catch (e) {
error = e;
}
expect(error).toBeUndefined();
});
describe('on load', () => {
let displayLayoutItem;
let item;
beforeEach((done) => {
openmct = createOpenMct();
openmct.install(new DisplayLayoutPlugin({
showAsView: []
}));
displayLayoutDefinition = openmct.types.get('layout');
element = document.createElement('div');
child = document.createElement('div');
element.appendChild(child);
openmct.on('start', done);
openmct.start(child);
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('defines a display layout object type with the correct key', () => {
expect(displayLayoutDefinition.definition.name).toEqual('Display Layout');
});
it('provides a view', () => {
const testViewObject = {
id: 'test-object',
type: 'layout',
configuration: {
items: [
{
'identifier': {
'namespace': '',
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
},
'x': 8,
'y': 3,
'width': 10,
'height': 5,
'displayMode': 'all',
'value': 'sin',
'stroke': '',
'fill': '',
'color': '',
'size': '13px',
'type': 'telemetry-view',
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
}
],
layoutGrid: [10, 10]
}
};
const applicableViews = openmct.objectViews.get(testViewObject, []);
let displayLayoutViewProvider = applicableViews.find((viewProvider) => viewProvider.key === 'layout.view');
expect(displayLayoutViewProvider).toBeDefined();
});
it('renders a display layout view without errors', () => {
const testViewObject = {
identifier: {
namespace: 'test-namespace',
key: 'test-key'
},
type: 'layout',
configuration: {
items: [],
layoutGrid: [10, 10]
},
composition: []
};
const applicableViews = openmct.objectViews.get(testViewObject, []);
let displayLayoutViewProvider = applicableViews.find((viewProvider) => viewProvider.key === 'layout.view');
let view = displayLayoutViewProvider.view(testViewObject);
let error;
try {
view.show(child, false);
} catch (e) {
error = e;
item = {
width: 32,
height: 18,
x: 78,
y: 8,
identifier: {
namespace: '',
key: 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
},
hasFrame: true,
type: 'line-view', // so no telemetry functionality is triggered, just want to test the sync
id: 'c0ff485a-344c-4e70-8d83-a9d9998a69fc'
};
displayLayoutItem = {
composition: [
// no item in compostion, but item in configuration items
],
configuration: {
items: [item],
layoutGrid: [10, 10]
},
name: 'Display Layout',
type: 'layout',
identifier: {
namespace: '',
key: 'c5e636c1-6771-4c9c-b933-8665cab189b3'
}
};
expect(error).toBeUndefined();
const applicableViews = openmct.objectViews.get(displayLayoutItem, []);
const displayLayoutViewProvider = applicableViews.find(
(viewProvider) => viewProvider.key === 'layout.view'
);
const view = displayLayoutViewProvider.view(displayLayoutItem);
view.show(child, false);
Vue.nextTick(done);
});
describe('on load', () => {
let displayLayoutItem;
let item;
it('will sync compostion and layout items', () => {
expect(displayLayoutItem.configuration.items.length).toBe(0);
});
});
beforeEach((done) => {
item = {
'width': 32,
'height': 18,
'x': 78,
'y': 8,
'identifier': {
'namespace': '',
'key': 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
},
'hasFrame': true,
'type': 'line-view', // so no telemetry functionality is triggered, just want to test the sync
'id': 'c0ff485a-344c-4e70-8d83-a9d9998a69fc'
describe('the alpha numeric format view', () => {
let displayLayoutItem;
let telemetryItem;
let selection;
};
displayLayoutItem = {
'composition': [
// no item in compostion, but item in configuration items
beforeEach(() => {
displayLayoutItem = {
composition: [],
configuration: {
items: [
{
identifier: {
namespace: '',
key: '55122607-e65e-44d5-9c9d-9c31a914ca89'
},
x: 8,
y: 3,
width: 10,
height: 5,
displayMode: 'all',
value: 'sin',
stroke: '',
fill: '',
color: '',
size: '13px',
type: 'telemetry-view',
id: 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
}
],
layoutGrid: [10, 10]
},
name: 'Display Layout',
type: 'layout',
identifier: {
namespace: '',
key: 'c5e636c1-6771-4c9c-b933-8665cab189b3'
}
};
telemetryItem = {
telemetry: {
period: 5,
amplitude: 5,
offset: 5,
dataRateInHz: 5,
phase: 5,
randomness: 0
},
name: 'Sine Wave Generator',
type: 'generator',
modified: 1592851063871,
location: 'mine',
persisted: 1592851063871,
id: '55122607-e65e-44d5-9c9d-9c31a914ca89',
identifier: {
namespace: '',
key: '55122607-e65e-44d5-9c9d-9c31a914ca89'
}
};
selection = [
[
{
context: {
layoutItem: displayLayoutItem.configuration.items[0],
item: telemetryItem,
index: 1
}
},
{
context: {
item: displayLayoutItem,
supportsMultiSelect: true
}
}
]
];
});
it('provides an alphanumeric format view', () => {
const displayLayoutAlphaNumFormatView = openmct.inspectorViews.get(selection);
expect(displayLayoutAlphaNumFormatView.length).toBeDefined();
});
});
describe('the toolbar', () => {
let displayLayoutItem;
let selection;
beforeEach(() => {
displayLayoutItem = {
composition: [],
configuration: {
items: [
{
fill: '#666666',
stroke: '',
x: 1,
y: 1,
width: 10,
height: 5,
type: 'box-view',
id: '89b88746-d325-487b-aec4-11b79afff9e8'
},
{
fill: '#666666',
stroke: '',
x: 1,
y: 1,
width: 10,
height: 10,
type: 'ellipse-view',
id: '19b88746-d325-487b-aec4-11b79afff9z8'
},
{
x: 18,
y: 9,
x2: 23,
y2: 4,
stroke: '#666666',
type: 'line-view',
id: '57d49a28-7863-43bd-9593-6570758916f0'
},
{
identifier: {
namespace: '',
key: '55122607-e65e-44d5-9c9d-9c31a914ca89'
},
x: 8,
y: 3,
width: 10,
height: 5,
displayMode: 'all',
value: 'sin',
stroke: '',
fill: '',
color: '',
size: '13px',
type: 'telemetry-view',
id: 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
},
{
width: 32,
height: 18,
x: 78,
y: 8,
identifier: {
namespace: '',
key: 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
},
hasFrame: true,
type: 'subobject-view',
id: 'c0ff485a-344c-4e70-8d83-a9d9998a69fc'
}
],
layoutGrid: [10, 10]
},
name: 'Display Layout',
type: 'layout',
identifier: {
namespace: '',
key: 'c5e636c1-6771-4c9c-b933-8665cab189b3'
}
};
selection = [
[
{
context: {
layoutItem: displayLayoutItem.configuration.items[1],
index: 1
}
},
{
context: {
item: displayLayoutItem,
supportsMultiSelect: true
}
}
],
[
{
context: {
layoutItem: displayLayoutItem.configuration.items[0],
index: 0
}
},
{
context: {
item: displayLayoutItem,
supportsMultiSelect: true
}
}
],
[
{
context: {
layoutItem: displayLayoutItem.configuration.items[2],
item: displayLayoutItem.configuration.items[2],
index: 2
}
},
{
context: {
item: displayLayoutItem,
supportsMultiSelect: true
}
}
],
[
{
context: {
item: {
composition: [
{
namespace: '',
key: '55122607-e65e-44d5-9c9d-9c31a914ca89'
}
],
'configuration': {
'items': [
item
],
'layoutGrid': [
10,
10
]
configuration: {
series: [
{
identifier: {
namespace: '',
key: '55122607-e65e-44d5-9c9d-9c31a914ca89'
}
}
],
yAxis: {},
xAxis: {}
},
'name': 'Display Layout',
'type': 'layout',
'identifier': {
'namespace': '',
'key': 'c5e636c1-6771-4c9c-b933-8665cab189b3'
}
};
const applicableViews = openmct.objectViews.get(displayLayoutItem, []);
const displayLayoutViewProvider = applicableViews.find((viewProvider) => viewProvider.key === 'layout.view');
const view = displayLayoutViewProvider.view(displayLayoutItem);
view.show(child, false);
Vue.nextTick(done);
});
it('will sync compostion and layout items', () => {
expect(displayLayoutItem.configuration.items.length).toBe(0);
});
name: 'Unnamed Overlay Plot',
type: 'telemetry.plot.overlay',
modified: 1594142141929,
location: 'mine',
identifier: {
namespace: '',
key: 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
},
persisted: 1594142141929
},
layoutItem: displayLayoutItem.configuration.items[3],
index: 3
}
},
{
context: {
item: displayLayoutItem,
supportsMultiSelect: true
}
}
]
];
});
describe('the alpha numeric format view', () => {
let displayLayoutItem;
let telemetryItem;
let selection;
it('provides controls including separators', () => {
const displayLayoutToolbar = openmct.toolbars.get(selection);
beforeEach(() => {
displayLayoutItem = {
'composition': [
],
'configuration': {
'items': [
{
'identifier': {
'namespace': '',
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
},
'x': 8,
'y': 3,
'width': 10,
'height': 5,
'displayMode': 'all',
'value': 'sin',
'stroke': '',
'fill': '',
'color': '',
'size': '13px',
'type': 'telemetry-view',
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
}
],
'layoutGrid': [
10,
10
]
},
'name': 'Display Layout',
'type': 'layout',
'identifier': {
'namespace': '',
'key': 'c5e636c1-6771-4c9c-b933-8665cab189b3'
}
};
telemetryItem = {
'telemetry': {
'period': 5,
'amplitude': 5,
'offset': 5,
'dataRateInHz': 5,
'phase': 5,
'randomness': 0
},
'name': 'Sine Wave Generator',
'type': 'generator',
'modified': 1592851063871,
'location': 'mine',
'persisted': 1592851063871,
'id': '55122607-e65e-44d5-9c9d-9c31a914ca89',
'identifier': {
'namespace': '',
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
}
};
selection = [
[{
context: {
'layoutItem': displayLayoutItem.configuration.items[0],
'item': telemetryItem,
'index': 1
}
},
{
context: {
'item': displayLayoutItem,
'supportsMultiSelect': true
}
}]
];
});
it('provides an alphanumeric format view', () => {
const displayLayoutAlphaNumFormatView = openmct.inspectorViews.get(selection);
expect(displayLayoutAlphaNumFormatView.length).toBeDefined();
});
});
describe('the toolbar', () => {
let displayLayoutItem;
let selection;
beforeEach(() => {
displayLayoutItem = {
'composition': [
],
'configuration': {
'items': [
{
'fill': '#666666',
'stroke': '',
'x': 1,
'y': 1,
'width': 10,
'height': 5,
'type': 'box-view',
'id': '89b88746-d325-487b-aec4-11b79afff9e8'
},
{
'fill': '#666666',
'stroke': '',
'x': 1,
'y': 1,
'width': 10,
'height': 10,
'type': 'ellipse-view',
'id': '19b88746-d325-487b-aec4-11b79afff9z8'
},
{
'x': 18,
'y': 9,
'x2': 23,
'y2': 4,
'stroke': '#666666',
'type': 'line-view',
'id': '57d49a28-7863-43bd-9593-6570758916f0'
},
{
'identifier': {
'namespace': '',
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
},
'x': 8,
'y': 3,
'width': 10,
'height': 5,
'displayMode': 'all',
'value': 'sin',
'stroke': '',
'fill': '',
'color': '',
'size': '13px',
'type': 'telemetry-view',
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
},
{
'width': 32,
'height': 18,
'x': 78,
'y': 8,
'identifier': {
'namespace': '',
'key': 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
},
'hasFrame': true,
'type': 'subobject-view',
'id': 'c0ff485a-344c-4e70-8d83-a9d9998a69fc'
}
],
'layoutGrid': [
10,
10
]
},
'name': 'Display Layout',
'type': 'layout',
'identifier': {
'namespace': '',
'key': 'c5e636c1-6771-4c9c-b933-8665cab189b3'
}
};
selection = [
[{
context: {
'layoutItem': displayLayoutItem.configuration.items[1],
'index': 1
}
},
{
context: {
'item': displayLayoutItem,
'supportsMultiSelect': true
}
}],
[{
context: {
'layoutItem': displayLayoutItem.configuration.items[0],
'index': 0
}
},
{
context: {
item: displayLayoutItem,
'supportsMultiSelect': true
}
}],
[{
context: {
'layoutItem': displayLayoutItem.configuration.items[2],
'item': displayLayoutItem.configuration.items[2],
'index': 2
}
},
{
context: {
item: displayLayoutItem,
'supportsMultiSelect': true
}
}],
[{
context: {
'item': {
'composition': [
{
'namespace': '',
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
}
],
'configuration': {
'series': [
{
'identifier': {
'namespace': '',
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
}
}
],
'yAxis': {
},
'xAxis': {
}
},
'name': 'Unnamed Overlay Plot',
'type': 'telemetry.plot.overlay',
'modified': 1594142141929,
'location': 'mine',
'identifier': {
'namespace': '',
'key': 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
},
'persisted': 1594142141929
},
'layoutItem': displayLayoutItem.configuration.items[3],
'index': 3
}
},
{
context: {
item: displayLayoutItem,
'supportsMultiSelect': true
}
}]
];
});
it('provides controls including separators', () => {
const displayLayoutToolbar = openmct.toolbars.get(selection);
expect(displayLayoutToolbar.length).toBe(8);
});
expect(displayLayoutToolbar.length).toBe(8);
});
});
});