diff options
author | Constance Okoghenun <cokoghenun@gitlab.com> | 2018-11-07 17:20:17 +0000 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2018-11-07 17:20:17 +0000 |
commit | baa37edd93d47e836835617ef08d6fc85ad3a689 (patch) | |
tree | 9241261a47917e76dc845eea5f47939d475d6685 /app/assets/javascripts/boards/components/issue_card_inner.vue | |
parent | 06e8cf58558cccc5a8556e94c93aa4bf25dc083e (diff) | |
download | gitlab-ce-baa37edd93d47e836835617ef08d6fc85ad3a689.tar.gz |
Resolve "Issue board card design"
Diffstat (limited to 'app/assets/javascripts/boards/components/issue_card_inner.vue')
-rw-r--r-- | app/assets/javascripts/boards/components/issue_card_inner.vue | 142 |
1 files changed, 94 insertions, 48 deletions
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue index d956777a86b..2315a48a306 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.vue +++ b/app/assets/javascripts/boards/components/issue_card_inner.vue @@ -1,18 +1,24 @@ <script> -import $ from 'jquery'; +import { GlTooltipDirective } from '@gitlab-org/gitlab-ui'; +import { sprintf, __ } from '~/locale'; import Icon from '~/vue_shared/components/icon.vue'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import eventHub from '../eventhub'; -import tooltip from '../../vue_shared/directives/tooltip'; +import IssueDueDate from './issue_due_date.vue'; +import IssueTimeEstimate from './issue_time_estimate.vue'; import boardsStore from '../stores/boards_store'; export default { components: { - UserAvatarLink, Icon, + UserAvatarLink, + TooltipOnTruncate, + IssueDueDate, + IssueTimeEstimate, }, directives: { - tooltip, + GlTooltip: GlTooltipDirective, }, props: { issue: { @@ -45,8 +51,8 @@ export default { }, data() { return { - limitBeforeCounter: 3, - maxRender: 4, + limitBeforeCounter: 2, + maxRender: 3, maxCounter: 99, }; }, @@ -55,7 +61,9 @@ export default { return this.issue.assignees.length - this.limitBeforeCounter; }, assigneeCounterTooltip() { - return `${this.assigneeCounterLabel} more`; + const { numberOverLimit, maxCounter } = this; + const count = numberOverLimit > maxCounter ? maxCounter : numberOverLimit; + return sprintf(__('%{count} more assignees'), { count }); }, assigneeCounterLabel() { if (this.numberOverLimit > this.maxCounter) { @@ -80,6 +88,10 @@ export default { showLabelFooter() { return this.issue.labels.find(l => this.showLabel(l)) !== undefined; }, + issueReferencePath() { + const { referencePath, groupId } = this.issue; + return !groupId ? referencePath.split('#')[0] : null; + }, }, methods: { isIndexLessThanlimit(index) { @@ -96,11 +108,9 @@ export default { return index < this.limitBeforeCounter; }, assigneeUrl(assignee) { + if (!assignee) return ''; return `${this.rootPath}${assignee.username}`; }, - assigneeUrlTitle(assignee) { - return `Assigned to ${assignee.name}`; - }, avatarUrlTitle(assignee) { return `Avatar for ${assignee.name}`; }, @@ -108,19 +118,29 @@ export default { if (!label.id) return false; return true; }, - filterByLabel(label, e) { + filterByLabel(label) { + if (!this.updateFilters) return; + const labelTitle = encodeURIComponent(label.title); + const filter = `label_name[]=${labelTitle}`; + + this.applyFilter(filter); + }, + filterByWeight(weight) { if (!this.updateFilters) return; + const issueWeight = encodeURIComponent(weight); + const filter = `weight=${issueWeight}`; + + this.applyFilter(filter); + }, + applyFilter(filter) { const filterPath = boardsStore.filter.path.split('&'); - const labelTitle = encodeURIComponent(label.title); - const param = `label_name[]=${labelTitle}`; - const labelIndex = filterPath.indexOf(param); - $(e.currentTarget).tooltip('hide'); + const filterIndex = filterPath.indexOf(filter); - if (labelIndex === -1) { - filterPath.push(param); + if (filterIndex === -1) { + filterPath.push(filter); } else { - filterPath.splice(labelIndex, 1); + filterPath.splice(filterIndex, 1); } boardsStore.filter.path = filterPath.join('&'); @@ -141,24 +161,62 @@ export default { <template> <div> <div class="board-card-header"> - <h4 class="board-card-title"> + <h4 class="board-card-title append-bottom-0 prepend-top-0"> <icon v-if="issue.confidential" + v-gl-tooltip name="eye-slash" - class="confidential-icon" - /> - <a + :title="__('Confidential')" + class="confidential-icon append-right-4" + :aria-label="__('Confidential')" + /><a :href="issue.path" :title="issue.title" class="js-no-trigger" @mousemove.stop>{{ issue.title }}</a> + </h4> + </div> + <div + v-if="showLabelFooter" + class="board-card-labels prepend-top-4 d-flex flex-wrap" + > + <button + v-for="label in issue.labels" + v-if="showLabel(label)" + :key="label.id" + v-gl-tooltip + :style="labelStyle(label)" + :title="label.description" + class="badge color-label append-right-4 prepend-top-4" + type="button" + @click="filterByLabel(label)" + > + {{ label.title }} + </button> + </div> + <div class="board-card-footer d-flex justify-content-between align-items-end"> + <div class="d-flex align-items-start flex-wrap-reverse board-card-number-container js-board-card-number-container"> <span - v-if="issueId" - class="board-card-number append-right-5" + v-if="issue.referencePath" + class="board-card-number d-flex append-right-8 prepend-top-8" > - {{ issue.referencePath }} + <tooltip-on-truncate + v-if="issueReferencePath" + :title="issueReferencePath" + placement="bottom" + class="board-issue-path block-truncated bold" + >{{ issueReferencePath }}</tooltip-on-truncate>#{{ issue.iid }} </span> - </h4> + <span class="board-info-items prepend-top-8 d-inline-block"> + <issue-due-date + v-if="issue.dueDate" + :date="issue.dueDate" + /><issue-time-estimate + v-if="issue.timeEstimate" + :estimate="issue.timeEstimate" + /> + </span> + </div> <div class="board-card-assignee"> <user-avatar-link v-for="(assignee, index) in issue.assignees" @@ -167,38 +225,26 @@ export default { :link-href="assigneeUrl(assignee)" :img-alt="avatarUrlTitle(assignee)" :img-src="assignee.avatar" - :tooltip-text="assigneeUrlTitle(assignee)" + :img-size="24" class="js-no-trigger" tooltip-placement="bottom" - /> + > + <span class="js-assignee-tooltip"> + <span class="bold d-block">Assignee</span> + {{ assignee.name }} + <span class="text-white-50">@{{ assignee.username }}</span> + </span> + </user-avatar-link> <span v-if="shouldRenderCounter" - v-tooltip + v-gl-tooltip :title="assigneeCounterTooltip" class="avatar-counter" + data-placement="bottom" > {{ assigneeCounterLabel }} </span> </div> </div> - <div - v-if="showLabelFooter" - class="board-card-footer" - > - <button - v-for="label in issue.labels" - v-if="showLabel(label)" - :key="label.id" - v-tooltip - :style="labelStyle(label)" - :title="label.description" - class="badge color-label" - type="button" - data-container="body" - @click="filterByLabel(label, $event)" - > - {{ label.title }} - </button> - </div> </div> </template> |