From 3788a132c44671bbf9bd7c76e6e77528f04456ec Mon Sep 17 00:00:00 2001 From: David Tsay <david.e.tsay@nasa.gov> Date: Mon, 13 May 2024 18:06:58 -0700 Subject: [PATCH] create useClock composable code clean up --- src/plugins/timeConductor/ConductorClock.vue | 78 +--------- .../timeConductor/ConductorComponent.vue | 31 +--- .../timeConductor/ConductorHistory.vue | 12 +- src/plugins/timeConductor/ConductorPopUp.vue | 19 +-- .../timeConductor/ConductorTimeSystem.vue | 10 +- src/plugins/timeConductor/clock-mixin.js | 9 -- .../independent/IndependentClock.vue | 2 +- .../independent/IndependentMode.vue | 2 +- src/plugins/timeConductor/mode-mixin.js | 9 -- src/plugins/timeConductor/useClock.js | 141 ++++++++++++++++++ 10 files changed, 161 insertions(+), 152 deletions(-) create mode 100644 src/plugins/timeConductor/useClock.js diff --git a/src/plugins/timeConductor/ConductorClock.vue b/src/plugins/timeConductor/ConductorClock.vue index 23f29d4895..db162167c6 100644 --- a/src/plugins/timeConductor/ConductorClock.vue +++ b/src/plugins/timeConductor/ConductorClock.vue @@ -23,8 +23,8 @@ <div v-if="readOnly === false" ref="clockButton" class="c-tc-input-popup__options"> <div class="c-menu-button c-ctrl-wrapper c-ctrl-wrapper--menus-left"> <button - class="c-button--menu js-clock-button" - :class="[buttonCssClass, selectedClock.cssClass]" + class="c-button--menu js-clock-button c-icon-button" + :class="selectedClock.cssClass" aria-label="Time Conductor Clock Menu" @click.prevent.stop="showClocksMenu" > @@ -38,18 +38,8 @@ </template> <script> -import { TIME_CONTEXT_EVENTS } from '../../api/time/constants.js'; -import clockMixin from './clock-mixin.js'; - export default { - mixins: [clockMixin], - inject: { - openmct: 'openmct', - configuration: { - from: 'configuration', - default: undefined - } - }, + inject: ['openmct', 'configuration', 'clock', 'getAllClockMetadata', 'getClockMetadata'], props: { readOnly: { type: Boolean, @@ -58,21 +48,15 @@ export default { } } }, - emits: ['clock-updated'], data() { - const activeClock = this.getActiveClock(); - return { - selectedClock: activeClock ? this.getClockMetadata(activeClock) : undefined, - clocks: [] + clocks: this.getAllClockMetadata(this.configuration.menuOptions) }; }, - mounted() { - this.loadClocks(this.configuration.menuOptions); - this.openmct.time.on(TIME_CONTEXT_EVENTS.clockChanged, this.setViewFromClock); - }, - unmounted() { - this.openmct.time.off(TIME_CONTEXT_EVENTS.clockChanged, this.setViewFromClock); + computed: { + selectedClock() { + return this.getClockMetadata(this.clock); + } }, methods: { showClocksMenu() { @@ -86,52 +70,6 @@ export default { }; this.dismiss = this.openmct.menus.showSuperMenu(x, y, this.clocks, menuOptions); - }, - setClock(clockKey) { - const option = { - clockKey - }; - let configuration = this.getMatchingConfig({ - clock: clockKey, - timeSystem: this.openmct.time.getTimeSystem().key - }); - - if (configuration === undefined) { - configuration = this.getMatchingConfig({ - clock: clockKey - }); - - option.timeSystem = configuration.timeSystem; - option.bounds = configuration.bounds; - - // this.openmct.time.setTimeSystem(configuration.timeSystem, configuration.bounds); - } - - const offsets = this.openmct.time.getClockOffsets() ?? configuration.clockOffsets; - option.offsets = offsets; - - this.$emit('clock-updated', option); - }, - getMatchingConfig(options) { - const matchers = { - clock(config) { - return options.clock === config.clock; - }, - timeSystem(config) { - return options.timeSystem === config.timeSystem; - } - }; - - function configMatches(config) { - return Object.keys(options).reduce((match, option) => { - return match && matchers[option](config); - }, true); - } - - return this.configuration.menuOptions.filter(configMatches)[0]; - }, - setViewFromClock(clock) { - this.selectedClock = this.getClockMetadata(clock); } } }; diff --git a/src/plugins/timeConductor/ConductorComponent.vue b/src/plugins/timeConductor/ConductorComponent.vue index df8ec451b7..614438586f 100644 --- a/src/plugins/timeConductor/ConductorComponent.vue +++ b/src/plugins/timeConductor/ConductorComponent.vue @@ -61,9 +61,6 @@ :position-x="positionX" :position-y="positionY" @popup-loaded="initializePopup" - @clock-updated="saveClock" - @fixed-bounds-updated="saveFixedBounds" - @clock-offsets-updated="saveClockOffsets" @dismiss="clearPopup" /> </div> @@ -72,7 +69,6 @@ <script> import { inject, onMounted, provide } from 'vue'; -import { FIXED_MODE_KEY, REALTIME_MODE_KEY } from '../../api/time/constants.js'; import ConductorAxis from './ConductorAxis.vue'; import ConductorClock from './ConductorClock.vue'; import ConductorInputsFixed from './ConductorInputsFixed.vue'; @@ -82,6 +78,7 @@ import ConductorModeIcon from './ConductorModeIcon.vue'; import ConductorPopUp from './ConductorPopUp.vue'; import conductorPopUpManager from './conductorPopUpManager.js'; import ConductorTimeSystem from './ConductorTimeSystem.vue'; +import { useClock } from './useClock.js'; import { useClockOffsets } from './useClockOffsets.js'; import { useTimeBounds } from './useTimeBounds.js'; import { useTimeMode } from './useTimeMode.js'; @@ -117,12 +114,14 @@ export default { getModeMetadata } = useTimeMode(openmct); const { observeTimeBounds, bounds, isTick } = useTimeBounds(openmct); + const { observeClock, clock, getAllClockMetadata, getClockMetadata } = useClock(openmct); const { observeClockOffsets, offsets } = useClockOffsets(openmct); onMounted(() => { observeTimeSystem(); observeTimeMode(); observeTimeBounds(); + observeClock(); observeClockOffsets(); }); @@ -137,22 +136,18 @@ export default { provide('bounds', bounds); provide('isTick', isTick); provide('offsets', offsets); + provide('clock', clock); + provide('getAllClockMetadata', getAllClockMetadata); + provide('getClockMetadata', getClockMetadata); return { timeSystemFormatter, - timeSystemDurationFormatter, isFixedTimeMode, - isRealTimeMode, - bounds, - isTick + bounds }; }, data() { return { - // offsets: { - // start: offsets && this.durationFormatter.format(Math.abs(offsets.start)), - // end: offsets && this.durationFormatter.format(Math.abs(offsets.end)) - // }, viewBounds: { start: this.bounds.start, end: this.bounds.end @@ -170,9 +165,6 @@ export default { start: this.timeSystemFormatter.format(this.bounds.start), end: this.timeSystemFormatter.format(this.bounds.end) }; - }, - mode() { - return this.isFixedTimeMode ? FIXED_MODE_KEY : REALTIME_MODE_KEY; } }, watch: { @@ -234,15 +226,6 @@ export default { // this.formattedBounds.end = this.timeFormatter.format(bounds.end); this.viewBounds.start = bounds.start; this.viewBounds.end = bounds.end; - }, - saveFixedBounds(bounds) { - // this.openmct.time.setBounds(bounds); - }, - saveClockOffsets(offsets) { - // this.openmct.time.setClockOffsets(offsets); - }, - saveClock(clockOptions) { - this.openmct.time.setClock(clockOptions.clockKey); } } }; diff --git a/src/plugins/timeConductor/ConductorHistory.vue b/src/plugins/timeConductor/ConductorHistory.vue index b7764fb5c0..cb215065c3 100644 --- a/src/plugins/timeConductor/ConductorHistory.vue +++ b/src/plugins/timeConductor/ConductorHistory.vue @@ -24,8 +24,7 @@ <div class="c-menu-button c-ctrl-wrapper c-ctrl-wrapper--menus-left"> <button aria-label="Time Conductor History" - class="c-button--menu c-history-button icon-history" - :class="buttonCssClass" + class="c-button--menu c-history-button icon-history c-icon-button" @click.prevent.stop="showHistoryMenu" > <span class="c-button__label">History</span> @@ -47,15 +46,6 @@ import UTCTimeFormat from '../utcTimeSystem/UTCTimeFormat.js'; export default { inject: ['openmct', 'configuration'], - props: { - buttonCssClass: { - type: String, - required: false, - default() { - return ''; - } - } - }, data() { const mode = this.openmct.time.getMode(); diff --git a/src/plugins/timeConductor/ConductorPopUp.vue b/src/plugins/timeConductor/ConductorPopUp.vue index 062a319b2c..b89bb8c221 100644 --- a/src/plugins/timeConductor/ConductorPopUp.vue +++ b/src/plugins/timeConductor/ConductorPopUp.vue @@ -12,35 +12,29 @@ v-else class="c-conductor__mode-select" title="Sets the Time Conductor's mode." - :button-css-class="'c-icon-button'" /> <IndependentClock v-if="isIndependent" class="c-conductor__mode-select" title="Sets the Time Conductor's clock." :clock="timeOptionClock" - :button-css-class="'c-icon-button'" @independent-clock-updated="saveIndependentClock" /> <ConductorClock v-else class="c-conductor__mode-select" title="Sets the Time Conductor's clock." - :button-css-class="'c-icon-button'" - @clock-updated="saveClock" /> <!-- TODO: Time system and history must work even with ITC later --> <ConductorTimeSystem v-if="!isIndependent" class="c-conductor__time-system-select" title="Sets the Time Conductor's time system." - :button-css-class="'c-icon-button'" /> <ConductorHistory v-if="!isIndependent" class="c-conductor__history-select" title="Select and apply previously entered time intervals." - :button-css-class="'c-icon-button'" /> </div> <conductor-inputs-fixed @@ -82,14 +76,7 @@ export default { ConductorInputsFixed, ConductorInputsRealtime }, - inject: { - openmct: 'openmct', - configuration: { - from: 'configuration', - default: undefined - }, - isFixedTimeMode: 'isFixedTimeMode' - }, + inject: ['openmct', 'configuration', 'isFixedTimeMode'], props: { positionX: { type: Number, @@ -130,7 +117,6 @@ export default { 'independent-clock-updated', 'fixed-bounds-updated', 'clock-offsets-updated', - 'clock-updated', 'independent-mode-updated' ], data() { @@ -225,9 +211,6 @@ export default { saveClockOffsets(offsets) { this.$emit('clock-offsets-updated', offsets); }, - saveClock(clockOptions) { - this.$emit('clock-updated', clockOptions); - }, saveIndependentMode(mode) { this.$emit('independent-mode-updated', mode); }, diff --git a/src/plugins/timeConductor/ConductorTimeSystem.vue b/src/plugins/timeConductor/ConductorTimeSystem.vue index 4023249fcb..08225e9051 100644 --- a/src/plugins/timeConductor/ConductorTimeSystem.vue +++ b/src/plugins/timeConductor/ConductorTimeSystem.vue @@ -26,8 +26,7 @@ class="c-ctrl-wrapper c-ctrl-wrapper--menus-up" > <button - class="c-button--menu c-time-system-button" - :class="[buttonCssClass]" + class="c-button--menu c-time-system-button c-icon-button" aria-label="Time Conductor Time System" @click.prevent.stop="showTimeSystemMenu" > @@ -50,13 +49,6 @@ import { TIME_CONTEXT_EVENTS } from '../../api/time/constants.js'; export default { inject: ['openmct', 'configuration'], props: { - buttonCssClass: { - type: String, - required: false, - default() { - return ''; - } - }, readOnly: { type: Boolean, default() { diff --git a/src/plugins/timeConductor/clock-mixin.js b/src/plugins/timeConductor/clock-mixin.js index 32da96c7ad..37ba025954 100644 --- a/src/plugins/timeConductor/clock-mixin.js +++ b/src/plugins/timeConductor/clock-mixin.js @@ -1,13 +1,4 @@ export default { - props: { - buttonCssClass: { - type: String, - required: false, - default() { - return ''; - } - } - }, methods: { loadClocks(menuOptions) { let clocks; diff --git a/src/plugins/timeConductor/independent/IndependentClock.vue b/src/plugins/timeConductor/independent/IndependentClock.vue index 79e532c84d..7ec8a04495 100644 --- a/src/plugins/timeConductor/independent/IndependentClock.vue +++ b/src/plugins/timeConductor/independent/IndependentClock.vue @@ -25,7 +25,7 @@ <button v-if="selectedClock" class="c-icon-button c-button--menu js-clock-button" - :class="[buttonCssClass, selectedClock.cssClass]" + :class="selectedClock.cssClass" aria-label="Independent Time Conductor Clock Menu" @click.prevent.stop="showClocksMenu" > diff --git a/src/plugins/timeConductor/independent/IndependentMode.vue b/src/plugins/timeConductor/independent/IndependentMode.vue index fe599a12e2..c203d848fc 100644 --- a/src/plugins/timeConductor/independent/IndependentMode.vue +++ b/src/plugins/timeConductor/independent/IndependentMode.vue @@ -24,7 +24,7 @@ <div class="c-menu-button c-ctrl-wrapper c-ctrl-wrapper--menus-left"> <button class="c-icon-button c-button--menu js-mode-button" - :class="[buttonCssClass, selectedMode.cssClass]" + :class="selectedMode.cssClass" aria-label="Independent Time Conductor Mode Menu" @click.prevent.stop="showModesMenu" > diff --git a/src/plugins/timeConductor/mode-mixin.js b/src/plugins/timeConductor/mode-mixin.js index f8dc37db64..110b49f8cc 100644 --- a/src/plugins/timeConductor/mode-mixin.js +++ b/src/plugins/timeConductor/mode-mixin.js @@ -1,15 +1,6 @@ import { FIXED_MODE_KEY, REALTIME_MODE_KEY } from '../../api/time/constants.js'; export default { - props: { - buttonCssClass: { - type: String, - required: false, - default() { - return ''; - } - } - }, methods: { loadModes() { this.modes = [FIXED_MODE_KEY, REALTIME_MODE_KEY].map(this.getModeMetadata); diff --git a/src/plugins/timeConductor/useClock.js b/src/plugins/timeConductor/useClock.js new file mode 100644 index 0000000000..df1dde14ee --- /dev/null +++ b/src/plugins/timeConductor/useClock.js @@ -0,0 +1,141 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2024, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web 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 Web 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 { onBeforeUnmount, ref } from 'vue'; + +/** + * Provides reactive TODO, + * as well as a function to observe and update the component's clock, + * which automatically stops observing when the component is unmounted. + * + * @param {OpenMCT} openmct the Open MCT API + * @returns {{ + * observeClock: () => void, + * timeMode: import('vue').Ref<string>, + * isFixedTimeMode: import('vue').Ref<boolean>, + * isRealTimeMode: import('vue').Ref<boolean> + * }} + */ +export function useClock(openmct, options) { + let stopObservingClock; + + const clock = ref(openmct.time.getClock()); + + onBeforeUnmount(() => stopObservingClock?.()); + + function observeClock() { + openmct.time.on(TIME_CONTEXT_EVENTS.clockChanged, updateClock); + stopObservingClock = () => openmct.time.off(TIME_CONTEXT_EVENTS.clockChanged, updateClock); + } + + function getAllClockMetadata(menuOptions) { + const clocks = menuOptions + ? menuOptions + .map((menuOption) => menuOption.clock) + .filter((key, index, array) => key !== undefined && array.indexOf(key) === index) + .map((clockKey) => openmct.time.getAllClocks().find((_clock) => _clock.key === clockKey)) + : openmct.time.getAllClocks(); + + const clockMetadata = clocks.map(getClockMetadata); + + return clockMetadata; + } + + function getClockMetadata(_clock) { + if (_clock === undefined) { + return; + } + + const clockMetadata = { + key: _clock.key, + name: _clock.name, + description: 'Uses the system clock as the current time basis. ' + _clock.description, + cssClass: _clock.cssClass || 'icon-clock', + onItemClicked: () => setClock(_clock.key) + }; + + return clockMetadata; + } + + function setClock(key) { + openmct.time.setClock(key); + } + + function updateClock(_clock) { + clock.value = _clock; + } + + /** + * TODO: bring this back. we lost this in the last refactor. + * changing clock requires a timesystem check. + * + function setClockWithOptions() { + const option = { + clockKey + }; + let configuration = this.getMatchingConfig({ + clock: clockKey, + timeSystem: this.openmct.time.getTimeSystem().key + }); + + if (configuration === undefined) { + configuration = this.getMatchingConfig({ + clock: clockKey + }); + + option.timeSystem = configuration.timeSystem; + option.bounds = configuration.bounds; + + // this.openmct.time.setTimeSystem(configuration.timeSystem, configuration.bounds); + } + + const offsets = this.openmct.time.getClockOffsets() ?? configuration.clockOffsets; + option.offsets = offsets; + } + + function getMatchingConfig(options) { + const matchers = { + clock(config) { + return options.clock === config.clock; + }, + timeSystem(config) { + return options.timeSystem === config.timeSystem; + } + }; + + function configMatches(config) { + return Object.keys(options).reduce((match, option) => { + return match && matchers[option](config); + }, true); + } + + return this.configuration.menuOptions.filter(configMatches)[0]; + } + */ + + return { + observeClock, + clock, + getAllClockMetadata, + getClockMetadata + }; +}