From 52d2fd49b5d913d40259161e44579b715b4a383c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 31 Aug 2016 15:28:58 +0100 Subject: Updated members UI --- app/assets/javascripts/dispatcher.js | 2 +- app/assets/javascripts/project_members.js | 10 ---- app/assets/javascripts/project_members.js.es6 | 36 +++++++++++++++ app/assets/stylesheets/framework/selects.scss | 6 ++- app/assets/stylesheets/pages/members.scss | 22 +++++++++ .../project_members/_new_project_member.html.haml | 35 ++++++-------- app/views/projects/project_members/_team.html.haml | 2 +- app/views/projects/project_members/index.html.haml | 23 ++++----- app/views/shared/members/_member.html.haml | 54 ++++++++-------------- 9 files changed, 111 insertions(+), 79 deletions(-) delete mode 100644 app/assets/javascripts/project_members.js create mode 100644 app/assets/javascripts/project_members.js.es6 create mode 100644 app/assets/stylesheets/pages/members.scss diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 99b16f7d59b..c95aaf61443 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -132,7 +132,7 @@ break; case 'projects:project_members:index': new gl.MemberExpirationDate(); - new ProjectMembers(); + new gl.ProjectMembers(); new UsersSelect(); break; case 'groups:new': diff --git a/app/assets/javascripts/project_members.js b/app/assets/javascripts/project_members.js deleted file mode 100644 index 78f7b48bc7d..00000000000 --- a/app/assets/javascripts/project_members.js +++ /dev/null @@ -1,10 +0,0 @@ -(function() { - this.ProjectMembers = (function() { - function ProjectMembers() { - $('li.project_member').bind('ajax:success', function() { - return $(this).fadeOut(); - }); - } - return ProjectMembers; - })(); -}).call(this); diff --git a/app/assets/javascripts/project_members.js.es6 b/app/assets/javascripts/project_members.js.es6 new file mode 100644 index 00000000000..74cedfd5006 --- /dev/null +++ b/app/assets/javascripts/project_members.js.es6 @@ -0,0 +1,36 @@ +((w) => { + window.gl = window.gl || {}; + + class ProjectMembers { + constructor() { + this.removeListeners(); + this.addListeners(); + } + + removeListeners() { + $('.project_member').off('ajax:success'); + $('.js-member-update-control').off('change'); + } + + addListeners() { + $('.project_member').on('ajax:success', this.removeRow); + $('.js-member-update-control').on('change', function () { + console.log($(this).val()); + }); + } + + removeRow(e) { + const $target = $(e.target); + + if ($target.hasClass('btn-remove')) { + $target.fadeOut(); + } + } + + submitForm() { + + } + } + + gl.ProjectMembers = ProjectMembers; +})(window); diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index c75dacf95d9..746ab89abd2 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -86,7 +86,7 @@ background: none; .select2-search-field input { - padding: $gl-padding / 2; + padding: 5px $gl-padding / 2; font-size: 13px; height: auto; font-family: inherit; @@ -191,6 +191,10 @@ &.input-clamp { max-width: 100%; } + + &.input-full { + width: 100%; + } } .select2-highlighted { diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss new file mode 100644 index 00000000000..9583d7c6161 --- /dev/null +++ b/app/assets/stylesheets/pages/members.scss @@ -0,0 +1,22 @@ +.project-members-new { + > h5 { + font-weight: normal; + } +} + +.member { + .controls { + display: flex; + width: 400px; + } + + .form-horizontal { + display: flex; + flex: 1; + margin-top: 3px; + } + + .member-form-control { + width: 50%; + } +} diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml index fa8cbf71733..c0b187fb460 100644 --- a/app/views/projects/project_members/_new_project_member.html.haml +++ b/app/views/projects/project_members/_new_project_member.html.haml @@ -1,27 +1,22 @@ -= form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'form-horizontal users-project-form' } do |f| - .form-group - = f.label :user_ids, "People", class: 'control-label' - .col-sm-10 - = users_select_tag(:user_ids, multiple: true, class: 'input-large', scope: :all, email_user: true) - .help-block += form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project) do |f| + .row + .col-md-4.col-lg-6 + = users_select_tag(:user_ids, multiple: true, class: "input-full", scope: :all, email_user: true) + .help-block.append-bottom-10 Search for users by name, username, or email, or invite new ones using their email address. - .form-group - = f.label :access_level, "Project Access", class: 'control-label' - .col-sm-10 - = select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "project-access-select select2" - .help-block - Read more about role permissions - %strong= link_to "here", help_page_path("user/permissions"), class: "vlink" + .col-md-3.col-lg-2 + = select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "form-control project-access-select" + .help-block.append-bottom-10 + = link_to "Read more", help_page_path("user/permissions"), class: "vlink" + about role permissions - .form-group - = f.label :expires_at, 'Access expiration date', class: 'control-label' - .col-sm-10 + .col-md-3.col-lg-2 .clearable-input - = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Select access expiration date' + = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date' %i.clear-icon.js-clear-input - .help-block + .help-block.append-bottom-10 On this date, the user(s) will automatically lose access to this project. - .form-actions - = f.submit 'Add users to project', class: "btn btn-create" + .col-md-2 + = f.submit "Add to project", class: "btn btn-create btn-block" diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index b0bfdd235f7..db6c1194da7 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -1,7 +1,7 @@ .panel.panel-default .panel-heading + Users with access to %strong #{@project.name} - project members %span.badge= members.size .controls = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 9d063b3081f..9d47e7d725c 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,20 +1,21 @@ - page_title "Members" .project-members-page.js-project-members-page.prepend-top-default + %h4 + Members + %hr - if can?(current_user, :admin_project_member, @project) - .panel.panel-default - .panel-heading - Add new user to project - .controls - = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do - Import members - .panel-body - %p.light - Users with access to this project are listed below. - = render "new_project_member" + .project-members-new.append-bottom-default + %h5.clearfix + Add new user to + %strong= @project.name + -# = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default pull-right", title: "Import members from another project" + = render "new_project_member" - = render 'shared/members/requests', membership_source: @project, requesters: @requesters + = render 'shared/members/requests', membership_source: @project, requesters: @requesters + %h5.append-bottom-default + Existing users and groups = render 'team', members: @project_members - if @group diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 5f20e4bd42a..fd9b688dc20 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -2,27 +2,28 @@ - show_controls = local_assigns.fetch(:show_controls, true) - user = member.user -%li.js-toggle-container{ class: dom_class(member), id: dom_id(member) } +%li.member{ class: dom_class(member), id: dom_id(member) } - if show_roles .controls - %strong.control-text= member.human_access - if show_controls - - if !user && can?(current_user, action_member_permission(:admin, member), member.source) - = link_to 'Resend invite', polymorphic_path([:resend_invite, member]), - method: :post, - class: 'btn' - - - if can?(current_user, action_member_permission(:update, member), member) - = button_tag icon('pencil'), - type: 'button', - class: 'btn inline js-toggle-button', - title: 'Edit' - - - if member.request? - = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]), + - if @project.owner != user + = form_for member, remote: true, html: { class: 'form-horizontal' } do |f| + = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + .prepend-left-5.append-right-10.clearable-input.member-form-control + = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + %i.clear-icon.js-clear-input + - if !user && can?(current_user, action_member_permission(:admin, member), member.source) + = link_to 'Resend invite', polymorphic_path([:resend_invite, member]), method: :post, - class: 'btn btn-success', - title: 'Grant access' + class: 'btn' + - else + Owner + + - if member.request? && can?(current_user, action_member_permission(:update, member), member) + = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]), + method: :post, + class: 'btn btn-success', + title: 'Grant access' - if can?(current_user, action_member_permission(:destroy, member), member) - if current_user == user @@ -44,7 +45,7 @@ = image_tag avatar_icon(user, 40), class: "avatar s40", alt: '' %strong = link_to user.name, user_path(user) - %span.cgray= user.username + %span.cgray= user.to_reference - if user == current_user %span.label.label-success It's you @@ -73,20 +74,3 @@ by = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) - - - if show_roles - .edit-member.hide.js-toggle-content - %br - = form_for member, remote: true, html: { class: 'form-horizontal' } do |f| - .form-group - = label_tag "member_access_level_#{member.id}", 'Project access', class: 'control-label' - .col-sm-10 - = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control', id: "member_access_level_#{member.id}" - .form-group - = label_tag "member_expires_at_#{member.id}", 'Access expiration date', class: 'control-label' - .col-sm-10 - .clearable-input - = f.text_field :expires_at, class: 'form-control js-access-expiration-date', placeholder: 'Select access expiration date', id: "member_expires_at_#{member.id}" - %i.clear-icon.js-clear-input - .prepend-top-10 - = f.submit 'Save', class: 'btn btn-save btn-sm' -- cgit v1.2.1 From 87a0501ded0d08ae718b6f3f6feb4ac2c9c6b016 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 1 Sep 2016 11:56:21 +0100 Subject: Updates the member row when values changed --- app/assets/javascripts/member_expiration_date.js | 8 ++++++-- app/assets/javascripts/project_members.js.es6 | 5 +++-- app/views/projects/project_members/update.js.haml | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/member_expiration_date.js b/app/assets/javascripts/member_expiration_date.js index 1935af491f7..e1532fd9ec4 100644 --- a/app/assets/javascripts/member_expiration_date.js +++ b/app/assets/javascripts/member_expiration_date.js @@ -14,14 +14,18 @@ inputs.datepicker({ dateFormat: 'yy-mm-dd', minDate: 1, - onSelect: toggleClearInput + onSelect: function () { + $(this).trigger('change'); + toggleClearInput.call(this); + } }); inputs.next('.js-clear-input').on('click', function(event) { event.preventDefault(); var input = $(this).closest('.clearable-input').find('.js-access-expiration-date'); - input.datepicker('setDate', null); + input.datepicker('setDate', null) + .trigger('change'); toggleClearInput.call(input); }); diff --git a/app/assets/javascripts/project_members.js.es6 b/app/assets/javascripts/project_members.js.es6 index 74cedfd5006..659c57d8b6c 100644 --- a/app/assets/javascripts/project_members.js.es6 +++ b/app/assets/javascripts/project_members.js.es6 @@ -15,7 +15,8 @@ addListeners() { $('.project_member').on('ajax:success', this.removeRow); $('.js-member-update-control').on('change', function () { - console.log($(this).val()); + $(this).closest('form') + .trigger("submit.rails"); }); } @@ -28,7 +29,7 @@ } submitForm() { - + } } diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml index 37e55dc72a3..91927181efb 100644 --- a/app/views/projects/project_members/update.js.haml +++ b/app/views/projects/project_members/update.js.haml @@ -1,3 +1,3 @@ :plain - $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @project_member))}'); - new gl.MemberExpirationDate(); + var $listItem = $('#{escape_javascript(render('shared/members/member', member: @project_member))}'); + $("##{dom_id(@project_member)} .list-item-name").replaceWith($listItem.find('.list-item-name')); -- cgit v1.2.1 From 4afd17b2786b5bca075ac7508979fad582c65bc9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 1 Sep 2016 13:48:20 +0100 Subject: Included groups on project_members page --- app/assets/stylesheets/framework/lists.scss | 8 +++ app/assets/stylesheets/pages/groups.scss | 2 - app/assets/stylesheets/pages/members.scss | 9 +++ app/controllers/projects/group_links_controller.rb | 12 ++++ .../projects/project_members_controller.rb | 1 + app/views/projects/group_links/update.js.haml | 3 + .../project_members/_group_members.html.haml | 2 +- .../projects/project_members/_groups.html.haml | 9 +++ app/views/projects/project_members/_team.html.haml | 12 ---- app/views/projects/project_members/index.html.haml | 14 +++-- app/views/shared/members/_group.html.haml | 23 ++++++++ app/views/shared/members/_member.html.haml | 69 ++++++++++------------ config/routes.rb | 2 +- 13 files changed, 108 insertions(+), 58 deletions(-) create mode 100644 app/views/projects/group_links/update.js.haml create mode 100644 app/views/projects/project_members/_groups.html.haml create mode 100644 app/views/shared/members/_group.html.haml diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 965fcc06518..dfdfe4a3c89 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -164,6 +164,14 @@ ul.content-list { } } + .member-controls { + float: none; + + @media (min-width: $screen-md-min) { + float: right; + } + } + // When dragging a list item &.ui-sortable-helper { border-bottom: none; diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index b657ca47d38..a27f7a2fd77 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -1,6 +1,4 @@ .member-search-form { - float: left; - input[type='search'] { width: 225px; vertical-align: bottom; diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 9583d7c6161..4bc34ac15df 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -5,6 +5,15 @@ } .member { + .list-item-name { + float: none; + + @media (min-width: $screen-md-min) { + float: left; + width: 50%; + } + } + .controls { display: flex; width: 400px; diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index d0c4550733c..57c54bf625a 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -19,9 +19,21 @@ class Projects::GroupLinksController < Projects::ApplicationController redirect_to namespace_project_group_links_path(project.namespace, project) end + def update + @group_link = @project.project_group_links.find(params[:id]) + + @group_link.update_attributes(group_link_params) + end + def destroy project.project_group_links.find(params[:id]).destroy redirect_to namespace_project_group_links_path(project.namespace, project) end + + protected + + def group_link_params + params.require(:group_link).permit(:group_access, :expires_at) + end end diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 42a7e5a2c30..d83e95cf097 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -5,6 +5,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] def index + @groups = @project.project_group_links.all @project_members = @project.project_members @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project) diff --git a/app/views/projects/group_links/update.js.haml b/app/views/projects/group_links/update.js.haml new file mode 100644 index 00000000000..d3a37847f58 --- /dev/null +++ b/app/views/projects/group_links/update.js.haml @@ -0,0 +1,3 @@ +:plain + var $listItem = $('#{escape_javascript(render('shared/members/group', group_link: @group_link, group: @group_link.group))}'); + $("##{dom_id(@group_link.group)} .list-item-name").replaceWith($listItem.find('.list-item-name')); diff --git a/app/views/projects/project_members/_group_members.html.haml b/app/views/projects/project_members/_group_members.html.haml index e783d8c72c5..9738f369a35 100644 --- a/app/views/projects/project_members/_group_members.html.haml +++ b/app/views/projects/project_members/_group_members.html.haml @@ -1,7 +1,7 @@ .panel.panel-default .panel-heading + Group members with access to %strong #{@group.name} - group members %span.badge= members.size - if can?(current_user, :admin_group_member, @group) .controls diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml new file mode 100644 index 00000000000..79791af7963 --- /dev/null +++ b/app/views/projects/project_members/_groups.html.haml @@ -0,0 +1,9 @@ +.panel.panel-default + .panel-heading + Groups with access to + %strong #{@project.name} + %span.badge= groups.size + %ul.content-list + - @groups.each do |group_link| + - group = group_link.group + = render 'shared/members/group', group_link: group_link, group: group diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index db6c1194da7..6a8b28d3886 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -3,17 +3,5 @@ Users with access to %strong #{@project.name} %span.badge= members.size - .controls - = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do - .form-group - = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false } - = button_tag class: 'btn', title: 'Search' do - = icon("search") %ul.content-list = render partial: 'shared/members/member', collection: members, as: :member - -:javascript - $('form.member-search-form').on('submit', function (event) { - event.preventDefault(); - Turbolinks.visit(this.action + '?' + $(this).serialize()); - }); diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 9d47e7d725c..db8a060d170 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -14,12 +14,16 @@ = render 'shared/members/requests', membership_source: @project, requesters: @requesters - %h5.append-bottom-default - Existing users and groups + .append-bottom-default.clearfix + %h5.pull-left + Existing users and groups + = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form pull-right hidden-xs hidden-sm' do + .form-group + = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } + = icon("search") + - if @grups + = render 'groups', groups: @groups = render 'team', members: @project_members - if @group = render "group_members", members: @group_members - - - if @project_group_links.any? && @project.allowed_to_share_with_group? - = render "shared_group_members" diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml new file mode 100644 index 00000000000..0502de5210b --- /dev/null +++ b/app/views/shared/members/_group.html.haml @@ -0,0 +1,23 @@ +- group = local_assigns[:group] +- group_link = local_assigns[:group_link] +%li.member{ class: dom_class(group), id: dom_id(group) } + %span{ class: "list-item-name" } + = image_tag group_icon(group), class: "avatar s40", alt: '' + %strong + = link_to group.name, group_path(group) + .cgray + Joined #{time_ago_with_tooltip(group.created_at)} + - if group_link.expires? + · + %span{ class: ('text-warning' if group_link.expires_soon?) } + Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)} + .controls.member-controls + = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal' do + = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}" + .prepend-left-5.append-right-10.clearable-input.member-form-control + = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}" + %i.clear-icon.js-clear-input + = link_to icon('trash'), namespace_project_group_link_path(@project.namespace, @project, group_link), + remote: true, + method: :delete, + class: 'btn btn-remove' diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index fd9b688dc20..800badc051a 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -3,43 +3,6 @@ - user = member.user %li.member{ class: dom_class(member), id: dom_id(member) } - - if show_roles - .controls - - if show_controls - - if @project.owner != user - = form_for member, remote: true, html: { class: 'form-horizontal' } do |f| - = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) - .prepend-left-5.append-right-10.clearable-input.member-form-control - = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) - %i.clear-icon.js-clear-input - - if !user && can?(current_user, action_member_permission(:admin, member), member.source) - = link_to 'Resend invite', polymorphic_path([:resend_invite, member]), - method: :post, - class: 'btn' - - else - Owner - - - if member.request? && can?(current_user, action_member_permission(:update, member), member) - = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]), - method: :post, - class: 'btn btn-success', - title: 'Grant access' - - - if can?(current_user, action_member_permission(:destroy, member), member) - - if current_user == user - = link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]), - method: :delete, - data: { confirm: leave_confirmation_message(member.source) }, - class: 'btn btn-remove' - - else - = link_to icon('trash'), member, - remote: true, - method: :delete, - data: { confirm: remove_member_message(member) }, - class: 'btn btn-remove', - title: remove_member_title(member) - - %span{ class: ("list-item-name" if show_controls) } - if user = image_tag avatar_icon(user, 40), class: "avatar s40", alt: '' @@ -74,3 +37,35 @@ by = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) + - if show_roles + .controls.member-controls + - if show_controls + = form_for member, remote: true, html: { class: 'form-horizontal' } do |f| + = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + .prepend-left-5.append-right-10.clearable-input.member-form-control + = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + %i.clear-icon.js-clear-input + - if !user && can?(current_user, action_member_permission(:admin, member), member.source) + = link_to 'Resend invite', polymorphic_path([:resend_invite, member]), + method: :post, + class: 'btn' + + - if member.request? && can?(current_user, action_member_permission(:update, member), member) + = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]), + method: :post, + class: 'btn btn-success', + title: 'Grant access' + + - if can?(current_user, action_member_permission(:destroy, member), member) + - if current_user == user + = link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]), + method: :delete, + data: { confirm: leave_confirmation_message(member.source) }, + class: 'btn btn-remove' + - else + = link_to icon('trash'), member, + remote: true, + method: :delete, + data: { confirm: remove_member_message(member) }, + class: 'btn btn-remove', + title: remove_member_title(member) diff --git a/config/routes.rb b/config/routes.rb index 068c92d1400..441f7249aa8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -867,7 +867,7 @@ Rails.application.routes.draw do end end - resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ } + resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ } resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do member do -- cgit v1.2.1 From 23993147fbf24e868d33927dc1194b60a106076d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 1 Sep 2016 14:13:49 +0100 Subject: Fixed issue with groups not displaying --- app/controllers/projects/project_members_controller.rb | 14 -------------- app/views/projects/project_members/index.html.haml | 6 ++---- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index d83e95cf097..6060ddf025b 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -16,20 +16,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController @project_members = @project_members.order('access_level DESC') - @group = @project.group - - if @group - @group_members = @group.group_members - @group_members = @group_members.non_invite unless can?(current_user, :admin_group, @group) - - if params[:search].present? - users = @group.users.search(params[:search]).to_a - @group_members = @group_members.where(user_id: users) - end - - @group_members = @group_members.order('access_level DESC') - end - @requesters = @project.requesters if can?(current_user, :admin_project, @project) @project_member = @project.project_members.new diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index db8a060d170..42a23057ff1 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -21,9 +21,7 @@ .form-group = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } = icon("search") - - if @grups + - if @groups.size > 0 = render 'groups', groups: @groups - = render 'team', members: @project_members - - if @group - = render "group_members", members: @group_members + = render 'team', members: @project_members -- cgit v1.2.1 From e33cda96cb20f47fdde4314f6bb00e43bbf5aeb4 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 1 Sep 2016 15:27:42 +0100 Subject: Fixed group members not deleting Combine both group members & project members in project members list --- app/assets/javascripts/project_members.js.es6 | 7 ++++--- app/controllers/projects/project_members_controller.rb | 9 +++++---- app/views/projects/project_members/_team.html.haml | 6 ++++-- app/views/projects/project_members/index.html.haml | 1 + 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/project_members.js.es6 b/app/assets/javascripts/project_members.js.es6 index 659c57d8b6c..8b5cb17ac2d 100644 --- a/app/assets/javascripts/project_members.js.es6 +++ b/app/assets/javascripts/project_members.js.es6 @@ -8,12 +8,12 @@ } removeListeners() { - $('.project_member').off('ajax:success'); + $('.project_member, .group_member').off('ajax:success'); $('.js-member-update-control').off('change'); } addListeners() { - $('.project_member').on('ajax:success', this.removeRow); + $('.project_member, .group_member').on('ajax:success', this.removeRow); $('.js-member-update-control').on('change', function () { $(this).closest('form') .trigger("submit.rails"); @@ -24,7 +24,8 @@ const $target = $(e.target); if ($target.hasClass('btn-remove')) { - $target.fadeOut(); + console.log('a'); + $target.closest('.member').fadeOut(); } } diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 6060ddf025b..abb92938211 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -6,15 +6,16 @@ class Projects::ProjectMembersController < Projects::ApplicationController def index @groups = @project.project_group_links.all - @project_members = @project.project_members + @project_members = @project.team.members.all + @project_members_size = @project_members.size + @group_members = @project.group.group_members @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project) if params[:search].present? - users = @project.users.search(params[:search]).to_a - @project_members = @project_members.where(user_id: users) + @project_members = @project_members.search(params[:search]) end - @project_members = @project_members.order('access_level DESC') + @project_members = @project_members.page(params[:page]) @requesters = @project.requesters if can?(current_user, :admin_project, @project) diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index 6a8b28d3886..23c35f91b6b 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -2,6 +2,8 @@ .panel-heading Users with access to %strong #{@project.name} - %span.badge= members.size + %span.badge= @project_members_size %ul.content-list - = render partial: 'shared/members/member', collection: members, as: :member + - members.each do |user| + - member = @project.team.find_member(user.id) + = render 'shared/members/member', member: member diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 42a23057ff1..85e512a75f4 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -25,3 +25,4 @@ = render 'groups', groups: @groups = render 'team', members: @project_members + = paginate @project_members, theme: "gitlab" -- cgit v1.2.1 From 843dd24bdf063bb199c841cd6a08643344ae7598 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 1 Sep 2016 16:22:53 +0100 Subject: Mobile improvements Added group name to members row Fixed saving group member --- app/assets/javascripts/project_members.js.es6 | 7 +++- app/assets/stylesheets/framework/lists.scss | 8 +++-- app/assets/stylesheets/pages/members.scss | 42 ++++++++++++++++++---- app/views/groups/group_members/update.js.haml | 4 +-- app/views/projects/project_members/_team.html.haml | 2 +- app/views/shared/members/_group.html.haml | 7 ++-- app/views/shared/members/_member.html.haml | 28 ++++++++++----- 7 files changed, 74 insertions(+), 24 deletions(-) diff --git a/app/assets/javascripts/project_members.js.es6 b/app/assets/javascripts/project_members.js.es6 index 8b5cb17ac2d..d11467cf6eb 100644 --- a/app/assets/javascripts/project_members.js.es6 +++ b/app/assets/javascripts/project_members.js.es6 @@ -1,5 +1,5 @@ ((w) => { - window.gl = window.gl || {}; + w.gl = w.gl || {}; class ProjectMembers { constructor() { @@ -10,6 +10,7 @@ removeListeners() { $('.project_member, .group_member').off('ajax:success'); $('.js-member-update-control').off('change'); + $('.js-edit-member-form').off('ajax:success'); } addListeners() { @@ -17,6 +18,10 @@ $('.js-member-update-control').on('change', function () { $(this).closest('form') .trigger("submit.rails"); + $(this).disable(); + }); + $('.js-edit-member-form').on('ajax:success', function () { + $(this).find('.js-member-update-control').enable(); }); } diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index dfdfe4a3c89..272d37763c1 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -128,6 +128,10 @@ ul.content-list { color: $gl-dark-link-color; } + .member-group-link { + color: $blue-normal; + } + .description { p { @include str-truncated; @@ -166,8 +170,8 @@ ul.content-list { .member-controls { float: none; - - @media (min-width: $screen-md-min) { + + @media (min-width: $screen-sm-min) { float: right; } } diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 4bc34ac15df..a69af862348 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -8,24 +8,52 @@ .list-item-name { float: none; - @media (min-width: $screen-md-min) { + @media (min-width: $screen-sm-min) { float: left; width: 50%; } } .controls { - display: flex; - width: 400px; + @media (min-width: $screen-sm-min) { + display: flex; + width: 400px; + max-width: 50%; + } } .form-horizontal { - display: flex; - flex: 1; - margin-top: 3px; + margin-top: 5px; + + @media (min-width: $screen-sm-min) { + display: flex; + flex: 1; + margin-top: 3px; + } + } + + .btn-remove { + width: 100%; + + @media (min-width: $screen-sm-min) { + width: auto; + } + } +} + +.member-form-control { + @media (max-width: $screen-xs-max) { + padding: 5px 0; + margin-left: 0; + margin-right: 0; } - .member-form-control { + @media (min-width: $screen-sm-min) { width: 50%; } } + +.member-access-text { + margin-left: auto; + line-height: 43px; +} diff --git a/app/views/groups/group_members/update.js.haml b/app/views/groups/group_members/update.js.haml index 3be7ed8432c..de8f53b6b52 100644 --- a/app/views/groups/group_members/update.js.haml +++ b/app/views/groups/group_members/update.js.haml @@ -1,3 +1,3 @@ :plain - $("##{dom_id(@group_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @group_member))}'); - new gl.MemberExpirationDate(); + var $listItem = $('#{escape_javascript(render('shared/members/member', member: @group_member))}'); + $("##{dom_id(@group_member)} .list-item-name").replaceWith($listItem.find('.list-item-name')); diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index 23c35f91b6b..2af9fe0519c 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -6,4 +6,4 @@ %ul.content-list - members.each do |user| - member = @project.team.find_member(user.id) - = render 'shared/members/member', member: member + = render 'shared/members/member', member: member, user: user diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index 0502de5210b..5d54195646c 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -17,7 +17,10 @@ .prepend-left-5.append-right-10.clearable-input.member-form-control = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}" %i.clear-icon.js-clear-input - = link_to icon('trash'), namespace_project_group_link_path(@project.namespace, @project, group_link), + = link_to namespace_project_group_link_path(@project.namespace, @project, group_link), remote: true, method: :delete, - class: 'btn btn-remove' + class: 'btn btn-remove' do + %span.visible-xs-block + Delete + = icon('trash', class: 'hidden-xs') diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 800badc051a..4518e84fe34 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -1,6 +1,6 @@ - show_roles = local_assigns.fetch(:show_roles, true) - show_controls = local_assigns.fetch(:show_controls, true) -- user = member.user +- user = local_assigns.fetch(:user, member.user) %li.member{ class: dom_class(member), id: dom_id(member) } %span{ class: ("list-item-name" if show_controls) } @@ -11,12 +11,16 @@ %span.cgray= user.to_reference - if user == current_user - %span.label.label-success It's you + %span.label.label-success.prepend-left-5 It's you - if user.blocked? %label.label.label-danger %strong Blocked + - if member.respond_to?(:group) && !@group + = link_to member.group, class: "member-group-link prepend-left-5" do + = "· #{member.group.name}" + .cgray - if member.request? Requested @@ -40,11 +44,14 @@ - if show_roles .controls.member-controls - if show_controls - = form_for member, remote: true, html: { class: 'form-horizontal' } do |f| - = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) - .prepend-left-5.append-right-10.clearable-input.member-form-control - = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) - %i.clear-icon.js-clear-input + - if user != current_user + = form_for member, remote: true, html: { class: 'form-horizontal js-edit-member-form' } do |f| + = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + .prepend-left-5.append-right-10.clearable-input.member-form-control + = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + %i.clear-icon.js-clear-input + - else + %span.member-access-text= member.human_access - if !user && can?(current_user, action_member_permission(:admin, member), member.source) = link_to 'Resend invite', polymorphic_path([:resend_invite, member]), method: :post, @@ -63,9 +70,12 @@ data: { confirm: leave_confirmation_message(member.source) }, class: 'btn btn-remove' - else - = link_to icon('trash'), member, + = link_to member, remote: true, method: :delete, data: { confirm: remove_member_message(member) }, class: 'btn btn-remove', - title: remove_member_title(member) + title: remove_member_title(member) do + %span.visible-xs-block + Delete + = icon('trash', class: 'hidden-xs') -- cgit v1.2.1 From 49a31e64b76b351c1bad91459991a69f0e0fb296 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 1 Sep 2016 17:04:46 +0100 Subject: Removed console log Hides time on mobile --- app/assets/javascripts/project_members.js.es6 | 1 - app/views/shared/members/_member.html.haml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/assets/javascripts/project_members.js.es6 b/app/assets/javascripts/project_members.js.es6 index d11467cf6eb..f525bdbb1ea 100644 --- a/app/assets/javascripts/project_members.js.es6 +++ b/app/assets/javascripts/project_members.js.es6 @@ -29,7 +29,6 @@ const $target = $(e.target); if ($target.hasClass('btn-remove')) { - console.log('a'); $target.closest('.member').fadeOut(); } } diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 4518e84fe34..ab4f1f1382b 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -21,7 +21,7 @@ = link_to member.group, class: "member-group-link prepend-left-5" do = "· #{member.group.name}" - .cgray + .hidden-xs.cgray - if member.request? Requested = time_ago_with_tooltip(member.requested_at) -- cgit v1.2.1 From 15a3111a6663894d952103e7395f2f56408f88ce Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 09:04:28 +0100 Subject: Mobile spacing improvements --- app/assets/stylesheets/framework/forms.scss | 4 --- app/assets/stylesheets/pages/groups.scss | 12 -------- app/assets/stylesheets/pages/members.scss | 36 ++++++++++++++++++++++ app/views/projects/project_members/index.html.haml | 7 +++-- app/views/shared/members/_group.html.haml | 2 +- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 37ff7e22ed1..d1f1a372c06 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -125,7 +125,3 @@ label { border-right: 0; } } - -.help-block { - margin-bottom: 0; -} diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index a27f7a2fd77..cc1c0249df3 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -1,15 +1,3 @@ -.member-search-form { - input[type='search'] { - width: 225px; - vertical-align: bottom; - - @media (max-width: $screen-xs-max) { - width: 100px; - vertical-align: bottom; - } - } -} - .milestone-row { @include str-truncated(90%); } diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index a69af862348..a7f1324f69a 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -57,3 +57,39 @@ margin-left: auto; line-height: 43px; } + +.member.existing-title { + @media (min-width: $screen-sm-min) { + float: left; + } +} + +.member-search-form { + position: relative; + + @media (min-width: $screen-sm-min) { + float: right; + } + + .form-control { + width: 100%; + padding-right: 35px; + + @media (min-width: $screen-sm-min) { + width: 350px; + } + } +} + +.member-search-btn { + position: absolute; + right: 0; + top: 0; + height: 35px; + padding-left: 10px; + padding-right: 10px; + color: $gray-darkest; + background: transparent; + border: 0; + outline: 0; +} diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 85e512a75f4..abe10433387 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -15,12 +15,13 @@ = render 'shared/members/requests', membership_source: @project, requesters: @requesters .append-bottom-default.clearfix - %h5.pull-left + %h5.member.existing-title Existing users and groups - = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form pull-right hidden-xs hidden-sm' do + = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do .form-group = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } - = icon("search") + %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" } + = icon("search") - if @groups.size > 0 = render 'groups', groups: @groups diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index 5d54195646c..e545aec80a9 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -12,7 +12,7 @@ %span{ class: ('text-warning' if group_link.expires_soon?) } Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)} .controls.member-controls - = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal' do + = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal js-edit-member-form' do = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}" .prepend-left-5.append-right-10.clearable-input.member-form-control = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}" -- cgit v1.2.1 From e477ad44565dbe69e3f0200f4f4f7bebbd48cb15 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 09:25:53 +0100 Subject: Removes row from dom when deleting Fixed spacing with buttons Disables group form when user doesnt have correct permissions --- app/assets/javascripts/project_members.js.es6 | 5 ++++- .../projects/project_members_controller.rb | 7 ++----- app/models/project_team.rb | 8 ++++---- app/views/shared/members/_group.html.haml | 21 +++++++++++---------- app/views/shared/members/_member.html.haml | 10 +++++----- app/views/shared/members/_requests.html.haml | 2 +- 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/app/assets/javascripts/project_members.js.es6 b/app/assets/javascripts/project_members.js.es6 index f525bdbb1ea..56bc98d1076 100644 --- a/app/assets/javascripts/project_members.js.es6 +++ b/app/assets/javascripts/project_members.js.es6 @@ -29,7 +29,10 @@ const $target = $(e.target); if ($target.hasClass('btn-remove')) { - $target.closest('.member').fadeOut(); + $target.closest('.member') + .fadeOut(function () { + $(this).remove(); + }); } } diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index abb92938211..cd31653698c 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -5,11 +5,9 @@ class Projects::ProjectMembersController < Projects::ApplicationController before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] def index - @groups = @project.project_group_links.all - @project_members = @project.team.members.all + @groups = @project.project_group_links + @project_members = @project.team.members(can?(current_user, :admin_project, @project)) @project_members_size = @project_members.size - @group_members = @project.group.group_members - @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project) if params[:search].present? @project_members = @project_members.search(params[:search]) @@ -20,7 +18,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController @requesters = @project.requesters if can?(current_user, :admin_project, @project) @project_member = @project.project_members.new - @project_group_links = @project.project_group_links end def create diff --git a/app/models/project_team.rb b/app/models/project_team.rb index ab6ea2aae36..57925a0861a 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -52,8 +52,8 @@ class ProjectTeam ProjectMember.truncate_team(project) end - def members - @members ||= fetch_members + def members(non_invite) + @members ||= fetch_members(nil, non_invite) end alias_method :users, :members @@ -197,7 +197,7 @@ class ProjectTeam access.each { |key, value| access[key] = [value, capped_access_level].min } end - def fetch_members(level = nil) + def fetch_members(level = nil, non_invite = false) project_members = project.members group_members = group ? group.members : [] invited_members = [] @@ -236,7 +236,7 @@ class ProjectTeam end user_ids = project_members.pluck(:user_id) - user_ids.push(*invited_members.map(&:user_id)) if invited_members.any? + user_ids.push(*invited_members.map(&:user_id)) if invited_members.any? && !non_invite user_ids.push(*group_members.pluck(:user_id)) if group User.where(id: user_ids) diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index e545aec80a9..19b58ef20ae 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -13,14 +13,15 @@ Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)} .controls.member-controls = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal js-edit-member-form' do - = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}" - .prepend-left-5.append-right-10.clearable-input.member-form-control - = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}" + = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}", disabled: !can?(current_user, action_member_permission(:admin, group), group) + .prepend-left-5.clearable-input.member-form-control + = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can?(current_user, action_member_permission(:admin, group), group) %i.clear-icon.js-clear-input - = link_to namespace_project_group_link_path(@project.namespace, @project, group_link), - remote: true, - method: :delete, - class: 'btn btn-remove' do - %span.visible-xs-block - Delete - = icon('trash', class: 'hidden-xs') + - if can?(current_user, action_member_permission(:admin, group), group) + = link_to namespace_project_group_link_path(@project.namespace, @project, group_link), + remote: true, + method: :delete, + class: 'btn btn-remove prepend-left-10' do + %span.visible-xs-block + Delete + = icon('trash', class: 'hidden-xs') diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index ab4f1f1382b..2d4853eef92 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -47,7 +47,7 @@ - if user != current_user = form_for member, remote: true, html: { class: 'form-horizontal js-edit-member-form' } do |f| = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) - .prepend-left-5.append-right-10.clearable-input.member-form-control + .prepend-left-5.clearable-input.member-form-control = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) %i.clear-icon.js-clear-input - else @@ -55,12 +55,12 @@ - if !user && can?(current_user, action_member_permission(:admin, member), member.source) = link_to 'Resend invite', polymorphic_path([:resend_invite, member]), method: :post, - class: 'btn' + class: 'btn btn-default prepend-left-10' - if member.request? && can?(current_user, action_member_permission(:update, member), member) = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]), method: :post, - class: 'btn btn-success', + class: 'btn btn-success prepend-left-10', title: 'Grant access' - if can?(current_user, action_member_permission(:destroy, member), member) @@ -68,13 +68,13 @@ = link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]), method: :delete, data: { confirm: leave_confirmation_message(member.source) }, - class: 'btn btn-remove' + class: 'btn btn-remove prepend-left-10' - else = link_to member, remote: true, method: :delete, data: { confirm: remove_member_message(member) }, - class: 'btn btn-remove', + class: 'btn btn-remove prepend-left-10', title: remove_member_title(member) do %span.visible-xs-block Delete diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml index 40b39e850b0..10050adfda5 100644 --- a/app/views/shared/members/_requests.html.haml +++ b/app/views/shared/members/_requests.html.haml @@ -1,8 +1,8 @@ - if requesters.any? .panel.panel-default .panel-heading + Users requesting access to %strong= membership_source.name - access requests %span.badge= requesters.size %ul.content-list = render partial: 'shared/members/member', collection: requesters, as: :member -- cgit v1.2.1 From b3d75ac5135130522f253d4b09f72a7c0a8e2f80 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 09:28:25 +0100 Subject: Return 403 if user can't update group --- app/controllers/projects/group_links_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index 57c54bf625a..b5e314dced3 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -21,6 +21,7 @@ class Projects::GroupLinksController < Projects::ApplicationController def update @group_link = @project.project_group_links.find(params[:id]) + return render_403 unless can?(current_user, action_member_permission(:admin, @group_link.group), @group_link.group) @group_link.update_attributes(group_link_params) end -- cgit v1.2.1 From cdc55db3452ca82f0dbdcdb631a1fc48abdf1f84 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 10:13:49 +0100 Subject: Fixed members error --- app/controllers/projects/project_members_controller.rb | 2 +- app/models/project_team.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index cd31653698c..617dd9823b9 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -6,7 +6,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController def index @groups = @project.project_group_links - @project_members = @project.team.members(can?(current_user, :admin_project, @project)) + @project_members = @project.team.members(!can?(current_user, :admin_project, @project)) @project_members_size = @project_members.size if params[:search].present? diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 57925a0861a..a58c56288dd 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -52,7 +52,7 @@ class ProjectTeam ProjectMember.truncate_team(project) end - def members(non_invite) + def members(non_invite = false) @members ||= fetch_members(nil, non_invite) end alias_method :users, :members @@ -236,7 +236,7 @@ class ProjectTeam end user_ids = project_members.pluck(:user_id) - user_ids.push(*invited_members.map(&:user_id)) if invited_members.any? && !non_invite + user_ids.push(*invited_members.map(&:user_id)) if invited_members.any? && non_invite user_ids.push(*group_members.pluck(:user_id)) if group User.where(id: user_ids) -- cgit v1.2.1 From 3e19f1976f9a13fc1b13ec49b3ce31c3e114a454 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 10:50:06 +0100 Subject: Fixed issue with invited users not showing up --- app/controllers/projects/project_members_controller.rb | 14 +++++++++++++- app/models/project_team.rb | 8 ++++---- app/views/projects/project_members/_team.html.haml | 5 ++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 617dd9823b9..2175a5d8dcb 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -6,7 +6,19 @@ class Projects::ProjectMembersController < Projects::ApplicationController def index @groups = @project.project_group_links - @project_members = @project.team.members(!can?(current_user, :admin_project, @project)) + + members = [] + project_members = @project.project_members + project_members = project_members.non_invite unless can?(current_user, :admin_project, @project) + members << project_members.pluck(:id) + + if @project.group + group_members = @project.group.group_members + group_members = group_members.non_invite unless can?(current_user, :admin_project, @project) + members << group_members.pluck(:id) + end + + @project_members = Member.where(id: members) @project_members_size = @project_members.size if params[:search].present? diff --git a/app/models/project_team.rb b/app/models/project_team.rb index a58c56288dd..ab6ea2aae36 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -52,8 +52,8 @@ class ProjectTeam ProjectMember.truncate_team(project) end - def members(non_invite = false) - @members ||= fetch_members(nil, non_invite) + def members + @members ||= fetch_members end alias_method :users, :members @@ -197,7 +197,7 @@ class ProjectTeam access.each { |key, value| access[key] = [value, capped_access_level].min } end - def fetch_members(level = nil, non_invite = false) + def fetch_members(level = nil) project_members = project.members group_members = group ? group.members : [] invited_members = [] @@ -236,7 +236,7 @@ class ProjectTeam end user_ids = project_members.pluck(:user_id) - user_ids.push(*invited_members.map(&:user_id)) if invited_members.any? && non_invite + user_ids.push(*invited_members.map(&:user_id)) if invited_members.any? user_ids.push(*group_members.pluck(:user_id)) if group User.where(id: user_ids) diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index 2af9fe0519c..867cb2b97e4 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -4,6 +4,5 @@ %strong #{@project.name} %span.badge= @project_members_size %ul.content-list - - members.each do |user| - - member = @project.team.find_member(user.id) - = render 'shared/members/member', member: member, user: user + - members.each do |member| + = render 'shared/members/member', member: member -- cgit v1.2.1 From 931d09f481d5e174a984c6f874e67273ba2864f0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 10:52:17 +0100 Subject: Fixed search --- .../projects/project_members_controller.rb | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 2175a5d8dcb..7581833eacc 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -10,21 +10,30 @@ class Projects::ProjectMembersController < Projects::ApplicationController members = [] project_members = @project.project_members project_members = project_members.non_invite unless can?(current_user, :admin_project, @project) + + if params[:search].present? + users = @project.users.search(params[:search]).to_a + project_members = project_members.where(user_id: users) + end + members << project_members.pluck(:id) - if @project.group - group_members = @project.group.group_members + @group = @project.group + if @group + group_members = @group.group_members group_members = group_members.non_invite unless can?(current_user, :admin_project, @project) + + if params[:search].present? + users = @group.users.search(params[:search]).to_a + group_members = group_members.where(user_id: users) + end + members << group_members.pluck(:id) end @project_members = Member.where(id: members) @project_members_size = @project_members.size - if params[:search].present? - @project_members = @project_members.search(params[:search]) - end - @project_members = @project_members.page(params[:page]) @requesters = @project.requesters if can?(current_user, :admin_project, @project) -- cgit v1.2.1 From 999f18480511d81b1499b502cbc89a5b34e54544 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 13:35:43 +0100 Subject: Tests update --- app/views/projects/project_members/_groups.html.haml | 2 +- .../project_members/_new_project_member.html.haml | 2 +- app/views/shared/members/_member.html.haml | 2 ++ features/steps/admin/projects.rb | 2 +- features/steps/group/members.rb | 4 ++-- features/steps/project/team_management.rb | 15 +++++++-------- .../groups/members/owner_manages_access_requests_spec.rb | 2 +- .../members/master_manages_access_requests_spec.rb | 2 +- 8 files changed, 16 insertions(+), 15 deletions(-) diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml index 79791af7963..340e4cd06b8 100644 --- a/app/views/projects/project_members/_groups.html.haml +++ b/app/views/projects/project_members/_groups.html.haml @@ -1,4 +1,4 @@ -.panel.panel-default +.panel.panel-default.project-members-groups .panel-heading Groups with access to %strong #{@project.name} diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml index c0b187fb460..26e06a14c07 100644 --- a/app/views/projects/project_members/_new_project_member.html.haml +++ b/app/views/projects/project_members/_new_project_member.html.haml @@ -1,4 +1,4 @@ -= form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project) do |f| += form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'users-project-form' } do |f| .row .col-md-4.col-lg-6 = users_select_tag(:user_ids, multiple: true, class: "input-full", scope: :all, email_user: true) diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 2d4853eef92..2f98eeff658 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -79,3 +79,5 @@ %span.visible-xs-block Delete = icon('trash', class: 'hidden-xs') + - else + %span.member-access-text= member.human_access diff --git a/features/steps/admin/projects.rb b/features/steps/admin/projects.rb index d77945a6b9c..2b8cd030ace 100644 --- a/features/steps/admin/projects.rb +++ b/features/steps/admin/projects.rb @@ -70,7 +70,7 @@ class Spinach::Features::AdminProjects < Spinach::FeatureSteps select "Developer", from: "access_level" end - click_button "Add users to project" + click_button "Add to project" end step 'I should see current user as "Developer"' do diff --git a/features/steps/group/members.rb b/features/steps/group/members.rb index e9b45823c67..4aec3d03ef6 100644 --- a/features/steps/group/members.rb +++ b/features/steps/group/members.rb @@ -1,4 +1,5 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps + include WaitForAjax include SharedAuthentication include SharedPaths include SharedGroup @@ -116,9 +117,8 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps member = mary_jane_member page.within "#group_member_#{member.id}" do - click_button 'Edit' select 'Developer', from: "member_access_level_#{member.id}" - click_on 'Save' + wait_for_ajax end end diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb index e920f5a706b..49821b85922 100644 --- a/features/steps/project/team_management.rb +++ b/features/steps/project/team_management.rb @@ -22,7 +22,7 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps select2(user.id, from: "#user_ids", multiple: true) select "Reporter", from: "access_level" end - click_button "Add users to project" + click_button "Add to project" end step 'I should see "Mike" in team list as "Reporter"' do @@ -36,10 +36,10 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps step 'I select "sjobs@apple.com" as "Reporter"' do page.within ".users-project-form" do - select2("sjobs@apple.com", from: "#user_ids", multiple: true) + find('#user_ids', visible: false).set('sjobs@apple.com') select "Reporter", from: "access_level" end - click_button "Add users to project" + click_button "Add to project" end step 'I should see "sjobs@apple.com" in team list as invited "Reporter"' do @@ -65,9 +65,7 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps user = User.find_by(name: 'Dmitriy') project_member = project.project_members.find_by(user_id: user.id) page.within "#project_member_#{project_member.id}" do - click_button 'Edit' select "Reporter", from: "member_access_level_#{project_member.id}" - click_button "Save" end end @@ -144,8 +142,9 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps end step 'I should see "Opensource" group user listing' do - expect(page).to have_content("Shared with OpenSource group, members with Master role (2)") - expect(page).to have_content(@os_user1.name) - expect(page).to have_content(@os_user2.name) + page.within '.project-members-groups' do + expect(page).to have_content('OpenSource') + expect(find('select').value).to eq('40') + end end end diff --git a/spec/features/groups/members/owner_manages_access_requests_spec.rb b/spec/features/groups/members/owner_manages_access_requests_spec.rb index 10d3713f19f..d811b05b0c3 100644 --- a/spec/features/groups/members/owner_manages_access_requests_spec.rb +++ b/spec/features/groups/members/owner_manages_access_requests_spec.rb @@ -41,7 +41,7 @@ feature 'Groups > Members > Owner manages access requests', feature: true do def expect_visible_access_request(group, user) expect(group.requesters.exists?(user_id: user)).to be_truthy - expect(page).to have_content "#{group.name} access requests 1" + expect(page).to have_content "Users requesting access to #{group.name} 1" expect(page).to have_content user.name end end diff --git a/spec/features/projects/members/master_manages_access_requests_spec.rb b/spec/features/projects/members/master_manages_access_requests_spec.rb index f7fcd9b6731..d15376931c3 100644 --- a/spec/features/projects/members/master_manages_access_requests_spec.rb +++ b/spec/features/projects/members/master_manages_access_requests_spec.rb @@ -41,7 +41,7 @@ feature 'Projects > Members > Master manages access requests', feature: true do def expect_visible_access_request(project, user) expect(project.requesters.exists?(user_id: user)).to be_truthy - expect(page).to have_content "#{project.name} access requests 1" + expect(page).to have_content "Users requesting access to #{project.name} 1" expect(page).to have_content user.name end end -- cgit v1.2.1 From a56216c8bd1ef82c09c7ce39596e4b6436ebb7fa Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 14:06:20 +0100 Subject: Added import button back in --- app/views/projects/project_members/index.html.haml | 4 ++-- features/steps/project/team_management.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index abe10433387..d289d75454d 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,15 +1,15 @@ - page_title "Members" .project-members-page.js-project-members-page.prepend-top-default - %h4 + %h4.clearfix Members + = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default pull-right hidden-xs", title: "Import members from another project" %hr - if can?(current_user, :admin_project_member, @project) .project-members-new.append-bottom-default %h5.clearfix Add new user to %strong= @project.name - -# = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default pull-right", title: "Import members from another project" = render "new_project_member" = render 'shared/members/requests', membership_source: @project, requesters: @requesters diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb index 49821b85922..b21d0849ad1 100644 --- a/features/steps/project/team_management.rb +++ b/features/steps/project/team_management.rb @@ -110,7 +110,7 @@ class Spinach::Features::ProjectTeamManagement < Spinach::FeatureSteps end step 'I click link "Import team from another project"' do - click_link "Import members from another project" + click_link "Import" end When 'I submit "Website" project for import team' do -- cgit v1.2.1 From ccf76831da422298242ce3d8d11f72ab50454c85 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 14:19:11 +0100 Subject: Updated groups member UI to match --- app/assets/javascripts/dispatcher.js | 4 +- app/assets/javascripts/groups.js | 13 ------- app/assets/javascripts/members.js.es6 | 45 ++++++++++++++++++++++ app/assets/javascripts/project_members.js.es6 | 45 ---------------------- .../group_members/_new_group_member.html.haml | 35 ++++++++--------- app/views/groups/group_members/index.html.haml | 40 +++++++++---------- app/views/projects/project_members/index.html.haml | 2 +- 7 files changed, 81 insertions(+), 103 deletions(-) delete mode 100644 app/assets/javascripts/groups.js create mode 100644 app/assets/javascripts/members.js.es6 delete mode 100644 app/assets/javascripts/project_members.js.es6 diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index c95aaf61443..da3757d8992 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -127,12 +127,12 @@ break; case 'groups:group_members:index': new gl.MemberExpirationDate(); - new GroupMembers(); + new gl.Members(); new UsersSelect(); break; case 'projects:project_members:index': new gl.MemberExpirationDate(); - new gl.ProjectMembers(); + new gl.Members(); new UsersSelect(); break; case 'groups:new': diff --git a/app/assets/javascripts/groups.js b/app/assets/javascripts/groups.js deleted file mode 100644 index 4382dd6860f..00000000000 --- a/app/assets/javascripts/groups.js +++ /dev/null @@ -1,13 +0,0 @@ -(function() { - this.GroupMembers = (function() { - function GroupMembers() { - $('li.group_member').bind('ajax:success', function() { - return $(this).fadeOut(); - }); - } - - return GroupMembers; - - })(); - -}).call(this); diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6 new file mode 100644 index 00000000000..fa259520810 --- /dev/null +++ b/app/assets/javascripts/members.js.es6 @@ -0,0 +1,45 @@ +((w) => { + w.gl = w.gl || {}; + + class Members { + constructor() { + this.removeListeners(); + this.addListeners(); + } + + removeListeners() { + $('.project_member, .group_member').off('ajax:success'); + $('.js-member-update-control').off('change'); + $('.js-edit-member-form').off('ajax:success'); + } + + addListeners() { + $('.project_member, .group_member').on('ajax:success', this.removeRow); + $('.js-member-update-control').on('change', function () { + $(this).closest('form') + .trigger("submit.rails"); + $(this).disable(); + }); + $('.js-edit-member-form').on('ajax:success', function () { + $(this).find('.js-member-update-control').enable(); + }); + } + + removeRow(e) { + const $target = $(e.target); + + if ($target.hasClass('btn-remove')) { + $target.closest('.member') + .fadeOut(function () { + $(this).remove(); + }); + } + } + + submitForm() { + + } + } + + gl.Members = Members; +})(window); diff --git a/app/assets/javascripts/project_members.js.es6 b/app/assets/javascripts/project_members.js.es6 deleted file mode 100644 index 56bc98d1076..00000000000 --- a/app/assets/javascripts/project_members.js.es6 +++ /dev/null @@ -1,45 +0,0 @@ -((w) => { - w.gl = w.gl || {}; - - class ProjectMembers { - constructor() { - this.removeListeners(); - this.addListeners(); - } - - removeListeners() { - $('.project_member, .group_member').off('ajax:success'); - $('.js-member-update-control').off('change'); - $('.js-edit-member-form').off('ajax:success'); - } - - addListeners() { - $('.project_member, .group_member').on('ajax:success', this.removeRow); - $('.js-member-update-control').on('change', function () { - $(this).closest('form') - .trigger("submit.rails"); - $(this).disable(); - }); - $('.js-edit-member-form').on('ajax:success', function () { - $(this).find('.js-member-update-control').enable(); - }); - } - - removeRow(e) { - const $target = $(e.target); - - if ($target.hasClass('btn-remove')) { - $target.closest('.member') - .fadeOut(function () { - $(this).remove(); - }); - } - } - - submitForm() { - - } - } - - gl.ProjectMembers = ProjectMembers; -})(window); diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml index 2fb3190ab11..2987befd2a4 100644 --- a/app/views/groups/group_members/_new_group_member.html.haml +++ b/app/views/groups/group_members/_new_group_member.html.haml @@ -1,27 +1,22 @@ -= form_for @group_member, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f| - .form-group - = f.label :user_ids, "People", class: 'control-label' - .col-sm-10 - = users_select_tag(:user_ids, multiple: true, class: 'input-large', scope: :all, email_user: true) - .help-block += form_for @group_member, url: group_group_members_path(@group), html: { class: 'users-project-form users-group-form' } do |f| + .row + .col-md-4.col-lg-6 + = users_select_tag(:user_ids, multiple: true, class: 'input-full', scope: :all, email_user: true) + .help-block.append-bottom-10 Search for users by name, username, or email, or invite new ones using their email address. - .form-group - = f.label :access_level, "Group Access", class: 'control-label' - .col-sm-10 - = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "project-access-select select2" - .help-block - Read more about role permissions - %strong= link_to "here", help_page_path("user/permissions"), class: "vlink" + .col-md-3.col-lg-2 + = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @group_member.access_level), class: "form-control project-access-select" + .help-block.append-bottom-10 + = link_to "Read more", help_page_path("user/permissions"), class: "vlink" + about role permissions - .form-group - = f.label :expires_at, 'Access expiration date', class: 'control-label' - .col-sm-10 + .col-md-3.col-lg-2 .clearable-input - = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Select access expiration date' + = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date' %i.clear-icon.js-clear-input - .help-block + .help-block.append-bottom-10 On this date, the user(s) will automatically lose access to this group and all of its projects. - .form-actions - = f.submit 'Add users to group', class: "btn btn-create" + .col-md-2 + = f.submit 'Add to group', class: "btn btn-create btn-block" diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index f789796e942..d2c7ec2e821 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,35 +1,31 @@ - page_title "Members" -.group-members-page.prepend-top-default +.project-members-page.prepend-top-default + %h4 + Members + %hr - if can?(current_user, :admin_group_member, @group) - .panel.panel-default - .panel-heading - Add new user to group - .panel-body - %p.light - Members of group have access to all group projects. - .new-group-member-holder - = render "new_group_member" + .project-members-new.append-bottom-default + %h5.clearfix + Add new user to + %strong= @group.name + = render "new_group_member" = render 'shared/members/requests', membership_source: @group, requesters: @requesters + .append-bottom-default.clearfix + %h5.member.existing-title + Existing users + = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do + .form-group + = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } + %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" } + = icon("search") .panel.panel-default .panel-heading + Users with access to %strong #{@group.name} - group members %span.badge= @members.total_count - .controls - = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do - .form-group - = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false } - = button_tag class: 'btn', title: 'Search' do - = icon("search") %ul.content-list = render partial: 'shared/members/member', collection: @members, as: :member = paginate @members, theme: 'gitlab' - -:javascript - $('form.member-search-form').on('submit', function(event) { - event.preventDefault(); - Turbolinks.visit(this.action + '?' + $(this).serialize()); - }); diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index d289d75454d..a90de32bd47 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,6 +1,6 @@ - page_title "Members" -.project-members-page.js-project-members-page.prepend-top-default +.project-members-page.prepend-top-default %h4.clearfix Members = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default pull-right hidden-xs", title: "Import members from another project" -- cgit v1.2.1 From 2c3fa33ca2e75792d1027eb73e2f69fed67bc435 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 15:10:22 +0100 Subject: Updated some specs Fixed issue with group name not showing --- .../projects/project_members_controller.rb | 19 +++++++++---------- app/views/projects/project_members/_team.html.haml | 2 +- app/views/projects/project_members/index.html.haml | 4 ++-- app/views/shared/members/_member.html.haml | 7 ++++--- features/steps/group/members.rb | 8 ++++---- .../master_adds_member_with_expiration_date_spec.rb | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 7581833eacc..bf6ac25266a 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -7,7 +7,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController def index @groups = @project.project_group_links - members = [] project_members = @project.project_members project_members = project_members.non_invite unless can?(current_user, :admin_project, @project) @@ -16,25 +15,25 @@ class Projects::ProjectMembersController < Projects::ApplicationController project_members = project_members.where(user_id: users) end - members << project_members.pluck(:id) + members_ids = project_members.pluck(:id) - @group = @project.group - if @group - group_members = @group.group_members + group = @project.group + if group + group_members = group.group_members group_members = group_members.non_invite unless can?(current_user, :admin_project, @project) if params[:search].present? - users = @group.users.search(params[:search]).to_a + users = group.users.search(params[:search]).to_a group_members = group_members.where(user_id: users) end - members << group_members.pluck(:id) + members_ids << group_members.pluck(:id) end - @project_members = Member.where(id: members) - @project_members_size = @project_members.size + @members = Member.where(id: members_ids.flatten) + @members_size = @members.size - @project_members = @project_members.page(params[:page]) + @members = @members.page(params[:page]) @requesters = @project.requesters if can?(current_user, :admin_project, @project) diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index 867cb2b97e4..d9799033e17 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -2,7 +2,7 @@ .panel-heading Users with access to %strong #{@project.name} - %span.badge= @project_members_size + %span.badge= @members_size %ul.content-list - members.each do |member| = render 'shared/members/member', member: member diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index a90de32bd47..80882d0c11c 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -25,5 +25,5 @@ - if @groups.size > 0 = render 'groups', groups: @groups - = render 'team', members: @project_members - = paginate @project_members, theme: "gitlab" + = render 'team', members: @members + = paginate @members, theme: "gitlab" diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 2f98eeff658..6f8c3c4da2e 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -1,6 +1,7 @@ - show_roles = local_assigns.fetch(:show_roles, true) - show_controls = local_assigns.fetch(:show_controls, true) - user = local_assigns.fetch(:user, member.user) +- source = member.source %li.member{ class: dom_class(member), id: dom_id(member) } %span{ class: ("list-item-name" if show_controls) } @@ -17,9 +18,9 @@ %label.label.label-danger %strong Blocked - - if member.respond_to?(:group) && !@group - = link_to member.group, class: "member-group-link prepend-left-5" do - = "· #{member.group.name}" + - if source.instance_of?(Group) && !@group + = link_to source, class: "member-group-link prepend-left-5" do + = "· #{source.name}" .hidden-xs.cgray - if member.request? diff --git a/features/steps/group/members.rb b/features/steps/group/members.rb index 4aec3d03ef6..e54add1d568 100644 --- a/features/steps/group/members.rb +++ b/features/steps/group/members.rb @@ -14,7 +14,7 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps select "Reporter", from: "access_level" end - click_button "Add users to group" + click_button "Add to group" end step 'I select "Mike" as "Master"' do @@ -25,7 +25,7 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps select "Master", from: "access_level" end - click_button "Add users to group" + click_button "Add to group" end step 'I should see "Mike" in team list as "Reporter"' do @@ -48,7 +48,7 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps select "Reporter", from: "access_level" end - click_button "Add users to group" + click_button "Add to group" end step 'I should see "sjobs@apple.com" in team list as invited "Reporter"' do @@ -67,7 +67,7 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps select "Reporter", from: "access_level" end - click_button "Add users to group" + click_button "Add to group" end step 'I should see user "John Doe" in team list' do diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb index 430c384ac2e..27a83fdcd1f 100644 --- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb +++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' feature 'Projects > Members > Master adds member with expiration date', feature: true, js: true do + include WaitForAjax include Select2Helper include ActiveSupport::Testing::TimeHelpers @@ -20,7 +21,7 @@ feature 'Projects > Members > Master adds member with expiration date', feature: page.within '.users-project-form' do select2(new_member.id, from: '#user_ids', multiple: true) fill_in 'expires_at', with: '2016-08-10' - click_on 'Add users to project' + click_on 'Add to project' end page.within '.project_member:first-child' do @@ -35,9 +36,8 @@ feature 'Projects > Members > Master adds member with expiration date', feature: visit namespace_project_project_members_path(project.namespace, project) page.within '.project_member:first-child' do - click_on 'Edit' - fill_in 'Access expiration date', with: '2016-08-09' - click_on 'Save' + find('.js-access-expiration-date').set '2016-08-09' + wait_for_ajax expect(page).to have_content('Expires in 3 days') end end -- cgit v1.2.1 From 638376c35494860936bf2858c01115dc4afe0bfe Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 15:44:46 +0100 Subject: Fixed group tests --- features/steps/admin/groups.rb | 2 +- features/steps/group/members.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/steps/admin/groups.rb b/features/steps/admin/groups.rb index 0c89a3db9ad..9396a76f0a2 100644 --- a/features/steps/admin/groups.rb +++ b/features/steps/admin/groups.rb @@ -105,7 +105,7 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps select "Developer", from: "access_level" end - click_button "Add users to group" + click_button "Add to group" end step 'I should see current user as "Developer"' do diff --git a/features/steps/group/members.rb b/features/steps/group/members.rb index e54add1d568..cefc55d07ab 100644 --- a/features/steps/group/members.rb +++ b/features/steps/group/members.rb @@ -109,7 +109,7 @@ class Spinach::Features::GroupMembers < Spinach::FeatureSteps step 'I search for \'Mary\' member' do page.within '.member-search-form' do fill_in 'search', with: 'Mary' - click_button 'Search' + find('.member-search-btn').click end end -- cgit v1.2.1 From 97a51817bf1e6b0504bb84b686daf7e931ded2da Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 17:39:16 +0100 Subject: Fixed error when updating groups --- app/controllers/projects/group_links_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index b5e314dced3..3574ecf2811 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -21,7 +21,7 @@ class Projects::GroupLinksController < Projects::ApplicationController def update @group_link = @project.project_group_links.find(params[:id]) - return render_403 unless can?(current_user, action_member_permission(:admin, @group_link.group), @group_link.group) + return render_403 unless can?(current_user, :admin_group, @group_link.group) @group_link.update_attributes(group_link_params) end -- cgit v1.2.1 From e747626fad5c0e675d6a5cd5b6fcd482f10dad90 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 5 Sep 2016 09:24:47 +0100 Subject: Added test for updating groups permissions --- app/controllers/projects/group_links_controller.rb | 2 +- app/views/shared/members/_group.html.haml | 6 ++-- spec/features/projects/members/group_links_spec.rb | 37 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 spec/features/projects/members/group_links_spec.rb diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index 3574ecf2811..7b4c39cdb8f 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -21,7 +21,7 @@ class Projects::GroupLinksController < Projects::ApplicationController def update @group_link = @project.project_group_links.find(params[:id]) - return render_403 unless can?(current_user, :admin_group, @group_link.group) + return render_403 unless can?(current_user, :admin_project_member, @project) @group_link.update_attributes(group_link_params) end diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index 19b58ef20ae..56d31a949ff 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -13,11 +13,11 @@ Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)} .controls.member-controls = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal js-edit-member-form' do - = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}", disabled: !can?(current_user, action_member_permission(:admin, group), group) + = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}", disabled: !can?(current_user, :admin_project_member, @project) .prepend-left-5.clearable-input.member-form-control - = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can?(current_user, action_member_permission(:admin, group), group) + = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can?(current_user, :admin_project_member, @project) %i.clear-icon.js-clear-input - - if can?(current_user, action_member_permission(:admin, group), group) + - if can?(current_user, :admin_project_member, @project) = link_to namespace_project_group_link_path(@project.namespace, @project, group_link), remote: true, method: :delete, diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb new file mode 100644 index 00000000000..3d59df20197 --- /dev/null +++ b/spec/features/projects/members/group_links_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +feature 'Projects > Members > Anonymous user sees members', feature: true, js: true do + include WaitForAjax + + let(:user) { create(:user) } + let(:group) { create(:group, :public) } + let(:project) { create(:empty_project, :public) } + + background do + project.team << [user, :master] + @group_link = create(:project_group_link, project: project, group: group) + + login_as(user) + visit namespace_project_project_members_path(project.namespace, project) + end + + it 'updates group access level' do + select 'Guest', from: "member_access_level_#{group.id}" + wait_for_ajax + + visit namespace_project_project_members_path(project.namespace, project) + + expect(page).to have_select("member_access_level_#{group.id}", selected: 'Guest') + end + + it 'updates expiry date' do + tomorrow = Date.today + 3 + + fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F") + wait_for_ajax + + page.within(first('li.member')) do + expect(page).to have_content('Expires in 3 days') + end + end +end -- cgit v1.2.1 From fe71edc3336ae662997ebbad3b4c46b2a2b4927c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 5 Sep 2016 15:11:45 +0100 Subject: JS update --- app/assets/javascripts/members.js.es6 | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6 index fa259520810..7986987e49a 100644 --- a/app/assets/javascripts/members.js.es6 +++ b/app/assets/javascripts/members.js.es6 @@ -15,14 +15,8 @@ addListeners() { $('.project_member, .group_member').on('ajax:success', this.removeRow); - $('.js-member-update-control').on('change', function () { - $(this).closest('form') - .trigger("submit.rails"); - $(this).disable(); - }); - $('.js-edit-member-form').on('ajax:success', function () { - $(this).find('.js-member-update-control').enable(); - }); + $('.js-member-update-control').on('change', this.formSubmit); + $('.js-edit-member-form').on('ajax:success', this.formSuccess); } removeRow(e) { @@ -36,8 +30,16 @@ } } - submitForm() { + formSubmit() { + const $this = $(this); + $this.disable() + .closest('form') + .trigger("submit.rails"); + } + + formSuccess() { + $(this).find('.js-member-update-control').enable(); } } -- cgit v1.2.1 From 3354bfd8f92ba034816890f0ea89bca630405103 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 5 Sep 2016 15:45:23 +0100 Subject: CSS cleanup --- app/assets/stylesheets/framework/selects.scss | 4 ---- app/assets/stylesheets/pages/members.scss | 10 +++------- app/views/groups/group_members/_new_group_member.html.haml | 2 +- app/views/groups/group_members/index.html.haml | 2 +- .../projects/project_members/_new_project_member.html.haml | 2 +- app/views/projects/project_members/index.html.haml | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index 746ab89abd2..b309e2ad9f4 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -191,10 +191,6 @@ &.input-clamp { max-width: 100%; } - - &.input-full { - width: 100%; - } } .select2-highlighted { diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index a7f1324f69a..72f31cb1168 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -1,9 +1,3 @@ -.project-members-new { - > h5 { - font-weight: normal; - } -} - .member { .list-item-name { float: none; @@ -16,6 +10,7 @@ .controls { @media (min-width: $screen-sm-min) { + display: -webkit-flex; display: flex; width: 400px; max-width: 50%; @@ -26,8 +21,9 @@ margin-top: 5px; @media (min-width: $screen-sm-min) { + display: -webkit-flex; display: flex; - flex: 1; + width: 100%; margin-top: 3px; } } diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml index 2987befd2a4..b185b81db7f 100644 --- a/app/views/groups/group_members/_new_group_member.html.haml +++ b/app/views/groups/group_members/_new_group_member.html.haml @@ -1,7 +1,7 @@ = form_for @group_member, url: group_group_members_path(@group), html: { class: 'users-project-form users-group-form' } do |f| .row .col-md-4.col-lg-6 - = users_select_tag(:user_ids, multiple: true, class: 'input-full', scope: :all, email_user: true) + = users_select_tag(:user_ids, multiple: true, class: 'input-clamp', scope: :all, email_user: true) .help-block.append-bottom-10 Search for users by name, username, or email, or invite new ones using their email address. diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index d2c7ec2e821..ebf9aca7700 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -6,7 +6,7 @@ %hr - if can?(current_user, :admin_group_member, @group) .project-members-new.append-bottom-default - %h5.clearfix + %p.clearfix Add new user to %strong= @group.name = render "new_group_member" diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml index 26e06a14c07..79dcd7a6ee9 100644 --- a/app/views/projects/project_members/_new_project_member.html.haml +++ b/app/views/projects/project_members/_new_project_member.html.haml @@ -1,7 +1,7 @@ = form_for @project_member, as: :project_member, url: namespace_project_project_members_path(@project.namespace, @project), html: { class: 'users-project-form' } do |f| .row .col-md-4.col-lg-6 - = users_select_tag(:user_ids, multiple: true, class: "input-full", scope: :all, email_user: true) + = users_select_tag(:user_ids, multiple: true, class: "input-clamp", scope: :all, email_user: true) .help-block.append-bottom-10 Search for users by name, username, or email, or invite new ones using their email address. diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 80882d0c11c..86b2752cc0b 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -7,7 +7,7 @@ %hr - if can?(current_user, :admin_project_member, @project) .project-members-new.append-bottom-default - %h5.clearfix + %p.clearfix Add new user to %strong= @project.name = render "new_project_member" -- cgit v1.2.1 From 68c7b52364307e26ef7a85b80aa11242abbfa5b6 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 5 Sep 2016 17:14:42 +0100 Subject: Fixed fields not being sent --- app/assets/javascripts/members.js.es6 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6 index 7986987e49a..12d212ca185 100644 --- a/app/assets/javascripts/members.js.es6 +++ b/app/assets/javascripts/members.js.es6 @@ -33,9 +33,10 @@ formSubmit() { const $this = $(this); - $this.disable() - .closest('form') + $this.closest('form') .trigger("submit.rails"); + + $this.disable(); } formSuccess() { -- cgit v1.2.1 From 11c0c6509251a280f46c6be74da64a1cd7a5e190 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 10:06:13 +0100 Subject: Expires in test update --- spec/features/projects/members/group_links_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 3d59df20197..2085e875f12 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -31,7 +31,7 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t wait_for_ajax page.within(first('li.member')) do - expect(page).to have_content('Expires in 3 days') + expect(page).to have_content('Expires in') end end end -- cgit v1.2.1 From 73c4da1780c5086543eb998d5bc9cbd632ef6576 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 16:20:20 +0100 Subject: Fixed removing groups --- app/controllers/projects/group_links_controller.rb | 7 ++++++- app/views/shared/members/_group.html.haml | 3 ++- spec/features/projects/members/group_links_spec.rb | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index 7b4c39cdb8f..7b6f07465e0 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -29,7 +29,12 @@ class Projects::GroupLinksController < Projects::ApplicationController def destroy project.project_group_links.find(params[:id]).destroy - redirect_to namespace_project_group_links_path(project.namespace, project) + respond_to do |format| + format.html do + redirect_to namespace_project_group_links_path(project.namespace, project) + end + format.js { head :ok } + end end protected diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index 56d31a949ff..171a388b233 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -1,6 +1,6 @@ - group = local_assigns[:group] - group_link = local_assigns[:group_link] -%li.member{ class: dom_class(group), id: dom_id(group) } +%li.member.group_member{ id: "group_member_#{group_link.id}" } %span{ class: "list-item-name" } = image_tag group_icon(group), class: "avatar s40", alt: '' %strong @@ -21,6 +21,7 @@ = link_to namespace_project_group_link_path(@project.namespace, @project, group_link), remote: true, method: :delete, + data: { confirm: "Are you sure you want to remove #{group.name}?" }, class: 'btn btn-remove prepend-left-10' do %span.visible-xs-block Delete diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 2085e875f12..7870bc663b1 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -34,4 +34,13 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t expect(page).to have_content('Expires in') end end + + it 'deletes group link' do + page.within(first('.group_member')) do + find('.btn-remove').click + end + wait_for_ajax + + expect(page).not_to have_selector('.group_member') + end end -- cgit v1.2.1 From 2b41db9215f322ba61113a7bef2f49da157bbd53 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 16:48:48 +0100 Subject: Search project groups --- .../projects/project_members_controller.rb | 49 ++++++++++++++++++---- spec/features/projects/members/group_links_spec.rb | 20 +++++++++ 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index bf6ac25266a..ac83377148a 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -10,23 +10,30 @@ class Projects::ProjectMembersController < Projects::ApplicationController project_members = @project.project_members project_members = project_members.non_invite unless can?(current_user, :admin_project, @project) - if params[:search].present? - users = @project.users.search(params[:search]).to_a - project_members = project_members.where(user_id: users) - end - - members_ids = project_members.pluck(:id) - group = @project.group + if group group_members = group.group_members group_members = group_members.non_invite unless can?(current_user, :admin_project, @project) + end + + if params[:search].present? + groups_id = @groups.pluck(:group_id) + groups = Group.where(id: groups_id).search(params[:search]).to_a + @groups = @project.project_group_links.where(group_id: groups) + + users = @project.users.search(params[:search]).to_a + project_members = project_members.where(user_id: users) - if params[:search].present? + if group_members users = group.users.search(params[:search]).to_a group_members = group_members.where(user_id: users) end + end + members_ids = project_members.pluck(:id) + + if group_members members_ids << group_members.pluck(:id) end @@ -48,6 +55,17 @@ class Projects::ProjectMembersController < Projects::ApplicationController current_user: current_user ) + group_ids = params[:group_ids].split(',') + groups = Group.where(id: group_ids) + + groups.each do |group| + project.project_group_links.create( + group: group, + group_access: params[:access_level], + expires_at: params[:expires_at] + ) + end + redirect_to namespace_project_project_members_path(@project.namespace, @project) end @@ -101,6 +119,21 @@ class Projects::ProjectMembersController < Projects::ApplicationController notice: notice) end + def options + users = User.all + users = users.search(params[:search]) if params[:search].present? + users = users.page(1) + + groups = Group.all + groups = groups.search(params[:search]) if params[:search].present? + groups = groups.page(1) + + render json: { + Groups: groups.as_json(only: [:id, :name], methods: [:avatar_url]), + Users: users.as_json(only: [:id, :name, :username], methods: [:avatar_url]), + } + end + protected def member_params diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 7870bc663b1..14ab7541fad 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -43,4 +43,24 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t expect(page).not_to have_selector('.group_member') end + + context 'search' do + it 'finds no results' do + page.within '.member-search-form' do + fill_in 'search', with: 'testing 123' + find('.member-search-btn').click + end + + expect(page).not_to have_selector('.group_member') + end + + it 'finds results' do + page.within '.member-search-form' do + fill_in 'search', with: group.name + find('.member-search-btn').click + end + + expect(page).to have_selector('.group_member', count: 1) + end + end end -- cgit v1.2.1 From 401b797671b9b67ef40c4afa75acdeca83b6a6de Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 17:11:58 +0100 Subject: Fixed bug when group_ids not present when creating --- .../projects/project_members_controller.rb | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index ac83377148a..d49598d2786 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -55,15 +55,17 @@ class Projects::ProjectMembersController < Projects::ApplicationController current_user: current_user ) - group_ids = params[:group_ids].split(',') - groups = Group.where(id: group_ids) - - groups.each do |group| - project.project_group_links.create( - group: group, - group_access: params[:access_level], - expires_at: params[:expires_at] - ) + if params[:group_ids].present? + group_ids = params[:group_ids].split(',') + groups = Group.where(id: group_ids) + + groups.each do |group| + project.project_group_links.create( + group: group, + group_access: params[:access_level], + expires_at: params[:expires_at] + ) + end end redirect_to namespace_project_project_members_path(@project.namespace, @project) -- cgit v1.2.1 From ecf7640b28562468880dda97ba42e5fd18c0859f Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 10:58:52 +0100 Subject: Fixed group_links expire date not updating in view --- app/views/projects/group_links/update.js.haml | 2 +- spec/features/projects/members/group_links_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/group_links/update.js.haml b/app/views/projects/group_links/update.js.haml index d3a37847f58..231d5a79723 100644 --- a/app/views/projects/group_links/update.js.haml +++ b/app/views/projects/group_links/update.js.haml @@ -1,3 +1,3 @@ :plain var $listItem = $('#{escape_javascript(render('shared/members/group', group_link: @group_link, group: @group_link.group))}'); - $("##{dom_id(@group_link.group)} .list-item-name").replaceWith($listItem.find('.list-item-name')); + $("#group_member_#{@group_link.id} .list-item-name").replaceWith($listItem.find('.list-item-name')); diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 14ab7541fad..cc2f695211c 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -30,7 +30,7 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F") wait_for_ajax - page.within(first('li.member')) do + page.within(find('li.group_member')) do expect(page).to have_content('Expires in') end end -- cgit v1.2.1 From d8fee09e338006acb09c80ebcb032b6a75f3d7cd Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 12:36:21 +0100 Subject: Fixed jQuery chaining --- app/assets/javascripts/members.js.es6 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6 index 12d212ca185..1b4b3f38838 100644 --- a/app/assets/javascripts/members.js.es6 +++ b/app/assets/javascripts/members.js.es6 @@ -31,12 +31,10 @@ } formSubmit() { - const $this = $(this); - - $this.closest('form') - .trigger("submit.rails"); - - $this.disable(); + $(this).closest('form') + .trigger("submit.rails") + .end() + .disable(); } formSuccess() { -- cgit v1.2.1 From 2abbb0980f061d4297aab02f914c324c7fbe073b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 14:26:07 +0100 Subject: Removed group members from the list for now --- .../projects/project_members_controller.rb | 25 ---------------------- 1 file changed, 25 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index d49598d2786..64cbc76da6f 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -10,33 +10,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController project_members = @project.project_members project_members = project_members.non_invite unless can?(current_user, :admin_project, @project) - group = @project.group - - if group - group_members = group.group_members - group_members = group_members.non_invite unless can?(current_user, :admin_project, @project) - end - - if params[:search].present? - groups_id = @groups.pluck(:group_id) - groups = Group.where(id: groups_id).search(params[:search]).to_a - @groups = @project.project_group_links.where(group_id: groups) - - users = @project.users.search(params[:search]).to_a - project_members = project_members.where(user_id: users) - - if group_members - users = group.users.search(params[:search]).to_a - group_members = group_members.where(user_id: users) - end - end - members_ids = project_members.pluck(:id) - if group_members - members_ids << group_members.pluck(:id) - end - @members = Member.where(id: members_ids.flatten) @members_size = @members.size -- cgit v1.2.1 From 7cca8ffe60f4cdc7ca012cf223c6d7855b928685 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 8 Sep 2016 10:45:53 +0100 Subject: Ruby update --- app/controllers/projects/project_members_controller.rb | 14 +++++++------- app/views/projects/project_members/_team.html.haml | 2 +- app/views/projects/project_members/index.html.haml | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 64cbc76da6f..1c49ebfb99d 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -7,15 +7,15 @@ class Projects::ProjectMembersController < Projects::ApplicationController def index @groups = @project.project_group_links - project_members = @project.project_members - project_members = project_members.non_invite unless can?(current_user, :admin_project, @project) + @project_members = @project.project_members + @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project) - members_ids = project_members.pluck(:id) - - @members = Member.where(id: members_ids.flatten) - @members_size = @members.size + if params[:search].present? + users = @project.users.search(params[:search]).to_a + @project_members = @project_members.where(user_id: users) + end - @members = @members.page(params[:page]) + @project_members = @project_members.page(params[:page]) @requesters = @project.requesters if can?(current_user, :admin_project, @project) diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index d9799033e17..ff54035cfe1 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -2,7 +2,7 @@ .panel-heading Users with access to %strong #{@project.name} - %span.badge= @members_size + %span.badge= @project_members.total_count %ul.content-list - members.each do |member| = render 'shared/members/member', member: member diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 86b2752cc0b..f566748e95a 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -25,5 +25,5 @@ - if @groups.size > 0 = render 'groups', groups: @groups - = render 'team', members: @members - = paginate @members, theme: "gitlab" + = render 'team', members: @project_members + = paginate @project_members, theme: "gitlab" -- cgit v1.2.1 From b61cd8a3930f194333ea417a03d53a0ad91efa42 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 9 Sep 2016 10:45:55 +0100 Subject: Added back ordering --- app/controllers/projects/project_members_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 1c49ebfb99d..5fd2e77a51a 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -15,6 +15,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController @project_members = @project_members.where(user_id: users) end + @project_members = @project_members.order('access_level DESC') @project_members = @project_members.page(params[:page]) @requesters = @project.requesters if can?(current_user, :admin_project, @project) -- cgit v1.2.1 From aac80d76c272523a1ee7c9ef751034e955dfab9e Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 9 Sep 2016 11:31:57 +0100 Subject: Group links search test fix --- app/controllers/projects/project_members_controller.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 5fd2e77a51a..4d27617608d 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -13,6 +13,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController if params[:search].present? users = @project.users.search(params[:search]).to_a @project_members = @project_members.where(user_id: users) + + group_ids = @groups.pluck(:group_id) + group_ids = Group.where(id: group_ids).search(params[:search]).to_a + @groups = @project.project_group_links.where(group_id: group_ids) end @project_members = @project_members.order('access_level DESC') -- cgit v1.2.1 From b8d41220bde1b5c1f0e86a3346959fc7b760ccf5 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 12 Sep 2016 15:34:54 +0100 Subject: Admin group members UI fix --- app/views/shared/members/_member.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 6f8c3c4da2e..80e52bf5637 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -4,7 +4,7 @@ - source = member.source %li.member{ class: dom_class(member), id: dom_id(member) } - %span{ class: ("list-item-name" if show_controls) } + %span.list-item-name - if user = image_tag avatar_icon(user, 40), class: "avatar s40", alt: '' %strong -- cgit v1.2.1 From a34c0e5490c78402b72fab7196d43352ff719cbb Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 4 Oct 2016 10:32:24 +0100 Subject: Border instead of hr --- app/assets/stylesheets/pages/members.scss | 5 +++++ app/views/projects/project_members/index.html.haml | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 72f31cb1168..187151fe26c 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -1,3 +1,8 @@ +.project-members-title { + padding-bottom: 10px; + border-bottom: 1px solid $border-color; +} + .member { .list-item-name { float: none; diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index f566748e95a..24e5a8e4015 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,10 +1,9 @@ - page_title "Members" .project-members-page.prepend-top-default - %h4.clearfix + %h4.project-members-title.clearfix Members = link_to "Import", import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-default pull-right hidden-xs", title: "Import members from another project" - %hr - if can?(current_user, :admin_project_member, @project) .project-members-new.append-bottom-default %p.clearfix -- cgit v1.2.1 From c2602aaff3f78ad12e1cc06136a7345699951454 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 4 Oct 2016 14:40:03 +0100 Subject: Updated Ruby --- app/controllers/projects/group_links_controller.rb | 2 +- app/controllers/projects/project_members_controller.rb | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index 7b6f07465e0..2994d8c9666 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -1,6 +1,7 @@ class Projects::GroupLinksController < Projects::ApplicationController layout 'project_settings' before_action :authorize_admin_project! + before_action :authorize_admin_project_member!, only: [:update] def index @group_links = project.project_group_links.all @@ -21,7 +22,6 @@ class Projects::GroupLinksController < Projects::ApplicationController def update @group_link = @project.project_group_links.find(params[:id]) - return render_403 unless can?(current_user, :admin_project_member, @project) @group_link.update_attributes(group_link_params) end diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index eb1bf445a7d..870dc8abbd4 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -19,8 +19,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController @groups = @project.project_group_links.where(group_id: group_ids) end - @project_members = @project_members.order('access_level DESC') - @project_members = @project_members.page(params[:page]) + @project_members = @project_members.order(access_level: :desc).page(params[:page]) @requesters = AccessRequestsFinder.new(@project).execute(current_user) @@ -40,6 +39,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController groups = Group.where(id: group_ids) groups.each do |group| + next unless can?(current_user, :read_group, group) + project.project_group_links.create( group: group, group_access: params[:access_level], -- cgit v1.2.1 From 66c7f5cb46d446a1c6c89ba888efd9e5f74f876d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 5 Oct 2016 14:31:33 +0200 Subject: fix empty import URL errors --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 507228606df..4beec36242d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -494,7 +494,7 @@ class Project < ActiveRecord::Base end def import_url - if import_data && super + if import_data && super.present? import_url = Gitlab::UrlSanitizer.new(super, credentials: import_data.credentials) import_url.full_url else -- cgit v1.2.1 From a0eaff14124b829ccc02df951bd7cb7d3abb7708 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 5 Oct 2016 14:37:03 +0100 Subject: Updated Ruby variable name Fixed Ruby code based on review feedback --- app/controllers/projects/project_members_controller.rb | 8 +++----- app/views/projects/project_members/_groups.html.haml | 4 ++-- app/views/projects/project_members/index.html.haml | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 870dc8abbd4..b2c8656d124 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -5,7 +5,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] def index - @groups = @project.project_group_links + @group_links = @project.project_group_links @project_members = @project.project_members @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project) @@ -14,9 +14,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController users = @project.users.search(params[:search]).to_a @project_members = @project_members.where(user_id: users) - group_ids = @groups.pluck(:group_id) - group_ids = Group.where(id: group_ids).search(params[:search]).to_a - @groups = @project.project_group_links.where(group_id: group_ids) + @group_links = @project.project_group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id)) end @project_members = @project_members.order(access_level: :desc).page(params[:page]) @@ -40,7 +38,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController groups.each do |group| next unless can?(current_user, :read_group, group) - + project.project_group_links.create( group: group, group_access: params[:access_level], diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml index 340e4cd06b8..11f896006da 100644 --- a/app/views/projects/project_members/_groups.html.haml +++ b/app/views/projects/project_members/_groups.html.haml @@ -2,8 +2,8 @@ .panel-heading Groups with access to %strong #{@project.name} - %span.badge= groups.size + %span.badge= group_links.size %ul.content-list - - @groups.each do |group_link| + - group_links.each do |group_link| - group = group_link.group = render 'shared/members/group', group_link: group_link, group: group diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 24e5a8e4015..f1461444241 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -21,8 +21,8 @@ = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" } = icon("search") - - if @groups.size > 0 - = render 'groups', groups: @groups + - if @group_links.size > 0 + = render 'groups', group_links: @group_links = render 'team', members: @project_members = paginate @project_members, theme: "gitlab" -- cgit v1.2.1 From c65ea7a5c30ee44c859ac711f1054dab734bdb89 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 16 Sep 2016 10:45:23 +0100 Subject: Merge request tabs stick when scrolling page Closes #20548 --- CHANGELOG | 1 + app/assets/javascripts/merge_request_tabs.js | 38 +++++++++++++++++++++++ app/assets/stylesheets/pages/merge_requests.scss | 9 ++++++ app/views/projects/merge_requests/_show.html.haml | 2 +- spec/features/merge_requests/sticky_tabs_spec.rb | 26 ++++++++++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 spec/features/merge_requests/sticky_tabs_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 68962f20d0b..5b68a670507 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -194,6 +194,7 @@ v 8.12.0 - Remove prefixes from transition CSS property (ClemMakesApps) - Add Sentry logging to API calls - Add BroadcastMessage API + - Merge request tabs are fixed when scrolling page - Use 'git update-ref' for safer web commits !6130 - Sort pipelines requested through the API - Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling) diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index bec11a198a1..f685af7d97e 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -68,6 +68,7 @@ this._location = location; this.bindEvents(); this.activateTab(this.opts.action); + this.initAffix(); } MergeRequestTabs.prototype.bindEvents = function() { @@ -367,6 +368,43 @@ // Only when sidebar is collapsed }; + MergeRequestTabs.prototype.initAffix = function () { + // Screen space on small screens is usually very sparse + // So we dont affix the tabs on these + if (Breakpoints.get().getBreakpointSize() === 'xs') return; + + var $tabs = $('.js-tabs-affix'), + tabsWidth = $tabs.outerWidth(), + $diffTabs = $('#diff-notes-app'), + offsetTop = $tabs.offset().top - ($('.navbar-fixed-top').height() + $('.layout-nav').height()); + + $tabs.off('affix.bs.affix affix-top.bs.affix') + .affix({ + offset: offsetTop + }).on('affix.bs.affix', function () { + $tabs.css({ + left: $tabs.offset().left, + width: tabsWidth + }); + $diffTabs.css({ + marginTop: $tabs.height() + }); + }).on('affix-top.bs.affix', function () { + $tabs.css({ + left: '', + width: '' + }); + $diffTabs.css({ + marginTop: '' + }); + }); + + // Fix bug when reloading the page already scrolling + if ($tabs.hasClass('affix')) { + $tabs.trigger('affix.bs.affix'); + } + }; + return MergeRequestTabs; })(); diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index bc8693ae467..d01aaa4be51 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -421,3 +421,12 @@ margin-bottom: 20px; } } + +.merge-request-tabs { + background-color: #fff; + + &.affix { + top: 100px; + z-index: 9; + } +} diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 9f34ca9ff4e..351c9d6ff91 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -47,7 +47,7 @@ = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal" - if @commits_count.nonzero? - %ul.merge-request-tabs.nav-links.no-top.no-bottom + %ul.merge-request-tabs.nav-links.no-top.no-bottom.js-tabs-affix %li.notes-tab = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do Discussion diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb new file mode 100644 index 00000000000..6f8c3dc55f4 --- /dev/null +++ b/spec/features/merge_requests/sticky_tabs_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +feature 'Merge request tabs', js: true, feature: true do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } + + before do + project.team << [user, :master] + login_as user + visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'affixes to top of page when scrolling' do + page.execute_script "window.scrollBy(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') + end + + it 'removes affix when scrolling to top' do + page.execute_script "window.scrollBy(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') + + page.execute_script "window.scrollBy(0,-10000)" + expect(page).to have_selector('.js-tabs-affix.affix-top') + end +end -- cgit v1.2.1 From 8962a3359c4282c755fff0fa08deeb64d74543a0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 16 Sep 2016 11:21:45 +0100 Subject: Fixed merge request tab JS spec --- spec/javascripts/merge_request_tabs_spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js index 395032a7416..96ee5235acf 100644 --- a/spec/javascripts/merge_request_tabs_spec.js +++ b/spec/javascripts/merge_request_tabs_spec.js @@ -1,5 +1,6 @@ /*= require merge_request_tabs */ +//= require breakpoints (function() { describe('MergeRequestTabs', function() { -- cgit v1.2.1 From 97dc95b18e5a5c29daab84e0d65522b3d3158dc1 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 16 Sep 2016 14:32:43 +0100 Subject: Fixed tests --- app/assets/javascripts/merge_request_tabs.js | 15 +++++++++------ spec/features/merge_requests/sticky_tabs_spec.rb | 10 +++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index f685af7d97e..1a214cdd00e 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -369,18 +369,21 @@ }; MergeRequestTabs.prototype.initAffix = function () { + var $tabs = $('.js-tabs-affix'); + // Screen space on small screens is usually very sparse // So we dont affix the tabs on these - if (Breakpoints.get().getBreakpointSize() === 'xs') return; + if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return; - var $tabs = $('.js-tabs-affix'), - tabsWidth = $tabs.outerWidth(), - $diffTabs = $('#diff-notes-app'), - offsetTop = $tabs.offset().top - ($('.navbar-fixed-top').height() + $('.layout-nav').height()); + var tabsWidth = $tabs.outerWidth(), + $diffTabs = $('#diff-notes-app'), + offsetTop = $tabs.offset().top - ($('.navbar-fixed-top').height() + $('.layout-nav').height()); $tabs.off('affix.bs.affix affix-top.bs.affix') .affix({ - offset: offsetTop + offset: { + top: offsetTop + } }).on('affix.bs.affix', function () { $tabs.css({ left: $tabs.offset().left, diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb index 6f8c3dc55f4..e78f3f134d5 100644 --- a/spec/features/merge_requests/sticky_tabs_spec.rb +++ b/spec/features/merge_requests/sticky_tabs_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' feature 'Merge request tabs', js: true, feature: true do + include WaitForAjax + let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } @@ -9,18 +11,20 @@ feature 'Merge request tabs', js: true, feature: true do project.team << [user, :master] login_as user visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + + wait_for_ajax end it 'affixes to top of page when scrolling' do - page.execute_script "window.scrollBy(0,10000)" + page.execute_script "window.scroll(0,10000)" expect(page).to have_selector('.js-tabs-affix.affix') end it 'removes affix when scrolling to top' do - page.execute_script "window.scrollBy(0,10000)" + page.execute_script "window.scroll(0,10000)" expect(page).to have_selector('.js-tabs-affix.affix') - page.execute_script "window.scrollBy(0,-10000)" + page.execute_script "window.scroll(0,-10000)" expect(page).to have_selector('.js-tabs-affix.affix-top') end end -- cgit v1.2.1 From ef1b5988af68a2811c079f785351e30fa8afd347 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 3 Oct 2016 09:50:50 +0100 Subject: Tests update --- spec/features/merge_requests/sticky_tabs_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb index e78f3f134d5..3e8bd768324 100644 --- a/spec/features/merge_requests/sticky_tabs_spec.rb +++ b/spec/features/merge_requests/sticky_tabs_spec.rb @@ -17,14 +17,17 @@ feature 'Merge request tabs', js: true, feature: true do it 'affixes to top of page when scrolling' do page.execute_script "window.scroll(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') end it 'removes affix when scrolling to top' do page.execute_script "window.scroll(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') page.execute_script "window.scroll(0,-10000)" + expect(page).to have_selector('.js-tabs-affix.affix-top') end end -- cgit v1.2.1 From 6865c46c6649118e09e60dd29dfa060470010aa9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 6 Oct 2016 15:41:00 +0100 Subject: Changed how collections are rendered Used variables in haml for replicated checks Fixed broken conflict --- .../projects/project_members_controller.rb | 15 - app/views/projects/group_links/update.js.haml | 2 +- .../projects/project_members/_groups.html.haml | 4 +- app/views/projects/project_members/_team.html.haml | 3 +- app/views/projects/project_members/index.html.haml | 2 +- app/views/shared/members/_group.html.haml | 9 +- app/views/shared/members/_member.html.haml | 10 +- config/routes.rb | 794 --------------------- 8 files changed, 15 insertions(+), 824 deletions(-) diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 67b41c4573a..37a86ed0523 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -98,21 +98,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController notice: notice) end - def options - users = User.all - users = users.search(params[:search]) if params[:search].present? - users = users.page(1) - - groups = Group.all - groups = groups.search(params[:search]) if params[:search].present? - groups = groups.page(1) - - render json: { - Groups: groups.as_json(only: [:id, :name], methods: [:avatar_url]), - Users: users.as_json(only: [:id, :name, :username], methods: [:avatar_url]), - } - end - protected def member_params diff --git a/app/views/projects/group_links/update.js.haml b/app/views/projects/group_links/update.js.haml index 231d5a79723..af9a5b19060 100644 --- a/app/views/projects/group_links/update.js.haml +++ b/app/views/projects/group_links/update.js.haml @@ -1,3 +1,3 @@ :plain - var $listItem = $('#{escape_javascript(render('shared/members/group', group_link: @group_link, group: @group_link.group))}'); + var $listItem = $('#{escape_javascript(render('shared/members/group', group_link: @group_link))}'); $("#group_member_#{@group_link.id} .list-item-name").replaceWith($listItem.find('.list-item-name')); diff --git a/app/views/projects/project_members/_groups.html.haml b/app/views/projects/project_members/_groups.html.haml index 11f896006da..d7f5fa96527 100644 --- a/app/views/projects/project_members/_groups.html.haml +++ b/app/views/projects/project_members/_groups.html.haml @@ -4,6 +4,4 @@ %strong #{@project.name} %span.badge= group_links.size %ul.content-list - - group_links.each do |group_link| - - group = group_link.group - = render 'shared/members/group', group_link: group_link, group: group + = render partial: 'shared/members/group', collection: group_links, as: :group_link diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml index ff54035cfe1..c1e894d8f40 100644 --- a/app/views/projects/project_members/_team.html.haml +++ b/app/views/projects/project_members/_team.html.haml @@ -4,5 +4,4 @@ %strong #{@project.name} %span.badge= @project_members.total_count %ul.content-list - - members.each do |member| - = render 'shared/members/member', member: member + = render partial: 'shared/members/member', collection: members, as: :member diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index f1461444241..bdeb704b6da 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -21,7 +21,7 @@ = search_field_tag :search, params[:search], { placeholder: 'Find existing members by name', class: 'form-control', spellcheck: false } %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" } = icon("search") - - if @group_links.size > 0 + - if @group_links.any? = render 'groups', group_links: @group_links = render 'team', members: @project_members diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml index 171a388b233..1c0346bbc78 100644 --- a/app/views/shared/members/_group.html.haml +++ b/app/views/shared/members/_group.html.haml @@ -1,5 +1,6 @@ -- group = local_assigns[:group] - group_link = local_assigns[:group_link] +- group = group_link.group +- can_admin_member = can?(current_user, :admin_project_member, @project) %li.member.group_member{ id: "group_member_#{group_link.id}" } %span{ class: "list-item-name" } = image_tag group_icon(group), class: "avatar s40", alt: '' @@ -13,11 +14,11 @@ Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)} .controls.member-controls = form_tag namespace_project_group_link_path(@project.namespace, @project, group_link), method: :put, remote: true, class: 'form-horizontal js-edit-member-form' do - = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}", disabled: !can?(current_user, :admin_project_member, @project) + = select_tag 'group_link[group_access]', options_for_select(ProjectGroupLink.access_options, group_link.group_access), class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{group.id}", disabled: !can_admin_member .prepend-left-5.clearable-input.member-form-control - = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can?(current_user, :admin_project_member, @project) + = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can_admin_member %i.clear-icon.js-clear-input - - if can?(current_user, :admin_project_member, @project) + - if can_admin_member = link_to namespace_project_group_link_path(@project.namespace, @project, group_link), remote: true, method: :delete, diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 80e52bf5637..432047a1c4e 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -2,6 +2,7 @@ - show_controls = local_assigns.fetch(:show_controls, true) - user = local_assigns.fetch(:user, member.user) - source = member.source +- can_admin_member = can?(current_user, action_member_permission(:update, member), member) %li.member{ class: dom_class(member), id: dom_id(member) } %span.list-item-name @@ -47,18 +48,19 @@ - if show_controls - if user != current_user = form_for member, remote: true, html: { class: 'form-horizontal js-edit-member-form' } do |f| - = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + = f.select :access_level, options_for_select(member.class.access_level_roles, member.access_level), {}, class: 'form-control member-form-control append-right-5 js-member-update-control', id: "member_access_level_#{member.id}", disabled: !can_admin_member .prepend-left-5.clearable-input.member-form-control - = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can?(current_user, action_member_permission(:update, member), member) + = f.text_field :expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{member.id}", disabled: !can_admin_member %i.clear-icon.js-clear-input - else %span.member-access-text= member.human_access - - if !user && can?(current_user, action_member_permission(:admin, member), member.source) + + - if member.invite? && can?(current_user, action_member_permission(:admin, member), member.source) = link_to 'Resend invite', polymorphic_path([:resend_invite, member]), method: :post, class: 'btn btn-default prepend-left-10' - - if member.request? && can?(current_user, action_member_permission(:update, member), member) + - elsif member.request? && can_admin_member = link_to icon('check inverse'), polymorphic_path([:approve_access_request, member]), method: :post, class: 'btn btn-success prepend-left-10', diff --git a/config/routes.rb b/config/routes.rb index f93c406e692..bf7c5b76128 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -74,799 +74,6 @@ Rails.application.routes.draw do # Notification settings resources :notification_settings, only: [:create, :update] -<<<<<<< HEAD - # - # Import - # - namespace :import do - resource :github, only: [:create, :new], controller: :github do - post :personal_access_token - get :status - get :callback - get :jobs - end - - resource :gitlab, only: [:create], controller: :gitlab do - get :status - get :callback - get :jobs - end - - resource :bitbucket, only: [:create], controller: :bitbucket do - get :status - get :callback - get :jobs - end - - resource :google_code, only: [:create, :new], controller: :google_code do - get :status - post :callback - get :jobs - - get :new_user_map, path: :user_map - post :create_user_map, path: :user_map - end - - resource :fogbugz, only: [:create, :new], controller: :fogbugz do - get :status - post :callback - get :jobs - - get :new_user_map, path: :user_map - post :create_user_map, path: :user_map - end - - resource :gitlab_project, only: [:create, :new] do - post :create - end - end - - # - # Uploads - # - - scope path: :uploads do - # Note attachments and User/Group/Project avatars - get ":model/:mounted_as/:id/:filename", - to: "uploads#show", - constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /[^\/]+/ } - - # Appearance - get ":model/:mounted_as/:id/:filename", - to: "uploads#show", - constraints: { model: /appearance/, mounted_as: /logo|header_logo/, filename: /.+/ } - - # Project markdown uploads - get ":namespace_id/:project_id/:secret/:filename", - to: "projects/uploads#show", - constraints: { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: /[^\/]+/ } - end - - # Redirect old note attachments path to new uploads path. - get "files/note/:id/:filename", - to: redirect("uploads/note/attachment/%{id}/%{filename}"), - constraints: { filename: /[^\/]+/ } - - # - # Explore area - # - namespace :explore do - resources :projects, only: [:index] do - collection do - get :trending - get :starred - end - end - - resources :groups, only: [:index] - resources :snippets, only: [:index] - root to: 'projects#trending' - end - - # Compatibility with old routing - get 'public' => 'explore/projects#index' - get 'public/projects' => 'explore/projects#index' - - # - # Admin Area - # - namespace :admin do - resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do - resources :keys, only: [:show, :destroy] - resources :identities, except: [:show] - - member do - get :projects - get :keys - get :groups - put :block - put :unblock - put :unlock - put :confirm - post :impersonate - patch :disable_two_factor - delete 'remove/:email_id', action: 'remove_email', as: 'remove_email' - end - end - - resource :impersonation, only: :destroy - - resources :abuse_reports, only: [:index, :destroy] - resources :spam_logs, only: [:index, :destroy] do - member do - post :mark_as_ham - end - end - - resources :applications - - resources :groups, constraints: { id: /[^\/]+/ } do - member do - put :members_update - end - end - - resources :deploy_keys, only: [:index, :new, :create, :destroy] - - resources :hooks, only: [:index, :create, :destroy] do - get :test - end - - resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] do - post :preview, on: :collection - end - - resource :logs, only: [:show] - resource :health_check, controller: 'health_check', only: [:show] - resource :background_jobs, controller: 'background_jobs', only: [:show] - resource :system_info, controller: 'system_info', only: [:show] - resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ } - - resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do - root to: 'projects#index', as: :projects - - resources(:projects, - path: '/', - constraints: { id: /[a-zA-Z.0-9_\-]+/ }, - only: [:index, :show]) do - root to: 'projects#show' - - member do - put :transfer - post :repository_check - end - - resources :runner_projects, only: [:create, :destroy] - end - end - - resource :appearances, only: [:show, :create, :update], path: 'appearance' do - member do - get :preview - delete :logo - delete :header_logos - end - end - - resource :application_settings, only: [:show, :update] do - resources :services, only: [:index, :edit, :update] - put :reset_runners_token - put :reset_health_check_token - put :clear_repository_check_states - end - - resources :labels - - resources :runners, only: [:index, :show, :update, :destroy] do - member do - get :resume - get :pause - end - end - - resources :builds, only: :index do - collection do - post :cancel_all - end - end - - root to: 'dashboard#index' - end - - # - # Profile Area - # - resource :profile, only: [:show, :update] do - member do - get :audit_log - get :applications, to: 'oauth/applications#index' - - put :reset_private_token - put :update_username - end - - scope module: :profiles do - resource :account, only: [:show] do - member do - delete :unlink - end - end - resource :notifications, only: [:show, :update] - resource :password, only: [:new, :create, :edit, :update] do - member do - put :reset - end - end - resource :preferences, only: [:show, :update] - resources :keys, only: [:index, :show, :new, :create, :destroy] - resources :emails, only: [:index, :create, :destroy] - resource :avatar, only: [:destroy] - - resources :personal_access_tokens, only: [:index, :create] do - member do - put :revoke - end - end - - resource :two_factor_auth, only: [:show, :create, :destroy] do - member do - post :create_u2f - post :codes - patch :skip - end - end - - resources :u2f_registrations, only: [:destroy] - end - end - - scope(path: 'u/:username', - as: :user, - constraints: { username: /[a-zA-Z.0-9_\-]+(? 'omniauth_callbacks#omniauth_error', as: :omniauth_error - get '/users/almost_there' => 'confirmations#almost_there' - end - - root to: "root#index" - - # - # Project Area - # - resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do - resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(? 'templates#show', as: :template - - scope do - get( - '/blob/*id/diff', - to: 'blob#diff', - constraints: { id: /.+/, format: false }, - as: :blob_diff - ) - get( - '/blob/*id', - to: 'blob#show', - constraints: { id: /.+/, format: false }, - as: :blob - ) - delete( - '/blob/*id', - to: 'blob#destroy', - constraints: { id: /.+/, format: false } - ) - put( - '/blob/*id', - to: 'blob#update', - constraints: { id: /.+/, format: false } - ) - post( - '/blob/*id', - to: 'blob#create', - constraints: { id: /.+/, format: false } - ) - end - - scope do - get( - '/raw/*id', - to: 'raw#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :raw - ) - end - - scope do - get( - '/tree/*id', - to: 'tree#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :tree - ) - end - - scope do - get( - '/find_file/*id', - to: 'find_file#show', - constraints: { id: /.+/, format: /html/ }, - as: :find_file - ) - end - - scope do - get( - '/files/*id', - to: 'find_file#list', - constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }, - as: :files - ) - end - - scope do - post( - '/create_dir/*id', - to: 'tree#create_dir', - constraints: { id: /.+/ }, - as: 'create_dir' - ) - end - - scope do - get( - '/blame/*id', - to: 'blame#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :blame - ) - end - - scope do - get( - '/commits/*id', - to: 'commits#show', - constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }, - as: :commits - ) - end - - resource :avatar, only: [:show, :destroy] - resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do - member do - get :branches - get :builds - get :pipelines - post :cancel_builds - post :retry_builds - post :revert - post :cherry_pick - get :diff_for_path - end - end - - resources :compare, only: [:index, :create] do - collection do - get :diff_for_path - end - end - - get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ } - - # Don't use format parameter as file extension (old 3.0.x behavior) - # See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments - scope format: false do - resources :network, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } - - resources :graphs, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } do - member do - get :commits - get :ci - get :languages - end - end - end - - resources :snippets, concerns: :awardable, constraints: { id: /\d+/ } do - member do - get 'raw' - end - end - - WIKI_SLUG_ID = { id: /\S+/ } unless defined? WIKI_SLUG_ID - - scope do - # Order matters to give priority to these matches - get '/wikis/git_access', to: 'wikis#git_access' - get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages' - post '/wikis', to: 'wikis#create' - - get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID - get '/wikis/*id/edit', to: 'wikis#edit', as: 'wiki_edit', constraints: WIKI_SLUG_ID - - get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID - delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID - put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID - post '/wikis/*id/preview_markdown', to: 'wikis#preview_markdown', constraints: WIKI_SLUG_ID, as: 'wiki_preview_markdown' - end - - resource :repository, only: [:create] do - member do - get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex } - end - end - - resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do - member do - get :test - end - end - - resources :deploy_keys, constraints: { id: /\d+/ }, only: [:index, :new, :create] do - member do - put :enable - put :disable - end - end - - resources :forks, only: [:index, :new, :create] - resource :import, only: [:new, :create, :show] - - resources :refs, only: [] do - collection do - get 'switch' - end - - member do - # tree viewer logs - get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } - # Directories with leading dots erroneously get rejected if git - # ref regex used in constraints. Regex verification now done in controller. - get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: { - id: /.*/, - path: /.*/ - } - end - end - - resources :merge_requests, concerns: :awardable, constraints: { id: /\d+/ } do - member do - get :commits - get :diffs - get :conflicts - get :builds - get :pipelines - get :merge_check - post :merge - post :cancel_merge_when_build_succeeds - get :ci_status - post :toggle_subscription - post :remove_wip - get :diff_for_path - post :resolve_conflicts - end - - collection do - get :branch_from - get :branch_to - get :update_branches - get :diff_for_path - post :bulk_update - end - - resources :discussions, only: [], constraints: { id: /\h{40}/ } do - member do - post :resolve - delete :resolve, action: :unresolve - end - end - end - - resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } - resources :tags, only: [:index, :show, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do - resource :release, only: [:edit, :update] - end - - resources :protected_branches, only: [:index, :show, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } - resources :variables, only: [:index, :show, :update, :create, :destroy] - resources :triggers, only: [:index, :create, :destroy] - - resources :pipelines, only: [:index, :new, :create, :show] do - collection do - resource :pipelines_settings, path: 'settings', only: [:show, :update] - end - - member do - post :cancel - post :retry - end - end - - resources :environments - - resource :cycle_analytics, only: [:show] - - resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do - collection do - post :cancel_all - - resources :artifacts, only: [] do - collection do - get :latest_succeeded, - path: '*ref_name_and_path', - format: false - end - end - end - - member do - get :status - post :cancel - post :retry - post :play - post :erase - get :trace - get :raw - end - - resource :artifacts, only: [] do - get :download - get :browse, path: 'browse(/*path)', format: false - get :file, path: 'file/*path', format: false - post :keep - end - end - - resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do - member do - get :test - end - end - - resources :container_registry, only: [:index, :destroy], constraints: { id: Gitlab::Regex.container_registry_reference_regex } - - resources :milestones, constraints: { id: /\d+/ } do - member do - put :sort_issues - put :sort_merge_requests - end - end - - resources :labels, except: [:show], constraints: { id: /\d+/ } do - collection do - post :generate - post :set_priorities - end - - member do - post :toggle_subscription - delete :remove_priority - end - end - - resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do - member do - post :toggle_subscription - post :mark_as_spam - get :referenced_merge_requests - get :related_branches - get :can_create_branch - end - collection do - post :bulk_update - end - end - - resources :project_members, except: [:show, :new, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }, concerns: :access_requestable do - collection do - delete :leave - - # Used for import team - # from another project - get :import - post :apply_import - end - - member do - post :resend_invite - end - end - - resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ } - - resources :notes, only: [:index, :create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do - member do - delete :delete_attachment - post :resolve - delete :resolve, action: :unresolve - end - end - - resource :board, only: [:show] do - scope module: :boards do - resources :issues, only: [:update] - - resources :lists, only: [:index, :create, :update, :destroy] do - collection do - post :generate - end - - resources :issues, only: [:index] - end - end - end - - resources :todos, only: [:create] - - resources :uploads, only: [:create] do - collection do - get ":secret/:filename", action: :show, as: :show, constraints: { filename: /[^\/]+/ } - end - end - - resources :runners, only: [:index, :edit, :update, :destroy, :show] do - member do - get :resume - get :pause - end - - collection do - post :toggle_shared_runners - end - end - - resources :runner_projects, only: [:create, :destroy] - resources :badges, only: [:index] do - collection do - scope '*ref', constraints: { ref: Gitlab::Regex.git_reference_regex } do - constraints format: /svg/ do - get :build - get :coverage - end - end - end - end - end - end - end -======= draw :import draw :uploads draw :explore @@ -876,7 +83,6 @@ Rails.application.routes.draw do draw :group draw :user draw :project ->>>>>>> master # Get all keys of user get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ } -- cgit v1.2.1 From b2e5240af3d14bd67900ef194226274639537888 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 6 Oct 2016 15:42:48 +0100 Subject: Changed jQuery to be in single line Removed un-required CSS --- app/assets/javascripts/members.js.es6 | 5 +---- app/assets/stylesheets/pages/members.scss | 2 -- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6 index 1b4b3f38838..5dc6990bdb6 100644 --- a/app/assets/javascripts/members.js.es6 +++ b/app/assets/javascripts/members.js.es6 @@ -31,10 +31,7 @@ } formSubmit() { - $(this).closest('form') - .trigger("submit.rails") - .end() - .disable(); + $(this).closest('form').trigger("submit.rails").end().disable(); } formSuccess() { diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 187151fe26c..ff4fd751f26 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -5,8 +5,6 @@ .member { .list-item-name { - float: none; - @media (min-width: $screen-sm-min) { float: left; width: 50%; -- cgit v1.2.1 From 680efd4f8d6fb3a1036edc135f5761a512f8eea7 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Wed, 24 Aug 2016 23:44:58 +0100 Subject: Added subnav to labels edit+new and milestones edit+new+show Added subnav to blame show, blob edit, builds show, commit builds, commit show, environments edit and pipelines show Added subnav to new enviro view Added sidebar top position calculation logic Added sidebar translation to follow the subnav up when the body is scrolled until a certain limit --- app/assets/javascripts/build.js | 36 ++++++++-- app/assets/stylesheets/pages/builds.scss | 6 ++ app/views/projects/blame/show.html.haml | 87 +++++++++++------------ app/views/projects/blob/edit.html.haml | 43 ++++++------ app/views/projects/builds/show.html.haml | 95 +++++++++++++------------- app/views/projects/commit/builds.html.haml | 11 +-- app/views/projects/commit/show.html.haml | 25 ++++--- app/views/projects/environments/edit.html.haml | 11 +-- app/views/projects/environments/new.html.haml | 11 +-- app/views/projects/labels/edit.html.haml | 11 +-- app/views/projects/labels/new.html.haml | 11 +-- app/views/projects/milestones/edit.html.haml | 12 ++-- app/views/projects/milestones/new.html.haml | 11 +-- app/views/projects/milestones/show.html.haml | 83 +++++++++++----------- app/views/projects/pipelines/_head.html.haml | 2 +- app/views/projects/pipelines/show.html.haml | 13 ++-- 16 files changed, 268 insertions(+), 200 deletions(-) diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js index f336bfc36d6..97462a5959c 100644 --- a/app/assets/javascripts/build.js +++ b/app/assets/javascripts/build.js @@ -15,18 +15,17 @@ this.hideSidebar = bind(this.hideSidebar, this); this.toggleSidebar = bind(this.toggleSidebar, this); this.updateDropdown = bind(this.updateDropdown, this); + this.$document = $(document); clearInterval(Build.interval); // Init breakpoint checker this.bp = Breakpoints.get(); - $('.js-build-sidebar').niceScroll(); + this.initSidebar(); this.populateJobs(this.build_stage); this.updateStageDropdownText(this.build_stage); - this.hideSidebar(); - $(document).off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar); $(window).off('resize.build').on('resize.build', this.hideSidebar); - $(document).off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown); + this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown); $('#js-build-scroll > a').off('click').on('click', this.stepTrace); this.updateArtifactRemoveDate(); if ($('#build-trace').length) { @@ -62,6 +61,21 @@ } } + Build.prototype.initSidebar = function() { + this.$sidebar = $('.js-build-sidebar'); + this.sidebarTranslationLimits = { + min: $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight() + } + this.sidebarTranslationLimits.max = this.sidebarTranslationLimits.min + $('.scrolling-tabs-container').outerHeight(); + this.$sidebar.css({ + top: this.sidebarTranslationLimits.max + }); + this.$sidebar.niceScroll(); + this.hideSidebar(); + this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar); + this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this)); + }; + Build.prototype.getInitialBuildTrace = function() { var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped'] @@ -129,15 +143,23 @@ Build.prototype.toggleSidebar = function() { if (this.shouldHideSidebar()) { - return $('.js-build-sidebar').toggleClass('right-sidebar-expanded right-sidebar-collapsed'); + return this.$sidebar.toggleClass('right-sidebar-expanded right-sidebar-collapsed'); } }; + Build.prototype.translateSidebar = function(e) { + var newPosition = this.sidebarTranslationLimits.max - document.body.scrollTop; + if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min; + this.$sidebar.css({ + top: newPosition + }); + }; + Build.prototype.hideSidebar = function() { if (this.shouldHideSidebar()) { - return $('.js-build-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); + return this.$sidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); } else { - return $('.js-build-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); + return this.$sidebar.removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); } }; diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 194a39a8377..fcaba954615 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -233,3 +233,9 @@ right: 0; margin-top: -17px; } + +@media (min-width: $screen-md-min) { + .sub-nav.build { + width: calc(100% + #{$gutter_width}); + } +} diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 5a98e258b22..dfb96305f48 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,45 +1,48 @@ +- @no_container = true - page_title "Blame", @blob.path, @ref += render "projects/commits/head" -%h3.page-title Blame view +%div{ class: container_class } + %h3.page-title Blame view -#blob-content-holder.tree-holder - .file-holder - .file-title - = blob_icon @blob.mode, @blob.name - %strong - = @path - %small= number_to_human_size @blob.size - .file-actions - = render "projects/blob/actions" - .table-responsive.file-content.blame.code.js-syntax-highlight - %table - - current_line = 1 - - @blame_groups.each do |blame_group| - %tr - %td.blame-commit - .commit - - commit = blame_group[:commit] - = author_avatar(commit, size: 36) - .commit-row-title - %strong - = link_to_gfm truncate(commit.title, length: 35), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "cdark" - .pull-right - = link_to commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit), class: "monospace" -   - .light - = commit_author_link(commit, avatar: false) - authored - #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} - %td.line-numbers - - line_count = blame_group[:lines].count - - (current_line...(current_line + line_count)).each do |i| - %a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i} - = icon("link") - = i - \ - - current_line += line_count - %td.lines - %pre.code.highlight - %code - - blame_group[:lines].each do |line| - #{line} + #blob-content-holder.tree-holder + .file-holder + .file-title + = blob_icon @blob.mode, @blob.name + %strong + = @path + %small= number_to_human_size @blob.size + .file-actions + = render "projects/blob/actions" + .table-responsive.file-content.blame.code.js-syntax-highlight + %table + - current_line = 1 + - @blame_groups.each do |blame_group| + %tr + %td.blame-commit + .commit + - commit = blame_group[:commit] + = author_avatar(commit, size: 36) + .commit-row-title + %strong + = link_to_gfm truncate(commit.title, length: 35), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "cdark" + .pull-right + = link_to commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit), class: "monospace" +   + .light + = commit_author_link(commit, avatar: false) + authored + #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} + %td.line-numbers + - line_count = blame_group[:lines].count + - (current_line...(current_line + line_count)).each do |i| + %a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i} + = icon("link") + = i + \ + - current_line += line_count + %td.lines + %pre.code.highlight + %code + - blame_group[:lines].each do |line| + #{line} diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 680e95ac6b5..2a0352a71b7 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -1,28 +1,31 @@ +- @no_container = true - page_title "Edit", @blob.path, @ref - content_for :page_specific_javascripts do = page_specific_javascript_tag('lib/ace.js') = page_specific_javascript_tag('blob_edit/blob_edit_bundle.js') += render "projects/commits/head" -- if @conflict - .alert.alert-danger - Someone edited the file the same time you did. Please check out - = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank" - and make sure your changes will not unintentionally remove theirs. +%div{ class: container_class } + - if @conflict + .alert.alert-danger + Someone edited the file the same time you did. Please check out + = link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank" + and make sure your changes will not unintentionally remove theirs. -.file-editor - %ul.nav-links.no-bottom.js-edit-mode - %li.active - = link_to '#editor' do - Edit File + .file-editor + %ul.nav-links.no-bottom.js-edit-mode + %li.active + = link_to '#editor' do + Edit File - %li - = link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do - = editing_preview_title(@blob.name) + %li + = link_to '#preview', 'data-preview-url' => namespace_project_preview_blob_path(@project.namespace, @project, @id) do + = editing_preview_title(@blob.name) - = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths) do - = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data - = render 'shared/new_commit_form', placeholder: "Update #{@blob.name}" - = hidden_field_tag 'last_commit_sha', @last_commit_sha - = hidden_field_tag 'content', '', id: "file-content" - = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id] - = render 'projects/commit_button', ref: @ref, cancel_path: namespace_project_blob_path(@project.namespace, @project, @id) + = form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths) do + = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data + = render 'shared/new_commit_form', placeholder: "Update #{@blob.name}" + = hidden_field_tag 'last_commit_sha', @last_commit_sha + = hidden_field_tag 'content', '', id: "file-content" + = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id] + = render 'projects/commit_button', ref: @ref, cancel_path: namespace_project_blob_path(@project.namespace, @project, @id) diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index e4d41288aa6..b5e8b0bf6eb 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,56 +1,59 @@ +- @no_container = true - page_title "#{@build.name} (##{@build.id})", "Builds" - trace_with_state = @build.trace_with_state - header_title project_title(@project, "Builds", project_builds_path(@project)) += render "projects/pipelines/head", build_subnav: true -.build-page - = render "header" +%div{ class: container_class } + .build-page + = render "header" - - if @build.stuck? - - unless @build.any_runners_online? - .bs-callout.bs-callout-warning - %p - - if no_runners_for_project?(@build.project) - This build is stuck, because the project doesn't have any runners online assigned to it. - - elsif @build.tags.any? - This build is stuck, because you don't have any active runners online with any of these tags assigned to them: - - @build.tags.each do |tag| - %span.label.label-primary - = tag - - else - This build is stuck, because you don't have any active runners that can run this build. + - if @build.stuck? + - unless @build.any_runners_online? + .bs-callout.bs-callout-warning + %p + - if no_runners_for_project?(@build.project) + This build is stuck, because the project doesn't have any runners online assigned to it. + - elsif @build.tags.any? + This build is stuck, because you don't have any active runners online with any of these tags assigned to them: + - @build.tags.each do |tag| + %span.label.label-primary + = tag + - else + This build is stuck, because you don't have any active runners that can run this build. - %br - Go to - = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do - Runners page + %br + Go to + = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do + Runners page - .prepend-top-default - - if @build.active? - .autoscroll-container - %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll - - if @build.erased? - .erased.alert.alert-warning - - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by - Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)} - - else - #js-build-scroll.scroll-controls - = link_to '#build-trace', class: 'btn' do - %i.fa.fa-angle-up - = link_to '#down-build-trace', class: 'btn' do - %i.fa.fa-angle-down - %pre.build-trace#build-trace - %code.bash.js-build-output - = icon("refresh spin", class: "js-build-refresh") + .prepend-top-default + - if @build.active? + .autoscroll-container + %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll + - if @build.erased? + .erased.alert.alert-warning + - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by + Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)} + - else + #js-build-scroll.scroll-controls + = link_to '#build-trace', class: 'btn' do + %i.fa.fa-angle-up + = link_to '#down-build-trace', class: 'btn' do + %i.fa.fa-angle-down + %pre.build-trace#build-trace + %code.bash.js-build-output + = icon("refresh spin", class: "js-build-refresh") - #down-build-trace + #down-build-trace -= render "sidebar" + = render "sidebar" -:javascript - new Build({ - page_url: "#{namespace_project_build_url(@project.namespace, @project, @build)}", - build_url: "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", - build_status: "#{@build.status}", - build_stage: "#{@build.stage}", - state1: "#{trace_with_state[:state]}" - }) + :javascript + new Build({ + page_url: "#{namespace_project_build_url(@project.namespace, @project, @build)}", + build_url: "#{namespace_project_build_url(@project.namespace, @project, @build, :json)}", + build_status: "#{@build.status}", + build_stage: "#{@build.stage}", + state1: "#{trace_with_state[:state]}" + }) diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml index 2f051fb90e0..f9d7eac3542 100644 --- a/app/views/projects/commit/builds.html.haml +++ b/app/views/projects/commit/builds.html.haml @@ -1,7 +1,10 @@ +- @no_container = true - page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits" += render "projects/commits/head" -.prepend-top-default - = render "commit_box" +%div{ class: container_class } + .prepend-top-default + = render "commit_box" -= render "ci_menu" -= render "builds" + = render "ci_menu" + = render "builds" diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index ed44d86a687..cebf58d63df 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,14 +1,17 @@ +- @no_container = true - page_title "#{@commit.title} (#{@commit.short_id})", "Commits" - page_description @commit.description += render "projects/commits/head" -.prepend-top-default - = render "commit_box" -- if @commit.status - = render "ci_menu" -- else - %div.block-connector -= render "projects/diffs/diffs", diffs: @diffs -= render "projects/notes/notes_with_form" -- if can_collaborate_with_project? - - %w(revert cherry-pick).each do |type| - = render "projects/commit/change", type: type, commit: @commit, title: @commit.title +%div{ class: container_class } + .prepend-top-default + = render "commit_box" + - if @commit.status + = render "ci_menu" + - else + %div.block-connector + = render "projects/diffs/diffs", diffs: @diffs + = render "projects/notes/notes_with_form" + - if can_collaborate_with_project? + - %w(revert cherry-pick).each do |type| + = render "projects/commit/change", type: type, commit: @commit, title: @commit.title diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml index 6d1bdb9320f..3871165763c 100644 --- a/app/views/projects/environments/edit.html.haml +++ b/app/views/projects/environments/edit.html.haml @@ -1,6 +1,9 @@ +- @no_container = true - page_title "Edit", @environment.name, "Environments" += render "projects/pipelines/head" -%h3.page-title - Edit environment -%hr -= render 'form' +%div{ class: container_class } + %h3.page-title + Edit environment + %hr + = render 'form' diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml index e51667ade2d..24638c77cbb 100644 --- a/app/views/projects/environments/new.html.haml +++ b/app/views/projects/environments/new.html.haml @@ -1,6 +1,9 @@ +- @no_container = true - page_title 'New Environment' += render "projects/pipelines/head" -%h3.page-title - New environment -%hr -= render 'form' +%div{ class: container_class } + %h3.page-title + New environment + %hr + = render 'form' diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index 6901ba13ab7..52b187e7e58 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,6 +1,9 @@ +- @no_container = true - page_title "Edit", @label.name, "Labels" += render "projects/issues/head" -%h3.page-title - Edit Label -%hr -= render 'form' +%div{ class: container_class } + %h3.page-title + Edit Label + %hr + = render 'form' diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index 49ddf901619..a1bb66cfb6c 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,6 +1,9 @@ +- @no_container = true - page_title "New Label" += render "projects/issues/head" -%h3.page-title - New Label -%hr -= render 'form' +%div{ class: container_class } + %h3.page-title + New Label + %hr + = render 'form' diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index be682226ab6..11f41e75e63 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1,8 +1,12 @@ +- @no_container = true - page_title "Edit", @milestone.title, "Milestones" += render "projects/issues/head" -%h3.page-title - Edit Milestone ##{@milestone.iid} +%div{ class: container_class } -%hr + %h3.page-title + Edit Milestone ##{@milestone.iid} -= render "form" + %hr + + = render "form" diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index 7f372b41698..cda093ade81 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1,8 +1,11 @@ +- @no_container = true - page_title "New Milestone" += render "projects/issues/head" -%h3.page-title - New Milestone +%div{ class: container_class } + %h3.page-title + New Milestone -%hr + %hr -= render "form" + = render "form" diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index e62f810a521..c83818e9199 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -1,49 +1,52 @@ +- @no_container = true - page_title @milestone.title, "Milestones" - page_description @milestone.description += render "projects/issues/head" -.detail-page-header - .status-box{ class: status_box_class(@milestone) } - - if @milestone.closed? - Closed - - elsif @milestone.expired? - Past due - - else - Open - %span.identifier - Milestone ##{@milestone.iid} - - if @milestone.expires_at - %span.creator - · - = @milestone.expires_at - .pull-right - - if can?(current_user, :admin_milestone, @project) - - if @milestone.active? - = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-nr btn-grouped" +%div{ class: container_class } + .detail-page-header + .status-box{ class: status_box_class(@milestone) } + - if @milestone.closed? + Closed + - elsif @milestone.expired? + Past due - else - = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped" + Open + %span.identifier + Milestone ##{@milestone.iid} + - if @milestone.expires_at + %span.creator + · + = @milestone.expires_at + .pull-right + - if can?(current_user, :admin_milestone, @project) + - if @milestone.active? + = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-nr btn-grouped" + - else + = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped" - = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped btn-nr" do - Edit + = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped btn-nr" do + Edit - = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-danger" do - Delete + = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-danger" do + Delete -.detail-page-description.milestone-detail - %h2.title - = markdown_field(@milestone, :title) - %div - - if @milestone.description.present? - .description - .wiki - = preserve do - = markdown_field(@milestone, :description) + .detail-page-description.milestone-detail + %h2.title + = markdown_field(@milestone, :title) + %div + - if @milestone.description.present? + .description + .wiki + = preserve do + = markdown_field(@milestone, :description) -- if @milestone.total_items_count(current_user).zero? - .alert.alert-success.prepend-top-default - %span Assign some issues to this milestone. -- elsif @milestone.complete?(current_user) && @milestone.active? - .alert.alert-success.prepend-top-default - %span All issues for this milestone are closed. You may close this milestone now. + - if @milestone.total_items_count(current_user).zero? + .alert.alert-success.prepend-top-default + %span Assign some issues to this milestone. + - elsif @milestone.complete?(current_user) && @milestone.active? + .alert.alert-success.prepend-top-default + %span All issues for this milestone are closed. You may close this milestone now. -= render 'shared/milestones/summary', milestone: @milestone, project: @project -= render 'shared/milestones/tabs', milestone: @milestone + = render 'shared/milestones/summary', milestone: @milestone, project: @project + = render 'shared/milestones/tabs', milestone: @milestone diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml index 7d421c0e740..b10dd47709f 100644 --- a/app/views/projects/pipelines/_head.html.haml +++ b/app/views/projects/pipelines/_head.html.haml @@ -1,7 +1,7 @@ = content_for :sub_nav do .scrolling-tabs-container.sub-nav-scroll = render 'shared/nav_scroll' - .nav-links.sub-nav.scrolling-tabs + .nav-links.sub-nav.scrolling-tabs{ class: ('build' if local_assigns.fetch(:build_subnav, false)) } %ul{ class: (container_class) } - if project_nav_tab? :pipelines = nav_link(controller: :pipelines) do diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml index 75943c64276..688535ad764 100644 --- a/app/views/projects/pipelines/show.html.haml +++ b/app/views/projects/pipelines/show.html.haml @@ -1,8 +1,11 @@ +- @no_container = true - page_title "Pipeline" += render "projects/pipelines/head" -.prepend-top-default - - if @commit - = render "projects/pipelines/info" - %div.block-connector +%div{ class: container_class } + .prepend-top-default + - if @commit + = render "projects/pipelines/info" + %div.block-connector -= render "projects/commit/pipeline", pipeline: @pipeline + = render "projects/commit/pipeline", pipeline: @pipeline -- cgit v1.2.1 From 517895da4c1ca6201f952e443a579e4f2845e6e0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 10 Oct 2016 13:13:07 +0100 Subject: Don't run affix tabs in test env This was messing up other tests --- app/views/projects/merge_requests/_show.html.haml | 2 +- spec/features/merge_requests/sticky_tabs_spec.rb | 33 ----------------------- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 spec/features/merge_requests/sticky_tabs_spec.rb diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 351c9d6ff91..72ad96aa217 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -47,7 +47,7 @@ = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal" - if @commits_count.nonzero? - %ul.merge-request-tabs.nav-links.no-top.no-bottom.js-tabs-affix + %ul.merge-request-tabs.nav-links.no-top.no-bottom{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') } %li.notes-tab = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#notes', action: 'notes', toggle: 'tab' } do Discussion diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb deleted file mode 100644 index 3e8bd768324..00000000000 --- a/spec/features/merge_requests/sticky_tabs_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'spec_helper' - -feature 'Merge request tabs', js: true, feature: true do - include WaitForAjax - - let(:user) { create(:user) } - let(:project) { create(:project, :public) } - let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } - - before do - project.team << [user, :master] - login_as user - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) - - wait_for_ajax - end - - it 'affixes to top of page when scrolling' do - page.execute_script "window.scroll(0,10000)" - - expect(page).to have_selector('.js-tabs-affix.affix') - end - - it 'removes affix when scrolling to top' do - page.execute_script "window.scroll(0,10000)" - - expect(page).to have_selector('.js-tabs-affix.affix') - - page.execute_script "window.scroll(0,-10000)" - - expect(page).to have_selector('.js-tabs-affix.affix-top') - end -end -- cgit v1.2.1 From 0a79e5cd44e1d83f0cd18ffb538da25e6b2deae3 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Mon, 10 Oct 2016 16:21:08 -0500 Subject: Replace generic table with --- app/assets/stylesheets/pages/environments.scss | 4 ++-- app/assets/stylesheets/pages/merge_requests.scss | 4 ++-- app/assets/stylesheets/pages/pipelines.scss | 4 ++-- app/views/admin/runners/show.html.haml | 2 +- app/views/projects/builds/_table.html.haml | 2 +- app/views/projects/commit/_pipeline.html.haml | 2 +- app/views/projects/commit/_pipelines_list.haml | 2 +- app/views/projects/environments/index.html.haml | 2 +- app/views/projects/environments/show.html.haml | 2 +- app/views/projects/pipelines/index.html.haml | 2 +- spec/features/merge_requests/created_from_fork_spec.rb | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 3f19e920166..820cc0fc991 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -52,13 +52,13 @@ } } -.table.builds.environments { +.table.ci-table.environments { .icon-container { width: 20px; text-align: center; } - + .branch-commit { .commit-id { margin-right: 0; diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 043f3f3afe1..9676c2d1026 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -264,7 +264,7 @@ line-height: 31px; } -.builds { +.ci-table { .table-holder { overflow-x: auto; } @@ -357,7 +357,7 @@ } .table-holder { - .builds { + .ci-table { th { background-color: $white-light; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index a2779704eff..bad4eeaa2cf 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -20,7 +20,7 @@ margin: 4px; } - .table.builds { + .table.ci-table { min-width: 1200px; .branch-commit { @@ -44,7 +44,7 @@ overflow: auto; } -.table.builds { +.table.ci-table { min-width: 900px; &.pipeline { diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index a5e82e55cc1..10fea1996aa 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -71,7 +71,7 @@ .col-md-6 %h4 Recent builds served by this Runner - %table.table.builds.runner-builds + %table.table.ci-table.runner-builds %thead %tr %th Build diff --git a/app/views/projects/builds/_table.html.haml b/app/views/projects/builds/_table.html.haml index f3747ba2a21..9b91ae688ae 100644 --- a/app/views/projects/builds/_table.html.haml +++ b/app/views/projects/builds/_table.html.haml @@ -5,7 +5,7 @@ .nothing-here-block No builds to show - else .table-holder - %table.table.builds + %table.table.ci-table %thead %tr %th Status diff --git a/app/views/projects/commit/_pipeline.html.haml b/app/views/projects/commit/_pipeline.html.haml index da5b9832ba5..b5e5e8db9eb 100644 --- a/app/views/projects/commit/_pipeline.html.haml +++ b/app/views/projects/commit/_pipeline.html.haml @@ -55,7 +55,7 @@ \.gitlab-ci.yml not found in this commit .table-holder.pipeline-holder - %table.table.builds.pipeline + %table.table.ci-table.pipeline %thead %tr %th Status diff --git a/app/views/projects/commit/_pipelines_list.haml b/app/views/projects/commit/_pipelines_list.haml index 998812793a2..640651e93f5 100644 --- a/app/views/projects/commit/_pipelines_list.haml +++ b/app/views/projects/commit/_pipelines_list.haml @@ -4,7 +4,7 @@ .nothing-here-block No pipelines to show - else .table-holder - %table.table.builds + %table.table.ci-table %tbody %th Status %th Pipeline diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index ab801409722..721ba156334 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -24,7 +24,7 @@ New environment - else .table-holder - %table.table.builds.environments + %table.table.ci-table.environments %tbody %th Environment %th Last Deployment diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index 7a8d196cf4e..90c59223a35 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -24,7 +24,7 @@ = link_to "Read more", help_page_path("ci/environments"), class: "btn btn-success" - else .table-holder - %table.table.builds.environments + %table.table.ci-table.environments %thead %tr %th ID diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 2d1df095bfa..9eeef5f57b4 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -43,7 +43,7 @@ .nothing-here-block No pipelines to show - else .table-holder - %table.table.builds + %table.table.ci-table %thead %th.col-xs-1.col-sm-1 Status %th.col-xs-2.col-sm-4 Pipeline diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb index 4d5d4aa121a..a506624b30d 100644 --- a/spec/features/merge_requests/created_from_fork_spec.rb +++ b/spec/features/merge_requests/created_from_fork_spec.rb @@ -45,7 +45,7 @@ feature 'Merge request created from fork' do page.within('.merge-request-tabs') { click_link 'Builds' } wait_for_ajax - page.within('table.builds') do + page.within('table.ci-table') do expect(page).to have_content 'rspec' expect(page).to have_content 'spinach' end -- cgit v1.2.1 From 0012b74e01429b98d2c42f68f50dc6ce6ad2b70f Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Mon, 10 Oct 2016 16:31:24 -0500 Subject: Set height on build page rows --- app/assets/stylesheets/pages/pipelines.scss | 7 +++++++ app/views/projects/builds/_table.html.haml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index bad4eeaa2cf..149c29858fb 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -51,6 +51,13 @@ min-width: 650px; } + &.builds-page { + + tr { + height: 71px; + } + } + tr { th { padding: 16px 8px; diff --git a/app/views/projects/builds/_table.html.haml b/app/views/projects/builds/_table.html.haml index 9b91ae688ae..36294c89fa8 100644 --- a/app/views/projects/builds/_table.html.haml +++ b/app/views/projects/builds/_table.html.haml @@ -5,7 +5,7 @@ .nothing-here-block No builds to show - else .table-holder - %table.table.ci-table + %table.table.ci-table.builds-page %thead %tr %th Status -- cgit v1.2.1 From 64609ba84845969ef084aee3058ce2fbea582a3f Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Mon, 10 Oct 2016 16:43:40 -0500 Subject: Set height on MR builds rows --- app/assets/stylesheets/pages/merge_requests.scss | 6 ----- app/assets/stylesheets/pages/pipelines.scss | 30 +++++++++++++++++------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 9676c2d1026..71cf17fdb41 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -264,12 +264,6 @@ line-height: 31px; } -.ci-table { - .table-holder { - overflow-x: auto; - } -} - .panel-new-merge-request { .panel-heading { padding: 5px 10px; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 149c29858fb..84af2a01997 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -574,19 +574,31 @@ } } -.pipelines.tab-pane { +.tab-pane { - .content-list.pipelines { - overflow: auto; - } + &.pipelines { - .stage { - max-width: 100px; - width: 100px; + .content-list.pipelines { + overflow: auto; + } + + .stage { + max-width: 100px; + width: 100px; + } + + .pipeline-actions { + min-width: initial; + } } - .pipeline-actions { - min-width: initial; + &.builds { + + .ci-table { + tr { + height: 71px; + } + } } } -- cgit v1.2.1 From 2461e10912b484c6942cd26f8fffd5c5557befa7 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 12 Oct 2016 13:44:33 +0200 Subject: Execute pipeline hooks asynchronously --- app/models/ci/pipeline.rb | 7 ++++++- app/workers/pipeline_hooks_worker.rb | 9 +++++++++ spec/workers/pipeline_hooks_worker_spec.rb | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 app/workers/pipeline_hooks_worker.rb create mode 100644 spec/workers/pipeline_hooks_worker_spec.rb diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 2cf9892edc5..13a58a7a308 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -3,6 +3,7 @@ module Ci extend Ci::Model include HasStatus include Importable + include AfterCommitQueue self.table_name = 'ci_commits' @@ -71,7 +72,11 @@ module Ci end after_transition do |pipeline, transition| - pipeline.execute_hooks unless transition.loopback? + next if transition.loopback? + + pipeline.run_after_commit do + PipelineHooksWorker.perform_async(id) + end end end diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb new file mode 100644 index 00000000000..ab5e9f6daad --- /dev/null +++ b/app/workers/pipeline_hooks_worker.rb @@ -0,0 +1,9 @@ +class PipelineHooksWorker + include Sidekiq::Worker + sidekiq_options queue: :default + + def perform(pipeline_id) + Ci::Pipeline.find_by(id: pipeline_id) + .try(:execute_hooks) + end +end diff --git a/spec/workers/pipeline_hooks_worker_spec.rb b/spec/workers/pipeline_hooks_worker_spec.rb new file mode 100644 index 00000000000..035e329839f --- /dev/null +++ b/spec/workers/pipeline_hooks_worker_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe PipelineHooksWorker do + describe '#perform' do + context 'when pipeline exists' do + let(:pipeline) { create(:ci_pipeline) } + + it 'executes hooks for the pipeline' do + expect_any_instance_of(Ci::Pipeline) + .to receive(:execute_hooks) + + described_class.new.perform(pipeline.id) + end + end + + context 'when pipeline does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 96ee975805dd9bbb20bd26edf2dcc7bfdc858c78 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 13 Oct 2016 10:25:38 +0100 Subject: Moved how we remove event listeners --- app/assets/javascripts/members.js.es6 | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/members.js.es6 b/app/assets/javascripts/members.js.es6 index 5dc6990bdb6..a0cd20f21e8 100644 --- a/app/assets/javascripts/members.js.es6 +++ b/app/assets/javascripts/members.js.es6 @@ -3,20 +3,13 @@ class Members { constructor() { - this.removeListeners(); this.addListeners(); } - removeListeners() { - $('.project_member, .group_member').off('ajax:success'); - $('.js-member-update-control').off('change'); - $('.js-edit-member-form').off('ajax:success'); - } - addListeners() { - $('.project_member, .group_member').on('ajax:success', this.removeRow); - $('.js-member-update-control').on('change', this.formSubmit); - $('.js-edit-member-form').on('ajax:success', this.formSuccess); + $('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow); + $('.js-member-update-control').off('change').on('change', this.formSubmit); + $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess); } removeRow(e) { -- cgit v1.2.1 From 9ec7aeac2362151e15e59531f347f2d7924437f8 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 13 Oct 2016 11:18:56 +0100 Subject: Tweaked position of badge in panel headings Various UI tweaks --- app/assets/stylesheets/framework/panels.scss | 5 +++++ app/assets/stylesheets/framework/selects.scss | 2 +- app/assets/stylesheets/pages/members.scss | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/framework/panels.scss b/app/assets/stylesheets/framework/panels.scss index c6f30e144fd..5ba0486177f 100644 --- a/app/assets/stylesheets/framework/panels.scss +++ b/app/assets/stylesheets/framework/panels.scss @@ -13,6 +13,11 @@ .dropdown-menu-toggle { line-height: 20px; } + + .badge { + margin-top: -2px; + margin-left: 5px; + } } .panel-body { diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index b309e2ad9f4..58f9db0fb21 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -94,7 +94,7 @@ } .select2-search-choice { - margin: 8px 0 0 8px; + margin: 5px 0 0 8px; box-shadow: none; border-color: $input-border; color: $gl-text-color; diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index ff4fd751f26..756efa9c7fa 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -9,6 +9,10 @@ float: left; width: 50%; } + + strong { + font-weight: 600; + } } .controls { -- cgit v1.2.1 From fafc5a1777484ba6b1b12c5e88f3fc783fb4d839 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 12:45:16 +0200 Subject: Perform CI build hooks asynchronously using worker --- app/models/ci/build.rb | 5 +++-- app/workers/build_hooks_worker.rb | 9 +++++++++ spec/workers/build_hooks_worker_spec.rb | 23 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 app/workers/build_hooks_worker.rb create mode 100644 spec/workers/build_hooks_worker_spec.rb diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 5dbf66173de..b0d13c1bf06 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -1,6 +1,7 @@ module Ci class Build < CommitStatus include TokenAuthenticatable + include AfterCommitQueue belongs_to :runner, class_name: 'Ci::Runner' belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' @@ -75,12 +76,12 @@ module Ci state_machine :status do after_transition pending: :running do |build| - build.execute_hooks + build.run_after_commit { BuildHooksWorker.perform_async(id) } end after_transition any => [:success, :failed, :canceled] do |build| build.update_coverage - build.execute_hooks + build.run_after_commit { BuildHooksWorker.perform_async(id) } end after_transition any => [:success] do |build| diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb new file mode 100644 index 00000000000..e22ececb3fd --- /dev/null +++ b/app/workers/build_hooks_worker.rb @@ -0,0 +1,9 @@ +class BuildHooksWorker + include Sidekiq::Worker + sidekiq_options queue: :default + + def perform(build_id) + Ci::Build.find_by(id: build_id) + .try(:execute_hooks) + end +end diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb new file mode 100644 index 00000000000..97654a93f5c --- /dev/null +++ b/spec/workers/build_hooks_worker_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe BuildHooksWorker do + describe '#perform' do + context 'when build exists' do + let!(:build) { create(:ci_build) } + + it 'calls build hooks' do + expect_any_instance_of(Ci::Build) + .to receive(:execute_hooks) + + described_class.new.perform(build.id) + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 204fdcb1abb9c76b2d4bd6260c6e5ce91529aeb8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 12:58:25 +0200 Subject: Add build success worker that runs asynchronously --- app/models/ci/build.rb | 21 +++++++++------------ app/workers/build_success_worker.rb | 27 +++++++++++++++++++++++++++ spec/workers/build_success_worker_spec.rb | 25 +++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 app/workers/build_success_worker.rb create mode 100644 spec/workers/build_success_worker_spec.rb diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index b0d13c1bf06..ff70f3deb52 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -76,25 +76,22 @@ module Ci state_machine :status do after_transition pending: :running do |build| - build.run_after_commit { BuildHooksWorker.perform_async(id) } + build.run_after_commit do + BuildHooksWorker.perform_async(id) + end end after_transition any => [:success, :failed, :canceled] do |build| build.update_coverage - build.run_after_commit { BuildHooksWorker.perform_async(id) } + + build.run_after_commit do + BuildHooksWorker.perform_async(id) + end end after_transition any => [:success] do |build| - if build.environment.present? - service = CreateDeploymentService.new( - build.project, build.user, - environment: build.environment, - sha: build.sha, - ref: build.ref, - tag: build.tag, - options: build.options.to_h[:environment], - variables: build.variables) - service.execute(build) + build.run_after_commit do + BuildSuccessWorker.perform_async(id) end end end diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb new file mode 100644 index 00000000000..d6db7642d82 --- /dev/null +++ b/app/workers/build_success_worker.rb @@ -0,0 +1,27 @@ +class BuildSuccessWorker + include Sidekiq::Worker + sidekiq_options queue: :default + + def perform(build_id) + Ci::Build.find_by(id: build_id).try do |build| + perform_deloyment(build) + end + end + + private + + def perform_deloyment(build) + return if build.environment.blank? + + service = CreateDeploymentService.new( + build.project, build.user, + environment: build.environment, + sha: build.sha, + ref: build.ref, + tag: build.tag, + options: build.options.to_h[:environment], + variables: build.variables) + + service.execute(build) + end +end diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb new file mode 100644 index 00000000000..c42bcd45d50 --- /dev/null +++ b/spec/workers/build_success_worker_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe BuildSuccessWorker do + describe '#perform' do + context 'when build exists' do + context 'when build belogs to the environment' do + let!(:build) { create(:ci_build, environment: 'production') } + + it 'executes deployment service' do + expect_any_instance_of(CreateDeploymentService) + .to receive(:execute) + + described_class.new.perform(build.id) + end + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 03a8ed971154cb218b82e8be53943612de94999f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 13:23:23 +0200 Subject: Use trasaction to process build deployment --- app/services/create_deployment_service.rb | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/app/services/create_deployment_service.rb b/app/services/create_deployment_service.rb index 799ad3e1bd0..c6dc2148c11 100644 --- a/app/services/create_deployment_service.rb +++ b/app/services/create_deployment_service.rb @@ -2,25 +2,29 @@ require_relative 'base_service' class CreateDeploymentService < BaseService def execute(deployable = nil) - environment = find_or_create_environment + ActiveRecord::Base.transaction do + @deployable = deployable + @environment = prepare_environment - deployment = project.deployments.create( - environment: environment, + deploy.tap do |deployment| + deployment.update_merge_request_metrics! + end + end + end + + private + + def deploy + project.deployments.create( + environment: @environment, ref: params[:ref], tag: params[:tag], sha: params[:sha], user: current_user, - deployable: deployable - ) - - deployment.update_merge_request_metrics! - - deployment + deployable: @deployable) end - private - - def find_or_create_environment + def prepare_environment project.environments.find_or_create_by(name: expanded_name) do |environment| environment.external_url = expanded_url end -- cgit v1.2.1 From 8efa041a730515e57f127850414b3557c7af60b4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 14:55:44 +0200 Subject: Do not process build success if project was removed --- app/workers/build_success_worker.rb | 6 ++++-- spec/workers/build_success_worker_spec.rb | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb index d6db7642d82..5afb15f52b4 100644 --- a/app/workers/build_success_worker.rb +++ b/app/workers/build_success_worker.rb @@ -4,13 +4,15 @@ class BuildSuccessWorker def perform(build_id) Ci::Build.find_by(id: build_id).try do |build| - perform_deloyment(build) + return unless build.project + + create_deloyment(build) end end private - def perform_deloyment(build) + def create_deloyment(build) return if build.environment.blank? service = CreateDeploymentService.new( diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb index c42bcd45d50..dba70883130 100644 --- a/spec/workers/build_success_worker_spec.rb +++ b/spec/workers/build_success_worker_spec.rb @@ -13,6 +13,17 @@ describe BuildSuccessWorker do described_class.new.perform(build.id) end end + + context 'when build is not associated with project' do + let!(:build) { create(:ci_build, project: nil) } + + it 'does not create deployment' do + expect_any_instance_of(CreateDeploymentService) + .not_to receive(:execute) + + described_class.new.perform(build.id) + end + end end context 'when build does not exist' do -- cgit v1.2.1 From 5fd635d18b77f56f6acd264ccaa1a357e2fa1cdd Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 15:22:55 +0200 Subject: Update code coverage for CI build asynchronously --- app/workers/build_coverage_worker.rb | 9 +++++++++ spec/workers/build_coverage_worker_spec.rb | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 app/workers/build_coverage_worker.rb create mode 100644 spec/workers/build_coverage_worker_spec.rb diff --git a/app/workers/build_coverage_worker.rb b/app/workers/build_coverage_worker.rb new file mode 100644 index 00000000000..0680645a8db --- /dev/null +++ b/app/workers/build_coverage_worker.rb @@ -0,0 +1,9 @@ +class BuildCoverageWorker + include Sidekiq::Worker + sidekiq_options queue: :default + + def perform(build_id) + Ci::Build.find_by(id: build_id) + .try(:update_coverage) + end +end diff --git a/spec/workers/build_coverage_worker_spec.rb b/spec/workers/build_coverage_worker_spec.rb new file mode 100644 index 00000000000..ba20488f663 --- /dev/null +++ b/spec/workers/build_coverage_worker_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe BuildCoverageWorker do + describe '#perform' do + context 'when build exists' do + let!(:build) { create(:ci_build) } + + it 'updates code coverage' do + expect_any_instance_of(Ci::Build) + .to receive(:update_coverage) + + described_class.new.perform(build.id) + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 4e9342599b472a28928a95fd43efc4df851f8e33 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 15:24:33 +0200 Subject: Fix typo in build success worker for deployment --- app/workers/build_success_worker.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb index 5afb15f52b4..a9dc34166a1 100644 --- a/app/workers/build_success_worker.rb +++ b/app/workers/build_success_worker.rb @@ -6,13 +6,13 @@ class BuildSuccessWorker Ci::Build.find_by(id: build_id).try do |build| return unless build.project - create_deloyment(build) + create_deployment(build) end end private - def create_deloyment(build) + def create_deployment(build) return if build.environment.blank? service = CreateDeploymentService.new( -- cgit v1.2.1 From 17237e14466dd75e703b93daf56e511e13bdd28b Mon Sep 17 00:00:00 2001 From: Matt Lee Date: Thu, 13 Oct 2016 14:43:05 +0000 Subject: Update README.md --- docker/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/README.md b/docker/README.md index ee1f32adc26..f9e12c5733b 100644 --- a/docker/README.md +++ b/docker/README.md @@ -2,6 +2,6 @@ * The official GitLab Community Edition Docker image is [available on Docker Hub](https://hub.docker.com/r/gitlab/gitlab-ce/). * The official GitLab Enterprise Edition Docker image is [available on Docker Hub](https://hub.docker.com/r/gitlab/gitlab-ee/). -* The complete usage guide can be found in [Using GitLab Docker images](http://doc.gitlab.com/omnibus/docker/) +* The complete usage guide can be found in [Using GitLab Docker images](https://docs.gitlab.com/omnibus/docker/) * The Dockerfile used for building public images is in [Omnibus Repository](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker) -* Check the guide for [creating Omnibus-based Docker Image](http://doc.gitlab.com/omnibus/build/README.html#build-docker-image) +* Check the guide for [creating Omnibus-based Docker Image](https://docs.gitlab.com/omnibus/build/README.html#build-docker-image) -- cgit v1.2.1 From ae851edc3c76fd7b81de2e3d48ec8a531f3609b3 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Mon, 10 Oct 2016 03:19:55 +0100 Subject: Added no-template functionality Added tests --- .../templates/issuable_template_selector.js.es6 | 8 ++++- app/views/shared/issuable/_form.html.haml | 2 ++ spec/features/projects/issuable_templates_spec.rb | 40 ++++++++++++++++++---- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/templates/issuable_template_selector.js.es6 b/app/assets/javascripts/templates/issuable_template_selector.js.es6 index 2ecf3b18975..bd4e3c3d00d 100644 --- a/app/assets/javascripts/templates/issuable_template_selector.js.es6 +++ b/app/assets/javascripts/templates/issuable_template_selector.js.es6 @@ -16,7 +16,13 @@ if (initialQuery.name) this.requestFile(initialQuery); $('.reset-template', this.dropdown.parent()).on('click', () => { - if (this.currentTemplate) this.setInputValueToTemplateContent(false); + this.setInputValueToTemplateContent(); + }); + + $('.no-template', this.dropdown.parent()).on('click', () => { + this.currentTemplate = ''; + this.setInputValueToTemplateContent(); + $('.dropdown-toggle-text', this.dropdown).text('Choose a template'); }); } diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index c3f4e10c954..16834c3db29 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -23,6 +23,8 @@ data: { data: issuable_template_names, field_name: 'issuable_template', selected: selected_template(issuable), project_path: ref_project.path, namespace_path: ref_project.namespace.path } } ) do %ul.dropdown-footer-list %li + %a.no-template + No template %a.reset-template Reset template %div{ class: issuable_template_names.any? ? 'col-sm-7 col-lg-8' : 'col-sm-10' } diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index cd79c4f512d..d886909ce85 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -15,6 +15,7 @@ feature 'issuable templates', feature: true, js: true do let(:template_content) { 'this is a test "bug" template' } let(:longtemplate_content) { %Q(this\n\n\n\n\nis\n\n\n\n\na\n\n\n\n\nbug\n\n\n\n\ntemplate) } let(:issue) { create(:issue, author: user, assignee: user, project: project) } + let(:description_addition) { ' appending to description' } background do project.repository.commit_file(user, '.gitlab/issue_templates/bug.md', template_content, 'added issue template', 'master', false) @@ -26,7 +27,26 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects "bug" template' do select_template 'bug' wait_for_ajax - preview_template(template_content) + preview_template + save_changes + end + + scenario 'user selects "bug" template and then "no template"' do + select_template 'bug' + wait_for_ajax + select_option 'No template' + wait_for_ajax + preview_template('') + save_changes('') + end + + scenario 'user selects "bug" template, edits description and then selects "reset template"' do + select_template 'bug' + wait_for_ajax + find_field('issue_description').send_keys(description_addition) + preview_template(template_content + description_addition) + select_option 'Reset template' + preview_template save_changes end @@ -37,7 +57,7 @@ feature 'issuable templates', feature: true, js: true do wait_for_ajax end_height = page.evaluate_script('$(".markdown-area").outerHeight()') - + expect(end_height).not_to eq(start_height) end end @@ -75,7 +95,7 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects "feature-proposal" template' do select_template 'feature-proposal' wait_for_ajax - preview_template(template_content) + preview_template save_changes end end @@ -102,25 +122,31 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects template' do select_template 'feature-proposal' wait_for_ajax - preview_template(template_content) + preview_template save_changes end end end end - def preview_template(expected_content) + def preview_template(expected_content = template_content) click_link 'Preview' expect(page).to have_content expected_content + click_link 'Write' end - def save_changes + def save_changes(expected_content = template_content) click_button "Save changes" - expect(page).to have_content template_content + expect(page).to have_content expected_content end def select_template(name) first('.js-issuable-selector').click first('.js-issuable-selector-wrap .dropdown-content a', text: name).click end + + def select_option(name) + first('.js-issuable-selector').click + first('.js-issuable-selector-wrap .dropdown-footer-list a', text: name).click + end end -- cgit v1.2.1 From 8751491b8db471dc661daa19bc82a9dbd58e4aae Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 13 Oct 2016 13:58:31 -0500 Subject: Improve tabbing usability for sign in page --- CHANGELOG | 1 + app/assets/stylesheets/pages/login.scss | 10 ++++++++++ app/views/devise/sessions/_new_base.html.haml | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7f96a9cba4e..a6091d3f4f1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ v 8.13.0 (unreleased) - Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675) - Respond with 404 Not Found for non-existent tags (Linus Thiel) - Truncate long labels with ellipsis in labels page + - Improve tabbing usability for sign in page (ClemMakesApps) - Adding members no longer silently fails when there is extra whitespace - Update runner version only when updating contacted_at - Add link from system note to compare with previous version diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index a5ca509163d..a08b033dff9 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -48,6 +48,16 @@ margin: 0 0 10px; } + .new_user { + position: relative; + padding-bottom: 35px; + } + + .sign-in { + position: absolute; + bottom: 0; + } + .login-footer { margin-top: 10px; diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml index 9f5520603cd..781fd1b32a6 100644 --- a/app/views/devise/sessions/_new_base.html.haml +++ b/app/views/devise/sessions/_new_base.html.haml @@ -1,6 +1,8 @@ = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off" = f.password_field :password, class: "form-control bottom", placeholder: "Password" + .sign-in + = f.submit "Sign in", class: "btn btn-save" - if devise_mapping.rememberable? .remember-me.checkbox %label{for: "user_remember_me"} @@ -8,5 +10,3 @@ %span Remember me .pull-right = link_to "Forgot your password?", new_password_path(resource_name) - %div - = f.submit "Sign in", class: "btn btn-save" -- cgit v1.2.1 From 6c7d3a0ee4c4c2b4e0a38fe92cd364c888eda907 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Fri, 14 Oct 2016 09:40:40 +1100 Subject: Remove '/u' prefix form username from Account page --- CHANGELOG | 1 + app/views/profiles/accounts/show.html.haml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 99bbd99726d..f933c298b01 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.13.0 (unreleased) + - Remove '/u' prefix form username from Account page (blackst0ne) - Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675) - Respond with 404 Not Found for non-existent tags (Linus Thiel) - Truncate long labels with ellipsis in labels page diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index c80f22457b4..8ee643f3bcc 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -86,11 +86,11 @@ = f.label :username, "Path", class: "label-light" .input-group .input-group-addon - = "#{root_url}u/" + = "#{root_url}" = f.text_field :username, required: true, class: 'form-control' .help-block Current path: - = "#{root_url}u/#{current_user.username}" + = "#{root_url}#{current_user.username}" .prepend-top-default = f.button class: "btn btn-warning", type: "submit" do = icon "spinner spin", class: "hidden loading-username" -- cgit v1.2.1 From 86d59657fc8ba0f96b8f957b1298a34144e060f9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 11:55:26 +0100 Subject: Increased performance of GL dropdown renderItem - Fixes an issue where `renderItem` is called several times even when not required - Increased performance when rendering dropdown items Closes #21110 --- app/assets/javascripts/gl_dropdown.js | 63 +++++++++++++++++------------------ 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index e034ca68645..c0cb70cb427 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -37,12 +37,9 @@ e.preventDefault() } }) - .on('keyup', function(e) { + .on('input', function(e) { var keyCode; keyCode = e.which; - if (ARROW_KEY_CODES.indexOf(keyCode) >= 0) { - return; - } if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) { $inputContainer.addClass(HAS_VALUE_CLASS); } else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) { @@ -500,14 +497,17 @@ // Render the full menu GitLabDropdown.prototype.renderMenu = function(html) { - var menu_html; - menu_html = ""; if (this.options.renderMenu) { - menu_html = this.options.renderMenu(html); + return this.options.renderMenu(html); } else { - menu_html = $('
    ').append(html); + var ul = document.createElement('ul'); + + for (var i = 0; i < html.length; i++) { + ul.appendChild(html[i]); + } + + return ul; } - return menu_html; }; // Append the menu into the dropdown @@ -521,7 +521,7 @@ }; GitLabDropdown.prototype.renderItem = function(data, group, index) { - var cssClass, field, fieldName, groupAttrs, html, selected, text, url, value; + var field, fieldName, html, selected, text, url, value; if (group == null) { group = false; } @@ -529,18 +529,16 @@ // Render the row index = false; } - html = ""; - // Divider - if (data === "divider") { - return "
  • "; - } - // Separator is a full-width divider - if (data === "separator") { - return "
  • "; + html = document.createElement('li'); + if (data === 'divider' || data === 'separator') { + html.className = data; + return html; } // Header if (data.header != null) { - return _.template('')({ header: data.header }); + html.className = 'dropdown-header'; + html.innerHTML = data.header; + return html; } if (this.options.renderRow) { // Call the render function @@ -567,24 +565,25 @@ } else { text = data.text != null ? data.text : ''; } - cssClass = ""; - if (selected) { - cssClass = "is-active"; - } if (this.highlight) { text = this.highlightTextMatches(text, this.filterInput.val()); } + // Create the list item & the link + var link = document.createElement('a'); + + link.href = url; + link.innerHTML = text; + + if (selected) { + link.className = 'is-active'; + } + if (group) { - groupAttrs = 'data-group=' + group + ' data-index=' + index; - } else { - groupAttrs = ''; + link.dataset.group = group; + link.dataset.index = index; } - html = _.template('
  • class="<%- cssClass %>"><%= text %>
  • ')({ - url: url, - groupAttrs: groupAttrs, - cssClass: cssClass, - text: text - }); + + html.appendChild(link); } return html; }; -- cgit v1.2.1 From ef5a76f68a89b9bee9070800ceb19753d0c602fe Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 17:31:08 +0100 Subject: Fixed rendering of HTML strings --- app/assets/javascripts/gl_dropdown.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index c0cb70cb427..06b31b9b24b 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -503,7 +503,13 @@ var ul = document.createElement('ul'); for (var i = 0; i < html.length; i++) { - ul.appendChild(html[i]); + var el = html[i]; + + if (typeof el === 'string') { + ul.innerHTML += el; + } else { + ul.appendChild(el); + } } return ul; -- cgit v1.2.1 From ba4e6376e1a6284286d2af46a9f5f1afa6382fd0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 09:29:37 +0100 Subject: Fixed appending jQuery elements --- app/assets/javascripts/gl_dropdown.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 06b31b9b24b..e94e7cd8be8 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -505,6 +505,10 @@ for (var i = 0; i < html.length; i++) { var el = html[i]; + if (el instanceof jQuery) { + el = el.get(0); + } + if (typeof el === 'string') { ul.innerHTML += el; } else { -- cgit v1.2.1 From e8901b20e9c07ae2654e267e5e88c0aa3476835d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 11:25:59 +0100 Subject: Changed trigger keyup to input --- app/assets/javascripts/gl_dropdown.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index e94e7cd8be8..b7a70fab74e 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -25,7 +25,7 @@ return function(e) { e.preventDefault(); e.stopPropagation(); - return _this.input.val('').trigger('keyup').focus(); + return _this.input.val('').trigger('input').focus(); }; })(this)); // Key events @@ -38,8 +38,6 @@ } }) .on('input', function(e) { - var keyCode; - keyCode = e.which; if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) { $inputContainer.addClass(HAS_VALUE_CLASS); } else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) { @@ -252,7 +250,7 @@ _this.fullData = data; _this.parseData(_this.fullData); if (_this.options.filterable && _this.filter && _this.filter.input) { - return _this.filter.input.trigger('keyup'); + return _this.filter.input.trigger('input'); } }; // Remote data @@ -484,7 +482,7 @@ // Triggering 'keyup' will re-render the dropdown which is not always required // specially if we want to keep the state of the dropdown needed for bulk-assignment if (!this.options.persistWhenHide) { - $input.trigger("keyup"); + $input.trigger("input"); } if (this.dropdown.find(".dropdown-toggle-page").length) { $('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS); -- cgit v1.2.1 From 88996deba5a1d8b29f03856b295b33caa7290981 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 12:32:30 +0100 Subject: Fixed keycode undefined --- app/assets/javascripts/gl_dropdown.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index b7a70fab74e..fe798509420 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -37,7 +37,7 @@ e.preventDefault() } }) - .on('input', function(e) { + .on('input', function() { if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) { $inputContainer.addClass(HAS_VALUE_CLASS); } else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) { @@ -50,10 +50,6 @@ if (this.options.remote) { clearTimeout(timeout); return timeout = setTimeout(function() { - var blurField = this.shouldBlur(keyCode); - if (blurField && this.filterInputBlur) { - this.input.blur(); - } return this.options.query(this.input.val(), function(data) { return this.options.callback(data); }.bind(this)); -- cgit v1.2.1 From ab2a7a806a698d6638bb8b3f2ecc694f265fe65e Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 13 Oct 2016 23:38:50 -0700 Subject: Add missing routes to make group edits work Closes #23306 --- config/routes/group.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/routes/group.rb b/config/routes/group.rb index 47a8a0a53d4..8bee2bb1eb4 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -3,6 +3,10 @@ require 'constraints/group_url_constrainer' constraints(GroupUrlConstrainer.new) do scope(path: ':id', as: :group, controller: :groups) do get '/', action: :show + post '/', action: :create + patch '/', action: :update + put '/', action: :update + delete '/', action: :destroy end end -- cgit v1.2.1 From 17e23b4c9c141bdbdcde4efec0bbcfdd544da8bd Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 14 Oct 2016 00:06:44 -0700 Subject: Add specs for group edit and deletion --- spec/features/groups_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index c54ec2563ad..3f908294cbb 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -47,6 +47,32 @@ feature 'Group', feature: true do end end + describe 'Group Edit' do + let(:group) { create(:group) } + let(:path) { edit_group_path(group) } + + it 'saves new settings' do + expect(group.request_access_enabled).to be_truthy + visit path + + find('#group_request_access_enabled').set(false) + + click_button 'Save group' + + expect(page).to have_content 'successfully updated' + group.reload + expect(group.request_access_enabled).to be_falsey + end + + it 'removes group' do + visit path + + click_link 'Remove Group' + + expect(page).to have_content "scheduled for deletion" + end + end + describe 'description' do let(:group) { create(:group) } let(:path) { group_path(group) } -- cgit v1.2.1 From 3726dc4bb73647123ebef5c97f401f5537d3ae16 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 14 Oct 2016 10:19:16 +0200 Subject: Check if project exists before creating deployment --- app/services/create_deployment_service.rb | 6 ++++++ app/workers/build_success_worker.rb | 2 -- spec/services/create_deployment_service_spec.rb | 17 ++++++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/app/services/create_deployment_service.rb b/app/services/create_deployment_service.rb index c6dc2148c11..ff9a8310a8c 100644 --- a/app/services/create_deployment_service.rb +++ b/app/services/create_deployment_service.rb @@ -2,6 +2,8 @@ require_relative 'base_service' class CreateDeploymentService < BaseService def execute(deployable = nil) + return unless executable? + ActiveRecord::Base.transaction do @deployable = deployable @environment = prepare_environment @@ -14,6 +16,10 @@ class CreateDeploymentService < BaseService private + def executable? + project && name.present? + end + def deploy project.deployments.create( environment: @environment, diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb index a9dc34166a1..500d357ce31 100644 --- a/app/workers/build_success_worker.rb +++ b/app/workers/build_success_worker.rb @@ -4,8 +4,6 @@ class BuildSuccessWorker def perform(build_id) Ci::Build.find_by(id: build_id).try do |build| - return unless build.project - create_deployment(build) end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 343b4385bf2..5fe56e7725f 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -84,11 +84,22 @@ describe CreateDeploymentService, services: true do expect(subject).to be_persisted end end + + context 'when project was removed' do + let(:project) { nil } + + it 'does not create deployment or environment' do + expect { subject }.not_to raise_error + + expect(Environment.count).to be_zero + expect(Deployment.count).to be_zero + end + end end describe 'processing of builds' do let(:environment) { nil } - + shared_examples 'does not create environment and deployment' do it 'does not create a new environment' do expect { subject }.not_to change { Environment.count } @@ -133,12 +144,12 @@ describe CreateDeploymentService, services: true do context 'without environment specified' do let(:build) { create(:ci_build, project: project) } - + it_behaves_like 'does not create environment and deployment' do subject { build.success } end end - + context 'when environment is specified' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline, environment: 'production', options: options) } -- cgit v1.2.1 From ebddb5f329778ebf96d78c31e2ac93707a455864 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 14 Oct 2016 09:34:53 +0100 Subject: Fixed undefined keycode build error --- app/assets/javascripts/gl_dropdown.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index fe798509420..53762f2965c 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -43,9 +43,6 @@ } else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) { $inputContainer.removeClass(HAS_VALUE_CLASS); } - if (keyCode === 13 && !options.elIsInput) { - return false; - } // Only filter asynchronously only if option remote is set if (this.options.remote) { clearTimeout(timeout); -- cgit v1.2.1 From b8003aa012843fac1745c94788b993c36570fbd9 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 14 Oct 2016 11:47:54 +0200 Subject: Calculate build coverage asynchronously --- app/models/ci/build.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index ff70f3deb52..23119c5ed61 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -82,9 +82,8 @@ module Ci end after_transition any => [:success, :failed, :canceled] do |build| - build.update_coverage - build.run_after_commit do + BuildCoverageWorker.perform_async(id) BuildHooksWorker.perform_async(id) end end -- cgit v1.2.1 From 270434f7372dcb4d412f3f62068f69d8eac212e8 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 13 Oct 2016 08:34:35 +0100 Subject: Loads GFM once for per page #22827 --- CHANGELOG | 1 + app/views/layouts/application.html.haml | 1 + app/views/projects/_zen.html.haml | 4 +--- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 99bbd99726d..7c8989b2072 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -116,6 +116,7 @@ v 8.13.0 (unreleased) v 8.12.7 - Use gitlab-markup gem instead of github-markup to fix `.rst` file rendering. !6659 + - Fix GFM autocomplete setup being called several times v 8.12.6 - Update mailroom to 0.8.1 in Gemfile.lock !6814 diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 15a94ac23c5..6c2285fa2b6 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -11,3 +11,4 @@ = render 'layouts/page', sidebar: sidebar, nav: nav = yield :scripts_body + = render "layouts/init_auto_complete" if @gfm_form diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml index cb97181b9e1..0c8241053e7 100644 --- a/app/views/projects/_zen.html.haml +++ b/app/views/projects/_zen.html.haml @@ -1,3 +1,4 @@ +- @gfm_form = true - supports_slash_commands = local_assigns.fetch(:supports_slash_commands, false) .zen-backdrop - classes << ' js-gfm-input js-autosize markdown-area' @@ -7,6 +8,3 @@ = text_area_tag attr, nil, class: classes, placeholder: placeholder %a.zen-control.zen-control-leave.js-zen-leave{ href: "#" } = icon('compress') - -- content_for :scripts_body do - = render "layouts/init_auto_complete" if current_user && (@target_project || @project) -- cgit v1.2.1 From eb4a42e0cef5e89b1d01cfa2a401908ffd09874c Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Fri, 14 Oct 2016 21:26:43 +1100 Subject: Remove changelog item and interpolation --- CHANGELOG | 1 - app/views/profiles/accounts/show.html.haml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f933c298b01..99bbd99726d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,6 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.13.0 (unreleased) - - Remove '/u' prefix form username from Account page (blackst0ne) - Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675) - Respond with 404 Not Found for non-existent tags (Linus Thiel) - Truncate long labels with ellipsis in labels page diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 8ee643f3bcc..e2e974ba072 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -86,7 +86,7 @@ = f.label :username, "Path", class: "label-light" .input-group .input-group-addon - = "#{root_url}" + = root_url = f.text_field :username, required: true, class: 'form-control' .help-block Current path: -- cgit v1.2.1 From d7324f0ed5181f0eb765871a35eaee587bf25fa9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 14 Oct 2016 14:51:59 +0300 Subject: Move edit group scenario to rspec and refactor groups_spec Signed-off-by: Dmitriy Zaporozhets --- config/routes/group.rb | 1 - features/groups.feature | 5 --- features/steps/groups.rb | 12 ------- spec/features/groups_spec.rb | 78 ++++++++++++++++++++++++-------------------- 4 files changed, 42 insertions(+), 54 deletions(-) diff --git a/config/routes/group.rb b/config/routes/group.rb index 8bee2bb1eb4..33143f0dfa2 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -3,7 +3,6 @@ require 'constraints/group_url_constrainer' constraints(GroupUrlConstrainer.new) do scope(path: ':id', as: :group, controller: :groups) do get '/', action: :show - post '/', action: :create patch '/', action: :update put '/', action: :update delete '/', action: :destroy diff --git a/features/groups.feature b/features/groups.feature index 49e939807b5..4044bd9be79 100644 --- a/features/groups.feature +++ b/features/groups.feature @@ -39,11 +39,6 @@ Feature: Groups When I visit group "Owned" merge requests page Then I should not see merge requests from the archived project - Scenario: I should see edit group "Owned" page - When I visit group "Owned" settings page - And I change group "Owned" name to "new-name" - Then I should see new group "Owned" name - Scenario: I edit group "Owned" avatar When I visit group "Owned" settings page And I change group "Owned" avatar diff --git a/features/steps/groups.rb b/features/steps/groups.rb index 4fa7d7c6567..0e81e99120b 100644 --- a/features/steps/groups.rb +++ b/features/steps/groups.rb @@ -73,18 +73,6 @@ class Spinach::Features::Groups < Spinach::FeatureSteps author: current_user end - step 'I change group "Owned" name to "new-name"' do - fill_in 'group_name', with: 'new-name' - fill_in 'group_path', with: 'new-name' - click_button "Save group" - end - - step 'I should see new group "Owned" name' do - page.within ".navbar-gitlab" do - expect(page).to have_content "new-name" - end - end - step 'I change group "Owned" avatar' do attach_file(:group_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')) click_button "Save group" diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index 3f908294cbb..13bfe90302c 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -11,93 +11,99 @@ feature 'Group', feature: true do end end - describe 'creating a group with space in group path' do - it 'renders new group form with validation errors' do - visit new_group_path - fill_in 'Group path', with: 'space group' + describe 'create a group' do + before { visit new_group_path } - click_button 'Create group' + describe 'with space in group path' do + it 'renders new group form with validation errors' do + fill_in 'Group path', with: 'space group' + click_button 'Create group' - expect(current_path).to eq(groups_path) - expect(page).to have_namespace_error_message + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message + end end - end - - describe 'creating a group with .atom at end of group path' do - it 'renders new group form with validation errors' do - visit new_group_path - fill_in 'Group path', with: 'atom_group.atom' - click_button 'Create group' + describe 'with .atom at end of group path' do + it 'renders new group form with validation errors' do + fill_in 'Group path', with: 'atom_group.atom' + click_button 'Create group' - expect(current_path).to eq(groups_path) - expect(page).to have_namespace_error_message + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message + end end - end - - describe 'creating a group with .git at end of group path' do - it 'renders new group form with validation errors' do - visit new_group_path - fill_in 'Group path', with: 'git_group.git' - click_button 'Create group' + describe 'with .git at end of group path' do + it 'renders new group form with validation errors' do + fill_in 'Group path', with: 'git_group.git' + click_button 'Create group' - expect(current_path).to eq(groups_path) - expect(page).to have_namespace_error_message + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message + end end end - describe 'Group Edit' do + describe 'group edit' do let(:group) { create(:group) } let(:path) { edit_group_path(group) } + let(:new_name) { 'new-name' } - it 'saves new settings' do - expect(group.request_access_enabled).to be_truthy - visit path - - find('#group_request_access_enabled').set(false) + before { visit path } + it 'saves new settings' do + fill_in 'group_name', with: new_name click_button 'Save group' expect(page).to have_content 'successfully updated' - group.reload - expect(group.request_access_enabled).to be_falsey + expect(find('#group_name').value).to eq(new_name) + + page.within ".navbar-gitlab" do + expect(page).to have_content new_name + end end it 'removes group' do - visit path - click_link 'Remove Group' expect(page).to have_content "scheduled for deletion" end end - describe 'description' do + describe 'group page with markdown description' do let(:group) { create(:group) } let(:path) { group_path(group) } it 'parses Markdown' do group.update_attribute(:description, 'This is **my** group') + visit path + expect(page).to have_css('.description > p > strong') end it 'passes through html-pipeline' do group.update_attribute(:description, 'This group is the :poop:') + visit path + expect(page).to have_css('.description > p > img') end it 'sanitizes unwanted tags' do group.update_attribute(:description, '# Group Description') + visit path + expect(page).not_to have_css('.description h1') end it 'permits `rel` attribute on links' do group.update_attribute(:description, 'https://google.com/') + visit path + expect(page).to have_css('.description a[rel]') end end -- cgit v1.2.1 From fd7fb993667265967633a1ac51f0ed17d852ae64 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Wed, 5 Oct 2016 18:24:39 -0600 Subject: Remove spinach retry. --- .gitlab-ci.yml | 2 +- Gemfile | 1 - Gemfile.lock | 3 --- features/support/db_cleaner.rb | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c3b864f16cf..30471286026 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -99,7 +99,7 @@ update-knapsack: - export KNAPSACK_REPORT_PATH=knapsack/spinach_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json - export KNAPSACK_GENERATE_REPORT=true - cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH} - - knapsack spinach "-r rerun" || retry '[ ! -e tmp/spinach-rerun.txt ] || bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt)' + - knapsack spinach artifacts: expire_in: 31d paths: diff --git a/Gemfile b/Gemfile index 5f754c1b66f..563851c25f5 100644 --- a/Gemfile +++ b/Gemfile @@ -278,7 +278,6 @@ group :development, :test do gem 'rspec-rails', '~> 3.5.0' gem 'rspec-retry', '~> 0.4.5' gem 'spinach-rails', '~> 0.2.1' - gem 'spinach-rerun-reporter', '~> 0.0.2' # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826) gem 'minitest', '~> 5.7.0' diff --git a/Gemfile.lock b/Gemfile.lock index a9892d1c130..60d434a1b69 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -700,8 +700,6 @@ GEM capybara (>= 2.0.0) railties (>= 3) spinach (>= 0.4) - spinach-rerun-reporter (0.0.2) - spinach (~> 0.8) spring (1.7.2) spring-commands-rspec (1.0.4) spring (>= 0.9.1) @@ -964,7 +962,6 @@ DEPENDENCIES simplecov (= 0.12.0) slack-notifier (~> 1.2.0) spinach-rails (~> 0.2.1) - spinach-rerun-reporter (~> 0.0.2) spring (~> 1.7.0) spring-commands-rspec (~> 1.0.4) spring-commands-spinach (~> 1.1.0) diff --git a/features/support/db_cleaner.rb b/features/support/db_cleaner.rb index 1ab308cfa55..8294bb1445f 100644 --- a/features/support/db_cleaner.rb +++ b/features/support/db_cleaner.rb @@ -1,6 +1,6 @@ require 'database_cleaner' -DatabaseCleaner.strategy = :truncation +DatabaseCleaner[:active_record].strategy = :truncation Spinach.hooks.before_scenario do DatabaseCleaner.start -- cgit v1.2.1 From 06528eebb2255a77904d751e9f3934210cd5945b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 14 Oct 2016 13:09:18 +0200 Subject: Re-run specs if failed --- .gitlab-ci.yml | 2 +- Gemfile | 1 + Gemfile.lock | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 30471286026..48015d5ec2a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -99,7 +99,7 @@ update-knapsack: - export KNAPSACK_REPORT_PATH=knapsack/spinach_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json - export KNAPSACK_GENERATE_REPORT=true - cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH} - - knapsack spinach + - if ! knapsack spinach "-r rerun"; then bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt); fi artifacts: expire_in: 31d paths: diff --git a/Gemfile b/Gemfile index 563851c25f5..5f754c1b66f 100644 --- a/Gemfile +++ b/Gemfile @@ -278,6 +278,7 @@ group :development, :test do gem 'rspec-rails', '~> 3.5.0' gem 'rspec-retry', '~> 0.4.5' gem 'spinach-rails', '~> 0.2.1' + gem 'spinach-rerun-reporter', '~> 0.0.2' # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826) gem 'minitest', '~> 5.7.0' diff --git a/Gemfile.lock b/Gemfile.lock index 60d434a1b69..a9892d1c130 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -700,6 +700,8 @@ GEM capybara (>= 2.0.0) railties (>= 3) spinach (>= 0.4) + spinach-rerun-reporter (0.0.2) + spinach (~> 0.8) spring (1.7.2) spring-commands-rspec (1.0.4) spring (>= 0.9.1) @@ -962,6 +964,7 @@ DEPENDENCIES simplecov (= 0.12.0) slack-notifier (~> 1.2.0) spinach-rails (~> 0.2.1) + spinach-rerun-reporter (~> 0.0.2) spring (~> 1.7.0) spring-commands-rspec (~> 1.0.4) spring-commands-spinach (~> 1.1.0) -- cgit v1.2.1 From caa141eaa719f52b126065ff42c68fdc36b52437 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 14 Oct 2016 14:12:30 +0200 Subject: Fix retries --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 48015d5ec2a..ace0de5cad3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -99,7 +99,7 @@ update-knapsack: - export KNAPSACK_REPORT_PATH=knapsack/spinach_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json - export KNAPSACK_GENERATE_REPORT=true - cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH} - - if ! knapsack spinach "-r rerun"; then bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt); fi + - knapsack spinach "-r rerun" || retry '[[ -e tmp/spinach-rerun.txt ]] && bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt)' artifacts: expire_in: 31d paths: -- cgit v1.2.1 From eaa22eb447b8dcd690f084221db26043274f343b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 14 Oct 2016 14:32:47 +0200 Subject: Try to fix re-run --- features/support/rerun.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/support/rerun.rb b/features/support/rerun.rb index 8b176c5be89..60b78f9d050 100644 --- a/features/support/rerun.rb +++ b/features/support/rerun.rb @@ -1,5 +1,7 @@ # The spinach-rerun-reporter doesn't define the on_undefined_step # See it here: https://github.com/javierav/spinach-rerun-reporter/blob/master/lib/spinach/reporter/rerun.rb +require 'spinach-rerun-reporter' + module Spinach class Reporter class Rerun -- cgit v1.2.1 From 5904793ad8ba88d3dfc9c973bcffd1d426db5a33 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 14 Oct 2016 12:53:51 +0200 Subject: Add build finished worker that creates a workflow --- app/models/ci/build.rb | 3 +-- app/workers/build_finished_worker.rb | 12 ++++++++++++ spec/workers/build_finished_worker_spec.rb | 30 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 app/workers/build_finished_worker.rb create mode 100644 spec/workers/build_finished_worker_spec.rb diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 23119c5ed61..87475119b23 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -83,8 +83,7 @@ module Ci after_transition any => [:success, :failed, :canceled] do |build| build.run_after_commit do - BuildCoverageWorker.perform_async(id) - BuildHooksWorker.perform_async(id) + BuildFinishedWorker.perform_async(id) end end diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb new file mode 100644 index 00000000000..f1267ab92fc --- /dev/null +++ b/app/workers/build_finished_worker.rb @@ -0,0 +1,12 @@ +class BuildFinishedWorker + include Sidekiq::Worker + + def perform(build_id) + Ci::Build.find_by(id: build_id).try do |build| + build.with_lock do + BuildCoverageWorker.new.perform(build.id) + BuildHooksWorker.new.perform(build.id) + end + end + end +end diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb new file mode 100644 index 00000000000..2868167c7d4 --- /dev/null +++ b/spec/workers/build_finished_worker_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe BuildFinishedWorker do + describe '#perform' do + context 'when build exists' do + let(:build) { create(:ci_build) } + + it 'calculates coverage and calls hooks' do + expect(BuildCoverageWorker) + .to receive(:new).ordered.and_call_original + expect(BuildHooksWorker) + .to receive(:new).ordered.and_call_original + + expect_any_instance_of(BuildCoverageWorker) + .to receive(:perform) + expect_any_instance_of(BuildHooksWorker) + .to receive(:perform) + + described_class.new.perform(build.id) + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From f24966174701024ece1e728315f5e847b684ee65 Mon Sep 17 00:00:00 2001 From: Sean Packham Date: Fri, 14 Oct 2016 13:53:35 +0100 Subject: Added book club to university --- doc/university/README.md | 1 + doc/university/bookclub/booklist.md | 113 ++++++++++++++++++++++++++++++++++++ doc/university/bookclub/index.md | 19 ++++++ 3 files changed, 133 insertions(+) create mode 100644 doc/university/bookclub/booklist.md create mode 100644 doc/university/bookclub/index.md diff --git a/doc/university/README.md b/doc/university/README.md index e71e49c33c8..f5a0dab39fe 100644 --- a/doc/university/README.md +++ b/doc/university/README.md @@ -64,6 +64,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project 1. [Making GitLab Great for Everyone - Video](https://www.youtube.com/watch?v=GGC40y4vMx0) - Response to "Dear GitHub" letter 1. [Using Innersourcing to Improve Collaboration](https://about.gitlab.com/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) 1. [The Software Development Market and GitLab - Video](https://www.youtube.com/watch?v=sXlhgPK1NTY&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=6) - [Slides](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit) +1. [The GitLab Book Club](bookclub/index.md) #### 1.7 Community and Support diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md new file mode 100644 index 00000000000..c4229832e9f --- /dev/null +++ b/doc/university/bookclub/booklist.md @@ -0,0 +1,113 @@ +# Books + +List of books and resources, that may be worth reading. + +## Papers + +1. **The Humble Programmer** + + Edsger W. Dijkstra, 1972 ([paper](http://dl.acm.org/citation.cfm?id=361591)) + +## Programming + +1. **Design Patterns: Elements of Reusable Object-Oriented Software** + + Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, 1994 ([amazon](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)) + +1. **Clean Code: A Handbook of Agile Software Craftsmanship** + + Robert C. "Uncle Bob" Martin, 2008 ([amazon](http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)) + +1. **Code Complete: A Practical Handbook of Software Construction**, 2nd Edition + + Steve McConnell, 2004 ([amazon](http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670)) + +1. **The Pragmatic Programmer: From Journeyman to Master** + + Andrew Hunt, David Thomas, 1999 ([amazon](http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X)) + +1. **Working Effectively with Legacy Code** + + Michael Feathers, 2004 ([amazon](http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052)) + +1. **Eloquent Ruby** + + Russ Olsen, 2011 ([amazon](http://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional/dp/0321584104)) + +1. **Domain-Driven Design: Tackling Complexity in the Heart of Software** + + Eric Evans, 2003 ([amazon](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215)) + +1. **How to Solve It: A New Aspect of Mathematical Method** + + Polya G. 1957 ([amazon](http://www.amazon.com/How-Solve-Mathematical-Princeton-Science/dp/069116407X)) + +1. **Software Creativity 2.0** + + Robert L. Glass, 2006 ([amazon](http://www.amazon.com/Software-Creativity-2-0-Robert-Glass/dp/0977213315)) + +1. **Object-Oriented Software Construction** + + Bertrand Meyer, 1997 ([amazon](http://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554)) + +1. **Refactoring: Improving the Design of Existing Code** + + Martin Fowler, Kent Beck, 1999 ([amazon](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672)) + +1. **Test Driven Development: By Example** + + Kent Beck, 2002 ([amazon](http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530)) + +1. **Algorithms in C++: Fundamentals, Data Structure, Sorting, Searching** + + Robert Sedgewick, 1990 ([amazon](http://www.amazon.com/Algorithms-Parts-1-4-Fundamentals-Structure/dp/0201350882)) + +1. **Effective C++** + + Scott Mayers, 1996 ([amazon](http://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876)) + +1. **Extreme Programming Explained: Embrace Change** + + Kent Beck, 1999 ([amazon](http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658)) + +1. **The Art of Computer Programming** + + Donald E. Knuth, 1997 ([amazon](http://www.amazon.com/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043)) + +1. **Writing Efficient Programs** + + Jon Louis Bentley, 1982 ([amazon](http://www.amazon.com/Writing-Efficient-Programs-Prentice-Hall-Software/dp/013970244X)) + +1. **The Mythical Man-Month: Essays on Software Engineering** + + Frederick Phillips Brooks, 1975 ([amazon](http://www.amazon.com/Mythical-Man-Month-Essays-Software-Engineering/dp/0201006502)) + +1. **Peopleware: Productive Projects and Teams** 3rd Edition + + Tom DeMarco, Tim Lister, 2013 ([amazon](http://www.amazon.com/Peopleware-Productive-Projects-Teams-3rd/dp/0321934113)) + +1. **Principles Of Software Engineering Management** + + Tom Gilb, 1988 ([amazon](http://www.amazon.com/Principles-Software-Engineering-Management-Gilb/dp/0201192462)) + +## Other + +1. **Thinking, Fast and Slow** + + Daniel Kahneman, 2013 ([amazon](http://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555)) + +1. **The Social Animal** 11th Edition + + Elliot Aronson, 2011 ([amazon](http://www.amazon.com/Social-Animal-Elliot-Aronson/dp/1429233419)) + +1. **Influence: Science and Practice** 5th Edition + + Robert B. Cialdini, 2008 ([amazon](http://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996)) + +1. **Getting to Yes: Negotiating Agreement Without Giving In** + + Roger Fisher, William L. Ury, Bruce Patton, 2011 ([amazon](http://www.amazon.com/Getting-Yes-Negotiating-Agreement-Without/dp/0143118757)) + +1. **How to Win Friends & Influence People** + + Dale Carnegie, 1981 ([amazon](http://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034)) diff --git a/doc/university/bookclub/index.md b/doc/university/bookclub/index.md new file mode 100644 index 00000000000..022a61f4429 --- /dev/null +++ b/doc/university/bookclub/index.md @@ -0,0 +1,19 @@ +# The GitLab Book Club + +The Book Club is a casual meet-up to read and discuss books we like. +We'll find a time that suits most, if not all. + +See the [book list](booklist.md) for additional recommendations. + +## Currently reading : Books about remote work + +1. **Remote: Office not required** + + David Heinemeier Hansson and Jason Fried, 2013 + ([amazon](http://www.amazon.co.uk/Remote-Required-David-Heinemeier-Hansson/dp/0091954673)) + +1. **The Year Without Pants** + + Scott Berkun, 2013 ([ScottBerkun.com](http://scottberkun.com/yearwithoutpants/)) + +Any other books you'd like to suggest? Edit this page and add them to the queue. -- cgit v1.2.1 From aef739605987dc70424b83c56ba393462520af52 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 30 Sep 2016 11:38:56 +0200 Subject: Cache gems in CI on tags --- .gitlab-ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 62e06683124..7d19f55aca3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -339,3 +339,16 @@ pages: - public only: - master + +# Insurance in case a gem needed by one of our releases gets yanked from +# rubygems.org in the future. +cache gems: + only: + - tags + variables: + SETUP_DB: "false" + script: + - bundle package --all --all-platforms + artifacts: + paths: + - vendor/cache -- cgit v1.2.1 From c736ffdfb043df34a89273639297cfc86d2d5f88 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 14 Oct 2016 16:04:23 +0300 Subject: Validate user id for users select autcomplete Single user autcomplete should be used only for existing users with digital ID provided. Now js code puts any input into generating user URL which can lead to 500 error because routing like this does not exists: GET "/autocomplete/users/whatever@example.com.json". Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/users_select.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js index 6aa0e1cd2b6..3020b7cc239 100644 --- a/app/assets/javascripts/users_select.js +++ b/app/assets/javascripts/users_select.js @@ -325,6 +325,10 @@ }; UsersSelect.prototype.user = function(user_id, callback) { + if(!/^\d+$/.test(user_id)) { + return false; + } + var url; url = this.buildUrl(this.userPath); url = url.replace(':id', user_id); -- cgit v1.2.1 From 9ec3c32f98f9548b4aa756c8fba74159b12492a7 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 14 Oct 2016 13:39:20 +0100 Subject: Improved specifity of toggleable file headers --- .gitlab-ci.yml | 13 ------------- app/assets/stylesheets/framework/files.scss | 9 --------- app/assets/stylesheets/pages/diff.scss | 13 +++++++++++++ app/assets/stylesheets/pages/notes.scss | 8 ++++++++ 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7d19f55aca3..62e06683124 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -339,16 +339,3 @@ pages: - public only: - master - -# Insurance in case a gem needed by one of our releases gets yanked from -# rubygems.org in the future. -cache gems: - only: - - tags - variables: - SETUP_DB: "false" - script: - - bundle package --all --all-platforms - artifacts: - paths: - - vendor/cache diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 81520500594..76a3c083697 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -26,15 +26,6 @@ padding: 10px $gl-padding; word-wrap: break-word; border-radius: 3px 3px 0 0; - cursor: pointer; - - &:hover { - background-color: $dark-background-color; - } - - .diff-toggle-caret { - padding-right: 6px; - } &.file-title-clear { padding-left: 0; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index b8ef76cc74e..84094b0cb1b 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -33,6 +33,19 @@ font-size: smaller; } } + + .file-title { + cursor: pointer; + + &:hover { + background-color: $dark-background-color; + } + + .diff-toggle-caret { + padding-right: 6px; + } + } + .diff-content { overflow: auto; overflow-y: hidden; diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index d399f84a2ff..efeea96373f 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -147,6 +147,14 @@ ul.notes { // Diff code in discussion view .discussion-body .diff-file { + .file-title { + cursor: default; + + &:hover { + background-color: $gray-light; + } + } + .diff-header > span { margin-right: 10px; } -- cgit v1.2.1 From 5bcf56401e502e9bb6094d37e76ea736d68cddfc Mon Sep 17 00:00:00 2001 From: De Wet Blomerus Date: Fri, 14 Oct 2016 15:16:18 +0200 Subject: remove a period that can be annoying --- .gitlab/merge_request_templates/Documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md index d2a1eb56423..9b541aadad1 100644 --- a/.gitlab/merge_request_templates/Documentation.md +++ b/.gitlab/merge_request_templates/Documentation.md @@ -1,4 +1,4 @@ -See the general Documentation guidelines http://docs.gitlab.com/ce/development/doc_styleguide.html. +See the general Documentation guidelines http://docs.gitlab.com/ce/development/doc_styleguide.html ## What does this MR do? -- cgit v1.2.1 From 513f061b5b521a1a428a05ebc467784f672ae07b Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 14 Oct 2016 14:47:13 +0100 Subject: Use gitlab-workhorse 0.8.5 --- GITLAB_WORKHORSE_VERSION | 2 +- doc/install/installation.md | 2 +- doc/update/8.12-to-8.13.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index b60d71966ae..7ada0d303f3 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.8.4 +0.8.5 diff --git a/doc/install/installation.md b/doc/install/installation.md index 1fa8678223a..c9acc9cdfb0 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -400,7 +400,7 @@ If you are not using Linux you may have to run `gmake` instead of cd /home/git sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git cd gitlab-workhorse - sudo -u git -H git checkout v0.8.4 + sudo -u git -H git checkout v0.8.5 sudo -u git -H make ### Initialize Database and Activate Advanced Features diff --git a/doc/update/8.12-to-8.13.md b/doc/update/8.12-to-8.13.md index 00d63c1b3c6..8940d14559b 100644 --- a/doc/update/8.12-to-8.13.md +++ b/doc/update/8.12-to-8.13.md @@ -84,7 +84,7 @@ GitLab 8.1. ```bash cd /home/git/gitlab-workhorse sudo -u git -H git fetch --all -sudo -u git -H git checkout v0.8.4 +sudo -u git -H git checkout v0.8.5 sudo -u git -H make ``` -- cgit v1.2.1 From c5bf8e362ce10e52428bda873eb14b41e15a1bd0 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 14 Oct 2016 14:34:31 +0200 Subject: Use module_function in Banzai::Renderer Using `extend self` prevents GitLab Performance Monitoring from being able to track class methods. Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/23347 --- CHANGELOG | 1 + lib/banzai/renderer.rb | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4f2f74a7595..d2f1501bd2a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,7 @@ v 8.13.0 (unreleased) - Add an example for testing a phoenix application with Gitlab CI in the docs (Manthan Mallikarjun) - Updating verbiage on git basics to be more intuitive - Clarify documentation for Runners API (Gennady Trafimenkov) + - The instrumentation for Banzai::Renderer has been restored - Change user & group landing page routing from /u/:username to /:username - Prevent running GfmAutocomplete setup for each diff note !6569 - Added documentation for .gitattributes files diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb index 6924a293da8..ce048a36fa0 100644 --- a/lib/banzai/renderer.rb +++ b/lib/banzai/renderer.rb @@ -1,6 +1,6 @@ module Banzai module Renderer - extend self + module_function # Convert a Markdown String into an HTML-safe String of HTML # @@ -141,8 +141,6 @@ module Banzai end.html_safe end - private - def cacheless_render(text, context = {}) Gitlab::Metrics.measure(:banzai_cacheless_render) do result = render_result(text, context) -- cgit v1.2.1 From 3f8fa3576509e2c90fbf9c18450e3daede32deac Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 14 Oct 2016 15:53:06 +0100 Subject: Document restrictions on cache and artifact paths See https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/1792 --- doc/ci/yaml/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 59399861a97..84ea59ab687 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -159,7 +159,8 @@ Variables can be also defined on [job level](#job-variables). > Introduced in GitLab Runner v0.7.0. `cache` is used to specify a list of files and directories which should be -cached between builds. +cached between builds. You can only use paths that are within the project +workspace. **By default the caching is enabled per-job and per-branch.** @@ -606,8 +607,8 @@ You can see a simple example at https://gitlab.com/gitlab-examples/review-apps-n > - Build artifacts are only collected for successful builds by default. `artifacts` is used to specify a list of files and directories which should be -attached to the build after success. To pass artifacts between different builds, -see [dependencies](#dependencies). +attached to the build after success. You can only use paths that are within the +project workspace. To pass artifacts between different builds, see [dependencies](#dependencies). Below are some examples. -- cgit v1.2.1 From 308769f82b19a142f443fb101a01a60c2b19757f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 14 Oct 2016 17:48:28 +0200 Subject: Remove unecessary lock --- app/workers/build_finished_worker.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb index f1267ab92fc..e7286b77ac5 100644 --- a/app/workers/build_finished_worker.rb +++ b/app/workers/build_finished_worker.rb @@ -3,10 +3,8 @@ class BuildFinishedWorker def perform(build_id) Ci::Build.find_by(id: build_id).try do |build| - build.with_lock do - BuildCoverageWorker.new.perform(build.id) - BuildHooksWorker.new.perform(build.id) - end + BuildCoverageWorker.new.perform(build.id) + BuildHooksWorker.new.perform(build.id) end end end -- cgit v1.2.1 From b9f351e8798529f09316c0d8ab77a01c6a18f7bf Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 14 Oct 2016 17:12:50 +0000 Subject: Rename pipeline.js.es6 to pipelines.js.es6 --- app/assets/javascripts/pipeline.js.es6 | 40 --------------------------------- app/assets/javascripts/pipelines.js.es6 | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) delete mode 100644 app/assets/javascripts/pipeline.js.es6 create mode 100644 app/assets/javascripts/pipelines.js.es6 diff --git a/app/assets/javascripts/pipeline.js.es6 b/app/assets/javascripts/pipeline.js.es6 deleted file mode 100644 index 6bf63ee6979..00000000000 --- a/app/assets/javascripts/pipeline.js.es6 +++ /dev/null @@ -1,40 +0,0 @@ -((global) => { - - class Pipelines { - constructor() { - $(document).off('click', '.toggle-pipeline-btn').on('click', '.toggle-pipeline-btn', this.toggleGraph); - this.addMarginToBuildColumns(); - } - - toggleGraph() { - const $pipelineBtn = $(this).closest('.toggle-pipeline-btn'); - const $pipelineGraph = $(this).closest('.row-content-block').next('.pipeline-graph'); - const $btnText = $(this).find('.toggle-btn-text'); - const graphCollapsed = $pipelineGraph.hasClass('graph-collapsed'); - - $($pipelineBtn).add($pipelineGraph).toggleClass('graph-collapsed'); - - - graphCollapsed ? $btnText.text('Expand') : $btnText.text('Hide') - } - - addMarginToBuildColumns() { - const $secondChildBuildNode = $('.build:nth-child(2)'); - if ($secondChildBuildNode.length) { - const $firstChildBuildNode = $secondChildBuildNode.prev('.build'); - const $multiBuildColumn = $secondChildBuildNode.closest('.stage-column'); - const $previousColumn = $multiBuildColumn.prev('.stage-column'); - $multiBuildColumn.addClass('left-margin'); - $firstChildBuildNode.addClass('left-connector'); - $previousColumn.each(function() { - $this = $(this); - if ($('.build', $this).length === 1) $this.addClass('no-margin'); - }); - } - $('.pipeline-graph').removeClass('hidden'); - } - } - - global.Pipelines = Pipelines; - -})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/pipelines.js.es6 b/app/assets/javascripts/pipelines.js.es6 new file mode 100644 index 00000000000..6bf63ee6979 --- /dev/null +++ b/app/assets/javascripts/pipelines.js.es6 @@ -0,0 +1,40 @@ +((global) => { + + class Pipelines { + constructor() { + $(document).off('click', '.toggle-pipeline-btn').on('click', '.toggle-pipeline-btn', this.toggleGraph); + this.addMarginToBuildColumns(); + } + + toggleGraph() { + const $pipelineBtn = $(this).closest('.toggle-pipeline-btn'); + const $pipelineGraph = $(this).closest('.row-content-block').next('.pipeline-graph'); + const $btnText = $(this).find('.toggle-btn-text'); + const graphCollapsed = $pipelineGraph.hasClass('graph-collapsed'); + + $($pipelineBtn).add($pipelineGraph).toggleClass('graph-collapsed'); + + + graphCollapsed ? $btnText.text('Expand') : $btnText.text('Hide') + } + + addMarginToBuildColumns() { + const $secondChildBuildNode = $('.build:nth-child(2)'); + if ($secondChildBuildNode.length) { + const $firstChildBuildNode = $secondChildBuildNode.prev('.build'); + const $multiBuildColumn = $secondChildBuildNode.closest('.stage-column'); + const $previousColumn = $multiBuildColumn.prev('.stage-column'); + $multiBuildColumn.addClass('left-margin'); + $firstChildBuildNode.addClass('left-connector'); + $previousColumn.each(function() { + $this = $(this); + if ($('.build', $this).length === 1) $this.addClass('no-margin'); + }); + } + $('.pipeline-graph').removeClass('hidden'); + } + } + + global.Pipelines = Pipelines; + +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From c180221a5b0e58c42632412d2084efc3bd4cda99 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Fri, 14 Oct 2016 19:49:36 +0200 Subject: Add docs for request profiling Closes #23239 --- CHANGELOG | 1 + doc/README.md | 1 + .../performance/img/request_profile_result.png | Bin 0 -> 9720 bytes .../performance/img/request_profiling_token.png | Bin 0 -> 30076 bytes .../monitoring/performance/request_profiling.md | 16 ++++++++++++++++ doc/development/performance.md | 3 ++- 6 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 doc/administration/monitoring/performance/img/request_profile_result.png create mode 100644 doc/administration/monitoring/performance/img/request_profiling_token.png create mode 100644 doc/administration/monitoring/performance/request_profiling.md diff --git a/CHANGELOG b/CHANGELOG index d2f1501bd2a..9def97ca342 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -115,6 +115,7 @@ v 8.13.0 (unreleased) - Fixes padding in all clipboard icons that have .btn class - Fix a typo in doc/api/labels.md - API: all unknown routing will be handled with 404 Not Found + - Add docs for request profiling - Make guests unable to view MRs on private projects v 8.12.7 diff --git a/doc/README.md b/doc/README.md index 7e3d9b00900..c30bf328003 100644 --- a/doc/README.md +++ b/doc/README.md @@ -49,6 +49,7 @@ - [Git LFS configuration](workflow/lfs/lfs_administration.md) - [Housekeeping](administration/housekeeping.md) Keep your Git repository tidy and fast. - [GitLab Performance Monitoring](administration/monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics. +- [Request Profiling](administration/monitoring/performance/request_profiling.md) Get a detailed profile on slow requests. - [Monitoring uptime](user/admin_area/monitoring/health_check.md) Check the server status using the health check endpoint. - [Debugging Tips](administration/troubleshooting/debug.md) Tips to debug problems when things go wrong - [Sidekiq Troubleshooting](administration/troubleshooting/sidekiq.md) Debug when Sidekiq appears hung and is not processing jobs. diff --git a/doc/administration/monitoring/performance/img/request_profile_result.png b/doc/administration/monitoring/performance/img/request_profile_result.png new file mode 100644 index 00000000000..73e2fdcab67 Binary files /dev/null and b/doc/administration/monitoring/performance/img/request_profile_result.png differ diff --git a/doc/administration/monitoring/performance/img/request_profiling_token.png b/doc/administration/monitoring/performance/img/request_profiling_token.png new file mode 100644 index 00000000000..04d87567816 Binary files /dev/null and b/doc/administration/monitoring/performance/img/request_profiling_token.png differ diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md new file mode 100644 index 00000000000..c358dfbead2 --- /dev/null +++ b/doc/administration/monitoring/performance/request_profiling.md @@ -0,0 +1,16 @@ +# Request Profiling + +## Procedure +1. Grab the profiling token from `Monitoring > Requests Profiles` admin page +(highlighted in a blue in the image below). +![Profile token](img/request_profiling_token.png) +1. Pass the header `X-Profile-Token: ` to the request you want to profile. You can use any of these tools + * [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) Chrome extension + * [Modify Headers](https://addons.mozilla.org/en-US/firefox/addon/modify-headers/) Firefox extension + * `curl --header 'X-Profile-Token: ' https://gitlab.example.com/group/project` +1. Once request is finished (which will take a little longer than usual), you can +view the profiling output from `Monitoring > Requests Profiles` admin page. +![Profiling output](img/request_profile_result.png) + +## Cleaning up +Profiling output will be cleared out every day via a Sidekiq worker. diff --git a/doc/development/performance.md b/doc/development/performance.md index 7ff603e2c4a..65d34829025 100644 --- a/doc/development/performance.md +++ b/doc/development/performance.md @@ -34,10 +34,11 @@ graphs/dashboards. ## Tooling -GitLab provides two built-in tools to aid the process of improving performance: +GitLab provides built-in tools to aid the process of improving performance: * [Sherlock](profiling.md#sherlock) * [GitLab Performance Monitoring](../monitoring/performance/monitoring.md) +* [Request Profiling](../administration/monitoring/performance/request_profiling.md) GitLab employees can use GitLab.com's performance monitoring systems located at , this requires you to log in using your -- cgit v1.2.1 From e88aa25f42c394785d4c176046f10c815250c8b1 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Fri, 14 Oct 2016 15:39:08 -0500 Subject: Enforce TrailingSemicolon and EmptyLineBetweenBlocks in scss-lint --- .scss-lint.yml | 4 +- CHANGELOG | 1 + app/assets/stylesheets/behaviors.scss | 1 + app/assets/stylesheets/framework/blocks.scss | 2 + app/assets/stylesheets/framework/buttons.scss | 6 +- app/assets/stylesheets/framework/callout.scss | 5 + app/assets/stylesheets/framework/common.scss | 39 +-- app/assets/stylesheets/framework/dropdowns.scss | 2 + app/assets/stylesheets/framework/files.scss | 9 + app/assets/stylesheets/framework/forms.scss | 4 +- app/assets/stylesheets/framework/gitlab-theme.scss | 2 +- app/assets/stylesheets/framework/header.scss | 1 + app/assets/stylesheets/framework/lists.scss | 1 + app/assets/stylesheets/framework/logo.scss | 7 + app/assets/stylesheets/framework/mixins.scss | 1 + app/assets/stylesheets/framework/nav.scss | 1 + app/assets/stylesheets/framework/selects.scss | 4 + app/assets/stylesheets/framework/timeline.scss | 1 + app/assets/stylesheets/framework/tw_bootstrap.scss | 10 + app/assets/stylesheets/framework/typography.scss | 1 + app/assets/stylesheets/highlight/dark.scss | 128 ++++----- app/assets/stylesheets/highlight/monokai.scss | 118 ++++----- .../stylesheets/highlight/solarized_dark.scss | 136 +++++----- .../stylesheets/highlight/solarized_light.scss | 136 +++++----- app/assets/stylesheets/highlight/white.scss | 2 +- .../stylesheets/mailers/repository_push_email.scss | 2 +- app/assets/stylesheets/notify.scss | 10 +- app/assets/stylesheets/pages/admin.scss | 12 +- app/assets/stylesheets/pages/builds.scss | 2 + app/assets/stylesheets/pages/commit.scss | 6 + app/assets/stylesheets/pages/commits.scss | 1 + app/assets/stylesheets/pages/dashboard.scss | 2 + app/assets/stylesheets/pages/diff.scss | 24 ++ app/assets/stylesheets/pages/editor.scss | 5 + app/assets/stylesheets/pages/events.scss | 8 +- app/assets/stylesheets/pages/groups.scss | 1 + app/assets/stylesheets/pages/help.scss | 8 +- app/assets/stylesheets/pages/issuable.scss | 8 +- app/assets/stylesheets/pages/issues.scss | 1 + app/assets/stylesheets/pages/labels.scss | 1 + app/assets/stylesheets/pages/lint.scss | 1 + app/assets/stylesheets/pages/login.scss | 2 +- app/assets/stylesheets/pages/merge_conflicts.scss | 2 + app/assets/stylesheets/pages/merge_requests.scss | 4 + app/assets/stylesheets/pages/milestone.scss | 1 + app/assets/stylesheets/pages/note_form.scss | 2 + app/assets/stylesheets/pages/notes.scss | 2 + app/assets/stylesheets/pages/pipelines.scss | 4 +- app/assets/stylesheets/pages/profile.scss | 1 + app/assets/stylesheets/pages/projects.scss | 18 ++ app/assets/stylesheets/pages/runners.scss | 1 + app/assets/stylesheets/pages/status.scss | 2 + app/assets/stylesheets/pages/tree.scss | 1 + app/assets/stylesheets/pages/xterm.scss | 290 ++++++++++++++++++++- 54 files changed, 746 insertions(+), 298 deletions(-) diff --git a/.scss-lint.yml b/.scss-lint.yml index 71df6be6a15..5093702519b 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -61,7 +61,7 @@ linters: # Separate rule, function, and mixin declarations with empty lines. EmptyLineBetweenBlocks: - enabled: false + enabled: true # Reports when you have an empty rule set. EmptyRule: @@ -219,7 +219,7 @@ linters: # Property values, @extend, @include, and @import directives, and variable # declarations should always end with a semicolon. TrailingSemicolon: - enabled: false + enabled: true # Reports lines containing trailing whitespace. TrailingWhitespace: diff --git a/CHANGELOG b/CHANGELOG index 3d6347c5395..194ee18b74c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ v 8.13.0 (unreleased) - Respond with 404 Not Found for non-existent tags (Linus Thiel) - Truncate long labels with ellipsis in labels page - Improve tabbing usability for sign in page (ClemMakesApps) + - Enforce TrailingSemicolon and EmptyLineBetweenBlocks in scss-lint - Adding members no longer silently fails when there is extra whitespace - Update runner version only when updating contacted_at - Add link from system note to compare with previous version diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss index 897bc49e7df..e3ca7f6373a 100644 --- a/app/assets/stylesheets/behaviors.scss +++ b/app/assets/stylesheets/behaviors.scss @@ -5,6 +5,7 @@ display: none; &.hide { display: block; } } + &.open .content { display: block; &.hide { display: none; } diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 8002e56724b..df2e2ea8d2c 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -19,6 +19,7 @@ &.diff-collapsed { padding: 5px; + .click-to-expand { cursor: pointer; } @@ -203,6 +204,7 @@ } } } + &.user-cover-block { padding: 24px 0 0; } diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index a7c8d782e9b..7c0ed72dbc5 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -25,7 +25,7 @@ &:focus { background-color: $hover-background; color: $hover-text; - border-color: $hover-border;; + border-color: $hover-border; } } @@ -240,6 +240,7 @@ width: 100%; margin: 0; margin-bottom: 15px; + &.btn { padding: 6px 0; } @@ -321,6 +322,7 @@ .btn-build { margin-left: 10px; + i { color: $gl-icon-color; } @@ -328,6 +330,7 @@ .clone-dropdown-btn a { color: $dropdown-link-color; + &:hover { text-decoration: none; } @@ -337,6 +340,7 @@ background-color: $background-color !important; border: 1px solid lightgrey; cursor: default; + &:active { -moz-box-shadow: inset 0 0 0 white; -webkit-box-shadow: inset 0 0 0 white; diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss index da7bab74a32..f3b6ad88ad6 100644 --- a/app/assets/stylesheets/framework/callout.scss +++ b/app/assets/stylesheets/framework/callout.scss @@ -13,10 +13,12 @@ color: $text-color; background: $background-color; } + .bs-callout h4 { margin-top: 0; margin-bottom: 5px; } + .bs-callout p:last-child { margin-bottom: 0; } @@ -27,16 +29,19 @@ border-color: #eed3d7; color: #b94a48; } + .bs-callout-warning { background-color: #faf8f0; border-color: #faebcc; color: #8a6d3b; } + .bs-callout-info { background-color: #f4f8fa; border-color: #bce8f1; color: #34789a; } + .bs-callout-success { background-color: #dff0d8; border-color: #5ca64d; diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 5957dce89bc..81e4e264560 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -1,31 +1,31 @@ /** COLORS **/ .cgray { color: $gl-gray; } -.clgray { color: #bbb } +.clgray { color: #bbb; } .cred { color: $gl-text-red; } .cgreen { color: $gl-text-green; } -.cdark { color: #444 } +.cdark { color: #444; } /** COMMON CLASSES **/ .prepend-top-0 { margin-top: 0; } .prepend-top-5 { margin-top: 5px; } -.prepend-top-10 { margin-top: 10px } +.prepend-top-10 { margin-top: 10px; } .prepend-top-default { margin-top: $gl-padding !important; } -.prepend-top-20 { margin-top: 20px } -.prepend-left-5 { margin-left: 5px } -.prepend-left-10 { margin-left: 10px } +.prepend-top-20 { margin-top: 20px; } +.prepend-left-5 { margin-left: 5px; } +.prepend-left-10 { margin-left: 10px; } .prepend-left-default { margin-left: $gl-padding; } -.prepend-left-20 { margin-left: 20px } -.append-right-5 { margin-right: 5px } -.append-right-10 { margin-right: 10px } +.prepend-left-20 { margin-left: 20px; } +.append-right-5 { margin-right: 5px; } +.append-right-10 { margin-right: 10px; } .append-right-default { margin-right: $gl-padding; } -.append-right-20 { margin-right: 20px } -.append-bottom-0 { margin-bottom: 0 } -.append-bottom-10 { margin-bottom: 10px } -.append-bottom-15 { margin-bottom: 15px } -.append-bottom-20 { margin-bottom: 20px } +.append-right-20 { margin-right: 20px; } +.append-bottom-0 { margin-bottom: 0; } +.append-bottom-10 { margin-bottom: 10px; } +.append-bottom-15 { margin-bottom: 15px; } +.append-bottom-20 { margin-bottom: 20px; } .append-bottom-default { margin-bottom: $gl-padding; } -.inline { display: inline-block } -.center { text-align: center } +.inline { display: inline-block; } +.center { text-align: center; } .underlined-link { text-decoration: underline; } .hint { font-style: italic; color: #999; } @@ -97,6 +97,7 @@ span.update-author { color: #999; font-weight: normal; font-style: italic; + strong { font-weight: bold; font-style: normal; @@ -128,7 +129,7 @@ p.time { // Fix issue with notes & lists creating a bunch of bottom borders. li.note { - img { max-width: 100% } + img { max-width: 100%; } .note-title { li { border-bottom: none !important; @@ -172,6 +173,7 @@ li.note { @extend .col-md-6; text-align: left; margin-top: 40px; + pre { background: white; border: none; @@ -197,6 +199,7 @@ li.note { background: #c67; color: #fff; font-weight: bold; + a { color: #fff; text-decoration: underline; @@ -227,6 +230,7 @@ li.note { &.milestone-closed { background: $gray-light; } + .progress { margin-bottom: 0; margin-top: 4px; @@ -286,6 +290,7 @@ table { .footer-links { margin-bottom: 20px; + a { margin-right: 15px; } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index baa95711329..a839371a6f2 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -12,6 +12,7 @@ .dropdown-menu, .dropdown-menu-nav { display: block; + @media (max-width: $screen-xs-max) { width: 100%; } @@ -48,6 +49,7 @@ margin-top: -6px; color: $dropdown-toggle-icon-color; font-size: 10px; + &.fa-spinner { font-size: 16px; margin-top: -8px; diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 76a3c083697..13c1bbf0359 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -57,6 +57,7 @@ margin-top: -3px; } } + .file-content { background: #fff; @@ -96,22 +97,27 @@ border: none; margin: 0; } + tr { border-bottom: 1px solid #eee; } + td { &:first-child { border-left: none; } + &:last-child { border-right: none; } } + td.blame-commit { padding: 0 10px; min-width: 400px; background: $gray-light; } + td.line-numbers { float: none; border-left: 1px solid #ddd; @@ -121,6 +127,7 @@ margin-right: 0; } } + td.lines { padding: 0; } @@ -137,8 +144,10 @@ border-left: 1px solid $border-color; margin-bottom: 0; background: white; + li { color: #888; + p { margin: 0; color: #333; diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 3d01179f074..311e3fa1a35 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -9,7 +9,7 @@ input { input[type='text'].danger { background: #f2dede!important; border-color: #d66; - text-shadow: 0 1px 1px #fff + text-shadow: 0 1px 1px #fff; } .datetime-controls { @@ -117,9 +117,11 @@ label { display: table-cell; width: 200px !important; } + .input-group-addon { background-color: #f7f8fa; } + .input-group-addon:not(:first-child):not(:last-child) { border-left: 0; border-right: 0; diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index 3673b81f183..fe834f4e2f6 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -62,7 +62,7 @@ } i { - color: $white-light + color: $white-light; } path, diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 9823abdde1f..3a4fdd0da22 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -168,6 +168,7 @@ header { a { color: $gl-text-color; + &:hover { text-decoration: underline; } diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 9114425cfdd..4b2627c1b87 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -60,6 +60,7 @@ padding-top: 1px; margin: 0; color: $gray-dark; + img { position: relative; top: 3px; diff --git a/app/assets/stylesheets/framework/logo.scss b/app/assets/stylesheets/framework/logo.scss index c214eabcad7..a90e45bb5f4 100644 --- a/app/assets/stylesheets/framework/logo.scss +++ b/app/assets/stylesheets/framework/logo.scss @@ -37,6 +37,7 @@ 0%, 10%, 100% { fill: lighten($tanuki-yellow, 25%); } + 90% { fill: $tanuki-yellow; } @@ -48,6 +49,7 @@ 10%, 80% { fill: $tanuki-orange; } + 20%, 90% { fill: lighten($tanuki-orange, 25%); } @@ -59,6 +61,7 @@ 10%, 80% { fill: $tanuki-red; } + 20%, 90% { fill: lighten($tanuki-red, 25%); } @@ -70,6 +73,7 @@ 20%, 70% { fill: $tanuki-red; } + 30%, 80% { fill: lighten($tanuki-red, 25%); } @@ -81,6 +85,7 @@ 30%, 60% { fill: $tanuki-orange; } + 40%, 70% { fill: lighten($tanuki-orange, 25%); } @@ -92,6 +97,7 @@ 30%, 60% { fill: $tanuki-red; } + 40%, 70% { fill: lighten($tanuki-red, 25%); } @@ -103,6 +109,7 @@ 40% { fill: $tanuki-yellow; } + 60% { fill: lighten($tanuki-yellow, 25%); } diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index 7fabf27a558..f84ca36d10f 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -34,6 +34,7 @@ &.active { background: $gray-light; + a { font-weight: 600; } diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index ea43f4afc37..899db045b74 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -210,6 +210,7 @@ @media (max-width: $screen-xs-max) { padding-bottom: 0; width: 100%; + .btn, form, .dropdown, .dropdown-menu-toggle, .form-control { margin: 0 0 10px; display: block; diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index bf9208f83f3..e0708c65695 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -137,6 +137,7 @@ .select2-results { max-height: 350px; + .select2-highlighted { background: $gl-primary; } @@ -212,9 +213,11 @@ .group-image { float: left; } + .group-name { font-weight: bold; } + .group-path { color: #999; } @@ -239,6 +242,7 @@ color: #aaa; font-weight: normal; } + .namespace-path { margin-left: 10px; font-weight: bolder; diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss index 0b0bd80c326..eb63a9f214b 100644 --- a/app/assets/stylesheets/framework/timeline.scss +++ b/app/assets/stylesheets/framework/timeline.scss @@ -48,6 +48,7 @@ &:before { background: none; } + .timeline-entry .timeline-entry-inner { .timeline-icon { display: none; diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss index e3154657c54..f4106641269 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap.scss @@ -48,31 +48,40 @@ .clearfix { @include clearfix(); } + .center-block { @include center-block(); } + .pull-right { float: right !important; } + .pull-left { float: left !important; } + .hide { display: none; } + .show { display: block !important; } + .invisible { visibility: hidden; } + .text-hide { @include text-hide(); } + .hidden { display: none !important; visibility: hidden !important; } + .affix { position: fixed; } @@ -146,6 +155,7 @@ padding: 6px 15px; font-size: 13px; font-weight: normal; + a { color: #777; } diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index d099a884f54..8df0067fac1 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -106,6 +106,7 @@ @extend .table-bordered; margin: 12px 0; color: #5c5d5e; + th { background: #f8fafc; } diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss index 16ffbe57a99..a3acee299e3 100644 --- a/app/assets/stylesheets/highlight/dark.scss +++ b/app/assets/stylesheets/highlight/dark.scss @@ -55,68 +55,68 @@ color: #000 !important; } - .hll { background-color: #373b41 } - .c { color: #969896 } /* Comment */ - .err { color: #c66 } /* Error */ - .k { color: #b294bb } /* Keyword */ - .l { color: #de935f } /* Literal */ - .n { color: #c5c8c6 } /* Name */ - .o { color: #8abeb7 } /* Operator */ - .p { color: #c5c8c6 } /* Punctuation */ - .cm { color: #969896 } /* Comment.Multiline */ - .cp { color: #969896 } /* Comment.Preproc */ - .c1 { color: #969896 } /* Comment.Single */ - .cs { color: #969896 } /* Comment.Special */ - .gd { color: #c66 } /* Generic.Deleted */ - .ge { font-style: italic } /* Generic.Emph */ - .gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */ - .gi { color: #b5bd68 } /* Generic.Inserted */ - .gp { color: #969896; font-weight: bold } /* Generic.Prompt */ - .gs { font-weight: bold } /* Generic.Strong */ - .gu { color: #8abeb7; font-weight: bold } /* Generic.Subheading */ - .kc { color: #b294bb } /* Keyword.Constant */ - .kd { color: #b294bb } /* Keyword.Declaration */ - .kn { color: #8abeb7 } /* Keyword.Namespace */ - .kp { color: #b294bb } /* Keyword.Pseudo */ - .kr { color: #b294bb } /* Keyword.Reserved */ - .kt { color: #f0c674 } /* Keyword.Type */ - .ld { color: #b5bd68 } /* Literal.Date */ - .m { color: #de935f } /* Literal.Number */ - .s { color: #b5bd68 } /* Literal.String */ - .na { color: #81a2be } /* Name.Attribute */ - .nb { color: #c5c8c6 } /* Name.Builtin */ - .nc { color: #f0c674 } /* Name.Class */ - .no { color: #c66 } /* Name.Constant */ - .nd { color: #8abeb7 } /* Name.Decorator */ - .ni { color: #c5c8c6 } /* Name.Entity */ - .ne { color: #c66 } /* Name.Exception */ - .nf { color: #81a2be } /* Name.Function */ - .nl { color: #c5c8c6 } /* Name.Label */ - .nn { color: #f0c674 } /* Name.Namespace */ - .nx { color: #81a2be } /* Name.Other */ - .py { color: #c5c8c6 } /* Name.Property */ - .nt { color: #8abeb7 } /* Name.Tag */ - .nv { color: #c66 } /* Name.Variable */ - .ow { color: #8abeb7 } /* Operator.Word */ - .w { color: #c5c8c6 } /* Text.Whitespace */ - .mf { color: #de935f } /* Literal.Number.Float */ - .mh { color: #de935f } /* Literal.Number.Hex */ - .mi { color: #de935f } /* Literal.Number.Integer */ - .mo { color: #de935f } /* Literal.Number.Oct */ - .sb { color: #b5bd68 } /* Literal.String.Backtick */ - .sc { color: #c5c8c6 } /* Literal.String.Char */ - .sd { color: #969896 } /* Literal.String.Doc */ - .s2 { color: #b5bd68 } /* Literal.String.Double */ - .se { color: #de935f } /* Literal.String.Escape */ - .sh { color: #b5bd68 } /* Literal.String.Heredoc */ - .si { color: #de935f } /* Literal.String.Interpol */ - .sx { color: #b5bd68 } /* Literal.String.Other */ - .sr { color: #b5bd68 } /* Literal.String.Regex */ - .s1 { color: #b5bd68 } /* Literal.String.Single */ - .ss { color: #b5bd68 } /* Literal.String.Symbol */ - .bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */ - .vc { color: #c66 } /* Name.Variable.Class */ - .vg { color: #c66 } /* Name.Variable.Global */ - .vi { color: #c66 } /* Name.Variable.Instance */ - .il { color: #de935f } /* Literal.Number.Integer.Long */ + .hll { background-color: #373b41; } + .c { color: #969896; } /* Comment */ + .err { color: #c66; } /* Error */ + .k { color: #b294bb; } /* Keyword */ + .l { color: #de935f; } /* Literal */ + .n { color: #c5c8c6; } /* Name */ + .o { color: #8abeb7; } /* Operator */ + .p { color: #c5c8c6; } /* Punctuation */ + .cm { color: #969896; } /* Comment.Multiline */ + .cp { color: #969896; } /* Comment.Preproc */ + .c1 { color: #969896; } /* Comment.Single */ + .cs { color: #969896; } /* Comment.Special */ + .gd { color: #c66; } /* Generic.Deleted */ + .ge { font-style: italic; } /* Generic.Emph */ + .gh { color: #c5c8c6; font-weight: bold; } /* Generic.Heading */ + .gi { color: #b5bd68; } /* Generic.Inserted */ + .gp { color: #969896; font-weight: bold; } /* Generic.Prompt */ + .gs { font-weight: bold; } /* Generic.Strong */ + .gu { color: #8abeb7; font-weight: bold; } /* Generic.Subheading */ + .kc { color: #b294bb; } /* Keyword.Constant */ + .kd { color: #b294bb; } /* Keyword.Declaration */ + .kn { color: #8abeb7; } /* Keyword.Namespace */ + .kp { color: #b294bb; } /* Keyword.Pseudo */ + .kr { color: #b294bb; } /* Keyword.Reserved */ + .kt { color: #f0c674; } /* Keyword.Type */ + .ld { color: #b5bd68; } /* Literal.Date */ + .m { color: #de935f; } /* Literal.Number */ + .s { color: #b5bd68; } /* Literal.String */ + .na { color: #81a2be; } /* Name.Attribute */ + .nb { color: #c5c8c6; } /* Name.Builtin */ + .nc { color: #f0c674; } /* Name.Class */ + .no { color: #c66; } /* Name.Constant */ + .nd { color: #8abeb7; } /* Name.Decorator */ + .ni { color: #c5c8c6; } /* Name.Entity */ + .ne { color: #c66; } /* Name.Exception */ + .nf { color: #81a2be; } /* Name.Function */ + .nl { color: #c5c8c6; } /* Name.Label */ + .nn { color: #f0c674; } /* Name.Namespace */ + .nx { color: #81a2be; } /* Name.Other */ + .py { color: #c5c8c6; } /* Name.Property */ + .nt { color: #8abeb7; } /* Name.Tag */ + .nv { color: #c66; } /* Name.Variable */ + .ow { color: #8abeb7; } /* Operator.Word */ + .w { color: #c5c8c6; } /* Text.Whitespace */ + .mf { color: #de935f; } /* Literal.Number.Float */ + .mh { color: #de935f; } /* Literal.Number.Hex */ + .mi { color: #de935f; } /* Literal.Number.Integer */ + .mo { color: #de935f; } /* Literal.Number.Oct */ + .sb { color: #b5bd68; } /* Literal.String.Backtick */ + .sc { color: #c5c8c6; } /* Literal.String.Char */ + .sd { color: #969896; } /* Literal.String.Doc */ + .s2 { color: #b5bd68; } /* Literal.String.Double */ + .se { color: #de935f; } /* Literal.String.Escape */ + .sh { color: #b5bd68; } /* Literal.String.Heredoc */ + .si { color: #de935f; } /* Literal.String.Interpol */ + .sx { color: #b5bd68; } /* Literal.String.Other */ + .sr { color: #b5bd68; } /* Literal.String.Regex */ + .s1 { color: #b5bd68; } /* Literal.String.Single */ + .ss { color: #b5bd68; } /* Literal.String.Symbol */ + .bp { color: #c5c8c6; } /* Name.Builtin.Pseudo */ + .vc { color: #c66; } /* Name.Variable.Class */ + .vg { color: #c66; } /* Name.Variable.Global */ + .vi { color: #c66; } /* Name.Variable.Instance */ + .il { color: #de935f; } /* Literal.Number.Integer.Long */ } diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss index 7de920e074b..e9228c94db9 100644 --- a/app/assets/stylesheets/highlight/monokai.scss +++ b/app/assets/stylesheets/highlight/monokai.scss @@ -55,65 +55,65 @@ color: #000 !important; } - .hll { background-color: #49483e } - .c { color: #75715e } /* Comment */ - .err { color: #960050; background-color: #1e0010 } /* Error */ - .k { color: #66d9ef } /* Keyword */ - .l { color: #ae81ff } /* Literal */ - .n { color: #f8f8f2 } /* Name */ - .o { color: #f92672 } /* Operator */ - .p { color: #f8f8f2 } /* Punctuation */ - .cm { color: #75715e } /* Comment.Multiline */ - .cp { color: #75715e } /* Comment.Preproc */ - .c1 { color: #75715e } /* Comment.Single */ - .cs { color: #75715e } /* Comment.Special */ - .ge { font-style: italic } /* Generic.Emph */ - .gs { font-weight: bold } /* Generic.Strong */ - .kc { color: #66d9ef } /* Keyword.Constant */ - .kd { color: #66d9ef } /* Keyword.Declaration */ - .kn { color: #f92672 } /* Keyword.Namespace */ - .kp { color: #66d9ef } /* Keyword.Pseudo */ - .kr { color: #66d9ef } /* Keyword.Reserved */ - .kt { color: #66d9ef } /* Keyword.Type */ - .ld { color: #e6db74 } /* Literal.Date */ - .m { color: #ae81ff } /* Literal.Number */ - .s { color: #e6db74 } /* Literal.String */ - .na { color: #a6e22e } /* Name.Attribute */ - .nb { color: #f8f8f2 } /* Name.Builtin */ - .nc { color: #a6e22e } /* Name.Class */ - .no { color: #66d9ef } /* Name.Constant */ - .nd { color: #a6e22e } /* Name.Decorator */ - .ni { color: #f8f8f2 } /* Name.Entity */ - .ne { color: #a6e22e } /* Name.Exception */ - .nf { color: #a6e22e } /* Name.Function */ - .nl { color: #f8f8f2 } /* Name.Label */ - .nn { color: #f8f8f2 } /* Name.Namespace */ - .nx { color: #a6e22e } /* Name.Other */ - .py { color: #f8f8f2 } /* Name.Property */ - .nt { color: #f92672 } /* Name.Tag */ - .nv { color: #f8f8f2 } /* Name.Variable */ - .ow { color: #f92672 } /* Operator.Word */ - .w { color: #f8f8f2 } /* Text.Whitespace */ - .mf { color: #ae81ff } /* Literal.Number.Float */ - .mh { color: #ae81ff } /* Literal.Number.Hex */ - .mi { color: #ae81ff } /* Literal.Number.Integer */ - .mo { color: #ae81ff } /* Literal.Number.Oct */ - .sb { color: #e6db74 } /* Literal.String.Backtick */ - .sc { color: #e6db74 } /* Literal.String.Char */ - .sd { color: #e6db74 } /* Literal.String.Doc */ - .s2 { color: #e6db74 } /* Literal.String.Double */ - .se { color: #ae81ff } /* Literal.String.Escape */ - .sh { color: #e6db74 } /* Literal.String.Heredoc */ - .si { color: #e6db74 } /* Literal.String.Interpol */ - .sx { color: #e6db74 } /* Literal.String.Other */ - .sr { color: #e6db74 } /* Literal.String.Regex */ - .s1 { color: #e6db74 } /* Literal.String.Single */ - .ss { color: #e6db74 } /* Literal.String.Symbol */ - .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ - .vc { color: #f8f8f2 } /* Name.Variable.Class */ - .vg { color: #f8f8f2 } /* Name.Variable.Global */ - .vi { color: #f8f8f2 } /* Name.Variable.Instance */ - .il { color: #ae81ff } /* Literal.Number.Integer.Long */ + .hll { background-color: #49483e; } + .c { color: #75715e; } /* Comment */ + .err { color: #960050; background-color: #1e0010; } /* Error */ + .k { color: #66d9ef; } /* Keyword */ + .l { color: #ae81ff; } /* Literal */ + .n { color: #f8f8f2; } /* Name */ + .o { color: #f92672; } /* Operator */ + .p { color: #f8f8f2; } /* Punctuation */ + .cm { color: #75715e; } /* Comment.Multiline */ + .cp { color: #75715e; } /* Comment.Preproc */ + .c1 { color: #75715e; } /* Comment.Single */ + .cs { color: #75715e; } /* Comment.Special */ + .ge { font-style: italic; } /* Generic.Emph */ + .gs { font-weight: bold; } /* Generic.Strong */ + .kc { color: #66d9ef; } /* Keyword.Constant */ + .kd { color: #66d9ef; } /* Keyword.Declaration */ + .kn { color: #f92672; } /* Keyword.Namespace */ + .kp { color: #66d9ef; } /* Keyword.Pseudo */ + .kr { color: #66d9ef; } /* Keyword.Reserved */ + .kt { color: #66d9ef; } /* Keyword.Type */ + .ld { color: #e6db74; } /* Literal.Date */ + .m { color: #ae81ff; } /* Literal.Number */ + .s { color: #e6db74; } /* Literal.String */ + .na { color: #a6e22e; } /* Name.Attribute */ + .nb { color: #f8f8f2; } /* Name.Builtin */ + .nc { color: #a6e22e; } /* Name.Class */ + .no { color: #66d9ef; } /* Name.Constant */ + .nd { color: #a6e22e; } /* Name.Decorator */ + .ni { color: #f8f8f2; } /* Name.Entity */ + .ne { color: #a6e22e; } /* Name.Exception */ + .nf { color: #a6e22e; } /* Name.Function */ + .nl { color: #f8f8f2; } /* Name.Label */ + .nn { color: #f8f8f2; } /* Name.Namespace */ + .nx { color: #a6e22e; } /* Name.Other */ + .py { color: #f8f8f2; } /* Name.Property */ + .nt { color: #f92672; } /* Name.Tag */ + .nv { color: #f8f8f2; } /* Name.Variable */ + .ow { color: #f92672; } /* Operator.Word */ + .w { color: #f8f8f2; } /* Text.Whitespace */ + .mf { color: #ae81ff; } /* Literal.Number.Float */ + .mh { color: #ae81ff; } /* Literal.Number.Hex */ + .mi { color: #ae81ff; } /* Literal.Number.Integer */ + .mo { color: #ae81ff; } /* Literal.Number.Oct */ + .sb { color: #e6db74; } /* Literal.String.Backtick */ + .sc { color: #e6db74; } /* Literal.String.Char */ + .sd { color: #e6db74; } /* Literal.String.Doc */ + .s2 { color: #e6db74; } /* Literal.String.Double */ + .se { color: #ae81ff; } /* Literal.String.Escape */ + .sh { color: #e6db74; } /* Literal.String.Heredoc */ + .si { color: #e6db74; } /* Literal.String.Interpol */ + .sx { color: #e6db74; } /* Literal.String.Other */ + .sr { color: #e6db74; } /* Literal.String.Regex */ + .s1 { color: #e6db74; } /* Literal.String.Single */ + .ss { color: #e6db74; } /* Literal.String.Symbol */ + .bp { color: #f8f8f2; } /* Name.Builtin.Pseudo */ + .vc { color: #f8f8f2; } /* Name.Variable.Class */ + .vg { color: #f8f8f2; } /* Name.Variable.Global */ + .vi { color: #f8f8f2; } /* Name.Variable.Instance */ + .il { color: #ae81ff; } /* Literal.Number.Integer.Long */ .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */ .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */ diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss index b11499c71ee..c3c7773b9e2 100644 --- a/app/assets/stylesheets/highlight/solarized_dark.scss +++ b/app/assets/stylesheets/highlight/solarized_dark.scss @@ -72,72 +72,72 @@ green #859900 operators, other keywords */ - .c { color: #586e75 } /* Comment */ - .err { color: #93a1a1 } /* Error */ - .g { color: #93a1a1 } /* Generic */ - .k { color: #859900 } /* Keyword */ - .l { color: #93a1a1 } /* Literal */ - .n { color: #93a1a1 } /* Name */ - .o { color: #859900 } /* Operator */ - .x { color: #cb4b16 } /* Other */ - .p { color: #93a1a1 } /* Punctuation */ - .cm { color: #586e75 } /* Comment.Multiline */ - .cp { color: #859900 } /* Comment.Preproc */ - .c1 { color: #586e75 } /* Comment.Single */ - .cs { color: #859900 } /* Comment.Special */ - .gd { color: #2aa198 } /* Generic.Deleted */ - .ge { color: #93a1a1; font-style: italic } /* Generic.Emph */ - .gr { color: #dc322f } /* Generic.Error */ - .gh { color: #cb4b16 } /* Generic.Heading */ - .gi { color: #859900 } /* Generic.Inserted */ - .go { color: #93a1a1 } /* Generic.Output */ - .gp { color: #93a1a1 } /* Generic.Prompt */ - .gs { color: #93a1a1; font-weight: bold } /* Generic.Strong */ - .gu { color: #cb4b16 } /* Generic.Subheading */ - .gt { color: #93a1a1 } /* Generic.Traceback */ - .kc { color: #cb4b16 } /* Keyword.Constant */ - .kd { color: #268bd2 } /* Keyword.Declaration */ - .kn { color: #859900 } /* Keyword.Namespace */ - .kp { color: #859900 } /* Keyword.Pseudo */ - .kr { color: #268bd2 } /* Keyword.Reserved */ - .kt { color: #dc322f } /* Keyword.Type */ - .ld { color: #93a1a1 } /* Literal.Date */ - .m { color: #2aa198 } /* Literal.Number */ - .s { color: #2aa198 } /* Literal.String */ - .na { color: #93a1a1 } /* Name.Attribute */ - .nb { color: #b58900 } /* Name.Builtin */ - .nc { color: #268bd2 } /* Name.Class */ - .no { color: #cb4b16 } /* Name.Constant */ - .nd { color: #268bd2 } /* Name.Decorator */ - .ni { color: #cb4b16 } /* Name.Entity */ - .ne { color: #cb4b16 } /* Name.Exception */ - .nf { color: #268bd2 } /* Name.Function */ - .nl { color: #93a1a1 } /* Name.Label */ - .nn { color: #93a1a1 } /* Name.Namespace */ - .nx { color: #93a1a1 } /* Name.Other */ - .py { color: #93a1a1 } /* Name.Property */ - .nt { color: #268bd2 } /* Name.Tag */ - .nv { color: #268bd2 } /* Name.Variable */ - .ow { color: #859900 } /* Operator.Word */ - .w { color: #93a1a1 } /* Text.Whitespace */ - .mf { color: #2aa198 } /* Literal.Number.Float */ - .mh { color: #2aa198 } /* Literal.Number.Hex */ - .mi { color: #2aa198 } /* Literal.Number.Integer */ - .mo { color: #2aa198 } /* Literal.Number.Oct */ - .sb { color: #586e75 } /* Literal.String.Backtick */ - .sc { color: #2aa198 } /* Literal.String.Char */ - .sd { color: #93a1a1 } /* Literal.String.Doc */ - .s2 { color: #2aa198 } /* Literal.String.Double */ - .se { color: #cb4b16 } /* Literal.String.Escape */ - .sh { color: #93a1a1 } /* Literal.String.Heredoc */ - .si { color: #2aa198 } /* Literal.String.Interpol */ - .sx { color: #2aa198 } /* Literal.String.Other */ - .sr { color: #dc322f } /* Literal.String.Regex */ - .s1 { color: #2aa198 } /* Literal.String.Single */ - .ss { color: #2aa198 } /* Literal.String.Symbol */ - .bp { color: #268bd2 } /* Name.Builtin.Pseudo */ - .vc { color: #268bd2 } /* Name.Variable.Class */ - .vg { color: #268bd2 } /* Name.Variable.Global */ - .vi { color: #268bd2 } /* Name.Variable.Instance */ - .il { color: #2aa198 } /* Literal.Number.Integer.Long */ + .c { color: #586e75; } /* Comment */ + .err { color: #93a1a1; } /* Error */ + .g { color: #93a1a1; } /* Generic */ + .k { color: #859900; } /* Keyword */ + .l { color: #93a1a1; } /* Literal */ + .n { color: #93a1a1; } /* Name */ + .o { color: #859900; } /* Operator */ + .x { color: #cb4b16; } /* Other */ + .p { color: #93a1a1; } /* Punctuation */ + .cm { color: #586e75; } /* Comment.Multiline */ + .cp { color: #859900; } /* Comment.Preproc */ + .c1 { color: #586e75; } /* Comment.Single */ + .cs { color: #859900; } /* Comment.Special */ + .gd { color: #2aa198; } /* Generic.Deleted */ + .ge { color: #93a1a1; font-style: italic; } /* Generic.Emph */ + .gr { color: #dc322f; } /* Generic.Error */ + .gh { color: #cb4b16; } /* Generic.Heading */ + .gi { color: #859900; } /* Generic.Inserted */ + .go { color: #93a1a1; } /* Generic.Output */ + .gp { color: #93a1a1; } /* Generic.Prompt */ + .gs { color: #93a1a1; font-weight: bold; } /* Generic.Strong */ + .gu { color: #cb4b16; } /* Generic.Subheading */ + .gt { color: #93a1a1; } /* Generic.Traceback */ + .kc { color: #cb4b16; } /* Keyword.Constant */ + .kd { color: #268bd2; } /* Keyword.Declaration */ + .kn { color: #859900; } /* Keyword.Namespace */ + .kp { color: #859900; } /* Keyword.Pseudo */ + .kr { color: #268bd2; } /* Keyword.Reserved */ + .kt { color: #dc322f; } /* Keyword.Type */ + .ld { color: #93a1a1; } /* Literal.Date */ + .m { color: #2aa198; } /* Literal.Number */ + .s { color: #2aa198; } /* Literal.String */ + .na { color: #93a1a1; } /* Name.Attribute */ + .nb { color: #b58900; } /* Name.Builtin */ + .nc { color: #268bd2; } /* Name.Class */ + .no { color: #cb4b16; } /* Name.Constant */ + .nd { color: #268bd2; } /* Name.Decorator */ + .ni { color: #cb4b16; } /* Name.Entity */ + .ne { color: #cb4b16; } /* Name.Exception */ + .nf { color: #268bd2; } /* Name.Function */ + .nl { color: #93a1a1; } /* Name.Label */ + .nn { color: #93a1a1; } /* Name.Namespace */ + .nx { color: #93a1a1; } /* Name.Other */ + .py { color: #93a1a1; } /* Name.Property */ + .nt { color: #268bd2; } /* Name.Tag */ + .nv { color: #268bd2; } /* Name.Variable */ + .ow { color: #859900; } /* Operator.Word */ + .w { color: #93a1a1; } /* Text.Whitespace */ + .mf { color: #2aa198; } /* Literal.Number.Float */ + .mh { color: #2aa198; } /* Literal.Number.Hex */ + .mi { color: #2aa198; } /* Literal.Number.Integer */ + .mo { color: #2aa198; } /* Literal.Number.Oct */ + .sb { color: #586e75; } /* Literal.String.Backtick */ + .sc { color: #2aa198; } /* Literal.String.Char */ + .sd { color: #93a1a1; } /* Literal.String.Doc */ + .s2 { color: #2aa198; } /* Literal.String.Double */ + .se { color: #cb4b16; } /* Literal.String.Escape */ + .sh { color: #93a1a1; } /* Literal.String.Heredoc */ + .si { color: #2aa198; } /* Literal.String.Interpol */ + .sx { color: #2aa198; } /* Literal.String.Other */ + .sr { color: #dc322f; } /* Literal.String.Regex */ + .s1 { color: #2aa198; } /* Literal.String.Single */ + .ss { color: #2aa198; } /* Literal.String.Symbol */ + .bp { color: #268bd2; } /* Name.Builtin.Pseudo */ + .vc { color: #268bd2; } /* Name.Variable.Class */ + .vg { color: #268bd2; } /* Name.Variable.Global */ + .vi { color: #268bd2; } /* Name.Variable.Instance */ + .il { color: #2aa198; } /* Literal.Number.Integer.Long */ } diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss index 657bb5e3cd9..5956a28cafe 100644 --- a/app/assets/stylesheets/highlight/solarized_light.scss +++ b/app/assets/stylesheets/highlight/solarized_light.scss @@ -78,72 +78,72 @@ green #859900 operators, other keywords */ - .c { color: #93a1a1 } /* Comment */ - .err { color: #586e75 } /* Error */ - .g { color: #586e75 } /* Generic */ - .k { color: #859900 } /* Keyword */ - .l { color: #586e75 } /* Literal */ - .n { color: #586e75 } /* Name */ - .o { color: #859900 } /* Operator */ - .x { color: #cb4b16 } /* Other */ - .p { color: #586e75 } /* Punctuation */ - .cm { color: #93a1a1 } /* Comment.Multiline */ - .cp { color: #859900 } /* Comment.Preproc */ - .c1 { color: #93a1a1 } /* Comment.Single */ - .cs { color: #859900 } /* Comment.Special */ - .gd { color: #2aa198 } /* Generic.Deleted */ - .ge { color: #586e75; font-style: italic } /* Generic.Emph */ - .gr { color: #dc322f } /* Generic.Error */ - .gh { color: #cb4b16 } /* Generic.Heading */ - .gi { color: #859900 } /* Generic.Inserted */ - .go { color: #586e75 } /* Generic.Output */ - .gp { color: #586e75 } /* Generic.Prompt */ - .gs { color: #586e75; font-weight: bold } /* Generic.Strong */ - .gu { color: #cb4b16 } /* Generic.Subheading */ - .gt { color: #586e75 } /* Generic.Traceback */ - .kc { color: #cb4b16 } /* Keyword.Constant */ - .kd { color: #268bd2 } /* Keyword.Declaration */ - .kn { color: #859900 } /* Keyword.Namespace */ - .kp { color: #859900 } /* Keyword.Pseudo */ - .kr { color: #268bd2 } /* Keyword.Reserved */ - .kt { color: #dc322f } /* Keyword.Type */ - .ld { color: #586e75 } /* Literal.Date */ - .m { color: #2aa198 } /* Literal.Number */ - .s { color: #2aa198 } /* Literal.String */ - .na { color: #586e75 } /* Name.Attribute */ - .nb { color: #b58900 } /* Name.Builtin */ - .nc { color: #268bd2 } /* Name.Class */ - .no { color: #cb4b16 } /* Name.Constant */ - .nd { color: #268bd2 } /* Name.Decorator */ - .ni { color: #cb4b16 } /* Name.Entity */ - .ne { color: #cb4b16 } /* Name.Exception */ - .nf { color: #268bd2 } /* Name.Function */ - .nl { color: #586e75 } /* Name.Label */ - .nn { color: #586e75 } /* Name.Namespace */ - .nx { color: #586e75 } /* Name.Other */ - .py { color: #586e75 } /* Name.Property */ - .nt { color: #268bd2 } /* Name.Tag */ - .nv { color: #268bd2 } /* Name.Variable */ - .ow { color: #859900 } /* Operator.Word */ - .w { color: #586e75 } /* Text.Whitespace */ - .mf { color: #2aa198 } /* Literal.Number.Float */ - .mh { color: #2aa198 } /* Literal.Number.Hex */ - .mi { color: #2aa198 } /* Literal.Number.Integer */ - .mo { color: #2aa198 } /* Literal.Number.Oct */ - .sb { color: #93a1a1 } /* Literal.String.Backtick */ - .sc { color: #2aa198 } /* Literal.String.Char */ - .sd { color: #586e75 } /* Literal.String.Doc */ - .s2 { color: #2aa198 } /* Literal.String.Double */ - .se { color: #cb4b16 } /* Literal.String.Escape */ - .sh { color: #586e75 } /* Literal.String.Heredoc */ - .si { color: #2aa198 } /* Literal.String.Interpol */ - .sx { color: #2aa198 } /* Literal.String.Other */ - .sr { color: #dc322f } /* Literal.String.Regex */ - .s1 { color: #2aa198 } /* Literal.String.Single */ - .ss { color: #2aa198 } /* Literal.String.Symbol */ - .bp { color: #268bd2 } /* Name.Builtin.Pseudo */ - .vc { color: #268bd2 } /* Name.Variable.Class */ - .vg { color: #268bd2 } /* Name.Variable.Global */ - .vi { color: #268bd2 } /* Name.Variable.Instance */ - .il { color: #2aa198 } /* Literal.Number.Integer.Long */ + .c { color: #93a1a1; } /* Comment */ + .err { color: #586e75; } /* Error */ + .g { color: #586e75; } /* Generic */ + .k { color: #859900; } /* Keyword */ + .l { color: #586e75; } /* Literal */ + .n { color: #586e75; } /* Name */ + .o { color: #859900; } /* Operator */ + .x { color: #cb4b16; } /* Other */ + .p { color: #586e75; } /* Punctuation */ + .cm { color: #93a1a1; } /* Comment.Multiline */ + .cp { color: #859900; } /* Comment.Preproc */ + .c1 { color: #93a1a1; } /* Comment.Single */ + .cs { color: #859900; } /* Comment.Special */ + .gd { color: #2aa198; } /* Generic.Deleted */ + .ge { color: #586e75; font-style: italic; } /* Generic.Emph */ + .gr { color: #dc322f; } /* Generic.Error */ + .gh { color: #cb4b16; } /* Generic.Heading */ + .gi { color: #859900; } /* Generic.Inserted */ + .go { color: #586e75; } /* Generic.Output */ + .gp { color: #586e75; } /* Generic.Prompt */ + .gs { color: #586e75; font-weight: bold; } /* Generic.Strong */ + .gu { color: #cb4b16; } /* Generic.Subheading */ + .gt { color: #586e75; } /* Generic.Traceback */ + .kc { color: #cb4b16; } /* Keyword.Constant */ + .kd { color: #268bd2; } /* Keyword.Declaration */ + .kn { color: #859900; } /* Keyword.Namespace */ + .kp { color: #859900; } /* Keyword.Pseudo */ + .kr { color: #268bd2; } /* Keyword.Reserved */ + .kt { color: #dc322f; } /* Keyword.Type */ + .ld { color: #586e75; } /* Literal.Date */ + .m { color: #2aa198; } /* Literal.Number */ + .s { color: #2aa198; } /* Literal.String */ + .na { color: #586e75; } /* Name.Attribute */ + .nb { color: #b58900; } /* Name.Builtin */ + .nc { color: #268bd2; } /* Name.Class */ + .no { color: #cb4b16; } /* Name.Constant */ + .nd { color: #268bd2; } /* Name.Decorator */ + .ni { color: #cb4b16; } /* Name.Entity */ + .ne { color: #cb4b16; } /* Name.Exception */ + .nf { color: #268bd2; } /* Name.Function */ + .nl { color: #586e75; } /* Name.Label */ + .nn { color: #586e75; } /* Name.Namespace */ + .nx { color: #586e75; } /* Name.Other */ + .py { color: #586e75; } /* Name.Property */ + .nt { color: #268bd2; } /* Name.Tag */ + .nv { color: #268bd2; } /* Name.Variable */ + .ow { color: #859900; } /* Operator.Word */ + .w { color: #586e75; } /* Text.Whitespace */ + .mf { color: #2aa198; } /* Literal.Number.Float */ + .mh { color: #2aa198; } /* Literal.Number.Hex */ + .mi { color: #2aa198; } /* Literal.Number.Integer */ + .mo { color: #2aa198; } /* Literal.Number.Oct */ + .sb { color: #93a1a1; } /* Literal.String.Backtick */ + .sc { color: #2aa198; } /* Literal.String.Char */ + .sd { color: #586e75; } /* Literal.String.Doc */ + .s2 { color: #2aa198; } /* Literal.String.Double */ + .se { color: #cb4b16; } /* Literal.String.Escape */ + .sh { color: #586e75; } /* Literal.String.Heredoc */ + .si { color: #2aa198; } /* Literal.String.Interpol */ + .sx { color: #2aa198; } /* Literal.String.Other */ + .sr { color: #dc322f; } /* Literal.String.Regex */ + .s1 { color: #2aa198; } /* Literal.String.Single */ + .ss { color: #2aa198; } /* Literal.String.Symbol */ + .bp { color: #268bd2; } /* Name.Builtin.Pseudo */ + .vc { color: #268bd2; } /* Name.Variable.Class */ + .vg { color: #268bd2; } /* Name.Variable.Global */ + .vi { color: #268bd2; } /* Name.Variable.Instance */ + .il { color: #2aa198; } /* Literal.Number.Integer.Long */ } diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss index 36a80a916b2..6f31a5235c0 100644 --- a/app/assets/stylesheets/highlight/white.scss +++ b/app/assets/stylesheets/highlight/white.scss @@ -86,7 +86,7 @@ background-color: #fafe3d !important; } - .hll { background-color: #f8f8f8 } + .hll { background-color: #f8f8f8; } .c { color: #998; font-style: italic; } .err { color: #a61717; background-color: #e3d2d2; } .k { font-weight: bold; } diff --git a/app/assets/stylesheets/mailers/repository_push_email.scss b/app/assets/stylesheets/mailers/repository_push_email.scss index 5bfe9bcb443..8d1a6020ca4 100644 --- a/app/assets/stylesheets/mailers/repository_push_email.scss +++ b/app/assets/stylesheets/mailers/repository_push_email.scss @@ -78,7 +78,7 @@ span.highlight_word { background-color: #fafe3d !important; } -.hll { background-color: #f8f8f8 } +.hll { background-color: #f8f8f8; } .c { color: #998; font-style: italic; } .err { color: #a61717; background-color: #e3d2d2; } .k { font-weight: bold; } diff --git a/app/assets/stylesheets/notify.scss b/app/assets/stylesheets/notify.scss index fc12964872d..ced8c4a9907 100644 --- a/app/assets/stylesheets/notify.scss +++ b/app/assets/stylesheets/notify.scss @@ -2,22 +2,28 @@ img { max-width: 100%; height: auto; } + p.details { font-style: italic; - color: #777 + color: #777; } + .footer > p { font-size: small; - color: #777 + color: #777; } + pre.commit-message { white-space: pre-wrap; } + .file-stats > a { text-decoration: none; + > .new-file { color: #090; } + > .deleted-file { color: #b00; } diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss index 8f71381f5c4..140d589024b 100644 --- a/app/assets/stylesheets/pages/admin.scss +++ b/app/assets/stylesheets/pages/admin.scss @@ -22,7 +22,7 @@ .admin-filter form { .select2-container { - width: 100% + width: 100%; } .controls { @@ -31,7 +31,7 @@ .form-actions { padding-left: 130px; - background: #fff + background: #fff; } .visibility-levels { @@ -106,26 +106,33 @@ .table { table-layout: fixed; } + .subheading { padding-bottom: $gl-padding; } + .message { word-wrap: break-word; } + .btn { white-space: normal; padding: $gl-btn-padding; } + th { width: 15%; + &.wide { width: 55%; } } + @media (max-width: $screen-sm-max) { th { width: 100%; } + td { width: 100%; float: left; @@ -137,6 +144,7 @@ margin-left: $btn-side-margin; margin-top: 3px; } + span { font-size: 19px; } diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index fcaba954615..2fbf0cf34bf 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -137,6 +137,7 @@ .retry-link { color: $gl-link-color; + &:hover { text-decoration: underline; } @@ -218,6 +219,7 @@ .build-detail-row { margin-bottom: 5px; + &:last-of-type { margin-bottom: 0; } diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss index 53ec0002afe..264e7e01a34 100644 --- a/app/assets/stylesheets/pages/commit.scss +++ b/app/assets/stylesheets/pages/commit.scss @@ -51,6 +51,7 @@ margin-left: 4px; } } + .commit-committer-link, .commit-author-link { color: $gl-gray; @@ -108,21 +109,25 @@ line-height: 20px; } } + .new-file { a { color: $gl-text-green; } } + .renamed-file { a { color: $gl-text-orange; } } + .deleted-file { a { color: $gl-text-red; } } + .edit-file { a { color: $gl-text-color; @@ -158,6 +163,7 @@ position: absolute; z-index: 1; } + > textarea { background-color: rgba(0, 0, 0, 0.0); font-family: inherit; diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index dc57a837155..2b5621e20d6 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -161,6 +161,7 @@ .branch-commit { color: $gl-gray; + .commit-id, .commit-row-message { color: $gl-gray; } diff --git a/app/assets/stylesheets/pages/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss index 42928ee279c..76225ed8d06 100644 --- a/app/assets/stylesheets/pages/dashboard.scss +++ b/app/assets/stylesheets/pages/dashboard.scss @@ -5,6 +5,7 @@ background: $background-color; border-top-left-radius: 0; } + border-top-left-radius: 0; } } @@ -17,6 +18,7 @@ float: left; @extend .col-md-2; } + .btn { margin-left: 5px; float: left; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 84094b0cb1b..bdc82a8f0f5 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -136,15 +136,18 @@ max-width: 50px; width: 35px; @include user-select(none); + a { float: left; width: 35px; font-weight: normal; + &:hover { text-decoration: underline; } } } + .line_content { display: block; margin: 0; @@ -164,10 +167,12 @@ white-space: pre-wrap; } } + .image { background: #ddd; text-align: center; padding: 30px; + .wrap { display: inline-block; } @@ -176,6 +181,7 @@ display: inline-block; background-color: #fff; line-height: 0; + img { border: 1px solid #fff; background-image: linear-gradient(45deg, #e5e5e5 25%, transparent 25%, transparent 75%, #e5e5e5 75%, #e5e5e5 100%), @@ -184,6 +190,7 @@ background-position: 0 0, 5px 5px; max-width: 100%; } + &.deleted { border: 1px solid $deleted; } @@ -192,6 +199,7 @@ border: 1px solid $added; } } + .image-info { font-size: 12px; margin: 5px 0 0; @@ -206,6 +214,7 @@ margin: auto; position: relative; } + .swipe-wrap { overflow: hidden; border-left: 1px solid #999; @@ -214,10 +223,12 @@ top: 13px; right: 7px; } + .frame { top: 0; right: 0; position: absolute; + &.deleted { margin: 0; display: block; @@ -225,6 +236,7 @@ right: 7px; } } + .swipe-bar { display: block; height: 100%; @@ -232,14 +244,17 @@ z-index: 100; position: absolute; cursor: pointer; + &:hover { .top-handle { background-position: -15px 3px; } + .bottom-handle { background-position: -15px -11px; } } + .top-handle { display: block; height: 14px; @@ -248,6 +263,7 @@ top: 0; background: image-url('swipemode_sprites.gif') 0 3px no-repeat; } + .bottom-handle { display: block; height: 14px; @@ -265,12 +281,14 @@ margin: auto; position: relative; } + .frame.added, .frame.deleted { position: absolute; display: block; top: 0; left: 0; } + .controls { display: block; height: 14px; @@ -324,6 +342,7 @@ } //.view.onion-skin } + .view-modes { padding: 10px; text-align: center; @@ -341,19 +360,24 @@ border-left: 1px solid #c1c1c1; padding: 0 12px 0 16px; cursor: pointer; + &:first-child { border-left: none; } + &:hover { text-decoration: underline; } + &.active { &:hover { text-decoration: none; } + cursor: default; color: #333; } + &.disabled { display: none; } diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index fcc5f32c738..029dabd2138 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -15,6 +15,7 @@ .cancel-btn { color: #b94a48; + &:hover { color: #b94a48; } @@ -70,16 +71,20 @@ .soft-wrap-toggle { margin: 0 $btn-side-margin; + .soft-wrap { display: block; } + .no-wrap { display: none; } + &.soft-wrap-active { .soft-wrap { display: none; } + .no-wrap { display: block; } diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index 789d6237df8..5d9a76dac05 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -78,6 +78,7 @@ margin-bottom: 0; } } + .event-note-icon { color: #777; float: left; @@ -86,6 +87,7 @@ margin-right: 5px; } } + .event_icon { position: relative; float: right; @@ -95,12 +97,13 @@ background: $gray-light; margin-left: 10px; top: -6px; + img { width: 20px; } } - &:last-child { border: none } + &:last-child { border: none; } .event_commits { li { @@ -109,6 +112,7 @@ padding: 3px; padding-left: 0; border: none; + .commit-row-title { font-size: $gl-font-size; } @@ -117,6 +121,7 @@ &.commits-stat { display: block; padding: 0 3px 0 0; + &:hover { background: none; } @@ -158,6 +163,7 @@ overflow: visible; max-width: 100%; } + .avatar { display: none; } diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index edc9592f564..ee2a398f031 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -34,6 +34,7 @@ .group-right-buttons { position: absolute; right: 16px; + .btn { @include btn-gray; padding: 3px 10px; diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss index 00ab42bec5c..a48b4c65db8 100644 --- a/app/assets/stylesheets/pages/help.scss +++ b/app/assets/stylesheets/pages/help.scss @@ -23,28 +23,28 @@ color: #555; tbody:first-child tr:first-child { - padding-top: 0 + padding-top: 0; } th { padding-top: 15px; line-height: 1.5; color: #333; - text-align: left + text-align: left; } td { padding-top: 3px; padding-bottom: 3px; vertical-align: top; - line-height: 20px + line-height: 20px; } .shortcut { padding-right: 10px; color: #999; text-align: right; - white-space: nowrap + white-space: nowrap; } .key { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 41079b6eeb5..230b927a17d 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -27,6 +27,7 @@ margin-right: 5px; margin-bottom: 5px; display: inline-block; + .color-label { padding: 6px 10px; } @@ -128,7 +129,7 @@ } .selectbox { - display: none + display: none; } .btn-clipboard { @@ -199,7 +200,7 @@ display: none; /* Small devices (tablets, 768px and up) */ @media (min-width: $screen-sm-min) { - display: block + display: block; } width: $sidebar_collapsed_width; @@ -276,7 +277,7 @@ } &.btn-primary { - @extend .btn-primary + @extend .btn-primary; } } @@ -400,6 +401,7 @@ .js-issuable-selector { width: 100%; } + @media (max-width: $screen-sm-max) { margin-bottom: $gl-padding; } diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index 3ac34cbc829..623da67a239 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -37,6 +37,7 @@ ul.related-merge-requests > li { display: -ms-flexbox; display: -webkit-flex; display: flex; + .merge-request-id { flex-shrink: 0; } diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index 701c29a3986..9bac6d46355 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -1,5 +1,6 @@ .suggest-colors { margin-top: 5px; + a { border-radius: 4px; width: 30px; diff --git a/app/assets/stylesheets/pages/lint.scss b/app/assets/stylesheets/pages/lint.scss index 6926448519e..8290519dc25 100644 --- a/app/assets/stylesheets/pages/lint.scss +++ b/app/assets/stylesheets/pages/lint.scss @@ -3,6 +3,7 @@ font-size: 19px; color: red; } + .correct-syntax { font-size: 19px; color: #47a447; diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index a08b033dff9..47d112dbbe3 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -68,7 +68,7 @@ a.forgot { float: right; - padding-top: 6px + padding-top: 6px; } .nav .active a { diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss index 5ec660799e3..49013d7cac9 100644 --- a/app/assets/stylesheets/pages/merge_conflicts.scss +++ b/app/assets/stylesheets/pages/merge_conflicts.scss @@ -131,6 +131,7 @@ $colors: ( } } } + &.head { background-color: map-get($colors, #{$color}_header_head_neutral); border-color: map-get($colors, #{$color}_header_head_neutral); @@ -174,6 +175,7 @@ $colors: ( background-color: map-get($colors, #{$color}_line_not_chosen); } } + &.head { background-color: map-get($colors, #{$color}_line_head_neutral); diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 0ccb0ccfd14..afc4e517fde 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -10,6 +10,7 @@ form { margin-bottom: 0; + .clearfix { margin-bottom: 0; } @@ -46,6 +47,7 @@ &.right { float: right; + a { color: $gl-gray; } @@ -192,6 +194,7 @@ padding-top: 2px; padding-bottom: 2px; list-style: none; + &:hover { background: none; } @@ -215,6 +218,7 @@ padding-top: 20px; padding-bottom: 10px; } + svg { width: 230px; } diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss index 8c2ba3ed58c..dd6d1783667 100644 --- a/app/assets/stylesheets/pages/milestone.scss +++ b/app/assets/stylesheets/pages/milestone.scss @@ -59,6 +59,7 @@ color: $gl-placeholder-color; margin-right: 5px; } + .avatar { float: none; } diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index bd875b9823f..17f28959414 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -11,6 +11,7 @@ filter: alpha(opacity=100); } } + .diff-file, .discussion { .new-note { @@ -194,6 +195,7 @@ min-height: 140px; max-height: 500px; } + .note-form-actions { background: transparent; } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index efeea96373f..fffcdc812a7 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -158,6 +158,7 @@ ul.notes { .diff-header > span { margin-right: 10px; } + .line_content { white-space: pre-wrap; } @@ -353,6 +354,7 @@ ul.notes { width: 32px; // "hide" it by default display: none; + &:hover { background: $gl-info; color: #fff; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 29dd03bfd60..7b71876b822 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -183,7 +183,7 @@ &::after { content: ''; width: 8px; - position: absolute;; + position: absolute; right: -7px; bottom: 8px; border-bottom: 2px solid $border-color; @@ -360,6 +360,7 @@ &:hover { background-color: $gray-lighter; + .dropdown-menu-toggle { background-color: transparent; } @@ -543,6 +544,7 @@ height: 29px; top: -9px; } + .curve { display: block; } diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index c7eac5cf4b9..ed80d2beec2 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -243,6 +243,7 @@ .btn { -webkit-flex-grow: 1; flex-grow: 1; + &:first-child { margin-left: 0; } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 530fb0c0d05..d30f02340b9 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -17,34 +17,43 @@ &.features .control-label { font-weight: normal; } + .form-group { margin-bottom: 5px; } + &> .form-group { padding-left: 0; } } + .help-block { margin-bottom: 10px; } + .project-path { padding-right: 0; + .form-control { border-radius: $border-radius-base; } } + .input-group > div { &:last-child { padding-right: 0; } } + @media (max-width: $screen-xs-max) { .input-group > div { margin-bottom: 14px; + &:last-child { margin-bottom: 0; } } + fieldset > .form-group:first-child { padding-right: 0; } @@ -56,6 +65,7 @@ border-radius: 3px; border: 1px solid #e5e5e5; } + &+ .select2 a { border-top-left-radius: 0; border-bottom-left-radius: 0; @@ -201,6 +211,7 @@ pointer-events: none; } } + .count { @include btn-gray; display: inline-block; @@ -361,10 +372,12 @@ a.deploy-project-label { margin: $gl-padding; text-align: center; width: 169px; + &:hover, &.forked { background-color: $row-hover; border-color: $row-hover-border; } + .no-avatar { width: 100px; height: 100px; @@ -372,17 +385,20 @@ a.deploy-project-label { border: 1px solid $gray-dark; margin: 0 auto; border-radius: 50%; + i { font-size: 100px; color: $gray-dark; } } + a { display: block; width: 100%; height: 100%; padding-top: $gl-padding; color: $gl-gray; + .caption { min-height: 30px; padding: $gl-padding 0; @@ -644,6 +660,7 @@ pre.light-well { .clone-options { display: table-cell; + a.btn { width: 100%; } @@ -832,6 +849,7 @@ pre.light-well { .form-control { min-width: 100px; } + .select2-choice { border-top-right-radius: 0; border-bottom-right-radius: 0; diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss index eec22c5dc96..7b3878c91df 100644 --- a/app/assets/stylesheets/pages/runners.scss +++ b/app/assets/stylesheets/pages/runners.scss @@ -6,6 +6,7 @@ &.runner-state-shared { background: #32b186; } + &.runner-state-specific { background: #3498db; } diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index c05f3d5ff32..f1d53c7b8bc 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -65,6 +65,7 @@ .ci-status-icon-success { color: $gl-success; } + .ci-status-icon-failed { color: $gl-danger; } @@ -77,6 +78,7 @@ .ci-status-icon-running { color: $blue-normal; } + .ci-status-icon-canceled, .ci-status-icon-disabled, .ci-status-icon-not-found, diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 41ad10f07bd..99c0f6362d0 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -5,6 +5,7 @@ .file-finder { width: 50%; + .file-finder-input { width: 95%; display: inline-block; diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss index c9846103762..3fa7fa3d7e3 100644 --- a/app/assets/stylesheets/pages/xterm.scss +++ b/app/assets/stylesheets/pages/xterm.scss @@ -23,15 +23,19 @@ .term-bold { font-weight: bold; } + .term-italic { font-style: italic; } + .term-conceal { visibility: hidden; } + .term-underline { text-decoration: underline; } + .term-cross { text-decoration: line-through; } @@ -39,48 +43,63 @@ .term-fg-black { color: $black; } + .term-fg-red { color: $red; } + .term-fg-green { color: $green; } + .term-fg-yellow { color: $yellow; } + .term-fg-blue { color: $blue; } + .term-fg-magenta { color: $magenta; } + .term-fg-cyan { color: $cyan; } + .term-fg-white { color: $white; } + .term-fg-l-black { color: $l-black; } + .term-fg-l-red { color: $l-red; } + .term-fg-l-green { color: $l-green; } + .term-fg-l-yellow { color: $l-yellow; } + .term-fg-l-blue { color: $l-blue; } + .term-fg-l-magenta { color: $l-magenta; } + .term-fg-l-cyan { color: $l-cyan; } + .term-fg-l-white { color: $l-white; } @@ -88,818 +107,1087 @@ .term-bg-black { background-color: $black; } + .term-bg-red { background-color: $red; } + .term-bg-green { background-color: $green; } + .term-bg-yellow { background-color: $yellow; } + .term-bg-blue { background-color: $blue; } + .term-bg-magenta { background-color: $magenta; } + .term-bg-cyan { background-color: $cyan; } + .term-bg-white { background-color: $white; } + .term-bg-l-black { background-color: $l-black; } + .term-bg-l-red { background-color: $l-red; } + .term-bg-l-green { background-color: $l-green; } + .term-bg-l-yellow { background-color: $l-yellow; } + .term-bg-l-blue { background-color: $l-blue; } + .term-bg-l-magenta { background-color: $l-magenta; } + .term-bg-l-cyan { background-color: $l-cyan; } + .term-bg-l-white { background-color: $l-white; } - .xterm-fg-0 { color: #000; } + .xterm-fg-1 { color: #800000; } + .xterm-fg-2 { color: #008000; } + .xterm-fg-3 { color: #808000; } + .xterm-fg-4 { color: #000080; } + .xterm-fg-5 { color: #800080; } + .xterm-fg-6 { color: #008080; } + .xterm-fg-7 { color: #c0c0c0; } + .xterm-fg-8 { color: #808080; } + .xterm-fg-9 { color: #f00; } + .xterm-fg-10 { color: #0f0; } + .xterm-fg-11 { color: #ff0; } + .xterm-fg-12 { color: #00f; } + .xterm-fg-13 { color: #f0f; } + .xterm-fg-14 { color: #0ff; } + .xterm-fg-15 { color: #fff; } + .xterm-fg-16 { color: #000; } + .xterm-fg-17 { color: #00005f; } + .xterm-fg-18 { color: #000087; } + .xterm-fg-19 { color: #0000af; } + .xterm-fg-20 { color: #0000d7; } + .xterm-fg-21 { color: #00f; } + .xterm-fg-22 { color: #005f00; } + .xterm-fg-23 { color: #005f5f; } + .xterm-fg-24 { color: #005f87; } + .xterm-fg-25 { color: #005faf; } + .xterm-fg-26 { color: #005fd7; } + .xterm-fg-27 { color: #005fff; } + .xterm-fg-28 { color: #008700; } + .xterm-fg-29 { color: #00875f; } + .xterm-fg-30 { color: #008787; } + .xterm-fg-31 { color: #0087af; } + .xterm-fg-32 { color: #0087d7; } + .xterm-fg-33 { color: #0087ff; } + .xterm-fg-34 { color: #00af00; } + .xterm-fg-35 { color: #00af5f; } + .xterm-fg-36 { color: #00af87; } + .xterm-fg-37 { color: #00afaf; } + .xterm-fg-38 { color: #00afd7; } + .xterm-fg-39 { color: #00afff; } + .xterm-fg-40 { color: #00d700; } + .xterm-fg-41 { color: #00d75f; } + .xterm-fg-42 { color: #00d787; } + .xterm-fg-43 { color: #00d7af; } + .xterm-fg-44 { color: #00d7d7; } + .xterm-fg-45 { color: #00d7ff; } + .xterm-fg-46 { color: #0f0; } + .xterm-fg-47 { color: #00ff5f; } + .xterm-fg-48 { color: #00ff87; } + .xterm-fg-49 { color: #00ffaf; } + .xterm-fg-50 { color: #00ffd7; } + .xterm-fg-51 { color: #0ff; } + .xterm-fg-52 { color: #5f0000; } + .xterm-fg-53 { color: #5f005f; } + .xterm-fg-54 { color: #5f0087; } + .xterm-fg-55 { color: #5f00af; } + .xterm-fg-56 { color: #5f00d7; } + .xterm-fg-57 { color: #5f00ff; } + .xterm-fg-58 { color: #5f5f00; } + .xterm-fg-59 { color: #5f5f5f; } + .xterm-fg-60 { color: #5f5f87; } + .xterm-fg-61 { color: #5f5faf; } + .xterm-fg-62 { color: #5f5fd7; } + .xterm-fg-63 { color: #5f5fff; } + .xterm-fg-64 { color: #5f8700; } + .xterm-fg-65 { color: #5f875f; } + .xterm-fg-66 { color: #5f8787; } + .xterm-fg-67 { color: #5f87af; } + .xterm-fg-68 { color: #5f87d7; } + .xterm-fg-69 { color: #5f87ff; } + .xterm-fg-70 { color: #5faf00; } + .xterm-fg-71 { color: #5faf5f; } + .xterm-fg-72 { color: #5faf87; } + .xterm-fg-73 { color: #5fafaf; } + .xterm-fg-74 { color: #5fafd7; } + .xterm-fg-75 { color: #5fafff; } + .xterm-fg-76 { color: #5fd700; } + .xterm-fg-77 { color: #5fd75f; } + .xterm-fg-78 { color: #5fd787; } + .xterm-fg-79 { color: #5fd7af; } + .xterm-fg-80 { color: #5fd7d7; } + .xterm-fg-81 { color: #5fd7ff; } + .xterm-fg-82 { color: #5fff00; } + .xterm-fg-83 { color: #5fff5f; } + .xterm-fg-84 { color: #5fff87; } + .xterm-fg-85 { color: #5fffaf; } + .xterm-fg-86 { color: #5fffd7; } + .xterm-fg-87 { color: #5fffff; } + .xterm-fg-88 { color: #870000; } + .xterm-fg-89 { color: #87005f; } + .xterm-fg-90 { color: #870087; } + .xterm-fg-91 { color: #8700af; } + .xterm-fg-92 { color: #8700d7; } + .xterm-fg-93 { color: #8700ff; } + .xterm-fg-94 { color: #875f00; } + .xterm-fg-95 { color: #875f5f; } + .xterm-fg-96 { color: #875f87; } + .xterm-fg-97 { color: #875faf; } + .xterm-fg-98 { color: #875fd7; } + .xterm-fg-99 { color: #875fff; } + .xterm-fg-100 { color: #878700; } + .xterm-fg-101 { color: #87875f; } + .xterm-fg-102 { color: #878787; } + .xterm-fg-103 { color: #8787af; } + .xterm-fg-104 { color: #8787d7; } + .xterm-fg-105 { color: #8787ff; } + .xterm-fg-106 { color: #87af00; } + .xterm-fg-107 { color: #87af5f; } + .xterm-fg-108 { color: #87af87; } + .xterm-fg-109 { color: #87afaf; } + .xterm-fg-110 { color: #87afd7; } + .xterm-fg-111 { color: #87afff; } + .xterm-fg-112 { color: #87d700; } + .xterm-fg-113 { color: #87d75f; } + .xterm-fg-114 { color: #87d787; } + .xterm-fg-115 { color: #87d7af; } + .xterm-fg-116 { color: #87d7d7; } + .xterm-fg-117 { color: #87d7ff; } + .xterm-fg-118 { color: #87ff00; } + .xterm-fg-119 { color: #87ff5f; } + .xterm-fg-120 { color: #87ff87; } + .xterm-fg-121 { color: #87ffaf; } + .xterm-fg-122 { color: #87ffd7; } + .xterm-fg-123 { color: #87ffff; } + .xterm-fg-124 { color: #af0000; } + .xterm-fg-125 { color: #af005f; } + .xterm-fg-126 { color: #af0087; } + .xterm-fg-127 { color: #af00af; } + .xterm-fg-128 { color: #af00d7; } + .xterm-fg-129 { color: #af00ff; } + .xterm-fg-130 { color: #af5f00; } + .xterm-fg-131 { color: #af5f5f; } + .xterm-fg-132 { color: #af5f87; } + .xterm-fg-133 { color: #af5faf; } + .xterm-fg-134 { color: #af5fd7; } + .xterm-fg-135 { color: #af5fff; } + .xterm-fg-136 { color: #af8700; } + .xterm-fg-137 { color: #af875f; } + .xterm-fg-138 { color: #af8787; } + .xterm-fg-139 { color: #af87af; } + .xterm-fg-140 { color: #af87d7; } + .xterm-fg-141 { color: #af87ff; } + .xterm-fg-142 { color: #afaf00; } + .xterm-fg-143 { color: #afaf5f; } + .xterm-fg-144 { color: #afaf87; } + .xterm-fg-145 { color: #afafaf; } + .xterm-fg-146 { color: #afafd7; } + .xterm-fg-147 { color: #afafff; } + .xterm-fg-148 { color: #afd700; } + .xterm-fg-149 { color: #afd75f; } + .xterm-fg-150 { color: #afd787; } + .xterm-fg-151 { color: #afd7af; } + .xterm-fg-152 { color: #afd7d7; } + .xterm-fg-153 { color: #afd7ff; } + .xterm-fg-154 { color: #afff00; } + .xterm-fg-155 { color: #afff5f; } + .xterm-fg-156 { color: #afff87; } + .xterm-fg-157 { color: #afffaf; } + .xterm-fg-158 { color: #afffd7; } + .xterm-fg-159 { color: #afffff; } + .xterm-fg-160 { color: #d70000; } + .xterm-fg-161 { color: #d7005f; } + .xterm-fg-162 { color: #d70087; } + .xterm-fg-163 { color: #d700af; } + .xterm-fg-164 { color: #d700d7; } + .xterm-fg-165 { color: #d700ff; } + .xterm-fg-166 { color: #d75f00; } + .xterm-fg-167 { color: #d75f5f; } + .xterm-fg-168 { color: #d75f87; } + .xterm-fg-169 { color: #d75faf; } + .xterm-fg-170 { color: #d75fd7; } + .xterm-fg-171 { color: #d75fff; } + .xterm-fg-172 { color: #d78700; } + .xterm-fg-173 { color: #d7875f; } + .xterm-fg-174 { color: #d78787; } + .xterm-fg-175 { color: #d787af; } + .xterm-fg-176 { color: #d787d7; } + .xterm-fg-177 { color: #d787ff; } + .xterm-fg-178 { color: #d7af00; } + .xterm-fg-179 { color: #d7af5f; } + .xterm-fg-180 { color: #d7af87; } + .xterm-fg-181 { color: #d7afaf; } + .xterm-fg-182 { color: #d7afd7; } + .xterm-fg-183 { color: #d7afff; } + .xterm-fg-184 { color: #d7d700; } + .xterm-fg-185 { color: #d7d75f; } + .xterm-fg-186 { color: #d7d787; } + .xterm-fg-187 { color: #d7d7af; } + .xterm-fg-188 { color: #d7d7d7; } + .xterm-fg-189 { color: #d7d7ff; } + .xterm-fg-190 { color: #d7ff00; } + .xterm-fg-191 { color: #d7ff5f; } + .xterm-fg-192 { color: #d7ff87; } + .xterm-fg-193 { color: #d7ffaf; } + .xterm-fg-194 { color: #d7ffd7; } + .xterm-fg-195 { color: #d7ffff; } + .xterm-fg-196 { color: #f00; } + .xterm-fg-197 { color: #ff005f; } + .xterm-fg-198 { color: #ff0087; } + .xterm-fg-199 { color: #ff00af; } + .xterm-fg-200 { color: #ff00d7; } + .xterm-fg-201 { color: #f0f; } + .xterm-fg-202 { color: #ff5f00; } + .xterm-fg-203 { color: #ff5f5f; } + .xterm-fg-204 { color: #ff5f87; } + .xterm-fg-205 { color: #ff5faf; } + .xterm-fg-206 { color: #ff5fd7; } + .xterm-fg-207 { color: #ff5fff; } + .xterm-fg-208 { color: #ff8700; } + .xterm-fg-209 { color: #ff875f; } + .xterm-fg-210 { color: #ff8787; } + .xterm-fg-211 { color: #ff87af; } + .xterm-fg-212 { color: #ff87d7; } + .xterm-fg-213 { color: #ff87ff; } + .xterm-fg-214 { color: #ffaf00; } + .xterm-fg-215 { color: #ffaf5f; } + .xterm-fg-216 { color: #ffaf87; } + .xterm-fg-217 { color: #ffafaf; } + .xterm-fg-218 { color: #ffafd7; } + .xterm-fg-219 { color: #ffafff; } + .xterm-fg-220 { color: #ffd700; } + .xterm-fg-221 { color: #ffd75f; } + .xterm-fg-222 { color: #ffd787; } + .xterm-fg-223 { color: #ffd7af; } + .xterm-fg-224 { color: #ffd7d7; } + .xterm-fg-225 { color: #ffd7ff; } + .xterm-fg-226 { color: #ff0; } + .xterm-fg-227 { color: #ffff5f; } + .xterm-fg-228 { color: #ffff87; } + .xterm-fg-229 { color: #ffffaf; } + .xterm-fg-230 { color: #ffffd7; } + .xterm-fg-231 { color: #fff; } + .xterm-fg-232 { color: #080808; } + .xterm-fg-233 { color: #121212; } + .xterm-fg-234 { color: #1c1c1c; } + .xterm-fg-235 { color: #262626; } + .xterm-fg-236 { color: #303030; } + .xterm-fg-237 { color: #3a3a3a; } + .xterm-fg-238 { color: #444; } + .xterm-fg-239 { color: #4e4e4e; } + .xterm-fg-240 { color: #585858; } + .xterm-fg-241 { color: #626262; } + .xterm-fg-242 { color: #6c6c6c; } + .xterm-fg-243 { color: #767676; } + .xterm-fg-244 { color: #808080; } + .xterm-fg-245 { color: #8a8a8a; } + .xterm-fg-246 { color: #949494; } + .xterm-fg-247 { color: #9e9e9e; } + .xterm-fg-248 { color: #a8a8a8; } + .xterm-fg-249 { color: #b2b2b2; } + .xterm-fg-250 { color: #bcbcbc; } + .xterm-fg-251 { color: #c6c6c6; } + .xterm-fg-252 { color: #d0d0d0; } + .xterm-fg-253 { color: #dadada; } + .xterm-fg-254 { color: #e4e4e4; } + .xterm-fg-255 { color: #eee; } -- cgit v1.2.1 From 2b9a25bd5a69c3c6a5bb24bb67838a4d354204e1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 15 Oct 2016 00:11:19 +0300 Subject: Handle unmatched routing with not_found method We need this to prevent routing error when user access URL like /123 when there is no resource located under such name Signed-off-by: Dmitriy Zaporozhets --- app/controllers/application_controller.rb | 4 ++++ config/routes.rb | 2 ++ 2 files changed, 6 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b3455e04c29..705824502eb 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -45,6 +45,10 @@ class ApplicationController < ActionController::Base redirect_to request.referer.present? ? :back : default, options end + def not_found + render_404 + end + protected # This filter handles both private tokens and personal access tokens diff --git a/config/routes.rb b/config/routes.rb index 83c3a42c19f..659ea51bc75 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -88,4 +88,6 @@ Rails.application.routes.draw do get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ } root to: "root#index" + + get '*unmatched_route', to: 'application#not_found' end -- cgit v1.2.1 From d60d5fe4e422ecd83437653bc5764c6269162125 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 15 Oct 2016 01:36:05 +0300 Subject: Improve ExtractsPath logic related to atom format * Don't set request format to atom if '.atom' suffix was not provided * Don't try '.atom' detection logic on request that uses extended_sha1 Signed-off-by: Dmitriy Zaporozhets --- lib/extracts_path.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index e4d996a3fb6..9b74364849e 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -113,17 +113,18 @@ module ExtractsPath @id = get_id @ref, @path = extract_ref(@id) @repo = @project.repository - if @options[:extended_sha1].blank? - @commit = @repo.commit(@ref) - else - @commit = @repo.commit(@options[:extended_sha1]) - end - if @path.empty? && !@commit - @id = @ref = extract_ref_without_atom(@id) + if @options[:extended_sha1].present? + @commit = @repo.commit(@options[:extended_sha1]) + else @commit = @repo.commit(@ref) - request.format = :atom if @commit + if @path.empty? && !@commit && @id.ends_with?('.atom') + @id = @ref = extract_ref_without_atom(@id) + @commit = @repo.commit(@ref) + + request.format = :atom if @commit + end end raise InvalidPathError unless @commit -- cgit v1.2.1 From b0622d657893b156ac0c265f397efeb28d5b0b4c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 15 Oct 2016 01:48:14 +0300 Subject: Revert "Update git over http test to match new routing" This reverts commit 68ab7047dae98172a0bd8b92956f2ee51b9167a0. --- spec/requests/git_http_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 5a1ed7d4a25..27f0fd22ae6 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -412,9 +412,10 @@ describe 'Git HTTP requests', lib: true do context "when the params are anything else" do let(:params) { { service: 'git-implode-pack' } } + before { get path, params } - it "fails to find a route" do - expect { get(path, params) }.to raise_error(ActionController::RoutingError) + it "redirects to the sign-in page" do + expect(response).to redirect_to(new_user_session_path) end end end -- cgit v1.2.1 From 762b63e56965223bd217224a407f15ec6b1b1d3d Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 14 Oct 2016 17:07:38 -0700 Subject: Fix Spinach failure due overprecise percentage matching The percentages in the language match changed by a tenth of a percentage point for Ruby and JavaScript, which led to this failure. Partial fix to #23378 --- features/steps/project/graph.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/steps/project/graph.rb b/features/steps/project/graph.rb index b09ec86e5df..7490d2bc6e7 100644 --- a/features/steps/project/graph.rb +++ b/features/steps/project/graph.rb @@ -19,8 +19,8 @@ class Spinach::Features::ProjectGraph < Spinach::FeatureSteps end step 'page should have languages graphs' do - expect(page).to have_content "Ruby 66.63 %" - expect(page).to have_content "JavaScript 22.96 %" + expect(page).to have_content /Ruby 66.* %/ + expect(page).to have_content /JavaScript 22.* %/ end step 'page should have commits graphs' do -- cgit v1.2.1 From 1dd826d4aad2ce6c195bad24b458b1967b74db1d Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 9 Sep 2016 14:21:00 +0200 Subject: Make UX upgrades to SignIn/Register views. - Tab between register and sign in forms - Add individual input validation error messages - Validate username - Update many styles for all login-box forms --- CHANGELOG | 1 + app/assets/javascripts/dispatcher.js | 11 + app/assets/javascripts/gl_field_errors.js.es6 | 100 +++ app/assets/javascripts/username_validator.js.es6 | 131 ++++ app/assets/stylesheets/framework/buttons.scss | 3 +- app/assets/stylesheets/framework/forms.scss | 13 +- app/assets/stylesheets/pages/login.scss | 138 +++- app/controllers/users_controller.rb | 6 +- app/views/admin/appearances/preview.html.haml | 17 +- app/views/devise/confirmations/new.html.haml | 12 +- app/views/devise/passwords/edit.html.haml | 20 +- app/views/devise/passwords/new.html.haml | 10 +- app/views/devise/sessions/_new_base.html.haml | 10 +- app/views/devise/sessions/_new_crowd.html.haml | 10 +- app/views/devise/sessions/_new_ldap.html.haml | 10 +- app/views/devise/sessions/new.html.haml | 32 +- app/views/devise/sessions/two_factor.html.haml | 17 +- app/views/devise/shared/_omniauth_box.html.haml | 15 +- app/views/devise/shared/_sign_in_link.html.haml | 1 - app/views/devise/shared/_signin_box.html.haml | 37 +- app/views/devise/shared/_signup_box.html.haml | 36 +- app/views/devise/shared/_tab_single.html.haml | 4 + app/views/devise/shared/_tabs_ldap.html.haml | 10 + app/views/devise/shared/_tabs_normal.html.haml | 5 + app/views/devise/unlocks/new.html.haml | 10 +- app/views/layouts/devise.html.haml | 59 +- app/views/u2f/_authenticate.html.haml | 2 +- config/routes.rb | 792 +++++++++++++++++++++++ spec/features/signup_spec.rb | 8 +- spec/features/u2f_spec.rb | 14 +- spec/features/users_spec.rb | 32 +- spec/javascripts/u2f/authenticate_spec.js | 2 +- 32 files changed, 1391 insertions(+), 177 deletions(-) create mode 100644 app/assets/javascripts/gl_field_errors.js.es6 create mode 100644 app/assets/javascripts/username_validator.js.es6 create mode 100644 app/views/devise/shared/_tab_single.html.haml create mode 100644 app/views/devise/shared/_tabs_ldap.html.haml create mode 100644 app/views/devise/shared/_tabs_normal.html.haml diff --git a/CHANGELOG b/CHANGELOG index 194ee18b74c..e3201cd2250 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -377,6 +377,7 @@ v 8.11.7 - Avoid conflict with admin labels when importing GitHub labels. !6158 - Restores `fieldName` to allow only string values in `gl_dropdown.js`. !6234 - Allow the Rails cookie to be used for API authentication. + - Login/Register UX upgrade !6328 v 8.11.6 - Fix unnecessary horizontal scroll area in pipeline visualizations. !6005 diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 858621218f8..fb6e82cd37c 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -8,6 +8,7 @@ Dispatcher = (function() { function Dispatcher() { this.initSearch(); + this.initFieldErrors(); this.initPageScripts(); } @@ -20,6 +21,10 @@ path = page.split(':'); shortcut_handler = null; switch (page) { + case 'sessions:new': + case 'sessions:create': + new UsernameValidator(); + break; case 'projects:boards:show': case 'projects:boards:index': shortcut_handler = new ShortcutsNavigation(); @@ -291,6 +296,12 @@ } }; + Dispatcher.prototype.initFieldErrors = function() { + $('form.show-gl-field-errors').each(function(i, form) { + new gl.GlFieldErrors(form); + }); + }; + return Dispatcher; })(); diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 new file mode 100644 index 00000000000..42a2ddeeafe --- /dev/null +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -0,0 +1,100 @@ +((global) => { + /* + * This class overrides the browser's validation error bubbles, displaying custom + * error messages for invalid fields instead. To begin validating any form, add the + * class `show-gl-field-errors` to the form element, and ensure error messages are + * declared in each inputs' title attribute. + * + * Example: + * + *
    + * + *
    + * + * */ + + const fieldErrorClass = 'gl-field-error'; + const fieldErrorSelector = `.${fieldErrorClass}`; + const inputErrorClass = 'gl-field-error-outline'; + + class GlFieldErrors { + constructor(form) { + this.form = $(form); + this.initValidators(); + } + + initValidators () { + this.inputs = this.form.find(':input:not([type=hidden])').toArray(); + this.inputs.forEach((input) => { + $(input).off('invalid').on('invalid', this.handleInvalidInput.bind(this)); + }); + this.form.on('submit', this.catchInvalidFormSubmit); + } + + /* Neccessary because Safari & iOS quietly allow form submission when form is invalid */ + catchInvalidFormSubmit (event) { + if (!event.currentTarget.checkValidity()) { + event.preventDefault(); + // Prevents disabling of invalid submit button by application.js + event.stopPropagation(); + } + } + + handleInvalidInput (event) { + event.preventDefault(); + this.updateFieldValidityState(event); + + const $input = $(event.currentTarget); + + // For UX, wait til after first invalid submission to check each keyup + $input.off('keyup.field_validator') + .on('keyup.field_validator', this.updateFieldValidityState.bind(this)); + + } + + displayFieldValidity (target, isValid) { + const $input = $(target).removeClass(inputErrorClass); + const $existingError = $input.siblings(fieldErrorSelector); + const alreadyInvalid = !!$existingError.length; + const implicitErrorMessage = $input.attr('title'); + const $errorToDisplay = alreadyInvalid ? $existingError.detach() : $(`

    ${implicitErrorMessage}

    `); + + if (!isValid) { + $input.after($errorToDisplay); + $input.addClass(inputErrorClass); + } + + this.updateFieldSiblings($errorToDisplay, isValid); + } + + updateFieldSiblings($target, isValid) { + const siblings = $target.siblings(`p${fieldErrorSelector}`); + return isValid ? siblings.show() : siblings.hide(); + } + + checkFieldValidity(target) { + return target.validity.valid; + } + + updateFieldValidityState(event) { + const target = event.currentTarget; + const isKeyup = event.type === 'keyup'; + const isValid = this.checkFieldValidity(target); + + this.displayFieldValidity(target, isValid); + + // prevent changing focus while user is typing. + if (!isKeyup) { + this.focusOnFirstInvalid.apply(this); + } + } + + focusOnFirstInvalid () { + const firstInvalid = this.inputs.find((input) => !input.validity.valid); + $(firstInvalid).focus(); + } + } + + global.GlFieldErrors = GlFieldErrors; + +})(window.gl || (window.gl = {})); diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6 new file mode 100644 index 00000000000..f8be356af04 --- /dev/null +++ b/app/assets/javascripts/username_validator.js.es6 @@ -0,0 +1,131 @@ +((global) => { + const debounceTimeoutDuration = 1000; + const inputErrorClass = 'gl-field-error-outline'; + const inputSuccessClass = 'gl-field-success-outline'; + const messageErrorSelector = '.username .validation-error'; + const messageSuccessSelector = '.username .validation-success'; + const messagePendingSelector = '.username .validation-pending'; + + class UsernameValidator { + constructor() { + this.inputElement = $('#new_user_username'); + this.inputDomElement = this.inputElement.get(0); + + this.available = false; + this.valid = false; + this.pending = false; + this.fresh = true; + this.empty = true; + + const debounceTimeout = _.debounce((username) => { + this.validateUsername(username); + }, debounceTimeoutDuration); + + this.inputElement.on('keyup.username_check', () => { + const username = this.inputElement.val(); + + this.valid = this.inputDomElement.validity.valid; + this.fresh = false; + this.empty = !username.length; + + if (this.valid) { + return debounceTimeout(username); + } + + this.renderState(); + }); + + // Override generic field validation + this.inputElement.on('invalid', this.handleInvalidInput.bind(this)); + } + + renderState() { + // Clear all state + this.clearFieldValidationState(); + + if (this.valid && this.available) { + return this.setSuccessState(); + } + + if (this.empty) { + return this.clearFieldValidationState(); + } + + if (this.pending) { + return this.setPendingState(); + } + + if (!this.available) { + return this.setUnavailableState(); + } + + if (!this.valid) { + return this.setInvalidState(); + } + } + + handleInvalidInput(event) { + event.preventDefault(); + event.stopPropagation(); + } + + validateUsername(username) { + if (this.valid) { + this.pending = true; + this.available = false; + this.renderState(); + return $.ajax({ + type: 'GET', + url: `/u/${username}/exists`, + dataType: 'json', + success: (res) => this.updateValidationState(res.exists) + }); + } + } + + updateValidationState(usernameTaken) { + if (usernameTaken) { + this.valid = false; + this.available = false; + } else { + this.available = true; + } + this.pending = false; + this.renderState(); + } + + clearFieldValidationState() { + this.inputElement.siblings('p').hide(); + this.inputElement.removeClass(inputErrorClass); + this.inputElement.removeClass(inputSuccessClass); + } + + setUnavailableState() { + const $usernameErrorMessage = this.inputElement.siblings(messageErrorSelector); + this.inputElement.addClass(inputErrorClass).removeClass(inputSuccessClass); + $usernameErrorMessage.show(); + } + + setSuccessState() { + const $usernameSuccessMessage = this.inputElement.siblings(messageSuccessSelector); + this.inputElement.addClass(inputSuccessClass).removeClass(inputErrorClass); + $usernameSuccessMessage.show(); + } + + setPendingState(show) { + const $usernamePendingMessage = $(messagePendingSelector); + if (this.pending) { + $usernamePendingMessage.show(); + } else { + $usernamePendingMessage.hide(); + } + } + + setInvalidState() { + this.inputElement.addClass(inputErrorClass).removeClass(inputSuccessClass); + $(`.gl-field-error`).show(); + } + } + + global.UsernameValidator = UsernameValidator; +})(window); diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 7c0ed72dbc5..e6656c2d69a 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -152,7 +152,8 @@ @include btn-blue-medium; } - &.btn-info { + &.btn-info, + &.btn-register { @include btn-blue; } diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 311e3fa1a35..761c07384f4 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -73,8 +73,8 @@ label { } .form-control { - box-shadow: none; - border-radius: 3px; + @include box-shadow(none); + border-radius: 2px; padding: $gl-vert-padding $gl-input-padding; } @@ -127,3 +127,12 @@ label { border-right: 0; } } + +.help-block { + margin-bottom: 0; +} + +.gl-field-error { + color: $red-normal; +} + diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 47d112dbbe3..06b90fbefab 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -17,6 +17,7 @@ line-height: 1.5; p { + font-size: 18px; color: #888; } @@ -36,10 +37,13 @@ } } + p { + font-size: 13px; + } .login-box { - background: #fafafa; - border-radius: 10px; - box-shadow: 0 0 2px #ccc; + box-shadow: 0 0 0 1px $border-color; + border-bottom-right-radius: 2px; + border-bottom-left-radius: 2px; padding: 15px; .login-heading h3 { @@ -74,7 +78,6 @@ .nav .active a { background: transparent; } - } .form-control { font-size: 14px; @@ -92,18 +95,109 @@ border-top: 0; margin-bottom: 20px; } + } + + // Styles the glowing border of focused input for username async validation + .login-body { + font-size: 13px; + + + input + p { + margin-top: 5px; + } + + .gl-field-success-outline { + border: 1px solid $green-normal; + + &:focus { + box-shadow: 0 0 0 1px $green-normal inset, 0 0 4px 0 $green-normal; + border: 0 none; + } + } + + .gl-field-error-outline { + border: 1px solid $red-normal; + + &:focus { + opacity: .6; + box-shadow: 0 0 0 1px $red-normal inset, 0 0 4px 0 $red-normal; + border: 0 none; + } + } + + .username .validation-success, + .gl-field-success-message { + color: $green-normal; + } + + .username .validation-error, + .gl-field-error-message { + color: $red-normal; + } + + .gl-field-hint { + color: $gl-text-color; + } + + } + + .new-session-tabs { // Are these being applied to other login-related screens? They need to be. + display: flex; + box-shadow: 0 0 0 1px $border-color; + border-top-right-radius: 2px; + border-top-left-radius: 2px; + + li { + flex: 1; + text-align: center; &.middle { border-top: 0; margin-bottom: 0; border-radius: 0; + &:last-of-type { + border-left: 1px solid $border-color; + } + + &:not(.active) { + background-color: $gray-light; + } + + a { + width: 100%; + font-size: 18px; + &:hover { + border: 1px solid transparent; + } + } + + &.active { + border-bottom: 1px solid $border-color; + + a { + border: none; + border-bottom: 2px solid $link-underline-blue; + color: $black; + + &:hover { + border-bottom: 2px solid $link-underline-blue; + } + } + } } + } + + .form-control { &:active, &:focus { background-color: #fff; } } + label { + font-weight: normal; + } + .devise-errors { h2 { margin-top: 0; @@ -111,14 +205,6 @@ color: #a00; } } - - .remember-me { - margin-top: -10px; - - label { - font-weight: normal; - } - } } @media (max-width: $screen-xs-max) { @@ -137,3 +223,31 @@ height: 32px; } } + +.devise-layout-html { + margin: 0; + padding: 0; + height: 100%; +} + +// Fixes footer container to bottom of viewport +.devise-layout-html body { + // offset height of fixed header + 1 to avoid scroll + height: calc(100% - 51px); + margin: 0; + padding: 0; + + .page-wrap { + min-height: 100%; + position: relative; + } + + .footer-container, hr.footer-fixed { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 40px; + background: $white-light; + } +} diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 838ecc837e4..30f0118254a 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,6 +1,6 @@ class UsersController < ApplicationController skip_before_action :authenticate_user! - before_action :user + before_action :user, except: [:exists] before_action :authorize_read_user!, only: [:show] def show @@ -85,6 +85,10 @@ class UsersController < ApplicationController render 'calendar_activities', layout: false end + def exists + render json: { exists: !User.find_by_username(params[:username]).nil? } + end + private def authorize_read_user! diff --git a/app/views/admin/appearances/preview.html.haml b/app/views/admin/appearances/preview.html.haml index 6c51639b840..0d35702c634 100644 --- a/app/views/admin/appearances/preview.html.haml +++ b/app/views/admin/appearances/preview.html.haml @@ -1,9 +1,12 @@ -- page_title "Preview | Appearance" += render 'devise/shared/tab_single', { :tab_title => 'Sign in preview' } .login-box - .login-heading - %h3 Existing user? Sign in - %form - = text_field_tag :login, nil, class: "form-control top", placeholder: "Username or Email" - = password_field_tag :password, nil, class: "form-control bottom", placeholder: "Password" - = button_tag "Sign in", class: "btn-create btn" + %form.show-gl-field-errors + .form-group + = label_tag :login + = text_field_tag :login, nil, class: "form-control top", title: 'Please provide your username or email address.' + .form-group + = label_tag :password + = password_field_tag :password, nil, class: "form-control bottom", title: 'This field is required.' + .form-group + = button_tag "Sign in", class: "btn-create btn" diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml index 970ba147111..443a316c6e2 100644 --- a/app/views/devise/confirmations/new.html.haml +++ b/app/views/devise/confirmations/new.html.haml @@ -1,14 +1,14 @@ += render 'devise/shared/tab_single', { :tab_title => 'Resend confirmation instructions' } .login-box - .login-heading - %h3 Resend confirmation instructions .login-body - = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| + = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f| .devise-errors = devise_error_messages! - .clearfix.append-bottom-20 - = f.email_field :email, placeholder: 'Email', class: "form-control", required: true + .form-group + = f.label :email + = f.email_field :email, class: "form-control", required: true, title: 'Please provide a valid email address.' .clearfix - = f.submit "Resend confirmation instructions", class: 'btn btn-success' + = f.submit "Resend", class: 'btn btn-success' .clearfix.prepend-top-20 = render 'devise/shared/sign_in_link' diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml index 56048e99c17..9c533ef9916 100644 --- a/app/views/devise/passwords/edit.html.haml +++ b/app/views/devise/passwords/edit.html.haml @@ -1,19 +1,21 @@ += render 'devise/shared/tab_single', { :tab_title => 'Change your password' } .login-box - .login-heading - %h3 Change your password .login-body - = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| + = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: 'show-gl-field-errors' }) do |f| .devise-errors = devise_error_messages! = f.hidden_field :reset_password_token - %div - = f.password_field :password, class: "form-control top", placeholder: "New password", required: true - %div - = f.password_field :password_confirmation, class: "form-control bottom", placeholder: "Confirm new password", required: true + .form-group + = f.label 'New password', for: :password + = f.password_field :password, class: "form-control top", required: true, title: 'This field is required' + .form-group + = f.label 'Confirm new password', for: :password_confirmation + = f.password_field :password_confirmation, class: "form-control bottom", title: 'This field is required', required: true .clearfix = f.submit "Change your password", class: "btn btn-primary" .clearfix.prepend-top-20 %p - = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) - = render 'devise/shared/sign_in_link' + %span.light Didn't receive a confirmation email? + = link_to "Request a new one", new_confirmation_path(resource_name) += render 'devise/shared/sign_in_link' diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml index 535e85869e5..91b46a12ac0 100644 --- a/app/views/devise/passwords/new.html.haml +++ b/app/views/devise/passwords/new.html.haml @@ -1,12 +1,12 @@ += render 'devise/shared/tab_single', { :tab_title => 'Reset Password' } .login-box - .login-heading - %h3 Reset password .login-body - = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| + = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f| .devise-errors = devise_error_messages! - .clearfix.append-bottom-20 - = f.email_field :email, placeholder: "Email", class: "form-control", required: true, value: params[:user_email], autofocus: true + .form-group + = f.label :email + = f.email_field :email, class: "form-control", required: true, value: params[:user_email], autofocus: true, title: 'Please provide a valid email address.' .clearfix = f.submit "Reset password", class: "btn-primary btn" diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml index 781fd1b32a6..cfb1b964d76 100644 --- a/app/views/devise/sessions/_new_base.html.haml +++ b/app/views/devise/sessions/_new_base.html.haml @@ -1,6 +1,10 @@ -= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| - = f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off" - = f.password_field :password, class: "form-control bottom", placeholder: "Password" += form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: 'new_user show-gl-field-errors', 'aria-live' => 'assertive'}) do |f| + %div.form-group + = f.label "Username or email", for: :login + = f.text_field :login, class: "form-control top", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required." + %div.form-group + = f.label :password + = f.password_field :password, class: "form-control bottom", required: true, title: "This field is required." .sign-in = f.submit "Sign in", class: "btn btn-save" - if devise_mapping.rememberable? diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml index b7d3acac2b1..5a192c63c7c 100644 --- a/app/views/devise/sessions/_new_crowd.html.haml +++ b/app/views/devise/sessions/_new_crowd.html.haml @@ -1,6 +1,10 @@ -= form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user' ) do - = text_field_tag :username, nil, {class: "form-control top", placeholder: "Username", autofocus: "autofocus"} - = password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"} += form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user' class: 'show-gl-field-errors') do + .form-group + = label_tag 'Username or email', for: :username + = text_field_tag :username, nil, {class: "form-control top", title: "This field is required", autofocus: "autofocus", required: true } + .form-group + = label_tag :password + = password_field_tag :password, nil, { class: "form-control bottom", title: "This field is required.", required: true } - if devise_mapping.rememberable? .remember-me.checkbox %label{for: "remember_me"} diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml index 2ef383960f4..b26efbb4535 100644 --- a/app/views/devise/sessions/_new_ldap.html.haml +++ b/app/views/devise/sessions/_new_ldap.html.haml @@ -1,6 +1,10 @@ -= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user') do - = text_field_tag :username, nil, {class: "form-control top", placeholder: "#{server['label']} Login", autofocus: "autofocus"} - = password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"} += form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "show-gl-field-errors") do + .form-group + = label_tag "#{server['label']} Login", for: :username + = text_field_tag :username, nil, {class: "form-control top", title: "This field is required.", autofocus: "autofocus", required: true } + .form-group + = label_tag :password + = password_field_tag :password, nil, { class: "form-control bottom", title: "This field is required.", required: true } - if devise_mapping.rememberable? .remember-me.checkbox %label{for: "remember_me"} diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 28194506acc..2fb05b9456b 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,19 +1,23 @@ - page_title "Sign in" %div - - if signin_enabled? || ldap_enabled? || crowd_enabled? - = render 'devise/shared/signin_box' + - if form_based_providers.any? + = render 'devise/shared/tabs_ldap' + - else + = render 'devise/shared/tabs_normal' + .tab-content + - if signin_enabled? || ldap_enabled? || crowd_enabled? + = render 'devise/shared/signin_box' - -# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box - - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? - .clearfix.prepend-top-20 - = render 'devise/shared/omniauth_box' - - -# Signup only makes sense if you can also sign-in - - if signin_enabled? && signup_enabled? - .prepend-top-20 + -# Signup only makes sense if you can also sign-in + - if signin_enabled? && signup_enabled? = render 'devise/shared/signup_box' - -# Show a message if none of the mechanisms above are enabled - - if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) - %div - No authentication methods configured. + - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? + .clearfix + = render 'devise/shared/omniauth_box' + + -# Show a message if none of the mechanisms above are enabled + - if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) + %div + No authentication methods configured. + diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml index e623f7cff88..56074c057d7 100644 --- a/app/views/devise/sessions/two_factor.html.haml +++ b/app/views/devise/sessions/two_factor.html.haml @@ -3,20 +3,19 @@ = page_specific_javascript_tag('u2f.js') %div + = render 'devise/shared/tab_single', { :tab_title => 'Two-Factor Authentication' } .login-box - .login-heading - %h3 Two-Factor Authentication .login-body - if @user.two_factor_otp_enabled? - %h5 Authenticate via Two-Factor App - = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f| + = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: 'edit_user show-gl-field-errors' }) do |f| - resource_params = params[resource_name].presence || params = f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0) - = f.text_field :otp_attempt, class: 'form-control', placeholder: 'Two-Factor Authentication code', required: true, autofocus: true, autocomplete: 'off' - %p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes. - .prepend-top-20 - = f.submit "Verify code", class: "btn btn-save" + .form-group + = f.label 'Two-Factor Authentication code', name: :otp_attempt + = f.text_field :otp_attempt, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.' + %p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes. + .prepend-top-20 + = f.submit "Verify code", class: "btn btn-save" - if @user.two_factor_u2f_enabled? - %hr = render "u2f/authenticate", locals: { params: params, resource: resource, resource_name: resource_name } diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml index 2e7da2747d0..d5b6db48a29 100644 --- a/app/views/devise/shared/_omniauth_box.html.haml +++ b/app/views/devise/shared/_omniauth_box.html.haml @@ -1,8 +1,9 @@ -%p - %span.light - Sign in with   - - providers = enabled_button_based_providers - - providers.each do |provider| +%div.login-box + %p %span.light - - has_icon = provider_has_icon?(provider) - = link_to provider_image_tag(provider), omniauth_authorize_path(:user, provider), method: :post, class: (has_icon ? 'oauth-image-link' : 'btn'), "data-no-turbolink" => "true" + Sign in with   + - providers = enabled_button_based_providers + - providers.each do |provider| + %span.light + - has_icon = provider_has_icon?(provider) + = link_to provider_image_tag(provider), omniauth_authorize_path(:user, provider), method: :post, class: (has_icon ? 'oauth-image-link' : 'btn'), "data-no-turbolink" => "true" diff --git a/app/views/devise/shared/_sign_in_link.html.haml b/app/views/devise/shared/_sign_in_link.html.haml index fafc4b82f53..289bf40f3de 100644 --- a/app/views/devise/shared/_sign_in_link.html.haml +++ b/app/views/devise/shared/_sign_in_link.html.haml @@ -1,5 +1,4 @@ %p %span.light Already have login and password? - %strong = link_to "Sign in", new_session_path(resource_name) diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml index 2c15e2c4891..810dd5ab687 100644 --- a/app/views/devise/shared/_signin_box.html.haml +++ b/app/views/devise/shared/_signin_box.html.haml @@ -1,32 +1,15 @@ -.login-box - - if signup_enabled? - .login-heading - %h3 Existing user? Sign in - - else - .login-heading - %h3 Sign in +#login-pane.login-box{ role: 'tabpanel', class: 'tab-pane active' } .login-body - if form_based_providers.any? - %ul.nav-links - - if crowd_enabled? - %li.active - = link_to "Crowd", "#tab-crowd", 'data-toggle' => 'tab' - - @ldap_servers.each_with_index do |server, i| - %li{class: (:active if i.zero? && !crowd_enabled?)} - = link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab' - - if signin_enabled? - %li - = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab' - .tab-content - - if crowd_enabled? - %div.tab-pane.active{id: "tab-crowd"} - = render 'devise/sessions/new_crowd' - - @ldap_servers.each_with_index do |server, i| - %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero? && !crowd_enabled?)} - = render 'devise/sessions/new_ldap', server: server - - if signin_enabled? - %div#tab-signin.tab-pane - = render 'devise/sessions/new_base' + - if crowd_enabled? + %div.tab-pane.active{id: "tab-crowd"} + = render 'devise/sessions/new_crowd' + - @ldap_servers.each_with_index do |server, i| + %div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero? && !crowd_enabled?)} + = render 'devise/sessions/new_ldap', server: server + - if signin_enabled? + %div#tab-signin.tab-pane + = render 'devise/sessions/new_base' - elsif signin_enabled? = render 'devise/sessions/new_base' diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index 905a8dbcd84..c43a6aa3e49 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -1,28 +1,30 @@ -.login-box - - if signin_enabled? - .login-heading - %h3 New user? Create an account - - else - .login-heading - %h3 Create an account +#register-pane.login-box{ role: 'tabpanel', class: 'tab-pane' } .login-body - = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name)) do |f| + = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user show-gl-field-errors", "aria-live" => "assertive" }) do |f| .devise-errors = devise_error_messages! - %div - = f.text_field :name, class: "form-control top", placeholder: "Name", required: true - %div - = f.text_field :username, class: "form-control middle", placeholder: "Username", required: true - %div - = f.email_field :email, class: "form-control middle", placeholder: "Email", required: true + %div.form-group + = f.label :name + = f.text_field :name, class: "form-control top", required: true, title: "This field is required." + %div.username.form-group + = f.label :username + = f.text_field :username, class: "form-control middle", pattern: "[a-zA-Z0-9]+", required: true + %p.gl-field-error.hide Please create a username with only alphanumeric characters. + %p.validation-error.hide Username is already taken. + %p.validation-success.hide Username is available. + %p.validation-pending.hide Checking username availability... + %div.form-group + = f.label :email + = f.email_field :email, class: "form-control middle", required: true, title: "Please provide a valid email address." .form-group.append-bottom-20#password-strength - = f.password_field :password, class: "form-control bottom", placeholder: "Password - minimum length #{@minimum_password_length} characters", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters" + = f.label :password + = f.password_field :password, class: "form-control bottom", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters." + %p.gl-field-hint Minimum length is #{@minimum_password_length} characters %div - if current_application_settings.recaptcha_enabled = recaptcha_tags %div - = f.submit "Sign up", class: "btn-create btn" - + = f.submit "Register", class: "btn-register btn" .clearfix.prepend-top-20 %p %span.light Didn't receive a confirmation email? diff --git a/app/views/devise/shared/_tab_single.html.haml b/app/views/devise/shared/_tab_single.html.haml new file mode 100644 index 00000000000..8590c43d54d --- /dev/null +++ b/app/views/devise/shared/_tab_single.html.haml @@ -0,0 +1,4 @@ +// = render 'devise/shared/tab_single', :tab_title => 'Tab Title' +%ul.nav-links.nav-tabs.new-session-tabs.single-tab + %li.active + = link_to tab_title, '#', disabled: true diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml new file mode 100644 index 00000000000..e276e91433a --- /dev/null +++ b/app/views/devise/shared/_tabs_ldap.html.haml @@ -0,0 +1,10 @@ +%ul.new-session-tabs.nav-links.nav-tabs + - if crowd_enabled? + %li.active + = link_to "Crowd", "#tab-crowd", 'data-toggle' => 'tab' + - @ldap_servers.each_with_index do |server, i| + %li{class: (:active if i.zero? && !crowd_enabled?)} + = link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab' + - if signin_enabled? + %li + = link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab' diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml new file mode 100644 index 00000000000..48abd6519d6 --- /dev/null +++ b/app/views/devise/shared/_tabs_normal.html.haml @@ -0,0 +1,5 @@ +%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist'} + %li.active{ role: 'presentation' } + %a{ href: '#login-pane', data: {'toggle':'tab'}, role: 'tab'} Sign in + %li{ role: 'presentation'} + %a{ href: '#register-pane', data: {'toggle':'tab'}, role: 'tab'} Register diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml index 49c087c0646..0036f3b98e5 100644 --- a/app/views/devise/unlocks/new.html.haml +++ b/app/views/devise/unlocks/new.html.haml @@ -1,12 +1,12 @@ += render 'devise/shared/tab_single', { :tab_title => 'Resend unlock instructions' } .login-box - .login-heading - %h3 Resend unlock email .login-body - = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| + = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f| .devise-errors = devise_error_messages! - .clearfix.append-bottom-20 - = f.email_field :email, class: 'form-control', placeholder: 'Email', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off' + .form-group.append-bottom-20 + = f.label :email + = f.email_field :email, class: 'form-control', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', title: 'Please provide a valid email address.' .clearfix = f.submit 'Resend unlock instructions', class: 'btn btn-success' diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index a9a384bd5f3..825e540cb0c 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -1,36 +1,37 @@ !!! 5 -%html{ lang: "en"} +%html{ lang: "en", class: "devise-layout-html"} = render "layouts/head" - %body.ui_charcoal.login-page.application.navless - = Gon::Base.render_data - = render "layouts/header/empty" - = render "layouts/broadcast" - .container.navless-container - .content - = render "layouts/flash" - .row - .col-sm-5.pull-right - = yield - .col-sm-7.brand-holder.pull-left - %h1 - = brand_title - - if brand_item - = brand_image - = brand_text - - else - %h3 Open source software to collaborate on code + %body{ class: "ui_charcoal login-page application navless", data: {page: body_data_page}} + .page-wrap + = Gon::Base.render_data + = render "layouts/header/empty" + = render "layouts/broadcast" + .container.navless-container + .content + = render "layouts/flash" + .row + .col-sm-5.pull-right.new-session-forms-container + = yield + .col-sm-7.brand-holder.pull-left + %h1 + = brand_title + - if brand_item + = brand_image + = brand_text + - else + %h3 Open source software to collaborate on code - %p - Manage git repositories with fine grained access controls that keep your code secure. - Perform code reviews and enhance collaboration with merge requests. - Each project can also have an issue tracker and a wiki. + %p + Manage git repositories with fine grained access controls that keep your code secure. + Perform code reviews and enhance collaboration with merge requests. + Each project can also have an issue tracker and a wiki. - if current_application_settings.sign_in_text.present? = markdown_field(current_application_settings, :sign_in_text) - %hr - .container - .footer-links - = link_to "Explore", explore_root_path - = link_to "Help", help_path - = link_to "About GitLab", "https://about.gitlab.com/" + %hr.footer-fixed + .container.footer-container + .footer-links + = link_to "Explore", explore_root_path + = link_to "Help", help_path + = link_to "About GitLab", "https://about.gitlab.com/" diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml index 9657101ace5..232ca26c1af 100644 --- a/app/views/u2f/_authenticate.html.haml +++ b/app/views/u2f/_authenticate.html.haml @@ -6,7 +6,7 @@ %script#js-authenticate-u2f-setup{ type: "text/template" } %div %p Insert your security key (if you haven't already), and press the button below. - %a.btn.btn-info#js-login-u2f-device{ href: 'javascript:void(0)' } Login Via U2F Device + %a.btn.btn-info#js-login-u2f-device{ href: 'javascript:void(0)' } Sign in via U2F device %script#js-authenticate-u2f-in-progress{ type: "text/template" } %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now. diff --git a/config/routes.rb b/config/routes.rb index 83c3a42c19f..93d7f99fb90 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -83,6 +83,798 @@ Rails.application.routes.draw do draw :group draw :user draw :project + # + # Import + # + namespace :import do + resource :github, only: [:create, :new], controller: :github do + post :personal_access_token + get :status + get :callback + get :jobs + end + + resource :gitlab, only: [:create], controller: :gitlab do + get :status + get :callback + get :jobs + end + + resource :bitbucket, only: [:create], controller: :bitbucket do + get :status + get :callback + get :jobs + end + + resource :google_code, only: [:create, :new], controller: :google_code do + get :status + post :callback + get :jobs + + get :new_user_map, path: :user_map + post :create_user_map, path: :user_map + end + + resource :fogbugz, only: [:create, :new], controller: :fogbugz do + get :status + post :callback + get :jobs + + get :new_user_map, path: :user_map + post :create_user_map, path: :user_map + end + + resource :gitlab_project, only: [:create, :new] do + post :create + end + end + + # + # Uploads + # + + scope path: :uploads do + # Note attachments and User/Group/Project avatars + get ":model/:mounted_as/:id/:filename", + to: "uploads#show", + constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /[^\/]+/ } + + # Appearance + get ":model/:mounted_as/:id/:filename", + to: "uploads#show", + constraints: { model: /appearance/, mounted_as: /logo|header_logo/, filename: /.+/ } + + # Project markdown uploads + get ":namespace_id/:project_id/:secret/:filename", + to: "projects/uploads#show", + constraints: { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: /[^\/]+/ } + end + + # Redirect old note attachments path to new uploads path. + get "files/note/:id/:filename", + to: redirect("uploads/note/attachment/%{id}/%{filename}"), + constraints: { filename: /[^\/]+/ } + + # + # Explore area + # + namespace :explore do + resources :projects, only: [:index] do + collection do + get :trending + get :starred + end + end + + resources :groups, only: [:index] + resources :snippets, only: [:index] + root to: 'projects#trending' + end + + # Compatibility with old routing + get 'public' => 'explore/projects#index' + get 'public/projects' => 'explore/projects#index' + + # + # Admin Area + # + namespace :admin do + resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do + resources :keys, only: [:show, :destroy] + resources :identities, except: [:show] + + member do + get :projects + get :keys + get :groups + put :block + put :unblock + put :unlock + put :confirm + post :impersonate + patch :disable_two_factor + delete 'remove/:email_id', action: 'remove_email', as: 'remove_email' + end + end + + resource :impersonation, only: :destroy + + resources :abuse_reports, only: [:index, :destroy] + resources :spam_logs, only: [:index, :destroy] do + member do + post :mark_as_ham + end + end + + resources :applications + + resources :groups, constraints: { id: /[^\/]+/ } do + member do + put :members_update + end + end + + resources :deploy_keys, only: [:index, :new, :create, :destroy] + + resources :hooks, only: [:index, :create, :destroy] do + get :test + end + + resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] do + post :preview, on: :collection + end + + resource :logs, only: [:show] + resource :health_check, controller: 'health_check', only: [:show] + resource :background_jobs, controller: 'background_jobs', only: [:show] + resource :system_info, controller: 'system_info', only: [:show] + resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ } + + resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do + root to: 'projects#index', as: :projects + + resources(:projects, + path: '/', + constraints: { id: /[a-zA-Z.0-9_\-]+/ }, + only: [:index, :show]) do + root to: 'projects#show' + + member do + put :transfer + post :repository_check + end + + resources :runner_projects, only: [:create, :destroy] + end + end + + resource :appearances, only: [:show, :create, :update], path: 'appearance' do + member do + get :preview + delete :logo + delete :header_logos + end + end + + resource :application_settings, only: [:show, :update] do + resources :services, only: [:index, :edit, :update] + put :reset_runners_token + put :reset_health_check_token + put :clear_repository_check_states + end + + resources :labels + + resources :runners, only: [:index, :show, :update, :destroy] do + member do + get :resume + get :pause + end + end + + resources :builds, only: :index do + collection do + post :cancel_all + end + end + + root to: 'dashboard#index' + end + + # + # Profile Area + # + resource :profile, only: [:show, :update] do + member do + get :audit_log + get :applications, to: 'oauth/applications#index' + + put :reset_private_token + put :update_username + end + + scope module: :profiles do + resource :account, only: [:show] do + member do + delete :unlink + end + end + resource :notifications, only: [:show, :update] + resource :password, only: [:new, :create, :edit, :update] do + member do + put :reset + end + end + resource :preferences, only: [:show, :update] + resources :keys, only: [:index, :show, :new, :create, :destroy] + resources :emails, only: [:index, :create, :destroy] + resource :avatar, only: [:destroy] + + resources :personal_access_tokens, only: [:index, :create] do + member do + put :revoke + end + end + + resource :two_factor_auth, only: [:show, :create, :destroy] do + member do + post :create_u2f + post :codes + patch :skip + end + end + + resources :u2f_registrations, only: [:destroy] + end + end + + scope(path: 'u/:username', + as: :user, + constraints: { username: /[a-zA-Z.0-9_\-]+(? 'omniauth_callbacks#omniauth_error', as: :omniauth_error + get '/users/almost_there' => 'confirmations#almost_there' + end + + root to: "root#index" + + # + # Project Area + # + resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do + resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(? 'templates#show', as: :template + + scope do + get( + '/blob/*id/diff', + to: 'blob#diff', + constraints: { id: /.+/, format: false }, + as: :blob_diff + ) + get( + '/blob/*id', + to: 'blob#show', + constraints: { id: /.+/, format: false }, + as: :blob + ) + delete( + '/blob/*id', + to: 'blob#destroy', + constraints: { id: /.+/, format: false } + ) + put( + '/blob/*id', + to: 'blob#update', + constraints: { id: /.+/, format: false } + ) + post( + '/blob/*id', + to: 'blob#create', + constraints: { id: /.+/, format: false } + ) + end + + scope do + get( + '/raw/*id', + to: 'raw#show', + constraints: { id: /.+/, format: /(html|js)/ }, + as: :raw + ) + end + + scope do + get( + '/tree/*id', + to: 'tree#show', + constraints: { id: /.+/, format: /(html|js)/ }, + as: :tree + ) + end + + scope do + get( + '/find_file/*id', + to: 'find_file#show', + constraints: { id: /.+/, format: /html/ }, + as: :find_file + ) + end + + scope do + get( + '/files/*id', + to: 'find_file#list', + constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }, + as: :files + ) + end + + scope do + post( + '/create_dir/*id', + to: 'tree#create_dir', + constraints: { id: /.+/ }, + as: 'create_dir' + ) + end + + scope do + get( + '/blame/*id', + to: 'blame#show', + constraints: { id: /.+/, format: /(html|js)/ }, + as: :blame + ) + end + + scope do + get( + '/commits/*id', + to: 'commits#show', + constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }, + as: :commits + ) + end + + resource :avatar, only: [:show, :destroy] + resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do + member do + get :branches + get :builds + get :pipelines + post :cancel_builds + post :retry_builds + post :revert + post :cherry_pick + get :diff_for_path + end + end + + resources :compare, only: [:index, :create] do + collection do + get :diff_for_path + end + end + + get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ } + + # Don't use format parameter as file extension (old 3.0.x behavior) + # See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments + scope format: false do + resources :network, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } + + resources :graphs, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } do + member do + get :commits + get :ci + get :languages + end + end + end + + resources :snippets, concerns: :awardable, constraints: { id: /\d+/ } do + member do + get 'raw' + end + end + + WIKI_SLUG_ID = { id: /\S+/ } unless defined? WIKI_SLUG_ID + + scope do + # Order matters to give priority to these matches + get '/wikis/git_access', to: 'wikis#git_access' + get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages' + post '/wikis', to: 'wikis#create' + + get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID + get '/wikis/*id/edit', to: 'wikis#edit', as: 'wiki_edit', constraints: WIKI_SLUG_ID + + get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID + delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID + put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID + post '/wikis/*id/preview_markdown', to: 'wikis#preview_markdown', constraints: WIKI_SLUG_ID, as: 'wiki_preview_markdown' + end + + resource :repository, only: [:create] do + member do + get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex } + end + end + + resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do + member do + get :test + end + end + + resources :deploy_keys, constraints: { id: /\d+/ }, only: [:index, :new, :create] do + member do + put :enable + put :disable + end + end + + resources :forks, only: [:index, :new, :create] + resource :import, only: [:new, :create, :show] + + resources :refs, only: [] do + collection do + get 'switch' + end + + member do + # tree viewer logs + get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } + # Directories with leading dots erroneously get rejected if git + # ref regex used in constraints. Regex verification now done in controller. + get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: { + id: /.*/, + path: /.*/ + } + end + end + + resources :merge_requests, concerns: :awardable, constraints: { id: /\d+/ } do + member do + get :commits + get :diffs + get :conflicts + get :builds + get :pipelines + get :merge_check + post :merge + post :cancel_merge_when_build_succeeds + get :ci_status + post :toggle_subscription + post :remove_wip + get :diff_for_path + post :resolve_conflicts + end + + collection do + get :branch_from + get :branch_to + get :update_branches + get :diff_for_path + post :bulk_update + end + + resources :discussions, only: [], constraints: { id: /\h{40}/ } do + member do + post :resolve + delete :resolve, action: :unresolve + end + end + end + + resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } + resources :tags, only: [:index, :show, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do + resource :release, only: [:edit, :update] + end + + resources :protected_branches, only: [:index, :show, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } + resources :variables, only: [:index, :show, :update, :create, :destroy] + resources :triggers, only: [:index, :create, :destroy] + + resources :pipelines, only: [:index, :new, :create, :show] do + collection do + resource :pipelines_settings, path: 'settings', only: [:show, :update] + end + + member do + post :cancel + post :retry + end + end + + resources :environments + + resource :cycle_analytics, only: [:show] + + resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do + collection do + post :cancel_all + + resources :artifacts, only: [] do + collection do + get :latest_succeeded, + path: '*ref_name_and_path', + format: false + end + end + end + + member do + get :status + post :cancel + post :retry + post :play + post :erase + get :trace + get :raw + end + + resource :artifacts, only: [] do + get :download + get :browse, path: 'browse(/*path)', format: false + get :file, path: 'file/*path', format: false + post :keep + end + end + + resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do + member do + get :test + end + end + + resources :container_registry, only: [:index, :destroy], constraints: { id: Gitlab::Regex.container_registry_reference_regex } + + resources :milestones, constraints: { id: /\d+/ } do + member do + put :sort_issues + put :sort_merge_requests + end + end + + resources :labels, except: [:show], constraints: { id: /\d+/ } do + collection do + post :generate + post :set_priorities + end + + member do + post :toggle_subscription + delete :remove_priority + end + end + + resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do + member do + post :toggle_subscription + post :mark_as_spam + get :referenced_merge_requests + get :related_branches + get :can_create_branch + end + collection do + post :bulk_update + end + end + + resources :project_members, except: [:show, :new, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }, concerns: :access_requestable do + collection do + delete :leave + + # Used for import team + # from another project + get :import + post :apply_import + end + + member do + post :resend_invite + end + end + + resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ } + + resources :notes, only: [:index, :create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do + member do + delete :delete_attachment + post :resolve + delete :resolve, action: :unresolve + end + end + + resource :board, only: [:show] do + scope module: :boards do + resources :issues, only: [:update] + + resources :lists, only: [:index, :create, :update, :destroy] do + collection do + post :generate + end + + resources :issues, only: [:index] + end + end + end + + resources :todos, only: [:create] + + resources :uploads, only: [:create] do + collection do + get ":secret/:filename", action: :show, as: :show, constraints: { filename: /[^\/]+/ } + end + end + + resources :runners, only: [:index, :edit, :update, :destroy, :show] do + member do + get :resume + get :pause + end + + collection do + post :toggle_shared_runners + end + end + + resources :runner_projects, only: [:create, :destroy] + resources :badges, only: [:index] do + collection do + scope '*ref', constraints: { ref: Gitlab::Regex.git_reference_regex } do + constraints format: /svg/ do + get :build + get :coverage + end + end + end + end + end + end + end # Get all keys of user get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ } diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index a752c1d7235..65544f79eba 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -14,7 +14,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq users_almost_there_path expect(page).to have_content("Please check your email to confirm your account") @@ -33,7 +33,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq dashboard_projects_path expect(page).to have_content("Welcome! You have signed up successfully.") @@ -52,7 +52,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: existing_user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq user_registration_path expect(page).to have_content("error prohibited this user from being saved") @@ -69,7 +69,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: existing_user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq user_registration_path expect(page.body).not_to match(/#{user.password}/) diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb index ff6933dc8d9..b750f27ea72 100644 --- a/spec/features/u2f_spec.rb +++ b/spec/features/u2f_spec.rb @@ -160,7 +160,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: login_with(user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -174,7 +174,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: login_with(user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -186,7 +186,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: login_with(user, remember: true) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') within 'div#js-authenticate-u2f' do @@ -209,7 +209,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: # Try authenticating user with the old U2F device login_as(current_user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -230,7 +230,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: # Try authenticating user with the same U2F device login_as(current_user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -244,7 +244,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: unregistered_device = FakeU2fDevice.new(page, FFaker::Name.first_name) login_as(user) unregistered_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -271,7 +271,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: [first_device, second_device].each do |device| login_as(user) device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 6498b7317b4..63743169302 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -1,15 +1,16 @@ require 'spec_helper' -feature 'Users', feature: true do +feature 'Users', feature: true, js: true do let(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') } scenario 'GET /users/sign_in creates a new user account' do visit new_user_session_path + click_link 'Register' fill_in 'new_user_name', with: 'Name Surname' fill_in 'new_user_username', with: 'Great' fill_in 'new_user_email', with: 'name@mail.com' fill_in 'new_user_password', with: 'password1234' - expect { click_button 'Sign up' }.to change { User.count }.by(1) + expect { click_button 'Register' }.to change { User.count }.by(1) end scenario 'Successful user signin invalidates password reset token' do @@ -31,11 +32,12 @@ feature 'Users', feature: true do scenario 'Should show one error if email is already taken' do visit new_user_session_path + click_link 'Register' fill_in 'new_user_name', with: 'Another user name' fill_in 'new_user_username', with: 'anotheruser' fill_in 'new_user_email', with: user.email fill_in 'new_user_password', with: '12341234' - expect { click_button 'Sign up' }.to change { User.count }.by(0) + expect { click_button 'Register' }.to change { User.count }.by(0) expect(page).to have_text('Email has already been taken') expect(number_of_errors_on_page(page)).to be(1), 'errors on page:\n #{errors_on_page page}' end @@ -51,6 +53,30 @@ feature 'Users', feature: true do end end + feature 'username validation' do + include WaitForAjax + let(:loading_icon) { '.fa.fa-spinner' } + let(:username_input) { 'new_user_username' } + + before(:each) do + visit new_user_session_path + click_link 'Register' + @username_field = find '.username' + end + + scenario 'shows an error border if the username already exists' do + fill_in username_input, with: user.username + wait_for_ajax + expect(@username_field).to have_css '.gl-field-error-outline' + end + + scenario 'doesn\'t show an error border if the username is available' do + fill_in username_input, with: 'new-user' + wait_for_ajax + expect(@username_field).not_to have_css '.gl-field-error-outline' + end + end + def errors_on_page(page) page.find('#error_explanation').find('ul').all('li').map{ |item| item.text }.join("\n") end diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js index 7ce3884f844..784b43d4846 100644 --- a/spec/javascripts/u2f/authenticate_spec.js +++ b/spec/javascripts/u2f/authenticate_spec.js @@ -21,7 +21,7 @@ setupButton = this.container.find("#js-login-u2f-device"); setupMessage = this.container.find("p"); expect(setupMessage.text()).toContain('Insert your security key'); - expect(setupButton.text()).toBe('Login Via U2F Device'); + expect(setupButton.text()).toBe('Sign in via U2F device'); setupButton.trigger('click'); inProgressMessage = this.container.find("p"); expect(inProgressMessage.text()).toContain("Trying to communicate with your device"); -- cgit v1.2.1 From d2bad46efee65688ab56d9d7c850775f1339f491 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 06:47:53 +0200 Subject: Add padding to fixed footer, to more quickly support scrolling. --- app/assets/stylesheets/pages/login.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 06b90fbefab..9cc1bf90122 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -250,4 +250,8 @@ height: 40px; background: $white-light; } + + .navless-container { + padding: 65px; // height of footer + bottom padding of email confirmation link + } } -- cgit v1.2.1 From 768cd071afa41acc5b9c91958ac280e1d6870dae Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 07:25:47 +0200 Subject: Clean up username_validator private vars and members. --- app/assets/javascripts/username_validator.js.es6 | 91 ++++++++++++------------ 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6 index f8be356af04..a22f598b753 100644 --- a/app/assets/javascripts/username_validator.js.es6 +++ b/app/assets/javascripts/username_validator.js.es6 @@ -1,34 +1,34 @@ ((global) => { const debounceTimeoutDuration = 1000; - const inputErrorClass = 'gl-field-error-outline'; - const inputSuccessClass = 'gl-field-success-outline'; - const messageErrorSelector = '.username .validation-error'; - const messageSuccessSelector = '.username .validation-success'; - const messagePendingSelector = '.username .validation-pending'; + const invalidInputClass = 'gl-field-error-outline'; + const successInputClass = 'gl-field-success-outline'; + const unavailableMessageSelector = '.username .validation-error'; + const successMessageSelector = '.username .validation-success'; + const pendingMessageSelector = '.username .validation-pending'; + const invalidMessageSelector = '.username .gl-field-error'; class UsernameValidator { constructor() { this.inputElement = $('#new_user_username'); this.inputDomElement = this.inputElement.get(0); - - this.available = false; - this.valid = false; - this.pending = false; - this.fresh = true; - this.empty = true; + this.state = { + available: false, + valid: false, + pending: false, + empty: true + }; const debounceTimeout = _.debounce((username) => { - this.validateUsername(username); + this.state.validateUsername(username); }, debounceTimeoutDuration); this.inputElement.on('keyup.username_check', () => { const username = this.inputElement.val(); - this.valid = this.inputDomElement.validity.valid; - this.fresh = false; - this.empty = !username.length; + this.state.valid = this.inputDomElement.validity.valid; + this.state.empty = !username.length; - if (this.valid) { + if (this.state.valid) { return debounceTimeout(username); } @@ -36,43 +36,43 @@ }); // Override generic field validation - this.inputElement.on('invalid', this.handleInvalidInput.bind(this)); + this.inputElement.on('invalid', this.interceptInvalid.bind(this)); } renderState() { // Clear all state this.clearFieldValidationState(); - if (this.valid && this.available) { + if (this.state.valid && this.state.available) { return this.setSuccessState(); } - if (this.empty) { + if (this.state.empty) { return this.clearFieldValidationState(); } - if (this.pending) { + if (this.state.pending) { return this.setPendingState(); } - if (!this.available) { + if (!this.state.available) { return this.setUnavailableState(); } - if (!this.valid) { + if (!this.state.valid) { return this.setInvalidState(); } } - handleInvalidInput(event) { + interceptInvalid(event) { event.preventDefault(); event.stopPropagation(); } validateUsername(username) { - if (this.valid) { - this.pending = true; - this.available = false; + if (this.state.valid) { + this.state.pending = true; + this.state.available = false; this.renderState(); return $.ajax({ type: 'GET', @@ -83,38 +83,40 @@ } } - updateValidationState(usernameTaken) { + setAvailabilityState(usernameTaken) { if (usernameTaken) { - this.valid = false; - this.available = false; + this.state.valid = false; + this.state.available = false; } else { - this.available = true; + this.state.available = true; } - this.pending = false; + this.state.pending = false; this.renderState(); } clearFieldValidationState() { - this.inputElement.siblings('p').hide(); - this.inputElement.removeClass(inputErrorClass); - this.inputElement.removeClass(inputSuccessClass); + // TODO: Double check if this is valid chaining + const $input = this.inputElement + .siblings('p').hide().end() + .removeClass(invalidInputClass); + removeClass(successInputClass); } setUnavailableState() { - const $usernameErrorMessage = this.inputElement.siblings(messageErrorSelector); - this.inputElement.addClass(inputErrorClass).removeClass(inputSuccessClass); - $usernameErrorMessage.show(); + const $usernameUnavailableMessage = this.inputElement.siblings(unavailableMessageSelector); + this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); + $usernameUnavailableMessage.show(); } setSuccessState() { - const $usernameSuccessMessage = this.inputElement.siblings(messageSuccessSelector); - this.inputElement.addClass(inputSuccessClass).removeClass(inputErrorClass); + const $usernameSuccessMessage = this.inputElement.siblings(successMessageSelector); + this.inputElement.addClass(successInputClass).removeClass(invalidInputClass); $usernameSuccessMessage.show(); } - setPendingState(show) { - const $usernamePendingMessage = $(messagePendingSelector); - if (this.pending) { + setPendingState() { + const $usernamePendingMessage = $(pendingMessageSelector); + if (this.state.pending) { $usernamePendingMessage.show(); } else { $usernamePendingMessage.hide(); @@ -122,8 +124,9 @@ } setInvalidState() { - this.inputElement.addClass(inputErrorClass).removeClass(inputSuccessClass); - $(`.gl-field-error`).show(); + const $inputErrorMessage = $(invalidMessageSelector); + this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); + $inputErrorMessage.show(); } } -- cgit v1.2.1 From a449b9b8a171c659c7b3ce37f685624e3e079192 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 08:31:04 +0200 Subject: Refactor gl field errors for simpler state management. --- app/assets/javascripts/gl_field_errors.js.es6 | 134 +++++++++++++++++--------- 1 file changed, 89 insertions(+), 45 deletions(-) diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index 42a2ddeeafe..f4c09dd407d 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -13,79 +13,123 @@ * * */ - const fieldErrorClass = 'gl-field-error'; - const fieldErrorSelector = `.${fieldErrorClass}`; + const errorMessageClass = 'gl-field-error'; const inputErrorClass = 'gl-field-error-outline'; - class GlFieldErrors { - constructor(form) { - this.form = $(form); - this.initValidators(); + class GlFieldError { + constructor({ input, form }) { + this.inputElement = $(input); + this.inputDomElement = this.inputElement.get(0); + this.form = form; + this.errorMessage = this.inputElement.attr('title') || 'This field is required.'; + this.fieldErrorElement = $(`

    ${ this.errorMessage }

    `); + + this.state = { + valid: false, + empty: true + }; + + this.initFieldValidation(); } - initValidators () { - this.inputs = this.form.find(':input:not([type=hidden])').toArray(); - this.inputs.forEach((input) => { - $(input).off('invalid').on('invalid', this.handleInvalidInput.bind(this)); - }); - this.form.on('submit', this.catchInvalidFormSubmit); + initFieldValidation() { + // hidden when injected into DOM + $input.after(this.fieldErrorElement); + this.inputElement.off('invalid').on('invalid', this.handleInvalidInput.bind(this)); } - /* Neccessary because Safari & iOS quietly allow form submission when form is invalid */ - catchInvalidFormSubmit (event) { - if (!event.currentTarget.checkValidity()) { - event.preventDefault(); - // Prevents disabling of invalid submit button by application.js - event.stopPropagation(); + renderValidity() { + this.setClearState(); + + if (this.state.valid) { + this.setValidState(); + } + + if (this.state.empty) { + this.setEmptyState(); + } + + if (!this.state.valid) { + this.setInvalidState(); } + + this.form.focusOnFirstInvalid.apply(this); } - handleInvalidInput (event) { + handleInvalidInput(event) { event.preventDefault(); - this.updateFieldValidityState(event); - const $input = $(event.currentTarget); + this.state.valid = true; + this.state.empty = false; + + this.renderValidity(); // For UX, wait til after first invalid submission to check each keyup - $input.off('keyup.field_validator') - .on('keyup.field_validator', this.updateFieldValidityState.bind(this)); + this.inputElement.off('keyup.field_validator') + .on('keyup.field_validator', this.updateValidityState.bind(this)); } - displayFieldValidity (target, isValid) { - const $input = $(target).removeClass(inputErrorClass); - const $existingError = $input.siblings(fieldErrorSelector); - const alreadyInvalid = !!$existingError.length; - const implicitErrorMessage = $input.attr('title'); - const $errorToDisplay = alreadyInvalid ? $existingError.detach() : $(`

    ${implicitErrorMessage}

    `); + getInputValidity() { + return this.inputDomElement.validity.valid; + } - if (!isValid) { - $input.after($errorToDisplay); - $input.addClass(inputErrorClass); - } + updateValidityState() { + const inputVal = this.inputElement.val(); + this.state.empty = !!inputVal.length; + this.state.valid = this.getInputValidity; - this.updateFieldSiblings($errorToDisplay, isValid); + this.renderValidity(); } - updateFieldSiblings($target, isValid) { - const siblings = $target.siblings(`p${fieldErrorSelector}`); - return isValid ? siblings.show() : siblings.hide(); + setValidState() { + return this.setClearState(); + } + + setEmptyState() { + return this.setClearState(); + } + + setInvalidState() { + $input.addClass(inputErrorClass); + return this.$fieldErrorElement.show(); + } + + setClearState() { + $input.removeClass(inputErrorClass); + return this.fieldErrorElement.hide(); } checkFieldValidity(target) { return target.validity.valid; } + } - updateFieldValidityState(event) { - const target = event.currentTarget; - const isKeyup = event.type === 'keyup'; - const isValid = this.checkFieldValidity(target); + class GlFieldErrors { + constructor(form) { + this.form = $(form); + this.initValidators(); + } - this.displayFieldValidity(target, isValid); + initValidators () { + // select all non-hidden inputs in form + const form = this.form; + + this.inputs = this.form.find(':input:not([type=hidden])') + .toArray() + .map((input) => new GlFieldError({ input, form })); + + this.form.on('submit', this.catchInvalidFormSubmit); + } - // prevent changing focus while user is typing. - if (!isKeyup) { - this.focusOnFirstInvalid.apply(this); + /* Neccessary to prevent intercept and override invalid form submit + * because Safari & iOS quietly allow form submission when form is invalid + * and prevents disabling of invalid submit button by application.js */ + + catchInvalidFormSubmit (event) { + if (!event.currentTarget.checkValidity()) { + event.preventDefault(); + event.stopPropagation(); } } -- cgit v1.2.1 From 00bfb645e16b24ce929211bf5080aa3083f8543b Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 10:29:21 +0200 Subject: Fix errors, get validation running for signup box and sign in. --- app/assets/javascripts/gl_field_errors.js.es6 | 52 ++++++++++++++---------- app/assets/javascripts/username_validator.js.es6 | 12 +++--- app/views/devise/shared/_signup_box.html.haml | 2 +- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index f4c09dd407d..e1de7f78efc 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -17,10 +17,10 @@ const inputErrorClass = 'gl-field-error-outline'; class GlFieldError { - constructor({ input, form }) { + constructor({ input, formErrors }) { this.inputElement = $(input); this.inputDomElement = this.inputElement.get(0); - this.form = form; + this.form = formErrors; this.errorMessage = this.inputElement.attr('title') || 'This field is required.'; this.fieldErrorElement = $(`

    ${ this.errorMessage }

    `); @@ -34,7 +34,7 @@ initFieldValidation() { // hidden when injected into DOM - $input.after(this.fieldErrorElement); + this.inputElement.after(this.fieldErrorElement); this.inputElement.off('invalid').on('invalid', this.handleInvalidInput.bind(this)); } @@ -42,24 +42,24 @@ this.setClearState(); if (this.state.valid) { - this.setValidState(); + return this.setValidState(); } if (this.state.empty) { - this.setEmptyState(); + return this.setEmptyState(); } if (!this.state.valid) { - this.setInvalidState(); + return this.setInvalidState(); } - this.form.focusOnFirstInvalid.apply(this); + this.form.focusOnFirstInvalid.apply(this.form); } handleInvalidInput(event) { event.preventDefault(); - this.state.valid = true; + this.state.valid = false; this.state.empty = false; this.renderValidity(); @@ -77,8 +77,7 @@ updateValidityState() { const inputVal = this.inputElement.val(); this.state.empty = !!inputVal.length; - this.state.valid = this.getInputValidity; - + this.state.valid = this.getInputValidity(); this.renderValidity(); } @@ -87,17 +86,24 @@ } setEmptyState() { - return this.setClearState(); + return this.setInvalidState(); } setInvalidState() { - $input.addClass(inputErrorClass); - return this.$fieldErrorElement.show(); + this.inputElement.addClass(inputErrorClass); + this.inputElement.siblings('p').hide(); + return this.fieldErrorElement.show(); } setClearState() { - $input.removeClass(inputErrorClass); - return this.fieldErrorElement.hide(); + const inputVal = this.inputElement.val(); + if (!inputVal.split(' ').length) { + const trimmedInput = this.inputElement.val().trim(); + this.inputElement.val(trimmedInput); + } + this.inputElement.removeClass(inputErrorClass); + this.inputElement.siblings('p').hide(); + this.fieldErrorElement.hide(); } checkFieldValidity(target) { @@ -105,19 +111,23 @@ } } + const customValidationFlag = 'no-gl-field-errors'; + class GlFieldErrors { constructor(form) { this.form = $(form); + this.state = { + inputs: [], + valid: false + }; this.initValidators(); } initValidators () { // select all non-hidden inputs in form - const form = this.form; - - this.inputs = this.form.find(':input:not([type=hidden])') - .toArray() - .map((input) => new GlFieldError({ input, form })); + this.state.inputs = this.form.find(':input:not([type=hidden])').toArray() + .filter((input) => !input.classList.contains(customValidationFlag)) + .map((input) => new GlFieldError({ input, formErrors: this })); this.form.on('submit', this.catchInvalidFormSubmit); } @@ -134,7 +144,7 @@ } focusOnFirstInvalid () { - const firstInvalid = this.inputs.find((input) => !input.validity.valid); + const firstInvalid = this.state.inputs.find((input) => !input.inputDomElement.validity.valid); $(firstInvalid).focus(); } } diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6 index a22f598b753..b19fb9b4771 100644 --- a/app/assets/javascripts/username_validator.js.es6 +++ b/app/assets/javascripts/username_validator.js.es6 @@ -19,7 +19,7 @@ }; const debounceTimeout = _.debounce((username) => { - this.state.validateUsername(username); + this.validateUsername(username); }, debounceTimeoutDuration); this.inputElement.on('keyup.username_check', () => { @@ -78,7 +78,7 @@ type: 'GET', url: `/u/${username}/exists`, dataType: 'json', - success: (res) => this.updateValidationState(res.exists) + success: (res) => this.setAvailabilityState(res.exists) }); } } @@ -96,10 +96,10 @@ clearFieldValidationState() { // TODO: Double check if this is valid chaining - const $input = this.inputElement - .siblings('p').hide().end() - .removeClass(invalidInputClass); - removeClass(successInputClass); + this.inputElement.siblings('p').hide(); + + this.inputElement.removeClass(invalidInputClass) + .removeClass(successInputClass); } setUnavailableState() { diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index c43a6aa3e49..7382042cc50 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -8,7 +8,7 @@ = f.text_field :name, class: "form-control top", required: true, title: "This field is required." %div.username.form-group = f.label :username - = f.text_field :username, class: "form-control middle", pattern: "[a-zA-Z0-9]+", required: true + = f.text_field :username, class: "form-control middle no-gl-field-error", pattern: "[a-zA-Z0-9]+", required: true %p.gl-field-error.hide Please create a username with only alphanumeric characters. %p.validation-error.hide Username is already taken. %p.validation-success.hide Username is available. -- cgit v1.2.1 From 83fb1190205c3d1fbe16a684794ed1af10ed1bff Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 11:15:07 +0200 Subject: Get tests passing. --- spec/features/users_spec.rb | 9 +++++---- spec/support/login_helpers.rb | 4 +++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 63743169302..73d6fb6b651 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -61,16 +61,17 @@ feature 'Users', feature: true, js: true do before(:each) do visit new_user_session_path click_link 'Register' - @username_field = find '.username' + @username_form_group = find '.username' + @username_field = find '#new_user_username' end - scenario 'shows an error border if the username already exists' do + scenario 'shows an error border if the username already exists', focus: true do fill_in username_input, with: user.username wait_for_ajax - expect(@username_field).to have_css '.gl-field-error-outline' + expect(@username_form_group).to have_css '.gl-field-error-outline' end - scenario 'doesn\'t show an error border if the username is available' do + scenario 'doesn\'t show an error border if the username is available', focus: true do fill_in username_input, with: 'new-user' wait_for_ajax expect(@username_field).not_to have_css '.gl-field-error-outline' diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index c0b3e83244d..3e90c95918c 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -33,7 +33,9 @@ module LoginHelpers fill_in "user_login", with: user.email fill_in "user_password", with: "12345678" check 'user_remember_me' if remember - click_button "Sign in" + page.within '.login-box' do + click_button "Sign in" + end Thread.current[:current_user] = user end -- cgit v1.2.1 From 74bfba72263ae28a1a9a9fd53984e5d11a125fa7 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 11:25:30 +0200 Subject: Include correct validation error with username invalid. --- app/views/devise/shared/_signup_box.html.haml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index 7382042cc50..fb7ee2dbd3b 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -8,8 +8,7 @@ = f.text_field :name, class: "form-control top", required: true, title: "This field is required." %div.username.form-group = f.label :username - = f.text_field :username, class: "form-control middle no-gl-field-error", pattern: "[a-zA-Z0-9]+", required: true - %p.gl-field-error.hide Please create a username with only alphanumeric characters. + = f.text_field :username, class: "form-control middle no-gl-field-error", pattern: "[a-zA-Z0-9]+", required: true, title: 'Please create a username with only alphanumeric characters.' %p.validation-error.hide Username is already taken. %p.validation-success.hide Username is available. %p.validation-pending.hide Checking username availability... -- cgit v1.2.1 From bd0bf40763ed7acd43d24413f4b4a421f0076242 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 13:30:26 +0200 Subject: Make style fixes, make all submit buttons full-width btn-block. --- app/assets/stylesheets/pages/login.scss | 5 +++++ app/views/devise/sessions/_new_base.html.haml | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 9cc1bf90122..f680fd68d70 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -198,6 +198,11 @@ font-weight: normal; } + input[type="submit"] { + @extend .btn-block; + margin-bottom: 0px; + } + .devise-errors { h2 { margin-top: 0; diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml index cfb1b964d76..d0cd418236a 100644 --- a/app/views/devise/sessions/_new_base.html.haml +++ b/app/views/devise/sessions/_new_base.html.haml @@ -5,8 +5,6 @@ %div.form-group = f.label :password = f.password_field :password, class: "form-control bottom", required: true, title: "This field is required." - .sign-in - = f.submit "Sign in", class: "btn btn-save" - if devise_mapping.rememberable? .remember-me.checkbox %label{for: "user_remember_me"} @@ -14,3 +12,5 @@ %span Remember me .pull-right = link_to "Forgot your password?", new_password_path(resource_name) + %div.prepend-top-20 + = f.submit "Sign in", class: "btn btn-save" -- cgit v1.2.1 From 2c7a1af66f45e475b5aa7b8b91e7f8c85134a762 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 13:38:39 +0200 Subject: Add submit button contain with custom margin. --- app/assets/stylesheets/pages/login.scss | 4 ++++ app/views/devise/sessions/_new_base.html.haml | 2 +- app/views/devise/shared/_signup_box.html.haml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index f680fd68d70..b235eb845b0 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -198,6 +198,10 @@ font-weight: normal; } + .submit-container { + margin-top: 16px; + } + input[type="submit"] { @extend .btn-block; margin-bottom: 0px; diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml index d0cd418236a..a96b579c593 100644 --- a/app/views/devise/sessions/_new_base.html.haml +++ b/app/views/devise/sessions/_new_base.html.haml @@ -12,5 +12,5 @@ %span Remember me .pull-right = link_to "Forgot your password?", new_password_path(resource_name) - %div.prepend-top-20 + %div.submit-container = f.submit "Sign in", class: "btn btn-save" diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index fb7ee2dbd3b..d0bbcf3115e 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -24,7 +24,7 @@ = recaptcha_tags %div = f.submit "Register", class: "btn-register btn" -.clearfix.prepend-top-20 +.clearfix.submit-container %p %span.light Didn't receive a confirmation email? = succeed '.' do -- cgit v1.2.1 From 49688d399a3b3c7d3ec50ae0bb728ff0d25671b0 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Tue, 27 Sep 2016 14:06:18 +0200 Subject: Add third box shadow to validation focus, for depth. --- app/assets/stylesheets/pages/login.scss | 90 ++++++++++++++------------------- 1 file changed, 37 insertions(+), 53 deletions(-) diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index b235eb845b0..f1d15417705 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -40,7 +40,7 @@ p { font-size: 13px; } - .login-box { + .login-box, .omniauth-container { box-shadow: 0 0 0 1px $border-color; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; @@ -79,69 +79,57 @@ background: transparent; } - .form-control { - font-size: 14px; - padding: 10px 8px; - width: 100%; - height: auto; - - &.top { - border-radius: 5px 5px 0 0; - margin-bottom: 0; - } + // Styles the glowing border of focused input for username async validation + .login-body { + font-size: 13px; - &.bottom { - border-radius: 0 0 5px 5px; - border-top: 0; - margin-bottom: 20px; - } - } - // Styles the glowing border of focused input for username async validation - .login-body { - font-size: 13px; + input + p { + margin-top: 5px; + } + .gl-field-success-outline { + border: 1px solid $green-normal; - input + p { - margin-top: 5px; - } + &:focus { + box-shadow: 0 0 0 1px $green-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 $green-normal; + border: 0 none; + } + } - .gl-field-success-outline { - border: 1px solid $green-normal; + .gl-field-error-outline { + border: 1px solid $red-normal; - &:focus { - box-shadow: 0 0 0 1px $green-normal inset, 0 0 4px 0 $green-normal; - border: 0 none; + &:focus { + box-shadow: 0 0 0 1px $red-normal inset, 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 4px 0 rgba(210, 40, 82, 0.6); + border: 0 none; + } } - } - .gl-field-error-outline { - border: 1px solid $red-normal; + .username .validation-success, + .gl-field-success-message { + color: $green-normal; + } - &:focus { - opacity: .6; - box-shadow: 0 0 0 1px $red-normal inset, 0 0 4px 0 $red-normal; - border: 0 none; + .username .validation-error, + .gl-field-error-message { + color: $red-normal; } - } - .username .validation-success, - .gl-field-success-message { - color: $green-normal; - } + .gl-field-hint { + color: $gl-text-color; + } - .username .validation-error, - .gl-field-error-message { - color: $red-normal; } + } - .gl-field-hint { - color: $gl-text-color; + .omniauth-container { + p { + margin: 0; } - } - - .new-session-tabs { // Are these being applied to other login-related screens? They need to be. + .new-session-tabs { + display: -webkit-flex; display: flex; box-shadow: 0 0 0 1px $border-color; border-top-right-radius: 2px; @@ -151,10 +139,6 @@ flex: 1; text-align: center; - &.middle { - border-top: 0; - margin-bottom: 0; - border-radius: 0; &:last-of-type { border-left: 1px solid $border-color; } @@ -204,7 +188,7 @@ input[type="submit"] { @extend .btn-block; - margin-bottom: 0px; + margin-bottom: 0; } .devise-errors { -- cgit v1.2.1 From 076749645a51c4fe948cdf5ed16dc8455a9aae05 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Tue, 27 Sep 2016 14:54:15 +0200 Subject: Shush rubocop. --- spec/features/users_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 73d6fb6b651..17a555e4673 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -65,13 +65,13 @@ feature 'Users', feature: true, js: true do @username_field = find '#new_user_username' end - scenario 'shows an error border if the username already exists', focus: true do + scenario 'shows an error border if the username already exists' do fill_in username_input, with: user.username wait_for_ajax expect(@username_form_group).to have_css '.gl-field-error-outline' end - scenario 'doesn\'t show an error border if the username is available', focus: true do + scenario 'doesn\'t show an error border if the username is available' do fill_in username_input, with: 'new-user' wait_for_ajax expect(@username_field).not_to have_css '.gl-field-error-outline' -- cgit v1.2.1 From 80cbc9838eae8836a9bf85bac1dca7e965d1d77d Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Tue, 27 Sep 2016 17:07:51 +0200 Subject: Fix omniauth box styling. --- app/views/devise/sessions/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 2fb05b9456b..dbdbc9689aa 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -13,7 +13,7 @@ = render 'devise/shared/signup_box' - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? - .clearfix + .clearfix.omniauth-box = render 'devise/shared/omniauth_box' -# Show a message if none of the mechanisms above are enabled -- cgit v1.2.1 From 503dcacaa42bc5870a87b579009c53c991b03c4e Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 12:59:58 +0200 Subject: Properly implement focus on first invalid. --- app/assets/javascripts/gl_field_errors.js.es6 | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index e1de7f78efc..91c25047f7b 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -53,17 +53,16 @@ return this.setInvalidState(); } - this.form.focusOnFirstInvalid.apply(this.form); } handleInvalidInput(event) { event.preventDefault(); - + const currentValue = this.inputElement.val(); this.state.valid = false; - this.state.empty = false; + this.state.empty = currentValue === ''; this.renderValidity(); - + this.form.focusOnFirstInvalid.apply(this.form); // For UX, wait til after first invalid submission to check each keyup this.inputElement.off('keyup.field_validator') .on('keyup.field_validator', this.updateValidityState.bind(this)); @@ -76,7 +75,7 @@ updateValidityState() { const inputVal = this.inputElement.val(); - this.state.empty = !!inputVal.length; + this.state.empty = !inputVal.length; this.state.valid = this.getInputValidity(); this.renderValidity(); } @@ -105,10 +104,6 @@ this.inputElement.siblings('p').hide(); this.fieldErrorElement.hide(); } - - checkFieldValidity(target) { - return target.validity.valid; - } } const customValidationFlag = 'no-gl-field-errors'; @@ -144,8 +139,8 @@ } focusOnFirstInvalid () { - const firstInvalid = this.state.inputs.find((input) => !input.inputDomElement.validity.valid); - $(firstInvalid).focus(); + const firstInvalid = this.state.inputs.filter((input) => !input.inputDomElement.validity.valid)[0]; + firstInvalid.inputElement.focus(); } } -- cgit v1.2.1 From 69f9c00cfb7d80959a523a10ef7d5f53a37b21e5 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 13:01:03 +0200 Subject: Add tests for gl_field_errors. --- .../javascripts/fixtures/gl_field_errors.html.haml | 15 +++ spec/javascripts/gl_field_errors_spec.js.es6 | 111 +++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 spec/javascripts/fixtures/gl_field_errors.html.haml create mode 100644 spec/javascripts/gl_field_errors_spec.js.es6 diff --git a/spec/javascripts/fixtures/gl_field_errors.html.haml b/spec/javascripts/fixtures/gl_field_errors.html.haml new file mode 100644 index 00000000000..2526e5e33a5 --- /dev/null +++ b/spec/javascripts/fixtures/gl_field_errors.html.haml @@ -0,0 +1,15 @@ +%form.show-gl-field-errors{action: 'submit', method: 'post'} + .form-group + %input.required-text{required: true, type: 'text'} Text + .form-group + %input.email{type: 'email', title: 'Please provide a valid email address.', required: true } Email + .form-group + %input.password{type: 'password', required: true} Password + .form-group + %input.alphanumeric{type: 'text', pattern: '[a-zA-Z0-9]', required: true} Alphanumeric + .form-group + %input.hidden{ type:'hidden' } + .form-group + %input.custom.no-gl-field-errors{ type:'text' } Custom, do not validate + .form-group + %input.submit{type: 'submit'} Submit diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6 new file mode 100644 index 00000000000..36feb2b2aa5 --- /dev/null +++ b/spec/javascripts/gl_field_errors_spec.js.es6 @@ -0,0 +1,111 @@ +//= require jquery +//= require gl_field_errors + +((global) => { + fixture.preload('gl_field_errors.html'); + + describe('GL Style Field Errors', function() { + beforeEach(function() { + fixture.load('gl_field_errors.html'); + const $form = this.$form = $('form.show-gl-field-errors'); + this.fieldErrors = new global.GlFieldErrors($form); + }); + + it('should properly initialize the form', function() { + expect(this.$form).toBeDefined(); + expect(this.$form.length).toBe(1); + expect(this.fieldErrors).toBeDefined(); + const inputs = this.fieldErrors.state.inputs; + expect(inputs.length).toBe(5); + }); + + it('should ignore elements with custom error handling', function() { + const customErrorFlag = 'no-gl-field-errors'; + const customErrorElem = $(`.${customErrorFlag}`); + + expect(customErrorElem.length).toBe(1); + + const customErrors = this.fieldErrors.state.inputs.filter((input) => { + return input.inputElement.hasClass(customErrorFlag); + }); + expect(customErrors.length).toBe(0); + }); + + it('should not show any errors before submit attempt', function() { + this.$form.find('.email').val('not-a-valid-email').keyup(); + this.$form.find('.text-required').val('').keyup(); + this.$form.find('.alphanumberic').val('?---*').keyup(); + + const errorsShown = this.$form.find('.gl-field-error-outline'); + expect(errorsShown.length).toBe(0); + }); + + it('should show errors when input valid is submitted', function() { + this.$form.find('.email').val('not-a-valid-email').keyup(); + this.$form.find('.text-required').val('').keyup(); + this.$form.find('.alphanumberic').val('?---*').keyup(); + + this.$form.submit(); + + const errorsShown = this.$form.find('.gl-field-error-outline'); + expect(errorsShown.length).toBe(4); + }); + + it('should properly track validity state on input after invalid submission attempt', function() { + this.$form.submit(); + + const emailInputModel = this.fieldErrors.state.inputs[1]; + const fieldState = emailInputModel.state; + const emailInputElement = emailInputModel.inputElement; + + // No input + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(true); + expect(fieldState.valid).toBe(false); + + // Then invalid input + emailInputElement.val('not-a-valid-email').keyup(); + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(false); + + // Then valid input + emailInputElement.val('email@gitlab.com').keyup(); + expect(emailInputElement).not.toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(true); + + // Then invalid input + emailInputElement.val('not-a-valid-email').keyup(); + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(false); + + // Then empty input + emailInputElement.val('').keyup(); + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(true); + expect(fieldState.valid).toBe(false); + + // Then valid input + emailInputElement.val('email@gitlab.com').keyup(); + expect(emailInputElement).not.toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(true); + }); + + it('should properly infer error messages', function() { + this.$form.submit(); + const trackedInputs = this.fieldErrors.state.inputs; + const inputHasTitle = trackedInputs[1]; + const hasTitleErrorElem = inputHasTitle.inputElement.siblings('.gl-field-error'); + const inputNoTitle = trackedInputs[2]; + const noTitleErrorElem = inputNoTitle.inputElement.siblings('.gl-field-error'); + + expect(noTitleErrorElem.text()).toBe('This field is required.'); + expect(hasTitleErrorElem.text()).toBe('Please provide a valid email address.'); + }); + + }); + +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 673c23dd7ebef7d6c370a0d0d5c024c1c042261c Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 13:26:37 +0200 Subject: Unbreak all the tests relying on one login-box. --- app/views/devise/sessions/new.html.haml | 2 +- app/views/devise/shared/_omniauth_box.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index dbdbc9689aa..2fb05b9456b 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -13,7 +13,7 @@ = render 'devise/shared/signup_box' - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? - .clearfix.omniauth-box + .clearfix = render 'devise/shared/omniauth_box' -# Show a message if none of the mechanisms above are enabled diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml index d5b6db48a29..8908b64cdac 100644 --- a/app/views/devise/shared/_omniauth_box.html.haml +++ b/app/views/devise/shared/_omniauth_box.html.haml @@ -1,4 +1,4 @@ -%div.login-box +%div.omniauth-container %p %span.light Sign in with   -- cgit v1.2.1 From 1fd09260826413da928363c3199d4dfbb770d2c3 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 15:47:21 +0200 Subject: Click first Sign In in login_helper. --- spec/support/login_helpers.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index 3e90c95918c..ea9edc85248 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -33,9 +33,7 @@ module LoginHelpers fill_in "user_login", with: user.email fill_in "user_password", with: "12345678" check 'user_remember_me' if remember - page.within '.login-box' do - click_button "Sign in" - end + first('.login-box').click_button('Sign in') Thread.current[:current_user] = user end -- cgit v1.2.1 From 445711675ca198660dcaee014cd4229b8eb266ab Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 17:13:42 +0200 Subject: Fix nesting on sessions/new. --- app/views/devise/sessions/new.html.haml | 15 +++++++-------- spec/support/login_helpers.rb | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 2fb05b9456b..fa8e7979461 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -12,12 +12,11 @@ - if signin_enabled? && signup_enabled? = render 'devise/shared/signup_box' - - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? - .clearfix - = render 'devise/shared/omniauth_box' - - -# Show a message if none of the mechanisms above are enabled - - if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) - %div - No authentication methods configured. + -# Show a message if none of the mechanisms above are enabled + - if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) + %div + No authentication methods configured. + - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? + .clearfix + = render 'devise/shared/omniauth_box' diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index ea9edc85248..c0b3e83244d 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -33,7 +33,7 @@ module LoginHelpers fill_in "user_login", with: user.email fill_in "user_password", with: "12345678" check 'user_remember_me' if remember - first('.login-box').click_button('Sign in') + click_button "Sign in" Thread.current[:current_user] = user end -- cgit v1.2.1 From c2766614ddc04b8df54fe8649d1dbe516f532987 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 29 Sep 2016 11:58:43 +0200 Subject: Fix syntax error -- missing comma in _new_crowd. --- app/views/devise/sessions/_new_crowd.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml index 5a192c63c7c..e82a08cdb0c 100644 --- a/app/views/devise/sessions/_new_crowd.html.haml +++ b/app/views/devise/sessions/_new_crowd.html.haml @@ -1,4 +1,4 @@ -= form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user' class: 'show-gl-field-errors') do += form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user', class: 'show-gl-field-errors') do .form-group = label_tag 'Username or email', for: :username = text_field_tag :username, nil, {class: "form-control top", title: "This field is required", autofocus: "autofocus", required: true } -- cgit v1.2.1 From 091f4cb26a79bf20542f5e260d461a235ec85011 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 29 Sep 2016 12:00:12 +0200 Subject: Update filled in field for two_factor auth to use id. --- spec/features/login_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb index 2523b4b7898..996f39ea06d 100644 --- a/spec/features/login_spec.rb +++ b/spec/features/login_spec.rb @@ -29,7 +29,7 @@ feature 'Login', feature: true do describe 'with two-factor authentication' do def enter_code(code) - fill_in 'Two-Factor Authentication code', with: code + fill_in 'user_otp_attempt', with: code click_button 'Verify code' end -- cgit v1.2.1 From 2486078d5b93aaaf5bb0f60e580f65fa3da0271a Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 30 Sep 2016 10:45:12 +0200 Subject: Prevent unneccessary loading of UsernameValidator. --- app/assets/javascripts/dispatcher.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index fb6e82cd37c..956e6085bfb 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -22,7 +22,6 @@ shortcut_handler = null; switch (page) { case 'sessions:new': - case 'sessions:create': new UsernameValidator(); break; case 'projects:boards:show': -- cgit v1.2.1 From cbd68e5bd10b8cc8b933a8bfffd446a433628ddc Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 30 Sep 2016 10:45:53 +0200 Subject: Remove superfluous comment. --- app/assets/javascripts/username_validator.js.es6 | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/username_validator.js.es6 b/app/assets/javascripts/username_validator.js.es6 index b19fb9b4771..2517f778365 100644 --- a/app/assets/javascripts/username_validator.js.es6 +++ b/app/assets/javascripts/username_validator.js.es6 @@ -95,7 +95,6 @@ } clearFieldValidationState() { - // TODO: Double check if this is valid chaining this.inputElement.siblings('p').hide(); this.inputElement.removeClass(invalidInputClass) -- cgit v1.2.1 From 80864a1939e495ca5e85ba3c0c3ea869d40abda4 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 5 Oct 2016 14:28:17 +0200 Subject: Safely scope siblings of validated input. --- app/assets/javascripts/gl_field_errors.js.es6 | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index 91c25047f7b..e54a10a1901 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -36,6 +36,19 @@ // hidden when injected into DOM this.inputElement.after(this.fieldErrorElement); this.inputElement.off('invalid').on('invalid', this.handleInvalidInput.bind(this)); + this.scopedSiblings = this.safelySelectSiblings(); + } + + safelySelectSiblings() { + // Apply `ignoreSelector` in markup to siblings whose visibility should not be toggled with input validity + const ignoreSelector = '.validation-ignore'; + const unignoredSiblings = this.inputElement.siblings(`p:not(${ignoreSelector})`); + const parentContainer = this.inputElement.parent('.form-group'); + + // Only select siblings when they're scoped within a form-group with one input + const safelyScoped = parentContainer.length && parentContainer.find('input').length === 1; + + return safelyScoped ? unignoredSiblings : this.fieldErrorElement; } renderValidity() { @@ -90,7 +103,7 @@ setInvalidState() { this.inputElement.addClass(inputErrorClass); - this.inputElement.siblings('p').hide(); + this.scopedSiblings.hide(); return this.fieldErrorElement.show(); } @@ -101,7 +114,7 @@ this.inputElement.val(trimmedInput); } this.inputElement.removeClass(inputErrorClass); - this.inputElement.siblings('p').hide(); + this.scopedSiblings.hide(); this.fieldErrorElement.hide(); } } -- cgit v1.2.1 From cdf232752a4c2bfc6ebb57bcca3b33bcf8755b40 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 5 Oct 2016 14:28:52 +0200 Subject: Add accessor for current val for convenience. --- app/assets/javascripts/gl_field_errors.js.es6 | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index e54a10a1901..86aea25fbbb 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -68,9 +68,13 @@ } + accessCurrentVal(newVal) { + return newVal ? this.inputElement.val(newVal) : this.inputElement.val(); + } + handleInvalidInput(event) { event.preventDefault(); - const currentValue = this.inputElement.val(); + const currentValue = this.accessCurrentVal(); this.state.valid = false; this.state.empty = currentValue === ''; @@ -87,7 +91,7 @@ } updateValidityState() { - const inputVal = this.inputElement.val(); + const inputVal = this.accessCurrentVal(); this.state.empty = !inputVal.length; this.state.valid = this.getInputValidity(); this.renderValidity(); @@ -108,10 +112,10 @@ } setClearState() { - const inputVal = this.inputElement.val(); + const inputVal = this.accessCurrentVal(); if (!inputVal.split(' ').length) { - const trimmedInput = this.inputElement.val().trim(); - this.inputElement.val(trimmedInput); + const trimmedInput = inputVal.trim(); + this.accessCurrentVal(trimmedInput); } this.inputElement.removeClass(inputErrorClass); this.scopedSiblings.hide(); -- cgit v1.2.1 From 349caec3088905cf4dc740b8809f9fd6fbdeeb0e Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 7 Oct 2016 11:35:23 +0200 Subject: Stringify username before passing to ActiveRecord. --- app/controllers/users_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 30f0118254a..7a2bd83f22f 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -86,7 +86,7 @@ class UsersController < ApplicationController end def exists - render json: { exists: !User.find_by_username(params[:username]).nil? } + render json: { exists: User.where(username: params[:username].to_s).any? } end private -- cgit v1.2.1 From 3c536bcc9d89e6d28d5a9bfb3ac8d1191ad03b88 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 7 Oct 2016 11:51:02 +0200 Subject: Improve method naming in gl_field_errors. --- app/assets/javascripts/gl_field_errors.js.es6 | 43 ++++++++++++++------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index 86aea25fbbb..bd8f3c52234 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -35,7 +35,7 @@ initFieldValidation() { // hidden when injected into DOM this.inputElement.after(this.fieldErrorElement); - this.inputElement.off('invalid').on('invalid', this.handleInvalidInput.bind(this)); + this.inputElement.off('invalid').on('invalid', this.handleInvalidSubmit.bind(this)); this.scopedSiblings = this.safelySelectSiblings(); } @@ -52,29 +52,25 @@ } renderValidity() { - this.setClearState(); + this.renderClear(); if (this.state.valid) { - return this.setValidState(); + return this.renderValid(); } if (this.state.empty) { - return this.setEmptyState(); + return this.renderEmpty(); } if (!this.state.valid) { - return this.setInvalidState(); + return this.renderInvalid(); } } - accessCurrentVal(newVal) { - return newVal ? this.inputElement.val(newVal) : this.inputElement.val(); - } - - handleInvalidInput(event) { + handleInvalidSubmit(event) { event.preventDefault(); - const currentValue = this.accessCurrentVal(); + const currentValue = this.accessCurrentValue(); this.state.valid = false; this.state.empty = currentValue === ''; @@ -86,36 +82,41 @@ } + /* Get or set current input value */ + accessCurrentValue(newVal) { + return newVal ? this.inputElement.val(newVal) : this.inputElement.val(); + } + getInputValidity() { return this.inputDomElement.validity.valid; } - updateValidityState() { - const inputVal = this.accessCurrentVal(); + updateValidity() { + const inputVal = this.accessCurrentValue(); this.state.empty = !inputVal.length; this.state.valid = this.getInputValidity(); this.renderValidity(); } - setValidState() { - return this.setClearState(); + renderValid() { + return this.renderClear(); } - setEmptyState() { - return this.setInvalidState(); + renderEmpty() { + return this.renderInvalid(); } - setInvalidState() { + renderInvalid() { this.inputElement.addClass(inputErrorClass); this.scopedSiblings.hide(); return this.fieldErrorElement.show(); } - setClearState() { - const inputVal = this.accessCurrentVal(); + renderClear() { + const inputVal = this.accessCurrentValue(); if (!inputVal.split(' ').length) { const trimmedInput = inputVal.trim(); - this.accessCurrentVal(trimmedInput); + this.accessCurrentValue(trimmedInput); } this.inputElement.removeClass(inputErrorClass); this.scopedSiblings.hide(); -- cgit v1.2.1 From 0f57245f0c81fe00ecedbb39c1e93fc48ef55099 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 7 Oct 2016 11:57:49 +0200 Subject: Use native dom in dispatcher field error init. --- app/assets/javascripts/dispatcher.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 956e6085bfb..846884ea793 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -296,9 +296,10 @@ }; Dispatcher.prototype.initFieldErrors = function() { - $('form.show-gl-field-errors').each(function(i, form) { - new gl.GlFieldErrors(form); - }); + return document.querySelectorAll('.show-gl-field-errors') + .forEach(function(form) { + new gl.GlFieldErrors(form); + }); }; return Dispatcher; -- cgit v1.2.1 From 80aa0a8f86a02e7b36a866906b902a3dfce325f3 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 7 Oct 2016 12:06:45 +0200 Subject: Revert conflict resolution in routes.rb. --- config/routes.rb | 792 ------------------------------------------------------- 1 file changed, 792 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 93d7f99fb90..83c3a42c19f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -83,798 +83,6 @@ Rails.application.routes.draw do draw :group draw :user draw :project - # - # Import - # - namespace :import do - resource :github, only: [:create, :new], controller: :github do - post :personal_access_token - get :status - get :callback - get :jobs - end - - resource :gitlab, only: [:create], controller: :gitlab do - get :status - get :callback - get :jobs - end - - resource :bitbucket, only: [:create], controller: :bitbucket do - get :status - get :callback - get :jobs - end - - resource :google_code, only: [:create, :new], controller: :google_code do - get :status - post :callback - get :jobs - - get :new_user_map, path: :user_map - post :create_user_map, path: :user_map - end - - resource :fogbugz, only: [:create, :new], controller: :fogbugz do - get :status - post :callback - get :jobs - - get :new_user_map, path: :user_map - post :create_user_map, path: :user_map - end - - resource :gitlab_project, only: [:create, :new] do - post :create - end - end - - # - # Uploads - # - - scope path: :uploads do - # Note attachments and User/Group/Project avatars - get ":model/:mounted_as/:id/:filename", - to: "uploads#show", - constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /[^\/]+/ } - - # Appearance - get ":model/:mounted_as/:id/:filename", - to: "uploads#show", - constraints: { model: /appearance/, mounted_as: /logo|header_logo/, filename: /.+/ } - - # Project markdown uploads - get ":namespace_id/:project_id/:secret/:filename", - to: "projects/uploads#show", - constraints: { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: /[^\/]+/ } - end - - # Redirect old note attachments path to new uploads path. - get "files/note/:id/:filename", - to: redirect("uploads/note/attachment/%{id}/%{filename}"), - constraints: { filename: /[^\/]+/ } - - # - # Explore area - # - namespace :explore do - resources :projects, only: [:index] do - collection do - get :trending - get :starred - end - end - - resources :groups, only: [:index] - resources :snippets, only: [:index] - root to: 'projects#trending' - end - - # Compatibility with old routing - get 'public' => 'explore/projects#index' - get 'public/projects' => 'explore/projects#index' - - # - # Admin Area - # - namespace :admin do - resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do - resources :keys, only: [:show, :destroy] - resources :identities, except: [:show] - - member do - get :projects - get :keys - get :groups - put :block - put :unblock - put :unlock - put :confirm - post :impersonate - patch :disable_two_factor - delete 'remove/:email_id', action: 'remove_email', as: 'remove_email' - end - end - - resource :impersonation, only: :destroy - - resources :abuse_reports, only: [:index, :destroy] - resources :spam_logs, only: [:index, :destroy] do - member do - post :mark_as_ham - end - end - - resources :applications - - resources :groups, constraints: { id: /[^\/]+/ } do - member do - put :members_update - end - end - - resources :deploy_keys, only: [:index, :new, :create, :destroy] - - resources :hooks, only: [:index, :create, :destroy] do - get :test - end - - resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] do - post :preview, on: :collection - end - - resource :logs, only: [:show] - resource :health_check, controller: 'health_check', only: [:show] - resource :background_jobs, controller: 'background_jobs', only: [:show] - resource :system_info, controller: 'system_info', only: [:show] - resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ } - - resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do - root to: 'projects#index', as: :projects - - resources(:projects, - path: '/', - constraints: { id: /[a-zA-Z.0-9_\-]+/ }, - only: [:index, :show]) do - root to: 'projects#show' - - member do - put :transfer - post :repository_check - end - - resources :runner_projects, only: [:create, :destroy] - end - end - - resource :appearances, only: [:show, :create, :update], path: 'appearance' do - member do - get :preview - delete :logo - delete :header_logos - end - end - - resource :application_settings, only: [:show, :update] do - resources :services, only: [:index, :edit, :update] - put :reset_runners_token - put :reset_health_check_token - put :clear_repository_check_states - end - - resources :labels - - resources :runners, only: [:index, :show, :update, :destroy] do - member do - get :resume - get :pause - end - end - - resources :builds, only: :index do - collection do - post :cancel_all - end - end - - root to: 'dashboard#index' - end - - # - # Profile Area - # - resource :profile, only: [:show, :update] do - member do - get :audit_log - get :applications, to: 'oauth/applications#index' - - put :reset_private_token - put :update_username - end - - scope module: :profiles do - resource :account, only: [:show] do - member do - delete :unlink - end - end - resource :notifications, only: [:show, :update] - resource :password, only: [:new, :create, :edit, :update] do - member do - put :reset - end - end - resource :preferences, only: [:show, :update] - resources :keys, only: [:index, :show, :new, :create, :destroy] - resources :emails, only: [:index, :create, :destroy] - resource :avatar, only: [:destroy] - - resources :personal_access_tokens, only: [:index, :create] do - member do - put :revoke - end - end - - resource :two_factor_auth, only: [:show, :create, :destroy] do - member do - post :create_u2f - post :codes - patch :skip - end - end - - resources :u2f_registrations, only: [:destroy] - end - end - - scope(path: 'u/:username', - as: :user, - constraints: { username: /[a-zA-Z.0-9_\-]+(? 'omniauth_callbacks#omniauth_error', as: :omniauth_error - get '/users/almost_there' => 'confirmations#almost_there' - end - - root to: "root#index" - - # - # Project Area - # - resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do - resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(? 'templates#show', as: :template - - scope do - get( - '/blob/*id/diff', - to: 'blob#diff', - constraints: { id: /.+/, format: false }, - as: :blob_diff - ) - get( - '/blob/*id', - to: 'blob#show', - constraints: { id: /.+/, format: false }, - as: :blob - ) - delete( - '/blob/*id', - to: 'blob#destroy', - constraints: { id: /.+/, format: false } - ) - put( - '/blob/*id', - to: 'blob#update', - constraints: { id: /.+/, format: false } - ) - post( - '/blob/*id', - to: 'blob#create', - constraints: { id: /.+/, format: false } - ) - end - - scope do - get( - '/raw/*id', - to: 'raw#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :raw - ) - end - - scope do - get( - '/tree/*id', - to: 'tree#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :tree - ) - end - - scope do - get( - '/find_file/*id', - to: 'find_file#show', - constraints: { id: /.+/, format: /html/ }, - as: :find_file - ) - end - - scope do - get( - '/files/*id', - to: 'find_file#list', - constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }, - as: :files - ) - end - - scope do - post( - '/create_dir/*id', - to: 'tree#create_dir', - constraints: { id: /.+/ }, - as: 'create_dir' - ) - end - - scope do - get( - '/blame/*id', - to: 'blame#show', - constraints: { id: /.+/, format: /(html|js)/ }, - as: :blame - ) - end - - scope do - get( - '/commits/*id', - to: 'commits#show', - constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }, - as: :commits - ) - end - - resource :avatar, only: [:show, :destroy] - resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do - member do - get :branches - get :builds - get :pipelines - post :cancel_builds - post :retry_builds - post :revert - post :cherry_pick - get :diff_for_path - end - end - - resources :compare, only: [:index, :create] do - collection do - get :diff_for_path - end - end - - get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ } - - # Don't use format parameter as file extension (old 3.0.x behavior) - # See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments - scope format: false do - resources :network, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } - - resources :graphs, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } do - member do - get :commits - get :ci - get :languages - end - end - end - - resources :snippets, concerns: :awardable, constraints: { id: /\d+/ } do - member do - get 'raw' - end - end - - WIKI_SLUG_ID = { id: /\S+/ } unless defined? WIKI_SLUG_ID - - scope do - # Order matters to give priority to these matches - get '/wikis/git_access', to: 'wikis#git_access' - get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages' - post '/wikis', to: 'wikis#create' - - get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID - get '/wikis/*id/edit', to: 'wikis#edit', as: 'wiki_edit', constraints: WIKI_SLUG_ID - - get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID - delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID - put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID - post '/wikis/*id/preview_markdown', to: 'wikis#preview_markdown', constraints: WIKI_SLUG_ID, as: 'wiki_preview_markdown' - end - - resource :repository, only: [:create] do - member do - get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex } - end - end - - resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do - member do - get :test - end - end - - resources :deploy_keys, constraints: { id: /\d+/ }, only: [:index, :new, :create] do - member do - put :enable - put :disable - end - end - - resources :forks, only: [:index, :new, :create] - resource :import, only: [:new, :create, :show] - - resources :refs, only: [] do - collection do - get 'switch' - end - - member do - # tree viewer logs - get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex } - # Directories with leading dots erroneously get rejected if git - # ref regex used in constraints. Regex verification now done in controller. - get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: { - id: /.*/, - path: /.*/ - } - end - end - - resources :merge_requests, concerns: :awardable, constraints: { id: /\d+/ } do - member do - get :commits - get :diffs - get :conflicts - get :builds - get :pipelines - get :merge_check - post :merge - post :cancel_merge_when_build_succeeds - get :ci_status - post :toggle_subscription - post :remove_wip - get :diff_for_path - post :resolve_conflicts - end - - collection do - get :branch_from - get :branch_to - get :update_branches - get :diff_for_path - post :bulk_update - end - - resources :discussions, only: [], constraints: { id: /\h{40}/ } do - member do - post :resolve - delete :resolve, action: :unresolve - end - end - end - - resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } - resources :tags, only: [:index, :show, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do - resource :release, only: [:edit, :update] - end - - resources :protected_branches, only: [:index, :show, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } - resources :variables, only: [:index, :show, :update, :create, :destroy] - resources :triggers, only: [:index, :create, :destroy] - - resources :pipelines, only: [:index, :new, :create, :show] do - collection do - resource :pipelines_settings, path: 'settings', only: [:show, :update] - end - - member do - post :cancel - post :retry - end - end - - resources :environments - - resource :cycle_analytics, only: [:show] - - resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do - collection do - post :cancel_all - - resources :artifacts, only: [] do - collection do - get :latest_succeeded, - path: '*ref_name_and_path', - format: false - end - end - end - - member do - get :status - post :cancel - post :retry - post :play - post :erase - get :trace - get :raw - end - - resource :artifacts, only: [] do - get :download - get :browse, path: 'browse(/*path)', format: false - get :file, path: 'file/*path', format: false - post :keep - end - end - - resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do - member do - get :test - end - end - - resources :container_registry, only: [:index, :destroy], constraints: { id: Gitlab::Regex.container_registry_reference_regex } - - resources :milestones, constraints: { id: /\d+/ } do - member do - put :sort_issues - put :sort_merge_requests - end - end - - resources :labels, except: [:show], constraints: { id: /\d+/ } do - collection do - post :generate - post :set_priorities - end - - member do - post :toggle_subscription - delete :remove_priority - end - end - - resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do - member do - post :toggle_subscription - post :mark_as_spam - get :referenced_merge_requests - get :related_branches - get :can_create_branch - end - collection do - post :bulk_update - end - end - - resources :project_members, except: [:show, :new, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }, concerns: :access_requestable do - collection do - delete :leave - - # Used for import team - # from another project - get :import - post :apply_import - end - - member do - post :resend_invite - end - end - - resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ } - - resources :notes, only: [:index, :create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do - member do - delete :delete_attachment - post :resolve - delete :resolve, action: :unresolve - end - end - - resource :board, only: [:show] do - scope module: :boards do - resources :issues, only: [:update] - - resources :lists, only: [:index, :create, :update, :destroy] do - collection do - post :generate - end - - resources :issues, only: [:index] - end - end - end - - resources :todos, only: [:create] - - resources :uploads, only: [:create] do - collection do - get ":secret/:filename", action: :show, as: :show, constraints: { filename: /[^\/]+/ } - end - end - - resources :runners, only: [:index, :edit, :update, :destroy, :show] do - member do - get :resume - get :pause - end - - collection do - post :toggle_shared_runners - end - end - - resources :runner_projects, only: [:create, :destroy] - resources :badges, only: [:index] do - collection do - scope '*ref', constraints: { ref: Gitlab::Regex.git_reference_regex } do - constraints format: /svg/ do - get :build - get :coverage - end - end - end - end - end - end - end # Get all keys of user get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ } -- cgit v1.2.1 From bad1feb23c63a86f8f4103e4b75ec590fc90da4f Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 7 Oct 2016 21:45:55 +0200 Subject: Convert field error NodeList to an Array. --- app/assets/javascripts/dispatcher.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 846884ea793..6452ae675b4 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -296,8 +296,8 @@ }; Dispatcher.prototype.initFieldErrors = function() { - return document.querySelectorAll('.show-gl-field-errors') - .forEach(function(form) { + var flaggedForms = document.querySelectorAll('.show-gl-field-errors'); + return [...taggedForms].forEach(function(form) { new gl.GlFieldErrors(form); }); }; -- cgit v1.2.1 From f141cdb3dddd16c729a828838e907473132a3a18 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 7 Oct 2016 21:50:35 +0200 Subject: Fixup invalid refs. --- app/assets/javascripts/dispatcher.js | 2 +- app/assets/javascripts/gl_field_errors.js.es6 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 6452ae675b4..abc077a404e 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -297,7 +297,7 @@ Dispatcher.prototype.initFieldErrors = function() { var flaggedForms = document.querySelectorAll('.show-gl-field-errors'); - return [...taggedForms].forEach(function(form) { + return [...flaggedForms].forEach(function(form) { new gl.GlFieldErrors(form); }); }; diff --git a/app/assets/javascripts/gl_field_errors.js.es6 b/app/assets/javascripts/gl_field_errors.js.es6 index bd8f3c52234..8657e7b4abf 100644 --- a/app/assets/javascripts/gl_field_errors.js.es6 +++ b/app/assets/javascripts/gl_field_errors.js.es6 @@ -78,7 +78,7 @@ this.form.focusOnFirstInvalid.apply(this.form); // For UX, wait til after first invalid submission to check each keyup this.inputElement.off('keyup.field_validator') - .on('keyup.field_validator', this.updateValidityState.bind(this)); + .on('keyup.field_validator', this.updateValidity.bind(this)); } -- cgit v1.2.1 From 23fd1f1630f4977ecc452ede086eaebfd836b978 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Mon, 10 Oct 2016 16:34:57 +0200 Subject: Use Ruby 1.9 syntax in tab_single def and usage. --- app/views/admin/appearances/preview.html.haml | 2 +- app/views/devise/confirmations/new.html.haml | 2 +- app/views/devise/passwords/edit.html.haml | 2 +- app/views/devise/passwords/new.html.haml | 2 +- app/views/devise/sessions/two_factor.html.haml | 2 +- app/views/devise/shared/_tab_single.html.haml | 3 +-- app/views/devise/unlocks/new.html.haml | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/views/admin/appearances/preview.html.haml b/app/views/admin/appearances/preview.html.haml index 0d35702c634..acbe17036f7 100644 --- a/app/views/admin/appearances/preview.html.haml +++ b/app/views/admin/appearances/preview.html.haml @@ -1,4 +1,4 @@ -= render 'devise/shared/tab_single', { :tab_title => 'Sign in preview' } += render 'devise/shared/tab_single', tab_title: 'Sign in preview' .login-box %form.show-gl-field-errors .form-group diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml index 443a316c6e2..5d25dd398d6 100644 --- a/app/views/devise/confirmations/new.html.haml +++ b/app/views/devise/confirmations/new.html.haml @@ -1,4 +1,4 @@ -= render 'devise/shared/tab_single', { :tab_title => 'Resend confirmation instructions' } += render 'devise/shared/tab_single', tab_title: 'Resend confirmation instructions' .login-box .login-body = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f| diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml index 9c533ef9916..b518fae7c95 100644 --- a/app/views/devise/passwords/edit.html.haml +++ b/app/views/devise/passwords/edit.html.haml @@ -1,4 +1,4 @@ -= render 'devise/shared/tab_single', { :tab_title => 'Change your password' } += render 'devise/shared/tab_single', tab_title:'Change your password' .login-box .login-body = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: 'show-gl-field-errors' }) do |f| diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml index 91b46a12ac0..1fcfd06419a 100644 --- a/app/views/devise/passwords/new.html.haml +++ b/app/views/devise/passwords/new.html.haml @@ -1,4 +1,4 @@ -= render 'devise/shared/tab_single', { :tab_title => 'Reset Password' } += render 'devise/shared/tab_single', tab_title: 'Reset Password' .login-box .login-body = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f| diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml index 56074c057d7..0e865b807c1 100644 --- a/app/views/devise/sessions/two_factor.html.haml +++ b/app/views/devise/sessions/two_factor.html.haml @@ -3,7 +3,7 @@ = page_specific_javascript_tag('u2f.js') %div - = render 'devise/shared/tab_single', { :tab_title => 'Two-Factor Authentication' } + = render 'devise/shared/tab_single', tab_title: 'Two-Factor Authentication' .login-box .login-body - if @user.two_factor_otp_enabled? diff --git a/app/views/devise/shared/_tab_single.html.haml b/app/views/devise/shared/_tab_single.html.haml index 8590c43d54d..f943d25e41a 100644 --- a/app/views/devise/shared/_tab_single.html.haml +++ b/app/views/devise/shared/_tab_single.html.haml @@ -1,4 +1,3 @@ -// = render 'devise/shared/tab_single', :tab_title => 'Tab Title' %ul.nav-links.nav-tabs.new-session-tabs.single-tab %li.active - = link_to tab_title, '#', disabled: true + %a= tab_title diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml index 0036f3b98e5..49b2f77111f 100644 --- a/app/views/devise/unlocks/new.html.haml +++ b/app/views/devise/unlocks/new.html.haml @@ -1,4 +1,4 @@ -= render 'devise/shared/tab_single', { :tab_title => 'Resend unlock instructions' } += render 'devise/shared/tab_single', tab_title: 'Resend unlock instructions' .login-box .login-body = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, class: 'show-gl-field-errors' }) do |f| -- cgit v1.2.1 From 85db5ba847ffc8f4b71ad9fe0ba22ab42f90b3e4 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Mon, 10 Oct 2016 16:35:27 +0200 Subject: Clean up layouts/devise.html. --- app/views/layouts/devise.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index 825e540cb0c..6922f1e153f 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -1,7 +1,7 @@ !!! 5 %html{ lang: "en", class: "devise-layout-html"} = render "layouts/head" - %body{ class: "ui_charcoal login-page application navless", data: {page: body_data_page}} + %body.ui_charcoal.login-page.application.navless{ data: { page: body_data_page }} .page-wrap = Gon::Base.render_data = render "layouts/header/empty" @@ -22,7 +22,7 @@ %h3 Open source software to collaborate on code %p - Manage git repositories with fine grained access controls that keep your code secure. + Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki. -- cgit v1.2.1 From 5439bd9f952c7e7ee9fa10613655a9761396e1f9 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Mon, 10 Oct 2016 16:54:55 +0200 Subject: Attempt to fix username validation ruby. --- app/controllers/users_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 7a2bd83f22f..1aa22995692 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -86,7 +86,7 @@ class UsersController < ApplicationController end def exists - render json: { exists: User.where(username: params[:username].to_s).any? } + render json: { exists: !Namespace.where(name: params[:username]).nil? } end private -- cgit v1.2.1 From 568a405ce43834d5b4da3ff81f1e8a6972db802b Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Tue, 11 Oct 2016 18:28:00 +0200 Subject: Add exists to users routes and fix endpoint. --- app/controllers/users_controller.rb | 2 +- config/routes/user.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1aa22995692..6a881b271d7 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -86,7 +86,7 @@ class UsersController < ApplicationController end def exists - render json: { exists: !Namespace.where(name: params[:username]).nil? } + render json: { exists: Namespace.where(path: params[:username].downcase).any? } end private diff --git a/config/routes/user.rb b/config/routes/user.rb index 54bbcb18f6a..dfb5d2a2ba4 100644 --- a/config/routes/user.rb +++ b/config/routes/user.rb @@ -33,5 +33,6 @@ scope(path: 'u/:username', get :projects get :contributed, as: :contributed_projects get :snippets + get :exists get '/', to: redirect('/%{username}') end -- cgit v1.2.1 From eb866dfe05c82b2a45da69d924bcbe15b151a054 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 12 Oct 2016 18:34:38 +0200 Subject: Convert dispatcher to es6. --- app/assets/javascripts/dispatcher.js | 309 ------------------------------- app/assets/javascripts/dispatcher.js.es6 | 309 +++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+), 309 deletions(-) delete mode 100644 app/assets/javascripts/dispatcher.js create mode 100644 app/assets/javascripts/dispatcher.js.es6 diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js deleted file mode 100644 index abc077a404e..00000000000 --- a/app/assets/javascripts/dispatcher.js +++ /dev/null @@ -1,309 +0,0 @@ -(function() { - var Dispatcher; - - $(function() { - return new Dispatcher(); - }); - - Dispatcher = (function() { - function Dispatcher() { - this.initSearch(); - this.initFieldErrors(); - this.initPageScripts(); - } - - Dispatcher.prototype.initPageScripts = function() { - var page, path, shortcut_handler; - page = $('body').attr('data-page'); - if (!page) { - return false; - } - path = page.split(':'); - shortcut_handler = null; - switch (page) { - case 'sessions:new': - new UsernameValidator(); - break; - case 'projects:boards:show': - case 'projects:boards:index': - shortcut_handler = new ShortcutsNavigation(); - break; - case 'projects:merge_requests:index': - case 'projects:issues:index': - Issuable.init(); - new gl.IssuableBulkActions(); - shortcut_handler = new ShortcutsNavigation(); - break; - case 'projects:issues:show': - new Issue(); - shortcut_handler = new ShortcutsIssuable(); - new ZenMode(); - break; - case 'projects:milestones:show': - case 'groups:milestones:show': - case 'dashboard:milestones:show': - new Milestone(); - break; - case 'dashboard:todos:index': - new gl.Todos(); - break; - case 'projects:milestones:new': - case 'projects:milestones:edit': - new ZenMode(); - new DueDateSelect(); - new GLForm($('.milestone-form')); - break; - case 'groups:milestones:new': - new ZenMode(); - break; - case 'projects:compare:show': - new Diff(); - break; - case 'projects:issues:new': - case 'projects:issues:edit': - shortcut_handler = new ShortcutsNavigation(); - new GLForm($('.issue-form')); - new IssuableForm($('.issue-form')); - new LabelsSelect(); - new MilestoneSelect(); - new gl.IssuableTemplateSelectors(); - break; - case 'projects:merge_requests:new': - case 'projects:merge_requests:edit': - new Diff(); - shortcut_handler = new ShortcutsNavigation(); - new GLForm($('.merge-request-form')); - new IssuableForm($('.merge-request-form')); - new LabelsSelect(); - new MilestoneSelect(); - new gl.IssuableTemplateSelectors(); - break; - case 'projects:tags:new': - new ZenMode(); - new GLForm($('.tag-form')); - break; - case 'projects:releases:edit': - new ZenMode(); - new GLForm($('.release-form')); - break; - case 'projects:merge_requests:show': - new Diff(); - shortcut_handler = new ShortcutsIssuable(true); - new ZenMode(); - new MergedButtons(); - break; - case 'projects:merge_requests:commits': - case 'projects:merge_requests:builds': - new MergedButtons(); - break; - case "projects:merge_requests:diffs": - new Diff(); - new ZenMode(); - new MergedButtons(); - break; - case "projects:merge_requests:conflicts": - window.mcui = new MergeConflictResolver() - break; - case 'projects:merge_requests:index': - shortcut_handler = new ShortcutsNavigation(); - Issuable.init(); - break; - case 'dashboard:activity': - new Activities(); - break; - case 'dashboard:projects:starred': - new Activities(); - break; - case 'projects:commit:show': - new Commit(); - new Diff(); - new ZenMode(); - shortcut_handler = new ShortcutsNavigation(); - break; - case 'projects:commits:show': - case 'projects:activity': - shortcut_handler = new ShortcutsNavigation(); - break; - case 'projects:show': - shortcut_handler = new ShortcutsNavigation(); - new NotificationsForm(); - if ($('#tree-slider').length) { - new TreeView(); - } - break; - case 'projects:pipelines:show': - new gl.Pipelines(); - break; - case 'groups:activity': - new Activities(); - break; - case 'groups:show': - shortcut_handler = new ShortcutsNavigation(); - new NotificationsForm(); - new NotificationsDropdown(); - break; - case 'groups:group_members:index': - new gl.MemberExpirationDate(); - new gl.Members(); - new UsersSelect(); - break; - case 'projects:project_members:index': - new gl.MemberExpirationDate(); - new gl.Members(); - new UsersSelect(); - break; - case 'groups:new': - case 'groups:edit': - case 'admin:groups:edit': - case 'admin:groups:new': - new GroupAvatar(); - break; - case 'projects:tree:show': - shortcut_handler = new ShortcutsNavigation(); - new TreeView(); - break; - case 'projects:find_file:show': - shortcut_handler = true; - break; - case 'projects:blob:show': - case 'projects:blame:show': - new LineHighlighter(); - shortcut_handler = new ShortcutsNavigation(); - new ShortcutsBlob(true); - break; - case 'projects:labels:new': - case 'projects:labels:edit': - new Labels(); - break; - case 'projects:labels:index': - if ($('.prioritized-labels').length) { - new gl.LabelManager(); - } - break; - case 'projects:network:show': - // Ensure we don't create a particular shortcut handler here. This is - // already created, where the network graph is created. - shortcut_handler = true; - break; - case 'projects:forks:new': - new ProjectFork(); - break; - case 'projects:artifacts:browse': - new BuildArtifacts(); - break; - case 'projects:group_links:index': - new gl.MemberExpirationDate(); - new GroupsSelect(); - break; - case 'search:show': - new Search(); - break; - case 'projects:protected_branches:index': - new gl.ProtectedBranchCreate(); - new gl.ProtectedBranchEditList(); - break; - case 'projects:cycle_analytics:show': - new gl.CycleAnalytics(); - break; - } - switch (path.first()) { - case 'admin': - new Admin(); - switch (path[1]) { - case 'groups': - new UsersSelect(); - break; - case 'projects': - new NamespaceSelects(); - break; - case 'labels': - switch (path[2]) { - case 'new': - case 'edit': - new Labels(); - } - case 'abuse_reports': - new gl.AbuseReports(); - break; - } - break; - case 'dashboard': - case 'root': - shortcut_handler = new ShortcutsDashboardNavigation(); - break; - case 'profiles': - new NotificationsForm(); - new NotificationsDropdown(); - break; - case 'projects': - new Project(); - new ProjectAvatar(); - switch (path[1]) { - case 'compare': - new CompareAutocomplete(); - break; - case 'edit': - shortcut_handler = new ShortcutsNavigation(); - new ProjectNew(); - break; - case 'new': - new ProjectNew(); - break; - case 'show': - new Star(); - new ProjectNew(); - new ProjectShow(); - new NotificationsDropdown(); - break; - case 'wikis': - new Wikis(); - shortcut_handler = new ShortcutsNavigation(); - new ZenMode(); - new GLForm($('.wiki-form')); - break; - case 'snippets': - shortcut_handler = new ShortcutsNavigation(); - if (path[2] === 'show') { - new ZenMode(); - } - break; - case 'labels': - case 'graphs': - case 'compare': - case 'pipelines': - case 'forks': - case 'milestones': - case 'project_members': - case 'deploy_keys': - case 'builds': - case 'hooks': - case 'services': - case 'protected_branches': - shortcut_handler = new ShortcutsNavigation(); - } - } - // If we haven't installed a custom shortcut handler, install the default one - if (!shortcut_handler) { - return new Shortcuts(); - } - }; - - Dispatcher.prototype.initSearch = function() { - // Only when search form is present - if ($('.search').length) { - return new gl.SearchAutocomplete(); - } - }; - - Dispatcher.prototype.initFieldErrors = function() { - var flaggedForms = document.querySelectorAll('.show-gl-field-errors'); - return [...flaggedForms].forEach(function(form) { - new gl.GlFieldErrors(form); - }); - }; - - return Dispatcher; - - })(); - -}).call(this); diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 new file mode 100644 index 00000000000..abc077a404e --- /dev/null +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -0,0 +1,309 @@ +(function() { + var Dispatcher; + + $(function() { + return new Dispatcher(); + }); + + Dispatcher = (function() { + function Dispatcher() { + this.initSearch(); + this.initFieldErrors(); + this.initPageScripts(); + } + + Dispatcher.prototype.initPageScripts = function() { + var page, path, shortcut_handler; + page = $('body').attr('data-page'); + if (!page) { + return false; + } + path = page.split(':'); + shortcut_handler = null; + switch (page) { + case 'sessions:new': + new UsernameValidator(); + break; + case 'projects:boards:show': + case 'projects:boards:index': + shortcut_handler = new ShortcutsNavigation(); + break; + case 'projects:merge_requests:index': + case 'projects:issues:index': + Issuable.init(); + new gl.IssuableBulkActions(); + shortcut_handler = new ShortcutsNavigation(); + break; + case 'projects:issues:show': + new Issue(); + shortcut_handler = new ShortcutsIssuable(); + new ZenMode(); + break; + case 'projects:milestones:show': + case 'groups:milestones:show': + case 'dashboard:milestones:show': + new Milestone(); + break; + case 'dashboard:todos:index': + new gl.Todos(); + break; + case 'projects:milestones:new': + case 'projects:milestones:edit': + new ZenMode(); + new DueDateSelect(); + new GLForm($('.milestone-form')); + break; + case 'groups:milestones:new': + new ZenMode(); + break; + case 'projects:compare:show': + new Diff(); + break; + case 'projects:issues:new': + case 'projects:issues:edit': + shortcut_handler = new ShortcutsNavigation(); + new GLForm($('.issue-form')); + new IssuableForm($('.issue-form')); + new LabelsSelect(); + new MilestoneSelect(); + new gl.IssuableTemplateSelectors(); + break; + case 'projects:merge_requests:new': + case 'projects:merge_requests:edit': + new Diff(); + shortcut_handler = new ShortcutsNavigation(); + new GLForm($('.merge-request-form')); + new IssuableForm($('.merge-request-form')); + new LabelsSelect(); + new MilestoneSelect(); + new gl.IssuableTemplateSelectors(); + break; + case 'projects:tags:new': + new ZenMode(); + new GLForm($('.tag-form')); + break; + case 'projects:releases:edit': + new ZenMode(); + new GLForm($('.release-form')); + break; + case 'projects:merge_requests:show': + new Diff(); + shortcut_handler = new ShortcutsIssuable(true); + new ZenMode(); + new MergedButtons(); + break; + case 'projects:merge_requests:commits': + case 'projects:merge_requests:builds': + new MergedButtons(); + break; + case "projects:merge_requests:diffs": + new Diff(); + new ZenMode(); + new MergedButtons(); + break; + case "projects:merge_requests:conflicts": + window.mcui = new MergeConflictResolver() + break; + case 'projects:merge_requests:index': + shortcut_handler = new ShortcutsNavigation(); + Issuable.init(); + break; + case 'dashboard:activity': + new Activities(); + break; + case 'dashboard:projects:starred': + new Activities(); + break; + case 'projects:commit:show': + new Commit(); + new Diff(); + new ZenMode(); + shortcut_handler = new ShortcutsNavigation(); + break; + case 'projects:commits:show': + case 'projects:activity': + shortcut_handler = new ShortcutsNavigation(); + break; + case 'projects:show': + shortcut_handler = new ShortcutsNavigation(); + new NotificationsForm(); + if ($('#tree-slider').length) { + new TreeView(); + } + break; + case 'projects:pipelines:show': + new gl.Pipelines(); + break; + case 'groups:activity': + new Activities(); + break; + case 'groups:show': + shortcut_handler = new ShortcutsNavigation(); + new NotificationsForm(); + new NotificationsDropdown(); + break; + case 'groups:group_members:index': + new gl.MemberExpirationDate(); + new gl.Members(); + new UsersSelect(); + break; + case 'projects:project_members:index': + new gl.MemberExpirationDate(); + new gl.Members(); + new UsersSelect(); + break; + case 'groups:new': + case 'groups:edit': + case 'admin:groups:edit': + case 'admin:groups:new': + new GroupAvatar(); + break; + case 'projects:tree:show': + shortcut_handler = new ShortcutsNavigation(); + new TreeView(); + break; + case 'projects:find_file:show': + shortcut_handler = true; + break; + case 'projects:blob:show': + case 'projects:blame:show': + new LineHighlighter(); + shortcut_handler = new ShortcutsNavigation(); + new ShortcutsBlob(true); + break; + case 'projects:labels:new': + case 'projects:labels:edit': + new Labels(); + break; + case 'projects:labels:index': + if ($('.prioritized-labels').length) { + new gl.LabelManager(); + } + break; + case 'projects:network:show': + // Ensure we don't create a particular shortcut handler here. This is + // already created, where the network graph is created. + shortcut_handler = true; + break; + case 'projects:forks:new': + new ProjectFork(); + break; + case 'projects:artifacts:browse': + new BuildArtifacts(); + break; + case 'projects:group_links:index': + new gl.MemberExpirationDate(); + new GroupsSelect(); + break; + case 'search:show': + new Search(); + break; + case 'projects:protected_branches:index': + new gl.ProtectedBranchCreate(); + new gl.ProtectedBranchEditList(); + break; + case 'projects:cycle_analytics:show': + new gl.CycleAnalytics(); + break; + } + switch (path.first()) { + case 'admin': + new Admin(); + switch (path[1]) { + case 'groups': + new UsersSelect(); + break; + case 'projects': + new NamespaceSelects(); + break; + case 'labels': + switch (path[2]) { + case 'new': + case 'edit': + new Labels(); + } + case 'abuse_reports': + new gl.AbuseReports(); + break; + } + break; + case 'dashboard': + case 'root': + shortcut_handler = new ShortcutsDashboardNavigation(); + break; + case 'profiles': + new NotificationsForm(); + new NotificationsDropdown(); + break; + case 'projects': + new Project(); + new ProjectAvatar(); + switch (path[1]) { + case 'compare': + new CompareAutocomplete(); + break; + case 'edit': + shortcut_handler = new ShortcutsNavigation(); + new ProjectNew(); + break; + case 'new': + new ProjectNew(); + break; + case 'show': + new Star(); + new ProjectNew(); + new ProjectShow(); + new NotificationsDropdown(); + break; + case 'wikis': + new Wikis(); + shortcut_handler = new ShortcutsNavigation(); + new ZenMode(); + new GLForm($('.wiki-form')); + break; + case 'snippets': + shortcut_handler = new ShortcutsNavigation(); + if (path[2] === 'show') { + new ZenMode(); + } + break; + case 'labels': + case 'graphs': + case 'compare': + case 'pipelines': + case 'forks': + case 'milestones': + case 'project_members': + case 'deploy_keys': + case 'builds': + case 'hooks': + case 'services': + case 'protected_branches': + shortcut_handler = new ShortcutsNavigation(); + } + } + // If we haven't installed a custom shortcut handler, install the default one + if (!shortcut_handler) { + return new Shortcuts(); + } + }; + + Dispatcher.prototype.initSearch = function() { + // Only when search form is present + if ($('.search').length) { + return new gl.SearchAutocomplete(); + } + }; + + Dispatcher.prototype.initFieldErrors = function() { + var flaggedForms = document.querySelectorAll('.show-gl-field-errors'); + return [...flaggedForms].forEach(function(form) { + new gl.GlFieldErrors(form); + }); + }; + + return Dispatcher; + + })(); + +}).call(this); -- cgit v1.2.1 From 716406bc71fc3866588ccca8c132060d4f33e53e Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 12 Oct 2016 18:47:31 +0200 Subject: Back off the array spreading, bc poltergeist freaks out. --- app/assets/javascripts/dispatcher.js.es6 | 7 +++---- spec/features/merge_requests/user_uses_slash_commands_spec.rb | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js.es6 b/app/assets/javascripts/dispatcher.js.es6 index abc077a404e..f3957ed374b 100644 --- a/app/assets/javascripts/dispatcher.js.es6 +++ b/app/assets/javascripts/dispatcher.js.es6 @@ -296,10 +296,9 @@ }; Dispatcher.prototype.initFieldErrors = function() { - var flaggedForms = document.querySelectorAll('.show-gl-field-errors'); - return [...flaggedForms].forEach(function(form) { - new gl.GlFieldErrors(form); - }); + $('.show-gl-field-errors').each((i, form) => { + new gl.GlFieldErrors(form); + }); }; return Dispatcher; diff --git a/spec/features/merge_requests/user_uses_slash_commands_spec.rb b/spec/features/merge_requests/user_uses_slash_commands_spec.rb index cb3cea3fd51..7b8af555f0e 100644 --- a/spec/features/merge_requests/user_uses_slash_commands_spec.rb +++ b/spec/features/merge_requests/user_uses_slash_commands_spec.rb @@ -20,7 +20,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do login_with(user) visit namespace_project_merge_request_path(project.namespace, project, merge_request) end - + after do wait_for_ajax end @@ -34,7 +34,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do expect(page).to have_content 'Your commands have been executed!' expect(merge_request.reload.work_in_progress?).to eq true - end + end it 'removes the WIP: prefix from the title' do merge_request.title = merge_request.wip_title @@ -45,7 +45,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do expect(page).to have_content 'Your commands have been executed!' expect(merge_request.reload.work_in_progress?).to eq false - end + end end context 'when the current user cannot toggle the WIP prefix' do -- cgit v1.2.1 From 75962a2ddd320fa03fc18d04861b42342c91a978 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 13 Oct 2016 17:50:35 +0200 Subject: Clean up stray Sign up ref. --- app/views/projects/notes/_notes_with_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index 8352eba7446..00b62a595ff 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -14,7 +14,7 @@ .disabled-comment.text-center .disabled-comment-text.inline Please - = link_to "sign up", new_session_path(:user, redirect_to_referer: 'yes') + = link_to "register", new_session_path(:user, redirect_to_referer: 'yes') or = link_to "sign in", new_session_path(:user, redirect_to_referer: 'yes') to post a comment -- cgit v1.2.1 From b46307d3c59e3cf24eef3a2411ea8af2f25e78ba Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 13 Oct 2016 17:59:55 +0200 Subject: Don't use member properties in users_spec, and remove loading ref. --- spec/features/users_spec.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 17a555e4673..ec4c4d62f53 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -61,20 +61,17 @@ feature 'Users', feature: true, js: true do before(:each) do visit new_user_session_path click_link 'Register' - @username_form_group = find '.username' - @username_field = find '#new_user_username' end - scenario 'shows an error border if the username already exists' do fill_in username_input, with: user.username wait_for_ajax - expect(@username_form_group).to have_css '.gl-field-error-outline' + expect(find('.username')).to have_css '.gl-field-error-outline' end scenario 'doesn\'t show an error border if the username is available' do fill_in username_input, with: 'new-user' wait_for_ajax - expect(@username_field).not_to have_css '.gl-field-error-outline' + expect(find('#new_user_username')).not_to have_css '.gl-field-error-outline' end end -- cgit v1.2.1 From 391e109c813542d5f32953088e91a6ea82dfdcfc Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Sat, 15 Oct 2016 09:05:37 +0200 Subject: Revert "Improve tabbing usability for sign in page" This reverts commit 8751491b8db471dc661daa19bc82a9dbd58e4aae. --- app/assets/stylesheets/pages/login.scss | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index f1d15417705..e210dc4c0b8 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -52,16 +52,6 @@ margin: 0 0 10px; } - .new_user { - position: relative; - padding-bottom: 35px; - } - - .sign-in { - position: absolute; - bottom: 0; - } - .login-footer { margin-top: 10px; -- cgit v1.2.1 From 54c0286a3f7306f8e5bfbbbf321cd098e4fc6e11 Mon Sep 17 00:00:00 2001 From: De Wet Blomerus Date: Fri, 14 Oct 2016 21:03:27 +0200 Subject: remove ashley since she no longer works here --- doc/development/doc_styleguide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md index 0b725cf200c..975ff9a4612 100644 --- a/doc/development/doc_styleguide.md +++ b/doc/development/doc_styleguide.md @@ -96,7 +96,7 @@ merge request. - When introducing a new document, be careful for the headings to be grammatically and syntactically correct. It is advised to mention one or all of the following GitLab members for a review: `@axil`, `@rspeicher`, - `@dblessing`, `@ashleys`. This is to ensure that no document + `@dblessing`. This is to ensure that no document with wrong heading is going live without an audit, thus preventing dead links and redirection issues when corrected - Leave exactly one newline after a heading -- cgit v1.2.1 From 5a8738a7b43ae567829bca36db6f13f430b56c83 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 15 Oct 2016 14:49:20 -0700 Subject: Fix Spinach merge request diff failures gitlab-git-test `master` was updated in ff076d88, and this caused the merge request diffs to change in a way that broke assumptions in the Spinach tests. Partial fix to #23378 --- features/steps/project/merge_requests.rb | 7 ++++--- spec/support/test_env.rb | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index 4a67cf06fba..b0c33aa6f2f 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -114,7 +114,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps source_project: project, target_project: project, source_branch: 'fix', - target_branch: 'master', + target_branch: 'merge-test', author: project.users.first, description: "# Description header" ) @@ -137,7 +137,8 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps title: "Bug NS-05", source_project: project, target_project: project, - author: project.users.first) + author: project.users.first, + source_branch: 'merge-test') end step 'project "Shop" have "Feature NS-05" merged merge request' do @@ -508,7 +509,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps step 'I should see new target branch changes' do expect(page).to have_content 'Request to merge fix into feature' - expect(page).to have_content 'Target branch changed from master to feature' + expect(page).to have_content 'Target branch changed from merge-test to feature' end step 'I click on "Email Patches"' do diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index d56274d0979..ad8ae763f6d 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -17,6 +17,7 @@ module TestEnv 'markdown' => '0ed8c6c', 'lfs' => 'be93687', 'master' => 'b83d6e3', + 'merge-test' => '5937ac0', "'test'" => 'e56497b', 'orphaned-branch' => '45127a9', 'binary-encoding' => '7b1cf43', -- cgit v1.2.1 From fa25f61d474849a7a1ac893af9896b3227c33404 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 15 Oct 2016 20:31:40 -0700 Subject: Fix Hash syntax to work for both Ruby 2.1 and 2.3 --- app/views/devise/shared/_tabs_normal.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml index 48abd6519d6..79b1d447a92 100644 --- a/app/views/devise/shared/_tabs_normal.html.haml +++ b/app/views/devise/shared/_tabs_normal.html.haml @@ -1,5 +1,5 @@ %ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist'} %li.active{ role: 'presentation' } - %a{ href: '#login-pane', data: {'toggle':'tab'}, role: 'tab'} Sign in + %a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab'} Sign in %li{ role: 'presentation'} - %a{ href: '#register-pane', data: {'toggle':'tab'}, role: 'tab'} Register + %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab'} Register -- cgit v1.2.1 From 4cea4d25270f604fb4b9335442657168b294e633 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 15 Oct 2016 20:40:25 -0700 Subject: Fix broken SCSS linter errors due to missing newlines --- app/assets/stylesheets/pages/login.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index e210dc4c0b8..4c0c0839fe2 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -40,6 +40,7 @@ p { font-size: 13px; } + .login-box, .omniauth-container { box-shadow: 0 0 0 1px $border-color; border-bottom-right-radius: 2px; @@ -118,6 +119,7 @@ margin: 0; } } + .new-session-tabs { display: -webkit-flex; display: flex; @@ -140,6 +142,7 @@ a { width: 100%; font-size: 18px; + &:hover { border: 1px solid transparent; } -- cgit v1.2.1 From 5174b7ad7e4b90761467388a29fa016d77e7a16d Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Sun, 16 Oct 2016 11:35:51 +0200 Subject: Add the tech writers usernames in the doc_sytleguide doc [ci skip] --- doc/development/doc_styleguide.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md index 0b725cf200c..47ebcebc770 100644 --- a/doc/development/doc_styleguide.md +++ b/doc/development/doc_styleguide.md @@ -95,10 +95,10 @@ merge request. someone in the Merge Request - When introducing a new document, be careful for the headings to be grammatically and syntactically correct. It is advised to mention one or all - of the following GitLab members for a review: `@axil`, `@rspeicher`, - `@dblessing`, `@ashleys`. This is to ensure that no document - with wrong heading is going live without an audit, thus preventing dead links - and redirection issues when corrected + of the following GitLab members for a review: `@axil`, `@rspeicher`, `@marcia`, + `@SeanPackham`. This is to ensure that no document with wrong heading is going + live without an audit, thus preventing dead links and redirection issues when + corrected - Leave exactly one newline after a heading ## Links -- cgit v1.2.1 From c48f7153181eab0d872d84b1c00e83cec5f2f046 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 16 Oct 2016 12:49:23 +0300 Subject: Fix 404 when group path has dot in the name Signed-off-by: Dmitriy Zaporozhets --- config/routes/group.rb | 5 ++++- spec/routing/routing_spec.rb | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config/routes/group.rb b/config/routes/group.rb index 33143f0dfa2..06b464d79c8 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -1,7 +1,10 @@ require 'constraints/group_url_constrainer' constraints(GroupUrlConstrainer.new) do - scope(path: ':id', as: :group, controller: :groups) do + scope(path: ':id', + as: :group, + constraints: { id: /[a-zA-Z.0-9_\-]+(? Date: Sun, 16 Oct 2016 15:03:44 +0300 Subject: Fix 500 error when creating mileston from group page Signed-off-by: Dmitriy Zaporozhets --- app/views/layouts/_init_auto_complete.html.haml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml index 67ff4b272b9..e138ebab018 100644 --- a/app/views/layouts/_init_auto_complete.html.haml +++ b/app/views/layouts/_init_auto_complete.html.haml @@ -1,7 +1,8 @@ - project = @target_project || @project - noteable_type = @noteable.class if @noteable.present? -:javascript - GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_type, type_id: params[:id])}" - GitLab.GfmAutoComplete.cachedData = undefined; - GitLab.GfmAutoComplete.setup(); +- if project + :javascript + GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_namespace_project_path(project.namespace, project, type: noteable_type, type_id: params[:id])}" + GitLab.GfmAutoComplete.cachedData = undefined; + GitLab.GfmAutoComplete.setup(); -- cgit v1.2.1 From b1b197ae5e42c7f9a645f249bff28235bdba4c80 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 16 Oct 2016 20:03:07 +0300 Subject: Wait for ajax call in merge request unsubscribe test Signed-off-by: Dmitriy Zaporozhets --- features/steps/project/merge_requests.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index b0c33aa6f2f..de065dffbc2 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -7,6 +7,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps include SharedMarkdown include SharedDiffNote include SharedUser + include WaitForAjax step 'I click link "New Merge Request"' do click_link "New Merge Request" @@ -90,6 +91,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps step 'I click button "Unsubscribe"' do click_on "Unsubscribe" + wait_for_ajax end step 'I click link "Close"' do -- cgit v1.2.1 From 9e30b75e9c5ab91de955b6212df825f5e85c0e57 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 16 Oct 2016 20:40:52 +0300 Subject: Fix merge requests feature tests Signed-off-by: Dmitriy Zaporozhets --- features/steps/shared/note.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index 3d7c6ef9d2d..d3b5b0bdebe 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -1,5 +1,8 @@ +require Rails.root.join('features/support/wait_for_ajax') + module SharedNote include Spinach::DSL + include WaitForAjax step 'I delete a comment' do page.within('.main-notes-list') do @@ -116,8 +119,9 @@ module SharedNote page.within(".js-main-target-form") do fill_in "note[note]", with: "# Comment with a header" click_button "Comment" - sleep 0.05 end + + wait_for_ajax end step 'The comment with the header should not have an ID' do -- cgit v1.2.1 From cd6af26de21b1d321306f69f5e0311d19e7c6b28 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 16 Oct 2016 20:49:05 +0300 Subject: Fix active tab test for branches page Signed-off-by: Dmitriy Zaporozhets --- features/steps/project/active_tab.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/active_tab.rb b/features/steps/project/active_tab.rb index 80043463188..58225032859 100644 --- a/features/steps/project/active_tab.rb +++ b/features/steps/project/active_tab.rb @@ -54,7 +54,7 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps end step 'I click the "Branches" tab' do - page.within '.content' do + page.within '.sub-nav' do click_link('Branches') end end -- cgit v1.2.1 From 9f7a7115a4c7b90e0203516f5aabf913ce02cbfe Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 16 Oct 2016 20:29:45 +0200 Subject: Convert CHANGELOG to Markdown All this does is convert the version sections into headers. The list items shouldn't really be indented by two spaces, but it makes no difference to the rendering and this way we retain authorship history for the actual changes. Related to https://gitlab.com/gitlab-org/release-tools/merge_requests/29 --- .gitattributes | 2 +- CHANGELOG | 2335 ---------------------------------------- CHANGELOG.md | 2465 +++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 2 +- doc/workflow/gitlab_flow.md | 2 +- scripts/lint-doc.sh | 6 +- 6 files changed, 2471 insertions(+), 2341 deletions(-) delete mode 100644 CHANGELOG create mode 100644 CHANGELOG.md diff --git a/.gitattributes b/.gitattributes index 17cbaa5eef5..ab791a4cd6c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ -CHANGELOG merge=union +CHANGELOG.md merge=union *.js.es6 gitlab-language=javascript diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index e3201cd2250..00000000000 --- a/CHANGELOG +++ /dev/null @@ -1,2335 +0,0 @@ -Please view this file on the master branch, on stable branches it's out of date. - -v 8.13.0 (unreleased) - - Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675) - - Respond with 404 Not Found for non-existent tags (Linus Thiel) - - Truncate long labels with ellipsis in labels page - - Improve tabbing usability for sign in page (ClemMakesApps) - - Enforce TrailingSemicolon and EmptyLineBetweenBlocks in scss-lint - - Adding members no longer silently fails when there is extra whitespace - - Update runner version only when updating contacted_at - - Add link from system note to compare with previous version - - Use gitlab-shell v3.6.6 - - Add `/projects/visible` API endpoint (Ben Boeckel) - - Fix centering of custom header logos (Ashley Dumaine) - - ExpireBuildArtifactsWorker query builds table without ordering enqueuing one job per build to cleanup - - Add an example for testing a phoenix application with Gitlab CI in the docs (Manthan Mallikarjun) - - Updating verbiage on git basics to be more intuitive - - Clarify documentation for Runners API (Gennady Trafimenkov) - - The instrumentation for Banzai::Renderer has been restored - - Change user & group landing page routing from /u/:username to /:username - - Prevent running GfmAutocomplete setup for each diff note !6569 - - Added documentation for .gitattributes files - - AbstractReferenceFilter caches project_refs on RequestStore when active - - Replaced the check sign to arrow in the show build view. !6501 - - Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar) - - Fix Error 500 when viewing old merge requests with bad diff data - - Create a new /templates namespace for the /licenses, /gitignores and /gitlab_ci_ymls API endpoints. !5717 (tbalthazar) - - Speed-up group milestones show page - - Fix inconsistent options dropdown caret on mobile viewports (ClemMakesApps) - - Extract project#update_merge_requests and SystemHooks to its own worker from GitPushService - - Don't include archived projects when creating group milestones. !4940 (Jeroen Jacobs) - - Add tag shortcut from the Commit page. !6543 - - Keep refs for each deployment - - Allow browsing branches that end with '.atom' - - Log LDAP lookup errors and don't swallow unrelated exceptions. !6103 (Markus Koller) - - Replace unique keyframes mixin with keyframe mixin with specific names (ClemMakesApps) - - Add more tests for calendar contribution (ClemMakesApps) - - Update Gitlab Shell to fix some problems with moving projects between storages - - Cache rendered markdown in the database, rather than Redis - - Avoid database queries on Banzai::ReferenceParser::BaseParser for nodes without references - - Do not alter 'force_remove_source_branch' options on MergeRequest unless specified - - Simplify Mentionable concern instance methods - - API: Ability to retrieve version information (Robert Schilling) - - Fix permission for setting an issue's due date - - API: Multi-file commit !6096 (mahcsig) - - Unicode emoji are now converted to images - - Revert "Label list shows all issues (opened or closed) with that label" - - Expose expires_at field when sharing project on API - - Fix VueJS template tags being rendered in code comments - - Added copy file path button to merge request diff files - - Fix issue with page scrolling to top when closing or pinning sidebar (lukehowell) - - Add Issue Board API support (andrebsguedes) - - Allow the Koding integration to be configured through the API - - Add new issue button to each list on Issues Board - - Added soft wrap button to repository file/blob editor - - Update namespace validation to forbid reserved names (.git and .atom) (Will Starms) - - Show the time ago a merge request was deployed to an environment - - Add word-wrap to issue title on issue and milestone boards (ClemMakesApps) - - Fix todos page mobile viewport layout (ClemMakesApps) - - Fix inconsistent highlighting of already selected activity nav-links (ClemMakesApps) - - Remove redundant mixins (ClemMakesApps) - - Added 'Download' button to the Snippets page (Justin DiPierro) - - Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison) - - Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska) - - Fix that manual jobs would no longer block jobs in the next stage. !6604 - - Add configurable email subject suffix (Fu Xu) - - Use defined colour for a language when available !6748 (nilsding) - - Added tooltip to fork count on project show page. (Justin DiPierro) - - Use a ConnectionPool for Rails.cache on Sidekiq servers - - Replace `alias_method_chain` with `Module#prepend` - - Enable GitLab Import/Export for non-admin users. - - Preserve label filters when sorting !6136 (Joseph Frazier) - - MergeRequest#new form load diff asynchronously - - Only update issuable labels if they have been changed - - Take filters in account in issuable counters. !6496 - - Use custom Ruby images to test builds (registry.dev.gitlab.org/gitlab/gitlab-build-images:*) - - Prevent flash alert text from being obscured when container is fluid - - Append issue template to existing description !6149 (Joseph Frazier) - - Trending projects now only show public projects and the list of projects is cached for a day - - Memoize Gitlab Shell's secret token (!6599, Justin DiPierro) - - Revoke button in Applications Settings underlines on hover. - - Use higher size on Gitlab::Redis connection pool on Sidekiq servers - - Add missing values to linter !6276 (Katarzyna Kobierska Ula Budziszewska) - - Fix Long commit messages overflow viewport in file tree - - Revert avoid touching file system on Build#artifacts? - - Stop using a Redis lease when updating the project activity timestamp whenever a new event is created - - Add disabled delete button to protected branches (ClemMakesApps) - - Add broadcast messages and alerts below sub-nav - - Better empty state for Groups view - - API: New /users/:id/events endpoint - - Update ruby-prof to 0.16.2. !6026 (Elan Ruusamäe) - - Replace bootstrap caret with fontawesome caret (ClemMakesApps) - - Fix unnecessary escaping of reserved HTML characters in milestone title. !6533 - - Add organization field to user profile - - Ignore deployment for statistics in Cycle Analytics, except in staging and production stages - - Fix enter key when navigating search site search dropdown. !6643 (Brennan Roberts) - - Fix deploy status responsiveness error !6633 - - Make searching for commits case insensitive - - Fix resolved discussion display in side-by-side diff view !6575 - - Optimize GitHub importing for speed and memory - - API: expose pipeline data in builds API (!6502, Guilherme Salazar) - - Notify the Merger about merge after successful build (Dimitris Karakasilis) - - Reorder issue and merge request titles to show IDs first. !6503 (Greg Laubenstein) - - Reduce queries needed to find users using their SSH keys when pushing commits - - Prevent rendering the link to all when the author has no access (Katarzyna Kobierska Ula Budziszewska) - - Fix broken repository 500 errors in project list - - Fix Pipeline list commit column width should be adjusted - - Close todos when accepting merge requests via the API !6486 (tonygambone) - - Ability to batch assign issues relating to a merge request to the author. !5725 (jamedjo) - - Changed Slack service user referencing from full name to username (Sebastian Poxhofer) - - Retouch environments list and deployments list - - Add multiple command support for all label related slash commands !6780 (barthc) - - Add Container Registry on/off status to Admin Area !6638 (the-undefined) - - Allow empty merge requests !6384 (Artem Sidorenko) - - Grouped pipeline dropdown is a scrollable container - - Cleanup Ci::ApplicationController. !6757 (Takuya Noguchi) - - Fixes padding in all clipboard icons that have .btn class - - Fix a typo in doc/api/labels.md - - API: all unknown routing will be handled with 404 Not Found - - Add docs for request profiling - - Make guests unable to view MRs on private projects - -v 8.12.7 - - Use gitlab-markup gem instead of github-markup to fix `.rst` file rendering. !6659 - - Fix GFM autocomplete setup being called several times - -v 8.12.6 - - Update mailroom to 0.8.1 in Gemfile.lock !6814 - -v 8.12.5 - - Switch from request to env in ::API::Helpers. !6615 - - Update the mail_room gem to 0.8.1 to fix a race condition with the mailbox watching thread. !6714 - - Improve issue load time performance by avoiding ORDER BY in find_by call. !6724 - - Add a new gitlab:users:clear_all_authentication_tokens task. !6745 - - Don't send Private-Token (API authentication) headers to Sentry - - Share projects via the API only with groups the authenticated user can access - -v 8.12.4 - - Fix "Copy to clipboard" tooltip to say "Copied!" when clipboard button is clicked. !6294 (lukehowell) - - Fix padding in build sidebar. !6506 - - Changed compare dropdowns to dropdowns with isolated search input. !6550 - - Fix race condition on LFS Token. !6592 - - Fix type mismatch bug when closing Jira issue. !6619 - - Fix lint-doc error. !6623 - - Skip wiki creation when GitHub project has wiki enabled. !6665 - - Fix issues importing services via Import/Export. !6667 - - Restrict failed login attempts for users with 2FA enabled. !6668 - - Fix failed project deletion when feature visibility set to private. !6688 - - Prevent claiming associated model IDs via import. - - Set GitLab project exported file permissions to owner only - - Improve the way merge request versions are compared with each other - -v 8.12.3 - - Update Gitlab Shell to support low IO priority for storage moves - -v 8.12.2 - - Fix Import/Export not recognising correctly the imported services. - - Fix snippets pagination - - Fix "Create project" button layout when visibility options are restricted - - Fix List-Unsubscribe header in emails - - Fix IssuesController#show degradation including project on loaded notes - - Fix an issue with the "Commits" section of the cycle analytics summary. !6513 - - Fix errors importing project feature and milestone models using GitLab project import - - Make JWT messages Docker-compatible - - Fix duplicate branch entry in the merge request version compare dropdown - - Respect the fork_project permission when forking projects - - Only update issuable labels if they have been changed - - Fix bug where 'Search results' repeated many times when a search in the emoji search form is cleared (Xavier Bick) (@zeiv) - - Fix resolve discussion buttons endpoint path - - Refactor remnants of CoffeeScript destructured opts and super !6261 - -v 8.12.1 - - Fix a memory leak in HTML::Pipeline::SanitizationFilter::WHITELIST - - Fix issue with search filter labels not displaying - -v 8.12.0 - - Removes inconsistency regarding tagging immediatelly as merged once you create a new branch. !6408 - - Update the rouge gem to 2.0.6, which adds highlighting support for JSX, Prometheus, and others. !6251 - - Only check :can_resolve permission if the note is resolvable - - Bump fog-aws to v0.11.0 to support ap-south-1 region - - Add ability to fork to a specific namespace using API. (ritave) - - Allow to set request_access_enabled for groups and projects - - Cleanup misalignments in Issue list view !6206 - - Only create a protected branch upon a push to a new branch if a rule for that branch doesn't exist - - Add Pipelines for Commit - - Prune events older than 12 months. (ritave) - - Prepend blank line to `Closes` message on merge request linked to issue (lukehowell) - - Fix issues/merge-request templates dropdown for forked projects - - Filter tags by name !6121 - - Update gitlab shell secret file also when it is empty. !3774 (glensc) - - Give project selection dropdowns responsive width, make non-wrapping. - - Fix note form hint showing slash commands supported for commits. - - Make push events have equal vertical spacing. - - API: Ensure invitees are not returned in Members API. - - Preserve applied filters on issues search. - - Add two-factor recovery endpoint to internal API !5510 - - Pass the "Remember me" value to the U2F authentication form - - Display stages in valid order in stages dropdown on build page - - Only update projects.last_activity_at once per hour when creating a new event - - Cycle analytics (first iteration) !5986 - - Remove vendor prefixes for linear-gradient CSS (ClemMakesApps) - - Move pushes_since_gc from the database to Redis - - Limit number of shown environments on Merge Request: show only environments for target_branch, source_branch and tags - - Add font color contrast to external label in admin area (ClemMakesApps) - - Fix find file navigation links (ClemMakesApps) - - Change logo animation to CSS (ClemMakesApps) - - Instructions for enabling Git packfile bitmaps !6104 - - Use Search::GlobalService.new in the `GET /projects/search/:query` endpoint - - Fix long comments in diffs messing with table width - - Add spec covering 'Gitlab::Git::committer_hash' !6433 (dandunckelman) - - Fix pagination on user snippets page - - Honor "fixed layout" preference in more places !6422 - - Run CI builds with the permissions of users !5735 - - Fix sorting of issues in API - - Fix download artifacts button links !6407 - - Sort project variables by key. !6275 (Diego Souza) - - Ensure specs on sorting of issues in API are deterministic on MySQL - - Added ability to use predefined CI variables for environment name - - Added ability to specify URL in environment configuration in gitlab-ci.yml - - Escape search term before passing it to Regexp.new !6241 (winniehell) - - Fix pinned sidebar behavior in smaller viewports !6169 - - Fix file permissions change when updating a file on the Gitlab UI !5979 - - Added horizontal padding on build page sidebar on code coverage block. !6196 (Vitaly Baev) - - Change merge_error column from string to text type - - Fix issue with search filter labels not displaying - - Reduce contributions calendar data payload (ClemMakesApps) - - Show all pipelines for merge requests even from discarded commits !6414 - - Replace contributions calendar timezone payload with dates (ClemMakesApps) - - Changed MR widget build status to pipeline status !6335 - - Add `web_url` field to issue, merge request, and snippet API objects (Ben Boeckel) - - Enable pipeline events by default !6278 - - Move parsing of sidekiq ps into helper !6245 (pascalbetz) - - Added go to issue boards keyboard shortcut - - Expose `sha` and `merge_commit_sha` in merge request API (Ben Boeckel) - - Emoji can be awarded on Snippets !4456 - - Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling) - - Fix blame table layout width - - Spec testing if issue authors can read issues on private projects - - Fix bug where pagination is still displayed despite all todos marked as done (ClemMakesApps) - - Request only the LDAP attributes we need !6187 - - Center build stage columns in pipeline overview (ClemMakesApps) - - Fix bug with tooltip not hiding on discussion toggle button - - Rename behaviour to behavior in bug issue template for consistency (ClemMakesApps) - - Fix bug stopping issue description being scrollable after selecting issue template - - Remove suggested colors hover underline (ClemMakesApps) - - Fix jump to discussion button being displayed on commit notes - - Shorten task status phrase (ClemMakesApps) - - Fix project visibility level fields on settings - - Add hover color to emoji icon (ClemMakesApps) - - Increase ci_builds artifacts_size column to 8-byte integer to allow larger files - - Add textarea autoresize after comment (ClemMakesApps) - - Do not write SSH public key 'comments' to authorized_keys !6381 - - Add due date to issue todos - - Refresh todos count cache when an Issue/MR is deleted - - Fix branches page dropdown sort alignment (ClemMakesApps) - - Hides merge request button on branches page is user doesn't have permissions - - Add white background for no readme container (ClemMakesApps) - - API: Expose issue confidentiality flag. (Robert Schilling) - - Fix markdown anchor icon interaction (ClemMakesApps) - - Test migration paths from 8.5 until current release !4874 - - Replace animateEmoji timeout with eventListener (ClemMakesApps) - - Show badges in Milestone tabs. !5946 (Dan Rowden) - - Optimistic locking for Issues and Merge Requests (title and description overriding prevention) - - Require confirmation when not logged in for unsubscribe links !6223 (Maximiliano Perez Coto) - - Add `wiki_page_events` to project hook APIs (Ben Boeckel) - - Remove Gitorious import - - Loads GFM autocomplete source only when required - - Fix issue with slash commands not loading on new issue page - - Fix inconsistent background color for filter input field (ClemMakesApps) - - Remove prefixes from transition CSS property (ClemMakesApps) - - Add Sentry logging to API calls - - Add BroadcastMessage API - - Merge request tabs are fixed when scrolling page - - Use 'git update-ref' for safer web commits !6130 - - Sort pipelines requested through the API - - Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling) - - Fix issue boards loading on large screens - - Change pipeline duration to be jobs running time instead of simple wall time from start to end !6084 - - Show queued time when showing a pipeline !6084 - - Remove unused mixins (ClemMakesApps) - - Fix issue board label filtering appending already filtered labels - - Add search to all issue board lists - - Scroll active tab into view on mobile - - Fix groups sort dropdown alignment (ClemMakesApps) - - Add horizontal scrolling to all sub-navs on mobile viewports (ClemMakesApps) - - Use JavaScript tooltips for mentions !5301 (winniehell) - - Add hover state to todos !5361 (winniehell) - - Fix icon alignment of star and fork buttons !5451 (winniehell) - - Fix alignment of icon buttons !5887 (winniehell) - - Added Ubuntu 16.04 support for packager.io (JonTheNiceGuy) - - Fix markdown help references (ClemMakesApps) - - Add last commit time to repo view (ClemMakesApps) - - Fix accessibility and visibility of project list dropdown button !6140 - - Fix missing flash messages on service edit page (airatshigapov) - - Added project-specific enable/disable setting for LFS !5997 - - Added group-specific enable/disable setting for LFS !6164 - - Add optional 'author' param when making commits. !5822 (dandunckelman) - - Don't expose a user's token in the `/api/v3/user` API (!6047) - - Remove redundant js-timeago-pending from user activity log (ClemMakesApps) - - Ability to manage project issues, snippets, wiki, merge requests and builds access level - - Remove inconsistent font weight for sidebar's labels (ClemMakesApps) - - Align add button on repository view (ClemMakesApps) - - Fix contributions calendar month label truncation (ClemMakesApps) - - Import release note descriptions from GitHub (EspadaV8) - - Added tests for diff notes - - Add pipeline events to Slack integration !5525 - - Add a button to download latest successful artifacts for branches and tags !5142 - - Remove redundant pipeline tooltips (ClemMakesApps) - - Expire commit info views after one day, instead of two weeks, to allow for user email updates - - Add delimiter to project stars and forks count (ClemMakesApps) - - Fix badge count alignment (ClemMakesApps) - - Remove green outline from `New branch unavailable` button on issue page !5858 (winniehell) - - Fix repo title alignment (ClemMakesApps) - - Change update interval of contacted_at - - Add LFS support to SSH !6043 - - Fix branch title trailing space on hover (ClemMakesApps) - - Don't include 'Created By' tag line when importing from GitHub if there is a linked GitLab account (EspadaV8) - - Award emoji tooltips containing more than 10 usernames are now truncated !4780 (jlogandavison) - - Fix duplicate "me" in award emoji tooltip !5218 (jlogandavison) - - Order award emoji tooltips in order they were added (EspadaV8) - - Fix spacing and vertical alignment on build status icon on commits page (ClemMakesApps) - - Update merge_requests.md with a simpler way to check out a merge request. !5944 - - Fix button missing type (ClemMakesApps) - - Gitlab::Checks is now instrumented - - Move to project dropdown with infinite scroll for better performance - - Fix leaking of submit buttons outside the width of a main container !18731 (originally by @pavelloz) - - Load branches asynchronously in Cherry Pick and Revert dialogs. - - Convert datetime coffeescript spec to ES6 (ClemMakesApps) - - Add merge request versions !5467 - - Change using size to use count and caching it for number of group members. !5935 - - Replace play icon font with svg (ClemMakesApps) - - Added 'only_allow_merge_if_build_succeeds' project setting in the API. !5930 (Duck) - - Reduce number of database queries on builds tab - - Wrap text in commit message containers - - Capitalize mentioned issue timeline notes (ClemMakesApps) - - Fix inconsistent checkbox alignment (ClemMakesApps) - - Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger) - - Adds response mime type to transaction metric action when it's not HTML - - Fix hover leading space bug in pipeline graph !5980 - - Avoid conflict with admin labels when importing GitHub labels - - User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496 - - Fix repository page ui issues - - Avoid protected branches checks when verifying access without branch name - - Add information about user and manual build start to runner as variables !6201 (Sergey Gnuskov) - - Fixed invisible scroll controls on build page on iPhone - - Fix error on raw build trace download for old builds stored in database !4822 - - Refactor the triggers page and documentation !6217 - - Show values of CI trigger variables only when clicked (Katarzyna Kobierska Ula Budziszewska) - - Use default clone protocol on "check out, review, and merge locally" help page URL - - Let the user choose a namespace and name on GitHub imports - - API for Ci Lint !5953 (Katarzyna Kobierska Urszula Budziszewska) - - Allow bulk update merge requests from merge requests index page - - Ensure validation messages are shown within the milestone form - - Add notification_settings API calls !5632 (mahcsig) - - Remove duplication between project builds and admin builds view !5680 (Katarzyna Kobierska Ula Budziszewska) - - Fix URLs with anchors in wiki !6300 (houqp) - - Deleting source project with existing fork link will close all related merge requests !6177 (Katarzyna Kobierska Ula Budziszeska) - - Return 204 instead of 404 for /ci/api/v1/builds/register.json if no builds are scheduled for a runner !6225 - - Fix Gitlab::Popen.popen thread-safety issue - - Add specs to removing project (Katarzyna Kobierska Ula Budziszewska) - - Clean environment variables when running git hooks - - Fix Import/Export issues importing protected branches and some specific models - - Fix non-master branch readme display in tree view - - Add UX improvements for merge request version diffs - -v 8.11.9 - - Don't send Private-Token (API authentication) headers to Sentry - - Share projects via the API only with groups the authenticated user can access - -v 8.11.8 - - Respect the fork_project permission when forking projects - - Set a restrictive CORS policy on the API for credentialed requests - - API: disable rails session auth for non-GET/HEAD requests - - Escape HTML nodes in builds commands in CI linter - -v 8.11.7 - - Avoid conflict with admin labels when importing GitHub labels. !6158 - - Restores `fieldName` to allow only string values in `gl_dropdown.js`. !6234 - - Allow the Rails cookie to be used for API authentication. - - Login/Register UX upgrade !6328 - -v 8.11.6 - - Fix unnecessary horizontal scroll area in pipeline visualizations. !6005 - - Make merge conflict file size limit 200 KB, to match the docs. !6052 - - Fix an error where we were unable to create a CommitStatus for running state. !6107 - - Optimize discussion notes resolving and unresolving. !6141 - - Fix GitLab import button. !6167 - - Restore SSH Key title auto-population behavior. !6186 - - Fix DB schema to match latest migration. !6256 - - Exclude some pending or inactivated rows in Member scopes. - -v 8.11.5 - - Optimize branch lookups and force a repository reload for Repository#find_branch. !6087 - - Fix member expiration date picker after update. !6184 - - Fix suggested colors options for new labels in the admin area. !6138 - - Optimize discussion notes resolving and unresolving - - Fix GitLab import button - - Fix confidential issues being exposed as public using gitlab.com export - - Remove gitorious from import_sources. !6180 - - Scope webhooks/services that will run for confidential issues - - Remove gitorious from import_sources - - Fix confidential issues being exposed as public using gitlab.com export - - Use oj gem for faster JSON processing - -v 8.11.4 - - Fix resolving conflicts on forks. !6082 - - Fix diff commenting on merge requests created prior to 8.10. !6029 - - Fix pipelines tab layout regression. !5952 - - Fix "Wiki" link not appearing in navigation for projects with external wiki. !6057 - - Do not enforce using hash with hidden key in CI configuration. !6079 - - Fix hover leading space bug in pipeline graph !5980 - - Fix sorting issues by "last updated" doesn't work after import from GitHub - - GitHub importer use default project visibility for non-private projects - - Creating an issue through our API now emails label subscribers !5720 - - Block concurrent updates for Pipeline - - Don't create groups for unallowed users when importing projects - - Fix issue boards leak private label names and descriptions - - Fix broken gitlab:backup:restore because of bad permissions on repo storage !6098 (Dirk Hörner) - - Remove gitorious. !5866 - - Allow compare merge request versions - -v 8.11.3 - - Allow system info page to handle case where info is unavailable - - Label list shows all issues (opened or closed) with that label - - Don't show resolve conflicts link before MR status is updated - - Fix IE11 fork button bug !5982 - - Don't prevent viewing the MR when git refs for conflicts can't be found on disk - - Fix external issue tracker "Issues" link leading to 404s - - Don't try to show merge conflict resolution info if a merge conflict contains non-UTF-8 characters - - Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling) - - Issues filters reset button - -v 8.11.2 - - Show "Create Merge Request" widget for push events to fork projects on the source project. !5978 - - Use gitlab-workhorse 0.7.11 !5983 - - Does not halt the GitHub import process when an error occurs. !5763 - - Fix file links on project page when default view is Files !5933 - - Fixed enter key in search input not working !5888 - -v 8.11.1 - - Pulled due to packaging error. - -v 8.11.0 - - Use test coverage value from the latest successful pipeline in badge. !5862 - - Add test coverage report badge. !5708 - - Remove the http_parser.rb dependency by removing the tinder gem. !5758 (tbalthazar) - - Add Koding (online IDE) integration - - Ability to specify branches for Pivotal Tracker integration (Egor Lynko) - - Fix don't pass a local variable called `i` to a partial. !20510 (herminiotorres) - - Fix rename `add_users_into_project` and `projects_ids`. !20512 (herminiotorres) - - Fix adding line comments on the initial commit to a repo !5900 - - Fix the title of the toggle dropdown button. !5515 (herminiotorres) - - Rename `markdown_preview` routes to `preview_markdown`. (Christopher Bartz) - - Update to Ruby 2.3.1. !4948 - - Add Issues Board !5548 - - Allow resolving merge conflicts in the UI !5479 - - Improve diff performance by eliminating redundant checks for text blobs - - Ensure that branch names containing escapable characters (e.g. %20) aren't unescaped indiscriminately. !5770 (ewiltshi) - - Convert switch icon into icon font (ClemMakesApps) - - API: Endpoints for enabling and disabling deploy keys - - API: List access requests, request access, approve, and deny access requests to a project or a group. !4833 - - Use long options for curl examples in documentation !5703 (winniehell) - - Added tooltip listing label names to the labels value in the collapsed issuable sidebar - - Remove magic comments (`# encoding: UTF-8`) from Ruby files. !5456 (winniehell) - - GitLab Performance Monitoring can now track custom events such as the number of tags pushed to a repository - - Add support for relative links starting with ./ or / to RelativeLinkFilter (winniehell) - - Allow naming U2F devices !5833 - - Ignore URLs starting with // in Markdown links !5677 (winniehell) - - Fix CI status icon link underline (ClemMakesApps) - - The Repository class is now instrumented - - Fix commit mention font inconsistency (ClemMakesApps) - - Do not escape URI when extracting path !5878 (winniehell) - - Fix filter label tooltip HTML rendering (ClemMakesApps) - - Cache the commit author in RequestStore to avoid extra lookups in PostReceive - - Expand commit message width in repo view (ClemMakesApps) - - Cache highlighted diff lines for merge requests - - Pre-create all builds for a Pipeline when the new Pipeline is created !5295 - - Allow merge request diff notes and discussions to be explicitly marked as resolved - - API: Add deployment endpoints - - API: Add Play endpoint on Builds - - Fix of 'Commits being passed to custom hooks are already reachable when using the UI' - - Show wall clock time when showing a pipeline. !5734 - - Show member roles to all users on members page - - Project.visible_to_user is instrumented again - - Fix awardable button mutuality loading spinners (ClemMakesApps) - - Sort todos by date and priority - - Add support for using RequestStore within Sidekiq tasks via SIDEKIQ_REQUEST_STORE env variable - - Optimize maximum user access level lookup in loading of notes - - Send notification emails to users newly mentioned in issue and MR edits !5800 - - Add "No one can push" as an option for protected branches. !5081 - - Improve performance of AutolinkFilter#text_parse by using XPath - - Add experimental Redis Sentinel support !1877 - - Rendering of SVGs as blobs is now limited to SVGs with a size smaller or equal to 2MB - - Fix branches page dropdown sort initial state (ClemMakesApps) - - Environments have an url to link to - - Various redundant database indexes have been removed - - Update `timeago` plugin to use multiple string/locale settings - - Remove unused images (ClemMakesApps) - - Get issue and merge request description templates from repositories - - Enforce 2FA restrictions on API authentication endpoints !5820 - - Limit git rev-list output count to one in forced push check - - Show deployment status on merge requests with external URLs - - Clean up unused routes (Josef Strzibny) - - Fix issue on empty project to allow developers to only push to protected branches if given permission - - API: Add enpoints for pipelines - - Add green outline to New Branch button. !5447 (winniehell) - - Optimize generating of cache keys for issues and notes - - Fix repository push email formatting in Outlook - - Improve performance of syntax highlighting Markdown code blocks - - Update to gitlab_git 10.4.1 and take advantage of preserved Ref objects - - Remove delay when hitting "Reply..." button on page with a lot of discussions - - Retrieve rendered HTML from cache in one request - - Fix renaming repository when name contains invalid chararacters under project settings - - Upgrade Grape from 0.13.0 to 0.15.0. !4601 - - Trigram indexes for the "ci_runners" table have been removed to speed up UPDATE queries - - Fix devise deprecation warnings. - - Check for 2FA when using Git over HTTP and only allow PersonalAccessTokens as password in that case !5764 - - Update version_sorter and use new interface for faster tag sorting - - Optimize checking if a user has read access to a list of issues !5370 - - Store all DB secrets in secrets.yml, under descriptive names !5274 - - Fix syntax highlighting in file editor - - Support slash commands in issue and merge request descriptions as well as comments. !5021 - - Nokogiri's various parsing methods are now instrumented - - Add archived badge to project list !5798 - - Add simple identifier to public SSH keys (muteor) - - Admin page now references docs instead of a specific file !5600 (AnAverageHuman) - - Fix filter input alignment (ClemMakesApps) - - Include old revision in merge request update hooks (Ben Boeckel) - - Add build event color in HipChat messages (David Eisner) - - Make fork counter always clickable. !5463 (winniehell) - - Document that webhook secret token is sent in X-Gitlab-Token HTTP header !5664 (lycoperdon) - - Gitlab::Highlight is now instrumented - - All created issues, API or WebUI, can be submitted to Akismet for spam check !5333 - - Allow users to import cross-repository pull requests from GitHub - - The overhead of instrumented method calls has been reduced - - Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le) - - Load project invited groups and members eagerly in `ProjectTeam#fetch_members` - - Add pipeline events hook - - Bump gitlab_git to speedup DiffCollection iterations - - Rewrite description of a blocked user in admin settings. (Elias Werberich) - - Make branches sortable without push permission !5462 (winniehell) - - Check for Ci::Build artifacts at database level on pipeline partial - - Convert image diff background image to CSS (ClemMakesApps) - - Remove unnecessary index_projects_on_builds_enabled index from the projects table - - Make "New issue" button in Issue page less obtrusive !5457 (winniehell) - - Gitlab::Metrics.current_transaction needs to be public for RailsQueueDuration - - Fix search for notes which belongs to deleted objects - - Allow Akismet to be trained by submitting issues as spam or ham !5538 - - Add GitLab Workhorse version to admin dashboard (Katarzyna Kobierska Ula Budziszewska) - - Allow branch names ending with .json for graph and network page !5579 (winniehell) - - Add the `sprockets-es6` gem - - Improve OAuth2 client documentation (muteor) - - Fix diff comments inverted toggle bug (ClemMakesApps) - - Multiple trigger variables show in separate lines (Katarzyna Kobierska Ula Budziszewska) - - Profile requests when a header is passed - - Avoid calculation of line_code and position for _line partial when showing diff notes on discussion tab. - - Speedup DiffNote#active? on discussions, preloading noteables and avoid touching git repository to return diff_refs when possible - - Add commit stats in commit api. !5517 (dixpac) - - Add CI configuration button on project page - - Fix merge request new view not changing code view rendering style - - edit_blob_link will use blob passed onto the options parameter - - Make error pages responsive (Takuya Noguchi) - - The performance of the project dropdown used for moving issues has been improved - - Fix skip_repo parameter being ignored when destroying a namespace - - Add all builds into stage/job dropdowns on builds page - - Change requests_profiles resource constraint to catch virtually any file - - Bump gitlab_git to lazy load compare commits - - Reduce number of queries made for merge_requests/:id/diffs - - Add the option to set the expiration date for the project membership when giving a user access to a project. !5599 (Adam Niedzielski) - - Sensible state specific default sort order for issues and merge requests !5453 (tomb0y) - - Fix bug where destroying a namespace would not always destroy projects - - Fix RequestProfiler::Middleware error when code is reloaded in development - - Allow horizontal scrolling of code blocks in issue body - - Catch what warden might throw when profiling requests to re-throw it - - Avoid commit lookup on diff_helper passing existing local variable to the helper method - - Add description to new_issue email and new_merge_request_email in text/plain content type. !5663 (dixpac) - - Speed up and reduce memory usage of Commit#repo_changes, Repository#expire_avatar_cache and IrkerWorker - - Add unfold links for Side-by-Side view. !5415 (Tim Masliuchenko) - - Adds support for pending invitation project members importing projects - - Add pipeline visualization/graph on pipeline page - - Update devise initializer to turn on changed password notification emails. !5648 (tombell) - - Avoid to show the original password field when password is automatically set. !5712 (duduribeiro) - - Fix importing GitLab projects with an invalid MR source project - - Sort folders with submodules in Files view !5521 - - Each `File::exists?` replaced to `File::exist?` because of deprecate since ruby version 2.2.0 - - Add auto-completition in pipeline (Katarzyna Kobierska Ula Budziszewska) - - Add pipelines tab to merge requests - - Fix notification_service argument error of declined invitation emails - - Fix a memory leak caused by Banzai::Filter::SanitizationFilter - - Speed up todos queries by limiting the projects set we join with - - Ensure file editing in UI does not overwrite commited changes without warning user - - Eliminate unneeded calls to Repository#blob_at when listing commits with no path - - Update gitlab_git gem to 10.4.7 - - Simplify SQL queries of marking a todo as done - -v 8.10.12 - - Don't send Private-Token (API authentication) headers to Sentry - - Share projects via the API only with groups the authenticated user can access - -v 8.10.11 - - Respect the fork_project permission when forking projects - - Set a restrictive CORS policy on the API for credentialed requests - - API: disable rails session auth for non-GET/HEAD requests - - Escape HTML nodes in builds commands in CI linter - -v 8.10.10 - - Allow the Rails cookie to be used for API authentication. - -v 8.10.9 - - Exclude some pending or inactivated rows in Member scopes - -v 8.10.8 - - Fix information disclosure in issue boards. - - Fix privilege escalation in project import. - -v 8.10.7 - - Upgrade Hamlit to 2.6.1. !5873 - - Upgrade Doorkeeper to 4.2.0. !5881 - -v 8.10.6 - - Upgrade Rails to 4.2.7.1 for security fixes. !5781 - - Restore "Largest repository" sort option on Admin > Projects page. !5797 - - Fix privilege escalation via project export. - - Require administrator privileges to perform a project import. - -v 8.10.5 - - Add a data migration to fix some missing timestamps in the members table. !5670 - - Revert the "Defend against 'Host' header injection" change in the source NGINX templates. !5706 - - Cache project count for 5 minutes to reduce DB load. !5746 & !5754 - -v 8.10.4 - - Don't close referenced upstream issues from a forked project. - - Fixes issue with dropdowns `enter` key not working correctly. !5544 - - Fix Import/Export project import not working in HA mode. !5618 - - Fix Import/Export error checking versions. !5638 - -v 8.10.3 - - Fix Import/Export issue importing milestones and labels not associated properly. !5426 - - Fix timing problems running imports on production. !5523 - - Add a log message when a project is scheduled for destruction for debugging. !5540 - - Fix hooks missing on imported GitLab projects. !5549 - - Properly abort a merge when merge conflicts occur. !5569 - - Fix importer for GitHub Pull Requests when a branch was removed. !5573 - - Ignore invalid IPs in X-Forwarded-For when trusted proxies are configured. !5584 - - Trim extra displayed carriage returns in diffs and files with CRLFs. !5588 - - Fix label already exist error message in the right sidebar. - -v 8.10.2 - - User can now search branches by name. !5144 - - Page is now properly rendered after committing the first file and creating the first branch. !5399 - - Add branch or tag icon to ref in builds page. !5434 - - Fix backup restore. !5459 - - Use project ID in repository cache to prevent stale data from persisting across projects. !5460 - - Fix issue with autocomplete search not working with enter key. !5466 - - Add iid to MR API response. !5468 - - Disable MySQL foreign key checks before dropping all tables. !5472 - - Ensure relative paths for video are rewritten as we do for images. !5474 - - Ensure current user can retry a build before showing the 'Retry' button. !5476 - - Add ENV variable to skip repository storages validations. !5478 - - Added `*.js.es6 gitlab-language=javascript` to `.gitattributes`. !5486 - - Don't show comment button in gutter of diffs on MR discussion tab. !5493 - - Rescue Rugged::OSError (lock exists) when creating references. !5497 - - Fix expand all diffs button in compare view. !5500 - - Show release notes in tags list. !5503 - - Fix a bug where forking a project from a repository storage to another would fail. !5509 - - Fix missing schema update for `20160722221922`. !5512 - - Update `gitlab-shell` version to 3.2.1 in the 8.9->8.10 update guide. !5516 - -v 8.10.1 - - Refactor repository storages documentation. !5428 - - Gracefully handle case when keep-around references are corrupted or exist already. !5430 - - Add detailed info on storage path mountpoints. !5437 - - Fix Error 500 when creating Wiki pages with hyphens or spaces. !5444 - - Fix bug where replies to commit notes displayed in the MR discussion tab wouldn't show up on the commit page. !5446 - - Ignore invalid trusted proxies in X-Forwarded-For header. !5454 - - Add links to the real markdown.md file for all GFM examples. !5458 - -v 8.10.0 - - Fix profile activity heatmap to show correct day name (eanplatter) - - Speed up ExternalWikiHelper#get_project_wiki_path - - Expose {should,force}_remove_source_branch (Ben Boeckel) - - Add the functionality to be able to rename a file. !5049 - - Disable PostgreSQL statement timeout during migrations - - Fix projects dropdown loading performance with a simplified api cal. !5113 - - Fix commit builds API, return all builds for all pipelines for given commit. !4849 - - Replace Haml with Hamlit to make view rendering faster. !3666 - - Refresh the branch cache after `git gc` runs - - Allow to disable request access button on projects/groups - - Refactor repository paths handling to allow multiple git mount points - - Optimize system note visibility checking by memoizing the visible reference count. !5070 - - Add Application Setting to configure default Repository Path for new projects - - Delete award emoji when deleting a user - - Remove pinTo from Flash and make inline flash messages look nicer. !4854 (winniehell) - - Add an API for downloading latest successful build from a particular branch or tag. !5347 - - Avoid data-integrity issue when cleaning up repository archive cache. - - Add link to profile to commit avatar. !5163 (winniehell) - - Wrap code blocks on Activies and Todos page. !4783 (winniehell) - - Align flash messages with left side of page content. !4959 (winniehell) - - Display tooltip for "Copy to Clipboard" button. !5164 (winniehell) - - Use default cursor for table header of project files. !5165 (winniehell) - - Store when and yaml variables in builds table - - Display last commit of deleted branch in push events. !4699 (winniehell) - - Escape file extension when parsing search results. !5141 (winniehell) - - Add "passing with warnings" to the merge request pipeline possible statuses, this happens when builds that allow failures have failed. !5004 - - Add image border in Markdown preview. !5162 (winniehell) - - Apply the trusted_proxies config to the rack request object for use with rack_attack - - Added the ability to block sign ups using a domain blacklist. !5259 - - Upgrade to Rails 4.2.7. !5236 - - Extend exposed environment variables for CI builds - - Deprecate APIs "projects/:id/keys/...". Use "projects/:id/deploy_keys/..." instead - - Add API "deploy_keys" for admins to get all deploy keys - - Allow to pull code with deploy key from public projects - - Use limit parameter rather than hardcoded value in `ldap:check` rake task (Mike Ricketts) - - Add Sidekiq queue duration to transaction metrics. - - Add a new column `artifacts_size` to table `ci_builds`. !4964 - - Let Workhorse serve format-patch diffs - - Display tooltip for mentioned users and groups. !5261 (winniehell) - - Allow build email service to be tested - - Added day name to contribution calendar tooltips - - Refactor user authorization check for a single project to avoid querying all user projects - - Make images fit to the size of the viewport. !4810 - - Fix check for New Branch button on Issue page. !4630 (winniehell) - - Fix GFM autocomplete not working on wiki pages - - Fixed enter key not triggering click on first row when searching in a dropdown - - Updated dropdowns in issuable form to use new GitLab dropdown style - - Make images fit to the size of the viewport !4810 - - Fix check for New Branch button on Issue page !4630 (winniehell) - - Fix MR-auto-close text added to description. !4836 - - Support U2F devices in Firefox. !5177 - - Fix issue, preventing users w/o push access to sort tags. !5105 (redetection) - - Add Spring EmojiOne updates. - - Added Rake task for tracking deployments. !5320 - - Fix fetching LFS objects for private CI projects - - Add the new 2016 Emoji! Adds 72 new emoji including bacon, facepalm, and selfie. !5237 - - Add syntax for multiline blockquote using `>>>` fence. !3954 - - Fix viewing notification settings when a project is pending deletion - - Updated compare dropdown menus to use GL dropdown - - Redirects back to issue after clicking login link - - Eager load award emoji on notes - - Allow to define manual actions/builds on Pipelines and Environments - - Fix pagination when sorting by columns with lots of ties (like priority) - - The Markdown reference parsers now re-use query results to prevent running the same queries multiple times. !5020 - - Updated project header design - - Issuable collapsed assignee tooltip is now the users name - - Fix compare view not changing code view rendering style - - Exclude email check from the standard health check - - Updated layout for Projects, Groups, Users on Admin area. !4424 - - Fix changing issue state columns in milestone view - - Update health_check gem to version 2.1.0 - - Add notification settings dropdown for groups - - Render inline diffs for multiple changed lines following eachother - - Wildcards for protected branches. !4665 - - Allow importing from Github using Personal Access Tokens. (Eric K Idema) - - API: Expose `due_date` for issues (Robert Schilling) - - API: Todos. !3188 (Robert Schilling) - - API: Expose shared groups for projects and shared projects for groups. !5050 (Robert Schilling) - - API: Expose `developers_can_push` and `developers_can_merge` for branches. !5208 (Robert Schilling) - - Add "Enabled Git access protocols" to Application Settings - - Diffs will create button/diff form on demand no on server side - - Reduce size of HTML used by diff comment forms - - Protected branches have a "Developers can Merge" setting. !4892 (original implementation by Mathias Vestergaard) - - Fix user creation with stronger minimum password requirements. !4054 (nathan-pmt) - - Only show New Snippet button to users that can create snippets. - - PipelinesFinder uses git cache data - - Track a user who created a pipeline - - Actually render old and new sections of parallel diff next to each other - - Throttle the update of `project.pushes_since_gc` to 1 minute. - - Allow expanding and collapsing files in diff view. !4990 - - Collapse large diffs by default (!4990) - - Fix mentioned users list on diff notes - - Add support for inline videos in GitLab Flavored Markdown. !5215 (original implementation by Eric Hayes) - - Fix creation of deployment on build that is retried, redeployed or rollback - - Don't parse Rinku returned value to DocFragment when it didn't change the original html string. - - Check for conflicts with existing Project's wiki path when creating a new project. - - Show last push widget in upstream after push to fork - - Fix stage status shown for pipelines - - Cache todos pending/done dashboard query counts. - - Don't instantiate a git tree on Projects show default view - - Bump Rinku to 2.0.0 - - Remove unused front-end variable -> default_issues_tracker - - ObjectRenderer retrieve renderer content using Rails.cache.read_multi - - Better caching of git calls on ProjectsController#show. - - Avoid to retrieve MR closes_issues as much as possible. - - Hide project name in project activities. !5068 (winniehell) - - Add API endpoint for a group issues. !4520 (mahcsig) - - Add Bugzilla integration. !4930 (iamtjg) - - Fix new snippet style bug (elliotec) - - Instrument Rinku usage - - Be explicit to define merge request discussion variables - - Use cache for todos counter calling TodoService - - Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab - - RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info. - - Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w) - - Made project list visibility icon fixed width - - Set import_url validation to be more strict - - Memoize MR merged/closed events retrieval - - Don't render discussion notes when requesting diff tab through AJAX - - Add basic system information like memory and disk usage to the admin panel - - Don't garbage collect commits that have related DB records like comments - - Allow to setup event by channel on slack service - - More descriptive message for git hooks and file locks - - Aliases of award emoji should be stored as original name. !5060 (dixpac) - - Handle custom Git hook result in GitLab UI - - Allow to access Container Registry for Public and Internal projects - - Allow '?', or '&' for label names - - Support redirected blobs for Container Registry integration - - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests - - Add date when user joined the team on the member page - - Fix 404 redirect after validation fails importing a GitLab project - - Added setting to set new users by default as external. !4545 (Dravere) - - Add min value for project limit field on user's form. !3622 (jastkand) - - Reset project pushes_since_gc when we enqueue the git gc call - - Add reminder to not paste private SSH keys. !4399 (Ingo Blechschmidt) - - Collapsed diffs lines/size don't acumulate to overflow diffs. - - Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel) - - Style of import project buttons were fixed in the new project page. !5183 (rdemirbay) - - Fix GitHub client requests when rate limit is disabled - - Optimistic locking for Issues and Merge Requests (Title and description overriding prevention) - - Redesign Builds and Pipelines pages - - Change status color and icon for running builds - - Fix commenting issue in side by side diff view for unchanged lines - - Fix markdown rendering for: consecutive labels references, label references that begin with a digit or contains `.` - - Project export filename now includes the project and namespace path - - Fix last update timestamp on issues not preserved on gitlab.com and project imports - - Fix issues importing projects from EE to CE - - Fix creating group with space in group path - - Improve cron_jobs loading error messages. !5318 / !5360 - - Prevent toggling sidebar when clipboard icon clicked - - Create Todos for Issue author when assign or mention himself (Katarzyna Kobierska) - - Limit the number of retries on error to 3 for exporting projects - - Allow empty repositories on project import/export - - Render only commit message title in builds (Katarzyna Kobierska Ula Budziszewska) - - Allow bulk (un)subscription from issues in issue index - - Fix MR diff encoding issues exporting GitLab projects - - Move builds settings out of project settings and rename Pipelines - - Add builds badge to Pipelines settings page - - Export and import avatar as part of project import/export - - Fix migration corrupting import data for old version upgrades - - Show tooltip on GitLab export link in new project page - - Fix import_data wrongly saved as a result of an invalid import_url !5206 - -v 8.9.11 - - Respect the fork_project permission when forking projects - - Set a restrictive CORS policy on the API for credentialed requests - - API: disable rails session auth for non-GET/HEAD requests - - Escape HTML nodes in builds commands in CI linter - -v 8.9.10 - - Allow the Rails cookie to be used for API authentication. - -v 8.9.9 - - Exclude some pending or inactivated rows in Member scopes - -v 8.9.8 - - Upgrade Doorkeeper to 4.2.0. !5881 - -v 8.9.7 - - Upgrade Rails to 4.2.7.1 for security fixes. !5781 - - Require administrator privileges to perform a project import. - -v 8.9.6 - - Fix importing of events under notes for GitLab projects. !5154 - - Fix log statements in import/export. !5129 - - Fix commit avatar alignment in compare view. !5128 - - Fix broken migration in MySQL. !5005 - - Overwrite Host and X-Forwarded-Host headers in NGINX !5213 - - Keeps issue number when importing from Gitlab.com - - Add Pending tab for Builds (Katarzyna Kobierska, Urszula Budziszewska) - -v 8.9.5 - - Add more debug info to import/export and memory killer. !5108 - - Fixed avatar alignment in new MR view. !5095 - - Fix diff comments not showing up in activity feed. !5069 - - Add index on both Award Emoji user and name. !5061 - - Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq. !5056 - - Re-enable import button when import process fails due to namespace already being taken. !5053 - - Fix snippets comments not displayed. !5045 - - Fix emoji paths in relative root configurations. !5027 - - Fix issues importing events in Import/Export. !4987 - - Fixed 'use shortcuts' button on docs. !4979 - - Admin should be able to turn shared runners into specific ones. !4961 - - Update RedCloth to 4.3.2 for CVE-2012-6684. !4929 (Takuya Noguchi) - - Improve the request / withdraw access button. !4860 - -v 8.9.4 - - Fix privilege escalation issue with OAuth external users. - - Ensure references to private repos aren't shown to logged-out users. - - Fixed search field blur not removing focus. !4704 - - Resolve "Sub nav isn't showing on file view". !4890 - - Fixes middle click and double request when navigating through the file browser. !4891 - - Fixed URL on label button when filtering. !4897 - - Fixed commit avatar alignment. !4933 - - Do not show build retry link when build is active. !4967 - - Fix restore Rake task warning message output. !4980 - - Handle external issues in IssueReferenceFilter. !4988 - - Expiry date on pinned nav cookie. !5009 - - Updated breakpoint for sidebar pinning. !5019 - -v 8.9.3 - - Fix encrypted data backwards compatibility after upgrading attr_encrypted gem. !4963 - - Fix rendering of commit notes. !4953 - - Resolve "Pin should show up at 1280px min". !4947 - - Switched mobile button icons to ellipsis and angle. !4944 - - Correctly returns todo ID after creating todo. !4941 - - Better debugging for memory killer middleware. !4936 - - Remove duplicate new page btn from edit wiki. !4904 - - Use clock_gettime for all performance timestamps. !4899 - - Use memorized tags array when searching tags by name. !4859 - - Fixed avatar alignment in new MR view. !4901 - - Removed fade when filtering results. !4932 - - Fix missing avatar on system notes. !4954 - - Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973 - - Use update_columns to bypass all the dirty code on active_record. !4985 - - Fix restore Rake task warning message output !4980 - -v 8.9.2 - - Fix visibility of snippets when searching. - - Fix an information disclosure when requesting access to a group containing private projects. - - Update omniauth-saml to 1.6.0 !4951 - -v 8.9.1 - - Refactor labels documentation. !3347 - - Eager load award emoji on notes. !4628 - - Fix some CI wording in documentation. !4660 - - Document `GIT_STRATEGY` and `GIT_DEPTH`. !4720 - - Add documentation for the export & import features. !4732 - - Add some docs for Docker Registry configuration. !4738 - - Ensure we don't send the "access request declined" email to access requesters on project deletion. !4744 - - Display group/project access requesters separately in the admin area. !4798 - - Add documentation and examples for configuring cloud storage for registry images. !4812 - - Clarifies documentation about artifact expiry. !4831 - - Fix the Network graph links. !4832 - - Fix MR-auto-close text added to description. !4836 - - Add documentation for award emoji now that comments can be awarded with emojis. !4839 - - Fix typo in export failure email. !4847 - - Fix header vertical centering. !4170 - - Fix subsequent SAML sign ins. !4718 - - Set button label when picking an option from status dropdown. !4771 - - Prevent invalid URLs from raising exceptions in WikiLink Filter. !4775 - - Handle external issues in IssueReferenceFilter. !4789 - - Support for rendering/redacting multiple documents. !4828 - - Update Todos documentation and screenshots to include new functionality. !4840 - - Hide nav arrows by default. !4843 - - Added bottom padding to label color suggestion link. !4845 - - Use jQuery objects in ref dropdown. !4850 - - Fix GitLab project import issues related to notes and builds. !4855 - - Restrict header logo to 36px so it doesn't overflow. !4861 - - Fix unwanted label unassignment. !4863 - - Fix mobile Safari bug where horizontal nav arrows would flicker on scroll. !4869 - - Restore old behavior around diff notes to outdated discussions. !4870 - - Fix merge requests project settings help link anchor. !4873 - - Fix 404 when accessing pipelines as guest user on public projects. !4881 - - Remove width restriction for logo on sign-in page. !4888 - - Bump gitlab_git to 10.2.3 to fix false truncated warnings with ISO-8559 files. !4884 - - Apply selected value as label. !4886 - - Change Retry to Re-deploy on Deployments page - - Fix temp file being deleted after the request while importing a GitLab project. !4894 - - Fix pagination when sorting by columns with lots of ties (like priority) - - Implement Subresource Integrity for CSS and JavaScript assets. This prevents malicious assets from loading in the case of a CDN compromise. - - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) - - Fix a wrong MR status when merge_when_build_succeeds & project.only_allow_merge_if_build_succeeds are true. !4912 - - Add SMTP as default delivery method to match gitlab-org/omnibus-gitlab!826. !4915 - - Remove duplicate 'New Page' button on edit wiki page - -v 8.9.0 - - Fix group visibility form layout in application settings - - Fix builds API response not including commit data - - Fix error when CI job variables key specified but not defined - - Fix pipeline status when there are no builds in pipeline - - Fix Error 500 when using closes_issues API with an external issue tracker - - Add more information into RSS feed for issues (Alexander Matyushentsev) - - Bulk assign/unassign labels to issues. - - Ability to prioritize labels !4009 / !3205 (Thijs Wouters) - - Show Star and Fork buttons on mobile. - - Performance improvements on RelativeLinkFilter - - Fix endless redirections when accessing user OAuth applications when they are disabled - - Allow enabling wiki page events from Webhook management UI - - Bump rouge to 1.11.0 - - Fix issue with arrow keys not working in search autocomplete dropdown - - Fix an issue where note polling stopped working if a window was in the - background during a refresh. - - Pre-processing Markdown now only happens when needed - - Make EmailsOnPushWorker use Sidekiq mailers queue - - Redesign all Devise emails. !4297 - - Don't show 'Leave Project' to group members - - Fix wiki page events' webhook to point to the wiki repository - - Add a border around images to differentiate them from the background. - - Don't show tags for revert and cherry-pick operations - - Show image ID on registry page - - Fix issue todo not remove when leave project !4150 (Long Nguyen) - - Allow customisable text on the 'nearly there' page after a user signs up - - Bump recaptcha gem to 3.0.0 to remove deprecated stoken support - - Fix SVG sanitizer to allow more elements - - Allow forking projects with restricted visibility level - - Added descriptions to notification settings dropdown - - Improve note validation to prevent errors when creating invalid note via API - - Reduce number of fog gem dependencies - - Add number of merge requests for a given milestone to the milestones view. - - Implement a fair usage of shared runners - - Remove project notification settings associated with deleted projects - - Fix 404 page when viewing TODOs that contain milestones or labels in different projects - - Add a metric for the number of new Redis connections created by a transaction - - Fix Error 500 when viewing a blob with binary characters after the 1024-byte mark - - Redesign navigation for project pages - - Fix images in sign-up confirmation email - - Added shortcut 'y' for copying a files content hash URL #14470 - - Fix groups API to list only user's accessible projects - - Fix horizontal scrollbar for long commit message. - - GitLab Performance Monitoring now tracks the total method execution time and call count per method - - Add Environments and Deployments - - Redesign account and email confirmation emails - - Don't fail builds for projects that are deleted - - Support Docker Registry manifest v1 - - `git clone https://host/namespace/project` now works, in addition to using the `.git` suffix - - Bump nokogiri to 1.6.8 - - Use gitlab-shell v3.0.0 - - Fixed alignment of download dropdown in merge requests - - Upgrade to jQuery 2 - - Adds selected branch name to the dropdown toggle - - Add API endpoint for Sidekiq Metrics !4653 - - Refactoring Award Emoji with API support for Issues and MergeRequests - - Use Knapsack to evenly distribute tests across multiple nodes - - Add `sha` parameter to MR merge API, to ensure only reviewed changes are merged - - Don't allow MRs to be merged when commits were added since the last review / page load - - Add DB index on users.state - - Limit email on push diff size to 30 files / 150 KB - - Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database - - Changed the Slack build message to use the singular duration if necessary (Aran Koning) - - Fix race condition on merge when build succeeds - - Added shortcut to focus filter search fields and added documentation #18120 - - Links from a wiki page to other wiki pages should be rewritten as expected - - Add option to project to only allow merge requests to be merged if the build succeeds (Rui Santos) - - Added navigation shortcuts to the project pipelines, milestones, builds and forks page. !4393 - - Fix issues filter when ordering by milestone - - Disable SAML account unlink feature - - Added artifacts:when to .gitlab-ci.yml - this requires GitLab Runner 1.3 - - Bamboo Service: Fix missing credentials & URL handling when base URL contains a path (Benjamin Schmid) - - TeamCity Service: Fix URL handling when base URL contains a path - - Todos will display target state if issuable target is 'Closed' or 'Merged' - - Validate only and except regexp - - Fix bug when sorting issues by milestone due date and filtering by two or more labels - - POST to API /projects/:id/runners/:runner_id would give 409 if the runner was already enabled for this project - - Add support for using Yubikeys (U2F) for two-factor authentication - - Link to blank group icon doesn't throw a 404 anymore - - Remove 'main language' feature - - Toggle whitespace button now available for compare branches diffs #17881 - - Pipelines can be canceled only when there are running builds - - Allow authentication using personal access tokens - - Use downcased path to container repository as this is expected path by Docker - - Allow to use CI token to fetch LFS objects - - Custom notification settings - - Projects pending deletion will render a 404 page - - Measure queue duration between gitlab-workhorse and Rails - - Added Gfm autocomplete for labels - - Added edit note 'up' shortcut documentation to the help panel and docs screenshot #18114 - - Make Omniauth providers specs to not modify global configuration - - Remove unused JiraIssue class and replace references with ExternalIssue. !4659 (Ilan Shamir) - - Make authentication service for Container Registry to be compatible with < Docker 1.11 - - Make it possible to lock a runner from being enabled for other projects - - Add Application Setting to configure Container Registry token expire delay (default 5min) - - Cache assigned issue and merge request counts in sidebar nav - - Use Knapsack only in CI environment - - Updated project creation page to match new UI #2542 - - Cache project build count in sidebar nav - - Add milestone expire date to the right sidebar - - Manually mark a issue or merge request as a todo - - Fix markdown_spec to use before instead of before(:all) to properly cleanup database after testing - - Reduce number of queries needed to render issue labels in the sidebar - - Improve error handling importing projects - - Remove duplicated notification settings - - Put project Files and Commits tabs under Code tab - - Decouple global notification level from user model - - Replace Colorize with Rainbow for coloring console output in Rake tasks. - - Add workhorse controller and API helpers - - An indicator is now displayed at the top of the comment field for confidential issues. - - Show categorised search queries in the search autocomplete - - RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented - - Dropdown for `.gitlab-ci.yml` templates - - Improve issuables APIs performance when accessing notes !4471 - - Add sorting dropdown to tags page !4423 - - External links now open in a new tab - - Prevent default actions of disabled buttons and links - - Markdown editor now correctly resets the input value on edit cancellation !4175 - - Toggling a task list item in a issue/mr description does not creates a Todo for mentions - - Improved UX of date pickers on issue & milestone forms - - Cache on the database if a project has an active external issue tracker. - - Put project Labels and Milestones pages links under Issues and Merge Requests tabs as subnav - - GitLab project import and export functionality - - All classes in the Banzai::ReferenceParser namespace are now instrumented - - Remove deprecated issues_tracker and issues_tracker_id from project model - - Allow users to create confidential issues in private projects - - Measure CPU time for instrumented methods - - Instrument private methods and private instance methods by default instead just public methods - - Only show notes through JSON on confidential issues that the user has access to - - Updated the allocations Gem to version 1.0.5 - - The background sampler now ignores classes without names - - Update design for `Close` buttons - - New custom icons for navigation - - Horizontally scrolling navigation on project, group, and profile settings pages - - Hide global side navigation by default - - Fix project Star/Unstar project button tooltip - - Remove tanuki logo from side navigation; center on top nav - - Include user relationships when retrieving award_emoji - - Various associations are now eager loaded when parsing issue references to reduce the number of queries executed - - Set inverse_of for Project/Service association to reduce the number of queries - - Update tanuki logo highlight/loading colors - - Remove explicit Gitlab::Metrics.action assignments, are already automatic. - - Use Git cached counters for branches and tags on project page - - Cache participable participants in an instance variable. - - Filter parameters for request_uri value on instrumented transactions. - - Remove duplicated keys add UNIQUE index to keys fingerprint column - - ExtractsPath get ref_names from repository cache, if not there access git. - - Show a flash warning about the error detail of XHR requests which failed with status code 404 and 500 - - Cache user todo counts from TodoService - - Ensure Todos counters doesn't count Todos for projects pending delete - - Add left/right arrows horizontal navigation - - Add tooltip to pin/unpin navbar - - Add new sub nav style to Wiki and Graphs sub navigation - -v 8.8.9 - - Upgrade Doorkeeper to 4.2.0. !5881 - -v 8.8.8 - - Upgrade Rails to 4.2.7.1 for security fixes. !5781 - -v 8.8.7 - - Fix privilege escalation issue with OAuth external users. - - Ensure references to private repos aren't shown to logged-out users. - -v 8.8.6 - - Fix visibility of snippets when searching. - - Update omniauth-saml to 1.6.0 !4951 - -v 8.8.5 - - Import GitHub repositories respecting the API rate limit !4166 - - Fix todos page throwing errors when you have a project pending deletion !4300 - - Disable Webhooks before proceeding with the GitHub import !4470 - - Fix importer for GitHub comments on diff !4488 - - Adjust the SAML control flow to allow LDAP identities to be added to an existing SAML user !4498 - - Fix incremental trace upload API when using multi-byte UTF-8 chars in trace !4541 - - Prevent unauthorized access for projects build traces - - Forbid scripting for wiki files - - Only show notes through JSON on confidential issues that the user has access to - - Banzai::Filter::UploadLinkFilter use XPath instead CSS expressions - - Banzai::Filter::ExternalLinkFilter use XPath instead CSS expressions - -v 8.8.4 - - Fix LDAP-based login for users with 2FA enabled. !4493 - - Added descriptions to notification settings dropdown - - Due date can be removed from milestones - -v 8.8.3 - - Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312 - - Fixed JS error when trying to remove discussion form. !4303 - - Fixed issue with button color when no CI enabled. !4287 - - Fixed potential issue with 2 CI status polling events happening. !3869 - - Improve design of Pipeline view. !4230 - - Fix gitlab importer failing to import new projects due to missing credentials. !4301 - - Fix import URL migration not rescuing with the correct Error. !4321 - - Fix health check access token changing due to old application settings being used. !4332 - - Make authentication service for Container Registry to be compatible with Docker versions before 1.11. !4363 - - Add Application Setting to configure Container Registry token expire delay (default 5 min). !4364 - - Pass the "Remember me" value to the 2FA token form. !4369 - - Fix incorrect links on pipeline page when merge request created from fork. !4376 - - Use downcased path to container repository as this is expected path by Docker. !4420 - - Fix wiki project clone address error (chujinjin). !4429 - - Fix serious performance bug with rendering Markdown with InlineDiffFilter. !4392 - - Fix missing number on generated ordered list element. !4437 - - Prevent disclosure of notes on confidential issues in search results. - -v 8.8.2 - - Added remove due date button. !4209 - - Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242 - - Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245 - - Fix table UI on CI builds page. !4249 - - Fix backups if registry is disabled. !4263 - - Fixed issue with merge button color. !4211 - - Fixed issue with enter key selecting wrong option in dropdown. !4210 - - When creating a .gitignore file a dropdown with templates will be provided. !4075 - - Fix concurrent request when updating build log in browser. !4183 - -v 8.8.1 - - Add documentation for the "Health Check" feature - - Allow anonymous users to access a public project's pipelines !4233 - - Fix MySQL compatibility in zero downtime migrations helpers - - Fix the CI login to Container Registry (the gitlab-ci-token user) - -v 8.8.0 - - Implement GFM references for milestones (Alejandro Rodríguez) - - Snippets tab under user profile. !4001 (Long Nguyen) - - Fix error when using link to uploads in global snippets - - Fix Error 500 when attempting to retrieve project license when HEAD points to non-existent ref - - Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen) - - Use a case-insensitive comparison in sanitizing URI schemes - - Toggle sign-up confirmation emails in application settings - - Make it possible to prevent tagged runner from picking untagged jobs - - Added `InlineDiffFilter` to the markdown parser. (Adam Butler) - - Added inline diff styling for `change_title` system notes. (Adam Butler) - - Project#open_branches has been cleaned up and no longer loads entire records into memory. - - Escape HTML in commit titles in system note messages - - Improve design of Pipeline View - - Fix scope used when accessing container registry - - Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios - - Improve multiple branch push performance by memoizing permission checking - - Log to application.log when an admin starts and stops impersonating a user - - Changing the confidentiality of an issue now creates a new system note (Alex Moore-Niemi) - - Updated gitlab_git to 10.1.0 - - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists - - Reduce delay in destroying a project from 1-minute to immediately - - Make build status canceled if any of the jobs was canceled and none failed - - Upgrade Sidekiq to 4.1.2 - - Added /health_check endpoint for checking service status - - Make 'upcoming' filter for milestones work better across projects - - Sanitize repo paths in new project error message - - Bump mail_room to 0.7.0 to fix stuck IDLE connections - - Remove future dates from contribution calendar graph. - - Support e-mail notifications for comments on project snippets - - Fix API leak of notes of unauthorized issues, snippets and merge requests - - Use ActionDispatch Remote IP for Akismet checking - - Fix error when visiting commit builds page before build was updated - - Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project - - Update SVG sanitizer to conform to SVG 1.1 - - Speed up push emails with multiple recipients by only generating the email once - - Updated search UI - - Added authentication service for Container Registry - - Display informative message when new milestone is created - - Sanitize milestones and labels titles - - Support multi-line tag messages. !3833 (Calin Seciu) - - Force users to reset their password after an admin changes it - - Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea) - - Added button to toggle whitespaces changes on diff view - - Backport GitHub Enterprise import support from EE - - Create tags using Rugged for performance reasons. !3745 - - Allow guests to set notification level in projects - - API: Expose Issue#user_notes_count. !3126 (Anton Popov) - - Don't show forks button when user can't view forks - - Fix atom feed links and rendering - - Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718 - - Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes) - - Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724 - - Added multiple colors for labels in dropdowns when dups happen. - - Show commits in the same order as `git log` - - Improve description for the Two-factor Authentication sign-in screen. (Connor Shea) - - API support for the 'since' and 'until' operators on commit requests (Paco Guzman) - - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) - - Expire repository exists? and has_visible_content? caches after a push if necessary - - Fix unintentional filtering bug in Issue/MR sorted by milestone due (Takuya Noguchi) - - Fix adding a todo for private group members (Ahmad Sherif) - - Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3 - - Total method execution timings are no longer tracked - - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga) - - Add API endpoints for un/subscribing from/to a label. !4051 (Ahmad Sherif) - - Hide left sidebar on phone screens to give more space for content - - Redesign navigation for profile and group pages - - Add counter metrics for rails cache - - Import pull requests from GitHub where the source or target branches were removed - - All Grape API helpers are now instrumented - - Improve Issue formatting for the Slack Service (Jeroen van Baarsen) - - Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine) - - Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs) - - When creating a .gitignore file a dropdown with templates will be provided - - Shows the issue/MR list search/filter form and corrects the mobile styling for guest users. #17562 - -v 8.7.9 - - Fix privilege escalation issue with OAuth external users. - - Ensure references to private repos aren't shown to logged-out users. - -v 8.7.8 - - Fix visibility of snippets when searching. - - Update omniauth-saml to 1.6.0 !4951 - -v 8.7.7 - - Fix import by `Any Git URL` broken if the URL contains a space - - Prevent unauthorized access to other projects build traces - - Forbid scripting for wiki files - - Only show notes through JSON on confidential issues that the user has access to - -v 8.7.6 - - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) - - Fix import from GitLab.com to a private instance failure. !4181 - - Fix external imports not finding the import data. !4106 - - Fix notification delay when changing status of an issue - - Bump Workhorse to 0.7.5 so it can serve raw diffs - -v 8.7.5 - - Fix relative links in wiki pages. !4050 - - Fix always showing build notification message when switching between merge requests !4086 - - Fix an issue when filtering merge requests with more than one label. !3886 - - Fix short note for the default scope on build page (Takuya Noguchi) - -v 8.7.4 - - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss) - - Fix setting trusted proxies !3970 - - Fix BitBucket importer bug when throwing exceptions !3941 - - Use sign out path only if not empty !3989 - - Running rake gitlab:db:drop_tables now drops tables with cascade !4020 - - Running rake gitlab:db:drop_tables uses "IF EXISTS" as a precaution !4100 - - Use a case-insensitive comparison in sanitizing URI schemes - -v 8.7.3 - - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented - - Merge request widget displays TeamCity build state and code coverage correctly again. - - Fix the line code when importing PR review comments from GitHub. !4010 - - Wikis are now initialized on legacy projects when checking repositories - - Remove animate.css in favor of a smaller subset of animations. !3937 (Connor Shea) - -v 8.7.2 - - The "New Branch" button is now loaded asynchronously - - Fix error 500 when trying to create a wiki page - - Updated spacing between notification label and button - - Label titles in filters are now escaped properly - -v 8.7.1 - - Throttle the update of `project.last_activity_at` to 1 minute. !3848 - - Fix .gitlab-ci.yml parsing issue when hidde job is a template without script definition. !3849 - - Fix license detection to detect all license files, not only known licenses. !3878 - - Use the `can?` helper instead of `current_user.can?`. !3882 - - Prevent users from deleting Webhooks via API they do not own - - Fix Error 500 due to stale cache when projects are renamed or transferred - - Update width of search box to fix Safari bug. !3900 (Jedidiah) - - Use the `can?` helper instead of `current_user.can?` - -v 8.7.0 - - Gitlab::GitAccess and Gitlab::GitAccessWiki are now instrumented - - Fix vulnerability that made it possible to gain access to private labels and milestones - - The number of InfluxDB points stored per UDP packet can now be configured - - Fix error when cross-project label reference used with non-existent project - - Transactions for /internal/allowed now have an "action" tag set - - Method instrumentation now uses Module#prepend instead of aliasing methods - - Repository.clean_old_archives is now instrumented - - Add support for environment variables on a job level in CI configuration file - - SQL query counts are now tracked per transaction - - The Projects::HousekeepingService class has extra instrumentation - - All service classes (those residing in app/services) are now instrumented - - Developers can now add custom tags to transactions - - Loading of an issue's referenced merge requests and related branches is now done asynchronously - - Enable gzip for assets, makes the page size significantly smaller. !3544 / !3632 (Connor Shea) - - Add support to cherry-pick any commit into any branch in the web interface (Minqi Pan) - - Project switcher uses new dropdown styling - - Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea) - - Do not include award_emojis in issue and merge_request comment_count !3610 (Lucas Charles) - - Restrict user profiles when public visibility level is restricted. - - Add ability set due date to issues, sort and filter issues by due date (Mehmet Beydogan) - - All images in discussions and wikis now link to their source files !3464 (Connor Shea). - - Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu) - - Add setting for customizing the list of trusted proxies !3524 - - Allow projects to be transfered to a lower visibility level group - - Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524 - - Improved Markdown rendering performance !3389 - - Make shared runners text in box configurable - - Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu) - - API: Ability to subscribe and unsubscribe from issues and merge requests (Robert Schilling) - - Expose project badges in project settings - - Make /profile/keys/new redirect to /profile/keys for back-compat. !3717 - - Preserve time notes/comments have been updated at when moving issue - - Make HTTP(s) label consistent on clone bar (Stan Hu) - - Add support for `after_script`, requires Runner 1.2 (Kamil Trzciński) - - Expose label description in API (Mariusz Jachimowicz) - - API: Ability to update a group (Robert Schilling) - - API: Ability to move issues (Robert Schilling) - - Fix Error 500 after renaming a project path (Stan Hu) - - Fix a bug whith trailing slash in teamcity_url (Charles May) - - Allow back dating on issues when created or updated through the API - - Allow back dating on issue notes when created through the API - - Propose license template when creating a new LICENSE file - - API: Expose /licenses and /licenses/:key - - Fix avatar stretching by providing a cropping feature - - API: Expose `subscribed` for issues and merge requests (Robert Schilling) - - Allow SAML to handle external users based on user's information !3530 - - Allow Omniauth providers to be marked as `external` !3657 - - Add endpoints to archive or unarchive a project !3372 - - Fix a bug whith trailing slash in bamboo_url - - Add links to CI setup documentation from project settings and builds pages - - Display project members page to all members - - Handle nil descriptions in Slack issue messages (Stan Hu) - - Add automated repository integrity checks (OFF by default) - - API: Expose open_issues_count, closed_issues_count, open_merge_requests_count for labels (Robert Schilling) - - API: Ability to star and unstar a project (Robert Schilling) - - Add default scope to projects to exclude projects pending deletion - - Allow to close merge requests which source projects(forks) are deleted. - - Ensure empty recipients are rejected in BuildsEmailService - - Use rugged to change HEAD in Project#change_head (P.S.V.R) - - API: Ability to filter milestones by state `active` and `closed` (Robert Schilling) - - API: Fix milestone filtering by `iid` (Robert Schilling) - - Make before_script and after_script overridable on per-job (Kamil Trzciński) - - API: Delete notes of issues, snippets, and merge requests (Robert Schilling) - - Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.) - - Better errors handling when creating milestones inside groups - - Fix high CPU usage when PostReceive receives refs/merge-requests/ - - Hide `Create a group` help block when creating a new project in a group - - Implement 'TODOs View' as an option for dashboard preferences !3379 (Elias W.) - - Allow issues and merge requests to be assigned to the author !2765 - - Make Ci::Commit to group only similar builds and make it stateful (ref, tag) - - Gracefully handle notes on deleted commits in merge requests (Stan Hu) - - Decouple membership and notifications - - Fix creation of merge requests for orphaned branches (Stan Hu) - - API: Ability to retrieve a single tag (Robert Schilling) - - While signing up, don't persist the user password across form redisplays - - Fall back to `In-Reply-To` and `References` headers when sub-addressing is not available (David Padilla) - - Remove "Congratulations!" tweet button on newly-created project. (Connor Shea) - - Fix admin/projects when using visibility levels on search (PotHix) - - Build status notifications - - Update email confirmation interface - - API: Expose user location (Robert Schilling) - - API: Do not leak group existence via return code (Robert Schilling) - - ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591 - - Update number of Todos in the sidebar when it's marked as "Done". !3600 - - Sanitize branch names created for confidential issues - - API: Expose 'updated_at' for issue, snippet, and merge request notes (Robert Schilling) - - API: User can leave a project through the API when not master or owner. !3613 - - Fix repository cache invalidation issue when project is recreated with an empty repo (Stan Hu) - - Fix: Allow empty recipients list for builds emails service when pushed is added (Frank Groeneveld) - - Improved markdown forms - - Diff design updates (colors, button styles, etc) - - Copying and pasting a diff no longer pastes the line numbers or +/- - - Add null check to formData when updating profile content to fix Firefox bug - - Disable spellcheck and autocorrect for username field in admin page - - Delete tags using Rugged for performance reasons (Robert Schilling) - - Add Slack notifications when Wiki is edited (Sebastian Klier) - - Diffs load at the correct point when linking from from number - - Selected diff rows highlight - - Fix emoji categories in the emoji picker - - API: Properly display annotated tags for GET /projects/:id/repository/tags (Robert Schilling) - - Add encrypted credentials for imported projects and migrate old ones - - Properly format all merge request references with ! rather than # !3740 (Ben Bodenmiller) - - Author and participants are displayed first on users autocompletion - - Show number sign on external issue reference text (Florent Baldino) - - Updated print style for issues - - Use GitHub Issue/PR number as iid to keep references - - Import GitHub labels - - Add option to filter by "Owned projects" on dashboard page - - Import GitHub milestones - - Execute system web hooks on push to the project - - Allow enable/disable push events for system hooks - - Fix GitHub project's link in the import page when provider has a custom URL - - Add RAW build trace output and button on build page - - Add incremental build trace update into CI API - -v 8.6.9 - - Prevent unauthorized access to other projects build traces - - Forbid scripting for wiki files - - Only show notes through JSON on confidential issues that the user has access to - -v 8.6.8 - - Prevent privilege escalation via "impersonate" feature - - Prevent privilege escalation via notes API - - Prevent privilege escalation via project webhook API - - Prevent XSS via Git branch and tag names - - Prevent XSS via custom issue tracker URL - - Prevent XSS via `window.opener` - - Prevent XSS via label drop-down - - Prevent information disclosure via milestone API - - Prevent information disclosure via snippet API - - Prevent information disclosure via project labels - - Prevent information disclosure via new merge request page - -v 8.6.7 - - Fix persistent XSS vulnerability in `commit_person_link` helper - - Fix persistent XSS vulnerability in Label and Milestone dropdowns - - Fix vulnerability that made it possible to enumerate private projects belonging to group - -v 8.6.6 - - Expire the exists cache before deletion to ensure project dir actually exists (Stan Hu). !3413 - - Fix error on language detection when repository has no HEAD (e.g., master branch) (Jeroen Bobbeldijk). !3654 - - Fix revoking of authorized OAuth applications (Connor Shea). !3690 - - Fix error on language detection when repository has no HEAD (e.g., master branch). !3654 (Jeroen Bobbeldijk) - - Issuable header is consistent between issues and merge requests - - Improved spacing in issuable header on mobile - -v 8.6.5 - - Fix importing from GitHub Enterprise. !3529 - - Perform the language detection after updating merge requests in `GitPushService`, leading to faster visual feedback for the end-user. !3533 - - Check permissions when user attempts to import members from another project. !3535 - - Only update repository language if it is not set to improve performance. !3556 - - Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu). !3583 - - Unblock user when active_directory is disabled and it can be found !3550 - - Fix a 2FA authentication spoofing vulnerability. - -v 8.6.4 - - Don't attempt to fetch any tags from a forked repo (Stan Hu) - - Redesign the Labels page - -v 8.6.3 - - Mentions on confidential issues doesn't create todos for non-members. !3374 - - Destroy related todos when an Issue/MR is deleted. !3376 - - Fix error 500 when target is nil on todo list. !3376 - - Fix copying uploads when moving issue to another project. !3382 - - Ensuring Merge Request API returns boolean values for work_in_progress (Abhi Rao). !3432 - - Fix raw/rendered diff producing different results on merge requests. !3450 - - Fix commit comment alignment (Stan Hu). !3466 - - Fix Error 500 when searching for a comment in a project snippet. !3468 - - Allow temporary email as notification email. !3477 - - Fix issue with dropdowns not selecting values. !3478 - - Update gitlab-shell version and doc to 2.6.12. gitlab-org/gitlab-ee!280 - -v 8.6.2 - - Fix dropdown alignment. !3298 - - Fix issuable sidebar overlaps on tablet. !3299 - - Make dropdowns pixel perfect. !3337 - - Fix order of steps to prevent PostgreSQL errors when running migration. !3355 - - Fix bold text in issuable sidebar. !3358 - - Fix error with anonymous token in applications settings. !3362 - - Fix the milestone 'upcoming' filter. !3364 + !3368 - - Fix comments on confidential issues showing up in activity feed to non-members. !3375 - - Fix `NoMethodError` when visiting CI root path at `/ci`. !3377 - - Add a tooltip to new branch button in issue page. !3380 - - Fix an issue hiding the password form when signed-in with a linked account. !3381 - - Add links to CI setup documentation from project settings and builds pages. !3384 - - Fix an issue with width of project select dropdown. !3386 - - Remove redundant `require`s from Banzai files. !3391 - - Fix error 500 with cancel button on issuable edit form. !3392 + !3417 - - Fix background when editing a highlighted note. !3423 - - Remove tabstop from the WIP toggle links. !3426 - - Ensure private project snippets are not viewable by unauthorized people. - - Gracefully handle notes on deleted commits in merge requests (Stan Hu). !3402 - - Fixed issue with notification settings not saving. !3452 - -v 8.6.1 - - Add option to reload the schema before restoring a database backup. !2807 - - Display navigation controls on mobile. !3214 - - Fixed bug where participants would not work correctly on merge requests. !3329 - - Fix sorting issues by votes on the groups issues page results in SQL errors. !3333 - - Restrict notifications for confidential issues. !3334 - - Do not allow to move issue if it has not been persisted. !3340 - - Add a confirmation step before deleting an issuable. !3341 - - Fixes issue with signin button overflowing on mobile. !3342 - - Auto collapses the navigation sidebar when resizing. !3343 - - Fix build dependencies, when the dependency is a string. !3344 - - Shows error messages when trying to create label in dropdown menu. !3345 - - Fixes issue with assign milestone not loading milestone list. !3346 - - Fix an issue causing the Dashboard/Milestones page to be blank. !3348 - -v 8.6.0 - - Add ability to move issue to another project - - Prevent tokens in the import URL to be showed by the UI - - Fix bug where wrong commit ID was being used in a merge request diff to show old image (Stan Hu) - - Add confidential issues - - Bump gitlab_git to 9.0.3 (Stan Hu) - - Fix diff image view modes (2-up, swipe, onion skin) not working (Stan Hu) - - Support Golang subpackage fetching (Stan Hu) - - Bump Capybara gem to 2.6.2 (Stan Hu) - - New branch button appears on issues where applicable - - Contributions to forked projects are included in calendar - - Improve the formatting for the user page bio (Connor Shea) - - Easily (un)mark merge request as WIP using link - - Use specialized system notes when MR is (un)marked as WIP - - Removed the default password from the initial admin account created during - setup. A password can be provided during setup (see installation docs), or - GitLab will ask the user to create a new one upon first visit. - - Fix issue when pushing to projects ending in .wiki - - Properly display YAML front matter in Markdown - - Add support for wiki with UTF-8 page names (Hiroyuki Sato) - - Fix wiki search results point to raw source (Hiroyuki Sato) - - Don't load all of GitLab in mail_room - - Add information about `image` and `services` field at `job` level in the `.gitlab-ci.yml` documentation (Pat Turner) - - HTTP error pages work independently from location and config (Artem Sidorenko) - - Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set - - Memoize @group in Admin::GroupsController (Yatish Mehta) - - Indicate how much an MR diverged from the target branch (Pierre de La Morinerie) - - Added omniauth-auth0 Gem (Daniel Carraro) - - Add label description in tooltip to labels in issue index and sidebar - - Strip leading and trailing spaces in URL validator (evuez) - - Add "last_sign_in_at" and "confirmed_at" to GET /users/* API endpoints for admins (evuez) - - Return empty array instead of 404 when commit has no statuses in commit status API - - Decrease the font size and the padding of the `.anchor` icons used in the README (Roberto Dip) - - Rewrite logo to simplify SVG code (Sean Lang) - - Allow to use YAML anchors when parsing the `.gitlab-ci.yml` (Pascal Bach) - - Ignore jobs that start with `.` (hidden jobs) - - Hide builds from project's settings when the feature is disabled - - Allow to pass name of created artifacts archive in `.gitlab-ci.yml` - - Refactor and greatly improve search performance - - Add support for cross-project label references - - Ensure "new SSH key" email do not ends up as dead Sidekiq jobs - - Update documentation to reflect Guest role not being enforced on internal projects - - Allow search for logged out users - - Allow to define on which builds the current one depends on - - Allow user subscription to a label: get notified for issues/merge requests related to that label (Timothy Andrew) - - Fix bug where Bitbucket `closed` issues were imported as `opened` (Iuri de Silvio) - - Don't show Issues/MRs from archived projects in Groups view - - Fix wrong "iid of max iid" in Issuable sidebar for some merged MRs - - Fix empty source_sha on Merge Request when there is no diff (Pierre de La Morinerie) - - Increase the notes polling timeout over time (Roberto Dip) - - Add shortcut to toggle markdown preview (Florent Baldino) - - Show labels in dashboard and group milestone views - - Fix an issue when the target branch of a MR had been deleted - - Add main language of a project in the list of projects (Tiago Botelho) - - Add #upcoming filter to Milestone filter (Tiago Botelho) - - Add ability to show archived projects on dashboard, explore and group pages - - Remove fork link closes all merge requests opened on source project (Florent Baldino) - - Move group activity to separate page - - Create external users which are excluded of internal and private projects unless access was explicitly granted - - Continue parameters are checked to ensure redirection goes to the same instance - - User deletion is now done in the background so the request can not time out - - Canceled builds are now ignored in compound build status if marked as `allowed to fail` - - Trigger a todo for mentions on commits page - - Let project owners and admins soft delete issues and merge requests - -v 8.5.13 - - Prevent unauthorized access to other projects build traces - - Forbid scripting for wiki files - -v 8.5.12 - - Prevent privilege escalation via "impersonate" feature - - Prevent privilege escalation via notes API - - Prevent privilege escalation via project webhook API - - Prevent XSS via Git branch and tag names - - Prevent XSS via custom issue tracker URL - - Prevent XSS via `window.opener` - - Prevent information disclosure via snippet API - - Prevent information disclosure via project labels - - Prevent information disclosure via new merge request page - -v 8.5.11 - - Fix persistent XSS vulnerability in `commit_person_link` helper - -v 8.5.10 - - Fix a 2FA authentication spoofing vulnerability. - -v 8.5.9 - - Don't attempt to fetch any tags from a forked repo (Stan Hu). - -v 8.5.8 - - Bump Git version requirement to 2.7.4 - -v 8.5.7 - - Bump Git version requirement to 2.7.3 - -v 8.5.6 - - Obtain a lease before querying LDAP - -v 8.5.5 - - Ensure removing a project removes associated Todo entries - - Prevent a 500 error in Todos when author was removed - - Fix pagination for filtered dashboard and explore pages - - Fix "Show all" link behavior - -v 8.5.4 - - Do not cache requests for badges (including builds badge) - -v 8.5.3 - - Flush repository caches before renaming projects - - Sort starred projects on dashboard based on last activity by default - - Show commit message in JIRA mention comment - - Makes issue page and merge request page usable on mobile browsers. - - Improved UI for profile settings - -v 8.5.2 - - Fix sidebar overlapping content when screen width was below 1200px - - Don't repeat labels listed on Labels tab - - Bring the "branded appearance" feature from EE to CE - - Fix error 500 when commenting on a commit - - Show days remaining instead of elapsed time for Milestone - - Fix broken icons on installations with relative URL (Artem Sidorenko) - - Fix issue where tag list wasn't refreshed after deleting a tag - - Fix import from gitlab.com (KazSawada) - - Improve implementation to check read access to forks and add pagination - - Don't show any "2FA required" message if it's not actually required - - Fix help keyboard shortcut on relative URL setups (Artem Sidorenko) - - Update Rails to 4.2.5.2 - - Fix permissions for deprecated CI build status badge - - Don't show "Welcome to GitLab" when the search didn't return any projects - - Add Todos documentation - -v 8.5.1 - - Fix group projects styles - - Show Crowd login tab when sign in is disabled and Crowd is enabled (Peter Hudec) - - Fix a set of small UI glitches in project, profile, and wiki pages - - Restrict permissions on public/uploads - - Fix the merge request side-by-side view after loading diff results - - Fix the look of tooltip for the "Revert" button - - Add when the Builds & Runners API changes got introduced - - Fix error 500 on some merged merge requests - - Fix an issue causing the content of the issuable sidebar to disappear - - Fix error 500 when trying to mark an already done todo as "done" - - Fix an issue where MRs weren't sortable - - Issues can now be dragged & dropped into empty milestone lists. This is also - possible with MRs - - Changed padding & background color for highlighted notes - - Re-add the newrelic_rpm gem which was removed without any deprecation or warning (Stan Hu) - - Update sentry-raven gem to 0.15.6 - - Add build coverage in project's builds page (Steffen Köhler) - - Changed # to ! for merge requests in activity view - -v 8.5.0 - - Fix duplicate "me" in tooltip of the "thumbsup" awards Emoji (Stan Hu) - - Cache various Repository methods to improve performance - - Fix duplicated branch creation/deletion Webhooks/service notifications when using Web UI (Stan Hu) - - Ensure rake tasks that don't need a DB connection can be run without one - - Update New Relic gem to 3.14.1.311 (Stan Hu) - - Add "visibility" flag to GET /projects api endpoint - - Add an option to supply root email through an environmental variable (Koichiro Mikami) - - Ignore binary files in code search to prevent Error 500 (Stan Hu) - - Render sanitized SVG images (Stan Hu) - - Support download access by PRIVATE-TOKEN header (Stan Hu) - - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push - - Add option to include the sender name in body of Notify email (Jason Lee) - - New UI for pagination - - Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet - set it up - - API: Added "merge_requests/:merge_request_id/closes_issues" (Gal Schlezinger) - - Fix diff comments loaded by AJAX to load comment with diff in discussion tab - - Fix relative links in other markup formats (Ben Boeckel) - - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) - - Fix label links for a merge request pointing to issues list - - Don't vendor minified JS - - Increase project import timeout to 15 minutes - - Be more permissive with email address validation: it only has to contain a single '@' - - Display 404 error on group not found - - Track project import failure - - Support Two-factor Authentication for LDAP users - - Display database type and version in Administration dashboard - - Allow limited Markdown in Broadcast Messages - - Fix visibility level text in admin area (Zeger-Jan van de Weg) - - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) - - Update the ExternalIssue regex pattern (Blake Hitchcock) - - Remember user's inline/side-by-side diff view preference in a cookie (Kirill Katsnelson) - - Optimized performance of finding issues to be closed by a merge request - - Add `avatar_url`, `description`, `git_ssh_url`, `git_http_url`, `path_with_namespace` - and `default_branch` in `project` in push, issue, merge-request and note webhooks data (Kirill Zaitsev) - - Deprecate the `ssh_url` in favor of `git_ssh_url` and `http_url` in favor of `git_http_url` - in `project` for push, issue, merge-request and note webhooks data (Kirill Zaitsev) - - Deprecate the `repository` key in push, issue, merge-request and note webhooks data, use `project` instead (Kirill Zaitsev) - - API: Expose MergeRequest#merge_status (Andrei Dziahel) - - Revert "Add IP check against DNSBLs at account sign-up" - - Actually use the `skip_merges` option in Repository#commits (Tony Chu) - - Fix API to keep request parameters in Link header (Michael Potthoff) - - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead - - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead - - Prevent parse error when name of project ends with .atom and prevent path issues - - Discover branches for commit statuses ref-less when doing merge when succeeded - - Mark inline difference between old and new paths when a file is renamed - - Support Akismet spam checking for creation of issues via API (Stan Hu) - - API: Allow to set or update a merge-request's milestone (Kirill Skachkov) - - Improve UI consistency between projects and groups lists - - Add sort dropdown to dashboard projects page - - Fixed logo animation on Safari (Roman Rott) - - Fix Merge When Succeeded when multiple stages - - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) - - In seach autocomplete show only groups and projects you are member of - - Don't process cross-reference notes from forks - - Fix: init.d script not working on OS X - - Faster snippet search - - Added API to download build artifacts - - Title for milestones should be unique (Zeger-Jan van de Weg) - - Validate correctness of maximum attachment size application setting - - Replaces "Create merge request" link with one to the "Merge Request" when one exists - - Fix CI builds badge, add a new link to builds badge, deprecate the old one - - Fix broken link to project in build notification emails - - Ability to see and sort on vote count from Issues and MR lists - - Fix builds scheduler when first build in stage was allowed to fail - - User project limit is reached notice is hidden if the projects limit is zero - - Add API support for managing runners and project's runners - - Allow SAML users to login with no previous account without having to allow - all Omniauth providers to do so. - - Allow existing users to auto link their SAML credentials by logging in via SAML - - Make it possible to erase a build (trace, artifacts) using UI and API - - Ability to revert changes from a Merge Request or Commit - - Emoji comment on diffs are not award emoji - - Add label description (Nuttanart Pornprasitsakul) - - Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul) - - Add Todos - -v 8.4.11 - - Prevent unauthorized access to other projects build traces - - Forbid scripting for wiki files - -v 8.4.10 - - Prevent privilege escalation via "impersonate" feature - - Prevent privilege escalation via notes API - - Prevent privilege escalation via project webhook API - - Prevent XSS via Git branch and tag names - - Prevent XSS via custom issue tracker URL - - Prevent XSS via `window.opener` - - Prevent information disclosure via snippet API - - Prevent information disclosure via project labels - - Prevent information disclosure via new merge request page - -v 8.4.9 - - Fix persistent XSS vulnerability in `commit_person_link` helper - -v 8.4.8 - - Fix a 2FA authentication spoofing vulnerability. - -v 8.4.7 - - Don't attempt to fetch any tags from a forked repo (Stan Hu). - -v 8.4.6 - - Bump Git version requirement to 2.7.4 - -v 8.4.5 - - No CE-specific changes - -v 8.4.4 - - Update omniauth-saml gem to 1.4.2 - - Prevent long-running backup tasks from timing out the database connection - - Add a Project setting to allow guests to view build logs (defaults to true) - - Sort project milestones by due date including issue editor (Oliver Rogers / Orih) - -v 8.4.3 - - Increase lfs_objects size column to 8-byte integer to allow files larger - than 2.1GB - - Correctly highlight MR diff when MR has merge conflicts - - Fix highlighting in blame view - - Update sentry-raven gem to prevent "Not a git repository" console output - when running certain commands - - Add instrumentation to additional Gitlab::Git and Rugged methods for - performance monitoring - - Allow autosize textareas to also be manually resized - -v 8.4.2 - - Bump required gitlab-workhorse version to bring in a fix for missing - artifacts in the build artifacts browser - - Get rid of those ugly borders on the file tree view - - Fix updating the runner information when asking for builds - - Bump gitlab_git version to 7.2.24 in order to bring in a performance - improvement when checking if a repository was empty - - Add instrumentation for Gitlab::Git::Repository instance methods so we can - track them in Performance Monitoring. - - Increase contrast between highlighted code comments and inline diff marker - - Fix method undefined when using external commit status in builds - - Fix highlighting in blame view. - -v 8.4.1 - - Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3), - and Nokogiri (1.6.7.2) - - Fix redirect loop during import - - Fix diff highlighting for all syntax themes - - Delete project and associations in a background worker - -v 8.4.0 - - Allow LDAP users to change their email if it was not set by the LDAP server - - Ensure Gravatar host looks like an actual host - - Consider re-assign as a mention from a notification point of view - - Add pagination headers to already paginated API resources - - Properly generate diff of orphan commits, like the first commit in a repository - - Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages - - Autocomplete data is now always loaded, instead of when focusing a comment text area - - Improved performance of finding issues for an entire group - - Added custom application performance measuring system powered by InfluxDB - - Add syntax highlighting to diffs - - Gracefully handle invalid UTF-8 sequences in Markdown links (Stan Hu) - - Bump fog to 1.36.0 (Stan Hu) - - Add user's last used IP addresses to admin page (Stan Hu) - - Add housekeeping function to project settings page - - The default GitLab logo now acts as a loading indicator - - Fix caching issue where build status was not updating in project dashboard (Stan Hu) - - Accept 2xx status codes for successful Webhook triggers (Stan Hu) - - Fix missing date of month in network graph when commits span a month (Stan Hu) - - Expire view caches when application settings change (e.g. Gravatar disabled) (Stan Hu) - - Don't notify users twice if they are both project watchers and subscribers (Stan Hu) - - Remove gray background from layout in UI - - Fix signup for OAuth providers that don't provide a name - - Implement new UI for group page - - Implement search inside emoji picker - - Let the CI runner know about builds that this build depends on - - Add API support for looking up a user by username (Stan Hu) - - Add project permissions to all project API endpoints (Stan Hu) - - Link to milestone in "Milestone changed" system note - - Only allow group/project members to mention `@all` - - Expose Git's version in the admin area (Trey Davis) - - Add "Frequently used" category to emoji picker - - Add CAS support (tduehr) - - Add link to merge request on build detail page - - Fix: Problem with projects ending with .keys (Jose Corcuera) - - Revert back upvote and downvote button to the issue and MR pages - - Swap position of Assignee and Author selector on Issuables (Zeger-Jan van de Weg) - - Add system hook messages for project rename and transfer (Steve Norman) - - Fix version check image in Safari - - Show 'All' tab by default in the builds page - - Add Open Graph and Twitter Card data to all pages - - Fix API project lookups when querying with a namespace with dots (Stan Hu) - - Enable forcing Two-factor authentication sitewide, with optional grace period - - Import GitHub Pull Requests into GitLab - - Change single user API endpoint to return more detailed data (Michael Potthoff) - - Update version check images to use SVG - - Validate README format before displaying - - Enable Microsoft Azure OAuth2 support (Janis Meybohm) - - Properly set task-list class on single item task lists - - Add file finder feature in tree view (Kyungchul Shin) - - Ajax filter by message for commits page - - API: Add support for deleting a tag via the API (Robert Schilling) - - Allow subsequent validations in CI Linter - - Show referenced MRs & Issues only when the current viewer can access them - - Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee) - - Add API support for managing project's builds - - Add API support for managing project's build triggers - - Add API support for managing project's build variables - - Allow broadcast messages to be edited - - Autosize Markdown textareas - - Import GitHub wiki into GitLab - - Add reporters ability to download and browse build artifacts (Andrew Johnson) - - Autofill referring url in message box when reporting user abuse. - - Remove leading comma on award emoji when the user is the first to award the emoji (Zeger-Jan van de Weg) - - Add build artifacts browser - - Improve UX in builds artifacts browser - - Increase default size of `data` column in `events` table when using MySQL - - Expose button to CI Lint tool on project builds page - - Fix: Creator should be added as a master of the project on creation - - Added X-GitLab-... headers to emails from CI and Email On Push services (Anton Baklanov) - - Add IP check against DNSBLs at account sign-up - - Added cache:key to .gitlab-ci.yml allowing to fine tune the caching - -v 8.3.10 - - Prevent unauthorized access to other projects build traces - - Forbid scripting for wiki files - -v 8.3.9 - - Prevent privilege escalation via "impersonate" feature - - Prevent privilege escalation via notes API - - Prevent privilege escalation via project webhook API - - Prevent XSS via custom issue tracker URL - - Prevent XSS via `window.opener` - - Prevent information disclosure via project labels - - Prevent information disclosure via new merge request page - -v 8.3.8 - - Fix persistent XSS vulnerability in `commit_person_link` helper - -v 8.3.7 - - Fix a 2FA authentication spoofing vulnerability. - -v 8.3.6 - - Don't attempt to fetch any tags from a forked repo (Stan Hu). - -v 8.3.5 - - Bump Git version requirement to 2.7.4 - -v 8.3.4 - - Use gitlab-workhorse 0.5.4 (fixes API routing bug) - -v 8.3.3 - - Preserve CE behavior with JIRA integration by only calling API if URL is set - - Fix duplicated branch creation/deletion events when using Web UI (Stan Hu) - - Add configurable LDAP server query timeout - - Get "Merge when build succeeds" to work when commits were pushed to MR target branch while builds were running - - Suppress e-mails on failed builds if allow_failure is set (Stan Hu) - - Fix project transfer e-mail sending incorrect paths in e-mail notification (Stan Hu) - - Better support for referencing and closing issues in Asana service (Mike Wyatt) - - Enable "Add key" button when user fills in a proper key (Stan Hu) - - Fix error in processing reply-by-email messages (Jason Lee) - - Fix Error 500 when visiting build page of project with nil runners_token (Stan Hu) - - Use WOFF versions of SourceSansPro fonts - - Fix regression when builds were not generated for tags created through web/api interface - - Fix: maintain milestone filter between Open and Closed tabs (Greg Smethells) - - Fix missing artifacts and build traces for build created before 8.3 - -v 8.3.2 - - Disable --follow in `git log` to avoid loading duplicate commit data in infinite scroll (Stan Hu) - - Add support for Google reCAPTCHA in user registration - -v 8.3.1 - - Fix Error 500 when global milestones have slashes (Stan Hu) - - Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu) - - Fix LDAP identity and user retrieval when special characters are used - - Move Sidekiq-cron configuration to gitlab.yml - -v 8.3.0 - - Bump rack-attack to 4.3.1 for security fix (Stan Hu) - - API support for starred projects for authorized user (Zeger-Jan van de Weg) - - Add open_issues_count to project API (Stan Hu) - - Expand character set of usernames created by Omniauth (Corey Hinshaw) - - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) - - Add unsubscribe link in the email footer (Zeger-Jan van de Weg) - - Provide better diagnostic message upon project creation errors (Stan Hu) - - Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu) - - Remove api credentials from link to build_page - - Deprecate GitLabCiService making it to always be inactive - - Bump gollum-lib to 4.1.0 (Stan Hu) - - Fix broken group avatar upload under "New group" (Stan Hu) - - Update project repositorize size and commit count during import:repos task (Stan Hu) - - Fix API setting of 'public' attribute to false will make a project private (Stan Hu) - - Handle and report SSL errors in Webhook test (Stan Hu) - - Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu) - - Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera) - - WIP identifier on merge requests no longer requires trailing space - - Add rake tasks for git repository maintainance (Zeger-Jan van de Weg) - - Fix 500 error when update group member permission - - Fix: As an admin, cannot add oneself as a member to a group/project - - Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera) - - Recognize issue/MR/snippet/commit links as references - - Backport JIRA features from EE to CE - - Add ignore whitespace change option to commit view - - Fire update hook from GitLab - - Allow account unlock via email - - Style warning about mentioning many people in a comment - - Fix: sort milestones by due date once again (Greg Smethells) - - Migrate all CI::Services and CI::WebHooks to Services and WebHooks - - Don't show project fork event as "imported" - - Add API endpoint to fetch merge request commits list - - Don't create CI status for refs that doesn't have .gitlab-ci.yml, even if the builds are enabled - - Expose events API with comment information and author info - - Fix: Ensure "Remove Source Branch" button is not shown when branch is being deleted. #3583 - - Run custom Git hooks when branch is created or deleted. - - Fix bug when simultaneously accepting multiple MRs results in MRs that are of "merged" status, but not merged to the target branch - - Add languages page to graphs - - Block LDAP user when they are no longer found in the LDAP server - - Improve wording on project visibility levels (Zeger-Jan van de Weg) - - Fix editing notes on a merge request diff - - Automatically select default clone protocol based on user preferences (Eirik Lygre) - - Make Network page as sub tab of Commits - - Add copy-to-clipboard button for Snippets - - Add indication to merge request list item that MR cannot be merged automatically - - Default target branch to patch-n when editing file in protected branch - - Add Builds tab to merge request detail page - - Allow milestones, issues and MRs to be created from dashboard and group indexes - - Use new style for wiki - - Use new style for milestone detail page - - Fix sidebar tooltips when collapsed - - Prevent possible XSS attack with award-emoji - - Upgraded Sidekiq to 4.x - - Accept COPYING,COPYING.lesser, and licence as license file (Zeger-Jan van de Weg) - - Fix emoji aliases problem - - Fix award-emojis Flash alert's width - - Fix deleting notes on a merge request diff - - Display referenced merge request statuses in the issue description (Greg Smethells) - - Implement new sidebar for issue and merge request pages - - Emoji picker improvements - - Suppress warning about missing `.gitlab-ci.yml` if builds are disabled - - Do not show build status unless builds are enabled and `.gitlab-ci.yml` is present - - Persist runners registration token in database - - Fix online editor should not remove newlines at the end of the file - - Expose Git's version in the admin area - - Show "New Merge Request" buttons on canonical repos when you have a fork (Josh Frye) - -v 8.2.6 - - Prevent unauthorized access to other projects build traces - - Forbid scripting for wiki files - -v 8.2.5 - - Prevent privilege escalation via "impersonate" feature - - Prevent privilege escalation via notes API - - Prevent privilege escalation via project webhook API - - Prevent XSS via `window.opener` - - Prevent information disclosure via project labels - - Prevent information disclosure via new merge request page - -v 8.2.4 - - Bump Git version requirement to 2.7.4 - -v 8.2.3 - - Fix application settings cache not expiring after changes (Stan Hu) - - Fix Error 500s when creating global milestones with Unicode characters (Stan Hu) - - Update documentation for "Guest" permissions - - Properly convert Emoji-only comments into Award Emojis - - Enable devise paranoid mode to prevent user enumeration attack - - Webhook payload has an added, modified and removed properties for each commit - - Fix 500 error when creating a merge request that removes a submodule - -v 8.2.2 - - Fix 404 in redirection after removing a project (Stan Hu) - - Ensure cached application settings are refreshed at startup (Stan Hu) - - Fix Error 500 when viewing user's personal projects from admin page (Stan Hu) - - Fix: Raw private snippets access workflow - - Prevent "413 Request entity too large" errors when pushing large files with LFS - - Fix invalid links within projects dashboard header - - Make current user the first user in assignee dropdown in issues detail page (Stan Hu) - - Fix: duplicate email notifications on issue comments - -v 8.2.1 - - Forcefully update builds that didn't want to update with state machine - - Fix: saving GitLabCiService as Admin Template - -v 8.2.0 - - Improved performance of finding projects and groups in various places - - Improved performance of rendering user profile pages and Atom feeds - - Expose build artifacts path as config option - - Fix grouping of contributors by email in graph. - - Improved performance of finding issues with/without labels - - Fix Drone CI service template not saving properly (Stan Hu) - - Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu) - - Added a GitLab specific profiling tool called "Sherlock" (see GitLab CE merge request #1749) - - Upgrade gitlab_git to 7.2.20 and rugged to 0.23.3 (Stan Hu) - - Improved performance of finding users by one of their Email addresses - - Add allow_failure field to commit status API (Stan Hu) - - Commits without .gitlab-ci.yml are marked as skipped - - Save detailed error when YAML syntax is invalid - - Since GitLab CI is enabled by default, remove enabling it by pushing .gitlab-ci.yml - - Added build artifacts - - Improved performance of replacing references in comments - - Show last project commit to default branch on project home page - - Highlight comment based on anchor in URL - - Adds ability to remove the forked relationship from project settings screen. (Han Loong Liauw) - - Improved performance of sorting milestone issues - - Allow users to select the Files view as default project view (Cristian Bica) - - Show "Empty Repository Page" for repository without branches (Artem V. Navrotskiy) - - Fix: Inability to reply to code comments in the MR view, if the MR comes from a fork - - Use git follow flag for commits page when retrieve history for file or directory - - Show merge request CI status on merge requests index page - - Send build name and stage in CI notification e-mail - - Extend yml syntax for only and except to support specifying repository path - - Enable shared runners to all new projects - - Bump GitLab-Workhorse to 0.4.1 - - Allow to define cache in `.gitlab-ci.yml` - - Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu) - - Remove deprecated CI events from project settings page - - Use issue editor as cross reference comment author when issue is edited with a new mention. - - Add graphs of commits ahead and behind default branch (Jeff Stubler) - - Improve personal snippet access workflow (Douglas Alexandre) - - [API] Add ability to fetch the commit ID of the last commit that actually touched a file - - Fix omniauth documentation setting for omnibus configuration (Jon Cairns) - - Add "New file" link to dropdown on project page - - Include commit logs in project search - - Add "added", "modified" and "removed" properties to commit object in webhook - - Rename "Back to" links to "Go to" because its not always a case it point to place user come from - - Allow groups to appear in the search results if the group owner allows it - - Add email notification to former assignee upon unassignment (Adam Lieskovský) - - New design for project graphs page - - Remove deprecated dumped yaml file generated from previous job definitions - - Show specific runners from projects where user is master or owner - - MR target branch is now visible on a list view when it is different from project's default one - - Improve Continuous Integration graphs page - - Make color of "Accept Merge Request" button consistent with current build status - - Add ignore white space option in merge request diff and commit and compare view - - Ability to add release notes (markdown text and attachments) to git tags (aka Releases) - - Relative links from a repositories README.md now link to the default branch - - Fix trailing whitespace issue in merge request/issue title - - Fix bug when milestone/label filter was empty for dashboard issues page - - Add ability to create milestone in group projects from single form - - Add option to create merge request when editing/creating a file (Dirceu Tiegs) - - Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master (James Lopez) - - Add Award Emoji to issue and merge request pages - -v 8.1.4 - - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) - - Prevent redirect loop when home_page_url is set to the root URL - - Fix incoming email config defaults - - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) - -v 8.1.3 - - Force update refs/merge-requests/X/head upon a push to the source branch of a merge request (Stan Hu) - - Spread out runner contacted_at updates - - Use issue editor as cross reference comment author when issue is edited with a new mention - - Add Facebook authentication - -v 8.1.2 - - Fix cloning Wiki repositories via HTTP (Stan Hu) - - Add migration to remove satellites directory - - Fix specific runners visibility - - Fix 500 when editing CI service - - Require CI jobs to be named - - Fix CSS for runner status - - Fix CI badge - - Allow developer to manage builds - -v 8.1.1 - - Removed, see 8.1.2 - -v 8.1.0 - - Ensure MySQL CI limits DB migrations occur after the fields have been created (Stan Hu) - - Fix duplicate repositories in GitHub import page (Stan Hu) - - Redirect to a default path if HTTP_REFERER is not set (Stan Hu) - - Adds ability to create directories using the web editor (Ben Ford) - - Cleanup stuck CI builds - - Send an email to admin email when a user is reported for spam (Jonathan Rochkind) - - Show notifications button when user is member of group rather than project (Grzegorz Bizon) - - Fix bug preventing mentioned issued from being closed when MR is merged using fast-forward merge. - - Fix nonatomic database update potentially causing project star counts to go negative (Stan Hu) - - Don't show "Add README" link in an empty repository if user doesn't have access to push (Stan Hu) - - Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu) - - Speed up load times of issue detail pages by roughly 1.5x - - Fix CI rendering regressions - - If a merge request is to close an issue, show this on the issue page (Zeger-Jan van de Weg) - - Add a system note and update relevant merge requests when a branch is deleted or re-added (Stan Hu) - - Make diff file view easier to use on mobile screens (Stan Hu) - - Improved performance of finding users by username or Email address - - Fix bug where merge request comments created by API would not trigger notifications (Stan Hu) - - Add support for creating directories from Files page (Stan Hu) - - Allow removing of project without confirmation when JavaScript is disabled (Stan Hu) - - Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu) - - Improved performance of the trending projects page - - Remove CI migration task - - Improved performance of finding projects by their namespace - - Add assignee data to Issuables' hook_data (Bram Daams) - - Fix bug where transferring a project would result in stale commit links (Stan Hu) - - Fix build trace updating - - Include full path of source and target branch names in New Merge Request page (Stan Hu) - - Add user preference to view activities as default dashboard (Stan Hu) - - Add option to admin area to sign in as a specific user (Pavel Forkert) - - Show CI status on all pages where commits list is rendered - - Automatically enable CI when push .gitlab-ci.yml file to repository - - Move CI charts to project graphs area - - Fix cases where Markdown did not render links in activity feed (Stan Hu) - - Add first and last to pagination (Zeger-Jan van de Weg) - - Added Commit Status API - - Added Builds View - - Added when to .gitlab-ci.yml - - Show CI status on commit page - - Added CI_BUILD_TAG, _STAGE, _NAME and _TRIGGERED to CI builds - - Show CI status on Your projects page and Starred projects page - - Remove "Continuous Integration" page from dashboard - - Add notes and SSL verification entries to hook APIs (Ben Boeckel) - - Fix grammar in admin area "labels" .nothing-here-block when no labels exist. - - Move CI runners page to project settings area - - Move CI variables page to project settings area - - Move CI triggers page to project settings area - - Move CI project settings page to CE project settings area - - Fix bug when removed file was not appearing in merge request diff - - Show warning when build cannot be served by any of the available CI runners - - Note the original location of a moved project when notifying users of the move - - Improve error message when merging fails - - Add support of multibyte characters in LDAP UID (Roman Petrov) - - Show additions/deletions stats on merge request diff - - Remove footer text in emails (Zeger-Jan van de Weg) - - Ensure code blocks are properly highlighted after a note is updated - - Fix wrong access level badge on MR comments - - Hide password in the service settings form - - Move CI webhooks page to project settings area - - Fix User Identities API. It now allows you to properly create or update user's identities. - - Add user preference to change layout width (Peter Göbel) - - Use commit status in merge request widget as preferred source of CI status - - Integrate CI commit and build pages into project pages - - Move CI services page to project settings area - - Add "Quick Submit" behavior to input fields throughout the application. Use - Cmd+Enter on Mac and Ctrl+Enter on Windows/Linux. - - Fix position of hamburger in header for smaller screens (Han Loong Liauw) - - Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji) - - Persist filters when sorting on admin user page (Jerry Lukins) - - Update style of snippets pages (Han Loong Liauw) - - Allow dashboard and group issues/MRs to be filtered by label - - Add spellcheck=false to certain input fields - - Invalidate stored service password if the endpoint URL is changed - - Project names are not fully shown if group name is too big, even on group page view - - Apply new design for Files page - - Add "New Page" button to Wiki Pages tab (Stan Hu) - - Only render 404 page from /public - - Hide passwords from services API (Alex Lossent) - - Fix: Images cannot show when projects' path was changed - - Let gitlab-git-http-server generate and serve 'git archive' downloads - - Optimize query when filtering on issuables (Zeger-Jan van de Weg) - - Fix padding of outdated discussion item. - - Animate the logo on hover - -v 8.0.5 - - Correct lookup-by-email for LDAP logins - - Fix loading spinner sometimes not being hidden on Merge Request tab switches - -v 8.0.4 - - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) - - Fix referrals for :back and relative URL installs - - Fix anchors to comments in diffs - - Remove CI token from build traces - - Fix "Assign All" button on Runner admin page - - Fix search in Files - - Add full project namespace to payload of system webhooks (Ricardo Band) - -v 8.0.3 - - Fix URL shown in Slack notifications - - Fix bug where projects would appear to be stuck in the forked import state (Stan Hu) - - Fix Error 500 in creating merge requests with > 1000 diffs (Stan Hu) - - Add work_in_progress key to MR webhooks (Ben Boeckel) - -v 8.0.2 - - Fix default avatar not rendering in network graph (Stan Hu) - - Skip check_initd_configured_correctly on omnibus installs - - Prevent double-prefixing of help page paths - - Clarify confirmation text on user deletion - - Make commit graphs responsive to window width changes (Stan Hu) - - Fix top margin for sign-in button on public pages - - Fix LDAP attribute mapping - - Remove git refs used internally by GitLab from network graph (Stan Hu) - - Use standard Markdown font in Markdown preview instead of fixed-width font (Stan Hu) - - Fix Reply by email for non-UTF-8 messages. - - Add option to use StartTLS with Reply by email IMAP server. - - Allow AWS S3 Server-Side Encryption with Amazon S3-Managed Keys for backups (Paul Beattie) - -v 8.0.1 - - Improve CI migration procedure and documentation - -v 8.0.0 - - Fix Markdown links not showing up in dashboard activity feed (Stan Hu) - - Remove milestones from merge requests when milestones are deleted (Stan Hu) - - Fix HTML link that was improperly escaped in new user e-mail (Stan Hu) - - Fix broken sort in merge request API (Stan Hu) - - Bump rouge to 1.10.1 to remove warning noise and fix other syntax highlighting bugs (Stan Hu) - - Gracefully handle errors in syntax highlighting by leaving the block unformatted (Stan Hu) - - Add "replace" and "upload" functionalities to allow user replace existing file and upload new file into current repository - - Fix URL construction for merge requests, issues, notes, and commits for relative URL config (Stan Hu) - - Fix emoji URLs in Markdown when relative_url_root is used (Stan Hu) - - Omit filename in Content-Disposition header in raw file download to avoid RFC 6266 encoding issues (Stan HU) - - Fix broken Wiki Page History (Stan Hu) - - Import forked repositories asynchronously to prevent large repositories from timing out (Stan Hu) - - Prevent anchors from being hidden by header (Stan Hu) - - Fix bug where only the first 15 Bitbucket issues would be imported (Stan Hu) - - Sort issues by creation date in Bitbucket importer (Stan Hu) - - Prevent too many redirects upon login when home page URL is set to external_url (Stan Hu) - - Improve dropdown positioning on the project home page (Hannes Rosenögger) - - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibilty mode (Stan Hu) - - Remove user OAuth tokens from the database and request new tokens each session (Stan Hu) - - Restrict users API endpoints to use integer IDs (Stan Hu) - - Only show recent push event if the branch still exists or a recent merge request has not been created (Stan Hu) - - Remove satellites - - Better performance for web editor (switched from satellites to rugged) - - Faster merge - - Ability to fetch merge requests from refs/merge-requests/:id - - Allow displaying of archived projects in the admin interface (Artem Sidorenko) - - Allow configuration of import sources for new projects (Artem Sidorenko) - - Search for comments should be case insensetive - - Create cross-reference for closing references on commits pushed to non-default branches (Maël Valais) - - Ability to search milestones - - Gracefully handle SMTP user input errors (e.g. incorrect email addresses) to prevent Sidekiq retries (Stan Hu) - - Move dashboard activity to separate page (for your projects and starred projects) - - Improve performance of git blame - - Limit content width to 1200px for most of pages to improve readability on big screens - - Fix 500 error when submit project snippet without body - - Improve search page usability - - Bring more UI consistency in way how projects, snippets and groups lists are rendered - - Make all profiles and group public - - Fixed login failure when extern_uid changes (Joel Koglin) - - Don't notify users without access to the project when they are (accidentally) mentioned in a note. - - Retrieving oauth token with LDAP credentials - - Load Application settings from running database unless env var USE_DB=false - - Added Drone CI integration (Kirill Zaitsev) - - Allow developers to retry builds - - Hide advanced project options for non-admin users - - Fail builds if no .gitlab-ci.yml is found - - Refactored service API and added automatically service docs generator (Kirill Zaitsev) - - Added web_url key project hook_attrs (Kirill Zaitsev) - - Add ability to get user information by ID of an SSH key via the API - - Fix bug which IE cannot show image at markdown when the image is raw file of gitlab - - Add support for Crowd - - Global Labels that are available to all projects - - Fix highlighting of deleted lines in diffs. - - Project notification level can be set on the project page itself - - Added service API endpoint to retrieve service parameters (Petheő Bence) - - Add FogBugz project import (Jared Szechy) - - Sort users autocomplete lists by user (Allister Antosik) - - Webhook for issue now contains repository field (Jungkook Park) - - Add ability to add custom text to the help page (Jeroen van Baarsen) - - Add pg_schema to backup config - - Fix references to target project issues in Merge Requests markdown preview and textareas (Francesco Levorato) - - Redirect from incorrectly cased group or project path to correct one (Francesco Levorato) - - Removed API calls from CE to CI - -v 7.14.3 through 0.8.0 - - See changelogs/archive.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000000..46f718fc88a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2465 @@ +Please view this file on the master branch, on stable branches it's out of date. + +## 8.13.0 (2016-10-22) + + - Improve Merge When Build Succeeds triggers and execute on pipeline success. (!6675) + - Respond with 404 Not Found for non-existent tags (Linus Thiel) + - Truncate long labels with ellipsis in labels page + - Improve tabbing usability for sign in page (ClemMakesApps) + - Enforce TrailingSemicolon and EmptyLineBetweenBlocks in scss-lint + - Adding members no longer silently fails when there is extra whitespace + - Update runner version only when updating contacted_at + - Add link from system note to compare with previous version + - Use gitlab-shell v3.6.6 + - Add `/projects/visible` API endpoint (Ben Boeckel) + - Fix centering of custom header logos (Ashley Dumaine) + - ExpireBuildArtifactsWorker query builds table without ordering enqueuing one job per build to cleanup + - Add an example for testing a phoenix application with Gitlab CI in the docs (Manthan Mallikarjun) + - Updating verbiage on git basics to be more intuitive + - Clarify documentation for Runners API (Gennady Trafimenkov) + - The instrumentation for Banzai::Renderer has been restored + - Change user & group landing page routing from /u/:username to /:username + - Prevent running GfmAutocomplete setup for each diff note !6569 + - Added documentation for .gitattributes files + - AbstractReferenceFilter caches project_refs on RequestStore when active + - Replaced the check sign to arrow in the show build view. !6501 + - Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar) + - Fix Error 500 when viewing old merge requests with bad diff data + - Create a new /templates namespace for the /licenses, /gitignores and /gitlab_ci_ymls API endpoints. !5717 (tbalthazar) + - Speed-up group milestones show page + - Fix inconsistent options dropdown caret on mobile viewports (ClemMakesApps) + - Extract project#update_merge_requests and SystemHooks to its own worker from GitPushService + - Don't include archived projects when creating group milestones. !4940 (Jeroen Jacobs) + - Add tag shortcut from the Commit page. !6543 + - Keep refs for each deployment + - Allow browsing branches that end with '.atom' + - Log LDAP lookup errors and don't swallow unrelated exceptions. !6103 (Markus Koller) + - Replace unique keyframes mixin with keyframe mixin with specific names (ClemMakesApps) + - Add more tests for calendar contribution (ClemMakesApps) + - Update Gitlab Shell to fix some problems with moving projects between storages + - Cache rendered markdown in the database, rather than Redis + - Avoid database queries on Banzai::ReferenceParser::BaseParser for nodes without references + - Do not alter 'force_remove_source_branch' options on MergeRequest unless specified + - Simplify Mentionable concern instance methods + - API: Ability to retrieve version information (Robert Schilling) + - Fix permission for setting an issue's due date + - API: Multi-file commit !6096 (mahcsig) + - Unicode emoji are now converted to images + - Revert "Label list shows all issues (opened or closed) with that label" + - Expose expires_at field when sharing project on API + - Fix VueJS template tags being rendered in code comments + - Added copy file path button to merge request diff files + - Fix issue with page scrolling to top when closing or pinning sidebar (lukehowell) + - Add Issue Board API support (andrebsguedes) + - Allow the Koding integration to be configured through the API + - Add new issue button to each list on Issues Board + - Added soft wrap button to repository file/blob editor + - Update namespace validation to forbid reserved names (.git and .atom) (Will Starms) + - Show the time ago a merge request was deployed to an environment + - Add word-wrap to issue title on issue and milestone boards (ClemMakesApps) + - Fix todos page mobile viewport layout (ClemMakesApps) + - Fix inconsistent highlighting of already selected activity nav-links (ClemMakesApps) + - Remove redundant mixins (ClemMakesApps) + - Added 'Download' button to the Snippets page (Justin DiPierro) + - Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison) + - Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska) + - Fix that manual jobs would no longer block jobs in the next stage. !6604 + - Add configurable email subject suffix (Fu Xu) + - Use defined colour for a language when available !6748 (nilsding) + - Added tooltip to fork count on project show page. (Justin DiPierro) + - Use a ConnectionPool for Rails.cache on Sidekiq servers + - Replace `alias_method_chain` with `Module#prepend` + - Enable GitLab Import/Export for non-admin users. + - Preserve label filters when sorting !6136 (Joseph Frazier) + - MergeRequest#new form load diff asynchronously + - Only update issuable labels if they have been changed + - Take filters in account in issuable counters. !6496 + - Use custom Ruby images to test builds (registry.dev.gitlab.org/gitlab/gitlab-build-images:*) + - Prevent flash alert text from being obscured when container is fluid + - Append issue template to existing description !6149 (Joseph Frazier) + - Trending projects now only show public projects and the list of projects is cached for a day + - Memoize Gitlab Shell's secret token (!6599, Justin DiPierro) + - Revoke button in Applications Settings underlines on hover. + - Use higher size on Gitlab::Redis connection pool on Sidekiq servers + - Add missing values to linter !6276 (Katarzyna Kobierska Ula Budziszewska) + - Fix Long commit messages overflow viewport in file tree + - Revert avoid touching file system on Build#artifacts? + - Stop using a Redis lease when updating the project activity timestamp whenever a new event is created + - Add disabled delete button to protected branches (ClemMakesApps) + - Add broadcast messages and alerts below sub-nav + - Better empty state for Groups view + - API: New /users/:id/events endpoint + - Update ruby-prof to 0.16.2. !6026 (Elan Ruusamäe) + - Replace bootstrap caret with fontawesome caret (ClemMakesApps) + - Fix unnecessary escaping of reserved HTML characters in milestone title. !6533 + - Add organization field to user profile + - Ignore deployment for statistics in Cycle Analytics, except in staging and production stages + - Fix enter key when navigating search site search dropdown. !6643 (Brennan Roberts) + - Fix deploy status responsiveness error !6633 + - Make searching for commits case insensitive + - Fix resolved discussion display in side-by-side diff view !6575 + - Optimize GitHub importing for speed and memory + - API: expose pipeline data in builds API (!6502, Guilherme Salazar) + - Notify the Merger about merge after successful build (Dimitris Karakasilis) + - Reorder issue and merge request titles to show IDs first. !6503 (Greg Laubenstein) + - Reduce queries needed to find users using their SSH keys when pushing commits + - Prevent rendering the link to all when the author has no access (Katarzyna Kobierska Ula Budziszewska) + - Fix broken repository 500 errors in project list + - Fix Pipeline list commit column width should be adjusted + - Close todos when accepting merge requests via the API !6486 (tonygambone) + - Ability to batch assign issues relating to a merge request to the author. !5725 (jamedjo) + - Changed Slack service user referencing from full name to username (Sebastian Poxhofer) + - Retouch environments list and deployments list + - Add multiple command support for all label related slash commands !6780 (barthc) + - Add Container Registry on/off status to Admin Area !6638 (the-undefined) + - Allow empty merge requests !6384 (Artem Sidorenko) + - Grouped pipeline dropdown is a scrollable container + - Cleanup Ci::ApplicationController. !6757 (Takuya Noguchi) + - Fixes padding in all clipboard icons that have .btn class + - Fix a typo in doc/api/labels.md + - API: all unknown routing will be handled with 404 Not Found + - Add docs for request profiling + - Make guests unable to view MRs on private projects + +## 8.12.7 + + - Use gitlab-markup gem instead of github-markup to fix `.rst` file rendering. !6659 + - Fix GFM autocomplete setup being called several times + +## 8.12.6 + + - Update mailroom to 0.8.1 in Gemfile.lock !6814 + +## 8.12.5 + + - Switch from request to env in ::API::Helpers. !6615 + - Update the mail_room gem to 0.8.1 to fix a race condition with the mailbox watching thread. !6714 + - Improve issue load time performance by avoiding ORDER BY in find_by call. !6724 + - Add a new gitlab:users:clear_all_authentication_tokens task. !6745 + - Don't send Private-Token (API authentication) headers to Sentry + - Share projects via the API only with groups the authenticated user can access + +## 8.12.4 + + - Fix "Copy to clipboard" tooltip to say "Copied!" when clipboard button is clicked. !6294 (lukehowell) + - Fix padding in build sidebar. !6506 + - Changed compare dropdowns to dropdowns with isolated search input. !6550 + - Fix race condition on LFS Token. !6592 + - Fix type mismatch bug when closing Jira issue. !6619 + - Fix lint-doc error. !6623 + - Skip wiki creation when GitHub project has wiki enabled. !6665 + - Fix issues importing services via Import/Export. !6667 + - Restrict failed login attempts for users with 2FA enabled. !6668 + - Fix failed project deletion when feature visibility set to private. !6688 + - Prevent claiming associated model IDs via import. + - Set GitLab project exported file permissions to owner only + - Improve the way merge request versions are compared with each other + +## 8.12.3 + + - Update Gitlab Shell to support low IO priority for storage moves + +## 8.12.2 + + - Fix Import/Export not recognising correctly the imported services. + - Fix snippets pagination + - Fix "Create project" button layout when visibility options are restricted + - Fix List-Unsubscribe header in emails + - Fix IssuesController#show degradation including project on loaded notes + - Fix an issue with the "Commits" section of the cycle analytics summary. !6513 + - Fix errors importing project feature and milestone models using GitLab project import + - Make JWT messages Docker-compatible + - Fix duplicate branch entry in the merge request version compare dropdown + - Respect the fork_project permission when forking projects + - Only update issuable labels if they have been changed + - Fix bug where 'Search results' repeated many times when a search in the emoji search form is cleared (Xavier Bick) (@zeiv) + - Fix resolve discussion buttons endpoint path + - Refactor remnants of CoffeeScript destructured opts and super !6261 + +## 8.12.1 + + - Fix a memory leak in HTML::Pipeline::SanitizationFilter::WHITELIST + - Fix issue with search filter labels not displaying + +## 8.12.0 (2016-09-22) + + - Removes inconsistency regarding tagging immediatelly as merged once you create a new branch. !6408 + - Update the rouge gem to 2.0.6, which adds highlighting support for JSX, Prometheus, and others. !6251 + - Only check :can_resolve permission if the note is resolvable + - Bump fog-aws to v0.11.0 to support ap-south-1 region + - Add ability to fork to a specific namespace using API. (ritave) + - Allow to set request_access_enabled for groups and projects + - Cleanup misalignments in Issue list view !6206 + - Only create a protected branch upon a push to a new branch if a rule for that branch doesn't exist + - Add Pipelines for Commit + - Prune events older than 12 months. (ritave) + - Prepend blank line to `Closes` message on merge request linked to issue (lukehowell) + - Fix issues/merge-request templates dropdown for forked projects + - Filter tags by name !6121 + - Update gitlab shell secret file also when it is empty. !3774 (glensc) + - Give project selection dropdowns responsive width, make non-wrapping. + - Fix note form hint showing slash commands supported for commits. + - Make push events have equal vertical spacing. + - API: Ensure invitees are not returned in Members API. + - Preserve applied filters on issues search. + - Add two-factor recovery endpoint to internal API !5510 + - Pass the "Remember me" value to the U2F authentication form + - Display stages in valid order in stages dropdown on build page + - Only update projects.last_activity_at once per hour when creating a new event + - Cycle analytics (first iteration) !5986 + - Remove vendor prefixes for linear-gradient CSS (ClemMakesApps) + - Move pushes_since_gc from the database to Redis + - Limit number of shown environments on Merge Request: show only environments for target_branch, source_branch and tags + - Add font color contrast to external label in admin area (ClemMakesApps) + - Fix find file navigation links (ClemMakesApps) + - Change logo animation to CSS (ClemMakesApps) + - Instructions for enabling Git packfile bitmaps !6104 + - Use Search::GlobalService.new in the `GET /projects/search/:query` endpoint + - Fix long comments in diffs messing with table width + - Add spec covering 'Gitlab::Git::committer_hash' !6433 (dandunckelman) + - Fix pagination on user snippets page + - Honor "fixed layout" preference in more places !6422 + - Run CI builds with the permissions of users !5735 + - Fix sorting of issues in API + - Fix download artifacts button links !6407 + - Sort project variables by key. !6275 (Diego Souza) + - Ensure specs on sorting of issues in API are deterministic on MySQL + - Added ability to use predefined CI variables for environment name + - Added ability to specify URL in environment configuration in gitlab-ci.yml + - Escape search term before passing it to Regexp.new !6241 (winniehell) + - Fix pinned sidebar behavior in smaller viewports !6169 + - Fix file permissions change when updating a file on the Gitlab UI !5979 + - Added horizontal padding on build page sidebar on code coverage block. !6196 (Vitaly Baev) + - Change merge_error column from string to text type + - Fix issue with search filter labels not displaying + - Reduce contributions calendar data payload (ClemMakesApps) + - Show all pipelines for merge requests even from discarded commits !6414 + - Replace contributions calendar timezone payload with dates (ClemMakesApps) + - Changed MR widget build status to pipeline status !6335 + - Add `web_url` field to issue, merge request, and snippet API objects (Ben Boeckel) + - Enable pipeline events by default !6278 + - Move parsing of sidekiq ps into helper !6245 (pascalbetz) + - Added go to issue boards keyboard shortcut + - Expose `sha` and `merge_commit_sha` in merge request API (Ben Boeckel) + - Emoji can be awarded on Snippets !4456 + - Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling) + - Fix blame table layout width + - Spec testing if issue authors can read issues on private projects + - Fix bug where pagination is still displayed despite all todos marked as done (ClemMakesApps) + - Request only the LDAP attributes we need !6187 + - Center build stage columns in pipeline overview (ClemMakesApps) + - Fix bug with tooltip not hiding on discussion toggle button + - Rename behaviour to behavior in bug issue template for consistency (ClemMakesApps) + - Fix bug stopping issue description being scrollable after selecting issue template + - Remove suggested colors hover underline (ClemMakesApps) + - Fix jump to discussion button being displayed on commit notes + - Shorten task status phrase (ClemMakesApps) + - Fix project visibility level fields on settings + - Add hover color to emoji icon (ClemMakesApps) + - Increase ci_builds artifacts_size column to 8-byte integer to allow larger files + - Add textarea autoresize after comment (ClemMakesApps) + - Do not write SSH public key 'comments' to authorized_keys !6381 + - Add due date to issue todos + - Refresh todos count cache when an Issue/MR is deleted + - Fix branches page dropdown sort alignment (ClemMakesApps) + - Hides merge request button on branches page is user doesn't have permissions + - Add white background for no readme container (ClemMakesApps) + - API: Expose issue confidentiality flag. (Robert Schilling) + - Fix markdown anchor icon interaction (ClemMakesApps) + - Test migration paths from 8.5 until current release !4874 + - Replace animateEmoji timeout with eventListener (ClemMakesApps) + - Show badges in Milestone tabs. !5946 (Dan Rowden) + - Optimistic locking for Issues and Merge Requests (title and description overriding prevention) + - Require confirmation when not logged in for unsubscribe links !6223 (Maximiliano Perez Coto) + - Add `wiki_page_events` to project hook APIs (Ben Boeckel) + - Remove Gitorious import + - Loads GFM autocomplete source only when required + - Fix issue with slash commands not loading on new issue page + - Fix inconsistent background color for filter input field (ClemMakesApps) + - Remove prefixes from transition CSS property (ClemMakesApps) + - Add Sentry logging to API calls + - Add BroadcastMessage API + - Merge request tabs are fixed when scrolling page + - Use 'git update-ref' for safer web commits !6130 + - Sort pipelines requested through the API + - Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling) + - Fix issue boards loading on large screens + - Change pipeline duration to be jobs running time instead of simple wall time from start to end !6084 + - Show queued time when showing a pipeline !6084 + - Remove unused mixins (ClemMakesApps) + - Fix issue board label filtering appending already filtered labels + - Add search to all issue board lists + - Scroll active tab into view on mobile + - Fix groups sort dropdown alignment (ClemMakesApps) + - Add horizontal scrolling to all sub-navs on mobile viewports (ClemMakesApps) + - Use JavaScript tooltips for mentions !5301 (winniehell) + - Add hover state to todos !5361 (winniehell) + - Fix icon alignment of star and fork buttons !5451 (winniehell) + - Fix alignment of icon buttons !5887 (winniehell) + - Added Ubuntu 16.04 support for packager.io (JonTheNiceGuy) + - Fix markdown help references (ClemMakesApps) + - Add last commit time to repo view (ClemMakesApps) + - Fix accessibility and visibility of project list dropdown button !6140 + - Fix missing flash messages on service edit page (airatshigapov) + - Added project-specific enable/disable setting for LFS !5997 + - Added group-specific enable/disable setting for LFS !6164 + - Add optional 'author' param when making commits. !5822 (dandunckelman) + - Don't expose a user's token in the `/api/v3/user` API (!6047) + - Remove redundant js-timeago-pending from user activity log (ClemMakesApps) + - Ability to manage project issues, snippets, wiki, merge requests and builds access level + - Remove inconsistent font weight for sidebar's labels (ClemMakesApps) + - Align add button on repository view (ClemMakesApps) + - Fix contributions calendar month label truncation (ClemMakesApps) + - Import release note descriptions from GitHub (EspadaV8) + - Added tests for diff notes + - Add pipeline events to Slack integration !5525 + - Add a button to download latest successful artifacts for branches and tags !5142 + - Remove redundant pipeline tooltips (ClemMakesApps) + - Expire commit info views after one day, instead of two weeks, to allow for user email updates + - Add delimiter to project stars and forks count (ClemMakesApps) + - Fix badge count alignment (ClemMakesApps) + - Remove green outline from `New branch unavailable` button on issue page !5858 (winniehell) + - Fix repo title alignment (ClemMakesApps) + - Change update interval of contacted_at + - Add LFS support to SSH !6043 + - Fix branch title trailing space on hover (ClemMakesApps) + - Don't include 'Created By' tag line when importing from GitHub if there is a linked GitLab account (EspadaV8) + - Award emoji tooltips containing more than 10 usernames are now truncated !4780 (jlogandavison) + - Fix duplicate "me" in award emoji tooltip !5218 (jlogandavison) + - Order award emoji tooltips in order they were added (EspadaV8) + - Fix spacing and vertical alignment on build status icon on commits page (ClemMakesApps) + - Update merge_requests.md with a simpler way to check out a merge request. !5944 + - Fix button missing type (ClemMakesApps) + - Gitlab::Checks is now instrumented + - Move to project dropdown with infinite scroll for better performance + - Fix leaking of submit buttons outside the width of a main container !18731 (originally by @pavelloz) + - Load branches asynchronously in Cherry Pick and Revert dialogs. + - Convert datetime coffeescript spec to ES6 (ClemMakesApps) + - Add merge request versions !5467 + - Change using size to use count and caching it for number of group members. !5935 + - Replace play icon font with svg (ClemMakesApps) + - Added 'only_allow_merge_if_build_succeeds' project setting in the API. !5930 (Duck) + - Reduce number of database queries on builds tab + - Wrap text in commit message containers + - Capitalize mentioned issue timeline notes (ClemMakesApps) + - Fix inconsistent checkbox alignment (ClemMakesApps) + - Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger) + - Adds response mime type to transaction metric action when it's not HTML + - Fix hover leading space bug in pipeline graph !5980 + - Avoid conflict with admin labels when importing GitHub labels + - User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496 + - Fix repository page ui issues + - Avoid protected branches checks when verifying access without branch name + - Add information about user and manual build start to runner as variables !6201 (Sergey Gnuskov) + - Fixed invisible scroll controls on build page on iPhone + - Fix error on raw build trace download for old builds stored in database !4822 + - Refactor the triggers page and documentation !6217 + - Show values of CI trigger variables only when clicked (Katarzyna Kobierska Ula Budziszewska) + - Use default clone protocol on "check out, review, and merge locally" help page URL + - Let the user choose a namespace and name on GitHub imports + - API for Ci Lint !5953 (Katarzyna Kobierska Urszula Budziszewska) + - Allow bulk update merge requests from merge requests index page + - Ensure validation messages are shown within the milestone form + - Add notification_settings API calls !5632 (mahcsig) + - Remove duplication between project builds and admin builds view !5680 (Katarzyna Kobierska Ula Budziszewska) + - Fix URLs with anchors in wiki !6300 (houqp) + - Deleting source project with existing fork link will close all related merge requests !6177 (Katarzyna Kobierska Ula Budziszeska) + - Return 204 instead of 404 for /ci/api/v1/builds/register.json if no builds are scheduled for a runner !6225 + - Fix Gitlab::Popen.popen thread-safety issue + - Add specs to removing project (Katarzyna Kobierska Ula Budziszewska) + - Clean environment variables when running git hooks + - Fix Import/Export issues importing protected branches and some specific models + - Fix non-master branch readme display in tree view + - Add UX improvements for merge request version diffs + +## 8.11.9 + + - Don't send Private-Token (API authentication) headers to Sentry + - Share projects via the API only with groups the authenticated user can access + +## 8.11.8 + + - Respect the fork_project permission when forking projects + - Set a restrictive CORS policy on the API for credentialed requests + - API: disable rails session auth for non-GET/HEAD requests + - Escape HTML nodes in builds commands in CI linter + +## 8.11.7 + + - Avoid conflict with admin labels when importing GitHub labels. !6158 + - Restores `fieldName` to allow only string values in `gl_dropdown.js`. !6234 + - Allow the Rails cookie to be used for API authentication. + - Login/Register UX upgrade !6328 + +## 8.11.6 + + - Fix unnecessary horizontal scroll area in pipeline visualizations. !6005 + - Make merge conflict file size limit 200 KB, to match the docs. !6052 + - Fix an error where we were unable to create a CommitStatus for running state. !6107 + - Optimize discussion notes resolving and unresolving. !6141 + - Fix GitLab import button. !6167 + - Restore SSH Key title auto-population behavior. !6186 + - Fix DB schema to match latest migration. !6256 + - Exclude some pending or inactivated rows in Member scopes. + +## 8.11.5 + + - Optimize branch lookups and force a repository reload for Repository#find_branch. !6087 + - Fix member expiration date picker after update. !6184 + - Fix suggested colors options for new labels in the admin area. !6138 + - Optimize discussion notes resolving and unresolving + - Fix GitLab import button + - Fix confidential issues being exposed as public using gitlab.com export + - Remove gitorious from import_sources. !6180 + - Scope webhooks/services that will run for confidential issues + - Remove gitorious from import_sources + - Fix confidential issues being exposed as public using gitlab.com export + - Use oj gem for faster JSON processing + +## 8.11.4 + + - Fix resolving conflicts on forks. !6082 + - Fix diff commenting on merge requests created prior to 8.10. !6029 + - Fix pipelines tab layout regression. !5952 + - Fix "Wiki" link not appearing in navigation for projects with external wiki. !6057 + - Do not enforce using hash with hidden key in CI configuration. !6079 + - Fix hover leading space bug in pipeline graph !5980 + - Fix sorting issues by "last updated" doesn't work after import from GitHub + - GitHub importer use default project visibility for non-private projects + - Creating an issue through our API now emails label subscribers !5720 + - Block concurrent updates for Pipeline + - Don't create groups for unallowed users when importing projects + - Fix issue boards leak private label names and descriptions + - Fix broken gitlab:backup:restore because of bad permissions on repo storage !6098 (Dirk Hörner) + - Remove gitorious. !5866 + - Allow compare merge request versions + +## 8.11.3 + + - Allow system info page to handle case where info is unavailable + - Label list shows all issues (opened or closed) with that label + - Don't show resolve conflicts link before MR status is updated + - Fix IE11 fork button bug !5982 + - Don't prevent viewing the MR when git refs for conflicts can't be found on disk + - Fix external issue tracker "Issues" link leading to 404s + - Don't try to show merge conflict resolution info if a merge conflict contains non-UTF-8 characters + - Automatically expand hidden discussions when accessed by a permalink !5585 (Mike Greiling) + - Issues filters reset button + +## 8.11.2 + + - Show "Create Merge Request" widget for push events to fork projects on the source project. !5978 + - Use gitlab-workhorse 0.7.11 !5983 + - Does not halt the GitHub import process when an error occurs. !5763 + - Fix file links on project page when default view is Files !5933 + - Fixed enter key in search input not working !5888 + +## 8.11.1 + + - Pulled due to packaging error. + +## 8.11.0 (2016-08-22) + + - Use test coverage value from the latest successful pipeline in badge. !5862 + - Add test coverage report badge. !5708 + - Remove the http_parser.rb dependency by removing the tinder gem. !5758 (tbalthazar) + - Add Koding (online IDE) integration + - Ability to specify branches for Pivotal Tracker integration (Egor Lynko) + - Fix don't pass a local variable called `i` to a partial. !20510 (herminiotorres) + - Fix rename `add_users_into_project` and `projects_ids`. !20512 (herminiotorres) + - Fix adding line comments on the initial commit to a repo !5900 + - Fix the title of the toggle dropdown button. !5515 (herminiotorres) + - Rename `markdown_preview` routes to `preview_markdown`. (Christopher Bartz) + - Update to Ruby 2.3.1. !4948 + - Add Issues Board !5548 + - Allow resolving merge conflicts in the UI !5479 + - Improve diff performance by eliminating redundant checks for text blobs + - Ensure that branch names containing escapable characters (e.g. %20) aren't unescaped indiscriminately. !5770 (ewiltshi) + - Convert switch icon into icon font (ClemMakesApps) + - API: Endpoints for enabling and disabling deploy keys + - API: List access requests, request access, approve, and deny access requests to a project or a group. !4833 + - Use long options for curl examples in documentation !5703 (winniehell) + - Added tooltip listing label names to the labels value in the collapsed issuable sidebar + - Remove magic comments (`# encoding: UTF-8`) from Ruby files. !5456 (winniehell) + - GitLab Performance Monitoring can now track custom events such as the number of tags pushed to a repository + - Add support for relative links starting with ./ or / to RelativeLinkFilter (winniehell) + - Allow naming U2F devices !5833 + - Ignore URLs starting with // in Markdown links !5677 (winniehell) + - Fix CI status icon link underline (ClemMakesApps) + - The Repository class is now instrumented + - Fix commit mention font inconsistency (ClemMakesApps) + - Do not escape URI when extracting path !5878 (winniehell) + - Fix filter label tooltip HTML rendering (ClemMakesApps) + - Cache the commit author in RequestStore to avoid extra lookups in PostReceive + - Expand commit message width in repo view (ClemMakesApps) + - Cache highlighted diff lines for merge requests + - Pre-create all builds for a Pipeline when the new Pipeline is created !5295 + - Allow merge request diff notes and discussions to be explicitly marked as resolved + - API: Add deployment endpoints + - API: Add Play endpoint on Builds + - Fix of 'Commits being passed to custom hooks are already reachable when using the UI' + - Show wall clock time when showing a pipeline. !5734 + - Show member roles to all users on members page + - Project.visible_to_user is instrumented again + - Fix awardable button mutuality loading spinners (ClemMakesApps) + - Sort todos by date and priority + - Add support for using RequestStore within Sidekiq tasks via SIDEKIQ_REQUEST_STORE env variable + - Optimize maximum user access level lookup in loading of notes + - Send notification emails to users newly mentioned in issue and MR edits !5800 + - Add "No one can push" as an option for protected branches. !5081 + - Improve performance of AutolinkFilter#text_parse by using XPath + - Add experimental Redis Sentinel support !1877 + - Rendering of SVGs as blobs is now limited to SVGs with a size smaller or equal to 2MB + - Fix branches page dropdown sort initial state (ClemMakesApps) + - Environments have an url to link to + - Various redundant database indexes have been removed + - Update `timeago` plugin to use multiple string/locale settings + - Remove unused images (ClemMakesApps) + - Get issue and merge request description templates from repositories + - Enforce 2FA restrictions on API authentication endpoints !5820 + - Limit git rev-list output count to one in forced push check + - Show deployment status on merge requests with external URLs + - Clean up unused routes (Josef Strzibny) + - Fix issue on empty project to allow developers to only push to protected branches if given permission + - API: Add enpoints for pipelines + - Add green outline to New Branch button. !5447 (winniehell) + - Optimize generating of cache keys for issues and notes + - Fix repository push email formatting in Outlook + - Improve performance of syntax highlighting Markdown code blocks + - Update to gitlab_git 10.4.1 and take advantage of preserved Ref objects + - Remove delay when hitting "Reply..." button on page with a lot of discussions + - Retrieve rendered HTML from cache in one request + - Fix renaming repository when name contains invalid chararacters under project settings + - Upgrade Grape from 0.13.0 to 0.15.0. !4601 + - Trigram indexes for the "ci_runners" table have been removed to speed up UPDATE queries + - Fix devise deprecation warnings. + - Check for 2FA when using Git over HTTP and only allow PersonalAccessTokens as password in that case !5764 + - Update version_sorter and use new interface for faster tag sorting + - Optimize checking if a user has read access to a list of issues !5370 + - Store all DB secrets in secrets.yml, under descriptive names !5274 + - Fix syntax highlighting in file editor + - Support slash commands in issue and merge request descriptions as well as comments. !5021 + - Nokogiri's various parsing methods are now instrumented + - Add archived badge to project list !5798 + - Add simple identifier to public SSH keys (muteor) + - Admin page now references docs instead of a specific file !5600 (AnAverageHuman) + - Fix filter input alignment (ClemMakesApps) + - Include old revision in merge request update hooks (Ben Boeckel) + - Add build event color in HipChat messages (David Eisner) + - Make fork counter always clickable. !5463 (winniehell) + - Document that webhook secret token is sent in X-Gitlab-Token HTTP header !5664 (lycoperdon) + - Gitlab::Highlight is now instrumented + - All created issues, API or WebUI, can be submitted to Akismet for spam check !5333 + - Allow users to import cross-repository pull requests from GitHub + - The overhead of instrumented method calls has been reduced + - Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le) + - Load project invited groups and members eagerly in `ProjectTeam#fetch_members` + - Add pipeline events hook + - Bump gitlab_git to speedup DiffCollection iterations + - Rewrite description of a blocked user in admin settings. (Elias Werberich) + - Make branches sortable without push permission !5462 (winniehell) + - Check for Ci::Build artifacts at database level on pipeline partial + - Convert image diff background image to CSS (ClemMakesApps) + - Remove unnecessary index_projects_on_builds_enabled index from the projects table + - Make "New issue" button in Issue page less obtrusive !5457 (winniehell) + - Gitlab::Metrics.current_transaction needs to be public for RailsQueueDuration + - Fix search for notes which belongs to deleted objects + - Allow Akismet to be trained by submitting issues as spam or ham !5538 + - Add GitLab Workhorse version to admin dashboard (Katarzyna Kobierska Ula Budziszewska) + - Allow branch names ending with .json for graph and network page !5579 (winniehell) + - Add the `sprockets-es6` gem + - Improve OAuth2 client documentation (muteor) + - Fix diff comments inverted toggle bug (ClemMakesApps) + - Multiple trigger variables show in separate lines (Katarzyna Kobierska Ula Budziszewska) + - Profile requests when a header is passed + - Avoid calculation of line_code and position for _line partial when showing diff notes on discussion tab. + - Speedup DiffNote#active? on discussions, preloading noteables and avoid touching git repository to return diff_refs when possible + - Add commit stats in commit api. !5517 (dixpac) + - Add CI configuration button on project page + - Fix merge request new view not changing code view rendering style + - edit_blob_link will use blob passed onto the options parameter + - Make error pages responsive (Takuya Noguchi) + - The performance of the project dropdown used for moving issues has been improved + - Fix skip_repo parameter being ignored when destroying a namespace + - Add all builds into stage/job dropdowns on builds page + - Change requests_profiles resource constraint to catch virtually any file + - Bump gitlab_git to lazy load compare commits + - Reduce number of queries made for merge_requests/:id/diffs + - Add the option to set the expiration date for the project membership when giving a user access to a project. !5599 (Adam Niedzielski) + - Sensible state specific default sort order for issues and merge requests !5453 (tomb0y) + - Fix bug where destroying a namespace would not always destroy projects + - Fix RequestProfiler::Middleware error when code is reloaded in development + - Allow horizontal scrolling of code blocks in issue body + - Catch what warden might throw when profiling requests to re-throw it + - Avoid commit lookup on diff_helper passing existing local variable to the helper method + - Add description to new_issue email and new_merge_request_email in text/plain content type. !5663 (dixpac) + - Speed up and reduce memory usage of Commit#repo_changes, Repository#expire_avatar_cache and IrkerWorker + - Add unfold links for Side-by-Side view. !5415 (Tim Masliuchenko) + - Adds support for pending invitation project members importing projects + - Add pipeline visualization/graph on pipeline page + - Update devise initializer to turn on changed password notification emails. !5648 (tombell) + - Avoid to show the original password field when password is automatically set. !5712 (duduribeiro) + - Fix importing GitLab projects with an invalid MR source project + - Sort folders with submodules in Files view !5521 + - Each `File::exists?` replaced to `File::exist?` because of deprecate since ruby version 2.2.0 + - Add auto-completition in pipeline (Katarzyna Kobierska Ula Budziszewska) + - Add pipelines tab to merge requests + - Fix notification_service argument error of declined invitation emails + - Fix a memory leak caused by Banzai::Filter::SanitizationFilter + - Speed up todos queries by limiting the projects set we join with + - Ensure file editing in UI does not overwrite commited changes without warning user + - Eliminate unneeded calls to Repository#blob_at when listing commits with no path + - Update gitlab_git gem to 10.4.7 + - Simplify SQL queries of marking a todo as done + +## 8.10.12 + + - Don't send Private-Token (API authentication) headers to Sentry + - Share projects via the API only with groups the authenticated user can access + +## 8.10.11 + + - Respect the fork_project permission when forking projects + - Set a restrictive CORS policy on the API for credentialed requests + - API: disable rails session auth for non-GET/HEAD requests + - Escape HTML nodes in builds commands in CI linter + +## 8.10.10 + + - Allow the Rails cookie to be used for API authentication. + +## 8.10.9 + + - Exclude some pending or inactivated rows in Member scopes + +## 8.10.8 + + - Fix information disclosure in issue boards. + - Fix privilege escalation in project import. + +## 8.10.7 + + - Upgrade Hamlit to 2.6.1. !5873 + - Upgrade Doorkeeper to 4.2.0. !5881 + +## 8.10.6 + + - Upgrade Rails to 4.2.7.1 for security fixes. !5781 + - Restore "Largest repository" sort option on Admin > Projects page. !5797 + - Fix privilege escalation via project export. + - Require administrator privileges to perform a project import. + +## 8.10.5 + + - Add a data migration to fix some missing timestamps in the members table. !5670 + - Revert the "Defend against 'Host' header injection" change in the source NGINX templates. !5706 + - Cache project count for 5 minutes to reduce DB load. !5746 & !5754 + +## 8.10.4 + + - Don't close referenced upstream issues from a forked project. + - Fixes issue with dropdowns `enter` key not working correctly. !5544 + - Fix Import/Export project import not working in HA mode. !5618 + - Fix Import/Export error checking versions. !5638 + +## 8.10.3 + + - Fix Import/Export issue importing milestones and labels not associated properly. !5426 + - Fix timing problems running imports on production. !5523 + - Add a log message when a project is scheduled for destruction for debugging. !5540 + - Fix hooks missing on imported GitLab projects. !5549 + - Properly abort a merge when merge conflicts occur. !5569 + - Fix importer for GitHub Pull Requests when a branch was removed. !5573 + - Ignore invalid IPs in X-Forwarded-For when trusted proxies are configured. !5584 + - Trim extra displayed carriage returns in diffs and files with CRLFs. !5588 + - Fix label already exist error message in the right sidebar. + +## 8.10.2 + + - User can now search branches by name. !5144 + - Page is now properly rendered after committing the first file and creating the first branch. !5399 + - Add branch or tag icon to ref in builds page. !5434 + - Fix backup restore. !5459 + - Use project ID in repository cache to prevent stale data from persisting across projects. !5460 + - Fix issue with autocomplete search not working with enter key. !5466 + - Add iid to MR API response. !5468 + - Disable MySQL foreign key checks before dropping all tables. !5472 + - Ensure relative paths for video are rewritten as we do for images. !5474 + - Ensure current user can retry a build before showing the 'Retry' button. !5476 + - Add ENV variable to skip repository storages validations. !5478 + - Added `*.js.es6 gitlab-language=javascript` to `.gitattributes`. !5486 + - Don't show comment button in gutter of diffs on MR discussion tab. !5493 + - Rescue Rugged::OSError (lock exists) when creating references. !5497 + - Fix expand all diffs button in compare view. !5500 + - Show release notes in tags list. !5503 + - Fix a bug where forking a project from a repository storage to another would fail. !5509 + - Fix missing schema update for `20160722221922`. !5512 + - Update `gitlab-shell` version to 3.2.1 in the 8.9->8.10 update guide. !5516 + +## 8.10.1 + + - Refactor repository storages documentation. !5428 + - Gracefully handle case when keep-around references are corrupted or exist already. !5430 + - Add detailed info on storage path mountpoints. !5437 + - Fix Error 500 when creating Wiki pages with hyphens or spaces. !5444 + - Fix bug where replies to commit notes displayed in the MR discussion tab wouldn't show up on the commit page. !5446 + - Ignore invalid trusted proxies in X-Forwarded-For header. !5454 + - Add links to the real markdown.md file for all GFM examples. !5458 + +## 8.10.0 (2016-07-22) + + - Fix profile activity heatmap to show correct day name (eanplatter) + - Speed up ExternalWikiHelper#get_project_wiki_path + - Expose {should,force}_remove_source_branch (Ben Boeckel) + - Add the functionality to be able to rename a file. !5049 + - Disable PostgreSQL statement timeout during migrations + - Fix projects dropdown loading performance with a simplified api cal. !5113 + - Fix commit builds API, return all builds for all pipelines for given commit. !4849 + - Replace Haml with Hamlit to make view rendering faster. !3666 + - Refresh the branch cache after `git gc` runs + - Allow to disable request access button on projects/groups + - Refactor repository paths handling to allow multiple git mount points + - Optimize system note visibility checking by memoizing the visible reference count. !5070 + - Add Application Setting to configure default Repository Path for new projects + - Delete award emoji when deleting a user + - Remove pinTo from Flash and make inline flash messages look nicer. !4854 (winniehell) + - Add an API for downloading latest successful build from a particular branch or tag. !5347 + - Avoid data-integrity issue when cleaning up repository archive cache. + - Add link to profile to commit avatar. !5163 (winniehell) + - Wrap code blocks on Activies and Todos page. !4783 (winniehell) + - Align flash messages with left side of page content. !4959 (winniehell) + - Display tooltip for "Copy to Clipboard" button. !5164 (winniehell) + - Use default cursor for table header of project files. !5165 (winniehell) + - Store when and yaml variables in builds table + - Display last commit of deleted branch in push events. !4699 (winniehell) + - Escape file extension when parsing search results. !5141 (winniehell) + - Add "passing with warnings" to the merge request pipeline possible statuses, this happens when builds that allow failures have failed. !5004 + - Add image border in Markdown preview. !5162 (winniehell) + - Apply the trusted_proxies config to the rack request object for use with rack_attack + - Added the ability to block sign ups using a domain blacklist. !5259 + - Upgrade to Rails 4.2.7. !5236 + - Extend exposed environment variables for CI builds + - Deprecate APIs "projects/:id/keys/...". Use "projects/:id/deploy_keys/..." instead + - Add API "deploy_keys" for admins to get all deploy keys + - Allow to pull code with deploy key from public projects + - Use limit parameter rather than hardcoded value in `ldap:check` rake task (Mike Ricketts) + - Add Sidekiq queue duration to transaction metrics. + - Add a new column `artifacts_size` to table `ci_builds`. !4964 + - Let Workhorse serve format-patch diffs + - Display tooltip for mentioned users and groups. !5261 (winniehell) + - Allow build email service to be tested + - Added day name to contribution calendar tooltips + - Refactor user authorization check for a single project to avoid querying all user projects + - Make images fit to the size of the viewport. !4810 + - Fix check for New Branch button on Issue page. !4630 (winniehell) + - Fix GFM autocomplete not working on wiki pages + - Fixed enter key not triggering click on first row when searching in a dropdown + - Updated dropdowns in issuable form to use new GitLab dropdown style + - Make images fit to the size of the viewport !4810 + - Fix check for New Branch button on Issue page !4630 (winniehell) + - Fix MR-auto-close text added to description. !4836 + - Support U2F devices in Firefox. !5177 + - Fix issue, preventing users w/o push access to sort tags. !5105 (redetection) + - Add Spring EmojiOne updates. + - Added Rake task for tracking deployments. !5320 + - Fix fetching LFS objects for private CI projects + - Add the new 2016 Emoji! Adds 72 new emoji including bacon, facepalm, and selfie. !5237 + - Add syntax for multiline blockquote using `>>>` fence. !3954 + - Fix viewing notification settings when a project is pending deletion + - Updated compare dropdown menus to use GL dropdown + - Redirects back to issue after clicking login link + - Eager load award emoji on notes + - Allow to define manual actions/builds on Pipelines and Environments + - Fix pagination when sorting by columns with lots of ties (like priority) + - The Markdown reference parsers now re-use query results to prevent running the same queries multiple times. !5020 + - Updated project header design + - Issuable collapsed assignee tooltip is now the users name + - Fix compare view not changing code view rendering style + - Exclude email check from the standard health check + - Updated layout for Projects, Groups, Users on Admin area. !4424 + - Fix changing issue state columns in milestone view + - Update health_check gem to version 2.1.0 + - Add notification settings dropdown for groups + - Render inline diffs for multiple changed lines following eachother + - Wildcards for protected branches. !4665 + - Allow importing from Github using Personal Access Tokens. (Eric K Idema) + - API: Expose `due_date` for issues (Robert Schilling) + - API: Todos. !3188 (Robert Schilling) + - API: Expose shared groups for projects and shared projects for groups. !5050 (Robert Schilling) + - API: Expose `developers_can_push` and `developers_can_merge` for branches. !5208 (Robert Schilling) + - Add "Enabled Git access protocols" to Application Settings + - Diffs will create button/diff form on demand no on server side + - Reduce size of HTML used by diff comment forms + - Protected branches have a "Developers can Merge" setting. !4892 (original implementation by Mathias Vestergaard) + - Fix user creation with stronger minimum password requirements. !4054 (nathan-pmt) + - Only show New Snippet button to users that can create snippets. + - PipelinesFinder uses git cache data + - Track a user who created a pipeline + - Actually render old and new sections of parallel diff next to each other + - Throttle the update of `project.pushes_since_gc` to 1 minute. + - Allow expanding and collapsing files in diff view. !4990 + - Collapse large diffs by default (!4990) + - Fix mentioned users list on diff notes + - Add support for inline videos in GitLab Flavored Markdown. !5215 (original implementation by Eric Hayes) + - Fix creation of deployment on build that is retried, redeployed or rollback + - Don't parse Rinku returned value to DocFragment when it didn't change the original html string. + - Check for conflicts with existing Project's wiki path when creating a new project. + - Show last push widget in upstream after push to fork + - Fix stage status shown for pipelines + - Cache todos pending/done dashboard query counts. + - Don't instantiate a git tree on Projects show default view + - Bump Rinku to 2.0.0 + - Remove unused front-end variable -> default_issues_tracker + - ObjectRenderer retrieve renderer content using Rails.cache.read_multi + - Better caching of git calls on ProjectsController#show. + - Avoid to retrieve MR closes_issues as much as possible. + - Hide project name in project activities. !5068 (winniehell) + - Add API endpoint for a group issues. !4520 (mahcsig) + - Add Bugzilla integration. !4930 (iamtjg) + - Fix new snippet style bug (elliotec) + - Instrument Rinku usage + - Be explicit to define merge request discussion variables + - Use cache for todos counter calling TodoService + - Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab + - RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info. + - Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w) + - Made project list visibility icon fixed width + - Set import_url validation to be more strict + - Memoize MR merged/closed events retrieval + - Don't render discussion notes when requesting diff tab through AJAX + - Add basic system information like memory and disk usage to the admin panel + - Don't garbage collect commits that have related DB records like comments + - Allow to setup event by channel on slack service + - More descriptive message for git hooks and file locks + - Aliases of award emoji should be stored as original name. !5060 (dixpac) + - Handle custom Git hook result in GitLab UI + - Allow to access Container Registry for Public and Internal projects + - Allow '?', or '&' for label names + - Support redirected blobs for Container Registry integration + - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests + - Add date when user joined the team on the member page + - Fix 404 redirect after validation fails importing a GitLab project + - Added setting to set new users by default as external. !4545 (Dravere) + - Add min value for project limit field on user's form. !3622 (jastkand) + - Reset project pushes_since_gc when we enqueue the git gc call + - Add reminder to not paste private SSH keys. !4399 (Ingo Blechschmidt) + - Collapsed diffs lines/size don't acumulate to overflow diffs. + - Remove duplicate `description` field in `MergeRequest` entities (Ben Boeckel) + - Style of import project buttons were fixed in the new project page. !5183 (rdemirbay) + - Fix GitHub client requests when rate limit is disabled + - Optimistic locking for Issues and Merge Requests (Title and description overriding prevention) + - Redesign Builds and Pipelines pages + - Change status color and icon for running builds + - Fix commenting issue in side by side diff view for unchanged lines + - Fix markdown rendering for: consecutive labels references, label references that begin with a digit or contains `.` + - Project export filename now includes the project and namespace path + - Fix last update timestamp on issues not preserved on gitlab.com and project imports + - Fix issues importing projects from EE to CE + - Fix creating group with space in group path + - Improve cron_jobs loading error messages. !5318 / !5360 + - Prevent toggling sidebar when clipboard icon clicked + - Create Todos for Issue author when assign or mention himself (Katarzyna Kobierska) + - Limit the number of retries on error to 3 for exporting projects + - Allow empty repositories on project import/export + - Render only commit message title in builds (Katarzyna Kobierska Ula Budziszewska) + - Allow bulk (un)subscription from issues in issue index + - Fix MR diff encoding issues exporting GitLab projects + - Move builds settings out of project settings and rename Pipelines + - Add builds badge to Pipelines settings page + - Export and import avatar as part of project import/export + - Fix migration corrupting import data for old version upgrades + - Show tooltip on GitLab export link in new project page + - Fix import_data wrongly saved as a result of an invalid import_url !5206 + +## 8.9.11 + + - Respect the fork_project permission when forking projects + - Set a restrictive CORS policy on the API for credentialed requests + - API: disable rails session auth for non-GET/HEAD requests + - Escape HTML nodes in builds commands in CI linter + +## 8.9.10 + + - Allow the Rails cookie to be used for API authentication. + +## 8.9.9 + + - Exclude some pending or inactivated rows in Member scopes + +## 8.9.8 + + - Upgrade Doorkeeper to 4.2.0. !5881 + +## 8.9.7 + + - Upgrade Rails to 4.2.7.1 for security fixes. !5781 + - Require administrator privileges to perform a project import. + +## 8.9.6 + + - Fix importing of events under notes for GitLab projects. !5154 + - Fix log statements in import/export. !5129 + - Fix commit avatar alignment in compare view. !5128 + - Fix broken migration in MySQL. !5005 + - Overwrite Host and X-Forwarded-Host headers in NGINX !5213 + - Keeps issue number when importing from Gitlab.com + - Add Pending tab for Builds (Katarzyna Kobierska, Urszula Budziszewska) + +## 8.9.5 + + - Add more debug info to import/export and memory killer. !5108 + - Fixed avatar alignment in new MR view. !5095 + - Fix diff comments not showing up in activity feed. !5069 + - Add index on both Award Emoji user and name. !5061 + - Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq. !5056 + - Re-enable import button when import process fails due to namespace already being taken. !5053 + - Fix snippets comments not displayed. !5045 + - Fix emoji paths in relative root configurations. !5027 + - Fix issues importing events in Import/Export. !4987 + - Fixed 'use shortcuts' button on docs. !4979 + - Admin should be able to turn shared runners into specific ones. !4961 + - Update RedCloth to 4.3.2 for CVE-2012-6684. !4929 (Takuya Noguchi) + - Improve the request / withdraw access button. !4860 + +## 8.9.4 + + - Fix privilege escalation issue with OAuth external users. + - Ensure references to private repos aren't shown to logged-out users. + - Fixed search field blur not removing focus. !4704 + - Resolve "Sub nav isn't showing on file view". !4890 + - Fixes middle click and double request when navigating through the file browser. !4891 + - Fixed URL on label button when filtering. !4897 + - Fixed commit avatar alignment. !4933 + - Do not show build retry link when build is active. !4967 + - Fix restore Rake task warning message output. !4980 + - Handle external issues in IssueReferenceFilter. !4988 + - Expiry date on pinned nav cookie. !5009 + - Updated breakpoint for sidebar pinning. !5019 + +## 8.9.3 + + - Fix encrypted data backwards compatibility after upgrading attr_encrypted gem. !4963 + - Fix rendering of commit notes. !4953 + - Resolve "Pin should show up at 1280px min". !4947 + - Switched mobile button icons to ellipsis and angle. !4944 + - Correctly returns todo ID after creating todo. !4941 + - Better debugging for memory killer middleware. !4936 + - Remove duplicate new page btn from edit wiki. !4904 + - Use clock_gettime for all performance timestamps. !4899 + - Use memorized tags array when searching tags by name. !4859 + - Fixed avatar alignment in new MR view. !4901 + - Removed fade when filtering results. !4932 + - Fix missing avatar on system notes. !4954 + - Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973 + - Use update_columns to bypass all the dirty code on active_record. !4985 + - Fix restore Rake task warning message output !4980 + +## 8.9.2 + + - Fix visibility of snippets when searching. + - Fix an information disclosure when requesting access to a group containing private projects. + - Update omniauth-saml to 1.6.0 !4951 + +## 8.9.1 + + - Refactor labels documentation. !3347 + - Eager load award emoji on notes. !4628 + - Fix some CI wording in documentation. !4660 + - Document `GIT_STRATEGY` and `GIT_DEPTH`. !4720 + - Add documentation for the export & import features. !4732 + - Add some docs for Docker Registry configuration. !4738 + - Ensure we don't send the "access request declined" email to access requesters on project deletion. !4744 + - Display group/project access requesters separately in the admin area. !4798 + - Add documentation and examples for configuring cloud storage for registry images. !4812 + - Clarifies documentation about artifact expiry. !4831 + - Fix the Network graph links. !4832 + - Fix MR-auto-close text added to description. !4836 + - Add documentation for award emoji now that comments can be awarded with emojis. !4839 + - Fix typo in export failure email. !4847 + - Fix header vertical centering. !4170 + - Fix subsequent SAML sign ins. !4718 + - Set button label when picking an option from status dropdown. !4771 + - Prevent invalid URLs from raising exceptions in WikiLink Filter. !4775 + - Handle external issues in IssueReferenceFilter. !4789 + - Support for rendering/redacting multiple documents. !4828 + - Update Todos documentation and screenshots to include new functionality. !4840 + - Hide nav arrows by default. !4843 + - Added bottom padding to label color suggestion link. !4845 + - Use jQuery objects in ref dropdown. !4850 + - Fix GitLab project import issues related to notes and builds. !4855 + - Restrict header logo to 36px so it doesn't overflow. !4861 + - Fix unwanted label unassignment. !4863 + - Fix mobile Safari bug where horizontal nav arrows would flicker on scroll. !4869 + - Restore old behavior around diff notes to outdated discussions. !4870 + - Fix merge requests project settings help link anchor. !4873 + - Fix 404 when accessing pipelines as guest user on public projects. !4881 + - Remove width restriction for logo on sign-in page. !4888 + - Bump gitlab_git to 10.2.3 to fix false truncated warnings with ISO-8559 files. !4884 + - Apply selected value as label. !4886 + - Change Retry to Re-deploy on Deployments page + - Fix temp file being deleted after the request while importing a GitLab project. !4894 + - Fix pagination when sorting by columns with lots of ties (like priority) + - Implement Subresource Integrity for CSS and JavaScript assets. This prevents malicious assets from loading in the case of a CDN compromise. + - Fix user creation with stronger minimum password requirements !4054 (nathan-pmt) + - Fix a wrong MR status when merge_when_build_succeeds & project.only_allow_merge_if_build_succeeds are true. !4912 + - Add SMTP as default delivery method to match gitlab-org/omnibus-gitlab!826. !4915 + - Remove duplicate 'New Page' button on edit wiki page + +## 8.9.0 (2016-06-22) + + - Fix group visibility form layout in application settings + - Fix builds API response not including commit data + - Fix error when CI job variables key specified but not defined + - Fix pipeline status when there are no builds in pipeline + - Fix Error 500 when using closes_issues API with an external issue tracker + - Add more information into RSS feed for issues (Alexander Matyushentsev) + - Bulk assign/unassign labels to issues. + - Ability to prioritize labels !4009 / !3205 (Thijs Wouters) + - Show Star and Fork buttons on mobile. + - Performance improvements on RelativeLinkFilter + - Fix endless redirections when accessing user OAuth applications when they are disabled + - Allow enabling wiki page events from Webhook management UI + - Bump rouge to 1.11.0 + - Fix issue with arrow keys not working in search autocomplete dropdown + - Fix an issue where note polling stopped working if a window was in the + background during a refresh. + - Pre-processing Markdown now only happens when needed + - Make EmailsOnPushWorker use Sidekiq mailers queue + - Redesign all Devise emails. !4297 + - Don't show 'Leave Project' to group members + - Fix wiki page events' webhook to point to the wiki repository + - Add a border around images to differentiate them from the background. + - Don't show tags for revert and cherry-pick operations + - Show image ID on registry page + - Fix issue todo not remove when leave project !4150 (Long Nguyen) + - Allow customisable text on the 'nearly there' page after a user signs up + - Bump recaptcha gem to 3.0.0 to remove deprecated stoken support + - Fix SVG sanitizer to allow more elements + - Allow forking projects with restricted visibility level + - Added descriptions to notification settings dropdown + - Improve note validation to prevent errors when creating invalid note via API + - Reduce number of fog gem dependencies + - Add number of merge requests for a given milestone to the milestones view. + - Implement a fair usage of shared runners + - Remove project notification settings associated with deleted projects + - Fix 404 page when viewing TODOs that contain milestones or labels in different projects + - Add a metric for the number of new Redis connections created by a transaction + - Fix Error 500 when viewing a blob with binary characters after the 1024-byte mark + - Redesign navigation for project pages + - Fix images in sign-up confirmation email + - Added shortcut 'y' for copying a files content hash URL #14470 + - Fix groups API to list only user's accessible projects + - Fix horizontal scrollbar for long commit message. + - GitLab Performance Monitoring now tracks the total method execution time and call count per method + - Add Environments and Deployments + - Redesign account and email confirmation emails + - Don't fail builds for projects that are deleted + - Support Docker Registry manifest v1 + - `git clone https://host/namespace/project` now works, in addition to using the `.git` suffix + - Bump nokogiri to 1.6.8 + - Use gitlab-shell v3.0.0 + - Fixed alignment of download dropdown in merge requests + - Upgrade to jQuery 2 + - Adds selected branch name to the dropdown toggle + - Add API endpoint for Sidekiq Metrics !4653 + - Refactoring Award Emoji with API support for Issues and MergeRequests + - Use Knapsack to evenly distribute tests across multiple nodes + - Add `sha` parameter to MR merge API, to ensure only reviewed changes are merged + - Don't allow MRs to be merged when commits were added since the last review / page load + - Add DB index on users.state + - Limit email on push diff size to 30 files / 150 KB + - Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database + - Changed the Slack build message to use the singular duration if necessary (Aran Koning) + - Fix race condition on merge when build succeeds + - Added shortcut to focus filter search fields and added documentation #18120 + - Links from a wiki page to other wiki pages should be rewritten as expected + - Add option to project to only allow merge requests to be merged if the build succeeds (Rui Santos) + - Added navigation shortcuts to the project pipelines, milestones, builds and forks page. !4393 + - Fix issues filter when ordering by milestone + - Disable SAML account unlink feature + - Added artifacts:when to .gitlab-ci.yml - this requires GitLab Runner 1.3 + - Bamboo Service: Fix missing credentials & URL handling when base URL contains a path (Benjamin Schmid) + - TeamCity Service: Fix URL handling when base URL contains a path + - Todos will display target state if issuable target is 'Closed' or 'Merged' + - Validate only and except regexp + - Fix bug when sorting issues by milestone due date and filtering by two or more labels + - POST to API /projects/:id/runners/:runner_id would give 409 if the runner was already enabled for this project + - Add support for using Yubikeys (U2F) for two-factor authentication + - Link to blank group icon doesn't throw a 404 anymore + - Remove 'main language' feature + - Toggle whitespace button now available for compare branches diffs #17881 + - Pipelines can be canceled only when there are running builds + - Allow authentication using personal access tokens + - Use downcased path to container repository as this is expected path by Docker + - Allow to use CI token to fetch LFS objects + - Custom notification settings + - Projects pending deletion will render a 404 page + - Measure queue duration between gitlab-workhorse and Rails + - Added Gfm autocomplete for labels + - Added edit note 'up' shortcut documentation to the help panel and docs screenshot #18114 + - Make Omniauth providers specs to not modify global configuration + - Remove unused JiraIssue class and replace references with ExternalIssue. !4659 (Ilan Shamir) + - Make authentication service for Container Registry to be compatible with < Docker 1.11 + - Make it possible to lock a runner from being enabled for other projects + - Add Application Setting to configure Container Registry token expire delay (default 5min) + - Cache assigned issue and merge request counts in sidebar nav + - Use Knapsack only in CI environment + - Updated project creation page to match new UI #2542 + - Cache project build count in sidebar nav + - Add milestone expire date to the right sidebar + - Manually mark a issue or merge request as a todo + - Fix markdown_spec to use before instead of before(:all) to properly cleanup database after testing + - Reduce number of queries needed to render issue labels in the sidebar + - Improve error handling importing projects + - Remove duplicated notification settings + - Put project Files and Commits tabs under Code tab + - Decouple global notification level from user model + - Replace Colorize with Rainbow for coloring console output in Rake tasks. + - Add workhorse controller and API helpers + - An indicator is now displayed at the top of the comment field for confidential issues. + - Show categorised search queries in the search autocomplete + - RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented + - Dropdown for `.gitlab-ci.yml` templates + - Improve issuables APIs performance when accessing notes !4471 + - Add sorting dropdown to tags page !4423 + - External links now open in a new tab + - Prevent default actions of disabled buttons and links + - Markdown editor now correctly resets the input value on edit cancellation !4175 + - Toggling a task list item in a issue/mr description does not creates a Todo for mentions + - Improved UX of date pickers on issue & milestone forms + - Cache on the database if a project has an active external issue tracker. + - Put project Labels and Milestones pages links under Issues and Merge Requests tabs as subnav + - GitLab project import and export functionality + - All classes in the Banzai::ReferenceParser namespace are now instrumented + - Remove deprecated issues_tracker and issues_tracker_id from project model + - Allow users to create confidential issues in private projects + - Measure CPU time for instrumented methods + - Instrument private methods and private instance methods by default instead just public methods + - Only show notes through JSON on confidential issues that the user has access to + - Updated the allocations Gem to version 1.0.5 + - The background sampler now ignores classes without names + - Update design for `Close` buttons + - New custom icons for navigation + - Horizontally scrolling navigation on project, group, and profile settings pages + - Hide global side navigation by default + - Fix project Star/Unstar project button tooltip + - Remove tanuki logo from side navigation; center on top nav + - Include user relationships when retrieving award_emoji + - Various associations are now eager loaded when parsing issue references to reduce the number of queries executed + - Set inverse_of for Project/Service association to reduce the number of queries + - Update tanuki logo highlight/loading colors + - Remove explicit Gitlab::Metrics.action assignments, are already automatic. + - Use Git cached counters for branches and tags on project page + - Cache participable participants in an instance variable. + - Filter parameters for request_uri value on instrumented transactions. + - Remove duplicated keys add UNIQUE index to keys fingerprint column + - ExtractsPath get ref_names from repository cache, if not there access git. + - Show a flash warning about the error detail of XHR requests which failed with status code 404 and 500 + - Cache user todo counts from TodoService + - Ensure Todos counters doesn't count Todos for projects pending delete + - Add left/right arrows horizontal navigation + - Add tooltip to pin/unpin navbar + - Add new sub nav style to Wiki and Graphs sub navigation + +## 8.8.9 + + - Upgrade Doorkeeper to 4.2.0. !5881 + +## 8.8.8 + + - Upgrade Rails to 4.2.7.1 for security fixes. !5781 + +## 8.8.7 + + - Fix privilege escalation issue with OAuth external users. + - Ensure references to private repos aren't shown to logged-out users. + +## 8.8.6 + + - Fix visibility of snippets when searching. + - Update omniauth-saml to 1.6.0 !4951 + +## 8.8.5 + + - Import GitHub repositories respecting the API rate limit !4166 + - Fix todos page throwing errors when you have a project pending deletion !4300 + - Disable Webhooks before proceeding with the GitHub import !4470 + - Fix importer for GitHub comments on diff !4488 + - Adjust the SAML control flow to allow LDAP identities to be added to an existing SAML user !4498 + - Fix incremental trace upload API when using multi-byte UTF-8 chars in trace !4541 + - Prevent unauthorized access for projects build traces + - Forbid scripting for wiki files + - Only show notes through JSON on confidential issues that the user has access to + - Banzai::Filter::UploadLinkFilter use XPath instead CSS expressions + - Banzai::Filter::ExternalLinkFilter use XPath instead CSS expressions + +## 8.8.4 + + - Fix LDAP-based login for users with 2FA enabled. !4493 + - Added descriptions to notification settings dropdown + - Due date can be removed from milestones + +## 8.8.3 + + - Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312 + - Fixed JS error when trying to remove discussion form. !4303 + - Fixed issue with button color when no CI enabled. !4287 + - Fixed potential issue with 2 CI status polling events happening. !3869 + - Improve design of Pipeline view. !4230 + - Fix gitlab importer failing to import new projects due to missing credentials. !4301 + - Fix import URL migration not rescuing with the correct Error. !4321 + - Fix health check access token changing due to old application settings being used. !4332 + - Make authentication service for Container Registry to be compatible with Docker versions before 1.11. !4363 + - Add Application Setting to configure Container Registry token expire delay (default 5 min). !4364 + - Pass the "Remember me" value to the 2FA token form. !4369 + - Fix incorrect links on pipeline page when merge request created from fork. !4376 + - Use downcased path to container repository as this is expected path by Docker. !4420 + - Fix wiki project clone address error (chujinjin). !4429 + - Fix serious performance bug with rendering Markdown with InlineDiffFilter. !4392 + - Fix missing number on generated ordered list element. !4437 + - Prevent disclosure of notes on confidential issues in search results. + +## 8.8.2 + + - Added remove due date button. !4209 + - Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242 + - Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245 + - Fix table UI on CI builds page. !4249 + - Fix backups if registry is disabled. !4263 + - Fixed issue with merge button color. !4211 + - Fixed issue with enter key selecting wrong option in dropdown. !4210 + - When creating a .gitignore file a dropdown with templates will be provided. !4075 + - Fix concurrent request when updating build log in browser. !4183 + +## 8.8.1 + + - Add documentation for the "Health Check" feature + - Allow anonymous users to access a public project's pipelines !4233 + - Fix MySQL compatibility in zero downtime migrations helpers + - Fix the CI login to Container Registry (the gitlab-ci-token user) + +## 8.8.0 (2016-05-22) + + - Implement GFM references for milestones (Alejandro Rodríguez) + - Snippets tab under user profile. !4001 (Long Nguyen) + - Fix error when using link to uploads in global snippets + - Fix Error 500 when attempting to retrieve project license when HEAD points to non-existent ref + - Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen) + - Use a case-insensitive comparison in sanitizing URI schemes + - Toggle sign-up confirmation emails in application settings + - Make it possible to prevent tagged runner from picking untagged jobs + - Added `InlineDiffFilter` to the markdown parser. (Adam Butler) + - Added inline diff styling for `change_title` system notes. (Adam Butler) + - Project#open_branches has been cleaned up and no longer loads entire records into memory. + - Escape HTML in commit titles in system note messages + - Improve design of Pipeline View + - Fix scope used when accessing container registry + - Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios + - Improve multiple branch push performance by memoizing permission checking + - Log to application.log when an admin starts and stops impersonating a user + - Changing the confidentiality of an issue now creates a new system note (Alex Moore-Niemi) + - Updated gitlab_git to 10.1.0 + - GitAccess#protected_tag? no longer loads all tags just to check if a single one exists + - Reduce delay in destroying a project from 1-minute to immediately + - Make build status canceled if any of the jobs was canceled and none failed + - Upgrade Sidekiq to 4.1.2 + - Added /health_check endpoint for checking service status + - Make 'upcoming' filter for milestones work better across projects + - Sanitize repo paths in new project error message + - Bump mail_room to 0.7.0 to fix stuck IDLE connections + - Remove future dates from contribution calendar graph. + - Support e-mail notifications for comments on project snippets + - Fix API leak of notes of unauthorized issues, snippets and merge requests + - Use ActionDispatch Remote IP for Akismet checking + - Fix error when visiting commit builds page before build was updated + - Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project + - Update SVG sanitizer to conform to SVG 1.1 + - Speed up push emails with multiple recipients by only generating the email once + - Updated search UI + - Added authentication service for Container Registry + - Display informative message when new milestone is created + - Sanitize milestones and labels titles + - Support multi-line tag messages. !3833 (Calin Seciu) + - Force users to reset their password after an admin changes it + - Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea) + - Added button to toggle whitespaces changes on diff view + - Backport GitHub Enterprise import support from EE + - Create tags using Rugged for performance reasons. !3745 + - Allow guests to set notification level in projects + - API: Expose Issue#user_notes_count. !3126 (Anton Popov) + - Don't show forks button when user can't view forks + - Fix atom feed links and rendering + - Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718 + - Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes) + - Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724 + - Added multiple colors for labels in dropdowns when dups happen. + - Show commits in the same order as `git log` + - Improve description for the Two-factor Authentication sign-in screen. (Connor Shea) + - API support for the 'since' and 'until' operators on commit requests (Paco Guzman) + - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) + - Expire repository exists? and has_visible_content? caches after a push if necessary + - Fix unintentional filtering bug in Issue/MR sorted by milestone due (Takuya Noguchi) + - Fix adding a todo for private group members (Ahmad Sherif) + - Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3 + - Total method execution timings are no longer tracked + - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga) + - Add API endpoints for un/subscribing from/to a label. !4051 (Ahmad Sherif) + - Hide left sidebar on phone screens to give more space for content + - Redesign navigation for profile and group pages + - Add counter metrics for rails cache + - Import pull requests from GitHub where the source or target branches were removed + - All Grape API helpers are now instrumented + - Improve Issue formatting for the Slack Service (Jeroen van Baarsen) + - Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine) + - Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs) + - When creating a .gitignore file a dropdown with templates will be provided + - Shows the issue/MR list search/filter form and corrects the mobile styling for guest users. #17562 + +## 8.7.9 + + - Fix privilege escalation issue with OAuth external users. + - Ensure references to private repos aren't shown to logged-out users. + +## 8.7.8 + + - Fix visibility of snippets when searching. + - Update omniauth-saml to 1.6.0 !4951 + +## 8.7.7 + + - Fix import by `Any Git URL` broken if the URL contains a space + - Prevent unauthorized access to other projects build traces + - Forbid scripting for wiki files + - Only show notes through JSON on confidential issues that the user has access to + +## 8.7.6 + + - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) + - Fix import from GitLab.com to a private instance failure. !4181 + - Fix external imports not finding the import data. !4106 + - Fix notification delay when changing status of an issue + - Bump Workhorse to 0.7.5 so it can serve raw diffs + +## 8.7.5 + + - Fix relative links in wiki pages. !4050 + - Fix always showing build notification message when switching between merge requests !4086 + - Fix an issue when filtering merge requests with more than one label. !3886 + - Fix short note for the default scope on build page (Takuya Noguchi) + +## 8.7.4 + + - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss) + - Fix setting trusted proxies !3970 + - Fix BitBucket importer bug when throwing exceptions !3941 + - Use sign out path only if not empty !3989 + - Running rake gitlab:db:drop_tables now drops tables with cascade !4020 + - Running rake gitlab:db:drop_tables uses "IF EXISTS" as a precaution !4100 + - Use a case-insensitive comparison in sanitizing URI schemes + +## 8.7.3 + + - Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented + - Merge request widget displays TeamCity build state and code coverage correctly again. + - Fix the line code when importing PR review comments from GitHub. !4010 + - Wikis are now initialized on legacy projects when checking repositories + - Remove animate.css in favor of a smaller subset of animations. !3937 (Connor Shea) + +## 8.7.2 + + - The "New Branch" button is now loaded asynchronously + - Fix error 500 when trying to create a wiki page + - Updated spacing between notification label and button + - Label titles in filters are now escaped properly + +## 8.7.1 + + - Throttle the update of `project.last_activity_at` to 1 minute. !3848 + - Fix .gitlab-ci.yml parsing issue when hidde job is a template without script definition. !3849 + - Fix license detection to detect all license files, not only known licenses. !3878 + - Use the `can?` helper instead of `current_user.can?`. !3882 + - Prevent users from deleting Webhooks via API they do not own + - Fix Error 500 due to stale cache when projects are renamed or transferred + - Update width of search box to fix Safari bug. !3900 (Jedidiah) + - Use the `can?` helper instead of `current_user.can?` + +## 8.7.0 (2016-04-22) + + - Gitlab::GitAccess and Gitlab::GitAccessWiki are now instrumented + - Fix vulnerability that made it possible to gain access to private labels and milestones + - The number of InfluxDB points stored per UDP packet can now be configured + - Fix error when cross-project label reference used with non-existent project + - Transactions for /internal/allowed now have an "action" tag set + - Method instrumentation now uses Module#prepend instead of aliasing methods + - Repository.clean_old_archives is now instrumented + - Add support for environment variables on a job level in CI configuration file + - SQL query counts are now tracked per transaction + - The Projects::HousekeepingService class has extra instrumentation + - All service classes (those residing in app/services) are now instrumented + - Developers can now add custom tags to transactions + - Loading of an issue's referenced merge requests and related branches is now done asynchronously + - Enable gzip for assets, makes the page size significantly smaller. !3544 / !3632 (Connor Shea) + - Add support to cherry-pick any commit into any branch in the web interface (Minqi Pan) + - Project switcher uses new dropdown styling + - Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea) + - Do not include award_emojis in issue and merge_request comment_count !3610 (Lucas Charles) + - Restrict user profiles when public visibility level is restricted. + - Add ability set due date to issues, sort and filter issues by due date (Mehmet Beydogan) + - All images in discussions and wikis now link to their source files !3464 (Connor Shea). + - Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu) + - Add setting for customizing the list of trusted proxies !3524 + - Allow projects to be transfered to a lower visibility level group + - Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524 + - Improved Markdown rendering performance !3389 + - Make shared runners text in box configurable + - Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu) + - API: Ability to subscribe and unsubscribe from issues and merge requests (Robert Schilling) + - Expose project badges in project settings + - Make /profile/keys/new redirect to /profile/keys for back-compat. !3717 + - Preserve time notes/comments have been updated at when moving issue + - Make HTTP(s) label consistent on clone bar (Stan Hu) + - Add support for `after_script`, requires Runner 1.2 (Kamil Trzciński) + - Expose label description in API (Mariusz Jachimowicz) + - API: Ability to update a group (Robert Schilling) + - API: Ability to move issues (Robert Schilling) + - Fix Error 500 after renaming a project path (Stan Hu) + - Fix a bug whith trailing slash in teamcity_url (Charles May) + - Allow back dating on issues when created or updated through the API + - Allow back dating on issue notes when created through the API + - Propose license template when creating a new LICENSE file + - API: Expose /licenses and /licenses/:key + - Fix avatar stretching by providing a cropping feature + - API: Expose `subscribed` for issues and merge requests (Robert Schilling) + - Allow SAML to handle external users based on user's information !3530 + - Allow Omniauth providers to be marked as `external` !3657 + - Add endpoints to archive or unarchive a project !3372 + - Fix a bug whith trailing slash in bamboo_url + - Add links to CI setup documentation from project settings and builds pages + - Display project members page to all members + - Handle nil descriptions in Slack issue messages (Stan Hu) + - Add automated repository integrity checks (OFF by default) + - API: Expose open_issues_count, closed_issues_count, open_merge_requests_count for labels (Robert Schilling) + - API: Ability to star and unstar a project (Robert Schilling) + - Add default scope to projects to exclude projects pending deletion + - Allow to close merge requests which source projects(forks) are deleted. + - Ensure empty recipients are rejected in BuildsEmailService + - Use rugged to change HEAD in Project#change_head (P.S.V.R) + - API: Ability to filter milestones by state `active` and `closed` (Robert Schilling) + - API: Fix milestone filtering by `iid` (Robert Schilling) + - Make before_script and after_script overridable on per-job (Kamil Trzciński) + - API: Delete notes of issues, snippets, and merge requests (Robert Schilling) + - Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.) + - Better errors handling when creating milestones inside groups + - Fix high CPU usage when PostReceive receives refs/merge-requests/ + - Hide `Create a group` help block when creating a new project in a group + - Implement 'TODOs View' as an option for dashboard preferences !3379 (Elias W.) + - Allow issues and merge requests to be assigned to the author !2765 + - Make Ci::Commit to group only similar builds and make it stateful (ref, tag) + - Gracefully handle notes on deleted commits in merge requests (Stan Hu) + - Decouple membership and notifications + - Fix creation of merge requests for orphaned branches (Stan Hu) + - API: Ability to retrieve a single tag (Robert Schilling) + - While signing up, don't persist the user password across form redisplays + - Fall back to `In-Reply-To` and `References` headers when sub-addressing is not available (David Padilla) + - Remove "Congratulations!" tweet button on newly-created project. (Connor Shea) + - Fix admin/projects when using visibility levels on search (PotHix) + - Build status notifications + - Update email confirmation interface + - API: Expose user location (Robert Schilling) + - API: Do not leak group existence via return code (Robert Schilling) + - ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591 + - Update number of Todos in the sidebar when it's marked as "Done". !3600 + - Sanitize branch names created for confidential issues + - API: Expose 'updated_at' for issue, snippet, and merge request notes (Robert Schilling) + - API: User can leave a project through the API when not master or owner. !3613 + - Fix repository cache invalidation issue when project is recreated with an empty repo (Stan Hu) + - Fix: Allow empty recipients list for builds emails service when pushed is added (Frank Groeneveld) + - Improved markdown forms + - Diff design updates (colors, button styles, etc) + - Copying and pasting a diff no longer pastes the line numbers or +/- + - Add null check to formData when updating profile content to fix Firefox bug + - Disable spellcheck and autocorrect for username field in admin page + - Delete tags using Rugged for performance reasons (Robert Schilling) + - Add Slack notifications when Wiki is edited (Sebastian Klier) + - Diffs load at the correct point when linking from from number + - Selected diff rows highlight + - Fix emoji categories in the emoji picker + - API: Properly display annotated tags for GET /projects/:id/repository/tags (Robert Schilling) + - Add encrypted credentials for imported projects and migrate old ones + - Properly format all merge request references with ! rather than # !3740 (Ben Bodenmiller) + - Author and participants are displayed first on users autocompletion + - Show number sign on external issue reference text (Florent Baldino) + - Updated print style for issues + - Use GitHub Issue/PR number as iid to keep references + - Import GitHub labels + - Add option to filter by "Owned projects" on dashboard page + - Import GitHub milestones + - Execute system web hooks on push to the project + - Allow enable/disable push events for system hooks + - Fix GitHub project's link in the import page when provider has a custom URL + - Add RAW build trace output and button on build page + - Add incremental build trace update into CI API + +## 8.6.9 + + - Prevent unauthorized access to other projects build traces + - Forbid scripting for wiki files + - Only show notes through JSON on confidential issues that the user has access to + +## 8.6.8 + + - Prevent privilege escalation via "impersonate" feature + - Prevent privilege escalation via notes API + - Prevent privilege escalation via project webhook API + - Prevent XSS via Git branch and tag names + - Prevent XSS via custom issue tracker URL + - Prevent XSS via `window.opener` + - Prevent XSS via label drop-down + - Prevent information disclosure via milestone API + - Prevent information disclosure via snippet API + - Prevent information disclosure via project labels + - Prevent information disclosure via new merge request page + +## 8.6.7 + + - Fix persistent XSS vulnerability in `commit_person_link` helper + - Fix persistent XSS vulnerability in Label and Milestone dropdowns + - Fix vulnerability that made it possible to enumerate private projects belonging to group + +## 8.6.6 + + - Expire the exists cache before deletion to ensure project dir actually exists (Stan Hu). !3413 + - Fix error on language detection when repository has no HEAD (e.g., master branch) (Jeroen Bobbeldijk). !3654 + - Fix revoking of authorized OAuth applications (Connor Shea). !3690 + - Fix error on language detection when repository has no HEAD (e.g., master branch). !3654 (Jeroen Bobbeldijk) + - Issuable header is consistent between issues and merge requests + - Improved spacing in issuable header on mobile + +## 8.6.5 + + - Fix importing from GitHub Enterprise. !3529 + - Perform the language detection after updating merge requests in `GitPushService`, leading to faster visual feedback for the end-user. !3533 + - Check permissions when user attempts to import members from another project. !3535 + - Only update repository language if it is not set to improve performance. !3556 + - Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu). !3583 + - Unblock user when active_directory is disabled and it can be found !3550 + - Fix a 2FA authentication spoofing vulnerability. + +## 8.6.4 + + - Don't attempt to fetch any tags from a forked repo (Stan Hu) + - Redesign the Labels page + +## 8.6.3 + + - Mentions on confidential issues doesn't create todos for non-members. !3374 + - Destroy related todos when an Issue/MR is deleted. !3376 + - Fix error 500 when target is nil on todo list. !3376 + - Fix copying uploads when moving issue to another project. !3382 + - Ensuring Merge Request API returns boolean values for work_in_progress (Abhi Rao). !3432 + - Fix raw/rendered diff producing different results on merge requests. !3450 + - Fix commit comment alignment (Stan Hu). !3466 + - Fix Error 500 when searching for a comment in a project snippet. !3468 + - Allow temporary email as notification email. !3477 + - Fix issue with dropdowns not selecting values. !3478 + - Update gitlab-shell version and doc to 2.6.12. gitlab-org/gitlab-ee!280 + +## 8.6.2 + + - Fix dropdown alignment. !3298 + - Fix issuable sidebar overlaps on tablet. !3299 + - Make dropdowns pixel perfect. !3337 + - Fix order of steps to prevent PostgreSQL errors when running migration. !3355 + - Fix bold text in issuable sidebar. !3358 + - Fix error with anonymous token in applications settings. !3362 + - Fix the milestone 'upcoming' filter. !3364 + !3368 + - Fix comments on confidential issues showing up in activity feed to non-members. !3375 + - Fix `NoMethodError` when visiting CI root path at `/ci`. !3377 + - Add a tooltip to new branch button in issue page. !3380 + - Fix an issue hiding the password form when signed-in with a linked account. !3381 + - Add links to CI setup documentation from project settings and builds pages. !3384 + - Fix an issue with width of project select dropdown. !3386 + - Remove redundant `require`s from Banzai files. !3391 + - Fix error 500 with cancel button on issuable edit form. !3392 + !3417 + - Fix background when editing a highlighted note. !3423 + - Remove tabstop from the WIP toggle links. !3426 + - Ensure private project snippets are not viewable by unauthorized people. + - Gracefully handle notes on deleted commits in merge requests (Stan Hu). !3402 + - Fixed issue with notification settings not saving. !3452 + +## 8.6.1 + + - Add option to reload the schema before restoring a database backup. !2807 + - Display navigation controls on mobile. !3214 + - Fixed bug where participants would not work correctly on merge requests. !3329 + - Fix sorting issues by votes on the groups issues page results in SQL errors. !3333 + - Restrict notifications for confidential issues. !3334 + - Do not allow to move issue if it has not been persisted. !3340 + - Add a confirmation step before deleting an issuable. !3341 + - Fixes issue with signin button overflowing on mobile. !3342 + - Auto collapses the navigation sidebar when resizing. !3343 + - Fix build dependencies, when the dependency is a string. !3344 + - Shows error messages when trying to create label in dropdown menu. !3345 + - Fixes issue with assign milestone not loading milestone list. !3346 + - Fix an issue causing the Dashboard/Milestones page to be blank. !3348 + +## 8.6.0 (2016-03-22) + + - Add ability to move issue to another project + - Prevent tokens in the import URL to be showed by the UI + - Fix bug where wrong commit ID was being used in a merge request diff to show old image (Stan Hu) + - Add confidential issues + - Bump gitlab_git to 9.0.3 (Stan Hu) + - Fix diff image view modes (2-up, swipe, onion skin) not working (Stan Hu) + - Support Golang subpackage fetching (Stan Hu) + - Bump Capybara gem to 2.6.2 (Stan Hu) + - New branch button appears on issues where applicable + - Contributions to forked projects are included in calendar + - Improve the formatting for the user page bio (Connor Shea) + - Easily (un)mark merge request as WIP using link + - Use specialized system notes when MR is (un)marked as WIP + - Removed the default password from the initial admin account created during + setup. A password can be provided during setup (see installation docs), or + GitLab will ask the user to create a new one upon first visit. + - Fix issue when pushing to projects ending in .wiki + - Properly display YAML front matter in Markdown + - Add support for wiki with UTF-8 page names (Hiroyuki Sato) + - Fix wiki search results point to raw source (Hiroyuki Sato) + - Don't load all of GitLab in mail_room + - Add information about `image` and `services` field at `job` level in the `.gitlab-ci.yml` documentation (Pat Turner) + - HTTP error pages work independently from location and config (Artem Sidorenko) + - Update `omniauth-saml` to 1.5.0 to allow for custom response attributes to be set + - Memoize @group in Admin::GroupsController (Yatish Mehta) + - Indicate how much an MR diverged from the target branch (Pierre de La Morinerie) + - Added omniauth-auth0 Gem (Daniel Carraro) + - Add label description in tooltip to labels in issue index and sidebar + - Strip leading and trailing spaces in URL validator (evuez) + - Add "last_sign_in_at" and "confirmed_at" to GET /users/* API endpoints for admins (evuez) + - Return empty array instead of 404 when commit has no statuses in commit status API + - Decrease the font size and the padding of the `.anchor` icons used in the README (Roberto Dip) + - Rewrite logo to simplify SVG code (Sean Lang) + - Allow to use YAML anchors when parsing the `.gitlab-ci.yml` (Pascal Bach) + - Ignore jobs that start with `.` (hidden jobs) + - Hide builds from project's settings when the feature is disabled + - Allow to pass name of created artifacts archive in `.gitlab-ci.yml` + - Refactor and greatly improve search performance + - Add support for cross-project label references + - Ensure "new SSH key" email do not ends up as dead Sidekiq jobs + - Update documentation to reflect Guest role not being enforced on internal projects + - Allow search for logged out users + - Allow to define on which builds the current one depends on + - Allow user subscription to a label: get notified for issues/merge requests related to that label (Timothy Andrew) + - Fix bug where Bitbucket `closed` issues were imported as `opened` (Iuri de Silvio) + - Don't show Issues/MRs from archived projects in Groups view + - Fix wrong "iid of max iid" in Issuable sidebar for some merged MRs + - Fix empty source_sha on Merge Request when there is no diff (Pierre de La Morinerie) + - Increase the notes polling timeout over time (Roberto Dip) + - Add shortcut to toggle markdown preview (Florent Baldino) + - Show labels in dashboard and group milestone views + - Fix an issue when the target branch of a MR had been deleted + - Add main language of a project in the list of projects (Tiago Botelho) + - Add #upcoming filter to Milestone filter (Tiago Botelho) + - Add ability to show archived projects on dashboard, explore and group pages + - Remove fork link closes all merge requests opened on source project (Florent Baldino) + - Move group activity to separate page + - Create external users which are excluded of internal and private projects unless access was explicitly granted + - Continue parameters are checked to ensure redirection goes to the same instance + - User deletion is now done in the background so the request can not time out + - Canceled builds are now ignored in compound build status if marked as `allowed to fail` + - Trigger a todo for mentions on commits page + - Let project owners and admins soft delete issues and merge requests + +## 8.5.13 + + - Prevent unauthorized access to other projects build traces + - Forbid scripting for wiki files + +## 8.5.12 + + - Prevent privilege escalation via "impersonate" feature + - Prevent privilege escalation via notes API + - Prevent privilege escalation via project webhook API + - Prevent XSS via Git branch and tag names + - Prevent XSS via custom issue tracker URL + - Prevent XSS via `window.opener` + - Prevent information disclosure via snippet API + - Prevent information disclosure via project labels + - Prevent information disclosure via new merge request page + +## 8.5.11 + + - Fix persistent XSS vulnerability in `commit_person_link` helper + +## 8.5.10 + + - Fix a 2FA authentication spoofing vulnerability. + +## 8.5.9 + + - Don't attempt to fetch any tags from a forked repo (Stan Hu). + +## 8.5.8 + + - Bump Git version requirement to 2.7.4 + +## 8.5.7 + + - Bump Git version requirement to 2.7.3 + +## 8.5.6 + + - Obtain a lease before querying LDAP + +## 8.5.5 + + - Ensure removing a project removes associated Todo entries + - Prevent a 500 error in Todos when author was removed + - Fix pagination for filtered dashboard and explore pages + - Fix "Show all" link behavior + +## 8.5.4 + + - Do not cache requests for badges (including builds badge) + +## 8.5.3 + + - Flush repository caches before renaming projects + - Sort starred projects on dashboard based on last activity by default + - Show commit message in JIRA mention comment + - Makes issue page and merge request page usable on mobile browsers. + - Improved UI for profile settings + +## 8.5.2 + + - Fix sidebar overlapping content when screen width was below 1200px + - Don't repeat labels listed on Labels tab + - Bring the "branded appearance" feature from EE to CE + - Fix error 500 when commenting on a commit + - Show days remaining instead of elapsed time for Milestone + - Fix broken icons on installations with relative URL (Artem Sidorenko) + - Fix issue where tag list wasn't refreshed after deleting a tag + - Fix import from gitlab.com (KazSawada) + - Improve implementation to check read access to forks and add pagination + - Don't show any "2FA required" message if it's not actually required + - Fix help keyboard shortcut on relative URL setups (Artem Sidorenko) + - Update Rails to 4.2.5.2 + - Fix permissions for deprecated CI build status badge + - Don't show "Welcome to GitLab" when the search didn't return any projects + - Add Todos documentation + +## 8.5.1 + + - Fix group projects styles + - Show Crowd login tab when sign in is disabled and Crowd is enabled (Peter Hudec) + - Fix a set of small UI glitches in project, profile, and wiki pages + - Restrict permissions on public/uploads + - Fix the merge request side-by-side view after loading diff results + - Fix the look of tooltip for the "Revert" button + - Add when the Builds & Runners API changes got introduced + - Fix error 500 on some merged merge requests + - Fix an issue causing the content of the issuable sidebar to disappear + - Fix error 500 when trying to mark an already done todo as "done" + - Fix an issue where MRs weren't sortable + - Issues can now be dragged & dropped into empty milestone lists. This is also + possible with MRs + - Changed padding & background color for highlighted notes + - Re-add the newrelic_rpm gem which was removed without any deprecation or warning (Stan Hu) + - Update sentry-raven gem to 0.15.6 + - Add build coverage in project's builds page (Steffen Köhler) + - Changed # to ! for merge requests in activity view + +## 8.5.0 (2016-02-22) + + - Fix duplicate "me" in tooltip of the "thumbsup" awards Emoji (Stan Hu) + - Cache various Repository methods to improve performance + - Fix duplicated branch creation/deletion Webhooks/service notifications when using Web UI (Stan Hu) + - Ensure rake tasks that don't need a DB connection can be run without one + - Update New Relic gem to 3.14.1.311 (Stan Hu) + - Add "visibility" flag to GET /projects api endpoint + - Add an option to supply root email through an environmental variable (Koichiro Mikami) + - Ignore binary files in code search to prevent Error 500 (Stan Hu) + - Render sanitized SVG images (Stan Hu) + - Support download access by PRIVATE-TOKEN header (Stan Hu) + - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push + - Add option to include the sender name in body of Notify email (Jason Lee) + - New UI for pagination + - Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet + set it up + - API: Added "merge_requests/:merge_request_id/closes_issues" (Gal Schlezinger) + - Fix diff comments loaded by AJAX to load comment with diff in discussion tab + - Fix relative links in other markup formats (Ben Boeckel) + - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) + - Fix label links for a merge request pointing to issues list + - Don't vendor minified JS + - Increase project import timeout to 15 minutes + - Be more permissive with email address validation: it only has to contain a single '@' + - Display 404 error on group not found + - Track project import failure + - Support Two-factor Authentication for LDAP users + - Display database type and version in Administration dashboard + - Allow limited Markdown in Broadcast Messages + - Fix visibility level text in admin area (Zeger-Jan van de Weg) + - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) + - Update the ExternalIssue regex pattern (Blake Hitchcock) + - Remember user's inline/side-by-side diff view preference in a cookie (Kirill Katsnelson) + - Optimized performance of finding issues to be closed by a merge request + - Add `avatar_url`, `description`, `git_ssh_url`, `git_http_url`, `path_with_namespace` + and `default_branch` in `project` in push, issue, merge-request and note webhooks data (Kirill Zaitsev) + - Deprecate the `ssh_url` in favor of `git_ssh_url` and `http_url` in favor of `git_http_url` + in `project` for push, issue, merge-request and note webhooks data (Kirill Zaitsev) + - Deprecate the `repository` key in push, issue, merge-request and note webhooks data, use `project` instead (Kirill Zaitsev) + - API: Expose MergeRequest#merge_status (Andrei Dziahel) + - Revert "Add IP check against DNSBLs at account sign-up" + - Actually use the `skip_merges` option in Repository#commits (Tony Chu) + - Fix API to keep request parameters in Link header (Michael Potthoff) + - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead + - Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead + - Prevent parse error when name of project ends with .atom and prevent path issues + - Discover branches for commit statuses ref-less when doing merge when succeeded + - Mark inline difference between old and new paths when a file is renamed + - Support Akismet spam checking for creation of issues via API (Stan Hu) + - API: Allow to set or update a merge-request's milestone (Kirill Skachkov) + - Improve UI consistency between projects and groups lists + - Add sort dropdown to dashboard projects page + - Fixed logo animation on Safari (Roman Rott) + - Fix Merge When Succeeded when multiple stages + - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) + - In seach autocomplete show only groups and projects you are member of + - Don't process cross-reference notes from forks + - Fix: init.d script not working on OS X + - Faster snippet search + - Added API to download build artifacts + - Title for milestones should be unique (Zeger-Jan van de Weg) + - Validate correctness of maximum attachment size application setting + - Replaces "Create merge request" link with one to the "Merge Request" when one exists + - Fix CI builds badge, add a new link to builds badge, deprecate the old one + - Fix broken link to project in build notification emails + - Ability to see and sort on vote count from Issues and MR lists + - Fix builds scheduler when first build in stage was allowed to fail + - User project limit is reached notice is hidden if the projects limit is zero + - Add API support for managing runners and project's runners + - Allow SAML users to login with no previous account without having to allow + all Omniauth providers to do so. + - Allow existing users to auto link their SAML credentials by logging in via SAML + - Make it possible to erase a build (trace, artifacts) using UI and API + - Ability to revert changes from a Merge Request or Commit + - Emoji comment on diffs are not award emoji + - Add label description (Nuttanart Pornprasitsakul) + - Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul) + - Add Todos + +## 8.4.11 + + - Prevent unauthorized access to other projects build traces + - Forbid scripting for wiki files + +## 8.4.10 + + - Prevent privilege escalation via "impersonate" feature + - Prevent privilege escalation via notes API + - Prevent privilege escalation via project webhook API + - Prevent XSS via Git branch and tag names + - Prevent XSS via custom issue tracker URL + - Prevent XSS via `window.opener` + - Prevent information disclosure via snippet API + - Prevent information disclosure via project labels + - Prevent information disclosure via new merge request page + +## 8.4.9 + + - Fix persistent XSS vulnerability in `commit_person_link` helper + +## 8.4.8 + + - Fix a 2FA authentication spoofing vulnerability. + +## 8.4.7 + + - Don't attempt to fetch any tags from a forked repo (Stan Hu). + +## 8.4.6 + + - Bump Git version requirement to 2.7.4 + +## 8.4.5 + + - No CE-specific changes + +## 8.4.4 + + - Update omniauth-saml gem to 1.4.2 + - Prevent long-running backup tasks from timing out the database connection + - Add a Project setting to allow guests to view build logs (defaults to true) + - Sort project milestones by due date including issue editor (Oliver Rogers / Orih) + +## 8.4.3 + + - Increase lfs_objects size column to 8-byte integer to allow files larger + than 2.1GB + - Correctly highlight MR diff when MR has merge conflicts + - Fix highlighting in blame view + - Update sentry-raven gem to prevent "Not a git repository" console output + when running certain commands + - Add instrumentation to additional Gitlab::Git and Rugged methods for + performance monitoring + - Allow autosize textareas to also be manually resized + +## 8.4.2 + + - Bump required gitlab-workhorse version to bring in a fix for missing + artifacts in the build artifacts browser + - Get rid of those ugly borders on the file tree view + - Fix updating the runner information when asking for builds + - Bump gitlab_git version to 7.2.24 in order to bring in a performance + improvement when checking if a repository was empty + - Add instrumentation for Gitlab::Git::Repository instance methods so we can + track them in Performance Monitoring. + - Increase contrast between highlighted code comments and inline diff marker + - Fix method undefined when using external commit status in builds + - Fix highlighting in blame view. + +## 8.4.1 + + - Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3), + and Nokogiri (1.6.7.2) + - Fix redirect loop during import + - Fix diff highlighting for all syntax themes + - Delete project and associations in a background worker + +## 8.4.0 (2016-01-22) + + - Allow LDAP users to change their email if it was not set by the LDAP server + - Ensure Gravatar host looks like an actual host + - Consider re-assign as a mention from a notification point of view + - Add pagination headers to already paginated API resources + - Properly generate diff of orphan commits, like the first commit in a repository + - Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages + - Autocomplete data is now always loaded, instead of when focusing a comment text area + - Improved performance of finding issues for an entire group + - Added custom application performance measuring system powered by InfluxDB + - Add syntax highlighting to diffs + - Gracefully handle invalid UTF-8 sequences in Markdown links (Stan Hu) + - Bump fog to 1.36.0 (Stan Hu) + - Add user's last used IP addresses to admin page (Stan Hu) + - Add housekeeping function to project settings page + - The default GitLab logo now acts as a loading indicator + - Fix caching issue where build status was not updating in project dashboard (Stan Hu) + - Accept 2xx status codes for successful Webhook triggers (Stan Hu) + - Fix missing date of month in network graph when commits span a month (Stan Hu) + - Expire view caches when application settings change (e.g. Gravatar disabled) (Stan Hu) + - Don't notify users twice if they are both project watchers and subscribers (Stan Hu) + - Remove gray background from layout in UI + - Fix signup for OAuth providers that don't provide a name + - Implement new UI for group page + - Implement search inside emoji picker + - Let the CI runner know about builds that this build depends on + - Add API support for looking up a user by username (Stan Hu) + - Add project permissions to all project API endpoints (Stan Hu) + - Link to milestone in "Milestone changed" system note + - Only allow group/project members to mention `@all` + - Expose Git's version in the admin area (Trey Davis) + - Add "Frequently used" category to emoji picker + - Add CAS support (tduehr) + - Add link to merge request on build detail page + - Fix: Problem with projects ending with .keys (Jose Corcuera) + - Revert back upvote and downvote button to the issue and MR pages + - Swap position of Assignee and Author selector on Issuables (Zeger-Jan van de Weg) + - Add system hook messages for project rename and transfer (Steve Norman) + - Fix version check image in Safari + - Show 'All' tab by default in the builds page + - Add Open Graph and Twitter Card data to all pages + - Fix API project lookups when querying with a namespace with dots (Stan Hu) + - Enable forcing Two-factor authentication sitewide, with optional grace period + - Import GitHub Pull Requests into GitLab + - Change single user API endpoint to return more detailed data (Michael Potthoff) + - Update version check images to use SVG + - Validate README format before displaying + - Enable Microsoft Azure OAuth2 support (Janis Meybohm) + - Properly set task-list class on single item task lists + - Add file finder feature in tree view (Kyungchul Shin) + - Ajax filter by message for commits page + - API: Add support for deleting a tag via the API (Robert Schilling) + - Allow subsequent validations in CI Linter + - Show referenced MRs & Issues only when the current viewer can access them + - Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee) + - Add API support for managing project's builds + - Add API support for managing project's build triggers + - Add API support for managing project's build variables + - Allow broadcast messages to be edited + - Autosize Markdown textareas + - Import GitHub wiki into GitLab + - Add reporters ability to download and browse build artifacts (Andrew Johnson) + - Autofill referring url in message box when reporting user abuse. + - Remove leading comma on award emoji when the user is the first to award the emoji (Zeger-Jan van de Weg) + - Add build artifacts browser + - Improve UX in builds artifacts browser + - Increase default size of `data` column in `events` table when using MySQL + - Expose button to CI Lint tool on project builds page + - Fix: Creator should be added as a master of the project on creation + - Added X-GitLab-... headers to emails from CI and Email On Push services (Anton Baklanov) + - Add IP check against DNSBLs at account sign-up + - Added cache:key to .gitlab-ci.yml allowing to fine tune the caching + +## 8.3.10 + + - Prevent unauthorized access to other projects build traces + - Forbid scripting for wiki files + +## 8.3.9 + + - Prevent privilege escalation via "impersonate" feature + - Prevent privilege escalation via notes API + - Prevent privilege escalation via project webhook API + - Prevent XSS via custom issue tracker URL + - Prevent XSS via `window.opener` + - Prevent information disclosure via project labels + - Prevent information disclosure via new merge request page + +## 8.3.8 + + - Fix persistent XSS vulnerability in `commit_person_link` helper + +## 8.3.7 + + - Fix a 2FA authentication spoofing vulnerability. + +## 8.3.6 + + - Don't attempt to fetch any tags from a forked repo (Stan Hu). + +## 8.3.5 + + - Bump Git version requirement to 2.7.4 + +## 8.3.4 + + - Use gitlab-workhorse 0.5.4 (fixes API routing bug) + +## 8.3.3 + + - Preserve CE behavior with JIRA integration by only calling API if URL is set + - Fix duplicated branch creation/deletion events when using Web UI (Stan Hu) + - Add configurable LDAP server query timeout + - Get "Merge when build succeeds" to work when commits were pushed to MR target branch while builds were running + - Suppress e-mails on failed builds if allow_failure is set (Stan Hu) + - Fix project transfer e-mail sending incorrect paths in e-mail notification (Stan Hu) + - Better support for referencing and closing issues in Asana service (Mike Wyatt) + - Enable "Add key" button when user fills in a proper key (Stan Hu) + - Fix error in processing reply-by-email messages (Jason Lee) + - Fix Error 500 when visiting build page of project with nil runners_token (Stan Hu) + - Use WOFF versions of SourceSansPro fonts + - Fix regression when builds were not generated for tags created through web/api interface + - Fix: maintain milestone filter between Open and Closed tabs (Greg Smethells) + - Fix missing artifacts and build traces for build created before 8.3 + +## 8.3.2 + + - Disable --follow in `git log` to avoid loading duplicate commit data in infinite scroll (Stan Hu) + - Add support for Google reCAPTCHA in user registration + +## 8.3.1 + + - Fix Error 500 when global milestones have slashes (Stan Hu) + - Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu) + - Fix LDAP identity and user retrieval when special characters are used + - Move Sidekiq-cron configuration to gitlab.yml + +## 8.3.0 (2015-12-22) + + - Bump rack-attack to 4.3.1 for security fix (Stan Hu) + - API support for starred projects for authorized user (Zeger-Jan van de Weg) + - Add open_issues_count to project API (Stan Hu) + - Expand character set of usernames created by Omniauth (Corey Hinshaw) + - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) + - Add unsubscribe link in the email footer (Zeger-Jan van de Weg) + - Provide better diagnostic message upon project creation errors (Stan Hu) + - Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu) + - Remove api credentials from link to build_page + - Deprecate GitLabCiService making it to always be inactive + - Bump gollum-lib to 4.1.0 (Stan Hu) + - Fix broken group avatar upload under "New group" (Stan Hu) + - Update project repositorize size and commit count during import:repos task (Stan Hu) + - Fix API setting of 'public' attribute to false will make a project private (Stan Hu) + - Handle and report SSL errors in Webhook test (Stan Hu) + - Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu) + - Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera) + - WIP identifier on merge requests no longer requires trailing space + - Add rake tasks for git repository maintainance (Zeger-Jan van de Weg) + - Fix 500 error when update group member permission + - Fix: As an admin, cannot add oneself as a member to a group/project + - Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera) + - Recognize issue/MR/snippet/commit links as references + - Backport JIRA features from EE to CE + - Add ignore whitespace change option to commit view + - Fire update hook from GitLab + - Allow account unlock via email + - Style warning about mentioning many people in a comment + - Fix: sort milestones by due date once again (Greg Smethells) + - Migrate all CI::Services and CI::WebHooks to Services and WebHooks + - Don't show project fork event as "imported" + - Add API endpoint to fetch merge request commits list + - Don't create CI status for refs that doesn't have .gitlab-ci.yml, even if the builds are enabled + - Expose events API with comment information and author info + - Fix: Ensure "Remove Source Branch" button is not shown when branch is being deleted. #3583 + - Run custom Git hooks when branch is created or deleted. + - Fix bug when simultaneously accepting multiple MRs results in MRs that are of "merged" status, but not merged to the target branch + - Add languages page to graphs + - Block LDAP user when they are no longer found in the LDAP server + - Improve wording on project visibility levels (Zeger-Jan van de Weg) + - Fix editing notes on a merge request diff + - Automatically select default clone protocol based on user preferences (Eirik Lygre) + - Make Network page as sub tab of Commits + - Add copy-to-clipboard button for Snippets + - Add indication to merge request list item that MR cannot be merged automatically + - Default target branch to patch-n when editing file in protected branch + - Add Builds tab to merge request detail page + - Allow milestones, issues and MRs to be created from dashboard and group indexes + - Use new style for wiki + - Use new style for milestone detail page + - Fix sidebar tooltips when collapsed + - Prevent possible XSS attack with award-emoji + - Upgraded Sidekiq to 4.x + - Accept COPYING,COPYING.lesser, and licence as license file (Zeger-Jan van de Weg) + - Fix emoji aliases problem + - Fix award-emojis Flash alert's width + - Fix deleting notes on a merge request diff + - Display referenced merge request statuses in the issue description (Greg Smethells) + - Implement new sidebar for issue and merge request pages + - Emoji picker improvements + - Suppress warning about missing `.gitlab-ci.yml` if builds are disabled + - Do not show build status unless builds are enabled and `.gitlab-ci.yml` is present + - Persist runners registration token in database + - Fix online editor should not remove newlines at the end of the file + - Expose Git's version in the admin area + - Show "New Merge Request" buttons on canonical repos when you have a fork (Josh Frye) + +## 8.2.6 + + - Prevent unauthorized access to other projects build traces + - Forbid scripting for wiki files + +## 8.2.5 + + - Prevent privilege escalation via "impersonate" feature + - Prevent privilege escalation via notes API + - Prevent privilege escalation via project webhook API + - Prevent XSS via `window.opener` + - Prevent information disclosure via project labels + - Prevent information disclosure via new merge request page + +## 8.2.4 + + - Bump Git version requirement to 2.7.4 + +## 8.2.3 + + - Fix application settings cache not expiring after changes (Stan Hu) + - Fix Error 500s when creating global milestones with Unicode characters (Stan Hu) + - Update documentation for "Guest" permissions + - Properly convert Emoji-only comments into Award Emojis + - Enable devise paranoid mode to prevent user enumeration attack + - Webhook payload has an added, modified and removed properties for each commit + - Fix 500 error when creating a merge request that removes a submodule + +## 8.2.2 + + - Fix 404 in redirection after removing a project (Stan Hu) + - Ensure cached application settings are refreshed at startup (Stan Hu) + - Fix Error 500 when viewing user's personal projects from admin page (Stan Hu) + - Fix: Raw private snippets access workflow + - Prevent "413 Request entity too large" errors when pushing large files with LFS + - Fix invalid links within projects dashboard header + - Make current user the first user in assignee dropdown in issues detail page (Stan Hu) + - Fix: duplicate email notifications on issue comments + +## 8.2.1 + + - Forcefully update builds that didn't want to update with state machine + - Fix: saving GitLabCiService as Admin Template + +## 8.2.0 (2015-11-22) + + - Improved performance of finding projects and groups in various places + - Improved performance of rendering user profile pages and Atom feeds + - Expose build artifacts path as config option + - Fix grouping of contributors by email in graph. + - Improved performance of finding issues with/without labels + - Fix Drone CI service template not saving properly (Stan Hu) + - Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu) + - Added a GitLab specific profiling tool called "Sherlock" (see GitLab CE merge request #1749) + - Upgrade gitlab_git to 7.2.20 and rugged to 0.23.3 (Stan Hu) + - Improved performance of finding users by one of their Email addresses + - Add allow_failure field to commit status API (Stan Hu) + - Commits without .gitlab-ci.yml are marked as skipped + - Save detailed error when YAML syntax is invalid + - Since GitLab CI is enabled by default, remove enabling it by pushing .gitlab-ci.yml + - Added build artifacts + - Improved performance of replacing references in comments + - Show last project commit to default branch on project home page + - Highlight comment based on anchor in URL + - Adds ability to remove the forked relationship from project settings screen. (Han Loong Liauw) + - Improved performance of sorting milestone issues + - Allow users to select the Files view as default project view (Cristian Bica) + - Show "Empty Repository Page" for repository without branches (Artem V. Navrotskiy) + - Fix: Inability to reply to code comments in the MR view, if the MR comes from a fork + - Use git follow flag for commits page when retrieve history for file or directory + - Show merge request CI status on merge requests index page + - Send build name and stage in CI notification e-mail + - Extend yml syntax for only and except to support specifying repository path + - Enable shared runners to all new projects + - Bump GitLab-Workhorse to 0.4.1 + - Allow to define cache in `.gitlab-ci.yml` + - Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu) + - Remove deprecated CI events from project settings page + - Use issue editor as cross reference comment author when issue is edited with a new mention. + - Add graphs of commits ahead and behind default branch (Jeff Stubler) + - Improve personal snippet access workflow (Douglas Alexandre) + - [API] Add ability to fetch the commit ID of the last commit that actually touched a file + - Fix omniauth documentation setting for omnibus configuration (Jon Cairns) + - Add "New file" link to dropdown on project page + - Include commit logs in project search + - Add "added", "modified" and "removed" properties to commit object in webhook + - Rename "Back to" links to "Go to" because its not always a case it point to place user come from + - Allow groups to appear in the search results if the group owner allows it + - Add email notification to former assignee upon unassignment (Adam Lieskovský) + - New design for project graphs page + - Remove deprecated dumped yaml file generated from previous job definitions + - Show specific runners from projects where user is master or owner + - MR target branch is now visible on a list view when it is different from project's default one + - Improve Continuous Integration graphs page + - Make color of "Accept Merge Request" button consistent with current build status + - Add ignore white space option in merge request diff and commit and compare view + - Ability to add release notes (markdown text and attachments) to git tags (aka Releases) + - Relative links from a repositories README.md now link to the default branch + - Fix trailing whitespace issue in merge request/issue title + - Fix bug when milestone/label filter was empty for dashboard issues page + - Add ability to create milestone in group projects from single form + - Add option to create merge request when editing/creating a file (Dirceu Tiegs) + - Prevent the last owner of a group from being able to delete themselves by 'adding' themselves as a master (James Lopez) + - Add Award Emoji to issue and merge request pages + +## 8.1.4 + + - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) + - Prevent redirect loop when home_page_url is set to the root URL + - Fix incoming email config defaults + - Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu) + +## 8.1.3 + + - Force update refs/merge-requests/X/head upon a push to the source branch of a merge request (Stan Hu) + - Spread out runner contacted_at updates + - Use issue editor as cross reference comment author when issue is edited with a new mention + - Add Facebook authentication + +## 8.1.2 + + - Fix cloning Wiki repositories via HTTP (Stan Hu) + - Add migration to remove satellites directory + - Fix specific runners visibility + - Fix 500 when editing CI service + - Require CI jobs to be named + - Fix CSS for runner status + - Fix CI badge + - Allow developer to manage builds + +## 8.1.1 + + - Removed, see 8.1.2 + +## 8.1.0 (2015-10-22) + + - Ensure MySQL CI limits DB migrations occur after the fields have been created (Stan Hu) + - Fix duplicate repositories in GitHub import page (Stan Hu) + - Redirect to a default path if HTTP_REFERER is not set (Stan Hu) + - Adds ability to create directories using the web editor (Ben Ford) + - Cleanup stuck CI builds + - Send an email to admin email when a user is reported for spam (Jonathan Rochkind) + - Show notifications button when user is member of group rather than project (Grzegorz Bizon) + - Fix bug preventing mentioned issued from being closed when MR is merged using fast-forward merge. + - Fix nonatomic database update potentially causing project star counts to go negative (Stan Hu) + - Don't show "Add README" link in an empty repository if user doesn't have access to push (Stan Hu) + - Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu) + - Speed up load times of issue detail pages by roughly 1.5x + - Fix CI rendering regressions + - If a merge request is to close an issue, show this on the issue page (Zeger-Jan van de Weg) + - Add a system note and update relevant merge requests when a branch is deleted or re-added (Stan Hu) + - Make diff file view easier to use on mobile screens (Stan Hu) + - Improved performance of finding users by username or Email address + - Fix bug where merge request comments created by API would not trigger notifications (Stan Hu) + - Add support for creating directories from Files page (Stan Hu) + - Allow removing of project without confirmation when JavaScript is disabled (Stan Hu) + - Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu) + - Improved performance of the trending projects page + - Remove CI migration task + - Improved performance of finding projects by their namespace + - Add assignee data to Issuables' hook_data (Bram Daams) + - Fix bug where transferring a project would result in stale commit links (Stan Hu) + - Fix build trace updating + - Include full path of source and target branch names in New Merge Request page (Stan Hu) + - Add user preference to view activities as default dashboard (Stan Hu) + - Add option to admin area to sign in as a specific user (Pavel Forkert) + - Show CI status on all pages where commits list is rendered + - Automatically enable CI when push .gitlab-ci.yml file to repository + - Move CI charts to project graphs area + - Fix cases where Markdown did not render links in activity feed (Stan Hu) + - Add first and last to pagination (Zeger-Jan van de Weg) + - Added Commit Status API + - Added Builds View + - Added when to .gitlab-ci.yml + - Show CI status on commit page + - Added CI_BUILD_TAG, _STAGE, _NAME and _TRIGGERED to CI builds + - Show CI status on Your projects page and Starred projects page + - Remove "Continuous Integration" page from dashboard + - Add notes and SSL verification entries to hook APIs (Ben Boeckel) + - Fix grammar in admin area "labels" .nothing-here-block when no labels exist. + - Move CI runners page to project settings area + - Move CI variables page to project settings area + - Move CI triggers page to project settings area + - Move CI project settings page to CE project settings area + - Fix bug when removed file was not appearing in merge request diff + - Show warning when build cannot be served by any of the available CI runners + - Note the original location of a moved project when notifying users of the move + - Improve error message when merging fails + - Add support of multibyte characters in LDAP UID (Roman Petrov) + - Show additions/deletions stats on merge request diff + - Remove footer text in emails (Zeger-Jan van de Weg) + - Ensure code blocks are properly highlighted after a note is updated + - Fix wrong access level badge on MR comments + - Hide password in the service settings form + - Move CI webhooks page to project settings area + - Fix User Identities API. It now allows you to properly create or update user's identities. + - Add user preference to change layout width (Peter Göbel) + - Use commit status in merge request widget as preferred source of CI status + - Integrate CI commit and build pages into project pages + - Move CI services page to project settings area + - Add "Quick Submit" behavior to input fields throughout the application. Use + Cmd+Enter on Mac and Ctrl+Enter on Windows/Linux. + - Fix position of hamburger in header for smaller screens (Han Loong Liauw) + - Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji) + - Persist filters when sorting on admin user page (Jerry Lukins) + - Update style of snippets pages (Han Loong Liauw) + - Allow dashboard and group issues/MRs to be filtered by label + - Add spellcheck=false to certain input fields + - Invalidate stored service password if the endpoint URL is changed + - Project names are not fully shown if group name is too big, even on group page view + - Apply new design for Files page + - Add "New Page" button to Wiki Pages tab (Stan Hu) + - Only render 404 page from /public + - Hide passwords from services API (Alex Lossent) + - Fix: Images cannot show when projects' path was changed + - Let gitlab-git-http-server generate and serve 'git archive' downloads + - Optimize query when filtering on issuables (Zeger-Jan van de Weg) + - Fix padding of outdated discussion item. + - Animate the logo on hover + +## 8.0.5 + + - Correct lookup-by-email for LDAP logins + - Fix loading spinner sometimes not being hidden on Merge Request tab switches + +## 8.0.4 + + - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) + - Fix referrals for :back and relative URL installs + - Fix anchors to comments in diffs + - Remove CI token from build traces + - Fix "Assign All" button on Runner admin page + - Fix search in Files + - Add full project namespace to payload of system webhooks (Ricardo Band) + +## 8.0.3 + + - Fix URL shown in Slack notifications + - Fix bug where projects would appear to be stuck in the forked import state (Stan Hu) + - Fix Error 500 in creating merge requests with > 1000 diffs (Stan Hu) + - Add work_in_progress key to MR webhooks (Ben Boeckel) + +## 8.0.2 + + - Fix default avatar not rendering in network graph (Stan Hu) + - Skip check_initd_configured_correctly on omnibus installs + - Prevent double-prefixing of help page paths + - Clarify confirmation text on user deletion + - Make commit graphs responsive to window width changes (Stan Hu) + - Fix top margin for sign-in button on public pages + - Fix LDAP attribute mapping + - Remove git refs used internally by GitLab from network graph (Stan Hu) + - Use standard Markdown font in Markdown preview instead of fixed-width font (Stan Hu) + - Fix Reply by email for non-UTF-8 messages. + - Add option to use StartTLS with Reply by email IMAP server. + - Allow AWS S3 Server-Side Encryption with Amazon S3-Managed Keys for backups (Paul Beattie) + +## 8.0.1 + + - Improve CI migration procedure and documentation + +## 8.0.0 (2015-09-22) + + - Fix Markdown links not showing up in dashboard activity feed (Stan Hu) + - Remove milestones from merge requests when milestones are deleted (Stan Hu) + - Fix HTML link that was improperly escaped in new user e-mail (Stan Hu) + - Fix broken sort in merge request API (Stan Hu) + - Bump rouge to 1.10.1 to remove warning noise and fix other syntax highlighting bugs (Stan Hu) + - Gracefully handle errors in syntax highlighting by leaving the block unformatted (Stan Hu) + - Add "replace" and "upload" functionalities to allow user replace existing file and upload new file into current repository + - Fix URL construction for merge requests, issues, notes, and commits for relative URL config (Stan Hu) + - Fix emoji URLs in Markdown when relative_url_root is used (Stan Hu) + - Omit filename in Content-Disposition header in raw file download to avoid RFC 6266 encoding issues (Stan HU) + - Fix broken Wiki Page History (Stan Hu) + - Import forked repositories asynchronously to prevent large repositories from timing out (Stan Hu) + - Prevent anchors from being hidden by header (Stan Hu) + - Fix bug where only the first 15 Bitbucket issues would be imported (Stan Hu) + - Sort issues by creation date in Bitbucket importer (Stan Hu) + - Prevent too many redirects upon login when home page URL is set to external_url (Stan Hu) + - Improve dropdown positioning on the project home page (Hannes Rosenögger) + - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibilty mode (Stan Hu) + - Remove user OAuth tokens from the database and request new tokens each session (Stan Hu) + - Restrict users API endpoints to use integer IDs (Stan Hu) + - Only show recent push event if the branch still exists or a recent merge request has not been created (Stan Hu) + - Remove satellites + - Better performance for web editor (switched from satellites to rugged) + - Faster merge + - Ability to fetch merge requests from refs/merge-requests/:id + - Allow displaying of archived projects in the admin interface (Artem Sidorenko) + - Allow configuration of import sources for new projects (Artem Sidorenko) + - Search for comments should be case insensetive + - Create cross-reference for closing references on commits pushed to non-default branches (Maël Valais) + - Ability to search milestones + - Gracefully handle SMTP user input errors (e.g. incorrect email addresses) to prevent Sidekiq retries (Stan Hu) + - Move dashboard activity to separate page (for your projects and starred projects) + - Improve performance of git blame + - Limit content width to 1200px for most of pages to improve readability on big screens + - Fix 500 error when submit project snippet without body + - Improve search page usability + - Bring more UI consistency in way how projects, snippets and groups lists are rendered + - Make all profiles and group public + - Fixed login failure when extern_uid changes (Joel Koglin) + - Don't notify users without access to the project when they are (accidentally) mentioned in a note. + - Retrieving oauth token with LDAP credentials + - Load Application settings from running database unless env var USE_DB=false + - Added Drone CI integration (Kirill Zaitsev) + - Allow developers to retry builds + - Hide advanced project options for non-admin users + - Fail builds if no .gitlab-ci.yml is found + - Refactored service API and added automatically service docs generator (Kirill Zaitsev) + - Added web_url key project hook_attrs (Kirill Zaitsev) + - Add ability to get user information by ID of an SSH key via the API + - Fix bug which IE cannot show image at markdown when the image is raw file of gitlab + - Add support for Crowd + - Global Labels that are available to all projects + - Fix highlighting of deleted lines in diffs. + - Project notification level can be set on the project page itself + - Added service API endpoint to retrieve service parameters (Petheő Bence) + - Add FogBugz project import (Jared Szechy) + - Sort users autocomplete lists by user (Allister Antosik) + - Webhook for issue now contains repository field (Jungkook Park) + - Add ability to add custom text to the help page (Jeroen van Baarsen) + - Add pg_schema to backup config + - Fix references to target project issues in Merge Requests markdown preview and textareas (Francesco Levorato) + - Redirect from incorrectly cased group or project path to correct one (Francesco Levorato) + - Removed API calls from CE to CI + +## 7.14.3 through 0.8.0 + +- See [changelogs/archive.md](changelogs/archive.md) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0cdcb54b0ae..b4635e50c28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -247,7 +247,7 @@ request is as follows: 1. Fork the project into your personal space on GitLab.com 1. Create a feature branch, branch away from `master` 1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code -1. Add your changes to the [CHANGELOG](CHANGELOG): +1. Add your changes to the [CHANGELOG.md](CHANGELOG.md): 1. If you are fixing a ~regression issue, you can add your entry to the next patch release (e.g. `8.12.5` if current version is `8.12.4`) 1. Otherwise, add your entry to the next minor release (e.g. `8.13.0` if diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index 7c0eb90d540..2215f37b81a 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -228,7 +228,7 @@ We'll discuss the three reasons to merge in master: leveraging code, merge confl If you need to leverage some code that was introduced in master after you created the feature branch you can sometimes solve this by just cherry-picking a commit. If your feature branch has a merge conflict, creating a merge commit is a normal way of solving this. You can prevent some merge conflicts by using [gitattributes](http://git-scm.com/docs/gitattributes) for files that can be in a random order. -For example in GitLab our changelog file is specified in .gitattributes as `CHANGELOG merge=union` so that there are fewer merge conflicts in it. +For example in GitLab our changelog file is specified in .gitattributes as `CHANGELOG.md merge=union` so that there are fewer merge conflicts in it. The last reason for creating merge commits is having long lived branches that you want to keep up to date with the latest state of the project. Martin Fowler, in [his article about feature branches](http://martinfowler.com/bliki/FeatureBranch.html) talks about this Continuous Integration (CI). At GitLab we are guilty of confusing CI with branch testing. Quoting Martin Fowler: "I've heard people say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit. diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh index fb4d8463981..7c4e8276902 100755 --- a/scripts/lint-doc.sh +++ b/scripts/lint-doc.sh @@ -10,11 +10,11 @@ then exit 1 fi -# Ensure that the CHANGELOG does not contain duplicate versions -DUPLICATE_CHANGELOG_VERSIONS=$(grep --extended-regexp '^v [0-9.]+' CHANGELOG | sed 's| (unreleased)||' | sort | uniq -d) +# Ensure that the CHANGELOG.md does not contain duplicate versions +DUPLICATE_CHANGELOG_VERSIONS=$(grep --extended-regexp '^## .+' CHANGELOG.md | sed -E 's| \(.+\)||' | sort -r | uniq -d) if [ "${DUPLICATE_CHANGELOG_VERSIONS}" != "" ] then - echo '✖ ERROR: Duplicate versions in CHANGELOG:' >&2 + echo '✖ ERROR: Duplicate versions in CHANGELOG.md:' >&2 echo "${DUPLICATE_CHANGELOG_VERSIONS}" >&2 exit 1 fi -- cgit v1.2.1 From d78c667d581dca6b75895f70f0ae6ebdd0f5d815 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 14 Oct 2016 16:47:55 -0700 Subject: Fix broken Spinach tests caused by changes in !6550 Partial fix to #23378 --- features/steps/project/commits/commits.rb | 20 ++++++++++++++------ spec/features/compare_spec.rb | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb index b8264f97687..fd7b1debd68 100644 --- a/features/steps/project/commits/commits.rb +++ b/features/steps/project/commits/commits.rb @@ -42,15 +42,16 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps end step 'I fill compare fields with branches' do - fill_in 'from', with: 'feature' - fill_in 'to', with: 'master' + select_using_dropdown('from', 'feature') + select_using_dropdown('to', 'master') click_button 'Compare' end step 'I fill compare fields with refs' do - fill_in "from", with: sample_commit.parent_id - fill_in "to", with: sample_commit.id + select_using_dropdown('from', sample_commit.parent_id) + select_using_dropdown('to', sample_commit.id) + click_button "Compare" end @@ -97,8 +98,8 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps end step 'I fill compare fields with branches' do - fill_in 'from', with: 'master' - fill_in 'to', with: 'feature' + select_using_dropdown('from', 'master') + select_using_dropdown('to', 'feature') click_button 'Compare' end @@ -182,4 +183,11 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps expect(page).to have_content "More submodules" expect(page).not_to have_content "Change some files" end + + def select_using_dropdown(dropdown_type, selection) + dropdown = find(".js-compare-#{dropdown_type}-dropdown") + dropdown.find(".compare-dropdown-toggle").click + dropdown.fill_in("Filter by branch/tag", with: selection) + find_link(selection, visible: true).click + end end diff --git a/spec/features/compare_spec.rb b/spec/features/compare_spec.rb index 33dfd0d5b62..c22109d19b6 100644 --- a/spec/features/compare_spec.rb +++ b/spec/features/compare_spec.rb @@ -45,6 +45,6 @@ describe "Compare", js: true do dropdown = find(".js-compare-#{dropdown_type}-dropdown") dropdown.find(".compare-dropdown-toggle").click dropdown.fill_in("Filter by branch/tag", with: selection) - click_link selection + find_link(selection, visible: true).click end end -- cgit v1.2.1 From 93e464f454ec997743048e34db5c848b4146d452 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sun, 16 Oct 2016 03:30:31 +0100 Subject: Added logic to handle a revision input that does not exist in the menu --- app/assets/javascripts/compare_autocomplete.js | 52 ------------------ app/assets/javascripts/compare_autocomplete.js.es6 | 63 ++++++++++++++++++++++ app/views/projects/compare/_ref_dropdown.html.haml | 4 +- features/steps/project/commits/commits.rb | 14 +++-- 4 files changed, 74 insertions(+), 59 deletions(-) delete mode 100644 app/assets/javascripts/compare_autocomplete.js create mode 100644 app/assets/javascripts/compare_autocomplete.js.es6 diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js deleted file mode 100644 index 294d2c9052c..00000000000 --- a/app/assets/javascripts/compare_autocomplete.js +++ /dev/null @@ -1,52 +0,0 @@ -(function() { - this.CompareAutocomplete = (function() { - function CompareAutocomplete() { - this.initDropdown(); - } - - CompareAutocomplete.prototype.initDropdown = function() { - return $('.js-compare-dropdown').each(function() { - var $dropdown, selected; - $dropdown = $(this); - selected = $dropdown.data('selected'); - return $dropdown.glDropdown({ - data: function(term, callback) { - return $.ajax({ - url: $dropdown.data('refs-url'), - data: { - ref: $dropdown.data('ref') - } - }).done(function(refs) { - return callback(refs); - }); - }, - selectable: true, - filterable: true, - filterByText: true, - toggleLabel: true, - fieldName: $dropdown.data('field-name'), - filterInput: 'input[type="search"]', - renderRow: function(ref) { - var link; - if (ref.header != null) { - return $('
  • ').addClass('dropdown-header').text(ref.header); - } else { - link = $('').attr('href', '#').addClass(ref === selected ? 'is-active' : '').text(ref).attr('data-ref', escape(ref)); - return $('
  • ').append(link); - } - }, - id: function(obj, $el) { - return $el.attr('data-ref'); - }, - toggleLabel: function(obj, $el) { - return $el.text().trim(); - } - }); - }); - }; - - return CompareAutocomplete; - - })(); - -}).call(this); diff --git a/app/assets/javascripts/compare_autocomplete.js.es6 b/app/assets/javascripts/compare_autocomplete.js.es6 new file mode 100644 index 00000000000..9a2082d97e0 --- /dev/null +++ b/app/assets/javascripts/compare_autocomplete.js.es6 @@ -0,0 +1,63 @@ +(function() { + this.CompareAutocomplete = (function() { + function CompareAutocomplete() { + this.initDropdown(); + } + + CompareAutocomplete.prototype.initDropdown = function() { + return $('.js-compare-dropdown').each(function() { + var $dropdown, selected; + $dropdown = $(this); + selected = $dropdown.data('selected'); + const $dropdownContainer = $dropdown.closest('.dropdown'); + const $fieldInput = $(`input[name="${$dropdown.data('field-name')}"]`, $dropdownContainer); + const $filterInput = $('input[type="search"]', $dropdownContainer); + $dropdown.glDropdown({ + data: function(term, callback) { + return $.ajax({ + url: $dropdown.data('refs-url'), + data: { + ref: $dropdown.data('ref') + } + }).done(function(refs) { + return callback(refs); + }); + }, + selectable: true, + filterable: true, + filterByText: true, + toggleLabel: true, + fieldName: $dropdown.data('field-name'), + filterInput: 'input[type="search"]', + renderRow: function(ref) { + var link; + if (ref.header != null) { + return $('
  • ').addClass('dropdown-header').text(ref.header); + } else { + link = $('').attr('href', '#').addClass(ref === selected ? 'is-active' : '').text(ref).attr('data-ref', escape(ref)); + return $('
  • ').append(link); + } + }, + id: function(obj, $el) { + return $el.attr('data-ref'); + }, + toggleLabel: function(obj, $el) { + return $el.text().trim(); + } + }); + $filterInput.on('keyup', (e) => { + const keyCode = e.keyCode || e.which; + if (keyCode !== 13) return; + const text = $filterInput.val(); + $fieldInput.val(text); + $('.dropdown-toggle-text', $dropdown).text(text); + $dropdownContainer.removeClass('open'); + }); + }); + }; + + return CompareAutocomplete; + + })(); + +}).call(this); diff --git a/app/views/projects/compare/_ref_dropdown.html.haml b/app/views/projects/compare/_ref_dropdown.html.haml index 27d928c87a0..05fb37cdc0f 100644 --- a/app/views/projects/compare/_ref_dropdown.html.haml +++ b/app/views/projects/compare/_ref_dropdown.html.haml @@ -1,5 +1,5 @@ .dropdown-menu.dropdown-menu-selectable - = dropdown_title "Select branch/tag" - = dropdown_filter "Filter by branch/tag" + = dropdown_title "Select Git revision" + = dropdown_filter "Filter by Git revision" = dropdown_content = dropdown_loading diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb index fd7b1debd68..b08912de25f 100644 --- a/features/steps/project/commits/commits.rb +++ b/features/steps/project/commits/commits.rb @@ -49,8 +49,8 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps end step 'I fill compare fields with refs' do - select_using_dropdown('from', sample_commit.parent_id) - select_using_dropdown('to', sample_commit.id) + select_using_dropdown('from', sample_commit.parent_id, true) + select_using_dropdown('to', sample_commit.id, true) click_button "Compare" end @@ -184,10 +184,14 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps expect(page).not_to have_content "Change some files" end - def select_using_dropdown(dropdown_type, selection) + def select_using_dropdown(dropdown_type, selection, is_commit = false) dropdown = find(".js-compare-#{dropdown_type}-dropdown") dropdown.find(".compare-dropdown-toggle").click - dropdown.fill_in("Filter by branch/tag", with: selection) - find_link(selection, visible: true).click + dropdown.fill_in("Filter by Git revision", with: selection) + if is_commit + dropdown.find('input[type="search"]').send_keys(:return) + else + find_link(selection, visible: true).click + end end end -- cgit v1.2.1 From 913c1cd87aee7450fa0f8b6571302cff9b5f1dc1 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 16 Oct 2016 21:09:38 -0700 Subject: Fix broken rspec in compare text !6910 changed the filter text from "Filter by branch/tag" to "Filter by Git revision" --- spec/features/compare_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/compare_spec.rb b/spec/features/compare_spec.rb index c22109d19b6..43eb4000e58 100644 --- a/spec/features/compare_spec.rb +++ b/spec/features/compare_spec.rb @@ -44,7 +44,7 @@ describe "Compare", js: true do def select_using_dropdown(dropdown_type, selection) dropdown = find(".js-compare-#{dropdown_type}-dropdown") dropdown.find(".compare-dropdown-toggle").click - dropdown.fill_in("Filter by branch/tag", with: selection) + dropdown.fill_in("Filter by Git revision", with: selection) find_link(selection, visible: true).click end end -- cgit v1.2.1