summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Schatz <jschatz@gitlab.com>2016-08-17 20:47:41 +0000
committerJacob Schatz <jschatz@gitlab.com>2016-08-17 20:47:41 +0000
commit30091edfb4d2d96d8b9a141619fc661d81356b41 (patch)
tree440a0a1543d503e6666466ed4e499fdeedb3b04c
parent2c6c23a430f56d9b9ec3d76576dffe71456befef (diff)
parentcc7b3db5a2d9a04d976c3db95059e3163a01ec70 (diff)
downloadgitlab-ce-30091edfb4d2d96d8b9a141619fc661d81356b41.tar.gz
Merge branch '18516-collapse-build-tabs' into 'master'
Collapse build tabs that don't fit ## What does this MR do? * Orders tests from `failed` > `pending` > `running` > `canceled` > `skipped` > `success` * Put stages in one dropdown * Once stage is selected, second dropdown shows all builds/jobs for that stage ## Are there points in the code the reviewer needs to double check? ## Why was this MR needed? So many tests! <img src="/uploads/d581b2670588121c6d64823f61906a1a/Screen_Shot_2016-08-01_at_9.52.50_AM.png" width="600px"> ## What are the relevant issue numbers? Closes #18516 Part of #19982 ## Screenshots (if relevant) ![Screen_Shot_2016-08-17_at_1.14.20_PM](/uploads/fa183361ed13137257caf20a6afc4ef1/Screen_Shot_2016-08-17_at_1.14.20_PM.png) ![Screen_Shot_2016-08-17_at_1.14.39_PM](/uploads/f568cac463abf5c625cf31912ddbd00a/Screen_Shot_2016-08-17_at_1.14.39_PM.png) See merge request !5595
-rw-r--r--CHANGELOG1
-rw-r--r--app/assets/javascripts/build.js35
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss4
-rw-r--r--app/assets/stylesheets/pages/builds.scss88
-rw-r--r--app/views/projects/builds/_sidebar.html.haml197
-rw-r--r--app/views/projects/builds/show.html.haml28
6 files changed, 234 insertions, 119 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 6000b3e9414..f528f8f633a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -106,6 +106,7 @@ v 8.11.0 (unreleased)
- Make error pages responsive (Takuya Noguchi)
- The performance of the project dropdown used for moving issues has been improved
- Fix skip_repo parameter being ignored when destroying a namespace
+ - Add all builds into stage/job dropdowns on builds page
- Change requests_profiles resource constraint to catch virtually any file
- Bump gitlab_git to lazy load compare commits
- Reduce number of queries made for merge_requests/:id/diffs
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index 3d9b824d406..0d7d29bb0d0 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -6,19 +6,26 @@
Build.state = null;
- function Build(page_url, build_url, build_status, state1) {
- this.page_url = page_url;
- this.build_url = build_url;
- this.build_status = build_status;
- this.state = state1;
+ function Build(options) {
+ this.page_url = options.page_url;
+ this.build_url = options.build_url;
+ this.build_status = options.build_status;
+ this.state = options.state1;
+ this.build_stage = options.build_stage;
this.hideSidebar = bind(this.hideSidebar, this);
this.toggleSidebar = bind(this.toggleSidebar, this);
+ this.updateDropdown = bind(this.updateDropdown, this);
clearInterval(Build.interval);
this.bp = Breakpoints.get();
- this.hideSidebar();
$('.js-build-sidebar').niceScroll();
+
+ this.populateJobs(this.build_stage);
+ this.updateStageDropdownText(this.build_stage);
+ this.hideSidebar();
+
$(document).off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar);
$(window).off('resize.build').on('resize.build', this.hideSidebar);
+ $(document).off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
this.updateArtifactRemoveDate();
if ($('#build-trace').length) {
this.getInitialBuildTrace();
@@ -132,6 +139,22 @@
}
};
+ Build.prototype.populateJobs = function(stage) {
+ $('.build-job').hide();
+ $('.build-job[data-stage="' + stage + '"]').show();
+ };
+
+ Build.prototype.updateStageDropdownText = function(stage) {
+ $('.stage-selection').text(stage);
+ };
+
+ Build.prototype.updateDropdown = function(e) {
+ e.preventDefault();
+ var stage = e.currentTarget.text;
+ this.updateStageDropdownText(stage);
+ this.populateJobs(stage);
+ };
+
return Build;
})();
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 3fa4a22258d..015fe3debf9 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -222,3 +222,7 @@ header.header-pinned-nav {
padding-right: $sidebar_collapsed_width;
}
}
+
+.right-sidebar {
+ border-left: 1px solid $border-color;
+}
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index e26f8f7080d..81fce55853c 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -53,14 +53,6 @@
left: 70px;
}
}
-
- .nav-links {
- svg {
- position: relative;
- top: 2px;
- margin-right: 3px;
- }
- }
}
.build-header {
@@ -108,24 +100,98 @@
}
.right-sidebar.build-sidebar {
- padding-top: $gl-padding;
- padding-bottom: $gl-padding;
+ padding: $gl-padding 0;
&.right-sidebar-collapsed {
display: none;
}
+ .blocks-container {
+ padding: $gl-padding;
+ }
+
.block {
width: 100%;
}
.build-sidebar-header {
- padding-top: 0;
+ padding: 0 $gl-padding $gl-padding;
.gutter-toggle {
margin-top: 0;
}
}
+
+ .stage-item {
+ cursor: pointer;
+
+ &:hover {
+ color: $gl-text-color;
+ }
+ }
+
+ .build-dropdown {
+ padding: 0 $gl-padding;
+
+ .dropdown-menu-toggle {
+ margin-top: 8px;
+ }
+
+ .dropdown-menu {
+ right: $gl-padding;
+ left: $gl-padding;
+ width: auto;
+ }
+ }
+
+ .builds-container {
+ margin-top: $gl-padding;
+ background-color: $white-light;
+ border-top: 1px solid $border-color;
+ border-bottom: 1px solid $border-color;
+ max-height: 300px;
+ overflow: scroll;
+
+ svg {
+ position: relative;
+ top: 2px;
+ margin-right: 3px;
+ height: 13px;
+ }
+
+ a {
+ display: block;
+ padding: $gl-padding 10px $gl-padding 40px;
+ width: 270px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ &:hover {
+ background-color: $row-hover;
+ color: $gl-text-color;
+ }
+ }
+
+ .build-job {
+ position: relative;
+
+ .fa {
+ position: absolute;
+ left: 15px;
+ top: 20px;
+ display: none;
+ }
+
+ &.active {
+ font-weight: bold;
+
+ .fa {
+ display: block;
+ }
+ }
+ }
+ }
}
.build-detail-row {
diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml
index a8bc53c2849..5b0b58e087b 100644
--- a/app/views/projects/builds/_sidebar.html.haml
+++ b/app/views/projects/builds/_sidebar.html.haml
@@ -11,98 +11,133 @@
%p.build-detail-row
#{@build.coverage}%
- - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?)
- .block{ class: ("block-first" if !@build.coverage) }
- .title
- Build artifacts
- - if @build.artifacts_expired?
- %p.build-detail-row
- The artifacts were removed
- #{time_ago_with_tooltip(@build.artifacts_expire_at)}
- - elsif @build.artifacts_expire_at
- %p.build-detail-row
- The artifacts will be removed in
- %span.js-artifacts-remove= @build.artifacts_expire_at
+ - builds = @build.pipeline.builds.latest.to_a
+ - statuses = ["failed", "pending", "running", "canceled", "success", "skipped"]
+ - if builds.size > 1
+ .dropdown.build-dropdown
+ .build-light-text Stage
+ %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'}
+ %span.stage-selection More
+ = icon('caret-down')
+ %ul.dropdown-menu
+ - builds.map(&:stage).uniq.each do |stage|
+ %li
+ %a.stage-item= stage
- - if @build.artifacts?
- .btn-group.btn-group-justified{ role: :group }
- - if @build.artifacts_expire_at
- = link_to keep_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post do
- Keep
+ .builds-container
+ - statuses.each do |build_status|
+ - builds.select{|build| build.status == build_status}.each do |build|
+ .build-job{class: ('active' if build == @build), data: {stage: build.stage}}
+ = link_to namespace_project_build_path(@project.namespace, @project, build) do
+ = icon('check')
+ = ci_icon_for_status(build.status)
+ %span
+ - if build.name
+ = build.name
+ - else
+ = build.id
- = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do
- Download
+ - if @build.retried?
+ %li.active
+ %a
+ Build ##{@build.id}
+ &middot;
+ %i.fa.fa-warning
+ This build was retried.
- - if @build.artifacts_metadata?
- = link_to browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do
- Browse
+ .blocks-container
+ - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?)
+ .block{ class: ("block-first" if !@build.coverage) }
+ .title
+ Build artifacts
+ - if @build.artifacts_expired?
+ %p.build-detail-row
+ The artifacts were removed
+ #{time_ago_with_tooltip(@build.artifacts_expire_at)}
+ - elsif @build.artifacts_expire_at
+ %p.build-detail-row
+ The artifacts will be removed in
+ %span.js-artifacts-remove= @build.artifacts_expire_at
- .block{ class: ("block-first" if !@build.coverage && !(can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?))) }
- .title
- Build details
- - if can?(current_user, :update_build, @build) && @build.retryable?
- = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right', method: :post
- - if @build.merge_request
- %p.build-detail-row
- %span.build-light-text Merge Request:
- = link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request)
- - if @build.duration
- %p.build-detail-row
- %span.build-light-text Duration:
- = time_interval_in_words(@build.duration)
- - if @build.finished_at
- %p.build-detail-row
- %span.build-light-text Finished:
- #{time_ago_with_tooltip(@build.finished_at)}
- - if @build.erased_at
- %p.build-detail-row
- %span.build-light-text Erased:
- #{time_ago_with_tooltip(@build.erased_at)}
- %p.build-detail-row
- %span.build-light-text Runner:
- - if @build.runner && current_user && current_user.admin
- = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id)
- - elsif @build.runner
- \##{@build.runner.id}
- .btn-group.btn-group-justified{ role: :group }
- - if @build.has_trace?
- = link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default'
- - if @build.active?
- = link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post
- - if can?(current_user, :update_build, @project) && @build.erasable?
- = link_to erase_namespace_project_build_path(@project.namespace, @project, @build),
- class: "btn btn-sm btn-default", method: :post,
- data: { confirm: "Are you sure you want to erase this build?" } do
- Erase
+ - if @build.artifacts?
+ .btn-group.btn-group-justified{ role: :group }
+ - if @build.artifacts_expire_at
+ = link_to keep_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post do
+ Keep
+
+ = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do
+ Download
- - if @build.trigger_request
- .build-widget
- %h4.title
- Trigger
+ - if @build.artifacts_metadata?
+ = link_to browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do
+ Browse
- %p
- %span.build-light-text Token:
- #{@build.trigger_request.trigger.short_token}
+ .block{ class: ("block-first" if !@build.coverage && !(can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?))) }
+ .title
+ Build details
+ - if can?(current_user, :update_build, @build) && @build.retryable?
+ = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right', method: :post
+ - if @build.merge_request
+ %p.build-detail-row
+ %span.build-light-text Merge Request:
+ = link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request)
+ - if @build.duration
+ %p.build-detail-row
+ %span.build-light-text Duration:
+ = time_interval_in_words(@build.duration)
+ - if @build.finished_at
+ %p.build-detail-row
+ %span.build-light-text Finished:
+ #{time_ago_with_tooltip(@build.finished_at)}
+ - if @build.erased_at
+ %p.build-detail-row
+ %span.build-light-text Erased:
+ #{time_ago_with_tooltip(@build.erased_at)}
+ %p.build-detail-row
+ %span.build-light-text Runner:
+ - if @build.runner && current_user && current_user.admin
+ = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id)
+ - elsif @build.runner
+ \##{@build.runner.id}
+ .btn-group.btn-group-justified{ role: :group }
+ - if @build.has_trace?
+ = link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default'
+ - if @build.active?
+ = link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post
+ - if can?(current_user, :update_build, @project) && @build.erasable?
+ = link_to erase_namespace_project_build_path(@project.namespace, @project, @build),
+ class: "btn btn-sm btn-default", method: :post,
+ data: { confirm: "Are you sure you want to erase this build?" } do
+ Erase
+
+ - if @build.trigger_request
+ .build-widget
+ %h4.title
+ Trigger
- - if @build.trigger_request.variables
%p
- %span.build-light-text Variables:
+ %span.build-light-text Token:
+ #{@build.trigger_request.trigger.short_token}
+ - if @build.trigger_request.variables
+ %p
+ %span.build-light-text Variables:
- - @build.trigger_request.variables.each do |key, value|
- %code
- #{key}=#{value}
- .block
- .title
- Commit title
- %p.build-light-text.append-bottom-0
- #{@build.pipeline.git_commit_title}
+ - @build.trigger_request.variables.each do |key, value|
+ %code
+ #{key}=#{value}
- - if @build.tags.any?
.block
.title
- Tags
- - @build.tag_list.each do |tag|
- %span.label.label-primary
- = tag
+ Commit title
+ %p.build-light-text.append-bottom-0
+ #{@build.pipeline.git_commit_title}
+
+ - if @build.tags.any?
+ .block
+ .title
+ Tags
+ - @build.tag_list.each do |tag|
+ %span.label.label-primary
+ = tag
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index 4421f3b9562..e4d41288aa6 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -5,26 +5,6 @@
.build-page
= render "header"
- - builds = @build.pipeline.builds.latest.to_a
- - if builds.size > 1
- %ul.nav-links.no-top.no-bottom
- - builds.each do |build|
- %li{class: ('active' if build == @build) }
- = link_to namespace_project_build_path(@project.namespace, @project, build) do
- = ci_icon_for_status(build.status)
- %span
- - if build.name
- = build.name
- - else
- = build.id
-
- - if @build.retried?
- %li.active
- %a
- Build ##{@build.id}
- &middot;
- %i.fa.fa-warning
- This build was retried.
- if @build.stuck?
- unless @build.any_runners_online?
.bs-callout.bs-callout-warning
@@ -67,4 +47,10 @@
= render "sidebar"
:javascript
- new Build("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", "#{@build.status}", "#{trace_with_state[:state]}")
+ new Build({
+ page_url: "#{namespace_project_build_url(@project.namespace, @project, @build)}",
+ build_url: "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}",
+ build_status: "#{@build.status}",
+ build_stage: "#{@build.stage}",
+ state1: "#{trace_with_state[:state]}"
+ })