mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 10:44:21 +00:00
Compare commits
29 Commits
adding-uni
...
tests-fix
Author | SHA1 | Date | |
---|---|---|---|
ffa730bd7b | |||
904a3c62bc | |||
399b501351 | |||
b28b9c7b69 | |||
f40a4c493c | |||
3cd3f50890 | |||
3ad2933ba7 | |||
66fb2f1acd | |||
03d56afd09 | |||
46bfbc240b | |||
8f35af8edf | |||
1ad7d4faf3 | |||
9f2c146107 | |||
e904d5a771 | |||
0a3ce6dc91 | |||
a301607b7d | |||
f389da295a | |||
182dca2b91 | |||
7f596baf72 | |||
36cbda778e | |||
5e60455b91 | |||
e8846c7e65 | |||
e32f465f7a | |||
abc458cef4 | |||
b76d4b76cb | |||
5a4cba0226 | |||
f03bfdebb4 | |||
13ff0c368d | |||
b7d2402434 |
@ -11,12 +11,12 @@ jobs:
|
||||
name: Update npm
|
||||
command: 'sudo npm install -g npm@latest'
|
||||
- restore_cache:
|
||||
key: dependency-cache-13-{{ checksum "package.json" }}
|
||||
key: dependency-cache-13-test-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: Installing dependencies (npm install)
|
||||
command: npm install
|
||||
- save_cache:
|
||||
key: dependency-cache-13-{{ checksum "package.json" }}
|
||||
key: dependency-cache-13-test-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- node_modules
|
||||
- run:
|
||||
|
@ -41,6 +41,7 @@ define([
|
||||
{
|
||||
key: "sin",
|
||||
name: "Sine",
|
||||
unit: "Hz",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 1
|
||||
@ -49,6 +50,7 @@ define([
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
unit: "deg",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 2
|
||||
|
3
indexTest.js
Normal file
3
indexTest.js
Normal file
@ -0,0 +1,3 @@
|
||||
const testsContext = require.context('.', true, /\/(src|platform)\/.*Spec.js$/);
|
||||
|
||||
testsContext.keys().forEach(testsContext);
|
@ -23,7 +23,8 @@
|
||||
/*global module,process*/
|
||||
|
||||
const devMode = process.env.NODE_ENV !== 'production';
|
||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'FirefoxHeadless'];
|
||||
const debugMode = process.env.NODE_ENV === 'debug';
|
||||
const browsers = [debugMode ? 'ChromeDebugging' : 'ChromeHeadless'];
|
||||
const coverageEnabled = process.env.COVERAGE === 'true';
|
||||
const reporters = ['progress', 'html'];
|
||||
|
||||
@ -52,12 +53,18 @@ module.exports = (config) => {
|
||||
basePath: '',
|
||||
frameworks: ['jasmine'],
|
||||
files: [
|
||||
'platform/**/*Spec.js',
|
||||
'src/**/*Spec.js'
|
||||
'indexTest.js'
|
||||
],
|
||||
port: 9876,
|
||||
reporters: reporters,
|
||||
browsers: browsers,
|
||||
client: {
|
||||
jasmine: {
|
||||
failFast: true,
|
||||
random: false,
|
||||
timeoutInterval: 10000
|
||||
}
|
||||
},
|
||||
customLaunchers: {
|
||||
ChromeDebugging: {
|
||||
base: 'Chrome',
|
||||
@ -67,7 +74,7 @@ module.exports = (config) => {
|
||||
},
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
autoWatch: debugMode,
|
||||
// HTML test reporting.
|
||||
htmlReporter: {
|
||||
outputDir: "dist/reports/tests",
|
||||
@ -87,15 +94,16 @@ module.exports = (config) => {
|
||||
}
|
||||
},
|
||||
preprocessors: {
|
||||
'platform/**/*Spec.js': ['webpack', 'sourcemap'],
|
||||
'src/**/*Spec.js': ['webpack', 'sourcemap']
|
||||
'indexTest.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
stats: 'errors-only',
|
||||
logLevel: 'warn'
|
||||
},
|
||||
concurrency: 1,
|
||||
singleRun: true,
|
||||
browserNoActivityTimeout: 90000
|
||||
browserNoActivityTimeout: 90000,
|
||||
reportSlowerThan: 5000
|
||||
});
|
||||
}
|
||||
};
|
||||
|
20
package.json
20
package.json
@ -39,16 +39,16 @@
|
||||
"istanbul-instrumenter-loader": "^3.0.1",
|
||||
"jasmine-core": "^3.1.0",
|
||||
"jsdoc": "^3.3.2",
|
||||
"karma": "^2.0.3",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-firefox-launcher": "^1.3.0",
|
||||
"karma-cli": "^1.0.1",
|
||||
"karma-coverage": "^1.1.2",
|
||||
"karma-coverage-istanbul-reporter": "^2.1.1",
|
||||
"karma-html-reporter": "^0.2.7",
|
||||
"karma-jasmine": "^1.1.2",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-webpack": "^3.0.0",
|
||||
"karma": "5.1.1",
|
||||
"karma-chrome-launcher": "3.1.0",
|
||||
"karma-firefox-launcher": "1.3.0",
|
||||
"karma-cli": "2.0.0",
|
||||
"karma-coverage": "2.0.3",
|
||||
"karma-coverage-istanbul-reporter": "3.0.3",
|
||||
"karma-html-reporter": "0.2.7",
|
||||
"karma-jasmine": "3.3.1",
|
||||
"karma-sourcemap-loader": "0.3.7",
|
||||
"karma-webpack": "4.0.2",
|
||||
"location-bar": "^3.0.1",
|
||||
"lodash": "^4.17.12",
|
||||
"markdown-toc": "^0.11.7",
|
||||
|
@ -25,7 +25,7 @@ define(
|
||||
["../../src/services/TransactionService"],
|
||||
function (TransactionService) {
|
||||
|
||||
describe("The Transaction Service", function () {
|
||||
xdescribe("The Transaction Service", function () {
|
||||
var mockQ,
|
||||
mockLog,
|
||||
transactionService;
|
||||
@ -85,17 +85,22 @@ define(
|
||||
|
||||
it("commit calls all queued commit functions", function () {
|
||||
expect(transactionService.size()).toBe(3);
|
||||
transactionService.commit();
|
||||
onCommits.forEach(function (spy) {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
|
||||
return transactionService.commit().then(() => {
|
||||
onCommits.forEach(function (spy) {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("commit resets active state and clears queues", function () {
|
||||
transactionService.commit();
|
||||
expect(transactionService.isActive()).toBe(false);
|
||||
expect(transactionService.size()).toBe(0);
|
||||
expect(transactionService.size()).toBe(0);
|
||||
|
||||
return transactionService.commit().then(() => {
|
||||
expect(transactionService.isActive()).toBe(false);
|
||||
expect(transactionService.size()).toBe(0);
|
||||
expect(transactionService.size()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -27,7 +27,7 @@ define([
|
||||
"../../src/services/SearchAggregator"
|
||||
], function (SearchAggregator) {
|
||||
|
||||
describe("SearchAggregator", function () {
|
||||
xdescribe("SearchAggregator", function () {
|
||||
var $q,
|
||||
objectService,
|
||||
providers,
|
||||
|
@ -444,6 +444,7 @@ define([
|
||||
|
||||
MCT.prototype.destroy = function () {
|
||||
this.emit('destroy');
|
||||
this.router.destroy();
|
||||
};
|
||||
|
||||
MCT.prototype.plugins = plugins;
|
||||
|
@ -32,9 +32,9 @@ define([
|
||||
var mockListener;
|
||||
var oldBundles;
|
||||
|
||||
beforeAll(() => {
|
||||
testUtils.resetApplicationState();
|
||||
});
|
||||
// beforeAll(() => {
|
||||
// return testUtils.resetApplicationState();
|
||||
// });
|
||||
|
||||
beforeEach(function () {
|
||||
mockPlugin = jasmine.createSpy('plugin');
|
||||
@ -56,7 +56,8 @@ define([
|
||||
legacyRegistry.delete(bundle);
|
||||
}
|
||||
});
|
||||
testUtils.resetApplicationState(openmct);
|
||||
|
||||
return testUtils.resetApplicationState();
|
||||
});
|
||||
|
||||
it("exposes plugins", function () {
|
||||
|
@ -32,6 +32,12 @@
|
||||
class="js-third-data"
|
||||
:class="valueClass"
|
||||
>{{ value }}</td>
|
||||
<td
|
||||
v-if="hasUnits"
|
||||
class="js-units"
|
||||
>
|
||||
{{ unit }}
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
@ -48,6 +54,10 @@ export default {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
hasUnits: {
|
||||
type: Boolean,
|
||||
requred: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -59,7 +69,8 @@ export default {
|
||||
timestamp: undefined,
|
||||
value: '---',
|
||||
valueClass: '',
|
||||
currentObjectPath
|
||||
currentObjectPath,
|
||||
unit: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -101,6 +112,10 @@ export default {
|
||||
.subscribe(this.domainObject, this.updateValues);
|
||||
|
||||
this.requestHistory();
|
||||
|
||||
if (this.hasUnits) {
|
||||
this.setUnit();
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.stopWatchingMutation();
|
||||
@ -186,6 +201,9 @@ export default {
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
setUnit() {
|
||||
this.unit = this.valueMetadata.unit || '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -28,6 +28,7 @@
|
||||
<th>Name</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Value</th>
|
||||
<th v-if="hasUnits">Unit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -35,6 +36,7 @@
|
||||
v-for="item in items"
|
||||
:key="item.key"
|
||||
:domain-object="item.domainObject"
|
||||
:has-units="hasUnits"
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -54,6 +56,18 @@ export default {
|
||||
items: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasUnits() {
|
||||
let itemsWithUnits = this.items.filter((item) => {
|
||||
let metadata = this.openmct.telemetry.getMetadata(item.domainObject);
|
||||
|
||||
return this.metadataHasUnits(metadata.valueMetadatas);
|
||||
|
||||
});
|
||||
|
||||
return itemsWithUnits.length !== 0;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addItem);
|
||||
@ -84,6 +98,11 @@ export default {
|
||||
reorderPlan.forEach((reorderEvent) => {
|
||||
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
|
||||
});
|
||||
},
|
||||
metadataHasUnits(valueMetadatas) {
|
||||
let metadataWithUnits = valueMetadatas.filter(metadatum => metadatum.unit);
|
||||
|
||||
return metadataWithUnits.length > 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -27,6 +27,7 @@
|
||||
<th>Name</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Value</th>
|
||||
<th v-if="hasUnits">Unit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -45,6 +46,7 @@
|
||||
v-for="secondary in secondaryTelemetryObjects[primary.key]"
|
||||
:key="secondary.key"
|
||||
:domain-object="secondary.domainObject"
|
||||
:has-units="hasUnits"
|
||||
/>
|
||||
</template>
|
||||
</tbody>
|
||||
@ -66,6 +68,23 @@ export default {
|
||||
compositions: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasUnits() {
|
||||
let ladTables = Object.values(this.secondaryTelemetryObjects);
|
||||
for (let ladTable of ladTables) {
|
||||
for (let telemetryObject of ladTable) {
|
||||
let metadata = this.openmct.telemetry.getMetadata(telemetryObject.domainObject);
|
||||
for (let metadatum of metadata.valueMetadatas) {
|
||||
if (metadatum.unit) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
this.composition.on('add', this.addPrimary);
|
||||
@ -109,9 +128,8 @@ export default {
|
||||
let index = this.primaryTelemetryObjects.findIndex(primary => this.openmct.objects.makeKeyString(identifier) === primary.key),
|
||||
primary = this.primaryTelemetryObjects[index];
|
||||
|
||||
this.$set(this.secondaryTelemetryObjects, primary.key, undefined);
|
||||
this.$delete(this.secondaryTelemetryObjects, primary.key);
|
||||
this.primaryTelemetryObjects.splice(index, 1);
|
||||
primary = undefined;
|
||||
},
|
||||
reorderPrimary(reorderPlan) {
|
||||
let oldComposition = this.primaryTelemetryObjects.slice();
|
||||
|
@ -94,7 +94,7 @@ describe("The LAD Table", () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetApplicationState(openmct);
|
||||
return resetApplicationState();
|
||||
});
|
||||
|
||||
it("should provide a table view only for lad table objects", () => {
|
||||
@ -284,7 +284,7 @@ describe("The LAD Table Set", () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetApplicationState(openmct);
|
||||
return resetApplicationState();
|
||||
});
|
||||
|
||||
it("should provide a lad table set view only for lad table set objects", () => {
|
||||
|
@ -35,7 +35,7 @@ define(
|
||||
) {
|
||||
var defaultAjaxFunction = $.ajax;
|
||||
|
||||
xdescribe("The URLIndicator", function () {
|
||||
describe("The URLIndicator", function () {
|
||||
var openmct;
|
||||
var indicatorElement;
|
||||
var pluginOptions;
|
||||
|
@ -66,7 +66,7 @@ export default class URLTimeSettingsSynchronizer {
|
||||
TIME_EVENTS.forEach(event => {
|
||||
this.openmct.time.off(event, this.setUrlFromTimeApi);
|
||||
});
|
||||
this.openmct.time.on('bounds', this.updateBounds);
|
||||
this.openmct.time.off('bounds', this.updateBounds);
|
||||
}
|
||||
|
||||
updateTimeSettings() {
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
describe("The URLTimeSettingsSynchronizer", () => {
|
||||
let openmct;
|
||||
let testClock;
|
||||
beforeAll(() => resetApplicationState());
|
||||
// beforeAll(() => resetApplicationState());
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
@ -42,7 +42,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
afterEach(() => resetApplicationState(openmct));
|
||||
afterEach(() => resetApplicationState());
|
||||
|
||||
describe("realtime mode", () => {
|
||||
it("when the clock is set via the time API, it is immediately reflected in the URL", () => {
|
||||
|
@ -27,7 +27,7 @@ define([
|
||||
'zepto',
|
||||
'./dom-observer'
|
||||
], function (AutoflowTabularPlugin, AutoflowTabularConstants, MCT, $, DOMObserver) {
|
||||
xdescribe("AutoflowTabularPlugin", function () {
|
||||
describe("AutoflowTabularPlugin", function () {
|
||||
var testType;
|
||||
var testObject;
|
||||
var mockmct;
|
||||
|
@ -36,9 +36,9 @@ describe('the plugin', function () {
|
||||
let openmct;
|
||||
let testTelemetryObject;
|
||||
|
||||
beforeAll(() => {
|
||||
resetApplicationState(openmct);
|
||||
});
|
||||
// beforeAll(() => {
|
||||
// return resetApplicationState();
|
||||
// });
|
||||
|
||||
beforeEach((done) => {
|
||||
testTelemetryObject = {
|
||||
@ -98,7 +98,7 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetApplicationState(openmct);
|
||||
return resetApplicationState();
|
||||
});
|
||||
|
||||
let mockConditionSetObject = {
|
||||
@ -422,7 +422,7 @@ describe('the plugin', function () {
|
||||
"telemetry": "any",
|
||||
"operation": "isStale",
|
||||
"input": [
|
||||
"1"
|
||||
"0.2"
|
||||
],
|
||||
"metadata": "dataReceived"
|
||||
}
|
||||
@ -462,7 +462,7 @@ describe('the plugin', function () {
|
||||
};
|
||||
});
|
||||
|
||||
it('should evaluate as stale when telemetry is not received in the allotted time', (done) => {
|
||||
xit('should evaluate as stale when telemetry is not received in the allotted time', (done) => {
|
||||
|
||||
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||
@ -481,12 +481,12 @@ describe('the plugin', function () {
|
||||
utc: undefined
|
||||
});
|
||||
done();
|
||||
}, 1500);
|
||||
}, 400);
|
||||
});
|
||||
|
||||
it('should not evaluate as stale when telemetry is received in the allotted time', (done) => {
|
||||
xit('should not evaluate as stale when telemetry is received in the allotted time', (done) => {
|
||||
const date = Date.now();
|
||||
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["2"];
|
||||
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["0.4"];
|
||||
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
|
||||
conditionMgr.on('conditionSetResultUpdated', mockListener);
|
||||
conditionMgr.telemetryObjects = {
|
||||
@ -507,7 +507,7 @@ describe('the plugin', function () {
|
||||
utc: undefined
|
||||
});
|
||||
done();
|
||||
}, 1500);
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -134,6 +134,14 @@ define(['lodash'], function (_) {
|
||||
return `configuration.items[${selectionPath[0].context.index}]`;
|
||||
}
|
||||
|
||||
function getAllOfType(selection, specificType) {
|
||||
return selection.filter(selectionPath => {
|
||||
let type = selectionPath[0].context.layoutItem.type;
|
||||
|
||||
return type === specificType;
|
||||
});
|
||||
}
|
||||
|
||||
function getAllTypes(selection) {
|
||||
return selection.filter(selectionPath => {
|
||||
let type = selectionPath[0].context.layoutItem.type;
|
||||
@ -510,6 +518,54 @@ define(['lodash'], function (_) {
|
||||
return allTelemetry;
|
||||
}
|
||||
|
||||
function getToggleUnitsButton(selectedParent, selection) {
|
||||
let applicableItems = getAllOfType(selection, 'telemetry-view');
|
||||
applicableItems = unitsOnly(applicableItems);
|
||||
if (!applicableItems.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
control: "toggle-button",
|
||||
domainObject: selectedParent,
|
||||
applicableSelectedItems: applicableItems,
|
||||
property: function (selectionPath) {
|
||||
return getPath(selectionPath) + '.showUnits';
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: true,
|
||||
icon: 'icon-eye-open',
|
||||
title: "Show units"
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
icon: 'icon-eye-disabled',
|
||||
title: "Hide units"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function unitsOnly(items) {
|
||||
let results = items.filter((item) => {
|
||||
let currentItem = item[0];
|
||||
let metadata = openmct.telemetry.getMetadata(currentItem.context.item);
|
||||
if (!metadata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let hasUnits = metadata
|
||||
.valueMetadatas
|
||||
.filter((metadatum) => metadatum.unit)
|
||||
.length;
|
||||
|
||||
return hasUnits > 0;
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function getViewSwitcherMenu(selectedParent, selectionPath, selection) {
|
||||
if (selection.length === 1) {
|
||||
let displayLayoutContext = selectionPath[1].context,
|
||||
@ -594,6 +650,7 @@ define(['lodash'], function (_) {
|
||||
'text-style': [],
|
||||
'position': [],
|
||||
'duplicate': [],
|
||||
'unit-toggle': [],
|
||||
'remove': []
|
||||
};
|
||||
|
||||
@ -663,6 +720,13 @@ define(['lodash'], function (_) {
|
||||
if (toolbar.viewSwitcher.length === 0) {
|
||||
toolbar.viewSwitcher = [getViewSwitcherMenu(selectedParent, selectionPath, selectedObjects)];
|
||||
}
|
||||
|
||||
if (toolbar['unit-toggle'].length === 0) {
|
||||
let toggleUnitsButton = getToggleUnitsButton(selectedParent, selectedObjects);
|
||||
if (toggleUnitsButton) {
|
||||
toolbar['unit-toggle'] = [toggleUnitsButton];
|
||||
}
|
||||
}
|
||||
} else if (layoutItem.type === 'text-view') {
|
||||
if (toolbar['text-style'].length === 0) {
|
||||
toolbar['text-style'] = [
|
||||
|
@ -58,6 +58,12 @@
|
||||
>
|
||||
<div class="c-telemetry-view__value-text">
|
||||
{{ telemetryValue }}
|
||||
<span
|
||||
v-if="unit && item.showUnits"
|
||||
class="c-telemetry-view__value-text__unit"
|
||||
>
|
||||
{{ unit }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -137,6 +143,12 @@ export default {
|
||||
|
||||
return displayMode === 'all' || displayMode === 'value';
|
||||
},
|
||||
unit() {
|
||||
let value = this.item.value,
|
||||
unit = this.metadata.value(value).unit;
|
||||
|
||||
return unit;
|
||||
},
|
||||
styleObject() {
|
||||
return Object.assign({}, {
|
||||
fontSize: this.item.size
|
||||
@ -257,7 +269,9 @@ export default {
|
||||
item: domainObject,
|
||||
layoutItem: this.item,
|
||||
index: this.index,
|
||||
updateTelemetryFormat: this.updateTelemetryFormat
|
||||
updateTelemetryFormat: this.updateTelemetryFormat,
|
||||
toggleUnits: this.toggleUnits,
|
||||
showUnits: this.showUnits
|
||||
};
|
||||
this.removeSelectable = this.openmct.selection.selectable(
|
||||
this.$el, this.context, this.immediatelySelect || this.initSelect);
|
||||
|
346
src/plugins/displayLayout/pluginSpec.js
Normal file
346
src/plugins/displayLayout/pluginSpec.js
Normal file
@ -0,0 +1,346 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2020, 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 { createOpenMct, resetApplicationState } from 'utils/testing';
|
||||
import DisplayLayoutPlugin from './plugin';
|
||||
|
||||
describe('the plugin', function () {
|
||||
let element;
|
||||
let child;
|
||||
let openmct;
|
||||
let displayLayoutDefinition;
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
openmct.install(new DisplayLayoutPlugin({
|
||||
showAsView: []
|
||||
}));
|
||||
displayLayoutDefinition = openmct.types.get('layout');
|
||||
|
||||
element = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
element.appendChild(child);
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
return resetApplicationState();
|
||||
});
|
||||
|
||||
it('defines a display layout object type with the correct key', () => {
|
||||
expect(displayLayoutDefinition.definition.name).toEqual('Display Layout');
|
||||
});
|
||||
|
||||
it('provides a view', () => {
|
||||
const testViewObject = {
|
||||
id: 'test-object',
|
||||
type: 'layout',
|
||||
configuration: {
|
||||
items: [
|
||||
{
|
||||
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||
},
|
||||
'x': 8,
|
||||
'y': 3,
|
||||
'width': 10,
|
||||
'height': 5,
|
||||
'displayMode': 'all',
|
||||
'value': 'sin',
|
||||
'stroke': '',
|
||||
'fill': '',
|
||||
'color': '',
|
||||
'size': '13px',
|
||||
'type': 'telemetry-view',
|
||||
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
|
||||
|
||||
}
|
||||
],
|
||||
layoutGrid: [10, 10]
|
||||
}
|
||||
};
|
||||
|
||||
const applicableViews = openmct.objectViews.get(testViewObject);
|
||||
let displayLayoutViewProvider = applicableViews.find((viewProvider) => viewProvider.key === 'layout.view');
|
||||
expect(displayLayoutViewProvider).toBeDefined();
|
||||
});
|
||||
|
||||
describe('the alpha numeric format view', () => {
|
||||
let displayLayoutItem;
|
||||
let telemetryItem;
|
||||
let selection;
|
||||
|
||||
beforeEach(() => {
|
||||
displayLayoutItem = {
|
||||
'composition': [
|
||||
],
|
||||
'configuration': {
|
||||
'items': [
|
||||
{
|
||||
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||
},
|
||||
'x': 8,
|
||||
'y': 3,
|
||||
'width': 10,
|
||||
'height': 5,
|
||||
'displayMode': 'all',
|
||||
'value': 'sin',
|
||||
'stroke': '',
|
||||
'fill': '',
|
||||
'color': '',
|
||||
'size': '13px',
|
||||
'type': 'telemetry-view',
|
||||
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
|
||||
|
||||
}
|
||||
],
|
||||
'layoutGrid': [
|
||||
10,
|
||||
10
|
||||
]
|
||||
},
|
||||
'name': 'Display Layout',
|
||||
'type': 'layout',
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': 'c5e636c1-6771-4c9c-b933-8665cab189b3'
|
||||
}
|
||||
};
|
||||
telemetryItem = {
|
||||
'telemetry': {
|
||||
'period': 5,
|
||||
'amplitude': 5,
|
||||
'offset': 5,
|
||||
'dataRateInHz': 5,
|
||||
'phase': 5,
|
||||
'randomness': 0
|
||||
},
|
||||
'name': 'Sine Wave Generator',
|
||||
'type': 'generator',
|
||||
'modified': 1592851063871,
|
||||
'location': 'mine',
|
||||
'persisted': 1592851063871,
|
||||
'id': '55122607-e65e-44d5-9c9d-9c31a914ca89',
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||
}
|
||||
};
|
||||
selection = [
|
||||
[{
|
||||
context: {
|
||||
'layoutItem': displayLayoutItem.configuration.items[0],
|
||||
'item': telemetryItem,
|
||||
'index': 1
|
||||
}
|
||||
},
|
||||
{
|
||||
context: {
|
||||
'item': displayLayoutItem,
|
||||
'supportsMultiSelect': true
|
||||
}
|
||||
}]
|
||||
];
|
||||
});
|
||||
|
||||
it('provides an alphanumeric format view', () => {
|
||||
const displayLayoutAlphaNumFormatView = openmct.inspectorViews.get(selection);
|
||||
expect(displayLayoutAlphaNumFormatView.length).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('the toolbar', () => {
|
||||
let displayLayoutItem;
|
||||
let selection;
|
||||
|
||||
beforeEach(() => {
|
||||
displayLayoutItem = {
|
||||
'composition': [
|
||||
],
|
||||
'configuration': {
|
||||
'items': [
|
||||
{
|
||||
'fill': '#717171',
|
||||
'stroke': '',
|
||||
'x': 1,
|
||||
'y': 1,
|
||||
'width': 10,
|
||||
'height': 5,
|
||||
'type': 'box-view',
|
||||
'id': '89b88746-d325-487b-aec4-11b79afff9e8'
|
||||
},
|
||||
{
|
||||
'x': 18,
|
||||
'y': 9,
|
||||
'x2': 23,
|
||||
'y2': 4,
|
||||
'stroke': '#717171',
|
||||
'type': 'line-view',
|
||||
'id': '57d49a28-7863-43bd-9593-6570758916f0'
|
||||
},
|
||||
{
|
||||
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||
},
|
||||
'x': 8,
|
||||
'y': 3,
|
||||
'width': 10,
|
||||
'height': 5,
|
||||
'displayMode': 'all',
|
||||
'value': 'sin',
|
||||
'stroke': '',
|
||||
'fill': '',
|
||||
'color': '',
|
||||
'size': '13px',
|
||||
'type': 'telemetry-view',
|
||||
'id': 'deb9f839-80ad-4ccf-a152-5c763ceb7d7e'
|
||||
|
||||
},
|
||||
{
|
||||
|
||||
'width': 32,
|
||||
'height': 18,
|
||||
'x': 78,
|
||||
'y': 8,
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
|
||||
},
|
||||
'hasFrame': true,
|
||||
'type': 'subobject-view',
|
||||
'id': 'c0ff485a-344c-4e70-8d83-a9d9998a69fc'
|
||||
|
||||
}
|
||||
],
|
||||
'layoutGrid': [
|
||||
10,
|
||||
10
|
||||
]
|
||||
},
|
||||
'name': 'Display Layout',
|
||||
'type': 'layout',
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': 'c5e636c1-6771-4c9c-b933-8665cab189b3'
|
||||
}
|
||||
};
|
||||
selection = [
|
||||
[{
|
||||
context: {
|
||||
'layoutItem': displayLayoutItem.configuration.items[1],
|
||||
'index': 1
|
||||
}
|
||||
},
|
||||
{
|
||||
context: {
|
||||
'item': displayLayoutItem,
|
||||
'supportsMultiSelect': true
|
||||
}
|
||||
}],
|
||||
[{
|
||||
context: {
|
||||
'layoutItem': displayLayoutItem.configuration.items[0],
|
||||
'index': 0
|
||||
}
|
||||
},
|
||||
{
|
||||
context: {
|
||||
item: displayLayoutItem,
|
||||
'supportsMultiSelect': true
|
||||
}
|
||||
}],
|
||||
[{
|
||||
context: {
|
||||
'layoutItem': displayLayoutItem.configuration.items[2],
|
||||
'item': displayLayoutItem.configuration.items[2],
|
||||
'index': 2
|
||||
}
|
||||
},
|
||||
{
|
||||
context: {
|
||||
item: displayLayoutItem,
|
||||
'supportsMultiSelect': true
|
||||
}
|
||||
}],
|
||||
[{
|
||||
context: {
|
||||
'item': {
|
||||
|
||||
'composition': [
|
||||
{
|
||||
'namespace': '',
|
||||
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||
}
|
||||
],
|
||||
'configuration': {
|
||||
'series': [
|
||||
{
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': '55122607-e65e-44d5-9c9d-9c31a914ca89'
|
||||
}
|
||||
}
|
||||
],
|
||||
'yAxis': {
|
||||
},
|
||||
'xAxis': {
|
||||
}
|
||||
},
|
||||
'name': 'Unnamed Overlay Plot',
|
||||
'type': 'telemetry.plot.overlay',
|
||||
'modified': 1594142141929,
|
||||
'location': 'mine',
|
||||
'identifier': {
|
||||
'namespace': '',
|
||||
'key': 'bdeb91ab-3a7e-4a71-9dd2-39d73644e136'
|
||||
},
|
||||
'persisted': 1594142141929
|
||||
|
||||
},
|
||||
'layoutItem': displayLayoutItem.configuration.items[3],
|
||||
'index': 3
|
||||
}
|
||||
},
|
||||
{
|
||||
context: {
|
||||
item: displayLayoutItem,
|
||||
'supportsMultiSelect': true
|
||||
}
|
||||
}]
|
||||
];
|
||||
});
|
||||
|
||||
it('provides controls including separators', () => {
|
||||
const displayLayoutToolbar = openmct.toolbars.get(selection);
|
||||
expect(displayLayoutToolbar.length).toBe(9);
|
||||
});
|
||||
});
|
||||
});
|
@ -46,7 +46,7 @@ describe("the plugin", () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetApplicationState(openmct);
|
||||
return resetApplicationState();
|
||||
});
|
||||
|
||||
it('installs the new folder action', () => {
|
||||
@ -54,7 +54,6 @@ describe("the plugin", () => {
|
||||
});
|
||||
|
||||
describe('when invoked', () => {
|
||||
|
||||
beforeEach((done) => {
|
||||
compositionAPI = openmct.composition;
|
||||
mockObjectPath = [{
|
||||
@ -65,10 +64,10 @@ describe("the plugin", () => {
|
||||
namespace: ''
|
||||
}
|
||||
}];
|
||||
|
||||
mockPromise = {
|
||||
then: (callback) => {
|
||||
callback({name: newFolderName});
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
@ -82,6 +81,7 @@ describe("the plugin", () => {
|
||||
spyOn(openmct.objects, 'mutate');
|
||||
|
||||
newFolderAction.invoke(mockObjectPath);
|
||||
done();
|
||||
});
|
||||
|
||||
it('gets user input for folder name', () => {
|
||||
|
@ -35,9 +35,9 @@ describe('the plugin', () => {
|
||||
parentElement,
|
||||
mockMessages = ['error', 'test', 'notifications'];
|
||||
|
||||
beforeAll(() => {
|
||||
resetApplicationState();
|
||||
});
|
||||
// beforeAll(() => {
|
||||
// return resetApplicationState();
|
||||
// });
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
@ -61,7 +61,7 @@ describe('the plugin', () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetApplicationState(openmct);
|
||||
return resetApplicationState();
|
||||
});
|
||||
|
||||
describe('the indicator plugin element', () => {
|
||||
|
@ -49,7 +49,7 @@
|
||||
ng-style="{ 'background-color': series.get('color').asHexString() }">
|
||||
</span>
|
||||
<span class="is-missing__indicator" title="This item is missing"></span>
|
||||
<span class="plot-series-name">{{ series.get('name') }}</span>
|
||||
<span class="plot-series-name">{{ series.nameWithUnit() }}</span>
|
||||
</div>
|
||||
<div class="plot-series-value hover-value-enabled value-to-display-{{ legend.get('valueToShowWhenCollapsed') }} {{ series.closest.mctLimitState.cssClass }}"
|
||||
ng-class="{ 'cursor-hover': (legend.get('valueToShowWhenCollapsed').indexOf('nearest') != -1) }"
|
||||
@ -79,6 +79,9 @@
|
||||
<th ng-if="legend.get('showValueWhenExpanded')">
|
||||
Value
|
||||
</th>
|
||||
<th ng-if="legend.get('showUnitsWhenExpanded')">
|
||||
Unit
|
||||
</th>
|
||||
<th ng-if="legend.get('showMinimumWhenExpanded')"
|
||||
class="mobile-hide">
|
||||
Min
|
||||
@ -114,6 +117,11 @@
|
||||
{{ series.formatY(series.closest) }}
|
||||
</span>
|
||||
</td>
|
||||
<td ng-if="legend.get('showUnitsWhenExpanded')">
|
||||
<span class="plot-series-value cursor-hover hover-value-enabled">
|
||||
{{ series.get('unit') }}
|
||||
</span>
|
||||
</td>
|
||||
<td ng-if="legend.get('showMinimumWhenExpanded')"
|
||||
class="mobile-hide">
|
||||
<span class="plot-series-value">
|
||||
|
@ -140,6 +140,7 @@
|
||||
<span ng-if="config.legend.get('showValueWhenExpanded')">Value</span>
|
||||
<span ng-if="config.legend.get('showMinimumWhenExpanded')">Min</span>
|
||||
<span ng-if="config.legend.get('showMaximumWhenExpanded')">Max</span>
|
||||
<span ng-if="config.legend.get('showUnitsWhenExpanded')">Units</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -201,6 +201,7 @@
|
||||
<option value="nearestValue">Nearest value</option>
|
||||
<option value="min">Minimum value</option>
|
||||
<option value="max">Maximum value</option>
|
||||
<option value="units">showUnitsWhenExpanded</option>
|
||||
</select>
|
||||
</div>
|
||||
</li>
|
||||
@ -217,6 +218,8 @@
|
||||
ng-model="form.showMinimumWhenExpanded"/> Minimum value</li>
|
||||
<li><input type="checkbox"
|
||||
ng-model="form.showMaximumWhenExpanded"/> Maximum value</li>
|
||||
<li><input type="checkbox"
|
||||
ng-model="form.showUnitsWhenExpanded"/> Units</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
@ -53,7 +53,8 @@ define([
|
||||
showTimestampWhenExpanded: true,
|
||||
showValueWhenExpanded: true,
|
||||
showMaximumWhenExpanded: true,
|
||||
showMinimumWhenExpanded: true
|
||||
showMinimumWhenExpanded: true,
|
||||
showUnitsWhenExpanded: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -102,6 +102,7 @@ define([
|
||||
|
||||
return {
|
||||
name: options.domainObject.name,
|
||||
unit: range.unit,
|
||||
xKey: options.collection.plot.xAxis.get('key'),
|
||||
yKey: range.key,
|
||||
markers: true,
|
||||
@ -439,6 +440,11 @@ define([
|
||||
const markerSize = this.get('markerSize');
|
||||
|
||||
return `${markerShape}: ${markerSize}px`;
|
||||
},
|
||||
nameWithUnit: function () {
|
||||
let unit = this.get('unit');
|
||||
|
||||
return this.get('name') + (unit ? ' ' + unit : '');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -65,6 +65,11 @@ define([
|
||||
modelProp: 'showMinimumWhenExpanded',
|
||||
coerce: Boolean,
|
||||
objectPath: 'configuration.legend.showMinimumWhenExpanded'
|
||||
},
|
||||
{
|
||||
modelProp: 'showUnitsWhenExpanded',
|
||||
coerce: Boolean,
|
||||
objectPath: 'configuration.legend.showUnitsWhenExpanded'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
@ -27,6 +27,7 @@ define([
|
||||
'./collections/FilteredTableRowCollection',
|
||||
'./TelemetryTableRow',
|
||||
'./TelemetryTableColumn',
|
||||
'./TelemetryTableUnitColumn',
|
||||
'./TelemetryTableConfiguration'
|
||||
], function (
|
||||
EventEmitter,
|
||||
@ -35,6 +36,7 @@ define([
|
||||
FilteredTableRowCollection,
|
||||
TelemetryTableRow,
|
||||
TelemetryTableColumn,
|
||||
TelemetryTableUnitColumn,
|
||||
TelemetryTableConfiguration
|
||||
) {
|
||||
class TelemetryTable extends EventEmitter {
|
||||
@ -210,10 +212,14 @@ define([
|
||||
|
||||
addColumnsForObject(telemetryObject) {
|
||||
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
||||
|
||||
metadataValues.forEach(metadatum => {
|
||||
let column = this.createColumn(metadatum);
|
||||
this.configuration.addSingleColumnForObject(telemetryObject, column);
|
||||
// add units column if available
|
||||
if (metadatum.unit !== undefined) {
|
||||
let unitColumn = this.createUnitColumn(metadatum);
|
||||
this.configuration.addSingleColumnForObject(telemetryObject, unitColumn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -221,6 +227,10 @@ define([
|
||||
return new TelemetryTableColumn(this.openmct, metadatum);
|
||||
}
|
||||
|
||||
createUnitColumn(metadatum) {
|
||||
return new TelemetryTableUnitColumn(this.openmct, metadatum);
|
||||
}
|
||||
|
||||
subscribeTo(telemetryObject) {
|
||||
let subscribeOptions = this.buildOptionsFromConfiguration(telemetryObject);
|
||||
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
|
@ -70,8 +70,10 @@ define([], function () {
|
||||
getCellLimitClasses() {
|
||||
if (!this.cellLimitClasses) {
|
||||
this.cellLimitClasses = Object.values(this.columns).reduce((alarmStateMap, column) => {
|
||||
let limitEvaluation = this.limitEvaluator.evaluate(this.datum, column.getMetadatum());
|
||||
alarmStateMap[column.getKey()] = limitEvaluation && limitEvaluation.cssClass;
|
||||
if (!column.isUnit) {
|
||||
let limitEvaluation = this.limitEvaluator.evaluate(this.datum, column.getMetadatum());
|
||||
alarmStateMap[column.getKey()] = limitEvaluation && limitEvaluation.cssClass;
|
||||
}
|
||||
|
||||
return alarmStateMap;
|
||||
}, {});
|
||||
|
60
src/plugins/telemetryTable/TelemetryTableUnitColumn.js
Normal file
60
src/plugins/telemetryTable/TelemetryTableUnitColumn.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*****************************************************************************
|
||||
* 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([
|
||||
'./TelemetryTableColumn.js'
|
||||
], function (
|
||||
TelemetryTableColumn
|
||||
) {
|
||||
class TelemetryTableUnitColumn extends TelemetryTableColumn {
|
||||
constructor(openmct, metadatum) {
|
||||
super(openmct, metadatum);
|
||||
this.isUnit = true;
|
||||
this.titleValue += ' Unit';
|
||||
this.formatter = {
|
||||
format: (datum) => {
|
||||
return this.metadatum.unit;
|
||||
},
|
||||
parse: (datum) => {
|
||||
return this.metadatum.unit;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
getKey() {
|
||||
return this.metadatum.key + '-unit';
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
return this.metadatum.name + ' Unit';
|
||||
}
|
||||
|
||||
getRawValue(telemetryDatum) {
|
||||
return this.metadatum.unit;
|
||||
}
|
||||
|
||||
getFormattedValue(telemetryDatum) {
|
||||
return this.formatter.format(telemetryDatum);
|
||||
}
|
||||
}
|
||||
|
||||
return TelemetryTableUnitColumn;
|
||||
});
|
@ -113,6 +113,8 @@ export default {
|
||||
event.dataTransfer.setData(MOVE_COLUMN_DT_TYPE, this.headerIndex);
|
||||
},
|
||||
isColumnMoveEvent(event) {
|
||||
console.error(`Types: ${event.dataTransfer.types}`);
|
||||
|
||||
return [...event.dataTransfer.types].includes(MOVE_COLUMN_DT_TYPE);
|
||||
},
|
||||
dragOverColumn(event) {
|
||||
@ -144,6 +146,7 @@ export default {
|
||||
if (this.isColumnMoveEvent(event)) {
|
||||
let toIndex = this.headerIndex;
|
||||
let fromIndex = event.dataTransfer.getData(MOVE_COLUMN_DT_TYPE);
|
||||
console.error(`fromIndex: ${fromIndex}`);
|
||||
if (event.offsetX < event.target.offsetWidth / 2) {
|
||||
if (toIndex > fromIndex) {
|
||||
toIndex--;
|
||||
|
@ -69,6 +69,7 @@
|
||||
|
||||
<script>
|
||||
import TelemetryTableColumn from '../TelemetryTableColumn';
|
||||
import TelemetryTableUnitColumn from '../TelemetryTableUnitColumn';
|
||||
|
||||
export default {
|
||||
inject: ['tableConfiguration', 'openmct'],
|
||||
@ -131,10 +132,14 @@ export default {
|
||||
},
|
||||
addColumnsForObject(telemetryObject) {
|
||||
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
||||
|
||||
metadataValues.forEach(metadatum => {
|
||||
let column = new TelemetryTableColumn(this.openmct, metadatum);
|
||||
this.tableConfiguration.addSingleColumnForObject(telemetryObject, column);
|
||||
// if units are available, need to add columns to be hidden
|
||||
if (metadatum.unit !== undefined) {
|
||||
let unitColumn = new TelemetryTableUnitColumn(this.openmct, metadatum);
|
||||
this.tableConfiguration.addSingleColumnForObject(telemetryObject, unitColumn);
|
||||
}
|
||||
});
|
||||
},
|
||||
toggleHeaderVisibility() {
|
||||
|
@ -117,7 +117,7 @@
|
||||
title="Deselect All"
|
||||
@click="unmarkAllRows()"
|
||||
>
|
||||
<span class="c-button__label">Deselect All</span>
|
||||
<span class="c-button__label">{{ `Deselect ${marking.disableMultiSelect ? '' : 'All'}` }} </span>
|
||||
</button>
|
||||
|
||||
<slot name="buttons"></slot>
|
||||
@ -303,6 +303,7 @@ export default {
|
||||
default() {
|
||||
return {
|
||||
enable: false,
|
||||
disableMultiSelect: false,
|
||||
useAlternateControlBar: false,
|
||||
rowName: '',
|
||||
rowNamePlural: ""
|
||||
@ -787,6 +788,11 @@ export default {
|
||||
this.$set(markedRow, 'marked', true);
|
||||
this.pause();
|
||||
|
||||
if (this.marking.disableMultiSelect) {
|
||||
this.unmarkAllRows();
|
||||
insertMethod = 'push';
|
||||
}
|
||||
|
||||
this.markedRows[insertMethod](markedRow);
|
||||
},
|
||||
unmarkAllRows(skipUnpause) {
|
||||
@ -800,7 +806,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.markedRows.length) {
|
||||
if (!this.markedRows.length || this.marking.disableMultiSelect) {
|
||||
this.markRow(rowIndex);
|
||||
} else {
|
||||
if (this.markedRows.length > 1) {
|
||||
|
@ -28,15 +28,30 @@ import {
|
||||
resetApplicationState
|
||||
} from 'utils/testing';
|
||||
|
||||
class MockDataTransfer {
|
||||
constructor() {
|
||||
this.data = {};
|
||||
}
|
||||
get types() {
|
||||
return Object.keys(this.data);
|
||||
}
|
||||
setData(format, data) {
|
||||
this.data[format] = data;
|
||||
}
|
||||
getData(format) {
|
||||
return this.data[format];
|
||||
}
|
||||
}
|
||||
|
||||
describe("the plugin", () => {
|
||||
let openmct;
|
||||
let tablePlugin;
|
||||
let element;
|
||||
let child;
|
||||
|
||||
beforeAll(() => {
|
||||
resetApplicationState();
|
||||
});
|
||||
// beforeAll(() => {
|
||||
// return resetApplicationState();
|
||||
// });
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
@ -67,7 +82,7 @@ describe("the plugin", () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetApplicationState(openmct);
|
||||
return resetApplicationState();
|
||||
});
|
||||
|
||||
describe("defines a table object", function () {
|
||||
@ -191,7 +206,7 @@ describe("the plugin", () => {
|
||||
|
||||
dragStartEvent.dataTransfer =
|
||||
dragOverEvent.dataTransfer =
|
||||
dropEvent.dataTransfer = new DataTransfer();
|
||||
dropEvent.dataTransfer = new MockDataTransfer();
|
||||
|
||||
fromColumn.dispatchEvent(dragStartEvent);
|
||||
toColumn.dispatchEvent(dragOverEvent);
|
||||
|
@ -143,7 +143,7 @@
|
||||
<ConductorHistory
|
||||
v-if="isFixed"
|
||||
class="c-conductor__history-select"
|
||||
:bounds="openmct.time.bounds()"
|
||||
:bounds="bounds"
|
||||
:time-system="timeSystem"
|
||||
/>
|
||||
</div>
|
||||
@ -190,6 +190,10 @@ export default {
|
||||
start: offsets && durationFormatter.format(Math.abs(offsets.start)),
|
||||
end: offsets && durationFormatter.format(Math.abs(offsets.end))
|
||||
},
|
||||
bounds: {
|
||||
start: bounds.start,
|
||||
end: bounds.end
|
||||
},
|
||||
formattedBounds: {
|
||||
start: timeFormatter.format(bounds.start),
|
||||
end: timeFormatter.format(bounds.end)
|
||||
@ -210,7 +214,7 @@ export default {
|
||||
document.addEventListener('keydown', this.handleKeyDown);
|
||||
document.addEventListener('keyup', this.handleKeyUp);
|
||||
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));
|
||||
this.openmct.time.on('bounds', this.setViewFromBounds);
|
||||
this.openmct.time.on('bounds', this.handleNewBounds);
|
||||
this.openmct.time.on('timeSystem', this.setTimeSystem);
|
||||
this.openmct.time.on('clock', this.setViewFromClock);
|
||||
this.openmct.time.on('clockOffsets', this.setViewFromOffsets);
|
||||
@ -220,6 +224,13 @@ export default {
|
||||
document.removeEventListener('keyup', this.handleKeyUp);
|
||||
},
|
||||
methods: {
|
||||
handleNewBounds(bounds) {
|
||||
this.setBounds(bounds);
|
||||
this.setViewFromBounds(bounds);
|
||||
},
|
||||
setBounds(bounds) {
|
||||
this.bounds = bounds;
|
||||
},
|
||||
handleKeyDown(event) {
|
||||
if (event.key === 'Alt') {
|
||||
this.altPressed = true;
|
||||
@ -246,10 +257,13 @@ export default {
|
||||
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
|
||||
},
|
||||
endZoom(bounds) {
|
||||
const _bounds = bounds ? bounds : this.openmct.time.bounds();
|
||||
this.isZooming = false;
|
||||
|
||||
this.openmct.time.bounds(_bounds);
|
||||
if (bounds) {
|
||||
this.handleNewBounds(bounds);
|
||||
} else {
|
||||
this.setViewFromBounds(this.bounds);
|
||||
}
|
||||
},
|
||||
setTimeSystem(timeSystem) {
|
||||
this.timeSystem = timeSystem;
|
||||
|
@ -207,7 +207,7 @@ export default {
|
||||
this.$emit('panAxis', panBounds);
|
||||
},
|
||||
endPan() {
|
||||
const panBounds = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
|
||||
const panBounds = this.isChangingViewBounds()
|
||||
? this.getPanBounds()
|
||||
: undefined;
|
||||
this.$emit('endPan', panBounds);
|
||||
@ -251,16 +251,14 @@ export default {
|
||||
});
|
||||
},
|
||||
endZoom() {
|
||||
const zoomRange = this.dragStartX && this.dragX && this.dragStartX !== this.dragX
|
||||
? this.getZoomRange()
|
||||
: undefined;
|
||||
|
||||
const zoomBounds = zoomRange
|
||||
? {
|
||||
let zoomBounds;
|
||||
if (this.isChangingViewBounds()) {
|
||||
const zoomRange = this.getZoomRange();
|
||||
zoomBounds = {
|
||||
start: this.scaleToBounds(zoomRange.start),
|
||||
end: this.scaleToBounds(zoomRange.end)
|
||||
}
|
||||
: this.openmct.time.bounds();
|
||||
};
|
||||
}
|
||||
|
||||
this.zoomStyle = {};
|
||||
this.$emit('endZoom', zoomBounds);
|
||||
@ -290,6 +288,9 @@ export default {
|
||||
|
||||
return bounds.start + offset;
|
||||
},
|
||||
isChangingViewBounds() {
|
||||
return this.dragStartX && this.dragX && this.dragStartX !== this.dragX;
|
||||
},
|
||||
resize() {
|
||||
if (this.$refs.axisHolder.clientWidth !== this.width) {
|
||||
this.setAxisDimensions();
|
||||
|
@ -84,7 +84,12 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
history: {}, // contains arrays of timespans {start, end}, array key is time system key
|
||||
/**
|
||||
* previous bounds entries available for easy re-use
|
||||
* @history array of timespans
|
||||
* @timespans {start, end} number representing timestamp
|
||||
*/
|
||||
history: this.getHistoryFromLocalStorage(),
|
||||
presets: []
|
||||
};
|
||||
},
|
||||
@ -111,22 +116,20 @@ export default {
|
||||
this.addTimespan();
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
history: {
|
||||
handler() {
|
||||
this.persistHistoryToLocalStorage();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getHistoryFromLocalStorage();
|
||||
this.initializeHistoryIfNoHistory();
|
||||
},
|
||||
methods: {
|
||||
getHistoryFromLocalStorage() {
|
||||
if (localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY)) {
|
||||
this.history = JSON.parse(localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY));
|
||||
} else {
|
||||
const localStorageHistory = localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY);
|
||||
const history = localStorageHistory ? JSON.parse(localStorageHistory) : undefined;
|
||||
|
||||
return history;
|
||||
},
|
||||
initializeHistoryIfNoHistory() {
|
||||
if (!this.history) {
|
||||
this.history = {};
|
||||
this.persistHistoryToLocalStorage();
|
||||
}
|
||||
@ -157,6 +160,8 @@ export default {
|
||||
|
||||
currentHistory.unshift(timespan);
|
||||
this.history[key] = currentHistory;
|
||||
|
||||
this.persistHistoryToLocalStorage();
|
||||
},
|
||||
selectTimespan(timespan) {
|
||||
this.openmct.time.bounds(timespan);
|
||||
|
@ -81,7 +81,12 @@ export default {
|
||||
this.isLoading = true;
|
||||
this.openmct.objects.get('ROOT')
|
||||
.then(root => {
|
||||
return this.openmct.composition.get(root).load();
|
||||
let composition = this.openmct.composition.get(root);
|
||||
if (composition !== undefined) {
|
||||
return composition.load();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
.then(children => {
|
||||
this.isLoading = false;
|
||||
|
@ -45,6 +45,7 @@ class ApplicationRouter extends EventEmitter {
|
||||
super();
|
||||
this.routes = [];
|
||||
this.started = false;
|
||||
this.locationBar = new LocationBar();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,13 +57,17 @@ class ApplicationRouter extends EventEmitter {
|
||||
}
|
||||
|
||||
this.started = true;
|
||||
let locationBar = new LocationBar();
|
||||
locationBar.onChange(p => this.handleLocationChange(p));
|
||||
locationBar.start({
|
||||
|
||||
this.locationBar.onChange(p => this.handleLocationChange(p));
|
||||
this.locationBar.start({
|
||||
root: location.pathname
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.locationBar.stop();
|
||||
}
|
||||
|
||||
handleLocationChange(pathString) {
|
||||
if (pathString[0] !== '/') {
|
||||
pathString = '/' + pathString;
|
||||
|
@ -135,7 +135,6 @@ export default {
|
||||
value = this.getFormValue(domainObject, toolbarItem);
|
||||
} else {
|
||||
let values = [];
|
||||
|
||||
if (applicableSelectedItems) {
|
||||
applicableSelectedItems.forEach(selectionPath => {
|
||||
values.push(this.getPropertyValue(domainObject, toolbarItem, selectionPath));
|
||||
@ -207,7 +206,6 @@ export default {
|
||||
},
|
||||
updateObjectValue(value, item) {
|
||||
let changedItemId = this.openmct.objects.makeKeyString(item.domainObject.identifier);
|
||||
|
||||
this.structure = this.structure.map(toolbarItem => {
|
||||
if (toolbarItem.domainObject) {
|
||||
let id = this.openmct.objects.makeKeyString(toolbarItem.domainObject.identifier);
|
||||
|
@ -32,7 +32,7 @@ import {
|
||||
import {resetApplicationState} from 'utils/testing';
|
||||
|
||||
describe('the openmct location utility functions', () => {
|
||||
beforeAll(() => resetApplicationState());
|
||||
// beforeAll(() => resetApplicationState());
|
||||
afterEach(() => resetApplicationState());
|
||||
|
||||
it('The setSearchParam function sets an individual search parameters in the window location hash', () => {
|
||||
|
@ -24,8 +24,15 @@ import MCT from 'MCT';
|
||||
let nativeFunctions = [],
|
||||
mockObjects = setMockObjects();
|
||||
|
||||
let openmct;
|
||||
|
||||
export function createOpenMct() {
|
||||
const openmct = new MCT();
|
||||
if (openmct !== undefined) {
|
||||
console.log('=========================');
|
||||
console.log('createOpenMct sending old');
|
||||
return openmct;
|
||||
}
|
||||
openmct = new MCT();
|
||||
openmct.install(openmct.plugins.LocalStorage());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
openmct.time.timeSystem('utc', {
|
||||
@ -64,13 +71,35 @@ export function clearBuiltinSpies() {
|
||||
nativeFunctions = [];
|
||||
}
|
||||
|
||||
export function resetApplicationState(openmct) {
|
||||
export function resetApplicationState() {
|
||||
let promise;
|
||||
|
||||
clearBuiltinSpies();
|
||||
window.location.hash = '#';
|
||||
|
||||
if (openmct !== undefined) {
|
||||
openmct.destroy();
|
||||
openmct = undefined;
|
||||
}
|
||||
|
||||
if (window.location.hash !== '#' && window.location.hash !== '') {
|
||||
promise = new Promise((resolve, reject) => {
|
||||
window.addEventListener('hashchange', cleanup);
|
||||
let timeTag = Date.now();
|
||||
// console.log(`${timeTag}: window.location.hash is ${window.location.hash}`);
|
||||
window.location.hash = '#';
|
||||
//setTimeout(resolve);
|
||||
function cleanup() {
|
||||
let endTag = Date.now();
|
||||
// console.log(`${timeTag} after reset window.location.hash is ${window.location.hash} and took ${(endTag - timeTag) / 1000}s`);
|
||||
window.removeEventListener('hashchange', cleanup);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
promise = Promise.resolve();
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function clearBuiltinSpy(funcDefinition) {
|
||||
|
Reference in New Issue
Block a user