diff options
Diffstat (limited to 'app')
29 files changed, 494 insertions, 354 deletions
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index b28327ce12d..e0ca546350b 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -267,8 +267,8 @@ $ -> $(document).trigger('breakpoint:change', [bootstrapBreakpoint]) $(window) - .off "resize" - .on "resize", (e) -> + .off "resize.app" + .on "resize.app", (e) -> fitSidebarForSize() gl.awardsHandler = new AwardsHandler() diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee index 98d05e41273..f763ba96e33 100644 --- a/app/assets/javascripts/ci/build.coffee +++ b/app/assets/javascripts/ci/build.coffee @@ -1,19 +1,31 @@ -class CiBuild +class @CiBuild @interval: null @state: null - constructor: (build_url, build_status, build_state) -> + constructor: (@build_url, @build_status, @state) -> clearInterval(CiBuild.interval) - @state = build_state + # Init breakpoint checker + @bp = Breakpoints.get() + @hideSidebar() + $('.js-build-sidebar').niceScroll() + $(document) + .off 'click', '.js-sidebar-build-toggle' + .on 'click', '.js-sidebar-build-toggle', @toggleSidebar - @initScrollButtonAffix() + $(window) + .off 'resize.build' + .on 'resize.build', @hideSidebar - if build_status == "running" || build_status == "pending" + if $('#build-trace').length + @getInitialBuildTrace() + @initScrollButtonAffix() + + if @build_status is "running" or @build_status is "pending" # # Bind autoscroll button to follow build output # - $("#autoscroll-button").bind "click", -> + $('#autoscroll-button').on 'click', -> state = $(this).data("state") if "enabled" is state $(this).data "state", "disabled" @@ -27,26 +39,37 @@ class CiBuild # Only valid for runnig build when output changes during time # CiBuild.interval = setInterval => - if window.location.href.split("#").first() is build_url - last_state = @state - $.ajax - url: build_url + "/trace.json?state=" + encodeURIComponent(@state) - dataType: "json" - success: (log) => - return unless last_state is @state - - if log.state and log.status is "running" - @state = log.state - if log.append - $('.fa-refresh').before log.html - else - $('#build-trace code').html log.html - $('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>' - @checkAutoscroll() - else if log.status isnt build_status - Turbolinks.visit build_url + if window.location.href.split("#").first() is @build_url + @getBuildTrace() , 4000 + getInitialBuildTrace: -> + $.ajax + url: @build_url + dataType: 'json' + success: (build_data) -> + $('.js-build-output').html build_data.trace_html + + if build_data.status is 'success' or build_data.status is 'failed' + $('.js-build-refresh').remove() + + getBuildTrace: -> + $.ajax + url: "#{@build_url}/trace.json?state=#{encodeURIComponent(@state)}" + dataType: "json" + success: (log) => + if log.state + @state = log.state + + if log.status is "running" + if log.append + $('.js-build-output').append log.html + else + $('.js-build-output').html log.html + @checkAutoscroll() + else if log.status isnt @build_status + Turbolinks.visit @build_url + checkAutoscroll: -> $("html,body").scrollTop $("#build-trace").height() if "enabled" is $("#autoscroll-button").data("state") @@ -61,4 +84,22 @@ class CiBuild $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top) ) -@CiBuild = CiBuild + shouldHideSidebar: -> + bootstrapBreakpoint = @bp.getBreakpointSize() + + bootstrapBreakpoint is 'xs' or bootstrapBreakpoint is 'sm' + + toggleSidebar: => + if @shouldHideSidebar() + $('.js-build-sidebar') + .toggleClass 'right-sidebar-expanded right-sidebar-collapsed' + + hideSidebar: => + if @shouldHideSidebar() + $('.js-build-sidebar') + .removeClass 'right-sidebar-expanded' + .addClass 'right-sidebar-collapsed' + else + $('.js-build-sidebar') + .removeClass 'right-sidebar-collapsed' + .addClass 'right-sidebar-expanded' diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 94985413746..06a688690f8 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -273,7 +273,9 @@ padding-right: 0; @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { - padding-right: $sidebar_collapsed_width; + &:not(.build-sidebar) { + padding-right: $sidebar_collapsed_width; + } } @media (min-width: $screen-md-min) { diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 99e3df119ed..847b2f80bdf 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -260,3 +260,6 @@ $calendar-header-color: #b8b8b8; $calendar-hover-bg: #ecf3fe; $calendar-border-color: rgba(#000, .1); $calendar-unselectable-bg: #faf9f9; + +$ci-output-bg: #1d1f21; +$ci-text-color: #c5c8c6; diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 44222e8e8a4..e8f1935d239 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -53,37 +53,92 @@ left: 70px; } } +} - .build-widget { - padding: 10px; - background: $background-color; - margin-bottom: 20px; - border-radius: 4px; +.build-header { + position: relative; + padding-right: 40px; - .title { - margin-top: 0; - color: #666; - line-height: 1.5; - } - .attr-name { - color: #777; - } + @media (min-width: $screen-sm-min) { + padding-right: 0; } - .alert-disabled { - background: $background-color; + a { + color: $gl-gray; - a { - color: #3084bb !important; + &:hover { + color: $gl-link-color; + text-decoration: none; } } + + code { + color: $code-color; + } + + .avatar { + float: none; + margin-right: 2px; + margin-left: 2px; + } } table.builds { - .build-link { a { color: $gl-dark-link-color; } } } + +.build-trace { + background: $ci-output-bg; + color: $ci-text-color; + white-space: pre; + overflow-x: auto; + font-size: 12px; + + .fa-refresh { + font-size: 24px; + } + + .bash { + display: block; + } +} + +.right-sidebar.build-sidebar { + padding-top: $gl-padding; + padding-bottom: $gl-padding; + + &.right-sidebar-collapsed { + display: none; + } + + .block { + width: 100%; + } + + .build-sidebar-header { + padding-top: 0; + + .gutter-toggle { + margin-top: 0; + } + } +} + +.build-detail-row { + margin-bottom: 5px; +} + +.build-light-text { + color: $gl-placeholder-color; +} + +.build-gutter-toggle { + position: absolute; + top: 50%; + right: 0; + margin-top: -17px; +} diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 787c387379e..ea453ce356a 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -29,7 +29,7 @@ } } -.issuable-sidebar { +.right-sidebar { a { color: inherit; } @@ -74,6 +74,10 @@ } } + .block-first { + padding-top: 0; + } + .title { color: $gl-text-color; margin-bottom: 10px; diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss index 3f28e402929..8d855ce99b0 100644 --- a/app/assets/stylesheets/pages/xterm.scss +++ b/app/assets/stylesheets/pages/xterm.scss @@ -11,18 +11,15 @@ $magenta: #cd00cd; $cyan: #00cdcd; $white: #e5e5e5; - $l-black: #7f7f7f; - $l-red: #f00; - $l-green: #0f0; - $l-yellow: #ff0; - $l-blue: #5c5cff; - $l-magenta: #f0f; - $l-cyan: #0ff; - $l-white: #fff; + $l-black: #373b41; + $l-red: #c66; + $l-green: #b5bd68; + $l-yellow: #f0c674; + $l-blue: #81a2be; + $l-magenta: #b294bb; + $l-cyan: #8abeb7; + $l-white: $ci-text-color; - .term-bold { - font-weight: bold; - } .term-italic { font-style: italic; } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 62f63701799..cd6ae507cf1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base include Gitlab::GonHelper include GitlabRoutingHelper include PageLayoutHelper + include WorkhorseHelper before_action :authenticate_user_from_token! before_action :authenticate_user! diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 72921b3aa14..5962f74c39b 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -10,10 +10,7 @@ class Projects::AvatarsController < Projects::ApplicationController return if cached_blob? - headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) - headers['Content-Disposition'] = 'inline' - headers['Content-Type'] = safe_content_type(@blob) - head :ok # 'render nothing: true' messes up the Content-Type + send_git_blob @repository, @blob else render_404 end diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 9b80efa5f11..14c82826342 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -41,7 +41,7 @@ class Projects::BuildsController < Projects::ApplicationController def trace respond_to do |format| format.json do - render json: @build.trace_with_state(params[:state]).merge!(id: @build.id, status: @build.status) + render json: @build.trace_with_state(params[:state].presence).merge!(id: @build.id, status: @build.status) end end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 06a114dcbe8..67e7187c10d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -61,12 +61,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController format.json { render json: @merge_request } format.patch { render text: @merge_request.to_patch } format.diff do - headers.store(*Gitlab::Workhorse.send_git_diff(@project.repository, - @merge_request.diff_base_commit.id, - @merge_request.last_commit.id)) - headers['Content-Disposition'] = 'inline' + return render_404 unless @merge_request.diff_refs - head :ok + send_git_diff @project.repository, @merge_request.diff_refs end end end diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 10de0e60530..10d24da16d7 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -18,10 +18,7 @@ class Projects::RawController < Projects::ApplicationController if @blob.lfs_pointer? send_lfs_object else - headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) - headers['Content-Disposition'] = 'inline' - headers['Content-Type'] = safe_content_type(@blob) - head :ok # 'render nothing: true' messes up the Content-Type + send_git_blob @repository, @blob end else render_404 diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index bb7a6b6a5ab..d5af0341d18 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -11,8 +11,7 @@ class Projects::RepositoriesController < Projects::ApplicationController end def archive - headers.store(*Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format])) - head :ok + send_git_archive @repository, ref: params[:ref], format: params[:format] rescue => ex logger.error("#{self.class.name}: #{ex}") return git_not_found! diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index f685e547537..39831ce2e48 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -30,6 +30,8 @@ module NavHelper else "page-gutter right-sidebar-expanded" end + elsif current_path?('builds#show') + "page-gutter build-sidebar right-sidebar-expanded" end end diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb new file mode 100644 index 00000000000..2bd0dbfd095 --- /dev/null +++ b/app/helpers/workhorse_helper.rb @@ -0,0 +1,24 @@ +# Helpers to send Git blobs, diffs or archives through Workhorse. +# Workhorse will also serve files when using `send_file`. +module WorkhorseHelper + # Send a Git blob through Workhorse + def send_git_blob(repository, blob) + headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob)) + headers['Content-Disposition'] = 'inline' + headers['Content-Type'] = safe_content_type(blob) + head :ok # 'render nothing: true' messes up the Content-Type + end + + # Send a Git diff through Workhorse + def send_git_diff(repository, diff_refs) + headers.store(*Gitlab::Workhorse.send_git_diff(repository, diff_refs)) + headers['Content-Disposition'] = 'inline' + head :ok + end + + # Archive a Git repository and send it through Workhorse + def send_git_archive(repository, ref:, format:) + headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format)) + head :ok + end +end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 29f36570912..7b8858b24d6 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -276,14 +276,6 @@ class MergeRequest < ActiveRecord::Base true end - def gitlab_merge_status - if work_in_progress? - "work_in_progress" - else - merge_status_name - end - end - def can_cancel_merge_when_build_succeeds?(current_user) can_be_merged_by?(current_user) || self.author == current_user end diff --git a/app/models/project.rb b/app/models/project.rb index 472e79cfcf8..e2f7ffe493c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -253,20 +253,69 @@ class Project < ActiveRecord::Base non_archived.where(table[:name].matches(pattern)) end - def find_with_namespace(id) - namespace_path, project_path = id.split('/', 2) + # Finds a single project for the given path. + # + # path - The full project path (including namespace path). + # + # Returns a Project, or nil if no project could be found. + def find_with_namespace(path) + where_paths_in([path]).reorder(nil).take + end - return nil if !namespace_path || !project_path + # Builds a relation to find multiple projects by their full paths. + # + # Each path must be in the following format: + # + # namespace_path/project_path + # + # For example: + # + # gitlab-org/gitlab-ce + # + # Usage: + # + # Project.where_paths_in(%w{gitlab-org/gitlab-ce gitlab-org/gitlab-ee}) + # + # This would return the projects with the full paths matching the values + # given. + # + # paths - An Array of full paths (namespace path + project path) for which + # to find the projects. + # + # Returns an ActiveRecord::Relation. + def where_paths_in(paths) + wheres = [] + cast_lower = Gitlab::Database.postgresql? + + paths.each do |path| + namespace_path, project_path = path.split('/', 2) + + next unless namespace_path && project_path + + namespace_path = connection.quote(namespace_path) + project_path = connection.quote(project_path) + + where = "(namespaces.path = #{namespace_path} + AND projects.path = #{project_path})" + + if cast_lower + where = "( + #{where} + OR ( + LOWER(namespaces.path) = LOWER(#{namespace_path}) + AND LOWER(projects.path) = LOWER(#{project_path}) + ) + )" + end - # Use of unscoped ensures we're not secretly adding any ORDER BYs, which - # have a negative impact on performance (and aren't needed for this - # query). - projects = unscoped. - joins(:namespace). - iwhere('namespaces.path' => namespace_path) + wheres << where + end - projects.find_by('projects.path' => project_path) || - projects.iwhere('projects.path' => project_path).take + if wheres.empty? + none + else + joins(:namespace).where(wheres.join(' OR ')) + end end def visibility_levels diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index ca99ba8def3..79cc5c02888 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -33,7 +33,7 @@ = navbar_icon('activity') %span Activity - + - if project_nav_tab? :files = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases network)) do = link_to project_files_path(@project), title: 'Code', class: 'shortcuts-tree' do @@ -62,15 +62,8 @@ %span Graphs - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do - = navbar_icon('milestones') - %span - Milestones - - if project_nav_tab? :issues - = nav_link(controller: :issues) do + = nav_link(controller: [:issues, :labels, :milestones]) do = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do = navbar_icon('issues') %span @@ -86,13 +79,6 @@ Merge Requests %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do - = icon('tags fw') - %span - Labels - - if project_nav_tab? :wiki = nav_link(controller: :wikis) do = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index ede01dcc1aa..539d07d634a 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -1,4 +1,5 @@ - page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds' +- header_title project_title(@project, "Builds", project_builds_path(@project)) .top-block.row-content-block.clearfix .pull-right diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml new file mode 100644 index 00000000000..51b5bd9db42 --- /dev/null +++ b/app/views/projects/builds/_header.html.haml @@ -0,0 +1,16 @@ +.content-block.build-header + = ci_status_with_icon(@build.status) + Build + %strong ##{@build.id} + for commit + = link_to ci_status_path(@build.pipeline) do + %strong= @build.pipeline.short_sha + from + = link_to namespace_project_commits_path(@project.namespace, @project, @build.ref) do + %code + = @build.ref + - if @build.user + = render "user" + = time_ago_with_tooltip(@build.created_at) + %button.btn.btn-default.pull-right.visible-xs-block.visible-sm-block.build-gutter-toggle.js-sidebar-build-toggle{ role: "button", type: "button" } + = icon('angle-double-left') diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml new file mode 100644 index 00000000000..5d931389dfb --- /dev/null +++ b/app/views/projects/builds/_sidebar.html.haml @@ -0,0 +1,93 @@ +%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar + .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default + Build + %strong ##{@build.id} + %a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" } + = icon('angle-double-right') + - if @build.coverage + .block.block-first + .title + Test coverage + %p.build-detail-row + #{@build.coverage}% + + - if can?(current_user, :read_build, @project) && @build.artifacts? + .block{ class: ("block-first" if !@build.coverage) } + .title + Build artifacts + .btn-group.btn-group-justified{ role: :group } + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do + Download + + - if @build.artifacts_metadata? + = link_to browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do + Browse + + .block{ class: ("block-first" if !@build.coverage && !(can?(current_user, :read_build, @project) && @build.artifacts?)) } + .title + Build details + - if @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: + #{duration_in_words(@build.finished_at, @build.started_at)} + - 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 + + %p + %span.build-light-text Token: + #{@build.trigger_request.trigger.short_token} + + - if @build.trigger_request.variables + %p + %span.build-light-text Variables: + + %code + - @build.trigger_request.variables.each do |key, value| + #{key}=#{value} + + .block + .title + Commit message + %p.build-light-text.append-bottom-0 + #{@build.pipeline.git_commit_message} + + - 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/_user.html.haml b/app/views/projects/builds/_user.html.haml new file mode 100644 index 00000000000..2642de8021d --- /dev/null +++ b/app/views/projects/builds/_user.html.haml @@ -0,0 +1,4 @@ +by +%a{ href: user_path(@build.user) } + = image_tag avatar_icon(@build.user, 24), class: "avatar s24" + %strong= @build.user.to_reference diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 5477fc65c2b..a26f8aeb315 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,18 +1,10 @@ - page_title "#{@build.name} (##{@build.id})", "Builds" - trace_with_state = @build.trace_with_state +- header_title project_title(@project, "Builds", project_builds_path(@project)) .build-page - .row-content-block.top-block - Build ##{@build.id} for commit - %strong.monospace= link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline) - from - = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref) - - merge_request = @build.merge_request - - if merge_request - via - = link_to "merge request #{merge_request.to_reference}", merge_request_path(merge_request) + = render "header" - #up-build-trace - builds = @build.pipeline.builds.latest.to_a - if builds.size > 1 %ul.nav-links.no-top.no-bottom @@ -33,18 +25,6 @@ · %i.fa.fa-warning This build was retried. - - .row-content-block.middle-block - .build-head - .clearfix - = ci_status_with_icon(@build.status) - - if @build.duration - %span - %i.fa.fa-time - #{duration_in_words(@build.finished_at, @build.started_at)} - .pull-right - #{time_ago_with_tooltip(@build.finished_at) if @build.finished_at} - - if @build.stuck? - unless @build.any_runners_online? .bs-callout.bs-callout-warning @@ -64,158 +44,27 @@ = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do Runners page - .row.prepend-top-default - .col-md-9 - .clearfix - - if @build.active? - .autoscroll-container - %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll - .clearfix + .prepend-top-default + - if @build.active? + .autoscroll-container + %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll #js-build-scroll.scroll-controls - = link_to '#up-build-trace', class: 'btn' do + = link_to '#build-trace', class: 'btn' do %i.fa.fa-angle-up = link_to '#down-build-trace', class: 'btn' do %i.fa.fa-angle-down + - if @build.erased? + .erased.alert.alert-warning + - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by + Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)} + - else + %pre.build-trace#build-trace + %code.bash.js-build-output + = icon("refresh spin", class: "js-build-refresh") - - if @build.erased? - .erased.alert.alert-warning - - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by - Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)} - - else - %pre.trace#build-trace - %code.bash - = preserve do - = raw trace_with_state[:html] - - if @build.active? - %i{:class => "fa fa-refresh fa-spin"} - - %div#down-build-trace - - .col-md-3 - - if @build.coverage - .build-widget - %h4.title - Test coverage - %h1 #{@build.coverage}% - - - if can?(current_user, :read_build, @project) && @build.artifacts? - .build-widget.artifacts - %h4.title Build artifacts - .center - .btn-group{ role: :group } - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary' do - = icon('download') - Download - - - if @build.artifacts_metadata? - = link_to browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary' do - = icon('folder-open') - Browse - - .build-widget.build-controls - %h4.title - Build ##{@build.id} - - if can?(current_user, :update_build, @project) - .center - .btn-group{ role: :group } - - if @build.active? - = link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-danger', method: :post - - elsif @build.retryable? - = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary', method: :post - - - if @build.erasable? - = link_to erase_namespace_project_build_path(@project.namespace, @project, @build), - class: 'btn btn-sm btn-warning', method: :post, - data: { confirm: 'Are you sure you want to erase this build?' } do - = icon('eraser') - Erase - - if @build.has_trace? - = link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build), - class: 'btn btn-sm btn-success', target: '_blank' - - .clearfix - - if @build.duration - %p - %span.attr-name Duration: - #{duration_in_words(@build.finished_at, @build.started_at)} - %p - %span.attr-name Created: - #{time_ago_with_tooltip(@build.created_at)} - - if @build.finished_at - %p - %span.attr-name Finished: - #{time_ago_with_tooltip(@build.finished_at)} - - if @build.erased_at - %p - %span.attr-name Erased: - #{time_ago_with_tooltip(@build.erased_at)} - %p - %span.attr-name 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} - - - if @build.trigger_request - .build-widget - %h4.title - Trigger - - %p - %span.attr-name Token: - #{@build.trigger_request.trigger.short_token} - - - if @build.trigger_request.variables - %p - %span.attr-name Variables: - - %code - - @build.trigger_request.variables.each do |key, value| - #{key}=#{value} - - .build-widget - %h4.title - Commit - .pull-right - %small - = link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline), class: "monospace" - %p - %span.attr-name Branch: - = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref) - %p - %span.attr-name Author: - #{@build.pipeline.git_author_name} - %p - %span.attr-name Message: - #{@build.pipeline.git_commit_message} - - - if @build.tags.any? - .build-widget - %h4.title - Tags - - @build.tag_list.each do |tag| - %span.label.label-primary - = tag - - - if @builds.present? - .build-widget - %h4.title #{pluralize(@builds.count(:id), "other build")} for - = succeed ":" do - = link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline), class: "monospace" - %table.table.builds - - @builds.each_with_index do |build, i| - %tr.build - %td - = ci_icon_for_status(build.status) - %td - = link_to namespace_project_build_path(@project.namespace, @project, build) do - - if build.name - = build.name - - else - %span ##{build.id} - - %td.status= build.status + #down-build-trace += render "sidebar" - :javascript - new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}") +:javascript + new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}") diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml new file mode 100644 index 00000000000..166dae248b6 --- /dev/null +++ b/app/views/projects/issues/_head.html.haml @@ -0,0 +1,25 @@ +%ul.nav-links.sub-nav + %div{ class: (container_class) } + - if project_nav_tab?(:issues) && !current_controller?(:merge_requests) + = nav_link(controller: :issues) do + = link_to url_for_project_issues(@project, only_path: true), title: 'Issues' do + %span + Issues + + - if project_nav_tab?(:merge_requests) && current_controller?(:merge_requests) + = nav_link(controller: :merge_requests) do + = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests' do + %span + Merge Requests + + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do + %span + Labels + + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do + %span + Milestones diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 7c1457553d9..cd876b5ea62 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,23 +1,26 @@ +- @no_container = true - page_title "Issues" += render "projects/issues/head" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") -.top-area - = render 'shared/issuable/nav', type: :issues - .nav-controls - - if current_user - = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do - = icon('rss') - %span.icon-label - Subscribe - = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project) - - if can? current_user, :create_issue, @project - = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do - New Issue +%div{ class: (container_class) } + .top-area + = render 'shared/issuable/nav', type: :issues + .nav-controls + - if current_user + = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do + = icon('rss') + %span.icon-label + Subscribe + = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project) + - if can? current_user, :create_issue, @project + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do + New Issue -= render 'shared/issuable/filter', type: :issues + = render 'shared/issuable/filter', type: :issues -.issues-holder - = render "issues" + .issues-holder + = render "issues" diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 93583c92609..6e1baa46b05 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,35 +1,38 @@ +- @no_container = true - page_title "Labels" - hide_class = '' += render "projects/issues/head" -.top-area - .nav-text - Labels can be applied to issues and merge requests. - .nav-controls - - if can?(current_user, :admin_label, @project) - = link_to new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" do - New label +%div{ class: (container_class) } + .top-area + .nav-text + Labels can be applied to issues and merge requests. + .nav-controls + - if can?(current_user, :admin_label, @project) + = link_to new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" do + New label -.labels - - if can?(current_user, :admin_label, @project) - -# Only show it in the first page - - hide = @project.labels.empty? || (params[:page].present? && params[:page] != '1') - .prioritized-labels{ class: ('hide' if hide) } - %h5 Prioritized Labels - %ul.content-list.manage-labels-list.js-prioritized-labels{ "data-url" => set_priorities_namespace_project_labels_path(@project.namespace, @project) } - - if @prioritized_labels.present? - = render @prioritized_labels - - else - %p.empty-message No prioritized labels yet - .other-labels + .labels - if can?(current_user, :admin_label, @project) - %h5{ class: ('hide' if hide) } Other Labels - - if @labels.present? - %ul.content-list.manage-labels-list.js-other-labels - = render @labels - = paginate @labels, theme: 'gitlab' - - else - .nothing-here-block - - if can?(current_user, :admin_label, @project) - Create a label or #{link_to 'generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post}. - - else - No labels created + -# Only show it in the first page + - hide = @project.labels.empty? || (params[:page].present? && params[:page] != '1') + .prioritized-labels{ class: ('hide' if hide) } + %h5 Prioritized Labels + %ul.content-list.manage-labels-list.js-prioritized-labels{ "data-url" => set_priorities_namespace_project_labels_path(@project.namespace, @project) } + - if @prioritized_labels.present? + = render @prioritized_labels + - else + %p.empty-message No prioritized labels yet + .other-labels + - if can?(current_user, :admin_label, @project) + %h5{ class: ('hide' if hide) } Other Labels + - if @labels.present? + %ul.content-list.manage-labels-list.js-other-labels + = render @labels + = paginate @labels, theme: 'gitlab' + - else + .nothing-here-block + - if can?(current_user, :admin_label, @project) + Create a label or #{link_to 'generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post}. + - else + No labels created diff --git a/app/views/projects/merge_requests/_head.html.haml b/app/views/projects/merge_requests/_head.html.haml deleted file mode 100644 index 19e4dab874b..00000000000 --- a/app/views/projects/merge_requests/_head.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -.top-tabs - = link_to namespace_project_merge_requests_path(@project.namespace, @project), class: "tab #{'active' if current_page?(namespace_project_merge_requests_path(@project.namespace, @project)) }" do - %span - Merge Requests - diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index c8653cb0c30..9f948d41dda 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -1,18 +1,20 @@ +- @no_container = true - page_title "Merge Requests" - += render "projects/issues/head" = render 'projects/last_push' -.top-area - = render 'shared/issuable/nav', type: :merge_requests - .nav-controls - = render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) +%div{ class: (container_class) } + .top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls + = render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) - - merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project)) - - if merge_project - = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do - New Merge Request + - merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project)) + - if merge_project + = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do + New Merge Request -= render 'shared/issuable/filter', type: :merge_requests + = render 'shared/issuable/filter', type: :merge_requests -.merge-requests-holder - = render 'merge_requests' + .merge-requests-holder + = render 'merge_requests' diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 60a5b83434e..b0e0bdfff5a 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,19 +1,22 @@ +- @no_container = true - page_title "Milestones" += render "projects/issues/head" -.top-area - = render 'shared/milestones_filter' +%div{ class: (container_class) } + .top-area + = render 'shared/milestones_filter' - .nav-controls - - if can?(current_user, :admin_milestone, @project) - = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "btn btn-new", title: "New Milestone" do - New Milestone + .nav-controls + - if can?(current_user, :admin_milestone, @project) + = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "btn btn-new", title: "New Milestone" do + New Milestone -.milestones - %ul.content-list - = render @milestones + .milestones + %ul.content-list + = render @milestones - - if @milestones.blank? - %li - .nothing-here-block No milestones to show + - if @milestones.blank? + %li + .nothing-here-block No milestones to show - = paginate @milestones, theme: "gitlab" + = paginate @milestones, theme: "gitlab" |