mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57:53 +00:00
Fix complex displays not loading (#7858)
Clock * pass in default timeContext in request options * observe for clock tick, instead of polling, to determine if clock has time set Progress Bars * use scale instead of move animation Plan * use a ResizeObserver instead of polling for size changes --------- Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov> Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com> Co-authored-by: Charles Hacskaylo <charles.f.hacskaylo@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
83e4a124e2
commit
4415fe7952
@ -231,26 +231,20 @@ export default class TelemetryAPI {
|
|||||||
* @returns {TelemetryRequestOptions} the options, with defaults filled in
|
* @returns {TelemetryRequestOptions} the options, with defaults filled in
|
||||||
*/
|
*/
|
||||||
standardizeRequestOptions(options = {}) {
|
standardizeRequestOptions(options = {}) {
|
||||||
if (!Object.hasOwn(options, 'start')) {
|
if (!Object.hasOwn(options, 'timeContext')) {
|
||||||
const bounds = options.timeContext?.getBounds();
|
options.timeContext = this.openmct.time;
|
||||||
if (bounds?.start) {
|
|
||||||
options.start = options.timeContext.getBounds().start;
|
|
||||||
} else {
|
|
||||||
options.start = this.openmct.time.getBounds().start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Object.hasOwn(options, 'end')) {
|
|
||||||
const bounds = options.timeContext?.getBounds();
|
|
||||||
if (bounds?.end) {
|
|
||||||
options.end = options.timeContext.getBounds().end;
|
|
||||||
} else {
|
|
||||||
options.end = this.openmct.time.getBounds().end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Object.hasOwn(options, 'domain')) {
|
if (!Object.hasOwn(options, 'domain')) {
|
||||||
options.domain = this.openmct.time.getTimeSystem().key;
|
options.domain = options.timeContext.getTimeSystem().key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.hasOwn(options, 'start')) {
|
||||||
|
options.start = options.timeContext.getBounds().start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.hasOwn(options, 'end')) {
|
||||||
|
options.end = options.timeContext.getBounds().end;
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
@ -269,36 +269,40 @@ describe('Telemetry API', () => {
|
|||||||
|
|
||||||
await telemetryAPI.request(domainObject);
|
await telemetryAPI.request(domainObject);
|
||||||
const { signal } = new AbortController();
|
const { signal } = new AbortController();
|
||||||
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(jasmine.any(Object), {
|
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(domainObject, {
|
||||||
signal,
|
signal,
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 1,
|
end: 1,
|
||||||
domain: 'system'
|
domain: 'system',
|
||||||
|
timeContext: openmct.time
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(telemetryProvider.request).toHaveBeenCalledWith(jasmine.any(Object), {
|
expect(telemetryProvider.request).toHaveBeenCalledWith(domainObject, {
|
||||||
signal,
|
signal,
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 1,
|
end: 1,
|
||||||
domain: 'system'
|
domain: 'system',
|
||||||
|
timeContext: openmct.time
|
||||||
});
|
});
|
||||||
|
|
||||||
telemetryProvider.supportsRequest.calls.reset();
|
telemetryProvider.supportsRequest.calls.reset();
|
||||||
telemetryProvider.request.calls.reset();
|
telemetryProvider.request.calls.reset();
|
||||||
|
|
||||||
await telemetryAPI.request(domainObject, {});
|
await telemetryAPI.request(domainObject, {});
|
||||||
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(jasmine.any(Object), {
|
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(domainObject, {
|
||||||
signal,
|
signal,
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 1,
|
end: 1,
|
||||||
domain: 'system'
|
domain: 'system',
|
||||||
|
timeContext: openmct.time
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(telemetryProvider.request).toHaveBeenCalledWith(jasmine.any(Object), {
|
expect(telemetryProvider.request).toHaveBeenCalledWith(domainObject, {
|
||||||
signal,
|
signal,
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 1,
|
end: 1,
|
||||||
domain: 'system'
|
domain: 'system',
|
||||||
|
timeContext: openmct.time
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -313,18 +317,20 @@ describe('Telemetry API', () => {
|
|||||||
domain: 'someDomain'
|
domain: 'someDomain'
|
||||||
});
|
});
|
||||||
const { signal } = new AbortController();
|
const { signal } = new AbortController();
|
||||||
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(jasmine.any(Object), {
|
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(domainObject, {
|
||||||
start: 20,
|
start: 20,
|
||||||
end: 30,
|
end: 30,
|
||||||
domain: 'someDomain',
|
domain: 'someDomain',
|
||||||
signal
|
signal,
|
||||||
|
timeContext: openmct.time
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(telemetryProvider.request).toHaveBeenCalledWith(jasmine.any(Object), {
|
expect(telemetryProvider.request).toHaveBeenCalledWith(domainObject, {
|
||||||
start: 20,
|
start: 20,
|
||||||
end: 30,
|
end: 30,
|
||||||
domain: 'someDomain',
|
domain: 'someDomain',
|
||||||
signal
|
signal,
|
||||||
|
timeContext: openmct.time
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('telemetry batching support', () => {
|
describe('telemetry batching support', () => {
|
||||||
|
@ -62,9 +62,6 @@ export default class TelemetryCollection extends EventEmitter {
|
|||||||
this.futureBuffer = [];
|
this.futureBuffer = [];
|
||||||
this.parseTime = undefined;
|
this.parseTime = undefined;
|
||||||
this.metadata = this.openmct.telemetry.getMetadata(domainObject);
|
this.metadata = this.openmct.telemetry.getMetadata(domainObject);
|
||||||
if (!Object.hasOwn(options, 'timeContext')) {
|
|
||||||
options.timeContext = this.openmct.time;
|
|
||||||
}
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.unsubscribe = undefined;
|
this.unsubscribe = undefined;
|
||||||
this.pageState = undefined;
|
this.pageState = undefined;
|
||||||
@ -84,6 +81,9 @@ export default class TelemetryCollection extends EventEmitter {
|
|||||||
this._error(LOADED_ERROR);
|
this._error(LOADED_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Object.hasOwn(this.options, 'timeContext')) {
|
||||||
|
this.options.timeContext = this.openmct.time;
|
||||||
|
}
|
||||||
this._setTimeSystem(this.options.timeContext.getTimeSystem());
|
this._setTimeSystem(this.options.timeContext.getTimeSystem());
|
||||||
this.lastBounds = this.options.timeContext.getBounds();
|
this.lastBounds = this.options.timeContext.getBounds();
|
||||||
this._watchBounds();
|
this._watchBounds();
|
||||||
@ -127,7 +127,7 @@ export default class TelemetryCollection extends EventEmitter {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
async _requestHistoricalTelemetry() {
|
async _requestHistoricalTelemetry() {
|
||||||
let options = this.openmct.telemetry.standardizeRequestOptions({ ...this.options });
|
const options = this.openmct.telemetry.standardizeRequestOptions({ ...this.options });
|
||||||
const historicalProvider = this.openmct.telemetry.findRequestProvider(
|
const historicalProvider = this.openmct.telemetry.findRequestProvider(
|
||||||
this.domainObject,
|
this.domainObject,
|
||||||
options
|
options
|
||||||
|
@ -69,7 +69,6 @@ const INNER_TEXT_PADDING = 15;
|
|||||||
const TEXT_LEFT_PADDING = 5;
|
const TEXT_LEFT_PADDING = 5;
|
||||||
const ROW_PADDING = 5;
|
const ROW_PADDING = 5;
|
||||||
const SWIMLANE_PADDING = 3;
|
const SWIMLANE_PADDING = 3;
|
||||||
const RESIZE_POLL_INTERVAL = 200;
|
|
||||||
const ROW_HEIGHT = 22;
|
const ROW_HEIGHT = 22;
|
||||||
const MAX_TEXT_WIDTH = 300;
|
const MAX_TEXT_WIDTH = 300;
|
||||||
const MIN_ACTIVITY_WIDTH = 2;
|
const MIN_ACTIVITY_WIDTH = 2;
|
||||||
@ -143,13 +142,15 @@ export default {
|
|||||||
this.canvasContext = canvas.getContext('2d');
|
this.canvasContext = canvas.getContext('2d');
|
||||||
this.setDimensions();
|
this.setDimensions();
|
||||||
this.setTimeContext();
|
this.setTimeContext();
|
||||||
this.resizeTimer = setInterval(this.resize, RESIZE_POLL_INTERVAL);
|
|
||||||
this.handleConfigurationChange(this.configuration);
|
this.handleConfigurationChange(this.configuration);
|
||||||
this.planViewConfiguration.on('change', this.handleConfigurationChange);
|
this.planViewConfiguration.on('change', this.handleConfigurationChange);
|
||||||
this.loadComposition();
|
this.loadComposition();
|
||||||
|
|
||||||
|
this.resizeObserver = new ResizeObserver(this.resize);
|
||||||
|
this.resizeObserver.observe(this.$refs.plan);
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
clearInterval(this.resizeTimer);
|
this.resizeObserver.disconnect();
|
||||||
this.stopFollowingTimeContext();
|
this.stopFollowingTimeContext();
|
||||||
if (this.unlisten) {
|
if (this.unlisten) {
|
||||||
this.unlisten();
|
this.unlisten();
|
||||||
|
@ -152,15 +152,18 @@ export default class RemoteClock extends DefaultClock {
|
|||||||
*/
|
*/
|
||||||
#waitForReady() {
|
#waitForReady() {
|
||||||
const waitForInitialTick = (resolve) => {
|
const waitForInitialTick = (resolve) => {
|
||||||
if (this.lastTick > 0) {
|
const tickListener = () => {
|
||||||
const offsets = this.openmct.time.getClockOffsets();
|
if (this.lastTick > 0) {
|
||||||
resolve({
|
const offsets = this.openmct.time.getClockOffsets();
|
||||||
start: this.lastTick + offsets.start,
|
this.openmct.time.off('tick', tickListener); // Unregister the tick listener
|
||||||
end: this.lastTick + offsets.end
|
resolve({
|
||||||
});
|
start: this.lastTick + offsets.start,
|
||||||
} else {
|
end: this.lastTick + offsets.end
|
||||||
setTimeout(() => waitForInitialTick(resolve), 100);
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.openmct.time.on('tick', tickListener);
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Promise(waitForInitialTick);
|
return new Promise(waitForInitialTick);
|
||||||
|
@ -20,16 +20,43 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepts requests to ensure the remote clock is ready.
|
||||||
|
*
|
||||||
|
* @param {import('../../openmct').OpenMCT} openmct - The OpenMCT instance.
|
||||||
|
* @param {import('../../openmct').Identifier} _remoteClockIdentifier - The identifier for the remote clock.
|
||||||
|
* @param {Function} waitForBounds - A function that returns a promise resolving to the initial bounds.
|
||||||
|
* @returns {Object} The request interceptor.
|
||||||
|
*/
|
||||||
function remoteClockRequestInterceptor(openmct, _remoteClockIdentifier, waitForBounds) {
|
function remoteClockRequestInterceptor(openmct, _remoteClockIdentifier, waitForBounds) {
|
||||||
let remoteClockLoaded = false;
|
let remoteClockLoaded = false;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
appliesTo: () => {
|
/**
|
||||||
|
* Determines if the interceptor applies to the given request.
|
||||||
|
*
|
||||||
|
* @param {Object} _ - Unused parameter.
|
||||||
|
* @param {import('../../api/telemetry/TelemetryAPI').TelemetryRequestOptions} request - The request object.
|
||||||
|
* @returns {boolean} True if the interceptor applies, false otherwise.
|
||||||
|
*/
|
||||||
|
appliesTo: (_, request) => {
|
||||||
// Get the activeClock from the Global Time Context
|
// Get the activeClock from the Global Time Context
|
||||||
|
/** @type {import("../../api/time/TimeContext").default} */
|
||||||
const { activeClock } = openmct.time;
|
const { activeClock } = openmct.time;
|
||||||
|
|
||||||
|
// this type of request does not rely on clock having bounds
|
||||||
|
if (request.strategy === 'latest' && request.timeContext.isRealTime()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return activeClock?.key === 'remote-clock' && !remoteClockLoaded;
|
return activeClock?.key === 'remote-clock' && !remoteClockLoaded;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Invokes the interceptor to modify the request.
|
||||||
|
*
|
||||||
|
* @param {Object} request - The request object.
|
||||||
|
* @returns {Promise<Object>} The modified request object.
|
||||||
|
*/
|
||||||
invoke: async (request) => {
|
invoke: async (request) => {
|
||||||
const timeContext = request?.timeContext ?? openmct.time;
|
const timeContext = request?.timeContext ?? openmct.time;
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.handleNewBounds = _.throttle(this.handleNewBounds, 300, {
|
this.handleNewBounds = _.throttle(this.handleNewBounds, 300, {
|
||||||
leading: true,
|
leading: true,
|
||||||
trailing: false
|
trailing: true
|
||||||
});
|
});
|
||||||
this.setTimeSystem(this.copy(this.openmct.time.getTimeSystem()));
|
this.setTimeSystem(this.copy(this.openmct.time.getTimeSystem()));
|
||||||
this.openmct.time.on(TIME_CONTEXT_EVENTS.timeSystemChanged, this.setTimeSystem);
|
this.openmct.time.on(TIME_CONTEXT_EVENTS.timeSystemChanged, this.setTimeSystem);
|
||||||
@ -181,6 +181,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
stopFollowingTime() {
|
stopFollowingTime() {
|
||||||
|
this.handleNewBounds.cancel();
|
||||||
|
|
||||||
if (this.timeContext) {
|
if (this.timeContext) {
|
||||||
this.timeContext.off(TIME_CONTEXT_EVENTS.boundsChanged, this.handleNewBounds);
|
this.timeContext.off(TIME_CONTEXT_EVENTS.boundsChanged, this.handleNewBounds);
|
||||||
this.timeContext.off(TIME_CONTEXT_EVENTS.clockOffsetsChanged, this.setViewFromOffsets);
|
this.timeContext.off(TIME_CONTEXT_EVENTS.clockOffsetsChanged, this.setViewFromOffsets);
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
/******************************************************** PROGRESS BAR */
|
/******************************************************** PROGRESS BAR */
|
||||||
@keyframes progressIndeterminate {
|
@keyframes progressIndeterminate {
|
||||||
0% {
|
0% {
|
||||||
left: 0;
|
transform:scaleX(0);
|
||||||
width: 0;
|
|
||||||
}
|
}
|
||||||
70% {
|
90% {
|
||||||
left: 0;
|
transform:scaleX(1);
|
||||||
width: 100%;
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
left: 100%;
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,11 +21,10 @@
|
|||||||
|
|
||||||
&__bar {
|
&__bar {
|
||||||
background: $colorProgressBar;
|
background: $colorProgressBar;
|
||||||
height: 100%;
|
transform-origin: left;
|
||||||
min-height: $progressBarMinH;
|
|
||||||
|
|
||||||
&.--indeterminate {
|
&.--indeterminate {
|
||||||
position: absolute;
|
@include abs();
|
||||||
animation: progressIndeterminate 1.5s ease-in infinite;
|
animation: progressIndeterminate 1.5s ease-in infinite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user