diff --git a/app/assets/javascripts/work_items/components/work_item_description.vue b/app/assets/javascripts/work_items/components/work_item_description.vue index d5ba2195b0ed2be7c1d2e88b9c197bd312dd681d..3470b31545e152fca769b02c4951dcbbcc997f93 100644 --- a/app/assets/javascripts/work_items/components/work_item_description.vue +++ b/app/assets/javascripts/work_items/components/work_item_description.vue @@ -61,6 +61,7 @@ export default { data() { return { workItem: {}, + disableTruncation: false, isEditing: this.editMode, isSubmitting: false, isSubmittingWithKeydown: false, @@ -181,6 +182,7 @@ export default { }, async startEditing() { this.isEditing = true; + this.disableTruncation = true; this.descriptionText = getDraft(this.autosaveKey) || this.workItemDescription?.description; @@ -359,6 +361,7 @@ export default { :disable-inline-editing="disableInlineEditing" :work-item-description="workItemDescription" :can-edit="canEdit" + :disable-truncation="disableTruncation" @startEditing="startEditing" @descriptionUpdated="handleDescriptionTextUpdated" /> diff --git a/app/assets/javascripts/work_items/components/work_item_description_rendered.vue b/app/assets/javascripts/work_items/components/work_item_description_rendered.vue index 1699f6c419e3ad220924e37f35579f43c802b7fc..c79905005cb8e8b926ccca99e5b4a4741786f3b7 100644 --- a/app/assets/javascripts/work_items/components/work_item_description_rendered.vue +++ b/app/assets/javascripts/work_items/components/work_item_description_rendered.vue @@ -2,6 +2,7 @@ import { GlButton, GlTooltipDirective } from '@gitlab/ui'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { renderGFM } from '~/behaviors/markdown/render_gfm'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; const isCheckbox = (target) => target?.classList.contains('task-list-item-checkbox'); @@ -13,7 +14,13 @@ export default { components: { GlButton, }, + mixins: [glFeatureFlagMixin()], props: { + disableTruncation: { + type: Boolean, + required: false, + default: false, + }, workItemDescription: { type: Object, required: true, @@ -30,6 +37,7 @@ export default { }, data() { return { + truncated: false, checkboxes: [], }; }, @@ -49,6 +57,9 @@ export default { showEditButton() { return this.canEdit && !this.disableInlineEditing; }, + isTruncated() { + return this.truncated && !this.disableTruncation && this.glFeatures.workItemsMvc2; + }, }, watch: { descriptionHtml: { @@ -74,6 +85,7 @@ export default { checkbox.disabled = false; }); } + this.truncateLongDescription(); }, toggleCheckboxes(event) { const { target } = event; @@ -105,6 +117,21 @@ export default { this.$emit('descriptionUpdated', newDescriptionText); } }, + truncateLongDescription() { + /* Truncate when description is > 40% viewport height or 512px. + Update `.work-item-description .truncated` max height if value changes. */ + const defaultMaxHeight = document.documentElement.clientHeight * 0.4; + let maxHeight = defaultMaxHeight; + if (defaultMaxHeight > 512) { + maxHeight = 512; + } else if (defaultMaxHeight < 256) { + maxHeight = 256; + } + this.truncated = this.$refs['gfm-content'].clientHeight > maxHeight; + }, + showAll() { + this.truncated = false; + }, }, }; @@ -130,11 +157,32 @@ export default {
This is a long description
', + }, + mockComputed: { + isTruncated() { + return true; + }, + }, + hasWorkItemsMvc2: true, + }); + + expect(wrapper.find('[data-test-id="description-read-more"]').exists()).toBe(true); + }); + }); + + describe('without truncation', () => { + it('does not show the untruncate action', () => { + createComponent({ + workItemDescription: { + description: 'This is a long description', + descriptionHtml: 'This is a long description
', + }, + mockComputed: { + isTruncated() { + return false; + }, + }, + hasWorkItemsMvc2: true, + }); + + expect(wrapper.find('[data-test-id="description-read-more"]').exists()).toBe(false); + }); + }); + describe('with checkboxes', () => { beforeEach(() => { createComponent({