mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 18:50:11 +00:00
Compare commits
49 Commits
tables-rem
...
edit-param
Author | SHA1 | Date | |
---|---|---|---|
79d1dff02e | |||
bf3293356e | |||
7cf53c8b9f | |||
5ecd742131 | |||
feee96b899 | |||
a04bd810bd | |||
4bf573bc4c | |||
fc70bed810 | |||
23b1ca2073 | |||
0e30fba72d | |||
a0d2cd5711 | |||
1c77ef142c | |||
e4e7ecd74e | |||
853764d863 | |||
d0ab59f9da | |||
21e08709cb | |||
514896884f | |||
fc024e583e | |||
a1aa99837b | |||
037264b0bf | |||
7f2f060417 | |||
6eda100af8 | |||
782ee9aa37 | |||
29e94befe8 | |||
24a1e9ba75 | |||
edeefe8f2f | |||
1a06702dbe | |||
d263723a0c | |||
666bb41697 | |||
e254fafb5c | |||
1dc1cc6c24 | |||
baa5d10009 | |||
58048d44b2 | |||
775e93484e | |||
0e27234389 | |||
ac2b9acccb | |||
075d4deecb | |||
ac11f898d4 | |||
dd31de6935 | |||
15d4b1a8e5 | |||
9e811e722f | |||
8ef53d85c4 | |||
abcc5cb023 | |||
931871ff95 | |||
6b1e8862ef | |||
00ce246fc5 | |||
c0c7d96429 | |||
92b2582d0d | |||
4084a1ac86 |
@ -43,15 +43,14 @@ define([
|
||||
form: [
|
||||
{
|
||||
name: "State Duration (seconds)",
|
||||
control: "textfield",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "duration",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"duration"
|
||||
],
|
||||
pattern: "^\\d*(\\.\\d*)?$"
|
||||
]
|
||||
}
|
||||
],
|
||||
initialize: function (object) {
|
||||
|
209
index.html
209
index.html
@ -36,7 +36,9 @@
|
||||
<body>
|
||||
</body>
|
||||
<script>
|
||||
var THIRTY_MINUTES = 30 * 60 * 1000;
|
||||
const FIVE_MINUTES = 5 * 60 * 1000;
|
||||
const THIRTY_MINUTES = 30 * 60 * 1000;
|
||||
|
||||
[
|
||||
'example/eventGenerator',
|
||||
'example/styleguide'
|
||||
@ -49,7 +51,6 @@
|
||||
openmct.install(openmct.plugins.ExampleImagery());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
openmct.install(openmct.plugins.ImportExport());
|
||||
openmct.install(openmct.plugins.FixedView());
|
||||
openmct.install(openmct.plugins.AutoflowView({
|
||||
type: "telemetry.panel"
|
||||
}));
|
||||
@ -68,8 +69,8 @@
|
||||
timeSystem: 'utc',
|
||||
clock: 'local',
|
||||
clockOffsets: {
|
||||
start: -25 * 60 * 1000,
|
||||
end: 5 * 60 * 1000
|
||||
start: - THIRTY_MINUTES,
|
||||
end: FIVE_MINUTES
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -80,206 +81,6 @@
|
||||
openmct.install(openmct.plugins.Tabs());
|
||||
openmct.install(openmct.plugins.FlexibleLayout());
|
||||
openmct.install(openmct.plugins.LADTable());
|
||||
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
|
||||
openmct.time.timeSystem('utc');
|
||||
openmct.start();
|
||||
|
||||
// openmct.toolbars.addProvider({
|
||||
// name: "Testing Toolbar",
|
||||
// key: "testing",
|
||||
// description: "a mock toolbar that exercises all controls",
|
||||
// forSelection: function (selection) {
|
||||
// return true; // always applies.
|
||||
// },
|
||||
// toolbar: function (selection) {
|
||||
// return [
|
||||
// {
|
||||
// control: 'menu',
|
||||
// icon: 'icon-plus',
|
||||
// label: 'Add',
|
||||
// options: [
|
||||
// { name: 'Box', class: 'icon-box', title: 'Add Box' },
|
||||
// { name: 'Line', class: 'icon-line-horz', title: 'Add Line' },
|
||||
// { name: 'Text', class: 'icon-font', title: 'Add Text' },
|
||||
// { name: 'Image', class: 'icon-image', title: 'Add Image' }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'color-picker',
|
||||
// icon: 'icon-paint-bucket',
|
||||
// value: '#33ff00',
|
||||
// },
|
||||
// {
|
||||
// control: 'color-picker',
|
||||
// icon: 'icon-pencil',
|
||||
// value: '#ffffff',
|
||||
// },
|
||||
// {
|
||||
// control: 'color-picker',
|
||||
// icon: 'icon-font',
|
||||
// value: '#333333',
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'select-menu',
|
||||
// value: 11,
|
||||
// options: [
|
||||
// { value: 9, name: '9 px' },
|
||||
// { value: 10, name: '10 px' },
|
||||
// { value: 11, name: '11 px' },
|
||||
// { value: 12, name: '12 px' },
|
||||
// { value: 13, name: '13 px' },
|
||||
// { value: 14, name: '14 px' },
|
||||
// { value: 16, name: '16 px' },
|
||||
// { value: 18, name: '18 px' },
|
||||
// { value: 20, name: '20 px' },
|
||||
// { value: 24, name: '24 px' },
|
||||
// { value: 28, name: '28 px' },
|
||||
// { value: 32, name: '32 px' },
|
||||
// { value: 40, name: '40 px' },
|
||||
// { value: 48, name: '48 px' },
|
||||
// { value: 56, name: '56 px' },
|
||||
// { value: 64, name: '64 px' },
|
||||
// { value: 72, name: '72 px' },
|
||||
// { value: 80, name: '80 px' },
|
||||
// { value: 88, name: '88 px' },
|
||||
// { value: 96, name: '96 px' },
|
||||
// { value: 128, name: '128 px' },
|
||||
// { value: 160, name: '160 px' }
|
||||
// ]
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'menu',
|
||||
// icon: 'icon-layers',
|
||||
// options: [
|
||||
// { name: 'Move to top', class: 'icon-arrow-double-up', title: 'Move to top' },
|
||||
// { name: 'Move up', class: 'icon-arrow-up', title: 'Move up' },
|
||||
// { name: 'Move down', class: 'icon-arrow-down', title: 'Move down' },
|
||||
// { name: 'Move to bottom', class: 'icon-arrow-double-down', title: 'Move to bottom' }
|
||||
// ]
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'button',
|
||||
// icon: 'icon-gear'
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'X',
|
||||
// value: 1,
|
||||
// title: 'X position'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'Y',
|
||||
// value: 2,
|
||||
// title: 'Y position'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'W',
|
||||
// value: 3,
|
||||
// title: 'Width'
|
||||
// },
|
||||
// {
|
||||
// control: 'input',
|
||||
// type: 'number',
|
||||
// label: 'H',
|
||||
// value: 4,
|
||||
// title: 'Height'
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'button',
|
||||
// icon: 'icon-trash',
|
||||
// label: 'delete',
|
||||
// modifier: 'caution'
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'checkbox',
|
||||
// name: 'this is a checkbox',
|
||||
// },
|
||||
// {
|
||||
// control: 'separator'
|
||||
// },
|
||||
// {
|
||||
// control: 'toggle-button',
|
||||
// title: 'Toggle Frame',
|
||||
// property: 'hideFrame',
|
||||
// value: false,
|
||||
// options: [
|
||||
// {
|
||||
// value: true,
|
||||
// icon: 'icon-frame-hide'
|
||||
// },
|
||||
// {
|
||||
// value: false,
|
||||
// icon: 'icon-frame-show'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// control: 'toggle-button',
|
||||
// title: 'Snap to grid',
|
||||
// property: 'snapToGrid',
|
||||
// value: true,
|
||||
// options: [
|
||||
// {
|
||||
// value: true,
|
||||
// icon: 'icon-grid-snap-to'
|
||||
// },
|
||||
// {
|
||||
// value: false,
|
||||
// icon: 'icon-grid-snap-no'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// control: 'toggle-button',
|
||||
// title: 'Toggle label',
|
||||
// property: 'showLabel',
|
||||
// value: true,
|
||||
// options: [
|
||||
// {
|
||||
// value: true,
|
||||
// icon: 'icon-two-parts-both'
|
||||
// },
|
||||
// {
|
||||
// value: false,
|
||||
// icon: 'icon-two-parts-one-only'
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ];
|
||||
// }
|
||||
// });
|
||||
|
||||
</script>
|
||||
</html>
|
||||
|
@ -25,7 +25,7 @@
|
||||
"eventemitter3": "^1.2.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"express": "^4.13.1",
|
||||
"fast-sass-loader": "^1.4.5",
|
||||
"fast-sass-loader": "1.4.6",
|
||||
"file-loader": "^1.1.11",
|
||||
"file-saver": "^1.3.8",
|
||||
"git-rev-sync": "^1.4.0",
|
||||
|
@ -10,6 +10,16 @@
|
||||
ng-show="ngModel.progressPerc !== undefined"></mct-include>
|
||||
</div>
|
||||
<div class="bottom-bar">
|
||||
<a ng-repeat="dialogOption in ngModel.options"
|
||||
class="s-button"
|
||||
ng-click="dialogOption.callback()">
|
||||
{{dialogOption.label}}
|
||||
</a>
|
||||
<a class="s-button major"
|
||||
ng-if="ngModel.primaryOption"
|
||||
ng-click="ngModel.primaryOption.callback()">
|
||||
{{ngModel.primaryOption.label}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -92,16 +92,7 @@ function (
|
||||
* @memberof platform/commonUI/edit.SaveAction#
|
||||
*/
|
||||
SaveAsAction.prototype.perform = function () {
|
||||
// Discard the current root view (which will be the editing
|
||||
// UI, which will have been pushed atop the Browse UI.)
|
||||
function returnToBrowse(object) {
|
||||
if (object) {
|
||||
object.getCapability("action").perform("navigate");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
return this.save().then(returnToBrowse);
|
||||
return this.save();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -169,15 +160,17 @@ function (
|
||||
}
|
||||
|
||||
function saveAfterClone(clonedObject) {
|
||||
return domainObject.getCapability("editor").save()
|
||||
.then(resolveWith(clonedObject));
|
||||
return this.openmct.editor.save().then(() => {
|
||||
// Force mutation for search indexing
|
||||
clonedObject.useCapability('mutation', (model) => {
|
||||
return model;
|
||||
});
|
||||
return clonedObject;
|
||||
})
|
||||
}
|
||||
|
||||
function finishEditing(clonedObject) {
|
||||
return domainObject.getCapability("editor").finish()
|
||||
.then(function () {
|
||||
return fetchObject(clonedObject.getId());
|
||||
});
|
||||
return fetchObject(clonedObject.getId())
|
||||
}
|
||||
|
||||
function onSuccess(object) {
|
||||
@ -190,7 +183,7 @@ function (
|
||||
if (reason !== "user canceled") {
|
||||
self.notificationService.error("Save Failed");
|
||||
}
|
||||
return false;
|
||||
throw reason;
|
||||
}
|
||||
|
||||
return getParent(domainObject)
|
||||
|
@ -65,24 +65,29 @@ define(
|
||||
CreateAction.prototype.perform = function () {
|
||||
var newModel = this.type.getInitialModel(),
|
||||
openmct = this.openmct,
|
||||
newObject,
|
||||
editAction;
|
||||
|
||||
function onSave() {
|
||||
openmct.editor.save();
|
||||
}
|
||||
newObject;
|
||||
|
||||
function onCancel() {
|
||||
openmct.editor.cancel();
|
||||
}
|
||||
|
||||
function navigateAndEdit(object) {
|
||||
let objectPath = object.getCapability('context').getPath(),
|
||||
url = '#/browse/' + objectPath
|
||||
.map(function (o) {
|
||||
return o && openmct.objects.makeKeyString(o.getId())
|
||||
})
|
||||
.join('/') + '?edit=true';
|
||||
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
newModel.type = this.type.getKey();
|
||||
newModel.location = this.parent.getId();
|
||||
newObject = this.parent.useCapability('instantiation', newModel);
|
||||
|
||||
openmct.editor.edit();
|
||||
editAction = newObject.getCapability("action").getActions("edit")[0];
|
||||
newObject.getCapability("action").perform("save-as").then(onSave, onCancel);
|
||||
newObject.getCapability("action").perform("save-as").then(navigateAndEdit, onCancel);
|
||||
// TODO: support editing object without saving object first.
|
||||
// Which means we have to toggle createwizard afterwards. For now,
|
||||
// We will disable this.
|
||||
|
@ -43,12 +43,25 @@ define(
|
||||
* Launch a dialog showing a list of current notifications.
|
||||
*/
|
||||
$scope.showNotificationsList = function () {
|
||||
let notificationsList = openmct.notifications.notifications.map(notification => {
|
||||
if (notification.model.severity === 'alert' || notification.model.severity === 'info') {
|
||||
notification.model.primaryOption = {
|
||||
label: 'Dismiss',
|
||||
callback: () => {
|
||||
let currentIndex = notificationsList.indexOf(notification);
|
||||
notification.dismiss();
|
||||
notificationsList.splice(currentIndex, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return notification;
|
||||
})
|
||||
dialogService.getDialogResponse('overlay-message-list', {
|
||||
dialog: {
|
||||
title: "Messages",
|
||||
//Launch the message list dialog with the models
|
||||
// from the notifications
|
||||
messages: openmct.notifications.notifications
|
||||
messages: notificationsList
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,475 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
"./src/FixedController",
|
||||
"./templates/fixed.html",
|
||||
"./templates/frame.html",
|
||||
"./templates/elements/telemetry.html",
|
||||
"./templates/elements/box.html",
|
||||
"./templates/elements/line.html",
|
||||
"./templates/elements/text.html",
|
||||
"./templates/elements/image.html",
|
||||
"legacyRegistry"
|
||||
], function (
|
||||
FixedController,
|
||||
fixedTemplate,
|
||||
frameTemplate,
|
||||
telemetryTemplate,
|
||||
boxTemplate,
|
||||
lineTemplate,
|
||||
textTemplate,
|
||||
imageTemplate,
|
||||
legacyRegistry
|
||||
) {
|
||||
return function() {
|
||||
return function (openmct) {
|
||||
openmct.legacyRegistry.register("platform/features/fixed", {
|
||||
"name": "Fixed position components.",
|
||||
"description": "Plug in adding Fixed Position object type.",
|
||||
"extensions": {
|
||||
"views": [
|
||||
{
|
||||
"key": "fixed-display",
|
||||
"name": "Fixed Position Display",
|
||||
"cssClass": "icon-box-with-dashed-lines",
|
||||
"type": "telemetry.fixed",
|
||||
"template": fixedTemplate,
|
||||
"uses": ["composition"],
|
||||
"editable": true
|
||||
}
|
||||
],
|
||||
"templates": [
|
||||
{
|
||||
"key": "fixed.telemetry",
|
||||
"template": telemetryTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.box",
|
||||
"template": boxTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.line",
|
||||
"template": lineTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.text",
|
||||
"template": textTemplate
|
||||
},
|
||||
{
|
||||
"key": "fixed.image",
|
||||
"template": imageTemplate
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "FixedController",
|
||||
"implementation": FixedController,
|
||||
"depends": [
|
||||
"$scope",
|
||||
"$q",
|
||||
"dialogService",
|
||||
"openmct",
|
||||
"$element"
|
||||
]
|
||||
}
|
||||
],
|
||||
"toolbars": [
|
||||
{
|
||||
name: "Fixed Position Toolbar",
|
||||
key: "fixed.position",
|
||||
description: "Toolbar for the selected element inside a fixed position display.",
|
||||
forSelection: function (selection) {
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (openmct.editor.isEditing() &&
|
||||
selection[0] && selection[0].context.elementProxy &&
|
||||
((selection[1] && selection[1].context.item.type === 'telemetry.fixed') ||
|
||||
(selection[0] && selection[0].context.item && selection[0].context.item.type === 'telemetry.fixed')));
|
||||
},
|
||||
toolbar: function (selection) {
|
||||
var imageProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "url"];
|
||||
var boxProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "fill"];
|
||||
var textProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "fill", "color", "size", "text"];
|
||||
var lineProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "x2", "y2"];
|
||||
var telemetryProperties = ["add", "remove", "order", "stroke", "useGrid", "x", "y", "height", "width", "fill", "color", "size", "titled"];
|
||||
var fixedPageProperties = ["add"];
|
||||
|
||||
var properties = [],
|
||||
fixedItem = selection[0] && selection[0].context.item,
|
||||
elementProxy = selection[0] && selection[0].context.elementProxy,
|
||||
domainObject = selection[1] && selection[1].context.item,
|
||||
path;
|
||||
|
||||
if (elementProxy) {
|
||||
var type = elementProxy.element.type;
|
||||
path = "configuration['fixed-display'].elements[" + elementProxy.index + "]";
|
||||
properties =
|
||||
type === 'fixed.image' ? imageProperties :
|
||||
type === 'fixed.text' ? textProperties :
|
||||
type === 'fixed.box' ? boxProperties :
|
||||
type === 'fixed.line' ? lineProperties :
|
||||
type === 'fixed.telemetry' ? telemetryProperties : [];
|
||||
} else if (fixedItem) {
|
||||
properties = domainObject && domainObject.type === 'layout' ? [] : fixedPageProperties;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
control: "menu",
|
||||
domainObject: domainObject || selection[0].context.item,
|
||||
method: function (option) {
|
||||
selection[0].context.fixedController.add(option.key);
|
||||
},
|
||||
key: "add",
|
||||
icon: "icon-plus",
|
||||
label: "Add",
|
||||
options: [
|
||||
{
|
||||
"name": "Box",
|
||||
"class": "icon-box",
|
||||
"key": "fixed.box"
|
||||
},
|
||||
{
|
||||
"name": "Line",
|
||||
"class": "icon-line-horz",
|
||||
"key": "fixed.line"
|
||||
},
|
||||
{
|
||||
"name": "Text",
|
||||
"class": "icon-T",
|
||||
"key": "fixed.text"
|
||||
},
|
||||
{
|
||||
"name": "Image",
|
||||
"class": "icon-image",
|
||||
"key": "fixed.image"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "menu",
|
||||
domainObject: domainObject,
|
||||
method: function (option) {
|
||||
console.log('option', option)
|
||||
selection[0].context.fixedController.order(
|
||||
selection[0].context.elementProxy,
|
||||
option.key
|
||||
);
|
||||
},
|
||||
key: "order",
|
||||
icon: "icon-layers",
|
||||
title: "Move the selected object above or below other objects",
|
||||
options: [
|
||||
{
|
||||
"name": "Move to Top",
|
||||
"class": "icon-arrow-double-up",
|
||||
"key": "top"
|
||||
},
|
||||
{
|
||||
"name": "Move Up",
|
||||
"class": "icon-arrow-up",
|
||||
"key": "up"
|
||||
},
|
||||
{
|
||||
"name": "Move Down",
|
||||
"class": "icon-arrow-down",
|
||||
"key": "down"
|
||||
},
|
||||
{
|
||||
"name": "Move to Bottom",
|
||||
"class": "icon-arrow-double-down",
|
||||
"key": "bottom"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "color-picker",
|
||||
domainObject: domainObject,
|
||||
property: path + ".fill",
|
||||
icon: "icon-paint-bucket",
|
||||
title: "Set fill color",
|
||||
key: 'fill'
|
||||
},
|
||||
{
|
||||
control: "color-picker",
|
||||
domainObject: domainObject,
|
||||
property: path + ".stroke",
|
||||
icon: "icon-line-horz",
|
||||
title: "Set border color",
|
||||
key: 'stroke'
|
||||
},
|
||||
{
|
||||
control: "button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".url",
|
||||
icon: "icon-image",
|
||||
title: "Edit image properties",
|
||||
key: 'url',
|
||||
dialog: {
|
||||
control: "input",
|
||||
type: "text",
|
||||
name: "Image URL",
|
||||
class: "l-input-lg",
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
control: "color-picker",
|
||||
domainObject: domainObject,
|
||||
property: path + ".color",
|
||||
icon: "icon-T",
|
||||
mandatory: true,
|
||||
title: "Set text color",
|
||||
key: 'color'
|
||||
},
|
||||
{
|
||||
control: "select-menu",
|
||||
domainObject: domainObject,
|
||||
property: path + ".size",
|
||||
title: "Set text size",
|
||||
key: 'size',
|
||||
options: [9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96].map(function (size) {
|
||||
return { "value": size + "px"};
|
||||
})
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".x",
|
||||
label: "X",
|
||||
title: "X position",
|
||||
key: "x",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".y",
|
||||
label: "Y",
|
||||
title: "Y position",
|
||||
key: "y",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".x",
|
||||
label: "X1",
|
||||
title: "X1 position",
|
||||
key: "x1",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".y",
|
||||
label: "Y1",
|
||||
title: "Y1 position",
|
||||
key: "y1",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".x2",
|
||||
label: "X2",
|
||||
title: "X2 position",
|
||||
key: "x2",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".y2",
|
||||
label: "Y2",
|
||||
title: "Y2 position",
|
||||
key: "y2",
|
||||
class: "l-input-sm",
|
||||
min: "0"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".height",
|
||||
label: "H",
|
||||
title: "Resize object height",
|
||||
key: "height",
|
||||
class: "l-input-sm",
|
||||
min: "1"
|
||||
},
|
||||
{
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: domainObject,
|
||||
property: path + ".width",
|
||||
label: "W",
|
||||
title: "Resize object width",
|
||||
key: "width",
|
||||
class: "l-input-sm",
|
||||
min: "1"
|
||||
},
|
||||
{
|
||||
control: "toggle-button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".useGrid",
|
||||
key: "useGrid",
|
||||
options: [
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-grid-snap-to',
|
||||
title: 'Snap to grid'
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-grid-snap-no',
|
||||
title: "Do not snap to grid"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".text",
|
||||
icon: "icon-gear",
|
||||
title: "Edit text properties",
|
||||
key: "text",
|
||||
dialog: {
|
||||
control: "input",
|
||||
type: "text",
|
||||
name: "Text",
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
control: "toggle-button",
|
||||
domainObject: domainObject,
|
||||
property: path + ".titled",
|
||||
key: "titled",
|
||||
options: [
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-two-parts-both',
|
||||
title: 'Show label'
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-two-parts-one-only',
|
||||
title: "Hide label"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
control: "button",
|
||||
domainObject: domainObject,
|
||||
method: function () {
|
||||
selection[0].context.fixedController.remove(
|
||||
selection[0].context.elementProxy
|
||||
);
|
||||
},
|
||||
key: "remove",
|
||||
icon: "icon-trash"
|
||||
}
|
||||
].filter(function (item) {
|
||||
var filtered;
|
||||
|
||||
properties.forEach(function (property) {
|
||||
if (item.property && item.key === property ||
|
||||
item.method && item.key === property) {
|
||||
filtered = item;
|
||||
}
|
||||
});
|
||||
|
||||
return filtered;
|
||||
});
|
||||
}
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"key": "telemetry.fixed",
|
||||
"name": "Fixed Position Display",
|
||||
"cssClass": "icon-box-with-dashed-lines",
|
||||
"description": "Collect and display telemetry elements in " +
|
||||
"alphanumeric format in a simple canvas workspace. " +
|
||||
"Elements can be positioned and sized. " +
|
||||
"Lines, boxes and images can be added as well.",
|
||||
"priority": 899,
|
||||
"delegates": [
|
||||
"telemetry"
|
||||
],
|
||||
"features": "creation",
|
||||
"contains": [
|
||||
{
|
||||
"has": "telemetry"
|
||||
}
|
||||
],
|
||||
"model": {
|
||||
"layoutGrid": [64, 16],
|
||||
"composition": []
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "Layout Grid",
|
||||
"control": "composite",
|
||||
"items": [
|
||||
{
|
||||
"name": "Horizontal grid (px)",
|
||||
"control": "textfield",
|
||||
"cssClass": "l-input-sm l-numeric"
|
||||
},
|
||||
{
|
||||
"name": "Vertical grid (px)",
|
||||
"control": "textfield",
|
||||
"cssClass": "l-input-sm l-numeric"
|
||||
}
|
||||
],
|
||||
"pattern": "^(\\d*[1-9]\\d*)?$",
|
||||
"property": "layoutGrid",
|
||||
"conversion": "number[]"
|
||||
}
|
||||
],
|
||||
"views": [
|
||||
"fixed-display"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
openmct.legacyRegistry.enable("platform/features/fixed");
|
||||
}
|
||||
}
|
||||
});
|
@ -1,720 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[
|
||||
'lodash',
|
||||
'./FixedProxy',
|
||||
'./elements/ElementProxies',
|
||||
'./FixedDragHandle',
|
||||
'../../../../src/api/objects/object-utils'
|
||||
],
|
||||
function (
|
||||
_,
|
||||
FixedProxy,
|
||||
ElementProxies,
|
||||
FixedDragHandle,
|
||||
objectUtils
|
||||
) {
|
||||
|
||||
var DEFAULT_DIMENSIONS = [2, 1];
|
||||
|
||||
// Convert from element x/y/width/height to an
|
||||
// appropriate ng-style argument, to position elements.
|
||||
function convertPosition(elementProxy) {
|
||||
if (elementProxy.getStyle) {
|
||||
return elementProxy.getStyle();
|
||||
}
|
||||
|
||||
var gridSize = elementProxy.getGridSize();
|
||||
|
||||
// Multiply position/dimensions by grid size
|
||||
return {
|
||||
left: (gridSize[0] * elementProxy.element.x) + 'px',
|
||||
top: (gridSize[1] * elementProxy.element.y) + 'px',
|
||||
width: (gridSize[0] * elementProxy.element.width) + 'px',
|
||||
height: (gridSize[1] * elementProxy.element.height) + 'px'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The FixedController is responsible for supporting the
|
||||
* Fixed Position view. It arranges frames according to saved
|
||||
* configuration and provides methods for updating these based on
|
||||
* mouse movement.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {Scope} $scope the controller's Angular scope
|
||||
*/
|
||||
function FixedController($scope, $q, dialogService, openmct, $element) {
|
||||
this.names = {}; // Cache names by ID
|
||||
this.values = {}; // Cache values by ID
|
||||
this.elementProxiesById = {};
|
||||
this.telemetryObjects = {};
|
||||
this.subscriptions = {};
|
||||
this.openmct = openmct;
|
||||
this.$element = $element;
|
||||
this.$scope = $scope;
|
||||
this.dialogService = dialogService;
|
||||
this.$q = $q;
|
||||
this.newDomainObject = $scope.domainObject.useCapability('adapter');
|
||||
this.fixedViewSelectable = false;
|
||||
|
||||
var self = this;
|
||||
[
|
||||
'digest',
|
||||
'fetchHistoricalData',
|
||||
'getTelemetry',
|
||||
'setDisplayedValue',
|
||||
'subscribeToObject',
|
||||
'unsubscribe',
|
||||
'updateView'
|
||||
].forEach(function (name) {
|
||||
self[name] = self[name].bind(self);
|
||||
});
|
||||
|
||||
// Decorate an element for display
|
||||
function makeProxyElement(element, index, elements) {
|
||||
var ElementProxy = ElementProxies[element.type],
|
||||
e = ElementProxy && new ElementProxy(element, index, elements, self.gridSize);
|
||||
|
||||
if (e) {
|
||||
// Provide a displayable position (convert from grid to px)
|
||||
e.style = convertPosition(e);
|
||||
// Template names are same as type names, presently
|
||||
e.template = element.type;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
// Decorate elements in the current configuration
|
||||
function refreshElements() {
|
||||
var elements = (((self.newDomainObject.configuration || {})['fixed-display'] || {}).elements || []);
|
||||
|
||||
// Create the new proxies...
|
||||
self.elementProxies = elements.map(makeProxyElement);
|
||||
|
||||
if (self.selectedElementProxy) {
|
||||
// If selection is not in array, select parent.
|
||||
// Otherwise, set the element to select after refresh.
|
||||
var index = elements.indexOf(self.selectedElementProxy.element);
|
||||
if (index === -1) {
|
||||
self.$element[0].click();
|
||||
} else if (!self.elementToSelectAfterRefresh) {
|
||||
self.elementToSelectAfterRefresh = self.elementProxies[index].element;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, rebuild lists of elements by id to
|
||||
// facilitate faster update when new telemetry comes in.
|
||||
self.elementProxiesById = {};
|
||||
self.elementProxies.forEach(function (elementProxy) {
|
||||
var id = elementProxy.id;
|
||||
if (elementProxy.element.type === 'fixed.telemetry') {
|
||||
// Provide it a cached name/value to avoid flashing
|
||||
elementProxy.name = self.names[id];
|
||||
elementProxy.value = self.values[id];
|
||||
self.elementProxiesById[id] = self.elementProxiesById[id] || [];
|
||||
self.elementProxiesById[id].push(elementProxy);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger a new query for telemetry data
|
||||
function updateDisplayBounds(bounds, isTick) {
|
||||
if (!isTick) {
|
||||
//Reset values
|
||||
self.values = {};
|
||||
refreshElements();
|
||||
|
||||
//Fetch new data
|
||||
Object.values(self.telemetryObjects).forEach(function (object) {
|
||||
self.fetchHistoricalData(object);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add an element to this view
|
||||
function addElement(element) {
|
||||
var index;
|
||||
var elements = (((self.newDomainObject.configuration || {})['fixed-display'] || {}).elements || []);
|
||||
elements.push(element);
|
||||
|
||||
if (self.selectedElementProxy) {
|
||||
index = elements.indexOf(self.selectedElementProxy.element);
|
||||
}
|
||||
|
||||
self.mutate("configuration['fixed-display'].elements", elements);
|
||||
elements = (self.newDomainObject.configuration)['fixed-display'].elements || [];
|
||||
self.elementToSelectAfterRefresh = elements[elements.length - 1];
|
||||
|
||||
if (self.selectedElementProxy) {
|
||||
// Update the selected element with the new
|
||||
// value since newDomainOject is mutated.
|
||||
self.selectedElementProxy.element = elements[index];
|
||||
}
|
||||
refreshElements();
|
||||
}
|
||||
|
||||
// Position a panel after a drop event
|
||||
function handleDrop(e, id, position) {
|
||||
// Don't handle this event if it has already been handled
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Store the position of this element.
|
||||
// color is set to "" to let the CSS theme determine the default color
|
||||
addElement({
|
||||
type: "fixed.telemetry",
|
||||
x: Math.floor(position.x / self.gridSize[0]),
|
||||
y: Math.floor(position.y / self.gridSize[1]),
|
||||
id: id,
|
||||
stroke: "transparent",
|
||||
color: "",
|
||||
titled: true,
|
||||
width: DEFAULT_DIMENSIONS[0],
|
||||
height: DEFAULT_DIMENSIONS[1],
|
||||
useGrid: true
|
||||
});
|
||||
|
||||
// Subscribe to the new object to get telemetry
|
||||
self.openmct.objects.get(id).then(function (object) {
|
||||
self.getTelemetry(object);
|
||||
});
|
||||
}
|
||||
|
||||
this.elementProxies = [];
|
||||
this.addElement = addElement;
|
||||
this.refreshElements = refreshElements;
|
||||
this.fixedProxy = new FixedProxy(this.addElement, this.$q, this.dialogService);
|
||||
|
||||
this.composition = this.openmct.composition.get(this.newDomainObject);
|
||||
this.composition.on('add', this.onCompositionAdd, this);
|
||||
this.composition.on('remove', this.onCompositionRemove, this);
|
||||
this.composition.load();
|
||||
|
||||
// Position panes where they are dropped
|
||||
$scope.$on("mctDrop", handleDrop);
|
||||
|
||||
$scope.$on("$destroy", this.destroy.bind(this));
|
||||
|
||||
// Respond to external bounds changes
|
||||
this.openmct.time.on("bounds", updateDisplayBounds);
|
||||
|
||||
this.openmct.selection.on('change', this.setSelection.bind(this));
|
||||
this.openmct.editor.on('isEditing', this.handleEditing.bind(this));
|
||||
|
||||
this.$element.on('click', this.bypassSelection.bind(this));
|
||||
this.unlisten = this.openmct.objects.observe(this.newDomainObject, '*', function (obj) {
|
||||
this.newDomainObject = JSON.parse(JSON.stringify(obj));
|
||||
this.updateElementPositions(this.newDomainObject.layoutGrid);
|
||||
}.bind(this));
|
||||
|
||||
this.updateElementPositions(this.newDomainObject.layoutGrid);
|
||||
refreshElements();
|
||||
}
|
||||
|
||||
FixedController.prototype.updateElementPositions = function (layoutGrid) {
|
||||
this.gridSize = layoutGrid;
|
||||
|
||||
this.elementProxies.forEach(function (elementProxy) {
|
||||
elementProxy.setGridSize(this.gridSize);
|
||||
elementProxy.style = convertPosition(elementProxy);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
FixedController.prototype.onCompositionAdd = function (object) {
|
||||
this.getTelemetry(object);
|
||||
};
|
||||
|
||||
FixedController.prototype.onCompositionRemove = function (identifier) {
|
||||
// Defer mutation of newDomainObject to prevent mutating an
|
||||
// outdated version since this is triggered by a composition change.
|
||||
setTimeout(function () {
|
||||
var id = objectUtils.makeKeyString(identifier);
|
||||
var elements = this.newDomainObject.configuration['fixed-display'].elements || [];
|
||||
var newElements = elements.filter(function (proxy) {
|
||||
return proxy.id !== id;
|
||||
});
|
||||
this.mutate("configuration['fixed-display'].elements", newElements);
|
||||
|
||||
if (this.subscriptions[id]) {
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
}
|
||||
|
||||
delete this.telemetryObjects[id];
|
||||
this.refreshElements();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes an element from the view.
|
||||
*
|
||||
* @param {Object} elementProxy the element proxy to remove.
|
||||
*/
|
||||
FixedController.prototype.remove = function (elementProxy) {
|
||||
var element = elementProxy.element;
|
||||
var elements = this.newDomainObject.configuration['fixed-display'].elements || [];
|
||||
elements.splice(elements.indexOf(element), 1);
|
||||
|
||||
if (element.type === 'fixed.telemetry') {
|
||||
this.newDomainObject.composition = this.newDomainObject.composition.filter(function (identifier) {
|
||||
return objectUtils.makeKeyString(identifier) !== element.id;
|
||||
});
|
||||
}
|
||||
|
||||
this.mutate("configuration['fixed-display'].elements", elements);
|
||||
this.refreshElements();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a new element to the view.
|
||||
*
|
||||
* @param {string} type the type of element to add. Supported types are:
|
||||
* `fixed.image`
|
||||
* `fixed.box`
|
||||
* `fixed.text`
|
||||
* `fixed.line`
|
||||
*/
|
||||
FixedController.prototype.add = function (type) {
|
||||
this.fixedProxy.add(type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the display order of the element proxy.
|
||||
*/
|
||||
FixedController.prototype.order = function (elementProxy, position) {
|
||||
var elements = elementProxy.order(position);
|
||||
|
||||
// Find the selected element index in the updated array.
|
||||
var selectedElemenetIndex = elements.indexOf(this.selectedElementProxy.element);
|
||||
|
||||
this.mutate("configuration['fixed-display'].elements", elements);
|
||||
elements = (this.newDomainObject.configuration)['fixed-display'].elements || [];
|
||||
|
||||
// Update the selected element with the new
|
||||
// value since newDomainOject is mutated.
|
||||
this.selectedElementProxy.element = elements[selectedElemenetIndex];
|
||||
this.refreshElements();
|
||||
};
|
||||
|
||||
FixedController.prototype.generateDragHandle = function (elementProxy, elementHandle) {
|
||||
var index = this.elementProxies.indexOf(elementProxy);
|
||||
|
||||
if (elementHandle) {
|
||||
elementHandle.element = elementProxy.element;
|
||||
elementProxy = elementHandle;
|
||||
}
|
||||
|
||||
return new FixedDragHandle(
|
||||
elementProxy,
|
||||
"configuration['fixed-display'].elements[" + index + "]",
|
||||
this
|
||||
);
|
||||
};
|
||||
|
||||
FixedController.prototype.generateDragHandles = function (elementProxy) {
|
||||
return elementProxy.handles().map(function (handle) {
|
||||
return this.generateDragHandle(elementProxy, handle);
|
||||
}, this);
|
||||
};
|
||||
|
||||
FixedController.prototype.updateSelectionStyle = function () {
|
||||
this.selectedElementProxy.style = convertPosition(this.selectedElementProxy);
|
||||
};
|
||||
|
||||
FixedController.prototype.setSelection = function (selectable) {
|
||||
var selection = selectable[0];
|
||||
|
||||
if (this.selectionListeners) {
|
||||
this.selectionListeners.forEach(function (l) {
|
||||
l();
|
||||
});
|
||||
}
|
||||
|
||||
this.selectionListeners = [];
|
||||
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (selection.context.elementProxy) {
|
||||
this.selectedElementProxy = selection.context.elementProxy;
|
||||
this.attachSelectionListeners();
|
||||
this.mvHandle = this.generateDragHandle(this.selectedElementProxy);
|
||||
this.resizeHandles = this.generateDragHandles(this.selectedElementProxy);
|
||||
} else {
|
||||
// Make fixed view selectable if it's not already.
|
||||
if (!this.fixedViewSelectable && selectable.length === 1) {
|
||||
this.fixedViewSelectable = true;
|
||||
selection.context.fixedController = this;
|
||||
this.openmct.selection.select(selection);
|
||||
}
|
||||
|
||||
this.resizeHandles = [];
|
||||
this.mvHandle = undefined;
|
||||
this.selectedElementProxy = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
FixedController.prototype.attachSelectionListeners = function () {
|
||||
var index = this.elementProxies.indexOf(this.selectedElementProxy);
|
||||
var path = "configuration['fixed-display'].elements[" + index + "]";
|
||||
|
||||
this.selectionListeners.push(this.openmct.objects.observe(this.newDomainObject, path + ".useGrid", function (newValue) {
|
||||
if (this.selectedElementProxy.useGrid() !== newValue) {
|
||||
this.selectedElementProxy.useGrid(newValue);
|
||||
this.updateSelectionStyle();
|
||||
this.openmct.objects.mutate(this.newDomainObject, path, this.selectedElementProxy.element);
|
||||
}
|
||||
}.bind(this)));
|
||||
[
|
||||
"width",
|
||||
"height",
|
||||
"stroke",
|
||||
"fill",
|
||||
"x",
|
||||
"y",
|
||||
"x1",
|
||||
"y1",
|
||||
"x2",
|
||||
"y2",
|
||||
"color",
|
||||
"size",
|
||||
"text",
|
||||
"titled"
|
||||
].forEach(function (property) {
|
||||
this.selectionListeners.push(this.openmct.objects.observe(this.newDomainObject, path + "." + property, function (newValue) {
|
||||
this.selectedElementProxy.element[property] = newValue;
|
||||
this.updateSelectionStyle();
|
||||
}.bind(this)));
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
FixedController.prototype.destroy = function () {
|
||||
this.unsubscribe();
|
||||
this.unlisten();
|
||||
this.openmct.time.off("bounds", this.updateDisplayBounds);
|
||||
this.openmct.selection.off("change", this.setSelection);
|
||||
this.composition.off('add', this.onCompositionAdd, this);
|
||||
this.composition.off('remove', this.onCompositionRemove, this);
|
||||
this.openmct.editor.off('isEditing', this.handleEditing, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* A rate-limited digest function. Caps digests at 60Hz
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.digest = function () {
|
||||
var self = this;
|
||||
|
||||
if (!this.digesting) {
|
||||
this.digesting = true;
|
||||
requestAnimationFrame(function () {
|
||||
self.$scope.$digest();
|
||||
self.digesting = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unsubscribe all listeners
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.unsubscribe = function () {
|
||||
Object.values(this.subscriptions).forEach(function (unsubscribeFunc) {
|
||||
unsubscribeFunc();
|
||||
});
|
||||
this.subscriptions = {};
|
||||
this.telemetryObjects = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribe to the given domain object
|
||||
* @private
|
||||
* @param {object} object Domain object to subscribe to
|
||||
* @returns {object} The provided object, for chaining.
|
||||
*/
|
||||
FixedController.prototype.subscribeToObject = function (object) {
|
||||
var self = this;
|
||||
var timeAPI = this.openmct.time;
|
||||
var id = objectUtils.makeKeyString(object.identifier);
|
||||
this.subscriptions[id] = self.openmct.telemetry.subscribe(object, function (datum) {
|
||||
if (timeAPI.clock() !== undefined) {
|
||||
self.updateView(object, datum);
|
||||
}
|
||||
}, {});
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
/**
|
||||
* Print the values from the given datum against the provided object in the view.
|
||||
* @private
|
||||
* @param {object} telemetryObject The domain object associated with the given telemetry data
|
||||
* @param {object} datum The telemetry datum containing the values to print
|
||||
*/
|
||||
FixedController.prototype.updateView = function (telemetryObject, datum) {
|
||||
var metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
var valueMetadata = this.chooseValueMetadataToDisplay(metadata);
|
||||
var formattedTelemetryValue = this.getFormattedTelemetryValueForKey(valueMetadata, datum);
|
||||
var limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
|
||||
var alarm = limitEvaluator && limitEvaluator.evaluate(datum, valueMetadata);
|
||||
|
||||
this.setDisplayedValue(
|
||||
telemetryObject,
|
||||
formattedTelemetryValue,
|
||||
alarm && alarm.cssClass
|
||||
);
|
||||
this.digest();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.getFormattedTelemetryValueForKey = function (valueMetadata, datum) {
|
||||
var formatter = this.openmct.telemetry.getValueFormatter(valueMetadata);
|
||||
|
||||
return formatter.format(datum);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.chooseValueMetadataToDisplay = function (metadata) {
|
||||
// If there is a range value, show that preferentially
|
||||
var valueMetadata = metadata.valuesForHints(['range'])[0];
|
||||
|
||||
// If no range is defined, default to the highest priority non time-domain data.
|
||||
if (valueMetadata === undefined) {
|
||||
var valuesOrderedByPriority = metadata.values();
|
||||
valueMetadata = valuesOrderedByPriority.filter(function (values) {
|
||||
return !(values.hints.domain);
|
||||
})[0];
|
||||
}
|
||||
|
||||
return valueMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request the last historical data point for the given domain object
|
||||
* @param {object} object
|
||||
* @returns {object} the provided object for chaining.
|
||||
*/
|
||||
FixedController.prototype.fetchHistoricalData = function (object) {
|
||||
var bounds = this.openmct.time.bounds();
|
||||
var self = this;
|
||||
|
||||
self.openmct.telemetry.request(object, {start: bounds.start, end: bounds.end, size: 1})
|
||||
.then(function (data) {
|
||||
if (data.length > 0) {
|
||||
self.updateView(object, data[data.length - 1]);
|
||||
}
|
||||
});
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Print a value to the onscreen element associated with a given telemetry object.
|
||||
* @private
|
||||
* @param {object} telemetryObject The telemetry object associated with the value
|
||||
* @param {string | number} value The value to print to screen
|
||||
* @param {string} [cssClass] an optional CSS class to apply to the onscreen element.
|
||||
*/
|
||||
FixedController.prototype.setDisplayedValue = function (telemetryObject, value, cssClass) {
|
||||
var id = objectUtils.makeKeyString(telemetryObject.identifier);
|
||||
var self = this;
|
||||
|
||||
(self.elementProxiesById[id] || []).forEach(function (element) {
|
||||
self.names[id] = telemetryObject.name;
|
||||
self.values[id] = value;
|
||||
element.name = self.names[id];
|
||||
element.value = self.values[id];
|
||||
element.cssClass = cssClass;
|
||||
});
|
||||
};
|
||||
|
||||
FixedController.prototype.getTelemetry = function (domainObject) {
|
||||
var id = objectUtils.makeKeyString(domainObject.identifier);
|
||||
|
||||
if (this.subscriptions[id]) {
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
}
|
||||
delete this.telemetryObjects[id];
|
||||
|
||||
if (!this.openmct.telemetry.isTelemetryObject(domainObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize display
|
||||
this.telemetryObjects[id] = domainObject;
|
||||
this.setDisplayedValue(domainObject, "");
|
||||
|
||||
return Promise.resolve(domainObject)
|
||||
.then(this.fetchHistoricalData)
|
||||
.then(this.subscribeToObject);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of the grid, in pixels. The returned array
|
||||
* is in the form `[x, y]`.
|
||||
* @returns {number[]} the grid size
|
||||
* @memberof platform/features/layout.FixedController#
|
||||
*/
|
||||
FixedController.prototype.getGridSize = function () {
|
||||
return this.gridSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an array of elements in this panel; these are
|
||||
* decorated proxies for both selection and display.
|
||||
* @returns {Array} elements in this panel
|
||||
*/
|
||||
FixedController.prototype.getElements = function () {
|
||||
return this.elementProxies;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the element should be selected or not.
|
||||
*
|
||||
* @param elementProxy the element to check
|
||||
* @returns {boolean} true if the element should be selected.
|
||||
*/
|
||||
FixedController.prototype.shouldSelect = function (elementProxy) {
|
||||
if (elementProxy.element === this.elementToSelectAfterRefresh) {
|
||||
delete this.elementToSelectAfterRefresh;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if an element is currently selected.
|
||||
*
|
||||
* @returns {boolean} true if an element is selected.
|
||||
*/
|
||||
FixedController.prototype.isElementSelected = function () {
|
||||
return (this.selectedElementProxy) ? true : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the style for the selected element.
|
||||
*
|
||||
* @returns {string} element style
|
||||
*/
|
||||
FixedController.prototype.getSelectedElementStyle = function () {
|
||||
return (this.selectedElementProxy) ? this.selectedElementProxy.style : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the selected element.
|
||||
*
|
||||
* @returns the selected element
|
||||
*/
|
||||
FixedController.prototype.getSelectedElement = function () {
|
||||
return this.selectedElementProxy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prevents the event from bubbling up if drag is in progress.
|
||||
*/
|
||||
FixedController.prototype.bypassSelection = function ($event) {
|
||||
if (this.dragInProgress) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get drag handles.
|
||||
* @returns {platform/features/layout.FixedDragHandle[]}
|
||||
* drag handles for the current selection
|
||||
*/
|
||||
FixedController.prototype.handles = function () {
|
||||
return this.resizeHandles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the handle to handle dragging to reposition an element.
|
||||
* @returns {platform/features/layout.FixedDragHandle} the drag handle
|
||||
*/
|
||||
FixedController.prototype.moveHandle = function () {
|
||||
return this.mvHandle;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the selection context.
|
||||
*
|
||||
* @param elementProxy the element proxy
|
||||
* @returns {object} the context object which includes elementProxy
|
||||
*/
|
||||
FixedController.prototype.getContext = function (elementProxy) {
|
||||
return {
|
||||
elementProxy: elementProxy,
|
||||
fixedController: this
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* End drag.
|
||||
*
|
||||
* @param handle the resize handle
|
||||
*/
|
||||
FixedController.prototype.endDrag = function (handle) {
|
||||
this.dragInProgress = true;
|
||||
|
||||
setTimeout(function () {
|
||||
this.dragInProgress = false;
|
||||
}.bind(this), 0);
|
||||
|
||||
if (handle) {
|
||||
handle.endDrag();
|
||||
} else {
|
||||
this.moveHandle().endDrag();
|
||||
}
|
||||
};
|
||||
|
||||
FixedController.prototype.mutate = function (path, value) {
|
||||
this.openmct.objects.mutate(this.newDomainObject, path, value);
|
||||
};
|
||||
|
||||
FixedController.prototype.handleEditing = function (isEditing) {
|
||||
// Listen for edit mode changes and update selection if necessary.
|
||||
// Mainly to ensure fixedController is on the selection context when editing.
|
||||
this.setSelection(this.openmct.selection.get());
|
||||
}
|
||||
|
||||
return FixedController;
|
||||
}
|
||||
);
|
@ -1,110 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
// Drag handle dimensions
|
||||
var DRAG_HANDLE_SIZE = [6, 6];
|
||||
|
||||
/**
|
||||
* Template-displayable drag handle for an element in fixed
|
||||
* position mode.
|
||||
*
|
||||
* @param elementHandle the element handle
|
||||
* @param configPath the configuration path of an element
|
||||
* @param {Object} fixedControl the fixed controller
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
*/
|
||||
function FixedDragHandle(elementHandle, configPath, fixedControl) {
|
||||
this.elementHandle = elementHandle;
|
||||
this.configPath = configPath;
|
||||
this.fixedControl = fixedControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a CSS style to position this drag handle.
|
||||
*
|
||||
* @returns CSS style object (for `ng-style`)
|
||||
* @memberof platform/features/layout.FixedDragHandle#
|
||||
*/
|
||||
FixedDragHandle.prototype.style = function () {
|
||||
var gridSize = this.elementHandle.getGridSize();
|
||||
|
||||
// Adjust from grid to pixel coordinates
|
||||
var x = this.elementHandle.x() * gridSize[0],
|
||||
y = this.elementHandle.y() * gridSize[1];
|
||||
|
||||
// Convert to a CSS style centered on that point
|
||||
return {
|
||||
left: (x - DRAG_HANDLE_SIZE[0] / 2) + 'px',
|
||||
top: (y - DRAG_HANDLE_SIZE[1] / 2) + 'px',
|
||||
width: DRAG_HANDLE_SIZE[0] + 'px',
|
||||
height: DRAG_HANDLE_SIZE[1] + 'px'
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a drag gesture. This should be called when a drag
|
||||
* begins to track initial state.
|
||||
*/
|
||||
FixedDragHandle.prototype.startDrag = function () {
|
||||
// Cache initial x/y positions
|
||||
this.dragging = {
|
||||
x: this.elementHandle.x(),
|
||||
y: this.elementHandle.y()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Continue a drag gesture; update x/y positions.
|
||||
*
|
||||
* @param {number[]} delta x/y pixel difference since drag started
|
||||
*/
|
||||
FixedDragHandle.prototype.continueDrag = function (delta) {
|
||||
var gridSize = this.elementHandle.getGridSize();
|
||||
|
||||
if (this.dragging) {
|
||||
// Update x/y positions (snapping to grid)
|
||||
var newX = this.dragging.x + Math.round(delta[0] / gridSize[0]);
|
||||
var newY = this.dragging.y + Math.round(delta[1] / gridSize[1]);
|
||||
|
||||
this.elementHandle.x(Math.max(0, newX));
|
||||
this.elementHandle.y(Math.max(0, newY));
|
||||
this.fixedControl.updateSelectionStyle();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End a drag gesture. This should be called when a drag
|
||||
* concludes to trigger commit of changes.
|
||||
*/
|
||||
FixedDragHandle.prototype.endDrag = function () {
|
||||
this.dragging = undefined;
|
||||
this.fixedControl.mutate(this.configPath, this.elementHandle.element);
|
||||
};
|
||||
|
||||
return FixedDragHandle;
|
||||
}
|
||||
);
|
@ -1,76 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./elements/ElementFactory'],
|
||||
function (ElementFactory) {
|
||||
|
||||
/**
|
||||
* Proxy for configuring a fixed position view via the toolbar.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {Function} addElementCallback callback to invoke when
|
||||
* elements are created
|
||||
* @param $q Angular's $q, for promise-handling
|
||||
* @param {DialogService} dialogService dialog service to use
|
||||
* when adding a new element will require user input
|
||||
*/
|
||||
function FixedProxy(addElementCallback, $q, dialogService) {
|
||||
this.factory = new ElementFactory(dialogService);
|
||||
this.$q = $q;
|
||||
this.addElementCallback = addElementCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new visual element to this view. Supported types are:
|
||||
*
|
||||
* * `fixed.image`
|
||||
* * `fixed.box`
|
||||
* * `fixed.text`
|
||||
* * `fixed.line`
|
||||
*
|
||||
* @param {string} type the type of element to add
|
||||
*/
|
||||
FixedProxy.prototype.add = function (type) {
|
||||
var addElementCallback = this.addElementCallback;
|
||||
|
||||
// Place a configured element into the view configuration
|
||||
function addElement(element) {
|
||||
// Configure common properties of the element
|
||||
element.x = element.x || 0;
|
||||
element.y = element.y || 0;
|
||||
element.width = element.width || 1;
|
||||
element.height = element.height || 1;
|
||||
element.type = type;
|
||||
element.useGrid = true;
|
||||
|
||||
// Finally, add it to the view's configuration
|
||||
addElementCallback(element);
|
||||
}
|
||||
|
||||
// Defer creation to the factory
|
||||
this.$q.when(this.factory.createElement(type)).then(addElement);
|
||||
};
|
||||
|
||||
return FixedProxy;
|
||||
}
|
||||
);
|
@ -1,115 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 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]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.getAdjustedPosition = function (pixelDelta) {
|
||||
var 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 LayoutDrag;
|
||||
|
||||
}
|
||||
);
|
@ -1,105 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'zepto',
|
||||
'../../../commonUI/general/src/services/Overlay'
|
||||
], function (
|
||||
$,
|
||||
Overlay
|
||||
) {
|
||||
/**
|
||||
* MCT Trigger Modal is intended for use in only one location: inside the
|
||||
* object-header to allow views in a layout to be popped out in a modal.
|
||||
* Users can close the modal and go back to normal, and everything generally
|
||||
* just works fine.
|
||||
*
|
||||
* This code is sensitive to how our html is constructed-- particularly with
|
||||
* how it locates the the container of an element in a layout. However, it
|
||||
* should be able to handle slight relocations so long as it is always a
|
||||
* descendent of a `.frame` element.
|
||||
*/
|
||||
function MCTTriggerModal($document) {
|
||||
|
||||
function link($scope, $element) {
|
||||
var actions = $scope.domainObject.getCapability('action'),
|
||||
notebookAction = actions.getActions({key: 'notebook-new-entry'})[0];
|
||||
|
||||
var frame = $element.parent();
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
if (frame.hasClass('frame')) {
|
||||
break;
|
||||
}
|
||||
frame = frame.parent();
|
||||
}
|
||||
if (!frame.hasClass('frame')) {
|
||||
$element.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
frame = frame[0];
|
||||
|
||||
var layoutContainer = frame.parentElement;
|
||||
|
||||
var notebookButton = notebookAction ?
|
||||
[
|
||||
{
|
||||
class: 'icon-notebook new-notebook-entry',
|
||||
title: 'New Notebook Entry',
|
||||
clickHandler: function (event) {
|
||||
event.stopPropagation();
|
||||
notebookAction.perform();
|
||||
}
|
||||
}
|
||||
] : [];
|
||||
|
||||
var overlayService = new Overlay ({
|
||||
$document: $document,
|
||||
$scope: $scope,
|
||||
$element: frame,
|
||||
overlayWillMount: function () {
|
||||
$(frame).removeClass('frame frame-template');
|
||||
layoutContainer.removeChild(frame);
|
||||
},
|
||||
overlayDidUnmount: function () {
|
||||
$(frame).addClass('frame frame-template');
|
||||
layoutContainer.appendChild(frame);
|
||||
},
|
||||
browseBarButtons: notebookButton
|
||||
});
|
||||
|
||||
$element.on('click', overlayService.toggleOverlay);
|
||||
$scope.$on('$destroy', function () {
|
||||
$element.off('click', overlayService.toggleOverlay);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: link
|
||||
};
|
||||
}
|
||||
|
||||
return MCTTriggerModal;
|
||||
|
||||
});
|
@ -1,58 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Utility function for creating getter-setter functions,
|
||||
* since these are frequently useful for element proxies.
|
||||
*
|
||||
* An optional third argument may be supplied in order to
|
||||
* constrain or modify arguments when using as a setter;
|
||||
* this argument is a function which takes two arguments
|
||||
* (the current value for the property, and the requested
|
||||
* new value.) This is useful when values need to be kept
|
||||
* in certain ranges; specifically, to keep x/y positions
|
||||
* non-negative in a fixed position view.
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {Object} object the object to get/set values upon
|
||||
* @param {string} key the property to get/set
|
||||
* @param {function} [updater] function used to process updates
|
||||
*/
|
||||
function AccessorMutator(object, key, updater) {
|
||||
return function (value) {
|
||||
if (arguments.length > 0) {
|
||||
object[key] = updater ?
|
||||
updater(value, object[key]) :
|
||||
value;
|
||||
}
|
||||
return object[key];
|
||||
};
|
||||
}
|
||||
|
||||
return AccessorMutator;
|
||||
}
|
||||
);
|
@ -1,61 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./ElementProxy', './AccessorMutator'],
|
||||
function (ElementProxy, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection proxy for Box elements in a fixed position view.
|
||||
* Also serves as a superclass for Text elements, since those
|
||||
* elements have a superset of Box properties.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @param {Array} elements the full array of elements
|
||||
*/
|
||||
function BoxProxy(element, index, elements, gridSize) {
|
||||
var proxy = new ElementProxy(element, index, elements, gridSize);
|
||||
|
||||
/**
|
||||
* Get/set this element's fill color. (Omitting the
|
||||
* argument makes this act as a getter.)
|
||||
* @method
|
||||
* @param {string} fill the new fill color
|
||||
* @returns {string} the fill color
|
||||
* @memberof platform/features/layout.BoxProxy#
|
||||
*/
|
||||
proxy.fill = new AccessorMutator(element, 'fill');
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return BoxProxy;
|
||||
}
|
||||
);
|
@ -1,115 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
var INITIAL_STATES = {
|
||||
"fixed.image": {
|
||||
stroke: "transparent"
|
||||
},
|
||||
"fixed.box": {
|
||||
fill: "#717171",
|
||||
border: "transparent",
|
||||
stroke: "transparent"
|
||||
},
|
||||
"fixed.line": {
|
||||
x: 5,
|
||||
y: 9,
|
||||
x2: 6,
|
||||
y2: 6,
|
||||
stroke: "#717171"
|
||||
},
|
||||
"fixed.text": {
|
||||
fill: "transparent",
|
||||
stroke: "transparent",
|
||||
size: "13px"
|
||||
}
|
||||
},
|
||||
DIALOGS = {
|
||||
"fixed.image": {
|
||||
name: "Image Properties",
|
||||
sections: [
|
||||
{
|
||||
rows: [
|
||||
{
|
||||
key: "url",
|
||||
control: "textfield",
|
||||
name: "Image URL",
|
||||
"cssClass": "l-input-lg",
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"fixed.text": {
|
||||
name: "Text Element Properties",
|
||||
sections: [
|
||||
{
|
||||
rows: [
|
||||
{
|
||||
key: "text",
|
||||
control: "textfield",
|
||||
name: "Text",
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The ElementFactory creates new instances of elements for the
|
||||
* fixed position view, prompting for user input where necessary.
|
||||
* @param {DialogService} dialogService service to request user input
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
*/
|
||||
function ElementFactory(dialogService) {
|
||||
this.dialogService = dialogService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new element for the fixed position view.
|
||||
* @param {string} type the type of element to create
|
||||
* @returns {Promise|object} the created element, or a promise
|
||||
* for that element
|
||||
*/
|
||||
ElementFactory.prototype.createElement = function (type) {
|
||||
var initialState = INITIAL_STATES[type] || {};
|
||||
|
||||
// Clone that state
|
||||
initialState = JSON.parse(JSON.stringify(initialState));
|
||||
|
||||
// Show a dialog to configure initial state, if appropriate
|
||||
return DIALOGS[type] ? this.dialogService.getUserInput(
|
||||
DIALOGS[type],
|
||||
initialState
|
||||
) : initialState;
|
||||
};
|
||||
|
||||
return ElementFactory;
|
||||
}
|
||||
);
|
@ -1,35 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./TelemetryProxy', './ImageProxy', './LineProxy', './BoxProxy', './TextProxy'],
|
||||
function (TelemetryProxy, ImageProxy, LineProxy, BoxProxy, TextProxy) {
|
||||
|
||||
return {
|
||||
"fixed.telemetry": TelemetryProxy,
|
||||
"fixed.line": LineProxy,
|
||||
"fixed.box": BoxProxy,
|
||||
"fixed.image": ImageProxy,
|
||||
"fixed.text": TextProxy
|
||||
};
|
||||
}
|
||||
);
|
@ -1,209 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./AccessorMutator', './ResizeHandle', './UnitAccessorMutator'],
|
||||
function (AccessorMutator, ResizeHandle, UnitAccessorMutator) {
|
||||
|
||||
// Index deltas for changes in order
|
||||
var ORDERS = {
|
||||
top: Number.POSITIVE_INFINITY,
|
||||
up: 1,
|
||||
down: -1,
|
||||
bottom: Number.NEGATIVE_INFINITY
|
||||
};
|
||||
|
||||
// Mininmum pixel height and width for objects
|
||||
var MIN_WIDTH = 10;
|
||||
var MIN_HEIGHT = 10;
|
||||
|
||||
// Ensure a value is non-negative (for x/y setters)
|
||||
function clamp(value) {
|
||||
return Math.max(value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract superclass for other classes which provide useful
|
||||
* interfaces upon an elements in a fixed position view.
|
||||
* This handles the generic operations (e.g. remove) so that
|
||||
* subclasses only need to implement element-specific behaviors.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
*/
|
||||
function ElementProxy(element, index, elements, gridSize) {
|
||||
/**
|
||||
* The element as stored in the view configuration.
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.element = element;
|
||||
|
||||
/**
|
||||
* The current grid size of the layout.
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.gridSize = gridSize || [1,1]; //Ensure a reasonable default
|
||||
|
||||
/**
|
||||
* Get and/or set the x position of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [x] the new x position (if setting)
|
||||
* @returns {number} the x position
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.x = new AccessorMutator(element, 'x', clamp);
|
||||
|
||||
/**
|
||||
* Get and/or set the y position of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [y] the new y position (if setting)
|
||||
* @returns {number} the y position
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.y = new AccessorMutator(element, 'y', clamp);
|
||||
|
||||
/**
|
||||
* Get and/or set the stroke color of this element.
|
||||
* @param {string} [stroke] the new stroke color (if setting)
|
||||
* @returns {string} the stroke color
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.stroke = new AccessorMutator(element, 'stroke');
|
||||
|
||||
/**
|
||||
* Get and/or set the width of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [w] the new width (if setting)
|
||||
* @returns {number} the width
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.width = new AccessorMutator(element, 'width');
|
||||
|
||||
/**
|
||||
* Get and/or set the height of this element.
|
||||
* Units are in fixed position grid space.
|
||||
* @param {number} [h] the new height (if setting)
|
||||
* @returns {number} the height
|
||||
* @memberof platform/features/layout.ElementProxy#
|
||||
*/
|
||||
this.height = new AccessorMutator(element, 'height');
|
||||
|
||||
this.useGrid = new UnitAccessorMutator(this);
|
||||
this.index = index;
|
||||
this.elements = elements;
|
||||
this.resizeHandles = [new ResizeHandle(this, this.element)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the display order of this element.
|
||||
* @param {string} o where to move this element;
|
||||
* one of "top", "up", "down", or "bottom"
|
||||
* @return {Array} the full array of elements
|
||||
*/
|
||||
ElementProxy.prototype.order = function (o) {
|
||||
var index = this.index,
|
||||
elements = this.elements,
|
||||
element = this.element,
|
||||
delta = ORDERS[o] || 0,
|
||||
desired = Math.max(
|
||||
Math.min(index + delta, elements.length - 1),
|
||||
0
|
||||
);
|
||||
// Move to the desired index, if this is a change
|
||||
if ((desired !== index) && (elements[index] === element)) {
|
||||
// Splice out the current element
|
||||
elements.splice(index, 1);
|
||||
// Splice it back in at the correct index
|
||||
elements.splice(desired, 0, element);
|
||||
// Track change in index (proxy should be recreated
|
||||
// anyway, but be consistent)
|
||||
this.index = desired;
|
||||
}
|
||||
|
||||
return elements;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get handles to control specific features of this element,
|
||||
* e.g. corner size.
|
||||
* @return {platform/features/layout.ElementHandle[]} handles
|
||||
* for moving/resizing this element
|
||||
*/
|
||||
ElementProxy.prototype.handles = function () {
|
||||
return this.resizeHandles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns which grid size the element is currently using.
|
||||
* @return {number[]} The current grid size in [x,y] form if the element
|
||||
* is currently using the grid, [1,1] if it is using
|
||||
* pixels.
|
||||
*/
|
||||
ElementProxy.prototype.getGridSize = function () {
|
||||
var gridSize;
|
||||
// Default to using the grid if useGrid was not defined
|
||||
if (typeof this.element.useGrid === 'undefined') {
|
||||
this.element.useGrid = true;
|
||||
}
|
||||
if (this.element.useGrid) {
|
||||
gridSize = this.gridSize;
|
||||
} else {
|
||||
gridSize = [1,1];
|
||||
}
|
||||
return gridSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the current grid size stored by this element proxy
|
||||
* @param {number[]} gridSize The current layout grid size in [x,y] form
|
||||
*/
|
||||
ElementProxy.prototype.setGridSize = function (gridSize) {
|
||||
this.gridSize = gridSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current minimum element width in grid units
|
||||
* @return {number} The current minimum element width
|
||||
*/
|
||||
ElementProxy.prototype.getMinWidth = function () {
|
||||
return Math.ceil(MIN_WIDTH / this.getGridSize()[0]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current minimum element height in grid units
|
||||
* @return {number} The current minimum element height
|
||||
*/
|
||||
ElementProxy.prototype.getMinHeight = function () {
|
||||
return Math.ceil(MIN_HEIGHT / this.getGridSize()[1]);
|
||||
};
|
||||
|
||||
return ElementProxy;
|
||||
}
|
||||
);
|
@ -1,58 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./ElementProxy', './AccessorMutator'],
|
||||
function (ElementProxy, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection proxy for Image elements in a fixed position view.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function ImageProxy(element, index, elements, gridSize) {
|
||||
var proxy = new ElementProxy(element, index, elements, gridSize);
|
||||
|
||||
/**
|
||||
* Get and/or set the displayed text of this element.
|
||||
* @param {string} [text] the new text (if setting)
|
||||
* @returns {string} the text
|
||||
* @memberof platform/features/layout.ImageProxy#
|
||||
*/
|
||||
proxy.url = new AccessorMutator(element, 'url');
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return ImageProxy;
|
||||
}
|
||||
);
|
@ -1,94 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Handle for changing x/y position of a line's end point.
|
||||
* This is used to support drag handles for line elements
|
||||
* in a fixed position view. Field names for opposite ends
|
||||
* are provided to avoid zero-length lines.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the line element
|
||||
* @param {string} xProperty field which stores x position
|
||||
* @param {string} yProperty field which stores y position
|
||||
* @param {string} xOther field which stores x of other end
|
||||
* @param {string} yOther field which stores y of other end
|
||||
* @implements {platform/features/layout.ElementHandle}
|
||||
*/
|
||||
function LineHandle(element, elementProxy, xProperty, yProperty, xOther, yOther) {
|
||||
this.elementProxy = elementProxy;
|
||||
this.element = element;
|
||||
this.xProperty = xProperty;
|
||||
this.yProperty = yProperty;
|
||||
this.xOther = xOther;
|
||||
this.yOther = yOther;
|
||||
}
|
||||
|
||||
LineHandle.prototype.x = function (value) {
|
||||
var element = this.element,
|
||||
xProperty = this.xProperty,
|
||||
yProperty = this.yProperty,
|
||||
xOther = this.xOther,
|
||||
yOther = this.yOther;
|
||||
|
||||
if (arguments.length > 0) {
|
||||
// Ensure we stay in view
|
||||
value = Math.max(value, 0);
|
||||
// Make sure end points will still be different
|
||||
if (element[yOther] !== element[yProperty] ||
|
||||
element[xOther] !== value) {
|
||||
element[xProperty] = value;
|
||||
}
|
||||
}
|
||||
return element[xProperty];
|
||||
};
|
||||
|
||||
LineHandle.prototype.y = function (value) {
|
||||
var element = this.element,
|
||||
xProperty = this.xProperty,
|
||||
yProperty = this.yProperty,
|
||||
xOther = this.xOther,
|
||||
yOther = this.yOther;
|
||||
|
||||
if (arguments.length > 0) {
|
||||
// Ensure we stay in view
|
||||
value = Math.max(value, 0);
|
||||
// Make sure end points will still be different
|
||||
if (element[xOther] !== element[xProperty] ||
|
||||
element[yOther] !== value) {
|
||||
element[yProperty] = value;
|
||||
}
|
||||
}
|
||||
return element[yProperty];
|
||||
};
|
||||
|
||||
LineHandle.prototype.getGridSize = function () {
|
||||
return this.elementProxy.getGridSize();
|
||||
};
|
||||
|
||||
return LineHandle;
|
||||
|
||||
}
|
||||
);
|
@ -1,171 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./ElementProxy', './LineHandle', './AccessorMutator'],
|
||||
function (ElementProxy, LineHandle, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection/diplay proxy for line elements of a fixed position
|
||||
* view.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function LineProxy(element, index, elements, gridSize) {
|
||||
var proxy = new ElementProxy(element, index, elements, gridSize),
|
||||
handles = [
|
||||
new LineHandle(element, proxy, 'x', 'y', 'x2', 'y2'),
|
||||
new LineHandle(element, proxy, 'x2', 'y2', 'x', 'y')
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets style specific to line proxy.
|
||||
*/
|
||||
proxy.getStyle = function () {
|
||||
var layoutGridSize = proxy.getGridSize();
|
||||
|
||||
return {
|
||||
left: (layoutGridSize[0] * proxy.x()) + 'px',
|
||||
top: (layoutGridSize[1] * proxy.y()) + 'px',
|
||||
width: (layoutGridSize[0] * proxy.width()) + 'px',
|
||||
height: (layoutGridSize[1] * proxy.height()) + 'px'
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the top-left x coordinate, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the x coordinate
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.x = function (v) {
|
||||
var x = Math.min(element.x, element.x2),
|
||||
delta = Math.max(v, 0) - x;
|
||||
if (arguments.length > 0 && delta) {
|
||||
element.x += delta;
|
||||
element.x2 += delta;
|
||||
}
|
||||
return x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the top-left y coordinate, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the y coordinate
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.y = function (v) {
|
||||
var y = Math.min(element.y, element.y2),
|
||||
delta = Math.max(v, 0) - y;
|
||||
if (arguments.length > 0 && delta) {
|
||||
element.y += delta;
|
||||
element.y2 += delta;
|
||||
}
|
||||
return y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the width, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the width
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.width = function () {
|
||||
return Math.max(Math.abs(element.x - element.x2), 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the height, in grid space, of
|
||||
* this line's bounding box.
|
||||
* @returns {number} the height
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.height = function () {
|
||||
return Math.max(Math.abs(element.y - element.y2), 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the x position, in grid units relative to
|
||||
* the top-left corner, of the first point in this line
|
||||
* segment.
|
||||
* @returns {number} the x position of the first point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.x1 = function () {
|
||||
return element.x - proxy.x();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the y position, in grid units relative to
|
||||
* the top-left corner, of the first point in this line
|
||||
* segment.
|
||||
* @returns {number} the y position of the first point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.y1 = function () {
|
||||
return element.y - proxy.y();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the x position, in grid units relative to
|
||||
* the top-left corner, of the second point in this line
|
||||
* segment.
|
||||
* @returns {number} the x position of the second point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.x2 = function () {
|
||||
return element.x2 - proxy.x();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the y position, in grid units relative to
|
||||
* the top-left corner, of the second point in this line
|
||||
* segment.
|
||||
* @returns {number} the y position of the second point
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.y2 = function () {
|
||||
return element.y2 - proxy.y();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get element handles for changing the position of end
|
||||
* points of this line.
|
||||
* @returns {LineHandle[]} line handles for both end points
|
||||
* @memberof platform/features/layout.LineProxy#
|
||||
*/
|
||||
proxy.handles = function () {
|
||||
return handles;
|
||||
};
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return LineProxy;
|
||||
}
|
||||
);
|
@ -1,72 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* @interface platform/features/layout.ElementHandle
|
||||
* @private
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle for changing width/height properties of an element.
|
||||
* This is used to support drag handles for different
|
||||
* element types in a fixed position view.
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
*/
|
||||
function ResizeHandle(elementProxy, element) {
|
||||
this.elementProxy = elementProxy;
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
ResizeHandle.prototype.x = function (value) {
|
||||
var element = this.element;
|
||||
if (arguments.length > 0) {
|
||||
element.width = Math.max(
|
||||
this.elementProxy.getMinWidth(),
|
||||
value - element.x
|
||||
);
|
||||
}
|
||||
return element.x + element.width;
|
||||
};
|
||||
|
||||
ResizeHandle.prototype.y = function (value) {
|
||||
var element = this.element;
|
||||
if (arguments.length > 0) {
|
||||
element.height = Math.max(
|
||||
this.elementProxy.getMinHeight(),
|
||||
value - element.y
|
||||
);
|
||||
}
|
||||
return element.y + element.height;
|
||||
};
|
||||
|
||||
ResizeHandle.prototype.getGridSize = function () {
|
||||
return this.elementProxy.getGridSize();
|
||||
};
|
||||
|
||||
return ResizeHandle;
|
||||
|
||||
}
|
||||
);
|
@ -1,56 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./TextProxy'],
|
||||
function (TextProxy) {
|
||||
|
||||
/**
|
||||
* Selection proxy for telemetry elements in a fixed position view.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] form
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function TelemetryProxy(element, index, elements, gridSize) {
|
||||
var proxy = new TextProxy(element, index, elements, gridSize);
|
||||
|
||||
// Expose the domain object identifier
|
||||
proxy.id = element.id;
|
||||
|
||||
// Don't expose text configuration
|
||||
delete proxy.text;
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return TelemetryProxy;
|
||||
}
|
||||
);
|
@ -1,75 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./BoxProxy', './AccessorMutator'],
|
||||
function (BoxProxy, AccessorMutator) {
|
||||
|
||||
/**
|
||||
* Selection proxy for Text elements in a fixed position view.
|
||||
*
|
||||
* Note that arguments here are meant to match those expected
|
||||
* by `Array.prototype.map`
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param element the fixed position element, as stored in its
|
||||
* configuration
|
||||
* @param index the element's index within its array
|
||||
* @param {Array} elements the full array of elements
|
||||
* @param {number[]} gridSize the current layout grid size in [x,y] from
|
||||
* @augments {platform/features/layout.ElementProxy}
|
||||
*/
|
||||
function TextProxy(element, index, elements, gridSize) {
|
||||
var proxy = new BoxProxy(element, index, elements, gridSize);
|
||||
|
||||
/**
|
||||
* Get and/or set the text color of this element.
|
||||
* @param {string} [color] the new text color (if setting)
|
||||
* @returns {string} the text color
|
||||
* @memberof platform/features/layout.TextProxy#
|
||||
*/
|
||||
proxy.color = new AccessorMutator(element, 'color');
|
||||
|
||||
/**
|
||||
* Get and/or set the displayed text of this element.
|
||||
* @param {string} [text] the new text (if setting)
|
||||
* @returns {string} the text
|
||||
* @memberof platform/features/layout.TextProxy#
|
||||
*/
|
||||
proxy.text = new AccessorMutator(element, 'text');
|
||||
|
||||
/**
|
||||
* Get and/or set the text size of this element.
|
||||
*
|
||||
* @param {string} [size] the new text size (if setting)
|
||||
* @returns {string} the text size
|
||||
* @memberof platform/features/layout.TextProxy#
|
||||
*/
|
||||
proxy.size = new AccessorMutator(element, 'size');
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return TextProxy;
|
||||
}
|
||||
);
|
@ -1,92 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Variant of AccessorMutator to handle the specific case of updating
|
||||
* useGrid, in order update the positions appropriately from within
|
||||
* the scope of UnitAccessorMutator
|
||||
*
|
||||
* @memberof platform/features/layout
|
||||
* @constructor
|
||||
* @param {ElementProxy} proxy ElementProxy object to perform the update
|
||||
* upon
|
||||
*/
|
||||
function UnitAccessorMutator(elementProxy) {
|
||||
var self = this;
|
||||
|
||||
this.elementProxy = elementProxy;
|
||||
return function (useGrid) {
|
||||
var current = elementProxy.element.useGrid;
|
||||
if (arguments.length > 0) {
|
||||
elementProxy.element.useGrid = useGrid;
|
||||
if (useGrid && !current) {
|
||||
self.convertCoordsTo('grid');
|
||||
} else if (!useGrid && current) {
|
||||
self.convertCoordsTo('px');
|
||||
}
|
||||
}
|
||||
|
||||
return elementProxy.element.useGrid;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* For the elementProxy object called upon, convert its element's
|
||||
* coordinates and size from pixels to grid units, or vice-versa.
|
||||
* @param {string} unit When called with 'px', converts grid units to
|
||||
* pixels; when called with 'grid', snaps element
|
||||
* to grid units
|
||||
*/
|
||||
UnitAccessorMutator.prototype.convertCoordsTo = function (unit) {
|
||||
var proxy = this.elementProxy,
|
||||
gridSize = proxy.gridSize,
|
||||
element = proxy.element,
|
||||
minWidth = proxy.getMinWidth(),
|
||||
minHeight = proxy.getMinHeight();
|
||||
if (unit === 'px') {
|
||||
element.x = element.x * gridSize[0];
|
||||
element.y = element.y * gridSize[1];
|
||||
element.width = element.width * gridSize[0];
|
||||
element.height = element.height * gridSize[1];
|
||||
if (element.x2 && element.y2) {
|
||||
element.x2 = element.x2 * gridSize[0];
|
||||
element.y2 = element.y2 * gridSize[1];
|
||||
}
|
||||
} else if (unit === 'grid') {
|
||||
element.x = Math.round(element.x / gridSize[0]);
|
||||
element.y = Math.round(element.y / gridSize[1]);
|
||||
element.width = Math.max(Math.round(element.width / gridSize[0]), minWidth);
|
||||
element.height = Math.max(Math.round(element.height / gridSize[1]), minHeight);
|
||||
if (element.x2 && element.y2) {
|
||||
element.x2 = Math.round(element.x2 / gridSize[0]);
|
||||
element.y2 = Math.round(element.y2 / gridSize[1]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return UnitAccessorMutator;
|
||||
}
|
||||
);
|
@ -1,26 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div
|
||||
class="l-fixed-position-box"
|
||||
ng-style="{ background: ngModel.fill(), border: '1px ' + ngModel.stroke() + ' solid' }"
|
||||
>
|
||||
</div>
|
@ -1,26 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div
|
||||
ng-style="{ 'background-image': 'url(' + ngModel.element.url + ')', border: '1px solid ' + ngModel.stroke() }"
|
||||
class="l-fixed-position-image"
|
||||
>
|
||||
</div>
|
@ -1,31 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<svg ng-attr-width="{{ngModel.getGridSize()[0] * ngModel.width()}}"
|
||||
ng-attr-height="{{ngModel.getGridSize()[1] * ngModel.height()}}">
|
||||
<line ng-attr-x1="{{ngModel.getGridSize()[0] * ngModel.x1() + 1}}"
|
||||
ng-attr-y1="{{ngModel.getGridSize()[1] * ngModel.y1() + 1}}"
|
||||
ng-attr-x2="{{ngModel.getGridSize()[0] * ngModel.x2() + 1}}"
|
||||
ng-attr-y2="{{ngModel.getGridSize()[1] * ngModel.y2() + 1}}"
|
||||
ng-attr-stroke="{{ngModel.stroke()}}"
|
||||
stroke-width="2">
|
||||
</line>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,39 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div
|
||||
class="l-fixed-position-text l-telemetry"
|
||||
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color(), 'font-size': ngModel.size() }"
|
||||
>
|
||||
<span
|
||||
class="l-elem l-value l-obj-val-format"
|
||||
data-value="{{ngModel.value}}"
|
||||
ng-class="ngModel.cssClass"
|
||||
>
|
||||
{{ngModel.value}}
|
||||
</span>
|
||||
<span
|
||||
class="l-elem l-title"
|
||||
ng-show="ngModel.element.titled"
|
||||
>
|
||||
{{ngModel.name}}
|
||||
</span>
|
||||
</div>
|
@ -1,27 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div
|
||||
class="l-fixed-position-text l-static-text"
|
||||
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color(), 'font-size': ngModel.size() }"
|
||||
>
|
||||
{{ngModel.element.text}}
|
||||
</div>
|
@ -1,62 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="t-fixed-position l-fixed-position"
|
||||
ng-controller="FixedController as controller">
|
||||
|
||||
<!-- Background grid -->
|
||||
<div class="l-fixed-position__grid-holder l-grid-holder c-grid" ng-click="controller.bypassSelection($event)">
|
||||
<div class="c-grid__x l-grid l-grid-x"
|
||||
ng-if="!controller.getGridSize()[0] < 3"
|
||||
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
|
||||
<div class="c-grid__y l-grid l-grid-y"
|
||||
ng-if="!controller.getGridSize()[1] < 3"
|
||||
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
|
||||
</div>
|
||||
|
||||
<!-- Fixed position elements -->
|
||||
<div ng-repeat="element in controller.getElements()"
|
||||
class="l-fixed-position-item s-selectable s-moveable is-selectable is-moveable"
|
||||
ng-style="element.style"
|
||||
mct-selectable="controller.getContext(element)"
|
||||
mct-init-select="controller.shouldSelect(element)">
|
||||
<mct-include key="element.template"
|
||||
parameters="{ gridSize: controller.getGridSize() }"
|
||||
ng-model="element">
|
||||
</mct-include>
|
||||
</div>
|
||||
<!-- Selection highlight, handles -->
|
||||
<span class="c-frame-edit" ng-if="controller.isElementSelected()">
|
||||
<div class="c-frame-edit__move"
|
||||
mct-drag-down="controller.moveHandle().startDrag()"
|
||||
mct-drag="controller.moveHandle().continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()"
|
||||
ng-style="controller.getSelectedElementStyle()">
|
||||
</div>
|
||||
<div ng-repeat="handle in controller.handles()"
|
||||
class="c-frame-edit__handle c-frame-edit__handle--nwse"
|
||||
ng-style="handle.style()"
|
||||
mct-drag-down="handle.startDrag()"
|
||||
mct-drag="handle.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag(handle)">
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
@ -1,49 +0,0 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="frame frame-template t-frame-inner abs has-local-controls t-object-type-{{ domainObject.getModel().type }}">
|
||||
<div class="abs object-browse-bar l-flex-row">
|
||||
<div class="left flex-elem l-flex-row grows">
|
||||
<mct-representation
|
||||
key="'object-header-frame'"
|
||||
mct-object="domainObject"
|
||||
class="l-flex-row flex-elem object-header grows">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed h-local-controls local-controls-hidden">
|
||||
<mct-representation
|
||||
key="'switcher'"
|
||||
ng-model="representation"
|
||||
mct-object="domainObject">
|
||||
</mct-representation>
|
||||
<a class="s-button icon-expand t-btn-view-large"
|
||||
title="View large"
|
||||
mct-trigger-modal>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="abs object-holder">
|
||||
<mct-representation
|
||||
key="representation.selected.key"
|
||||
mct-object="representation.selected.key && domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
@ -1,641 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[
|
||||
"../src/FixedController",
|
||||
"zepto"
|
||||
],
|
||||
function (
|
||||
FixedController,
|
||||
$
|
||||
) {
|
||||
|
||||
describe("The Fixed Position controller", function () {
|
||||
var mockScope,
|
||||
mockQ,
|
||||
mockDialogService,
|
||||
mockFormatter,
|
||||
mockDomainObject,
|
||||
mockEvent,
|
||||
testGrid,
|
||||
testModel,
|
||||
testConfiguration,
|
||||
mockOpenMCT,
|
||||
mockTelemetryAPI,
|
||||
mockCompositionAPI,
|
||||
mockCompositionCollection,
|
||||
mockChildren,
|
||||
mockConductor,
|
||||
mockMetadata,
|
||||
mockTimeSystem,
|
||||
mockLimitEvaluator,
|
||||
mockSelection,
|
||||
mockObjects,
|
||||
mockNewDomainObject,
|
||||
unlistenFunc,
|
||||
$element = [],
|
||||
selectable = [],
|
||||
controller;
|
||||
|
||||
// Utility function; find a $on calls for a given expression.
|
||||
function findOn(expr) {
|
||||
var on;
|
||||
mockScope.$on.calls.all().forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
on = call.args[1];
|
||||
}
|
||||
});
|
||||
return on;
|
||||
}
|
||||
|
||||
function makeMockDomainObject(id) {
|
||||
return {
|
||||
identifier: {
|
||||
key: "domainObject-" + id,
|
||||
namespace: ""
|
||||
},
|
||||
name: "Point " + id
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
'$scope',
|
||||
["$on", "$watch", "$digest", "commit"]
|
||||
);
|
||||
mockQ = jasmine.createSpyObj('$q', ['when']);
|
||||
mockDialogService = jasmine.createSpyObj(
|
||||
'dialogService',
|
||||
['getUserInput']
|
||||
);
|
||||
mockFormatter = jasmine.createSpyObj(
|
||||
'telemetryFormatter',
|
||||
['format']
|
||||
);
|
||||
mockFormatter.format.and.callFake(function (valueMetadata) {
|
||||
return "Formatted " + valueMetadata.value;
|
||||
});
|
||||
|
||||
mockConductor = jasmine.createSpyObj('conductor', [
|
||||
'on',
|
||||
'off',
|
||||
'bounds',
|
||||
'timeSystem',
|
||||
'clock'
|
||||
]);
|
||||
mockConductor.bounds.and.returnValue({});
|
||||
mockTimeSystem = {
|
||||
metadata: {
|
||||
key: 'key'
|
||||
}
|
||||
};
|
||||
mockConductor.timeSystem.and.returnValue(mockTimeSystem);
|
||||
|
||||
mockEvent = jasmine.createSpyObj(
|
||||
'event',
|
||||
['preventDefault']
|
||||
);
|
||||
|
||||
mockTelemetryAPI = jasmine.createSpyObj('telemetry',
|
||||
[
|
||||
'subscribe',
|
||||
'request',
|
||||
'isTelemetryObject',
|
||||
'getMetadata',
|
||||
'limitEvaluator',
|
||||
'getValueFormatter'
|
||||
]
|
||||
);
|
||||
mockTelemetryAPI.isTelemetryObject.and.returnValue(true);
|
||||
mockTelemetryAPI.request.and.returnValue(Promise.resolve([]));
|
||||
|
||||
testGrid = [123, 456];
|
||||
testModel = {
|
||||
composition: ['a', 'b', 'c'],
|
||||
layoutGrid: testGrid
|
||||
};
|
||||
testConfiguration = { elements: [
|
||||
{ type: "fixed.telemetry", id: 'a', x: 1, y: 1, useGrid: true},
|
||||
{ type: "fixed.telemetry", id: 'b', x: 1, y: 1, useGrid: true},
|
||||
{ type: "fixed.telemetry", id: 'c', x: 1, y: 1, useGrid: true}
|
||||
]};
|
||||
|
||||
mockChildren = testModel.composition.map(makeMockDomainObject);
|
||||
mockCompositionCollection = jasmine.createSpyObj('compositionCollection', [
|
||||
'load',
|
||||
'on',
|
||||
'off'
|
||||
]);
|
||||
mockCompositionAPI = jasmine.createSpyObj('composition', [
|
||||
'get'
|
||||
]);
|
||||
mockCompositionAPI.get.and.returnValue(mockCompositionCollection);
|
||||
mockCompositionCollection.load.and.returnValue(
|
||||
Promise.resolve(mockChildren)
|
||||
);
|
||||
|
||||
mockScope.model = testModel;
|
||||
mockScope.configuration = testConfiguration;
|
||||
|
||||
mockNewDomainObject = jasmine.createSpyObj("newDomainObject", [
|
||||
'layoutGrid',
|
||||
'configuration',
|
||||
'composition'
|
||||
]);
|
||||
mockNewDomainObject.layoutGrid = testGrid;
|
||||
mockNewDomainObject.configuration = {
|
||||
'fixed-display': testConfiguration
|
||||
};
|
||||
mockNewDomainObject.composition = ['a', 'b', 'c'];
|
||||
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
['getId', 'getModel', 'getCapability', 'useCapability']
|
||||
);
|
||||
mockDomainObject.useCapability.and.returnValue(mockNewDomainObject);
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
|
||||
selectable[0] = {
|
||||
context: {
|
||||
oldItem: mockDomainObject
|
||||
}
|
||||
};
|
||||
mockSelection = jasmine.createSpyObj("selection", [
|
||||
'select',
|
||||
'on',
|
||||
'off',
|
||||
'get'
|
||||
]);
|
||||
mockSelection.get.and.returnValue([]);
|
||||
|
||||
unlistenFunc = jasmine.createSpy("unlisten");
|
||||
mockObjects = jasmine.createSpyObj('objects', [
|
||||
'observe',
|
||||
'get'
|
||||
]);
|
||||
mockObjects.observe.and.returnValue(unlistenFunc);
|
||||
|
||||
mockOpenMCT = {
|
||||
time: mockConductor,
|
||||
telemetry: mockTelemetryAPI,
|
||||
composition: mockCompositionAPI,
|
||||
selection: mockSelection,
|
||||
objects: mockObjects
|
||||
};
|
||||
|
||||
$element = $('<div></div>');
|
||||
spyOn($element[0], 'click');
|
||||
|
||||
mockMetadata = jasmine.createSpyObj('mockMetadata', [
|
||||
'valuesForHints',
|
||||
'value',
|
||||
'values'
|
||||
]);
|
||||
mockMetadata.value.and.returnValue({
|
||||
key: 'value'
|
||||
});
|
||||
|
||||
mockMetadata.valuesForHints.and.callFake(function (hints) {
|
||||
if (hints === ['domain']) {
|
||||
return [{
|
||||
key: 'time'
|
||||
}];
|
||||
} else {
|
||||
return [{
|
||||
key: 'value'
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
mockLimitEvaluator = jasmine.createSpyObj('limitEvaluator', [
|
||||
'evaluate'
|
||||
]);
|
||||
|
||||
mockLimitEvaluator.evaluate.and.returnValue({});
|
||||
|
||||
mockTelemetryAPI.getMetadata.and.returnValue(mockMetadata);
|
||||
mockTelemetryAPI.limitEvaluator.and.returnValue(mockLimitEvaluator);
|
||||
mockTelemetryAPI.getValueFormatter.and.returnValue(mockFormatter);
|
||||
|
||||
controller = new FixedController(
|
||||
mockScope,
|
||||
mockQ,
|
||||
mockDialogService,
|
||||
mockOpenMCT,
|
||||
$element
|
||||
);
|
||||
spyOn(controller, "mutate");
|
||||
});
|
||||
|
||||
it("subscribes a domain object", function () {
|
||||
var object = makeMockDomainObject("mock");
|
||||
|
||||
return controller.getTelemetry(object).then(function () {
|
||||
expect(mockTelemetryAPI.subscribe).toHaveBeenCalledWith(
|
||||
object,
|
||||
jasmine.any(Function),
|
||||
jasmine.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("releases subscription when a domain objects is removed", function () {
|
||||
var unsubscribe = jasmine.createSpy('unsubscribe');
|
||||
var unsubscribePromise = new Promise(function (resolve) {
|
||||
unsubscribe.and.callFake(resolve);
|
||||
});
|
||||
var object = makeMockDomainObject("mock");
|
||||
|
||||
mockTelemetryAPI.subscribe.and.returnValue(unsubscribe);
|
||||
return controller.getTelemetry(object).then(function () {
|
||||
controller.onCompositionRemove(object.identifier);
|
||||
return unsubscribePromise;
|
||||
}).then(function () {
|
||||
expect(unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes visible elements based on configuration", function () {
|
||||
var elements = controller.getElements();
|
||||
|
||||
expect(elements.length).toEqual(3);
|
||||
expect(elements[0].id).toEqual('a');
|
||||
expect(elements[1].id).toEqual('b');
|
||||
expect(elements[2].id).toEqual('c');
|
||||
});
|
||||
|
||||
it("allows elements to be selected", function () {
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
expect(controller.isElementSelected()).toBe(true);
|
||||
});
|
||||
|
||||
it("allows selection retrieval", function () {
|
||||
var elements = controller.getElements();
|
||||
selectable[0].context.elementProxy = elements[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
expect(controller.getSelectedElement()).toEqual(elements[1]);
|
||||
});
|
||||
|
||||
it("selects the parent view when selected element is removed", function () {
|
||||
var elements = controller.getElements();
|
||||
selectable[0].context.elementProxy = elements[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
controller.remove(elements[1]);
|
||||
|
||||
expect($element[0].click).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("retains selections during refresh", function () {
|
||||
// Get elements; remove one of them; trigger refresh.
|
||||
// Same element (at least by index) should still be selected.
|
||||
var elements = controller.getElements();
|
||||
selectable[0].context.elementProxy = elements[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
expect(controller.getSelectedElement()).toEqual(elements[1]);
|
||||
|
||||
controller.remove(elements[2]);
|
||||
elements = controller.getElements();
|
||||
|
||||
// Verify removal, as test assumes this
|
||||
expect(elements.length).toEqual(2);
|
||||
|
||||
expect(controller.shouldSelect(elements[1])).toBe(true);
|
||||
});
|
||||
|
||||
it("Displays received values for telemetry elements", function () {
|
||||
var elements;
|
||||
var mockTelemetry = {
|
||||
time: 100,
|
||||
value: 200
|
||||
};
|
||||
var testElement = {};
|
||||
var telemetryObject = {
|
||||
identifier: {
|
||||
key: '12345'
|
||||
}
|
||||
};
|
||||
mockConductor.clock.and.returnValue({});
|
||||
controller.elementProxiesById = {};
|
||||
controller.elementProxiesById['12345'] = [testElement];
|
||||
controller.elementProxies = [testElement];
|
||||
|
||||
controller.subscribeToObject(telemetryObject);
|
||||
mockTelemetryAPI.subscribe.calls.mostRecent().args[1](mockTelemetry);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
mockScope.$digest.and.callFake(resolve);
|
||||
}).then(function () {
|
||||
// Get elements that controller is now exposing
|
||||
elements = controller.getElements();
|
||||
|
||||
// Formatted values should be available
|
||||
expect(elements[0].value).toEqual("Formatted 200");
|
||||
});
|
||||
});
|
||||
|
||||
it("updates elements styles when grid size changes", function () {
|
||||
// Grid size is initially set to testGrid which is [123, 456]
|
||||
var originalLeft = controller.getElements()[0].style.left;
|
||||
|
||||
// Change the grid size
|
||||
controller.updateElementPositions([20, 20]);
|
||||
|
||||
expect(controller.getElements()[0].style.left).not.toEqual(originalLeft);
|
||||
});
|
||||
|
||||
it("listens for drop events", function () {
|
||||
mockScope.domainObject = mockDomainObject;
|
||||
mockScope.model = testModel;
|
||||
|
||||
// Layout should position panels according to
|
||||
// where the user dropped them, so it needs to
|
||||
// listen for drop events.
|
||||
expect(mockScope.$on).toHaveBeenCalledWith(
|
||||
'mctDrop',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
// Verify precondition
|
||||
expect(testConfiguration.elements.length).toEqual(3);
|
||||
|
||||
// Notify that a drop occurred
|
||||
testModel.composition.push('d');
|
||||
|
||||
mockObjects.get.and.returnValue(Promise.resolve([]));
|
||||
|
||||
findOn('mctDrop')(
|
||||
mockEvent,
|
||||
'd',
|
||||
{ x: 300, y: 100 }
|
||||
);
|
||||
|
||||
// Should have added an element
|
||||
expect(testConfiguration.elements.length).toEqual(4);
|
||||
|
||||
// ...and prevented default...
|
||||
expect(mockEvent.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("ignores drops when default has been prevented", function () {
|
||||
// Avoids redundant drop-handling, WTD-1233
|
||||
mockEvent.defaultPrevented = true;
|
||||
|
||||
// Notify that a drop occurred
|
||||
testModel.composition.push('d');
|
||||
findOn('mctDrop')(
|
||||
mockEvent,
|
||||
'd',
|
||||
{ x: 300, y: 100 }
|
||||
);
|
||||
|
||||
// Should NOT have added an element
|
||||
expect(testConfiguration.elements.length).toEqual(3);
|
||||
});
|
||||
|
||||
it("unsubscribes when destroyed", function () {
|
||||
var unsubscribe = jasmine.createSpy('unsubscribe');
|
||||
var object = makeMockDomainObject("mock");
|
||||
|
||||
mockTelemetryAPI.subscribe.and.returnValue(unsubscribe);
|
||||
|
||||
return controller.getTelemetry(object).then(function () {
|
||||
expect(unsubscribe).not.toHaveBeenCalled();
|
||||
// Destroy the scope
|
||||
findOn('$destroy')();
|
||||
|
||||
expect(unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes its grid size", function () {
|
||||
expect(controller.getGridSize()).toEqual(testGrid);
|
||||
});
|
||||
|
||||
it("exposes drag handles", function () {
|
||||
var handles;
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
// Should have a non-empty array of handles
|
||||
handles = controller.handles();
|
||||
|
||||
expect(handles).toEqual(jasmine.any(Array));
|
||||
expect(handles.length).not.toEqual(0);
|
||||
|
||||
// And they should have start/continue/end drag methods
|
||||
handles.forEach(function (handle) {
|
||||
expect(handle.startDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.continueDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.endDrag).toEqual(jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes a move handle", function () {
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
// Should have a move handle
|
||||
var handle = controller.moveHandle();
|
||||
|
||||
// And it should have start/continue/end drag methods
|
||||
expect(handle.startDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.continueDrag).toEqual(jasmine.any(Function));
|
||||
expect(handle.endDrag).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("updates selection style during drag", function () {
|
||||
var oldStyle;
|
||||
selectable[0].context.elementProxy = controller.getElements()[1];
|
||||
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
|
||||
|
||||
// Get style
|
||||
oldStyle = controller.getSelectedElementStyle();
|
||||
|
||||
// Start a drag gesture
|
||||
controller.moveHandle().startDrag();
|
||||
|
||||
// Haven't moved yet; style shouldn't have updated yet
|
||||
expect(controller.getSelectedElementStyle()).toEqual(oldStyle);
|
||||
|
||||
// Drag a little
|
||||
controller.moveHandle().continueDrag([1000, 100]);
|
||||
|
||||
// Style should have been updated
|
||||
expect(controller.getSelectedElementStyle()).not.toEqual(oldStyle);
|
||||
});
|
||||
|
||||
it("cleans up selection on scope destroy", function () {
|
||||
expect(mockScope.$on).toHaveBeenCalledWith(
|
||||
'$destroy',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
mockScope.$on.calls.mostRecent().args[1]();
|
||||
|
||||
expect(mockOpenMCT.selection.off).toHaveBeenCalledWith(
|
||||
'change',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
describe("on display bounds changes", function () {
|
||||
var testBounds;
|
||||
var boundsChangeCallback;
|
||||
var objectOne;
|
||||
var objectTwo;
|
||||
|
||||
beforeEach(function () {
|
||||
testBounds = { start: 123, end: 321 };
|
||||
boundsChangeCallback = mockConductor.on.calls.mostRecent().args[1];
|
||||
objectOne = {};
|
||||
objectTwo = {};
|
||||
controller.telemetryObjects = [
|
||||
objectOne,
|
||||
objectTwo
|
||||
];
|
||||
spyOn(controller, "fetchHistoricalData");
|
||||
controller.fetchHistoricalData.and.callThrough();
|
||||
});
|
||||
|
||||
it("registers a bounds change listener", function () {
|
||||
expect(mockConductor.on).toHaveBeenCalledWith("bounds", jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("requests only a single point", function () {
|
||||
mockConductor.clock.and.returnValue(undefined);
|
||||
boundsChangeCallback(testBounds);
|
||||
expect(mockTelemetryAPI.request.calls.count()).toBe(2);
|
||||
|
||||
mockTelemetryAPI.request.calls.all().forEach(function (call) {
|
||||
expect(call.args[1].size).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("Does not fetch historical data on tick", function () {
|
||||
boundsChangeCallback(testBounds, true);
|
||||
expect(mockTelemetryAPI.request.calls.count()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("on receipt of telemetry", function () {
|
||||
var mockTelemetryObject;
|
||||
var testValue;
|
||||
var testElement;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTelemetryObject = {
|
||||
identifier: {
|
||||
key: '12345'
|
||||
}
|
||||
};
|
||||
testValue = 30;
|
||||
testElement = {};
|
||||
|
||||
controller.elementProxiesById = {};
|
||||
controller.elementProxiesById['12345'] = [testElement];
|
||||
controller.elementProxies = [testElement];
|
||||
});
|
||||
|
||||
it("updates displayed values from historical telemetry", function () {
|
||||
spyOn(controller, "updateView");
|
||||
controller.updateView.and.callThrough();
|
||||
|
||||
mockTelemetryAPI.request.and.returnValue(Promise.resolve([{
|
||||
time: 100,
|
||||
value: testValue
|
||||
}]));
|
||||
|
||||
controller.fetchHistoricalData(mockTelemetryObject);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
mockScope.$digest.and.callFake(resolve);
|
||||
}).then(function () {
|
||||
expect(controller.updateView).toHaveBeenCalled();
|
||||
expect(controller.getElements()[0].value)
|
||||
.toEqual("Formatted " + testValue);
|
||||
});
|
||||
});
|
||||
|
||||
it("selects an range value to display, if available", function () {
|
||||
mockMetadata.valuesForHints.and.returnValue([
|
||||
{
|
||||
key: 'range',
|
||||
source: 'range'
|
||||
}
|
||||
]);
|
||||
var key = controller.chooseValueMetadataToDisplay(mockMetadata).source;
|
||||
expect(key).toEqual('range');
|
||||
});
|
||||
|
||||
it("selects the first non-domain value to display, if no range available", function () {
|
||||
mockMetadata.valuesForHints.and.returnValue([]);
|
||||
mockMetadata.values.and.returnValue([
|
||||
{
|
||||
key: 'domain',
|
||||
source: 'domain',
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'image',
|
||||
source: 'image',
|
||||
hints: {
|
||||
image: 1
|
||||
}
|
||||
}
|
||||
]);
|
||||
var key = controller.chooseValueMetadataToDisplay(mockMetadata).source;
|
||||
expect(key).toEqual('image');
|
||||
});
|
||||
|
||||
it("reflects limit status", function () {
|
||||
mockLimitEvaluator.evaluate.and.returnValue({cssClass: "alarm-a"});
|
||||
controller.updateView(mockTelemetryObject, [{
|
||||
time: 100,
|
||||
value: testValue
|
||||
}]);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
mockScope.$digest.and.callFake(resolve);
|
||||
}).then(function () {
|
||||
// Limit-based CSS classes should be available
|
||||
expect(controller.getElements()[0].cssClass).toEqual("alarm-a");
|
||||
});
|
||||
});
|
||||
|
||||
it("listens for selection change events", function () {
|
||||
expect(mockOpenMCT.selection.on).toHaveBeenCalledWith(
|
||||
'change',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,92 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../src/FixedDragHandle'],
|
||||
function (FixedDragHandle) {
|
||||
|
||||
var TEST_GRID_SIZE = [13, 33];
|
||||
|
||||
describe("A fixed position drag handle", function () {
|
||||
var mockElementHandle,
|
||||
mockConfigPath,
|
||||
mockFixedControl,
|
||||
handle;
|
||||
|
||||
beforeEach(function () {
|
||||
mockElementHandle = jasmine.createSpyObj(
|
||||
'elementHandle',
|
||||
['x', 'y','getGridSize']
|
||||
);
|
||||
mockElementHandle.x.and.returnValue(6);
|
||||
mockElementHandle.y.and.returnValue(8);
|
||||
mockElementHandle.getGridSize.and.returnValue(TEST_GRID_SIZE);
|
||||
|
||||
mockFixedControl = jasmine.createSpyObj(
|
||||
'fixedControl',
|
||||
['updateSelectionStyle', 'mutate']
|
||||
);
|
||||
mockFixedControl.updateSelectionStyle.and.returnValue();
|
||||
mockFixedControl.mutate.and.returnValue();
|
||||
|
||||
mockConfigPath = jasmine.createSpy('configPath');
|
||||
|
||||
handle = new FixedDragHandle(
|
||||
mockElementHandle,
|
||||
mockConfigPath,
|
||||
mockFixedControl
|
||||
);
|
||||
});
|
||||
|
||||
it("provides a style for positioning", function () {
|
||||
var style = handle.style();
|
||||
// 6 grid coords * 13 pixels - 3 pixels for centering
|
||||
expect(style.left).toEqual('75px');
|
||||
// 8 grid coords * 33 pixels - 3 pixels for centering
|
||||
expect(style.top).toEqual('261px');
|
||||
});
|
||||
|
||||
it("allows handles to be dragged", function () {
|
||||
handle.startDrag();
|
||||
handle.continueDrag([16, 8]);
|
||||
|
||||
// Should update x/y, snapped to grid
|
||||
expect(mockElementHandle.x).toHaveBeenCalledWith(7);
|
||||
expect(mockElementHandle.y).toHaveBeenCalledWith(8);
|
||||
|
||||
handle.continueDrag([-16, -35]);
|
||||
|
||||
// Should have interpreted relative to initial state
|
||||
expect(mockElementHandle.x).toHaveBeenCalledWith(5);
|
||||
expect(mockElementHandle.y).toHaveBeenCalledWith(7);
|
||||
|
||||
// Should have called updateSelectionStyle once per continueDrag
|
||||
expect(mockFixedControl.updateSelectionStyle.calls.count()).toEqual(2);
|
||||
|
||||
// Finally, ending drag should mutate
|
||||
handle.endDrag();
|
||||
expect(mockFixedControl.mutate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,71 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../src/FixedProxy'],
|
||||
function (FixedProxy) {
|
||||
|
||||
describe("Fixed Position view's selection proxy", function () {
|
||||
var mockCallback,
|
||||
mockQ,
|
||||
mockDialogService,
|
||||
mockPromise,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
mockCallback = jasmine.createSpy('callback');
|
||||
mockQ = jasmine.createSpyObj('$q', ['when']);
|
||||
mockDialogService = jasmine.createSpyObj('dialogService', ['getUserInput']);
|
||||
mockPromise = jasmine.createSpyObj('promise', ['then']);
|
||||
|
||||
mockQ.when.and.returnValue(mockPromise);
|
||||
|
||||
proxy = new FixedProxy(mockCallback, mockQ, mockDialogService);
|
||||
});
|
||||
|
||||
it("handles promised element creation", function () {
|
||||
// The element factory may return promises (e.g. if
|
||||
// user input is required) so make sure proxy is wrapping these
|
||||
proxy.add("fixed.box");
|
||||
expect(mockQ.when).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("notifies its callback when an element is created", function () {
|
||||
proxy.add("fixed.box");
|
||||
// Callback should not have been invoked yet
|
||||
expect(mockCallback).not.toHaveBeenCalled();
|
||||
// Resolve the promise
|
||||
mockPromise.then.calls.mostRecent().args[0]({});
|
||||
// Should have fired the callback
|
||||
expect(mockCallback).toHaveBeenCalledWith({
|
||||
type: "fixed.box",
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1,
|
||||
height: 1,
|
||||
useGrid: true
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,81 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["../src/LayoutDrag"],
|
||||
function (LayoutDrag) {
|
||||
|
||||
describe("A Layout drag handler", function () {
|
||||
var testPosition = {
|
||||
position: [8, 11],
|
||||
dimensions: [3, 2]
|
||||
};
|
||||
|
||||
it("changes position by a supplied factor, rounding by grid size", function () {
|
||||
var handler = new LayoutDrag(
|
||||
testPosition,
|
||||
[1, 1],
|
||||
[0, 0],
|
||||
[10, 20]
|
||||
);
|
||||
|
||||
expect(handler.getAdjustedPosition([37, 84])).toEqual({
|
||||
position: [12, 15],
|
||||
dimensions: [3, 2]
|
||||
});
|
||||
expect(handler.getAdjustedPosition([-37, 84])).toEqual({
|
||||
position: [4, 15],
|
||||
dimensions: [3, 2]
|
||||
});
|
||||
});
|
||||
|
||||
it("changes dimensions by a supplied factor, rounding by grid size", function () {
|
||||
var handler = new LayoutDrag(
|
||||
testPosition,
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
[10, 20]
|
||||
);
|
||||
|
||||
expect(handler.getAdjustedPosition([37, 84])).toEqual({
|
||||
position: [8, 11],
|
||||
dimensions: [7, 6]
|
||||
});
|
||||
});
|
||||
|
||||
it("allows mixing dimension and position factors", function () {
|
||||
var handler = new LayoutDrag(
|
||||
testPosition,
|
||||
[0, 1],
|
||||
[-1, 0],
|
||||
[10, 20]
|
||||
);
|
||||
|
||||
expect(handler.getAdjustedPosition([11, 84])).toEqual({
|
||||
position: [8, 15],
|
||||
dimensions: [2, 2]
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,128 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../src/MCTTriggerModal'
|
||||
], function (
|
||||
MCTTriggerModal
|
||||
) {
|
||||
describe('MCTTriggerModal', function () {
|
||||
var $scope,
|
||||
$element,
|
||||
frame,
|
||||
layoutContainer,
|
||||
$document,
|
||||
mctTriggerModal;
|
||||
|
||||
function makeElement(classes, parentEl) {
|
||||
var elem = jasmine.createSpyObj('element.' + classes.join('.'), [
|
||||
'hasClass',
|
||||
'parent'
|
||||
]);
|
||||
elem.hasClass.and.callFake(function (className) {
|
||||
return classes.indexOf(className) !== -1;
|
||||
});
|
||||
elem.parent.and.returnValue(parentEl);
|
||||
var div = document.createElement('div');
|
||||
div.className = classes.join(' ');
|
||||
parentEl[0].appendChild(div);
|
||||
elem[0] = div;
|
||||
return elem;
|
||||
}
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
$scope = jasmine.createSpyObj('$scope', ['$on']);
|
||||
$scope.domainObject = { getCapability: function () {
|
||||
return { getActions: function () {
|
||||
return [];
|
||||
}};
|
||||
}};
|
||||
|
||||
$element = jasmine.createSpyObj('$element', [
|
||||
'parent',
|
||||
'remove',
|
||||
'on',
|
||||
'off'
|
||||
]);
|
||||
layoutContainer = document.createElement('div');
|
||||
frame = makeElement(['frame'], [layoutContainer]);
|
||||
var child = makeElement([], frame);
|
||||
for (var i = 0; i < 5; i++) {
|
||||
child = makeElement([], child);
|
||||
}
|
||||
$element.parent.and.returnValue(child);
|
||||
$document = [jasmine.createSpyObj('document', ['createElement'])];
|
||||
$document[0].body = document.createElement('div');
|
||||
$document[0].createElement.and.callFake(function (tag) {
|
||||
return document.createElement(tag);
|
||||
});
|
||||
|
||||
mctTriggerModal = new MCTTriggerModal($document);
|
||||
});
|
||||
|
||||
it('is a directive definition', function () {
|
||||
expect(mctTriggerModal.restrict).toBe('A');
|
||||
expect(mctTriggerModal.link).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
describe('link', function () {
|
||||
beforeEach(function () {
|
||||
mctTriggerModal.link($scope, $element);
|
||||
});
|
||||
|
||||
it('attaches handlers to $element', function () {
|
||||
expect($element.on).toHaveBeenCalledWith(
|
||||
'click',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('cleans up on $scope $destroy', function () {
|
||||
expect($scope.$on).toHaveBeenCalledWith(
|
||||
'$destroy',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
$scope.$on.calls.mostRecent().args[1]();
|
||||
expect($element.off).toHaveBeenCalledWith(
|
||||
'click',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('opens and closes overlays', function () {
|
||||
[
|
||||
'a.close', 'a.t-done', '.abs.blocker'
|
||||
].forEach(function (selector) {
|
||||
$element.on.calls.mostRecent().args[1]();
|
||||
var container = $document[0].body.querySelector('.t-contents');
|
||||
expect(container.children[0]).toBe(frame[0]);
|
||||
expect(layoutContainer.children[0]).not.toBe(frame[0]);
|
||||
$document[0].body.querySelector(selector)
|
||||
.dispatchEvent(new Event('click'));
|
||||
expect(container.children[0]).not.toBe(frame[0]);
|
||||
expect(layoutContainer.children[0]).toBe(frame[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,50 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/AccessorMutator'],
|
||||
function (AccessorMutator) {
|
||||
|
||||
describe("An accessor-mutator", function () {
|
||||
var testObject,
|
||||
am;
|
||||
|
||||
beforeEach(function () {
|
||||
testObject = { t: 42, other: 100 };
|
||||
am = new AccessorMutator(testObject, 't');
|
||||
});
|
||||
|
||||
it("allows access to a property", function () {
|
||||
expect(am()).toEqual(42);
|
||||
});
|
||||
|
||||
it("allows mutation of a property", function () {
|
||||
expect(am("some other value")).toEqual("some other value");
|
||||
expect(testObject).toEqual({
|
||||
t: "some other value",
|
||||
other: 100
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,55 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/BoxProxy'],
|
||||
function (BoxProxy) {
|
||||
|
||||
describe("A fixed position box proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
width: 42,
|
||||
height: 24,
|
||||
fill: "transparent"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new BoxProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("provides getter/setter for fill color", function () {
|
||||
expect(proxy.fill()).toEqual('transparent');
|
||||
expect(proxy.fill('#FFF')).toEqual('#FFF');
|
||||
expect(proxy.fill()).toEqual('#FFF');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,69 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ElementFactory'],
|
||||
function (ElementFactory) {
|
||||
|
||||
var DIALOG_ELEMENTS = ['image', 'text'],
|
||||
NON_DIALOG_ELEMENTS = ['box', 'line'];
|
||||
|
||||
describe("The fixed position element factory", function () {
|
||||
var mockDialogService,
|
||||
mockPromise,
|
||||
factory;
|
||||
|
||||
beforeEach(function () {
|
||||
mockDialogService = jasmine.createSpyObj(
|
||||
'dialogService',
|
||||
['getUserInput']
|
||||
);
|
||||
mockPromise = jasmine.createSpyObj(
|
||||
'promise',
|
||||
['then']
|
||||
);
|
||||
|
||||
mockDialogService.getUserInput.and.returnValue(mockPromise);
|
||||
mockPromise.then.and.returnValue(mockPromise);
|
||||
|
||||
factory = new ElementFactory(mockDialogService);
|
||||
});
|
||||
|
||||
DIALOG_ELEMENTS.forEach(function (type) {
|
||||
it("shows a dialog for " + type + " elements", function () {
|
||||
expect(factory.createElement('fixed.' + type))
|
||||
.toEqual(mockPromise);
|
||||
expect(mockDialogService.getUserInput).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
NON_DIALOG_ELEMENTS.forEach(function (type) {
|
||||
it("immediately provides " + type + " elements", function () {
|
||||
var result = factory.createElement('fixed.' + type);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).not.toEqual(mockPromise);
|
||||
expect(mockDialogService.getUserInput).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,51 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ElementProxies'],
|
||||
function (ElementProxies) {
|
||||
|
||||
// Expect these element types to have proxies
|
||||
var ELEMENT_TYPES = [
|
||||
"fixed.telemetry",
|
||||
"fixed.line",
|
||||
"fixed.box",
|
||||
"fixed.text",
|
||||
"fixed.image"
|
||||
];
|
||||
|
||||
// Verify that the set of proxies exposed matches the specific
|
||||
// list above.
|
||||
describe("The set of element proxies", function () {
|
||||
ELEMENT_TYPES.forEach(function (t) {
|
||||
it("exposes a proxy wrapper for " + t + " elements", function () {
|
||||
expect(typeof ElementProxies[t]).toEqual('function');
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes no additional wrappers", function () {
|
||||
expect(Object.keys(ElementProxies).length)
|
||||
.toEqual(ELEMENT_TYPES.length);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,98 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ElementProxy'],
|
||||
function (ElementProxy) {
|
||||
|
||||
describe("A fixed position element proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
stroke: '#717171',
|
||||
width: 42,
|
||||
height: 24,
|
||||
useGrid: true
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new ElementProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements,
|
||||
[13,21]
|
||||
);
|
||||
});
|
||||
|
||||
it("exposes element properties", function () {
|
||||
Object.keys(testElement).forEach(function (k) {
|
||||
expect(proxy[k]()).toEqual(testElement[k]);
|
||||
});
|
||||
});
|
||||
|
||||
it("allows order to be changed", function () {
|
||||
proxy.order("down");
|
||||
expect(testElements).toEqual([{}, testElement, {}, {}]);
|
||||
proxy.order("up");
|
||||
expect(testElements).toEqual([{}, {}, testElement, {}]);
|
||||
proxy.order("bottom");
|
||||
expect(testElements).toEqual([testElement, {}, {}, {}]);
|
||||
proxy.order("top");
|
||||
expect(testElements).toEqual([{}, {}, {}, testElement]);
|
||||
});
|
||||
|
||||
it("ensures x/y values are non-negative", function () {
|
||||
proxy.x(-1);
|
||||
proxy.y(-400);
|
||||
expect(proxy.x()).toEqual(0);
|
||||
expect(proxy.y()).toEqual(0);
|
||||
});
|
||||
|
||||
it("allows modifying the current grid size", function () {
|
||||
proxy.setGridSize([112,420]);
|
||||
expect(proxy.gridSize).toEqual([112,420]);
|
||||
});
|
||||
|
||||
it("returns the current grid size only if the element snaps to grid", function () {
|
||||
expect(proxy.getGridSize()).toEqual([13,21]);
|
||||
proxy.useGrid(false);
|
||||
expect(proxy.getGridSize()).toEqual([1,1]);
|
||||
});
|
||||
|
||||
it("returns the mininum height and width of an element currently used units", function () {
|
||||
// Assumes mininum height and width are 10, in pixels
|
||||
expect(proxy.getMinWidth()).toEqual(1);
|
||||
expect(proxy.getMinHeight()).toEqual(1);
|
||||
proxy.setGridSize([7,4]);
|
||||
expect(proxy.getMinWidth()).toEqual(2);
|
||||
expect(proxy.getMinHeight()).toEqual(3);
|
||||
proxy.useGrid(false);
|
||||
expect(proxy.getMinWidth()).toEqual(10);
|
||||
expect(proxy.getMinHeight()).toEqual(10);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,56 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ImageProxy'],
|
||||
function (ImageProxy) {
|
||||
|
||||
describe("A fixed position image proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
width: 42,
|
||||
height: 24,
|
||||
url: "http://www.nasa.gov"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new ImageProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("provides getter/setter for image URL", function () {
|
||||
expect(proxy.url()).toEqual("http://www.nasa.gov");
|
||||
expect(proxy.url("http://www.nasa.gov/some.jpg"))
|
||||
.toEqual("http://www.nasa.gov/some.jpg");
|
||||
expect(proxy.url()).toEqual("http://www.nasa.gov/some.jpg");
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,81 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/LineHandle'],
|
||||
function (LineHandle) {
|
||||
|
||||
describe("A fixed position drag handle", function () {
|
||||
var testElement,
|
||||
mockElementProxy,
|
||||
handle,
|
||||
TEST_GRID_SIZE = [45, 21];
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 3,
|
||||
y: 42,
|
||||
x2: 8,
|
||||
y2: 11,
|
||||
useGrid: true
|
||||
};
|
||||
mockElementProxy = jasmine.createSpyObj('elementProxy', ['getGridSize']);
|
||||
mockElementProxy.getGridSize.and.returnValue(TEST_GRID_SIZE);
|
||||
|
||||
handle = new LineHandle(testElement, mockElementProxy, 'x', 'y', 'x2', 'y2');
|
||||
});
|
||||
|
||||
it("provides x/y grid coordinates for its corner", function () {
|
||||
expect(handle.x()).toEqual(3);
|
||||
expect(handle.y()).toEqual(42);
|
||||
});
|
||||
|
||||
it("changes x and y positions", function () {
|
||||
handle.x(30);
|
||||
expect(testElement.x).toEqual(30);
|
||||
handle.y(40);
|
||||
expect(testElement.y).toEqual(40);
|
||||
});
|
||||
|
||||
it("disallows values less than zero", function () {
|
||||
handle.x(-1);
|
||||
handle.y(-400);
|
||||
expect(testElement.x).toEqual(0);
|
||||
expect(testElement.y).toEqual(0);
|
||||
});
|
||||
|
||||
it("ensures that end points remain different", function () {
|
||||
handle.x(testElement.x2);
|
||||
handle.y(testElement.y2);
|
||||
// First change should have been fine, because y was different
|
||||
expect(testElement.x).toEqual(testElement.x2);
|
||||
// Second change should have been rejected
|
||||
expect(testElement.y).not.toEqual(testElement.y2);
|
||||
});
|
||||
|
||||
it("returns the correct grid size", function () {
|
||||
expect(handle.getGridSize()).toEqual(TEST_GRID_SIZE);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,95 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/LineProxy'],
|
||||
function (LineProxy) {
|
||||
|
||||
describe("A fixed position line proxy", function () {
|
||||
var vertical, horizontal, diagonal, reversed;
|
||||
|
||||
beforeEach(function () {
|
||||
vertical = { x: 1, y: 4, x2: 1, y2: 8};
|
||||
horizontal = { x: 3, y: 3, x2: 12, y2: 3};
|
||||
diagonal = { x: 3, y: 8, x2: 5, y2: 11};
|
||||
reversed = { x2: 3, y2: 8, x: 5, y: 11};
|
||||
});
|
||||
|
||||
it("ensures visible width for vertical lines", function () {
|
||||
expect(new LineProxy(vertical).width()).toEqual(1);
|
||||
});
|
||||
|
||||
it("ensures visible height for horizontal lines", function () {
|
||||
expect(new LineProxy(horizontal).height()).toEqual(1);
|
||||
});
|
||||
|
||||
it("provides a bounding box for lines", function () {
|
||||
var proxy = new LineProxy(diagonal);
|
||||
expect(proxy.x()).toEqual(3);
|
||||
expect(proxy.y()).toEqual(8);
|
||||
expect(proxy.width()).toEqual(2);
|
||||
expect(proxy.height()).toEqual(3);
|
||||
});
|
||||
|
||||
it("bounds lines identically regardless of point order", function () {
|
||||
// That is, x(), width(), y(), and height() should always give
|
||||
// the same results for the same line segments, regardless of
|
||||
// which point is x,y and which is x2,y2
|
||||
['x', 'y', 'width', 'height'].forEach(function (method) {
|
||||
expect(new LineProxy(diagonal)[method]())
|
||||
.toEqual(new LineProxy(reversed)[method]());
|
||||
});
|
||||
});
|
||||
|
||||
it("adjusts both ends when mutating x", function () {
|
||||
var proxy = new LineProxy(diagonal);
|
||||
proxy.x(6);
|
||||
expect(diagonal).toEqual({ x: 6, y: 8, x2: 8, y2: 11});
|
||||
});
|
||||
|
||||
it("adjusts both ends when mutating y", function () {
|
||||
var proxy = new LineProxy(diagonal);
|
||||
proxy.y(6);
|
||||
expect(diagonal).toEqual({ x: 3, y: 6, x2: 5, y2: 9});
|
||||
});
|
||||
|
||||
it("provides internal positions for SVG lines", function () {
|
||||
var proxy;
|
||||
proxy = new LineProxy(diagonal);
|
||||
expect(proxy.x1()).toEqual(0);
|
||||
expect(proxy.y1()).toEqual(0);
|
||||
expect(proxy.x2()).toEqual(2);
|
||||
expect(proxy.y2()).toEqual(3);
|
||||
proxy = new LineProxy(reversed);
|
||||
expect(proxy.x1()).toEqual(2);
|
||||
expect(proxy.y1()).toEqual(3);
|
||||
expect(proxy.x2()).toEqual(0);
|
||||
expect(proxy.y2()).toEqual(0);
|
||||
});
|
||||
|
||||
it("provides handles for both ends", function () {
|
||||
expect(new LineProxy(diagonal).handles().length).toEqual(2);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,93 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/ResizeHandle'],
|
||||
function (ResizeHandle) {
|
||||
|
||||
var TEST_MIN_WIDTH = 4,
|
||||
TEST_MIN_HEIGHT = 2,
|
||||
TEST_GRID_SIZE = [34, 81];
|
||||
|
||||
describe("A fixed position drag handle", function () {
|
||||
var testElement,
|
||||
mockElementProxy,
|
||||
handle;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 3,
|
||||
y: 42,
|
||||
width: 30,
|
||||
height: 36,
|
||||
useGrid: true
|
||||
};
|
||||
mockElementProxy = jasmine.createSpyObj('elementProxy', [
|
||||
'getGridSize',
|
||||
'getMinWidth',
|
||||
'getMinHeight'
|
||||
]);
|
||||
mockElementProxy.getGridSize.and.returnValue(TEST_GRID_SIZE);
|
||||
mockElementProxy.getMinWidth.and.returnValue(TEST_MIN_WIDTH);
|
||||
mockElementProxy.getMinHeight.and.returnValue(TEST_MIN_HEIGHT);
|
||||
|
||||
handle = new ResizeHandle(
|
||||
mockElementProxy,
|
||||
testElement
|
||||
);
|
||||
});
|
||||
|
||||
it("provides x/y grid coordinates for lower-right corner", function () {
|
||||
expect(handle.x()).toEqual(33);
|
||||
expect(handle.y()).toEqual(78);
|
||||
});
|
||||
|
||||
it("changes width of an element", function () {
|
||||
handle.x(30);
|
||||
// Should change width, not x
|
||||
expect(testElement.x).toEqual(3);
|
||||
expect(testElement.width).toEqual(27);
|
||||
});
|
||||
|
||||
it("changes height of an element", function () {
|
||||
handle.y(60);
|
||||
// Should change height, not y
|
||||
expect(testElement.y).toEqual(42);
|
||||
expect(testElement.height).toEqual(18);
|
||||
});
|
||||
|
||||
it("enforces minimum width/height", function () {
|
||||
handle.x(testElement.x);
|
||||
handle.y(testElement.y);
|
||||
expect(testElement.x).toEqual(3);
|
||||
expect(testElement.y).toEqual(42);
|
||||
expect(testElement.width).toEqual(TEST_MIN_WIDTH);
|
||||
expect(testElement.height).toEqual(TEST_MIN_HEIGHT);
|
||||
});
|
||||
|
||||
it("returns the correct grid size", function () {
|
||||
expect(handle.getGridSize()).toEqual(TEST_GRID_SIZE);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,54 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/TelemetryProxy'],
|
||||
function (TelemetryProxy) {
|
||||
|
||||
describe("A fixed position telemetry proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
z: 3,
|
||||
width: 42,
|
||||
height: 24,
|
||||
id: "test-id"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new TelemetryProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("exposes the element's id", function () {
|
||||
expect(proxy.id).toEqual('test-id');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -1,70 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/TextProxy'],
|
||||
function (TextProxy) {
|
||||
|
||||
describe("A fixed position text proxy", function () {
|
||||
var testElement,
|
||||
testElements,
|
||||
proxy;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 1,
|
||||
y: 2,
|
||||
width: 42,
|
||||
height: 24,
|
||||
fill: "transparent",
|
||||
size: "20px"
|
||||
};
|
||||
testElements = [{}, {}, testElement, {}];
|
||||
proxy = new TextProxy(
|
||||
testElement,
|
||||
testElements.indexOf(testElement),
|
||||
testElements
|
||||
);
|
||||
});
|
||||
|
||||
it("provides getter/setter for fill color", function () {
|
||||
expect(proxy.fill()).toEqual('transparent');
|
||||
expect(proxy.fill('#FFF')).toEqual('#FFF');
|
||||
expect(proxy.fill()).toEqual('#FFF');
|
||||
});
|
||||
|
||||
it("provides getter/setter for text size", function () {
|
||||
expect(proxy.size()).toEqual('20px');
|
||||
expect(proxy.size('12px')).toEqual('12px');
|
||||
expect(proxy.size()).toEqual('12px');
|
||||
});
|
||||
|
||||
it("defaults to 13px for unspecified text size", function () {
|
||||
testElement = {x: 1, y: 2};
|
||||
proxy = new TextProxy(testElement, 0, [testElement]);
|
||||
|
||||
expect(proxy.size()).toEqual('13px');
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -1,157 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/elements/UnitAccessorMutator'],
|
||||
function (UnitAccessorMutator) {
|
||||
|
||||
var GRID_SIZE = [13,17];
|
||||
|
||||
describe("An elementProxy.gridSize accessor-mutator", function () {
|
||||
var mockElementProxy,
|
||||
testElement,
|
||||
mockLineProxy,
|
||||
testLine,
|
||||
uAM,
|
||||
uAMLine;
|
||||
|
||||
beforeEach(function () {
|
||||
testElement = {
|
||||
x: 2,
|
||||
y: 3,
|
||||
width: 4,
|
||||
height: 5,
|
||||
useGrid: true
|
||||
};
|
||||
|
||||
mockElementProxy = {
|
||||
element: testElement,
|
||||
gridSize: GRID_SIZE,
|
||||
getMinHeight: jasmine.createSpy('minHeight'),
|
||||
getMinWidth: jasmine.createSpy('minWidth')
|
||||
};
|
||||
|
||||
testLine = {
|
||||
x: 7,
|
||||
y: 8,
|
||||
x2: 9,
|
||||
y2: 10,
|
||||
width: 11,
|
||||
height: 12,
|
||||
useGrid: true
|
||||
};
|
||||
|
||||
mockLineProxy = {
|
||||
element: testLine,
|
||||
gridSize: GRID_SIZE,
|
||||
getMinHeight: jasmine.createSpy('minHeight'),
|
||||
getMinWidth: jasmine.createSpy('minWidth')
|
||||
};
|
||||
|
||||
|
||||
|
||||
uAM = new UnitAccessorMutator(mockElementProxy);
|
||||
uAMLine = new UnitAccessorMutator(mockLineProxy);
|
||||
|
||||
mockElementProxy.getMinWidth.and.returnValue(1);
|
||||
mockElementProxy.getMinHeight.and.returnValue(1);
|
||||
|
||||
mockLineProxy.getMinWidth.and.returnValue(1);
|
||||
mockLineProxy.getMinHeight.and.returnValue(1);
|
||||
});
|
||||
|
||||
it("allows access to useGrid", function () {
|
||||
expect(uAM()).toEqual(mockElementProxy.element.useGrid);
|
||||
});
|
||||
|
||||
it("allows mutation of useGrid", function () {
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.useGrid).toEqual(false);
|
||||
});
|
||||
|
||||
it("converts coordinates appropriately for a box", function () {
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.x).toEqual(26);
|
||||
expect(mockElementProxy.element.y).toEqual(51);
|
||||
expect(mockElementProxy.element.width).toEqual(52);
|
||||
expect(mockElementProxy.element.height).toEqual(85);
|
||||
uAM(true);
|
||||
expect(mockElementProxy.element.x).toEqual(2);
|
||||
expect(mockElementProxy.element.y).toEqual(3);
|
||||
expect(mockElementProxy.element.width).toEqual(4);
|
||||
expect(mockElementProxy.element.height).toEqual(5);
|
||||
});
|
||||
|
||||
it("converts coordinates appropriately for a line", function () {
|
||||
uAMLine(false);
|
||||
expect(mockLineProxy.element.x).toEqual(91);
|
||||
expect(mockLineProxy.element.y).toEqual(136);
|
||||
expect(mockLineProxy.element.x2).toEqual(117);
|
||||
expect(mockLineProxy.element.y2).toEqual(170);
|
||||
expect(mockLineProxy.element.width).toEqual(143);
|
||||
expect(mockLineProxy.element.height).toEqual(204);
|
||||
uAMLine(true);
|
||||
expect(mockLineProxy.element.x).toEqual(7);
|
||||
expect(mockLineProxy.element.y).toEqual(8);
|
||||
expect(mockLineProxy.element.x2).toEqual(9);
|
||||
expect(mockLineProxy.element.y2).toEqual(10);
|
||||
expect(mockLineProxy.element.width).toEqual(11);
|
||||
expect(mockLineProxy.element.height).toEqual(12);
|
||||
});
|
||||
|
||||
it("doesn't covert coordinates unecessarily", function () {
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.x).toEqual(26);
|
||||
expect(mockElementProxy.element.y).toEqual(51);
|
||||
expect(mockElementProxy.element.width).toEqual(52);
|
||||
expect(mockElementProxy.element.height).toEqual(85);
|
||||
uAM(false);
|
||||
expect(mockElementProxy.element.x).toEqual(26);
|
||||
expect(mockElementProxy.element.y).toEqual(51);
|
||||
expect(mockElementProxy.element.width).toEqual(52);
|
||||
expect(mockElementProxy.element.height).toEqual(85);
|
||||
});
|
||||
|
||||
it("snaps coordinates onto the grid", function () {
|
||||
uAM(false);
|
||||
mockElementProxy.element.x += 11;
|
||||
mockElementProxy.element.y -= 27;
|
||||
mockElementProxy.element.width -= 14;
|
||||
mockElementProxy.element.height += 4;
|
||||
uAM(true);
|
||||
expect(mockElementProxy.element.x).toEqual(3);
|
||||
expect(mockElementProxy.element.y).toEqual(1);
|
||||
expect(mockElementProxy.element.width).toEqual(3);
|
||||
expect(mockElementProxy.element.height).toEqual(5);
|
||||
});
|
||||
|
||||
it("enforces a minimum height and width", function () {
|
||||
uAM(false);
|
||||
mockElementProxy.element.width = 4;
|
||||
mockElementProxy.element.height = 4;
|
||||
uAM(true);
|
||||
expect(mockElementProxy.element.width).toEqual(1);
|
||||
expect(mockElementProxy.element.height).toEqual(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -29,13 +29,22 @@ define(
|
||||
function SnapshotPreviewController($scope, openmct) {
|
||||
|
||||
$scope.previewImage = function (imageUrl) {
|
||||
var image = document.createElement('img');
|
||||
image.src = imageUrl;
|
||||
let imageDiv = document.createElement('div');
|
||||
imageDiv.classList = 'image-main s-image-main';
|
||||
imageDiv.style.backgroundImage = `url(${imageUrl})`;
|
||||
|
||||
openmct.overlays.overlay(
|
||||
let previewImageOverlay = openmct.overlays.overlay(
|
||||
{
|
||||
element: image,
|
||||
size: 'large'
|
||||
element: imageDiv,
|
||||
size: 'large',
|
||||
buttons: [
|
||||
{
|
||||
label: 'Done',
|
||||
callback: function () {
|
||||
previewImageOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -43,13 +52,13 @@ define(
|
||||
$scope.annotateImage = function (ngModel, field, imageUrl) {
|
||||
$scope.imageUrl = imageUrl;
|
||||
|
||||
var div = document.createElement('div'),
|
||||
let div = document.createElement('div'),
|
||||
painterroInstance = {},
|
||||
save = false;
|
||||
|
||||
div.id = 'snap-annotation';
|
||||
|
||||
openmct.overlays.overlay(
|
||||
let annotateImageOverlay = openmct.overlays.overlay(
|
||||
{
|
||||
element: div,
|
||||
size: 'large',
|
||||
@ -59,6 +68,7 @@ define(
|
||||
callback: function () {
|
||||
save = false;
|
||||
painterroInstance.save();
|
||||
annotateImageOverlay.dismiss();
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -66,6 +76,7 @@ define(
|
||||
callback: function () {
|
||||
save = true;
|
||||
painterroInstance.save();
|
||||
annotateImageOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -97,7 +108,7 @@ define(
|
||||
},
|
||||
saveHandler: function (image, done) {
|
||||
if (save) {
|
||||
var url = image.asBlob(),
|
||||
let url = image.asBlob(),
|
||||
reader = new window.FileReader();
|
||||
|
||||
reader.readAsDataURL(url);
|
||||
|
@ -43,6 +43,7 @@ define([
|
||||
'./ui/layout/Layout.vue',
|
||||
'../platform/core/src/objects/DomainObjectImpl',
|
||||
'../platform/core/src/capabilities/ContextualDomainObject',
|
||||
'./ui/preview/plugin',
|
||||
'vue'
|
||||
], function (
|
||||
EventEmitter,
|
||||
@ -67,6 +68,7 @@ define([
|
||||
Layout,
|
||||
DomainObjectImpl,
|
||||
ContextualDomainObject,
|
||||
PreviewPlugin,
|
||||
Vue
|
||||
) {
|
||||
/**
|
||||
@ -230,7 +232,7 @@ define([
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
this.install(this.plugins.DisplayLayout());
|
||||
this.install(this.plugins.Preview());
|
||||
this.install(PreviewPlugin.default());
|
||||
|
||||
if (typeof BUILD_CONSTANTS !== 'undefined') {
|
||||
this.install(buildInfoPlugin(BUILD_CONSTANTS));
|
||||
|
@ -58,11 +58,8 @@ define([
|
||||
|
||||
handleLegacyMutation = function (legacyObject) {
|
||||
var newStyleObject = utils.toNewFormat(legacyObject.getModel(), legacyObject.getId());
|
||||
|
||||
//Don't trigger self
|
||||
this.eventEmitter.off('mutation', handleMutation);
|
||||
this.eventEmitter.emit(newStyleObject.identifier.key + ":*", newStyleObject);
|
||||
this.eventEmitter.on('mutation', handleMutation);
|
||||
this.eventEmitter.emit('mutation', newStyleObject);
|
||||
}.bind(this);
|
||||
|
||||
this.eventEmitter.on('mutation', handleMutation);
|
||||
|
@ -28,12 +28,18 @@ export default class Editor extends EventEmitter {
|
||||
super();
|
||||
this.editing = false;
|
||||
this.openmct = openmct;
|
||||
document.addEventListener('drop', (event) => {
|
||||
if (!this.isEditing()) {
|
||||
this.edit();
|
||||
}
|
||||
}, {capture: true});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate an editing session. This will start a transaction during
|
||||
* which any persist operations will be deferred until either save()
|
||||
* or finish() are called.
|
||||
* @private
|
||||
*/
|
||||
edit() {
|
||||
if (this.editing === true) {
|
||||
@ -54,6 +60,8 @@ export default class Editor extends EventEmitter {
|
||||
/**
|
||||
* Save any unsaved changes from this editing session. This will
|
||||
* end the current transaction.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
save() {
|
||||
return this.getTransactionService().commit().then((result)=>{
|
||||
@ -67,6 +75,8 @@ export default class Editor extends EventEmitter {
|
||||
|
||||
/**
|
||||
* End the currently active transaction and discard unsaved changes.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
cancel() {
|
||||
this.getTransactionService().cancel();
|
||||
|
@ -46,6 +46,7 @@ define([
|
||||
function DefaultCompositionProvider(publicAPI, compositionAPI) {
|
||||
this.publicAPI = publicAPI;
|
||||
this.listeningTo = {};
|
||||
this.onMutation = this.onMutation.bind(this);
|
||||
|
||||
this.cannotContainDuplicates = this.cannotContainDuplicates.bind(this);
|
||||
this.cannotContainItself = this.cannotContainItself.bind(this);
|
||||
@ -177,8 +178,12 @@ define([
|
||||
* @method remove
|
||||
*/
|
||||
DefaultCompositionProvider.prototype.remove = function (domainObject, childId) {
|
||||
// TODO: this needs to be synchronized via mutation.
|
||||
throw new Error('Default Provider does not implement removal.');
|
||||
let composition = domainObject.composition.filter(function (child) {
|
||||
return !(childId.namespace === child.namespace &&
|
||||
childId.key === child.key);
|
||||
});
|
||||
|
||||
this.publicAPI.objects.mutate(domainObject, 'composition', composition);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -208,9 +213,10 @@ define([
|
||||
if (this.topicListener) {
|
||||
return;
|
||||
}
|
||||
var topic = this.publicAPI.$injector.get('topic');
|
||||
var mutation = topic('mutation');
|
||||
this.topicListener = mutation.listen(this.onMutation.bind(this));
|
||||
this.publicAPI.objects.eventEmitter.on('mutation', this.onMutation);
|
||||
this.topicListener = () => {
|
||||
this.publicAPI.objects.eventEmitter.off('mutation', this.onMutation)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@ -220,7 +226,7 @@ define([
|
||||
* @private
|
||||
*/
|
||||
DefaultCompositionProvider.prototype.onMutation = function (oldDomainObject) {
|
||||
var id = oldDomainObject.getId();
|
||||
var id = objectUtils.makeKeyString(oldDomainObject.identifier);
|
||||
var listeners = this.listeningTo[id];
|
||||
|
||||
if (!listeners) {
|
||||
@ -228,7 +234,7 @@ define([
|
||||
}
|
||||
|
||||
var oldComposition = listeners.composition.map(objectUtils.makeKeyString);
|
||||
var newComposition = oldDomainObject.getModel().composition.map(objectUtils.makeKeyString);
|
||||
var newComposition = oldDomainObject.composition.map(objectUtils.makeKeyString);
|
||||
|
||||
var added = _.difference(newComposition, oldComposition).map(objectUtils.parseKeyString);
|
||||
var removed = _.difference(oldComposition, newComposition).map(objectUtils.parseKeyString);
|
||||
|
@ -83,18 +83,15 @@ define([
|
||||
this.object = newObject;
|
||||
}.bind(this);
|
||||
|
||||
this.eventEmitter.on(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
|
||||
//Emit event specific to property
|
||||
this.eventEmitter.emit(qualifiedEventName(this.object, path), value);
|
||||
|
||||
this.eventEmitter.off(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
|
||||
//Emit wildcare event
|
||||
//Emit wildcard event
|
||||
this.eventEmitter.emit(qualifiedEventName(this.object, '*'), this.object);
|
||||
|
||||
//Emit a general "any object" event
|
||||
this.eventEmitter.emit(ANY_OBJECT_EVENT, this.object);
|
||||
|
||||
this.eventEmitter.on(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
//Emit event specific to property
|
||||
this.eventEmitter.emit(qualifiedEventName(this.object, path), value);
|
||||
this.eventEmitter.off(qualifiedEventName(this.object, '*'), handleRecursiveMutation);
|
||||
};
|
||||
|
||||
return MutableObject;
|
||||
|
@ -215,6 +215,19 @@ define([
|
||||
return utils.makeKeyString(identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given any number of identifiers, will return true if they are all equal, otherwise false.
|
||||
* @param {module:openmct.ObjectAPI~Identifier[]} identifiers
|
||||
*/
|
||||
ObjectAPI.prototype.areIdsEqual = function (...identifiers) {
|
||||
return identifiers.map(utils.parseKeyString)
|
||||
.every(identifier => {
|
||||
return identifier === identifiers[0] ||
|
||||
(identifier.namespace === identifiers[0].namespace &&
|
||||
identifier.key === identifiers[0].key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Uniquely identifies a domain object.
|
||||
*
|
||||
|
@ -22,7 +22,7 @@ class Dialog extends Overlay {
|
||||
super({
|
||||
element: component.$el,
|
||||
size: 'fit',
|
||||
notDismissable: true,
|
||||
dismissable: false,
|
||||
...options
|
||||
});
|
||||
|
||||
|
@ -12,6 +12,7 @@ class Overlay extends EventEmitter {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
this.dismissable = options.dismissable !== false ? true : false;
|
||||
this.container = document.createElement('div');
|
||||
this.container.classList.add('l-overlay-wrapper', cssClasses[options.size]);
|
||||
|
||||
@ -20,7 +21,7 @@ class Overlay extends EventEmitter {
|
||||
dismiss: this.dismiss.bind(this),
|
||||
element: options.element,
|
||||
buttons: options.buttons,
|
||||
notDismissable: options.notDismissable ? true : false
|
||||
dismissable: this.dismissable
|
||||
},
|
||||
components: {
|
||||
OverlayComponent: OverlayComponent
|
||||
@ -35,8 +36,8 @@ class Overlay extends EventEmitter {
|
||||
|
||||
dismiss() {
|
||||
this.emit('destroy');
|
||||
this.component.$destroy();
|
||||
document.body.removeChild(this.container);
|
||||
this.component.$destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,14 @@ import ProgressDialog from './ProgressDialog';
|
||||
class OverlayAPI {
|
||||
constructor() {
|
||||
this.activeOverlays = [];
|
||||
|
||||
this.dismissLastOverlay = this.dismissLastOverlay.bind(this);
|
||||
|
||||
document.addEventListener('keyup', (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
this.dismissLastOverlay();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,14 +46,24 @@ class OverlayAPI {
|
||||
}
|
||||
|
||||
/**
|
||||
] * A description of option properties that can be passed into the overlay
|
||||
* @typedef options
|
||||
* private
|
||||
*/
|
||||
dismissLastOverlay() {
|
||||
let lastOverlay = this.activeOverlays[this.activeOverlays.length - 1];
|
||||
if (lastOverlay && lastOverlay.dismissable) {
|
||||
lastOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of option properties that can be passed into the overlay
|
||||
* @typedef options
|
||||
* @property {object} element DOMElement that is to be inserted/shown on the overlay
|
||||
* @property {string} size prefered size of the overlay (large, small, fit)
|
||||
* @property {array} buttons optional button objects with label and callback properties
|
||||
* @property {function} onDestroy callback to be called when overlay is destroyed
|
||||
* @property {boolean} notDismissable to prevent user from dismissing the overlay, calling code
|
||||
* will need to explicitly dismiss the overlay.
|
||||
* @property {boolean} dismissable allow user to dismiss overlay by using esc, and clicking away
|
||||
* from overlay. Unless set to false, all overlays will be dismissable by default.
|
||||
*/
|
||||
overlay(options) {
|
||||
let overlay = new Overlay(options);
|
||||
|
@ -25,7 +25,7 @@ class ProgressDialog extends Overlay {
|
||||
super({
|
||||
element: component.$el,
|
||||
size: 'fit',
|
||||
notDismissable: true,
|
||||
dismissable: false,
|
||||
...options
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<div class="c-overlay__outer">
|
||||
<button class="c-click-icon c-overlay__close-button icon-x-in-circle"
|
||||
v-if="!notDismissable"
|
||||
v-if="dismissable"
|
||||
@click="destroy">
|
||||
</button>
|
||||
<div class="c-overlay__contents" ref="element"></div>
|
||||
@ -129,19 +129,19 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inject: ['dismiss', 'element', 'buttons', 'notDismissable'],
|
||||
inject: ['dismiss', 'element', 'buttons', 'dismissable'],
|
||||
mounted() {
|
||||
this.$refs.element.appendChild(this.element);
|
||||
},
|
||||
methods: {
|
||||
destroy: function () {
|
||||
if (!this.notDismissable) {
|
||||
if (this.dismissable) {
|
||||
this.dismiss();
|
||||
}
|
||||
},
|
||||
buttonClickHandler: function (method) {
|
||||
method();
|
||||
this.destroy();
|
||||
this.$emit('destroy');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ define([], function () {
|
||||
key: "layout",
|
||||
description: "A toolbar for objects inside a display layout.",
|
||||
forSelection: function (selection) {
|
||||
// Apply the layout toolbar if the edit mode is on, and the selected object
|
||||
// Apply the layout toolbar if the selected object
|
||||
// is inside a layout, or the main layout is selected.
|
||||
return (openmct.editor.isEditing() && selection &&
|
||||
return (selection &&
|
||||
((selection[1] && selection[1].context.item && selection[1].context.item.type === 'layout') ||
|
||||
(selection[0].context.item && selection[0].context.item.type === 'layout')));
|
||||
(selection[0].context.item && selection[0].context.item.type === 'layout')));
|
||||
},
|
||||
toolbar: function (selection) {
|
||||
const DIALOG_FORM = {
|
||||
@ -73,10 +73,13 @@ define([], function () {
|
||||
return openmct.$injector.get('dialogService').getUserInput(form, {});
|
||||
}
|
||||
|
||||
function getPath() {
|
||||
return `configuration.items[${selection[0].context.index}]`;
|
||||
}
|
||||
|
||||
let selectedParent = selection[1] && selection[1].context.item,
|
||||
selectedObject = selection[0].context.item,
|
||||
layoutItem = selection[0].context.layoutItem,
|
||||
layoutItemIndex = selection[0].context.index,
|
||||
toolbar = [];
|
||||
|
||||
if (selectedObject && selectedObject.type === 'layout') {
|
||||
@ -121,7 +124,6 @@ define([], function () {
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
let path = `configuration.items[${layoutItemIndex}]`;
|
||||
let separator = {
|
||||
control: "separator"
|
||||
};
|
||||
@ -140,7 +142,7 @@ define([], function () {
|
||||
label: 'Ok',
|
||||
emphasis: 'true',
|
||||
callback: function () {
|
||||
removeItem(layoutItem, layoutItemIndex);
|
||||
removeItem(layoutItem, selection[0].context.index);
|
||||
prompt.dismiss();
|
||||
}
|
||||
},
|
||||
@ -154,6 +156,96 @@ define([], function () {
|
||||
});
|
||||
}
|
||||
};
|
||||
let stackOrder = {
|
||||
control: "menu",
|
||||
domainObject: selectedParent,
|
||||
icon: "icon-layers",
|
||||
title: "Move the selected object above or below other objects",
|
||||
options: [
|
||||
{
|
||||
name: "Move to Top",
|
||||
value: "top",
|
||||
class: "icon-arrow-double-up"
|
||||
},
|
||||
{
|
||||
name: "Move Up",
|
||||
value: "up",
|
||||
class: "icon-arrow-up"
|
||||
},
|
||||
{
|
||||
name: "Move Down",
|
||||
value: "down",
|
||||
class: "icon-arrow-down"
|
||||
},
|
||||
{
|
||||
name: "Move to Bottom",
|
||||
value: "bottom",
|
||||
class: "icon-arrow-double-down"
|
||||
}
|
||||
],
|
||||
method: function (option) {
|
||||
selection[1].context.orderItem(option.value, selection[0].context.index);
|
||||
}
|
||||
};
|
||||
let useGrid = {
|
||||
control: "toggle-button",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".useGrid";
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
icon: "icon-grid-snap-to",
|
||||
title: "Grid snapping enabled"
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
icon: "icon-grid-snap-no",
|
||||
title: "Grid snapping disabled"
|
||||
}
|
||||
]
|
||||
};
|
||||
let x = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".x";
|
||||
},
|
||||
label: "X:",
|
||||
title: "X position"
|
||||
},
|
||||
y = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".y";
|
||||
},
|
||||
label: "Y:",
|
||||
title: "Y position",
|
||||
},
|
||||
width = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".width";
|
||||
},
|
||||
label: 'W:',
|
||||
title: 'Resize object width'
|
||||
},
|
||||
height = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".height";
|
||||
},
|
||||
label: 'H:',
|
||||
title: 'Resize object height'
|
||||
};
|
||||
|
||||
if (layoutItem.type === 'subobject-view') {
|
||||
if (toolbar.length > 0) {
|
||||
@ -163,124 +255,113 @@ define([], function () {
|
||||
toolbar.push({
|
||||
control: "toggle-button",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".hasFrame",
|
||||
property: function () {
|
||||
return getPath() + ".hasFrame";
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-frame-hide',
|
||||
title: "Hide frame"
|
||||
icon: 'icon-frame-show',
|
||||
title: "Frame visible"
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-frame-show',
|
||||
title: "Show frame"
|
||||
icon: 'icon-frame-hide',
|
||||
title: "Frame hidden"
|
||||
}
|
||||
]
|
||||
});
|
||||
toolbar.push(separator);
|
||||
toolbar.push(stackOrder);
|
||||
toolbar.push(x);
|
||||
toolbar.push(y);
|
||||
toolbar.push(width);
|
||||
toolbar.push(height);
|
||||
toolbar.push(useGrid);
|
||||
toolbar.push(separator);
|
||||
toolbar.push(remove);
|
||||
} else {
|
||||
const TEXT_SIZE = [9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96];
|
||||
const TEXT_SIZE = [8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96, 128];
|
||||
let fill = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".fill",
|
||||
icon: "icon-paint-bucket",
|
||||
title: "Set fill color"
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".fill";
|
||||
},
|
||||
stroke = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".stroke",
|
||||
icon: "icon-line-horz",
|
||||
title: "Set border color"
|
||||
icon: "icon-paint-bucket",
|
||||
title: "Set fill color"
|
||||
},
|
||||
stroke = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".stroke";
|
||||
},
|
||||
color = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".color",
|
||||
icon: "icon-font",
|
||||
mandatory: true,
|
||||
title: "Set text color",
|
||||
preventNone: true
|
||||
icon: "icon-line-horz",
|
||||
title: "Set border color"
|
||||
},
|
||||
color = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".color";
|
||||
},
|
||||
size = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".size",
|
||||
title: "Set text size",
|
||||
options: TEXT_SIZE.map(size => {
|
||||
return {
|
||||
value: size + "px"
|
||||
};
|
||||
})
|
||||
icon: "icon-font",
|
||||
mandatory: true,
|
||||
title: "Set text color",
|
||||
preventNone: true
|
||||
},
|
||||
size = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".size";
|
||||
},
|
||||
x = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".x",
|
||||
label: "X:",
|
||||
title: "X position"
|
||||
},
|
||||
y = {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".y",
|
||||
label: "Y:",
|
||||
title: "Y position",
|
||||
},
|
||||
width = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: path + ".width",
|
||||
label: 'W:',
|
||||
title: 'Resize object width'
|
||||
},
|
||||
height = {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: path + ".height",
|
||||
label: 'H:',
|
||||
title: 'Resize object height'
|
||||
};
|
||||
title: "Set text size",
|
||||
options: TEXT_SIZE.map(size => {
|
||||
return {
|
||||
value: size + "px"
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
if (layoutItem.type === 'telemetry-view') {
|
||||
let displayMode = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".displayMode",
|
||||
title: "Set display mode",
|
||||
options: [
|
||||
{
|
||||
name: 'Label + Value',
|
||||
value: 'all'
|
||||
},
|
||||
{
|
||||
name: "Label only",
|
||||
value: "label"
|
||||
},
|
||||
{
|
||||
name: "Value only",
|
||||
value: "value"
|
||||
}
|
||||
]
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".displayMode";
|
||||
},
|
||||
value = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".value",
|
||||
title: "Set value",
|
||||
options: openmct.telemetry.getMetadata(selectedObject).values().map(value => {
|
||||
return {
|
||||
name: value.name,
|
||||
value: value.key
|
||||
}
|
||||
})
|
||||
};
|
||||
title: "Set display mode",
|
||||
options: [
|
||||
{
|
||||
name: 'Label + Value',
|
||||
value: 'all'
|
||||
},
|
||||
{
|
||||
name: "Label only",
|
||||
value: "label"
|
||||
},
|
||||
{
|
||||
name: "Value only",
|
||||
value: "value"
|
||||
}
|
||||
]
|
||||
},
|
||||
value = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: function () {
|
||||
return getPath() + ".value";
|
||||
},
|
||||
title: "Set value",
|
||||
options: openmct.telemetry.getMetadata(selectedObject).values().map(value => {
|
||||
return {
|
||||
name: value.name,
|
||||
value: value.key
|
||||
}
|
||||
})
|
||||
};
|
||||
toolbar = [
|
||||
displayMode,
|
||||
separator,
|
||||
@ -292,18 +373,22 @@ define([], function () {
|
||||
separator,
|
||||
size,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
} else if (layoutItem.type === 'text-view' ) {
|
||||
} else if (layoutItem.type === 'text-view') {
|
||||
let text = {
|
||||
control: "button",
|
||||
domainObject: selectedParent,
|
||||
property: path,
|
||||
property: function () {
|
||||
return getPath();
|
||||
},
|
||||
icon: "icon-gear",
|
||||
title: "Edit text properties",
|
||||
dialog: DIALOG_FORM['text']
|
||||
@ -311,14 +396,16 @@ define([], function () {
|
||||
toolbar = [
|
||||
fill,
|
||||
stroke,
|
||||
color,
|
||||
separator,
|
||||
color,
|
||||
size,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
text,
|
||||
separator,
|
||||
@ -329,10 +416,12 @@ define([], function () {
|
||||
fill,
|
||||
stroke,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
@ -340,7 +429,9 @@ define([], function () {
|
||||
let url = {
|
||||
control: "button",
|
||||
domainObject: selectedParent,
|
||||
property: path,
|
||||
property: function () {
|
||||
return getPath();
|
||||
},
|
||||
icon: "icon-image",
|
||||
title: "Edit image properties",
|
||||
dialog: DIALOG_FORM['image']
|
||||
@ -348,10 +439,12 @@ define([], function () {
|
||||
toolbar = [
|
||||
stroke,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
url,
|
||||
separator,
|
||||
@ -362,7 +455,9 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".x2",
|
||||
property: function () {
|
||||
return getPath() + ".x2";
|
||||
},
|
||||
label: "X2:",
|
||||
title: "X2 position"
|
||||
},
|
||||
@ -370,17 +465,21 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".y2",
|
||||
property: function () {
|
||||
return getPath() + ".y2";
|
||||
},
|
||||
label: "Y2:",
|
||||
title: "Y2 position",
|
||||
};
|
||||
toolbar = [
|
||||
stroke,
|
||||
separator,
|
||||
stackOrder,
|
||||
x,
|
||||
y,
|
||||
x2,
|
||||
y2,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
|
@ -25,6 +25,7 @@ define(function () {
|
||||
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 = [];
|
||||
@ -32,7 +33,31 @@ define(function () {
|
||||
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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,8 @@
|
||||
x: 1,
|
||||
y: 1,
|
||||
width: 10,
|
||||
height: 5
|
||||
height: 5,
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -25,30 +25,26 @@
|
||||
@dragover="handleDragOver"
|
||||
@click="bypassSelection"
|
||||
@drop="handleDrop">
|
||||
<div class="l-layout__object">
|
||||
<!-- Background grid -->
|
||||
<div class="l-layout__grid-holder c-grid"
|
||||
v-if="!drilledIn">
|
||||
<div class="c-grid__x l-grid l-grid-x"
|
||||
v-if="gridSize[0] >= 3"
|
||||
:style="[{ backgroundSize: gridSize[0] + 'px 100%' }]">
|
||||
</div>
|
||||
<div class="c-grid__y l-grid l-grid-y"
|
||||
v-if="gridSize[1] >= 3"
|
||||
:style="[{ backgroundSize: '100%' + gridSize[1] + 'px' }]"></div>
|
||||
<!-- Background grid -->
|
||||
<div class="l-layout__grid-holder c-grid">
|
||||
<div class="c-grid__x l-grid l-grid-x"
|
||||
v-if="gridSize[0] >= 3"
|
||||
:style="[{ backgroundSize: gridSize[0] + 'px 100%' }]">
|
||||
</div>
|
||||
<component v-for="(item, index) in layoutItems"
|
||||
:is="item.type"
|
||||
:item="item"
|
||||
:key="item.id"
|
||||
:gridSize="gridSize"
|
||||
:initSelect="initSelectIndex === index"
|
||||
:index="index"
|
||||
@drilledIn="updateDrilledIn"
|
||||
@endDrag="endDrag"
|
||||
>
|
||||
</component>
|
||||
<div class="c-grid__y l-grid l-grid-y"
|
||||
v-if="gridSize[1] >= 3"
|
||||
:style="[{ backgroundSize: '100%' + gridSize[1] + 'px' }]"></div>
|
||||
</div>
|
||||
<component v-for="(item, index) in layoutItems"
|
||||
:is="item.type"
|
||||
:item="item"
|
||||
:key="item.id"
|
||||
:gridSize="item.useGrid ? gridSize : [1, 1]"
|
||||
:initSelect="initSelectIndex === index"
|
||||
:index="index"
|
||||
@endDrag="endDrag"
|
||||
>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -59,30 +55,47 @@
|
||||
@include abs();
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
&__grid-holder {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__object {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&__frame {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.l-shell__main-container {
|
||||
> .l-layout {
|
||||
[s-selected] {
|
||||
border: $browseSelectedBorder;
|
||||
.is-editing {
|
||||
.l-shell__main-container {
|
||||
&[s-selected],
|
||||
&[s-selected-parent] {
|
||||
// Display grid in main layout holder when editing
|
||||
> .l-layout {
|
||||
background: $editUIGridColorBg;
|
||||
|
||||
> [class*="__grid-holder"] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-layout__frame {
|
||||
&[s-selected],
|
||||
&[s-selected-parent] {
|
||||
// Display grid in nested layouts when editing
|
||||
> * > * > .l-layout {
|
||||
background: $editUIGridColorBg;
|
||||
box-shadow: inset $editUIGridColorFg 0 0 2px 1px;
|
||||
|
||||
> [class*='grid-holder'] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Styles moved to _global.scss;
|
||||
</style>
|
||||
|
||||
|
||||
@ -104,6 +117,14 @@
|
||||
'text-view': TextView,
|
||||
'image-view': ImageView
|
||||
};
|
||||
const ORDERS = {
|
||||
top: Number.POSITIVE_INFINITY,
|
||||
up: 1,
|
||||
down: -1,
|
||||
bottom: Number.NEGATIVE_INFINITY
|
||||
};
|
||||
|
||||
const DRAG_OBJECT_TRANSFER_PREFIX = 'openmct/domain-object/';
|
||||
|
||||
function getItemDefinition(itemType, ...options) {
|
||||
let itemView = ITEM_TYPE_VIEW_MAP[itemType];
|
||||
@ -119,7 +140,6 @@
|
||||
data() {
|
||||
let domainObject = JSON.parse(JSON.stringify(this.domainObject));
|
||||
return {
|
||||
drilledIn: undefined,
|
||||
internalDomainObject: domainObject,
|
||||
initSelectIndex: undefined
|
||||
};
|
||||
@ -144,16 +164,49 @@
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateDrilledIn();
|
||||
if (this.removeSelectionListener) {
|
||||
this.removeSelectionListener();
|
||||
}
|
||||
|
||||
let itemIndex = selection[0].context.index;
|
||||
|
||||
if (itemIndex !== undefined) {
|
||||
this.attachSelectionListener(itemIndex);
|
||||
}
|
||||
},
|
||||
updateDrilledIn(drilledInItem) {
|
||||
let identifier = drilledInItem && this.openmct.objects.makeKeyString(drilledInItem.identifier);
|
||||
this.drilledIn = identifier;
|
||||
this.layoutItems.forEach(item => {
|
||||
if (item.type === 'subobject-view') {
|
||||
item.drilledIn = this.openmct.objects.makeKeyString(item.identifier) === identifier;
|
||||
attachSelectionListener(index) {
|
||||
let path = `configuration.items[${index}].useGrid`;
|
||||
this.removeSelectionListener = this.openmct.objects.observe(this.internalDomainObject, path, function (value) {
|
||||
let item = this.layoutItems[index];
|
||||
|
||||
if (value) {
|
||||
item.x = Math.round(item.x / this.gridSize[0]);
|
||||
item.y = Math.round(item.y / this.gridSize[1]);
|
||||
item.width = Math.round(item.width / this.gridSize[0]);
|
||||
item.height = Math.round(item.height / this.gridSize[1]);
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = Math.round(item.x2 / this.gridSize[0]);
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = Math.round(item.y2 / this.gridSize[1]);
|
||||
}
|
||||
} else {
|
||||
item.x = this.gridSize[0] * item.x;
|
||||
item.y = this.gridSize[1] * item.y;
|
||||
item.width = this.gridSize[0] * item.width;
|
||||
item.height = this.gridSize[1] * item.height;
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = this.gridSize[0] * item.x2;
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = this.gridSize[1] * item.y2;
|
||||
}
|
||||
}
|
||||
});
|
||||
item.useGrid = value;
|
||||
this.mutate(`configuration.items[${index}]`, item);
|
||||
}.bind(this));
|
||||
},
|
||||
bypassSelection($event) {
|
||||
if (this.dragInProgress) {
|
||||
@ -177,13 +230,13 @@
|
||||
this.openmct.objects.mutate(this.internalDomainObject, path, value);
|
||||
},
|
||||
handleDrop($event) {
|
||||
if (!$event.dataTransfer.types.includes('domainobject')) {
|
||||
if (!$event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event.preventDefault();
|
||||
|
||||
let domainObject = JSON.parse($event.dataTransfer.getData('domainobject'));
|
||||
let domainObject = JSON.parse($event.dataTransfer.getData('openmct/domain-object-path'))[0];
|
||||
let elementRect = this.$el.getBoundingClientRect();
|
||||
let droppedObjectPosition = [
|
||||
Math.floor(($event.pageX - elementRect.left) / this.gridSize[0]),
|
||||
@ -213,12 +266,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
handleDragOver($event){
|
||||
$event.preventDefault();
|
||||
containsObject(identifier) {
|
||||
return _.get(this.internalDomainObject, 'composition')
|
||||
.some(childId => this.openmct.objects.areIdsEqual(childId, identifier));
|
||||
},
|
||||
handleDragOver($event) {
|
||||
// Get the ID of the dragged object
|
||||
let draggedKeyString = $event.dataTransfer.types
|
||||
.filter(type => type.startsWith(DRAG_OBJECT_TRANSFER_PREFIX))
|
||||
.map(type => type.substring(DRAG_OBJECT_TRANSFER_PREFIX.length))[0];
|
||||
|
||||
// If the layout already contains the given object, then shortcut the default dragover behavior and
|
||||
// potentially allow drop. Display layouts allow drag drop of duplicate telemetry objects.
|
||||
if (this.containsObject(draggedKeyString)){
|
||||
$event.preventDefault();
|
||||
}
|
||||
},
|
||||
isTelemetry(domainObject) {
|
||||
if (this.openmct.telemetry.isTelemetryObject(domainObject)
|
||||
&& domainObject.type !== 'summary-widget') {
|
||||
&& domainObject.type !== 'summary-widget'
|
||||
&& domainObject.type !== 'example.imagery') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -234,12 +301,17 @@
|
||||
this.initSelectIndex = this.layoutItems.length - 1;
|
||||
},
|
||||
trackItem(item) {
|
||||
if (!item.identifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
||||
|
||||
if (item.type === "telemetry-view") {
|
||||
let keyString = this.openmct.objects.makeKeyString(item.identifier);
|
||||
let count = this.telemetryViewMap[keyString] || 0;
|
||||
this.telemetryViewMap[keyString] = ++count;
|
||||
} else if (item.type === "subobject-view") {
|
||||
this.objectViewMap[this.openmct.objects.makeKeyString(item.identifier)] = true;
|
||||
this.objectViewMap[keyString] = true;
|
||||
}
|
||||
},
|
||||
removeItem(item, index) {
|
||||
@ -311,13 +383,28 @@
|
||||
});
|
||||
this.mutate("configuration.items", layoutItems);
|
||||
this.$el.click();
|
||||
},
|
||||
orderItem(position, index) {
|
||||
let delta = ORDERS[position];
|
||||
let newIndex = Math.max(Math.min(index + delta, this.layoutItems.length - 1), 0);
|
||||
let item = this.layoutItems[index];
|
||||
|
||||
if (newIndex !== index) {
|
||||
this.layoutItems.splice(index, 1);
|
||||
this.layoutItems.splice(newIndex, 0, item);
|
||||
this.mutate('configuration.items', this.layoutItems);
|
||||
|
||||
if (this.removeSelectionListener) {
|
||||
this.removeSelectionListener();
|
||||
this.attachSelectionListener(newIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.unlisten = this.openmct.objects.observe(this.internalDomainObject, '*', function (obj) {
|
||||
this.internalDomainObject = JSON.parse(JSON.stringify(obj));
|
||||
}.bind(this));
|
||||
|
||||
this.openmct.selection.on('change', this.setSelection);
|
||||
this.initializeItems();
|
||||
this.composition = this.openmct.composition.get(this.internalDomainObject);
|
||||
@ -330,7 +417,10 @@
|
||||
this.composition.off('add', this.addChild);
|
||||
this.composition.off('remove', this.removeChild);
|
||||
this.unlisten();
|
||||
|
||||
if (this.removeSelectionListener) {
|
||||
this.removeSelectionListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -56,7 +56,8 @@
|
||||
y: 1,
|
||||
width: 10,
|
||||
height: 5,
|
||||
url: element.url
|
||||
url: element.url,
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -25,25 +25,24 @@
|
||||
:class="{
|
||||
'no-frame': !item.hasFrame,
|
||||
'u-inspectable': inspectable,
|
||||
'is-drilled-in': item.drilledIn
|
||||
'is-resizing': isResizing
|
||||
}"
|
||||
:style="style"
|
||||
@dblclick="drill($event)">
|
||||
:style="style">
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<!-- Drag handles -->
|
||||
<div class="c-frame-edit">
|
||||
<div class="c-frame-edit__move"
|
||||
@mousedown="startDrag([1,1], [0,0], $event)"></div>
|
||||
@mousedown="startDrag([1,1], [0,0], $event, 'move')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--nw"
|
||||
@mousedown="startDrag([1,1], [-1,-1], $event)"></div>
|
||||
@mousedown="startDrag([1,1], [-1,-1], $event, 'resize')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--ne"
|
||||
@mousedown="startDrag([0,1], [1,-1], $event)"></div>
|
||||
@mousedown="startDrag([0,1], [1,-1], $event, 'resize')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--sw"
|
||||
@mousedown="startDrag([1,0], [-1,1], $event)"></div>
|
||||
@mousedown="startDrag([1,0], [-1,1], $event, 'resize')"></div>
|
||||
<div class="c-frame-edit__handle c-frame-edit__handle--se"
|
||||
@mousedown="startDrag([0,0], [1,1], $event)"></div>
|
||||
@mousedown="startDrag([0,0], [1,1], $event, 'resize')"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -55,20 +54,167 @@
|
||||
.c-frame {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid transparent;
|
||||
|
||||
/*************************** NO-FRAME */
|
||||
&.no-frame {
|
||||
> [class*="contents"] > [class*="__header"] {
|
||||
display: none;
|
||||
}
|
||||
// Whatever is placed into the slot, make it fill the entirety of the space, obeying padding
|
||||
> *:first-child {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
&:not(.no-frame) {
|
||||
background: $colorBodyBg;
|
||||
border: 1px solid $colorInteriorBorder;
|
||||
border: $browseFrameBorder;
|
||||
padding: $interiorMargin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.c-frame-edit {
|
||||
// In Layouts, this is the editing rect and handles
|
||||
// In Fixed Position, this is a wrapper element
|
||||
@include abs();
|
||||
display: none;
|
||||
|
||||
&__move {
|
||||
@include abs();
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
&__handle {
|
||||
$d: 6px;
|
||||
$o: floor($d * -0.5);
|
||||
background: $editFrameColorHandleFg;
|
||||
box-shadow: $editFrameColorHandleBg 0 0 0 2px;
|
||||
display: none; // Set to block via s-selected selector
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-so-view.has-complex-content + .c-frame-edit {
|
||||
// Target frames that hold domain objects that include header elements, as opposed to drawing and alpha objects
|
||||
// Make the __move element a more affordable drag UI element
|
||||
.c-frame-edit__move {
|
||||
@include userSelectNone();
|
||||
background: $editFrameMovebarColorBg;
|
||||
box-shadow: rgba(black, 0.2) 0 1px;
|
||||
bottom: auto;
|
||||
height: 0; // Height is set on hover on s-selected.c-frame
|
||||
opacity: 0.8;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
|
||||
&:before {
|
||||
// Grippy
|
||||
$h: 4px;
|
||||
$tbOffset: ($editFrameMovebarH - $h) / 2;
|
||||
$lrOffset: 25%;
|
||||
@include grippy($editFrameMovebarColorFg);
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: $tbOffset; right: $lrOffset; bottom: $tbOffset; left: $lrOffset;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $editFrameHovMovebarColorBg;
|
||||
&:before { @include grippy($editFrameHovMovebarColorFg); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-editing {
|
||||
.c-frame {
|
||||
$moveBarOutDelay: 500ms;
|
||||
&.no-frame {
|
||||
border: $editFrameBorder; // Base border style for a frame element while editing.
|
||||
}
|
||||
|
||||
&-edit {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
&-edit__move,
|
||||
.c-so-view {
|
||||
transition: $transOut;
|
||||
transition-delay: $moveBarOutDelay;
|
||||
}
|
||||
|
||||
&:not([s-selected]) {
|
||||
&:hover {
|
||||
border: $editFrameBorderHov;
|
||||
}
|
||||
}
|
||||
|
||||
&[s-selected] {
|
||||
// All frames selected while editing
|
||||
border: $editFrameSelectedBorder;
|
||||
box-shadow: $editFrameSelectedShdw;
|
||||
|
||||
> .c-frame-edit {
|
||||
[class*='__handle'] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-layout__frame:not(.is-resizing) {
|
||||
// Show and animate the __move bar for sub-object views with complex content
|
||||
&:hover > .c-so-view.has-complex-content {
|
||||
// Move content down so the __move bar doesn't cover it.
|
||||
padding-top: $editFrameMovebarH;
|
||||
transition: $transIn;
|
||||
|
||||
&.c-so-view--no-frame {
|
||||
// Move content down with a bit more space
|
||||
padding-top: $editFrameMovebarH + $interiorMarginSm;
|
||||
}
|
||||
|
||||
// Show the move bar
|
||||
+ .c-frame-edit .c-frame-edit__move {
|
||||
height: $editFrameMovebarH;
|
||||
transition: $transIn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -84,7 +230,8 @@
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dragPosition: undefined
|
||||
dragPosition: undefined,
|
||||
isResizing: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -110,24 +257,6 @@
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
drill($event) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
if (!this.openmct.editor.isEditing() || !this.item.identifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.openmct.objects.get(this.item.identifier)
|
||||
.then(domainObject => {
|
||||
if (this.openmct.composition.get(domainObject) === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$emit('drilledIn', this.item);
|
||||
});
|
||||
},
|
||||
updatePosition(event) {
|
||||
let currentPosition = [event.pageX, event.pageY];
|
||||
this.initialPosition = this.initialPosition || currentPosition;
|
||||
@ -135,7 +264,7 @@
|
||||
return value - this.initialPosition[index];
|
||||
}.bind(this));
|
||||
},
|
||||
startDrag(posFactor, dimFactor, event) {
|
||||
startDrag(posFactor, dimFactor, event, type) {
|
||||
document.body.addEventListener('mousemove', this.continueDrag);
|
||||
document.body.addEventListener('mouseup', this.endDrag);
|
||||
|
||||
@ -145,6 +274,7 @@
|
||||
};
|
||||
this.updatePosition(event);
|
||||
this.activeDrag = new LayoutDrag(this.dragPosition, posFactor, dimFactor, this.gridSize);
|
||||
this.isResizing = type === 'resize';
|
||||
event.preventDefault();
|
||||
},
|
||||
continueDrag(event) {
|
||||
@ -162,6 +292,7 @@
|
||||
this.dragPosition = undefined;
|
||||
this.initialPosition = undefined;
|
||||
this.delta = undefined;
|
||||
this.isResizing = undefined;
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,8 @@
|
||||
y: 10,
|
||||
x2: 10,
|
||||
y2: 5,
|
||||
stroke: '#717171'
|
||||
stroke: '#717171',
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -22,12 +22,12 @@
|
||||
<template>
|
||||
<layout-frame :item="item"
|
||||
:grid-size="gridSize"
|
||||
@endDrag="(item, updates) => $emit('endDrag', item, updates)"
|
||||
@drilledIn="item => $emit('drilledIn', item)">
|
||||
@endDrag="(item, updates) => $emit('endDrag', item, updates)">
|
||||
<object-frame v-if="domainObject"
|
||||
:domain-object="domainObject"
|
||||
:object-path="objectPath"
|
||||
:has-frame="item.hasFrame">
|
||||
:has-frame="item.hasFrame"
|
||||
ref="objectFrame">
|
||||
</object-frame>
|
||||
</layout-frame>
|
||||
</template>
|
||||
@ -65,7 +65,8 @@
|
||||
x: position[0],
|
||||
y: position[1],
|
||||
identifier: domainObject.identifier,
|
||||
hasFrame: hasFrameByDefault(domainObject.type)
|
||||
hasFrame: hasFrameByDefault(domainObject.type),
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
@ -98,13 +99,15 @@
|
||||
setObject(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
this.objectPath = [this.domainObject].concat(this.openmct.router.path);
|
||||
this.context = {
|
||||
item: domainObject,
|
||||
layoutItem: this.item,
|
||||
index: this.index
|
||||
};
|
||||
this.removeSelectable = this.openmct.selection.selectable(
|
||||
this.$el, this.context, this.initSelect);
|
||||
this.$nextTick(function () {
|
||||
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.initSelect);
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -99,6 +99,7 @@
|
||||
fill: "",
|
||||
color: "",
|
||||
size: "13px",
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -59,7 +59,8 @@
|
||||
y: 1,
|
||||
width: 10,
|
||||
height: 5,
|
||||
text: element.text
|
||||
text: element.text,
|
||||
useGrid: true
|
||||
};
|
||||
},
|
||||
inject: ['openmct'],
|
||||
|
@ -61,7 +61,8 @@ export default function () {
|
||||
return {
|
||||
item: domainObject,
|
||||
addElement: component && component.$refs.displayLayout.addElement,
|
||||
removeItem: component && component.$refs.displayLayout.removeItem
|
||||
removeItem: component && component.$refs.displayLayout.removeItem,
|
||||
orderItem: component && component.$refs.displayLayout.orderItem
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
|
@ -24,7 +24,7 @@
|
||||
<div class="c-fl-container"
|
||||
:style="[{'flex-basis': sizeString}]"
|
||||
:class="{'is-empty': !frames.length}">
|
||||
<div class="c-fl-container__header icon-grippy-ew"
|
||||
<div class="c-fl-container__header"
|
||||
v-show="isEditing"
|
||||
draggable="true"
|
||||
@dragstart="startContainerDrag">
|
||||
@ -35,7 +35,7 @@
|
||||
class="c-fl-frame__drop-hint"
|
||||
:index="-1"
|
||||
:allow-drop="allowDrop"
|
||||
@object-drop-to="moveOrCreateFrame">
|
||||
@object-drop-to="moveOrCreateNewFrame">
|
||||
</drop-hint>
|
||||
|
||||
<div class="c-fl-container__frames-holder">
|
||||
@ -47,7 +47,8 @@
|
||||
:key="frame.id"
|
||||
:frame="frame"
|
||||
:index="i"
|
||||
:containerIndex="index">
|
||||
:containerIndex="index"
|
||||
:isEditing="isEditing">
|
||||
</frame-component>
|
||||
|
||||
<drop-hint
|
||||
@ -55,7 +56,7 @@
|
||||
:key="i"
|
||||
:index="i"
|
||||
:allowDrop="allowDrop"
|
||||
@object-drop-to="moveOrCreateFrame">
|
||||
@object-drop-to="moveOrCreateNewFrame">
|
||||
</drop-hint>
|
||||
|
||||
<resize-handle
|
||||
@ -65,7 +66,8 @@
|
||||
:orientation="rowsLayout ? 'horizontal' : 'vertical'"
|
||||
@init-move="startFrameResizing"
|
||||
@move="frameResizing"
|
||||
@end-move="endFrameResizing">
|
||||
@end-move="endFrameResizing"
|
||||
:isEditing="isEditing">
|
||||
</resize-handle>
|
||||
</template>
|
||||
</div>
|
||||
@ -77,14 +79,12 @@ import FrameComponent from './frame.vue';
|
||||
import Frame from '../utils/frame';
|
||||
import ResizeHandle from './resizeHandle.vue';
|
||||
import DropHint from './dropHint.vue';
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
const MIN_FRAME_SIZE = 5;
|
||||
|
||||
export default {
|
||||
inject:['openmct'],
|
||||
props: ['container', 'index', 'rowsLayout'],
|
||||
mixins: [isEditingMixin],
|
||||
props: ['container', 'index', 'rowsLayout', 'isEditing'],
|
||||
components: {
|
||||
FrameComponent,
|
||||
ResizeHandle,
|
||||
@ -100,7 +100,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
allowDrop(event, index) {
|
||||
if (event.dataTransfer.getData('domainObject')) {
|
||||
if (event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
return true;
|
||||
}
|
||||
let frameId = event.dataTransfer.getData('frameid'),
|
||||
@ -123,15 +123,12 @@ export default {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
moveOrCreateFrame(insertIndex, event) {
|
||||
if (event.dataTransfer.types.includes('domainobject')) {
|
||||
// create frame using domain object
|
||||
let domainObject = JSON.parse(event.dataTransfer.getData('domainObject'));
|
||||
moveOrCreateNewFrame(insertIndex, event) {
|
||||
if (event.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
this.$emit(
|
||||
'create-frame',
|
||||
'new-frame',
|
||||
this.index,
|
||||
insertIndex,
|
||||
domainObject.identifier
|
||||
insertIndex
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
@ -21,10 +21,10 @@
|
||||
*****************************************************************************/
|
||||
|
||||
<template>
|
||||
<div v-if="isEditing"
|
||||
v-show="isValidTarget">
|
||||
<div v-show="isValidTarget">
|
||||
<div class="c-drop-hint c-drop-hint--always-show"
|
||||
:class="{'is-mouse-over': isMouseOver}"
|
||||
@dragover.prevent
|
||||
@dragenter="dragenter"
|
||||
@dragleave="dragleave"
|
||||
@drop="dropHandler">
|
||||
@ -37,8 +37,6 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
export default {
|
||||
props:{
|
||||
index: Number,
|
||||
@ -47,7 +45,6 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
mixins: [isEditingMixin],
|
||||
data() {
|
||||
return {
|
||||
isMouseOver: false,
|
||||
@ -75,10 +72,12 @@ export default {
|
||||
mounted() {
|
||||
document.addEventListener('dragstart', this.dragstart);
|
||||
document.addEventListener('dragend', this.dragend);
|
||||
document.addEventListener('drop', this.dragend);
|
||||
},
|
||||
destroyed() {
|
||||
document.removeEventListener('dragstart', this.dragstart);
|
||||
document.removeEventListener('dragend', this.dragend);
|
||||
document.removeEventListener('drop', this.dragend);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -22,6 +22,11 @@
|
||||
|
||||
<template>
|
||||
<div class="c-fl">
|
||||
<div
|
||||
id="js-fl-drag-ghost"
|
||||
class="c-fl__drag-ghost">
|
||||
</div>
|
||||
|
||||
<div class="c-fl__empty"
|
||||
v-if="areAllContainersEmpty()">
|
||||
<span class="c-fl__empty-message">This Flexible Layout is currently empty</span>
|
||||
@ -49,8 +54,9 @@
|
||||
:index="index"
|
||||
:container="container"
|
||||
:rowsLayout="rowsLayout"
|
||||
:isEditing="isEditing"
|
||||
@move-frame="moveFrame"
|
||||
@create-frame="createFrame"
|
||||
@new-frame="setFrameLocation"
|
||||
@persist="persist">
|
||||
</container-component>
|
||||
|
||||
@ -59,6 +65,7 @@
|
||||
:key="index"
|
||||
:index="index"
|
||||
:orientation="rowsLayout ? 'vertical' : 'horizontal'"
|
||||
:isEditing="isEditing"
|
||||
@init-move="startContainerResizing"
|
||||
@move="containerResizing"
|
||||
@end-move="endContainerResizing">
|
||||
@ -79,6 +86,22 @@
|
||||
|
||||
<style lang="scss">
|
||||
@import '~styles/sass-base';
|
||||
|
||||
@mixin containerGrippy($headerSize, $dir) {
|
||||
position: absolute;
|
||||
$h: 6px;
|
||||
$minorOffset: ($headerSize - $h) / 2;
|
||||
$majorOffset: 35%;
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
@include grippy($c: $editFrameSelectedMovebarColorFg, $dir: $dir);
|
||||
@if $dir == 'x' {
|
||||
top: $minorOffset; right: $majorOffset; bottom: $minorOffset; left: $majorOffset;
|
||||
} @else {
|
||||
top: $majorOffset; right: $minorOffset; bottom: $majorOffset; left: $minorOffset;
|
||||
}
|
||||
}
|
||||
|
||||
.c-fl {
|
||||
@include abs();
|
||||
@ -100,7 +123,6 @@
|
||||
> * + * { margin-left: 1px; }
|
||||
|
||||
&[class*='--rows'] {
|
||||
//@include test(blue, 0.1);
|
||||
flex-direction: column;
|
||||
> * + * {
|
||||
margin-left: 0;
|
||||
@ -122,13 +144,29 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
&__drag-ghost{
|
||||
background: $colorItemTreeHoverBg;
|
||||
color: $colorItemTreeHoverFg;
|
||||
border-radius: $basicCr;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: $interiorMarginLg $interiorMarginLg * 2;
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
z-index: 2;
|
||||
|
||||
&:before {
|
||||
color: $colorKey;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.c-fl-container {
|
||||
/***************************************************** CONTAINERS */
|
||||
$headerSize: 16px;
|
||||
|
||||
border: 1px solid transparent;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
@ -138,9 +176,9 @@
|
||||
flex-shrink: 1;
|
||||
|
||||
&__header {
|
||||
// Only displayed when editing
|
||||
background: $editSelectableColor;
|
||||
color: $editSelectableColorFg;
|
||||
// Only displayed when editing, controlled via JS
|
||||
background: $editFrameMovebarColorBg;
|
||||
color: $editFrameMovebarColorFg;
|
||||
cursor: move;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -148,12 +186,8 @@
|
||||
|
||||
&:before {
|
||||
// Drag grippy
|
||||
font-size: 0.8em;
|
||||
@include containerGrippy($headerSize, 'x');
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
left: 50%; top: 50%;
|
||||
transform-origin: center;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,19 +207,27 @@
|
||||
}
|
||||
|
||||
.is-editing & {
|
||||
//background: $editCanvasColorBg;
|
||||
border-color: $editSelectableColor;
|
||||
|
||||
&:hover {
|
||||
border-color: $editSelectableColorHov;
|
||||
.c-fl-container__header {
|
||||
background: $editFrameHovMovebarColorBg;
|
||||
color: $editFrameHovMovebarColorFg;
|
||||
|
||||
&:before {
|
||||
opacity: .75;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[s-selected] {
|
||||
border-color: $editSelectableColorSelected;
|
||||
border: $editFrameSelectedBorder;
|
||||
|
||||
.c-fl-container__header {
|
||||
background: $editSelectableColorSelected;
|
||||
color: $editSelectableColorSelectedFg;
|
||||
background:$editFrameSelectedMovebarColorBg;
|
||||
color: $editFrameSelectedMovebarColorFg;
|
||||
&:before {
|
||||
// Grippy
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -194,11 +236,6 @@
|
||||
// Frames get styled here because this is particular to their presence in this layout type
|
||||
.c-fl-frame {
|
||||
@include browserPrefix(margin-collapse, collapse);
|
||||
margin: 1px;
|
||||
|
||||
//&__drag-wrapper {
|
||||
// border: 1px solid $colorInteriorBorder; // Now handled by is-selectable
|
||||
//}
|
||||
}
|
||||
|
||||
/****** ROWS LAYOUT */
|
||||
@ -211,8 +248,8 @@
|
||||
overflow: hidden;
|
||||
|
||||
&:before {
|
||||
// Drag grippy
|
||||
transform: rotate(90deg) translate(-50%, 50%);
|
||||
// Grippy
|
||||
@include containerGrippy($headerSize, 'y');
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,8 +272,6 @@
|
||||
$dropHintSize: 15px;
|
||||
|
||||
display: flex;
|
||||
// justify-content: stretch;
|
||||
// align-items: stretch;
|
||||
flex: 1 1;
|
||||
flex-direction: column;
|
||||
overflow: hidden; // Needed to allow frames to collapse when sized down
|
||||
@ -275,7 +310,6 @@
|
||||
pointer-events: none;
|
||||
text-align: center;
|
||||
width: $size;
|
||||
z-index: 2;
|
||||
|
||||
// Changed when layout is different, see below
|
||||
border-top-right-radius: $controlCr;
|
||||
@ -304,37 +338,16 @@
|
||||
|
||||
&:before {
|
||||
// The visible resize line
|
||||
background: $editColor;
|
||||
background: $editUIColor;
|
||||
content: '';
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
min-height: $size; min-width: $size;
|
||||
}
|
||||
|
||||
&__grippy {
|
||||
// Grippy element
|
||||
$d: 4px;
|
||||
$c: black;
|
||||
$a: 0.9;
|
||||
$d: 5px;
|
||||
background: $editColor;
|
||||
color: $editColorBg;
|
||||
border-radius: $smallCr;
|
||||
font-size: 0.8em;
|
||||
height: $d;
|
||||
width: $d * 10;
|
||||
position: absolute;
|
||||
left: 50%; top: 50%;
|
||||
text-align: center;
|
||||
transform-origin: center center;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
padding: $margin $size;
|
||||
&:hover{
|
||||
// padding: $marginHov 0;
|
||||
cursor: row-resize;
|
||||
}
|
||||
}
|
||||
@ -342,20 +355,15 @@
|
||||
&.horizontal {
|
||||
padding: $size $margin;
|
||||
&:hover{
|
||||
// padding: 0 $marginHov;
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
[class*='grippy'] {
|
||||
transform: translate(-50%) rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transition: $transOut;
|
||||
&:before {
|
||||
// The visible resize line
|
||||
background: $editColorHov;
|
||||
background: $editUIColorHov;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,7 +422,6 @@ import Container from '../utils/container';
|
||||
import Frame from '../utils/frame';
|
||||
import ResizeHandle from './resizeHandle.vue';
|
||||
import DropHint from './dropHint.vue';
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
const MIN_CONTAINER_SIZE = 5;
|
||||
|
||||
@ -459,7 +466,6 @@ function sizeToFill(items) {
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'layoutObject'],
|
||||
mixins: [isEditingMixin],
|
||||
components: {
|
||||
ContainerComponent,
|
||||
ResizeHandle,
|
||||
@ -467,9 +473,13 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domainObject: this.layoutObject
|
||||
domainObject: this.layoutObject,
|
||||
newFrameLocation: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
isEditing: Boolean
|
||||
},
|
||||
computed: {
|
||||
layoutDirectionStr() {
|
||||
if (this.rowsLayout) {
|
||||
@ -496,9 +506,27 @@ export default {
|
||||
this.persist();
|
||||
},
|
||||
deleteContainer(containerId) {
|
||||
let container = this.containers.filter(c => c.id === containerId)[0];
|
||||
let containerIndex = this.containers.indexOf(container);
|
||||
let container = this.containers.filter(c => c.id === containerId)[0],
|
||||
containerIndex = this.containers.indexOf(container);
|
||||
|
||||
/*
|
||||
remove associated domainObjects from composition
|
||||
*/
|
||||
container.frames.forEach(f => {
|
||||
this.composition.remove({identifier: f.domainObjectIdentifier});
|
||||
});
|
||||
|
||||
this.containers.splice(containerIndex, 1);
|
||||
|
||||
/*
|
||||
add a container when there are no containers in the FL,
|
||||
to prevent user from not being able to add a frame via
|
||||
drag and drop.
|
||||
*/
|
||||
if (this.containers.length === 0) {
|
||||
this.containers.push(new Container(100));
|
||||
}
|
||||
|
||||
sizeToFill(this.containers);
|
||||
this.persist();
|
||||
},
|
||||
@ -513,12 +541,22 @@ export default {
|
||||
sizeItems(toContainer.frames, frame);
|
||||
this.persist();
|
||||
},
|
||||
createFrame(containerIndex, insertFrameIndex, objectIdentifier) {
|
||||
let frame = new Frame(objectIdentifier);
|
||||
let container = this.containers[containerIndex];
|
||||
container.frames.splice(insertFrameIndex + 1, 0, frame);
|
||||
sizeItems(container.frames, frame);
|
||||
this.persist();
|
||||
setFrameLocation(containerIndex, insertFrameIndex) {
|
||||
this.newFrameLocation = [containerIndex, insertFrameIndex];
|
||||
},
|
||||
addFrame(domainObject) {
|
||||
if (this.newFrameLocation.length) {
|
||||
let containerIndex = this.newFrameLocation[0],
|
||||
frameIndex = this.newFrameLocation[1],
|
||||
frame = new Frame(domainObject.identifier),
|
||||
container = this.containers[containerIndex];
|
||||
|
||||
container.frames.splice(frameIndex + 1, 0, frame);
|
||||
sizeItems(container.frames, frame);
|
||||
|
||||
this.newFrameLocation = [];
|
||||
this.persist(containerIndex);
|
||||
}
|
||||
},
|
||||
deleteFrame(frameId) {
|
||||
let container = this.containers
|
||||
@ -528,6 +566,12 @@ export default {
|
||||
.frames
|
||||
.filter((f => f.id === frameId))[0];
|
||||
let frameIndex = container.frames.indexOf(frame);
|
||||
|
||||
/*
|
||||
remove associated domainObject from composition
|
||||
*/
|
||||
this.composition.remove({identifier: frame.domainObjectIdentifier});
|
||||
|
||||
container.frames.splice(frameIndex, 1);
|
||||
sizeToFill(container.frames);
|
||||
this.persist(containerIndex);
|
||||
@ -600,24 +644,33 @@ export default {
|
||||
} else {
|
||||
this.containers.splice(toIndex, 0, container);
|
||||
}
|
||||
this.persist();
|
||||
},
|
||||
removeChildObject(identifier) {
|
||||
let removeIdentifier = this.openmct.objects.makeKeyString(identifier);
|
||||
|
||||
this.containers.forEach(container => {
|
||||
container.frames = container.frames.filter(frame => {
|
||||
let frameIdentifier = this.openmct.objects.makeKeyString(frame.domainObjectIdentifier);
|
||||
|
||||
return removeIdentifier !== frameIdentifier;
|
||||
});
|
||||
});
|
||||
|
||||
this.persist();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('remove', this.removeChildObject);
|
||||
this.composition.on('add', this.addFrame);
|
||||
|
||||
let context = {
|
||||
item: this.domainObject,
|
||||
addContainer: this.addContainer,
|
||||
deleteContainer: this.deleteContainer,
|
||||
deleteFrame: this.deleteFrame,
|
||||
type: 'flexible-layout'
|
||||
}
|
||||
|
||||
this.unsubscribeSelection = this.openmct.selection.selectable(this.$el, context, true);
|
||||
this.unobserve = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.unsubscribeSelection();
|
||||
this.composition.off('remove', this.removeChildObject);
|
||||
this.composition.off('add', this.addFrame);
|
||||
|
||||
this.unobserve();
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
'flex-basis': `${frame.size}%`
|
||||
}">
|
||||
|
||||
<div class="c-frame c-fl-frame__drag-wrapper is-selectable is-moveable"
|
||||
<div class="c-frame c-fl-frame__drag-wrapper is-selectable u-inspectable is-moveable"
|
||||
draggable="true"
|
||||
@dragstart="initDrag"
|
||||
ref="frame">
|
||||
@ -35,7 +35,8 @@
|
||||
v-if="domainObject"
|
||||
:domain-object="domainObject"
|
||||
:object-path="objectPath"
|
||||
:has-frame="hasFrame">
|
||||
:has-frame="hasFrame"
|
||||
ref="objectFrame">
|
||||
</object-frame>
|
||||
|
||||
<div class="c-fl-frame__size-indicator"
|
||||
@ -50,12 +51,10 @@
|
||||
<script>
|
||||
import ResizeHandle from './resizeHandle.vue';
|
||||
import ObjectFrame from '../../../ui/components/ObjectFrame.vue';
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
props: ['frame', 'index', 'containerIndex'],
|
||||
mixins: [isEditingMixin],
|
||||
props: ['frame', 'index', 'containerIndex', 'isEditing'],
|
||||
data() {
|
||||
return {
|
||||
domainObject: undefined,
|
||||
@ -73,22 +72,33 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
setDomainObject(object) {
|
||||
console.log('setting object!');
|
||||
this.domainObject = object;
|
||||
this.objectPath = [object];
|
||||
this.setSelection();
|
||||
},
|
||||
setSelection() {
|
||||
let context = {
|
||||
item: this.domainObject,
|
||||
addContainer: this.addContainer,
|
||||
type: 'frame',
|
||||
frameId: this.frame.id
|
||||
};
|
||||
|
||||
this.unsubscribeSelection = this.openmct.selection.selectable(this.$refs.frame, context, false);
|
||||
this.$nextTick(function () {
|
||||
let childContext = this.$refs.objectFrame.getSelectionContext();
|
||||
childContext.item = this.domainObject;
|
||||
childContext.type = 'frame';
|
||||
childContext.frameId = this.frame.id;
|
||||
this.unsubscribeSelection = this.openmct.selection.selectable(
|
||||
this.$refs.frame, childContext, false);
|
||||
});
|
||||
},
|
||||
initDrag(event) {
|
||||
let type = this.openmct.types.get(this.domainObject.type),
|
||||
iconClass = type.definition ? type.definition.cssClass : 'icon-object-unknown';
|
||||
|
||||
if (this.dragGhost) {
|
||||
let originalClassName = this.dragGhost.classList[0];
|
||||
this.dragGhost.className = '';
|
||||
this.dragGhost.classList.add(originalClassName, iconClass);
|
||||
|
||||
this.dragGhost.innerHTML = `<span>${this.domainObject.name}</span>`;
|
||||
event.dataTransfer.setDragImage(this.dragGhost, 0, 0);
|
||||
}
|
||||
|
||||
event.dataTransfer.setData('frameid', this.frame.id);
|
||||
event.dataTransfer.setData('containerIndex', this.containerIndex);
|
||||
}
|
||||
@ -99,6 +109,8 @@ export default {
|
||||
this.setDomainObject(object);
|
||||
});
|
||||
}
|
||||
|
||||
this.dragGhost = document.getElementById('js-fl-drag-ghost');
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.unsubscribeSelection) {
|
||||
|
@ -29,11 +29,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import isEditingMixin from '../mixins/isEditing';
|
||||
|
||||
export default {
|
||||
props: ['orientation', 'index'],
|
||||
mixins: [isEditingMixin],
|
||||
props: ['orientation', 'index', 'isEditing'],
|
||||
data() {
|
||||
return {
|
||||
initialPos: 0,
|
||||
|
@ -42,8 +42,13 @@ define([
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
show: function (element, isEditing) {
|
||||
component = new Vue({
|
||||
data() {
|
||||
return {
|
||||
isEditing: isEditing
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FlexibleLayoutComponent: FlexibleLayoutComponent.default
|
||||
},
|
||||
@ -52,9 +57,21 @@ define([
|
||||
layoutObject: domainObject
|
||||
},
|
||||
el: element,
|
||||
template: '<flexible-layout-component></flexible-layout-component>'
|
||||
template: '<flexible-layout-component ref="flexibleLayout" :isEditing="isEditing"></flexible-layout-component>'
|
||||
});
|
||||
},
|
||||
getSelectionContext: function () {
|
||||
return {
|
||||
item: domainObject,
|
||||
addContainer: component.$refs.flexibleLayout.addContainer,
|
||||
deleteContainer: component.$refs.flexibleLayout.deleteContainer,
|
||||
deleteFrame: component.$refs.flexibleLayout.deleteFrame,
|
||||
type: 'flexible-layout'
|
||||
};
|
||||
},
|
||||
onEditModeChange: function (isEditing) {
|
||||
component.isEditing = isEditing;
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
|
@ -1,19 +0,0 @@
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
data() {
|
||||
return {
|
||||
isEditing: this.openmct.editor.isEditing()
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.openmct.editor.on('isEditing', this.toggleEditing);
|
||||
},
|
||||
destroyed() {
|
||||
this.openmct.editor.off('isEditing', this.toggleEditing);
|
||||
},
|
||||
methods: {
|
||||
toggleEditing(value) {
|
||||
this.isEditing = value;
|
||||
}
|
||||
}
|
||||
};
|
@ -44,6 +44,7 @@ define([
|
||||
containers: [new Container.default(50), new Container.default(50)],
|
||||
rowsLayout: false
|
||||
};
|
||||
domainObject.composition = [];
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -29,7 +29,7 @@ function ToolbarProvider(openmct) {
|
||||
forSelection: function (selection) {
|
||||
let context = selection[0].context;
|
||||
|
||||
return (openmct.editor.isEditing() && context && context.type &&
|
||||
return (context && context.type &&
|
||||
(context.type === 'flexible-layout' || context.type === 'container' || context.type === 'frame'));
|
||||
},
|
||||
toolbar: function (selection) {
|
||||
@ -53,18 +53,18 @@ function ToolbarProvider(openmct) {
|
||||
toggleContainer = {
|
||||
control: 'toggle-button',
|
||||
key: 'toggle-layout',
|
||||
domainObject: secondary ? secondary.context.item : primary.context.item,
|
||||
domainObject: primary.context.item,
|
||||
property: 'configuration.rowsLayout',
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
value: true,
|
||||
icon: 'icon-columns',
|
||||
title: 'Columns'
|
||||
title: 'Columns layout'
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
value: false,
|
||||
icon: 'icon-rows',
|
||||
title: 'Rows'
|
||||
title: 'Rows layout'
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -120,14 +120,14 @@ function ToolbarProvider(openmct) {
|
||||
property: `configuration.containers[${containerIndex}].frames[${frameIndex}].noFrame`,
|
||||
options: [
|
||||
{
|
||||
value: true,
|
||||
value: false,
|
||||
icon: 'icon-frame-hide',
|
||||
title: "Hide frame"
|
||||
title: "Frame hidden"
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
value: true,
|
||||
icon: 'icon-frame-show',
|
||||
title: "Show frame"
|
||||
title: "Frame visible"
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -140,6 +140,8 @@ function ToolbarProvider(openmct) {
|
||||
title: 'Add Container'
|
||||
};
|
||||
|
||||
toggleContainer.domainObject = secondary.context.item;
|
||||
|
||||
} else if (primary.context.type === 'container') {
|
||||
|
||||
deleteContainer = {
|
||||
@ -151,7 +153,7 @@ function ToolbarProvider(openmct) {
|
||||
|
||||
let prompt = openmct.overlays.dialog({
|
||||
iconClass: 'alert',
|
||||
message: `This action will permanently delete container ${containerIndex + 1} from this Flexible Layout`,
|
||||
message: 'This action will permanently delete this container from this Flexible Layout',
|
||||
buttons: [
|
||||
{
|
||||
label: 'Ok',
|
||||
@ -202,7 +204,7 @@ function ToolbarProvider(openmct) {
|
||||
addContainer,
|
||||
toggleFrame ? separator: undefined,
|
||||
toggleFrame,
|
||||
deleteFrame || deleteContainer ? separator: undefined,
|
||||
deleteFrame || deleteContainer ? separator : undefined,
|
||||
deleteFrame,
|
||||
deleteContainer
|
||||
];
|
||||
|
@ -4,9 +4,8 @@
|
||||
@click="navigate">
|
||||
<td class="c-list-item__name">
|
||||
<a :href="objectLink" ref="objectLink">
|
||||
<div class="c-list-item__type-icon"
|
||||
:class="item.type.cssClass"></div>
|
||||
{{item.model.name}}
|
||||
<div class="c-list-item__type-icon" :class="item.type.cssClass"></div>
|
||||
<div class="c-list-item__name-value">{{item.model.name}}</div>
|
||||
</a>
|
||||
</td>
|
||||
<td class="c-list-item__type">{{ item.type.name }}</td>
|
||||
@ -20,17 +19,24 @@
|
||||
|
||||
/******************************* LIST ITEM */
|
||||
.c-list-item {
|
||||
&__name {
|
||||
@include ellipsize();
|
||||
&__name a {
|
||||
display: flex;
|
||||
|
||||
> * + * { margin-left: $interiorMarginSm; }
|
||||
}
|
||||
|
||||
&__type-icon {
|
||||
// Have to do it this way instead of using icon-* class, due to need to apply alias to the icon
|
||||
color: $colorKey;
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
margin-right:$interiorMarginSm;
|
||||
}
|
||||
|
||||
&__name-value {
|
||||
@include ellipsize();
|
||||
}
|
||||
|
||||
&.is-alias {
|
||||
// Object is an alias to an original.
|
||||
[class*='__type-icon'] {
|
||||
@ -48,7 +54,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
@ -78,9 +78,12 @@
|
||||
|
||||
td {
|
||||
$p: floor($interiorMargin * 1.5);
|
||||
font-size: 1.1em;
|
||||
@include ellipsize();
|
||||
line-height: 120%; // Needed for icon alignment
|
||||
max-width: 0;
|
||||
padding-top: $p;
|
||||
padding-bottom: $p;
|
||||
width: 25%;
|
||||
|
||||
&:not(.c-list-item__name) {
|
||||
color: $colorItemFgDetails;
|
||||
|
@ -7,18 +7,19 @@
|
||||
<div class="c-ne__embed__info">
|
||||
<div class="c-ne__embed__name">
|
||||
<a class="c-ne__embed__link"
|
||||
v-on:click="navigate(embed.type)"
|
||||
v-bind:class="[embed.cssClass]">{{embed.name}}</a>
|
||||
:href="objectLink"
|
||||
:class="embed.cssClass">{{embed.name}}</a>
|
||||
<a class="c-ne__embed__context-available icon-arrow-down"
|
||||
v-on:click="toggleActionMenu"></a>
|
||||
@click="toggleActionMenu"></a>
|
||||
</div>
|
||||
<div class="hide-menu hidden">
|
||||
<div class="menu-element context-menu-wrapper mobile-disable-select">
|
||||
<div class="menu context-menu">
|
||||
<div class="c-menu">
|
||||
<ul>
|
||||
<li v-for="action in actions"
|
||||
v-bind:class="[action.cssClass]"
|
||||
v-on:click="action.perform(embed, entry)">
|
||||
<li v-for="action in actions"
|
||||
:key="action.name"
|
||||
:class="action.cssClass"
|
||||
@click="action.perform(embed, entry)">
|
||||
{{ action.name }}
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<li class="c-notebook__entry c-ne has-local-controls"
|
||||
v-on:drop="dropOnEntry(entry.id, $event)"
|
||||
v-on:dragover="dragoverOnEntry"
|
||||
>
|
||||
@drop.prevent="dropOnEntry(entry.id, $event)">
|
||||
<div class="c-ne__time-and-content">
|
||||
<div class="c-ne__time">
|
||||
<span>{{formatTime(entry.createdOn, 'YYYY-MM-DD')}}</span>
|
||||
@ -11,18 +9,18 @@
|
||||
<div class="c-ne__text c-input-inline"
|
||||
contenteditable="true"
|
||||
ref="contenteditable"
|
||||
v-on:blur="textBlur($event, entry.id)"
|
||||
v-on:focus="textFocus($event, entry.id)"
|
||||
v-bind:key="entry.id"
|
||||
@blur="textBlur($event, entry.id)"
|
||||
@focus="textFocus($event, entry.id)"
|
||||
v-html="entry.text">
|
||||
</div>
|
||||
<div class="c-ne__embeds">
|
||||
<notebook-embed
|
||||
v-for="(embed, index) in entry.embeds"
|
||||
:key="index"
|
||||
v-for="embed in entry.embeds"
|
||||
:key="embed.id"
|
||||
:embed="embed"
|
||||
:entry="entry"
|
||||
></notebook-embed>
|
||||
:objectPath="embed.objectPath"
|
||||
:entry="entry">
|
||||
</notebook-embed>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -30,6 +28,7 @@
|
||||
<div class="c-ne__local-controls--hidden">
|
||||
<button class="c-click-icon c-click-icon--major icon-trash"
|
||||
title="Delete this entry"
|
||||
v-on:click="deleteEntry"></button>
|
||||
@click="deleteEntry">
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
@ -5,30 +5,25 @@
|
||||
@input="search"
|
||||
@clear="search">
|
||||
</search>
|
||||
<div class="c-notebook__controls">
|
||||
<div class="select c-notebook__controls__time">
|
||||
<select v-model="showTime">
|
||||
<option value="0" selected="selected">Show all</option>
|
||||
<option value="1">Last hour</option>
|
||||
<option value="8">Last 8 hours</option>
|
||||
<option value="24">Last 24 hours</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="select c-notebook__controls__sort">
|
||||
<select v-model="sortEntries">
|
||||
<option value="newest" :selected="sortEntries === 'newest'">Newest first</option>
|
||||
<option value="oldest" :selected="sortEntries === 'oldest'">Oldest first</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="c-notebook__controls ">
|
||||
<select class="c-notebook__controls__time" v-model="showTime">
|
||||
<option value="0" selected="selected">Show all</option>
|
||||
<option value="1">Last hour</option>
|
||||
<option value="8">Last 8 hours</option>
|
||||
<option value="24">Last 24 hours</option>
|
||||
</select>
|
||||
<select class="c-notebook__controls__time" v-model="sortEntries">
|
||||
<option value="newest" :selected="sortEntries === 'newest'">Newest first</option>
|
||||
<option value="oldest" :selected="sortEntries === 'oldest'">Oldest first</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-notebook__drag-area icon-plus"
|
||||
@click="newEntry($event)"
|
||||
@drop="newEntry($event)"
|
||||
id="newEntry">
|
||||
@drop="newEntry($event)">
|
||||
<span class="c-notebook__drag-area__label">To start a new entry, click here or drag and drop any object</span>
|
||||
</div>
|
||||
<div class="c-notebook__entries" ng-mouseover="handleActive()">
|
||||
<div class="c-notebook__entries">
|
||||
<ul>
|
||||
<notebook-entry
|
||||
v-for="(entry,index) in filteredAndSortedEntries"
|
||||
|
@ -34,28 +34,17 @@ function (
|
||||
Vue,
|
||||
Painterro
|
||||
) {
|
||||
function EmbedController (openmct, domainObject) {
|
||||
function EmbedController(openmct, domainObject) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.objectService = openmct.$injector.get('objectService');
|
||||
this.navigationService = openmct.$injector.get('navigationService');
|
||||
this.popupService = openmct.$injector.get('popupService');
|
||||
this.agentService = openmct.$injector.get('agentService');
|
||||
this.dialogService = openmct.$injector.get('dialogService');
|
||||
|
||||
|
||||
this.navigate = this.navigate.bind(this);
|
||||
this.exposedData = this.exposedData.bind(this);
|
||||
this.exposedMethods = this.exposedMethods.bind(this);
|
||||
this.toggleActionMenu = this.toggleActionMenu.bind(this);
|
||||
}
|
||||
|
||||
EmbedController.prototype.navigate = function (embedType) {
|
||||
this.objectService.getObjects([embedType]).then(function (objects) {
|
||||
this.navigationService.setNavigation(objects[embedType]);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
EmbedController.prototype.openSnapshot = function (domainObject, entry, embed) {
|
||||
|
||||
function annotateSnapshot(openmct) {
|
||||
@ -63,20 +52,22 @@ function (
|
||||
|
||||
var save = false,
|
||||
painterroInstance = {},
|
||||
annotateOverlay = new Vue({
|
||||
annotateVue = new Vue({
|
||||
template: '<div id="snap-annotation"></div>'
|
||||
}),
|
||||
self = this;
|
||||
|
||||
openmct.overlays.overlay({
|
||||
element: annotateOverlay.$mount().$el,
|
||||
let annotateOverlay = openmct.overlays.overlay({
|
||||
element: annotateVue.$mount().$el,
|
||||
size: 'large',
|
||||
dismissable: false,
|
||||
buttons: [
|
||||
{
|
||||
label: 'Cancel',
|
||||
callback: function () {
|
||||
save = false;
|
||||
painterroInstance.save();
|
||||
annotateOverlay.dismiss();
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -84,11 +75,12 @@ function (
|
||||
callback: function () {
|
||||
save = true;
|
||||
painterroInstance.save();
|
||||
annotateOverlay.dismiss();
|
||||
}
|
||||
}
|
||||
],
|
||||
onDestroy: function () {
|
||||
annotateOverlay.$destroy(true);
|
||||
annotateVue.$destroy(true);
|
||||
}
|
||||
});
|
||||
|
||||
@ -162,14 +154,11 @@ function (
|
||||
}
|
||||
});
|
||||
|
||||
function onDestroyCallback() {
|
||||
snapshot.$destroy(true);
|
||||
}
|
||||
|
||||
var snapshotOverlay = this.openmct.overlays.overlay({
|
||||
element: snapshot.$mount().$el,
|
||||
onDestroy: onDestroyCallback,
|
||||
onDestroy: () => {snapshot.$destroy(true)},
|
||||
size: 'large',
|
||||
dismissable: true,
|
||||
buttons: [
|
||||
{
|
||||
label: 'Done',
|
||||
@ -199,23 +188,20 @@ function (
|
||||
return foundId;
|
||||
};
|
||||
|
||||
EmbedController.prototype.actionToMenuDecorator = function (action) {
|
||||
return {
|
||||
name: action.getMetadata().name,
|
||||
cssClass: action.getMetadata().cssClass,
|
||||
perform: action.perform
|
||||
};
|
||||
};
|
||||
|
||||
EmbedController.prototype.populateActionMenu = function (objectService, actionService) {
|
||||
EmbedController.prototype.populateActionMenu = function (openmct, actions) {
|
||||
return function () {
|
||||
var self = this;
|
||||
|
||||
objectService.getObjects([self.embed.type]).then(function (resp) {
|
||||
var domainObject = resp[self.embed.type],
|
||||
previewAction = actionService.getActions({key: 'mct-preview-action', domainObject: domainObject})[0];
|
||||
|
||||
self.actions.push(self.actionToMenuDecorator(previewAction));
|
||||
openmct.objects.get(self.embed.type).then(function (domainObject) {
|
||||
actions.forEach((action) => {
|
||||
self.actions.push({
|
||||
cssClass: action.cssClass,
|
||||
name: action.name,
|
||||
perform: () => {
|
||||
action.invoke([domainObject].concat(openmct.router.path));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
@ -268,13 +254,14 @@ function (
|
||||
// Remove the context menu
|
||||
function dismiss() {
|
||||
container.find('.hide-menu').append(menu);
|
||||
body.off(initiatingEvent, dismiss);
|
||||
menu.off(initiatingEvent, menuClickHandler);
|
||||
body.off(initiatingEvent, menuClickHandler);
|
||||
dismissExistingMenu = undefined;
|
||||
}
|
||||
|
||||
function menuClickHandler(e) {
|
||||
e.stopPropagation();
|
||||
window.setTimeout(() => {
|
||||
dismiss();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Dismiss any menu which was already showing
|
||||
@ -290,11 +277,7 @@ function (
|
||||
marginY: -50
|
||||
});
|
||||
|
||||
// Stop propagation so that clicks or touches on the menu do not close the menu
|
||||
menu.on(initiatingEvent, menuClickHandler);
|
||||
|
||||
body.on(initiatingEvent, dismiss);
|
||||
|
||||
body.on(initiatingEvent, menuClickHandler);
|
||||
};
|
||||
|
||||
EmbedController.prototype.exposedData = function () {
|
||||
@ -308,11 +291,9 @@ function (
|
||||
var self = this;
|
||||
|
||||
return {
|
||||
navigate: self.navigate,
|
||||
openSnapshot: self.openSnapshot,
|
||||
formatTime: self.formatTime,
|
||||
toggleActionMenu: self.toggleActionMenu,
|
||||
actionToMenuDecorator: self.actionToMenuDecorator,
|
||||
findInArray: self.findInArray
|
||||
};
|
||||
};
|
||||
|
@ -30,8 +30,6 @@ function (
|
||||
function EntryController (openmct, domainObject) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.dndService = this.openmct.$injector.get('dndService');
|
||||
this.dialogService = this.openmct.$injector.get('dialogService');
|
||||
|
||||
this.currentEntryValue = '';
|
||||
|
||||
@ -106,37 +104,35 @@ function (
|
||||
};
|
||||
|
||||
EntryController.prototype.dropOnEntry = function (entryid, event) {
|
||||
|
||||
var data = event.dataTransfer.getData('domainObject');
|
||||
var data = event.dataTransfer.getData('openmct/domain-object-path');
|
||||
|
||||
if (data) {
|
||||
var selectedObject = JSON.parse(data),
|
||||
selectedObjectId = selectedObject.identifier.key,
|
||||
cssClass = this.openmct.types.get(selectedObject.type),
|
||||
var objectPath = JSON.parse(data),
|
||||
domainObject = objectPath[0],
|
||||
domainObjectKey = domainObject.identifier.key,
|
||||
domainObjectType = this.openmct.types.get(domainObject.type),
|
||||
cssClass = domainObjectType && domainObjectType.definition ?
|
||||
domainObjectType.definition.cssClass : 'icon-object-unknown',
|
||||
entryPos = this.entryPosById(entryid),
|
||||
currentEntryEmbeds = this.domainObject.entries[entryPos].embeds,
|
||||
newEmbed = {
|
||||
type: selectedObjectId,
|
||||
id: '' + Date.now(),
|
||||
domainObject: domainObject,
|
||||
objectPath: objectPath,
|
||||
type: domainObjectKey,
|
||||
cssClass: cssClass,
|
||||
name: selectedObject.name,
|
||||
name: domainObject.name,
|
||||
snapshot: ''
|
||||
};
|
||||
|
||||
currentEntryEmbeds.push(newEmbed);
|
||||
this.openmct.objects.mutate(this.domainObject, 'entries[' + entryPos + '].embeds', currentEntryEmbeds);
|
||||
}
|
||||
};
|
||||
|
||||
EntryController.prototype.dragoverOnEntry = function () {
|
||||
|
||||
};
|
||||
|
||||
EntryController.prototype.exposedData = function () {
|
||||
return {
|
||||
openmct: this.openmct,
|
||||
domainObject: this.domainObject,
|
||||
dialogService: this.dialogService,
|
||||
currentEntryValue: this.currentEntryValue
|
||||
};
|
||||
};
|
||||
@ -148,8 +144,7 @@ function (
|
||||
textBlur: this.textBlur,
|
||||
formatTime: this.formatTime,
|
||||
deleteEntry: this.deleteEntry,
|
||||
dropOnEntry: this.dropOnEntry,
|
||||
dragoverOnEntry: this.dragoverOnEntry
|
||||
dropOnEntry: this.dropOnEntry
|
||||
};
|
||||
};
|
||||
return EntryController;
|
||||
|
@ -27,7 +27,9 @@ define([
|
||||
'../../res/templates/notebook.html',
|
||||
'../../res/templates/entry.html',
|
||||
'../../res/templates/embed.html',
|
||||
'../../../../ui/components/search.vue'
|
||||
'../../../../ui/components/search.vue',
|
||||
'../../../../ui/preview/PreviewAction',
|
||||
'../../../../ui/mixins/object-link'
|
||||
],
|
||||
function (
|
||||
Vue,
|
||||
@ -36,15 +38,16 @@ function (
|
||||
NotebookTemplate,
|
||||
EntryTemplate,
|
||||
EmbedTemplate,
|
||||
search
|
||||
search,
|
||||
PreviewAction,
|
||||
objectLinkMixin
|
||||
) {
|
||||
|
||||
function NotebookController(openmct, domainObject) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.entrySearch = '';
|
||||
this.objectService = openmct.$injector.get('objectService');
|
||||
this.actionService = openmct.$injector.get('actionService');
|
||||
this.previewAction = new PreviewAction.default(openmct);
|
||||
|
||||
this.show = this.show.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
@ -61,11 +64,12 @@ function (
|
||||
|
||||
var notebookEmbed = {
|
||||
inject:['openmct', 'domainObject'],
|
||||
mixins:[objectLinkMixin.default],
|
||||
props:['embed', 'entry'],
|
||||
template: EmbedTemplate,
|
||||
data: embedController.exposedData,
|
||||
methods: embedController.exposedMethods(),
|
||||
beforeMount: embedController.populateActionMenu(self.objectService, self.actionService)
|
||||
beforeMount: embedController.populateActionMenu(self.openmct, [self.previewAction])
|
||||
};
|
||||
|
||||
var entryComponent = {
|
||||
@ -120,8 +124,8 @@ function (
|
||||
var date = Date.now(),
|
||||
embed;
|
||||
|
||||
if (event.dataTransfer && event.dataTransfer.getData('domainObject')) {
|
||||
var selectedObject = JSON.parse(event.dataTransfer.getData('domainObject')),
|
||||
if (event.dataTransfer && event.dataTransfer.getData('openmct/domain-object-path')) {
|
||||
var selectedObject = JSON.parse(event.dataTransfer.getData('openmct/domain-object-path'))[0],
|
||||
selectedObjectId = selectedObject.identifier.key,
|
||||
cssClass = this.openmct.types.get(selectedObject.type);
|
||||
|
||||
|
@ -41,28 +41,24 @@
|
||||
<div class="grid-cell label"
|
||||
title="The field to be plotted as a value for this series.">Value</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.yKey">
|
||||
<option ng-repeat="option in yKeyOptions"
|
||||
value="{{option.value}}"
|
||||
ng-selected="option.value == form.yKey">
|
||||
{{option.name}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.yKey">
|
||||
<option ng-repeat="option in yKeyOptions"
|
||||
value="{{option.value}}"
|
||||
ng-selected="option.value == form.yKey">
|
||||
{{option.name}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
<div class="grid-cell label"
|
||||
title="The line rendering style for this series.">Line Style</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.interpolate">
|
||||
<option value="none">None</option>
|
||||
<option value="linear">Linear interpolate</option>
|
||||
<option value="stepAfter">Step after</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.interpolate">
|
||||
<option value="none">None</option>
|
||||
<option value="linear">Linear interpolate</option>
|
||||
<option value="stepAfter">Step after</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
@ -160,15 +156,13 @@
|
||||
<div class="grid-cell label"
|
||||
title="The position of the legend relative to the plot display area.">Position</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.position">
|
||||
<option value="hidden">Hidden</option>
|
||||
<option value="top">Top</option>
|
||||
<option value="right">Right</option>
|
||||
<option value="bottom">Bottom</option>
|
||||
<option value="left">Left</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.position">
|
||||
<option value="hidden">Hidden</option>
|
||||
<option value="top">Top</option>
|
||||
<option value="right">Right</option>
|
||||
<option value="bottom">Bottom</option>
|
||||
<option value="left">Left</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
@ -180,15 +174,13 @@
|
||||
<div class="grid-cell label"
|
||||
title="What to display in the legend when it's collapsed.">When collapsed show</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="select">
|
||||
<select ng-model="form.valueToShowWhenCollapsed">
|
||||
<option value="none">nothing</option>
|
||||
<option value="nearestTimestamp">nearest timestamp</option>
|
||||
<option value="nearestValue">nearest Value</option>
|
||||
<option value="min">minimum value</option>
|
||||
<option value="max">maximum value</option>
|
||||
</select>
|
||||
</div>
|
||||
<select ng-model="form.valueToShowWhenCollapsed">
|
||||
<option value="none">Nothing</option>
|
||||
<option value="nearestTimestamp">Nearest timestamp</option>
|
||||
<option value="nearestValue">Nearest value</option>
|
||||
<option value="min">Minimum value</option>
|
||||
<option value="max">Maximum value</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
|
@ -30,7 +30,7 @@ define(
|
||||
],
|
||||
function (
|
||||
html2canvas,
|
||||
saveAs
|
||||
{ saveAs }
|
||||
) {
|
||||
|
||||
/**
|
||||
|
@ -39,9 +39,7 @@ define([
|
||||
'./folderView/plugin',
|
||||
'./flexibleLayout/plugin',
|
||||
'./tabs/plugin',
|
||||
'../../platform/features/fixed/plugin',
|
||||
'./LADTable/plugin',
|
||||
'./preview/plugin'
|
||||
'./LADTable/plugin'
|
||||
], function (
|
||||
_,
|
||||
UTCTimeSystem,
|
||||
@ -61,9 +59,7 @@ define([
|
||||
FolderView,
|
||||
FlexibleLayout,
|
||||
Tabs,
|
||||
FixedView,
|
||||
LADTable,
|
||||
PreviewPlugin
|
||||
LADTable
|
||||
) {
|
||||
var bundleMap = {
|
||||
LocalStorage: 'platform/persistence/local',
|
||||
@ -176,10 +172,8 @@ define([
|
||||
plugins.DisplayLayout = DisplayLayoutPlugin.default;
|
||||
plugins.FolderView = FolderView;
|
||||
plugins.Tabs = Tabs;
|
||||
plugins.FixedView = FixedView;
|
||||
plugins.FlexibleLayout = FlexibleLayout;
|
||||
plugins.LADTable = LADTable;
|
||||
plugins.Preview = PreviewPlugin.default;
|
||||
|
||||
return plugins;
|
||||
});
|
||||
|
@ -24,16 +24,10 @@ define([
|
||||
return domainObject.type === 'summary-widget';
|
||||
},
|
||||
view: function (domainObject) {
|
||||
var statusService = openmct.$injector.get('statusService');
|
||||
var objectId = objectUtils.makeKeyString(domainObject.identifier);
|
||||
var statuses = statusService.listStatuses(objectId);
|
||||
var isEditing = statuses.indexOf('editing') !== -1;
|
||||
|
||||
if (isEditing) {
|
||||
return new SummaryWidgetEditView(domainObject, openmct);
|
||||
} else {
|
||||
return new SummaryWidgetView(domainObject, openmct);
|
||||
}
|
||||
return new SummaryWidgetView(domainObject, openmct);
|
||||
},
|
||||
edit: function (domainObject) {
|
||||
return new SummaryWidgetEditView(domainObject, openmct);
|
||||
},
|
||||
priority: function (domainObject) {
|
||||
if (domainObject.type === 'summary-widget') {
|
||||
|
@ -15,25 +15,25 @@
|
||||
v-for="(tab,index) in tabsList"
|
||||
:key="index"
|
||||
:class="[
|
||||
{'is-current': tab=== currentTab},
|
||||
{'is-current': isCurrent(tab)},
|
||||
tab.type.definition.cssClass
|
||||
]"
|
||||
@click="showTab(tab)">
|
||||
<span class="c-button__label">{{tab.model.name}}</span>
|
||||
<span class="c-button__label">{{tab.domainObject.name}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="c-tabs-view__object-holder"
|
||||
v-for="(object, index) in tabsList"
|
||||
v-for="(tab, index) in tabsList"
|
||||
:key="index"
|
||||
:class="{'invisible': object !== currentTab}">
|
||||
:class="{'invisible': !isCurrent(tab)}">
|
||||
<div class="c-tabs-view__object-name l-browse-bar__object-name--w"
|
||||
:class="currentTab.type.definition.cssClass">
|
||||
<div class="l-browse-bar__object-name">
|
||||
{{currentTab.model.name}}
|
||||
{{currentTab.domainObject.name}}
|
||||
</div>
|
||||
</div>
|
||||
<object-view class="c-tabs-view__object"
|
||||
:object="object.model">
|
||||
:object="tab.domainObject">
|
||||
</object-view>
|
||||
</div>
|
||||
</div>
|
||||
@ -87,6 +87,7 @@
|
||||
|
||||
<script>
|
||||
import ObjectView from '../../../ui/components/ObjectView.vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
var unknownObjectType = {
|
||||
definition: {
|
||||
@ -100,9 +101,71 @@ export default {
|
||||
components: {
|
||||
ObjectView
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
currentTab: {},
|
||||
tabsList: [],
|
||||
setCurrentTab: true,
|
||||
isDragging: false,
|
||||
allowDrop: false
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
showTab(tab) {
|
||||
this.currentTab = tab;
|
||||
},
|
||||
addItem(domainObject) {
|
||||
let type = this.openmct.types.get(domainObject.type) || unknownObjectType,
|
||||
tabItem = {
|
||||
domainObject,
|
||||
type: type
|
||||
};
|
||||
|
||||
this.tabsList.push(tabItem);
|
||||
|
||||
if (this.setCurrentTab) {
|
||||
this.currentTab = tabItem;
|
||||
this.setCurrentTab = false;
|
||||
}
|
||||
},
|
||||
removeItem(identifier) {
|
||||
let pos = this.tabsList.findIndex(tab =>
|
||||
tab.domainObject.identifier.namespace === identifier.namespace && tab.domainObject.identifier.key === identifier.key
|
||||
),
|
||||
tabToBeRemoved = this.tabsList[pos];
|
||||
|
||||
this.tabsList.splice(pos, 1);
|
||||
|
||||
if (this.isCurrent(tabToBeRemoved)) {
|
||||
this.showTab(this.tabsList[this.tabsList.length - 1]);
|
||||
}
|
||||
},
|
||||
onDrop(e) {
|
||||
this.setCurrentTab = true;
|
||||
},
|
||||
dragstart (e) {
|
||||
if (e.dataTransfer.types.includes('openmct/domain-object-path')) {
|
||||
this.isDragging = true;
|
||||
}
|
||||
},
|
||||
dragend(e) {
|
||||
this.isDragging = false;
|
||||
this.allowDrop = false;
|
||||
},
|
||||
dragenter() {
|
||||
this.allowDrop = true;
|
||||
},
|
||||
dragleave() {
|
||||
this.allowDrop = false;
|
||||
},
|
||||
isCurrent(tab) {
|
||||
return _.isEqual(this.currentTab, tab)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.composition) {
|
||||
this.composition.on('add', this.addItem, this);
|
||||
this.composition.on('add', this.addItem);
|
||||
this.composition.on('remove', this.removeItem);
|
||||
this.composition.load();
|
||||
}
|
||||
|
||||
@ -116,54 +179,9 @@ export default {
|
||||
dropHint.addEventListener('dragleave', this.dragleave);
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
currentTab: {},
|
||||
tabsList: [],
|
||||
setCurrentTab: true,
|
||||
isDragging: false,
|
||||
allowDrop: false
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
showTab (tab) {
|
||||
this.currentTab = tab;
|
||||
},
|
||||
addItem (model) {
|
||||
let type = this.openmct.types.get(model.type) || unknownObjectType,
|
||||
tabItem = {
|
||||
model,
|
||||
type: type
|
||||
};
|
||||
|
||||
this.tabsList.push(tabItem);
|
||||
|
||||
if (this.setCurrentTab) {
|
||||
this.currentTab = tabItem;
|
||||
this.setCurrentTab = false;
|
||||
}
|
||||
},
|
||||
onDrop (e) {
|
||||
this.setCurrentTab = true;
|
||||
},
|
||||
dragstart (e) {
|
||||
if (e.dataTransfer.getData('domainObject')) {
|
||||
this.isDragging = true;
|
||||
}
|
||||
},
|
||||
dragend (e) {
|
||||
this.isDragging = false;
|
||||
this.allowDrop = false;
|
||||
},
|
||||
dragenter () {
|
||||
this.allowDrop = true;
|
||||
},
|
||||
dragleave() {
|
||||
this.allowDrop = false;
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.composition.off('add', this.addItem, this);
|
||||
this.composition.off('add', this.addItem);
|
||||
this.composition.off('remove', this.removeItem);
|
||||
|
||||
document.removeEventListener('dragstart', this.dragstart);
|
||||
document.removeEventListener('dragend', this.dragend);
|
||||
|
@ -79,8 +79,8 @@ define([
|
||||
|
||||
loadComposition() {
|
||||
this.tableComposition = this.openmct.composition.get(this.domainObject);
|
||||
if (this.tableComposition !== undefined){
|
||||
this.tableComposition.load().then((composition)=>{
|
||||
if (this.tableComposition !== undefined) {
|
||||
this.tableComposition.load().then((composition) => {
|
||||
composition = composition.filter(this.isTelemetryObject);
|
||||
|
||||
this.configuration.addColumnsForAllObjects(composition);
|
||||
@ -122,7 +122,6 @@ define([
|
||||
|
||||
let telemetryRows = telemetryData.map(datum => new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
|
||||
this.boundedRows.add(telemetryRows);
|
||||
console.log('Loaded %i rows', telemetryRows.length);
|
||||
this.decrementOutstandingRequests();
|
||||
});
|
||||
}
|
||||
@ -131,7 +130,7 @@ define([
|
||||
* @private
|
||||
*/
|
||||
incrementOutstandingRequests() {
|
||||
if (this.outstandingRequests === 0){
|
||||
if (this.outstandingRequests === 0) {
|
||||
this.emit('outstanding-requests', true);
|
||||
}
|
||||
this.outstandingRequests++;
|
||||
@ -143,7 +142,7 @@ define([
|
||||
decrementOutstandingRequests() {
|
||||
this.outstandingRequests--;
|
||||
|
||||
if (this.outstandingRequests === 0){
|
||||
if (this.outstandingRequests === 0) {
|
||||
this.emit('outstanding-requests', false);
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ define([
|
||||
objectMutated(object) {
|
||||
//Synchronize domain object reference. Duplicate object otherwise change detection becomes impossible.
|
||||
this.domainObject = object;
|
||||
//Was it the configuration that changed?
|
||||
if (!_.eq(object.configuration, this.oldConfiguration)) {
|
||||
//Make copy of configuration, otherwise change detection is impossible if shared instance is being modified.
|
||||
this.oldConfiguration = JSON.parse(JSON.stringify(this.getConfiguration()));
|
||||
@ -91,16 +92,19 @@ define([
|
||||
let columnsToRemove = this.columns[objectKeyString];
|
||||
|
||||
delete this.columns[objectKeyString];
|
||||
|
||||
let configuration = this.domainObject.configuration;
|
||||
let configurationChanged = false;
|
||||
columnsToRemove.forEach((column) => {
|
||||
//There may be more than one column with the same key (eg. time system columns)
|
||||
if (!this.hasColumnWithKey(column.getKey())) {
|
||||
let configuration = this.domainObject.configuration;
|
||||
delete configuration.hiddenColumns[column.getKey()];
|
||||
// If there are no more columns with this key, delete any configuration, and trigger
|
||||
// a column refresh.
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration', configuration);
|
||||
configurationChanged = true;
|
||||
}
|
||||
});
|
||||
if (configurationChanged) {
|
||||
this.updateConfiguration(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
hasColumnWithKey(columnKey) {
|
||||
|
@ -47,8 +47,13 @@ define([
|
||||
let table = new TelemetryTable(domainObject, openmct);
|
||||
let component;
|
||||
return {
|
||||
show: function (element) {
|
||||
show: function (element, isEditing) {
|
||||
component = new Vue({
|
||||
data() {
|
||||
return {
|
||||
isEditing: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
TableComponent: TableComponent.default,
|
||||
},
|
||||
@ -58,9 +63,12 @@ define([
|
||||
table
|
||||
},
|
||||
el: element,
|
||||
template: '<table-component></table-component>'
|
||||
template: '<table-component :isEditing="isEditing"></table-component>'
|
||||
});
|
||||
},
|
||||
onEditModeChange(isEditing) {
|
||||
component.isEditing = isEditing;
|
||||
},
|
||||
destroy: function (element) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
|
@ -73,18 +73,14 @@ const MOVE_COLUMN_DT_TYPE = 'movecolumnfromindex';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
data() {
|
||||
return {
|
||||
isEditing: this.openmct.editor.isEditing()
|
||||
}
|
||||
},
|
||||
props: {
|
||||
headerKey: String,
|
||||
headerIndex: Number,
|
||||
isHeaderTitle: Boolean,
|
||||
sortOptions: Object,
|
||||
columnWidth: Number,
|
||||
hotzone: Boolean
|
||||
hotzone: Boolean,
|
||||
isEditing: Boolean
|
||||
},
|
||||
computed: {
|
||||
isSortable() {
|
||||
@ -167,16 +163,7 @@ export default {
|
||||
},
|
||||
sort() {
|
||||
this.$emit("sort");
|
||||
},
|
||||
toggleEditMode(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.openmct.editor.on('isEditing', this.toggleEditMode);
|
||||
},
|
||||
destroyed() {
|
||||
this.openmct.editor.off('isEditing', this.toggleEditMode);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -34,7 +34,7 @@
|
||||
<div class="c-telemetry-table__headers-w js-table__headers-w" ref="headersTable" :style="{ 'max-width': widthWithScroll}">
|
||||
<table class="c-table__headers c-telemetry-table__headers">
|
||||
<thead>
|
||||
<tr>
|
||||
<tr class="c-telemetry-table__headers__name">
|
||||
<table-column-header
|
||||
v-for="(title, key, headerIndex) in headers"
|
||||
:key="key"
|
||||
@ -48,9 +48,10 @@
|
||||
@resizeColumnEnd="updateConfiguredColumnWidths"
|
||||
:columnWidth="columnWidths[key]"
|
||||
:sortOptions="sortOptions"
|
||||
:isEditing="isEditing"
|
||||
>{{title}}</table-column-header>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="c-telemetry-table__headers__filter">
|
||||
<table-column-header
|
||||
v-for="(title, key, headerIndex) in headers"
|
||||
:key="key"
|
||||
@ -61,7 +62,9 @@
|
||||
@dropTargetActive="dropTargetActive"
|
||||
@reorderColumn="reorderColumn"
|
||||
@resizeColumnEnd="updateConfiguredColumnWidths"
|
||||
:columnWidth="columnWidths[key]">
|
||||
:columnWidth="columnWidths[key]"
|
||||
:isEditing="isEditing"
|
||||
>
|
||||
<search class="c-table__search"
|
||||
v-model="filters[key]"
|
||||
v-on:input="filterChanged(key)"
|
||||
@ -110,8 +113,8 @@
|
||||
.c-telemetry-table__drop-target {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
background-color: $editColor;
|
||||
box-shadow: rgba($editColor, 0.5) 0 0 10px;
|
||||
background-color: $editUIColor;
|
||||
box-shadow: rgba($editUIColor, 0.5) 0 0 10px;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
@ -214,6 +217,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
/******************************* EDITING */
|
||||
.is-editing {
|
||||
.c-telemetry-table__headers__name {
|
||||
th[draggable],
|
||||
th[draggable] > * {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
th[draggable]:hover {
|
||||
$b: $editFrameHovMovebarColorBg;
|
||||
background: $b;
|
||||
> * { background: $b; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************* LEGACY */
|
||||
.s-status-taking-snapshot,
|
||||
.overlay.snapshot {
|
||||
@ -244,6 +263,12 @@ export default {
|
||||
search
|
||||
},
|
||||
inject: ['table', 'openmct', 'csvExporter'],
|
||||
props: {
|
||||
isEditing: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
let configuration = this.table.configuration.getConfiguration();
|
||||
|
||||
|
@ -22,9 +22,8 @@
|
||||
<template>
|
||||
<div class="c-conductor"
|
||||
:class="[isFixed ? 'is-fixed-mode' : 'is-realtime-mode']">
|
||||
<form class="u-contents" ref="conductorForm"
|
||||
@submit="isFixed ? setBoundsFromView($event) : setOffsetsFromView($event)">
|
||||
|
||||
<form class="u-contents" ref="conductorForm" @submit.prevent="updateTimeFromConductor">
|
||||
<button class="c-input--submit" type="submit" ref="submitButton"></button>
|
||||
<ConductorModeIcon class="c-conductor__mode-icon"></ConductorModeIcon>
|
||||
|
||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__start-fixed"
|
||||
@ -35,8 +34,9 @@
|
||||
type="text" autocorrect="off" spellcheck="false"
|
||||
ref="startDate"
|
||||
v-model="formattedBounds.start"
|
||||
@change="validateBounds('start', $event.target); setBoundsFromView()" />
|
||||
@change="validateAllBounds(); submitForm()" />
|
||||
<date-picker
|
||||
v-if="isFixed && isUTCBased"
|
||||
:default-date-time="formattedBounds.start"
|
||||
:formatter="timeFormatter"
|
||||
@date-selected="startDateSelected"></date-picker>
|
||||
@ -48,9 +48,10 @@
|
||||
<div class="c-direction-indicator icon-minus"></div>
|
||||
<input class="c-input--hrs-min-sec"
|
||||
type="text" autocorrect="off"
|
||||
ref="startOffset"
|
||||
spellcheck="false"
|
||||
v-model="offsets.start"
|
||||
@change="validateOffsets($event); setOffsetsFromView()">
|
||||
@change="validateAllOffsets(); submitForm()">
|
||||
</div>
|
||||
|
||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__end-fixed">
|
||||
@ -63,13 +64,13 @@
|
||||
v-model="formattedBounds.end"
|
||||
:disabled="!isFixed"
|
||||
ref="endDate"
|
||||
@change="validateBounds('end', $event.target); setBoundsFromView()">
|
||||
@change="validateAllBounds(); submitForm()">
|
||||
<date-picker
|
||||
v-if="isFixed && isUTCBased"
|
||||
class="c-ctrl-wrapper--menus-left"
|
||||
:default-date-time="formattedBounds.end"
|
||||
:formatter="timeFormatter"
|
||||
@date-selected="endDateSelected"
|
||||
v-if="isFixed"></date-picker>
|
||||
@date-selected="endDateSelected"></date-picker>
|
||||
</div>
|
||||
|
||||
<div class="c-ctrl-wrapper c-conductor-input c-conductor__end-delta"
|
||||
@ -80,8 +81,9 @@
|
||||
type="text"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
ref="endOffset"
|
||||
v-model="offsets.end"
|
||||
@change="validateOffsets($event); setOffsetsFromView()">
|
||||
@change="validateAllOffsets(); submitForm()">
|
||||
</div>
|
||||
|
||||
<conductor-axis
|
||||
@ -101,6 +103,14 @@
|
||||
<style lang="scss">
|
||||
@import "~styles/sass-base";
|
||||
|
||||
.c-input--submit {
|
||||
// Can't use display: none because some browsers will pretend the input doesn't exist, and enter won't work
|
||||
visibility: none;
|
||||
height: 0;
|
||||
width: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*********************************************** CONDUCTOR LAYOUT */
|
||||
.c-conductor {
|
||||
display: grid;
|
||||
@ -357,6 +367,7 @@ export default {
|
||||
},
|
||||
setViewFromClock(clock) {
|
||||
this.isFixed = clock === undefined;
|
||||
this.clearAllValidation();
|
||||
},
|
||||
setViewFromBounds(bounds) {
|
||||
this.formattedBounds.start = this.timeFormatter.format(bounds.start);
|
||||
@ -368,45 +379,87 @@ export default {
|
||||
this.offsets.start = this.durationFormatter.format(Math.abs(offsets.start));
|
||||
this.offsets.end = this.durationFormatter.format(Math.abs(offsets.end));
|
||||
},
|
||||
validateBounds(startOrEnd, input) {
|
||||
let validationResult = true;
|
||||
|
||||
if (!this.timeFormatter.validate(input.value)){
|
||||
validationResult = 'Invalid date value';
|
||||
updateTimeFromConductor() {
|
||||
if (this.isFixed) {
|
||||
this.setBoundsFromView();
|
||||
} else {
|
||||
let boundsValues = {
|
||||
start: this.timeFormatter.parse(this.formattedBounds.start),
|
||||
end: this.timeFormatter.parse(this.formattedBounds.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateBounds(boundsValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
this.setOffsetsFromView();
|
||||
}
|
||||
},
|
||||
validateOffsets(event) {
|
||||
let input = event.target;
|
||||
let validationResult = true;
|
||||
|
||||
if (!this.durationFormatter.validate(input.value)) {
|
||||
validationResult = 'Invalid offset value';
|
||||
} else {
|
||||
let offsetValues = {
|
||||
start: 0 - this.durationFormatter.parse(this.offsets.start),
|
||||
end: this.durationFormatter.parse(this.offsets.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateOffsets(offsetValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
} else {
|
||||
clearAllValidation() {
|
||||
[this.$refs.startDate, this.$refs.endDate, this.$refs.startOffset, this.$refs.endOffset].forEach((input) => {
|
||||
input.setCustomValidity('');
|
||||
}
|
||||
input.title = '';
|
||||
});
|
||||
},
|
||||
validateAllBounds() {
|
||||
return [this.$refs.startDate, this.$refs.endDate].every((input) => {
|
||||
let validationResult = true;
|
||||
let formattedDate;
|
||||
|
||||
if (input === this.$refs.startDate) {
|
||||
formattedDate = this.formattedBounds.start;
|
||||
} else {
|
||||
formattedDate = this.formattedBounds.end;
|
||||
}
|
||||
|
||||
if (!this.timeFormatter.validate(formattedDate)){
|
||||
validationResult = 'Invalid date';
|
||||
} else {
|
||||
let boundsValues = {
|
||||
start: this.timeFormatter.parse(this.formattedBounds.start),
|
||||
end: this.timeFormatter.parse(this.formattedBounds.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateBounds(boundsValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
input.title = validationResult;
|
||||
return false;
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
validateAllOffsets(event) {
|
||||
return [this.$refs.startOffset, this.$refs.endOffset].every((input) => {
|
||||
let validationResult = true;
|
||||
let formattedOffset;
|
||||
|
||||
if (input === this.$refs.startOffset) {
|
||||
formattedOffset = this.offsets.start;
|
||||
} else {
|
||||
formattedOffset = this.offsets.end;
|
||||
}
|
||||
|
||||
if (!this.durationFormatter.validate(formattedOffset)) {
|
||||
validationResult = 'Offsets must be in the format hh:mm:ss and less than 24 hours in duration';
|
||||
} else {
|
||||
let offsetValues = {
|
||||
start: 0 - this.durationFormatter.parse(this.offsets.start),
|
||||
end: this.durationFormatter.parse(this.offsets.end)
|
||||
};
|
||||
validationResult = this.openmct.time.validateOffsets(offsetValues);
|
||||
}
|
||||
|
||||
if (validationResult !== true){
|
||||
input.setCustomValidity(validationResult);
|
||||
input.title = validationResult;
|
||||
return false;
|
||||
} else {
|
||||
input.setCustomValidity('');
|
||||
input.title = '';
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
submitForm() {
|
||||
// Allow Vue model to catch up to user input.
|
||||
// Submitting form will cause validation messages to display (but only if triggered by button click)
|
||||
this.$nextTick(() => this.$refs.submitButton.click());
|
||||
},
|
||||
getFormatter(key) {
|
||||
return this.openmct.telemetry.getValueFormatter({
|
||||
@ -415,13 +468,13 @@ export default {
|
||||
},
|
||||
startDateSelected(date){
|
||||
this.formattedBounds.start = this.timeFormatter.format(date);
|
||||
this.validateBounds('start', this.$refs.startDate);
|
||||
this.setBoundsFromView();
|
||||
this.validateAllBounds();
|
||||
this.submitForm();
|
||||
},
|
||||
endDateSelected(date){
|
||||
this.formattedBounds.end = this.timeFormatter.format(date);
|
||||
this.validateBounds('end', this.$refs.endDate);
|
||||
this.setBoundsFromView();
|
||||
this.validateAllBounds();
|
||||
this.submitForm();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user