Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
1c10fa21
Commit
1c10fa21
authored
Dec 03, 2018
by
Paul Slaughter
Committed by
Phil Hughes
Dec 03, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Redesign of MR header sections
parent
d390f8f7
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
453 additions
and
205 deletions
+453
-205
app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
...cripts/vue_merge_request_widget/components/deployment.vue
+1
-1
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_container.vue
...e_merge_request_widget/components/mr_widget_container.vue
+6
-0
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
.../vue_merge_request_widget/components/mr_widget_header.vue
+3
-1
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue
...ts/vue_merge_request_widget/components/mr_widget_icon.vue
+17
-0
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
...ue_merge_request_widget/components/mr_widget_pipeline.vue
+63
-66
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
...equest_widget/components/mr_widget_pipeline_container.vue
+74
-0
app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
...avascripts/vue_merge_request_widget/mr_widget_options.vue
+12
-36
app/assets/stylesheets/framework/icons.scss
app/assets/stylesheets/framework/icons.scss
+12
-0
app/assets/stylesheets/pages/merge_requests.scss
app/assets/stylesheets/pages/merge_requests.scss
+17
-21
changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
...elogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
+5
-0
ee/app/assets/javascripts/vue_merge_request_widget/components/approvals/mr_widget_approvals.vue
...quest_widget/components/approvals/mr_widget_approvals.vue
+31
-33
ee/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
...avascripts/vue_merge_request_widget/mr_widget_options.vue
+15
-34
ee/app/assets/stylesheets/pages/merge_requests.scss
ee/app/assets/stylesheets/pages/merge_requests.scss
+0
-8
ee/changelogs/unreleased/1979-redesign-mr-widget-approvals.yml
...angelogs/unreleased/1979-redesign-mr-widget-approvals.yml
+5
-0
ee/spec/features/merge_request/user_approves_spec.rb
ee/spec/features/merge_request/user_approves_spec.rb
+2
-2
ee/spec/features/merge_request/user_sees_approval_widget_spec.rb
.../features/merge_request/user_sees_approval_widget_spec.rb
+2
-2
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/features/merge_request/user_sees_merge_widget_spec.rb
spec/features/merge_request/user_sees_merge_widget_spec.rb
+1
-1
spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js
...ipts/vue_mr_widget/components/mr_widget_container_spec.js
+51
-0
spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js
...vascripts/vue_mr_widget/components/mr_widget_icon_spec.js
+30
-0
spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
...mr_widget/components/mr_widget_pipeline_container_spec.js
+90
-0
spec/javascripts/vue_mr_widget/mock_data.js
spec/javascripts/vue_mr_widget/mock_data.js
+13
-0
No files found.
app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
View file @
1c10fa21
...
@@ -112,7 +112,7 @@ export default {
...
@@ -112,7 +112,7 @@ export default {
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"
mr-widget-heading deploy-heading append-bottom-default
"
>
<div
class=
"
deploy-heading
"
>
<div
class=
"ci-widget media"
>
<div
class=
"ci-widget media"
>
<div
class=
"media-body"
>
<div
class=
"media-body"
>
<div
class=
"deploy-body"
>
<div
class=
"deploy-body"
>
...
...
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_container.vue
0 → 100644
View file @
1c10fa21
<
template
>
<div
class=
"mr-widget-heading"
>
<div
class=
"mr-widget-content"
><slot
name=
"default"
></slot></div>
<slot
name=
"footer"
></slot>
</div>
</
template
>
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
View file @
1c10fa21
...
@@ -6,6 +6,7 @@ import Icon from '~/vue_shared/components/icon.vue';
...
@@ -6,6 +6,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import
clipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
clipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
import
MrWidgetIcon
from
'
./mr_widget_icon.vue
'
;
export
default
{
export
default
{
name
:
'
MRWidgetHeader
'
,
name
:
'
MRWidgetHeader
'
,
...
@@ -13,6 +14,7 @@ export default {
...
@@ -13,6 +14,7 @@ export default {
Icon
,
Icon
,
clipboardButton
,
clipboardButton
,
TooltipOnTruncate
,
TooltipOnTruncate
,
MrWidgetIcon
,
},
},
directives
:
{
directives
:
{
tooltip
,
tooltip
,
...
@@ -76,7 +78,7 @@ export default {
...
@@ -76,7 +78,7 @@ export default {
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"mr-source-target append-bottom-default"
>
<div
class=
"mr-source-target append-bottom-default"
>
<
div
class=
"git-merge-icon-container append-right-default"
><icon
name=
"git-merge"
/></div
>
<
mr-widget-icon
name=
"git-merge"
/
>
<div
class=
"git-merge-container d-flex"
>
<div
class=
"git-merge-container d-flex"
>
<div
class=
"normal"
>
<div
class=
"normal"
>
<strong>
<strong>
...
...
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue
0 → 100644
View file @
1c10fa21
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
export
default
{
components
:
{
Icon
},
props
:
{
name
:
{
type
:
String
,
required
:
true
,
},
},
};
</
script
>
<
template
>
<div
class=
"circle-icon-container append-right-default"
><icon
:name=
"name"
/></div>
</
template
>
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
View file @
1c10fa21
...
@@ -91,77 +91,74 @@ export default {
...
@@ -91,77 +91,74 @@ export default {
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<div
v-if=
"hasPipeline || hasCIError"
class=
"mr-widget-heading append-bottom-default"
>
<div
v-if=
"hasPipeline || hasCIError"
class=
"ci-widget media"
>
<div
class=
"ci-widget media"
>
<template
v-if=
"hasCIError"
>
<template
v-if=
"hasCIError"
>
<div
<div
class=
"add-border ci-status-icon ci-status-icon-failed ci-error
class=
"add-border ci-status-icon ci-status-icon-failed ci-error
js-ci-error append-right-default"
js-ci-error append-right-default"
>
>
<icon
:size=
"32"
name=
"status_failed_borderless"
/>
<icon
:size=
"32"
name=
"status_failed_borderless"
/>
</div>
</div>
<div
class=
"media-body"
v-html=
"errorText"
></div>
<div
class=
"media-body"
v-html=
"errorText"
></div>
</
template
>
</
template
>
<
template
v-else-if=
"hasPipeline"
>
<
template
v-else-if=
"hasPipeline"
>
<a
:href=
"status.details_path"
class=
"align-self-start append-right-default"
>
<a
:href=
"status.details_path"
class=
"align-self-start append-right-default"
>
<ci-icon
:status=
"status"
:size=
"32"
:borderless=
"true"
class=
"add-border"
/>
<ci-icon
:status=
"status"
:size=
"32"
:borderless=
"true"
class=
"add-border"
/>
</a>
</a>
<div
class=
"ci-widget-container d-flex"
>
<div
class=
"ci-widget-container d-flex"
>
<div
class=
"ci-widget-content"
>
<div
class=
"ci-widget-content"
>
<div
class=
"media-body"
>
<div
class=
"media-body"
>
<div
class=
"font-weight-bold"
>
<div
class=
"font-weight-bold"
>
Pipeline
Pipeline
<a
:href=
"pipeline.path"
class=
"pipeline-id font-weight-normal pipeline-number"
<a
:href=
"pipeline.path"
class=
"pipeline-id font-weight-normal pipeline-number"
>
#
{{
pipeline
.
id
}}
</a
>
#
{{
pipeline
.
id
}}
</a
>
>
{{
pipeline
.
details
.
status
.
label
}}
{{
pipeline
.
details
.
status
.
label
}}
<template
v-if=
"hasCommitInfo"
>
<template
v-if=
"hasCommitInfo"
>
for
for
<a
<a
:href=
"pipeline.commit.commit_path"
:href=
"pipeline.commit.commit_path"
class=
"commit-sha js-commit-link font-weight-normal"
class=
"commit-sha js-commit-link font-weight-normal"
>
>
{{
pipeline
.
commit
.
short_id
}}
</a
{{
pipeline
.
commit
.
short_id
}}
</a
>
>
on
on
<tooltip-on-truncate
<tooltip-on-truncate
:title=
"sourceBranch"
:title=
"sourceBranch"
truncate-target=
"child"
truncate-target=
"child"
class=
"label-branch label-truncate"
class=
"label-branch label-truncate"
v-html=
"sourceBranchLink"
v-html=
"sourceBranchLink"
/>
/>
</
template
>
</
template
>
</div>
<div
v-if=
"pipeline.coverage"
class=
"coverage"
>
Coverage {{ pipeline.coverage }}%
</div>
</div>
</div>
<div
v-if=
"pipeline.coverage"
class=
"coverage"
>
Coverage {{ pipeline.coverage }}%
</div>
</div>
</div>
<div>
</div>
<span
class=
"mr-widget-pipeline-graph"
>
<div>
<span
class=
"stage-cell"
>
<span
class=
"mr-widget-pipeline-graph"
>
<linked-pipelines-mini-list
v-if=
"triggeredBy.length"
:triggered-by=
"triggeredBy"
/>
<span
class=
"stage-cell"
>
<
template
v-if=
"hasStages"
>
<linked-pipelines-mini-list
v-if=
"triggeredBy.length"
:triggered-by=
"triggeredBy"
/>
<div
<
template
v-if=
"hasStages"
>
v-for=
"(stage, i) in pipeline.details.stages"
<div
:key=
"i"
v-for=
"(stage, i) in pipeline.details.stages"
:class=
"
{
:key=
"i"
'has-downstream':
:class=
"
{
i === pipeline.details.stages.length - 1
&&
triggered.length,
'has-downstream': i === pipeline.details.stages.length - 1
&&
triggered.length,
}"
}"
class="stage-container dropdown js-mini-pipeline-graph
class="stage-container dropdown js-mini-pipeline-graph
mr-widget-pipeline-stages"
mr-widget-pipeline-stages"
>
>
<pipeline-stage
:stage=
"stage"
/>
<pipeline-stage
:stage=
"stage"
/>
</div>
</div>
</
template
>
</
template
>
</span>
<linked-pipelines-mini-list
v-if=
"triggered.length"
:triggered=
"triggered"
/>
</span>
</span>
</div>
<linked-pipelines-mini-list
v-if=
"triggered.length"
:triggered=
"triggered"
/>
</span>
</div>
</div>
</
template
>
</
div
>
</
div
>
</
template
>
</div>
</div>
</template>
</template>
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
0 → 100644
View file @
1c10fa21
<
script
>
import
Deployment
from
'
./deployment.vue
'
;
import
MrWidgetContainer
from
'
./mr_widget_container.vue
'
;
import
MrWidgetPipeline
from
'
./mr_widget_pipeline.vue
'
;
/**
* Renders the pipeline and related deployments from the store.
*
* | Props | Description
* |---------------|-------------
* | `mr` | This is the mr_widget store
* | `isPostMerge` | If true, show the "post merge" pipeline and deployments
*/
export
default
{
name
:
'
MrWidgetPipelineContainer
'
,
components
:
{
Deployment
,
MrWidgetContainer
,
MrWidgetPipeline
,
},
props
:
{
mr
:
{
type
:
Object
,
required
:
true
,
},
isPostMerge
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
pipeline
()
{
return
this
.
isPostMerge
?
this
.
mr
.
mergePipeline
:
this
.
mr
.
pipeline
;
},
branch
()
{
return
this
.
isPostMerge
?
this
.
mr
.
targetBranch
:
this
.
mr
.
sourceBranch
;
},
branchLink
()
{
return
this
.
isPostMerge
?
this
.
mr
.
targetBranch
:
this
.
mr
.
sourceBranchLink
;
},
deployments
()
{
return
this
.
isPostMerge
?
this
.
mr
.
postMergeDeployments
:
this
.
mr
.
deployments
;
},
deploymentClass
()
{
return
this
.
isPostMerge
?
'
js-post-deployment
'
:
'
js-pre-deployment
'
;
},
hasDeploymentMetrics
()
{
return
this
.
isPostMerge
;
},
},
};
</
script
>
<
template
>
<mr-widget-container>
<mr-widget-pipeline
:pipeline=
"pipeline"
:ci-status=
"mr.ciStatus"
:has-ci=
"mr.hasCI"
:source-branch=
"branch"
:source-branch-link=
"branchLink"
:troubleshooting-docs-path=
"mr.troubleshootingDocsPath"
/>
<div
v-if=
"deployments.length"
slot=
"footer"
class=
"mr-widget-extension"
>
<deployment
v-for=
"deployment in deployments"
:key=
"deployment.id"
:class=
"deploymentClass"
:deployment=
"deployment"
:show-metrics=
"hasDeploymentMetrics"
/>
</div>
</mr-widget-container>
</
template
>
app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
View file @
1c10fa21
...
@@ -6,7 +6,7 @@ import SmartInterval from '~/smart_interval';
...
@@ -6,7 +6,7 @@ import SmartInterval from '~/smart_interval';
import
createFlash
from
'
../flash
'
;
import
createFlash
from
'
../flash
'
;
import
WidgetHeader
from
'
./components/mr_widget_header.vue
'
;
import
WidgetHeader
from
'
./components/mr_widget_header.vue
'
;
import
WidgetMergeHelp
from
'
./components/mr_widget_merge_help.vue
'
;
import
WidgetMergeHelp
from
'
./components/mr_widget_merge_help.vue
'
;
import
WidgetPipeline
from
'
./components/mr_widget_pipeline
.vue
'
;
import
MrWidgetPipelineContainer
from
'
./components/mr_widget_pipeline_container
.vue
'
;
import
Deployment
from
'
./components/deployment.vue
'
;
import
Deployment
from
'
./components/deployment.vue
'
;
import
WidgetRelatedLinks
from
'
./components/mr_widget_related_links.vue
'
;
import
WidgetRelatedLinks
from
'
./components/mr_widget_related_links.vue
'
;
import
MergedState
from
'
./components/states/mr_widget_merged.vue
'
;
import
MergedState
from
'
./components/states/mr_widget_merged.vue
'
;
...
@@ -44,7 +44,7 @@ export default {
...
@@ -44,7 +44,7 @@ export default {
components
:
{
components
:
{
'
mr-widget-header
'
:
WidgetHeader
,
'
mr-widget-header
'
:
WidgetHeader
,
'
mr-widget-merge-help
'
:
WidgetMergeHelp
,
'
mr-widget-merge-help
'
:
WidgetMergeHelp
,
'
mr-widget-pipeline
'
:
WidgetPipeline
,
MrWidgetPipelineContainer
,
Deployment
,
Deployment
,
'
mr-widget-related-links
'
:
WidgetRelatedLinks
,
'
mr-widget-related-links
'
:
WidgetRelatedLinks
,
'
mr-widget-merged
'
:
MergedState
,
'
mr-widget-merged
'
:
MergedState
,
...
@@ -297,23 +297,12 @@ export default {
...
@@ -297,23 +297,12 @@ export default {
<
template
>
<
template
>
<div
class=
"mr-state-widget prepend-top-default"
>
<div
class=
"mr-state-widget prepend-top-default"
>
<mr-widget-header
:mr=
"mr"
/>
<mr-widget-header
:mr=
"mr"
/>
<mr-widget-pipeline
<mr-widget-pipeline
-container
v-if=
"shouldRenderPipelines"
v-if=
"shouldRenderPipelines"
:pipeline=
"mr.pipeline"
class=
"mr-widget-workflow"
:ci-status=
"mr.ciStatus"
:mr=
"mr"
:has-ci=
"mr.hasCI"
:source-branch=
"mr.sourceBranch"
:source-branch-link=
"mr.sourceBranchLink"
:troubleshooting-docs-path=
"mr.troubleshootingDocsPath"
/>
/>
<deployment
<div
class=
"mr-section-container mr-widget-workflow"
>
v-for=
"deployment in mr.deployments"
:key=
"`pre-merge-deploy-$
{deployment.id}`"
class="js-pre-merge-deploy"
:deployment="deployment"
:show-metrics="false"
/>
<div
class=
"mr-section-container"
>
<grouped-test-reports-app
<grouped-test-reports-app
v-if=
"mr.testResultsPath"
v-if=
"mr.testResultsPath"
class=
"js-reports-container"
class=
"js-reports-container"
...
@@ -337,24 +326,11 @@ export default {
...
@@ -337,24 +326,11 @@ export default {
</div>
</div>
<div
v-if=
"shouldRenderMergeHelp"
class=
"mr-widget-footer"
><mr-widget-merge-help
/></div>
<div
v-if=
"shouldRenderMergeHelp"
class=
"mr-widget-footer"
><mr-widget-merge-help
/></div>
</div>
</div>
<mr-widget-pipeline-container
<template
v-if=
"shouldRenderMergedPipeline"
>
v-if=
"shouldRenderMergedPipeline"
<mr-widget-pipeline
class=
"js-post-merge-pipeline mr-widget-workflow"
class=
"js-post-merge-pipeline prepend-top-default"
:mr=
"mr"
:pipeline=
"mr.mergePipeline"
:is-post-merge=
"true"
:ci-status=
"mr.ciStatus"
/>
:has-ci=
"mr.hasCI"
:source-branch=
"mr.targetBranch"
:source-branch-link=
"mr.targetBranch"
:troubleshooting-docs-path=
"mr.troubleshootingDocsPath"
/>
<deployment
v-for=
"postMergeDeployment in mr.postMergeDeployments"
:key=
"`post-merge-deploy-$
{postMergeDeployment.id}`"
:deployment="postMergeDeployment"
:show-metrics="true"
class="js-post-deployment"
/>
</
template
>
</div>
</div>
</
template
>
</
template
>
app/assets/stylesheets/framework/icons.scss
View file @
1c10fa21
...
@@ -80,3 +80,15 @@
...
@@ -80,3 +80,15 @@
.user-avatar-link
{
.user-avatar-link
{
text-decoration
:
none
;
text-decoration
:
none
;
}
}
.circle-icon-container
{
$border-size
:
1px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
border
:
$border-size
solid
$theme-gray-400
;
border-radius
:
50%
;
padding
:
$gl-padding-8
-
$border-size
;
color
:
$theme-gray-700
;
}
app/assets/stylesheets/pages/merge_requests.scss
View file @
1c10fa21
...
@@ -50,9 +50,19 @@
...
@@ -50,9 +50,19 @@
.mr-widget-heading
{
.mr-widget-heading
{
position
:
relative
;
position
:
relative
;
border
:
1px
solid
$border-color
;
border
:
1px
solid
$border-color
;
border-radius
:
4px
;
border-radius
:
$border-radius-default
;
}
&
:not
(
.deploy-heading
)
::before
{
.mr-widget-extension
{
border-top
:
1px
solid
$border-color
;
background-color
:
$gray-light
;
}
.mr-widget-workflow
{
margin-top
:
$gl-padding
;
position
:
relative
;
&
:
:
before
{
content
:
''
;
content
:
''
;
border-left
:
1px
solid
$theme-gray-200
;
border-left
:
1px
solid
$theme-gray-200
;
position
:
absolute
;
position
:
absolute
;
...
@@ -68,8 +78,8 @@
...
@@ -68,8 +78,8 @@
border-top
:
0
;
border-top
:
0
;
}
}
.mr-widget-heading
,
.mr-widget-section
,
.mr-widget-section
,
.mr-widget-content
,
.mr-widget-footer
{
.mr-widget-footer
{
padding
:
$gl-padding
;
padding
:
$gl-padding
;
}
}
...
@@ -560,19 +570,6 @@
...
@@ -560,19 +570,6 @@
color
:
$gl-text-color
;
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
{
.git-merge-container
{
justify-content
:
space-between
;
justify-content
:
space-between
;
...
@@ -854,11 +851,6 @@
...
@@ -854,11 +851,6 @@
}
}
.deploy-heading
{
.deploy-heading
{
margin-top
:
-19px
;
border-top-left-radius
:
0
;
border-top-right-radius
:
0
;
background-color
:
$gray-light
;
@include
media-breakpoint-up
(
md
)
{
@include
media-breakpoint-up
(
md
)
{
padding
:
$gl-padding-8
$gl-padding
;
padding
:
$gl-padding-8
$gl-padding
;
}
}
...
@@ -868,6 +860,10 @@
...
@@ -868,6 +860,10 @@
font-size
:
12px
;
font-size
:
12px
;
margin-left
:
48px
;
margin-left
:
48px
;
}
}
&
:not
(
:last-child
)
{
border-bottom
:
1px
solid
$border-color
;
}
}
}
.deploy-body
{
.deploy-body
{
...
...
changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
0 → 100644
View file @
1c10fa21
---
title
:
Redesign of MR header sections (CE)
merge_request
:
23465
author
:
type
:
changed
ee/app/assets/javascripts/vue_merge_request_widget/components/approvals/mr_widget_approvals.vue
View file @
1c10fa21
<
script
>
<
script
>
import
Flash
from
'
~/flash
'
;
import
Flash
from
'
~/flash
'
;
import
statusIcon
from
'
~/vue_merge_request_widget/components/mr_widget_status_icon.vue
'
;
import
MrWidgetContainer
from
'
~/vue_merge_request_widget/components/mr_widget_container.vue
'
;
import
MrWidgetIcon
from
'
~/vue_merge_request_widget/components/mr_widget_icon.vue
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
import
ApprovalsBody
from
'
./approvals_body.vue
'
;
import
ApprovalsBody
from
'
./approvals_body.vue
'
;
import
ApprovalsFooter
from
'
./approvals_footer.vue
'
;
import
ApprovalsFooter
from
'
./approvals_footer.vue
'
;
...
@@ -10,7 +11,8 @@ export default {
...
@@ -10,7 +11,8 @@ export default {
components
:
{
components
:
{
ApprovalsBody
,
ApprovalsBody
,
ApprovalsFooter
,
ApprovalsFooter
,
statusIcon
,
MrWidgetContainer
,
MrWidgetIcon
,
},
},
props
:
{
props
:
{
mr
:
{
mr
:
{
...
@@ -59,36 +61,32 @@ export default {
...
@@ -59,36 +61,32 @@ export default {
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<section
<mr-widget-container>
v-if=
"mr.approvalsRequired"
<div
v-if=
"mr.approvalsRequired"
class=
"media media-section js-mr-approvals align-items-center"
>
class=
"mr-widget-approvals-container mr-widget-section media media-section"
<mr-widget-icon
name=
"approval"
/>
>
<div
v-show=
"fetchingApprovals"
class=
"mr-approvals-loading-state media-body"
>
<status-icon
<span
class=
"approvals-loading-text"
>
{{
__
(
'
Checking approval status
'
)
}}
</span>
:class=
"approvalsOptional ? 'zero-approvals' : ''"
</div>
:status=
"fetchingApprovals ? 'loading' : status"
<div
v-if=
"!fetchingApprovals"
class=
"approvals-components media-body"
>
/>
<approvals-body
<div
v-show=
"fetchingApprovals"
class=
"mr-approvals-loading-state media-body"
>
:mr=
"mr"
<span
class=
"approvals-loading-text"
>
Checking approval status
</span>
:service=
"service"
:user-can-approve=
"mr.approvals.user_can_approve"
:user-has-approved=
"mr.approvals.user_has_approved"
:approved-by=
"mr.approvals.approved_by"
:approvals-left=
"mr.approvals.approvals_left"
:approvals-optional=
"approvalsOptional"
:suggested-approvers=
"mr.approvals.suggested_approvers"
/>
<approvals-footer
:mr=
"mr"
:service=
"service"
:user-can-approve=
"mr.approvals.user_can_approve"
:user-has-approved=
"mr.approvals.user_has_approved"
:approved-by=
"mr.approvals.approved_by"
:approvals-left=
"mr.approvals.approvals_left"
/>
</div>
</div>
</div>
<div
v-if=
"!fetchingApprovals"
class=
"approvals-components media-body"
>
</mr-widget-container>
<approvals-body
:mr=
"mr"
:service=
"service"
:user-can-approve=
"mr.approvals.user_can_approve"
:user-has-approved=
"mr.approvals.user_has_approved"
:approved-by=
"mr.approvals.approved_by"
:approvals-left=
"mr.approvals.approvals_left"
:approvals-optional=
"approvalsOptional"
:suggested-approvers=
"mr.approvals.suggested_approvers"
/>
<approvals-footer
:mr=
"mr"
:service=
"service"
:user-can-approve=
"mr.approvals.user_can_approve"
:user-has-approved=
"mr.approvals.user_has_approved"
:approved-by=
"mr.approvals.approved_by"
:approvals-left=
"mr.approvals.approvals_left"
/>
</div>
</section>
</
template
>
</
template
>
ee/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
View file @
1c10fa21
...
@@ -191,24 +191,18 @@ export default {
...
@@ -191,24 +191,18 @@ export default {
<
template
>
<
template
>
<div
class=
"mr-state-widget prepend-top-default"
>
<div
class=
"mr-state-widget prepend-top-default"
>
<mr-widget-header
:mr=
"mr"
/>
<mr-widget-header
:mr=
"mr"
/>
<mr-widget-pipeline
<mr-widget-pipeline
-container
v-if=
"shouldRenderPipelines"
v-if=
"shouldRenderPipelines"
:pipeline=
"mr.pipeline"
class=
"mr-widget-workflow"
:ci-status=
"mr.ciStatus"
:mr=
"mr"
:has-ci=
"mr.hasCI"
:source-branch-link=
"mr.sourceBranchLink"
:source-branch=
"mr.sourceBranch"
:troubleshooting-docs-path=
"mr.troubleshootingDocsPath"
/>
/>
<deployment
<mr-widget-approvals
v-for=
"deployment in mr.deployments"
v-if=
"shouldRenderApprovals"
:key=
"`pre-merge-deploy-$
{deployment.id}`"
class=
"mr-widget-workflow"
class="js-pre-merge-deploy"
:mr=
"mr"
:deployment="deployment"
:service=
"service"
:show-metrics="false"
/>
/>
<div
class=
"mr-section-container"
>
<div
class=
"mr-section-container mr-widget-workflow"
>
<mr-widget-approvals
v-if=
"shouldRenderApprovals"
:mr=
"mr"
:service=
"service"
/>
<report-section
<report-section
v-if=
"shouldRenderCodeQuality"
v-if=
"shouldRenderCodeQuality"
:status=
"codequalityStatus"
:status=
"codequalityStatus"
...
@@ -288,24 +282,11 @@ export default {
...
@@ -288,24 +282,11 @@ export default {
</div>
</div>
<div
v-if=
"shouldRenderMergeHelp"
class=
"mr-widget-footer"
><mr-widget-merge-help
/></div>
<div
v-if=
"shouldRenderMergeHelp"
class=
"mr-widget-footer"
><mr-widget-merge-help
/></div>
</div>
</div>
<mr-widget-pipeline-container
<template
v-if=
"shouldRenderMergedPipeline"
>
v-if=
"shouldRenderMergedPipeline"
<mr-widget-pipeline
class=
"js-post-merge-pipeline mr-widget-workflow"
class=
"js-post-merge-pipeline prepend-top-default"
:mr=
"mr"
:pipeline=
"mr.mergePipeline"
:is-post-merge=
"true"
:ci-status=
"mr.ciStatus"
/>
:has-ci=
"mr.hasCI"
:source-branch=
"mr.targetBranch"
:source-branch-link=
"mr.targetBranch"
:troubleshooting-docs-path=
"mr.troubleshootingDocsPath"
/>
<deployment
v-for=
"postMergeDeployment in mr.postMergeDeployments"
:key=
"`post-merge-deploy-$
{postMergeDeployment.id}`"
:deployment="postMergeDeployment"
:show-metrics="true"
class="js-post-deployment"
/>
</
template
>
</div>
</div>
</
template
>
</
template
>
ee/app/assets/stylesheets/pages/merge_requests.scss
View file @
1c10fa21
...
@@ -11,14 +11,6 @@
...
@@ -11,14 +11,6 @@
}
}
}
}
.mr-widget-approvals-container
{
align-items
:
center
;
.zero-approvals
.ci-status-icon-success
svg
{
fill
:
$gray-darkest
;
}
}
.approvals-body
{
.approvals-body
{
@include
media-breakpoint-up
(
md
)
{
@include
media-breakpoint-up
(
md
)
{
display
:
flex
;
display
:
flex
;
...
...
ee/changelogs/unreleased/1979-redesign-mr-widget-approvals.yml
0 → 100644
View file @
1c10fa21
---
title
:
Redesign MR header sections and approvals (EE)
merge_request
:
8593
author
:
type
:
changed
ee/spec/features/merge_request/user_approves_spec.rb
View file @
1c10fa21
...
@@ -94,8 +94,8 @@ describe 'Merge request > User approves', :js do
...
@@ -94,8 +94,8 @@ describe 'Merge request > User approves', :js do
end
end
it
'does not show checking ability text'
do
it
'does not show checking ability text'
do
expect
(
find
(
'.
mr-widget-approvals-container
'
)).
not_to
have_text
(
'Checking ability to merge automatically'
)
expect
(
find
(
'.
js-mr-approvals
'
)).
not_to
have_text
(
'Checking ability to merge automatically'
)
expect
(
find
(
'.
mr-widget-approvals-container
'
)).
to
have_selector
(
'.approvals-body'
)
expect
(
find
(
'.
js-mr-approvals
'
)).
to
have_selector
(
'.approvals-body'
)
end
end
end
end
end
end
...
...
ee/spec/features/merge_request/user_sees_approval_widget_spec.rb
View file @
1c10fa21
...
@@ -19,8 +19,8 @@ describe 'Merge request > User sees approval widget', :js do
...
@@ -19,8 +19,8 @@ describe 'Merge request > User sees approval widget', :js do
end
end
it
'does not show checking ability text'
do
it
'does not show checking ability text'
do
expect
(
find
(
'.
mr-widget-approvals-container
'
)).
not_to
have_text
(
'Checking ability to merge automatically'
)
expect
(
find
(
'.
js-mr-approvals
'
)).
not_to
have_text
(
'Checking ability to merge automatically'
)
expect
(
find
(
'.
mr-widget-approvals-container
'
)).
to
have_selector
(
'.approvals-body'
)
expect
(
find
(
'.
js-mr-approvals
'
)).
to
have_selector
(
'.approvals-body'
)
end
end
end
end
end
end
locale/gitlab.pot
View file @
1c10fa21
...
@@ -1510,6 +1510,9 @@ msgstr ""
...
@@ -1510,6 +1510,9 @@ msgstr ""
msgid "Checking %{text} availability…"
msgid "Checking %{text} availability…"
msgstr ""
msgstr ""
msgid "Checking approval status"
msgstr ""
msgid "Checking branch availability..."
msgid "Checking branch availability..."
msgstr ""
msgstr ""
...
...
spec/features/merge_request/user_sees_merge_widget_spec.rb
View file @
1c10fa21
...
@@ -60,7 +60,7 @@ describe 'Merge request > User sees merge widget', :js do
...
@@ -60,7 +60,7 @@ describe 'Merge request > User sees merge widget', :js do
it
'shows environments link'
do
it
'shows environments link'
do
wait_for_requests
wait_for_requests
page
.
within
(
'.js-pre-
merge-deploy
'
)
do
page
.
within
(
'.js-pre-
deployment
'
)
do
expect
(
page
).
to
have_content
(
"Deployed to
#{
environment
.
name
}
"
)
expect
(
page
).
to
have_content
(
"Deployed to
#{
environment
.
name
}
"
)
expect
(
find
(
'.js-deploy-url'
)[
:href
]).
to
include
(
environment
.
formatted_external_url
)
expect
(
find
(
'.js-deploy-url'
)[
:href
]).
to
include
(
environment
.
formatted_external_url
)
end
end
...
...
spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js
0 → 100644
View file @
1c10fa21
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
MrWidgetContainer
from
'
~/vue_merge_request_widget/components/mr_widget_container.vue
'
;
const
BODY_HTML
=
'
<div class="test-body">Hello World</div>
'
;
const
FOOTER_HTML
=
'
<div class="test-footer">Goodbye!</div>
'
;
describe
(
'
MrWidgetContainer
'
,
()
=>
{
let
wrapper
;
const
factory
=
(
options
=
{})
=>
{
const
localVue
=
createLocalVue
();
wrapper
=
shallowMount
(
localVue
.
extend
(
MrWidgetContainer
),
{
localVue
,
...
options
,
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
has layout
'
,
()
=>
{
factory
();
expect
(
wrapper
.
is
(
'
.mr-widget-heading
'
)).
toBe
(
true
);
expect
(
wrapper
.
contains
(
'
.mr-widget-content
'
)).
toBe
(
true
);
});
it
(
'
accepts default slot
'
,
()
=>
{
factory
({
slots
:
{
default
:
BODY_HTML
,
},
});
expect
(
wrapper
.
contains
(
'
.mr-widget-content .test-body
'
)).
toBe
(
true
);
});
it
(
'
accepts footer slot
'
,
()
=>
{
factory
({
slots
:
{
default
:
BODY_HTML
,
footer
:
FOOTER_HTML
,
},
});
expect
(
wrapper
.
contains
(
'
.mr-widget-content .test-body
'
)).
toBe
(
true
);
expect
(
wrapper
.
contains
(
'
.test-footer
'
)).
toBe
(
true
);
});
});
spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js
0 → 100644
View file @
1c10fa21
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
MrWidgetIcon
from
'
~/vue_merge_request_widget/components/mr_widget_icon.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
const
TEST_ICON
=
'
commit
'
;
describe
(
'
MrWidgetIcon
'
,
()
=>
{
let
wrapper
;
beforeEach
(()
=>
{
const
localVue
=
createLocalVue
();
wrapper
=
shallowMount
(
localVue
.
extend
(
MrWidgetIcon
),
{
propsData
:
{
name
:
TEST_ICON
,
},
sync
:
false
,
localVue
,
});
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
renders icon and container
'
,
()
=>
{
expect
(
wrapper
.
is
(
'
.circle-icon-container
'
)).
toBe
(
true
);
expect
(
wrapper
.
find
(
Icon
).
props
(
'
name
'
)).
toEqual
(
TEST_ICON
);
});
});
spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
0 → 100644
View file @
1c10fa21
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
MrWidgetPipelineContainer
from
'
~/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
'
;
import
MrWidgetPipeline
from
'
~/vue_merge_request_widget/components/mr_widget_pipeline.vue
'
;
import
{
mockStore
}
from
'
../mock_data
'
;
describe
(
'
MrWidgetPipelineContainer
'
,
()
=>
{
let
wrapper
;
const
factory
=
(
props
=
{})
=>
{
const
localVue
=
createLocalVue
();
wrapper
=
shallowMount
(
localVue
.
extend
(
MrWidgetPipelineContainer
),
{
propsData
:
{
mr
:
Object
.
assign
({},
mockStore
),
...
props
,
},
localVue
,
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
when pre merge
'
,
()
=>
{
beforeEach
(()
=>
{
factory
();
});
it
(
'
renders pipeline
'
,
()
=>
{
expect
(
wrapper
.
find
(
MrWidgetPipeline
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
MrWidgetPipeline
).
props
()).
toEqual
(
jasmine
.
objectContaining
({
pipeline
:
mockStore
.
pipeline
,
ciStatus
:
mockStore
.
ciStatus
,
hasCi
:
mockStore
.
hasCI
,
sourceBranch
:
mockStore
.
sourceBranch
,
sourceBranchLink
:
mockStore
.
sourceBranchLink
,
}),
);
});
it
(
'
renders deployments
'
,
()
=>
{
const
expectedProps
=
mockStore
.
deployments
.
map
(
dep
=>
jasmine
.
objectContaining
({
deployment
:
dep
,
showMetrics
:
false
,
}),
);
const
deployments
=
wrapper
.
findAll
(
'
.mr-widget-extension .js-pre-deployment
'
);
expect
(
deployments
.
wrappers
.
map
(
x
=>
x
.
props
())).
toEqual
(
expectedProps
);
});
});
describe
(
'
when post merge
'
,
()
=>
{
beforeEach
(()
=>
{
factory
({
isPostMerge
:
true
,
});
});
it
(
'
renders pipeline
'
,
()
=>
{
expect
(
wrapper
.
find
(
MrWidgetPipeline
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
MrWidgetPipeline
).
props
()).
toEqual
(
jasmine
.
objectContaining
({
pipeline
:
mockStore
.
mergePipeline
,
ciStatus
:
mockStore
.
ciStatus
,
hasCi
:
mockStore
.
hasCI
,
sourceBranch
:
mockStore
.
targetBranch
,
sourceBranchLink
:
mockStore
.
targetBranch
,
}),
);
});
it
(
'
renders deployments
'
,
()
=>
{
const
expectedProps
=
mockStore
.
postMergeDeployments
.
map
(
dep
=>
jasmine
.
objectContaining
({
deployment
:
dep
,
showMetrics
:
true
,
}),
);
const
deployments
=
wrapper
.
findAll
(
'
.mr-widget-extension .js-post-deployment
'
);
expect
(
deployments
.
wrappers
.
map
(
x
=>
x
.
props
())).
toEqual
(
expectedProps
);
});
});
});
spec/javascripts/vue_mr_widget/mock_data.js
View file @
1c10fa21
...
@@ -401,3 +401,16 @@ export const codequalityParsedIssues = [
...
@@ -401,3 +401,16 @@ export const codequalityParsedIssues = [
urlPath
:
'
foo/Gemfile.lock
'
,
urlPath
:
'
foo/Gemfile.lock
'
,
},
},
];
];
export
const
mockStore
=
{
pipeline
:
{
id
:
0
},
mergePipeline
:
{
id
:
1
},
targetBranch
:
'
target-branch
'
,
sourceBranch
:
'
source-branch
'
,
sourceBranchLink
:
'
source-branch-link
'
,
deployments
:
[{
id
:
0
,
name
:
'
bogus
'
},
{
id
:
1
,
name
:
'
bogus-docs
'
}],
postMergeDeployments
:
[{
id
:
0
,
name
:
'
prod
'
},
{
id
:
1
,
name
:
'
prod-docs
'
}],
troubleshootingDocsPath
:
'
troubleshooting-docs-path
'
,
ciStatus
:
'
ci-status
'
,
hasCI
:
true
,
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment