diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue index 4456f5a0d2e76090fdb7530e296c7dd3bd3baee4..44c16324950e60cbe5580f0e33b030ab0eb93ab1 100644 --- a/app/assets/javascripts/boards/components/board_card.vue +++ b/app/assets/javascripts/boards/components/board_card.vue @@ -30,6 +30,11 @@ export default { default: 0, required: false, }, + showWorkItemTypeIcon: { + type: Boolean, + default: false, + required: false, + }, }, computed: { ...mapState(['selectedBoardItems', 'activeId']), @@ -98,6 +103,12 @@ export default { class="board-card gl-p-5 gl-rounded-base gl-line-height-normal gl-relative gl-mb-3" @click="toggleIssue($event)" > - <board-card-inner :list="list" :item="item" :update-filters="true" :index="index" /> + <board-card-inner + :list="list" + :item="item" + :update-filters="true" + :index="index" + :show-work-item-type-icon="showWorkItemTypeIcon" + /> </li> </template> diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue index 055ed912663b1c5f87df8664804ef2c79b11feb5..f7e881defb78e7e5410d53f7ccaabf3050c8ada1 100644 --- a/app/assets/javascripts/boards/components/board_card_inner.vue +++ b/app/assets/javascripts/boards/components/board_card_inner.vue @@ -16,6 +16,7 @@ import { sprintf, __, n__ } from '~/locale'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue'; +import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue'; import { ListType } from '../constants'; import eventHub from '../eventhub'; import BoardBlockedIcon from './board_blocked_icon.vue'; @@ -36,6 +37,7 @@ export default { BoardBlockedIcon, GlSprintf, BoardCardMoveToPosition, + WorkItemTypeIcon, }, directives: { GlTooltip: GlTooltipDirective, @@ -61,6 +63,11 @@ export default { type: Number, required: true, }, + showWorkItemTypeIcon: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -265,6 +272,11 @@ export default { class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden" > <gl-loading-icon v-if="item.isLoading" size="lg" class="gl-mt-5" /> + <work-item-type-icon + v-if="showWorkItemTypeIcon" + :work-item-type="item.type" + show-tooltip-on-hover + /> <span v-if="item.referencePath" class="board-card-number gl-overflow-hidden gl-display-flex gl-mr-3 gl-mt-3 gl-text-secondary" diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index 1d265874bf236bed7db023621f22f205e12cb6eb..93835519033a4dbb2a058bb125fb6504655021e0 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -301,6 +301,7 @@ export default { :item="item" :data-draggable-item-type="$options.draggableItemTypes.card" :disabled="disabled" + :show-work-item-type-icon="!isEpicBoard" /> <gl-intersection-observer @appear="onReachingListBottom"> <li diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 8fd004233e2c653f38b3c359e79bdcf311060712..3b9cf7d05f80099da6e96f52f3fb96017a9f312c 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -156,7 +156,7 @@ def issuable_meta(issuable, project) output = [] if issuable.respond_to?(:work_item_type) && WorkItems::Type::WI_TYPES_WITH_CREATED_HEADER.include?(issuable.work_item_type.base_type) - output << content_tag(:span, sprite_icon("#{issuable.work_item_type.icon_name}", css_class: 'gl-icon gl-vertical-align-middle'), class: 'gl-mr-2', aria: { hidden: 'true' }) + output << content_tag(:span, sprite_icon("#{issuable.work_item_type.icon_name}", css_class: 'gl-icon gl-vertical-align-middle gl-text-gray-500'), class: 'gl-mr-2', aria: { hidden: 'true' }) output << s_('IssuableStatus|%{wi_type} created %{created_at} by ').html_safe % { wi_type: issuable.issue_type.capitalize, created_at: time_ago_with_tooltip(issuable.created_at) } else output << s_('IssuableStatus|Created %{created_at} by').html_safe % { created_at: time_ago_with_tooltip(issuable.created_at) } diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js index 7be2d57220b9f35b07be6758ca36ce855d40478b..2c3ec69f9ae9612ac8b0aece6a71d86bbe66d36c 100644 --- a/spec/frontend/boards/board_card_inner_spec.js +++ b/spec/frontend/boards/board_card_inner_spec.js @@ -8,6 +8,7 @@ import { mountExtended } from 'helpers/vue_test_utils_helper'; import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue'; import BoardCardInner from '~/boards/components/board_card_inner.vue'; import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue'; +import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue'; import { issuableTypes } from '~/boards/constants'; import eventHub from '~/boards/eventhub'; import defaultStore from '~/boards/stores'; @@ -49,6 +50,7 @@ describe('Board card component', () => { const findEpicProgressTooltip = () => wrapper.findByTestId('epic-progress-tooltip-content'); const findHiddenIssueIcon = () => wrapper.findByTestId('hidden-icon'); const findMoveToPositionComponent = () => wrapper.findComponent(BoardCardMoveToPosition); + const findWorkItemIcon = () => wrapper.findComponent(WorkItemTypeIcon); const performSearchMock = jest.fn(); @@ -145,6 +147,16 @@ describe('Board card component', () => { expect(findMoveToPositionComponent().exists()).toBe(true); }); + it('does not render the work type icon by default', () => { + expect(findWorkItemIcon().exists()).toBe(false); + }); + + it('renders the work type icon when props is passed', () => { + createWrapper({ item: issue, list, showWorkItemTypeIcon: true }); + expect(findWorkItemIcon().exists()).toBe(true); + expect(findWorkItemIcon().props('workItemType')).toBe(issue.type); + }); + it('renders issue ID with #', () => { expect(wrapper.find('.board-card-number').text()).toContain(`#${issue.iid}`); }); diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js index 1ee05d81f37ca2559d2538026243a6bc540a9d35..0e739f03f31b6b6bef8cb5fc81041ebcc8b7c32b 100644 --- a/spec/frontend/boards/mock_data.js +++ b/spec/frontend/boards/mock_data.js @@ -262,6 +262,7 @@ export const rawIssue = { epic: { id: 'gid://gitlab/Epic/41', }, + type: 'ISSUE', }; export const mockIssueFullPath = 'gitlab-org/test-subgroup/gitlab-test'; @@ -287,6 +288,7 @@ export const mockIssue = { epic: { id: 'gid://gitlab/Epic/41', }, + type: 'ISSUE', }; export const mockActiveIssue = {