Skip to content
Snippets Groups Projects
Commit bc5a9206 authored by Clement Ho's avatar Clement Ho Committed by Filipa Lacerda
Browse files

Redesign for mr widget info and pipelines section

parent e0c0ce28
No related branches found
No related tags found
1 merge request!10495Merge Requests - Assignee
Showing
with 449 additions and 235 deletions
Loading
Loading
@@ -79,66 +79,62 @@ export default {
</script>
 
<template>
<div class="mr-widget-heading deploy-heading">
<div class="mr-widget-heading deploy-heading append-bottom-default">
<div class="ci-widget media">
<div class="ci-status-icon ci-status-icon-success">
<span class="js-icon-link icon-link">
<status-icon status="success" />
</span>
</div>
<div class="media-body">
<div class="deploy-body">
<template v-if="hasDeploymentMeta">
<span>
Deployed to
</span>
<a
:href="deployment.url"
target="_blank"
rel="noopener noreferrer nofollow"
class="deploy-link js-deploy-meta"
<div class="deployment-info">
<template v-if="hasDeploymentMeta">
<span>
Deployed to
</span>
<a
:href="deployment.url"
target="_blank"
rel="noopener noreferrer nofollow"
class="deploy-link js-deploy-meta"
>
{{ deployment.name }}
</a>
</template>
<span
v-tooltip
v-if="hasDeploymentTime"
:title="deployment.deployed_at_formatted"
class="js-deploy-time"
>
{{ deployment.name }}
</a>
</template>
<template v-if="hasExternalUrls">
<span>
on
{{ deployTimeago }}
</span>
<memory-usage
v-if="hasMetrics"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
/>
</div>
<div>
<a
v-if="hasExternalUrls"
:href="deployment.external_url"
target="_blank"
rel="noopener noreferrer nofollow"
class="deploy-link js-deploy-url"
class="deploy-link js-deploy-url btn btn-default btn-sm inline"
>
{{ deployment.external_url_formatted }}
<icon
:size="16"
name="external-link"
/>
<span>
View app
<icon name="external-link" />
</span>
</a>
</template>
<span
v-tooltip
v-if="hasDeploymentTime"
:title="deployment.deployed_at_formatted"
class="js-deploy-time"
>
{{ deployTimeago }}
</span>
<loading-button
v-if="deployment.stop_url"
:loading="isStopping"
container-class="btn btn-default btn-sm prepend-left-default"
label="Stop environment"
@click="stopEnvironment"
/>
<loading-button
v-if="deployment.stop_url"
:loading="isStopping"
container-class="btn btn-default btn-sm inline prepend-left-4"
title="Stop environment"
@click="stopEnvironment"
>
<icon name="stop" />
</loading-button>
</div>
</div>
<memory-usage
v-if="hasMetrics"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
/>
</div>
</div>
</div>
Loading
Loading
Loading
Loading
@@ -2,7 +2,7 @@
import tooltip from '~/vue_shared/directives/tooltip';
import { n__ } from '~/locale';
import { webIDEUrl } from '~/lib/utils/url_utility';
import icon from '~/vue_shared/components/icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
 
export default {
Loading
Loading
@@ -11,7 +11,7 @@ export default {
tooltip,
},
components: {
icon,
Icon,
clipboardButton,
},
props: {
Loading
Loading
@@ -54,104 +54,114 @@ export default {
};
</script>
<template>
<div class="mr-source-target">
<div class="normal">
<strong>
{{ s__("mrWidget|Request to merge") }}
<span
:class="{ 'label-truncated': isSourceBranchLong }"
:title="isSourceBranchLong ? mr.sourceBranch : ''"
:v-tooltip="isSourceBranchLong"
class="label-branch js-source-branch"
data-placement="bottom"
v-html="mr.sourceBranchLink"
>
</span>
<div class="mr-source-target append-bottom-default">
<div class="git-merge-icon-container append-right-default">
<icon name="git-merge" />
</div>
<div class="git-merge-container d-flex">
<div class="normal">
<strong>
{{ s__("mrWidget|Request to merge") }}
<span
:class="{ 'label-truncated': isSourceBranchLong }"
:title="isSourceBranchLong ? mr.sourceBranch : ''"
:v-tooltip="isSourceBranchLong"
class="label-branch js-source-branch"
data-placement="bottom"
v-html="mr.sourceBranchLink"
>
</span>
 
<clipboard-button
:text="branchNameClipboardData"
:title="__('Copy branch name to clipboard')"
css-class="btn-default btn-transparent btn-clipboard"
/>
<clipboard-button
:text="branchNameClipboardData"
:title="__('Copy branch name to clipboard')"
css-class="btn-default btn-transparent btn-clipboard"
/>
 
{{ s__("mrWidget|into") }}
{{ s__("mrWidget|into") }}
 
<span
:v-tooltip="isTargetBranchLong"
:class="{ 'label-truncatedtooltip': isTargetBranchLong }"
:title="isTargetBranchLong ? mr.targetBranch : ''"
class="label-branch"
data-placement="bottom"
>
<a
:href="mr.targetBranchTreePath"
class="js-target-branch"
<span
:v-tooltip="isTargetBranchLong"
:class="{ 'label-truncatedtooltip': isTargetBranchLong }"
:title="isTargetBranchLong ? mr.targetBranch : ''"
class="label-branch"
data-placement="bottom"
>
{{ mr.targetBranch }}
</a>
</span>
</strong>
<span
v-if="shouldShowCommitsBehindText"
class="diverged-commits-count"
>
(<a :href="mr.targetBranchPath">{{ commitsText }}</a>)
</span>
</div>
<a
:href="mr.targetBranchTreePath"
class="js-target-branch"
>
{{ mr.targetBranch }}
</a>
</span>
</strong>
<div
v-if="shouldShowCommitsBehindText"
class="diverged-commits-count"
>
<span class="monospace">{{ mr.sourceBranch }}</span>
is {{ commitsText }}
<span class="monospace">{{ mr.targetBranch }}</span>
</div>
</div>
 
<div v-if="mr.isOpen">
<a
v-if="!mr.sourceBranchRemoved"
:href="webIdePath"
class="btn btn-sm btn-default inline js-web-ide"
>
{{ s__("mrWidget|Web IDE") }}
</a>
<button
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
class="btn btn-sm btn-default inline js-check-out-branch"
type="button"
<div
v-if="mr.isOpen"
class="branch-actions"
>
{{ s__("mrWidget|Check out branch") }}
</button>
<span class="dropdown prepend-left-10">
<a
v-if="!mr.sourceBranchRemoved"
:href="webIdePath"
class="btn btn-default inline js-web-ide d-none d-md-inline-block"
>
{{ s__("mrWidget|Open in Web IDE") }}
</a>
<button
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
class="btn btn-default inline js-check-out-branch"
type="button"
class="btn btn-sm inline dropdown-toggle"
data-toggle="dropdown"
aria-label="Download as"
aria-haspopup="true"
aria-expanded="false"
>
<icon name="download" />
<i
class="fa fa-caret-down"
aria-hidden="true">
</i>
{{ s__("mrWidget|Check out branch") }}
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li>
<a
:href="mr.emailPatchesPath"
class="js-download-email-patches"
download
>
{{ s__("mrWidget|Email patches") }}
</a>
</li>
<li>
<a
:href="mr.plainDiffPath"
class="js-download-plain-diff"
download
>
{{ s__("mrWidget|Plain diff") }}
</a>
</li>
</ul>
</span>
<span class="dropdown prepend-left-10">
<button
type="button"
class="btn inline dropdown-toggle"
data-toggle="dropdown"
aria-label="Download as"
aria-haspopup="true"
aria-expanded="false"
>
<icon name="download" />
<i
class="fa fa-caret-down"
aria-hidden="true">
</i>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li>
<a
:href="mr.emailPatchesPath"
class="js-download-email-patches"
download
>
{{ s__("mrWidget|Email patches") }}
</a>
</li>
<li>
<a
:href="mr.plainDiffPath"
class="js-download-plain-diff"
download
>
{{ s__("mrWidget|Plain diff") }}
</a>
</li>
</ul>
</span>
</div>
</div>
</div>
</template>
Loading
Loading
@@ -26,6 +26,10 @@ export default {
type: String,
required: false,
},
sourceBranchLink: {
type: String,
required: false,
},
},
computed: {
hasPipeline() {
Loading
Loading
@@ -54,12 +58,18 @@ export default {
<template>
<div
v-if="hasPipeline || hasCIError"
class="mr-widget-heading"
class="mr-widget-heading append-bottom-default"
>
<div class="ci-widget media">
<template v-if="hasCIError">
<div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-10">
<icon name="status_failed" />
<div
class="add-border ci-status-icon ci-status-icon-failed ci-error
js-ci-error append-right-default"
>
<icon
:size="32"
name="status_failed_borderless"
/>
</div>
<div class="media-body">
Could not connect to the CI server. Please check your settings and try again
Loading
Loading
@@ -68,50 +78,66 @@ export default {
<template v-else-if="hasPipeline">
<a
:href="status.details_path"
class="append-right-10"
class="align-self-start append-right-default"
>
<ci-icon :status="status" />
<ci-icon
:status="status"
:size="32"
:borderless="true"
class="add-border"
/>
</a>
<div class="ci-widget-container d-flex">
<div class="ci-widget-content">
<div class="media-body">
<div class="font-weight-bold">
Pipeline
<a
:href="pipeline.path"
class="pipeline-id font-weight-normal pipeline-number"
>#{{ pipeline.id }}</a>
 
<div class="media-body">
Pipeline
<a
:href="pipeline.path"
class="pipeline-id"
>
#{{ pipeline.id }}
</a>
{{ pipeline.details.status.label }}
{{ pipeline.details.status.label }}
 
<template v-if="hasCommitInfo">
for
<a
:href="pipeline.commit.commit_path"
class="commit-sha js-commit-link"
>
{{ pipeline.commit.short_id }}</a>.
</template>
<span class="mr-widget-pipeline-graph">
<span
v-if="hasStages"
class="stage-cell"
>
<template v-if="hasCommitInfo">
for
<a
:href="pipeline.commit.commit_path"
class="commit-sha js-commit-link font-weight-normal"
>
{{ pipeline.commit.short_id }}</a>
on
<span
class="label-branch"
v-html="sourceBranchLink"
>
</span>
</template>
</div>
<div
v-for="(stage, i) in pipeline.details.stages"
:key="i"
class="stage-container dropdown js-mini-pipeline-graph"
v-if="pipeline.coverage"
class="coverage"
>
<pipeline-stage :stage="stage" />
Coverage {{ pipeline.coverage }}%
</div>
</div>
</div>
<div>
<span class="mr-widget-pipeline-graph">
<span
v-if="hasStages"
class="stage-cell"
>
<div
v-for="(stage, i) in pipeline.details.stages"
:key="i"
class="stage-container dropdown js-mini-pipeline-graph mr-widget-pipeline-stages"
>
<pipeline-stage :stage="stage" />
</div>
</span>
</span>
</span>
<template v-if="pipeline.coverage">
Coverage {{ pipeline.coverage }}%
</template>
</div>
</div>
</template>
</div>
Loading
Loading
Loading
Loading
@@ -43,6 +43,7 @@
<ci-icon
v-else
:status="statusObj"
:size="24"
/>
 
<button
Loading
Loading
Loading
Loading
@@ -252,41 +252,44 @@ export default {
:pipeline="mr.pipeline"
:ci-status="mr.ciStatus"
:has-ci="mr.hasCI"
:source-branch-link="mr.sourceBranchLink"
/>
<deployment
v-for="deployment in mr.deployments"
:key="deployment.id"
:deployment="deployment"
/>
<div class="mr-widget-section">
<component
:is="componentName"
:mr="mr"
:service="service"
/>
<div class="mr-section-container">
<div class="mr-widget-section">
<component
:is="componentName"
:mr="mr"
:service="service"
/>
 
<section
v-if="mr.allowCollaboration"
class="mr-info-list mr-links"
>
{{ s__("mrWidget|Allows commits from members who can merge to the target branch") }}
</section>
<section
v-if="mr.allowCollaboration"
class="mr-info-list mr-links"
>
{{ s__("mrWidget|Allows commits from members who can merge to the target branch") }}
</section>
 
<mr-widget-related-links
v-if="shouldRenderRelatedLinks"
:state="mr.state"
:related-links="mr.relatedLinks"
/>
<mr-widget-related-links
v-if="shouldRenderRelatedLinks"
:state="mr.state"
:related-links="mr.relatedLinks"
/>
 
<source-branch-removal-status
v-if="shouldRenderSourceBranchRemovalStatus"
/>
</div>
<div
v-if="shouldRenderMergeHelp"
class="mr-widget-footer"
>
<mr-widget-merge-help />
<source-branch-removal-status
v-if="shouldRenderSourceBranchRemovalStatus"
/>
</div>
<div
v-if="shouldRenderMergeHelp"
class="mr-widget-footer"
>
<mr-widget-merge-help />
</div>
</div>
</div>
</template>
Loading
Loading
@@ -3,12 +3,20 @@
svg {
fill: $green-500;
}
&.add-border {
@include borderless-status-icon($green-500);
}
}
 
.ci-status-icon-failed {
svg {
fill: $gl-danger;
}
&.add-border {
@include borderless-status-icon($red-500);
}
}
 
.ci-status-icon-pending,
Loading
Loading
@@ -17,12 +25,20 @@
svg {
fill: $orange-500;
}
&.add-border {
@include borderless-status-icon($orange-500);
}
}
 
.ci-status-icon-running {
svg {
fill: $blue-400;
}
&.add-border {
@include borderless-status-icon($blue-400);
}
}
 
.ci-status-icon-canceled,
Loading
Loading
@@ -30,6 +46,10 @@
svg {
fill: $gl-text-color;
}
&.add-border {
@include borderless-status-icon($gl-text-color);
}
}
 
.ci-status-icon-created,
Loading
Loading
@@ -38,6 +58,10 @@
svg {
fill: $gray-darkest;
}
&.add-border {
@include borderless-status-icon($gray-darkest);
}
}
 
.ci-status-icon-manual {
Loading
Loading
Loading
Loading
@@ -232,3 +232,10 @@
word-break: break-word;
max-width: 100%;
}
@mixin borderless-status-icon($color) {
svg {
border: 1px solid $color;
border-radius: 50%;
}
}
Loading
Loading
@@ -350,7 +350,8 @@ code {
}
 
.commit-sha,
.ref-name {
.ref-name,
.pipeline-number {
@extend .monospace;
font-size: 95%;
}
Loading
Loading
Loading
Loading
@@ -743,6 +743,7 @@ Pipeline Graph
*/
$stage-hover-bg: $gray-darker;
$ci-action-icon-size: 22px;
$ci-action-icon-size-lg: 24px;
$pipeline-dropdown-line-height: 20px;
$pipeline-dropdown-status-icon-size: 18px;
$ci-action-dropdown-button-size: 24px;
Loading
Loading
Loading
Loading
@@ -15,16 +15,38 @@
}
}
 
.mr-widget-heading {
position: relative;
border: 1px solid $border-color;
border-radius: 4px;
&:not(.deploy-heading)::before {
content: '';
border-left: 1px solid $theme-gray-200;
position: absolute;
left: 32px;
top: -17px;
height: 16px;
}
}
.mr-section-container {
border: 1px solid $border-color;
border-radius: $border-radius-default;
border-top: 0;
}
.mr-widget-heading,
.mr-widget-section,
.mr-widget-footer {
padding: $gl-padding;
}
.mr-state-widget {
color: $gl-text-color;
border: 1px solid $border-color;
border-radius: 2px;
line-height: 28px;
 
.mr-widget-heading,
.mr-widget-section,
.mr-widget-footer {
padding: $gl-padding;
border-top: solid 1px $border-color;
}
 
Loading
Loading
@@ -124,10 +146,17 @@
.ci-widget {
color: $gl-text-color;
display: flex;
align-items: center;
justify-content: space-between;
 
@include media-breakpoint-down(xs) {
flex-wrap: wrap;
}
.ci-widget-content {
display: flex;
align-items: center;
}
}
 
.mr-widget-icon {
Loading
Loading
@@ -136,8 +165,6 @@
}
 
.ci-status-icon svg {
width: $status-icon-size;
height: $status-icon-size;
margin: 3px 0;
position: relative;
overflow: visible;
Loading
Loading
@@ -145,8 +172,6 @@
}
 
.mr-widget-pipeline-graph {
padding: 0 4px;
.dropdown-menu {
z-index: 300;
}
Loading
Loading
@@ -157,7 +182,7 @@
}
 
.normal {
line-height: 28px;
flex: 1;
}
 
.capitalize {
Loading
Loading
@@ -168,7 +193,7 @@
@extend .ref-name;
 
color: $gl-text-color;
font-weight: $gl-font-weight-bold;
font-weight: normal;
overflow: hidden;
word-break: break-all;
 
Loading
Loading
@@ -192,6 +217,8 @@
}
 
.mr-widget-body {
line-height: 28px;
@include clearfix;
 
&.media > *:first-child {
Loading
Loading
@@ -474,18 +501,66 @@
}
}
 
.merge-request-details .content-block {
border-bottom: 0;
}
.mr-source-target {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
background-color: $gray-light;
border-radius: $border-radius-default $border-radius-default 0 0;
padding: $gl-padding / 2 $gl-padding;
border-radius: $border-radius-default;
padding: $gl-padding;
border: 1px solid $border-color;
min-height: 69px;
@include media-breakpoint-up(md) {
align-items: center;
}
 
.dropdown-toggle .fa {
color: $gl-text-color;
}
.git-merge-icon-container {
border: 1px solid $theme-gray-400;
border-radius: 50%;
height: 32px;
width: 32px;
color: $theme-gray-700;
line-height: 28px;
.ic-git-merge {
vertical-align: middle;
width: 31px;
}
}
.git-merge-container {
justify-content: space-between;
flex: 1;
flex-direction: row;
align-items: center;
@include media-breakpoint-down(md) {
flex-direction: column;
align-items: flex-start;
.branch-actions {
margin-top: 16px;
}
}
@include media-breakpoint-up(lg) {
.branch-actions {
align-self: center;
}
}
}
.diverged-commits-count {
color: $gl-text-color-secondary;
font-size: 12px;
}
}
 
.card-new-merge-request {
Loading
Loading
@@ -720,13 +795,25 @@
}
 
.deploy-heading {
margin-top: -19px;
border-top-left-radius: 0;
border-top-right-radius: 0;
background-color: $gray-light;
@include media-breakpoint-up(md) {
padding: $gl-padding-8 $gl-padding;
}
.media-body {
min-width: 0;
font-size: 12px;
margin-left: 48px;
}
}
 
.deploy-body {
display: flex;
align-items: center;
flex-wrap: wrap;
 
@include media-breakpoint-up(xs) {
Loading
Loading
@@ -734,6 +821,15 @@
white-space: nowrap;
}
 
@include media-breakpoint-down(md) {
flex-direction: column;
align-items: flex-start;
.deployment-info {
margin-bottom: $gl-padding;
}
}
> *:not(:last-child) {
margin-right: .3em;
}
Loading
Loading
@@ -741,18 +837,22 @@
svg {
vertical-align: text-top;
}
}
 
.deploy-link {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 100px;
max-width: 150px;
.deployment-info {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 100px;
 
@include media-breakpoint-up(xs) {
min-width: 0;
max-width: 100%;
@include media-breakpoint-up(xs) {
min-width: 0;
max-width: 100%;
}
}
.btn svg {
fill: $theme-gray-700;
}
}
 
Loading
Loading
@@ -772,3 +872,33 @@
}
}
}
.ci-widget-container {
justify-content: space-between;
flex: 1;
flex-direction: row;
@include media-breakpoint-down(md) {
flex-direction: column;
.stage-cell .stage-container {
margin-top: 16px;
}
.dropdown .mini-pipeline-graph-dropdown-menu.dropdown-menu {
transform: initial;
}
}
.coverage {
font-size: 12px;
color: $theme-gray-700;
line-height: initial;
}
.mini-pipeline-graph-dropdown-toggle,
.stage-cell .mini-pipeline-graph-dropdown-toggle svg {
height: $ci-action-icon-size-lg;
width: $ci-action-icon-size-lg;
}
}
Loading
Loading
@@ -301,6 +301,21 @@
border-bottom: 2px solid $border-color;
}
}
//delete when all pipelines are updated to new size
&.mr-widget-pipeline-stages {
+ .stage-container {
margin-left: 4px;
}
&:not(:last-child) {
&::after {
width: 4px;
right: -4px;
top: 11px;
}
}
}
}
}
 
Loading
Loading
Loading
Loading
@@ -153,7 +153,7 @@ describe('Deployment component', () => {
 
it('renders external URL', () => {
expect(el.querySelector('.js-deploy-url').getAttribute('href')).toEqual(deploymentMockData.external_url);
expect(el.querySelector('.js-deploy-url').innerText).toContain(deploymentMockData.external_url_formatted);
expect(el.querySelector('.js-deploy-url').innerText).toContain('View app');
});
 
it('renders stop button', () => {
Loading
Loading
Loading
Loading
@@ -145,7 +145,7 @@ describe('MRWidgetHeader', () => {
it('renders web ide button', () => {
const button = vm.$el.querySelector('.js-web-ide');
 
expect(button.textContent.trim()).toEqual('Web IDE');
expect(button.textContent.trim()).toEqual('Open in Web IDE');
expect(button.getAttribute('href')).toEqual('/-/ide/projectabc');
});
 
Loading
Loading
@@ -154,7 +154,7 @@ describe('MRWidgetHeader', () => {
 
const button = vm.$el.querySelector('.js-web-ide');
 
expect(button.textContent.trim()).toEqual('Web IDE');
expect(button.textContent.trim()).toEqual('Open in Web IDE');
expect(button.getAttribute('href')).toEqual('/-/ide/projectabc');
});
 
Loading
Loading
@@ -253,8 +253,8 @@ describe('MRWidgetHeader', () => {
});
 
it('renders diverged commits info', () => {
expect(vm.$el.querySelector('.diverged-commits-count').textContent.trim()).toEqual(
'(12 commits behind)',
expect(vm.$el.querySelector('.diverged-commits-count').textContent).toMatch(
/(mr-widget-refactor[\s\S]+?is 12 commits behind[\s\S]+?master)/,
);
});
});
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment