diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-06-14 12:41:18 +0200 |
---|---|---|
committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-06-14 12:41:18 +0200 |
commit | 7d9e8b04c025278e26904e061e8b0a005cd81ab0 (patch) | |
tree | 82cf4b183228718d99fd8542104047450f5378b3 /app | |
parent | 672aec4a2da36d9ee755156be4a907f4b8d96347 (diff) | |
parent | 066020fcd015ca92397b794342a49a46dd02582c (diff) | |
download | gitlab-ce-7d9e8b04c025278e26904e061e8b0a005cd81ab0.tar.gz |
Merge remote-tracking branch 'origin/master' into environments-and-deployments
Diffstat (limited to 'app')
50 files changed, 322 insertions, 365 deletions
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index e0ca546350b..69d4c4f5dd3 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -162,19 +162,6 @@ $ -> $el.data('placement') || 'bottom' ) - $('.header-logo .home').tooltip( - placement: (_, el) -> - $el = $(el) - if $('.page-with-sidebar').hasClass('page-sidebar-collapsed') then 'right' else 'bottom' - container: 'body' - ) - - $('.page-with-sidebar').tooltip( - selector: '.sidebar-collapsed .nav-sidebar a, .sidebar-collapsed a.sidebar-user' - placement: 'right' - container: 'body' - ) - # Form submitter $('.trigger-submit').on 'change', -> $(@).parents('form').submit() @@ -207,6 +194,7 @@ $ -> $('.navbar-toggle').on 'click', -> $('.header-content .title').toggle() + $('.header-content .header-logo').toggle() $('.header-content .navbar-collapse').toggle() $('.navbar-toggle').toggleClass('active') $('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left") @@ -241,7 +229,6 @@ $ -> $this.attr 'value', $this.val() $sidebarGutterToggle = $('.js-sidebar-toggle') - $navIconToggle = $('.toggle-nav-collapse') $(document) .off 'breakpoint:change' @@ -251,10 +238,6 @@ $ -> if $gutterIcon.hasClass('fa-angle-double-right') $sidebarGutterToggle.trigger('click') - $navIcon = $navIconToggle.find('.fa') - if $navIcon.hasClass('fa-angle-left') - $navIconToggle.trigger('click') - fitSidebarForSize = -> oldBootstrapBreakpoint = bootstrapBreakpoint bootstrapBreakpoint = bp.getBreakpointSize() diff --git a/app/assets/javascripts/issues-bulk-assignment.js.coffee b/app/assets/javascripts/issues-bulk-assignment.js.coffee index 16d023dd391..9dc3529a17f 100644 --- a/app/assets/javascripts/issues-bulk-assignment.js.coffee +++ b/app/assets/javascripts/issues-bulk-assignment.js.coffee @@ -97,13 +97,22 @@ class @IssuableBulkActions $labels = @form.find('.labels-filter input[name="update[label_ids][]"]') $labels.each (k, label) -> - labelIds.push $(label).val() if label + labelIds.push parseInt($(label).val()) if label labelIds ###* - * Just an alias of @getUnmarkedIndeterminedLabels - * @return {Array} Array of labels + * Returns Label IDs that will be removed from issue selection + * @return {Array} Array of labels IDs ### getLabelsToRemove: -> - @getUnmarkedIndeterminedLabels() + result = [] + indeterminatedLabels = @getUnmarkedIndeterminedLabels() + labelsToApply = @getLabelsToApply() + + indeterminatedLabels.map (id) -> + # We need to exclude label IDs that will be applied + # By not doing this will cause issues from selection to not add labels at all + result.push(id) if labelsToApply.indexOf(id) is -1 + + result diff --git a/app/assets/javascripts/logo.js.coffee b/app/assets/javascripts/logo.js.coffee index d14b7139237..9fdc27a9787 100644 --- a/app/assets/javascripts/logo.js.coffee +++ b/app/assets/javascripts/logo.js.coffee @@ -47,4 +47,4 @@ $ -> # Make logo clickable as part of a workaround for Safari visited # link behaviour (See !2690). $('#logo').on 'click', -> - $('#js-shortcuts-home').get(0).click() + Turbolinks.visit('/') diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee index ea4ac52da31..2ce63c16428 100644 --- a/app/assets/javascripts/sidebar.js.coffee +++ b/app/assets/javascripts/sidebar.js.coffee @@ -4,8 +4,6 @@ expanded = 'page-sidebar-expanded' toggleSidebar = -> $('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}") $('header').toggleClass("header-collapsed header-expanded") - $('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left") - $.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' }) setTimeout ( -> niceScrollBars = $('.nicescroll').niceScroll(); @@ -17,10 +15,3 @@ $(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) -> toggleSidebar() ) - -$ -> - size = bp.getBreakpointSize() - - if size is "xs" or size is "sm" - if $('.page-with-sidebar').hasClass(expanded) - toggleSidebar() diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index 2540ff497f2..408d4a68e1e 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -8,34 +8,16 @@ */ @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { .page-with-sidebar { - .header-logo { - background: $color-darker; - a { - color: $color-light; - - h3 { - color: $color-light; - } - } + .collapse-nav a { + color: $color-light; + background: $color; &:hover { - background-color: $color-dark; - a { - color: $white-light; - - h3 { - color: $white-light; - } - } + color: $white-light; } } - .collapse-nav a { - color: $white-light; - background: $color; - } - .sidebar-wrapper { background: $color-darker; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index b8d4233537b..63996ea44f6 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -109,10 +109,8 @@ header { position: relative; height: $header-height; padding-right: 40px; - - @media (max-width: $screen-xs-min) { - padding-left: 40px; - } + padding-left: 30px; + transition-duration: .3s; @media (min-width: $screen-sm-min) { padding-right: 0; @@ -122,9 +120,29 @@ header { margin-top: -5px; } + .header-logo { + position: absolute; + left: 50%; + margin-left: -18px; + top: 7px; + transition-duration: .3s; + z-index: 999; + + &:hover { + cursor: pointer; + } + + @media (max-width: $screen-xs-max) { + right: 25px; + left: auto; + } + } + .title { margin: 0; font-size: 19px; + max-width: 400px; + display: inline-block; line-height: $header-height; font-weight: normal; color: $gl-text-color; @@ -133,6 +151,10 @@ header { vertical-align: top; white-space: nowrap; + @media (max-width: $screen-sm-max) { + max-width: 190px; + } + a { color: $gl-text-color; &:hover { @@ -160,6 +182,10 @@ header { .navbar-collapse { float: right; border-top: none; + + @media (max-width: $screen-xs-max) { + float: none; + } } } @@ -176,17 +202,20 @@ header { margin-left: 0; .header-content { - padding-left: 30px; - transition-duration: .3s; + + @media (min-width: $screen-sm-max) { + padding-left: 30px; + transition-duration: .3s; + } } } -.header-expanded { - margin-left: 0; +.tanuki-shape { + transition: all 0.8s; - .header-content { - margin-left: $sidebar_width; - transition-duration: .3s; + &:hover, &.highlight { + fill: rgb(255, 255, 255); + transition: all 0.1s; } } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index a036799e15a..4de89daeb36 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -1,6 +1,7 @@ @mixin fade($gradient-direction, $rgba, $gradient-color) { visibility: visible; opacity: 1; + z-index: 2; position: absolute; bottom: 12px; width: 43px; @@ -68,6 +69,7 @@ } &.sub-nav { + text-align: center; background-color: $background-color; .container-fluid { @@ -171,7 +173,6 @@ > form { display: inline-block; margin-top: -1px; - margin-bottom: 12px; } .icon-label { @@ -250,6 +251,7 @@ background: $background-color; border-bottom: 1px solid $border-color; transition-duration: .3s; + text-align: center; .container-fluid { position: relative; @@ -352,7 +354,7 @@ .fade-right { @media (min-width: $screen-xs-max) { - right: 67px; + right: 68px; } @media (max-width: $screen-xs-min) { right: 0; diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 06a688690f8..b7ec3f70bfb 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -35,24 +35,11 @@ } .sidebar-wrapper { - .header-logo { - height: $header-height; - padding: 8px 26px; - width: $sidebar_width; - position: fixed; - z-index: 999; - overflow: hidden; - transition-duration: .3s; - - &:hover { - background-color: #eee; - } - } .sidebar-user { padding: 15px 22px; position: fixed; - bottom: 40px; + bottom: 0; width: $sidebar_width; overflow: hidden; transition-duration: .3s; @@ -97,10 +84,10 @@ } a { - text-align: center; - padding: 8px; + width: $sidebar_width; + padding: 7px 15px 7px 23px; font-size: $gl-font-size; - color: $gray; + line-height: 24px; display: block; text-decoration: none; font-weight: normal; @@ -118,10 +105,9 @@ font-size: 16px; } - .nav-link-text { - margin-top: 3px; - font-size: 13px; - line-height: 18px; + i, + svg { + margin-right: 13px; } &.back-link i { @@ -129,6 +115,12 @@ } } } + + .count { + float: right; + padding: 0 8px; + @include border-radius(6px); + } } .sidebar-subnav { @@ -143,11 +135,12 @@ .collapse-nav a { width: $sidebar_width; position: fixed; - bottom: 0; + top: 0; left: 0; - font-size: 13px; + padding: 5px 0; + font-size: 18px; background: transparent; - height: 40px; + height: 50px; text-align: center; line-height: 40px; transition-duration: .3s; @@ -170,25 +163,8 @@ .sidebar-wrapper { width: 0; - .header-logo { - width: 0; - padding: 8px 0; - - a { - padding-left: ($sidebar_collapsed_width - 36) / 2; - - .gitlab-text-container { - display: none; - } - } - } - - #logo { - display: none; - } - .nav-sidebar { - width: $sidebar_collapsed_width; + width: 0; li { width: auto; @@ -203,6 +179,10 @@ .collapse-nav a { width: 0; + + i { + display: none; + } } .sidebar-user { @@ -218,9 +198,8 @@ } .page-sidebar-expanded { - padding-left: $sidebar_width; - @media (max-width: $screen-xs-min) { + @media (max-width: $screen-sm-max) { padding-left: 0; } @@ -241,20 +220,6 @@ } } } - - .layout-nav { - @media (max-width: $screen-xs-min) { - padding-right: 0; - } - - @media (min-width: $screen-xs-min) and (max-width: $screen-md-min) { - padding-right: 90px; - } - - @media (min-width: $screen-md-min) { - padding-right: $sidebar_width; - } - } } .right-sidebar-collapsed { diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 847b2f80bdf..752d8ec8788 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -2,7 +2,7 @@ * Layout */ $sidebar_collapsed_width: 62px; -$sidebar_width: 90px; +$sidebar_width: 220px; $gutter_collapsed_width: 62px; $gutter_width: 290px; $gutter_inner_width: 258px; diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index 131a16dad9b..014b9b43ff2 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -42,7 +42,7 @@ class JwtController < ApplicationController end def authenticate_user(login, password) - user = Gitlab::Auth.find_in_gitlab_or_ldap(login, password) + user = Gitlab::Auth.find_with_user_password(login, password) Gitlab::Auth.rate_limit!(request.ip, success: user.present?, login: login) user end diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index 18ee55c839a..40d1906a53f 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -1,12 +1,13 @@ class Profiles::NotificationsController < Profiles::ApplicationController def show - @user = current_user - @group_notifications = current_user.notification_settings.for_groups - @project_notifications = current_user.notification_settings.for_projects + @user = current_user + @group_notifications = current_user.notification_settings.for_groups + @project_notifications = current_user.notification_settings.for_projects + @global_notification_setting = current_user.global_notification_setting end def update - if current_user.update_attributes(user_params) + if current_user.update_attributes(user_params) && update_notification_settings flash[:notice] = "Notification settings saved" else flash[:alert] = "Failed to save new settings" @@ -16,6 +17,18 @@ class Profiles::NotificationsController < Profiles::ApplicationController end def user_params - params.require(:user).permit(:notification_email, :notification_level) + params.require(:user).permit(:notification_email) + end + + def global_notification_setting_params + params.require(:global_notification_setting).permit(:level) + end + + private + + def update_notification_settings + return true unless global_notification_setting_params + + current_user.global_notification_setting.update_attributes(global_notification_setting_params) end end diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb index 348d6cf4d96..f907d63258b 100644 --- a/app/controllers/projects/git_http_controller.rb +++ b/app/controllers/projects/git_http_controller.rb @@ -43,7 +43,7 @@ class Projects::GitHttpController < Projects::ApplicationController return if project && project.public? && upload_pack? authenticate_or_request_with_http_basic do |login, password| - auth_result = Gitlab::Auth.find(login, password, project: project, ip: request.ip) + auth_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip) if auth_result.type == :ci && upload_pack? @ci = true diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb index 01cbf91c658..00ff1611039 100644 --- a/app/finders/snippets_finder.rb +++ b/app/finders/snippets_finder.rb @@ -51,7 +51,7 @@ class SnippetsFinder snippets = project.snippets.fresh if current_user - if project.team.member?(current_user.id) || current_user.admin? + if project.team.member?(current_user) || current_user.admin? snippets else snippets.public_and_internal diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb index e39548e17e1..3ee3fc74f0c 100644 --- a/app/helpers/branches_helper.rb +++ b/app/helpers/branches_helper.rb @@ -14,4 +14,8 @@ module BranchesHelper ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(branch_name) end + + def project_branches + options_for_select(@project.repository.branch_names, @project.default_branch) + end end diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 39831ce2e48..469accf3142 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -36,13 +36,7 @@ module NavHelper end def nav_header_class - class_name = - if nav_menu_collapsed? - "header-collapsed" - else - "header-expanded" - end - class_name += " with-horizontal-nav" if defined?(nav) && nav + class_name = " with-horizontal-nav" if defined?(nav) && nav class_name end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index b8e64b3890a..50c21fc0d49 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -61,4 +61,23 @@ module NotificationsHelper end end end + + def notification_level_radio_buttons + html = "" + + NotificationSetting.levels.each_key do |level| + level = level.to_sym + next if level == :global + + html << content_tag(:div, class: "radio") do + content_tag(:label, { value: level }) do + radio_button_tag(:"global_notification_setting[level]", level, @global_notification_setting.level.to_sym == level) + + content_tag(:div, level.to_s.capitalize, class: "level-title") + + content_tag(:p, notification_description(level)) + end + end + end + + html.html_safe + end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 747f250ff4f..93905abbee8 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -543,7 +543,7 @@ class Ability def filter_confidential_issues_abilities(user, issue, rules) return rules if user.admin? || !issue.confidential? - unless issue.author == user || issue.assignee == user || issue.project.team.member?(user.id) + unless issue.author == user || issue.assignee == user || issue.project.team.member?(user, Gitlab::Access::REPORTER) rules.delete(:admin_issue) rules.delete(:read_issue) rules.delete(:update_issue) diff --git a/app/models/issue.rb b/app/models/issue.rb index 235922710ad..1bdf9c011b2 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -51,10 +51,18 @@ class Issue < ActiveRecord::Base end def self.visible_to_user(user) - return where(confidential: false) if user.blank? + return where('issues.confidential IS NULL OR issues.confidential IS FALSE') if user.blank? return all if user.admin? - where('issues.confidential = false OR (issues.confidential = true AND (issues.author_id = :user_id OR issues.assignee_id = :user_id OR issues.project_id IN(:project_ids)))', user_id: user.id, project_ids: user.authorized_projects.select(:id)) + where(' + issues.confidential IS NULL + OR issues.confidential IS FALSE + OR (issues.confidential = TRUE + AND (issues.author_id = :user_id + OR issues.assignee_id = :user_id + OR issues.project_id IN(:project_ids)))', + user_id: user.id, + project_ids: user.authorized_projects(Gitlab::Access::REPORTER).select(:id)) end def self.reference_prefix diff --git a/app/models/note.rb b/app/models/note.rb index 585d8c4ad84..58133f1581f 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -88,22 +88,9 @@ class Note < ActiveRecord::Base table = arel_table pattern = "%#{query}%" - found_notes = joins('LEFT JOIN issues ON issues.id = noteable_id'). - where(table[:note].matches(pattern)) - - if as_user - found_notes.where(' - issues.confidential IS NULL - OR issues.confidential IS FALSE - OR (issues.confidential IS TRUE - AND (issues.author_id = :user_id - OR issues.assignee_id = :user_id - OR issues.project_id IN(:project_ids)))', - user_id: as_user.id, - project_ids: as_user.authorized_projects.select(:id)) - else - found_notes.where('issues.confidential IS NULL OR issues.confidential IS FALSE') - end + Note.joins('LEFT JOIN issues ON issues.id = noteable_id'). + where(table[:note].matches(pattern)). + merge(Issue.visible_to_user(as_user)) end end diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb index 17fb15b08df..0ce87968e46 100644 --- a/app/models/notification_setting.rb +++ b/app/models/notification_setting.rb @@ -7,7 +7,6 @@ class NotificationSetting < ActiveRecord::Base belongs_to :source, polymorphic: true validates :user, presence: true - validates :source, presence: true validates :level, presence: true validates :user_id, uniqueness: { scope: [:source_type, :source_id], message: "already exists in source", diff --git a/app/models/project.rb b/app/models/project.rb index be714ea41fd..9930c5bd089 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -148,7 +148,6 @@ class Project < ActiveRecord::Base message: Gitlab::Regex.project_path_regex_message } validates :issues_enabled, :merge_requests_enabled, :wiki_enabled, inclusion: { in: [true, false] } - validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true validates :namespace, presence: true validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :path, scope: :namespace_id @@ -591,10 +590,6 @@ class Project < ActiveRecord::Base update_column(:has_external_issue_tracker, services.external_issue_trackers.any?) end - def can_have_issues_tracker_id? - self.issues_enabled && !self.default_issues_tracker? - end - def build_missing_services services_templates = Service.where(template: true) diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index 1d1780dcfbf..b5c76e4d4fe 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -1,6 +1,4 @@ class BambooService < CiService - include HTTParty - prop_accessor :bamboo_url, :build_key, :username, :password validates :bamboo_url, presence: true, url: true, if: :activated? @@ -61,18 +59,7 @@ class BambooService < CiService end def build_info(sha) - url = URI.join(bamboo_url, "/rest/api/latest/result?label=#{sha}").to_s - - if username.blank? && password.blank? - @response = HTTParty.get(url, verify: false) - else - url << '&os_authType=basic' - auth = { - username: username, - password: password - } - @response = HTTParty.get(url, verify: false, basic_auth: auth) - end + @response = get_path("rest/api/latest/result?label=#{sha}") end def build_page(sha, ref) @@ -80,11 +67,11 @@ class BambooService < CiService if @response.code != 200 || @response['results']['results']['size'] == '0' # If actual build link can't be determined, send user to build summary page. - URI.join(bamboo_url, "/browse/#{build_key}").to_s + URI.join("#{bamboo_url}/", "browse/#{build_key}").to_s else # If actual build link is available, go to build result page. result_key = @response['results']['results']['result']['planResultKey']['key'] - URI.join(bamboo_url, "/browse/#{result_key}").to_s + URI.join("#{bamboo_url}/", "browse/#{result_key}").to_s end end @@ -112,8 +99,27 @@ class BambooService < CiService def execute(data) return unless supported_events.include?(data[:object_kind]) - # Bamboo requires a GET and does not take any data. - url = URI.join(bamboo_url, "/updateAndBuild.action?buildKey=#{build_key}").to_s - self.class.get(url, verify: false) + get_path("updateAndBuild.action?buildKey=#{build_key}") + end + + private + + def build_url(path) + URI.join("#{bamboo_url}/", path).to_s + end + + def get_path(path) + url = build_url(path) + + if username.blank? && password.blank? + HTTParty.get(url, verify: false) + else + url << '&os_authType=basic' + HTTParty.get(url, verify: false, + basic_auth: { + username: username, + password: password + }) + end end end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 6ae9b16d3ce..87ecb3b8b86 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -38,9 +38,9 @@ class IssueTrackerService < Service if enabled_in_gitlab_config self.properties = { title: issues_tracker['title'], - project_url: add_issues_tracker_id(issues_tracker['project_url']), - issues_url: add_issues_tracker_id(issues_tracker['issues_url']), - new_issue_url: add_issues_tracker_id(issues_tracker['new_issue_url']) + project_url: issues_tracker['project_url'], + issues_url: issues_tracker['issues_url'], + new_issue_url: issues_tracker['new_issue_url'] } else self.properties = {} @@ -83,16 +83,4 @@ class IssueTrackerService < Service def issues_tracker Gitlab.config.issues_tracker[to_param] end - - def add_issues_tracker_id(url) - if self.project - id = self.project.issues_tracker_id - - if id - url = url.gsub(":issues_tracker_id", id) - end - end - - url - end end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index b0dcb52eba1..a4a967c9bc9 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -1,6 +1,4 @@ class TeamcityService < CiService - include HTTParty - prop_accessor :teamcity_url, :build_type, :username, :password validates :teamcity_url, presence: true, url: true, if: :activated? @@ -64,15 +62,7 @@ class TeamcityService < CiService end def build_info(sha) - url = URI.join( - teamcity_url, - "/httpAuth/app/rest/builds/branch:unspecified:any,number:#{sha}" - ).to_s - auth = { - username: username, - password: password - } - @response = HTTParty.get(url, verify: false, basic_auth: auth) + @response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,number:#{sha}") end def build_page(sha, ref) @@ -81,14 +71,11 @@ class TeamcityService < CiService if @response.code != 200 # If actual build link can't be determined, # send user to build summary page. - URI.join(teamcity_url, "/viewLog.html?buildTypeId=#{build_type}").to_s + build_url("viewLog.html?buildTypeId=#{build_type}") else # If actual build link is available, go to build result page. built_id = @response['build']['id'] - URI.join( - teamcity_url, - "/viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}" - ).to_s + build_url("viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}") end end @@ -123,8 +110,8 @@ class TeamcityService < CiService branch = Gitlab::Git.ref_name(data[:ref]) - self.class.post( - URI.join(teamcity_url, '/httpAuth/app/rest/buildQueue').to_s, + HTTParty.post( + build_url('httpAuth/app/rest/buildQueue'), body: "<build branchName=\"#{branch}\">"\ "<buildType id=\"#{build_type}\"/>"\ '</build>', @@ -132,4 +119,18 @@ class TeamcityService < CiService basic_auth: auth ) end + + private + + def build_url(path) + URI.join("#{teamcity_url}/", path).to_s + end + + def get_path(path) + HTTParty.get(build_url(path), verify: false, + basic_auth: { + username: username, + password: password + }) + end end diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 70a8bbaba65..e29e854860a 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -131,8 +131,14 @@ class ProjectTeam max_member_access(user.id) == Gitlab::Access::MASTER end - def member?(user_id) - !!find_member(user_id) + def member?(user, min_member_access = nil) + member = !!find_member(user.id) + + if min_member_access + member && max_member_access(user.id) >= min_member_access + else + member + end end def human_max_access(user_id) diff --git a/app/models/user.rb b/app/models/user.rb index e0987e07e1f..a5b3c8afe51 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,6 +10,8 @@ class User < ActiveRecord::Base include CaseSensitivity include TokenAuthenticatable + DEFAULT_NOTIFICATION_LEVEL = :participating + add_authentication_token_field :authentication_token default_value_for :admin, false @@ -99,7 +101,6 @@ class User < ActiveRecord::Base presence: true, uniqueness: { case_sensitive: false } - validates :notification_level, presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :unique_email, if: ->(user) { user.email_changed? } @@ -133,13 +134,6 @@ class User < ActiveRecord::Base # Note: When adding an option, it MUST go on the end of the array. enum project_view: [:readme, :activity, :files] - # Notification level - # Note: When adding an option, it MUST go on the end of the array. - # - # TODO: Add '_prefix: :notification' to enum when update to Rails 5. https://github.com/rails/rails/pull/19813 - # Because user.notification_disabled? is much better than user.disabled? - enum notification_level: [:disabled, :participating, :watch, :global, :mention] - alias_attribute :private_token, :authentication_token delegate :path, to: :namespace, allow_nil: true, prefix: true @@ -411,8 +405,8 @@ class User < ActiveRecord::Base end # Returns projects user is authorized to access. - def authorized_projects - Project.where("projects.id IN (#{projects_union.to_sql})") + def authorized_projects(min_access_level = nil) + Project.where("projects.id IN (#{projects_union(min_access_level).to_sql})") end def viewable_starred_projects @@ -800,6 +794,17 @@ class User < ActiveRecord::Base notification_settings.find_or_initialize_by(source: source) end + # Lazy load global notification setting + # Initializes User setting with Participating level if setting not persisted + def global_notification_setting + return @global_notification_setting if defined?(@global_notification_setting) + + @global_notification_setting = notification_settings.find_or_initialize_by(source: nil) + @global_notification_setting.update_attributes(level: NotificationSetting.levels[DEFAULT_NOTIFICATION_LEVEL]) unless @global_notification_setting.persisted? + + @global_notification_setting + end + def assigned_open_merge_request_count(force: false) Rails.cache.fetch(['users', id, 'assigned_open_merge_request_count'], force: force) do assigned_merge_requests.opened.count @@ -819,11 +824,19 @@ class User < ActiveRecord::Base private - def projects_union - Gitlab::SQL::Union.new([personal_projects.select(:id), - groups_projects.select(:id), - projects.select(:id), - groups.joins(:shared_projects).select(:project_id)]) + def projects_union(min_access_level = nil) + relations = [personal_projects.select(:id), + groups_projects.select(:id), + projects.select(:id), + groups.joins(:shared_projects).select(:project_id)] + + + if min_access_level + scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } } + relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) } + end + + Gitlab::SQL::Union.new(relations) end def ci_projects_union diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 91ca82ed3b7..875a3f4fab6 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -279,10 +279,11 @@ class NotificationService end def users_with_global_level_watch(ids) - User.where( - id: ids, - notification_level: NotificationSetting.levels[:watch] - ).pluck(:id) + NotificationSetting.where( + user_id: ids, + source_type: nil, + level: NotificationSetting.levels[:watch] + ).pluck(:user_id) end # Build a list of users based on project notifcation settings @@ -352,7 +353,9 @@ class NotificationService users = users.reject(&:blocked?) users.reject do |user| - next user.notification_level == level unless project + global_notification_setting = user.global_notification_setting + + next global_notification_setting.level == level unless project setting = user.notification_settings_for(project) @@ -361,13 +364,13 @@ class NotificationService end # reject users who globally set mention notification and has no setting per project/group - next user.notification_level == level unless setting + next global_notification_setting.level == level unless setting # reject users who set mention notification in project next true if setting.level == level # reject users who have mention level in project and disabled in global settings - setting.global? && user.notification_level == level + setting.global? && global_notification_setting.level == level end end @@ -456,7 +459,6 @@ class NotificationService def build_recipients(target, project, current_user, action: nil, previous_assignee: nil) recipients = target.participants(current_user) - recipients = add_project_watchers(recipients, project) recipients = reject_mention_users(recipients, project) diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder index 83c0c6da21b..0404d0728ea 100644 --- a/app/views/dashboard/issues.atom.builder +++ b/app/views/dashboard/issues.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: issues_dashboard_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: issues_dashboard_url, rel: "alternate", type: "text/html" xml.id issues_dashboard_url - xml.updated @issues.first.created_at.xmlschema if @issues.any? + xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any? - xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? + xml << render(partial: 'issues/issue', collection: @issues) if @issues.reorder(nil).any? end diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder index c19671295af..b1628040325 100644 --- a/app/views/groups/issues.atom.builder +++ b/app/views/groups/issues.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: issues_group_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: issues_group_url, rel: "alternate", type: "text/html" xml.id issues_group_url - xml.updated @issues.first.created_at.xmlschema if @issues.any? + xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any? - xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? + xml << render(partial: 'issues/issue', collection: @issues) if @issues.reorder(nil).any? end diff --git a/app/views/issues/_issue.atom.builder b/app/views/issues/_issue.atom.builder index 68a2d19e58d..96831874144 100644 --- a/app/views/issues/_issue.atom.builder +++ b/app/views/issues/_issue.atom.builder @@ -5,10 +5,28 @@ xml.entry do xml.updated issue.created_at.xmlschema xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email)) - xml.author do |author| + xml.author do xml.name issue.author_name xml.email issue.author_email end xml.summary issue.title + xml.description issue.description if issue.description + xml.milestone issue.milestone.title if issue.milestone + xml.due_date issue.due_date if issue.due_date + + unless issue.labels.empty? + xml.labels do + issue.labels.each do |label| + xml.label label.name + end + end + end + + if issue.assignee + xml.assignee do + xml.name issue.assignee.name + xml.email issue.assignee.email + end + end end diff --git a/app/views/layouts/_collapse_button.html.haml b/app/views/layouts/_collapse_button.html.haml index 2ed51d87ca1..e4fab897377 100644 --- a/app/views/layouts/_collapse_button.html.haml +++ b/app/views/layouts/_collapse_button.html.haml @@ -1,4 +1 @@ -- if nav_menu_collapsed? - = link_to icon('angle-right'), '#', class: 'toggle-nav-collapse', title: "Open/Close" -- else - = link_to icon('angle-left'), '#', class: 'toggle-nav-collapse', title: "Open/Close" += link_to icon('bars'), '#', class: 'toggle-nav-collapse', title: "Open/Close" diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 261038ef940..f89e8582792 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,9 +1,5 @@ -.page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" } +.page-with-sidebar.page-sidebar-collapsed{ class: "#{page_gutter_class}" } .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } - = link_to root_path, class: 'gitlab-text-container-link', title: 'Dashboard', id: 'js-shortcuts-home' do - .header-logo - #logo - = brand_header_logo - if defined?(sidebar) && sidebar = render "layouts/nav/#{sidebar}" @@ -16,7 +12,9 @@ = render partial: 'layouts/collapse_button' - if current_user = link_to current_user, class: 'sidebar-user', title: "Profile", data: {user: current_user.username} do - = image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s46' + = image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s36' + .username + = current_user.username - if defined?(nav) && nav .layout-nav .container-fluid diff --git a/app/views/layouts/ci/_page.html.haml b/app/views/layouts/ci/_page.html.haml index a13241bebee..2e56d0ac6a3 100644 --- a/app/views/layouts/ci/_page.html.haml +++ b/app/views/layouts/ci/_page.html.haml @@ -1,12 +1,6 @@ .page-with-sidebar{ class: page_sidebar_class } = render "layouts/broadcast" .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } - .header-logo - %a#logo - = brand_header_logo - = link_to root_path, class: 'gitlab-text-container-link', title: 'Dashboard', id: 'js-shortcuts-home' do - .gitlab-text-container - %h3 GitLab - if defined?(sidebar) && sidebar = render "layouts/ci/#{sidebar}" diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index c33740e23fa..ad30a367fc5 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -1,4 +1,4 @@ -%header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } +%header.navbar.navbar-fixed-top.navbar-gitlab.header-collapsed{ class: nav_header_class } %div{ class: fluid_layout ? "container-fluid" : "container-fluid" } .header-content %button.side-nav-toggle{type: 'button'} @@ -50,6 +50,10 @@ %h1.title= title + .header-logo + #logo + = brand_header_logo + = yield :header_content = render 'shared/outdated_browser' diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index de2276e75e4..f292730fe45 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -2,102 +2,106 @@ = nav_link(controller: :dashboard, html_options: {class: 'home'}) do = link_to admin_root_path, title: 'Overview' do = icon('dashboard fw') - .nav-link-text + %span Overview = nav_link(controller: [:admin, :projects]) do = link_to admin_namespaces_projects_path, title: 'Projects' do = icon('cube fw') - .nav-link-text + %span Projects = nav_link(controller: :users) do = link_to admin_users_path, title: 'Users' do = icon('user fw') - .nav-link-text + %span Users = nav_link(controller: :groups) do = link_to admin_groups_path, title: 'Groups' do = icon('group fw') - .nav-link-text + %span Groups = nav_link(controller: :deploy_keys) do = link_to admin_deploy_keys_path, title: 'Deploy Keys' do = icon('key fw') - .nav-link-text + %span Deploy Keys = nav_link path: ['runners#index', 'runners#show'] do = link_to admin_runners_path, title: 'Runners' do = icon('cog fw') - .nav-link-text + %span Runners + %span.count= number_with_delimiter(Ci::Runner.count(:all)) = nav_link path: 'builds#index' do = link_to admin_builds_path, title: 'Builds' do = icon('link fw') - .nav-link-text + %span Builds + %span.count= number_with_delimiter(Ci::Build.count(:all)) = nav_link(controller: :logs) do = link_to admin_logs_path, title: 'Logs' do = icon('file-text fw') - .nav-link-text + %span Logs = nav_link(controller: :health_check) do = link_to admin_health_check_path, title: 'Health Check' do = icon('medkit fw') - .nav-link-text + %span Health Check = nav_link(controller: :broadcast_messages) do = link_to admin_broadcast_messages_path, title: 'Messages' do = icon('bullhorn fw') - .nav-link-text + %span Messages = nav_link(controller: :hooks) do = link_to admin_hooks_path, title: 'Hooks' do = icon('external-link fw') - .nav-link-text + %span Hooks = nav_link(controller: :background_jobs) do = link_to admin_background_jobs_path, title: 'Background Jobs' do = icon('cog fw') - .nav-link-text + %span Background Jobs = nav_link(controller: :appearances) do = link_to admin_appearances_path, title: 'Appearances' do = icon('image') - .nav-link-text + %span Appearance = nav_link(controller: :applications) do = link_to admin_applications_path, title: 'Applications' do = icon('cloud fw') - .nav-link-text + %span Applications = nav_link(controller: :services) do = link_to admin_application_settings_services_path, title: 'Service Templates' do = icon('copy fw') - .nav-link-text + %span Service Templates = nav_link(controller: :labels) do = link_to admin_labels_path, title: 'Labels' do = icon('tags fw') - .nav-link-text + %span Labels = nav_link(controller: :abuse_reports) do = link_to admin_abuse_reports_path, title: "Abuse Reports" do = icon('exclamation-circle fw') - .nav-link-text + %span Abuse Reports + %span.count= number_with_delimiter(AbuseReport.count(:all)) - if askimet_enabled? = nav_link(controller: :spam_logs) do = link_to admin_spam_logs_path, title: "Spam Logs" do = icon('exclamation-triangle fw') - .nav-link-text + %span Spam Logs + %span.count= number_with_delimiter(SpamLog.count(:all)) = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = link_to admin_application_settings_path, title: 'Settings' do = icon('cogs fw') - .nav-link-text + %span Settings diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index b73fde7797f..18cae5bf87f 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -2,50 +2,53 @@ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do = navbar_icon('project') - .nav-link-text + %span Projects = nav_link(controller: :todos) do = link_to dashboard_todos_path, title: 'Todos' do = icon('bell fw') - .nav-link-text + %span Todos + %span.count= number_with_delimiter(todos_pending_count) = nav_link(path: 'dashboard#activity') do = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do = navbar_icon('activity') - .nav-link-text + %span Activity = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do = link_to dashboard_groups_path, title: 'Groups' do = navbar_icon('group') - .nav-link-text + %span Groups = nav_link(controller: 'dashboard/milestones') do = link_to dashboard_milestones_path, title: 'Milestones' do = navbar_icon('milestones') - .nav-link-text + %span Milestones = nav_link(path: 'dashboard#issues') do = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do = navbar_icon('issues') - .nav-link-text + %span Issues + %span.count= number_with_delimiter(current_user.assigned_issues.opened.count) = nav_link(path: 'dashboard#merge_requests') do = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do = navbar_icon('mr') - .nav-link-text + %span Merge Requests + %span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count) = nav_link(controller: :snippets) do = link_to dashboard_snippets_path, title: 'Snippets' do = icon('clipboard fw') - .nav-link-text + %span Snippets = nav_link(controller: :help) do = link_to help_path, title: 'Help' do = icon('question-circle fw') - .nav-link-text + %span Help = nav_link(html_options: {class: profile_tab_class}) do = link_to profile_path, title: 'Profile Settings', data: {placement: 'bottom'} do = icon('user fw') - .nav-link-text + %span Profile Settings diff --git a/app/views/layouts/nav/_explore.html.haml b/app/views/layouts/nav/_explore.html.haml index 46fcf1545f2..3b40006a0cc 100644 --- a/app/views/layouts/nav/_explore.html.haml +++ b/app/views/layouts/nav/_explore.html.haml @@ -2,20 +2,20 @@ = nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do = link_to explore_root_path, title: 'Projects' do = icon('bookmark fw') - .nav-link-text + %span Projects = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do = link_to explore_groups_path, title: 'Groups' do = icon('group fw') - .nav-link-text + %span Groups = nav_link(controller: :snippets) do = link_to explore_snippets_path, title: 'Snippets' do = icon('clipboard fw') - .nav-link-text + %span Snippets = nav_link(controller: :help) do = link_to help_path, title: 'Help' do = icon('question-circle fw') - .nav-link-text + %span Help diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 9cbee0aa363..66361a644dd 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -5,36 +5,30 @@ .fade-left = nav_link(path: 'groups#show', html_options: {class: 'home'}) do = link_to group_path(@group), title: 'Home' do - = navbar_icon('group') %span Group = nav_link(path: 'groups#activity') do = link_to activity_group_path(@group), title: 'Activity' do - = navbar_icon('activity') %span Activity = nav_link(controller: [:group, :milestones]) do = link_to group_milestones_path(@group), title: 'Milestones' do - = navbar_icon('milestones') %span Milestones = nav_link(path: 'groups#issues') do = link_to issues_group_path(@group), title: 'Issues' do - = navbar_icon('issues') %span Issues - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute %span.badge.count= number_with_delimiter(issues.count) = nav_link(path: 'groups#merge_requests') do = link_to merge_requests_group_path(@group), title: 'Merge Requests' do - = navbar_icon('mr') %span Merge Requests - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute %span.badge.count= number_with_delimiter(merge_requests.count) = nav_link(controller: [:group_members]) do = link_to group_group_members_path(@group), title: 'Members' do - = navbar_icon('members') %span Members .fade-right diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index 09d9f0184be..d4b1f477f3f 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -2,51 +2,41 @@ .fade-left = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = link_to profile_path, title: 'Profile Settings' do - = icon('user fw') %span Profile = nav_link(controller: [:accounts, :two_factor_auths]) do = link_to profile_account_path, title: 'Account' do - = icon('gear fw') %span Account - if current_application_settings.user_oauth_applications? = nav_link(controller: 'oauth/applications') do = link_to applications_profile_path, title: 'Applications' do - = icon('cloud fw') %span Applications = nav_link(controller: :emails) do = link_to profile_emails_path, title: 'Emails' do - = icon('envelope-o fw') %span Emails - unless current_user.ldap_user? = nav_link(controller: :passwords) do = link_to edit_profile_password_path, title: 'Password' do - = icon('lock fw') %span Password = nav_link(controller: :notifications) do = link_to profile_notifications_path, title: 'Notifications' do - = icon('inbox fw') %span Notifications = nav_link(controller: :keys) do = link_to profile_keys_path, title: 'SSH Keys' do - = icon('key fw') %span SSH Keys = nav_link(controller: :preferences) do = link_to profile_preferences_path, title: 'Preferences' do - -# TODO (rspeicher): Better icon? - = icon('image fw') %span Preferences = nav_link(path: 'profiles#audit_log') do = link_to audit_log_profile_path, title: 'Audit Log' do - = icon('history fw') %span Audit Log .fade-right diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 79cc5c02888..53d1fcc30a6 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -24,48 +24,41 @@ .fade-left = nav_link(path: 'projects#show', html_options: {class: 'home'}) do = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do - = navbar_icon('project') %span Project = nav_link(path: 'projects#activity') do = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do - = 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 - = icon('code fw') %span Code - if project_nav_tab? :pipelines = nav_link(controller: :pipelines) do = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do - = navbar_icon('pipelines') %span Pipelines - if project_nav_tab? :container_registry = nav_link(controller: %w(container_registry)) do = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do - = icon('hdd-o fw') %span Registry - if project_nav_tab? :graphs = nav_link(controller: %w(graphs)) do = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do - = icon('area-chart fw') %span Graphs - if project_nav_tab? :issues = 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 Issues - if @project.default_issues_tracker? @@ -74,7 +67,6 @@ - if project_nav_tab? :merge_requests = nav_link(controller: :merge_requests) do = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do - = navbar_icon('mr') %span Merge Requests %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) @@ -82,14 +74,12 @@ - if project_nav_tab? :wiki = nav_link(controller: :wikis) do = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do - = navbar_icon('wiki') %span Wiki - if project_nav_tab? :snippets = nav_link(controller: :snippets) do = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do - = icon('clipboard fw') %span Snippets diff --git a/app/views/profiles/notifications/_group_settings.html.haml b/app/views/profiles/notifications/_group_settings.html.haml index 89ae7ffda2b..f0cf82afe83 100644 --- a/app/views/profiles/notifications/_group_settings.html.haml +++ b/app/views/profiles/notifications/_group_settings.html.haml @@ -1,7 +1,7 @@ %li.notification-list-item %span.notification.fa.fa-holder.append-right-5 - if setting.global? - = notification_icon(current_user.notification_level) + = notification_icon(current_user.global_notification_setting.level) - else = notification_icon(setting.level) diff --git a/app/views/profiles/notifications/_project_settings.html.haml b/app/views/profiles/notifications/_project_settings.html.haml index 17c097154da..e0fad555c09 100644 --- a/app/views/profiles/notifications/_project_settings.html.haml +++ b/app/views/profiles/notifications/_project_settings.html.haml @@ -1,7 +1,7 @@ %li.notification-list-item %span.notification.fa.fa-holder.append-right-5 - if setting.global? - = notification_icon(current_user.notification_level) + = notification_icon(current_user.global_notification_setting.level) - else = notification_icon(setting.level) diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml index 7696f112bb3..f2659ac14b5 100644 --- a/app/views/profiles/notifications/show.html.haml +++ b/app/views/profiles/notifications/show.html.haml @@ -26,33 +26,7 @@ = f.select :notification_email, @user.all_emails, { include_blank: false }, class: "select2" .form-group = f.label :notification_level, class: 'label-light' - .radio - = f.label :notification_level, value: :disabled do - = f.radio_button :notification_level, :disabled - .level-title - Disabled - %p You will not get any notifications via email - - .radio - = f.label :notification_level, value: :mention do - = f.radio_button :notification_level, :mention - .level-title - On Mention - %p You will receive notifications only for comments in which you were @mentioned - - .radio - = f.label :notification_level, value: :participating do - = f.radio_button :notification_level, :participating - .level-title - Participating - %p You will only receive notifications from related resources (e.g. from your commits or assigned issues) - - .radio - = f.label :notification_level, value: :watch do - = f.radio_button :notification_level, :watch - .level-title - Watch - %p You will receive notifications for any activity + = notification_level_radio_buttons .prepend-top-default = f.submit 'Update settings', class: "btn btn-create" diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml index 44ef1fdbbe3..d9b800a4ded 100644 --- a/app/views/projects/commit/_change.html.haml +++ b/app/views/projects/commit/_change.html.haml @@ -17,7 +17,7 @@ .form-group.branch = label_tag 'target_branch', target_label, class: 'control-label' .col-sm-10 - = select_tag "target_branch", grouped_options_refs, class: "select2 select2-sm js-target-branch" + = select_tag "target_branch", project_branches, class: "select2 select2-sm js-target-branch" - if can?(current_user, :push_code, @project) .js-create-merge-request-container .checkbox diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml index 75f36579b11..d8075371853 100644 --- a/app/views/projects/issues/_merge_requests.html.haml +++ b/app/views/projects/issues/_merge_requests.html.haml @@ -24,8 +24,6 @@ MERGED - elsif merge_request.closed? CLOSED - %li - = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count} - if @closed_by_merge_requests.present? %li = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count} diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml index b9bb6fe559d..c6fc499a7b8 100644 --- a/app/views/projects/issues/_related_branches.html.haml +++ b/app/views/projects/issues/_related_branches.html.haml @@ -6,7 +6,7 @@ %li - sha = @project.repository.find_branch(branch).target - pipeline = @project.pipeline(sha, branch) if sha - - if ci_copipelinemmit + - if pipeline %span.related-branch-ci-status = render_pipeline_status(pipeline) %span.related-branch-info diff --git a/app/views/projects/issues/index.atom.builder b/app/views/projects/issues/index.atom.builder index 7ad7c9c87e8..36957560de0 100644 --- a/app/views/projects/issues/index.atom.builder +++ b/app/views/projects/issues/index.atom.builder @@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear xml.link href: namespace_project_issues_url(@project.namespace, @project, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: namespace_project_issues_url(@project.namespace, @project), rel: "alternate", type: "text/html" xml.id namespace_project_issues_url(@project.namespace, @project) - xml.updated @issues.first.created_at.xmlschema if @issues.any? + xml.updated @issues.first.created_at.xmlschema if @issues.reorder(nil).any? - xml << render(partial: 'issues/issue', collection: @issues) if @issues.any? + xml << render(partial: 'issues/issue', collection: @issues) if @issues.reorder(nil).any? end diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml index 8374cb4223d..9356608f318 100644 --- a/app/views/projects/pipelines/_head.html.haml +++ b/app/views/projects/pipelines/_head.html.haml @@ -5,18 +5,15 @@ = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do %span Pipelines - %span.badge.count.ci_counter= number_with_delimiter(@project.pipelines.running_or_pending.count) - if project_nav_tab? :builds = nav_link(controller: %w(builds)) do = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do %span Builds - %span.badge.count.builds_counter= number_with_delimiter(@project.running_or_pending_build_count) - if project_nav_tab? :environments = nav_link(controller: %w(environments)) do = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do %span Environments - %span.badge.count.environments_counter= number_with_delimiter(@project.environments.count) diff --git a/app/views/shared/_merge_requests.html.haml b/app/views/shared/_merge_requests.html.haml index e74fc36c797..ca3178395c1 100644 --- a/app/views/shared/_merge_requests.html.haml +++ b/app/views/shared/_merge_requests.html.haml @@ -1,4 +1,4 @@ -- if @merge_requests.any? +- if @merge_requests.reorder(nil).any? - @merge_requests.group_by(&:target_project).each do |group| .panel.panel-default.panel-small - project = group[0] diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 17e2a7e9290..c30bdb0ae91 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -35,13 +35,13 @@ .clearfix .error-alert -- if issuable.is_a?(Issue) && !issuable.project.private? +- if issuable.is_a?(Issue) .form-group .col-sm-offset-2.col-sm-10 .checkbox = f.label :confidential do = f.check_box :confidential - This issue is confidential and should only be visible to team members + This issue is confidential and should only be visible to team members with at least Reporter access. - if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project) - has_due_date = issuable.has_attribute?(:due_date) |