Compare commits
17 Commits
misc-fixes
...
alpha-enum
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fef060501 | ||
|
|
c38d810658 | ||
|
|
f5c48b7bf6 | ||
|
|
d0e08f1d9a | ||
|
|
72ea7b80fd | ||
|
|
35d0c02bc5 | ||
|
|
abd7506b45 | ||
|
|
526b4aa07e | ||
|
|
b5e23963d4 | ||
|
|
2c11eb90d4 | ||
|
|
90e9c79e19 | ||
|
|
1b83631e43 | ||
|
|
547d4e82db | ||
|
|
3377ad5e0d | ||
|
|
1c0df60f05 | ||
|
|
138067dca9 | ||
|
|
844280eaa5 |
@@ -86,6 +86,7 @@
|
|||||||
openmct.install(openmct.plugins.LADTable());
|
openmct.install(openmct.plugins.LADTable());
|
||||||
openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
|
openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
|
||||||
openmct.install(openmct.plugins.ObjectMigration());
|
openmct.install(openmct.plugins.ObjectMigration());
|
||||||
|
openmct.install(openmct.plugins.GoToOriginalAction());
|
||||||
openmct.start();
|
openmct.start();
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
"node-bourbon": "^4.2.3",
|
"node-bourbon": "^4.2.3",
|
||||||
"node-sass": "^4.9.2",
|
"node-sass": "^4.9.2",
|
||||||
"painterro": "^0.2.65",
|
"painterro": "^0.2.65",
|
||||||
"printj": "^1.1.0",
|
"printj": "^1.2.1",
|
||||||
"raw-loader": "^0.5.1",
|
"raw-loader": "^0.5.1",
|
||||||
"request": "^2.69.0",
|
"request": "^2.69.0",
|
||||||
"split": "^1.0.0",
|
"split": "^1.0.0",
|
||||||
|
|||||||
@@ -9,17 +9,17 @@
|
|||||||
ng-model="ngModel"
|
ng-model="ngModel"
|
||||||
ng-show="ngModel.progressPerc !== undefined"></mct-include>
|
ng-show="ngModel.progressPerc !== undefined"></mct-include>
|
||||||
</div>
|
</div>
|
||||||
<div class="c-overlay__button-bar">
|
</div>
|
||||||
<button ng-repeat="dialogOption in ngModel.options"
|
<div class="c-overlay__button-bar">
|
||||||
|
<button ng-repeat="dialogOption in ngModel.options"
|
||||||
class="c-button"
|
class="c-button"
|
||||||
ng-click="dialogOption.callback()">
|
ng-click="dialogOption.callback()">
|
||||||
{{dialogOption.label}}
|
{{dialogOption.label}}
|
||||||
</button>
|
</button>
|
||||||
<button class="c-button c-button--major"
|
<button class="c-button c-button--major"
|
||||||
ng-if="ngModel.primaryOption"
|
ng-if="ngModel.primaryOption"
|
||||||
ng-click="ngModel.primaryOption.callback()">
|
ng-click="ngModel.primaryOption.callback()">
|
||||||
{{ngModel.primaryOption.label}}
|
{{ngModel.primaryOption.label}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ define(
|
|||||||
* @returns boolean
|
* @returns boolean
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.inEditContext = function () {
|
EditorCapability.prototype.inEditContext = function () {
|
||||||
console.warn('DEPRECATION WARNING: isEditing checks must be done via openmct.editor.');
|
|
||||||
return this.openmct.editor.isEditing();
|
return this.openmct.editor.isEditing();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,7 +73,6 @@ define(
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.isEditContextRoot = function () {
|
EditorCapability.prototype.isEditContextRoot = function () {
|
||||||
console.warn('DEPRECATION WARNING: isEditing checks must be done via openmct.editor.');
|
|
||||||
return this.openmct.editor.isEditing();
|
return this.openmct.editor.isEditing();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ define([
|
|||||||
"./src/actions/MoveAction",
|
"./src/actions/MoveAction",
|
||||||
"./src/actions/CopyAction",
|
"./src/actions/CopyAction",
|
||||||
"./src/actions/LinkAction",
|
"./src/actions/LinkAction",
|
||||||
"./src/actions/GoToOriginalAction",
|
|
||||||
"./src/actions/SetPrimaryLocationAction",
|
"./src/actions/SetPrimaryLocationAction",
|
||||||
"./src/services/LocatingCreationDecorator",
|
"./src/services/LocatingCreationDecorator",
|
||||||
"./src/services/LocatingObjectDecorator",
|
"./src/services/LocatingObjectDecorator",
|
||||||
@@ -41,7 +40,6 @@ define([
|
|||||||
MoveAction,
|
MoveAction,
|
||||||
CopyAction,
|
CopyAction,
|
||||||
LinkAction,
|
LinkAction,
|
||||||
GoToOriginalAction,
|
|
||||||
SetPrimaryLocationAction,
|
SetPrimaryLocationAction,
|
||||||
LocatingCreationDecorator,
|
LocatingCreationDecorator,
|
||||||
LocatingObjectDecorator,
|
LocatingObjectDecorator,
|
||||||
@@ -104,14 +102,6 @@ define([
|
|||||||
"linkService"
|
"linkService"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"key": "follow",
|
|
||||||
"name": "Go To Original",
|
|
||||||
"description": "Go to the original, un-linked instance of this object.",
|
|
||||||
"cssClass": "",
|
|
||||||
"category": "contextual",
|
|
||||||
"implementation": GoToOriginalAction
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "locate",
|
"key": "locate",
|
||||||
"name": "Set Primary Location",
|
"name": "Set Primary Location",
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
function () {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the "Go To Original" action, which follows a link back
|
|
||||||
* to an original instance of an object.
|
|
||||||
*
|
|
||||||
* @implements {Action}
|
|
||||||
* @constructor
|
|
||||||
* @private
|
|
||||||
* @memberof platform/entanglement
|
|
||||||
* @param {ActionContext} context the context in which the action
|
|
||||||
* will be performed
|
|
||||||
*/
|
|
||||||
function GoToOriginalAction(context) {
|
|
||||||
this.domainObject = context.domainObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
GoToOriginalAction.prototype.perform = function () {
|
|
||||||
return this.domainObject.getCapability("location").getOriginal()
|
|
||||||
.then(function (originalObject) {
|
|
||||||
var actionCapability =
|
|
||||||
originalObject.getCapability("action");
|
|
||||||
return actionCapability &&
|
|
||||||
actionCapability.perform("navigate");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
GoToOriginalAction.appliesTo = function (context) {
|
|
||||||
var domainObject = context.domainObject;
|
|
||||||
return domainObject && domainObject.hasCapability("location") &&
|
|
||||||
domainObject.getCapability("location").isLink();
|
|
||||||
};
|
|
||||||
|
|
||||||
return GoToOriginalAction;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2018, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
define(
|
|
||||||
[
|
|
||||||
'../../src/actions/GoToOriginalAction',
|
|
||||||
'../DomainObjectFactory',
|
|
||||||
'../ControlledPromise'
|
|
||||||
],
|
|
||||||
function (GoToOriginalAction, domainObjectFactory, ControlledPromise) {
|
|
||||||
|
|
||||||
describe("The 'go to original' action", function () {
|
|
||||||
var testContext,
|
|
||||||
originalDomainObject,
|
|
||||||
mockLocationCapability,
|
|
||||||
mockOriginalActionCapability,
|
|
||||||
originalPromise,
|
|
||||||
action;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockLocationCapability = jasmine.createSpyObj(
|
|
||||||
'location',
|
|
||||||
['isLink', 'isOriginal', 'getOriginal']
|
|
||||||
);
|
|
||||||
mockOriginalActionCapability = jasmine.createSpyObj(
|
|
||||||
'action',
|
|
||||||
['perform', 'getActions']
|
|
||||||
);
|
|
||||||
originalPromise = new ControlledPromise();
|
|
||||||
mockLocationCapability.getOriginal.and.returnValue(originalPromise);
|
|
||||||
mockLocationCapability.isLink.and.returnValue(true);
|
|
||||||
mockLocationCapability.isOriginal.and.callFake(function () {
|
|
||||||
return !mockLocationCapability.isLink();
|
|
||||||
});
|
|
||||||
testContext = {
|
|
||||||
domainObject: domainObjectFactory({
|
|
||||||
capabilities: {
|
|
||||||
location: mockLocationCapability
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
originalDomainObject = domainObjectFactory({
|
|
||||||
capabilities: {
|
|
||||||
action: mockOriginalActionCapability
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
action = new GoToOriginalAction(testContext);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("is applicable to links", function () {
|
|
||||||
expect(GoToOriginalAction.appliesTo(testContext))
|
|
||||||
.toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("is not applicable to originals", function () {
|
|
||||||
mockLocationCapability.isLink.and.returnValue(false);
|
|
||||||
expect(GoToOriginalAction.appliesTo(testContext))
|
|
||||||
.toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("navigates to original objects when performed", function () {
|
|
||||||
expect(mockOriginalActionCapability.perform)
|
|
||||||
.not.toHaveBeenCalled();
|
|
||||||
action.perform();
|
|
||||||
originalPromise.resolve(originalDomainObject);
|
|
||||||
expect(mockOriginalActionCapability.perform)
|
|
||||||
.toHaveBeenCalledWith('navigate');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
@@ -80,15 +80,17 @@ define(['zepto'], function ($) {
|
|||||||
var newObj;
|
var newObj;
|
||||||
|
|
||||||
seen.push(parent.getId());
|
seen.push(parent.getId());
|
||||||
parentModel.composition.forEach(function (childId, index) {
|
|
||||||
if (!tree[childId] || seen.includes(childId)) {
|
parentModel.composition.forEach(function (childId) {
|
||||||
|
let keystring = this.openmct.objects.makeKeyString(childId);
|
||||||
|
|
||||||
|
if (!tree[keystring] || seen.includes(keystring)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
newObj = this.instantiate(tree[childId], childId);
|
newObj = this.instantiate(tree[keystring], keystring);
|
||||||
parent.getCapability("composition").add(newObj);
|
|
||||||
newObj.getCapability("location")
|
newObj.getCapability("location")
|
||||||
.setPrimaryLocation(tree[childId].location);
|
.setPrimaryLocation(tree[keystring].location);
|
||||||
this.deepInstantiate(newObj, tree, seen);
|
this.deepInstantiate(newObj, tree, seen);
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ define([
|
|||||||
'./runs/RegisterLegacyTypes',
|
'./runs/RegisterLegacyTypes',
|
||||||
'./services/LegacyObjectAPIInterceptor',
|
'./services/LegacyObjectAPIInterceptor',
|
||||||
'./views/installLegacyViews',
|
'./views/installLegacyViews',
|
||||||
'./policies/legacyCompositionPolicyAdapter',
|
'./policies/LegacyCompositionPolicyAdapter',
|
||||||
'./actions/LegacyActionAdapter'
|
'./actions/LegacyActionAdapter'
|
||||||
], function (
|
], function (
|
||||||
legacyRegistry,
|
legacyRegistry,
|
||||||
|
|||||||
@@ -45,22 +45,27 @@ define([
|
|||||||
view: function (domainObject) {
|
view: function (domainObject) {
|
||||||
let $rootScope = openmct.$injector.get('$rootScope');
|
let $rootScope = openmct.$injector.get('$rootScope');
|
||||||
let templateLinker = openmct.$injector.get('templateLinker');
|
let templateLinker = openmct.$injector.get('templateLinker');
|
||||||
let scope = $rootScope.$new();
|
let scope = $rootScope.$new(true);
|
||||||
let legacyObject = convertToLegacyObject(domainObject);
|
let legacyObject = convertToLegacyObject(domainObject);
|
||||||
let isDestroyed = false;
|
let isDestroyed = false;
|
||||||
let unlistenToStatus;
|
let unlistenToStatus;
|
||||||
|
let element;
|
||||||
scope.domainObject = legacyObject;
|
scope.domainObject = legacyObject;
|
||||||
scope.model = legacyObject.getModel();
|
scope.model = legacyObject.getModel();
|
||||||
|
let child;
|
||||||
|
let parent;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
show: function (container) {
|
show: function (container) {
|
||||||
|
parent = container;
|
||||||
|
child = document.createElement('div');
|
||||||
|
parent.appendChild(child);
|
||||||
let statusCapability = legacyObject.getCapability('status');
|
let statusCapability = legacyObject.getCapability('status');
|
||||||
unlistenToStatus = statusCapability.listen((newStatus) => {
|
unlistenToStatus = statusCapability.listen((newStatus) => {
|
||||||
container.classList.remove('s-status-timeconductor-unsynced');
|
child.classList.remove('s-status-timeconductor-unsynced');
|
||||||
|
|
||||||
if (newStatus.includes('timeconductor-unsynced')) {
|
if (newStatus.includes('timeconductor-unsynced')) {
|
||||||
container.classList.add('s-status-timeconductor-unsynced');
|
child.classList.add('s-status-timeconductor-unsynced');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,12 +89,13 @@ define([
|
|||||||
uses.forEach(function (key, i) {
|
uses.forEach(function (key, i) {
|
||||||
scope[key] = results[i];
|
scope[key] = results[i];
|
||||||
});
|
});
|
||||||
|
element = openmct.$angular.element(child);
|
||||||
templateLinker.link(
|
templateLinker.link(
|
||||||
scope,
|
scope,
|
||||||
openmct.$angular.element(container),
|
element,
|
||||||
legacyView
|
legacyView
|
||||||
);
|
);
|
||||||
container.classList.add('u-contents');
|
child.classList.add('u-contents');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promises.length) {
|
if (promises.length) {
|
||||||
@@ -103,7 +109,11 @@ define([
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
|
element.off();
|
||||||
|
element.remove();
|
||||||
scope.$destroy();
|
scope.$destroy();
|
||||||
|
element = null;
|
||||||
|
scope = null;
|
||||||
unlistenToStatus();
|
unlistenToStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,15 +41,18 @@ define([
|
|||||||
let domainObject = selection[0][0].context.item;
|
let domainObject = selection[0][0].context.item;
|
||||||
let $rootScope = openmct.$injector.get('$rootScope');
|
let $rootScope = openmct.$injector.get('$rootScope');
|
||||||
let templateLinker = openmct.$injector.get('templateLinker');
|
let templateLinker = openmct.$injector.get('templateLinker');
|
||||||
let scope = $rootScope.$new();
|
let scope = $rootScope.$new(true);
|
||||||
let legacyObject = convertToLegacyObject(domainObject);
|
let legacyObject = convertToLegacyObject(domainObject);
|
||||||
let isDestroyed = false;
|
let isDestroyed = false;
|
||||||
|
let element;
|
||||||
scope.domainObject = legacyObject;
|
scope.domainObject = legacyObject;
|
||||||
scope.model = legacyObject.getModel();
|
scope.model = legacyObject.getModel();
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
show: function (container) {
|
show: function (container) {
|
||||||
|
let child = document.createElement('div');
|
||||||
|
container.appendChild(child);
|
||||||
// TODO: implement "gestures" support ?
|
// TODO: implement "gestures" support ?
|
||||||
let uses = representation.uses || [];
|
let uses = representation.uses || [];
|
||||||
let promises = [];
|
let promises = [];
|
||||||
@@ -70,9 +73,10 @@ define([
|
|||||||
uses.forEach(function (key, i) {
|
uses.forEach(function (key, i) {
|
||||||
scope[key] = results[i];
|
scope[key] = results[i];
|
||||||
});
|
});
|
||||||
|
element = openmct.$angular.element(child)
|
||||||
templateLinker.link(
|
templateLinker.link(
|
||||||
scope,
|
scope,
|
||||||
openmct.$angular.element(container),
|
element,
|
||||||
representation
|
representation
|
||||||
);
|
);
|
||||||
container.style.height = '100%';
|
container.style.height = '100%';
|
||||||
@@ -89,7 +93,11 @@ define([
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
|
element.off();
|
||||||
|
element.remove();
|
||||||
scope.$destroy();
|
scope.$destroy();
|
||||||
|
element = null;
|
||||||
|
scope = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,20 @@ define([
|
|||||||
publicAPI = {};
|
publicAPI = {};
|
||||||
publicAPI.objects = jasmine.createSpyObj('ObjectAPI', [
|
publicAPI.objects = jasmine.createSpyObj('ObjectAPI', [
|
||||||
'get',
|
'get',
|
||||||
'mutate'
|
'mutate',
|
||||||
|
'observe',
|
||||||
|
'areIdsEqual'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
publicAPI.objects.areIdsEqual.and.callFake(function (id1, id2) {
|
||||||
|
return id1.namespace === id2.namespace && id1.key === id2.key;
|
||||||
|
});
|
||||||
|
|
||||||
|
publicAPI.composition = jasmine.createSpyObj('CompositionAPI', [
|
||||||
|
'checkPolicy'
|
||||||
|
]);
|
||||||
|
publicAPI.composition.checkPolicy.and.returnValue(true);
|
||||||
|
|
||||||
publicAPI.objects.eventEmitter = jasmine.createSpyObj('eventemitter', [
|
publicAPI.objects.eventEmitter = jasmine.createSpyObj('eventemitter', [
|
||||||
'on'
|
'on'
|
||||||
]);
|
]);
|
||||||
@@ -91,7 +103,7 @@ define([
|
|||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
listener = jasmine.createSpy('reorderListener');
|
listener = jasmine.createSpy('reorderListener');
|
||||||
composition.on('reorder', listener);
|
composition.on('reorder', listener);
|
||||||
|
|
||||||
return composition.load();
|
return composition.load();
|
||||||
});
|
});
|
||||||
it('', function () {
|
it('', function () {
|
||||||
@@ -119,49 +131,16 @@ define([
|
|||||||
expect(newComposition[2].key).toEqual('a');
|
expect(newComposition[2].key).toEqual('a');
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
it('supports adding an object to composition', function () {
|
||||||
// TODO: Implement add/removal in new default provider.
|
let addListener = jasmine.createSpy('addListener');
|
||||||
xit('synchronizes changes between instances', function () {
|
let mockChildObject = {
|
||||||
var otherComposition = compositionAPI.get(domainObject);
|
identifier: {key: 'mock-key', namespace: ''}
|
||||||
var addListener = jasmine.createSpy('addListener');
|
};
|
||||||
var removeListener = jasmine.createSpy('removeListener');
|
|
||||||
var otherAddListener = jasmine.createSpy('otherAddListener');
|
|
||||||
var otherRemoveListener = jasmine.createSpy('otherRemoveListener');
|
|
||||||
composition.on('add', addListener);
|
composition.on('add', addListener);
|
||||||
composition.on('remove', removeListener);
|
composition.add(mockChildObject);
|
||||||
otherComposition.on('add', otherAddListener);
|
|
||||||
otherComposition.on('remove', otherRemoveListener);
|
|
||||||
|
|
||||||
return Promise.all([composition.load(), otherComposition.load()])
|
expect(domainObject.composition.length).toBe(4);
|
||||||
.then(function () {
|
expect(domainObject.composition[3]).toEqual(mockChildObject.identifier);
|
||||||
expect(addListener).toHaveBeenCalled();
|
|
||||||
expect(otherAddListener).toHaveBeenCalled();
|
|
||||||
expect(removeListener).not.toHaveBeenCalled();
|
|
||||||
expect(otherRemoveListener).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
var object = addListener.calls.mostRecent().args[0];
|
|
||||||
composition.remove(object);
|
|
||||||
expect(removeListener).toHaveBeenCalled();
|
|
||||||
expect(otherRemoveListener).toHaveBeenCalled();
|
|
||||||
|
|
||||||
addListener.reset();
|
|
||||||
otherAddListener.reset();
|
|
||||||
composition.add(object);
|
|
||||||
expect(addListener).toHaveBeenCalled();
|
|
||||||
expect(otherAddListener).toHaveBeenCalled();
|
|
||||||
|
|
||||||
removeListener.reset();
|
|
||||||
otherRemoveListener.reset();
|
|
||||||
otherComposition.remove(object);
|
|
||||||
expect(removeListener).toHaveBeenCalled();
|
|
||||||
expect(otherRemoveListener).toHaveBeenCalled();
|
|
||||||
|
|
||||||
addListener.reset();
|
|
||||||
otherAddListener.reset();
|
|
||||||
otherComposition.add(object);
|
|
||||||
expect(addListener).toHaveBeenCalled();
|
|
||||||
expect(otherAddListener).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -184,7 +163,9 @@ define([
|
|||||||
key: 'thing'
|
key: 'thing'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
},
|
||||||
|
add: jasmine.createSpy('add'),
|
||||||
|
remove: jasmine.createSpy('remove')
|
||||||
};
|
};
|
||||||
domainObject = {
|
domainObject = {
|
||||||
identifier: {
|
identifier: {
|
||||||
@@ -214,6 +195,25 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('Calling add or remove', function () {
|
||||||
|
let mockChildObject;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockChildObject = {
|
||||||
|
identifier: {key: 'mock-key', namespace: ''}
|
||||||
|
};
|
||||||
|
composition.add(mockChildObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls add on the provider', function () {
|
||||||
|
expect(customProvider.add).toHaveBeenCalledWith(domainObject, mockChildObject.identifier);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls remove on the provider', function () {
|
||||||
|
composition.remove(mockChildObject);
|
||||||
|
expect(customProvider.remove).toHaveBeenCalledWith(domainObject, mockChildObject.identifier);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('dynamic custom composition', function () {
|
describe('dynamic custom composition', function () {
|
||||||
|
|||||||
@@ -75,9 +75,7 @@ define([
|
|||||||
throw new Error('Event not supported by composition: ' + event);
|
throw new Error('Event not supported by composition: ' + event);
|
||||||
}
|
}
|
||||||
if (!this.mutationListener) {
|
if (!this.mutationListener) {
|
||||||
this.mutationListener = this.publicAPI.objects.observe(this.domainObject, '*', (newDomainObject) => {
|
this._synchronize();
|
||||||
this.domainObject = newDomainObject;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (this.provider.on && this.provider.off) {
|
if (this.provider.on && this.provider.off) {
|
||||||
if (event === 'add') {
|
if (event === 'add') {
|
||||||
@@ -134,10 +132,8 @@ define([
|
|||||||
|
|
||||||
this.listeners[event].splice(index, 1);
|
this.listeners[event].splice(index, 1);
|
||||||
if (this.listeners[event].length === 0) {
|
if (this.listeners[event].length === 0) {
|
||||||
if (this.mutationListener) {
|
this._destroy();
|
||||||
this.mutationListener();
|
|
||||||
delete this.mutationListener;
|
|
||||||
}
|
|
||||||
// Remove provider listener if this is the last callback to
|
// Remove provider listener if this is the last callback to
|
||||||
// be removed.
|
// be removed.
|
||||||
if (this.provider.off && this.provider.on) {
|
if (this.provider.off && this.provider.on) {
|
||||||
@@ -181,6 +177,9 @@ define([
|
|||||||
*/
|
*/
|
||||||
CompositionCollection.prototype.add = function (child, skipMutate) {
|
CompositionCollection.prototype.add = function (child, skipMutate) {
|
||||||
if (!skipMutate) {
|
if (!skipMutate) {
|
||||||
|
if (!this.publicAPI.composition.checkPolicy(this.domainObject, child)) {
|
||||||
|
throw `Object of type ${child.type} cannot be added to object of type ${this.domainObject.type}`;
|
||||||
|
}
|
||||||
this.provider.add(this.domainObject, child.identifier);
|
this.provider.add(this.domainObject, child.identifier);
|
||||||
} else {
|
} else {
|
||||||
this.emit('add', child);
|
this.emit('add', child);
|
||||||
@@ -272,6 +271,19 @@ define([
|
|||||||
this.remove(child, true);
|
this.remove(child, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CompositionCollection.prototype._synchronize = function () {
|
||||||
|
this.mutationListener = this.publicAPI.objects.observe(this.domainObject, '*', (newDomainObject) => {
|
||||||
|
this.domainObject = JSON.parse(JSON.stringify(newDomainObject));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
CompositionCollection.prototype._destroy = function () {
|
||||||
|
if (this.mutationListener) {
|
||||||
|
this.mutationListener();
|
||||||
|
delete this.mutationListener;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit events.
|
* Emit events.
|
||||||
* @private
|
* @private
|
||||||
|
|||||||
@@ -48,24 +48,11 @@ define([
|
|||||||
this.listeningTo = {};
|
this.listeningTo = {};
|
||||||
this.onMutation = this.onMutation.bind(this);
|
this.onMutation = this.onMutation.bind(this);
|
||||||
|
|
||||||
this.cannotContainDuplicates = this.cannotContainDuplicates.bind(this);
|
|
||||||
this.cannotContainItself = this.cannotContainItself.bind(this);
|
this.cannotContainItself = this.cannotContainItself.bind(this);
|
||||||
|
|
||||||
compositionAPI.addPolicy(this.cannotContainDuplicates);
|
|
||||||
compositionAPI.addPolicy(this.cannotContainItself);
|
compositionAPI.addPolicy(this.cannotContainItself);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
DefaultCompositionProvider.prototype.cannotContainDuplicates = function (parent, child) {
|
|
||||||
return this.appliesTo(parent) &&
|
|
||||||
parent.composition.findIndex((composeeId) => {
|
|
||||||
return composeeId.namespace === child.identifier.namespace &&
|
|
||||||
composeeId.key === child.identifier.key;
|
|
||||||
}) === -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -199,9 +186,18 @@ define([
|
|||||||
* @memberof module:openmct.CompositionProvider#
|
* @memberof module:openmct.CompositionProvider#
|
||||||
* @method add
|
* @method add
|
||||||
*/
|
*/
|
||||||
DefaultCompositionProvider.prototype.add = function (domainObject, child) {
|
DefaultCompositionProvider.prototype.add = function (parent, childId) {
|
||||||
throw new Error('Default Provider does not implement adding.');
|
if (!this.includes(parent, childId)) {
|
||||||
// TODO: this needs to be synchronized via mutation
|
parent.composition.push(childId);
|
||||||
|
this.publicAPI.objects.mutate(parent, 'composition', parent.composition);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
DefaultCompositionProvider.prototype.includes = function (parent, childId) {
|
||||||
|
return parent.composition.findIndex(composee =>
|
||||||
|
this.publicAPI.objects.areIdsEqual(composee, childId)) !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
DefaultCompositionProvider.prototype.reorder = function (domainObject, oldIndex, newIndex) {
|
DefaultCompositionProvider.prototype.reorder = function (domainObject, oldIndex, newIndex) {
|
||||||
|
|||||||
@@ -92,6 +92,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
height: 0; // Chrome 73 overflow bug fix
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-right: $interiorMargin; // fend off scroll bar
|
padding-right: $interiorMargin; // fend off scroll bar
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
define([
|
||||||
'./components/LadTable.vue',
|
'./components/LADTable.vue',
|
||||||
'vue'
|
'vue'
|
||||||
], function (
|
], function (
|
||||||
LadTableComponent,
|
LadTableComponent,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
import LadRow from './LadRow.vue';
|
import LadRow from './LADRow.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct', 'domainObject'],
|
inject: ['openmct', 'domainObject'],
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
import LadRow from './LadRow.vue';
|
import LadRow from './LADRow.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct', 'domainObject'],
|
inject: ['openmct', 'domainObject'],
|
||||||
|
|||||||
77
src/plugins/displayLayout/AlphanumericFormatViewProvider.js
Normal file
77
src/plugins/displayLayout/AlphanumericFormatViewProvider.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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/AlphanumericFormatView.vue',
|
||||||
|
'vue'
|
||||||
|
], function (AlphanumericFormatView, Vue) {
|
||||||
|
|
||||||
|
function AlphanumericFormatViewProvider(openmct, options) {
|
||||||
|
function isTelemetryObject(selectionPath) {
|
||||||
|
let selectedObject = selectionPath[0].context.item;
|
||||||
|
let parentObject = selectionPath[1].context.item;
|
||||||
|
return parentObject &&
|
||||||
|
parentObject.type === 'layout' &&
|
||||||
|
selectedObject &&
|
||||||
|
openmct.telemetry.isTelemetryObject(selectedObject) &&
|
||||||
|
!options.showAsView.includes(selectedObject.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: 'alphanumeric-format',
|
||||||
|
name: 'Alphanumeric Format',
|
||||||
|
canView: function (selection) {
|
||||||
|
if (selection.length === 0 || selection[0].length === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return selection.every(isTelemetryObject);
|
||||||
|
},
|
||||||
|
view: function (selection) {
|
||||||
|
let component;
|
||||||
|
return {
|
||||||
|
show: function (element) {
|
||||||
|
component = new Vue({
|
||||||
|
provide: {
|
||||||
|
openmct
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
AlphanumericFormatView: AlphanumericFormatView.default
|
||||||
|
},
|
||||||
|
template: '<alphanumeric-format-view></alphanumeric-format-view>',
|
||||||
|
el: element
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroy: function () {
|
||||||
|
component.$destroy();
|
||||||
|
component = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
priority: function () {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AlphanumericFormatViewProvider;
|
||||||
|
});
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="c-properties" v-if="isEditing">
|
||||||
|
<div class="c-properties__header">Alphanumeric Format</div>
|
||||||
|
<ul class="c-properties__section" v-if="!multiSelect">
|
||||||
|
<li class="c-properties__row">
|
||||||
|
<div class="c-properties__label" title="Printf formatting for the selected telemetry">
|
||||||
|
<label for="telemetryPrintfFormat">Format</label>
|
||||||
|
</div>
|
||||||
|
<div class="c-properties__value">
|
||||||
|
<input id="telemetryPrintfFormat" type="text" @change="formatTelemetry" :value="telemetryFormat">
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="c-properties__row--span-all" v-if="multiSelect">No format to display for multiple items</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
inject: ['openmct'],
|
||||||
|
data() {
|
||||||
|
let selectionPath = this.openmct.selection.get()[0];
|
||||||
|
return {
|
||||||
|
isEditing: this.openmct.editor.isEditing(),
|
||||||
|
telemetryFormat: selectionPath[0].context.layoutItem.format,
|
||||||
|
multiSelect: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleEdit(isEditing) {
|
||||||
|
this.isEditing = isEditing;
|
||||||
|
},
|
||||||
|
formatTelemetry(event) {
|
||||||
|
let selectionPath = this.openmct.selection.get()[0];
|
||||||
|
let newFormat = event.currentTarget.value;
|
||||||
|
selectionPath[0].context.updateTelemetryFormat(newFormat);
|
||||||
|
this.telemetryFormat = newFormat;
|
||||||
|
},
|
||||||
|
handleSelection(selection) {
|
||||||
|
if (selection.length === 0 || selection[0].length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.multiSelect = selection.length > 1 ? true : false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.openmct.editor.on('isEditing', this.toggleEdit);
|
||||||
|
this.openmct.selection.on('change', this.handleSelection);
|
||||||
|
this.handleSelection(this.openmct.selection.get());
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.openmct.editor.off('isEditing', this.toggleEdit);
|
||||||
|
this.openmct.selection.off('change', this.handleSelection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -48,7 +48,8 @@
|
|||||||
:multiSelect="selectedLayoutItems.length > 1"
|
:multiSelect="selectedLayoutItems.length > 1"
|
||||||
@move="move"
|
@move="move"
|
||||||
@endMove="endMove"
|
@endMove="endMove"
|
||||||
@endLineResize='endLineResize'>
|
@endLineResize='endLineResize'
|
||||||
|
@formatChanged='updateTelemetryFormat'>
|
||||||
</component>
|
</component>
|
||||||
<edit-marquee v-if='showMarquee'
|
<edit-marquee v-if='showMarquee'
|
||||||
:gridSize="gridSize"
|
:gridSize="gridSize"
|
||||||
@@ -269,33 +270,63 @@
|
|||||||
_.cloneDeep(this.selectedLayoutItems).forEach(selectedItem => {
|
_.cloneDeep(this.selectedLayoutItems).forEach(selectedItem => {
|
||||||
if (selectedItem.type === 'line-view') {
|
if (selectedItem.type === 'line-view') {
|
||||||
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y, selectedItem.x2, selectedItem.y2];
|
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y, selectedItem.x2, selectedItem.y2];
|
||||||
|
this.startingMinX2 = this.startingMinX2 !== undefined ? Math.min(this.startingMinX2, selectedItem.x2) : selectedItem.x2;
|
||||||
|
this.startingMinY2 = this.startingMinY2 !== undefined ? Math.min(this.startingMinY2, selectedItem.y2) : selectedItem.y2;
|
||||||
} else {
|
} else {
|
||||||
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y];
|
this.initialPositions[selectedItem.id] = [selectedItem.x, selectedItem.y];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.startingMinX = this.startingMinX !== undefined ? Math.min(this.startingMinX, selectedItem.x) : selectedItem.x;
|
||||||
|
this.startingMinY = this.startingMinY !== undefined ? Math.min(this.startingMinY, selectedItem.y) : selectedItem.y;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let layoutItems = this.layoutItems.map(item => {
|
let layoutItems = this.layoutItems.map(item => {
|
||||||
if (this.initialPositions[item.id]) {
|
if (this.initialPositions[item.id]) {
|
||||||
let startingPosition = this.initialPositions[item.id];
|
this.updateItemPosition(item, gridDelta);
|
||||||
let [startingX, startingY, startingX2, startingY2] = startingPosition;
|
|
||||||
item.x = startingX + gridDelta[0];
|
|
||||||
item.y = startingY + gridDelta[1];
|
|
||||||
|
|
||||||
if (item.x2) {
|
|
||||||
item.x2 = startingX2 + gridDelta[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.y2) {
|
|
||||||
item.y2 = startingY2 + gridDelta[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updateItemPosition(item, gridDelta) {
|
||||||
|
let startingPosition = this.initialPositions[item.id];
|
||||||
|
let [startingX, startingY, startingX2, startingY2] = startingPosition;
|
||||||
|
|
||||||
|
if (this.startingMinX + gridDelta[0] >= 0) {
|
||||||
|
if (item.x2 !== undefined) {
|
||||||
|
if (this.startingMinX2 + gridDelta[0] >= 0) {
|
||||||
|
item.x = startingX + gridDelta[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.x = startingX + gridDelta[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.startingMinY + gridDelta[1] >= 0) {
|
||||||
|
if (item.y2 !== undefined) {
|
||||||
|
if (this.startingMinY2 + gridDelta[1] >= 0) {
|
||||||
|
item.y = startingY + gridDelta[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.y = startingY + gridDelta[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.x2 !== undefined && this.startingMinX2 + gridDelta[0] >= 0 && this.startingMinX + gridDelta[0] >= 0) {
|
||||||
|
item.x2 = startingX2 + gridDelta[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.y2 !== undefined && this.startingMinY2 + gridDelta[1] >= 0 && this.startingMinY + gridDelta[1] >= 0) {
|
||||||
|
item.y2 = startingY2 + gridDelta[1];
|
||||||
|
}
|
||||||
|
},
|
||||||
endMove() {
|
endMove() {
|
||||||
this.mutate('configuration.items', this.layoutItems);
|
this.mutate('configuration.items', this.layoutItems);
|
||||||
this.initialPositions = undefined;
|
this.initialPositions = undefined;
|
||||||
|
this.startingMinX = undefined;
|
||||||
|
this.startingMinY = undefined;
|
||||||
|
this.startingMinX2 = undefined;
|
||||||
|
this.startingMinY2 = undefined;
|
||||||
},
|
},
|
||||||
mutate(path, value) {
|
mutate(path, value) {
|
||||||
this.openmct.objects.mutate(this.internalDomainObject, path, value);
|
this.openmct.objects.mutate(this.internalDomainObject, path, value);
|
||||||
@@ -527,6 +558,11 @@
|
|||||||
this.layoutItems.splice(itemIndex, 1);
|
this.layoutItems.splice(itemIndex, 1);
|
||||||
this.layoutItems.splice(newIndex, 0, items[itemIndex]);
|
this.layoutItems.splice(newIndex, 0, items[itemIndex]);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
updateTelemetryFormat(item, format) {
|
||||||
|
let index = this.layoutItems.indexOf(item);
|
||||||
|
item.format = format;
|
||||||
|
this.mutate(`configuration.items[${index}]`, item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
@@ -116,7 +116,7 @@
|
|||||||
let height = Number.NEGATIVE_INFINITY;
|
let height = Number.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
this.selectedLayoutItems.forEach(item => {
|
this.selectedLayoutItems.forEach(item => {
|
||||||
if (item.x2) {
|
if (item.x2 !== undefined) {
|
||||||
let lineWidth = Math.abs(item.x - item.x2);
|
let lineWidth = Math.abs(item.x - item.x2);
|
||||||
let lineMinX = Math.min(item.x, item.x2);
|
let lineMinX = Math.min(item.x, item.x2);
|
||||||
x = Math.min(lineMinX, x);
|
x = Math.min(lineMinX, x);
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
width = Math.max(item.width + item.x, width);
|
width = Math.max(item.width + item.x, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.y2) {
|
if (item.y2 !== undefined) {
|
||||||
let lineHeight = Math.abs(item.y - item.y2);
|
let lineHeight = Math.abs(item.y - item.y2);
|
||||||
let lineMinY = Math.min(item.y, item.y2);
|
let lineMinY = Math.min(item.y, item.y2);
|
||||||
y = Math.min(lineMinY, y);
|
y = Math.min(lineMinY, y);
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LayoutFrame from './LayoutFrame.vue'
|
import LayoutFrame from './LayoutFrame.vue'
|
||||||
|
import printj from 'printj'
|
||||||
|
|
||||||
const DEFAULT_TELEMETRY_DIMENSIONS = [10, 5],
|
const DEFAULT_TELEMETRY_DIMENSIONS = [10, 5],
|
||||||
DEFAULT_POSITION = [1, 1];
|
DEFAULT_POSITION = [1, 1];
|
||||||
@@ -143,6 +144,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.item.format) {
|
||||||
|
return printj.sprintf(this.item.format, this.datum[this.valueMetadata.key]);
|
||||||
|
}
|
||||||
|
|
||||||
return this.valueFormatter && this.valueFormatter.format(this.datum);
|
return this.valueFormatter && this.valueFormatter.format(this.datum);
|
||||||
},
|
},
|
||||||
telemetryClass() {
|
telemetryClass() {
|
||||||
@@ -168,6 +173,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.context.index = newIndex;
|
this.context.index = newIndex;
|
||||||
|
},
|
||||||
|
item(newItem) {
|
||||||
|
this.context.layoutItem = newItem;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -194,6 +202,7 @@
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
updateView(datum) {
|
updateView(datum) {
|
||||||
|
// TODO: normalize datum
|
||||||
this.datum = datum;
|
this.datum = datum;
|
||||||
},
|
},
|
||||||
removeSubscription() {
|
removeSubscription() {
|
||||||
@@ -219,10 +228,14 @@
|
|||||||
this.context = {
|
this.context = {
|
||||||
item: domainObject,
|
item: domainObject,
|
||||||
layoutItem: this.item,
|
layoutItem: this.item,
|
||||||
index: this.index
|
index: this.index,
|
||||||
|
updateTelemetryFormat: this.updateTelemetryFormat
|
||||||
};
|
};
|
||||||
this.removeSelectable = this.openmct.selection.selectable(
|
this.removeSelectable = this.openmct.selection.selectable(
|
||||||
this.$el, this.context, this.initSelect);
|
this.$el, this.context, this.initSelect);
|
||||||
|
},
|
||||||
|
updateTelemetryFormat(format) {
|
||||||
|
this.$emit('formatChanged', this.item, format);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import Vue from 'vue'
|
|||||||
import objectUtils from '../../api/objects/object-utils.js'
|
import objectUtils from '../../api/objects/object-utils.js'
|
||||||
import DisplayLayoutType from './DisplayLayoutType.js'
|
import DisplayLayoutType from './DisplayLayoutType.js'
|
||||||
import DisplayLayoutToolbar from './DisplayLayoutToolbar.js'
|
import DisplayLayoutToolbar from './DisplayLayoutToolbar.js'
|
||||||
|
import AlphaNumericFormatViewProvider from './AlphaNumericFormatViewProvider.js'
|
||||||
|
|
||||||
export default function DisplayLayoutPlugin(options) {
|
export default function DisplayLayoutPlugin(options) {
|
||||||
return function (openmct) {
|
return function (openmct) {
|
||||||
openmct.objectViews.addProvider({
|
openmct.objectViews.addProvider({
|
||||||
@@ -76,7 +78,8 @@ export default function DisplayLayoutPlugin(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
openmct.types.addType('layout', DisplayLayoutType());
|
openmct.types.addType('layout', DisplayLayoutType());
|
||||||
openmct.toolbars.addProvider(new DisplayLayoutToolbar(openmct));
|
openmct.toolbars.addProvider(new DisplayLayoutToolbar(openmct, options));
|
||||||
|
openmct.inspectorViews.addProvider(new AlphaNumericFormatViewProvider(openmct, options));
|
||||||
openmct.composition.addPolicy((parent, child) => {
|
openmct.composition.addPolicy((parent, child) => {
|
||||||
if (parent.type === 'layout' && child.type === 'folder') {
|
if (parent.type === 'layout' && child.type === 'folder') {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
53
src/plugins/goToOriginalAction/goToOriginalAction.js
Normal file
53
src/plugins/goToOriginalAction/goToOriginalAction.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
export default class GoToOriginalAction {
|
||||||
|
constructor(openmct) {
|
||||||
|
this.name = 'Go To Original';
|
||||||
|
this.description = 'Go to the original unlinked instance of this object';
|
||||||
|
|
||||||
|
this._openmct = openmct;
|
||||||
|
}
|
||||||
|
invoke(objectPath) {
|
||||||
|
this._openmct.objects.getOriginalPath(objectPath[0].identifier)
|
||||||
|
.then((originalPath) => {
|
||||||
|
let url = '#/browse/' + originalPath
|
||||||
|
.map(function (o) {
|
||||||
|
return o && this._openmct.objects.makeKeyString(o.identifier);
|
||||||
|
}.bind(this))
|
||||||
|
.reverse()
|
||||||
|
.slice(1)
|
||||||
|
.join('/');
|
||||||
|
|
||||||
|
window.location.href = url;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
appliesTo(objectPath) {
|
||||||
|
let parentKeystring = objectPath[1] && this._openmct.objects.makeKeyString(objectPath[1].identifier);
|
||||||
|
|
||||||
|
if (!parentKeystring) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (parentKeystring !== objectPath[0].location);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/plugins/goToOriginalAction/plugin.js
Normal file
28
src/plugins/goToOriginalAction/plugin.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
import GoToOriginalAction from './goToOriginalAction';
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
return function (openmct) {
|
||||||
|
openmct.contextMenu.registerAction(new GoToOriginalAction(openmct));
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -64,35 +64,45 @@ define([
|
|||||||
Object.keys(panels).forEach(key => {
|
Object.keys(panels).forEach(key => {
|
||||||
let panel = panels[key];
|
let panel = panels[key];
|
||||||
let domainObject = childObjects[key];
|
let domainObject = childObjects[key];
|
||||||
|
let identifier = undefined;
|
||||||
|
|
||||||
if (isTelemetry(domainObject)) {
|
if (isTelemetry(domainObject)) {
|
||||||
items.push({
|
// If object is a telemetry point, convert it to a plot and
|
||||||
width: panel.dimensions[0],
|
// replace the object in migratedObject composition with the plot.
|
||||||
height: panel.dimensions[1],
|
identifier = {
|
||||||
x: panel.position[0],
|
key: uuid(),
|
||||||
y: panel.position[1],
|
namespace: migratedObject.identifier.namespace
|
||||||
identifier: domainObject.identifier,
|
};
|
||||||
id: uuid(),
|
let plotObject = {
|
||||||
type: 'telemetry-view',
|
identifier: identifier,
|
||||||
displayMode: 'all',
|
location: domainObject.location,
|
||||||
value: openmct.telemetry.getMetadata(domainObject).getDefaultDisplayValue(),
|
name: domainObject.name,
|
||||||
stroke: "transparent",
|
type: "telemetry.plot.overlay"
|
||||||
fill: "",
|
};
|
||||||
color: "",
|
let plotType = openmct.types.get('telemetry.plot.overlay');
|
||||||
size: "13px"
|
plotType.definition.initialize(plotObject);
|
||||||
});
|
plotObject.composition.push(domainObject.identifier);
|
||||||
} else {
|
openmct.objects.mutate(plotObject, 'persisted', Date.now());
|
||||||
items.push({
|
|
||||||
width: panel.dimensions[0],
|
let keyString = openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
height: panel.dimensions[1],
|
let clonedComposition = Object.assign([], migratedObject.composition);
|
||||||
x: panel.position[0],
|
clonedComposition.forEach((identifier, index) => {
|
||||||
y: panel.position[1],
|
if (openmct.objects.makeKeyString(identifier) === keyString) {
|
||||||
identifier: domainObject.identifier,
|
migratedObject.composition[index] = plotObject.identifier;
|
||||||
id: uuid(),
|
}
|
||||||
type: 'subobject-view',
|
|
||||||
hasFrame: panel.hasFrame
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
width: panel.dimensions[0],
|
||||||
|
height: panel.dimensions[1],
|
||||||
|
x: panel.position[0],
|
||||||
|
y: panel.position[1],
|
||||||
|
identifier: identifier || domainObject.identifier,
|
||||||
|
id: uuid(),
|
||||||
|
type: 'subobject-view',
|
||||||
|
hasFrame: panel.hasFrame
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
migratedObject.configuration.items = items;
|
migratedObject.configuration.items = items;
|
||||||
@@ -167,7 +177,9 @@ define([
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
check(domainObject) {
|
check(domainObject) {
|
||||||
return domainObject.type === 'layout' && domainObject.configuration.layout;
|
return domainObject.type === 'layout' &&
|
||||||
|
domainObject.configuration &&
|
||||||
|
domainObject.configuration.layout;
|
||||||
},
|
},
|
||||||
migrate(domainObject) {
|
migrate(domainObject) {
|
||||||
let childObjects = {};
|
let childObjects = {};
|
||||||
@@ -186,7 +198,9 @@ define([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
check(domainObject) {
|
check(domainObject) {
|
||||||
return domainObject.type === 'telemetry.fixed' && domainObject.configuration['fixed-display'];
|
return domainObject.type === 'telemetry.fixed' &&
|
||||||
|
domainObject.configuration &&
|
||||||
|
domainObject.configuration['fixed-display'];
|
||||||
},
|
},
|
||||||
migrate(domainObject) {
|
migrate(domainObject) {
|
||||||
const DEFAULT_GRID_SIZE = [64, 16];
|
const DEFAULT_GRID_SIZE = [64, 16];
|
||||||
@@ -224,6 +238,7 @@ define([
|
|||||||
{
|
{
|
||||||
check(domainObject) {
|
check(domainObject) {
|
||||||
return domainObject.type === 'table' &&
|
return domainObject.type === 'table' &&
|
||||||
|
domainObject.configuration &&
|
||||||
domainObject.configuration.table;
|
domainObject.configuration.table;
|
||||||
},
|
},
|
||||||
migrate(domainObject) {
|
migrate(domainObject) {
|
||||||
|
|||||||
@@ -115,11 +115,13 @@ define([
|
|||||||
|
|
||||||
Collection.prototype.remove = function (model) {
|
Collection.prototype.remove = function (model) {
|
||||||
var index = this.indexOf(model);
|
var index = this.indexOf(model);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
throw new Error('model not found in collection.');
|
throw new Error('model not found in collection.');
|
||||||
}
|
}
|
||||||
this.models.splice(index, 1);
|
|
||||||
this.emit('remove', model, index);
|
this.emit('remove', model, index);
|
||||||
|
this.models.splice(index, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
Collection.prototype.destroy = function (model) {
|
Collection.prototype.destroy = function (model) {
|
||||||
|
|||||||
@@ -100,19 +100,33 @@ define([
|
|||||||
removeTelemetryObject: function (identifier) {
|
removeTelemetryObject: function (identifier) {
|
||||||
var plotObject = this.plot.get('domainObject');
|
var plotObject = this.plot.get('domainObject');
|
||||||
if (plotObject.type === 'telemetry.plot.overlay') {
|
if (plotObject.type === 'telemetry.plot.overlay') {
|
||||||
var index = _.findIndex(plotObject.configuration.series, function (s) {
|
|
||||||
|
var persistedIndex = _.findIndex(plotObject.configuration.series, function (s) {
|
||||||
return _.isEqual(identifier, s.identifier);
|
return _.isEqual(identifier, s.identifier);
|
||||||
});
|
});
|
||||||
this.remove(this.at(index));
|
|
||||||
// Because this is triggered by a composition change, we have
|
var configIndex = _.findIndex(this.models, function (m) {
|
||||||
// to defer mutation of our plot object, otherwise we might
|
return _.isEqual(m.domainObject.identifier, identifier);
|
||||||
// mutate an outdated version of the plotObject.
|
});
|
||||||
setTimeout(function () {
|
|
||||||
var newPlotObject = this.plot.get('domainObject');
|
/*
|
||||||
var cSeries = newPlotObject.configuration.series.slice();
|
when cancelling out of edit mode, the config store and domain object are out of sync
|
||||||
cSeries.splice(index, 1);
|
thus it is necesarry to check both and remove the models that are no longer in composition
|
||||||
this.openmct.objects.mutate(newPlotObject, 'configuration.series', cSeries);
|
*/
|
||||||
}.bind(this));
|
if (persistedIndex === -1) {
|
||||||
|
this.remove(this.at(configIndex));
|
||||||
|
} else {
|
||||||
|
this.remove(this.at(persistedIndex));
|
||||||
|
// Because this is triggered by a composition change, we have
|
||||||
|
// to defer mutation of our plot object, otherwise we might
|
||||||
|
// mutate an outdated version of the plotObject.
|
||||||
|
setTimeout(function () {
|
||||||
|
var newPlotObject = this.plot.get('domainObject');
|
||||||
|
var cSeries = newPlotObject.configuration.series.slice();
|
||||||
|
cSeries.splice(persistedIndex, 1);
|
||||||
|
this.openmct.objects.mutate(newPlotObject, 'configuration.series', cSeries);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSeriesAdd: function (series) {
|
onSeriesAdd: function (series) {
|
||||||
|
|||||||
@@ -25,23 +25,11 @@ define([
|
|||||||
|
|
||||||
function ConfigStore() {
|
function ConfigStore() {
|
||||||
this.store = {};
|
this.store = {};
|
||||||
this.tracking = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigStore.prototype.track = function (id) {
|
ConfigStore.prototype.deleteStore = function (id) {
|
||||||
if (!this.tracking[id]) {
|
this.store[id].destroy();
|
||||||
this.tracking[id] = 0;
|
delete this.store[id];
|
||||||
}
|
|
||||||
this.tracking[id] += 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
ConfigStore.prototype.untrack = function (id) {
|
|
||||||
this.tracking[id] -= 1;
|
|
||||||
if (this.tracking[id] <= 0) {
|
|
||||||
delete this.tracking[id];
|
|
||||||
this.store[id].destroy();
|
|
||||||
delete this.store[id];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ConfigStore.prototype.add = function (id, config) {
|
ConfigStore.prototype.add = function (id, config) {
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
PlotOptionsController.prototype.destroy = function () {
|
PlotOptionsController.prototype.destroy = function () {
|
||||||
configStore.untrack(this.configId);
|
|
||||||
this.stopListening();
|
this.stopListening();
|
||||||
this.unlisten();
|
this.unlisten();
|
||||||
};
|
};
|
||||||
@@ -60,7 +59,7 @@ define([
|
|||||||
this.$timeout(this.setUpScope.bind(this));
|
this.$timeout(this.setUpScope.bind(this));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
configStore.track(this.configId);
|
|
||||||
this.config = this.$scope.config = config;
|
this.config = this.$scope.config = config;
|
||||||
this.$scope.plotSeries = [];
|
this.$scope.plotSeries = [];
|
||||||
|
|
||||||
|
|||||||
@@ -282,11 +282,19 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
MCTPlotController.prototype.zoom = function (zoomDirection, zoomFactor) {
|
MCTPlotController.prototype.zoom = function (zoomDirection, zoomFactor) {
|
||||||
|
var currentXaxis = this.$scope.xAxis.get('displayRange'),
|
||||||
|
currentYaxis = this.$scope.yAxis.get('displayRange');
|
||||||
|
|
||||||
|
// when there is no plot data, the ranges can be undefined
|
||||||
|
// in which case we should not perform zoom
|
||||||
|
if (!currentXaxis || !currentYaxis) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.freeze();
|
this.freeze();
|
||||||
this.trackHistory();
|
this.trackHistory();
|
||||||
var currentXaxis = this.$scope.xAxis.get('displayRange'),
|
|
||||||
currentYaxis = this.$scope.yAxis.get('displayRange'),
|
var xAxisDist= (currentXaxis.max - currentXaxis.min) * zoomFactor,
|
||||||
xAxisDist= (currentXaxis.max - currentXaxis.min) * zoomFactor,
|
|
||||||
yAxisDist = (currentYaxis.max - currentYaxis.min) * zoomFactor;
|
yAxisDist = (currentYaxis.max - currentYaxis.min) * zoomFactor;
|
||||||
|
|
||||||
if (zoomDirection === 'in') {
|
if (zoomDirection === 'in') {
|
||||||
@@ -322,12 +330,19 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let xDisplayRange = this.$scope.xAxis.get('displayRange'),
|
||||||
|
yDisplayRange = this.$scope.yAxis.get('displayRange');
|
||||||
|
|
||||||
|
// when there is no plot data, the ranges can be undefined
|
||||||
|
// in which case we should not perform zoom
|
||||||
|
if (!xDisplayRange || !yDisplayRange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.freeze();
|
this.freeze();
|
||||||
window.clearTimeout(this.stillZooming);
|
window.clearTimeout(this.stillZooming);
|
||||||
|
|
||||||
let xDisplayRange = this.$scope.xAxis.get('displayRange'),
|
let xAxisDist = (xDisplayRange.max - xDisplayRange.min),
|
||||||
yDisplayRange = this.$scope.yAxis.get('displayRange'),
|
|
||||||
xAxisDist = (xDisplayRange.max - xDisplayRange.min),
|
|
||||||
yAxisDist = (yDisplayRange.max - yDisplayRange.min),
|
yAxisDist = (yDisplayRange.max - yDisplayRange.min),
|
||||||
xDistMouseToMax = xDisplayRange.max - this.positionOverPlot.x,
|
xDistMouseToMax = xDisplayRange.max - this.positionOverPlot.x,
|
||||||
xDistMouseToMin = this.positionOverPlot.x - xDisplayRange.min,
|
xDistMouseToMin = this.positionOverPlot.x - xDisplayRange.min,
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ define([
|
|||||||
});
|
});
|
||||||
configStore.add(configId, config);
|
configStore.add(configId, config);
|
||||||
}
|
}
|
||||||
configStore.track(configId);
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,7 +156,8 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
PlotController.prototype.destroy = function () {
|
PlotController.prototype.destroy = function () {
|
||||||
configStore.untrack(this.config.id);
|
configStore.deleteStore(this.config.id);
|
||||||
|
|
||||||
this.stopListening();
|
this.stopListening();
|
||||||
if (this.checkForSize) {
|
if (this.checkForSize) {
|
||||||
clearInterval(this.checkForSize);
|
clearInterval(this.checkForSize);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
define([
|
define([
|
||||||
'lodash',
|
'lodash',
|
||||||
'./utcTimeSystem/plugin',
|
'./utcTimeSystem/plugin',
|
||||||
|
'./localTimeSystem/plugin',
|
||||||
'../../example/generator/plugin',
|
'../../example/generator/plugin',
|
||||||
'./autoflow/AutoflowTabularPlugin',
|
'./autoflow/AutoflowTabularPlugin',
|
||||||
'./timeConductor/plugin',
|
'./timeConductor/plugin',
|
||||||
@@ -41,10 +42,12 @@ define([
|
|||||||
'./tabs/plugin',
|
'./tabs/plugin',
|
||||||
'./LADTable/plugin',
|
'./LADTable/plugin',
|
||||||
'./filters/plugin',
|
'./filters/plugin',
|
||||||
'./objectMigration/plugin'
|
'./objectMigration/plugin',
|
||||||
|
'./goToOriginalAction/plugin'
|
||||||
], function (
|
], function (
|
||||||
_,
|
_,
|
||||||
UTCTimeSystem,
|
UTCTimeSystem,
|
||||||
|
LocalTimeSystem,
|
||||||
GeneratorPlugin,
|
GeneratorPlugin,
|
||||||
AutoflowPlugin,
|
AutoflowPlugin,
|
||||||
TimeConductorPlugin,
|
TimeConductorPlugin,
|
||||||
@@ -63,7 +66,8 @@ define([
|
|||||||
Tabs,
|
Tabs,
|
||||||
LADTable,
|
LADTable,
|
||||||
Filters,
|
Filters,
|
||||||
ObjectMigration
|
ObjectMigration,
|
||||||
|
GoToOriginalAction
|
||||||
) {
|
) {
|
||||||
var bundleMap = {
|
var bundleMap = {
|
||||||
LocalStorage: 'platform/persistence/local',
|
LocalStorage: 'platform/persistence/local',
|
||||||
@@ -79,6 +83,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
plugins.UTCTimeSystem = UTCTimeSystem;
|
plugins.UTCTimeSystem = UTCTimeSystem;
|
||||||
|
plugins.LocalTimeSystem = LocalTimeSystem;
|
||||||
|
|
||||||
plugins.ImportExport = ImportExport;
|
plugins.ImportExport = ImportExport;
|
||||||
|
|
||||||
@@ -160,6 +165,7 @@ define([
|
|||||||
plugins.LADTable = LADTable;
|
plugins.LADTable = LADTable;
|
||||||
plugins.Filters = Filters;
|
plugins.Filters = Filters;
|
||||||
plugins.ObjectMigration = ObjectMigration.default;
|
plugins.ObjectMigration = ObjectMigration.default;
|
||||||
|
plugins.GoToOriginalAction = GoToOriginalAction.default;
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -70,16 +70,14 @@ define([
|
|||||||
*/
|
*/
|
||||||
function onValueInput(event) {
|
function onValueInput(event) {
|
||||||
var elem = event.target,
|
var elem = event.target,
|
||||||
value = (isNaN(elem.valueAsNumber) ? elem.value : elem.valueAsNumber),
|
value = isNaN(Number(elem.value)) ? elem.value : Number(elem.value),
|
||||||
inputIndex = self.valueInputs.indexOf(elem);
|
inputIndex = self.valueInputs.indexOf(elem);
|
||||||
|
|
||||||
if (elem.tagName.toUpperCase() === 'INPUT') {
|
self.eventEmitter.emit('change', {
|
||||||
self.eventEmitter.emit('change', {
|
value: value,
|
||||||
value: value,
|
property: 'values[' + inputIndex + ']',
|
||||||
property: 'values[' + inputIndex + ']',
|
index: self.index
|
||||||
index: self.index
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.listenTo(this.deleteButton, 'click', this.remove, this);
|
this.listenTo(this.deleteButton, 'click', this.remove, this);
|
||||||
@@ -108,8 +106,7 @@ define([
|
|||||||
Object.values(this.selects).forEach(function (select) {
|
Object.values(this.selects).forEach(function (select) {
|
||||||
$('.t-configuration', self.domElement).append(select.getDOM());
|
$('.t-configuration', self.domElement).append(select.getDOM());
|
||||||
});
|
});
|
||||||
|
this.listenTo($('.t-value-inputs', this.domElement), 'input', onValueInput);
|
||||||
this.listenTo($(this.domElement), 'input', onValueInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Condition.prototype.getDOM = function (container) {
|
Condition.prototype.getDOM = function (container) {
|
||||||
@@ -167,7 +164,9 @@ define([
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* When an operation is selected, create the appropriate value inputs
|
* When an operation is selected, create the appropriate value inputs
|
||||||
* and add them to the view
|
* and add them to the view. If an operation is of type enum, create
|
||||||
|
* a drop-down menu instead.
|
||||||
|
*
|
||||||
* @param {string} operation The key of currently selected operation
|
* @param {string} operation The key of currently selected operation
|
||||||
*/
|
*/
|
||||||
Condition.prototype.generateValueInputs = function (operation) {
|
Condition.prototype.generateValueInputs = function (operation) {
|
||||||
@@ -176,25 +175,49 @@ define([
|
|||||||
inputCount,
|
inputCount,
|
||||||
inputType,
|
inputType,
|
||||||
newInput,
|
newInput,
|
||||||
index = 0;
|
index = 0,
|
||||||
|
emitChange = false;
|
||||||
|
|
||||||
inputArea.html('');
|
inputArea.html('');
|
||||||
this.valueInputs = [];
|
this.valueInputs = [];
|
||||||
|
this.config.values = [];
|
||||||
|
|
||||||
if (evaluator.getInputCount(operation)) {
|
if (evaluator.getInputCount(operation)) {
|
||||||
inputCount = evaluator.getInputCount(operation);
|
inputCount = evaluator.getInputCount(operation);
|
||||||
inputType = evaluator.getInputType(operation);
|
inputType = evaluator.getInputType(operation);
|
||||||
|
|
||||||
while (index < inputCount) {
|
while (index < inputCount) {
|
||||||
if (!this.config.values[index]) {
|
if (inputType === 'select') {
|
||||||
this.config.values[index] = (inputType === 'number' ? 0 : '');
|
newInput = $('<select>' + this.generateSelectOptions() + '</select>');
|
||||||
|
emitChange = true;
|
||||||
|
} else {
|
||||||
|
this.config.values[index] = inputType === 'number' ? 0 : '';
|
||||||
|
newInput = $('<input type = "' + inputType + '" value = "' + this.config.values[index] + '"> </input>');
|
||||||
}
|
}
|
||||||
newInput = $('<input type = "' + inputType + '" value = "' + this.config.values[index] + '"> </input>');
|
|
||||||
this.valueInputs.push(newInput.get(0));
|
this.valueInputs.push(newInput.get(0));
|
||||||
inputArea.append(newInput);
|
inputArea.append(newInput);
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emitChange) {
|
||||||
|
this.eventEmitter.emit('change', {
|
||||||
|
value: Number(newInput[0].options[0].value),
|
||||||
|
property: 'values[0]',
|
||||||
|
index: this.index
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Condition.prototype.generateSelectOptions = function () {
|
||||||
|
let telemetryMetadata = this.conditionManager.getTelemetryMetadata(this.config.object);
|
||||||
|
let options = '';
|
||||||
|
telemetryMetadata[this.config.key].enumerations.forEach(enumeration => {
|
||||||
|
options += '<option value="' + enumeration.value + '">'+ enumeration.string + '</option>';
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
return Condition;
|
return Condition;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ define([], function () {
|
|||||||
*/
|
*/
|
||||||
this.inputTypes = {
|
this.inputTypes = {
|
||||||
number: 'number',
|
number: 'number',
|
||||||
string: 'text'
|
string: 'text',
|
||||||
|
enum: 'select'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +35,8 @@ define([], function () {
|
|||||||
*/
|
*/
|
||||||
this.inputValidators = {
|
this.inputValidators = {
|
||||||
number: this.validateNumberInput,
|
number: this.validateNumberInput,
|
||||||
string: this.validateStringInput
|
string: this.validateStringInput,
|
||||||
|
enum: this.validateNumberInput
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -201,7 +203,7 @@ define([], function () {
|
|||||||
return typeof input[0] === 'undefined';
|
return typeof input[0] === 'undefined';
|
||||||
},
|
},
|
||||||
text: 'is undefined',
|
text: 'is undefined',
|
||||||
appliesTo: ['string', 'number'],
|
appliesTo: ['string', 'number', 'enum'],
|
||||||
inputCount: 0,
|
inputCount: 0,
|
||||||
getDescription: function () {
|
getDescription: function () {
|
||||||
return ' is undefined';
|
return ' is undefined';
|
||||||
@@ -212,11 +214,33 @@ define([], function () {
|
|||||||
return typeof input[0] !== 'undefined';
|
return typeof input[0] !== 'undefined';
|
||||||
},
|
},
|
||||||
text: 'is defined',
|
text: 'is defined',
|
||||||
appliesTo: ['string', 'number'],
|
appliesTo: ['string', 'number', 'enum'],
|
||||||
inputCount: 0,
|
inputCount: 0,
|
||||||
getDescription: function () {
|
getDescription: function () {
|
||||||
return ' is defined';
|
return ' is defined';
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
enumValueIs: {
|
||||||
|
operation: function (input) {
|
||||||
|
return input[0] === input[1];
|
||||||
|
},
|
||||||
|
text: 'is',
|
||||||
|
appliesTo: ['enum'],
|
||||||
|
inputCount: 1,
|
||||||
|
getDescription: function (values) {
|
||||||
|
return ' == ' + values[0];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enumValueIsNot: {
|
||||||
|
operation: function (input) {
|
||||||
|
return input[0] !== input[1];
|
||||||
|
},
|
||||||
|
text: 'is not',
|
||||||
|
appliesTo: ['enum'],
|
||||||
|
inputCount: 1,
|
||||||
|
getDescription: function (values) {
|
||||||
|
return ' != ' + values[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -310,13 +334,16 @@ define([], function () {
|
|||||||
validator;
|
validator;
|
||||||
|
|
||||||
if (cache[object] && typeof cache[object][key] !== 'undefined') {
|
if (cache[object] && typeof cache[object][key] !== 'undefined') {
|
||||||
telemetryValue = [cache[object][key]];
|
let value = cache[object][key];
|
||||||
|
telemetryValue = [isNaN(Number(value)) ? value : Number(value)];
|
||||||
}
|
}
|
||||||
|
|
||||||
op = this.operations[operation] && this.operations[operation].operation;
|
op = this.operations[operation] && this.operations[operation].operation;
|
||||||
input = telemetryValue && telemetryValue.concat(values);
|
input = telemetryValue && telemetryValue.concat(values);
|
||||||
validator = op && this.inputValidators[this.operations[operation].appliesTo[0]];
|
validator = op && this.inputValidators[this.operations[operation].appliesTo[0]];
|
||||||
|
|
||||||
if (op && input && validator) {
|
if (op && input && validator) {
|
||||||
if (this.operations[operation].appliesTo.length === 2) {
|
if (this.operations[operation].appliesTo.length > 1) {
|
||||||
return (this.validateNumberInput(input) || this.validateStringInput(input)) && op(input);
|
return (this.validateNumberInput(input) || this.validateStringInput(input)) && op(input);
|
||||||
} else {
|
} else {
|
||||||
return validator(input) && op(input);
|
return validator(input) && op(input);
|
||||||
@@ -372,7 +399,7 @@ define([], function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true only of the given operation applies to a given type
|
* Returns true only if the given operation applies to a given type
|
||||||
* @param {string} key The key of the operation
|
* @param {string} key The key of the operation
|
||||||
* @param {string} type The value type to query
|
* @param {string} type The value type to query
|
||||||
* @returns {boolean} True if the condition applies, false otherwise
|
* @returns {boolean} True if the condition applies, false otherwise
|
||||||
|
|||||||
@@ -130,7 +130,9 @@ define ([
|
|||||||
this.telemetryTypesById[objectId] = {};
|
this.telemetryTypesById[objectId] = {};
|
||||||
Object.values(this.telemetryMetadataById[objectId]).forEach(function (valueMetadata) {
|
Object.values(this.telemetryMetadataById[objectId]).forEach(function (valueMetadata) {
|
||||||
var type;
|
var type;
|
||||||
if (valueMetadata.hints.hasOwnProperty('range')) {
|
if (valueMetadata.enumerations !== undefined) {
|
||||||
|
type = 'enum';
|
||||||
|
} else if (valueMetadata.hints.hasOwnProperty('range')) {
|
||||||
type = 'number';
|
type = 'number';
|
||||||
} else if (valueMetadata.hints.hasOwnProperty('domain')) {
|
} else if (valueMetadata.hints.hasOwnProperty('domain')) {
|
||||||
type = 'number';
|
type = 'number';
|
||||||
@@ -163,11 +165,18 @@ define ([
|
|||||||
* @param {datum} datum The new data from the telemetry source
|
* @param {datum} datum The new data from the telemetry source
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ConditionManager.prototype.handleSubscriptionCallback = function (objId, datum) {
|
ConditionManager.prototype.handleSubscriptionCallback = function (objId, telemetryDatum) {
|
||||||
this.subscriptionCache[objId] = datum;
|
this.subscriptionCache[objId] = this.createNormalizedDatum(objId, telemetryDatum);
|
||||||
this.eventEmitter.emit('receiveTelemetry');
|
this.eventEmitter.emit('receiveTelemetry');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ConditionManager.prototype.createNormalizedDatum = function (objId, telemetryDatum) {
|
||||||
|
return Object.values(this.telemetryMetadataById[objId]).reduce((normalizedDatum, metadatum) => {
|
||||||
|
normalizedDatum[metadatum.key] = telemetryDatum[metadatum.source];
|
||||||
|
return normalizedDatum;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for an add event in this Summary Widget's composition.
|
* Event handler for an add event in this Summary Widget's composition.
|
||||||
* Sets up subscription handlers and parses its property types.
|
* Sets up subscription handlers and parses its property types.
|
||||||
@@ -236,6 +245,7 @@ define ([
|
|||||||
id.namespace === identifier.namespace;
|
id.namespace === identifier.namespace;
|
||||||
});
|
});
|
||||||
delete this.compositionObjs[objectId];
|
delete this.compositionObjs[objectId];
|
||||||
|
delete this.subscriptionCache[objectId];
|
||||||
this.subscriptions[objectId](); //unsubscribe from telemetry source
|
this.subscriptions[objectId](); //unsubscribe from telemetry source
|
||||||
delete this.subscriptions[objectId];
|
delete this.subscriptions[objectId];
|
||||||
this.eventEmitter.emit('remove', identifier);
|
this.eventEmitter.emit('remove', identifier);
|
||||||
|
|||||||
@@ -110,9 +110,11 @@ define([
|
|||||||
|
|
||||||
type = self.manager.getTelemetryPropertyType(self.config.object, key);
|
type = self.manager.getTelemetryPropertyType(self.config.object, key);
|
||||||
|
|
||||||
self.operationKeys = operations.filter(function (operation) {
|
if (type !== undefined) {
|
||||||
return self.evaluator.operationAppliesTo(operation, type);
|
self.operationKeys = operations.filter(function (operation) {
|
||||||
});
|
return self.evaluator.operationAppliesTo(operation, type);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
OperationSelect.prototype.destroy = function () {
|
OperationSelect.prototype.destroy = function () {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ define([
|
|||||||
return this.openmct.time.getAllTimeSystems().map(function (ts, i) {
|
return this.openmct.time.getAllTimeSystems().map(function (ts, i) {
|
||||||
return {
|
return {
|
||||||
key: ts.key,
|
key: ts.key,
|
||||||
name: 'UTC',
|
name: ts.name,
|
||||||
format: ts.timeFormat,
|
format: ts.timeFormat,
|
||||||
hints: {
|
hints: {
|
||||||
domain: i
|
domain: i
|
||||||
@@ -64,7 +64,7 @@ define([
|
|||||||
// Generally safe assumption is that we have one domain per timeSystem.
|
// Generally safe assumption is that we have one domain per timeSystem.
|
||||||
values: this.getDomains().concat([
|
values: this.getDomains().concat([
|
||||||
{
|
{
|
||||||
name: 'state',
|
name: 'State',
|
||||||
key: 'state',
|
key: 'state',
|
||||||
source: 'ruleIndex',
|
source: 'ruleIndex',
|
||||||
format: 'enum',
|
format: 'enum',
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ define([
|
|||||||
return typeof input[0] === 'undefined';
|
return typeof input[0] === 'undefined';
|
||||||
},
|
},
|
||||||
text: 'is undefined',
|
text: 'is undefined',
|
||||||
appliesTo: ['string', 'number'],
|
appliesTo: ['string', 'number', 'enum'],
|
||||||
inputCount: 0,
|
inputCount: 0,
|
||||||
getDescription: function () {
|
getDescription: function () {
|
||||||
return ' is undefined';
|
return ' is undefined';
|
||||||
@@ -185,11 +185,33 @@ define([
|
|||||||
return typeof input[0] !== 'undefined';
|
return typeof input[0] !== 'undefined';
|
||||||
},
|
},
|
||||||
text: 'is defined',
|
text: 'is defined',
|
||||||
appliesTo: ['string', 'number'],
|
appliesTo: ['string', 'number', 'enum'],
|
||||||
inputCount: 0,
|
inputCount: 0,
|
||||||
getDescription: function () {
|
getDescription: function () {
|
||||||
return ' is defined';
|
return ' is defined';
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
enumValueIs: {
|
||||||
|
operation: function (input) {
|
||||||
|
return input[0] === input[1];
|
||||||
|
},
|
||||||
|
text: 'is',
|
||||||
|
appliesTo: ['enum'],
|
||||||
|
inputCount: 1,
|
||||||
|
getDescription: function (values) {
|
||||||
|
return ' == ' + values[0];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enumValueIsNot: {
|
||||||
|
operation: function (input) {
|
||||||
|
return input[0] !== input[1];
|
||||||
|
},
|
||||||
|
text: 'is not',
|
||||||
|
appliesTo: ['enum'],
|
||||||
|
inputCount: 1,
|
||||||
|
getDescription: function (values) {
|
||||||
|
return ' != ' + values[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ define([
|
|||||||
this.filteredRows.destroy();
|
this.filteredRows.destroy();
|
||||||
Object.keys(this.subscriptions).forEach(this.unsubscribe, this);
|
Object.keys(this.subscriptions).forEach(this.unsubscribe, this);
|
||||||
this.openmct.time.off('bounds', this.refreshData);
|
this.openmct.time.off('bounds', this.refreshData);
|
||||||
this.openmct.time.on('timeSystem', this.refreshData);
|
this.openmct.time.off('timeSystem', this.refreshData);
|
||||||
if (this.filterObserver) {
|
if (this.filterObserver) {
|
||||||
this.filterObserver();
|
this.filterObserver();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ define(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
class BoundedTableRowCollection extends SortedTableRowCollection {
|
class BoundedTableRowCollection extends SortedTableRowCollection {
|
||||||
constructor (openmct) {
|
constructor(openmct) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.futureBuffer = new SortedTableRowCollection();
|
this.futureBuffer = new SortedTableRowCollection();
|
||||||
this.openmct = openmct;
|
this.openmct = openmct;
|
||||||
|
|
||||||
@@ -46,12 +46,13 @@ define(
|
|||||||
openmct.time.on('bounds', this.bounds);
|
openmct.time.on('bounds', this.bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
addOne (item) {
|
addOne(item) {
|
||||||
|
let parsedValue = this.getValueForSortColumn(item);
|
||||||
// Insert into either in-bounds array, or the future buffer.
|
// Insert into either in-bounds array, or the future buffer.
|
||||||
// Data in the future buffer will be re-evaluated for possible
|
// Data in the future buffer will be re-evaluated for possible
|
||||||
// insertion on next bounds change
|
// insertion on next bounds change
|
||||||
let beforeStartOfBounds = this.parseTime(item.datum[this.sortOptions.key]) < this.lastBounds.start;
|
let beforeStartOfBounds = parsedValue < this.lastBounds.start;
|
||||||
let afterEndOfBounds = this.parseTime(item.datum[this.sortOptions.key]) > this.lastBounds.end;
|
let afterEndOfBounds = parsedValue > this.lastBounds.end;
|
||||||
|
|
||||||
if (!afterEndOfBounds && !beforeStartOfBounds) {
|
if (!afterEndOfBounds && !beforeStartOfBounds) {
|
||||||
return super.addOne(item);
|
return super.addOne(item);
|
||||||
@@ -86,13 +87,13 @@ define(
|
|||||||
* @fires TelemetryCollection#discarded
|
* @fires TelemetryCollection#discarded
|
||||||
* @param bounds
|
* @param bounds
|
||||||
*/
|
*/
|
||||||
bounds (bounds) {
|
bounds(bounds) {
|
||||||
let startChanged = this.lastBounds.start !== bounds.start;
|
let startChanged = this.lastBounds.start !== bounds.start;
|
||||||
let endChanged = this.lastBounds.end !== bounds.end;
|
let endChanged = this.lastBounds.end !== bounds.end;
|
||||||
|
|
||||||
let startIndex = 0;
|
let startIndex = 0;
|
||||||
let endIndex = 0;
|
let endIndex = 0;
|
||||||
|
|
||||||
let discarded = [];
|
let discarded = [];
|
||||||
let added = [];
|
let added = [];
|
||||||
let testValue = {
|
let testValue = {
|
||||||
@@ -135,9 +136,13 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getValueForSortColumn(row) {
|
||||||
|
return this.parseTime(row.datum[this.sortOptions.key]);
|
||||||
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
this.openmct.time.off('bounds', this.bounds);
|
this.openmct.time.off('bounds', this.bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BoundedTableRowCollection;
|
return BoundedTableRowCollection;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ define(
|
|||||||
if (rowsAdded.length > 0) {
|
if (rowsAdded.length > 0) {
|
||||||
this.emit('add', rowsAdded);
|
this.emit('add', rowsAdded);
|
||||||
}
|
}
|
||||||
this.dupeCheck = true;
|
this.dupeCheck = true;
|
||||||
} else {
|
} else {
|
||||||
let wasAdded = this.addOne(rows);
|
let wasAdded = this.addOne(rows);
|
||||||
if (wasAdded) {
|
if (wasAdded) {
|
||||||
@@ -115,11 +115,10 @@ define(
|
|||||||
if (this.rows.length === 0) {
|
if (this.rows.length === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortOptionsKey = this.sortOptions.key;
|
const testRowValue = this.getValueForSortColumn(testRow);
|
||||||
const testRowValue = testRow.datum[sortOptionsKey];
|
const firstValue = this.getValueForSortColumn(this.rows[0]);
|
||||||
const firstValue = this.rows[0].datum[sortOptionsKey];
|
const lastValue = this.getValueForSortColumn(this.rows[this.rows.length - 1]);
|
||||||
const lastValue = this.rows[this.rows.length - 1].datum[sortOptionsKey];
|
|
||||||
|
|
||||||
lodashFunction = lodashFunction || _.sortedIndex;
|
lodashFunction = lodashFunction || _.sortedIndex;
|
||||||
|
|
||||||
@@ -133,7 +132,7 @@ define(
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return lodashFunction(rows, testRow, (thisRow) => {
|
return lodashFunction(rows, testRow, (thisRow) => {
|
||||||
return thisRow.datum[sortOptionsKey];
|
return this.getValueForSortColumn(thisRow);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -147,7 +146,7 @@ define(
|
|||||||
} else {
|
} else {
|
||||||
// Use a custom comparison function to support descending sort.
|
// Use a custom comparison function to support descending sort.
|
||||||
return lodashFunction(rows, testRow, (thisRow) => {
|
return lodashFunction(rows, testRow, (thisRow) => {
|
||||||
const thisRowValue = thisRow.datum[sortOptionsKey];
|
const thisRowValue = this.getValueForSortColumn(thisRow);
|
||||||
if (testRowValue === thisRowValue) {
|
if (testRowValue === thisRowValue) {
|
||||||
return EQUAL;
|
return EQUAL;
|
||||||
} else if (testRowValue < thisRowValue) {
|
} else if (testRowValue < thisRowValue) {
|
||||||
@@ -206,7 +205,7 @@ define(
|
|||||||
this.emit('sort');
|
this.emit('sort');
|
||||||
}
|
}
|
||||||
// Return duplicate to avoid direct modification of underlying object
|
// Return duplicate to avoid direct modification of underlying object
|
||||||
return Object.assign({}, this.sortOptions);
|
return Object.assign({}, this.sortOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllRowsForObject(objectKeyString) {
|
removeAllRowsForObject(objectKeyString) {
|
||||||
@@ -218,25 +217,32 @@ define(
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.emit('remove', removed);
|
this.emit('remove', removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getValueForSortColumn(row) {
|
||||||
|
return row.datum[this.sortOptions.key];
|
||||||
|
}
|
||||||
|
|
||||||
remove(removedRows) {
|
remove(removedRows) {
|
||||||
this.rows = this.rows.filter(row => {
|
this.rows = this.rows.filter(row => {
|
||||||
return removedRows.indexOf(row) === -1;
|
return removedRows.indexOf(row) === -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.emit('remove', removedRows);
|
this.emit('remove', removedRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRows () {
|
getRows() {
|
||||||
return this.rows;
|
return this.rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
let removedRows = this.rows;
|
let removedRows = this.rows;
|
||||||
this.rows = [];
|
this.rows = [];
|
||||||
|
|
||||||
this.emit('remove', removedRows);
|
this.emit('remove', removedRows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SortedTableRowCollection;
|
return SortedTableRowCollection;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
<!-- Content table -->
|
<!-- Content table -->
|
||||||
<div class="c-table__body-w c-telemetry-table__body-w js-telemetry-table__body-w" @scroll="scroll" :style="{ 'max-width': widthWithScroll}">
|
<div class="c-table__body-w c-telemetry-table__body-w js-telemetry-table__body-w" @scroll="scroll" :style="{ 'max-width': widthWithScroll}">
|
||||||
<div class="c-telemetry-table__scroll-forcer" :style="{ width: totalWidth + 'px' }"></div>
|
<div class="c-telemetry-table__scroll-forcer" :style="{ width: totalWidth + 'px' }"></div>
|
||||||
<table class="c-table__body c-telemetry-table__body"
|
<table class="c-table__body c-telemetry-table__body js-telemetry-table__content"
|
||||||
:style="{ height: totalHeight + 'px'}">
|
:style="{ height: totalHeight + 'px'}">
|
||||||
<tbody>
|
<tbody>
|
||||||
<telemetry-table-row v-for="(row, rowIndex) in visibleRows"
|
<telemetry-table-row v-for="(row, rowIndex) in visibleRows"
|
||||||
@@ -284,7 +284,7 @@ import _ from 'lodash';
|
|||||||
const VISIBLE_ROW_COUNT = 100;
|
const VISIBLE_ROW_COUNT = 100;
|
||||||
const ROW_HEIGHT = 17;
|
const ROW_HEIGHT = 17;
|
||||||
const RESIZE_POLL_INTERVAL = 200;
|
const RESIZE_POLL_INTERVAL = 200;
|
||||||
const AUTO_SCROLL_TRIGGER_HEIGHT = 20;
|
const AUTO_SCROLL_TRIGGER_HEIGHT = 100;
|
||||||
const RESIZE_HOT_ZONE = 10;
|
const RESIZE_HOT_ZONE = 10;
|
||||||
const MOVE_TRIGGER_WAIT = 500;
|
const MOVE_TRIGGER_WAIT = 500;
|
||||||
const VERTICAL_SCROLL_WIDTH = 30;
|
const VERTICAL_SCROLL_WIDTH = 30;
|
||||||
@@ -364,42 +364,48 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateVisibleRows() {
|
updateVisibleRows() {
|
||||||
|
if (!this.updatingView) {
|
||||||
|
this.updatingView = true;
|
||||||
|
requestAnimationFrame(()=> {
|
||||||
|
|
||||||
let start = 0;
|
let start = 0;
|
||||||
let end = VISIBLE_ROW_COUNT;
|
let end = VISIBLE_ROW_COUNT;
|
||||||
let filteredRows = this.table.filteredRows.getRows();
|
let filteredRows = this.table.filteredRows.getRows();
|
||||||
let filteredRowsLength = filteredRows.length;
|
let filteredRowsLength = filteredRows.length;
|
||||||
|
|
||||||
this.totalHeight = this.rowHeight * filteredRowsLength - 1;
|
if (filteredRowsLength < VISIBLE_ROW_COUNT) {
|
||||||
|
end = filteredRowsLength;
|
||||||
|
} else {
|
||||||
|
let firstVisible = this.calculateFirstVisibleRow();
|
||||||
|
let lastVisible = this.calculateLastVisibleRow();
|
||||||
|
let totalVisible = lastVisible - firstVisible;
|
||||||
|
|
||||||
if (filteredRowsLength < VISIBLE_ROW_COUNT) {
|
let numberOffscreen = VISIBLE_ROW_COUNT - totalVisible;
|
||||||
end = filteredRowsLength;
|
start = firstVisible - Math.floor(numberOffscreen / 2);
|
||||||
} else {
|
end = lastVisible + Math.ceil(numberOffscreen / 2);
|
||||||
let firstVisible = this.calculateFirstVisibleRow();
|
|
||||||
let lastVisible = this.calculateLastVisibleRow();
|
|
||||||
let totalVisible = lastVisible - firstVisible;
|
|
||||||
|
|
||||||
let numberOffscreen = VISIBLE_ROW_COUNT - totalVisible;
|
if (start < 0) {
|
||||||
start = firstVisible - Math.floor(numberOffscreen / 2);
|
start = 0;
|
||||||
end = lastVisible + Math.ceil(numberOffscreen / 2);
|
end = Math.min(VISIBLE_ROW_COUNT, filteredRowsLength);
|
||||||
|
} else if (end >= filteredRowsLength) {
|
||||||
|
end = filteredRowsLength;
|
||||||
|
start = end - VISIBLE_ROW_COUNT + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.rowOffset = start;
|
||||||
|
this.visibleRows = filteredRows.slice(start, end);
|
||||||
|
|
||||||
if (start < 0) {
|
this.updatingView = false;
|
||||||
start = 0;
|
});
|
||||||
end = Math.min(VISIBLE_ROW_COUNT, filteredRowsLength);
|
|
||||||
} else if (end >= filteredRowsLength) {
|
|
||||||
end = filteredRowsLength;
|
|
||||||
start = end - VISIBLE_ROW_COUNT + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.rowOffset = start;
|
|
||||||
this.visibleRows = filteredRows.slice(start, end);
|
|
||||||
},
|
},
|
||||||
calculateFirstVisibleRow() {
|
calculateFirstVisibleRow() {
|
||||||
return Math.floor(this.scrollable.scrollTop / this.rowHeight);
|
let scrollTop = this.scrollable.scrollTop;
|
||||||
|
return Math.floor(scrollTop / this.rowHeight);
|
||||||
},
|
},
|
||||||
calculateLastVisibleRow() {
|
calculateLastVisibleRow() {
|
||||||
let bottomScroll = this.scrollable.scrollTop + this.scrollable.offsetHeight;
|
let scrollBottom = this.scrollable.scrollTop + this.scrollable.offsetHeight;
|
||||||
return Math.floor(bottomScroll / this.rowHeight);
|
return Math.ceil(scrollBottom / this.rowHeight);
|
||||||
},
|
},
|
||||||
updateHeaders() {
|
updateHeaders() {
|
||||||
this.headers = this.table.configuration.getVisibleHeaders();
|
this.headers = this.table.configuration.getVisibleHeaders();
|
||||||
@@ -443,71 +449,70 @@ export default {
|
|||||||
}
|
}
|
||||||
this.table.sortBy(this.sortOptions);
|
this.table.sortBy(this.sortOptions);
|
||||||
},
|
},
|
||||||
scroll() {
|
scroll () {
|
||||||
if (!this.processingScroll) {
|
this.updateVisibleRows();
|
||||||
this.processingScroll = true;
|
this.synchronizeScrollX();
|
||||||
requestAnimationFrame(()=> {
|
|
||||||
this.updateVisibleRows();
|
|
||||||
this.synchronizeScrollX();
|
|
||||||
|
|
||||||
if (this.shouldSnapToBottom()) {
|
if (this.shouldSnapToBottom()) {
|
||||||
this.autoScroll = true;
|
this.autoScroll = true;
|
||||||
} else {
|
} else {
|
||||||
// If user scrolls away from bottom, disable auto-scroll.
|
// If user scrolls away from bottom, disable auto-scroll.
|
||||||
// Auto-scroll will be re-enabled if user scrolls to bottom again.
|
// Auto-scroll will be re-enabled if user scrolls to bottom again.
|
||||||
this.autoScroll = false;
|
this.autoScroll = false;
|
||||||
}
|
|
||||||
this.processingScroll = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shouldSnapToBottom() {
|
shouldSnapToBottom() {
|
||||||
return this.scrollable.scrollTop >= (this.scrollable.scrollHeight - this.scrollable.offsetHeight - AUTO_SCROLL_TRIGGER_HEIGHT);
|
return this.scrollable.scrollTop >= (this.scrollable.scrollHeight - this.scrollable.offsetHeight - AUTO_SCROLL_TRIGGER_HEIGHT);
|
||||||
},
|
},
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
this.scrollable.scrollTop = Number.MAX_SAFE_INTEGER;
|
||||||
},
|
},
|
||||||
synchronizeScrollX() {
|
synchronizeScrollX() {
|
||||||
this.headersHolderEl.scrollLeft = this.scrollable.scrollLeft;
|
this.headersHolderEl.scrollLeft = this.scrollable.scrollLeft;
|
||||||
},
|
},
|
||||||
filterChanged(columnKey) {
|
filterChanged(columnKey) {
|
||||||
this.table.filteredRows.setColumnFilter(columnKey, this.filters[columnKey]);
|
this.table.filteredRows.setColumnFilter(columnKey, this.filters[columnKey]);
|
||||||
|
this.setHeight();
|
||||||
},
|
},
|
||||||
clearFilter(columnKey) {
|
clearFilter(columnKey) {
|
||||||
this.filters[columnKey] = '';
|
this.filters[columnKey] = '';
|
||||||
this.table.filteredRows.setColumnFilter(columnKey, '');
|
this.table.filteredRows.setColumnFilter(columnKey, '');
|
||||||
|
this.setHeight();
|
||||||
},
|
},
|
||||||
rowsAdded(rows) {
|
rowsAdded (rows) {
|
||||||
|
this.setHeight();
|
||||||
|
|
||||||
let sizingRow;
|
let sizingRow;
|
||||||
if (Array.isArray(rows)) {
|
if (Array.isArray(rows)) {
|
||||||
sizingRow = rows[0];
|
sizingRow = rows[0];
|
||||||
} else {
|
} else {
|
||||||
sizingRow = rows;
|
sizingRow = rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.sizingRows[sizingRow.objectKeyString]) {
|
if (!this.sizingRows[sizingRow.objectKeyString]) {
|
||||||
this.sizingRows[sizingRow.objectKeyString] = sizingRow;
|
this.sizingRows[sizingRow.objectKeyString] = sizingRow;
|
||||||
this.$nextTick().then(this.calculateColumnWidths);
|
this.$nextTick().then(this.calculateColumnWidths);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.updatingView) {
|
if (this.autoScroll) {
|
||||||
this.updatingView = true;
|
this.scrollToBottom();
|
||||||
requestAnimationFrame(()=> {
|
|
||||||
this.updateVisibleRows();
|
|
||||||
if (this.autoScroll) {
|
|
||||||
this.$nextTick().then(this.scrollToBottom);
|
|
||||||
}
|
|
||||||
this.updatingView = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateVisibleRows();
|
||||||
},
|
},
|
||||||
rowsRemoved(rows) {
|
rowsRemoved (rows) {
|
||||||
if (!this.updatingView) {
|
this.setHeight();
|
||||||
this.updatingView = true;
|
this.updateVisibleRows();
|
||||||
requestAnimationFrame(()=> {
|
},
|
||||||
this.updateVisibleRows();
|
/**
|
||||||
this.updatingView = false;
|
* Calculates height based on total number of rows, and sets table height.
|
||||||
});
|
*/
|
||||||
}
|
setHeight() {
|
||||||
|
let filteredRowsLength = this.table.filteredRows.getRows().length;
|
||||||
|
this.totalHeight = this.rowHeight * filteredRowsLength - 1;
|
||||||
|
// Set element height directly to avoid having to wait for Vue to update DOM
|
||||||
|
// which causes subsequent scroll to use an out of date height.
|
||||||
|
this.contentTable.style.height = this.totalHeight + 'px';
|
||||||
},
|
},
|
||||||
exportAsCSV() {
|
exportAsCSV() {
|
||||||
const headerKeys = Object.keys(this.headers);
|
const headerKeys = Object.keys(this.headers);
|
||||||
@@ -595,7 +600,11 @@ export default {
|
|||||||
this.calculateTableSize();
|
this.calculateTableSize();
|
||||||
// On some resize events scrollTop is reset to 0. Possibly due to a transition we're using?
|
// On some resize events scrollTop is reset to 0. Possibly due to a transition we're using?
|
||||||
// Need to preserve scroll position in this case.
|
// Need to preserve scroll position in this case.
|
||||||
this.scrollable.scrollTop = scrollTop;
|
if (this.autoScroll) {
|
||||||
|
this.scrollToBottom();
|
||||||
|
} else {
|
||||||
|
this.scrollable.scrollTop = scrollTop;
|
||||||
|
}
|
||||||
width = el.clientWidth;
|
width = el.clientWidth;
|
||||||
height = el.clientHeight;
|
height = el.clientHeight;
|
||||||
}
|
}
|
||||||
@@ -608,6 +617,9 @@ export default {
|
|||||||
this.filterChanged = _.debounce(this.filterChanged, 500);
|
this.filterChanged = _.debounce(this.filterChanged, 500);
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.rowsAdded = _.throttle(this.rowsAdded, 200);
|
||||||
|
this.rowsRemoved = _.throttle(this.rowsRemoved, 200);
|
||||||
|
this.scroll = _.throttle(this.scroll, 100);
|
||||||
|
|
||||||
this.table.on('object-added', this.addObject);
|
this.table.on('object-added', this.addObject);
|
||||||
this.table.on('object-removed', this.removeObject);
|
this.table.on('object-removed', this.removeObject);
|
||||||
@@ -621,6 +633,7 @@ export default {
|
|||||||
//Default sort
|
//Default sort
|
||||||
this.sortOptions = this.table.filteredRows.sortBy();
|
this.sortOptions = this.table.filteredRows.sortBy();
|
||||||
this.scrollable = this.$el.querySelector('.js-telemetry-table__body-w');
|
this.scrollable = this.$el.querySelector('.js-telemetry-table__body-w');
|
||||||
|
this.contentTable = this.$el.querySelector('.js-telemetry-table__content');
|
||||||
this.sizingTable = this.$el.querySelector('.js-telemetry-table__sizing');
|
this.sizingTable = this.$el.querySelector('.js-telemetry-table__sizing');
|
||||||
this.headersHolderEl = this.$el.querySelector('.js-table__headers-w');
|
this.headersHolderEl = this.$el.querySelector('.js-table__headers-w');
|
||||||
|
|
||||||
|
|||||||
@@ -54,10 +54,11 @@
|
|||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
// App logo
|
// App logo
|
||||||
top: 0;
|
$d: 25%;
|
||||||
right: 15%;
|
top: $d;
|
||||||
bottom: 0;
|
right: $d;
|
||||||
left: 15%;
|
bottom: $d;
|
||||||
|
left: $d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,12 +76,20 @@
|
|||||||
|
|
||||||
&__image,
|
&__image,
|
||||||
&__text {
|
&__text {
|
||||||
height: 50%;
|
flex: 1 1 auto;
|
||||||
flex: 1 1 0;
|
}
|
||||||
|
|
||||||
|
&__image {
|
||||||
|
height: 35%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__text {
|
&__text {
|
||||||
|
height: 65%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
> * + * {
|
||||||
|
border-top: 1px solid $colorInteriorBorder;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--licenses {
|
&--licenses {
|
||||||
@@ -107,7 +116,7 @@
|
|||||||
|
|
||||||
h1, h2, h3 {
|
h1, h2, h3 {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-bottom: 1em;
|
margin-bottom: .25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
|||||||
@@ -393,6 +393,11 @@ select {
|
|||||||
color: $colorMenuIc;
|
color: $colorMenuIc;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
margin-right: $interiorMargin;
|
margin-right: $interiorMargin;
|
||||||
|
min-width: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not([class]):before {
|
||||||
|
content: ''; // Add this element so that menu items without an icon still indent properly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,3 +33,4 @@
|
|||||||
@import "table";
|
@import "table";
|
||||||
@import "legacy";
|
@import "legacy";
|
||||||
@import "legacy-plots";
|
@import "legacy-plots";
|
||||||
|
@import "legacy-messages";
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ export default {
|
|||||||
this.currentObject = this.object;
|
this.currentObject = this.object;
|
||||||
this.updateView();
|
this.updateView();
|
||||||
this.$el.addEventListener('dragover', this.onDragOver);
|
this.$el.addEventListener('dragover', this.onDragOver);
|
||||||
this.$el.addEventListener('drop', this.addObjectToParent);
|
|
||||||
this.$el.addEventListener('drop', this.editIfEditable, {
|
this.$el.addEventListener('drop', this.editIfEditable, {
|
||||||
capture: true
|
capture: true
|
||||||
});
|
});
|
||||||
|
this.$el.addEventListener('drop', this.addObjectToParent);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clear() {
|
clear() {
|
||||||
@@ -57,6 +57,10 @@ export default {
|
|||||||
this.removeSelectable();
|
this.removeSelectable();
|
||||||
delete this.removeSelectable;
|
delete this.removeSelectable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.composition) {
|
||||||
|
this.composition._destroy();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
invokeEditModeHandler(editMode) {
|
invokeEditModeHandler(editMode) {
|
||||||
this.currentView.onEditModeChange(editMode);
|
this.currentView.onEditModeChange(editMode);
|
||||||
@@ -70,6 +74,13 @@ export default {
|
|||||||
if (!this.currentObject) {
|
if (!this.currentObject) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.composition = this.openmct.composition.get(this.currentObject);
|
||||||
|
if (this.composition) {
|
||||||
|
this.composition._synchronize();
|
||||||
|
this.loadComposition();
|
||||||
|
}
|
||||||
|
|
||||||
this.viewContainer = document.createElement('div');
|
this.viewContainer = document.createElement('div');
|
||||||
this.viewContainer.classList.add('c-object-view','u-contents');
|
this.viewContainer.classList.add('c-object-view','u-contents');
|
||||||
this.$el.append(this.viewContainer);
|
this.$el.append(this.viewContainer);
|
||||||
@@ -112,6 +123,10 @@ export default {
|
|||||||
delete this.removeSelectable;
|
delete this.removeSelectable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.composition) {
|
||||||
|
this.composition._destroy();
|
||||||
|
}
|
||||||
|
|
||||||
this.currentObject = object;
|
this.currentObject = object;
|
||||||
this.unlisten = this.openmct.objects.observe(this.currentObject, '*', (mutatedObject) => {
|
this.unlisten = this.openmct.objects.observe(this.currentObject, '*', (mutatedObject) => {
|
||||||
this.currentObject = mutatedObject;
|
this.currentObject = mutatedObject;
|
||||||
@@ -120,6 +135,9 @@ export default {
|
|||||||
this.viewKey = viewKey;
|
this.viewKey = viewKey;
|
||||||
this.updateView(immediatelySelect);
|
this.updateView(immediatelySelect);
|
||||||
},
|
},
|
||||||
|
loadComposition() {
|
||||||
|
return this.composition.load();
|
||||||
|
},
|
||||||
getSelectionContext() {
|
getSelectionContext() {
|
||||||
if (this.currentView.getSelectionContext) {
|
if (this.currentView.getSelectionContext) {
|
||||||
return this.currentView.getSelectionContext();
|
return this.currentView.getSelectionContext();
|
||||||
@@ -133,10 +151,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
addObjectToParent(event) {
|
addObjectToParent(event) {
|
||||||
if (this.hasComposableDomainObject(event)) {
|
if (this.hasComposableDomainObject(event) && this.composition) {
|
||||||
let composableDomainObject = this.getComposableDomainObject(event);
|
let composableDomainObject = this.getComposableDomainObject(event);
|
||||||
this.currentObject.composition.push(composableDomainObject.identifier);
|
this.loadComposition().then(() => {
|
||||||
this.openmct.objects.mutate(this.currentObject, 'composition', this.currentObject.composition);
|
this.composition.add(composableDomainObject);
|
||||||
|
});
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
@@ -155,6 +175,7 @@ export default {
|
|||||||
editIfEditable(event) {
|
editIfEditable(event) {
|
||||||
let provider = this.getViewProvider();
|
let provider = this.getViewProvider();
|
||||||
if (provider &&
|
if (provider &&
|
||||||
|
provider.canEdit &&
|
||||||
provider.canEdit(this.currentObject) &&
|
provider.canEdit(this.currentObject) &&
|
||||||
!this.openmct.editor.isEditing()) {
|
!this.openmct.editor.isEditing()) {
|
||||||
this.openmct.editor.edit();
|
this.openmct.editor.edit();
|
||||||
|
|||||||
@@ -25,10 +25,6 @@ import _ from 'lodash';
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateSelection(selection) {
|
updateSelection(selection) {
|
||||||
if (_.isEqual(this.selection, selection)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
|
|
||||||
if (this.selectedViews) {
|
if (this.selectedViews) {
|
||||||
@@ -38,10 +34,6 @@ import _ from 'lodash';
|
|||||||
this.$el.innerHTML = '';
|
this.$el.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection.length > 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectedViews = this.openmct.inspectorViews.get(selection);
|
this.selectedViews = this.openmct.inspectorViews.get(selection);
|
||||||
this.selectedViews.forEach(selectedView => {
|
this.selectedViews.forEach(selectedView => {
|
||||||
let viewContainer = document.createElement('div');
|
let viewContainer = document.createElement('div');
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-about c-about--splash">
|
<div class="c-about c-about--splash">
|
||||||
<div v-if="!branding.aboutHtml" class="c-about__image c-splash-image"></div>
|
<div class="c-about__image c-splash-image"></div>
|
||||||
|
|
||||||
<div class="c-about__text s-text">
|
<div class="c-about__text s-text">
|
||||||
<div v-if="branding.aboutHtml" class="s-text l-content" v-html="branding.aboutHtml"></div>
|
<div class="c-about__text__element" v-if="branding.aboutHtml" v-html="branding.aboutHtml"></div>
|
||||||
<h1 class="l-title s-title">Open MCT</h1>
|
<div class="c-about__text__element">
|
||||||
<div class="l-description s-description">
|
<h1 class="l-title s-title">Open MCT</h1>
|
||||||
<p>Open MCT, Copyright © 2014-2019, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.</p>
|
<div class="l-description s-description">
|
||||||
<p>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 <a target="_blank" href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>.</p>
|
<p>Open MCT, Copyright © 2014-2019, United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All rights reserved.</p>
|
||||||
<p>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.</p>
|
<p>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 <a target="_blank" href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>.</p>
|
||||||
<p>Open MCT includes source code licensed under additional open source licenses. See the Open Source Licenses file included with this distribution or <a @click="showLicenses">click here for third party licensing information</a>.</p>
|
<p>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.</p>
|
||||||
|
<p>Open MCT includes source code licensed under additional open source licenses. See the Open Source Licenses file included with this distribution or <a @click="showLicenses">click here for third party licensing information</a>.</p>
|
||||||
|
</div>
|
||||||
|
<h2>Version Information</h2>
|
||||||
|
<ul class="t-info l-info s-info">
|
||||||
|
<li>Version: {{buildInfo.version || 'Unknown'}}</li>
|
||||||
|
<li>Build Date: {{buildInfo.buildDate || 'Unknown'}}</li>
|
||||||
|
<li>Revision: {{buildInfo.revision || 'Unknown'}}</li>
|
||||||
|
<li>Branch: {{buildInfo.branch || 'Unknown'}}</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<h2>Version Information</h2>
|
|
||||||
<ul class="t-info l-info s-info">
|
|
||||||
<li>Version: {{buildInfo.version || 'Unknown'}}</li>
|
|
||||||
<li>Build Date: {{buildInfo.buildDate || 'Unknown'}}</li>
|
|
||||||
<li>Revision: {{buildInfo.revision || 'Unknown'}}</li>
|
|
||||||
<li>Branch: {{buildInfo.branch || 'Unknown'}}</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -70,17 +70,18 @@
|
|||||||
this.domainObject = newObject;
|
this.domainObject = newObject;
|
||||||
});
|
});
|
||||||
this.$once('hook:destroyed', removeListener);
|
this.$once('hook:destroyed', removeListener);
|
||||||
|
|
||||||
if (this.openmct.composition.get(this.node.object)) {
|
if (this.openmct.composition.get(this.node.object)) {
|
||||||
this.hasChildren = true;
|
this.hasChildren = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.openmct.router.on('change:path', this.highlightIfNavigated);
|
this.openmct.router.on('change:path', this.highlightIfNavigated);
|
||||||
},
|
},
|
||||||
destroy() {
|
destroyed() {
|
||||||
|
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
||||||
if (this.composition) {
|
if (this.composition) {
|
||||||
this.composition.off('add', this.addChild);
|
this.composition.off('add', this.addChild);
|
||||||
this.composition.off('remove', this.removeChild);
|
this.composition.off('remove', this.removeChild);
|
||||||
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
|
||||||
delete this.composition;
|
delete this.composition;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default {
|
|||||||
|
|
||||||
this.objectPath.forEach(object => {
|
this.objectPath.forEach(object => {
|
||||||
if (object) {
|
if (object) {
|
||||||
this.$once('hook:destroy',
|
this.$once('hook:destroyed',
|
||||||
this.openmct.objects.observe(object, '*', updateObject.bind(this, object)))
|
this.openmct.objects.observe(object, '*', updateObject.bind(this, object)))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -116,7 +116,7 @@
|
|||||||
this.notebookEnabled = true;
|
this.notebookEnabled = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroy() {
|
destroyed() {
|
||||||
this.view.destroy();
|
this.view.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const webpackConfig = {
|
|||||||
"bourbon": "bourbon.scss",
|
"bourbon": "bourbon.scss",
|
||||||
"vue": path.join(__dirname, "node_modules/vue/dist/vue.js"),
|
"vue": path.join(__dirname, "node_modules/vue/dist/vue.js"),
|
||||||
"d3-scale": path.join(__dirname, "node_modules/d3-scale/build/d3-scale.min.js"),
|
"d3-scale": path.join(__dirname, "node_modules/d3-scale/build/d3-scale.min.js"),
|
||||||
|
"printj": path.join(__dirname, "node_modules/printj/dist/printj.min.js"),
|
||||||
"styles": path.join(__dirname, "src/styles-new")
|
"styles": path.join(__dirname, "src/styles-new")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user