mirror of
https://github.com/nasa/openmct.git
synced 2025-06-29 20:23:04 +00:00
Compare commits
26 Commits
table-perf
...
table-colu
Author | SHA1 | Date | |
---|---|---|---|
ca88996d86 | |||
4111c12895 | |||
b6ec023920 | |||
e8e7067993 | |||
0e9319e97b | |||
df53af7b4d | |||
bcbf244fd2 | |||
7ff5febae0 | |||
019d108bb2 | |||
a14f628ca3 | |||
6116351dad | |||
23efef4469 | |||
95549f7be2 | |||
6338bd1168 | |||
f7d0d2c166 | |||
7c2e10ba0e | |||
350d3c92e7 | |||
0f2918efaf | |||
b72ad529aa | |||
f77c6c821c | |||
248f160e73 | |||
5151f90bb8 | |||
402062110d | |||
1c8f23dea1 | |||
5ee22b3481 | |||
322a7bd5a8 |
@ -27,7 +27,7 @@
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title></title>
|
||||
<script src="dist/openmct.js"></script>
|
||||
<link rel="stylesheet" href="dist/openmct.css">
|
||||
<link rel="stylesheet" href="dist/styles/openmct.css">
|
||||
<link rel="icon" type="image/png" href="dist/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="dist/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="dist/favicons/favicon-16x16.png" sizes="16x16">
|
||||
@ -81,6 +81,8 @@
|
||||
openmct.install(openmct.plugins.Tabs());
|
||||
openmct.install(openmct.plugins.FlexibleLayout());
|
||||
openmct.install(openmct.plugins.LADTable());
|
||||
openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
|
||||
openmct.install(openmct.plugins.ObjectMigration());
|
||||
openmct.start();
|
||||
</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",
|
||||
|
@ -28,6 +28,7 @@ define([
|
||||
"./res/templates/dialog.html",
|
||||
"./res/templates/overlay-blocking-message.html",
|
||||
"./res/templates/message.html",
|
||||
"./res/templates/notification-message.html",
|
||||
"./res/templates/overlay-message-list.html",
|
||||
"./res/templates/overlay.html",
|
||||
'legacyRegistry'
|
||||
@ -39,6 +40,7 @@ define([
|
||||
dialogTemplate,
|
||||
overlayBlockingMessageTemplate,
|
||||
messageTemplate,
|
||||
notificationMessageTemplate,
|
||||
overlayMessageListTemplate,
|
||||
overlayTemplate,
|
||||
legacyRegistry
|
||||
@ -88,6 +90,10 @@ define([
|
||||
"key": "message",
|
||||
"template": messageTemplate
|
||||
},
|
||||
{
|
||||
"key": "notification-message",
|
||||
"template": notificationMessageTemplate
|
||||
},
|
||||
{
|
||||
"key": "overlay-message-list",
|
||||
"template": overlayMessageListTemplate
|
||||
|
@ -19,24 +19,24 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="abs top-bar">
|
||||
<div class="dialog-title">{{ngModel.title}}</div>
|
||||
<div class="hint">All fields marked <span class="req icon-asterisk"></span> are required.</div>
|
||||
<div class="c-overlay__top-bar">
|
||||
<div class="c-overlay__dialog-title">{{ngModel.title}}</div>
|
||||
<div class="c-overlay__dialog-hint hint">All fields marked <span class="req icon-asterisk"></span> are required.</div>
|
||||
</div>
|
||||
<div class='abs editor'>
|
||||
<div class='c-overlay__contents-main'>
|
||||
<mct-form ng-model="ngModel.value"
|
||||
structure="ngModel.structure"
|
||||
class="validates"
|
||||
name="createForm">
|
||||
</mct-form>
|
||||
</div>
|
||||
<div class="abs bottom-bar">
|
||||
<a class='s-button major'
|
||||
<div class="c-overlay__button-bar">
|
||||
<a class='c-button c-button--major'
|
||||
ng-class="{ disabled: !createForm.$valid }"
|
||||
ng-click="ngModel.confirm()">
|
||||
OK
|
||||
</a>
|
||||
<a class='s-button'
|
||||
<a class='c-button '
|
||||
ng-click="ngModel.cancel()">
|
||||
Cancel
|
||||
</a>
|
||||
|
@ -1,25 +1,32 @@
|
||||
<div class="l-message"
|
||||
<div class="c-message"
|
||||
ng-class="'message-severity-' + ngModel.severity">
|
||||
<div class="w-message-contents">
|
||||
<div class="top-bar">
|
||||
<div class="title">{{ngModel.message}}</div>
|
||||
<div class="c-message__top-bar">
|
||||
<div class="c-message__title">{{ngModel.title}}</div>
|
||||
</div>
|
||||
<div class="c-message__hint" ng-hide="ngModel.hint === undefined">
|
||||
{{ngModel.hint}}
|
||||
<span ng-if="ngModel.timestamp !== undefined">[{{ngModel.timestamp}}]</span>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
<div class="message-action">
|
||||
{{ngModel.actionText}}
|
||||
</div>
|
||||
<mct-include key="'progress-bar'"
|
||||
ng-model="ngModel"
|
||||
ng-show="ngModel.progressPerc !== undefined"></mct-include>
|
||||
ng-show="ngModel.progress !== undefined || ngModel.unknownProgress"></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 class="c-overlay__button-bar">
|
||||
<button ng-repeat="dialogOption in ngModel.options"
|
||||
class="c-button"
|
||||
ng-click="dialogOption.callback()">
|
||||
{{dialogOption.label}}
|
||||
</button>
|
||||
<button class="c-button c-button--major"
|
||||
ng-if="ngModel.primaryOption"
|
||||
ng-click="ngModel.primaryOption.callback()">
|
||||
{{ngModel.primaryOption.label}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
<div class="c-message"
|
||||
ng-class="'message-severity-' + ngModel.severity">
|
||||
<div class="w-message-contents">
|
||||
<div class="c-message__top-bar">
|
||||
<div class="c-message__title">{{ngModel.message}}</div>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
<mct-include key="'progress-bar'"
|
||||
ng-model="ngModel"
|
||||
ng-show="ngModel.progressPerc !== undefined"></mct-include>
|
||||
</div>
|
||||
<div class="c-overlay__button-bar">
|
||||
<button ng-repeat="dialogOption in ngModel.options"
|
||||
class="c-button"
|
||||
ng-click="dialogOption.callback()">
|
||||
{{dialogOption.label}}
|
||||
</button>
|
||||
<button class="c-button c-button--major"
|
||||
ng-if="ngModel.primaryOption"
|
||||
ng-click="ngModel.primaryOption.callback()">
|
||||
{{ngModel.primaryOption.label}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,22 +1,23 @@
|
||||
<mct-container key="overlay">
|
||||
<div class="t-message-list">
|
||||
<div class="top-bar">
|
||||
<div class="dialog-title">{{ngModel.dialog.title}}</div>
|
||||
<div class="hint">Displaying {{ngModel.dialog.messages.length}} message<span ng-show="ngModel.dialog.messages.length > 1 ||
|
||||
ngModel.dialog.messages.length == 0">s</span>
|
||||
<div class="t-message-list c-overlay__contents">
|
||||
<div class="c-overlay__top-bar">
|
||||
<div class="c-overlay__dialog-title">{{ngModel.dialog.title}}</div>
|
||||
<div class="c-overlay__dialog-hint">Displaying {{ngModel.dialog.messages.length}} message<span
|
||||
ng-show="ngModel.dialog.messages.length > 1 ||
|
||||
ngModel.dialog.messages.length == 0">s</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-messages">
|
||||
<div class="w-messages c-overlay__messages">
|
||||
<mct-include
|
||||
ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'"
|
||||
key="'message'" ng-model="msg.model"></mct-include>
|
||||
key="'notification-message'" ng-model="msg.model"></mct-include>
|
||||
</div>
|
||||
<div class="bottom-bar">
|
||||
<a ng-repeat="dialogAction in ngModel.dialog.actions"
|
||||
class="s-button major"
|
||||
<div class="c-overlay__bottom-bar">
|
||||
<button ng-repeat="dialogAction in ngModel.dialog.actions"
|
||||
class="c-button c-button--major"
|
||||
ng-click="dialogAction.action()">
|
||||
{{dialogAction.label}}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</mct-container>
|
||||
|
@ -19,18 +19,18 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<mct-container key="overlay">
|
||||
<div class="abs top-bar">
|
||||
<div class="dialog-title">{{ngModel.dialog.title}}</div>
|
||||
<div class="hint">{{ngModel.dialog.hint}}</div>
|
||||
<mct-container key="c-overlay__contents">
|
||||
<div class=c-overlay__top-bar">
|
||||
<div class="c-overlay__dialog-title">{{ngModel.dialog.title}}</div>
|
||||
<div class="c-overlay__dialog-hint hint">{{ngModel.dialog.hint}}</div>
|
||||
</div>
|
||||
<div class='abs editor'>
|
||||
<div class='c-overlay__contents-main'>
|
||||
<mct-include key="ngModel.dialog.template"
|
||||
parameters="ngModel.dialog.parameters"
|
||||
ng-model="ngModel.dialog.model">
|
||||
</mct-include>
|
||||
</div>
|
||||
<div class="abs bottom-bar">
|
||||
<div class="c-overlay__button-bar">
|
||||
<a ng-repeat="option in ngModel.dialog.options"
|
||||
href=''
|
||||
class="s-button lg"
|
||||
|
@ -19,12 +19,12 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="abs overlay l-dialog" ng-class="{'delayEntry100ms' : ngModel.delay}">
|
||||
<div class="abs blocker"></div>
|
||||
<div class="abs outer-holder">
|
||||
<a ng-click="ngModel.cancel()"
|
||||
<div class="c-overlay l-overlay-small" ng-class="{'delayEntry100ms' : ngModel.delay}">
|
||||
<div class="c-overlay__blocker"></div>
|
||||
<div class="c-overlay__outer">
|
||||
<button ng-click="ngModel.cancel()"
|
||||
ng-if="ngModel.cancel"
|
||||
class="close icon-x-in-circle"></a>
|
||||
<div class="abs inner-holder contents" ng-transclude></div>
|
||||
class="c-click-icon c-overlay__close-button icon-x-in-circle"></button>
|
||||
<div class="c-overlay__contents" ng-transclude></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -160,7 +160,7 @@ define([
|
||||
},
|
||||
{
|
||||
"key": "remove",
|
||||
"category": "contextual",
|
||||
"category": "legacy",
|
||||
"implementation": RemoveAction,
|
||||
"cssClass": "icon-trash",
|
||||
"name": "Remove",
|
||||
|
@ -23,11 +23,7 @@
|
||||
/**
|
||||
* Module defining RemoveAction. Created by vwoeltje on 11/17/14.
|
||||
*/
|
||||
define([
|
||||
'./RemoveDialog'
|
||||
], function (
|
||||
RemoveDialog
|
||||
) {
|
||||
define([], function () {
|
||||
|
||||
/**
|
||||
* Construct an action which will remove the provided object manifestation.
|
||||
@ -114,12 +110,7 @@ define([
|
||||
return parent.useCapability('mutation', doMutate);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass in the function to remove the domain object so it can be
|
||||
* associated with an 'OK' button press
|
||||
*/
|
||||
dialog = new RemoveDialog(this.openmct, domainObject, removeFromContext);
|
||||
dialog.show();
|
||||
removeFromContext();
|
||||
};
|
||||
|
||||
// Object needs to have a parent for Remove to be applicable
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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 () {
|
||||
|
||||
/**
|
||||
* @callback removeCallback
|
||||
* @param {DomainObject} domainObject the domain object to be removed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Construct a new Remove dialog.
|
||||
*
|
||||
* @param {DialogService} dialogService the service that shows the dialog
|
||||
* @param {DomainObject} domainObject the domain object to be removed
|
||||
* @param {removeCallback} removeCallback callback that handles removal of the domain object
|
||||
* @memberof platform/commonUI/edit
|
||||
* @constructor
|
||||
*/
|
||||
function RemoveDialog(openmct, domainObject, removeCallback) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
this.removeCallback = removeCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a dialog to confirm the removal of a domain object.
|
||||
*/
|
||||
RemoveDialog.prototype.show = function () {
|
||||
let dialog = this.openmct.overlays.dialog({
|
||||
title: 'Remove ' + this.domainObject.getModel().name,
|
||||
iconClass: 'alert',
|
||||
message: 'Warning! This action will permanently remove this object. Are you sure you want to continue?',
|
||||
buttons: [
|
||||
{
|
||||
label: 'OK',
|
||||
callback: () => {
|
||||
this.removeCallback();
|
||||
dialog.dismiss();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Cancel',
|
||||
callback: () => {
|
||||
dialog.dismiss();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
return RemoveDialog;
|
||||
});
|
@ -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();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -192,7 +183,7 @@ function (
|
||||
if (reason !== "user canceled") {
|
||||
self.notificationService.error("Save Failed");
|
||||
}
|
||||
return false;
|
||||
throw reason;
|
||||
}
|
||||
|
||||
return getParent(domainObject)
|
||||
|
@ -67,20 +67,30 @@ define(
|
||||
openmct = this.openmct,
|
||||
newObject;
|
||||
|
||||
function onSave() {
|
||||
// openmct.editor.save();
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
openmct.editor.cancel();
|
||||
}
|
||||
|
||||
function navigateAndEdit(object) {
|
||||
let objectPath = object.getCapability('context').getPath(),
|
||||
url = '#/browse/' + objectPath
|
||||
.slice(1)
|
||||
.map(function (o) {
|
||||
return o && openmct.objects.makeKeyString(o.getId());
|
||||
})
|
||||
.join('/');
|
||||
|
||||
window.location.href = url;
|
||||
|
||||
openmct.editor.edit();
|
||||
}
|
||||
|
||||
newModel.type = this.type.getKey();
|
||||
newModel.location = this.parent.getId();
|
||||
newObject = this.parent.useCapability('instantiation', newModel);
|
||||
|
||||
openmct.editor.edit();
|
||||
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.
|
||||
|
@ -19,7 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="t-object-label l-flex-row flex-elem grows">
|
||||
<div class="t-item-icon flex-elem {{type.getCssClass()}}" ng-class="{ 'l-icon-link':location.isLink() }"></div>
|
||||
<div class='t-title-label flex-elem grows'>{{model.name}}</div>
|
||||
<div class="c-object-label">
|
||||
<div class="c-object-label__type-icon {{type.getCssClass()}}" ng-class="{ 'l-icon-link':location.isLink() }"></div>
|
||||
<div class='c-object-label__name'>{{model.name}}</div>
|
||||
</div>
|
||||
|
@ -1,13 +1,13 @@
|
||||
<div ng-controller="BannerController" ng-show="active.notification"
|
||||
class="l-message-banner s-message-banner {{active.notification.model.severity}}" ng-class="{
|
||||
class="c-message-banner {{active.notification.model.severity}}" ng-class="{
|
||||
'minimized': active.notification.model.minimized,
|
||||
'new': !active.notification.model.minimized}"
|
||||
ng-click="maximize(active.notification)">
|
||||
<span class="banner-elem label">
|
||||
<span class="c-message-banner__message">
|
||||
{{active.notification.model.title}}
|
||||
</span>
|
||||
<span ng-show="active.notification.model.progress !== undefined || active.notification.model.unknownProgress">
|
||||
<mct-include key="'progress-bar'" class="banner-elem"
|
||||
<mct-include key="'progress-bar'" class="c-message-banner__progress-bar"
|
||||
ng-model="active.notification.model">
|
||||
</mct-include>
|
||||
</span>
|
||||
@ -16,5 +16,5 @@
|
||||
ng-click="action(active.notification.model.primaryOption.callback, $event)">
|
||||
{{active.notification.model.primaryOption.label}}
|
||||
</a>
|
||||
<a class="banner-elem close icon-x" ng-click="dismiss(active.notification, $event)"></a>
|
||||
<button class="c-message-banner__close-button c-click-icon icon-x-in-circle" ng-click="dismiss(active.notification, $event)"></button>
|
||||
</div>
|
||||
|
@ -20,14 +20,11 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span ng-controller="ToggleController as toggle">
|
||||
<span ng-controller="TreeNodeController as treeNode">
|
||||
<span
|
||||
class="tree-item menus-to-left"
|
||||
ng-class="{selected: treeNode.isSelected()}"
|
||||
>
|
||||
<span
|
||||
class='ui-symbol view-control flex-elem'
|
||||
ng-class="{ 'has-children': model.composition !== undefined, expanded: toggle.isActive() }"
|
||||
<div class="u-contents" ng-controller="TreeNodeController as treeNode">
|
||||
<div class="c-tree__item menus-to-left"
|
||||
ng-class="{selected: treeNode.isSelected()}">
|
||||
<span class='c-disclosure-triangle c-tree__item__view-control'
|
||||
ng-class="{ 'is-enabled': model.composition !== undefined, 'c-disclosure-triangle--expanded': toggle.isActive() }"
|
||||
ng-click="toggle.toggle(); treeNode.trackExpansion()"
|
||||
>
|
||||
</span>
|
||||
@ -39,19 +36,15 @@
|
||||
ng-click="treeNode.select()"
|
||||
>
|
||||
</mct-representation>
|
||||
</span>
|
||||
<span
|
||||
class="tree-item-subtree"
|
||||
</div>
|
||||
<div class="u-contents"
|
||||
ng-show="toggle.isActive()"
|
||||
ng-if="model.composition !== undefined"
|
||||
>
|
||||
|
||||
ng-if="model.composition !== undefined">
|
||||
<mct-representation key="'subtree'"
|
||||
ng-model="ngModel"
|
||||
parameters="parameters"
|
||||
mct-object="treeNode.hasBeenExpanded() && domainObject">
|
||||
</mct-representation>
|
||||
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
|
@ -19,8 +19,8 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<ul class="tree">
|
||||
<li>
|
||||
<ul class="c-tree">
|
||||
<li class="c-tree__item-h">
|
||||
<mct-representation key="'tree-node'"
|
||||
mct-object="domainObject"
|
||||
ng-model="ngModel"
|
||||
|
@ -1,4 +1,2 @@
|
||||
<span class="tree-item menus-to-left">
|
||||
</span>
|
||||
<span class="tree-item-subtree">
|
||||
</span>
|
||||
<span class="c-tree__item js-tree__item"></span>
|
||||
<span class="c-tree__item-subtree"></span>
|
||||
|
@ -1,2 +1 @@
|
||||
<span class='ui-symbol view-control flex-elem'>
|
||||
</span>
|
||||
<span class='c-disclosure-triangle c-tree__item__view-control'></span>
|
||||
|
@ -1,6 +1,4 @@
|
||||
<span class="rep-object-label">
|
||||
<div class="t-object-label l-flex-row flex-elem grows">
|
||||
<div class="t-item-icon flex-elem"></div>
|
||||
<div class='t-title-label flex-elem grows'></div>
|
||||
</div>
|
||||
</span>
|
||||
<div class="rep-object-label c-object-label c-tree__item__label">
|
||||
<div class="c-object-label__type-icon c-tree__item__type-icon t-item-icon"></div>
|
||||
<div class="c-object-label__name c-tree__item__name t-title-label"></div>
|
||||
</div>
|
||||
|
@ -37,9 +37,9 @@ define([
|
||||
this.expanded = state;
|
||||
|
||||
if (state) {
|
||||
this.el.addClass('expanded');
|
||||
this.el.addClass('c-disclosure-triangle--expanded');
|
||||
} else {
|
||||
this.el.removeClass('expanded');
|
||||
this.el.removeClass('c-disclosure-triangle--expanded');
|
||||
}
|
||||
|
||||
this.callbacks.forEach(function (callback) {
|
||||
|
@ -28,7 +28,7 @@ define([
|
||||
], function ($, nodeTemplate, ToggleView, TreeLabelView) {
|
||||
|
||||
function TreeNodeView(gestureService, subtreeFactory, selectFn, openmct) {
|
||||
this.li = $('<li>');
|
||||
this.li = $('<li class="c-tree__item-h">');
|
||||
this.openmct = openmct;
|
||||
this.statusClasses = [];
|
||||
|
||||
@ -38,7 +38,7 @@ define([
|
||||
if (!this.subtreeView) {
|
||||
this.subtreeView = subtreeFactory();
|
||||
this.subtreeView.model(this.activeObject);
|
||||
this.li.find('.tree-item-subtree').eq(0)
|
||||
this.li.find('.c-tree__item-subtree').eq(0)
|
||||
.append($(this.subtreeView.elements()));
|
||||
}
|
||||
$(this.subtreeView.elements()).removeClass('hidden');
|
||||
@ -85,9 +85,9 @@ define([
|
||||
var obj = domainObject.useCapability('adapter');
|
||||
var hasComposition = this.openmct.composition.get(obj) !== undefined;
|
||||
if (hasComposition) {
|
||||
$(this.toggleView.elements()).removeClass('no-children');
|
||||
$(this.toggleView.elements()).addClass('is-enabled');
|
||||
} else {
|
||||
$(this.toggleView.elements()).addClass('no-children');
|
||||
$(this.toggleView.elements()).removeClass('is-enabled');
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ define([
|
||||
selectedIdPath = getIdPath(domainObject);
|
||||
|
||||
if (this.onSelectionPath) {
|
||||
this.li.find('.tree-item').eq(0).removeClass('selected');
|
||||
this.li.find('.js-tree__item').eq(0).removeClass('is-selected');
|
||||
if (this.subtreeView) {
|
||||
this.subtreeView.value(undefined);
|
||||
}
|
||||
@ -136,7 +136,7 @@ define([
|
||||
|
||||
if (this.onSelectionPath) {
|
||||
if (activeIdPath.length === selectedIdPath.length) {
|
||||
this.li.find('.tree-item').eq(0).addClass('selected');
|
||||
this.li.find('.js-tree__item').eq(0).addClass('is-selected');
|
||||
} else {
|
||||
// Expand to reveal the selection
|
||||
this.toggleView.value(true);
|
||||
|
@ -27,7 +27,7 @@ define([
|
||||
], function ($, TreeNodeView, spinnerTemplate) {
|
||||
|
||||
function TreeView(gestureService, openmct, selectFn) {
|
||||
this.ul = $('<ul class="tree"></ul>');
|
||||
this.ul = $('<ul class="c-tree"></ul>');
|
||||
this.nodeViews = [];
|
||||
this.callbacks = [];
|
||||
this.selectFn = selectFn || this.value.bind(this);
|
||||
|
@ -24,10 +24,10 @@
|
||||
<button ng-click="timer.clickStopButton()"
|
||||
ng-hide="timer.timerState == 'stopped'"
|
||||
title="Reset"
|
||||
class="c-timer__ctrl-reset c-click-icon c-click-icon--major icon-reset"></button>
|
||||
class="c-timer__ctrl-reset c-icon-button c-icon-button--major icon-reset"></button>
|
||||
<button ng-click="timer.clickButton()"
|
||||
title="{{timer.buttonText()}}"
|
||||
class="c-timer__ctrl-pause-play c-click-icon c-click-icon--major {{timer.buttonCssClass()}}"></button>
|
||||
class="c-timer__ctrl-pause-play c-icon-button c-icon-button--major {{timer.buttonCssClass()}}"></button>
|
||||
</div>
|
||||
<div class="c-timer__direction {{timer.signClass()}}"
|
||||
ng-hide="!timer.signClass()"></div>
|
||||
|
@ -45,7 +45,6 @@ define([
|
||||
"key": "url",
|
||||
"name": "URL",
|
||||
"control": "textfield",
|
||||
"pattern": "^(ftp|https?)\\:\\/\\/",
|
||||
"required": true,
|
||||
"cssClass": "l-input-lg"
|
||||
},
|
||||
|
@ -1,22 +1,18 @@
|
||||
<div class="t-imagery" ng-controller="ImageryController as imagery">
|
||||
<div class="t-imagery c-imagery" ng-controller="ImageryController as imagery">
|
||||
<mct-split-pane class='abs' anchor="bottom" alias="imagery">
|
||||
<div class="split-pane-component has-local-controls l-image-main-wrapper l-flex-col"
|
||||
ng-mouseenter="showLocalControls = true;"
|
||||
ng-mouseleave="showLocalControls = false;">
|
||||
<div class="h-local-controls h-local-controls-overlay-content h-local-controls-trans s-local-controls local-controls-hidden l-flex-row">
|
||||
<span class="holder flex-elem grows">
|
||||
<div class="split-pane-component has-local-controls l-image-main-wrapper l-flex-col">
|
||||
<div class="h-local-controls h-local-controls--overlay-content c-local-controls--show-on-hover l-flex-row c-imagery__lc">
|
||||
<span class="holder flex-elem grows c-imagery__lc__sliders">
|
||||
<input class="icon-brightness" type="range"
|
||||
min="0"
|
||||
max="500"
|
||||
ng-model="filters.brightness">
|
||||
</input>
|
||||
ng-model="filters.brightness" />
|
||||
<input class="icon-contrast" type="range"
|
||||
min="0"
|
||||
max="500"
|
||||
ng-model="filters.contrast">
|
||||
</input>
|
||||
ng-model="filters.contrast" />
|
||||
</span>
|
||||
<span class="holder flex-elem t-reset-btn-holder">
|
||||
<span class="holder flex-elem t-reset-btn-holder c-imagery__lc__reset-btn">
|
||||
<a class="s-icon-button icon-reset t-btn-reset"
|
||||
ng-click="filters = { brightness: 100, contrast: 100 }"></a>
|
||||
</span>
|
||||
@ -33,14 +29,14 @@
|
||||
|
||||
<div class="l-image-main-controlbar flex-elem l-flex-row">
|
||||
<div class="l-datetime-w flex-elem grows">
|
||||
<a class="s-button show-thumbs sm hidden icon-thumbs-strip"
|
||||
<a class="c-button show-thumbs sm hidden icon-thumbs-strip"
|
||||
ng-click="showThumbsBubble = (showThumbsBubble) ? false:true"></a>
|
||||
<span class="l-time">{{imagery.getTime()}}</span>
|
||||
</div>
|
||||
<div class="h-local-controls flex-elem">
|
||||
<a class="s-button pause-play"
|
||||
<a class="c-button icon-pause pause-play"
|
||||
ng-click="imagery.paused(!imagery.paused())"
|
||||
ng-class="{ paused: imagery.paused() }"></a>
|
||||
ng-class="{ 'is-paused': imagery.paused() }"></a>
|
||||
<a href=""
|
||||
class="s-button l-mag s-mag vsm icon-reset"
|
||||
ng-click="clipped = false"
|
||||
|
@ -47,7 +47,6 @@ define([
|
||||
"key": "url",
|
||||
"name": "URL",
|
||||
"control": "textfield",
|
||||
"pattern": "^(ftp|https?)\\:\\/\\/",
|
||||
"required": true,
|
||||
"cssClass": "l-input-lg"
|
||||
}
|
||||
|
@ -19,13 +19,13 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<form name="mctForm" novalidate class="form l-flex-col">
|
||||
<form name="mctForm" novalidate class="form c-form" autocomplete="off">
|
||||
<span ng-repeat="section in structure.sections"
|
||||
class="l-form-section l-flex-col flex-elem {{ section.cssClass }}">
|
||||
<h2 class="section-header flex-elem" ng-if="section.name">
|
||||
class="l-form-section c-form__section {{ section.cssClass }}">
|
||||
<h2 class="c-form__header" ng-if="section.name">
|
||||
{{section.name}}
|
||||
</h2>
|
||||
<ng-form class="form-row validates l-flex-row flex-elem {{ section.cssClass }}"
|
||||
<ng-form class="form-row c-form__row validates {{ section.cssClass }}"
|
||||
ng-class="{
|
||||
first:$index < 1,
|
||||
req: row.required,
|
||||
@ -37,11 +37,11 @@
|
||||
}"
|
||||
name="mctFormInner"
|
||||
ng-repeat="row in section.rows">
|
||||
<div class='label flex-elem' title="{{row.description}}">
|
||||
<div class='c-form__row__label label flex-elem' title="{{row.description}}">
|
||||
{{row.name}}
|
||||
</div>
|
||||
<div class='controls flex-elem'>
|
||||
<div class="wrapper" ng-if="row.control">
|
||||
<div class='c-form__row__controls controls flex-elem'>
|
||||
<div class="c-form__controls-wrapper wrapper" ng-if="row.control">
|
||||
<mct-control key="row.control"
|
||||
ng-model="ngModel"
|
||||
ng-required="row.required"
|
||||
|
@ -29,12 +29,13 @@ define(
|
||||
function SnapshotPreviewController($scope, openmct) {
|
||||
|
||||
$scope.previewImage = function (imageUrl) {
|
||||
let image = document.createElement('img');
|
||||
image.src = imageUrl;
|
||||
let imageDiv = document.createElement('div');
|
||||
imageDiv.classList = 'image-main s-image-main';
|
||||
imageDiv.style.backgroundImage = `url(${imageUrl})`;
|
||||
|
||||
let previewImageOverlay = openmct.overlays.overlay(
|
||||
{
|
||||
element: image,
|
||||
element: imageDiv,
|
||||
size: 'large',
|
||||
buttons: [
|
||||
{
|
||||
|
@ -45,7 +45,7 @@
|
||||
</mct-include>
|
||||
</div>
|
||||
|
||||
<a class="s-button c-search__btn-cancel"
|
||||
<a class="c-button c-search__btn-cancel"
|
||||
ng-show="!(ngModel.input === '' || ngModel.input === undefined)"
|
||||
ng-click="ngModel.input = ''; ngModel.checkAll = true; menuController.checkAll(); controller.search()">
|
||||
Cancel</a>
|
||||
|
24
src/MCT.js
24
src/MCT.js
@ -44,6 +44,9 @@ define([
|
||||
'../platform/core/src/objects/DomainObjectImpl',
|
||||
'../platform/core/src/capabilities/ContextualDomainObject',
|
||||
'./ui/preview/plugin',
|
||||
'./api/Branding',
|
||||
'./plugins/licenses/plugin',
|
||||
'./plugins/remove/plugin',
|
||||
'vue'
|
||||
], function (
|
||||
EventEmitter,
|
||||
@ -69,6 +72,9 @@ define([
|
||||
DomainObjectImpl,
|
||||
ContextualDomainObject,
|
||||
PreviewPlugin,
|
||||
BrandingAPI,
|
||||
LicensesPlugin,
|
||||
RemoveActionPlugin,
|
||||
Vue
|
||||
) {
|
||||
/**
|
||||
@ -89,6 +95,13 @@ define([
|
||||
*/
|
||||
function MCT() {
|
||||
EventEmitter.call(this);
|
||||
this.buildInfo = {
|
||||
version: __OPENMCT_VERSION__,
|
||||
buildDate: __OPENMCT_BUILD_DATE__,
|
||||
revision: __OPENMCT_REVISION__,
|
||||
branch: __OPENMCT_BUILD_BRANCH__
|
||||
};
|
||||
|
||||
this.legacyBundle = { extensions: {
|
||||
services: [
|
||||
{
|
||||
@ -228,11 +241,18 @@ define([
|
||||
|
||||
this.contextMenu = new api.ContextMenuRegistry();
|
||||
|
||||
this.router = new ApplicationRouter();
|
||||
|
||||
this.branding = BrandingAPI.default;
|
||||
|
||||
this.legacyRegistry = defaultRegistry;
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
this.install(this.plugins.DisplayLayout());
|
||||
this.install(PreviewPlugin.default());
|
||||
this.install(LegacyIndicatorsPlugin());
|
||||
this.install(LicensesPlugin.default());
|
||||
this.install(RemoveActionPlugin.default());
|
||||
|
||||
if (typeof BUILD_CONSTANTS !== 'undefined') {
|
||||
this.install(buildInfoPlugin(BUILD_CONSTANTS));
|
||||
@ -331,10 +351,6 @@ define([
|
||||
legacyRegistry.register('adapter', this.legacyBundle);
|
||||
legacyRegistry.enable('adapter');
|
||||
|
||||
this.install(LegacyIndicatorsPlugin());
|
||||
|
||||
this.router = new ApplicationRouter();
|
||||
|
||||
this.router.route(/^\/$/, () => {
|
||||
this.router.setPath('/browse/mine');
|
||||
});
|
||||
|
@ -158,7 +158,7 @@ define([
|
||||
|
||||
return {
|
||||
evaluate: function (datum, property) {
|
||||
return limitEvaluator.evaluate(datum, property.key);
|
||||
return limitEvaluator.evaluate(datum, property && property.key);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2019, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@ -19,31 +19,27 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
// Styles for extended text copy
|
||||
|
||||
.abs.l-standalone {
|
||||
$d: 20%;
|
||||
padding: $d/4 $d;
|
||||
}
|
||||
let brandingOptions = {};
|
||||
|
||||
.s-text {
|
||||
font-size: 0.8em;
|
||||
ol, ul {
|
||||
list-style: square;
|
||||
margin-left: 1.5em;
|
||||
li {
|
||||
/**
|
||||
* @typedef {Object} BrandingOptions
|
||||
* @memberOf openmct/branding
|
||||
* @property {string} smallLogoImage URL to the image to use as the applications logo.
|
||||
* This logo will appear on every screen and when clicked will launch the about dialog.
|
||||
* @property {string} aboutHtml Custom content for the about screen. When defined the
|
||||
* supplied content will be inserted at the start of the about dialog, and the default
|
||||
* Open MCT splash logo will be suppressed.
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-weight: 200 !important;
|
||||
}
|
||||
|
||||
table {
|
||||
td { font-size: inherit; }
|
||||
tr.header {
|
||||
background-color: rgba($colorBodyFg, 0.2);
|
||||
}
|
||||
/**
|
||||
* Set branding options for the application. These will override certain visual elements
|
||||
* of the application and allow for customization of the application.
|
||||
* @param {BrandingOptions} options
|
||||
*/
|
||||
export default function Branding(options) {
|
||||
if (arguments.length === 1) {
|
||||
brandingOptions = options;
|
||||
}
|
||||
return brandingOptions;
|
||||
}
|
@ -21,7 +21,11 @@ define([
|
||||
topicService.and.returnValue(mutationTopic);
|
||||
publicAPI = {};
|
||||
publicAPI.objects = jasmine.createSpyObj('ObjectAPI', [
|
||||
'get'
|
||||
'get',
|
||||
'mutate'
|
||||
]);
|
||||
publicAPI.objects.eventEmitter = jasmine.createSpyObj('eventemitter', [
|
||||
'on'
|
||||
]);
|
||||
publicAPI.objects.get.and.callFake(function (identifier) {
|
||||
return Promise.resolve({identifier: identifier});
|
||||
@ -52,6 +56,14 @@ define([
|
||||
{
|
||||
namespace: 'test',
|
||||
key: 'a'
|
||||
},
|
||||
{
|
||||
namespace: 'test',
|
||||
key: 'b'
|
||||
},
|
||||
{
|
||||
namespace: 'test',
|
||||
key: 'c'
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -68,12 +80,45 @@ define([
|
||||
composition.on('add', listener);
|
||||
|
||||
return composition.load().then(function () {
|
||||
expect(listener.calls.count()).toBe(1);
|
||||
expect(listener.calls.count()).toBe(3);
|
||||
expect(listener).toHaveBeenCalledWith({
|
||||
identifier: {namespace: 'test', key: 'a'}
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('supports reordering of composition', function () {
|
||||
var listener;
|
||||
beforeEach(function () {
|
||||
listener = jasmine.createSpy('reorderListener');
|
||||
composition.on('reorder', listener);
|
||||
|
||||
return composition.load();
|
||||
});
|
||||
it('', function () {
|
||||
composition.reorder(1, 0);
|
||||
let newComposition =
|
||||
publicAPI.objects.mutate.calls.mostRecent().args[2];
|
||||
let reorderPlan = listener.calls.mostRecent().args[0][0];
|
||||
|
||||
expect(reorderPlan.oldIndex).toBe(1);
|
||||
expect(reorderPlan.newIndex).toBe(0);
|
||||
expect(newComposition[0].key).toEqual('b');
|
||||
expect(newComposition[1].key).toEqual('a');
|
||||
expect(newComposition[2].key).toEqual('c');
|
||||
});
|
||||
it('', function () {
|
||||
composition.reorder(0, 2);
|
||||
let newComposition =
|
||||
publicAPI.objects.mutate.calls.mostRecent().args[2];
|
||||
let reorderPlan = listener.calls.mostRecent().args[0][0];
|
||||
|
||||
expect(reorderPlan.oldIndex).toBe(0);
|
||||
expect(reorderPlan.newIndex).toBe(2);
|
||||
expect(newComposition[0].key).toEqual('b');
|
||||
expect(newComposition[1].key).toEqual('c');
|
||||
expect(newComposition[2].key).toEqual('a');
|
||||
})
|
||||
});
|
||||
|
||||
// TODO: Implement add/removal in new default provider.
|
||||
xit('synchronizes changes between instances', function () {
|
||||
|
@ -56,7 +56,8 @@ define([
|
||||
this.listeners = {
|
||||
add: [],
|
||||
remove: [],
|
||||
load: []
|
||||
load: [],
|
||||
reorder: []
|
||||
};
|
||||
this.onProviderAdd = this.onProviderAdd.bind(this);
|
||||
this.onProviderRemove = this.onProviderRemove.bind(this);
|
||||
@ -91,6 +92,13 @@ define([
|
||||
this.onProviderRemove,
|
||||
this
|
||||
);
|
||||
} if (event === 'reorder') {
|
||||
this.provider.on(
|
||||
this.domainObject,
|
||||
'reorder',
|
||||
this.onProviderReorder,
|
||||
this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,6 +149,13 @@ define([
|
||||
this.onProviderRemove,
|
||||
this
|
||||
);
|
||||
} else if (event === 'reorder') {
|
||||
this.provider.off(
|
||||
this.domainObject,
|
||||
'reorder',
|
||||
this.onProviderReorder,
|
||||
this
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,6 +224,29 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reorder the domain objects in this composition.
|
||||
*
|
||||
* A call to [load]{@link module:openmct.CompositionCollection#load}
|
||||
* must have resolved before using this method.
|
||||
*
|
||||
* @param {number} oldIndex
|
||||
* @param {number} newIndex
|
||||
* @memberof module:openmct.CompositionCollection#
|
||||
* @name remove
|
||||
*/
|
||||
CompositionCollection.prototype.reorder = function (oldIndex, newIndex, skipMutate) {
|
||||
this.provider.reorder(this.domainObject, oldIndex, newIndex);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle reorder from provider.
|
||||
* @private
|
||||
*/
|
||||
CompositionCollection.prototype.onProviderReorder = function (reorderMap) {
|
||||
this.emit('reorder', reorderMap);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle adds from provider.
|
||||
* @private
|
||||
@ -232,12 +270,12 @@ define([
|
||||
* Emit events.
|
||||
* @private
|
||||
*/
|
||||
CompositionCollection.prototype.emit = function (event, payload) {
|
||||
CompositionCollection.prototype.emit = function (event, ...payload) {
|
||||
this.listeners[event].forEach(function (l) {
|
||||
if (l.context) {
|
||||
l.callback.call(l.context, payload);
|
||||
l.callback.apply(l.context, payload);
|
||||
} else {
|
||||
l.callback(payload);
|
||||
l.callback(...payload);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -126,6 +126,7 @@ define([
|
||||
objectListeners = this.listeningTo[keyString] = {
|
||||
add: [],
|
||||
remove: [],
|
||||
reorder: [],
|
||||
composition: [].slice.apply(domainObject.composition)
|
||||
};
|
||||
}
|
||||
@ -160,7 +161,7 @@ define([
|
||||
});
|
||||
|
||||
objectListeners[event].splice(index, 1);
|
||||
if (!objectListeners.add.length && !objectListeners.remove.length) {
|
||||
if (!objectListeners.add.length && !objectListeners.remove.length && !objectListeners.reorder.length) {
|
||||
delete this.listeningTo[keyString];
|
||||
}
|
||||
};
|
||||
@ -178,8 +179,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -199,6 +204,54 @@ define([
|
||||
// TODO: this needs to be synchronized via mutation
|
||||
};
|
||||
|
||||
DefaultCompositionProvider.prototype.reorder = function (domainObject, oldIndex, newIndex) {
|
||||
let newComposition = domainObject.composition.slice();
|
||||
let removeId = oldIndex > newIndex ? oldIndex + 1 : oldIndex;
|
||||
let insertPosition = oldIndex < newIndex ? newIndex + 1 : newIndex;
|
||||
//Insert object in new position
|
||||
newComposition.splice(insertPosition, 0, domainObject.composition[oldIndex]);
|
||||
newComposition.splice(removeId, 1);
|
||||
|
||||
let reorderPlan = [{
|
||||
oldIndex,
|
||||
newIndex
|
||||
}];
|
||||
|
||||
if (oldIndex > newIndex) {
|
||||
for (let i = newIndex; i < oldIndex; i++) {
|
||||
reorderPlan.push({
|
||||
oldIndex: i,
|
||||
newIndex: i + 1
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (let i = oldIndex + 1; i <= newIndex; i++) {
|
||||
reorderPlan.push({
|
||||
oldIndex: i,
|
||||
newIndex: i - 1
|
||||
});
|
||||
}
|
||||
}
|
||||
this.publicAPI.objects.mutate(domainObject, 'composition', newComposition);
|
||||
|
||||
let id = objectUtils.makeKeyString(domainObject.identifier);
|
||||
var listeners = this.listeningTo[id];
|
||||
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
listeners.reorder.forEach(notify);
|
||||
|
||||
function notify(listener) {
|
||||
if (listener.context) {
|
||||
listener.callback.call(listener.context, reorderPlan);
|
||||
} else {
|
||||
listener.callback(reorderPlan);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens on general mutation topic, using injector to fetch to avoid
|
||||
* circular dependencies.
|
||||
|
@ -226,7 +226,20 @@ define([
|
||||
(identifier.namespace === identifiers[0].namespace &&
|
||||
identifier.key === identifiers[0].key);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ObjectAPI.prototype.getOriginalPath = function (identifier, path = []) {
|
||||
return this.get(identifier).then((domainObject) => {
|
||||
path.push(domainObject);
|
||||
let location = domainObject.location;
|
||||
|
||||
if (location) {
|
||||
return this.getOriginalPath(utils.parseKeyString(location), path);
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Uniquely identifies a domain object.
|
||||
|
@ -5,7 +5,8 @@ import Vue from 'vue';
|
||||
const cssClasses = {
|
||||
large: 'l-overlay-large',
|
||||
small: 'l-overlay-small',
|
||||
fit: 'l-overlay-fit'
|
||||
fit: 'l-overlay-fit',
|
||||
fullscreen: 'l-overlay-fullscreen'
|
||||
};
|
||||
|
||||
class Overlay extends EventEmitter {
|
||||
|
@ -27,10 +27,16 @@
|
||||
<style lang="scss">
|
||||
@import "~styles/sass-base";
|
||||
|
||||
@mixin legacyMessage() {
|
||||
flex: 0 1 auto;
|
||||
font-family: symbolsfont;
|
||||
font-size: $messageIconD; // Singleton message in a dialog
|
||||
margin-right: $interiorMarginLg;
|
||||
}
|
||||
|
||||
.c-message {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: $interiorMarginLg;
|
||||
align-items: flex-start;
|
||||
|
||||
> * + * {
|
||||
margin-left: $interiorMarginLg;
|
||||
@ -58,7 +64,33 @@
|
||||
&__title,
|
||||
&__action-text {
|
||||
font-size: 1.2em; // TEMP
|
||||
}
|
||||
|
||||
/************************** LEGACY */
|
||||
&.message-severity-info:before {
|
||||
@include legacyMessage();
|
||||
content: $glyph-icon-info;
|
||||
color: $colorInfo;
|
||||
}
|
||||
|
||||
&.message-severity-alert:before {
|
||||
@include legacyMessage();
|
||||
content: $glyph-icon-alert-rect;
|
||||
color: $colorWarningLo;
|
||||
}
|
||||
|
||||
&.message-severity-error:before {
|
||||
@include legacyMessage();
|
||||
content: $glyph-icon-alert-triangle;
|
||||
color: $colorWarningLo;
|
||||
}
|
||||
|
||||
// Messages in a list
|
||||
.c-overlay__messages & {
|
||||
padding: $interiorMarginLg;
|
||||
&:before {
|
||||
font-size: $messageListIconD;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -56,16 +56,44 @@
|
||||
}
|
||||
|
||||
&__close-button {
|
||||
$p: $interiorMarginSm;
|
||||
$p: $interiorMargin;
|
||||
border-radius: 100% !important;
|
||||
color: $overlayColorFg;
|
||||
display: inline-block;
|
||||
font-size: 1.25em;
|
||||
position: absolute;
|
||||
top: $p; right: $p;
|
||||
}
|
||||
|
||||
&__contents {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__top-bar {
|
||||
flex: 0 0 auto;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
&__dialog-title {
|
||||
@include ellipsize();
|
||||
font-size: 1.5em;
|
||||
line-height: 120%;
|
||||
}
|
||||
|
||||
&__contents-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
padding-right: $interiorMargin; // fend off scroll bar
|
||||
}
|
||||
|
||||
&__button-bar {
|
||||
@ -89,18 +117,29 @@
|
||||
.c-overlay {
|
||||
&__blocker {
|
||||
@include abs();
|
||||
background: rgba(black, 0.7);
|
||||
background: $colorOvrBlocker;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&__outer {
|
||||
border-radius: $overlayCr;
|
||||
box-shadow: rgba(black, 0.5) 0 2px 25px;
|
||||
}
|
||||
}
|
||||
|
||||
// Overlay types, styling for desktop. Appended to .l-overlay-wrapper element.
|
||||
.l-overlay-large,
|
||||
.l-overlay-small,
|
||||
.l-overlay-fit {
|
||||
.c-overlay__outer {
|
||||
border-radius: $overlayCr;
|
||||
box-shadow: rgba(black, 0.5) 0 2px 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.l-overlay-fullscreen {
|
||||
// Used by About > Licenses display
|
||||
.c-overlay__outer {
|
||||
@include overlaySizing($overlayOuterMarginFullscreen);
|
||||
}
|
||||
}
|
||||
|
||||
.l-overlay-large {
|
||||
// Default
|
||||
.c-overlay__outer {
|
||||
@ -114,6 +153,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.t-dialog-sm .l-overlay-small, // Legacy dialog support
|
||||
.l-overlay-fit {
|
||||
.c-overlay__outer {
|
||||
@include overlaySizing(auto);
|
||||
|
@ -297,7 +297,7 @@ define([
|
||||
* @returns {Function} a function which may be called to terminate
|
||||
* the subscription
|
||||
*/
|
||||
TelemetryAPI.prototype.subscribe = function (domainObject, callback) {
|
||||
TelemetryAPI.prototype.subscribe = function (domainObject, callback, options) {
|
||||
var provider = this.findSubscriptionProvider(domainObject);
|
||||
|
||||
if (!this.subscribeCache) {
|
||||
@ -316,7 +316,7 @@ define([
|
||||
subscriber.callbacks.forEach(function (cb) {
|
||||
cb(value);
|
||||
});
|
||||
});
|
||||
}, options);
|
||||
} else {
|
||||
subscriber.unsubscribe = function () {};
|
||||
}
|
||||
|
@ -28,14 +28,22 @@ define([
|
||||
describe('Telemetry API', function () {
|
||||
var openmct;
|
||||
var telemetryAPI;
|
||||
var mockTypeService;
|
||||
|
||||
beforeEach(function () {
|
||||
openmct = {
|
||||
time: jasmine.createSpyObj('timeAPI', [
|
||||
'timeSystem',
|
||||
'bounds'
|
||||
]),
|
||||
$injector: jasmine.createSpyObj('injector', [
|
||||
'get'
|
||||
])
|
||||
};
|
||||
mockTypeService = jasmine.createSpyObj('typeService', [
|
||||
'getType'
|
||||
]);
|
||||
openmct.$injector.get.and.returnValue(mockTypeService);
|
||||
openmct.time.timeSystem.and.returnValue({key: 'system'});
|
||||
openmct.time.bounds.and.returnValue({start: 0, end: 1});
|
||||
telemetryAPI = new TelemetryAPI(openmct);
|
||||
@ -296,5 +304,233 @@ define([
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('metadata', function () {
|
||||
let mockMetadata = {};
|
||||
let mockObjectType = {
|
||||
typeDef: {}
|
||||
};
|
||||
beforeEach(function () {
|
||||
telemetryAPI.addProvider({
|
||||
key: 'mockMetadataProvider',
|
||||
supportsMetadata() {
|
||||
return true;
|
||||
},
|
||||
getMetadata() {
|
||||
return mockMetadata;
|
||||
}
|
||||
});
|
||||
mockTypeService.getType.and.returnValue(mockObjectType);
|
||||
})
|
||||
it('respects explicit priority', function () {
|
||||
mockMetadata.values = [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
hints: {
|
||||
priority: 2
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
key: "timestamp",
|
||||
name: "Timestamp",
|
||||
hints: {
|
||||
priority: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "sin",
|
||||
name: "Sine",
|
||||
hints: {
|
||||
priority: 4
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
hints: {
|
||||
priority: 3
|
||||
}
|
||||
}
|
||||
];
|
||||
let metadata = telemetryAPI.getMetadata({});
|
||||
let values = metadata.values();
|
||||
|
||||
values.forEach((value, index) => {
|
||||
expect(value.hints.priority).toBe(index + 1);
|
||||
});
|
||||
});
|
||||
it('if no explicit priority, defaults to order defined', function () {
|
||||
mockMetadata.values = [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name"
|
||||
|
||||
},
|
||||
{
|
||||
key: "timestamp",
|
||||
name: "Timestamp"
|
||||
},
|
||||
{
|
||||
key: "sin",
|
||||
name: "Sine"
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine"
|
||||
}
|
||||
];
|
||||
let metadata = telemetryAPI.getMetadata({});
|
||||
let values = metadata.values();
|
||||
|
||||
values.forEach((value, index) => {
|
||||
expect(value.key).toBe(mockMetadata.values[index].key);
|
||||
});
|
||||
});
|
||||
it('respects domain priority', function () {
|
||||
mockMetadata.values = [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name"
|
||||
|
||||
},
|
||||
{
|
||||
key: "timestamp-utc",
|
||||
name: "Timestamp UTC",
|
||||
hints: {
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "timestamp-local",
|
||||
name: "Timestamp Local",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "sin",
|
||||
name: "Sine",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
}
|
||||
];
|
||||
let metadata = telemetryAPI.getMetadata({});
|
||||
let values = metadata.valuesForHints(['domain']);
|
||||
|
||||
expect(values[0].key).toBe('timestamp-local');
|
||||
expect(values[1].key).toBe('timestamp-utc');
|
||||
});
|
||||
it('respects range priority', function () {
|
||||
mockMetadata.values = [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name"
|
||||
|
||||
},
|
||||
{
|
||||
key: "timestamp-utc",
|
||||
name: "Timestamp UTC",
|
||||
hints: {
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "timestamp-local",
|
||||
name: "Timestamp Local",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "sin",
|
||||
name: "Sine",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
}
|
||||
];
|
||||
let metadata = telemetryAPI.getMetadata({});
|
||||
let values = metadata.valuesForHints(['range']);
|
||||
|
||||
expect(values[0].key).toBe('cos');
|
||||
expect(values[1].key).toBe('sin');
|
||||
});
|
||||
it('respects priority and domain ordering', function () {
|
||||
mockMetadata.values = [
|
||||
{
|
||||
key: "id",
|
||||
name: "ID",
|
||||
hints: {
|
||||
priority: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
hints: {
|
||||
priority: 1
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
key: "timestamp-utc",
|
||||
name: "Timestamp UTC",
|
||||
hints: {
|
||||
domain: 2,
|
||||
priority: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "timestamp-local",
|
||||
name: "Timestamp Local",
|
||||
hints: {
|
||||
domain: 1,
|
||||
priority: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "timestamp-pst",
|
||||
name: "Timestamp PST",
|
||||
hints: {
|
||||
domain: 3,
|
||||
priority: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "sin",
|
||||
name: "Sine"
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine"
|
||||
}
|
||||
];
|
||||
let metadata = telemetryAPI.getMetadata({});
|
||||
let values = metadata.valuesForHints(['priority', 'domain']);
|
||||
[
|
||||
'timestamp-utc',
|
||||
'timestamp-local',
|
||||
'timestamp-pst'
|
||||
].forEach((key, index) => {
|
||||
expect(values[index].key).toBe(key);
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@ -116,14 +116,18 @@ define([
|
||||
return hints.every(hasHint, metadata);
|
||||
}
|
||||
var matchingMetadata = this.valueMetadatas.filter(hasHints);
|
||||
var sortedMetadata = _.sortBy(matchingMetadata, function (metadata) {
|
||||
return hints.map(function (hint) {
|
||||
let iteratees = hints.map(hint => {
|
||||
return (metadata) => {
|
||||
return metadata.hints[hint];
|
||||
});
|
||||
}
|
||||
});
|
||||
return sortedMetadata;
|
||||
return _.sortByAll(matchingMetadata, ...iteratees);
|
||||
};
|
||||
|
||||
TelemetryMetadataManager.prototype.getFilterableValues = function () {
|
||||
return this.valueMetadatas.filter(metadatum => metadatum.filters && metadatum.filters.length > 0);
|
||||
}
|
||||
|
||||
TelemetryMetadataManager.prototype.getDefaultDisplayValue = function () {
|
||||
let valueMetadata = this.valuesForHints(['range'])[0];
|
||||
|
||||
|
@ -35,6 +35,9 @@ define([
|
||||
canView: function (domainObject) {
|
||||
return domainObject.type === 'LadTableSet';
|
||||
},
|
||||
canEdit: function (domainObject) {
|
||||
return domainObject.type === 'LadTableSet';
|
||||
},
|
||||
view: function (domainObject) {
|
||||
let component;
|
||||
|
||||
|
@ -35,6 +35,9 @@ define([
|
||||
canView: function (domainObject) {
|
||||
return domainObject.type === 'LadTable';
|
||||
},
|
||||
canEdit: function (domainObject) {
|
||||
return domainObject.type === 'LadTable';
|
||||
},
|
||||
view: function (domainObject) {
|
||||
let component;
|
||||
|
||||
|
@ -65,17 +65,25 @@ export default {
|
||||
let index = _.findIndex(this.items, (item) => this.openmct.objects.makeKeyString(identifier) === item.key);
|
||||
|
||||
this.items.splice(index, 1);
|
||||
},
|
||||
reorder(reorderPlan) {
|
||||
let oldItems = this.items.slice();
|
||||
reorderPlan.forEach((reorderEvent) => {
|
||||
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addItem);
|
||||
this.composition.on('remove', this.removeItem);
|
||||
this.composition.on('reorder', this.reorder);
|
||||
this.composition.load();
|
||||
},
|
||||
destroyed() {
|
||||
this.composition.off('add', this.addItem);
|
||||
this.composition.off('remove', this.removeItem);
|
||||
this.composition.off('reorder', this.reorder);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -93,6 +93,12 @@
|
||||
this.primaryTelemetryObjects.splice(index,1);
|
||||
primary = undefined;
|
||||
},
|
||||
reorderPrimary(reorderPlan) {
|
||||
let oldComposition = this.primaryTelemetryObjects.slice();
|
||||
reorderPlan.forEach(reorderEvent => {
|
||||
this.$set(this.primaryTelemetryObjects, reorderEvent.newIndex, oldComposition[reorderEvent.oldIndex]);
|
||||
});
|
||||
},
|
||||
addSecondary(primary) {
|
||||
return (domainObject) => {
|
||||
let secondary = {};
|
||||
@ -120,11 +126,13 @@
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addPrimary);
|
||||
this.composition.on('remove', this.removePrimary);
|
||||
this.composition.on('reorder', this.reorderPrimary);
|
||||
this.composition.load();
|
||||
},
|
||||
destroyed() {
|
||||
this.composition.off('add', this.addPrimary);
|
||||
this.composition.off('remove', this.removePrimary);
|
||||
this.composition.off('reorder', this.reorderPrimary);
|
||||
this.compositions.forEach(c => {
|
||||
c.composition.off('add', c.addCallback);
|
||||
c.composition.off('remove', c.removeCallback);
|
||||
|
@ -28,9 +28,9 @@ 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')));
|
||||
},
|
||||
|
@ -27,6 +27,7 @@
|
||||
:domain-object="domainObject"
|
||||
:object-path="objectPath"
|
||||
:has-frame="item.hasFrame"
|
||||
:show-edit-view="false"
|
||||
ref="objectFrame">
|
||||
</object-frame>
|
||||
</layout-frame>
|
||||
|
113
src/plugins/filters/components/FilterField.vue
Normal file
113
src/plugins/filters/components/FilterField.vue
Normal file
@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div class="u-contents c-filter-settings">
|
||||
<li class="grid-row c-filter-settings__setting"
|
||||
v-for="(filter, index) in filterField.filters"
|
||||
:key="index">
|
||||
<div class="grid-cell label">
|
||||
{{ filterField.name }} =
|
||||
</div>
|
||||
<div class="grid-cell value">
|
||||
<!-- EDITING -->
|
||||
<!-- String input, editing -->
|
||||
<template v-if="!filter.possibleValues && isEditing">
|
||||
<input class="c-input--flex"
|
||||
type="text"
|
||||
placeholder="Enter Value"
|
||||
:id="`${filter}filterControl`"
|
||||
:value="persistedValue(filter)"
|
||||
@change="updateFilterValue($event, filter)">
|
||||
</template>
|
||||
|
||||
<!-- Checkbox list, editing -->
|
||||
<template v-if="filter.possibleValues && isEditing">
|
||||
<div class="c-checkbox-list__row"
|
||||
v-for="value in filter.possibleValues"
|
||||
:key="value">
|
||||
<input class="c-checkbox-list__input"
|
||||
type="checkbox"
|
||||
:id="`${value}filterControl`"
|
||||
@change="onUserSelect($event, filter.comparator, value)"
|
||||
:checked="isChecked(filter.comparator, value)">
|
||||
<span class="c-checkbox-list__value">
|
||||
{{ value }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- BROWSING -->
|
||||
<!-- String input, NOT editing -->
|
||||
<template v-if="!filter.possibleValues && !isEditing">
|
||||
{{ persistedValue(filter) }}
|
||||
</template>
|
||||
|
||||
<!-- Checkbox list, NOT editing -->
|
||||
<template v-if="filter.possibleValues && !isEditing">
|
||||
<span>{{persistedFilters[filter.comparator].join(', ')}}</span>
|
||||
</template>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~styles/sass-base";
|
||||
|
||||
.c-filter-settings {
|
||||
&__setting {
|
||||
.grid-cell.label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
inject: [
|
||||
'openmct'
|
||||
],
|
||||
props: {
|
||||
filterField: Object,
|
||||
persistedFilters: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
isEditing: this.openmct.editor.isEditing()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIsEditing(isEditing) {
|
||||
this.isEditing = isEditing;
|
||||
},
|
||||
onUserSelect(event, comparator, value){
|
||||
this.$emit('onUserSelect', this.filterField.key, comparator, value, event.target.checked);
|
||||
},
|
||||
isChecked(comparator, value) {
|
||||
if (this.persistedFilters[comparator] && this.persistedFilters[comparator].includes(value)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
persistedValue(comparator) {
|
||||
return this.persistedFilters && this.persistedFilters[comparator];
|
||||
},
|
||||
updateFilterValue(event, comparator) {
|
||||
this.$emit('onTextEnter', this.filterField.key, comparator, event.target.value);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.openmct.editor.on('isEditing', this.toggleIsEditing);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.openmct.editor.off('isEditing', this.toggleIsEditing);
|
||||
}
|
||||
}
|
||||
</script>
|
93
src/plugins/filters/components/FilterObject.vue
Normal file
93
src/plugins/filters/components/FilterObject.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<li>
|
||||
<div class="c-tree__item menus-to-left"
|
||||
@click="toggleExpanded">
|
||||
<span class="c-disclosure-triangle is-enabled flex-elem"
|
||||
:class="{'c-disclosure-triangle--expanded': expanded}"></span>
|
||||
<div class="c-tree__item__label">
|
||||
<div class="t-object-label l-flex-row flex-elem grows">
|
||||
<div class="t-item-icon flex-elem"
|
||||
:class="objectCssClass">
|
||||
</div>
|
||||
<div class="t-title-label flex-elem grows">{{ filterObject.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="grid-properties" v-if="expanded">
|
||||
<filter-field
|
||||
v-for="field in filterObject.valuesWithFilters"
|
||||
:key="field.key"
|
||||
:filterField="field"
|
||||
:persistedFilters="persistedFilters[field.key]"
|
||||
@onUserSelect="collectUserSelects"
|
||||
@onTextEnter="updateTextFilter">
|
||||
</filter-field>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import FilterField from './FilterField.vue';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
components: {
|
||||
FilterField
|
||||
},
|
||||
props: {
|
||||
filterObject: Object,
|
||||
persistedFilters: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: false,
|
||||
objectCssClass: undefined,
|
||||
updatedFilters: this.persistedFilters
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleExpanded() {
|
||||
this.expanded = !this.expanded;
|
||||
},
|
||||
collectUserSelects(key, comparator, valueName, value) {
|
||||
let filterValue = this.updatedFilters[key];
|
||||
|
||||
if (filterValue && filterValue[comparator]) {
|
||||
if (value === false) {
|
||||
filterValue[comparator] = filterValue[comparator].filter(v => v !== valueName);
|
||||
} else {
|
||||
filterValue[comparator].push(valueName);
|
||||
}
|
||||
} else {
|
||||
if (!this.updatedFilters[key]) {
|
||||
this.updatedFilters[key] = {};
|
||||
}
|
||||
this.updatedFilters[key][comparator] = [value ? valueName : undefined];
|
||||
}
|
||||
|
||||
this.$emit('updateFilters', this.keyString, this.updatedFilters);
|
||||
},
|
||||
updateTextFilter(key, comparator, value) {
|
||||
if (!this.updatedFilters[key]) {
|
||||
this.updatedFilters[key] = {};
|
||||
}
|
||||
this.updatedFilters[key][comparator] = value;
|
||||
this.$emit('updateFilters', this.keyString, this.updatedFilters);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let type = this.openmct.types.get(this.filterObject.domainObject.type) || {};
|
||||
this.keyString = this.openmct.objects.makeKeyString(this.filterObject.domainObject.identifier);
|
||||
this.objectCssClass = type.definition.cssClass;
|
||||
}
|
||||
}
|
||||
</script>
|
85
src/plugins/filters/components/FiltersView.vue
Normal file
85
src/plugins/filters/components/FiltersView.vue
Normal file
@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<ul class="tree c-tree c-properties__section" v-if="Object.keys(children).length">
|
||||
<h2 class="c-properties__header">Filters</h2>
|
||||
<filter-object
|
||||
v-for="(child, key) in children"
|
||||
:key="key"
|
||||
:filterObject="child"
|
||||
:persistedFilters="persistedFilters[key]"
|
||||
@updateFilters="persistFilters">
|
||||
</filter-object>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import FilterObject from './FilterObject.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
FilterObject
|
||||
},
|
||||
inject: [
|
||||
'openmct',
|
||||
'providedObject'
|
||||
],
|
||||
data() {
|
||||
let persistedFilters = {};
|
||||
|
||||
if (this.providedObject.configuration && this.providedObject.configuration.filters) {
|
||||
persistedFilters = this.providedObject.configuration.filters;
|
||||
}
|
||||
|
||||
return {
|
||||
persistedFilters,
|
||||
children: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addChildren(child) {
|
||||
let keyString = this.openmct.objects.makeKeyString(child.identifier),
|
||||
metadata = this.openmct.telemetry.getMetadata(child),
|
||||
valuesWithFilters = metadata.valueMetadatas.filter((value) => value.filters),
|
||||
childObject = {
|
||||
name: child.name,
|
||||
domainObject: child,
|
||||
valuesWithFilters
|
||||
};
|
||||
|
||||
if (childObject.valuesWithFilters.length) {
|
||||
this.$set(this.children, keyString, childObject);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
removeChildren(identifier) {
|
||||
let keyString = this.openmct.objects.makeKeyString(identifier);
|
||||
this.$delete(this.children, keyString);
|
||||
this.persistFilters(keyString);
|
||||
},
|
||||
persistFilters(keyString, userSelects) {
|
||||
this.persistedFilters[keyString] = userSelects;
|
||||
this.openmct.objects.mutate(this.providedObject, 'configuration.filters', this.persistedFilters);
|
||||
},
|
||||
updatePersistedFilters(filters) {
|
||||
this.persistedFilters = filters;
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.composition = this.openmct.composition.get(this.providedObject);
|
||||
this.composition.on('add', this.addChildren);
|
||||
this.composition.on('remove', this.removeChildren);
|
||||
this.composition.load();
|
||||
|
||||
this.unobserve = this.openmct.objects.observe(this.providedObject, 'configuration.filters', this.updatePersistedFilters);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.composition.off('add', this.addChildren);
|
||||
this.composition.off('remove', this.removeChildren);
|
||||
this.unobserve();
|
||||
}
|
||||
}
|
||||
</script>
|
73
src/plugins/filters/filtersInspectorViewProvider.js
Normal file
73
src/plugins/filters/filtersInspectorViewProvider.js
Normal file
@ -0,0 +1,73 @@
|
||||
/*****************************************************************************
|
||||
* 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([
|
||||
'./components/FiltersView.vue',
|
||||
'vue'
|
||||
], function (
|
||||
FiltersView,
|
||||
Vue
|
||||
) {
|
||||
|
||||
function FiltersInspectorViewProvider(openmct, supportedObjectTypesArray) {
|
||||
return {
|
||||
key: 'filters-inspector',
|
||||
name: 'Filters Inspector View',
|
||||
canView: function (selection) {
|
||||
if (selection.length === 0) {
|
||||
return false;
|
||||
}
|
||||
let object = selection[0].context.item;
|
||||
|
||||
return object && supportedObjectTypesArray.some(type => object.type === type);
|
||||
},
|
||||
view: function (selection) {
|
||||
let component;
|
||||
let providedObject = selection[0].context.item;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
component = new Vue({
|
||||
provide: {
|
||||
openmct,
|
||||
providedObject
|
||||
},
|
||||
components: {
|
||||
FiltersView: FiltersView.default
|
||||
},
|
||||
template: '<filters-view></filters-view>',
|
||||
el: element
|
||||
});
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
priority: function () {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FiltersInspectorViewProvider;
|
||||
});
|
@ -20,6 +20,14 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
@import "vendor/normalize.min.css";
|
||||
@import "startup-base";
|
||||
@import "openmct";
|
||||
define([
|
||||
'./filtersInspectorViewProvider'
|
||||
], function (
|
||||
FiltersInspectorViewProvider
|
||||
) {
|
||||
return function plugin(supportedObjectTypesArray) {
|
||||
return function install(openmct) {
|
||||
openmct.inspectorViews.addProvider(new FiltersInspectorViewProvider(openmct, supportedObjectTypesArray));
|
||||
};
|
||||
};
|
||||
});
|
@ -506,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();
|
||||
},
|
||||
@ -548,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);
|
||||
@ -620,7 +644,7 @@ export default {
|
||||
} else {
|
||||
this.containers.splice(toIndex, 0, container);
|
||||
}
|
||||
this.persist(index);
|
||||
this.persist();
|
||||
},
|
||||
removeChildObject(identifier) {
|
||||
let removeIdentifier = this.openmct.objects.makeKeyString(identifier);
|
||||
|
@ -36,6 +36,7 @@
|
||||
:domain-object="domainObject"
|
||||
:object-path="objectPath"
|
||||
:has-frame="hasFrame"
|
||||
:show-edit-view="false"
|
||||
ref="objectFrame">
|
||||
</object-frame>
|
||||
|
||||
|
@ -57,7 +57,7 @@ define([
|
||||
layoutObject: domainObject
|
||||
},
|
||||
el: element,
|
||||
template: '<flexible-layout-component ref="flexibleLayout"></flexible-layout-component>'
|
||||
template: '<flexible-layout-component ref="flexibleLayout" :isEditing="isEditing"></flexible-layout-component>'
|
||||
});
|
||||
},
|
||||
getSelectionContext: function () {
|
||||
|
@ -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) {
|
||||
@ -204,7 +204,7 @@ function ToolbarProvider(openmct) {
|
||||
addContainer,
|
||||
toggleFrame ? separator: undefined,
|
||||
toggleFrame,
|
||||
deleteFrame || deleteContainer ? separator: undefined,
|
||||
deleteFrame || deleteContainer ? separator : undefined,
|
||||
deleteFrame,
|
||||
deleteContainer
|
||||
];
|
||||
|
@ -16,7 +16,7 @@
|
||||
</div>
|
||||
<div class="c-grid-item__controls">
|
||||
<div class="icon-people" title='Shared'></div>
|
||||
<button class="c-click-icon icon-info c-info-button" title='More Info'></button>
|
||||
<button class="c-icon-button icon-info c-info-button" title='More Info'></button>
|
||||
<div class="icon-pointer-right c-pointer-icon"></div>
|
||||
</div>
|
||||
</a>
|
||||
|
52
src/plugins/licenses/Licenses.vue
Normal file
52
src/plugins/licenses/Licenses.vue
Normal file
@ -0,0 +1,52 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2019, 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.
|
||||
*****************************************************************************/
|
||||
<template>
|
||||
<div class="c-about c-about--licenses">
|
||||
<h1>Open MCT Third Party Licenses</h1>
|
||||
<p>This software includes components released under the following licenses:</p>
|
||||
<div v-for="(pkg, key) in packages" :key="key" class="c-license">
|
||||
<h2 class="c-license__name">{{key}}</h2>
|
||||
<div class="c-license__details">
|
||||
<span class="c-license__author"><em>Author</em> {{pkg.publisher}}</span> |
|
||||
<span class="c-license__license"><em>License(s)</em> {{pkg.licenses}}</span> |
|
||||
<span class="c-license__repo"><em>Repository</em> <a :href="pkg.repository" target="_blank">{{pkg.repository}}</a></span>
|
||||
</div>
|
||||
<div class="c-license__text">
|
||||
<p>{{pkg.licenseText}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="sass">
|
||||
</style>
|
||||
<script>
|
||||
import packages from './third-party-licenses.json';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
packages: packages
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2019, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@ -19,23 +19,20 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import Licenses from './Licenses.vue';
|
||||
import Vue from 'vue';
|
||||
|
||||
// Override the Create menu for mobile
|
||||
@include phoneandtablet {
|
||||
.super-menu {
|
||||
$d: 250px;
|
||||
width: $d;
|
||||
height: $d;
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
openmct.router.route(/^\/licenses$/, () => {
|
||||
let licensesVm = new Vue(Licenses).$mount();
|
||||
|
||||
.pane {
|
||||
&.left {
|
||||
border-right: none;
|
||||
padding-right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
&.right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
openmct.overlays.overlay({
|
||||
element: licensesVm.$el,
|
||||
size: 'fullscreen',
|
||||
dismissable: false,
|
||||
onDestroy: () => licensesVm.$destroy()
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
268
src/plugins/licenses/third-party-licenses.json
Normal file
268
src/plugins/licenses/third-party-licenses.json
Normal file
@ -0,0 +1,268 @@
|
||||
{
|
||||
"angular-route@1.4.14": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/angular/angular.js",
|
||||
"publisher": "Angular Core Team",
|
||||
"email": "angular-core+npm@google.com",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/angular-route",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/angular-route/LICENSE.md",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2016 Angular\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.",
|
||||
"copyright": "Copyright (c) 2016 Angular"
|
||||
},
|
||||
"angular@1.4.14": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/angular/angular.js",
|
||||
"publisher": "Angular Core Team",
|
||||
"email": "angular-core+npm@google.com",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/angular",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/angular/LICENSE.md",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2016 Angular\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.",
|
||||
"copyright": "Copyright (c) 2016 Angular"
|
||||
},
|
||||
"base64-arraybuffer@0.1.5": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/niklasvh/base64-arraybuffer",
|
||||
"publisher": "Niklas von Hertzen",
|
||||
"email": "niklasvh@gmail.com",
|
||||
"url": "http://hertzen.com",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/base64-arraybuffer",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/base64-arraybuffer/LICENSE-MIT",
|
||||
"licenseText": "Copyright (c) 2012 Niklas von Hertzen\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.",
|
||||
"copyright": "Copyright (c) 2012 Niklas von Hertzen"
|
||||
},
|
||||
"comma-separated-values@3.6.4": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/knrz/CSV.js",
|
||||
"publisher": "=",
|
||||
"email": "hi@knrz.co",
|
||||
"url": "http://knrz.co/",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/comma-separated-values",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/comma-separated-values/LICENSE",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2014 Kash Nouroozi\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.",
|
||||
"copyright": "Copyright (c) 2014 Kash Nouroozi"
|
||||
},
|
||||
"css-line-break@1.0.1": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/niklasvh/css-line-break",
|
||||
"publisher": "Niklas von Hertzen",
|
||||
"email": "niklasvh@gmail.com",
|
||||
"url": "https://hertzen.com",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/css-line-break",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/css-line-break/LICENSE",
|
||||
"licenseText": "Copyright (c) 2017 Niklas von Hertzen\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.",
|
||||
"copyright": "Copyright (c) 2017 Niklas von Hertzen"
|
||||
},
|
||||
"d3-array@1.2.4": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-array",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-array",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-array/LICENSE",
|
||||
"licenseText": "Copyright 2010-2016 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2016 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-axis@1.0.12": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-axis",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-axis",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-axis/LICENSE",
|
||||
"licenseText": "Copyright 2010-2016 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2016 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-collection@1.0.7": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-collection",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-collection",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-collection/LICENSE",
|
||||
"licenseText": "Copyright 2010-2016, Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2016, Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-color@1.0.4": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-color",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-color",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-color/LICENSE",
|
||||
"licenseText": "Copyright 2010-2016 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2016 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-format@1.2.2": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-format",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-format",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-format/LICENSE",
|
||||
"licenseText": "Copyright 2010-2015 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2015 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-interpolate@1.1.6": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-interpolate",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-interpolate",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-interpolate/LICENSE",
|
||||
"licenseText": "Copyright 2010-2016 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2016 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-scale@1.0.7": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-scale",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-scale",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-scale/LICENSE",
|
||||
"licenseText": "Copyright 2010-2015 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2015 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-selection@1.3.2": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-selection",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "https://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-selection",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-selection/LICENSE",
|
||||
"licenseText": "Copyright (c) 2010-2018, Michael Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* The name Michael Bostock may not be used to endorse or promote products\n derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\nOF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright (c) 2010-2018, Michael Bostock. All rights reserved."
|
||||
},
|
||||
"d3-time-format@2.1.3": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-time-format",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-time-format",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-time-format/LICENSE",
|
||||
"licenseText": "Copyright 2010-2017 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2017 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"d3-time@1.0.10": {
|
||||
"licenses": "BSD-3-Clause",
|
||||
"repository": "https://github.com/d3/d3-time",
|
||||
"publisher": "Mike Bostock",
|
||||
"url": "http://bost.ocks.org/mike",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/d3-time",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/d3-time/LICENSE",
|
||||
"licenseText": "Copyright 2010-2016 Mike Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the author nor the names of contributors may be used to\n endorse or promote products derived from this software without specific prior\n written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
|
||||
"copyright": "Copyright 2010-2016 Mike Bostock. All rights reserved."
|
||||
},
|
||||
"eventemitter3@1.2.0": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/primus/eventemitter3",
|
||||
"publisher": "Arnout Kazemier",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/eventemitter3",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/eventemitter3/LICENSE",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2014 Arnout Kazemier\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.",
|
||||
"copyright": "Copyright (c) 2014 Arnout Kazemier"
|
||||
},
|
||||
"file-saver@1.3.8": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/eligrey/FileSaver.js",
|
||||
"publisher": "Eli Grey",
|
||||
"email": "me@eligrey.com",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/file-saver",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/file-saver/LICENSE.md",
|
||||
"licenseText": "The MIT License\n\nCopyright © 2016 [Eli Grey][1].\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n [1]: http://eligrey.com",
|
||||
"copyright": "Copyright © 2016 [Eli Grey][1]."
|
||||
},
|
||||
"html2canvas@1.0.0-alpha.12": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/niklasvh/html2canvas",
|
||||
"publisher": "Niklas von Hertzen",
|
||||
"email": "niklasvh@gmail.com",
|
||||
"url": "https://hertzen.com",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/html2canvas",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/html2canvas/LICENSE",
|
||||
"licenseText": "Copyright (c) 2012 Niklas von Hertzen\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.",
|
||||
"copyright": "Copyright (c) 2012 Niklas von Hertzen"
|
||||
},
|
||||
"location-bar@3.0.1": {
|
||||
"licenses": "BSD-2-Clause",
|
||||
"repository": "https://github.com/KidkArolis/location-bar",
|
||||
"publisher": "Karolis Narkevicius",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/location-bar",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/location-bar/README.md",
|
||||
"licenseText": ""
|
||||
},
|
||||
"lodash@3.10.1": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/lodash/lodash",
|
||||
"publisher": "John-David Dalton",
|
||||
"email": "john.david.dalton@gmail.com",
|
||||
"url": "http://allyoucanleet.com/",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/lodash",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/lodash/LICENSE",
|
||||
"licenseText": "Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>\nBased on Underscore.js, copyright 2009-2015 Jeremy Ashkenas,\nDocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
|
||||
"copyright": "Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>. Based on Underscore.js, copyright 2009-2015 Jeremy Ashkenas,. DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>"
|
||||
},
|
||||
"moment-duration-format@2.2.2": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/jsmreese/moment-duration-format",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/moment-duration-format",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/moment-duration-format/LICENSE",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2018 John Madhavan-Reese\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
|
||||
"copyright": "Copyright (c) 2018 John Madhavan-Reese"
|
||||
},
|
||||
"moment-timezone@0.5.23": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/moment/moment-timezone",
|
||||
"publisher": "Tim Wood",
|
||||
"email": "washwithcare@gmail.com",
|
||||
"url": "http://timwoodcreates.com/",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/moment-timezone",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/moment-timezone/LICENSE",
|
||||
"licenseText": "The MIT License (MIT)\r\n\r\nCopyright (c) JS Foundation and other contributors\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy of\r\nthis software and associated documentation files (the \"Software\"), to deal in\r\nthe Software without restriction, including without limitation the rights to\r\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r\nthe Software, and to permit persons to whom the Software is furnished to do so,\r\nsubject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
|
||||
"copyright": "Copyright (c) JS Foundation and other contributors"
|
||||
},
|
||||
"moment@2.24.0": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/moment/moment",
|
||||
"publisher": "Iskren Ivov Chernev",
|
||||
"email": "iskren.chernev@gmail.com",
|
||||
"url": "https://github.com/ichernev",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/moment",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/moment/LICENSE",
|
||||
"licenseText": "Copyright (c) JS Foundation and other contributors\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.",
|
||||
"copyright": "Copyright (c) JS Foundation and other contributors"
|
||||
},
|
||||
"painterro@0.2.71": {
|
||||
"licenses": "MIT",
|
||||
"publisher": "Ivan Borshchov",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/painterro",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/painterro/LICENSE",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2017 Ivan Borshchov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.",
|
||||
"copyright": "Copyright (c) 2017 Ivan Borshchov"
|
||||
},
|
||||
"printj@1.2.1": {
|
||||
"licenses": "Apache-2.0",
|
||||
"repository": "https://github.com/SheetJS/printj",
|
||||
"publisher": "sheetjs",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/printj",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/printj/LICENSE",
|
||||
"licenseText": "Copyright (C) 2016-present SheetJS\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.",
|
||||
"copyright": "Copyright (C) 2016-present SheetJS"
|
||||
},
|
||||
"vue@2.5.6": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/vuejs/vue",
|
||||
"publisher": "Evan You",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/vue",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/vue/LICENSE",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2013-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.",
|
||||
"copyright": "Copyright (c) 2013-present, Yuxi (Evan) You"
|
||||
},
|
||||
"zepto@1.2.0": {
|
||||
"licenses": "MIT",
|
||||
"repository": "https://github.com/madrobby/zepto",
|
||||
"path": "/Users/akhenry/Code/licenses/node_modules/zepto",
|
||||
"licenseFile": "/Users/akhenry/Code/licenses/node_modules/zepto/README.md",
|
||||
"licenseText": "Copyright (c) 2010-2018 Thomas Fuchs\nhttp://zeptojs.com/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
</div>
|
||||
|
||||
<div class="c-ne__local-controls--hidden">
|
||||
<button class="c-click-icon c-click-icon--major icon-trash"
|
||||
<button class="c-icon-button c-icon-button--major icon-trash"
|
||||
title="Delete this entry"
|
||||
@click="deleteEntry">
|
||||
</button>
|
||||
|
200
src/plugins/objectMigration/Migrations.js
Normal file
200
src/plugins/objectMigration/Migrations.js
Normal file
@ -0,0 +1,200 @@
|
||||
/*****************************************************************************
|
||||
* 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([
|
||||
'uuid'
|
||||
], function (
|
||||
uuid
|
||||
) {
|
||||
function isTelemetry(domainObject) {
|
||||
if (openmct.telemetry.isTelemetryObject(domainObject)
|
||||
&& domainObject.type !== 'summary-widget'
|
||||
&& domainObject.type !== 'example.imagery') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function migrateDisplayLayout(domainObject, childObjects) {
|
||||
const DEFAULT_GRID_SIZE = [32, 32];
|
||||
let migratedObject = Object.assign({}, domainObject);
|
||||
let panels = migratedObject.configuration.layout.panels;
|
||||
let items = [];
|
||||
|
||||
Object.keys(panels).forEach(key => {
|
||||
let panel = panels[key];
|
||||
let domainObject = childObjects[key];
|
||||
|
||||
if (isTelemetry(domainObject)) {
|
||||
items.push({
|
||||
width: panel.dimensions[0],
|
||||
height: panel.dimensions[1],
|
||||
x: panel.position[0],
|
||||
y: panel.position[1],
|
||||
useGrid: true,
|
||||
identifier: domainObject.identifier,
|
||||
id: uuid(),
|
||||
type: 'telemetry-view',
|
||||
displayMode: 'all',
|
||||
value: openmct.telemetry.getMetadata(domainObject).getDefaultDisplayValue(),
|
||||
stroke: "transparent",
|
||||
fill: "",
|
||||
color: "",
|
||||
size: "13px"
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
width: panel.dimensions[0],
|
||||
height: panel.dimensions[1],
|
||||
x: panel.position[0],
|
||||
y: panel.position[1],
|
||||
useGrid: true,
|
||||
identifier: domainObject.identifier,
|
||||
id: uuid(),
|
||||
type: 'subobject-view',
|
||||
hasFrame: panel.hasFrame
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
migratedObject.configuration.items = items;
|
||||
migratedObject.configuration.layoutGrid = migratedObject.layoutGrid || DEFAULT_GRID_SIZE;
|
||||
delete migratedObject.layoutGrid;
|
||||
delete migratedObject.configuration.layout;
|
||||
return migratedObject;
|
||||
}
|
||||
|
||||
function migrateFixedPositionConfiguration(elements, telemetryObjects) {
|
||||
const DEFAULT_STROKE = "transparent";
|
||||
const DEFAULT_SIZE = "13px";
|
||||
const DEFAULT_COLOR = "";
|
||||
const DEFAULT_FILL = "";
|
||||
let items = [];
|
||||
|
||||
elements.forEach(element => {
|
||||
let item = {
|
||||
x: element.x,
|
||||
y: element.y,
|
||||
width: element.width,
|
||||
height: element.height,
|
||||
useGrid: element.useGrid,
|
||||
id: uuid()
|
||||
};
|
||||
|
||||
if (element.type === "fixed.telemetry") {
|
||||
item.type = "telemetry-view";
|
||||
item.stroke = element.stroke || DEFAULT_STROKE;
|
||||
item.fill = element.fill || DEFAULT_FILL;
|
||||
item.color = element.color || DEFAULT_COLOR;
|
||||
item.size = element.size || DEFAULT_SIZE;
|
||||
item.identifier = telemetryObjects[element.id].identifier;
|
||||
item.displayMode = element.titled ? 'all' : 'value';
|
||||
item.value = openmct.telemetry.getMetadata(telemetryObjects[element.id]).getDefaultDisplayValue();
|
||||
} else if (element.type === 'fixed.box') {
|
||||
item.type = "box-view";
|
||||
item.stroke = element.stroke || DEFAULT_STROKE;
|
||||
item.fill = element.fill || DEFAULT_FILL;
|
||||
} else if (element.type === 'fixed.line') {
|
||||
item.type = "line-view";
|
||||
item.x2 = element.x2;
|
||||
item.y2 = element.y2;
|
||||
item.stroke = element.stroke || DEFAULT_STROKE;
|
||||
delete item.height;
|
||||
delete item.width;
|
||||
} else if (element.type === 'fixed.text') {
|
||||
item.type = "text-view";
|
||||
item.text = element.text;
|
||||
item.stroke = element.stroke || DEFAULT_STROKE;
|
||||
item.fill = element.fill || DEFAULT_FILL;
|
||||
item.color = element.color || DEFAULT_COLOR;
|
||||
item.size = element.size || DEFAULT_SIZE;
|
||||
} else if (element.type === 'fixed.image') {
|
||||
item.type = "image-view";
|
||||
item.url =element.url;
|
||||
item.stroke = element.stroke || DEFAULT_STROKE;
|
||||
}
|
||||
|
||||
items.push(item);
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
check(domainObject) {
|
||||
return domainObject.type === 'layout' && domainObject.configuration.layout;
|
||||
},
|
||||
migrate(domainObject) {
|
||||
let childObjects = {};
|
||||
let promises = Object.keys(domainObject.configuration.layout.panels).map(key => {
|
||||
return openmct.objects.get(key)
|
||||
.then(object => {
|
||||
childObjects[key] = object;
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(function () {
|
||||
return migrateDisplayLayout(domainObject, childObjects);
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
check(domainObject) {
|
||||
return domainObject.type === 'telemetry.fixed' && domainObject.configuration['fixed-display'];
|
||||
},
|
||||
migrate(domainObject) {
|
||||
const DEFAULT_GRID_SIZE = [64, 16];
|
||||
let newLayoutObject = {
|
||||
identifier: domainObject.identifier,
|
||||
location: domainObject.location,
|
||||
name: domainObject.name,
|
||||
type: "layout"
|
||||
};
|
||||
let layoutType = openmct.types.get('layout');
|
||||
layoutType.definition.initialize(newLayoutObject);
|
||||
newLayoutObject.composition = domainObject.composition;
|
||||
newLayoutObject.configuration.layoutGrid = domainObject.layoutGrid || DEFAULT_GRID_SIZE;
|
||||
|
||||
let elements = domainObject.configuration['fixed-display'].elements;
|
||||
let telemetryObjects = {};
|
||||
let promises = elements.map(element => {
|
||||
if (element.id) {
|
||||
return openmct.objects.get(element.id)
|
||||
.then(object => {
|
||||
telemetryObjects[element.id] = object;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(function () {
|
||||
newLayoutObject.configuration.items =
|
||||
migrateFixedPositionConfiguration(elements, telemetryObjects);
|
||||
return newLayoutObject;
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
@ -19,40 +19,33 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
@mixin labelValidate($sym, $c) {
|
||||
> .label {
|
||||
@include glyphAfter($sym);
|
||||
&:after {
|
||||
color: $c;
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
|
||||
import migrations from './Migrations.js'
|
||||
|
||||
export default function () {
|
||||
function needsMigration(domainObject) {
|
||||
return migrations.some(m => m.check(domainObject));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mct-form.validates {
|
||||
.form-row.validates {
|
||||
> .label {
|
||||
padding-right: $reqSymbolM; // Keep room for validation element
|
||||
&:after {
|
||||
font-size: $reqSymbolFontSize;
|
||||
}
|
||||
}
|
||||
&.invalid,
|
||||
&.invalid.req { @include labelValidate($glyph-icon-x, $colorFormInvalid); }
|
||||
|
||||
&.valid,
|
||||
&.valid.req { @include labelValidate($glyph-icon-check, $colorFormValid); }
|
||||
|
||||
&.req { @include labelValidate($glyph-icon-asterisk, $colorFormRequired); }
|
||||
function migrateObject(domainObject) {
|
||||
return migrations.filter(m => m.check(domainObject))[0]
|
||||
.migrate(domainObject);
|
||||
}
|
||||
}
|
||||
|
||||
body.desktop .form-row.validates > .label {
|
||||
&:after {
|
||||
position: absolute;
|
||||
right: $interiorMargin;
|
||||
height: 100%;
|
||||
line-height: 200%;
|
||||
}
|
||||
}
|
||||
return function (openmct) {
|
||||
let wrappedFunction = openmct.objects.get;
|
||||
openmct.objects.get = function migrate(identifier) {
|
||||
return wrappedFunction.apply(openmct.objects, [identifier])
|
||||
.then(function (object) {
|
||||
if (needsMigration(object)) {
|
||||
migrateObject(object)
|
||||
.then(newObject => {
|
||||
openmct.objects.mutate(newObject, 'persisted', Date.now());
|
||||
return newObject;
|
||||
});
|
||||
}
|
||||
return object;
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
@ -250,7 +250,8 @@ define([
|
||||
{"has": "telemetry"}
|
||||
],
|
||||
"model": {
|
||||
"composition": []
|
||||
"composition": [],
|
||||
"configuration": {}
|
||||
},
|
||||
"properties": [],
|
||||
"priority": 890
|
||||
|
@ -136,7 +136,7 @@
|
||||
<span class="t-object-alert t-alert-unsynced"
|
||||
title="This plot is not currently displaying the latest data.
|
||||
Reset Pan/zoom to return to view latest data."></span>
|
||||
<div class="gl-plot-display-area">
|
||||
<div class="gl-plot-display-area has-local-controls has-cursor-guides">
|
||||
<mct-ticks axis="xAxis">
|
||||
<div class="gl-plot-hash hash-v"
|
||||
ng-repeat="tick in ticks track by tick.value"
|
||||
@ -147,7 +147,6 @@
|
||||
</div>
|
||||
</mct-ticks>
|
||||
|
||||
|
||||
<mct-ticks axis="yAxis">
|
||||
<div class="gl-plot-hash hash-h"
|
||||
ng-repeat="tick in ticks track by tick.value"
|
||||
@ -155,7 +154,6 @@
|
||||
</div>
|
||||
</mct-ticks>
|
||||
|
||||
|
||||
<mct-chart config="config"
|
||||
series="series"
|
||||
rectangles="rectangles"
|
||||
@ -164,23 +162,37 @@
|
||||
the-y-axis="yAxis">
|
||||
</mct-chart>
|
||||
|
||||
<div class="h-local-controls h-local-controls-overlay-content"
|
||||
ng-show="plotHistory.length">
|
||||
<div class="l-btn-set">
|
||||
<a class="s-button icon-arrow-left"
|
||||
ng-click="plot.back()"
|
||||
title="Restore previous pan/zoom">
|
||||
</a>
|
||||
<a class="s-button icon-reset"
|
||||
ng-click="plot.clear()"
|
||||
title="Reset pan/zoom">
|
||||
</a>
|
||||
<div class="gl-plot__local-controls h-local-controls h-local-controls--overlay-content c-local-controls--show-on-hover">
|
||||
<div class="c-button-set c-button-set--strip-h">
|
||||
<button class="c-button icon-minus"
|
||||
ng-click="plot.zoom('out', 0.2)"
|
||||
title="Zoom out">
|
||||
</button>
|
||||
<button class="c-button icon-plus"
|
||||
ng-click="plot.zoom('in', 0.2)"
|
||||
title="Zoom in">
|
||||
</button>
|
||||
</div>
|
||||
<div class="c-button-set c-button-set--strip-h"
|
||||
ng-disabled="!plotHistory.length">
|
||||
<button class="c-button icon-arrow-left"
|
||||
ng-click="plot.back()"
|
||||
title="Restore previous pan/zoom">
|
||||
</button>
|
||||
<button class="c-button icon-reset"
|
||||
ng-click="plot.clear()"
|
||||
title="Reset pan/zoom">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="t-wait-spinner loading" ng-show="plot.isRequestPending()">
|
||||
</span>
|
||||
|
||||
<!--Cursor guides-->
|
||||
<div class="c-cursor-guide--v js-cursor-guide--v"
|
||||
ng-show="plot.cursorGuide">
|
||||
</div>
|
||||
<div class="c-cursor-guide--h js-cursor-guide--h"
|
||||
ng-show="plot.cursorGuide">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gl-plot-axis-area gl-plot-x"
|
||||
|
@ -20,7 +20,7 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div ng-controller="PlotOptionsController">
|
||||
<ul class="tree c-tree">
|
||||
<ul class="c-tree">
|
||||
<h2 title="Plot series display properties in this object">Plot Series</h2>
|
||||
<li ng-repeat="series in config.series.models">
|
||||
<div class="c-tree__item menus-to-left">
|
||||
|
@ -20,7 +20,7 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div ng-controller="PlotOptionsController">
|
||||
<ul class="tree c-tree">
|
||||
<ul class="c-tree">
|
||||
<h2 title="Display properties for this object">Plot Series</h2>
|
||||
<li ng-repeat="series in plotSeries"
|
||||
ng-controller="PlotSeriesFormController"
|
||||
@ -87,13 +87,15 @@
|
||||
ng-style="{ background: series.get('color').asHexString() }">
|
||||
</span>
|
||||
</div>
|
||||
<div class="c-palette--inline c-palette__items" ng-show="toggle.isActive()">
|
||||
<div class="u-contents" ng-repeat="group in config.series.palette.groups()">
|
||||
<div class="c-palette__item"
|
||||
ng-repeat="color in group"
|
||||
ng-class="{ 'selected': series.get('color').equalTo(color) }"
|
||||
ng-style="{ background: color.asHexString() }"
|
||||
ng-click="setColor(color)">
|
||||
<div class="c-palette c-palette--color">
|
||||
<div class="c-palette__items" ng-show="toggle.isActive()">
|
||||
<div class="u-contents" ng-repeat="group in config.series.palette.groups()">
|
||||
<div class="c-palette__item"
|
||||
ng-repeat="color in group"
|
||||
ng-class="{ 'selected': series.get('color').equalTo(color) }"
|
||||
ng-style="{ background: color.asHexString() }"
|
||||
ng-click="setColor(color)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -20,31 +20,34 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span ng-controller="PlotController as controller"
|
||||
class="abs holder holder-plot has-control-bar"
|
||||
ng-class="{
|
||||
'loading': !!pending
|
||||
}"
|
||||
>
|
||||
class="abs holder holder-plot has-control-bar">
|
||||
<div class="l-control-bar" ng-show="!controller.hideExportButtons">
|
||||
<span class="l-btn-set">
|
||||
<a class="s-button t-export labeled icon-download"
|
||||
<span class="c-button-set c-button-set--strip-h">
|
||||
<button class="c-button icon-download"
|
||||
ng-click="controller.exportPNG()"
|
||||
title="Export This View's Data as PNG">
|
||||
PNG
|
||||
</a>
|
||||
<a class="s-button t-export labeled"
|
||||
<span class="c-button__label">PNG</span>
|
||||
</button>
|
||||
<button class="c-button"
|
||||
ng-click="controller.exportJPG()"
|
||||
title="Export This View's Data as JPG">
|
||||
JPG
|
||||
</a>
|
||||
<span class="c-button__label">JPG</span>
|
||||
</button>
|
||||
</span>
|
||||
<button class="c-button icon-crosshair"
|
||||
ng-class="{ 'is-active': controller.cursorGuide }"
|
||||
ng-click="controller.toggleCursorGuide($event)"
|
||||
title="Toggle cursor guides">
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="l-view-section">
|
||||
<div class="c-loading--overlay loading"
|
||||
ng-show="!!pending"></div>
|
||||
<mct-plot config="controller.config"
|
||||
series="series"
|
||||
the-y-axis="yAxis"
|
||||
the-x-axis="xAxis">
|
||||
</mct-plot>
|
||||
</mct-plot>
|
||||
</div>
|
||||
</span>
|
||||
|
@ -20,26 +20,29 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span ng-controller="StackedPlotController as stackedPlot"
|
||||
class="abs holder holder-plot has-control-bar t-plot-stacked"
|
||||
ng-class="{
|
||||
'loading': !!currentRequest.pending
|
||||
}">
|
||||
|
||||
class="abs holder holder-plot has-control-bar t-plot-stacked">
|
||||
<div class="l-control-bar" ng-show="!stackedPlot.hideExportButtons">
|
||||
<span class="l-btn-set">
|
||||
<a class="s-button t-export labeled icon-download"
|
||||
<span class="c-button-set c-button-set--strip-h">
|
||||
<button class="c-button icon-download"
|
||||
ng-click="stackedPlot.exportPNG()"
|
||||
title="Export This View's Data as PNG">
|
||||
PNG
|
||||
</a>
|
||||
<a class="s-button t-export labeled"
|
||||
<span class="c-button__label">PNG</span>
|
||||
</button>
|
||||
<button class="c-button"
|
||||
ng-click="stackedPlot.exportJPG()"
|
||||
title="Export This View's Data as JPG">
|
||||
JPG
|
||||
</a>
|
||||
</span>
|
||||
<span class="c-button__label">JPG</span>
|
||||
</button>
|
||||
</span>
|
||||
<button class="c-button icon-crosshair"
|
||||
ng-class="{ 'is-active': stackedPlot.cursorGuide }"
|
||||
ng-click="stackedPlot.toggleCursorGuide($event)"
|
||||
title="Toggle cursor guides">
|
||||
</button>
|
||||
</div>
|
||||
<div class="l-view-section">
|
||||
<div class="c-loading--overlay loading"
|
||||
ng-show="!!currentRequest.pending"></div>
|
||||
<div class="gl-plot child-frame"
|
||||
ng-repeat="telemetryObject in telemetryObjects"
|
||||
ng-class="{
|
||||
|
@ -101,6 +101,19 @@ define([
|
||||
seriesConfig.identifier.namespace === identifier.namespace;
|
||||
})[0];
|
||||
},
|
||||
/**
|
||||
* Retrieve the persisted filters for a given identifier.
|
||||
*/
|
||||
getPersistedFilters: function (identifier) {
|
||||
var domainObject = this.get('domainObject'),
|
||||
keystring = this.openmct.objects.makeKeyString(identifier);
|
||||
|
||||
if (!domainObject.configuration || !domainObject.configuration.filters) {
|
||||
return;
|
||||
}
|
||||
|
||||
return domainObject.configuration.filters[keystring];
|
||||
},
|
||||
/**
|
||||
* Update the domain object with the given value.
|
||||
*/
|
||||
|
@ -84,6 +84,7 @@ define([
|
||||
this.listenTo(this, 'change:xKey', this.onXKeyChange, this);
|
||||
this.listenTo(this, 'change:yKey', this.onYKeyChange, this);
|
||||
this.persistedConfig = options.persistedConfig;
|
||||
this.filters = options.filters;
|
||||
|
||||
Model.apply(this, arguments);
|
||||
this.onXKeyChange(this.get('xKey'));
|
||||
@ -139,13 +140,16 @@ define([
|
||||
* @returns {Promise}
|
||||
*/
|
||||
fetch: function (options) {
|
||||
options = _.extend({}, {size: 1000, strategy: 'minmax'}, options || {});
|
||||
options = _.extend({}, {size: 1000, strategy: 'minmax', filters: this.filters}, options || {});
|
||||
if (!this.unsubscribe) {
|
||||
this.unsubscribe = this.openmct
|
||||
.telemetry
|
||||
.subscribe(
|
||||
this.domainObject,
|
||||
this.add.bind(this)
|
||||
this.add.bind(this),
|
||||
{
|
||||
filters: this.filters
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -360,6 +364,19 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* Updates filters, clears the plot series, unsubscribes and resubscribes
|
||||
* @public
|
||||
*/
|
||||
updateFiltersAndRefresh: function (updatedFilters) {
|
||||
this.filters = updatedFilters;
|
||||
this.reset();
|
||||
if (this.unsubscribe) {
|
||||
this.unsubscribe();
|
||||
delete this.unsubscribe;
|
||||
}
|
||||
this.fetch();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -66,6 +66,7 @@ define([
|
||||
},
|
||||
addTelemetryObject: function (domainObject, index) {
|
||||
var seriesConfig = this.plot.getPersistedSeriesConfig(domainObject.identifier);
|
||||
var filters = this.plot.getPersistedFilters(domainObject.identifier);
|
||||
var plotObject = this.plot.get('domainObject');
|
||||
|
||||
if (!seriesConfig) {
|
||||
@ -92,7 +93,8 @@ define([
|
||||
collection: this,
|
||||
openmct: this.openmct,
|
||||
persistedConfig: this.plot
|
||||
.getPersistedSeriesConfig(domainObject.identifier)
|
||||
.getPersistedSeriesConfig(domainObject.identifier),
|
||||
filters: filters
|
||||
}));
|
||||
},
|
||||
removeTelemetryObject: function (identifier) {
|
||||
|
@ -78,6 +78,7 @@ define([
|
||||
this.listenTo(this.$canvas, 'mousemove', this.trackMousePosition, this);
|
||||
this.listenTo(this.$canvas, 'mouseleave', this.untrackMousePosition, this);
|
||||
this.listenTo(this.$canvas, 'mousedown', this.onMouseDown, this);
|
||||
this.listenTo(this.$canvas, 'wheel', this.wheelZoom, this);
|
||||
|
||||
this.watchForMarquee();
|
||||
|
||||
@ -92,6 +93,12 @@ define([
|
||||
this.$scope.series = this.config.series.models;
|
||||
this.$scope.legend = this.config.legend;
|
||||
|
||||
this.cursorGuideVertical = this.$element[0].querySelector('.js-cursor-guide--v');
|
||||
this.cursorGuideHorizontal = this.$element[0].querySelector('.js-cursor-guide--h');
|
||||
this.cursorGuide = false;
|
||||
|
||||
this.listenTo(this.$scope, 'cursorguide', this.toggleCursorGuide, this);
|
||||
|
||||
this.listenTo(this.$scope, '$destroy', this.destroy, this);
|
||||
this.listenTo(this.$scope, 'plot:tickWidth', this.onTickWidthChange, this);
|
||||
this.listenTo(this.$scope, 'plot:highlight:set', this.onPlotHighlightSet, this);
|
||||
@ -143,6 +150,9 @@ define([
|
||||
y: this.yScale.invert(this.positionOverElement.y)
|
||||
};
|
||||
|
||||
if (this.cursorGuide) {
|
||||
this.updateCrosshairs($event);
|
||||
}
|
||||
this.highlightValues(this.positionOverPlot.x);
|
||||
this.updateMarquee();
|
||||
this.updatePan();
|
||||
@ -150,6 +160,11 @@ define([
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
MCTPlotController.prototype.updateCrosshairs = function ($event) {
|
||||
this.cursorGuideVertical.style.left = ($event.clientX - this.chartElementBounds.x) + 'px';
|
||||
this.cursorGuideHorizontal.style.top = ($event.clientY - this.chartElementBounds.y) + 'px';
|
||||
};
|
||||
|
||||
MCTPlotController.prototype.trackChartElementBounds = function ($event) {
|
||||
if ($event.target === this.$canvas[1]) {
|
||||
this.chartElementBounds = $event.target.getBoundingClientRect();
|
||||
@ -266,6 +281,102 @@ define([
|
||||
this.marquee = undefined;
|
||||
};
|
||||
|
||||
MCTPlotController.prototype.zoom = function (zoomDirection, zoomFactor) {
|
||||
this.freeze();
|
||||
this.trackHistory();
|
||||
var currentXaxis = this.$scope.xAxis.get('displayRange'),
|
||||
currentYaxis = this.$scope.yAxis.get('displayRange'),
|
||||
xAxisDist= (currentXaxis.max - currentXaxis.min) * zoomFactor,
|
||||
yAxisDist = (currentYaxis.max - currentYaxis.min) * zoomFactor;
|
||||
|
||||
if (zoomDirection === 'in') {
|
||||
this.$scope.xAxis.set('displayRange', {
|
||||
min: currentXaxis.min + xAxisDist,
|
||||
max: currentXaxis.max - xAxisDist
|
||||
});
|
||||
|
||||
this.$scope.yAxis.set('displayRange', {
|
||||
min: currentYaxis.min + yAxisDist,
|
||||
max: currentYaxis.max - yAxisDist
|
||||
});
|
||||
} else if (zoomDirection === 'out') {
|
||||
this.$scope.xAxis.set('displayRange', {
|
||||
min: currentXaxis.min - xAxisDist,
|
||||
max: currentXaxis.max + xAxisDist
|
||||
});
|
||||
|
||||
this.$scope.yAxis.set('displayRange', {
|
||||
min: currentYaxis.min - yAxisDist,
|
||||
max: currentYaxis.max + yAxisDist
|
||||
});
|
||||
}
|
||||
|
||||
this.$scope.$emit('user:viewport:change:end');
|
||||
};
|
||||
|
||||
MCTPlotController.prototype.wheelZoom = function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!this.positionOverPlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.freeze();
|
||||
window.clearTimeout(this.stillZooming);
|
||||
|
||||
let xDisplayRange = this.$scope.xAxis.get('displayRange'),
|
||||
yDisplayRange = this.$scope.yAxis.get('displayRange'),
|
||||
xAxisDist = (xDisplayRange.max - xDisplayRange.min),
|
||||
yAxisDist = (yDisplayRange.max - yDisplayRange.min),
|
||||
xDistMouseToMax = xDisplayRange.max - this.positionOverPlot.x,
|
||||
xDistMouseToMin = this.positionOverPlot.x - xDisplayRange.min,
|
||||
yDistMouseToMax = yDisplayRange.max - this.positionOverPlot.y,
|
||||
yDistMouseToMin = this.positionOverPlot.y - yDisplayRange.min,
|
||||
xAxisMaxDist = xDistMouseToMax / xAxisDist,
|
||||
xAxisMinDist = xDistMouseToMin / xAxisDist,
|
||||
yAxisMaxDist = yDistMouseToMax / yAxisDist,
|
||||
yAxisMinDist = yDistMouseToMin / yAxisDist;
|
||||
|
||||
let plotHistoryStep;
|
||||
|
||||
if (!plotHistoryStep) {
|
||||
plotHistoryStep = {
|
||||
x: xDisplayRange,
|
||||
y: yDisplayRange
|
||||
};
|
||||
}
|
||||
|
||||
if (event.wheelDelta < 0) {
|
||||
|
||||
this.$scope.xAxis.set('displayRange', {
|
||||
min: xDisplayRange.min + ((xAxisDist * 0.01) * xAxisMinDist),
|
||||
max: xDisplayRange.max - ((xAxisDist * 0.01) * xAxisMaxDist)
|
||||
});
|
||||
|
||||
this.$scope.yAxis.set('displayRange', {
|
||||
min: yDisplayRange.min + ((yAxisDist * 0.01) * yAxisMinDist),
|
||||
max: yDisplayRange.max - ((yAxisDist * 0.01) * yAxisMaxDist)
|
||||
});
|
||||
} else if (event.wheelDelta >= 0) {
|
||||
|
||||
this.$scope.xAxis.set('displayRange', {
|
||||
min: xDisplayRange.min - ((xAxisDist * 0.01) * xAxisMinDist),
|
||||
max: xDisplayRange.max + ((xAxisDist * 0.01) * xAxisMaxDist)
|
||||
});
|
||||
|
||||
this.$scope.yAxis.set('displayRange', {
|
||||
min: yDisplayRange.min - ((yAxisDist * 0.01) * yAxisMinDist),
|
||||
max: yDisplayRange.max + ((yAxisDist * 0.01) * yAxisMaxDist)
|
||||
});
|
||||
}
|
||||
|
||||
this.stillZooming = window.setTimeout(function () {
|
||||
this.plotHistory.push(plotHistoryStep);
|
||||
plotHistoryStep = undefined;
|
||||
this.$scope.$emit('user:viewport:change:end');
|
||||
}.bind(this), 250);
|
||||
};
|
||||
|
||||
MCTPlotController.prototype.startPan = function ($event) {
|
||||
this.trackMousePosition($event);
|
||||
this.freeze();
|
||||
@ -362,5 +473,9 @@ define([
|
||||
this.stopListening();
|
||||
};
|
||||
|
||||
MCTPlotController.prototype.toggleCursorGuide = function ($event) {
|
||||
this.cursorGuide = !this.cursorGuide;
|
||||
};
|
||||
|
||||
return MCTPlotController;
|
||||
});
|
||||
|
@ -30,7 +30,7 @@ define(
|
||||
],
|
||||
function (
|
||||
html2canvas,
|
||||
saveAs
|
||||
{ saveAs }
|
||||
) {
|
||||
|
||||
/**
|
||||
|
@ -59,6 +59,7 @@ define([
|
||||
this.openmct = openmct;
|
||||
this.objectService = objectService;
|
||||
this.exportImageService = exportImageService;
|
||||
this.cursorGuide = false;
|
||||
|
||||
$scope.pending = 0;
|
||||
|
||||
@ -71,6 +72,14 @@ define([
|
||||
this.config.series.forEach(this.addSeries, this);
|
||||
|
||||
this.followTimeConductor();
|
||||
|
||||
this.newStyleDomainObject = $scope.domainObject.useCapability('adapter');
|
||||
|
||||
this.filterObserver = this.openmct.objects.observe(
|
||||
this.newStyleDomainObject,
|
||||
'configuration.filters',
|
||||
this.updateFiltersAndResubscribe.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
eventHelpers.extend(PlotController.prototype);
|
||||
@ -154,6 +163,9 @@ define([
|
||||
clearInterval(this.checkForSize);
|
||||
delete this.checkForSize;
|
||||
}
|
||||
if (this.filterObserver) {
|
||||
this.filterObserver();
|
||||
}
|
||||
};
|
||||
|
||||
PlotController.prototype.loadMoreData = function (range, purge) {
|
||||
@ -244,6 +256,12 @@ define([
|
||||
xRange.max === xDisplayRange.max);
|
||||
};
|
||||
|
||||
PlotController.prototype.updateFiltersAndResubscribe = function (updatedFilters) {
|
||||
this.config.series.forEach(function (series) {
|
||||
series.updateFiltersAndRefresh(updatedFilters[series.keyString]);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Export view as JPG.
|
||||
*/
|
||||
@ -266,6 +284,11 @@ define([
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
PlotController.prototype.toggleCursorGuide = function ($event) {
|
||||
this.cursorGuide = !this.cursorGuide;
|
||||
this.$scope.$broadcast('cursorguide', $event);
|
||||
};
|
||||
|
||||
return PlotController;
|
||||
|
||||
});
|
||||
|
@ -35,6 +35,8 @@ define([
|
||||
|
||||
this.$element = $element;
|
||||
this.exportImageService = exportImageService;
|
||||
this.$scope = $scope;
|
||||
this.cursorGuide = false;
|
||||
|
||||
$scope.telemetryObjects = [];
|
||||
|
||||
@ -145,5 +147,10 @@ define([
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
StackedPlotController.prototype.toggleCursorGuide = function ($event) {
|
||||
this.cursorGuide = !this.cursorGuide;
|
||||
this.$scope.$broadcast('cursorguide', $event);
|
||||
};
|
||||
|
||||
return StackedPlotController;
|
||||
});
|
||||
|
@ -39,7 +39,9 @@ define([
|
||||
'./folderView/plugin',
|
||||
'./flexibleLayout/plugin',
|
||||
'./tabs/plugin',
|
||||
'./LADTable/plugin'
|
||||
'./LADTable/plugin',
|
||||
'./filters/plugin',
|
||||
'./objectMigration/plugin'
|
||||
], function (
|
||||
_,
|
||||
UTCTimeSystem,
|
||||
@ -59,7 +61,9 @@ define([
|
||||
FolderView,
|
||||
FlexibleLayout,
|
||||
Tabs,
|
||||
LADTable
|
||||
LADTable,
|
||||
Filters,
|
||||
ObjectMigration
|
||||
) {
|
||||
var bundleMap = {
|
||||
LocalStorage: 'platform/persistence/local',
|
||||
@ -74,26 +78,6 @@ define([
|
||||
};
|
||||
});
|
||||
|
||||
plugins.Snow = function () {
|
||||
return function install(openmct) {
|
||||
openmct.legacyExtension('constants', {
|
||||
key: "THEME",
|
||||
value: "snow"
|
||||
});
|
||||
import('snow' /* webpackChunkName: "theme-snow" */);
|
||||
};
|
||||
};
|
||||
|
||||
plugins.Espresso = function () {
|
||||
return function install(openmct) {
|
||||
openmct.legacyExtension('constants', {
|
||||
key: "THEME",
|
||||
value: "espresso"
|
||||
});
|
||||
import('espresso' /* webpackChunkName: "theme-espresso" */);
|
||||
};
|
||||
};
|
||||
|
||||
plugins.UTCTimeSystem = UTCTimeSystem;
|
||||
|
||||
plugins.ImportExport = ImportExport;
|
||||
@ -174,6 +158,8 @@ define([
|
||||
plugins.Tabs = Tabs;
|
||||
plugins.FlexibleLayout = FlexibleLayout;
|
||||
plugins.LADTable = LADTable;
|
||||
plugins.Filters = Filters;
|
||||
plugins.ObjectMigration = ObjectMigration.default;
|
||||
|
||||
return plugins;
|
||||
});
|
||||
|
101
src/plugins/remove/RemoveAction.js
Normal file
101
src/plugins/remove/RemoveAction.js
Normal file
@ -0,0 +1,101 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2019, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
export default class RemoveAction {
|
||||
constructor(openmct) {
|
||||
this.name = 'Remove';
|
||||
this.description = 'Remove this object from its containing object.';
|
||||
this.cssClass = "icon-trash";
|
||||
|
||||
this.openmct = openmct;
|
||||
}
|
||||
|
||||
invoke(objectPath) {
|
||||
let object = objectPath[0];
|
||||
let parent = objectPath[1];
|
||||
this.showConfirmDialog(object).then(() => {
|
||||
this.removeFromComposition(parent, object);
|
||||
if (this.inNavigationPath(object)) {
|
||||
this.navigateTo(objectPath.slice(1));
|
||||
}
|
||||
}).catch(() =>{});
|
||||
}
|
||||
|
||||
showConfirmDialog(object) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let dialog = this.openmct.overlays.dialog({
|
||||
title: `Remove ${object.name}`,
|
||||
iconClass: 'alert',
|
||||
message: 'Warning! This action will remove this object. Are you sure you want to continue?',
|
||||
buttons: [
|
||||
{
|
||||
label: 'OK',
|
||||
callback: () => {
|
||||
dialog.dismiss();
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Cancel',
|
||||
callback: () => {
|
||||
dialog.dismiss();
|
||||
reject();
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
inNavigationPath(object) {
|
||||
return this.openmct.router.path
|
||||
.some(objectInPath => this.openmct.objects.areIdsEqual(objectInPath.identifier, object.identifier));
|
||||
}
|
||||
|
||||
navigateTo(objectPath) {
|
||||
let urlPath = objectPath.reverse()
|
||||
.map(object => this.openmct.objects.makeKeyString(object.identifier))
|
||||
.join("/");
|
||||
|
||||
window.location.href = '#/browse/' + urlPath;
|
||||
}
|
||||
|
||||
removeFromComposition(parent, child) {
|
||||
let composition = parent.composition.filter(id =>
|
||||
!this.openmct.objects.areIdsEqual(id, child.identifier)
|
||||
);
|
||||
|
||||
this.openmct.objects.mutate(parent, 'composition', composition);
|
||||
}
|
||||
|
||||
appliesTo(objectPath) {
|
||||
let object = objectPath[0];
|
||||
let objectType = object && this.openmct.types.get(object.type);
|
||||
let parent = objectPath[1];
|
||||
let parentType = parent && this.openmct.types.get(parent.type);
|
||||
|
||||
return objectType.definition.creatable &&
|
||||
parentType &&
|
||||
parentType.definition.creatable &&
|
||||
Array.isArray(parent.composition);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2019, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@ -19,13 +19,10 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/* Styles for the iframe EmbeddedPageController element */
|
||||
import RemoveAction from "./RemoveAction";
|
||||
|
||||
.l-iframe {
|
||||
iframe {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: none;
|
||||
export default function () {
|
||||
return function (openmct) {
|
||||
openmct.contextMenu.registerAction(new RemoveAction(openmct));
|
||||
}
|
||||
}
|
@ -61,7 +61,6 @@ define([
|
||||
"key": "url",
|
||||
"name": "URL",
|
||||
"control": "textfield",
|
||||
"pattern": "^(ftp|https?)\\:\\/\\/",
|
||||
"required": false,
|
||||
"cssClass": "l-input-lg"
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
<a class="e-control s-button s-menu-button menu-element">
|
||||
<!--a class="e-control s-button s-menu-button menu-element">
|
||||
<span class="l-click-area"></span>
|
||||
<span class="t-swatch"></span>
|
||||
<div class="menu l-palette">
|
||||
@ -7,4 +7,15 @@
|
||||
<span class="l-palette-item-label">None</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</a-->
|
||||
<div class="c-ctrl-wrapper">
|
||||
<button class="c-button--menu c-button--swatched js-button">
|
||||
<div class="c-swatch t-swatch"></div>
|
||||
</button>
|
||||
<div class="c-menu c-palette">
|
||||
<div class="c-palette__item-none">
|
||||
<div class="c-palette__item"></div>
|
||||
</div>
|
||||
<div class="c-palette__items"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="e-control select">
|
||||
<span>
|
||||
<select>
|
||||
</select>
|
||||
</div>
|
||||
</span>
|
||||
|
@ -1,21 +1,20 @@
|
||||
<div>
|
||||
<div class="l-compact-form has-local-controls l-widget-rule s-widget-rule">
|
||||
<div class="widget-rule-header">
|
||||
<span class="flex-elem l-widget-thumb-wrapper">
|
||||
<span class="grippy-holder">
|
||||
<span class="t-grippy grippy local-control local-controls-hidden"></span>
|
||||
</span>
|
||||
<span class="view-control expanded"></span>
|
||||
<span class="t-widget-thumb widget-thumb">
|
||||
<span class="widget-label">DEF</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="flex-elem rule-title">Default Title</span>
|
||||
<span class="flex-elem rule-description grows">Rule description goes here</span>
|
||||
<span class="flex-elem local-control local-controls-hidden l-rule-action-buttons-wrapper">
|
||||
<div class="c-sw-rule">
|
||||
<div class="c-sw-rule__ui l-compact-form has-local-controls l-widget-rule s-widget-rule">
|
||||
<div class="c-sw-rule__ui__header widget-rule-header">
|
||||
<div class="c-sw-rule__grippy-wrapper">
|
||||
<div class="c-sw-rule__grippy t-grippy local-control local-controls-hidden"></div>
|
||||
</div>
|
||||
<div class="c-disclosure-triangle c-disclosure-triangle--expanded is-enabled js-disclosure"></div>
|
||||
<div class="t-widget-thumb widget-thumb c-sw c-sw--thumb">
|
||||
<div class="c-sw__icon js-sw__icon"></div>
|
||||
<div class="c-sw__label js-sw__label"></div>
|
||||
</div>
|
||||
<div class="flex-elem rule-title">Default Title</div>
|
||||
<div class="flex-elem rule-description grows">Rule description goes here</div>
|
||||
<div class="flex-elem local-control local-controls-hidden l-rule-action-buttons-wrapper">
|
||||
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this rule"></a>
|
||||
<a class="s-icon-button icon-trash t-delete" title="Delete this rule"></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="widget-rule-content expanded">
|
||||
<ul>
|
||||
@ -28,7 +27,7 @@
|
||||
<li class="connects-to-previous">
|
||||
<label>Label:</label>
|
||||
<span class="controls t-label-input">
|
||||
<input class="e-control t-rule-label-input" type="text" />
|
||||
<input class="t-rule-label-input" type="text" />
|
||||
</span>
|
||||
</li>
|
||||
<li class="connects-to-previous">
|
||||
@ -40,26 +39,25 @@
|
||||
</li>
|
||||
<li class="connects-to-previous">
|
||||
<label>Style:</label>
|
||||
<span class="controls t-style-input">
|
||||
</span>
|
||||
<span class="controls t-style-input"></span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="t-widget-rule-config">
|
||||
<li>
|
||||
<label>Trigger when</label>
|
||||
<span class="controls">
|
||||
<div class="e-control select">
|
||||
<select class="t-trigger">
|
||||
<option value="any">any condition is met</option>
|
||||
<option value="all">all conditions are met</option>
|
||||
</select>
|
||||
</div>
|
||||
<select class="t-trigger">
|
||||
<option value="any">any condition is met</option>
|
||||
<option value="all">all conditions are met</option>
|
||||
</select>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<label></label>
|
||||
<span class="controls">
|
||||
<a class="e-control s-button labeled add-condition icon-plus">Add Condition</a>
|
||||
<button class="c-button add-condition icon-plus">
|
||||
<span class="c-button__label">Add Condition</span>
|
||||
</button>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -8,7 +8,9 @@
|
||||
</div>
|
||||
<div class="t-test-data-config w-widget-test-data-items">
|
||||
<div class="holder add-rule-button-wrapper align-right">
|
||||
<a id="addRule" class="e-control s-button major labeled add-test-condition icon-plus">Add Test Value</a>
|
||||
<button id="addRule" class="c-button c-button--major add-test-condition icon-plus">
|
||||
<span class="c-button__label">Add Test Value</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,22 +1,31 @@
|
||||
<div class="w-summary-widget s-status-no-data">
|
||||
<a id="widget" class="t-summary-widget l-summary-widget s-summary-widget labeled">
|
||||
<span id="widgetLabel" class="label widget-label">Default Static Name</span>
|
||||
<div class="c-sw-edit w-summary-widget s-status-no-data">
|
||||
<a id="widget" class="t-summary-widget l-summary-widget s-summary-widget labeled c-sw">
|
||||
<div id="widgetIcon" class="c-sw__icon js-sw__icon"></div>
|
||||
<div id="widgetLabel" class="label widget-label c-sw__label js-sw__label">Default Static Name</div>
|
||||
</a>
|
||||
<div class="holder flex-elem t-message-inline l-message message-severity-alert t-message-widget-no-data">
|
||||
<div class="c-summary-widget__message holder flex-elem t-message-inline c-message message-severity-alert t-message-widget-no-data">
|
||||
<div class="w-message-contents l-message-body-only">
|
||||
<div class="message-body">
|
||||
You must add at least one telemetry object to edit this widget.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="holder l-flex-col l-flex-accordion flex-elem grows widget-edit-holder expanded-widget-test-data expanded-widget-rules">
|
||||
<div class="section-header"><span class="view-control t-view-control-test-data expanded"></span>Test Data Values</div>
|
||||
<div class="widget-test-data flex-accordion-holder"></div>
|
||||
<div class="section-header"><span class="view-control t-view-control-rules expanded"></span>Rules</div>
|
||||
<div class="holder widget-rules-wrapper flex-elem expanded">
|
||||
<div id="ruleArea" class="widget-rules"></div>
|
||||
<div class="c-sw-edit__ui holder l-flex-accordion flex-elem grows widget-edit-holder expanded-widget-test-data expanded-widget-rules">
|
||||
<div class="c-sw-edit__ui__header">
|
||||
<span class="c-disclosure-triangle c-disclosure-triangle--expanded is-enabled t-view-control-test-data"></span>
|
||||
<span class="c-sw-edit__ui__header-label">Test Data Values</span>
|
||||
</div>
|
||||
<div class="c-sw-edit__ui__test-data widget-test-data flex-accordion-holder"></div>
|
||||
<div class="c-sw-edit__ui__header">
|
||||
<span class="c-disclosure-triangle c-disclosure-triangle--expanded is-enabled t-view-control-rules"></span>
|
||||
<span class="c-sw-edit__ui__header-label">Rules</span>
|
||||
</div>
|
||||
<div class="c-sw-editui__rules-wrapper holder widget-rules-wrapper flex-elem expanded">
|
||||
<div id="ruleArea" class="c-sw-editui__rules widget-rules"></div>
|
||||
<div class="holder add-rule-button-wrapper align-right">
|
||||
<a id="addRule" class="s-button major labeled add-rule-button icon-plus">Add Rule</a>
|
||||
<button id="addRule" class="c-button c-button--major add-rule-button icon-plus">
|
||||
<span class="c-button__label">Add Rule</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -32,6 +32,7 @@ define([
|
||||
function Rule(ruleConfig, domainObject, openmct, conditionManager, widgetDnD, container) {
|
||||
eventHelpers.extend(this);
|
||||
var self = this;
|
||||
const THUMB_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
|
||||
this.config = ruleConfig;
|
||||
this.domainObject = domainObject;
|
||||
@ -50,11 +51,12 @@ define([
|
||||
this.duplicate = this.duplicate.bind(this);
|
||||
|
||||
this.thumbnail = $('.t-widget-thumb', this.domElement);
|
||||
this.thumbnailLabel = $('.widget-label', this.domElement);
|
||||
this.thumbnailIcon = $('.js-sw__icon', this.domElement);
|
||||
this.thumbnailLabel = $('.c-sw__label', this.domElement);
|
||||
this.title = $('.rule-title', this.domElement);
|
||||
this.description = $('.rule-description', this.domElement);
|
||||
this.trigger = $('.t-trigger', this.domElement);
|
||||
this.toggleConfigButton = $('.view-control', this.domElement);
|
||||
this.toggleConfigButton = $('.js-disclosure', this.domElement);
|
||||
this.configArea = $('.widget-rule-content', this.domElement);
|
||||
this.grippy = $('.t-grippy', this.domElement);
|
||||
this.conditionArea = $('.t-widget-rule-config', this.domElement);
|
||||
@ -79,7 +81,7 @@ define([
|
||||
this.colorInputs = {
|
||||
'background-color': new ColorPalette('icon-paint-bucket', container),
|
||||
'border-color': new ColorPalette('icon-line-horz', container),
|
||||
'color': new ColorPalette('icon-T', container)
|
||||
'color': new ColorPalette('icon-font', container)
|
||||
};
|
||||
|
||||
this.colorInputs.color.toggleNullOption();
|
||||
@ -92,7 +94,7 @@ define([
|
||||
function onIconInput(icon) {
|
||||
self.config.icon = icon;
|
||||
self.updateDomainObject('icon', icon);
|
||||
self.thumbnailLabel.removeClass().addClass('label widget-label ' + icon);
|
||||
self.thumbnailIcon.removeClass().addClass(THUMB_ICON_CLASS + ' ' + icon);
|
||||
self.eventEmitter.emit('change');
|
||||
}
|
||||
|
||||
@ -168,7 +170,7 @@ define([
|
||||
*/
|
||||
function toggleConfig() {
|
||||
self.configArea.toggleClass('expanded');
|
||||
self.toggleConfigButton.toggleClass('expanded');
|
||||
self.toggleConfigButton.toggleClass('c-disclosure-triangle--expanded');
|
||||
self.config.expanded = !self.config.expanded;
|
||||
}
|
||||
|
||||
@ -179,7 +181,7 @@ define([
|
||||
});
|
||||
|
||||
// Initialize thumbs when first loading
|
||||
this.thumbnailLabel.removeClass().addClass('label widget-label ' + self.config.icon);
|
||||
this.thumbnailIcon.removeClass().addClass(THUMB_ICON_CLASS + ' ' + self.config.icon);
|
||||
this.thumbnailLabel.html(self.config.label);
|
||||
|
||||
Object.keys(this.colorInputs).forEach(function (inputKey) {
|
||||
@ -227,7 +229,7 @@ define([
|
||||
|
||||
if (!this.config.expanded) {
|
||||
this.configArea.removeClass('expanded');
|
||||
this.toggleConfigButton.removeClass('expanded');
|
||||
this.toggleConfigButton.removeClass('c-disclosure-triangle--expanded');
|
||||
}
|
||||
|
||||
if (this.domainObject.configuration.ruleOrder.length === 2) {
|
||||
|
@ -22,8 +22,8 @@ define([
|
||||
|
||||
//default css configuration for new rules
|
||||
var DEFAULT_PROPS = {
|
||||
'color': '#ffffff',
|
||||
'background-color': '#38761d',
|
||||
'color': '#cccccc',
|
||||
'background-color': '#666666',
|
||||
'border-color': 'rgba(0,0,0,0)'
|
||||
};
|
||||
|
||||
@ -74,15 +74,12 @@ define([
|
||||
this.show = this.show.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
this.addRule = this.addRule.bind(this);
|
||||
this.onEdit = this.onEdit.bind(this);
|
||||
|
||||
this.addHyperlink(domainObject.url, domainObject.openNewTab);
|
||||
this.watchForChanges(openmct, domainObject);
|
||||
|
||||
var id = objectUtils.makeKeyString(this.domainObject.identifier),
|
||||
self = this,
|
||||
oldDomainObject,
|
||||
statusCapability;
|
||||
self = this;
|
||||
|
||||
/**
|
||||
* Toggles the configuration area for test data in the view
|
||||
@ -90,7 +87,7 @@ define([
|
||||
*/
|
||||
function toggleTestData() {
|
||||
self.outerWrapper.toggleClass('expanded-widget-test-data');
|
||||
self.toggleTestDataControl.toggleClass('expanded');
|
||||
self.toggleTestDataControl.toggleClass('c-disclosure-triangle--expanded');
|
||||
}
|
||||
this.listenTo(this.toggleTestDataControl, 'click', toggleTestData);
|
||||
|
||||
@ -100,22 +97,12 @@ define([
|
||||
*/
|
||||
function toggleRules() {
|
||||
self.outerWrapper.toggleClass('expanded-widget-rules');
|
||||
self.toggleRulesControl.toggleClass('expanded');
|
||||
self.toggleRulesControl.toggleClass('c-disclosure-triangle--expanded');
|
||||
}
|
||||
this.listenTo(this.toggleRulesControl, 'click', toggleRules);
|
||||
|
||||
openmct.$injector.get('objectService')
|
||||
.getObjects([id])
|
||||
.then(function (objs) {
|
||||
oldDomainObject = objs[id];
|
||||
statusCapability = oldDomainObject.getCapability('status');
|
||||
self.editListenerUnsubscribe = statusCapability.listen(self.onEdit);
|
||||
if (statusCapability.get('editing')) {
|
||||
self.onEdit(['editing']);
|
||||
} else {
|
||||
self.onEdit([]);
|
||||
}
|
||||
});
|
||||
.getObjects([id]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,7 +159,6 @@ define([
|
||||
});
|
||||
this.refreshRules();
|
||||
this.updateWidget();
|
||||
this.updateView();
|
||||
|
||||
this.listenTo(this.addRuleButton, 'click', this.addRule);
|
||||
this.conditionManager.on('receiveTelemetry', this.executeRules, this);
|
||||
@ -196,37 +182,6 @@ define([
|
||||
this.stopListening();
|
||||
};
|
||||
|
||||
/**
|
||||
* A callback function for the Open MCT status capability listener. If the
|
||||
* view representing the domain object is in edit mode, update the internal
|
||||
* state and widget view accordingly.
|
||||
* @param {string[]} status an array containing the domain object's current status
|
||||
*/
|
||||
SummaryWidget.prototype.onEdit = function (status) {
|
||||
if (status && status.includes('editing')) {
|
||||
this.editing = true;
|
||||
} else {
|
||||
this.editing = false;
|
||||
}
|
||||
this.updateView();
|
||||
};
|
||||
|
||||
/**
|
||||
* If this view is currently in edit mode, show all rule configuration interfaces.
|
||||
* Otherwise, hide them.
|
||||
*/
|
||||
SummaryWidget.prototype.updateView = function () {
|
||||
if (this.editing) {
|
||||
this.ruleArea.show();
|
||||
this.testDataArea.show();
|
||||
this.addRuleButton.show();
|
||||
} else {
|
||||
this.ruleArea.hide();
|
||||
this.testDataArea.hide();
|
||||
this.addRuleButton.hide();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the view from the current rule configuration and order
|
||||
*/
|
||||
@ -260,11 +215,14 @@ define([
|
||||
* Update the widget's appearance from the configuration of the active rule
|
||||
*/
|
||||
SummaryWidget.prototype.updateWidget = function () {
|
||||
const WIDGET_CLASS = 'c-sw js-sw',
|
||||
WIDGET_LABEL_CLASS = 'c-sw__label js-sw__label',
|
||||
WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
var activeRule = this.rulesById[this.activeId];
|
||||
this.applyStyle($('#widget', this.domElement), activeRule.getProperty('style'));
|
||||
$('#widget', this.domElement).prop('title', activeRule.getProperty('message'));
|
||||
$('#widgetLabel', this.domElement).html(activeRule.getProperty('label'));
|
||||
$('#widgetLabel', this.domElement).removeClass().addClass('label widget-label c-summary-widget__label ' + activeRule.getProperty('icon'));
|
||||
$('#widgetIcon', this.domElement).removeClass().addClass(WIDGET_ICON_CLASS + ' ' + activeRule.getProperty('icon'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -36,11 +36,11 @@ function (
|
||||
var domElement = $(this.palette.getDOM()),
|
||||
self = this;
|
||||
|
||||
$('.s-menu-button', domElement).addClass('t-color-palette-menu-button');
|
||||
$('.c-button--menu', domElement).addClass('c-button--swatched');
|
||||
$('.t-swatch', domElement).addClass('color-swatch');
|
||||
$('.l-palette', domElement).addClass('l-color-palette');
|
||||
$('.c-palette', domElement).addClass('c-palette--color');
|
||||
|
||||
$('.s-palette-item', domElement).each(function () {
|
||||
$('.c-palette__item', domElement).each(function () {
|
||||
var elem = this;
|
||||
$(elem).css('background-color', elem.dataset.item);
|
||||
});
|
||||
|
@ -51,11 +51,11 @@ define([
|
||||
var domElement = $(this.palette.getDOM()),
|
||||
self = this;
|
||||
|
||||
$('.s-menu-button', domElement).addClass('t-icon-palette-menu-button');
|
||||
$('.c-button--menu', domElement).addClass('c-button--swatched');
|
||||
$('.t-swatch', domElement).addClass('icon-swatch');
|
||||
$('.l-palette', domElement).addClass('l-icon-palette');
|
||||
$('.c-palette', domElement).addClass('c-palette--icon');
|
||||
|
||||
$('.s-palette-item', domElement).each(function () {
|
||||
$('.c-palette-item', domElement).each(function () {
|
||||
var elem = this;
|
||||
$(elem).addClass(elem.dataset.item);
|
||||
});
|
||||
|
@ -30,33 +30,34 @@ define([
|
||||
|
||||
this.domElement = $(paletteTemplate);
|
||||
this.itemElements = {
|
||||
nullOption: $('.l-option-row .s-palette-item', this.domElement)
|
||||
nullOption: $('.c-palette__item-none .c-palette__item', this.domElement)
|
||||
};
|
||||
this.eventEmitter = new EventEmitter();
|
||||
this.supportedCallbacks = ['change'];
|
||||
this.value = this.items[0];
|
||||
this.nullOption = ' ';
|
||||
this.button = $('.js-button', this.domElement);
|
||||
this.menu = $('.c-menu', this.domElement);
|
||||
|
||||
this.hideMenu = this.hideMenu.bind(this);
|
||||
|
||||
self.domElement.addClass(this.cssClass);
|
||||
self.button.addClass(this.cssClass);
|
||||
self.setNullOption(this.nullOption);
|
||||
|
||||
$('.l-palette-row', self.domElement).after('<div class = "l-palette-row"> </div>');
|
||||
self.items.forEach(function (item) {
|
||||
var itemElement = $('<div class = "l-palette-item s-palette-item"' +
|
||||
' data-item = ' + item + '> </div>');
|
||||
$('.l-palette-row:last-of-type', self.domElement).append(itemElement);
|
||||
var itemElement = $('<div class = "c-palette__item ' + item + '"' +
|
||||
' data-item = ' + item + '></div>');
|
||||
$('.c-palette__items', self.domElement).append(itemElement);
|
||||
self.itemElements[item] = itemElement;
|
||||
});
|
||||
|
||||
$('.menu', self.domElement).hide();
|
||||
$('.c-menu', self.domElement).hide();
|
||||
|
||||
this.listenTo($(document), 'click', this.hideMenu);
|
||||
this.listenTo($('.l-click-area', self.domElement), 'click', function (event) {
|
||||
this.listenTo($('.js-button', self.domElement), 'click', function (event) {
|
||||
event.stopPropagation();
|
||||
$('.menu', self.container).hide();
|
||||
$('.menu', self.domElement).show();
|
||||
$('.c-menu', self.container).hide();
|
||||
$('.c-menu', self.domElement).show();
|
||||
});
|
||||
|
||||
/**
|
||||
@ -69,10 +70,10 @@ define([
|
||||
var elem = event.currentTarget,
|
||||
item = elem.dataset.item;
|
||||
self.set(item);
|
||||
$('.menu', self.domElement).hide();
|
||||
$('.c-menu', self.domElement).hide();
|
||||
}
|
||||
|
||||
this.listenTo($('.s-palette-item', self.domElement), 'click', handleItemClick);
|
||||
this.listenTo($('.c-palette__item', self.domElement), 'click', handleItemClick);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +91,7 @@ define([
|
||||
};
|
||||
|
||||
Palette.prototype.hideMenu = function () {
|
||||
$('.menu', this.domElement).hide();
|
||||
$('.c-menu', this.domElement).hide();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -139,8 +140,8 @@ define([
|
||||
* Update the view assoicated with the currently selected item
|
||||
*/
|
||||
Palette.prototype.updateSelected = function (item) {
|
||||
$('.s-palette-item', this.domElement).removeClass('selected');
|
||||
this.itemElements[item].addClass('selected');
|
||||
$('.c-palette__item', this.domElement).removeClass('is-selected');
|
||||
this.itemElements[item].addClass('is-selected');
|
||||
if (item === 'nullOption') {
|
||||
$('.t-swatch', this.domElement).addClass('no-selection');
|
||||
} else {
|
||||
@ -162,7 +163,7 @@ define([
|
||||
* Hides the 'no selection' option to be hidden in the view if it doesn't apply
|
||||
*/
|
||||
Palette.prototype.toggleNullOption = function () {
|
||||
$('.l-option-row', this.domElement).toggle();
|
||||
$('.c-palette__item-none', this.domElement).toggle();
|
||||
};
|
||||
|
||||
return Palette;
|
||||
|
@ -3,6 +3,8 @@ define([
|
||||
], function (
|
||||
summaryWidgetTemplate
|
||||
) {
|
||||
const WIDGET_ICON_CLASS = 'c-sw__icon js-sw__icon';
|
||||
|
||||
function SummaryWidgetView(domainObject, openmct) {
|
||||
this.openmct = openmct;
|
||||
this.domainObject = domainObject;
|
||||
@ -18,7 +20,7 @@ define([
|
||||
this.widget.title = datum.message;
|
||||
this.label.title = datum.message;
|
||||
this.label.innerHTML = datum.ruleLabel;
|
||||
this.label.className = 'label widget-label c-summary-widget__label ' + datum.icon;
|
||||
this.icon.className = WIDGET_ICON_CLASS + ' ' + datum.icon;
|
||||
};
|
||||
|
||||
SummaryWidgetView.prototype.render = function () {
|
||||
@ -29,7 +31,8 @@ define([
|
||||
|
||||
this.container.innerHTML = summaryWidgetTemplate;
|
||||
this.widget = this.container.querySelector('a');
|
||||
this.label = this.container.querySelector('.widget-label');
|
||||
this.icon = this.container.querySelector('#widgetIcon');
|
||||
this.label = this.container.querySelector('.js-sw__label');
|
||||
|
||||
|
||||
if (this.domainObject.url) {
|
||||
|
@ -1,5 +1,4 @@
|
||||
<div class="w-summary-widget s-status-no-data c-widget-wrapper u-contents">
|
||||
<a class="t-summary-widget c-button c-summary-widget u-links u-fills-container">
|
||||
<span class="label widget-label c-summary-widget__label">Loading...</span>
|
||||
</a>
|
||||
</div>
|
||||
<a class="t-summary-widget c-summary-widget js-sw u-links u-fills-container">
|
||||
<div id="widgetIcon" class="c-sw__icon js-sw__icon"></div>
|
||||
<div id="widgetLabel" class="c-sw__label js-sw__label">Loading...</div>
|
||||
</a>
|
@ -46,7 +46,7 @@ define([
|
||||
view: function (selection) {
|
||||
let component;
|
||||
let domainObject = selection[0].context.item;
|
||||
const tableConfiguration = new TelemetryTableConfiguration(domainObject, openmct);
|
||||
let tableConfiguration = new TelemetryTableConfiguration(domainObject, openmct);
|
||||
return {
|
||||
show: function (element) {
|
||||
component = new Vue({
|
||||
@ -64,6 +64,7 @@ define([
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
tableConfiguration = undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -53,13 +53,20 @@ define([
|
||||
this.isTelemetryObject = this.isTelemetryObject.bind(this);
|
||||
this.refreshData = this.refreshData.bind(this);
|
||||
this.requestDataFor = this.requestDataFor.bind(this);
|
||||
this.updateFilters = this.updateFilters.bind(this);
|
||||
this.buildOptionsFromConfiguration = this.buildOptionsFromConfiguration.bind(this);
|
||||
|
||||
this.filterObserver = undefined;
|
||||
|
||||
this.createTableRowCollections();
|
||||
|
||||
openmct.time.on('bounds', this.refreshData);
|
||||
openmct.time.on('timeSystem', this.refreshData);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
if (this.domainObject.type === 'table') {
|
||||
this.filterObserver = this.openmct.objects.observe(this.domainObject, 'configuration.filters', this.updateFilters);
|
||||
this.loadComposition();
|
||||
} else {
|
||||
this.addTelemetryObject(this.domainObject);
|
||||
@ -68,19 +75,24 @@ define([
|
||||
|
||||
createTableRowCollections() {
|
||||
this.boundedRows = new BoundedTableRowCollection(this.openmct);
|
||||
|
||||
//By default, sort by current time system, ascending.
|
||||
this.filteredRows = new FilteredTableRowCollection(this.boundedRows);
|
||||
this.filteredRows.sortBy({
|
||||
|
||||
//Fetch any persisted default sort
|
||||
let sortOptions = this.configuration.getConfiguration().sortOptions;
|
||||
|
||||
//If no persisted sort order, default to sorting by time system, ascending.
|
||||
sortOptions = sortOptions || {
|
||||
key: this.openmct.time.timeSystem().key,
|
||||
direction: 'asc'
|
||||
});
|
||||
};
|
||||
this.filteredRows.sortBy(sortOptions);
|
||||
}
|
||||
|
||||
loadComposition() {
|
||||
this.tableComposition = this.openmct.composition.get(this.domainObject);
|
||||
if (this.tableComposition !== undefined) {
|
||||
this.tableComposition.load().then((composition) => {
|
||||
|
||||
composition = composition.filter(this.isTelemetryObject);
|
||||
|
||||
this.configuration.addColumnsForAllObjects(composition);
|
||||
@ -101,6 +113,15 @@ define([
|
||||
this.emit('object-added', telemetryObject);
|
||||
}
|
||||
|
||||
updateFilters() {
|
||||
this.filteredRows.clear();
|
||||
this.boundedRows.clear();
|
||||
Object.keys(this.subscriptions).forEach(this.unsubscribe, this);
|
||||
|
||||
this.telemetryObjects.forEach(this.requestDataFor.bind(this));
|
||||
this.telemetryObjects.forEach(this.subscribeTo.bind(this));
|
||||
}
|
||||
|
||||
removeTelemetryObject(objectIdentifier) {
|
||||
this.configuration.removeColumnsForObject(objectIdentifier, true);
|
||||
let keyString = this.openmct.objects.makeKeyString(objectIdentifier);
|
||||
@ -113,8 +134,8 @@ define([
|
||||
|
||||
requestDataFor(telemetryObject) {
|
||||
this.incrementOutstandingRequests();
|
||||
|
||||
return this.openmct.telemetry.request(telemetryObject)
|
||||
let requestOptions = this.buildOptionsFromConfiguration(telemetryObject);
|
||||
return this.openmct.telemetry.request(telemetryObject, requestOptions)
|
||||
.then(telemetryData => {
|
||||
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
let columnMap = this.getColumnMapForObject(keyString);
|
||||
@ -151,6 +172,7 @@ define([
|
||||
if (!isTick) {
|
||||
this.filteredRows.clear();
|
||||
this.boundedRows.clear();
|
||||
this.boundedRows.sortByTimeSystem(this.openmct.time.timeSystem());
|
||||
this.telemetryObjects.forEach(this.requestDataFor);
|
||||
}
|
||||
}
|
||||
@ -165,29 +187,53 @@ define([
|
||||
}
|
||||
|
||||
subscribeTo(telemetryObject) {
|
||||
let subscribeOptions = this.buildOptionsFromConfiguration(telemetryObject);
|
||||
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
let columnMap = this.getColumnMapForObject(keyString);
|
||||
let limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
|
||||
|
||||
this.subscriptions[keyString] = this.openmct.telemetry.subscribe(telemetryObject, (datum) => {
|
||||
this.boundedRows.add(new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
|
||||
});
|
||||
}, subscribeOptions);
|
||||
}
|
||||
|
||||
isTelemetryObject(domainObject) {
|
||||
return domainObject.hasOwnProperty('telemetry');
|
||||
}
|
||||
|
||||
buildOptionsFromConfiguration(telemetryObject) {
|
||||
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier),
|
||||
filters = this.domainObject.configuration &&
|
||||
this.domainObject.configuration.filters &&
|
||||
this.domainObject.configuration.filters[keyString];
|
||||
|
||||
return {filters} || {};
|
||||
}
|
||||
|
||||
unsubscribe(keyString) {
|
||||
this.subscriptions[keyString]();
|
||||
delete this.subscriptions[keyString];
|
||||
}
|
||||
|
||||
sortBy(sortOptions) {
|
||||
this.filteredRows.sortBy(sortOptions);
|
||||
|
||||
if (this.openmct.editor.isEditing()) {
|
||||
let configuration = this.configuration.getConfiguration();
|
||||
configuration.sortOptions = sortOptions;
|
||||
this.configuration.updateConfiguration(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.boundedRows.destroy();
|
||||
this.filteredRows.destroy();
|
||||
Object.keys(this.subscriptions).forEach(this.unsubscribe, this);
|
||||
this.openmct.time.off('bounds', this.refreshData);
|
||||
this.openmct.time.on('timeSystem', this.refreshData);
|
||||
if (this.filterObserver) {
|
||||
this.filterObserver();
|
||||
}
|
||||
|
||||
if (this.tableComposition !== undefined) {
|
||||
this.tableComposition.off('add', this.addTelemetryObject);
|
||||
|
@ -49,7 +49,7 @@ define(function () {
|
||||
|
||||
getFormattedValue(telemetryDatum) {
|
||||
let formattedValue = this.formatter.format(telemetryDatum);
|
||||
if (typeof formattedValue !== 'string') {
|
||||
if (formattedValue !== undefined && typeof formattedValue !== 'string') {
|
||||
return formattedValue.toString();
|
||||
} else {
|
||||
return formattedValue;
|
||||
|
@ -44,7 +44,7 @@ define([], function () {
|
||||
|
||||
getRowLimitClass() {
|
||||
if (!this.rowLimitClass) {
|
||||
let limitEvaluation = this.limitEvaluator.evaluate(this.datum);
|
||||
let limitEvaluation = this.limitEvaluator.evaluate(this.datum);
|
||||
this.rowLimitClass = limitEvaluation && limitEvaluation.cssClass;
|
||||
}
|
||||
return this.rowLimitClass;
|
||||
|
@ -41,7 +41,6 @@ define(
|
||||
this.bounds = this.bounds.bind(this)
|
||||
|
||||
this.sortByTimeSystem(openmct.time.timeSystem());
|
||||
openmct.time.on('timeSystem', this.sortByTimeSystem);
|
||||
|
||||
this.lastBounds = openmct.time.bounds();
|
||||
openmct.time.on('bounds', this.bounds);
|
||||
@ -51,8 +50,8 @@ define(
|
||||
// Insert into either in-bounds array, or the future buffer.
|
||||
// Data in the future buffer will be re-evaluated for possible
|
||||
// insertion on next bounds change
|
||||
let beforeStartOfBounds = item.datum[this.sortOptions.key] < this.lastBounds.start;
|
||||
let afterEndOfBounds = item.datum[this.sortOptions.key] > this.lastBounds.end;
|
||||
let beforeStartOfBounds = this.parseTime(item.datum[this.sortOptions.key]) < this.lastBounds.start;
|
||||
let afterEndOfBounds = this.parseTime(item.datum[this.sortOptions.key]) > this.lastBounds.end;
|
||||
|
||||
if (!afterEndOfBounds && !beforeStartOfBounds) {
|
||||
return super.addOne(item);
|
||||
@ -64,6 +63,12 @@ define(
|
||||
|
||||
sortByTimeSystem(timeSystem) {
|
||||
this.sortBy({key: timeSystem.key, direction: 'asc'});
|
||||
let formatter = this.openmct.telemetry.getValueFormatter({
|
||||
key: timeSystem.key,
|
||||
source: timeSystem.key,
|
||||
format: timeSystem.timeFormat
|
||||
});
|
||||
this.parseTime = formatter.parse.bind(formatter);
|
||||
this.futureBuffer.sortBy({key: timeSystem.key, direction: 'asc'});
|
||||
}
|
||||
|
||||
@ -131,7 +136,6 @@ define(
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.openmct.time.off('timeSystem', this.sortByTimeSystem);
|
||||
this.openmct.time.off('bounds', this.bounds);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user