From ee6aab2f598885499702f7f4ef80fe7b0f069d1d Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 3 Mar 2025 16:21:31 -0800 Subject: [PATCH] persist swimlane height resizing --- src/plugins/timeline/TimelineViewLayout.vue | 42 ++++++++++++--- src/plugins/timeline/plugin.js | 3 +- src/utils/vue/useFlexContainers.js | 58 ++++++++++++++------- 3 files changed, 76 insertions(+), 27 deletions(-) diff --git a/src/plugins/timeline/TimelineViewLayout.vue b/src/plugins/timeline/TimelineViewLayout.vue index c1f3157187..43bddd29a3 100644 --- a/src/plugins/timeline/TimelineViewLayout.vue +++ b/src/plugins/timeline/TimelineViewLayout.vue @@ -104,7 +104,6 @@ export default { SwimLane, ExtendedLinesOverlay }, - inject: ['openmct', 'domainObject', 'path', 'composition', 'extendedLinesBus'], props: { isEditing: { type: Boolean, @@ -112,10 +111,14 @@ export default { } }, setup() { + const openmct = inject('openmct'); const domainObject = inject('domainObject'); const path = inject('path'); - const openmct = inject('openmct'); + const composition = inject('composition'); + const extendedLinesBus = inject('extendedLinesBus'); + const items = ref([]); + const loadedComposition = ref(null); const { alignment: alignmentData, reset: resetAlignment } = useAlignment( domainObject, @@ -140,7 +143,8 @@ export default { endContainerResizing } = useFlexContainers(timelineHolder, { containerClass: Container, - rowsLayout: true + rowsLayout: true, + callback: mutateContainers }); function getContainerSize(item) { @@ -151,17 +155,33 @@ export default { return containerforItem?.size; } + function mutateContainers() { + if ( + loadedComposition?.value?.length && + loadedComposition?.value?.length === containers?.value?.length + ) { + openmct.objects.mutate(domainObject, 'configuration.containers', containers.value); + } + } + return { + openmct, + domainObject, + path, + composition, + extendedLinesBus, containers, getContainerSize, timelineHolder, + loadedComposition, items, addContainer, alignmentData, resetAlignment, startContainerResizing, containerResizing, - endContainerResizing + endContainerResizing, + mutateContainers }; }, data() { @@ -196,7 +216,7 @@ export default { this.extendedLinesBus.off('update-extended-hover', this.updateExtendedHover); this.openmct.selection.off('change', this.checkForLineSelection); }, - mounted() { + async mounted() { this.items = []; this.setTimeContext(); @@ -208,7 +228,8 @@ export default { this.composition.on('add', this.addItem); this.composition.on('remove', this.removeItem); this.composition.on('reorder', this.reorder); - this.composition.load(); + + this.loadedComposition = await this.composition.load(); } this.handleContentResize = _.debounce(this.handleContentResize, 500); @@ -243,7 +264,14 @@ export default { this.items.push(item); - const container = new Container(domainObject); + const containerSizeFromConfiguration = this.domainObject.configuration?.containers?.find( + (container) => + this.openmct.objects.areIdsEqual( + container.domainObjectIdentifier, + domainObject.identifier + ) + )?.size; + const container = new Container(domainObject, containerSizeFromConfiguration); this.addContainer(container); }, removeItem(identifier) { diff --git a/src/plugins/timeline/plugin.js b/src/plugins/timeline/plugin.js index 380a66d921..bf18e1c841 100644 --- a/src/plugins/timeline/plugin.js +++ b/src/plugins/timeline/plugin.js @@ -41,7 +41,8 @@ export default function () { initialize: function (domainObject) { domainObject.composition = []; domainObject.configuration = { - useIndependentTime: false + useIndependentTime: false, + containers: [] }; } }); diff --git a/src/utils/vue/useFlexContainers.js b/src/utils/vue/useFlexContainers.js index 7e3df9c7c1..4abc7a4514 100644 --- a/src/utils/vue/useFlexContainers.js +++ b/src/utils/vue/useFlexContainers.js @@ -1,6 +1,21 @@ import _ from 'lodash'; import { ref } from 'vue'; +/** + * @typedef {Object} configuration + * @property {boolean} rowsLayout true if containers arranged as rows, false if columns + * @property {number} minContainerSize minimum size in pixels of a container + * @property {Function} callback function to call when container resize completes + */ + +/** + * Provides a means to size a collection of containers to a total size of 100%. + * The containers will resize proportionally to fit the total size on add/remove. + * The containers will initially be sized based on their scale property. + * @param {import('vue').Ref !_.isEqual(item, newItem)); + const remainingSize = 100 - newItem.size; + + oldItems.forEach((item) => { + const itemScale = item.scale || 1; + item.size = Math.round((item.size * itemScale * remainingSize) / 100); + }); + + // Ensure items add up to 100 in case of rounding error. + let total = items.reduce((t, item) => t + item.size, 0); + let excess = Math.round(100 - total); + oldItems[oldItems.length - 1].size += excess; } - - // Resize oldItems to fit inside remaining space; - const oldItems = items.filter((item) => !_.isEqual(item, newItem)); - const remainingSize = 100 - newItem.size; - - oldItems.forEach((item) => { - const itemScale = item.scale || 1; - item.size = Math.round((item.size * itemScale * remainingSize) / 100); - }); - - // Ensure items add up to 100 in case of rounding error. - let total = items.reduce((t, item) => t + item.size, 0); - let excess = Math.round(100 - total); - oldItems[oldItems.length - 1].size += excess; } }