Commit 7e9246e4 authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch 'sy-delete_branch_confirmation_modals-feature' into 'master'

Remove delete_branch_confirmation_modals feature flag

See merge request gitlab-org/gitlab!77231
parents 9cc354fe 336301f7
import $ from 'jquery';
const MODAL_SELECTOR = '#modal-delete-branch';
class DeleteModal {
constructor() {
this.$modal = $(MODAL_SELECTOR);
this.$toggleBtns = $(`[data-target="${MODAL_SELECTOR}"]`);
this.$branchName = $('.js-branch-name', this.$modal);
this.$confirmInput = $('.js-delete-branch-input', this.$modal);
this.$deleteBtn = $('.js-delete-branch', this.$modal);
this.$notMerged = $('.js-not-merged', this.$modal);
this.bindEvents();
}
bindEvents() {
this.$toggleBtns.on('click', this.setModalData.bind(this));
this.$confirmInput.on('input', this.setDeleteDisabled.bind(this));
this.$deleteBtn.on('click', this.setDisableDeleteButton.bind(this));
}
setModalData(e) {
const branchData = e.currentTarget.dataset;
this.branchName = branchData.branchName || '';
this.deletePath = branchData.deletePath || '';
this.isMerged = Boolean(branchData.isMerged);
this.updateModal();
}
setDeleteDisabled(e) {
this.$deleteBtn.attr('disabled', e.currentTarget.value !== this.branchName);
}
setDisableDeleteButton(e) {
if (this.$deleteBtn.is('[disabled]')) {
e.preventDefault();
e.stopPropagation();
return false;
}
return true;
}
updateModal() {
this.$branchName.text(this.branchName);
this.$confirmInput.val('');
this.$deleteBtn.attr('href', this.deletePath);
this.$deleteBtn.attr('disabled', true);
this.$notMerged.toggleClass('hidden', this.isMerged);
}
}
export default DeleteModal;
import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
import AjaxLoadingSpinner from '~/branches/ajax_loading_spinner';
import BranchSortDropdown from '~/branches/branch_sort_dropdown';
import DeleteModal from '~/branches/branches_delete_modal';
import initDiverganceGraph from '~/branches/divergence_graph';
import initDeleteBranchButton from '~/branches/init_delete_branch_button';
import initDeleteBranchModal from '~/branches/init_delete_branch_modal';
AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new
const { divergingCountsEndpoint, defaultBranch } = document.querySelector(
'.js-branch-list',
......
......@@ -45,38 +45,4 @@
= render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name], class: 'gl-vertical-align-top'
- if Feature.enabled?(:delete_branch_confirmation_modals, @project, default_enabled: :yaml)
= render 'projects/branches/delete_branch_modal_button', project: @project, branch: branch, merged: merged
- elsif can?(current_user, :push_code, @project)
- if branch.name == @project.repository.root_ref
- delete_default_branch_tooltip = s_('Branches|The default branch cannot be deleted')
%span.gl-display-inline-block.has-tooltip{ title: delete_default_branch_tooltip }
%button{ class: 'gl-button btn btn-default btn-icon disabled', disabled: true, 'aria-label' => delete_default_branch_tooltip }
= sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- elsif protected_branch?(@project, branch)
- if can?(current_user, :push_to_delete_protected_branch, @project)
- delete_protected_branch_tooltip = s_('Branches|Delete protected branch')
%button{ class: 'gl-button btn btn-default btn-icon has-tooltip',
title: delete_protected_branch_tooltip,
'aria-label' => delete_protected_branch_tooltip,
data: { toggle: 'modal',
target: '#modal-delete-branch',
delete_path: project_branch_path(@project, branch.name),
branch_name: branch.name,
is_merged: ('true' if merged) } }
= sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- else
- delete_protected_branch_disabled_tooltip = s_('Branches|Only a project maintainer or owner can delete a protected branch')
%span.has-tooltip{ title: delete_protected_branch_disabled_tooltip }
%button{ class: 'gl-button btn btn-default btn-icon disabled', disabled: true, 'aria-label' => delete_protected_branch_disabled_tooltip, data: { testid: 'remove-protected-branch' } }
= sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- else
= link_to project_branch_path(@project, branch.name),
class: 'gl-button btn btn-default btn-icon js-remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip',
title: s_('Branches|Delete branch'),
method: :delete,
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
remote: true,
'aria-label' => s_('Branches|Delete branch') do
= sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
= render 'projects/branches/delete_branch_modal_button', project: @project, branch: branch, merged: merged
#modal-delete-branch.modal{ tabindex: -1 }
.modal-dialog
.modal-content
.modal-header
%h3.page-title
- title_branch_name = capture do
%span.js-branch-name.ref-name>[branch name]
= s_("Branches|Delete protected branch '%{branch_name}'?").html_safe % { branch_name: title_branch_name }
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": "true" } ×
.modal-body
%p
- branch_name = capture do
%strong.js-branch-name.ref-name>[branch name]
= s_('Branches|You’re about to permanently delete the protected branch %{branch_name}.').html_safe % { branch_name: branch_name }
%p.js-not-merged
- default_branch = capture do
%span.ref-name= @repository.root_ref
= s_('Branches|This branch hasn’t been merged into %{default_branch}.').html_safe % { default_branch: default_branch }
= s_('Branches|To avoid data loss, consider merging this branch before deleting it.')
%p
- delete_protected_branch = capture do
%strong
= s_('Branches|Delete protected branch')
= s_('Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered.').html_safe % { delete_protected_branch: delete_protected_branch }
%p
- branch_name_confirmation = capture do
%kbd.js-branch-name [branch name]
%strong
= s_('Branches|To confirm, type %{branch_name_confirmation}:').html_safe % { branch_name_confirmation: branch_name_confirmation }
.form-group
= text_field_tag 'delete_branch_input', '', class: 'form-control js-delete-branch-input'
.modal-footer
%button.gl-button.btn.btn-default{ data: { dismiss: 'modal' } } Cancel
= link_to s_('Branches|Delete protected branch'), '',
class: "gl-button btn btn-danger js-delete-branch",
title: s_('Branches|Delete branch'),
method: :delete,
'aria-label' => s_('Branches|Delete branch')
......@@ -50,7 +50,5 @@
.nothing-here-block
= s_('Branches|No branches to show')
- if Feature.enabled?(:delete_branch_confirmation_modals, @project, default_enabled: :yaml) && can?(current_user, :push_code, @project)
- if can?(current_user, :push_code, @project)
.js-delete-branch-modal
- elsif can?(current_user, :push_code, @project)
= render 'projects/branches/delete_protected_modal'
---
name: delete_branch_confirmation_modals
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56782
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/329052
milestone: '14.3'
type: development
group: group::expansion
default_enabled: true
......@@ -5943,18 +5943,12 @@ msgstr ""
msgid "Branches|Delete protected branch"
msgstr ""
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
msgstr ""
msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
msgstr ""
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr ""
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr ""
......@@ -5970,9 +5964,6 @@ msgstr ""
msgid "Branches|No branches to show"
msgstr ""
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
msgstr ""
......@@ -6021,15 +6012,6 @@ msgstr ""
msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
msgstr ""
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
msgstr ""
msgid "Branches|To confirm, type %{branch_name_confirmation}:"
msgstr ""
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
msgstr ""
......@@ -6048,9 +6030,6 @@ msgstr ""
msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
msgstr ""
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr ""
msgid "Branches|diverged from upstream"
msgstr ""
......
......@@ -14,7 +14,6 @@ module QA
end
view 'app/views/projects/branches/_branch.html.haml' do
element :remove_btn
element :branch_name
end
......
......@@ -24,8 +24,6 @@ module QA
proj.initialize_with_readme = true
end
Runtime::Feature.enable(:delete_branch_confirmation_modals, project: project)
master_branch = project.default_branch
Git::Repository.perform do |repository|
......
......@@ -32,28 +32,4 @@ RSpec.describe "User deletes branch", :js do
expect(page).to have_content('Branch was deleted')
end
context 'when the feature flag :delete_branch_confirmation_modals is disabled' do
before do
stub_feature_flags(bootstrap_confirmation_modals: false)
stub_feature_flags(delete_branch_confirmation_modals: false)
end
it "deletes branch" do
visit(project_branches_path(project))
branch_search = find('input[data-testid="branch-search"]')
branch_search.set('improve/awesome')
branch_search.native.send_keys(:enter)
page.within(".js-branch-improve\\/awesome") do
accept_alert { click_link(title: 'Delete branch') }
end
wait_for_requests
expect(page).to have_css(".js-branch-improve\\/awesome", visible: :hidden)
end
end
end
......@@ -175,26 +175,6 @@ RSpec.describe 'Branches' do
expect(page).not_to have_content('fix')
expect(all('.all-branches').last).to have_selector('li', count: 0)
end
context 'when the delete_branch_confirmation_modals feature flag is disabled' do
it 'removes branch after confirmation', :js do
stub_feature_flags(delete_branch_confirmation_modals: false)
stub_feature_flags(bootstrap_confirmation_modals: false)
visit project_branches_filtered_path(project, state: 'all')
search_for_branch('fix')
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
accept_confirm do
within('.js-branch-item', match: :first) { click_link(title: 'Delete branch') }
end
expect(page).not_to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 0)
end
end
end
context 'on project with 0 branch' do
......
......@@ -342,24 +342,6 @@ RSpec.describe 'Environment' do
expect(page).not_to have_button('Stop')
end
context 'when the feature flag :delete_branch_confirmation_modals is disabled' do
before do
stub_feature_flags(delete_branch_confirmation_modals: false)
end
it 'user deletes the branch with running environment' do
visit project_branches_filtered_path(project, state: 'all', search: 'feature')
remove_branch_with_hooks(project, user, 'feature') do
within('.js-branch-feature') { click_link(title: 'Delete branch') }
end
visit_environment(environment)
expect(page).not_to have_button('Stop')
end
end
##
# This is a workaround for problem described in #24543
#
......
......@@ -29,21 +29,6 @@ RSpec.describe 'Protected Branches', :js do
expect(page).to have_button('Only a project maintainer or owner can delete a protected branch', disabled: true)
end
context 'when feature flag :delete_branch_confirmation_modals is disabled' do
before do
stub_feature_flags(delete_branch_confirmation_modals: false)
end
it 'does not allow developer to remove protected branch' do
visit project_branches_path(project)
find('input[data-testid="branch-search"]').set('fix')
find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_selector('button[data-testid="remove-protected-branch"][disabled]')
end
end
end
end
......@@ -79,32 +64,6 @@ RSpec.describe 'Protected Branches', :js do
expect(page).to have_content('No branches to show')
end
context 'when the feature flag :delete_branch_confirmation_modals is disabled' do
before do
stub_feature_flags(delete_branch_confirmation_modals: false)
end
it 'removes branch after modal confirmation' do
visit project_branches_path(project)
find('input[data-testid="branch-search"]').set('fix')
find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
page.find('[data-target="#modal-delete-branch"]').click
expect(page).to have_css('.js-delete-branch[disabled]')
fill_in 'delete_branch_input', with: 'fix'
click_link 'Delete protected branch'
find('input[data-testid="branch-search"]').set('fix')
find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_content('No branches to show')
end
end
end
end
......
import $ from 'jquery';
import DeleteModal from '~/branches/branches_delete_modal';
describe('branches delete modal', () => {
describe('setDisableDeleteButton', () => {
let submitSpy;
let $deleteButton;
beforeEach(() => {
setFixtures(`
<div id="modal-delete-branch">
<form>
<button type="submit" class="js-delete-branch">Delete</button>
</form>
</div>
`);
$deleteButton = $('.js-delete-branch');
submitSpy = jest.fn((event) => event.preventDefault());
$('#modal-delete-branch form').on('submit', submitSpy);
// eslint-disable-next-line no-new
new DeleteModal();
});
it('does not submit if button is disabled', () => {
$deleteButton.attr('disabled', true);
$deleteButton.click();
expect(submitSpy).not.toHaveBeenCalled();
});
it('submits if button is not disabled', () => {
$deleteButton.attr('disabled', false);
$deleteButton.click();
expect(submitSpy).toHaveBeenCalled();
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment