From fd25aa03c57fb41a571b3fbf79a294b99ec72690 Mon Sep 17 00:00:00 2001 From: Chad Lavimoniere <clavimoniere@gitlab.com> Date: Wed, 6 Dec 2023 22:12:06 +0000 Subject: [PATCH] Fix overflow issues for Roadmap When system header or footer is turned on, Roadmap was having overflow issues. Changelog: fixed EE: true --- .../roadmap/components/epics_list_section.vue | 12 +++++++++++- .../roadmap/components/milestones_list_section.vue | 1 + .../javascripts/roadmap/components/roadmap_shell.vue | 11 ++++++++++- ee/app/assets/stylesheets/page_bundles/roadmap.scss | 4 ---- .../roadmap/components/epics_list_section_spec.js | 6 +++--- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue b/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue index 3b8997df6bbe1..5df15ef791ffd 100644 --- a/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue +++ b/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue @@ -70,9 +70,16 @@ export default { }, sectionContainerStyles() { return { + height: `calc(100% - ${60 + this.milestonesHeight}px)`, width: `${EPIC_DETAILS_CELL_WIDTH + TIMELINE_CELL_MIN_WIDTH * this.timeframe.length}px`, }; }, + footerMessageHeight() { + return document.querySelector('.footer-message')?.getBoundingClientRect().height || 0; + }, + milestonesHeight() { + return document.querySelector('.milestones-list-section')?.clientHeight || 0; + }, epicsWithAssociatedParents() { return this.epics.filter((epic) => { if (epic.hasParent) { @@ -93,6 +100,9 @@ export default { // Return epics with correct parent associations. return this.epicsWithAssociatedParents; }, + scrollBarHeight() { + return this.$parent.$el.getBoundingClientRect().height - this.$parent.$el.clientHeight + 1; + }, }, mounted() { eventHub.$on('epicsListScrolled', this.handleEpicsListScroll); @@ -141,7 +151,7 @@ export default { return { height: this.isScopedRoadmap ? `calc(${this.$root.$el.clientHeight}px - ${offsetTop}px)` - : `calc(100vh - ${top}px)`, + : `calc(100vh - ${top + this.scrollBarHeight + this.footerMessageHeight}px)`, }; } return {}; diff --git a/ee/app/assets/javascripts/roadmap/components/milestones_list_section.vue b/ee/app/assets/javascripts/roadmap/components/milestones_list_section.vue index 842652158d821..39ebb03337771 100644 --- a/ee/app/assets/javascripts/roadmap/components/milestones_list_section.vue +++ b/ee/app/assets/javascripts/roadmap/components/milestones_list_section.vue @@ -85,6 +85,7 @@ export default { mounted() { eventHub.$on('epicsListScrolled', this.handleEpicsListScroll); this.initMounted(); + this.$emit('milestonesMounted'); }, beforeDestroy() { eventHub.$off('epicsListScrolled', this.handleEpicsListScroll); diff --git a/ee/app/assets/javascripts/roadmap/components/roadmap_shell.vue b/ee/app/assets/javascripts/roadmap/components/roadmap_shell.vue index c626181527f8e..ecab5c10d8a99 100644 --- a/ee/app/assets/javascripts/roadmap/components/roadmap_shell.vue +++ b/ee/app/assets/javascripts/roadmap/components/roadmap_shell.vue @@ -40,6 +40,7 @@ export default { data() { return { containerStyles: {}, + canCalculateEpicsListHeight: false, }; }, computed: { @@ -60,6 +61,9 @@ export default { return this.milestones; } }, + footerMessageHeight() { + return document.querySelector('.footer-message')?.getBoundingClientRect().height || 0; + }, }, mounted() { if (this.isShowingMilestones) { @@ -79,9 +83,12 @@ export default { getContainerStyles() { const { top } = this.$el.getBoundingClientRect(); return { - height: this.isScopedRoadmap ? '100%' : `calc(100vh - ${top}px)`, + height: this.isScopedRoadmap ? '100%' : `calc(100vh - ${top + this.footerMessageHeight}px)`, }; }, + toggleCanCalculateEpicsListHeight() { + this.canCalculateEpicsListHeight = true; + }, }, }; </script> @@ -105,8 +112,10 @@ export default { :milestones="milestonesToShow" :timeframe="timeframe" :current-group-id="currentGroupId" + @milestonesMounted="toggleCanCalculateEpicsListHeight" /> <epics-list-section + :key="canCalculateEpicsListHeight" :preset-type="presetType" :epics="epics" :timeframe="timeframe" diff --git a/ee/app/assets/stylesheets/page_bundles/roadmap.scss b/ee/app/assets/stylesheets/page_bundles/roadmap.scss index 5a807dfae25d1..a2a6e3a9128e7 100644 --- a/ee/app/assets/stylesheets/page_bundles/roadmap.scss +++ b/ee/app/assets/stylesheets/page_bundles/roadmap.scss @@ -200,10 +200,6 @@ html.group-epics-roadmap-html { } } -.epics-list-section { - height: calc(100% - 60px); -} - .epics-list-item { &:hover { .epic-details-cell, diff --git a/ee/spec/frontend/roadmap/components/epics_list_section_spec.js b/ee/spec/frontend/roadmap/components/epics_list_section_spec.js index c5f6404e2ca3d..3ec0692095b1a 100644 --- a/ee/spec/frontend/roadmap/components/epics_list_section_spec.js +++ b/ee/spec/frontend/roadmap/components/epics_list_section_spec.js @@ -95,7 +95,7 @@ describe('EpicsListSectionComponent', () => { describe('sectionContainerStyles', () => { it('returns style string for container element based on sectionShellWidth', () => { - expect(wrapper.attributes('style')).toBe( + expect(wrapper.attributes('style')).toContain( `width: ${ EPIC_DETAILS_CELL_WIDTH + TIMELINE_CELL_MIN_WIDTH * mockTimeframeMonths.length }px;`, @@ -165,7 +165,7 @@ describe('EpicsListSectionComponent', () => { }); it('sets style attribute containing `height` on empty row', () => { - expect(findEmptyRowEl().attributes('style')).toBe('height: calc(100vh - 0px);'); + expect(findEmptyRowEl().attributes('style')).toBe('height: calc(100vh - 1px);'); }); }); @@ -177,7 +177,7 @@ describe('EpicsListSectionComponent', () => { }); it('sets style attribute with `height` on empty row when there epics available to render', () => { - expect(findEmptyRowEl().attributes('style')).toBe('height: calc(100vh - 0px);'); + expect(findEmptyRowEl().attributes('style')).toBe('height: calc(100vh - 1px);'); }); }); -- GitLab