diff options
Diffstat (limited to 'app/assets/javascripts/boards/components/issue_card_inner.vue')
-rw-r--r-- | app/assets/javascripts/boards/components/issue_card_inner.vue | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue new file mode 100644 index 00000000000..a0b7fe81a4a --- /dev/null +++ b/app/assets/javascripts/boards/components/issue_card_inner.vue @@ -0,0 +1,196 @@ +<script> + import $ from 'jquery'; + import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; + import eventHub from '../eventhub'; + + const Store = gl.issueBoards.BoardsStore; + + export default { + components: { + UserAvatarLink, + }, + props: { + issue: { + type: Object, + required: true, + }, + issueLinkBase: { + type: String, + required: true, + }, + list: { + type: Object, + required: false, + default: () => ({}), + }, + rootPath: { + type: String, + required: true, + }, + updateFilters: { + type: Boolean, + required: false, + default: false, + }, + groupId: { + type: Number, + required: false, + default: null, + }, + }, + data() { + return { + limitBeforeCounter: 3, + maxRender: 4, + maxCounter: 99, + }; + }, + computed: { + numberOverLimit() { + return this.issue.assignees.length - this.limitBeforeCounter; + }, + assigneeCounterTooltip() { + return `${this.assigneeCounterLabel} more`; + }, + assigneeCounterLabel() { + if (this.numberOverLimit > this.maxCounter) { + return `${this.maxCounter}+`; + } + + return `+${this.numberOverLimit}`; + }, + shouldRenderCounter() { + if (this.issue.assignees.length <= this.maxRender) { + return false; + } + + return this.issue.assignees.length > this.numberOverLimit; + }, + issueId() { + if (this.issue.iid) { + return `#${this.issue.iid}`; + } + return false; + }, + showLabelFooter() { + return this.issue.labels.find(l => this.showLabel(l)) !== undefined; + }, + }, + methods: { + isIndexLessThanlimit(index) { + return index < this.limitBeforeCounter; + }, + shouldRenderAssignee(index) { + // Eg. maxRender is 4, + // Render up to all 4 assignees if there are only 4 assigness + // Otherwise render up to the limitBeforeCounter + if (this.issue.assignees.length <= this.maxRender) { + return index < this.maxRender; + } + + return index < this.limitBeforeCounter; + }, + assigneeUrl(assignee) { + return `${this.rootPath}${assignee.username}`; + }, + assigneeUrlTitle(assignee) { + return `Assigned to ${assignee.name}`; + }, + avatarUrlTitle(assignee) { + return `Avatar for ${assignee.name}`; + }, + showLabel(label) { + if (!label.id) return false; + return true; + }, + filterByLabel(label, e) { + if (!this.updateFilters) return; + + const filterPath = gl.issueBoards.BoardsStore.filter.path.split('&'); + const labelTitle = encodeURIComponent(label.title); + const param = `label_name[]=${labelTitle}`; + const labelIndex = filterPath.indexOf(param); + $(e.currentTarget).tooltip('hide'); + + if (labelIndex === -1) { + filterPath.push(param); + } else { + filterPath.splice(labelIndex, 1); + } + + gl.issueBoards.BoardsStore.filter.path = filterPath.join('&'); + + Store.updateFiltersUrl(); + + eventHub.$emit('updateTokens'); + }, + labelStyle(label) { + return { + backgroundColor: label.color, + color: label.textColor, + }; + }, + }, + }; +</script> +<template> + <div> + <div class="board-card-header"> + <h4 class="board-card-title"> + <i + v-if="issue.confidential" + class="fa fa-eye-slash confidential-icon" + aria-hidden="true" + ></i> + <a + :href="issue.path" + :title="issue.title" + class="js-no-trigger">{{ issue.title }}</a> + <span + v-if="issueId" + class="board-card-number" + > + {{ issue.referencePath }} + </span> + </h4> + <div class="board-card-assignee"> + <user-avatar-link + v-for="(assignee, index) in issue.assignees" + v-if="shouldRenderAssignee(index)" + :key="assignee.id" + :link-href="assigneeUrl(assignee)" + :img-alt="avatarUrlTitle(assignee)" + :img-src="assignee.avatar" + :tooltip-text="assigneeUrlTitle(assignee)" + class="js-no-trigger" + tooltip-placement="bottom" + /> + <span + v-if="shouldRenderCounter" + :title="assigneeCounterTooltip" + class="avatar-counter has-tooltip" + > + {{ 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" + :style="labelStyle(label)" + :title="label.description" + class="badge color-label has-tooltip" + type="button" + data-container="body" + @click="filterByLabel(label, $event)" + > + {{ label.title }} + </button> + </div> + </div> +</template> |