Compare commits
23 Commits
new-eslint
...
tree-refac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15bef1c162 | ||
|
|
a2d21e3479 | ||
|
|
5693b153cb | ||
|
|
13e9541ad2 | ||
|
|
c0e3f6b577 | ||
|
|
43628ad9d6 | ||
|
|
67bea86bc8 | ||
|
|
4eb4cbfffc | ||
|
|
f763d1dea1 | ||
|
|
eda01abcbc | ||
|
|
694b8f4666 | ||
|
|
bbb271a678 | ||
|
|
fec1438806 | ||
|
|
28f19ec310 | ||
|
|
f934454c25 | ||
|
|
eb49ffae02 | ||
|
|
5751012872 | ||
|
|
aa041e04cf | ||
|
|
24e7ea143a | ||
|
|
79d5d9c4d0 | ||
|
|
b5bfdc4418 | ||
|
|
59730c60ec | ||
|
|
4a87a5d847 |
@@ -10,7 +10,8 @@ module.exports = {
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/recommended"
|
||||
"plugin:vue/recommended",
|
||||
"plugin:you-dont-need-lodash-underscore/compatible"
|
||||
],
|
||||
"parser": "vue-eslint-parser",
|
||||
"parserOptions": {
|
||||
@@ -22,6 +23,9 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"you-dont-need-lodash-underscore/omit": "off",
|
||||
"you-dont-need-lodash-underscore/throttle": "off",
|
||||
"you-dont-need-lodash-underscore/flatten": "off",
|
||||
"no-bitwise": "error",
|
||||
"curly": "error",
|
||||
"eqeqeq": "error",
|
||||
|
||||
4
API.md
4
API.md
@@ -427,8 +427,8 @@ Each telemetry value description has an object defining hints. Keys in this thi
|
||||
|
||||
Known hints:
|
||||
|
||||
* `domain`: Indicates that the value represents the "input" of a datum. Values with a `domain` hint will be used for the x-axis of a plot, and tables will render columns for these values first.
|
||||
* `range`: Indicates that the value is the "output" of a datum. Values with a `range` hint will be used as the y-axis on a plot, and tables will render columns for these values after the `domain` values.
|
||||
* `domain`: Values with a `domain` hint will be used for the x-axis of a plot, and tables will render columns for these values first.
|
||||
* `range`: Values with a `range` hint will be used as the y-axis on a plot, and tables will render columns for these values after the `domain` values.
|
||||
* `image`: Indicates that the value may be interpreted as the URL to an image file, in which case appropriate views will be made available.
|
||||
|
||||
##### The Time Conductor and Telemetry
|
||||
|
||||
@@ -103,7 +103,7 @@ the name chosen could not be mistaken for a topic or master branch.
|
||||
### Merging
|
||||
|
||||
When development is complete on an issue, the first step toward merging it
|
||||
back into the master branch is to file a Pull Request. The contributions
|
||||
back into the master branch is to file a Pull Request (PR). The contributions
|
||||
should meet code, test, and commit message standards as described below,
|
||||
and the pull request should include a completed author checklist, also
|
||||
as described below. Pull requests may be assigned to specific team
|
||||
@@ -114,6 +114,15 @@ request. When the reviewer is satisfied, they should add a comment to
|
||||
the pull request containing the reviewer checklist (from below) and complete
|
||||
the merge back to the master branch.
|
||||
|
||||
Additionally:
|
||||
* Every pull request must link to the issue that it addresses. Eg. “Addresses #1234” or “Closes #1234”. This is the responsibility of the pull request’s __author__. If no issue exists, create one.
|
||||
* Every __author__ must include testing instructions. These instructions should identify the areas of code affected, and some minimal test steps. If addressing a bug, reproduction steps should be included, if they were not included in the original issue. If reproduction steps were included on the original issue, and are sufficient, refer to them.
|
||||
* A pull request that closes an issue should say so in the description. Including the text “Closes #1234” will cause the linked issue to be automatically closed when the pull request is merged. This is the responsibility of the pull request’s __author__.
|
||||
* When a pull request is merged, and the corresponding issue closed, the __reviewer__ must add the tag “unverified” to the original issue. This will indicate that although the issue is closed, it has not been tested yet.
|
||||
* Every PR must have two reviewers assigned, though only one approval is necessary for merge.
|
||||
* Changes to API require approval by a senior developer.
|
||||
* When creating a PR, it is the author's responsibility to apply any priority label from the issue to the PR as well. This helps with prioritization.
|
||||
|
||||
## Standards
|
||||
|
||||
Contributions to Open MCT are expected to meet the following standards.
|
||||
@@ -292,6 +301,7 @@ checklist).
|
||||
2. Unit tests included and/or updated with changes?
|
||||
3. Command line build passes?
|
||||
4. Changes have been smoke-tested?
|
||||
5. Testing instructions included?
|
||||
|
||||
### Reviewer Checklist
|
||||
|
||||
@@ -299,3 +309,4 @@ checklist).
|
||||
2. Appropriate unit tests included?
|
||||
3. Code style and in-line documentation are appropriate?
|
||||
4. Commit messages meet standards?
|
||||
5. Has associated issue been labelled `unverified`? (only applicable if this PR closes the issue)
|
||||
|
||||
@@ -50,7 +50,8 @@ define([
|
||||
values: [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name"
|
||||
name: "Name",
|
||||
format: "string"
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
@@ -99,7 +100,7 @@ define([
|
||||
};
|
||||
|
||||
GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) {
|
||||
return _.extend(
|
||||
return Object.assign(
|
||||
{},
|
||||
domainObject.telemetry,
|
||||
METADATA_BY_TYPE[domainObject.type]
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"d3-time-format": "2.1.x",
|
||||
"eslint": "5.2.0",
|
||||
"eslint-plugin-vue": "^6.0.0",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0",
|
||||
"eventemitter3": "^1.2.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"express": "^4.13.1",
|
||||
@@ -48,7 +49,7 @@
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-webpack": "^3.0.0",
|
||||
"location-bar": "^3.0.1",
|
||||
"lodash": "^3.10.1",
|
||||
"lodash": "^4.17.12",
|
||||
"markdown-toc": "^0.11.7",
|
||||
"marked": "^0.3.5",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../../../../src/api/objects/object-utils'],
|
||||
['objectUtils'],
|
||||
function (objectUtils) {
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* @namespace platform/containment
|
||||
*/
|
||||
define(
|
||||
['../../../src/api/objects/object-utils'],
|
||||
['objectUtils'],
|
||||
function (objectUtils) {
|
||||
|
||||
function PersistableCompositionPolicy(openmct) {
|
||||
|
||||
@@ -81,7 +81,7 @@ define(
|
||||
baseContext = context || {};
|
||||
}
|
||||
|
||||
var actionContext = _.extend({}, baseContext);
|
||||
var actionContext = Object.assign({}, baseContext);
|
||||
actionContext.domainObject = this.domainObject;
|
||||
|
||||
return this.actionService.getActions(actionContext);
|
||||
|
||||
@@ -121,7 +121,7 @@ define(['lodash'], function (_) {
|
||||
*/
|
||||
ExportAsJSONAction.prototype.rewriteLink = function (child, parent) {
|
||||
this.externalIdentifiers.push(this.getId(child));
|
||||
var index = _.findIndex(parent.composition, function (id) {
|
||||
var index = parent.composition.findIndex(id => {
|
||||
return _.isEqual(child.identifier, id);
|
||||
});
|
||||
var copyOfChild = this.copyObject(child);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
define(['zepto', '../../../../src/api/objects/object-utils.js'], function ($, objectUtils) {
|
||||
define(['zepto', 'objectUtils'], function ($, objectUtils) {
|
||||
|
||||
/**
|
||||
* The ImportAsJSONAction is available from context menus and allows a user
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* Module defining GenericSearchProvider. Created by shale on 07/16/2015.
|
||||
*/
|
||||
define([
|
||||
'../../../../src/api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'lodash'
|
||||
], function (
|
||||
objectUtils,
|
||||
@@ -191,7 +191,7 @@ define([
|
||||
}
|
||||
|
||||
var domainObject = objectUtils.toNewFormat(model, id);
|
||||
var composition = _.find(this.openmct.composition.registry, function (p) {
|
||||
var composition = this.openmct.composition.registry.find(p => {
|
||||
return p.appliesTo(domainObject);
|
||||
});
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
define(
|
||||
[
|
||||
'../../../src/api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'lodash'
|
||||
],
|
||||
function (
|
||||
@@ -235,7 +235,7 @@ define(
|
||||
var defaultRange = metadata.valuesForHints(['range'])[0];
|
||||
defaultRange = defaultRange ? defaultRange.key : undefined;
|
||||
|
||||
var sourceMap = _.indexBy(metadata.values(), 'key');
|
||||
var sourceMap = _.keyBy(metadata.values(), 'key');
|
||||
|
||||
var isLegacyProvider = telemetryAPI.findRequestProvider(domainObject) ===
|
||||
telemetryAPI.legacyProvider;
|
||||
@@ -300,7 +300,7 @@ define(
|
||||
var defaultRange = metadata.valuesForHints(['range'])[0];
|
||||
defaultRange = defaultRange ? defaultRange.key : undefined;
|
||||
|
||||
var sourceMap = _.indexBy(metadata.values(), 'key');
|
||||
var sourceMap = _.keyBy(metadata.values(), 'key');
|
||||
|
||||
var isLegacyProvider = telemetryAPI.findSubscriptionProvider(domainObject) ===
|
||||
telemetryAPI.legacyProvider;
|
||||
|
||||
41
src/MCT.js
41
src/MCT.js
@@ -28,7 +28,7 @@ define([
|
||||
'./api/api',
|
||||
'./api/overlays/OverlayAPI',
|
||||
'./selection/Selection',
|
||||
'./api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'./plugins/plugins',
|
||||
'./adapter/indicators/legacy-indicators-plugin',
|
||||
'./plugins/buildInfo/plugin',
|
||||
@@ -249,7 +249,7 @@ define([
|
||||
this.legacyRegistry = new BundleRegistry();
|
||||
installDefaultBundles(this.legacyRegistry);
|
||||
|
||||
// Plugin's that are installed by default
|
||||
// Plugins that are installed by default
|
||||
|
||||
this.install(this.plugins.Plot());
|
||||
this.install(this.plugins.TelemetryTable());
|
||||
@@ -350,17 +350,13 @@ define([
|
||||
* @param {HTMLElement} [domElement] the DOM element in which to run
|
||||
* MCT; if undefined, MCT will be run in the body of the document
|
||||
*/
|
||||
MCT.prototype.start = function (domElement) {
|
||||
MCT.prototype.start = function (domElement = document.body, isHeadlessMode = false) {
|
||||
if (!this.plugins.DisplayLayout._installed) {
|
||||
this.install(this.plugins.DisplayLayout({
|
||||
showAsView: ['summary-widget']
|
||||
}));
|
||||
}
|
||||
|
||||
if (!domElement) {
|
||||
domElement = document.body;
|
||||
}
|
||||
|
||||
this.element = domElement;
|
||||
|
||||
this.legacyExtension('runs', {
|
||||
@@ -400,24 +396,31 @@ define([
|
||||
// something has depended upon objectService. Cool, right?
|
||||
this.$injector.get('objectService');
|
||||
|
||||
var appLayout = new Vue({
|
||||
components: {
|
||||
'Layout': Layout.default
|
||||
},
|
||||
provide: {
|
||||
openmct: this
|
||||
},
|
||||
template: '<Layout ref="layout"></Layout>'
|
||||
});
|
||||
domElement.appendChild(appLayout.$mount().$el);
|
||||
if (!isHeadlessMode) {
|
||||
var appLayout = new Vue({
|
||||
components: {
|
||||
'Layout': Layout.default
|
||||
},
|
||||
provide: {
|
||||
openmct: this
|
||||
},
|
||||
template: '<Layout ref="layout"></Layout>'
|
||||
});
|
||||
domElement.appendChild(appLayout.$mount().$el);
|
||||
|
||||
this.layout = appLayout.$refs.layout;
|
||||
Browse(this);
|
||||
this.layout = appLayout.$refs.layout;
|
||||
Browse(this);
|
||||
}
|
||||
this.router.start();
|
||||
this.emit('start');
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
MCT.prototype.startHeadless = function () {
|
||||
let unreachableNode = document.createElement('div');
|
||||
return this.start(unreachableNode, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a plugin in MCT.
|
||||
*
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'./MCT',
|
||||
'./plugins/plugins',
|
||||
'legacyRegistry'
|
||||
], function (MCT, plugins, legacyRegistry) {
|
||||
xdescribe("MCT", function () {
|
||||
'legacyRegistry',
|
||||
'testUtils'
|
||||
], function (plugins, legacyRegistry, testUtils) {
|
||||
describe("MCT", function () {
|
||||
var openmct;
|
||||
var mockPlugin;
|
||||
var mockPlugin2;
|
||||
@@ -38,7 +38,7 @@ define([
|
||||
mockListener = jasmine.createSpy('listener');
|
||||
oldBundles = legacyRegistry.list();
|
||||
|
||||
openmct = new MCT();
|
||||
openmct = testUtils.createOpenMct();
|
||||
|
||||
openmct.install(mockPlugin);
|
||||
openmct.install(mockPlugin2);
|
||||
@@ -63,8 +63,11 @@ define([
|
||||
});
|
||||
|
||||
describe("start", function () {
|
||||
beforeEach(function () {
|
||||
openmct.start();
|
||||
let appHolder;
|
||||
beforeEach(function (done) {
|
||||
appHolder = document.createElement("div");
|
||||
openmct.on('start', done);
|
||||
openmct.start(appHolder);
|
||||
});
|
||||
|
||||
it("calls plugins for configuration", function () {
|
||||
@@ -75,25 +78,51 @@ define([
|
||||
it("emits a start event", function () {
|
||||
expect(mockListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Renders the application into the provided container element", function () {
|
||||
let openMctShellElements = appHolder.querySelectorAll('div.l-shell');
|
||||
expect(openMctShellElements.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("startHeadless", function () {
|
||||
beforeEach(function (done) {
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
it("calls plugins for configuration", function () {
|
||||
expect(mockPlugin).toHaveBeenCalledWith(openmct);
|
||||
expect(mockPlugin2).toHaveBeenCalledWith(openmct);
|
||||
});
|
||||
|
||||
it("emits a start event", function () {
|
||||
expect(mockListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Does not render Open MCT", function () {
|
||||
let openMctShellElements = document.body.querySelectorAll('div.l-shell');
|
||||
expect(openMctShellElements.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setAssetPath", function () {
|
||||
var testAssetPath;
|
||||
|
||||
beforeEach(function () {
|
||||
testAssetPath = "some/path";
|
||||
openmct.legacyExtension = jasmine.createSpy('legacyExtension');
|
||||
openmct.setAssetPath(testAssetPath);
|
||||
});
|
||||
|
||||
it("internally configures the path for assets", function () {
|
||||
expect(openmct.legacyExtension).toHaveBeenCalledWith(
|
||||
'constants',
|
||||
{
|
||||
key: "ASSETS_PATH",
|
||||
value: testAssetPath
|
||||
}
|
||||
);
|
||||
it("configures the path for assets", function () {
|
||||
testAssetPath = "some/path/";
|
||||
openmct.setAssetPath(testAssetPath);
|
||||
expect(openmct.getAssetPath()).toBe(testAssetPath);
|
||||
});
|
||||
|
||||
it("adds a trailing /", function () {
|
||||
testAssetPath = "some/path";
|
||||
openmct.setAssetPath(testAssetPath);
|
||||
expect(openmct.getAssetPath()).toBe(testAssetPath + "/");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (objectUtils) {
|
||||
function ActionDialogDecorator(mct, actionService) {
|
||||
this.mct = mct;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(['../../api/objects/object-utils'], function (objectUtils) {
|
||||
define(['objectUtils'], function (objectUtils) {
|
||||
function AdapterCapability(domainObject) {
|
||||
this.domainObject = domainObject;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* Module defining AlternateCompositionCapability. Created by vwoeltje on 11/7/14.
|
||||
*/
|
||||
define([
|
||||
'../../api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'../../../platform/core/src/capabilities/ContextualDomainObject'
|
||||
], function (objectUtils, ContextualDomainObject) {
|
||||
function AlternateCompositionCapability($injector, domainObject) {
|
||||
|
||||
@@ -31,6 +31,7 @@ define([
|
||||
var capability = viewConstructor(domainObject);
|
||||
var oldInvoke = capability.invoke.bind(capability);
|
||||
|
||||
/* eslint-disable you-dont-need-lodash-underscore/map */
|
||||
capability.invoke = function () {
|
||||
var availableViews = oldInvoke();
|
||||
var newDomainObject = capability
|
||||
@@ -52,6 +53,8 @@ define([
|
||||
.map('view')
|
||||
.value();
|
||||
};
|
||||
/* eslint-enable you-dont-need-lodash-underscore/map */
|
||||
|
||||
return capability;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
define([
|
||||
'../capabilities/AlternateCompositionCapability',
|
||||
'../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
AlternateCompositionCapability,
|
||||
objectUtils
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
utils
|
||||
) {
|
||||
|
||||
@@ -78,7 +78,7 @@ define([
|
||||
};
|
||||
|
||||
TimeSettingsURLHandler.prototype.parseQueryParams = function () {
|
||||
var searchParams = _.pick(this.$location.search(), _.values(SEARCH));
|
||||
var searchParams = _.pick(this.$location.search(), Object.values(SEARCH));
|
||||
var parsedParams = {
|
||||
clock: searchParams[SEARCH.MODE],
|
||||
timeSystem: searchParams[SEARCH.TIME_SYSTEM]
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
utils
|
||||
) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
define([
|
||||
'./LegacyViewProvider',
|
||||
'./TypeInspectorViewProvider',
|
||||
'../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
LegacyViewProvider,
|
||||
TypeInspectorViewProvider,
|
||||
|
||||
@@ -70,7 +70,7 @@ define([
|
||||
* @memberof module:openmct.CompositionAPI#
|
||||
*/
|
||||
CompositionAPI.prototype.get = function (domainObject) {
|
||||
var provider = _.find(this.registry, function (p) {
|
||||
var provider = this.registry.find(p => {
|
||||
return p.appliesTo(domainObject);
|
||||
});
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ define([
|
||||
throw new Error('Event not supported by composition: ' + event);
|
||||
}
|
||||
|
||||
var index = _.findIndex(this.listeners[event], function (l) {
|
||||
var index = this.listeners[event].findIndex(l => {
|
||||
return l.callback === callback && l.context === context;
|
||||
});
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
define([
|
||||
'lodash',
|
||||
'../objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
_,
|
||||
objectUtils
|
||||
@@ -143,7 +143,7 @@ define([
|
||||
var keyString = objectUtils.makeKeyString(domainObject.identifier);
|
||||
var objectListeners = this.listeningTo[keyString];
|
||||
|
||||
var index = _.findIndex(objectListeners[event], function (l) {
|
||||
var index = objectListeners[event].findIndex(l => {
|
||||
return l.callback === callback && l.context === context;
|
||||
});
|
||||
|
||||
@@ -196,8 +196,8 @@ define([
|
||||
* @private
|
||||
*/
|
||||
DefaultCompositionProvider.prototype.includes = function (parent, childId) {
|
||||
return parent.composition.findIndex(composee =>
|
||||
this.publicAPI.objects.areIdsEqual(composee, childId)) !== -1;
|
||||
return parent.composition.some(composee =>
|
||||
this.publicAPI.objects.areIdsEqual(composee, childId));
|
||||
};
|
||||
|
||||
DefaultCompositionProvider.prototype.reorder = function (domainObject, oldIndex, newIndex) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'./object-utils.js',
|
||||
'objectUtils',
|
||||
'lodash'
|
||||
], function (
|
||||
utils,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
define([
|
||||
'lodash',
|
||||
'./object-utils',
|
||||
'objectUtils',
|
||||
'./MutableObject',
|
||||
'./RootRegistry',
|
||||
'./RootObjectProvider',
|
||||
|
||||
@@ -43,7 +43,7 @@ define([
|
||||
}
|
||||
|
||||
RootRegistry.prototype.addRoot = function (key) {
|
||||
if (isKey(key) || (_.isArray(key) && _.every(key, isKey))) {
|
||||
if (isKey(key) || (Array.isArray(key) && key.every(isKey))) {
|
||||
this.providers.push(function () {
|
||||
return key;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
define([
|
||||
'../object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
|
||||
@@ -85,9 +85,9 @@ define([
|
||||
value: +e.value
|
||||
};
|
||||
}), 'e.value');
|
||||
valueMetadata.values = _.pluck(valueMetadata.enumerations, 'value');
|
||||
valueMetadata.max = _.max(valueMetadata.values);
|
||||
valueMetadata.min = _.min(valueMetadata.values);
|
||||
valueMetadata.values = valueMetadata.enumerations.map(e => e.value);
|
||||
valueMetadata.max = Math.max(valueMetadata.values);
|
||||
valueMetadata.min = Math.min(valueMetadata.values);
|
||||
}
|
||||
|
||||
valueMetadatas.push(valueMetadata);
|
||||
@@ -103,7 +103,7 @@ define([
|
||||
var metadata = domainObject.telemetry || {};
|
||||
if (this.typeHasTelemetry(domainObject)) {
|
||||
var typeMetadata = this.typeService.getType(domainObject.type).typeDef.telemetry;
|
||||
_.extend(metadata, typeMetadata);
|
||||
Object.assign(metadata, typeMetadata);
|
||||
if (!metadata.values) {
|
||||
metadata.values = valueMetadatasFromOldFormat(metadata);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ define([
|
||||
'./TelemetryMetadataManager',
|
||||
'./TelemetryValueFormatter',
|
||||
'./DefaultMetadataProvider',
|
||||
'../objects/object-utils',
|
||||
'objectUtils',
|
||||
'lodash'
|
||||
], function (
|
||||
TelemetryMetadataManager,
|
||||
@@ -370,7 +370,7 @@ define([
|
||||
TelemetryAPI.prototype.commonValuesForHints = function (metadatas, hints) {
|
||||
var options = metadatas.map(function (metadata) {
|
||||
var values = metadata.valuesForHints(hints);
|
||||
return _.indexBy(values, 'key');
|
||||
return _.keyBy(values, 'key');
|
||||
}).reduce(function (a, b) {
|
||||
var results = {};
|
||||
Object.keys(a).forEach(function (key) {
|
||||
@@ -383,7 +383,7 @@ define([
|
||||
var sortKeys = hints.map(function (h) {
|
||||
return 'hints.' + h;
|
||||
});
|
||||
return _.sortByAll(options, sortKeys);
|
||||
return _.sortBy(options, sortKeys);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,13 +57,13 @@ define([
|
||||
|
||||
if (valueMetadata.format === 'enum') {
|
||||
if (!valueMetadata.values) {
|
||||
valueMetadata.values = _.pluck(valueMetadata.enumerations, 'value');
|
||||
valueMetadata.values = valueMetadata.enumerations.map(e => e.value);
|
||||
}
|
||||
if (!valueMetadata.hasOwnProperty('max')) {
|
||||
valueMetadata.max = _.max(valueMetadata.values) + 1;
|
||||
valueMetadata.max = Math.max(valueMetadata.values) + 1;
|
||||
}
|
||||
if (!valueMetadata.hasOwnProperty('min')) {
|
||||
valueMetadata.min = _.min(valueMetadata.values) - 1;
|
||||
valueMetadata.min = Math.min(valueMetadata.values) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ define([
|
||||
return metadata.hints[hint];
|
||||
}
|
||||
});
|
||||
return _.sortByAll(matchingMetadata, ...iteratees);
|
||||
return _.sortBy(matchingMetadata, ...iteratees);
|
||||
};
|
||||
|
||||
TelemetryMetadataManager.prototype.getFilterableValues = function () {
|
||||
|
||||
@@ -75,7 +75,7 @@ export default {
|
||||
this.items.push(item);
|
||||
},
|
||||
removeItem(identifier) {
|
||||
let index = _.findIndex(this.items, (item) => this.openmct.objects.makeKeyString(identifier) === item.key);
|
||||
let index = this.items.findIndex(item => this.openmct.objects.makeKeyString(identifier) === item.key);
|
||||
|
||||
this.items.splice(index, 1);
|
||||
},
|
||||
|
||||
@@ -102,7 +102,7 @@ export default {
|
||||
this.compositions.push({composition, addCallback, removeCallback});
|
||||
},
|
||||
removePrimary(identifier) {
|
||||
let index = _.findIndex(this.primaryTelemetryObjects, (primary) => this.openmct.objects.makeKeyString(identifier) === primary.key),
|
||||
let index = this.primaryTelemetryObjects.findIndex(primary => this.openmct.objects.makeKeyString(identifier) === primary.key),
|
||||
primary = this.primaryTelemetryObjects[index];
|
||||
|
||||
this.$set(this.secondaryTelemetryObjects, primary.key, undefined);
|
||||
@@ -130,7 +130,7 @@ export default {
|
||||
removeSecondary(primary) {
|
||||
return (identifier) => {
|
||||
let array = this.secondaryTelemetryObjects[primary.key],
|
||||
index = _.findIndex(array, (secondary) => this.openmct.objects.makeKeyString(identifier) === secondary.key);
|
||||
index = array.findIndex(secondary => this.openmct.objects.makeKeyString(identifier) === secondary.key);
|
||||
|
||||
array.splice(index, 1);
|
||||
|
||||
|
||||
@@ -70,15 +70,18 @@ export default class ConditionClass extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
this.criteria.forEach(criterion => {
|
||||
if (this.isAnyOrAllTelemetry(criterion)) {
|
||||
criterion.getResult(datum, this.conditionManager.telemetryObjects);
|
||||
} else {
|
||||
criterion.getResult(datum);
|
||||
}
|
||||
});
|
||||
if (this.isTelemetryUsed(datum.id)) {
|
||||
|
||||
this.result = evaluateResults(this.criteria.map(criterion => criterion.result), this.trigger);
|
||||
this.criteria.forEach(criterion => {
|
||||
if (this.isAnyOrAllTelemetry(criterion)) {
|
||||
criterion.getResult(datum, this.conditionManager.telemetryObjects);
|
||||
} else {
|
||||
criterion.getResult(datum);
|
||||
}
|
||||
});
|
||||
|
||||
this.result = evaluateResults(this.criteria.map(criterion => criterion.result), this.trigger);
|
||||
}
|
||||
}
|
||||
|
||||
isAnyOrAllTelemetry(criterion) {
|
||||
|
||||
@@ -47,17 +47,24 @@ describe("The condition", function () {
|
||||
name: "Test Object",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "some-key",
|
||||
name: "Some attribute",
|
||||
key: "value",
|
||||
name: "Value",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
}, {
|
||||
key: "some-other-key",
|
||||
name: "Another attribute",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
key: "testSource",
|
||||
source: "value",
|
||||
name: "Test",
|
||||
format: "string"
|
||||
}]
|
||||
}
|
||||
};
|
||||
@@ -136,4 +143,38 @@ describe("The condition", function () {
|
||||
expect(result).toBeTrue();
|
||||
expect(conditionObj.criteria.length).toEqual(0);
|
||||
});
|
||||
|
||||
it("gets the result of a condition when new telemetry data is received", function () {
|
||||
conditionObj.getResult({
|
||||
value: '0',
|
||||
utc: 'Hi',
|
||||
id: testTelemetryObject.identifier.key
|
||||
});
|
||||
expect(conditionObj.result).toBeTrue();
|
||||
});
|
||||
|
||||
it("gets the result of a condition when new telemetry data is received", function () {
|
||||
conditionObj.getResult({
|
||||
value: '1',
|
||||
utc: 'Hi',
|
||||
id: testTelemetryObject.identifier.key
|
||||
});
|
||||
expect(conditionObj.result).toBeFalse();
|
||||
});
|
||||
|
||||
it("keeps the old result new telemetry data is not used by it", function () {
|
||||
conditionObj.getResult({
|
||||
value: '0',
|
||||
utc: 'Hi',
|
||||
id: testTelemetryObject.identifier.key
|
||||
});
|
||||
expect(conditionObj.result).toBeTrue();
|
||||
|
||||
conditionObj.getResult({
|
||||
value: '1',
|
||||
utc: 'Hi',
|
||||
id: '1234'
|
||||
});
|
||||
expect(conditionObj.result).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -200,7 +200,7 @@ export default {
|
||||
this.$emit('telemetryUpdated', this.telemetryObjs);
|
||||
},
|
||||
removeTelemetryObject(identifier) {
|
||||
let index = _.findIndex(this.telemetryObjs, (obj) => {
|
||||
let index = this.telemetryObjs.findIndex(obj => {
|
||||
let objId = this.openmct.objects.makeKeyString(obj.identifier);
|
||||
let id = this.openmct.objects.makeKeyString(identifier);
|
||||
return objId === id;
|
||||
|
||||
@@ -108,6 +108,7 @@ import ConditionError from "@/plugins/condition/components/ConditionError.vue";
|
||||
import Vue from 'vue';
|
||||
import PreviewAction from "@/ui/preview/PreviewAction.js";
|
||||
import {getApplicableStylesForItem} from "@/plugins/condition/utils/styleUtils";
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
export default {
|
||||
name: 'ConditionalStylesView',
|
||||
@@ -288,7 +289,7 @@ export default {
|
||||
delete domainObjectStyles[this.itemId].conditionSetIdentifier;
|
||||
domainObjectStyles[this.itemId].styles = undefined;
|
||||
delete domainObjectStyles[this.itemId].styles;
|
||||
if (_.isEmpty(domainObjectStyles[this.itemId])) {
|
||||
if (isEmpty(domainObjectStyles[this.itemId])) {
|
||||
delete domainObjectStyles[this.itemId];
|
||||
}
|
||||
} else {
|
||||
@@ -299,7 +300,7 @@ export default {
|
||||
domainObjectStyles.styles = undefined;
|
||||
delete domainObjectStyles.styles;
|
||||
}
|
||||
if (_.isEmpty(domainObjectStyles)) {
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
|
||||
@@ -337,7 +338,7 @@ export default {
|
||||
delete domainObjectStyles[this.itemId];
|
||||
}
|
||||
});
|
||||
if (_.isEmpty(domainObjectStyles)) {
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
this.persist(domainObjectStyles);
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
import StyleEditor from "./StyleEditor.vue";
|
||||
import PreviewAction from "@/ui/preview/PreviewAction.js";
|
||||
import { getApplicableStylesForItem, getConsolidatedStyleValues, getConditionalStyleForItem } from "@/plugins/condition/utils/styleUtils";
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
export default {
|
||||
name: 'MultiSelectStylesView',
|
||||
@@ -178,7 +179,7 @@ export default {
|
||||
domainObjectStyles[itemId] = undefined;
|
||||
delete domainObjectStyles[this.itemId];
|
||||
|
||||
if (_.isEmpty(domainObjectStyles)) {
|
||||
if (isEmpty(domainObjectStyles)) {
|
||||
domainObjectStyles = undefined;
|
||||
}
|
||||
this.persist(this.domainObject, domainObjectStyles);
|
||||
@@ -239,7 +240,7 @@ export default {
|
||||
if (this.isStaticAndConditionalStyles) {
|
||||
this.removeConditionalStyles(domainObjectStyles, item.id);
|
||||
}
|
||||
if (_.isEmpty(itemStaticStyle)) {
|
||||
if (isEmpty(itemStaticStyle)) {
|
||||
itemStaticStyle = undefined;
|
||||
domainObjectStyles[item.id] = undefined;
|
||||
} else {
|
||||
|
||||
@@ -20,25 +20,21 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import { createOpenMct } from "testTools";
|
||||
import { createOpenMct } from "testUtils";
|
||||
import ConditionPlugin from "./plugin";
|
||||
|
||||
let openmct = createOpenMct();
|
||||
openmct.install(new ConditionPlugin());
|
||||
|
||||
let conditionSetDefinition;
|
||||
let mockConditionSetDomainObject;
|
||||
let element;
|
||||
let child;
|
||||
|
||||
describe('the plugin', function () {
|
||||
let conditionSetDefinition;
|
||||
let mockConditionSetDomainObject;
|
||||
let element;
|
||||
let child;
|
||||
let openmct;
|
||||
|
||||
beforeAll((done) => {
|
||||
openmct = createOpenMct();
|
||||
openmct.install(new ConditionPlugin());
|
||||
|
||||
conditionSetDefinition = openmct.types.get('conditionSet').definition;
|
||||
const appHolder = document.createElement('div');
|
||||
appHolder.style.width = '640px';
|
||||
appHolder.style.height = '480px';
|
||||
|
||||
element = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
@@ -55,7 +51,7 @@ describe('the plugin', function () {
|
||||
conditionSetDefinition.initialize(mockConditionSetDomainObject);
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.start(appHolder);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
let mockConditionSetObject = {
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
const convertToNumbers = (input) => {
|
||||
let numberInputs = [];
|
||||
input.forEach(inputValue => numberInputs.push(Number(inputValue)));
|
||||
@@ -257,7 +255,7 @@ export const OPERATIONS = [
|
||||
const lhsValue = input[0] !== undefined ? input[0].toString() : '';
|
||||
if (input[1]) {
|
||||
const values = input[1].split(',');
|
||||
return values.find((value) => lhsValue === _.trim(value.toString()));
|
||||
return values.find((value) => lhsValue === value.toString().trim());
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@@ -274,7 +272,7 @@ export const OPERATIONS = [
|
||||
const lhsValue = input[0] !== undefined ? input[0].toString() : '';
|
||||
if (input[1]) {
|
||||
const values = input[1].split(',');
|
||||
const found = values.find((value) => lhsValue === _.trim(value.toString()));
|
||||
const found = values.find((value) => lhsValue === value.toString().trim());
|
||||
return !found;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
const NONE_VALUE = '__no_value';
|
||||
|
||||
const styleProps = {
|
||||
@@ -154,7 +156,7 @@ export const getApplicableStylesForItem = (domainObject, item) => {
|
||||
};
|
||||
|
||||
export const getStylesWithoutNoneValue = (style) => {
|
||||
if (_.isEmpty(style) || !style) {
|
||||
if (isEmpty(style) || !style) {
|
||||
return;
|
||||
}
|
||||
let styleObj = {};
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
|
||||
<script>
|
||||
import uuid from 'uuid';
|
||||
|
||||
import SubobjectView from './SubobjectView.vue'
|
||||
import TelemetryView from './TelemetryView.vue'
|
||||
import BoxView from './BoxView.vue'
|
||||
@@ -76,6 +75,7 @@ import TextView from './TextView.vue'
|
||||
import LineView from './LineView.vue'
|
||||
import ImageView from './ImageView.vue'
|
||||
import EditMarquee from './EditMarquee.vue'
|
||||
import _ from 'lodash'
|
||||
|
||||
const ITEM_TYPE_VIEW_MAP = {
|
||||
'subobject-view': SubobjectView,
|
||||
@@ -512,7 +512,7 @@ export default {
|
||||
}
|
||||
},
|
||||
updateTelemetryFormat(item, format) {
|
||||
let index = _.findIndex(this.layoutItems, item);
|
||||
let index = this.layoutItems.findIndex(item);
|
||||
item.format = format;
|
||||
this.mutate(`configuration.items[${index}]`, item);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
<script>
|
||||
import LayoutDrag from './../LayoutDrag'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
<script>
|
||||
|
||||
import conditionalStylesMixin from "../mixins/objectStyles-mixin";
|
||||
import _ from 'lodash';
|
||||
|
||||
const START_HANDLE_QUADRANTS = {
|
||||
1: 'c-frame-edit__handle--sw',
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
import Layout from './components/DisplayLayout.vue'
|
||||
import Vue from 'vue'
|
||||
import objectUtils from '../../api/objects/object-utils.js'
|
||||
import objectUtils from 'objectUtils'
|
||||
import DisplayLayoutType from './DisplayLayoutType.js'
|
||||
import DisplayLayoutToolbar from './DisplayLayoutToolbar.js'
|
||||
import AlphaNumericFormatViewProvider from './AlphanumericFormatViewProvider.js'
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
<script>
|
||||
import FilterField from './FilterField.vue';
|
||||
import ToggleSwitch from '../../../ui/components/ToggleSwitch.vue';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
@@ -102,7 +103,7 @@ export default {
|
||||
hasActiveFilters() {
|
||||
// Should be true when the user has entered any filter values.
|
||||
return Object.values(this.persistedFilters).some(comparator => {
|
||||
return (typeof(comparator) === 'object' && !_.isEmpty(comparator));
|
||||
return (typeof(comparator) === 'object' && !isEmpty(comparator));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
|
||||
<script>
|
||||
import FilterObject from './FilterObject.vue';
|
||||
import GlobalFilters from './GlobalFilters.vue'
|
||||
import GlobalFilters from './GlobalFilters.vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
const FILTER_VIEW_TITLE = 'Filters applied';
|
||||
const FILTER_VIEW_TITLE_MIXED = 'Mixed filters applied';
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<script>
|
||||
import compositionLoader from './composition-loader';
|
||||
import ListItem from './ListItem.vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
components: {ListItem},
|
||||
|
||||
@@ -220,7 +220,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = _.sortedIndex(this.imageHistory, datum, this.timeFormat.format.bind(this.timeFormat));
|
||||
const index = _.sortedIndexBy(this.imageHistory, datum, this.timeFormat.format.bind(this.timeFormat));
|
||||
this.imageHistory.splice(index, 0, datum);
|
||||
},
|
||||
updateValues(datum) {
|
||||
|
||||
@@ -172,6 +172,7 @@ export default {
|
||||
&& this.embed.bounds.end !== bounds.end;
|
||||
const isFixedTimespanMode = !this.openmct.time.clock();
|
||||
|
||||
this.openmct.time.stopClock();
|
||||
window.location.href = link;
|
||||
|
||||
let message = '';
|
||||
|
||||
@@ -152,7 +152,7 @@ function (
|
||||
MCTChartController.prototype.destroy = function () {
|
||||
this.isDestroyed = true;
|
||||
this.stopListening();
|
||||
_.invoke(this.lines, 'destroy');
|
||||
this.lines.forEach(line => line.destroy());
|
||||
DrawLoader.releaseDrawAPI(this.drawAPI);
|
||||
};
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ define([
|
||||
this.initialize(options);
|
||||
}
|
||||
|
||||
_.extend(Collection.prototype, EventEmitter.prototype);
|
||||
Object.assign(Collection.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(Collection.prototype);
|
||||
|
||||
Collection.extend = extend;
|
||||
@@ -105,12 +105,7 @@ define([
|
||||
};
|
||||
|
||||
Collection.prototype.indexOf = function (model) {
|
||||
return _.findIndex(
|
||||
this.models,
|
||||
function (m) {
|
||||
return m === model;
|
||||
}
|
||||
);
|
||||
return this.models.findIndex(m => m === model);
|
||||
};
|
||||
|
||||
Collection.prototype.remove = function (model) {
|
||||
|
||||
@@ -49,7 +49,7 @@ define([
|
||||
this.initialize(options);
|
||||
}
|
||||
|
||||
_.extend(Model.prototype, EventEmitter.prototype);
|
||||
Object.assign(Model.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(Model.prototype);
|
||||
|
||||
Model.extend = extend;
|
||||
|
||||
@@ -146,7 +146,7 @@ define([
|
||||
strategy = 'minmax';
|
||||
}
|
||||
|
||||
options = _.extend({}, { size: 1000, strategy, filters: this.filters }, options || {});
|
||||
options = Object.assign({}, { size: 1000, strategy, filters: this.filters }, options || {});
|
||||
|
||||
if (!this.unsubscribe) {
|
||||
this.unsubscribe = this.openmct
|
||||
@@ -160,6 +160,7 @@ define([
|
||||
);
|
||||
}
|
||||
|
||||
/* eslint-disable you-dont-need-lodash-underscore/concat */
|
||||
return this.openmct
|
||||
.telemetry
|
||||
.request(this.domainObject, options)
|
||||
@@ -171,6 +172,7 @@ define([
|
||||
.value();
|
||||
this.reset(newPoints);
|
||||
}.bind(this));
|
||||
/* eslint-enable you-dont-need-lodash-underscore/concat */
|
||||
},
|
||||
/**
|
||||
* Update x formatter on x change.
|
||||
@@ -270,7 +272,7 @@ define([
|
||||
* @private
|
||||
*/
|
||||
sortedIndex: function (point) {
|
||||
return _.sortedIndex(this.data, point, this.getXVal);
|
||||
return _.sortedIndexBy(this.data, point, this.getXVal);
|
||||
},
|
||||
/**
|
||||
* Update min/max stats for the series.
|
||||
|
||||
@@ -101,11 +101,11 @@ define([
|
||||
var plotObject = this.plot.get('domainObject');
|
||||
if (plotObject.type === 'telemetry.plot.overlay') {
|
||||
|
||||
var persistedIndex = _.findIndex(plotObject.configuration.series, function (s) {
|
||||
var persistedIndex = plotObject.configuration.series.findIndex(s => {
|
||||
return _.isEqual(identifier, s.identifier);
|
||||
});
|
||||
|
||||
var configIndex = _.findIndex(this.models, function (m) {
|
||||
var configIndex = this.models.findIndex(m => {
|
||||
return _.isEqual(m.domainObject.identifier, identifier);
|
||||
});
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
_.extend(Draw2D.prototype, EventEmitter.prototype);
|
||||
Object.assign(Draw2D.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(Draw2D.prototype);
|
||||
|
||||
// Convert from logical to physical x coordinates
|
||||
|
||||
@@ -78,7 +78,7 @@ define([
|
||||
this.listenTo(this.canvas, "webglcontextlost", this.onContextLost, this);
|
||||
}
|
||||
|
||||
_.extend(DrawWebGL.prototype, EventEmitter.prototype);
|
||||
Object.assign(DrawWebGL.prototype, EventEmitter.prototype);
|
||||
eventHelpers.extend(DrawWebGL.prototype);
|
||||
|
||||
DrawWebGL.prototype.onContextLost = function (event) {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
define([
|
||||
'../configuration/configStore',
|
||||
'../lib/eventHelpers',
|
||||
'../../../../api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'lodash'
|
||||
], function (
|
||||
configStore,
|
||||
|
||||
@@ -31,7 +31,7 @@ define([
|
||||
function dynamicPathForKey(key) {
|
||||
return function (object, model) {
|
||||
var modelIdentifier = model.get('identifier');
|
||||
var index = _.findIndex(object.configuration.series, function (s) {
|
||||
var index = object.configuration.series.findIndex(s => {
|
||||
return _.isEqual(s.identifier, modelIdentifier);
|
||||
});
|
||||
return 'configuration.series[' + index + '].' + key;
|
||||
|
||||
@@ -73,10 +73,10 @@ define([
|
||||
if (range.max === '' || range.max === null || typeof range.max === 'undefined') {
|
||||
return 'Must specify Maximum';
|
||||
}
|
||||
if (_.isNaN(Number(range.min))) {
|
||||
if (Number.isNaN(Number(range.min))) {
|
||||
return 'Minimum must be a number.';
|
||||
}
|
||||
if (_.isNaN(Number(range.max))) {
|
||||
if (Number.isNaN(Number(range.max))) {
|
||||
return 'Maximum must be a number.';
|
||||
}
|
||||
if (Number(range.min) > Number(range.max)) {
|
||||
|
||||
@@ -325,7 +325,7 @@ define([
|
||||
} else {
|
||||
// A history entry is created by startMarquee, need to remove
|
||||
// if marquee zoom doesn't occur.
|
||||
this.back();
|
||||
this.plotHistory.pop();
|
||||
}
|
||||
this.$scope.rectangles = [];
|
||||
this.marquee = undefined;
|
||||
|
||||
@@ -76,7 +76,7 @@ define([
|
||||
if (childObj) {
|
||||
var index = telemetryObjects.indexOf(childObj);
|
||||
telemetryObjects.splice(index, 1);
|
||||
$scope.$broadcast('plot:tickWidth', _.max(tickWidthMap));
|
||||
$scope.$broadcast('plot:tickWidth', Math.max(...Object.values(tickWidthMap)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
define([
|
||||
'../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
define ([
|
||||
'./ConditionEvaluator',
|
||||
'../../../api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'EventEmitter',
|
||||
'zepto',
|
||||
'lodash'
|
||||
@@ -9,7 +9,8 @@ define ([
|
||||
objectUtils,
|
||||
EventEmitter,
|
||||
$,
|
||||
_
|
||||
_,
|
||||
|
||||
) {
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ define([
|
||||
'./TestDataManager',
|
||||
'./WidgetDnD',
|
||||
'./eventHelpers',
|
||||
'../../../api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'lodash',
|
||||
'zepto'
|
||||
], function (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
define([
|
||||
'./Select',
|
||||
'../../../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
Select,
|
||||
objectUtils
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
define([
|
||||
'./SummaryWidgetEvaluator',
|
||||
'../../../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
SummaryWidgetEvaluator,
|
||||
objectUtils
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
define([
|
||||
'./SummaryWidgetRule',
|
||||
'../eventHelpers',
|
||||
'../../../../api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'lodash'
|
||||
], function (
|
||||
SummaryWidgetRule,
|
||||
@@ -80,10 +80,12 @@ define([
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
/* eslint-disable you-dont-need-lodash-underscore/map */
|
||||
unsubscribes = _.map(
|
||||
realtimeStates,
|
||||
this.subscribeToObjectState.bind(this, updateCallback)
|
||||
);
|
||||
/* eslint-enable you-dont-need-lodash-underscore/map */
|
||||
}.bind(this));
|
||||
|
||||
return function () {
|
||||
@@ -151,11 +153,13 @@ define([
|
||||
SummaryWidgetEvaluator.prototype.getBaseStateClone = function () {
|
||||
return this.load()
|
||||
.then(function () {
|
||||
/* eslint-disable you-dont-need-lodash-underscore/values */
|
||||
return _(this.baseState)
|
||||
.values()
|
||||
.map(_.clone)
|
||||
.indexBy('id')
|
||||
.keyBy('id')
|
||||
.value();
|
||||
/* eslint-enable you-dont-need-lodash-underscore/values */
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
@@ -182,7 +186,7 @@ define([
|
||||
* @private.
|
||||
*/
|
||||
SummaryWidgetEvaluator.prototype.updateObjectStateFromLAD = function (options, objectState) {
|
||||
options = _.extend({}, options, {
|
||||
options = Object.assign({}, options, {
|
||||
strategy: 'latest',
|
||||
size: 1
|
||||
});
|
||||
@@ -255,10 +259,12 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-disable you-dont-need-lodash-underscore/map */
|
||||
var latestTimestamp = _(state)
|
||||
.map('timestamps')
|
||||
.sortBy(timestampKey)
|
||||
.last();
|
||||
/* eslint-enable you-dont-need-lodash-underscore/map */
|
||||
|
||||
if (!latestTimestamp) {
|
||||
latestTimestamp = {};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
define([
|
||||
'../SummaryWidget',
|
||||
'./SummaryWidgetView',
|
||||
'../../../../api/objects/object-utils'
|
||||
'objectUtils'
|
||||
], function (
|
||||
SummaryWidgetEditView,
|
||||
SummaryWidgetView,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
/*jshint latedef: nofunc */
|
||||
/*global console */
|
||||
define([
|
||||
'../../../api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'./TelemetryAverager'
|
||||
], function (objectUtils, TelemetryAverager) {
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../../api/objects/object-utils',
|
||||
'objectUtils',
|
||||
'./components/table-configuration.vue',
|
||||
'./TelemetryTableConfiguration',
|
||||
'vue'
|
||||
|
||||
@@ -100,7 +100,7 @@ define([
|
||||
|
||||
hasColumnWithKey(columnKey) {
|
||||
return _.flatten(Object.values(this.columns))
|
||||
.findIndex(column => column.getKey() === columnKey) !== -1;
|
||||
.some(column => column.getKey() === columnKey);
|
||||
}
|
||||
|
||||
getColumns() {
|
||||
@@ -109,9 +109,10 @@ define([
|
||||
|
||||
getAllHeaders() {
|
||||
let flattenedColumns = _.flatten(Object.values(this.columns));
|
||||
/* eslint-disable you-dont-need-lodash-underscore/uniq */
|
||||
let headers = _.uniq(flattenedColumns, false, column => column.getKey())
|
||||
.reduce(fromColumnsToHeadersMap, {});
|
||||
|
||||
/* eslint-enable you-dont-need-lodash-underscore/uniq */
|
||||
function fromColumnsToHeadersMap(headersMap, column) {
|
||||
headersMap[column.getKey()] = column.getTitle();
|
||||
return headersMap;
|
||||
|
||||
@@ -93,7 +93,7 @@ define(
|
||||
// same time stamp
|
||||
let potentialDupes = this.rows.slice(startIx, endIx + 1);
|
||||
// Search potential dupes for exact dupe
|
||||
isDuplicate = _.findIndex(potentialDupes, _.isEqual.bind(undefined, row)) > -1;
|
||||
isDuplicate = potentialDupes.some(_.isEqual.bind(undefined, row));
|
||||
}
|
||||
|
||||
if (!isDuplicate) {
|
||||
@@ -120,7 +120,7 @@ define(
|
||||
const firstValue = this.getValueForSortColumn(this.rows[0]);
|
||||
const lastValue = this.getValueForSortColumn(this.rows[this.rows.length - 1]);
|
||||
|
||||
lodashFunction = lodashFunction || _.sortedIndex;
|
||||
lodashFunction = lodashFunction || _.sortedIndexBy;
|
||||
|
||||
if (this.sortOptions.direction === 'asc') {
|
||||
if (testRowValue > lastValue) {
|
||||
@@ -201,7 +201,7 @@ define(
|
||||
sortBy(sortOptions) {
|
||||
if (arguments.length > 0) {
|
||||
this.sortOptions = sortOptions;
|
||||
this.rows = _.sortByOrder(this.rows, (row) => row.getParsedValue(sortOptions.key) , sortOptions.direction);
|
||||
this.rows = _.orderBy(this.rows, (row) => row.getParsedValue(sortOptions.key) , sortOptions.direction);
|
||||
this.emit('sort');
|
||||
}
|
||||
// Return duplicate to avoid direct modification of underlying object
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
|
||||
const FILTER_INDICATOR_LABEL = 'Filters:';
|
||||
const FILTER_INDICATOR_LABEL_MIXED = 'Mixed Filters:';
|
||||
const FILTER_INDICATOR_TITLE = 'Data filters are being applied to this view.';
|
||||
|
||||
@@ -24,34 +24,39 @@ import Vue from 'vue';
|
||||
import {
|
||||
createOpenMct,
|
||||
createMouseEvent
|
||||
} from 'testTools';
|
||||
|
||||
let openmct;
|
||||
let tablePlugin;
|
||||
let element;
|
||||
let child;
|
||||
} from 'testUtils';
|
||||
|
||||
describe("the plugin", () => {
|
||||
beforeEach((done) => {
|
||||
const appHolder = document.createElement('div');
|
||||
appHolder.style.width = '640px';
|
||||
appHolder.style.height = '480px';
|
||||
let openmct;
|
||||
let tablePlugin;
|
||||
let element;
|
||||
let child;
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
|
||||
// Table Plugin is actually installed by default, but because installing it
|
||||
// again is harmless it is left here as an examplar for non-default plugins.
|
||||
tablePlugin = new TablePlugin();
|
||||
openmct.install(tablePlugin);
|
||||
|
||||
element = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
element.appendChild(child);
|
||||
|
||||
tablePlugin = new TablePlugin();
|
||||
openmct.install(tablePlugin);
|
||||
|
||||
spyOn(openmct.telemetry, 'request').and.returnValue(Promise.resolve([]));
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.start(appHolder);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
describe("defines a table object", function () {
|
||||
it("that is creatable", () => {
|
||||
let tableType = openmct.types.get('table');
|
||||
expect(tableType.definition.creatable).toBe(true);
|
||||
});
|
||||
})
|
||||
|
||||
it("provides a table view for objects with telemetry", () => {
|
||||
const testTelemetryObject = {
|
||||
id:"test-object",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<span
|
||||
class="c-disclosure-triangle"
|
||||
:class="{
|
||||
'c-disclosure-triangle--expanded' : value,
|
||||
'is-enabled' : enabled
|
||||
}"
|
||||
:class="[
|
||||
controlClass,
|
||||
{ 'c-disclosure-triangle--expanded' : value },
|
||||
{'is-enabled' : enabled }
|
||||
]"
|
||||
@click="handleClick"
|
||||
></span>
|
||||
</template>
|
||||
@@ -25,6 +25,10 @@ export default {
|
||||
propagate: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
controlClass: {
|
||||
type: String,
|
||||
default: 'c-disclosure-triangle'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
class="l-browse-bar__context-actions c-disclosure-button"
|
||||
@click.prevent.stop="showContextMenu"
|
||||
></div>
|
||||
<div
|
||||
class="l-browse-sync-tree"
|
||||
@click="syncNavigationTree"
|
||||
>Sync</div>
|
||||
</div>
|
||||
|
||||
<div class="l-browse-bar__end">
|
||||
@@ -271,6 +275,9 @@ export default {
|
||||
},
|
||||
goToParent() {
|
||||
window.location.hash = this.parentUrl;
|
||||
},
|
||||
syncNavigationTree() {
|
||||
this.$emit('syncTreeNavigation');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
<script>
|
||||
import CreateAction from '../../../platform/commonUI/edit/src/creation/CreateAction';
|
||||
import objectUtils from '../../api/objects/object-utils';
|
||||
import objectUtils from 'objectUtils';
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
|
||||
@@ -47,12 +47,16 @@
|
||||
label="Browse"
|
||||
collapsable
|
||||
>
|
||||
<mct-tree class="l-shell__tree" />
|
||||
<mct-tree
|
||||
:sync-tree-navigation="triggerSync"
|
||||
class="l-shell__tree"
|
||||
/>
|
||||
</pane>
|
||||
<pane class="l-shell__pane-main">
|
||||
<browse-bar
|
||||
ref="browseBar"
|
||||
class="l-shell__main-view-browse-bar"
|
||||
@syncTreeNavigation="handleSyncTreeNavigation"
|
||||
/>
|
||||
<toolbar
|
||||
v-if="toolbar"
|
||||
@@ -154,7 +158,8 @@ export default {
|
||||
conductorComponent: undefined,
|
||||
isEditing: false,
|
||||
hasToolbar: false,
|
||||
headExpanded
|
||||
headExpanded,
|
||||
triggerSync: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -204,6 +209,9 @@ export default {
|
||||
}
|
||||
|
||||
this.hasToolbar = structure.length > 0;
|
||||
},
|
||||
handleSyncTreeNavigation() {
|
||||
this.triggerSync = !this.triggerSync;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
.c-tree-and-search {
|
||||
$hoverBg: rgba(#000, 0.1);
|
||||
$hoverFg: #ccc;
|
||||
$selected: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
//TODO: Do we need this???
|
||||
//padding-right: $interiorMarginSm;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
> * + * { margin-top: $interiorMargin; }
|
||||
|
||||
@@ -26,6 +30,105 @@
|
||||
height: 0; // Chrome 73 overflow bug fix
|
||||
padding-right: $interiorMarginSm;
|
||||
}
|
||||
|
||||
// new tree refactor
|
||||
.c-tree,
|
||||
.c-list {
|
||||
&__item {
|
||||
border-radius: 0;
|
||||
|
||||
&:hover {
|
||||
background: $hoverBg;
|
||||
|
||||
[class*="__name"] {
|
||||
color: darken($colorKeyFg, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-navigated-object,
|
||||
&.is-selected {
|
||||
background: none;
|
||||
|
||||
[class*="__name"] {
|
||||
color: $selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// new tree refactor
|
||||
.c-tree {
|
||||
flex: 1 1 auto;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
transition: all;
|
||||
|
||||
.c-tree {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&__item {
|
||||
border-bottom: 1px solid $colorInteriorBorder;
|
||||
|
||||
&.is-navigated-object,
|
||||
&.is-selected {
|
||||
.c-tree__item__type-icon:before {
|
||||
color: $selected;
|
||||
}
|
||||
}
|
||||
|
||||
.c-nav {
|
||||
$dimension: 20px;
|
||||
border-radius: 3px;
|
||||
|
||||
&__up, &__down {
|
||||
color: #fff;
|
||||
flex: 0 0 auto;
|
||||
height: $dimension;
|
||||
width: $dimension;
|
||||
opacity: 0;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
||||
&.is-enabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: darken($colorKeyFg, 10%);
|
||||
}
|
||||
|
||||
&:before {
|
||||
// Nav arrow
|
||||
$color: rgba(#999, 0.5);
|
||||
$dimension: 7px;
|
||||
$width: 3px;
|
||||
border: solid $color;
|
||||
border-width: $width;
|
||||
border-width: 0 $width $width 0;
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 50%; top: 50%;
|
||||
height: $dimension;
|
||||
width: $dimension;
|
||||
}
|
||||
|
||||
&:hover:before {
|
||||
border-color: $colorItemTreeHoverFg;
|
||||
}
|
||||
}
|
||||
|
||||
&__up:before {
|
||||
transform: translate(-30%, -50%) rotate(135deg);
|
||||
}
|
||||
|
||||
&__down:before {
|
||||
transform: translate(-70%, -50%) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.c-tree,
|
||||
@@ -72,8 +175,9 @@
|
||||
}
|
||||
|
||||
.c-tree {
|
||||
|
||||
.c-tree {
|
||||
margin-left: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
&__item {
|
||||
@@ -157,3 +261,32 @@
|
||||
padding: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
// TRANSITIONS
|
||||
.slide-left,
|
||||
.slide-right {
|
||||
animation-duration: 500ms;
|
||||
animation-iteration-count: 1;
|
||||
transition: all;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
|
||||
.slide-left {
|
||||
animation-name: animSlideLeft;
|
||||
}
|
||||
|
||||
.slide-right {
|
||||
animation-name: animSlideRight;
|
||||
}
|
||||
|
||||
@keyframes animSlideLeft {
|
||||
0% {opactiy: 0; transform: translateX(100%);}
|
||||
10% {opacity: 1;}
|
||||
100% {transform: translateX(0);}
|
||||
}
|
||||
|
||||
@keyframes animSlideRight {
|
||||
0% {opactiy: 0; transform: translateX(-100%);}
|
||||
10% {opacity: 1;}
|
||||
100% {transform: translateX(0);}
|
||||
}
|
||||
@@ -31,9 +31,11 @@
|
||||
class="c-tree-and-search__tree c-tree"
|
||||
>
|
||||
<tree-item
|
||||
v-for="treeItem in allTreeItems"
|
||||
:key="treeItem.id"
|
||||
:node="treeItem"
|
||||
v-for="item in allTreeItems"
|
||||
:key="item.id"
|
||||
:class="childrenSlideClass"
|
||||
:node="item"
|
||||
:sync-check="checkForSync"
|
||||
/>
|
||||
</ul>
|
||||
<!-- end main tree -->
|
||||
@@ -44,9 +46,9 @@
|
||||
class="c-tree-and-search__tree c-tree"
|
||||
>
|
||||
<tree-item
|
||||
v-for="treeItem in filteredTreeItems"
|
||||
:key="treeItem.id"
|
||||
:node="treeItem"
|
||||
v-for="item in filteredTreeItems"
|
||||
:key="item.id"
|
||||
:node="item"
|
||||
/>
|
||||
</ul>
|
||||
<!-- end search tree -->
|
||||
@@ -64,26 +66,43 @@ export default {
|
||||
search,
|
||||
treeItem
|
||||
},
|
||||
props: {
|
||||
syncTreeNavigation: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchValue: '',
|
||||
allTreeItems: [],
|
||||
filteredTreeItems: [],
|
||||
isLoading: false
|
||||
isLoading: false,
|
||||
childrenSlideClass: 'slide-left',
|
||||
checkForSync: this.makeHash()
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
syncTreeNavigation() {
|
||||
console.log('sync in mct-tree');
|
||||
this.checkForSync = this.makeHash();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.searchService = this.openmct.$injector.get('searchService');
|
||||
this.getAllChildren();
|
||||
console.log('tree: mounted');
|
||||
},
|
||||
methods: {
|
||||
getAllChildren() {
|
||||
this.isLoading = true;
|
||||
this.openmct.objects.get('ROOT')
|
||||
.then(root => {
|
||||
console.log('tree: root', root);
|
||||
return this.openmct.composition.get(root).load()
|
||||
})
|
||||
.then(children => {
|
||||
console.log('tree: children', children);
|
||||
this.isLoading = false;
|
||||
this.allTreeItems = children.map(c => {
|
||||
return {
|
||||
@@ -128,6 +147,14 @@ export default {
|
||||
if (this.searchValue !== '') {
|
||||
this.getFilteredChildren();
|
||||
}
|
||||
},
|
||||
makeHash(length = 20) {
|
||||
let hash = '',
|
||||
characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
for (let i = 0; i < length; i++) {
|
||||
hash += characters.charAt(Math.floor(Math.random() * characters.length)) + Date.now();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,26 @@
|
||||
<div
|
||||
class="c-tree__item"
|
||||
:class="{ 'is-alias': isAlias, 'is-navigated-object': navigated }"
|
||||
:style="{ paddingLeft: ancestors * 10 + 10 + 'px' }"
|
||||
>
|
||||
<view-control
|
||||
v-model="expanded"
|
||||
class="c-tree__item__view-control"
|
||||
:enabled="hasChildren"
|
||||
:enabled="hasChildren && activeChild !== undefined"
|
||||
:control-class="'c-nav__up'"
|
||||
@input="resetTreeHere"
|
||||
/>
|
||||
<object-label
|
||||
:domain-object="node.object"
|
||||
:object-path="node.objectPath"
|
||||
:navigate-to-path="navigateToPath"
|
||||
/>
|
||||
<view-control
|
||||
v-model="expanded"
|
||||
class="c-tree__item__view-control"
|
||||
:control-class="'c-nav__down'"
|
||||
:enabled="hasChildren && !activeChild && !expanded"
|
||||
/>
|
||||
</div>
|
||||
<ul
|
||||
v-if="expanded"
|
||||
@@ -27,11 +36,21 @@
|
||||
<span class="c-tree__item__label">Loading...</span>
|
||||
</div>
|
||||
</li>
|
||||
<tree-item
|
||||
<template
|
||||
v-for="child in children"
|
||||
:key="child.id"
|
||||
:node="child"
|
||||
/>
|
||||
>
|
||||
<tree-item
|
||||
v-if="activeChild && child.id === activeChild || !activeChild"
|
||||
:key="child.id"
|
||||
:class="{[childrenSlideClass] : child.id !== activeChild}"
|
||||
:node="child"
|
||||
:collapse-children="collapseMyChildren"
|
||||
:ancestors="ancestors + 1"
|
||||
:sync-check="triggerChildSync"
|
||||
@expanded="handleExpanded"
|
||||
@childState="handleChildState"
|
||||
/>
|
||||
</template>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
@@ -41,6 +60,12 @@ import viewControl from '../components/viewControl.vue';
|
||||
import ObjectLabel from '../components/ObjectLabel.vue';
|
||||
|
||||
const LOCAL_STORAGE_KEY__TREE_EXPANDED = 'mct-tree-expanded';
|
||||
const SLIDE_RIGHT = 'slide-right';
|
||||
const SLIDE_LEFT = 'slide-left';
|
||||
|
||||
function copyItem(item) {
|
||||
return JSON.parse(JSON.stringify(item));
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'TreeItem',
|
||||
@@ -53,6 +78,18 @@ export default {
|
||||
node: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
ancestors: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
collapseChildren: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
syncCheck: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -63,7 +100,14 @@ export default {
|
||||
loaded: false,
|
||||
navigated: this.navigateToPath === this.openmct.router.currentLocation.path,
|
||||
children: [],
|
||||
expanded: false
|
||||
expanded: false,
|
||||
activeChild: undefined,
|
||||
collapseMyChildren: '',
|
||||
childrenSlideClass: SLIDE_LEFT,
|
||||
triggerChildSync: '',
|
||||
onChildrenLoaded: [],
|
||||
mountedChildren: [],
|
||||
onChildMounted: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -81,23 +125,77 @@ export default {
|
||||
if (!this.hasChildren) {
|
||||
return;
|
||||
}
|
||||
if (!this.loaded && !this.isLoading) {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addChild);
|
||||
this.composition.on('remove', this.removeChild);
|
||||
this.composition.load().then(this.finishLoading);
|
||||
this.isLoading = true;
|
||||
if(this.expanded) {
|
||||
this.$emit('expanded', this.domainObject);
|
||||
this.loadChildren();
|
||||
}
|
||||
this.setLocalStorageExpanded(this.navigateToPath);
|
||||
},
|
||||
collapseChildren() {
|
||||
if(this.collapseChildren) {
|
||||
this.expanded = false;
|
||||
this.activeChild = undefined;
|
||||
this.loaded = false;
|
||||
this.children = [];
|
||||
}
|
||||
},
|
||||
syncCheck() {
|
||||
let currentLocationPath = this.openmct.router.currentLocation.path;
|
||||
if(currentLocationPath) {
|
||||
let isAncestor = currentLocationPath.includes(this.navigateToPath);
|
||||
|
||||
// not the currently navigated object, but it is an ancestor
|
||||
if(isAncestor && !this.navigated) {
|
||||
let descendantPath = currentLocationPath.split(this.navigateToPath + '/')[1],
|
||||
descendants = descendantPath.split('/'),
|
||||
descendantCount = descendants.length,
|
||||
immediateDescendant = descendants[0];
|
||||
|
||||
this.activeChild = undefined;
|
||||
|
||||
if(descendantCount > 1) {
|
||||
this.activeChild = immediateDescendant;
|
||||
}
|
||||
|
||||
// if current path is not expanded, need to expand (load children) and trigger sync
|
||||
if(!this.expanded) {
|
||||
if(descendantCount > 1) {
|
||||
this.onChildrenLoaded.push(() => {
|
||||
this.triggerChildrenSyncCheck()
|
||||
});
|
||||
}
|
||||
this.expanded = true;
|
||||
|
||||
// if current path IS expanded, then we need to check that child is mounted
|
||||
// as it could have been unmounted previously if it was not the activeChild
|
||||
} else {
|
||||
let alreadyMounted = this.mountedChildren.includes(immediateDescendant);
|
||||
if(alreadyMounted) {
|
||||
this.triggerChildrenSyncCheck()
|
||||
} else {
|
||||
this.onChildMounted.push({
|
||||
child: immediateDescendant,
|
||||
callback: () => {
|
||||
this.triggerChildrenSyncCheck()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.expanded = false;
|
||||
this.activeChild = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// TODO: should update on mutation.
|
||||
// TODO: click navigation should not fubar hash quite so much.
|
||||
// TODO: should highlight if navigated to.
|
||||
// TODO: should have context menu.
|
||||
// TODO: should support drag/drop composition
|
||||
// TODO: set isAlias per tree-item
|
||||
let objectComposition = this.openmct.composition.get(this.node.object);
|
||||
|
||||
this.$emit('childState', {
|
||||
type: 'mounted',
|
||||
id: this.openmct.objects.makeKeyString(this.node.object.identifier),
|
||||
name: this.node.object.name
|
||||
});
|
||||
|
||||
this.domainObject = this.node.object;
|
||||
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
|
||||
@@ -105,7 +203,7 @@ export default {
|
||||
});
|
||||
|
||||
this.$once('hook:destroyed', removeListener);
|
||||
if (this.openmct.composition.get(this.node.object)) {
|
||||
if (objectComposition && objectComposition.domainObject.composition.length > 0) {
|
||||
this.hasChildren = true;
|
||||
}
|
||||
|
||||
@@ -121,8 +219,14 @@ export default {
|
||||
*****/
|
||||
this.expanded = false;
|
||||
this.setLocalStorageExpanded();
|
||||
this.activeChild = undefined;
|
||||
},
|
||||
destroyed() {
|
||||
this.$emit('childState', {
|
||||
type: 'destroyed',
|
||||
id: this.openmct.objects.makeKeyString(this.domainObject.identifier),
|
||||
name: this.domainObject.name
|
||||
});
|
||||
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
||||
if (this.composition) {
|
||||
this.composition.off('add', this.addChild);
|
||||
@@ -144,9 +248,26 @@ export default {
|
||||
this.children = this.children
|
||||
.filter(c => c.id !== removeId);
|
||||
},
|
||||
loadChildren() {
|
||||
if (!this.loaded && !this.isLoading) {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addChild);
|
||||
this.composition.on('remove', this.removeChild);
|
||||
this.composition.load().then(this.finishLoading);
|
||||
this.isLoading = true;
|
||||
}
|
||||
},
|
||||
finishLoading() {
|
||||
this.isLoading = false;
|
||||
this.loaded = true;
|
||||
// specifically for sync child loading
|
||||
for(let callback of this.onChildrenLoaded) {
|
||||
callback();
|
||||
}
|
||||
this.onChildrenLoaded = [];
|
||||
},
|
||||
triggerChildrenSyncCheck() {
|
||||
this.triggerChildSync = this.makeHash();
|
||||
},
|
||||
buildPathString(parentPath) {
|
||||
return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/');
|
||||
@@ -160,7 +281,6 @@ export default {
|
||||
},
|
||||
getLocalStorageExpanded() {
|
||||
let expandedPaths = localStorage.getItem(LOCAL_STORAGE_KEY__TREE_EXPANDED);
|
||||
|
||||
if (expandedPaths) {
|
||||
expandedPaths = JSON.parse(expandedPaths);
|
||||
this.expanded = expandedPaths.includes(this.navigateToPath);
|
||||
@@ -170,7 +290,6 @@ export default {
|
||||
setLocalStorageExpanded() {
|
||||
let expandedPaths = localStorage.getItem(LOCAL_STORAGE_KEY__TREE_EXPANDED);
|
||||
expandedPaths = expandedPaths ? JSON.parse(expandedPaths) : [];
|
||||
|
||||
if (this.expanded) {
|
||||
if (!expandedPaths.includes(this.navigateToPath)) {
|
||||
expandedPaths.push(this.navigateToPath);
|
||||
@@ -187,6 +306,39 @@ export default {
|
||||
expandedPaths = expandedPaths ? JSON.parse(expandedPaths) : [];
|
||||
expandedPaths = expandedPaths.filter(path => !path.startsWith(this.navigateToPath));
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY__TREE_EXPANDED, JSON.stringify(expandedPaths));
|
||||
},
|
||||
handleExpanded(expandedObject) {
|
||||
this.activeChild = this.openmct.objects.makeKeyString(expandedObject.identifier);
|
||||
this.childrenSlideClass = SLIDE_LEFT;
|
||||
},
|
||||
handleChildState(opts) {
|
||||
if(opts.type === 'mounted') {
|
||||
this.mountedChildren.push(opts.id);
|
||||
if(this.onChildMounted.length && this.onChildMounted[0].child === opts.id) {
|
||||
this.onChildMounted[0].callback();
|
||||
this.onChildMounted = [];
|
||||
}
|
||||
} else {
|
||||
if(this.mountedChildren.includes(opts.id)) {
|
||||
let removeIndex = this.mountedChildren.indexOf(opts.id);
|
||||
this.mountedChildren.splice(removeIndex, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
resetTreeHere() {
|
||||
this.childrenSlideClass = SLIDE_RIGHT;
|
||||
this.activeChild = undefined;
|
||||
this.collapseMyChildren = this.makeHash();
|
||||
this.expanded = true;
|
||||
},
|
||||
makeHash(length = 20) {
|
||||
let hash = String(Date.now()),
|
||||
characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
length -= hash.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
hash += characters.charAt(Math.floor(Math.random() * characters.length));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
|
||||
<script>
|
||||
import PreviewHeader from './preview-header.vue';
|
||||
import {STYLE_CONSTANTS} from "@/plugins/condition/utils/constants";
|
||||
import StyleRuleManager from "@/plugins/condition/StyleRuleManager";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -69,6 +71,14 @@ export default {
|
||||
},
|
||||
destroyed() {
|
||||
this.view.destroy();
|
||||
if (this.stopListeningStyles) {
|
||||
this.stopListeningStyles();
|
||||
}
|
||||
|
||||
if (this.styleRuleManager) {
|
||||
this.styleRuleManager.destroy();
|
||||
delete this.styleRuleManager;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clear() {
|
||||
@@ -90,6 +100,46 @@ export default {
|
||||
|
||||
this.view = this.currentView.view(this.domainObject, this.objectPath);
|
||||
this.view.show(this.viewContainer, false);
|
||||
this.initObjectStyles();
|
||||
},
|
||||
initObjectStyles() {
|
||||
if (!this.styleRuleManager) {
|
||||
this.styleRuleManager = new StyleRuleManager((this.domainObject.configuration && this.domainObject.configuration.objectStyles), this.openmct, this.updateStyle.bind(this));
|
||||
} else {
|
||||
this.styleRuleManager.updateObjectStyleConfig(this.domainObject.configuration && this.domainObject.configuration.objectStyles);
|
||||
}
|
||||
|
||||
if (this.stopListeningStyles) {
|
||||
this.stopListeningStyles();
|
||||
}
|
||||
|
||||
this.stopListeningStyles = this.openmct.objects.observe(this.domainObject, 'configuration.objectStyles', (newObjectStyle) => {
|
||||
//Updating styles in the inspector view will trigger this so that the changes are reflected immediately
|
||||
this.styleRuleManager.updateObjectStyleConfig(newObjectStyle);
|
||||
});
|
||||
},
|
||||
updateStyle(styleObj) {
|
||||
if (!styleObj) {
|
||||
return;
|
||||
}
|
||||
let keys = Object.keys(styleObj);
|
||||
keys.forEach(key => {
|
||||
let firstChild = this.$refs.objectView.querySelector(':first-child');
|
||||
if (firstChild) {
|
||||
if ((typeof styleObj[key] === 'string') && (styleObj[key].indexOf('__no_value') > -1)) {
|
||||
if (firstChild.style[key]) {
|
||||
firstChild.style[key] = '';
|
||||
}
|
||||
} else {
|
||||
if (!styleObj.isStyleInvisible && firstChild.classList.contains(STYLE_CONSTANTS.isStyleInvisible)) {
|
||||
firstChild.classList.remove(STYLE_CONSTANTS.isStyleInvisible);
|
||||
} else if (styleObj.isStyleInvisible && !firstChild.classList.contains(styleObj.isStyleInvisible)) {
|
||||
firstChild.classList.add(styleObj.isStyleInvisible);
|
||||
}
|
||||
firstChild.style[key] = styleObj[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ const webpackConfig = {
|
||||
"printj": path.join(__dirname, "node_modules/printj/dist/printj.min.js"),
|
||||
"styles": path.join(__dirname, "src/styles"),
|
||||
"MCT": path.join(__dirname, "src/MCT"),
|
||||
"testTools": path.join(__dirname, "src/testTools.js")
|
||||
"testUtils": path.join(__dirname, "src/testUtils.js"),
|
||||
"objectUtils": path.join(__dirname, "src/api/objects/object-utils.js")
|
||||
}
|
||||
},
|
||||
devtool: devMode ? 'eval-source-map' : 'source-map',
|
||||
|
||||
Reference in New Issue
Block a user