mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 02:29:24 +00:00
Compare commits
20 Commits
fix-missin
...
stackplots
Author | SHA1 | Date | |
---|---|---|---|
fe1d8c0866 | |||
93f76ac0d7 | |||
4f8cba160d | |||
c74439a013 | |||
0aeab0361a | |||
21f447dd3d | |||
0ca3bde106 | |||
a8f8415dc7 | |||
c269e089da | |||
4873f40614 | |||
10bb9173ec | |||
ea8c9c7cc8 | |||
294bed974f | |||
4c9c084eec | |||
b64ee10812 | |||
ee1ecf43db | |||
4d8db8eb7c | |||
1b13965200 | |||
38db8f7fe5 | |||
4ba8f893a6 |
@ -42,6 +42,7 @@ jobs:
|
||||
- ~/.npm
|
||||
- ~/.cache
|
||||
- node_modules
|
||||
- run: npm run lint
|
||||
- run: npm run test:coverage -- --browsers=<<parameters.browser>> || <<parameters.always-pass>>
|
||||
- store_test_results:
|
||||
path: dist/reports/tests/
|
||||
|
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -2,6 +2,7 @@
|
||||
|
||||
* [ ] Have you followed the guidelines in our [Contributing document](https://github.com/nasa/openmct/blob/master/CONTRIBUTING.md)?
|
||||
* [ ] Have you checked to ensure there aren't other open [Pull Requests](https://github.com/nasa/openmct/pulls) for the same update/change?
|
||||
* [ ] Is this change backwards compatible? For example, developers won't need to change how they are calling the API or how they've extended core plugins such as Tables or Plots.
|
||||
|
||||
### Author Checklist
|
||||
|
||||
|
@ -317,6 +317,7 @@ checklist).
|
||||
### Reviewer Checklist
|
||||
|
||||
* [ ] Changes appear to address issue?
|
||||
* [ ] Changes appear not to be breaking changes?
|
||||
* [ ] Appropriate unit tests included?
|
||||
* [ ] Code style and in-line documentation are appropriate?
|
||||
* [ ] Commit messages meet standards?
|
||||
|
@ -25,7 +25,7 @@
|
||||
const devMode = process.env.NODE_ENV !== 'production';
|
||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless'];
|
||||
const coverageEnabled = process.env.COVERAGE === 'true';
|
||||
const reporters = ['progress', 'html', 'junit'];
|
||||
const reporters = ['spec', 'html', 'junit'];
|
||||
|
||||
if (coverageEnabled) {
|
||||
reporters.push('coverage-istanbul');
|
||||
@ -60,7 +60,7 @@ module.exports = (config) => {
|
||||
client: {
|
||||
jasmine: {
|
||||
random: false,
|
||||
timeoutInterval: 30000
|
||||
timeoutInterval: 5000
|
||||
}
|
||||
},
|
||||
customLaunchers: {
|
||||
@ -88,11 +88,6 @@ module.exports = (config) => {
|
||||
outputFile: "test-results.xml",
|
||||
useBrowserName: false
|
||||
},
|
||||
browserConsoleLogOptions: {
|
||||
level: "error",
|
||||
format: "%b %T: %m",
|
||||
terminal: true
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
fixWebpackSourcePaths: true,
|
||||
dir: process.env.CIRCLE_ARTIFACTS
|
||||
@ -105,6 +100,15 @@ module.exports = (config) => {
|
||||
}
|
||||
}
|
||||
},
|
||||
specReporter: {
|
||||
maxLogLines: 5,
|
||||
suppressErrorSummary: true,
|
||||
suppressFailed: false,
|
||||
suppressPassed: false,
|
||||
suppressSkipped: true,
|
||||
showSpecTiming: true,
|
||||
failFast: false
|
||||
},
|
||||
preprocessors: {
|
||||
'indexTest.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
|
@ -41,6 +41,7 @@
|
||||
"karma-jasmine": "4.0.1",
|
||||
"karma-junit-reporter": "2.0.1",
|
||||
"karma-sourcemap-loader": "0.3.8",
|
||||
"karma-spec-reporter": "0.0.32",
|
||||
"karma-webpack": "4.0.2",
|
||||
"location-bar": "^3.0.1",
|
||||
"lodash": "^4.17.12",
|
||||
@ -64,6 +65,7 @@
|
||||
"uuid": "^3.3.3",
|
||||
"v8-compile-cache": "^1.1.0",
|
||||
"vue": "2.5.6",
|
||||
"vue-eslint-parser": "7.11.0",
|
||||
"vue-loader": "^15.2.6",
|
||||
"vue-template-compiler": "2.5.6",
|
||||
"webpack": "^4.16.2",
|
||||
|
@ -50,8 +50,6 @@ define(
|
||||
* or finish() are called.
|
||||
*/
|
||||
EditorCapability.prototype.edit = function () {
|
||||
console.warn('DEPRECATED: cannot edit via edit capability, use openmct.editor instead.');
|
||||
|
||||
if (!this.openmct.editor.isEditing()) {
|
||||
this.openmct.editor.edit();
|
||||
this.domainObject.getCapability('status').set('editing', true);
|
||||
@ -82,8 +80,6 @@ define(
|
||||
* @returns {*}
|
||||
*/
|
||||
EditorCapability.prototype.save = function () {
|
||||
console.warn('DEPRECATED: cannot save via edit capability, use openmct.editor instead.');
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
@ -95,8 +91,6 @@ define(
|
||||
* @returns {*}
|
||||
*/
|
||||
EditorCapability.prototype.finish = function () {
|
||||
console.warn('DEPRECATED: cannot finish via edit capability, use openmct.editor instead.');
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
|
@ -25,15 +25,14 @@ define([
|
||||
], function (
|
||||
moment
|
||||
) {
|
||||
|
||||
var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss.SSS",
|
||||
DATE_FORMATS = [
|
||||
DATE_FORMAT,
|
||||
DATE_FORMAT + "Z",
|
||||
"YYYY-MM-DD HH:mm:ss",
|
||||
"YYYY-MM-DD HH:mm",
|
||||
"YYYY-MM-DD"
|
||||
];
|
||||
const DATE_FORMAT = "YYYY-MM-DD HH:mm:ss.SSS";
|
||||
const DATE_FORMATS = [
|
||||
DATE_FORMAT,
|
||||
DATE_FORMAT + "Z",
|
||||
"YYYY-MM-DD HH:mm:ss",
|
||||
"YYYY-MM-DD HH:mm",
|
||||
"YYYY-MM-DD"
|
||||
];
|
||||
|
||||
/**
|
||||
* @typedef Scale
|
||||
@ -53,15 +52,27 @@ define([
|
||||
this.key = "utc";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} formatString
|
||||
* @returns the value of formatString if the value is a string type and exists in the DATE_FORMATS array; otherwise the DATE_FORMAT value.
|
||||
*/
|
||||
function validateFormatString(formatString) {
|
||||
return typeof formatString === 'string' && DATE_FORMATS.includes(formatString) ? formatString : DATE_FORMAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} value The value to format.
|
||||
* @returns {string} the formatted date(s). If multiple values were requested, then an array of
|
||||
* @param {string} formatString The string format to format. Default "YYYY-MM-DD HH:mm:ss.SSS" + "Z"
|
||||
* @returns {string} the formatted date(s) according to the proper parameter of formatString or the default value of "YYYY-MM-DD HH:mm:ss.SSS" + "Z".
|
||||
* If multiple values were requested, then an array of
|
||||
* formatted values will be returned. Where a value could not be formatted, `undefined` will be returned at its position
|
||||
* in the array.
|
||||
*/
|
||||
UTCTimeFormat.prototype.format = function (value) {
|
||||
UTCTimeFormat.prototype.format = function (value, formatString) {
|
||||
if (value !== undefined) {
|
||||
return moment.utc(value).format(DATE_FORMAT) + "Z";
|
||||
const format = validateFormatString(formatString);
|
||||
|
||||
return moment.utc(value).format(format) + (formatString ? '' : 'Z');
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
|
@ -28,8 +28,6 @@ export default function LegacyActionAdapter(openmct, legacyActions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
console.warn(`DEPRECATION WARNING: Action ${action.definition.key} in bundle ${action.bundle.path} is non-contextual and should be migrated.`);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ define([
|
||||
'./capabilities/APICapabilityDecorator',
|
||||
'./policies/AdaptedViewPolicy',
|
||||
'./runs/AlternateCompositionInitializer',
|
||||
'./runs/TypeDeprecationChecker',
|
||||
'./runs/LegacyTelemetryProvider',
|
||||
'./runs/RegisterLegacyTypes',
|
||||
'./services/LegacyObjectAPIInterceptor',
|
||||
@ -46,7 +45,6 @@ define([
|
||||
APICapabilityDecorator,
|
||||
AdaptedViewPolicy,
|
||||
AlternateCompositionInitializer,
|
||||
TypeDeprecationChecker,
|
||||
LegacyTelemetryProvider,
|
||||
RegisterLegacyTypes,
|
||||
LegacyObjectAPIInterceptor,
|
||||
@ -135,10 +133,6 @@ define([
|
||||
}
|
||||
],
|
||||
runs: [
|
||||
{
|
||||
implementation: TypeDeprecationChecker,
|
||||
depends: ["types[]"]
|
||||
},
|
||||
{
|
||||
implementation: AlternateCompositionInitializer,
|
||||
depends: ["openmct"]
|
||||
|
@ -4,12 +4,6 @@ define([
|
||||
|
||||
) {
|
||||
function RegisterLegacyTypes(types, openmct) {
|
||||
types.forEach(function (legacyDefinition) {
|
||||
if (!openmct.types.get(legacyDefinition.key)) {
|
||||
console.warn(`DEPRECATION WARNING: Migrate type ${legacyDefinition.key} from ${legacyDefinition.bundle.path} to use the new Types API. Legacy type support will be removed soon.`);
|
||||
}
|
||||
});
|
||||
|
||||
openmct.types.importLegacyTypes(types);
|
||||
}
|
||||
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open openmct, Copyright (c) 2014-2021, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open openmct 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 openmct includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
|
||||
function checkForDeprecatedFunctionality(typeDef) {
|
||||
if (Object.prototype.hasOwnProperty.call(typeDef, 'telemetry')) {
|
||||
console.warn(
|
||||
'DEPRECATION WARNING: Telemetry data on type '
|
||||
+ 'registrations will be deprecated in a future version, '
|
||||
+ 'please convert to a custom telemetry metadata provider '
|
||||
+ 'for type: ' + typeDef.key
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function TypeDeprecationChecker(types) {
|
||||
types.forEach(checkForDeprecatedFunctionality);
|
||||
}
|
||||
|
||||
return TypeDeprecationChecker;
|
||||
|
||||
});
|
@ -15,8 +15,6 @@ define([
|
||||
};
|
||||
|
||||
function LegacyViewProvider(legacyView, openmct, convertToLegacyObject) {
|
||||
console.warn(`DEPRECATION WARNING: Migrate ${legacyView.key} from ${legacyView.bundle.path} to use the new View APIs. Legacy view support will be removed soon.`);
|
||||
|
||||
return {
|
||||
key: legacyView.key,
|
||||
name: legacyView.name,
|
||||
|
@ -4,7 +4,6 @@ define([
|
||||
|
||||
) {
|
||||
function TypeInspectorViewProvider(typeDefinition, openmct, convertToLegacyObject) {
|
||||
console.warn(`DEPRECATION WARNING: Migrate ${typeDefinition.key} from ${typeDefinition.bundle.path} to use the new Inspector View APIs. Legacy Inspector view support will be removed soon.`);
|
||||
let representation = openmct.$injector.get('representations[]')
|
||||
.filter((r) => r.key === typeDefinition.inspector)[0];
|
||||
|
||||
|
@ -182,6 +182,12 @@ ObjectAPI.prototype.get = function (identifier, abortSignal) {
|
||||
let objectPromise = provider.get(identifier, abortSignal).then(result => {
|
||||
delete this.cache[keystring];
|
||||
result = this.applyGetInterceptors(identifier, result);
|
||||
if (result.isMutable) {
|
||||
result.$refresh(result);
|
||||
} else {
|
||||
let mutableDomainObject = this._toMutable(result);
|
||||
mutableDomainObject.$refresh(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
@ -298,10 +304,15 @@ ObjectAPI.prototype.save = function (domainObject) {
|
||||
savedResolve = resolve;
|
||||
});
|
||||
domainObject.persisted = persistedTime;
|
||||
provider.create(domainObject).then((response) => {
|
||||
this.mutate(domainObject, 'persisted', persistedTime);
|
||||
savedResolve(response);
|
||||
});
|
||||
const newObjectPromise = provider.create(domainObject);
|
||||
if (newObjectPromise) {
|
||||
newObjectPromise.then(response => {
|
||||
this.mutate(domainObject, 'persisted', persistedTime);
|
||||
savedResolve(response);
|
||||
});
|
||||
} else {
|
||||
result = Promise.reject(`[ObjectAPI][save] Object provider returned ${newObjectPromise} when creating new object.`);
|
||||
}
|
||||
} else {
|
||||
domainObject.persisted = persistedTime;
|
||||
this.mutate(domainObject, 'persisted', persistedTime);
|
||||
|
@ -180,12 +180,6 @@ define([
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
*/
|
||||
TelemetryAPI.prototype.canProvideTelemetry = function (domainObject) {
|
||||
console.warn(
|
||||
'DEPRECATION WARNING: openmct.telemetry.canProvideTelemetry '
|
||||
+ 'will not be supported in future versions of Open MCT. Please '
|
||||
+ 'use openmct.telemetry.isTelemetryObject instead.'
|
||||
);
|
||||
|
||||
return Boolean(this.findSubscriptionProvider(domainObject))
|
||||
|| Boolean(this.findRequestProvider(domainObject));
|
||||
};
|
||||
|
@ -31,11 +31,6 @@ define([
|
||||
valueMetadata.hints = valueMetadata.hints || {};
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(valueMetadata.hints, 'x')) {
|
||||
console.warn(
|
||||
'DEPRECATION WARNING: `x` hints should be replaced with '
|
||||
+ '`domain` hints moving forward. '
|
||||
+ 'https://github.com/nasa/openmct/issues/1546'
|
||||
);
|
||||
if (!Object.prototype.hasOwnProperty.call(valueMetadata.hints, 'domain')) {
|
||||
valueMetadata.hints.domain = valueMetadata.hints.x;
|
||||
}
|
||||
@ -44,11 +39,6 @@ define([
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(valueMetadata.hints, 'y')) {
|
||||
console.warn(
|
||||
'DEPRECATION WARNING: `y` hints should be replaced with '
|
||||
+ '`range` hints moving forward. '
|
||||
+ 'https://github.com/nasa/openmct/issues/1546'
|
||||
);
|
||||
if (!Object.prototype.hasOwnProperty.call(valueMetadata.hints, 'range')) {
|
||||
valueMetadata.hints.range = valueMetadata.hints.y;
|
||||
}
|
||||
|
@ -63,12 +63,6 @@ define(['./Type'], function (Type) {
|
||||
*/
|
||||
TypeRegistry.prototype.standardizeType = function (typeDef) {
|
||||
if (Object.prototype.hasOwnProperty.call(typeDef, 'label')) {
|
||||
console.warn(
|
||||
'DEPRECATION WARNING typeDef: ' + typeDef.label + '. '
|
||||
+ '`label` is deprecated in type definitions. Please use '
|
||||
+ '`name` instead. This will cause errors in a future version '
|
||||
+ 'of Open MCT. For more information, see '
|
||||
+ 'https://github.com/nasa/openmct/issues/1568');
|
||||
if (!typeDef.name) {
|
||||
typeDef.name = typeDef.label;
|
||||
}
|
||||
|
@ -30,10 +30,10 @@
|
||||
<div v-if="staticStyle"
|
||||
class="c-inspect-styles__style"
|
||||
>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="isEditing"
|
||||
@persist="updateStaticStyle"
|
||||
<StyleEditor class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="isEditing"
|
||||
@persist="updateStaticStyle"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
@ -87,10 +87,10 @@
|
||||
<condition-description :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
/>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="conditionStyle"
|
||||
:is-editing="isEditing"
|
||||
@persist="updateConditionalStyle"
|
||||
<StyleEditor class="c-inspect-styles__editor"
|
||||
:style-item="conditionStyle"
|
||||
:is-editing="isEditing"
|
||||
@persist="updateConditionalStyle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -240,10 +240,10 @@ export default {
|
||||
}
|
||||
|
||||
let vm = new Vue({
|
||||
components: {ConditionSetSelectorDialog},
|
||||
provide: {
|
||||
openmct: this.openmct
|
||||
},
|
||||
components: {ConditionSetSelectorDialog},
|
||||
data() {
|
||||
return {
|
||||
handleItemSelection
|
||||
|
@ -40,13 +40,13 @@
|
||||
<div v-if="staticStyle"
|
||||
class="c-inspect-styles__style"
|
||||
>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="allowEditing"
|
||||
:mixed-styles="mixedStyles"
|
||||
:non-specific-font-properties="nonSpecificFontProperties"
|
||||
@persist="updateStaticStyle"
|
||||
@save-style="saveStyle"
|
||||
<StyleEditor class="c-inspect-styles__editor"
|
||||
:style-item="staticStyle"
|
||||
:is-editing="allowEditing"
|
||||
:mixed-styles="mixedStyles"
|
||||
:non-specific-font-properties="nonSpecificFontProperties"
|
||||
@persist="updateStaticStyle"
|
||||
@save-style="saveStyle"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
@ -108,12 +108,12 @@
|
||||
<condition-description :show-label="true"
|
||||
:condition="getCondition(conditionStyle.conditionId)"
|
||||
/>
|
||||
<style-editor class="c-inspect-styles__editor"
|
||||
:style-item="conditionStyle"
|
||||
:non-specific-font-properties="nonSpecificFontProperties"
|
||||
:is-editing="allowEditing"
|
||||
@persist="updateConditionalStyle"
|
||||
@save-style="saveStyle"
|
||||
<StyleEditor class="c-inspect-styles__editor"
|
||||
:style-item="conditionStyle"
|
||||
:non-specific-font-properties="nonSpecificFontProperties"
|
||||
:is-editing="allowEditing"
|
||||
@persist="updateConditionalStyle"
|
||||
@save-style="saveStyle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -556,10 +556,10 @@ export default {
|
||||
}
|
||||
|
||||
let vm = new Vue({
|
||||
components: {ConditionSetSelectorDialog},
|
||||
provide: {
|
||||
openmct: this.openmct
|
||||
},
|
||||
components: {ConditionSetSelectorDialog},
|
||||
data() {
|
||||
return {
|
||||
handleItemSelection
|
||||
|
@ -38,12 +38,16 @@ a.c-condition-widget {
|
||||
|
||||
// Make Condition Widget expand when in a hidden frame Layout context
|
||||
// For both static and Flexible Layouts
|
||||
.c-so-view--no-frame > .c-so-view__object-view > .c-condition-widget {
|
||||
@include abs();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
.c-so-view--conditionWidget.c-so-view--no-frame {
|
||||
.c-condition-widget {
|
||||
@include abs();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.c-so-view__frame-controls { display: none; }
|
||||
}
|
||||
|
||||
// Add some margin when a Condition Widget is in a Flexible Layout
|
||||
|
@ -47,8 +47,8 @@
|
||||
|
||||
.is-editing {
|
||||
.l-shell__main-container {
|
||||
&[s-selected],
|
||||
&[s-selected-parent] {
|
||||
[s-selected],
|
||||
[s-selected-parent] {
|
||||
// Display grid and allow edit marquee to display in main layout holder when editing
|
||||
> .l-layout {
|
||||
background: $editUIGridColorBg;
|
||||
|
@ -39,10 +39,13 @@ describe("The Compass component", () => {
|
||||
sunAngle: 30
|
||||
};
|
||||
let propsData = {
|
||||
containerWidth: 600,
|
||||
containerHeight: 600,
|
||||
naturalAspectRatio: 0.9,
|
||||
image: imageDatum
|
||||
image: imageDatum,
|
||||
sizedImageDimensions: {
|
||||
width: 100,
|
||||
height: 100
|
||||
},
|
||||
compassRoseSizingClasses: '--rose-small --rose-min'
|
||||
};
|
||||
|
||||
app = new Vue({
|
||||
@ -51,13 +54,13 @@ describe("The Compass component", () => {
|
||||
return propsData;
|
||||
},
|
||||
template: `<Compass
|
||||
:container-width="containerWidth"
|
||||
:container-height="containerHeight"
|
||||
:compass-rose-sizing-classes="compassRoseSizingClasses"
|
||||
:image="image"
|
||||
:natural-aspect-ratio="naturalAspectRatio"
|
||||
:image="image" />`
|
||||
:sized-image-dimensions="sizedImageDimensions"
|
||||
/>`
|
||||
});
|
||||
instance = app.$mount();
|
||||
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
@ -84,18 +84,18 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-local-controls c-local-controls--show-on-hover c-imagery__prev-next-buttons">
|
||||
<button class="c-nav c-nav--prev"
|
||||
title="Previous image"
|
||||
:disabled="isPrevDisabled"
|
||||
@click="prevImage()"
|
||||
></button>
|
||||
<button class="c-nav c-nav--next"
|
||||
title="Next image"
|
||||
:disabled="isNextDisabled"
|
||||
@click="nextImage()"
|
||||
></button>
|
||||
</div>
|
||||
|
||||
<button class="c-local-controls c-local-controls--show-on-hover c-imagery__prev-next-button c-nav c-nav--prev"
|
||||
title="Previous image"
|
||||
:disabled="isPrevDisabled"
|
||||
@click="prevImage()"
|
||||
></button>
|
||||
|
||||
<button class="c-local-controls c-local-controls--show-on-hover c-imagery__prev-next-button c-nav c-nav--next"
|
||||
title="Next image"
|
||||
:disabled="isNextDisabled"
|
||||
@click="nextImage()"
|
||||
></button>
|
||||
|
||||
<div class="c-imagery__control-bar">
|
||||
<div class="c-imagery__time">
|
||||
|
@ -285,17 +285,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
.c-imagery__prev-next-buttons {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
pointer-events: none;
|
||||
.c-imagery__prev-next-button {
|
||||
pointer-events: all;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-75%);
|
||||
transform: translateY(-75%); // 75% due to transform: rotation approach to the button
|
||||
|
||||
.c-nav {
|
||||
pointer-events: all;
|
||||
&.c-nav {
|
||||
position: absolute;
|
||||
|
||||
&--prev { left: 0; }
|
||||
&--next { right: 0; }
|
||||
}
|
||||
|
||||
.s-status-taking-snapshot & {
|
||||
|
@ -220,7 +220,7 @@ describe("The Imagery View Layouts", () => {
|
||||
});
|
||||
|
||||
spyOn(openmct.telemetry, 'request').and.returnValue(Promise.resolve([]));
|
||||
spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve({}));
|
||||
spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve(imageryObject));
|
||||
|
||||
originalRouterPath = openmct.router.path;
|
||||
|
||||
@ -370,18 +370,15 @@ describe("The Imagery View Layouts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
xit("should show that an image is not new", (done) => {
|
||||
it("should show that an image is not new", (done) => {
|
||||
const target = imageTelemetry[2].url;
|
||||
parent.querySelectorAll(`img[src='${target}']`)[0].click();
|
||||
|
||||
Vue.nextTick(() => {
|
||||
// used in code, need to wait to the 500ms here too
|
||||
setTimeout(() => {
|
||||
const imageIsNew = isNew(parent);
|
||||
const imageIsNew = isNew(parent);
|
||||
|
||||
expect(imageIsNew).toBeFalse();
|
||||
done();
|
||||
}, REFRESH_CSS_MS);
|
||||
expect(imageIsNew).toBeFalse();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -45,8 +45,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="sass">
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import packages from './third-party-licenses.json';
|
||||
|
||||
|
@ -96,6 +96,9 @@ export function setDefaultNotebookPageId(pageId) {
|
||||
|
||||
export function validateNotebookStorageObject() {
|
||||
const notebookStorage = getDefaultNotebook();
|
||||
if (!notebookStorage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let valid = false;
|
||||
if (notebookStorage) {
|
||||
|
@ -34,7 +34,7 @@ describe('the plugin', () => {
|
||||
let countFramesPromise;
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct(false);
|
||||
openmct = createOpenMct();
|
||||
|
||||
element = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
|
@ -49,7 +49,7 @@ describe('the plugin', () => {
|
||||
filter: {},
|
||||
disableObserve: true
|
||||
};
|
||||
openmct = createOpenMct(false);
|
||||
openmct = createOpenMct();
|
||||
|
||||
openmct.$injector = jasmine.createSpyObj('$injector', ['get']);
|
||||
mockIdentifierService = jasmine.createSpyObj(
|
||||
|
@ -36,7 +36,15 @@ describe('the plugin', function () {
|
||||
appHolder.style.width = '640px';
|
||||
appHolder.style.height = '480px';
|
||||
|
||||
openmct = createOpenMct();
|
||||
const timeSystemOptions = {
|
||||
timeSystemKey: 'utc',
|
||||
bounds: {
|
||||
start: 1597160002854,
|
||||
end: 1597181232854
|
||||
}
|
||||
};
|
||||
|
||||
openmct = createOpenMct(timeSystemOptions);
|
||||
openmct.install(new PlanPlugin());
|
||||
|
||||
planDefinition = openmct.types.get('plan').definition;
|
||||
@ -48,7 +56,6 @@ describe('the plugin', function () {
|
||||
child.style.width = '640px';
|
||||
child.style.height = '480px';
|
||||
element.appendChild(child);
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.start(appHolder);
|
||||
});
|
||||
@ -72,7 +79,6 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
describe('the plan view', () => {
|
||||
|
||||
it('provides a plan view', () => {
|
||||
const testViewObject = {
|
||||
id: "test-object",
|
||||
@ -83,7 +89,6 @@ describe('the plugin', function () {
|
||||
let planView = applicableViews.find((viewProvider) => viewProvider.key === 'plan.view');
|
||||
expect(planView).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('the plan view displays activities', () => {
|
||||
@ -155,12 +160,22 @@ describe('the plugin', function () {
|
||||
expect(labelEl.innerHTML).toEqual('TEST-GROUP');
|
||||
});
|
||||
|
||||
it('displays the activities and their labels', () => {
|
||||
const rectEls = element.querySelectorAll('.c-plan__contents rect');
|
||||
expect(rectEls.length).toEqual(2);
|
||||
const textEls = element.querySelectorAll('.c-plan__contents text');
|
||||
expect(textEls.length).toEqual(3);
|
||||
it('displays the activities and their labels', (done) => {
|
||||
const bounds = {
|
||||
start: 1597160002854,
|
||||
end: 1597181232854
|
||||
};
|
||||
|
||||
openmct.time.bounds(bounds);
|
||||
|
||||
Vue.nextTick(() => {
|
||||
const rectEls = element.querySelectorAll('.c-plan__contents rect');
|
||||
expect(rectEls.length).toEqual(2);
|
||||
const textEls = element.querySelectorAll('.c-plan__contents text');
|
||||
expect(textEls.length).toEqual(3);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -39,10 +39,6 @@ export default function BarGraphCompositionPolicy(openmct) {
|
||||
return metadata.values().length > 0 && hasAggregateDomainAndRange(metadata);
|
||||
}
|
||||
|
||||
function hasNoChildren(parentObject) {
|
||||
return parentObject.composition && parentObject.composition.length < 1;
|
||||
}
|
||||
|
||||
return {
|
||||
allow: function (parent, child) {
|
||||
if ((parent.type === BAR_GRAPH_KEY)
|
||||
|
@ -19,6 +19,9 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
|
||||
<template>
|
||||
<div class="gl-plot-chart-area">
|
||||
<span v-html="canvasTemplate"></span>
|
||||
|
@ -37,7 +37,6 @@ describe("the plugin", function () {
|
||||
let openmct;
|
||||
let telemetryPromise;
|
||||
let telemetryPromiseResolve;
|
||||
let cleanupFirst;
|
||||
let mockObjectPath;
|
||||
let telemetrylimitProvider;
|
||||
|
||||
@ -77,9 +76,16 @@ describe("the plugin", function () {
|
||||
'some-other-key': 'some-other-value 3'
|
||||
}
|
||||
];
|
||||
cleanupFirst = [];
|
||||
|
||||
openmct = createOpenMct();
|
||||
const timeSystem = {
|
||||
timeSystemKey: 'utc',
|
||||
bounds: {
|
||||
start: 0,
|
||||
end: 4
|
||||
}
|
||||
};
|
||||
|
||||
openmct = createOpenMct(timeSystem);
|
||||
|
||||
telemetryPromise = new Promise((resolve) => {
|
||||
telemetryPromiseResolve = resolve;
|
||||
@ -146,11 +152,6 @@ describe("the plugin", function () {
|
||||
disconnect() {}
|
||||
});
|
||||
|
||||
openmct.time.timeSystem("utc", {
|
||||
start: 0,
|
||||
end: 4
|
||||
});
|
||||
|
||||
openmct.types.addType("test-object", {
|
||||
creatable: true
|
||||
});
|
||||
@ -170,19 +171,8 @@ describe("the plugin", function () {
|
||||
end: 1
|
||||
});
|
||||
|
||||
// Needs to be in a timeout because plots use a bunch of setTimeouts, some of which can resolve during or after
|
||||
// teardown, which causes problems
|
||||
// This is hacky, we should find a better approach here.
|
||||
setTimeout(() => {
|
||||
//Cleanup code that needs to happen before dom elements start being destroyed
|
||||
cleanupFirst.forEach(cleanup => cleanup());
|
||||
cleanupFirst = [];
|
||||
document.body.removeChild(element);
|
||||
|
||||
configStore.deleteAll();
|
||||
|
||||
resetApplicationState(openmct).then(done).catch(done);
|
||||
});
|
||||
configStore.deleteAll();
|
||||
resetApplicationState(openmct).then(done).catch(done);
|
||||
});
|
||||
|
||||
describe("the plot views", () => {
|
||||
@ -395,10 +385,6 @@ describe("the plugin", function () {
|
||||
plotView = plotViewProvider.view(testTelemetryObject, [testTelemetryObject]);
|
||||
plotView.show(child, true);
|
||||
|
||||
cleanupFirst.push(() => {
|
||||
plotView.destroy();
|
||||
});
|
||||
|
||||
return Vue.nextTick();
|
||||
});
|
||||
|
||||
@ -418,12 +404,23 @@ describe("the plugin", function () {
|
||||
expect(legend.length).toBe(6);
|
||||
});
|
||||
|
||||
it("Renders X-axis ticks for the telemetry object", () => {
|
||||
let xAxisElement = element.querySelectorAll(".gl-plot-axis-area.gl-plot-x .gl-plot-tick-wrapper");
|
||||
expect(xAxisElement.length).toBe(1);
|
||||
it("Renders X-axis ticks for the telemetry object", (done) => {
|
||||
const configId = openmct.objects.makeKeyString(testTelemetryObject.identifier);
|
||||
const config = configStore.get(configId);
|
||||
config.xAxis.set('displayRange', {
|
||||
min: 0,
|
||||
max: 4
|
||||
});
|
||||
|
||||
let ticks = xAxisElement[0].querySelectorAll(".gl-plot-tick");
|
||||
expect(ticks.length).toBe(5);
|
||||
Vue.nextTick(() => {
|
||||
let xAxisElement = element.querySelectorAll(".gl-plot-axis-area.gl-plot-x .gl-plot-tick-wrapper");
|
||||
expect(xAxisElement.length).toBe(1);
|
||||
|
||||
let ticks = xAxisElement[0].querySelectorAll(".gl-plot-tick");
|
||||
expect(ticks.length).toBe(5);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Renders Y-axis options for the telemetry object", () => {
|
||||
@ -750,11 +747,6 @@ describe("the plugin", function () {
|
||||
template: "<stacked-plot></stacked-plot>"
|
||||
});
|
||||
|
||||
cleanupFirst.push(() => {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
});
|
||||
|
||||
return telemetryPromise
|
||||
.then(Vue.nextTick())
|
||||
.then(() => {
|
||||
@ -780,12 +772,21 @@ describe("the plugin", function () {
|
||||
expect(legend.length).toBe(6);
|
||||
});
|
||||
|
||||
xit("Renders X-axis ticks for the telemetry object", () => {
|
||||
it("Renders X-axis ticks for the telemetry object", (done) => {
|
||||
let xAxisElement = element.querySelectorAll(".gl-plot-axis-area.gl-plot-x .gl-plot-tick-wrapper");
|
||||
expect(xAxisElement.length).toBe(1);
|
||||
|
||||
let ticks = xAxisElement[0].querySelectorAll(".gl-plot-tick");
|
||||
expect(ticks.length).toBe(5);
|
||||
config.xAxis.set('displayRange', {
|
||||
min: 0,
|
||||
max: 4
|
||||
});
|
||||
|
||||
Vue.nextTick(() => {
|
||||
let ticks = xAxisElement[0].querySelectorAll(".gl-plot-tick");
|
||||
expect(ticks.length).toBe(5);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Renders Y-axis ticks for the telemetry object", (done) => {
|
||||
|
@ -52,22 +52,24 @@
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<stacked-plot-item v-for="object in compositionObjects"
|
||||
:key="object.id"
|
||||
class="c-plot--stacked-container"
|
||||
:object="object"
|
||||
:options="options"
|
||||
:grid-lines="gridLines"
|
||||
:cursor-guide="cursorGuide"
|
||||
:plot-tick-width="maxTickWidth"
|
||||
@plotTickWidth="onTickWidthChange"
|
||||
@loadingUpdated="loadingUpdated"
|
||||
/>
|
||||
<div class="l-view-section">
|
||||
<stacked-plot-item v-for="object in compositionObjects"
|
||||
:key="object.id"
|
||||
class="c-plot--stacked-container"
|
||||
:object="object"
|
||||
:options="options"
|
||||
:grid-lines="gridLines"
|
||||
:cursor-guide="cursorGuide"
|
||||
:plot-tick-width="maxTickWidth"
|
||||
@plotTickWidth="onTickWidthChange"
|
||||
@loadingUpdated="loadingUpdated"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import eventHelpers from '../lib/eventHelpers';
|
||||
|
||||
import StackedPlotItem from './StackedPlotItem.vue';
|
||||
import ImageExporter from '../../../exporters/ImageExporter';
|
||||
|
||||
@ -102,8 +104,6 @@ export default {
|
||||
this.destroy();
|
||||
},
|
||||
mounted() {
|
||||
eventHelpers.extend(this);
|
||||
|
||||
this.imageExporter = new ImageExporter(this.openmct);
|
||||
|
||||
this.tickWidthMap = {};
|
||||
@ -118,7 +118,6 @@ export default {
|
||||
this.loading = loaded;
|
||||
},
|
||||
destroy() {
|
||||
this.stopListening();
|
||||
this.composition.off('add', this.addChild);
|
||||
this.composition.off('remove', this.removeChild);
|
||||
this.composition.off('reorder', this.compositionReorder);
|
||||
|
@ -75,6 +75,11 @@ export default {
|
||||
mounted() {
|
||||
this.updateView();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.component) {
|
||||
this.component.$destroy();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateComponentProp(prop, value) {
|
||||
if (this.component) {
|
||||
|
@ -48,17 +48,17 @@ define([
|
||||
components: {
|
||||
TabsComponent: TabsComponent.default
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: editMode
|
||||
};
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
domainObject,
|
||||
objectPath,
|
||||
composition: openmct.composition.get(domainObject)
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: editMode
|
||||
};
|
||||
},
|
||||
template: '<tabs-component :isEditing="isEditing"></tabs-component>'
|
||||
});
|
||||
},
|
||||
|
@ -528,7 +528,6 @@ export default {
|
||||
if (!this.updatingView) {
|
||||
this.updatingView = true;
|
||||
requestAnimationFrame(() => {
|
||||
|
||||
let start = 0;
|
||||
let end = VISIBLE_ROW_COUNT;
|
||||
let tableRows = this.table.tableRows.getRows();
|
||||
|
@ -222,9 +222,13 @@ describe("the plugin", () => {
|
||||
openmct.router.path = originalRouterPath;
|
||||
});
|
||||
|
||||
it("Renders a row for every telemetry datum returned", () => {
|
||||
it("Renders a row for every telemetry datum returned", (done) => {
|
||||
let rows = element.querySelectorAll('table.c-telemetry-table__body tr');
|
||||
expect(rows.length).toBe(3);
|
||||
Vue.nextTick(() => {
|
||||
expect(rows.length).toBe(3);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Renders a column for every item in telemetry metadata", () => {
|
||||
|
@ -168,13 +168,16 @@ export default {
|
||||
}
|
||||
},
|
||||
zoom(bounds) {
|
||||
this.isZooming = true;
|
||||
this.formattedBounds.start = this.timeFormatter.format(bounds.start);
|
||||
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
|
||||
if (isNaN(bounds.start) || isNaN(bounds.end)) {
|
||||
this.isZooming = false;
|
||||
} else {
|
||||
this.isZooming = true;
|
||||
this.formattedBounds.start = this.timeFormatter.format(bounds.start);
|
||||
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
|
||||
}
|
||||
},
|
||||
endZoom(bounds) {
|
||||
this.isZooming = false;
|
||||
|
||||
if (bounds) {
|
||||
this.openmct.time.bounds(bounds);
|
||||
} else {
|
||||
|
@ -40,7 +40,7 @@ const LOCAL_STORAGE_HISTORY_KEY_FIXED = 'tcHistory';
|
||||
const LOCAL_STORAGE_HISTORY_KEY_REALTIME = 'tcHistoryRealtime';
|
||||
const DEFAULT_RECORDS = 10;
|
||||
|
||||
import { getDuration } from "utils/duration";
|
||||
import { millisecondsToDHMS } from "utils/duration";
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'configuration'],
|
||||
@ -142,7 +142,7 @@ export default {
|
||||
let description = `${startTime} - ${this.formatTime(timespan.end)}`;
|
||||
|
||||
if (this.timeSystem.isUTCBased && !this.openmct.time.clock()) {
|
||||
name = `${startTime} ${getDuration(timespan.end - timespan.start)}`;
|
||||
name = `${startTime} ${millisecondsToDHMS(timespan.end - timespan.start)}`;
|
||||
} else {
|
||||
name = description;
|
||||
}
|
||||
@ -263,7 +263,7 @@ export default {
|
||||
format: format
|
||||
}).formatter;
|
||||
|
||||
return (isNegativeOffset ? '-' : '') + formatter.format(time);
|
||||
return (isNegativeOffset ? '-' : '') + formatter.format(time, 'YYYY-MM-DD HH:mm:ss');
|
||||
},
|
||||
showHistoryMenu() {
|
||||
const elementBoundingClientRect = this.$refs.historyButton.getBoundingClientRect();
|
||||
|
@ -51,7 +51,15 @@ describe('the plugin', function () {
|
||||
}
|
||||
];
|
||||
|
||||
openmct = createOpenMct();
|
||||
const timeSystem = {
|
||||
timeSystemKey: 'utc',
|
||||
bounds: {
|
||||
start: 1597160002854,
|
||||
end: 1597181232854
|
||||
}
|
||||
};
|
||||
|
||||
openmct = createOpenMct(timeSystem);
|
||||
openmct.install(new TimelinePlugin());
|
||||
|
||||
objectDef = openmct.types.get('time-strip').definition;
|
||||
@ -64,11 +72,6 @@ describe('the plugin', function () {
|
||||
child.style.height = '480px';
|
||||
element.appendChild(child);
|
||||
|
||||
openmct.time.timeSystem('utc', {
|
||||
start: 1597160002854,
|
||||
end: 1597181232854
|
||||
});
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
@ -88,7 +91,6 @@ describe('the plugin', function () {
|
||||
});
|
||||
|
||||
describe('the time-strip object', () => {
|
||||
|
||||
it('is creatable', () => {
|
||||
expect(objectDef.creatable).toEqual(mockObject.creatable);
|
||||
});
|
||||
|
@ -453,12 +453,16 @@ select {
|
||||
}
|
||||
}
|
||||
|
||||
.c-so-view--no-frame > .c-so-view__object-view > .c-hyperlink--button {
|
||||
.c-so-view--hyperlink.c-so-view--no-frame {
|
||||
.c-hyperlink--button {
|
||||
@include abs();
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.c-so-view__frame-controls { display: none; }
|
||||
}
|
||||
|
||||
/******************************************************** MENUS */
|
||||
@ -1006,6 +1010,9 @@ input[type="range"] {
|
||||
transition: $transIn;
|
||||
opacity: 1;
|
||||
pointer-events: inherit;
|
||||
|
||||
&[disabled] { opacity: $controlDisabledOpacity; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,6 @@ mct-plot {
|
||||
|
||||
.c-plot,
|
||||
.gl-plot {
|
||||
overflow: hidden;
|
||||
min-height: 100px;
|
||||
|
||||
.s-status-taking-snapshot & {
|
||||
.c-control-bar {
|
||||
display: none;
|
||||
@ -67,16 +64,17 @@ mct-plot {
|
||||
|
||||
.c-plot {
|
||||
@include abs($mainViewPad);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
min-height: $plotMinH;
|
||||
|
||||
.c-control-bar {
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: $interiorMargin;
|
||||
}
|
||||
|
||||
.l-view-section, .c-plot--stacked-container {
|
||||
.l-view-section {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
@ -84,7 +82,18 @@ mct-plot {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.c-plot--stacked-container {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
min-height: $plotMinH;
|
||||
overflow: hidden;
|
||||
}
|
||||
;
|
||||
|
||||
&--stacked {
|
||||
min-height: auto !important;
|
||||
|
||||
.child-frame {
|
||||
.has-control-bar {
|
||||
.c-control-bar {
|
||||
@ -124,7 +133,7 @@ mct-plot {
|
||||
.plot-wrapper-axis-and-display-area {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
min-height: $plotMinH;
|
||||
//min-height: $plotMinH;
|
||||
}
|
||||
|
||||
.gl-plot-wrapper-display-area-and-x-axis {
|
||||
@ -465,6 +474,7 @@ mct-plot {
|
||||
.gl-plot-legend,
|
||||
.c-plot-legend {
|
||||
overflow: hidden;
|
||||
flex: 0 0 auto; // Prevents clipping for all legend placements (top, bottom, etc.)
|
||||
|
||||
&__wrapper {
|
||||
// Holds view-control and both collapsed and expanded legends
|
||||
|
@ -599,8 +599,6 @@
|
||||
@mixin cArrowButtonBase($colorBg: transparent, $colorFg: $colorBtnFg, $filterHov: $filterHov) {
|
||||
// Copied from branch new-tree-refactor
|
||||
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
background: $colorBg;
|
||||
|
||||
&:before {
|
||||
|
@ -54,15 +54,15 @@ export default {
|
||||
let viewContainer = document.createElement('div');
|
||||
this.$el.append(viewContainer);
|
||||
this.component = new Vue({
|
||||
el: viewContainer,
|
||||
components: {
|
||||
StylesView
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct,
|
||||
selection: selection,
|
||||
stylesManager: this.stylesManager
|
||||
},
|
||||
el: viewContainer,
|
||||
components: {
|
||||
StylesView
|
||||
},
|
||||
template: '<styles-view/>'
|
||||
});
|
||||
}
|
||||
|
@ -42,10 +42,10 @@ export default {
|
||||
methods: {
|
||||
launchAbout() {
|
||||
let vm = new Vue({
|
||||
components: {AboutDialog},
|
||||
provide: {
|
||||
openmct: this.openmct
|
||||
},
|
||||
components: {AboutDialog},
|
||||
template: '<about-dialog></about-dialog>'
|
||||
}).$mount();
|
||||
|
||||
|
@ -6,133 +6,74 @@ let child;
|
||||
let appHolder;
|
||||
let resolveFunction;
|
||||
|
||||
let initialHash = '';
|
||||
|
||||
xdescribe('Application router utility functions', () => {
|
||||
beforeAll(done => {
|
||||
describe('Application router utility functions', () => {
|
||||
beforeEach(done => {
|
||||
appHolder = document.createElement('div');
|
||||
appHolder.style.width = '640px';
|
||||
appHolder.style.height = '480px';
|
||||
|
||||
openmct = createOpenMct();
|
||||
openmct.install(openmct.plugins.MyItems());
|
||||
openmct.install(openmct.plugins.LocalTimeSystem());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
|
||||
element = document.createElement('div');
|
||||
child = document.createElement('div');
|
||||
element.appendChild(child);
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.on('start', () => {
|
||||
resolveFunction = () => {
|
||||
const success = window.location.hash !== null && window.location.hash !== '';
|
||||
if (success) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
openmct.router.on('change:hash', resolveFunction);
|
||||
openmct.router.setLocationFromUrl();
|
||||
});
|
||||
|
||||
openmct.start(appHolder);
|
||||
|
||||
document.body.append(appHolder);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
openmct.router.setHash(initialHash);
|
||||
afterEach(() => {
|
||||
openmct.router.removeListener('change:hash', resolveFunction);
|
||||
appHolder.remove();
|
||||
|
||||
return resetApplicationState(openmct);
|
||||
});
|
||||
|
||||
it('has initial hash when loaded', (done) => {
|
||||
let success;
|
||||
resolveFunction = () => {
|
||||
openmct.router.setLocationFromUrl();
|
||||
success = window.location.hash !== null;
|
||||
if (success) {
|
||||
initialHash = window.location.hash;
|
||||
expect(success).toBe(true);
|
||||
|
||||
openmct.router.removeListener('change:hash', resolveFunction);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
openmct.router.on('change:hash', resolveFunction);
|
||||
it('has initial hash when loaded', () => {
|
||||
const success = window.location.hash !== null;
|
||||
expect(success).toBe(true);
|
||||
});
|
||||
|
||||
it('The setSearchParam function sets an individual search parameter in the window location hash', (done) => {
|
||||
let success;
|
||||
it('The setSearchParam function sets an individual search parameter in the window location hash', () => {
|
||||
openmct.router.setSearchParam('testParam', 'testValue');
|
||||
resolveFunction = () => {
|
||||
success = window.location.hash.includes('testParam=testValue');
|
||||
if (success) {
|
||||
expect(success).toBe(true);
|
||||
|
||||
openmct.router.removeListener('change:hash', resolveFunction);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
openmct.router.on('change:hash', resolveFunction);
|
||||
const searchParams = openmct.router.getAllSearchParams();
|
||||
expect(searchParams.get('testParam')).toBe('testValue');
|
||||
});
|
||||
|
||||
it('The getSearchParam function returns the value of an individual search parameter in the window location hash', () => {
|
||||
expect(openmct.router.getSearchParam('testParam')).toBe('testValue');
|
||||
});
|
||||
|
||||
it('The deleteSearchParam function deletes an individual search parameter in the window location hash', (done) => {
|
||||
let success;
|
||||
it('The deleteSearchParam function deletes an individual search paramater in the window location hash', () => {
|
||||
openmct.router.deleteSearchParam('testParam');
|
||||
resolveFunction = () => {
|
||||
success = window.location.hash.includes('testParam=testValue') === false;
|
||||
if (success) {
|
||||
expect(success).toBe(true);
|
||||
|
||||
openmct.router.removeListener('change:hash', resolveFunction);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
openmct.router.on('change:hash', resolveFunction);
|
||||
const searchParams = openmct.router.getAllSearchParams();
|
||||
expect(searchParams.get('testParam')).toBe(null);
|
||||
});
|
||||
|
||||
it('The setSearchParam function sets an individual search parameters in the window location hash', (done) => {
|
||||
let success;
|
||||
it('The setSearchParam function sets a multiple individual search parameters in the window location hash', () => {
|
||||
openmct.router.setSearchParam('testParam1', 'testValue1');
|
||||
openmct.router.setSearchParam('testParam2', 'testValue2');
|
||||
|
||||
resolveFunction = () => {
|
||||
const hasTestParam1 = window.location.hash.includes('testParam1=testValue1');
|
||||
const hasTestParam2 = window.location.hash.includes('testParam2=testValue2');
|
||||
success = hasTestParam1 && hasTestParam2;
|
||||
if (success) {
|
||||
expect(success).toBe(true);
|
||||
|
||||
openmct.router.removeListener('change:hash', resolveFunction);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
openmct.router.on('change:hash', resolveFunction);
|
||||
const searchParams = openmct.router.getAllSearchParams();
|
||||
expect(searchParams.get('testParam1')).toBe('testValue1');
|
||||
expect(searchParams.get('testParam2')).toBe('testValue2');
|
||||
});
|
||||
|
||||
it('The setAllSearchParams function replaces all search parameters in the window location hash', (done) => {
|
||||
let success;
|
||||
|
||||
it('The setAllSearchParams function replaces all search paramaters in the window location hash', () => {
|
||||
openmct.router.setSearchParam('testParam2', 'updatedtestValue2');
|
||||
openmct.router.setSearchParam('newTestParam3', 'newTestValue3');
|
||||
|
||||
resolveFunction = () => {
|
||||
const hasupdatedValueForTestParam2 = window.location.hash.includes('testParam2=updatedtestValue2');
|
||||
const hasNewTestParam3 = window.location.hash.includes('newTestParam3=newTestValue3');
|
||||
success = hasupdatedValueForTestParam2 && hasNewTestParam3;
|
||||
if (success) {
|
||||
expect(success).toBe(true);
|
||||
|
||||
openmct.router.removeListener('change:hash', resolveFunction);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
openmct.router.on('change:hash', resolveFunction);
|
||||
});
|
||||
|
||||
it('The getAllSearchParams function returns the values of all search parameters in the window location hash', () => {
|
||||
let searchParams = openmct.router.getAllSearchParams();
|
||||
expect(searchParams.get('testParam1')).toBe('testValue1');
|
||||
const searchParams = openmct.router.getAllSearchParams();
|
||||
expect(searchParams.get('testParam2')).toBe('updatedtestValue2');
|
||||
expect(searchParams.get('newTestParam3')).toBe('newTestValue3');
|
||||
});
|
||||
|
@ -119,11 +119,16 @@ define([
|
||||
function navigateToFirstChildOfRoot() {
|
||||
openmct.objects.get('ROOT')
|
||||
.then(rootObject => {
|
||||
openmct.composition.get(rootObject).load()
|
||||
const composition = openmct.composition.get(rootObject);
|
||||
if (!composition) {
|
||||
return;
|
||||
}
|
||||
|
||||
composition.load()
|
||||
.then(children => {
|
||||
let lastChild = children[children.length - 1];
|
||||
if (!lastChild) {
|
||||
console.error('Unable to navigate to anything. No root objects found.');
|
||||
console.debug('Unable to navigate to anything. No root objects found.');
|
||||
} else {
|
||||
let lastChildId = openmct.objects.makeKeyString(lastChild.identifier);
|
||||
openmct.router.setPath(`#/browse/${lastChildId}`);
|
||||
|
@ -20,7 +20,8 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
const ONE_SECOND = 1000;
|
||||
const ONE_MINUTE = 60 * ONE_SECOND;
|
||||
const ONE_HOUR = ONE_MINUTE * 60;
|
||||
const ONE_DAY = ONE_HOUR * 24;
|
||||
|
||||
@ -39,34 +40,20 @@ function toDoubleDigits(num) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getDuration(numericDuration) {
|
||||
let result;
|
||||
let age;
|
||||
function addTimeSuffix(value, suffix) {
|
||||
return typeof value === 'number' && value > 0 ? `${value + suffix}` : '';
|
||||
}
|
||||
|
||||
if (numericDuration > ONE_DAY - 1) {
|
||||
age = normalizeAge((numericDuration / ONE_DAY)).toFixed(2);
|
||||
result = `+ ${age} day`;
|
||||
export function millisecondsToDHMS(numericDuration) {
|
||||
const ms = numericDuration || 0;
|
||||
const dhms = [
|
||||
addTimeSuffix(Math.floor(normalizeAge(ms / ONE_DAY)), 'd'),
|
||||
addTimeSuffix(Math.floor(normalizeAge((ms % ONE_DAY) / ONE_HOUR)), 'h'),
|
||||
addTimeSuffix(Math.floor(normalizeAge((ms % ONE_HOUR) / ONE_MINUTE)), 'm'),
|
||||
addTimeSuffix(Math.floor(normalizeAge((ms % ONE_MINUTE) / ONE_SECOND)), 's')
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
} else if (numericDuration > ONE_HOUR - 1) {
|
||||
age = normalizeAge((numericDuration / ONE_HOUR).toFixed(2));
|
||||
result = `+ ${age} hour`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
} else {
|
||||
age = normalizeAge((numericDuration / ONE_MINUTE).toFixed(2));
|
||||
result = `+ ${age} min`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return `${ dhms ? '+' : ''} ${dhms}`;
|
||||
}
|
||||
|
||||
export function getPreciseDuration(numericDuration) {
|
||||
|
@ -25,13 +25,26 @@ import MCT from 'MCT';
|
||||
let nativeFunctions = [];
|
||||
let mockObjects = setMockObjects();
|
||||
|
||||
export function createOpenMct() {
|
||||
const DEFAULT_TIME_OPTIONS = {
|
||||
timeSystemKey: 'utc',
|
||||
bounds: {
|
||||
start: 0,
|
||||
end: 1
|
||||
}
|
||||
};
|
||||
|
||||
export function createOpenMct(timeSystemOptions = DEFAULT_TIME_OPTIONS) {
|
||||
const openmct = new MCT();
|
||||
openmct.install(openmct.plugins.LocalStorage());
|
||||
openmct.install(openmct.plugins.UTCTimeSystem());
|
||||
openmct.time.timeSystem('utc', {
|
||||
start: 0,
|
||||
end: 1
|
||||
|
||||
const timeSystemKey = timeSystemOptions.timeSystemKey;
|
||||
const start = timeSystemOptions.bounds.start;
|
||||
const end = timeSystemOptions.bounds.end;
|
||||
|
||||
openmct.time.timeSystem(timeSystemKey, {
|
||||
start,
|
||||
end
|
||||
});
|
||||
|
||||
return openmct;
|
||||
|
Reference in New Issue
Block a user