summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/behaviors/autosize.js23
-rw-r--r--app/assets/javascripts/monitoring/components/monitoring_column.vue2
-rw-r--r--app/assets/javascripts/users_select.js2
-rw-r--r--app/controllers/projects/issues_controller.rb2
-rw-r--r--app/finders/labels_finder.rb7
-rw-r--r--app/finders/users_finder.rb4
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/form_helper.rb16
-rw-r--r--app/helpers/groups_helper.rb5
-rw-r--r--app/helpers/search_helper.rb12
-rw-r--r--app/models/ci/build.rb7
-rw-r--r--app/models/concerns/issuable.rb8
-rw-r--r--app/models/concerns/sortable.rb23
-rw-r--r--app/models/forked_project_link.rb4
-rw-r--r--app/models/merge_request.rb10
-rw-r--r--app/models/project.rb6
-rw-r--r--app/policies/base_policy.rb7
-rw-r--r--app/policies/global_policy.rb14
-rw-r--r--app/policies/user_policy.rb7
-rw-r--r--app/services/delete_merged_branches_service.rb2
-rw-r--r--app/services/merge_requests/merge_service.rb8
-rw-r--r--app/services/quick_actions/interpret_service.rb72
-rw-r--r--app/views/groups/edit.html.haml15
-rw-r--r--app/views/layouts/header/_default.html.haml5
-rw-r--r--app/views/profiles/preferences/show.html.haml35
-rw-r--r--app/views/projects/boards/components/sidebar/_assignee.html.haml5
-rw-r--r--app/views/projects/pipelines/charts.html.haml4
-rw-r--r--app/views/projects/pipelines/charts/_overall.haml16
-rw-r--r--app/views/projects/pipelines/charts/_pipeline_times.haml2
-rw-r--r--app/views/projects/pipelines/charts/_pipelines.haml12
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml9
-rw-r--r--app/views/shared/issuable/form/_metadata_issue_assignee.html.haml2
33 files changed, 224 insertions, 128 deletions
diff --git a/app/assets/javascripts/behaviors/autosize.js b/app/assets/javascripts/behaviors/autosize.js
index 3bea460dcc6..e00af4b2fa8 100644
--- a/app/assets/javascripts/behaviors/autosize.js
+++ b/app/assets/javascripts/behaviors/autosize.js
@@ -1,23 +1,8 @@
import autosize from 'vendor/autosize';
-$(() => {
- const $fields = $('.js-autosize');
+document.addEventListener('DOMContentLoaded', () => {
+ const autosizeEls = document.querySelectorAll('.js-autosize');
- $fields.on('autosize:resized', function resized() {
- const $field = $(this);
- $field.data('height', $field.outerHeight());
- });
-
- $fields.on('resize.autosize', function resize() {
- const $field = $(this);
- if ($field.data('height') !== $field.outerHeight()) {
- $field.data('height', $field.outerHeight());
- autosize.destroy($field);
- $field.css('max-height', window.outerHeight);
- }
- });
-
- autosize($fields);
- autosize.update($fields);
- $fields.css('resize', 'vertical');
+ autosize(autosizeEls);
+ autosize.update(autosizeEls);
});
diff --git a/app/assets/javascripts/monitoring/components/monitoring_column.vue b/app/assets/javascripts/monitoring/components/monitoring_column.vue
index 4f4792877ee..e933634643b 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_column.vue
+++ b/app/assets/javascripts/monitoring/components/monitoring_column.vue
@@ -104,7 +104,7 @@
}
this.data = query.result[0].values;
this.unitOfDisplay = query.unit || 'N/A';
- this.yAxisLabel = this.columnData.y_axis || 'Values';
+ this.yAxisLabel = this.columnData.y_label || 'Values';
this.legendTitle = query.legend || 'Average';
this.graphWidth = this.$refs.baseSvg.clientWidth -
this.margin.left - this.margin.right;
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index 46efdcf4202..5728afb4c59 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -206,8 +206,6 @@ function UsersSelect(currentUser, els) {
return $dropdown.glDropdown({
showMenuAbove: showMenuAbove,
data: function(term, callback) {
- var isAuthorFilter;
- isAuthorFilter = $('.js-author-search');
return _this.users(term, options, function(users) {
// GitLabDropdownFilter returns this.instance
// GitLabDropdownRemote returns this.options.instance
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index ca483c105b6..54f108353cd 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -227,7 +227,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue
return @issue if defined?(@issue)
# The Sortable default scope causes performance issues when used with find_by
- @noteable = @issue ||= @project.issues.where(iid: params[:id]).reorder(nil).take!
+ @noteable = @issue ||= @project.issues.find_by!(iid: params[:id])
return render_404 unless can?(current_user, :read_issue, @issue)
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index 042d792dada..ce432ddbfe6 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -83,7 +83,12 @@ class LabelsFinder < UnionFinder
def projects
return @projects if defined?(@projects)
- @projects = skip_authorization ? Project.all : ProjectsFinder.new(current_user: current_user).execute
+ @projects = if skip_authorization
+ Project.all
+ else
+ ProjectsFinder.new(params: { non_archived: true }, current_user: current_user).execute
+ end
+
@projects = @projects.in_namespace(params[:group_id]) if group?
@projects = @projects.where(id: params[:project_ids]) if projects?
@projects = @projects.reorder(nil)
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index dbd50d1db7c..07deceb827b 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -60,13 +60,13 @@ class UsersFinder
end
def by_external_identity(users)
- return users unless current_user.admin? && params[:extern_uid] && params[:provider]
+ return users unless current_user&.admin? && params[:extern_uid] && params[:provider]
users.joins(:identities).merge(Identity.with_extern_uid(params[:provider], params[:extern_uid]))
end
def by_external(users)
- return users = users.where.not(external: true) unless current_user.admin?
+ return users = users.where.not(external: true) unless current_user&.admin?
return users unless params[:external]
users.external
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 7be8e3b96cf..1c165700b19 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -298,10 +298,6 @@ module ApplicationHelper
end
end
- def can_toggle_new_nav?
- Rails.env.development?
- end
-
def show_new_nav?
cookies["new_nav"] == "true"
end
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index 8ceb5c36bda..9247b1f72de 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -16,8 +16,8 @@ module FormHelper
end
end
- def issue_dropdown_options(issuable, has_multiple_assignees = true)
- options = {
+ def issue_assignees_dropdown_options
+ {
toggle_class: 'js-user-search js-assignee-search js-multiselect js-save-user-data',
title: 'Select assignee',
filter: true,
@@ -27,8 +27,8 @@ module FormHelper
first_user: current_user&.username,
null_user: true,
current_user: true,
- project_id: issuable.project.try(:id),
- field_name: "#{issuable.class.model_name.param_key}[assignee_ids][]",
+ project_id: @project.id,
+ field_name: 'issue[assignee_ids][]',
default_label: 'Unassigned',
'max-select': 1,
'dropdown-header': 'Assignee',
@@ -38,13 +38,5 @@ module FormHelper
current_user_info: current_user.to_json(only: [:id, :name])
}
}
-
- if has_multiple_assignees
- options[:title] = 'Select assignee(s)'
- options[:data][:'dropdown-header'] = 'Assignee(s)'
- options[:data].delete(:'max-select')
- end
-
- options
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index af0b3e9c5bc..8cd61f738e1 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -58,6 +58,11 @@ module GroupsHelper
IssuesFinder.new(current_user, group_id: group.id).execute
end
+ def remove_group_message(group)
+ _("You are going to remove %{group_name}.\nRemoved groups CANNOT be restored!\nAre you ABSOLUTELY sure?") %
+ { group_name: group.name }
+ end
+
private
def group_title_link(group, hidable: false)
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 8f15904f068..f39a3bb55a8 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -126,6 +126,18 @@ module SearchHelper
search_path(options)
end
+ def search_filter_input_options(type)
+ {
+ id: "filtered-search-#{type}",
+ placeholder: 'Search or filter results...',
+ data: {
+ 'project-id' => @project.id,
+ 'username-params' => @users.to_json(only: [:id, :username]),
+ 'base-endpoint' => namespace_project_path(@project.namespace, @project)
+ }
+ }
+ end
+
# Sanitize a HTML field for search display. Most tags are stripped out and the
# maximum length is set to 200 characters.
def search_md_sanitize(object, field)
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index a300536532b..2e7a80d308b 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -176,9 +176,12 @@ module Ci
# * Lowercased
# * Anything not matching [a-z0-9-] is replaced with a -
# * Maximum length is 63 bytes
+ # * First/Last Character is not a hyphen
def ref_slug
- slugified = ref.to_s.downcase
- slugified.gsub(/[^a-z0-9]/, '-')[0..62]
+ ref.to_s
+ .downcase
+ .gsub(/[^a-z0-9]/, '-')[0..62]
+ .gsub(/(\A-+|-+\z)/, '')
end
# Variables whose value does not depend on environment
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index d178ee4422b..41c8b525273 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -102,6 +102,14 @@ module Issuable
def locking_enabled?
title_changed? || description_changed?
end
+
+ def allows_multiple_assignees?
+ false
+ end
+
+ def has_multiple_assignees?
+ assignees.count > 1
+ end
end
module ClassMethods
diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb
index a155a064032..fdacfa5a194 100644
--- a/app/models/concerns/sortable.rb
+++ b/app/models/concerns/sortable.rb
@@ -5,6 +5,25 @@
module Sortable
extend ActiveSupport::Concern
+ module DropDefaultScopeOnFinders
+ # Override these methods to drop the `ORDER BY id DESC` default scope.
+ # See http://dba.stackexchange.com/a/110919 for why we do this.
+ %i[find find_by find_by!].each do |meth|
+ define_method meth do |*args, &block|
+ return super(*args, &block) if block
+
+ unordered_relation = unscope(:order)
+
+ # We cannot simply call `meth` on `unscope(:order)`, since that is also
+ # an instance of the same relation class this module is included into,
+ # which means we'd get infinite recursion.
+ # We explicitly use the original implementation to prevent this.
+ original_impl = method(__method__).super_method.unbind
+ original_impl.bind(unordered_relation).call(*args)
+ end
+ end
+ end
+
included do
# By default all models should be ordered
# by created_at field starting from newest
@@ -18,6 +37,10 @@ module Sortable
scope :order_updated_asc, -> { reorder(updated_at: :asc) }
scope :order_name_asc, -> { reorder(name: :asc) }
scope :order_name_desc, -> { reorder(name: :desc) }
+
+ # All queries (relations) on this model are instances of this `relation_klass`.
+ relation_klass = relation_delegate_class(ActiveRecord::Relation)
+ relation_klass.prepend DropDefaultScopeOnFinders
end
module ClassMethods
diff --git a/app/models/forked_project_link.rb b/app/models/forked_project_link.rb
index 36cf7ad6a28..8d35864eff6 100644
--- a/app/models/forked_project_link.rb
+++ b/app/models/forked_project_link.rb
@@ -1,4 +1,4 @@
class ForkedProjectLink < ActiveRecord::Base
- belongs_to :forked_to_project, class_name: 'Project'
- belongs_to :forked_from_project, class_name: 'Project'
+ belongs_to :forked_to_project, -> { where.not(pending_delete: true) }, class_name: 'Project'
+ belongs_to :forked_from_project, -> { where.not(pending_delete: true) }, class_name: 'Project'
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index c099d731082..808212c780c 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -197,11 +197,19 @@ class MergeRequest < ActiveRecord::Base
}
end
- # This method is needed for compatibility with issues to not mess view and other code
+ # These method are needed for compatibility with issues to not mess view and other code
def assignees
Array(assignee)
end
+ def assignee_ids
+ Array(assignee_id)
+ end
+
+ def assignee_ids=(ids)
+ write_attribute(:assignee_id, ids.last)
+ end
+
def assignee_or_author?(user)
author_id == user.id || assignee_id == user.id
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 241e7e60dd2..8e9e42d28ab 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -815,7 +815,7 @@ class Project < ActiveRecord::Base
end
def ci_service
- @ci_service ||= ci_services.reorder(nil).find_by(active: true)
+ @ci_service ||= ci_services.find_by(active: true)
end
def deployment_services
@@ -823,7 +823,7 @@ class Project < ActiveRecord::Base
end
def deployment_service
- @deployment_service ||= deployment_services.reorder(nil).find_by(active: true)
+ @deployment_service ||= deployment_services.find_by(active: true)
end
def monitoring_services
@@ -831,7 +831,7 @@ class Project < ActiveRecord::Base
end
def monitoring_service
- @monitoring_service ||= monitoring_services.reorder(nil).find_by(active: true)
+ @monitoring_service ||= monitoring_services.find_by(active: true)
end
def jira_tracker?
diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb
index 191c2e78a08..a605a3457c8 100644
--- a/app/policies/base_policy.rb
+++ b/app/policies/base_policy.rb
@@ -1,6 +1,8 @@
require_dependency 'declarative_policy'
class BasePolicy < DeclarativePolicy::Base
+ include Gitlab::CurrentSettings
+
desc "User is an instance admin"
with_options scope: :user, score: 0
condition(:admin) { @user&.admin? }
@@ -10,4 +12,9 @@ class BasePolicy < DeclarativePolicy::Base
with_options scope: :user, score: 0
condition(:can_create_group) { @user&.can_create_group }
+
+ desc "The application is restricted from public visibility"
+ condition(:restricted_public_level, scope: :global) do
+ current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC)
+ end
end
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index 535faa922dd..55eefa76d3f 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -11,10 +11,16 @@ class GlobalPolicy < BasePolicy
with_options scope: :user, score: 0
condition(:access_locked) { @user.access_locked? }
- rule { anonymous }.prevent_all
+ rule { anonymous }.policy do
+ prevent :log_in
+ prevent :access_api
+ prevent :access_git
+ prevent :receive_notifications
+ prevent :use_quick_actions
+ prevent :create_group
+ end
rule { default }.policy do
- enable :read_users_list
enable :log_in
enable :access_api
enable :access_git
@@ -37,4 +43,8 @@ class GlobalPolicy < BasePolicy
rule { access_locked }.policy do
prevent :log_in
end
+
+ rule { ~restricted_public_level }.policy do
+ enable :read_users_list
+ end
end
diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb
index 0181ddf85e0..0905ddd9b38 100644
--- a/app/policies/user_policy.rb
+++ b/app/policies/user_policy.rb
@@ -1,11 +1,4 @@
class UserPolicy < BasePolicy
- include Gitlab::CurrentSettings
-
- desc "The application is restricted from public visibility"
- condition(:restricted_public_level, scope: :global) do
- current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC)
- end
-
desc "The current user is the user in question"
condition(:user_is_self, score: 0) { @subject == @user }
diff --git a/app/services/delete_merged_branches_service.rb b/app/services/delete_merged_branches_service.rb
index 3b611588466..5c9e2a16c71 100644
--- a/app/services/delete_merged_branches_service.rb
+++ b/app/services/delete_merged_branches_service.rb
@@ -10,6 +10,8 @@ class DeleteMergedBranchesService < BaseService
branches = branches.select { |branch| project.repository.merged_to_root_ref?(branch) }
# Prevent deletion of branches relevant to open merge requests
branches -= merge_request_branch_names
+ # Prevent deletion of protected branches
+ branches -= project.protected_branches.pluck(:name)
branches.each do |branch|
DeleteBranchService.new(project, current_user).execute(branch)
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index b247cb89e5e..bc846e07f24 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -61,8 +61,12 @@ module MergeRequests
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
if params[:should_remove_source_branch].present? || @merge_request.force_remove_source_branch?
- DeleteBranchService.new(@merge_request.source_project, branch_deletion_user)
- .execute(merge_request.source_branch)
+ # Verify again that the source branch can be removed, since branch may be protected,
+ # or the source branch may have been updated.
+ if @merge_request.can_remove_source_branch?(branch_deletion_user)
+ DeleteBranchService.new(@merge_request.source_project, branch_deletion_user)
+ .execute(merge_request.source_branch)
+ end
end
end
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index 6816b137361..e4dfe87e614 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -92,9 +92,12 @@ module QuickActions
desc 'Assign'
explanation do |users|
- "Assigns #{users.first.to_reference}." if users.any?
+ users = issuable.allows_multiple_assignees? ? users : users.take(1)
+ "Assigns #{users.map(&:to_reference).to_sentence}."
+ end
+ params do
+ issuable.allows_multiple_assignees? ? '@user1 @user2' : '@user'
end
- params '@user'
condition do
current_user.can?(:"admin_#{issuable.to_ability_name}", project)
end
@@ -104,28 +107,69 @@ module QuickActions
command :assign do |users|
next if users.empty?
- if issuable.is_a?(Issue)
- @updates[:assignee_ids] = [users.last.id]
+ @updates[:assignee_ids] =
+ if issuable.allows_multiple_assignees?
+ issuable.assignees.pluck(:id) + users.map(&:id)
+ else
+ [users.last.id]
+ end
+ end
+
+ desc do
+ if issuable.allows_multiple_assignees?
+ 'Remove all or specific assignee(s)'
else
- @updates[:assignee_id] = users.last.id
+ 'Remove assignee'
end
end
-
- desc 'Remove assignee'
explanation do
- "Removes assignee #{issuable.assignees.first.to_reference}."
+ "Removes #{'assignee'.pluralize(issuable.assignees.size)} #{issuable.assignees.map(&:to_reference).to_sentence}."
+ end
+ params do
+ issuable.allows_multiple_assignees? ? '@user1 @user2' : ''
end
condition do
issuable.persisted? &&
issuable.assignees.any? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", project)
end
- command :unassign do
- if issuable.is_a?(Issue)
- @updates[:assignee_ids] = []
- else
- @updates[:assignee_id] = nil
- end
+ parse_params do |unassign_param|
+ # When multiple users are assigned, all will be unassigned if multiple assignees are no longer allowed
+ extract_users(unassign_param) if issuable.allows_multiple_assignees?
+ end
+ command :unassign do |users = nil|
+ @updates[:assignee_ids] =
+ if users&.any?
+ issuable.assignees.pluck(:id) - users.map(&:id)
+ else
+ []
+ end
+ end
+
+ desc do
+ "Change assignee#{'(s)' if issuable.allows_multiple_assignees?}"
+ end
+ explanation do |users|
+ users = issuable.allows_multiple_assignees? ? users : users.take(1)
+ "Change #{'assignee'.pluralize(users.size)} to #{users.map(&:to_reference).to_sentence}."
+ end
+ params do
+ issuable.allows_multiple_assignees? ? '@user1 @user2' : '@user'
+ end
+ condition do
+ issuable.persisted? &&
+ current_user.can?(:"admin_#{issuable.to_ability_name}", project)
+ end
+ parse_params do |assignee_param|
+ extract_users(assignee_param)
+ end
+ command :reassign do |users|
+ @updates[:assignee_ids] =
+ if issuable.allows_multiple_assignees?
+ users.map(&:id)
+ else
+ [users.last.id]
+ end
end
desc 'Set milestone'
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 7d5add3cc1c..9ebb3894c55 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -45,10 +45,13 @@
.panel.panel-danger
.panel-heading Remove group
.panel-body
- %p
- Removing group will cause all child projects and resources to be removed.
- %br
- %strong Removed group can not be restored!
+ = form_tag(@group, method: :delete) do
+ %p
+ Removing group will cause all child projects and resources to be removed.
+ %br
+ %strong Removed group can not be restored!
- .form-actions
- = link_to 'Remove group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove"
+ .form-actions
+ = button_to 'Remove group', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_group_message(@group) }
+
+= render 'shared/confirm_modal', phrase: @group.path
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 8cbc3f6105f..7e8b9cb9ad0 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -74,9 +74,8 @@
= link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
%li
= link_to "Settings", profile_path
- - if can_toggle_new_nav?
- %li
- = link_to "Turn on new nav", profile_preferences_path(anchor: "new-navigation")
+ %li
+ = link_to "Turn on new nav", profile_preferences_path(anchor: "new-navigation")
%li.divider
%li
= link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link"
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index a089aeb2447..2dd938f8379 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -16,25 +16,22 @@
.preview= image_tag "#{scheme.css_class}-scheme-preview.png"
= f.radio_button :color_scheme_id, scheme.id
= scheme.name
- - if can_toggle_new_nav?
- .col-sm-12
- %hr
- .col-lg-3.profile-settings-sidebar#new-navigation
- %h4.prepend-top-0
- New Navigation
- %p
- This setting allows you to turn on or off the new upcoming navigation concept.
- = succeed '.' do
- = link_to 'Learn more', '', target: '_blank'
- .col-lg-9.syntax-theme
- = label_tag do
- .preview= image_tag "old_nav.png"
- %input.js-experiment-feature-toggle{ type: "radio", value: "false", name: "new_nav", checked: !show_new_nav? }
- Old
- = label_tag do
- .preview= image_tag "new_nav.png"
- %input.js-experiment-feature-toggle{ type: "radio", value: "true", name: "new_nav", checked: show_new_nav? }
- New
+ .col-sm-12
+ %hr
+ .col-lg-3.profile-settings-sidebar#new-navigation
+ %h4.prepend-top-0
+ New Navigation
+ %p
+ This setting allows you to turn on or off the new upcoming navigation concept.
+ .col-lg-9.syntax-theme
+ = label_tag do
+ .preview= image_tag "old_nav.png"
+ %input.js-experiment-feature-toggle{ type: "radio", value: "false", name: "new_nav", checked: !show_new_nav? }
+ Old
+ = label_tag do
+ .preview= image_tag "new_nav.png"
+ %input.js-experiment-feature-toggle{ type: "radio", value: "true", name: "new_nav", checked: show_new_nav? }
+ New
.col-sm-12
%hr
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/projects/boards/components/sidebar/_assignee.html.haml b/app/views/projects/boards/components/sidebar/_assignee.html.haml
index e8db868f49b..c314573bdea 100644
--- a/app/views/projects/boards/components/sidebar/_assignee.html.haml
+++ b/app/views/projects/boards/components/sidebar/_assignee.html.haml
@@ -19,10 +19,11 @@
":data-name" => "assignee.name",
":data-username" => "assignee.username" }
.dropdown
- %button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: "button", ref: "assigneeDropdown", data: { toggle: "dropdown", field_name: "issue[assignee_ids][]", first_user: (current_user.username if current_user), current_user: "true", project_id: @project.id, null_user: "true", multi_select: "true", 'max-select' => 1, dropdown: { header: 'Assignee' } },
+ - dropdown_options = issue_assignees_dropdown_options
+ %button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: 'button', ref: 'assigneeDropdown', data: { toggle: 'dropdown', field_name: 'issue[assignee_ids][]', first_user: current_user&.username, current_user: 'true', project_id: @project.id, null_user: 'true', multi_select: 'true', 'dropdown-header': dropdown_options[:data][:'dropdown-header'], 'max-select': dropdown_options[:data][:'max-select'] },
":data-issuable-id" => "issue.id",
":data-issue-update" => "'#{namespace_project_issues_path(@project.namespace, @project)}/' + issue.id + '.json'" }
- Select assignee
+ = dropdown_options[:title]
= icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author
= dropdown_title("Assign to")
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index 8ffddfe6154..78002e8cd64 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Charts", "Pipelines"
+- page_title _("Charts"), _("Pipelines")
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('graphs')
@@ -8,7 +8,7 @@
%div{ class: container_class }
.sub-header-block
.oneline
- A collection of graphs for Continuous Integration
+ = _("A collection of graphs regarding Continuous Integration")
#charts.ci-charts
.row
diff --git a/app/views/projects/pipelines/charts/_overall.haml b/app/views/projects/pipelines/charts/_overall.haml
index 93083397d5b..66786c7ff59 100644
--- a/app/views/projects/pipelines/charts/_overall.haml
+++ b/app/views/projects/pipelines/charts/_overall.haml
@@ -1,15 +1,15 @@
-%h4 Overall stats
+%h4= s_("PipelineCharts|Overall statistics")
%ul
%li
- Total:
- %strong= pluralize @counts[:total], 'pipeline'
+ = s_("PipelineCharts|Total:")
+ %strong= n_("1 pipeline", "%d pipelines", @counts[:total]) % @counts[:total]
%li
- Successful:
- %strong= pluralize @counts[:success], 'pipeline'
+ = s_("PipelineCharts|Successful:")
+ %strong= n_("1 pipeline", "%d pipelines", @counts[:success]) % @counts[:success]
%li
- Failed:
- %strong= pluralize @counts[:failed], 'pipeline'
+ = s_("PipelineCharts|Failed:")
+ %strong= n_("1 pipeline", "%d pipelines", @counts[:failed]) % @counts[:failed]
%li
- Success ratio:
+ = s_("PipelineCharts|Success ratio:")
%strong
#{success_ratio(@counts)}%
diff --git a/app/views/projects/pipelines/charts/_pipeline_times.haml b/app/views/projects/pipelines/charts/_pipeline_times.haml
index aee7c5492aa..1292f580a81 100644
--- a/app/views/projects/pipelines/charts/_pipeline_times.haml
+++ b/app/views/projects/pipelines/charts/_pipeline_times.haml
@@ -1,6 +1,6 @@
%div
%p.light
- Commit duration in minutes for last 30 commits
+ = _("Commit duration in minutes for last 30 commits")
%canvas#build_timesChart{ height: 200 }
diff --git a/app/views/projects/pipelines/charts/_pipelines.haml b/app/views/projects/pipelines/charts/_pipelines.haml
index b6f453b9736..be884448087 100644
--- a/app/views/projects/pipelines/charts/_pipelines.haml
+++ b/app/views/projects/pipelines/charts/_pipelines.haml
@@ -1,29 +1,29 @@
-%h4 Pipelines charts
+%h4= _("Pipelines charts")
%p
&nbsp;
%span.cgreen
= icon("circle")
- success
+ = s_("Pipeline|success")
&nbsp;
%span.cgray
= icon("circle")
- all
+ = s_("Pipeline|all")
.prepend-top-default
%p.light
- Jobs for last week
+ = _("Jobs for last week")
(#{date_from_to(Date.today - 7.days, Date.today)})
%canvas#weekChart{ height: 200 }
.prepend-top-default
%p.light
- Jobs for last month
+ = _("Jobs for last month")
(#{date_from_to(Date.today - 30.days, Date.today)})
%canvas#monthChart{ height: 200 }
.prepend-top-default
%p.light
- Jobs for last year
+ = _("Jobs for last year")
%canvas#yearChart.padded{ height: 250 }
- [:week, :month, :year].each do |scope|
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index d3d290692a2..ae890567225 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -23,7 +23,7 @@
.scroll-container
%ul.tokens-container.list-unstyled
%li.input-token
- %input.form-control.filtered-search{ id: "filtered-search-#{type.to_s}", placeholder: 'Search or filter results...', data: { 'project-id' => @project.id, 'username-params' => @users.to_json(only: [:id, :username]), 'base-endpoint' => namespace_project_path(@project.namespace, @project) } }
+ %input.form-control.filtered-search{ search_filter_input_options(type) }
= icon('filter')
#js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
%ul{ data: { dropdown: true } }
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index 2ea5eb960c0..57392cd7fbb 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -37,19 +37,20 @@
- issuable.assignees.each do |assignee|
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil, data: { avatar_url: assignee.avatar_url, name: assignee.name, username: assignee.username }
- - options = { toggle_class: 'js-user-search js-author-search', title: 'Assign to', filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: 'Search users', data: { first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_ids][]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true } }
-
+ - options = { toggle_class: 'js-user-search js-author-search', title: 'Assign to', filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: 'Search users', data: { first_user: current_user&.username, current_user: true, project_id: @project&.id, author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_ids][]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true } }
- title = 'Select assignee'
- if issuable.is_a?(Issue)
- unless issuable.assignees.any?
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil
+ - dropdown_options = issue_assignees_dropdown_options
+ - title = dropdown_options[:title]
- options[:toggle_class] += ' js-multiselect js-save-user-data'
- data = { field_name: "#{issuable.to_ability_name}[assignee_ids][]" }
- data[:multi_select] = true
- data['dropdown-title'] = title
- - data['dropdown-header'] = 'Assignee'
- - data['max-select'] = 1
+ - data['dropdown-header'] = dropdown_options[:data][:'dropdown-header']
+ - data['max-select'] = dropdown_options[:data][:'max-select']
- options[:data].merge!(data)
= dropdown_tag(title, options: options)
diff --git a/app/views/shared/issuable/form/_metadata_issue_assignee.html.haml b/app/views/shared/issuable/form/_metadata_issue_assignee.html.haml
index 77175c839a6..567cde764e2 100644
--- a/app/views/shared/issuable/form/_metadata_issue_assignee.html.haml
+++ b/app/views/shared/issuable/form/_metadata_issue_assignee.html.haml
@@ -7,5 +7,5 @@
- if issuable.assignees.length === 0
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil, data: { meta: '' }
- = dropdown_tag(users_dropdown_label(issuable.assignees), options: issue_dropdown_options(issuable,false))
+ = dropdown_tag(users_dropdown_label(issuable.assignees), options: issue_assignees_dropdown_options)
= link_to 'Assign to me', '#', class: "assign-to-me-link #{'hide' if issuable.assignees.include?(current_user)}"