diff options
author | Douwe Maan <douwe@gitlab.com> | 2016-01-20 14:53:41 +0100 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2016-01-20 14:53:41 +0100 |
commit | c23ca0b0b5640d9cbf3fbfd446916a228b581b2f (patch) | |
tree | 1aa14035e6484f0f1c16e71746391d6e6a0277b1 /app | |
parent | 701513dcc7afb403372bc738642a9a52e9be5983 (diff) | |
parent | 481644ca7c9f763d4646ad557cc3bcf8f4f71816 (diff) | |
download | gitlab-ce-c23ca0b0b5640d9cbf3fbfd446916a228b581b2f.tar.gz |
Merge branch 'master' into issue_3945
Diffstat (limited to 'app')
72 files changed, 244 insertions, 122 deletions
diff --git a/app/assets/fonts/SourceSansPro-Black.ttf.woff2 b/app/assets/fonts/SourceSansPro-Black.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..c90d078406c --- /dev/null +++ b/app/assets/fonts/SourceSansPro-Black.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..b87e22c41b5 --- /dev/null +++ b/app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-Bold.ttf.woff2 b/app/assets/fonts/SourceSansPro-Bold.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..0f46f3e833a --- /dev/null +++ b/app/assets/fonts/SourceSansPro-Bold.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..8007df6df32 --- /dev/null +++ b/app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2 b/app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..b715f274082 --- /dev/null +++ b/app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..d8f9d29d4aa --- /dev/null +++ b/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-It.ttf.woff2 b/app/assets/fonts/SourceSansPro-It.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..a00852641f8 --- /dev/null +++ b/app/assets/fonts/SourceSansPro-It.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-Light.ttf.woff2 b/app/assets/fonts/SourceSansPro-Light.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..d8b610ad76e --- /dev/null +++ b/app/assets/fonts/SourceSansPro-Light.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-LightIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-LightIt.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..e0eebac8273 --- /dev/null +++ b/app/assets/fonts/SourceSansPro-LightIt.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-Regular.ttf.woff2 b/app/assets/fonts/SourceSansPro-Regular.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..0dd3464c74b --- /dev/null +++ b/app/assets/fonts/SourceSansPro-Regular.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-Semibold.ttf.woff2 b/app/assets/fonts/SourceSansPro-Semibold.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..2526d2e1b60 --- /dev/null +++ b/app/assets/fonts/SourceSansPro-Semibold.ttf.woff2 diff --git a/app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2 Binary files differnew file mode 100755 index 00000000000..606935af089 --- /dev/null +++ b/app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2 diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 619abb1fb07..9d5ae6c04e9 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -5,7 +5,7 @@ class @AwardsHandler event.preventDefault() $(".emoji-menu").show() - $("html").click -> + $("html").on 'click', (event) -> if !$(event.target).closest(".emoji-menu").length if $(".emoji-menu").is(":visible") $(".emoji-menu").hide() @@ -19,7 +19,7 @@ class @AwardsHandler @addAwardToEmojiBar(emoji) $(".emoji-menu").hide() - + addAwardToEmojiBar: (emoji) -> @addEmojiToFrequentlyUsedList(emoji) @@ -66,9 +66,14 @@ class @AwardsHandler addMeToAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() - authors = award_block.attr("data-original-title").split(", ") + authors = _.compact(award_block.attr("data-original-title").split(", ")) authors.push("me") - award_block.attr("title", authors.join(", ")) + + if authors.length == 1 + award_block.attr("title", "me") + else + award_block.attr("title", authors.join(", ")) + @resetTooltip(award_block) resetTooltip: (award) -> @@ -78,7 +83,7 @@ class @AwardsHandler setTimeout (-> award.tooltip() ), 200 - + createEmoji: (emoji) -> emojiCssClass = @resolveNameToCssClass(emoji) diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee index 0d26c58a81d..cbc70cd846c 100644 --- a/app/assets/javascripts/issue.js.coffee +++ b/app/assets/javascripts/issue.js.coffee @@ -6,11 +6,25 @@ class @Issue constructor: -> # Prevent duplicate event bindings @disableTaskList() - + @fixAffixScroll() if $('a.btn-close').length @initTaskList() @initIssueBtnEventListeners() + fixAffixScroll: -> + fixAffix = -> + $discussion = $('.issuable-discussion') + $sidebar = $('.issuable-sidebar') + if $sidebar.hasClass('no-affix') + $sidebar.removeClass(['affix-top','affix']) + discussionHeight = $discussion.height() + sidebarHeight = $sidebar.height() + if sidebarHeight > discussionHeight + $discussion.height(sidebarHeight + 50) + $sidebar.addClass('no-affix') + $(window).on('resize', fixAffix) + fixAffix() + initTaskList: -> $('.detail-page-description .js-task-list-container').taskList('enable') $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee index 1f46e331427..6af5a48a0bb 100644 --- a/app/assets/javascripts/merge_request.js.coffee +++ b/app/assets/javascripts/merge_request.js.coffee @@ -15,6 +15,8 @@ class @MergeRequest this.$('.show-all-commits').on 'click', => this.showAllCommits() + @fixAffixScroll(); + @initTabs() # Prevent duplicate event bindings @@ -28,6 +30,20 @@ class @MergeRequest $: (selector) -> this.$el.find(selector) + fixAffixScroll: -> + fixAffix = -> + $discussion = $('.issuable-discussion') + $sidebar = $('.issuable-sidebar') + if $sidebar.hasClass('no-affix') + $sidebar.removeClass(['affix-top','affix']) + discussionHeight = $discussion.height() + sidebarHeight = $sidebar.height() + if sidebarHeight > discussionHeight + $discussion.height(sidebarHeight + 50) + $sidebar.addClass('no-affix') + $(window).on('resize', fixAffix) + fixAffix() + initTabs: -> if @opts.action != 'new' # `MergeRequests#new` has no tab-persisting or lazy-loading behavior diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 356fb6aa08c..2bfc5cb2d9c 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -320,6 +320,7 @@ class @Notes form.show() textarea = form.find("textarea") textarea.focus() + autosize(textarea) # HACK (rspeicher/DouweM): Work around a Chrome 43 bug(?). # The textarea has the correct value, Chrome just won't show it unless we @@ -355,7 +356,7 @@ class @Notes $('.note[id="' + note_id + '"]').each -> note = $(this) notes = note.closest(".notes") - count = notes.closest(".notes_holder").find(".discussion-notes-count") + count = notes.closest(".issuable-details").find(".notes-tab .badge") # check if this is the last note for this line if notes.find(".note").length is 1 @@ -365,9 +366,10 @@ class @Notes # for diff lines notes.closest("tr").remove() - else - # update notes count - count.get(0).lastChild.nodeValue = " #{notes.children().length - 1}" + + # update notes count + oldNum = parseInt(count.text()) + count.text(oldNum - 1) note.remove() diff --git a/app/assets/javascripts/star.js.coffee b/app/assets/javascripts/star.js.coffee index d849b2e7950..f27780dda93 100644 --- a/app/assets/javascripts/star.js.coffee +++ b/app/assets/javascripts/star.js.coffee @@ -6,7 +6,7 @@ class @Star $starIcon = $this.find('i') toggleStar = (isStarred) -> - $this.parent().find('span.count').text data.star_count + $this.parent().find('.star-count').text data.star_count if isStarred $starSpan.removeClass('starred').text 'Star' $starIcon.removeClass('fa-star').addClass 'fa-star-o' @@ -19,4 +19,4 @@ class @Star return ).on 'ajax:error', (e, xhr, status, error) -> new Flash('Star toggle failed. Try again later.', 'alert') - return
\ No newline at end of file + return diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 05645116268..585a9d83913 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -75,6 +75,8 @@ hr { @include str-truncated; } +.item-title { font-weight: 600; } + /** FLASH message **/ .author_link { color: $gl-link-color; diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss index 8e6922c9231..b7638c86bfa 100644 --- a/app/assets/stylesheets/framework/filters.scss +++ b/app/assets/stylesheets/framework/filters.scss @@ -1,5 +1,5 @@ .filter-item { - margin-right: 15px; + margin-right: 6px; } @media (min-width: 800px) { diff --git a/app/assets/stylesheets/framework/fonts.scss b/app/assets/stylesheets/framework/fonts.scss index 20988f7b430..7a946109e3a 100644 --- a/app/assets/stylesheets/framework/fonts.scss +++ b/app/assets/stylesheets/framework/fonts.scss @@ -3,23 +3,39 @@ font-family: 'Source Sans Pro'; font-style: normal; font-weight: 300; - src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), font-url('SourceSansPro-Light.ttf.woff'); + src: + local('Source Sans Pro Light'), + local('SourceSansPro-Light'), + font-url('SourceSansPro-Light.ttf.woff2') format('woff2'), + font-url('SourceSansPro-Light.ttf.woff') format('woff'); } @font-face { font-family: 'Source Sans Pro'; font-style: normal; font-weight: 400; - src: local('Source Sans Pro'), local('SourceSansPro-Regular'), font-url('SourceSansPro-Regular.ttf.woff'); + src: + local('Source Sans Pro'), + local('SourceSansPro-Regular'), + font-url('SourceSansPro-Regular.ttf.woff2') format('woff2'), + font-url('SourceSansPro-Regular.ttf.woff') format('woff'); } @font-face { font-family: 'Source Sans Pro'; font-style: normal; font-weight: 600; - src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), font-url('SourceSansPro-Semibold.ttf.woff'); + src: + local('Source Sans Pro Semibold'), + local('SourceSansPro-Semibold'), + font-url('SourceSansPro-Semibold.ttf.woff2') format('woff2'), + font-url('SourceSansPro-Semibold.ttf.woff') format('woff'); } @font-face { font-family: 'Source Sans Pro'; font-style: normal; font-weight: 700; - src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), font-url('SourceSansPro-Bold.ttf.woff'); + src: + local('Source Sans Pro Bold'), + local('SourceSansPro-Bold'), + font-url('SourceSansPro-Bold.ttf.woff2') format('woff2'), + font-url('SourceSansPro-Bold.ttf.woff') format('woff'); } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 85ecdddda79..3ec48da9a41 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -26,6 +26,7 @@ $gl-vert-padding: 6px; $gl-padding-top:10px; $gl-avatar-size: 46px; $secondary-text: #7f8fa4; +$error-exclamation-point: #E62958; /* * Color schema diff --git a/app/assets/stylesheets/pages/branches.scss b/app/assets/stylesheets/pages/branches.scss deleted file mode 100644 index abae5c3d0a5..00000000000 --- a/app/assets/stylesheets/pages/branches.scss +++ /dev/null @@ -1,3 +0,0 @@ -.branch-name{ - font-weight: 600; -} diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index 6ec88bdd804..e53d6fc6bdc 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -2,10 +2,6 @@ display: block; } -.commit-row-title .commit-title { - font-weight: 600; -} - .commit-author, .commit-committer{ display: block; color: #999; diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index 800df95cff3..818fd03e2ae 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -36,6 +36,10 @@ li.commit { line-height: 20px; margin-bottom: 2px; + .btn-clipboard { + margin-top: -1px; + } + .notes_count { float: right; margin-right: 10px; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 012232a708e..0b79aa172a4 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -66,6 +66,7 @@ width: 100%; font-family: $monospace_font; border: none; + border-collapse: separate; margin: 0px; padding: 0px; .line_holder td { diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index 3404c2631e1..263993f59a5 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -11,8 +11,3 @@ height: 42px; } } - -.content-list .group-name { - font-weight: 600; - color: #4c4e54; -} diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index eae3590a189..977ada0ff38 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -20,6 +20,11 @@ position: fixed; top: 70px; margin-right: 35px; + + &.no-affix { + position: relative; + top: 0; + } } } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 13b0ed769fc..003a4c22f20 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -92,12 +92,12 @@ } .project-repo-buttons { - margin-top: 12px; + margin-top: 20px; margin-bottom: 0px; .count-buttons { display: block; - margin-bottom: 12px; + margin-bottom: 20px; } .clone-row { @@ -163,7 +163,7 @@ line-height: 13px; padding: $gl-vert-padding $gl-padding; letter-spacing: .4px; - padding: 10px; + padding: 10px 14px; text-align: center; vertical-align: middle; touch-action: manipulation; @@ -558,3 +558,9 @@ pre.light-well { width: 101%; } } + +.cannot-be-merged, +.cannot-be-merged:hover { + color: #E62958; + margin-top: 2px; +} diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 3aaa96da609..bdcf1897522 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -3,6 +3,10 @@ border-bottom: 1px solid #DDD; padding-bottom: 15px; margin-bottom: 15px; + + .term { + height: 22px; + } } } diff --git a/app/assets/stylesheets/pages/tags.scss b/app/assets/stylesheets/pages/tags.scss deleted file mode 100644 index e9cd6dc6c5e..00000000000 --- a/app/assets/stylesheets/pages/tags.scss +++ /dev/null @@ -1,3 +0,0 @@ -.tag-name{ - font-weight: 600; -} diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb index 38814459f66..2eac0cabf7a 100644 --- a/app/controllers/abuse_reports_controller.rb +++ b/app/controllers/abuse_reports_controller.rb @@ -2,6 +2,7 @@ class AbuseReportsController < ApplicationController def new @abuse_report = AbuseReport.new @abuse_report.user_id = params[:user_id] + @ref_url = params.fetch(:ref_url, '') end def create diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8484a502024..8b62c11f7cc 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -116,7 +116,7 @@ class ApplicationController < ActionController::Base # localhost/group/project # if id =~ /\.git\Z/ - redirect_to request.original_url.gsub(/\.git\Z/, '') and return + redirect_to request.original_url.gsub(/\.git\/?\Z/, '') and return end project_path = "#{namespace}/#{id}" diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index dff0732bdfe..f159a6d6dc6 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -8,7 +8,7 @@ class Projects::ArtifactsController < Projects::ApplicationController end unless artifacts_file.exists? - return not_found! + return render_404 end send_file artifacts_file.path, disposition: 'attachment' diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 0e965966ffa..92d9699fe84 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -42,7 +42,7 @@ class Projects::BuildsController < Projects::ApplicationController def retry unless @build.retryable? - return page_404 + return render_404 end build = Ci::Build.retry(@build) @@ -72,7 +72,7 @@ class Projects::BuildsController < Projects::ApplicationController def authorize_manage_builds! unless can?(current_user, :manage_builds, project) - return page_404 + return render_404 end end end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index ba924ccc5a5..f5a169e5aa9 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -80,7 +80,7 @@ class Projects::CommitController < Projects::ApplicationController def authorize_manage_builds! unless can?(current_user, :manage_builds, project) - return page_404 + return render_404 end end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index f476afb2d92..68244883803 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -49,7 +49,7 @@ class Projects::IssuesController < Projects::ApplicationController assignee_id: "" ) - @issue = @project.issues.new(issue_params) + @issue = @noteable = @project.issues.new(issue_params) respond_with(@issue) end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index de948d271c8..a6284a24223 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -90,6 +90,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController def new params[:merge_request] ||= ActionController::Parameters.new(source_project: @project) @merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute + @noteable = @merge_request @target_branches = if @merge_request.target_project @merge_request.target_project.repository.branch_names diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 2104c7a7a71..92b0caa2efb 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -25,7 +25,7 @@ class Projects::SnippetsController < Projects::ApplicationController end def new - @snippet = @project.snippets.build + @snippet = @noteable = @project.snippets.build end def create diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 4d56b48e3f8..0a4192e6bac 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -81,7 +81,8 @@ class IssuableFinder elsif current_user && params[:authorized_only].presence && !current_user_related? @projects = current_user.authorized_projects.reorder(nil) else - @projects = ProjectsFinder.new.execute(current_user).reorder(nil) + @projects = ProjectsFinder.new.execute(current_user, group: group). + reorder(nil) end end diff --git a/app/mailers/emails/builds.rb b/app/mailers/emails/builds.rb index d58609a2de5..64c1ce8cfab 100644 --- a/app/mailers/emails/builds.rb +++ b/app/mailers/emails/builds.rb @@ -3,13 +3,26 @@ module Emails def build_fail_email(build_id, to) @build = Ci::Build.find(build_id) @project = @build.project + add_project_headers + add_build_headers + headers['X-GitLab-Build-Status'] = "failed" mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha)) end def build_success_email(build_id, to) @build = Ci::Build.find(build_id) @project = @build.project + add_project_headers + add_build_headers + headers['X-GitLab-Build-Status'] = "success" mail(to: to, subject: subject("Build success for #{@project.name}", @build.short_sha)) end + + private + def add_build_headers + headers['X-GitLab-Build-Id'] = @build.id + headers['X-GitLab-Build-Ref'] = @build.ref + end + end end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index b96418679bd..377c2999d6c 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -43,7 +43,7 @@ module Emails @current_user = @created_by = User.find(created_by_id) @access_level = access_level @invite_email = invite_email - + @target_url = namespace_project_url(@project.namespace, @project) mail(to: @created_by.notification_email, @@ -65,6 +65,10 @@ module Emails # used in notify layout @target_url = @message.target_url + @project = Project.find project_id + + add_project_headers + headers['X-GitLab-Author'] = @message.author_username mail(from: sender(@message.author_id, @message.send_from_committer_email?), reply_to: @message.reply_to, diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index e1cd075a978..8cbc9eefc7b 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -100,12 +100,7 @@ class Notify < BaseMailer end def mail_thread(model, headers = {}) - if @project - headers['X-GitLab-Project'] = @project.name - headers['X-GitLab-Project-Id'] = @project.id - headers['X-GitLab-Project-Path'] = @project.path_with_namespace - end - + add_project_headers headers["X-GitLab-#{model.class.name}-ID"] = model.id headers['X-GitLab-Reply-Key'] = reply_key @@ -152,4 +147,12 @@ class Notify < BaseMailer def reply_key @reply_key ||= SentNotification.reply_key end + + def add_project_headers + return unless @project + + headers['X-GitLab-Project'] = @project.name + headers['X-GitLab-Project-Id'] = @project.id + headers['X-GitLab-Project-Path'] = @project.path_with_namespace + end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 5375148a654..ab59a3506a2 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -160,6 +160,7 @@ class Ability @project_report_rules ||= project_guest_rules + [ :create_commit_status, :read_commit_statuses, + :read_build_artifacts, :download_code, :fork_project, :create_project_snippet, @@ -175,7 +176,6 @@ class Ability :create_merge_request, :create_wiki, :manage_builds, - :read_build_artifacts, :push_code ] end diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb index 2bc15c60d57..cc59aa4e911 100644 --- a/app/models/abuse_report.rb +++ b/app/models/abuse_report.rb @@ -17,7 +17,7 @@ class AbuseReport < ActiveRecord::Base validates :reporter, presence: true validates :user, presence: true validates :message, presence: true - validates :user_id, uniqueness: true + validates :user_id, uniqueness: { message: 'has already been reported' } def remove_user user.block diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 6cc26abce66..16a5b03f591 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -128,6 +128,14 @@ module Ci !self.commit.latest_builds_for_ref(self.ref).include?(self) end + def depends_on_builds + # Get builds of the same type + latest_builds = self.commit.builds.similar(self).latest + + # Return builds from previous stages + latest_builds.where('stage_idx < ?', stage_idx) + end + def trace_html html = Ci::Ansi2html::convert(trace) if trace.present? html || '' diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb index fa18ba5dbbe..fe923fafbe0 100644 --- a/app/models/hooks/project_hook.rb +++ b/app/models/hooks/project_hook.rb @@ -3,11 +3,11 @@ # Table name: web_hooks # # id :integer not null, primary key -# url :string(255) +# url :string(2000) # project_id :integer # created_at :datetime # updated_at :datetime -# type :string(255) default("ProjectHook") +# type :string default("ProjectHook") # service_id :integer # push_events :boolean default(TRUE), not null # issues_events :boolean default(FALSE), not null diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb index b333a337347..80962264ba2 100644 --- a/app/models/hooks/service_hook.rb +++ b/app/models/hooks/service_hook.rb @@ -3,11 +3,11 @@ # Table name: web_hooks # # id :integer not null, primary key -# url :string(255) +# url :string(2000) # project_id :integer # created_at :datetime # updated_at :datetime -# type :string(255) default("ProjectHook") +# type :string default("ProjectHook") # service_id :integer # push_events :boolean default(TRUE), not null # issues_events :boolean default(FALSE), not null diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb index d81512fae5d..c147d8762a9 100644 --- a/app/models/hooks/system_hook.rb +++ b/app/models/hooks/system_hook.rb @@ -3,11 +3,11 @@ # Table name: web_hooks # # id :integer not null, primary key -# url :string(255) +# url :string(2000) # project_id :integer # created_at :datetime # updated_at :datetime -# type :string(255) default("ProjectHook") +# type :string default("ProjectHook") # service_id :integer # push_events :boolean default(TRUE), not null # issues_events :boolean default(FALSE), not null diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 3bb50c63cac..7a13c3f0a39 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -3,11 +3,11 @@ # Table name: web_hooks # # id :integer not null, primary key -# url :string(255) +# url :string(2000) # project_id :integer # created_at :datetime # updated_at :datetime -# type :string(255) default("ProjectHook") +# type :string default("ProjectHook") # service_id :integer # push_events :boolean default(TRUE), not null # issues_events :boolean default(FALSE), not null diff --git a/app/models/project.rb b/app/models/project.rb index 7e131151513..5579710a476 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -272,6 +272,10 @@ class Project < ActiveRecord::Base query: "%#{query.try(:downcase)}%") end + def search_by_visibility(level) + where(visibility_level: Gitlab::VisibilityLevel.const_get(level.upcase)) + end + def search_by_title(query) where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%") end @@ -468,12 +472,9 @@ class Project < ActiveRecord::Base !external_issue_tracker end - def external_issues_trackers - services.select(&:issue_tracker?).reject(&:default?) - end - def external_issue_tracker - @external_issues_tracker ||= external_issues_trackers.find(&:activated?) + @external_issue_tracker ||= + services.issue_trackers.active.without_defaults.first end def can_have_issues_tracker_id? diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index c3f70d1f972..e10b5529b42 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -23,14 +23,12 @@ # List methods you need to implement to get your CI service # working with GitLab Merge Requests class CiService < Service - def category - :ci - end - + default_value_for :category, 'ci' + def valid_token?(token) self.respond_to?(:token) && self.token.present? && self.token == token end - + def supported_events %w(push) end diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 7aa04309f54..05436cd0f79 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -24,9 +24,7 @@ class GitlabIssueTrackerService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url - def default? - true - end + default_value_for :default, true def to_param 'gitlab' diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index ed201979d39..25045224ce5 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -23,12 +23,10 @@ class IssueTrackerService < Service validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated? - def category - :issue_tracker - end + default_value_for :category, 'issue_tracker' def default? - false + default end def issue_url(iid) diff --git a/app/models/service.rb b/app/models/service.rb index 24f4bf7646e..721273250ea 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -43,6 +43,9 @@ class Service < ActiveRecord::Base validates :project_id, presence: true, unless: Proc.new { |service| service.template? } scope :visible, -> { where.not(type: ['GitlabIssueTrackerService', 'GitlabCiService']) } + scope :issue_trackers, -> { where(category: 'issue_tracker') } + scope :active, -> { where(active: true) } + scope :without_defaults, -> { where(default: false) } scope :push_hooks, -> { where(push_events: true, active: true) } scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) } @@ -51,6 +54,8 @@ class Service < ActiveRecord::Base scope :note_hooks, -> { where(note_events: true, active: true) } scope :build_hooks, -> { where(build_events: true, active: true) } + default_value_for :category, 'common' + def activated? active end @@ -60,7 +65,7 @@ class Service < ActiveRecord::Base end def category - :common + read_attribute(:category).to_sym end def initialize_properties @@ -153,7 +158,7 @@ class Service < ActiveRecord::Base # Returns a hash of the properties that have been assigned a new value since last save, # indicating their original values (attr => original value). - # ActiveRecord does not provide a mechanism to track changes in serialized keys, + # ActiveRecord does not provide a mechanism to track changes in serialized keys, # so we need a specific implementation for service properties. # This allows to track changes to properties set with the accessor methods, # but not direct manipulation of properties hash. @@ -164,7 +169,7 @@ class Service < ActiveRecord::Base def reset_updated_properties @updated_properties = nil end - + def async_execute(data) return unless supported_events.include?(data[:object_kind]) diff --git a/app/models/user.rb b/app/models/user.rb index 592468933ed..4214f01f6a4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -664,7 +664,10 @@ class User < ActiveRecord::Base end def all_emails - [self.email, *self.emails.map(&:email)] + all_emails = [] + all_emails << self.email unless self.temp_oauth_email? + all_emails.concat(self.emails.map(&:email)) + all_emails end def hook_attrs diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index e4edc55bf69..ca8a41d93b8 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -376,10 +376,10 @@ class NotificationService end def reassign_resource_email(target, project, current_user, method) - previous_assignee_id = previous_record(target, "assignee_id") + previous_assignee_id = previous_record(target, 'assignee_id') previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id - recipients = build_recipients(target, project, current_user, [previous_assignee]) + recipients = build_recipients(target, project, current_user, action: :reassign, previous_assignee: previous_assignee) recipients.each do |recipient| mailer.send( @@ -400,22 +400,27 @@ class NotificationService end end - def build_recipients(target, project, current_user, extra_recipients = nil) + def build_recipients(target, project, current_user, action: nil, previous_assignee: nil) recipients = target.participants(current_user) - recipients = recipients.concat(extra_recipients).compact.uniq if extra_recipients - recipients = add_project_watchers(recipients, project) recipients = reject_mention_users(recipients, project) - recipients = reject_muted_users(recipients, project) + # Re-assign is considered as a mention of the new assignee so we add the + # new assignee to the list of recipients after we rejected users with + # the "on mention" notification level + if action == :reassign + recipients << previous_assignee if previous_assignee + recipients << target.assignee + end + + recipients = reject_muted_users(recipients, project) recipients = add_subscribed_users(recipients, target) recipients = reject_unsubscribed_users(recipients, target) recipients.delete(current_user) - recipients = recipients.uniq - recipients + recipients.uniq end def mailer diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index a6820183bee..c94d7ab710f 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -95,7 +95,7 @@ module Projects system_hook_service.execute_hooks_for(@project, :create) unless @project.group - @project.team << [current_user, :master, current_user] + @project.team << [current_user, :master] end @project.import_start if @project.import? diff --git a/app/uploaders/artifact_uploader.rb b/app/uploaders/artifact_uploader.rb index 1b0ae6c0056..1cd93263c9f 100644 --- a/app/uploaders/artifact_uploader.rb +++ b/app/uploaders/artifact_uploader.rb @@ -32,6 +32,10 @@ class ArtifactUploader < CarrierWave::Uploader::Base self.class.storage == CarrierWave::Storage::File end + def filename + file.try(:filename) + end + def exists? file.try(:exists?) end diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml index 3e5cdd2ce4a..f125ecf7be5 100644 --- a/app/views/abuse_reports/new.html.haml +++ b/app/views/abuse_reports/new.html.haml @@ -16,7 +16,7 @@ .form-group = f.label :message, class: 'control-label' .col-sm-10 - = f.text_area :message, class: "form-control js-quick-submit", rows: 2, required: true + = f.text_area :message, class: "form-control js-quick-submit", rows: 2, required: true, value: sanitize(@ref_url) .help-block Explain the problem with this user. If appropriate, provide a link to the relevant issue or comment. diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 9459d8a6295..add9a00138b 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -21,10 +21,10 @@ .form-group = f.label :email, class: "control-label" .col-sm-10 - - if @user.ldap_user? + - if @user.ldap_user? && @user.ldap_email? = f.text_field :email, class: "form-control", required: true, readonly: true %span.help-block.light - Email is read-only for LDAP user + Your email address was automatically set based on the LDAP server. - else - if @user.temp_oauth_email? = f.text_field :email, class: "form-control", required: true, value: nil diff --git a/app/views/projects/artifacts/_tree_directory.html.haml b/app/views/projects/artifacts/_tree_directory.html.haml index 5b87d55efd5..e4b7979949c 100644 --- a/app/views/projects/artifacts/_tree_directory.html.haml +++ b/app/views/projects/artifacts/_tree_directory.html.haml @@ -1,7 +1,9 @@ -%tr{ class: 'tree-item' } +- path_to_directory = browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: directory.path) + +%tr.tree-item{ 'data-link' => path_to_directory} %td.tree-item-file-name = tree_icon('folder', '755', directory.name) %span.str-truncated - = link_to directory.name, browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: directory.path) + = link_to directory.name, path_to_directory %td %td diff --git a/app/views/projects/artifacts/_tree_file.html.haml b/app/views/projects/artifacts/_tree_file.html.haml index 92c1648f726..3dfc09cc495 100644 --- a/app/views/projects/artifacts/_tree_file.html.haml +++ b/app/views/projects/artifacts/_tree_file.html.haml @@ -1,11 +1,11 @@ -%tr{ class: 'tree-item' } +- path_to_file = file_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: file.path) + +%tr.tree-item{ 'data-link' => path_to_file } %td.tree-item-file-name = tree_icon('file', '664', file.name) %span.str-truncated - = file.name + = link_to file.name, path_to_file %td = number_to_human_size(file.metadata[:size], precision: 2) %td - = link_to file_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: file.path), - class: 'btn btn-xs btn-default artifact-download' do - = icon('download') + = number_to_human_size(file.metadata[:zipped], precision: 2) diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index 1add7ef6bfb..b70c776a2b2 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -1,24 +1,32 @@ - page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds' = render 'projects/builds/header_title' -#tree-holder.tree-holder - .gray-content-block.top-block.clearfix - .pull-right - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), - class: 'btn btn-default' do - = icon('download') - Download artifacts archive +.top-block.gray-content-block.clearfix + .pull-right + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), + class: 'btn btn-default' do + = icon('download') + Download artifacts archive -%div.tree-content-holder - .table-holder - %table.table.tree-table.table-striped +.tree-holder + %div.tree-content-holder + %table.table.tree-table %thead %tr %th Name %th Size - %th Download + %th Compressed to = render partial: 'tree_directory', collection: @entry.directories(parent: true), as: :directory = render partial: 'tree_file', collection: @entry.files, as: :file - if @entry.empty? .center Empty + +:javascript + $('.tree-holder').on('click', 'tr[data-link] a', function(e) { + e.stopImmediatePropagation(); + }); + + $('.tree-holder').on('click', 'tr[data-link]', function(e) { + window.location = this.dataset.link; + }); diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index d276e5932d1..76a823d3828 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -1,12 +1,12 @@ - commit = @repository.commit(branch.target) - bar_graph_width_factor = @max_commits > 0 ? 100.0/@max_commits : 0 -- diverging_commit_counts = @repository.diverging_commit_counts(branch) +- diverging_commit_counts = @repository.diverging_commit_counts(branch) - number_commits_behind = diverging_commit_counts[:behind] - number_commits_ahead = diverging_commit_counts[:ahead] %li(class="js-branch-#{branch.name}") %div = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do - .branch-name.str-truncated= branch.name + %span.item-title.str-truncated= branch.name - if branch.name == @repository.root_ref %span.label.label-primary default diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 5d18c0d803a..bbb6944a65a 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -6,7 +6,12 @@ - if can?(current_user, :manage_builds, @project) .pull-left.hidden-xs - if @all_builds.running_or_pending.any? - = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), + data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + = link_to ci_lint_path, class: 'btn btn-default' do + = icon('wrench') + %span CI Lint %ul.nav-links %li{class: ('active' if @scope.nil?)} diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 4d4b410ee29..7f2903589a9 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -11,7 +11,7 @@ = cache(cache_key) do %li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" } .commit-row-title - .commit-title.str-truncated + %span.item-title.str-truncated = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message" - if commit.description? %a.text-expander.js-toggle-button ... diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index 56a7ced1236..399782273d3 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -3,7 +3,7 @@ %li %div = link_to namespace_project_tag_path(@project.namespace, @project, tag.name) do - .tag-name + %span.item-title = icon('tag') = tag.name - if tag.message.present? diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index dbb20347860..8c7f93f93b6 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -17,8 +17,8 @@ .pull-right = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has_tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do %i.fa.fa-trash-o - .tag-name.title - = @tag.name + .title + %span.item-title= @tag.name - if @tag.message.present? %span.light diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index f4cfa29ae56..778b20fb4f2 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -10,7 +10,8 @@ %i.fa.fa-sign-out = image_tag group_icon(group), class: "avatar s46 hidden-xs" - = link_to group.name, group, class: 'group-name' + = link_to group, class: 'group-name' do + %span.item-title= group.name - if group_member as @@ -18,4 +19,3 @@ %div.light #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} - diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 9f4a7098ea2..3092ff54242 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -10,6 +10,9 @@ .value - if issuable.assignee %strong= link_to_member(@project, issuable.assignee, size: 24) + - if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee) + %a.pull-right.cannot-be-merged{href: '#', data: {toggle: 'tooltip'}, title: 'Not allowed to merge'} + = icon('exclamation-triangle') - else .light None diff --git a/app/views/sherlock/transactions/_queries.html.haml b/app/views/sherlock/transactions/_queries.html.haml index b7e0162e80d..b8d93e9ff45 100644 --- a/app/views/sherlock/transactions/_queries.html.haml +++ b/app/views/sherlock/transactions/_queries.html.haml @@ -8,7 +8,7 @@ %tr %th= t('sherlock.time') %th= t('sherlock.query') - %td + %th %tbody - @transaction.sorted_queries.each do |query| %tr diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 849304ee2b6..3bfd781e51d 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -20,7 +20,7 @@ data: { toggle: 'tooltip', placement: 'left', container: 'body' }} = icon('exclamation-circle') - else - = link_to new_abuse_report_path(user_id: @user.id), class: 'btn btn-gray', + = link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referrer), class: 'btn btn-gray', title: 'Report abuse', data: {toggle: 'tooltip', placement: 'left', container: 'body'} do = icon('exclamation-circle') - if current_user |