summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfredo Sumaran <alfredo@gitlab.com>2016-08-01 16:08:36 -0500
committerAlfredo Sumaran <alfredo@gitlab.com>2016-08-05 17:19:01 -0500
commit1ac953dab437b3f2eaeca0ae39b80e40f8a09848 (patch)
tree3b08bb0153afd0d27bd6e547eb053623cbe94b24
parentd4f06e4907b5154fa864634eb67cb74427a31dd6 (diff)
downloadgitlab-ce-1ac953dab437b3f2eaeca0ae39b80e40f8a09848.tar.gz
Update layout and JS for create protected branch.
Also updates protect branch list
-rw-r--r--app/assets/javascripts/allowed_to_merge_select.js.es60
-rw-r--r--app/assets/javascripts/dispatcher.js3
-rw-r--r--app/assets/javascripts/protect_branch.js.es684
-rw-r--r--app/assets/javascripts/protected_branch_select.js72
-rw-r--r--app/assets/javascripts/protected_branch_select.js.es688
-rw-r--r--app/assets/javascripts/protected_branches_access_select.js.es663
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss8
-rw-r--r--app/assets/stylesheets/pages/projects.scss16
-rw-r--r--app/views/projects/protected_branches/_branches_list.html.haml47
-rw-r--r--app/views/projects/protected_branches/_create_protected_branch.html.haml34
-rw-r--r--app/views/projects/protected_branches/_dropdown.html.haml9
-rw-r--r--app/views/projects/protected_branches/_protected_branch.html.haml6
-rw-r--r--app/views/projects/protected_branches/index.html.haml36
-rw-r--r--spec/features/protected_branches_spec.rb8
14 files changed, 259 insertions, 215 deletions
diff --git a/app/assets/javascripts/allowed_to_merge_select.js.es6 b/app/assets/javascripts/allowed_to_merge_select.js.es6
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/app/assets/javascripts/allowed_to_merge_select.js.es6
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 9e6901962c6..ca4593d87a7 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -173,8 +173,7 @@
new Search();
break;
case 'projects:protected_branches:index':
- new ProtectedBranchesAccessSelect($(".new_protected_branch"), false, true);
- new ProtectedBranchesAccessSelect($(".protected-branches-list"), true, false);
+ new CreateProtectedBranch();
break;
}
switch (path.first()) {
diff --git a/app/assets/javascripts/protect_branch.js.es6 b/app/assets/javascripts/protect_branch.js.es6
new file mode 100644
index 00000000000..be987adc4a7
--- /dev/null
+++ b/app/assets/javascripts/protect_branch.js.es6
@@ -0,0 +1,84 @@
+class ProtectedBranchesAccessDropdown {
+ constructor(options) {
+ const { $dropdown, data, onSelect } = options;
+
+ $dropdown.glDropdown({
+ data: data,
+ selectable: true,
+ fieldName: $dropdown.data('field-name'),
+ toggleLabel(item) {
+ return item.text;
+ },
+ clicked(item, $el, e) {
+ e.preventDefault();
+ onSelect();
+ }
+ });
+ }
+}
+
+class AllowedToMergeDropdowns {
+ constructor (options) {
+ const { $dropdowns, onSelect } = options;
+
+ $dropdowns.each((i, el) => {
+ new ProtectedBranchesAccessDropdown({
+ $dropdown: $(el),
+ data: gon.merge_access_levels,
+ onSelect: onSelect
+ });
+ });
+ }
+}
+
+class AllowedToPushSelects {
+ constructor (options) {
+ const { $dropdowns, onSelect } = options;
+
+ $dropdowns.each((i, el) => {
+ new ProtectedBranchesAccessDropdown({
+ $dropdown: $(el),
+ data: gon.push_access_levels,
+ onSelect: onSelect
+ });
+ });
+ }
+}
+
+class CreateProtectedBranch {
+ constructor() {
+ this.$wrap = this.$form = $('#new_protected_branch');
+ this.buildDropdowns();
+ }
+
+ buildDropdowns() {
+ // Allowed to Merge dropdowns
+ new AllowedToMergeDropdowns({
+ $dropdowns: this.$wrap.find('.js-allowed-to-merge'),
+ onSelect: this.onSelect.bind(this)
+ });
+
+ // Allowed to Push dropdowns
+ new AllowedToPushSelects({
+ $dropdowns: this.$wrap.find('.js-allowed-to-push'),
+ onSelect: this.onSelect.bind(this)
+ });
+
+ new ProtectedBranchSelects({
+ $dropdowns: this.$wrap.find('.js-protected-branch-select'),
+ onSelect: this.onSelect.bind(this)
+ });
+ }
+
+ // This will run after clicked callback
+ onSelect() {
+ // Enable submit button
+ const $branchInput = this.$wrap.find('input[name="protected_branch[name]"]');
+ const $allowedToMergeInput = this.$wrap.find('input[name="protected_branch[merge_access_level_attributes][access_level]"]');
+ const $allowedToPushInput = this.$wrap.find('input[name="protected_branch[push_access_level_attributes][access_level]"]');
+
+ if ($branchInput.val() && $allowedToMergeInput.val() && $allowedToPushInput.val()){
+ this.$form.find('[type="submit"]').removeAttr('disabled');
+ }
+ }
+}
diff --git a/app/assets/javascripts/protected_branch_select.js b/app/assets/javascripts/protected_branch_select.js
deleted file mode 100644
index 3a47fc972dc..00000000000
--- a/app/assets/javascripts/protected_branch_select.js
+++ /dev/null
@@ -1,72 +0,0 @@
-(function() {
- var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
-
- this.ProtectedBranchSelect = (function() {
- function ProtectedBranchSelect(currentProject) {
- this.toggleCreateNewButton = bind(this.toggleCreateNewButton, this);
- this.getProtectedBranches = bind(this.getProtectedBranches, this);
- $('.dropdown-footer').hide();
- this.dropdown = $('.js-protected-branch-select').glDropdown({
- data: this.getProtectedBranches,
- filterable: true,
- remote: false,
- search: {
- fields: ['title']
- },
- selectable: true,
- toggleLabel: function(selected) {
- if (selected && 'id' in selected) {
- return selected.title;
- } else {
- return 'Protected Branch';
- }
- },
- fieldName: 'protected_branch[name]',
- text: function(protected_branch) {
- return _.escape(protected_branch.title);
- },
- id: function(protected_branch) {
- return _.escape(protected_branch.id);
- },
- onFilter: this.toggleCreateNewButton,
- clicked: function() {
- return $('.protect-branch-btn').attr('disabled', false);
- }
- });
- $('.create-new-protected-branch').on('click', (function(_this) {
- return function(event) {
- _this.dropdown.data('glDropdown').remote.execute();
- return _this.dropdown.data('glDropdown').selectRowAtIndex(event, 0);
- };
- })(this));
- }
-
- ProtectedBranchSelect.prototype.getProtectedBranches = function(term, callback) {
- if (this.selectedBranch) {
- return callback(gon.open_branches.concat(this.selectedBranch));
- } else {
- return callback(gon.open_branches);
- }
- };
-
- ProtectedBranchSelect.prototype.toggleCreateNewButton = function(branchName) {
- this.selectedBranch = {
- title: branchName,
- id: branchName,
- text: branchName
- };
- if (branchName === '') {
- $('.protected-branch-select-footer-list').addClass('hidden');
- return $('.dropdown-footer').hide();
- } else {
- $('.create-new-protected-branch').text("Create Protected Branch: " + branchName);
- $('.protected-branch-select-footer-list').removeClass('hidden');
- return $('.dropdown-footer').show();
- }
- };
-
- return ProtectedBranchSelect;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/protected_branch_select.js.es6 b/app/assets/javascripts/protected_branch_select.js.es6
new file mode 100644
index 00000000000..9a259a473ae
--- /dev/null
+++ b/app/assets/javascripts/protected_branch_select.js.es6
@@ -0,0 +1,88 @@
+class ProtectedBranchSelect {
+ constructor(options) {
+ this.onSelect = options.onSelect;
+ this.$dropdown = options.$dropdown;
+ this.$dropdownContainer = this.$dropdown.parent();
+ this.$dropdownFooter = this.$dropdownContainer.find('.dropdown-footer');
+ this.$protectedBranch = this.$dropdownContainer.find('.create-new-protected-branch');
+
+ this.buildDropdown();
+ this.bindEvents();
+
+ // Hide footer
+ this.$dropdownFooter.addClass('hidden');
+ }
+
+ buildDropdown() {
+ this.$dropdown.glDropdown({
+ data: this.getProtectedBranches.bind(this),
+ filterable: true,
+ remote: false,
+ search: {
+ fields: ['title']
+ },
+ selectable: true,
+ toggleLabel(selected) {
+ return (selected && 'id' in selected) ? selected.title : 'Protected Branch';
+ },
+ fieldName: 'protected_branch[name]',
+ text(protected_branch) {
+ return _.escape(protected_branch.title);
+ },
+ id(protected_branch) {
+ return _.escape(protected_branch.id);
+ },
+ onFilter: this.toggleCreateNewButton.bind(this),
+ clicked: (item, $el, e) => {
+ e.preventDefault();
+ this.onSelect();
+ }
+ });
+ }
+
+ bindEvents() {
+ this.$protectedBranch.on('click', this.onClickCreateWildcard.bind(this));
+ }
+
+ onClickCreateWildcard(e) {
+ this.$dropdown.data('glDropdown').remote.execute();
+ this.$dropdown.data('glDropdown').selectRowAtIndex(e, 0);
+ }
+
+ getProtectedBranches(term, callback) {
+ if (this.selectedBranch) {
+ callback(gon.open_branches.concat(this.selectedBranch));
+ } else {
+ callback(gon.open_branches);
+ }
+ }
+
+ toggleCreateNewButton(branchName) {
+ this.selectedBranch = {
+ title: branchName,
+ id: branchName,
+ text: branchName
+ };
+
+ if (branchName) {
+ this.$dropdownContainer
+ .find('.create-new-protected-branch')
+ .html(`Create wildcard <code>${branchName}</code>`);
+ }
+
+ this.$dropdownFooter.toggleClass('hidden', !branchName);
+ }
+}
+
+class ProtectedBranchSelects {
+ constructor(options) {
+ const { $dropdowns, onSelect } = options;
+
+ $dropdowns.each((i, el) => {
+ new ProtectedBranchSelect({
+ $dropdown: $(el),
+ onSelect: onSelect
+ });
+ });
+ }
+ }
diff --git a/app/assets/javascripts/protected_branches_access_select.js.es6 b/app/assets/javascripts/protected_branches_access_select.js.es6
deleted file mode 100644
index e98312bbf37..00000000000
--- a/app/assets/javascripts/protected_branches_access_select.js.es6
+++ /dev/null
@@ -1,63 +0,0 @@
-class ProtectedBranchesAccessSelect {
- constructor(container, saveOnSelect, selectDefault) {
- this.container = container;
- this.saveOnSelect = saveOnSelect;
-
- this.container.find(".allowed-to-merge").each((i, element) => {
- var fieldName = $(element).data('field-name');
- var dropdown = $(element).glDropdown({
- data: gon.merge_access_levels,
- selectable: true,
- fieldName: fieldName,
- clicked: _.chain(this.onSelect).partial(element).bind(this).value()
- });
-
- if (selectDefault) {
- dropdown.data('glDropdown').selectRowAtIndex(document.createEvent("Event"), 0);
- }
- });
-
-
- this.container.find(".allowed-to-push").each((i, element) => {
- var fieldName = $(element).data('field-name');
- var dropdown = $(element).glDropdown({
- data: gon.push_access_levels,
- selectable: true,
- fieldName: fieldName,
- clicked: _.chain(this.onSelect).partial(element).bind(this).value()
- });
-
- if (selectDefault) {
- dropdown.data('glDropdown').selectRowAtIndex(document.createEvent("Event"), 0);
- }
- });
- }
-
- onSelect(dropdown, selected, element, e) {
- $(dropdown).find('.dropdown-toggle-text').text(selected.text);
- if (this.saveOnSelect) {
- return $.ajax({
- type: "POST",
- url: $(dropdown).data('url'),
- dataType: "json",
- data: {
- _method: 'PATCH',
- id: $(dropdown).data('id'),
- protected_branch: {
- ["" + ($(dropdown).data('type')) + "_attributes"]: {
- "access_level": selected.id
- }
- }
- },
- success: function() {
- var row;
- row = $(e.target);
- return row.closest('tr').effect('highlight');
- },
- error: function() {
- return new Flash("Failed to update branch!", "alert");
- }
- });
- }
- }
-}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index c54eb0d6479..e8eafa15899 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -72,6 +72,14 @@
&.large {
width: 200px;
}
+
+ &.wide {
+ width: 100%;
+
+ + .dropdown-select {
+ width: 100%;
+ }
+ }
}
.dropdown-menu,
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index d91c8e61165..63ac471b356 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -656,13 +656,9 @@ pre.light-well {
}
.new_protected_branch {
- .dropdown {
- display: inline;
- margin-left: 15px;
- }
-
label {
- min-width: 120px;
+ margin-top: 6px;
+ font-weight: normal;
}
}
@@ -678,6 +674,14 @@ pre.light-well {
font-weight: 600;
}
}
+
+ &.table-bordered {
+ border-radius: 1px;
+
+ th:not(:last-child), td:not(:last-child) {
+ border-right: solid 1px transparent;
+ }
+ }
}
.custom-notifications-form {
diff --git a/app/views/projects/protected_branches/_branches_list.html.haml b/app/views/projects/protected_branches/_branches_list.html.haml
index 0603a014008..dc471f515d4 100644
--- a/app/views/projects/protected_branches/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/_branches_list.html.haml
@@ -1,26 +1,25 @@
-%h5.prepend-top-0
- Already Protected (#{@protected_branches.size})
-- if @protected_branches.empty?
- %p.settings-message.text-center
- No branches are protected, protect a branch with the form above.
-- else
- - can_admin_project = can?(current_user, :admin_project, @project)
+.panel.panel-default
+ - if @protected_branches.empty?
+ %p.settings-message.text-center
+ No branches are protected, protect a branch with the form above.
+ - else
+ - can_admin_project = can?(current_user, :admin_project, @project)
- %table.table.protected-branches-list
- %colgroup
- %col{ width: "20%" }
- %col{ width: "30%" }
- %col{ width: "25%" }
- %col{ width: "25%" }
- %thead
- %tr
- %th Branch
- %th Last commit
- %th Allowed to merge
- %th Allowed to push
- - if can_admin_project
- %th
- %tbody
- = render partial: @protected_branches, locals: { can_admin_project: can_admin_project }
+ %table.table.protected-branches-list.table-bordered
+ %colgroup
+ %col{ width: "20%" }
+ %col{ width: "30%" }
+ %col{ width: "25%" }
+ %col{ width: "25%" }
+ %thead
+ %tr
+ %th Protected branch (#{@protected_branches.size})
+ %th Last commit
+ %th Allowed to merge
+ %th Allowed to push
+ - if can_admin_project
+ %th
+ %tbody
+ = render partial: @protected_branches, locals: { can_admin_project: can_admin_project }
- = paginate @protected_branches, theme: 'gitlab'
+ = paginate @protected_branches, theme: 'gitlab'
diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml
new file mode 100644
index 00000000000..7006b340b34
--- /dev/null
+++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml
@@ -0,0 +1,34 @@
+= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f|
+ .panel.panel-default
+ .panel-heading
+ %b Protect a branch
+ .panel-body
+ .form-horizontal
+ .form-group
+ %label.col-md-2.text-right
+ Branch:
+ .col-md-10
+ = render partial: "dropdown", locals: { f: f }
+ .help-block
+ Wildcards such as
+ %code *-stable
+ or
+ %code production/*
+ are supported
+ .form-group
+ %label.col-md-2.text-right
+ Allowed to merge:
+ .col-md-10
+ = dropdown_tag('Select',
+ options: { toggle_class: 'js-allowed-to-merge wide',
+ data: { field_name: 'protected_branch[merge_access_level_attributes][access_level]' }})
+ .form-group
+ %label.col-md-2.text-right
+ Allowed to push:
+ .col-md-10
+ = dropdown_tag('Select',
+ options: { toggle_class: 'js-allowed-to-push wide',
+ data: { field_name: 'protected_branch[push_access_level_attributes][access_level]' }})
+
+ .panel-footer
+ = f.submit 'Protect', class: 'btn-create btn', disabled: true
diff --git a/app/views/projects/protected_branches/_dropdown.html.haml b/app/views/projects/protected_branches/_dropdown.html.haml
index b803d932e67..1281e6664dd 100644
--- a/app/views/projects/protected_branches/_dropdown.html.haml
+++ b/app/views/projects/protected_branches/_dropdown.html.haml
@@ -1,17 +1,14 @@
= f.hidden_field(:name)
-= dropdown_tag("Protected Branch",
- options: { title: "Pick protected branch", toggle_class: 'js-protected-branch-select js-filter-submit',
+= dropdown_tag('Select branch or create wildcard',
+ options: { toggle_class: 'js-protected-branch-select js-filter-submit wide',
filter: true, dropdown_class: "dropdown-menu-selectable", placeholder: "Search protected branches",
footer_content: true,
data: { show_no: true, show_any: true, show_upcoming: true,
selected: params[:protected_branch_name],
project_id: @project.try(:id) } }) do
- %ul.dropdown-footer-list.hidden.protected-branch-select-footer-list
+ %ul.dropdown-footer-list
%li
= link_to '#', title: "New Protected Branch", class: "create-new-protected-branch" do
Create new
-
-:javascript
- new ProtectedBranchSelect();
diff --git a/app/views/projects/protected_branches/_protected_branch.html.haml b/app/views/projects/protected_branches/_protected_branch.html.haml
index 498e412235e..986d591b764 100644
--- a/app/views/projects/protected_branches/_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_protected_branch.html.haml
@@ -17,13 +17,13 @@
%td
= hidden_field_tag "allowed_to_merge_#{protected_branch.id}", protected_branch.merge_access_level.access_level
= dropdown_tag(protected_branch.merge_access_level.humanize,
- options: { title: "Allowed to merge", toggle_class: 'allowed-to-merge', dropdown_class: 'dropdown-menu-selectable merge',
+ options: { toggle_class: 'allowed-to-merge', dropdown_class: 'dropdown-menu-selectable merge',
data: { field_name: "allowed_to_merge_#{protected_branch.id}", url: url, id: protected_branch.id, type: "merge_access_level" }})
%td
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", protected_branch.push_access_level.access_level
= dropdown_tag(protected_branch.push_access_level.humanize,
- options: { title: "Allowed to push", toggle_class: 'allowed-to-push', dropdown_class: 'dropdown-menu-selectable push',
+ options: { toggle_class: 'allowed-to-push', dropdown_class: 'dropdown-menu-selectable push',
data: { field_name: "allowed_to_push_#{protected_branch.id}", url: url, id: protected_branch.id, type: "push_access_level" }})
- if can_admin_project
%td
- = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right"
+ = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml
index 4efe44c7233..49dcc9a6ba4 100644
--- a/app/views/projects/protected_branches/index.html.haml
+++ b/app/views/projects/protected_branches/index.html.haml
@@ -14,41 +14,7 @@
%li prevent <strong>anyone</strong> from deleting the branch
%p.append-bottom-0 Read more about #{link_to "protected branches", help_page_path("user/project/protected_branches"), class: "underlined-link"} and #{link_to "project permissions", help_page_path("user/permissions"), class: "underlined-link"}.
.col-lg-9
- %h5.prepend-top-0
- Protect a branch
- if can? current_user, :admin_project, @project
- = form_for [@project.namespace.becomes(Namespace), @project, @protected_branch] do |f|
- = form_errors(@protected_branch)
+ = render 'create_protected_branch'
- .form-group
- = f.label :name, "Branch", class: "label-light"
- = render partial: "dropdown", locals: { f: f }
- %p.help-block
- = link_to "Wildcards", help_page_path('user/project/protected_branches', anchor: "wildcard-protected-branches")
- such as
- %code *-stable
- or
- %code production/*
- are supported.
-
- .form-group
- = hidden_field_tag 'protected_branch[merge_access_level_attributes][access_level]'
- = label_tag "Allowed to merge: ", nil, class: "label-light append-bottom-0"
- = dropdown_tag("<Make a selection>",
- options: { title: "Allowed to merge", toggle_class: 'allowed-to-merge',
- dropdown_class: 'dropdown-menu-selectable',
- data: { field_name: "protected_branch[merge_access_level_attributes][access_level]" }})
-
- .form-group
- = hidden_field_tag 'protected_branch[push_access_level_attributes][access_level]'
- = label_tag "Allowed to push: ", nil, class: "label-light append-bottom-0"
- = dropdown_tag("<Make a selection>",
- options: { title: "Allowed to push", toggle_class: 'allowed-to-push',
- dropdown_class: 'dropdown-menu-selectable',
- data: { field_name: "protected_branch[push_access_level_attributes][access_level]" }})
-
-
- = f.submit "Protect", class: "btn-create btn protect-branch-btn", disabled: true
-
- %hr
= render "branches_list"
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 57734b33a44..2a6f3b3bb1c 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -90,7 +90,7 @@ feature 'Projected Branches', feature: true, js: true do
visit namespace_project_protected_branches_path(project.namespace, project)
set_protected_branch_name('master')
within('.new_protected_branch') do
- find(".allowed-to-push").click
+ find(".js-allowed-to-push").click
within(".dropdown.open .dropdown-menu") { click_on access_type_name }
end
click_on "Protect"
@@ -107,7 +107,7 @@ feature 'Projected Branches', feature: true, js: true do
expect(ProtectedBranch.count).to eq(1)
within(".protected-branches-list") do
- find(".allowed-to-push").click
+ find(".js-allowed-to-push").click
within('.dropdown-menu.push') { click_on access_type_name }
end
@@ -121,7 +121,7 @@ feature 'Projected Branches', feature: true, js: true do
visit namespace_project_protected_branches_path(project.namespace, project)
set_protected_branch_name('master')
within('.new_protected_branch') do
- find(".allowed-to-merge").click
+ find(".js-allowed-to-merge").click
within(".dropdown.open .dropdown-menu") { click_on access_type_name }
end
click_on "Protect"
@@ -138,7 +138,7 @@ feature 'Projected Branches', feature: true, js: true do
expect(ProtectedBranch.count).to eq(1)
within(".protected-branches-list") do
- find(".allowed-to-merge").click
+ find(".js-allowed-to-merge").click
within('.dropdown-menu.merge') { click_on access_type_name }
end