WIP: get independent time contexts working again

This commit is contained in:
David Tsay 2024-05-21 17:34:18 -07:00
parent 5dba73e83c
commit 1bb49ead0a
2 changed files with 138 additions and 224 deletions

View File

@ -22,29 +22,28 @@
<template> <template>
<time-popup-realtime <time-popup-realtime
v-if="readOnly === false" v-if="readOnly === false"
:offsets="offsets" :offsets="formattedOffsets"
@focus="$event.target.select()" @focus="$event.target.select()"
@update="timePopUpdate"
@dismiss="dismiss" @dismiss="dismiss"
/> />
<div v-else class="c-compact-tc__setting-wrapper"> <div v-else class="c-compact-tc__setting-wrapper">
<div <div
v-if="!compact" v-if="!compact"
class="c-compact-tc__setting-value icon-minus u-fade-truncate--lg --no-sep" class="c-compact-tc__setting-value icon-minus u-fade-truncate--lg --no-sep"
:aria-label="`Start offset: ${offsets.start}`" :aria-label="`Start offset: ${formattedOffsets.start}`"
:title="`Start offset: ${offsets.start}`" :title="`Start offset: ${formattedOffsets.start}`"
> >
{{ offsets.start }} {{ formattedOffsets.start }}
</div> </div>
<div v-if="!compact" class="c-compact-tc__bounds__start-end-sep icon-arrows-right-left"></div> <div v-if="!compact" class="c-compact-tc__bounds__start-end-sep icon-arrows-right-left"></div>
<div <div
v-if="!compact" v-if="!compact"
class="c-compact-tc__setting-value icon-plus u-fade-truncate--lg" class="c-compact-tc__setting-value icon-plus u-fade-truncate--lg"
:class="{ '--no-sep': compact }" :class="{ '--no-sep': compact }"
:aria-label="`End offset: ${offsets.end}`" :aria-label="`End offset: ${formattedOffsets.end}`"
:title="`End offset: ${offsets.end}`" :title="`End offset: ${formattedOffsets.end}`"
> >
{{ offsets.end }} {{ formattedOffsets.end }}
</div> </div>
<div <div
class="c-compact-tc__setting-value icon-clock c-compact-tc__current-update u-fade-truncate--lg --no-sep" class="c-compact-tc__setting-value icon-clock c-compact-tc__current-update u-fade-truncate--lg --no-sep"
@ -58,18 +57,13 @@
</template> </template>
<script> <script>
import _ from 'lodash';
import { TIME_CONTEXT_EVENTS } from '../../api/time/constants.js';
import TimePopupRealtime from './TimePopupRealtime.vue'; import TimePopupRealtime from './TimePopupRealtime.vue';
const DEFAULT_DURATION_FORMATTER = 'duration';
export default { export default {
components: { components: {
TimePopupRealtime TimePopupRealtime
}, },
inject: ['openmct'], inject: ['openmct', 'bounds', 'clock', 'offsets', 'timeSystemKey', 'timeSystemFormatter', 'timeSystemDurationFormatter'],
props: { props: {
objectPath: { objectPath: {
type: Array, type: Array,
@ -77,12 +71,6 @@ export default {
return []; return [];
} }
}, },
inputBounds: {
type: Object,
default() {
return undefined;
}
},
readOnly: { readOnly: {
type: Boolean, type: Boolean,
default() { default() {
@ -98,165 +86,46 @@ export default {
}, },
emits: ['offsets-updated', 'dismiss-inputs-realtime'], emits: ['offsets-updated', 'dismiss-inputs-realtime'],
data() { data() {
const timeSystem = this.openmct.time.getTimeSystem();
const durationFormatter = this.getFormatter(
timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER
);
const timeFormatter = this.getFormatter(timeSystem.timeFormat);
const bounds = this.bounds ?? this.openmct.time.getBounds();
const offsets = this.offsets ?? this.openmct.time.getClockOffsets();
const currentValue = this.openmct.time.getClock()?.currentValue();
return { return {
showTCInputStart: false, showTCInputStart: false,
showTCInputEnd: false, showTCInputEnd: false,
durationFormatter, currentValue: this.clock.currentValue()
timeFormatter,
bounds: {
start: bounds.start,
end: bounds.end
},
offsets: {
start: offsets && durationFormatter.format(Math.abs(offsets.start)),
end: offsets && durationFormatter.format(Math.abs(offsets.end))
},
formattedBounds: {
start: timeFormatter.format(bounds.start),
end: timeFormatter.format(bounds.end)
},
currentValue,
formattedCurrentValue: timeFormatter.format(currentValue),
isUTCBased: timeSystem.isUTCBased
}; };
}, },
watch: { computed: {
objectPath: { formattedBounds() {
handler(newPath, oldPath) { return {
if (newPath === oldPath) { start: this.timeSystemFormatter.format(this.bounds.start),
return; end: this.timeSystemFormatter.format(this.bounds.end)
} };
this.setTimeContext();
},
deep: true
}, },
inputBounds: { formattedOffsets() {
handler(newBounds) { return {
this.handleNewBounds(newBounds); start: this.timeSystemDurationFormatter.format(Math.abs(this.offsets.start)),
}, end: this.timeSystemDurationFormatter.format(Math.abs(this.offsets.end))
deep: true };
},
formattedCurrentValue() {
return this.timeSystemFormatter.format(this.currentValue);
} }
}, },
mounted() { watch: {
this.handleNewBounds = _.throttle(this.handleNewBounds, 300, { bounds() {
leading: true, console.log(this.formattedOffsets);
trailing: false this.updateCurrentValue();
}); }
this.setTimeSystem(this.copy(this.openmct.time.getTimeSystem()));
this.openmct.time.on(TIME_CONTEXT_EVENTS.timeSystemChanged, this.setTimeSystem);
this.setTimeContext();
},
beforeUnmount() {
this.openmct.time.off(TIME_CONTEXT_EVENTS.timeSystemChanged, this.setTimeSystem);
this.stopFollowingTime();
}, },
methods: { methods: {
followTime() {
const bounds = this.timeContext
? this.timeContext.getBounds()
: this.openmct.time.getBounds();
const offsets = this.timeContext
? this.timeContext.getClockOffsets()
: this.openmct.time.getClockOffsets();
this.handleNewBounds(bounds);
this.setViewFromOffsets(offsets);
if (this.timeContext) {
this.timeContext.on(TIME_CONTEXT_EVENTS.boundsChanged, this.handleNewBounds);
this.timeContext.on(TIME_CONTEXT_EVENTS.clockOffsetsChanged, this.setViewFromOffsets);
} else {
this.openmct.time.on(TIME_CONTEXT_EVENTS.boundsChanged, this.handleNewBounds);
this.openmct.time.on(TIME_CONTEXT_EVENTS.clockOffsetsChanged, this.setViewFromOffsets);
}
},
stopFollowingTime() {
if (this.timeContext) {
this.timeContext.off(TIME_CONTEXT_EVENTS.boundsChanged, this.handleNewBounds);
this.timeContext.off(TIME_CONTEXT_EVENTS.clockOffsetsChanged, this.setViewFromOffsets);
} else {
this.openmct.time.off(TIME_CONTEXT_EVENTS.boundsChanged, this.handleNewBounds);
this.openmct.time.off(TIME_CONTEXT_EVENTS.clockOffsetsChanged, this.setViewFromOffsets);
}
},
setTimeContext() {
this.stopFollowingTime();
this.timeContext = this.openmct.time.getContextForView(this.objectPath);
this.followTime();
},
handleNewBounds(bounds, isTick) {
if (this.timeContext.isRealTime() || !isTick) {
this.setBounds(bounds);
this.setViewFromBounds(bounds);
this.updateCurrentValue();
}
},
setViewFromOffsets(offsets) {
if (offsets) {
this.offsets.start = this.durationFormatter.format(Math.abs(offsets.start));
this.offsets.end = this.durationFormatter.format(Math.abs(offsets.end));
}
},
setBounds(bounds) {
this.bounds = bounds;
},
setViewFromBounds(bounds) {
this.formattedBounds.start = this.timeFormatter.format(bounds.start);
this.formattedBounds.end = this.timeFormatter.format(bounds.end);
},
updateCurrentValue() { updateCurrentValue() {
const currentValue = this.timeContext.getClock().currentValue(); this.currentValue = this.clock.currentValue();
if (currentValue !== undefined) {
this.setCurrentValue(currentValue);
}
},
setCurrentValue(value) {
this.currentValue = value;
this.formattedCurrentValue = this.timeFormatter.format(value);
},
setTimeSystem(timeSystem) {
this.timeSystem = timeSystem;
this.timeFormatter = this.getFormatter(timeSystem.timeFormat);
this.durationFormatter = this.getFormatter(
timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER
);
this.isUTCBased = timeSystem.isUTCBased;
},
getFormatter(key) {
return this.openmct.telemetry.getValueFormatter({
format: key
}).formatter;
}, },
timePopUpdate({ start, end }) { timePopUpdate({ start, end }) {
this.offsets.start = [start.hours, start.minutes, start.seconds].join(':'); this.offsets.start = [start.hours, start.minutes, start.seconds].join(':');
this.offsets.end = [end.hours, end.minutes, end.seconds].join(':'); this.offsets.end = [end.hours, end.minutes, end.seconds].join(':');
this.setOffsetsFromView(); this.setOffsetsFromView();
}, },
setOffsetsFromView() {
let startOffset = 0 - this.durationFormatter.parse(this.offsets.start);
let endOffset = this.durationFormatter.parse(this.offsets.end);
this.$emit('offsets-updated', {
start: startOffset,
end: endOffset
});
},
dismiss() { dismiss() {
this.$emit('dismiss-inputs-realtime'); this.$emit('dismiss-inputs-realtime');
},
copy(object) {
return JSON.parse(JSON.stringify(object));
} }
} }
}; };

View File

@ -82,6 +82,8 @@
</template> </template>
<script> <script>
import { inject, provide, watch } from 'vue';
import ConductorModeIcon from '@/plugins/timeConductor/ConductorModeIcon.vue'; import ConductorModeIcon from '@/plugins/timeConductor/ConductorModeIcon.vue';
import { FIXED_MODE_KEY, TIME_CONTEXT_EVENTS } from '../../../api/time/constants.js'; import { FIXED_MODE_KEY, TIME_CONTEXT_EVENTS } from '../../../api/time/constants.js';
@ -89,6 +91,12 @@ import ToggleSwitch from '../../../ui/components/ToggleSwitch.vue';
import ConductorInputsFixed from '../ConductorInputsFixed.vue'; import ConductorInputsFixed from '../ConductorInputsFixed.vue';
import ConductorInputsRealtime from '../ConductorInputsRealtime.vue'; import ConductorInputsRealtime from '../ConductorInputsRealtime.vue';
import ConductorPopUp from '../ConductorPopUp.vue'; import ConductorPopUp from '../ConductorPopUp.vue';
import { useClock } from '../useClock.js';
import { useClockOffsets } from '../useClockOffsets.js';
import { useTimeBounds } from '../useTimeBounds.js';
import { useTimeContext } from '../useTimeContext.js';
import { useTimeMode } from '../useTimeMode.js';
import { useTimeSystem } from '../useTimeSystem.js';
import independentTimeConductorPopUpManager from './independentTimeConductorPopUpManager.js'; import independentTimeConductorPopUpManager from './independentTimeConductorPopUpManager.js';
export default { export default {
@ -100,13 +108,7 @@ export default {
ToggleSwitch ToggleSwitch
}, },
mixins: [independentTimeConductorPopUpManager], mixins: [independentTimeConductorPopUpManager],
inject: { inject: ['openmct'],
openmct: 'openmct',
configuration: {
from: 'configuration',
default: undefined
}
},
props: { props: {
domainObject: { domainObject: {
type: Object, type: Object,
@ -117,34 +119,71 @@ export default {
required: true required: true
} }
}, },
emits: ['updated'], setup(props) {
const openmct = inject('openmct');
const { timeContext } = useTimeContext(openmct, getReactiveObjectPath);
const { timeSystemFormatter, timeSystemDurationFormatter, isTimeSystemUTCBased } =
useTimeSystem(openmct, getReactiveObjectPath);
const { timeMode, isFixedTimeMode, isRealTimeMode, getAllModeMetadata, getModeMetadata } =
useTimeMode(openmct, getReactiveObjectPath);
const { bounds, isTick } = useTimeBounds(openmct, getReactiveObjectPath);
const { clock, getAllClockMetadata, getClockMetadata } = useClock(openmct, getReactiveObjectPath);
const { offsets } = useClockOffsets(openmct, getReactiveObjectPath);
watch(timeContext, () => {
console.log('context changed');
});
provide('timeContext', timeContext);
provide('timeSystemFormatter', timeSystemFormatter);
provide('timeSystemDurationFormatter', timeSystemDurationFormatter);
provide('isTimeSystemUTCBased', isTimeSystemUTCBased);
provide('timeMode', timeMode);
provide('isFixedTimeMode', isFixedTimeMode);
provide('isRealTimeMode', isRealTimeMode);
provide('getAllModeMetadata', getAllModeMetadata);
provide('getModeMetadata', getModeMetadata);
provide('bounds', bounds);
provide('isTick', isTick);
provide('offsets', offsets);
provide('clock', clock);
provide('getAllClockMetadata', getAllClockMetadata);
provide('getClockMetadata', getClockMetadata);
function getReactiveObjectPath() {
return props.objectPath;
}
return {
timeContext,
timeMode,
clock,
timeSystemFormatter,
isFixedTimeMode,
isRealTimeMode,
bounds
};
},
data() { data() {
const fixedOffsets = this.openmct.time.getBounds();
const clockOffsets = this.openmct.time.getClockOffsets();
const clock = this.openmct.time.getClock().key;
const mode = this.openmct.time.getMode();
const timeOptions = this.domainObject.configuration.timeOptions ?? { const timeOptions = this.domainObject.configuration.timeOptions ?? {
clockOffsets, clockOffsets: this.clockOffsets,
fixedOffsets bounds: this.bounds
}; };
timeOptions.clock = timeOptions.clock ?? clock; timeOptions.clock = timeOptions.clock ?? this.clock.key;
timeOptions.mode = timeOptions.mode ?? mode; timeOptions.mode = timeOptions.mode ?? this.timeMode;
// check for older configurations that stored a key // check for older configurations that stored a key
if (timeOptions.mode.key) { if (timeOptions.mode.key) {
timeOptions.mode = timeOptions.mode.key; timeOptions.mode = timeOptions.mode.key;
} }
const isFixed = timeOptions.mode === FIXED_MODE_KEY;
return { return {
timeOptions, timeOptions,
isFixed,
independentTCEnabled: this.domainObject.configuration.useIndependentTime === true,
viewBounds: { viewBounds: {
start: fixedOffsets.start, start: this.bounds.start,
end: fixedOffsets.end end: this.bounds.end
} }
}; };
}, },
@ -153,10 +192,13 @@ export default {
return `${this.independentTCEnabled ? 'Disable' : 'Enable'} Independent Time Conductor`; return `${this.independentTCEnabled ? 'Disable' : 'Enable'} Independent Time Conductor`;
}, },
showFixedInputs() { showFixedInputs() {
return this.isFixed && this.independentTCEnabled; return this.isFixedTimeMode && this.independentTCEnabled;
}, },
showRealtimeInputs() { showRealtimeInputs() {
return !this.isFixed && this.independentTCEnabled; return this.isRealTimeMode && this.independentTCEnabled;
},
independentTCEnabled() {
return this.domainObject.configuration.useIndependentTime === true;
} }
}, },
watch: { watch: {
@ -165,9 +207,10 @@ export default {
const key = this.openmct.objects.makeKeyString(domainObject.identifier); const key = this.openmct.objects.makeKeyString(domainObject.identifier);
if (key !== this.keyString) { if (key !== this.keyString) {
//domain object has changed //domain object has changed
console.log(`TODO: THIS SHOULD NEVER HAPPEN!!! `);
this.destroyIndependentTime(); this.destroyIndependentTime();
this.independentTCEnabled = domainObject.configuration.useIndependentTime === true; // this.independentTCEnabled = domainObject.configuration.useIndependentTime === true;
this.timeOptions = domainObject.configuration.timeOptions ?? { this.timeOptions = domainObject.configuration.timeOptions ?? {
clockOffsets: this.openmct.time.getClockOffsets(), clockOffsets: this.openmct.time.getClockOffsets(),
fixedOffsets: this.openmct.time.getBounds() fixedOffsets: this.openmct.time.getBounds()
@ -189,12 +232,18 @@ export default {
}, },
deep: true deep: true
}, },
objectPath: { // objectPath: {
handler(newPath, oldPath) { // handler(newPath, oldPath) {
//domain object or view has probably changed // //domain object or view has probably changed
this.setTimeContext(); // this.setTimeContext();
}, // },
deep: true // deep: true
// }
clock(newClock) {
this.setTimeOptionsClock(newClock);
},
timeMode(newTimeMode) {
this.setTimeOptionsMode(newTimeMode);
} }
}, },
created() { created() {
@ -207,14 +256,18 @@ export default {
methods: { methods: {
initialize() { initialize() {
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier); this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
this.setTimeContext(); // this.setTimeContext();
if (this.independentTCEnabled) { if (this.independentTCEnabled) {
this.registerIndependentTimeOffsets(); this.registerIndependentTimeOffsets();
} }
}, },
toggleIndependentTC() { toggleIndependentTC() {
this.independentTCEnabled = !this.independentTCEnabled; this.openmct.objects.mutate(
this.domainObject,
'configuration.useIndependentTime',
!this.independentTCEnabled
);
if (this.independentTCEnabled) { if (this.independentTCEnabled) {
this.registerIndependentTimeOffsets(); this.registerIndependentTimeOffsets();
@ -222,26 +275,20 @@ export default {
this.clearPopup(); this.clearPopup();
this.destroyIndependentTime(); this.destroyIndependentTime();
} }
},
// setTimeContext() {
// if (this.timeContext) {
// this.stopFollowingTimeContext();
// }
this.openmct.objects.mutate( // this.timeContext = this.openmct.time.getContextForView(this.objectPath);
this.domainObject, // this.timeContext.on(TIME_CONTEXT_EVENTS.clockChanged, this.setTimeOptionsClock);
'configuration.useIndependentTime', // this.timeContext.on(TIME_CONTEXT_EVENTS.modeChanged, this.setTimeOptionsMode);
this.independentTCEnabled // },
); // stopFollowingTimeContext() {
}, // this.timeContext.off(TIME_CONTEXT_EVENTS.clockChanged, this.setTimeOptionsClock);
setTimeContext() { // this.timeContext.off(TIME_CONTEXT_EVENTS.modeChanged, this.setTimeOptionsMode);
if (this.timeContext) { // },
this.stopFollowingTimeContext();
}
this.timeContext = this.openmct.time.getContextForView(this.objectPath);
this.timeContext.on(TIME_CONTEXT_EVENTS.clockChanged, this.setTimeOptionsClock);
this.timeContext.on(TIME_CONTEXT_EVENTS.modeChanged, this.setTimeOptionsMode);
},
stopFollowingTimeContext() {
this.timeContext.off(TIME_CONTEXT_EVENTS.clockChanged, this.setTimeOptionsClock);
this.timeContext.off(TIME_CONTEXT_EVENTS.modeChanged, this.setTimeOptionsMode);
},
setTimeOptionsClock(clock) { setTimeOptionsClock(clock) {
this.setTimeOptionsOffsets(); this.setTimeOptionsOffsets();
this.timeOptions.clock = clock.key; this.timeOptions.clock = clock.key;
@ -251,9 +298,8 @@ export default {
this.timeOptions.mode = mode; this.timeOptions.mode = mode;
}, },
setTimeOptionsOffsets() { setTimeOptionsOffsets() {
this.timeOptions.clockOffsets = this.timeOptions.clockOffsets = this.timeOptions.clockOffsets ?? this.clockOffsets;
this.timeOptions.clockOffsets ?? this.timeContext.getClockOffsets(); this.timeOptions.fixedOffsets = this.timeOptions.fixedOffsets ?? this.bounds;
this.timeOptions.fixedOffsets = this.timeOptions.fixedOffsets ?? this.timeContext.getBounds();
}, },
saveFixedBounds(bounds) { saveFixedBounds(bounds) {
const newOptions = this.updateTimeOptionProperty({ const newOptions = this.updateTimeOptionProperty({
@ -287,31 +333,30 @@ export default {
this.timeOptions = options; this.timeOptions = options;
this.registerIndependentTimeOffsets(); this.registerIndependentTimeOffsets();
this.$emit('updated', this.timeOptions); // no longer use this, but may be used elsewhere
this.openmct.objects.mutate(this.domainObject, 'configuration.timeOptions', this.timeOptions); this.openmct.objects.mutate(this.domainObject, 'configuration.timeOptions', this.timeOptions);
}, },
registerIndependentTimeOffsets() { registerIndependentTimeOffsets() {
const timeContext = this.openmct.time.getIndependentContext(this.keyString); // const timeContext = this.openmct.time.getIndependentContext(this.keyString);
let offsets; let offsets;
if (this.isFixed) { if (this.isFixedTimeMode) {
offsets = this.timeOptions.fixedOffsets ?? this.timeContext.getBounds(); offsets = this.timeOptions.fixedOffsets ?? this.bounds;
} else { } else {
offsets = this.timeOptions.clockOffsets ?? this.openmct.time.getClockOffsets(); offsets = this.timeOptions.clockOffsets ?? this.clockOffsets();
} }
if (!timeContext.hasOwnContext()) { if (!this.timeContext.hasOwnContext()) {
this.unregisterIndependentTime = this.openmct.time.addIndependentContext( this.unregisterIndependentTime = this.openmct.time.addIndependentContext(
this.keyString, this.keyString,
offsets, offsets,
this.isFixed ? undefined : this.timeOptions.clock this.isFixed ? undefined : this.timeOptions.clock
); );
} else { } else {
if (!this.isFixed) { if (this.isRealTimeMode) {
timeContext.setClock(this.timeOptions.clock); this.timeContext.setClock(this.timeOptions.clock);
} }
timeContext.setMode(this.timeOptions.mode, offsets); this.timeContext.setMode(this.timeOptions.mode, offsets);
} }
}, },
destroyIndependentTime() { destroyIndependentTime() {