diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-05 00:07:50 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-05 00:07:50 +0000 |
commit | 54cbcea92909e69248abc9e6b92c7d14db3308a5 (patch) | |
tree | 1276f1c57b5ab1064db7197c2d28a8837d68d02d /app/assets | |
parent | 71221554dd9ddf30f73035c89f78164e001aa96d (diff) | |
download | gitlab-ce-54cbcea92909e69248abc9e6b92c7d14db3308a5.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
5 files changed, 181 insertions, 24 deletions
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js index 2ffe07500e0..7b373a8ce22 100644 --- a/app/assets/javascripts/performance_bar/index.js +++ b/app/assets/javascripts/performance_bar/index.js @@ -70,9 +70,9 @@ export default ({ container }) => let durationString = ''; if (navigationEntries.length > 0) { - durationString = `BE ${this.formatMs(navigationEntries[0].responseEnd)} / `; - durationString += `FCP ${this.formatMs(paintEntries[1].startTime)} / `; - durationString += `DOM ${this.formatMs(navigationEntries[0].domContentLoadedEventEnd)}`; + durationString = `${Math.round(navigationEntries[0].responseEnd)} | `; + durationString += `${Math.round(paintEntries[1].startTime)} | `; + durationString += ` ${Math.round(navigationEntries[0].domContentLoadedEventEnd)}`; } let newEntries = resourceEntries.map(this.transformResourceEntry); @@ -105,10 +105,6 @@ export default ({ container }) => size: entry.transferSize ? `${nf.format(entry.transferSize)} bytes` : 'cached', }; }, - formatMs(msValue) { - const nf = new Intl.NumberFormat(); - return `${nf.format(Math.round(msValue))}ms`; - }, }, render(createElement) { return createElement('performance-bar-app', { diff --git a/app/assets/javascripts/releases/list/components/release_block.vue b/app/assets/javascripts/releases/list/components/release_block.vue index 2ae6b1a595f..09ef857ae4a 100644 --- a/app/assets/javascripts/releases/list/components/release_block.vue +++ b/app/assets/javascripts/releases/list/components/release_block.vue @@ -12,6 +12,7 @@ import { scrollToElement } from '~/lib/utils/common_utils'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import ReleaseBlockFooter from './release_block_footer.vue'; import EvidenceBlock from './evidence_block.vue'; +import ReleaseBlockMilestoneInfo from './release_block_milestone_info.vue'; export default { name: 'ReleaseBlock', @@ -23,6 +24,7 @@ export default { Icon, UserAvatarLink, ReleaseBlockFooter, + ReleaseBlockMilestoneInfo, }, directives: { GlTooltip: GlTooltipDirective, @@ -90,6 +92,12 @@ export default { shouldShowFooter() { return this.glFeatures.releaseIssueSummary; }, + shouldRenderReleaseMetaData() { + return !this.glFeatures.releaseIssueSummary; + }, + shouldRenderMilestoneInfo() { + return Boolean(this.glFeatures.releaseIssueSummary && !_.isEmpty(this.release.milestones)); + }, }, mounted() { const hash = getLocationHash(); @@ -106,26 +114,30 @@ export default { </script> <template> <div :id="id" :class="{ 'bg-line-target-blue': isHighlighted }" class="card release-block"> + <div class="card-header d-flex align-items-center bg-white pr-0"> + <h2 class="card-title my-2 mr-auto gl-font-size-20"> + {{ release.name }} + <gl-badge v-if="release.upcoming_release" variant="warning" class="align-middle">{{ + __('Upcoming Release') + }}</gl-badge> + </h2> + <gl-link + v-if="shouldShowEditButton" + v-gl-tooltip + class="btn btn-default append-right-10 js-edit-button ml-2" + :title="__('Edit this release')" + :href="release._links.edit_url" + > + <icon name="pencil" /> + </gl-link> + </div> <div class="card-body"> - <div class="d-flex align-items-start"> - <h2 class="card-title mt-0 mr-auto"> - {{ release.name }} - <gl-badge v-if="release.upcoming_release" variant="warning" class="align-middle">{{ - __('Upcoming Release') - }}</gl-badge> - </h2> - <gl-link - v-if="shouldShowEditButton" - v-gl-tooltip - class="btn btn-default js-edit-button ml-2" - :title="__('Edit this release')" - :href="release._links.edit_url" - > - <icon name="pencil" /> - </gl-link> + <div v-if="shouldRenderMilestoneInfo"> + <release-block-milestone-info :milestones="release.milestones" /> + <hr class="mb-3 mt-0" /> </div> - <div class="card-subtitle d-flex flex-wrap text-secondary"> + <div v-if="shouldRenderReleaseMetaData" class="card-subtitle d-flex flex-wrap text-secondary"> <div class="append-right-8"> <icon name="commit" class="align-middle" /> <gl-link v-if="commitUrl" v-gl-tooltip.bottom :title="commit.title" :href="commitUrl"> diff --git a/app/assets/javascripts/releases/list/components/release_block_milestone_info.vue b/app/assets/javascripts/releases/list/components/release_block_milestone_info.vue new file mode 100644 index 00000000000..d3e354d6157 --- /dev/null +++ b/app/assets/javascripts/releases/list/components/release_block_milestone_info.vue @@ -0,0 +1,136 @@ +<script> +import { GlProgressBar, GlLink, GlBadge, GlButton, GlTooltipDirective } from '@gitlab/ui'; +import { __, n__, sprintf } from '~/locale'; +import { MAX_MILESTONES_TO_DISPLAY } from '../constants'; + +/** Sums the values of an array. For use with Array.reduce. */ +const sumReducer = (acc, curr) => acc + curr; + +export default { + name: 'ReleaseBlockMilestoneInfo', + components: { + GlProgressBar, + GlLink, + GlBadge, + GlButton, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + props: { + milestones: { + type: Array, + required: true, + }, + }, + data() { + return { + showAllMilestones: false, + }; + }, + computed: { + percentCompleteText() { + return sprintf(__('%{percent}%{percentSymbol} complete'), { + percent: this.percentComplete, + percentSymbol: '%', + }); + }, + percentComplete() { + const percent = Math.round((this.closedIssuesCount / this.totalIssuesCount) * 100); + return Number.isNaN(percent) ? 0 : percent; + }, + allIssueStats() { + return this.milestones.map(m => m.issue_stats || {}); + }, + openIssuesCount() { + return this.allIssueStats.map(stats => stats.opened || 0).reduce(sumReducer); + }, + closedIssuesCount() { + return this.allIssueStats.map(stats => stats.closed || 0).reduce(sumReducer); + }, + totalIssuesCount() { + return this.openIssuesCount + this.closedIssuesCount; + }, + milestoneLabelText() { + return n__('Milestone', 'Milestones', this.milestones.length); + }, + issueCountsText() { + return sprintf(__('Open: %{open} • Closed: %{closed}'), { + open: this.openIssuesCount, + closed: this.closedIssuesCount, + }); + }, + milestonesToDisplay() { + return this.showAllMilestones + ? this.milestones + : this.milestones.slice(0, MAX_MILESTONES_TO_DISPLAY); + }, + showMoreLink() { + return this.milestones.length > MAX_MILESTONES_TO_DISPLAY; + }, + moreText() { + return this.showAllMilestones + ? __('show fewer') + : sprintf(__('show %{count} more'), { + count: this.milestones.length - MAX_MILESTONES_TO_DISPLAY, + }); + }, + }, + methods: { + toggleShowAll() { + this.showAllMilestones = !this.showAllMilestones; + }, + shouldRenderBullet(milestoneIndex) { + return Boolean(milestoneIndex !== this.milestonesToDisplay.length - 1 || this.showMoreLink); + }, + shouldRenderShowMoreLink(milestoneIndex) { + return Boolean(milestoneIndex === this.milestonesToDisplay.length - 1 && this.showMoreLink); + }, + }, +}; +</script> +<template> + <div class="release-block-milestone-info d-flex align-items-start flex-wrap"> + <div + v-gl-tooltip + class="milestone-progress-bar-container js-milestone-progress-bar-container d-flex flex-column align-items-start flex-shrink-1 mr-4 mb-3" + :title="__('Closed issues')" + > + <span class="mb-2">{{ percentCompleteText }}</span> + <span class="w-100"> + <gl-progress-bar :value="closedIssuesCount" :max="totalIssuesCount" variant="success" /> + </span> + </div> + <div class="d-flex flex-column align-items-start mr-4 mb-3 js-milestone-list-container"> + <span class="mb-1">{{ milestoneLabelText }}</span> + <div class="d-flex flex-wrap align-items-end"> + <template v-for="(milestone, index) in milestonesToDisplay"> + <gl-link + :key="milestone.id" + v-gl-tooltip + :title="milestone.description" + :href="milestone.web_url" + class="append-right-4" + > + {{ milestone.title }} + </gl-link> + <template v-if="shouldRenderBullet(index)"> + <span :key="'bullet-' + milestone.id" class="append-right-4">•</span> + </template> + <template v-if="shouldRenderShowMoreLink(index)"> + <gl-button :key="'more-button-' + milestone.id" variant="link" @click="toggleShowAll"> + {{ moreText }} + </gl-button> + </template> + </template> + </div> + </div> + <div class="d-flex flex-column align-items-start flex-shrink-0 mr-4 mb-3 js-issues-container"> + <span class="mb-1"> + {{ __('Issues') }} + <gl-badge pill variant="light" class="font-weight-bold">{{ totalIssuesCount }}</gl-badge> + </span> + {{ issueCountsText }} + </div> + </div> +</template> diff --git a/app/assets/javascripts/releases/list/constants.js b/app/assets/javascripts/releases/list/constants.js new file mode 100644 index 00000000000..defcd917465 --- /dev/null +++ b/app/assets/javascripts/releases/list/constants.js @@ -0,0 +1,7 @@ +/* eslint-disable import/prefer-default-export */ +// This eslint-disable ^^^ can be removed when at least +// one more constant is added to this file. Currently +// constants.js files with only a single constant +// are flagged by this rule. + +export const MAX_MILESTONES_TO_DISPLAY = 5; diff --git a/app/assets/stylesheets/components/release_block_milestone_info.scss b/app/assets/stylesheets/components/release_block_milestone_info.scss new file mode 100644 index 00000000000..b6a85ae965a --- /dev/null +++ b/app/assets/stylesheets/components/release_block_milestone_info.scss @@ -0,0 +1,6 @@ +.release-block-milestone-info { + .milestone-progress-bar-container { + width: 300px; + min-height: 46px; + } +} |