Commit 07fa8e09 authored by Peter Hegman's avatar Peter Hegman Committed by Jan Provaznik

Add `Delete` button to label edit view

Allow users to delete labels from the edit view

Changelog: added
parent 4d5b4447
......@@ -56,6 +56,7 @@ export default {
</gl-sprintf>
</template>
<gl-sprintf
v-if="subjectName"
:message="
__(
`%{strongStart}${labelName}%{strongEnd} will be permanently deleted from ${subjectName}. This cannot be undone.`,
......@@ -66,6 +67,18 @@ export default {
<strong>{{ content }}</strong>
</template>
</gl-sprintf>
<gl-sprintf
v-else
:message="
__(
`%{strongStart}${labelName}%{strongEnd} will be permanently deleted. This cannot be undone.`,
)
"
>
<template #strong="{ content }">
<strong>{{ content }}</strong>
</template>
</gl-sprintf>
<template #modal-footer>
<gl-button category="secondary" @click="closeModal">{{ __('Cancel') }}</gl-button>
<gl-button
......
import Labels from '~/labels/labels';
import { initDeleteLabelModal } from '~/labels';
new Labels(); // eslint-disable-line no-new
initDeleteLabelModal();
import Labels from 'ee_else_ce/labels/labels';
import { initDeleteLabelModal } from '~/labels';
// eslint-disable-next-line no-new
new Labels();
initDeleteLabelModal();
import Labels from 'ee_else_ce/labels/labels';
import { initDeleteLabelModal } from '~/labels';
new Labels(); // eslint-disable-line no-new
initDeleteLabelModal();
......@@ -260,7 +260,7 @@ class Label < ApplicationRecord
attributes
end
def present(attributes)
def present(attributes = {})
super(**attributes.merge(presenter_class: ::LabelPresenter))
end
......
......@@ -2,7 +2,7 @@
class LabelPresenter < Gitlab::View::Presenter::Delegated
presents ::Label, as: :label
delegate :name, :full_name, to: :label_subject, prefix: :subject
delegate :name, :full_name, to: :label_subject, prefix: :subject, allow_nil: true
delegator_override :subject # TODO: Fix `Gitlab::View::Presenter::Delegated#subject` not to override `Label#subject`.
......@@ -10,6 +10,7 @@ class LabelPresenter < Gitlab::View::Presenter::Delegated
case label
when GroupLabel then edit_group_label_path(label.group, label)
when ProjectLabel then edit_project_label_path(label.project, label)
else edit_admin_label_path(label)
end
end
......@@ -17,6 +18,7 @@ class LabelPresenter < Gitlab::View::Presenter::Delegated
case label
when GroupLabel then group_label_path(label.group, label)
when ProjectLabel then project_label_path(label.project, label)
else admin_label_path(label)
end
end
......@@ -43,7 +45,7 @@ class LabelPresenter < Gitlab::View::Presenter::Delegated
end
def label_subject
@label_subject ||= label.subject
@label_subject ||= label.subject if label.respond_to?(:subject)
end
private
......
......@@ -26,9 +26,14 @@
%br
= _("Or you can choose one of the suggested colors below")
= render_suggested_colors
.form-actions
.gl-display-flex.gl-justify-content-space-between.gl-p-5.gl-bg-gray-10.gl-border-t-solid.gl-border-t-gray-100.gl-border-t-1
%div
- if @label.persisted?
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm js-save-button'
- else
= f.submit _('Create label'), class: 'btn gl-button btn-confirm js-save-button qa-label-create-button'
= link_to _('Cancel'), back_path, class: 'btn gl-button btn-default btn-cancel'
- if @label.persisted?
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm js-save-button'
- else
= f.submit _('Create label'), class: 'btn gl-button btn-confirm js-save-button qa-label-create-button'
= link_to _('Cancel'), back_path, class: 'btn gl-button btn-default btn-cancel'
- presented_label = @label.present
%button.btn.btn-danger.gl-button.btn-danger-secondary.js-delete-label-modal-button{ type: 'button', data: { label_name: presented_label.name, subject_name: presented_label.subject_name, destroy_path: presented_label.destroy_path } }
%span.gl-button-text= _('Delete')
......@@ -7,13 +7,12 @@ type: reference
# Labels administration **(FREE SELF)**
In the Admin Area, you can manage labels for the GitLab instance. For more details, see [Labels](../project/labels.md).
To manage labels for the GitLab instance, select **Labels** (**{labels}**) from the Admin Area sidebar. For more details on how to manage labels, see [Labels](../project/labels.md).
## Default Labels
Labels created in the Admin Area are automatically added to new projects.
Updating or adding labels in the Admin Area does not modify labels in existing projects.
Labels created in the Admin Area become available to each _new_ project.
![Default label set](img/admin_labels.png)
![Default label set](img/admin_labels_v14_7.png)
<!-- ## Troubleshooting
......
......@@ -90,9 +90,10 @@ label section of the right sidebar of an issue or a merge request:
color value for a specific color.
1. Click **Create**.
Once created, you can edit a label by clicking the pencil (**{pencil}**), or delete
a label by clicking the three dots (**{ellipsis_v}**) next to the **Subscribe** button
and selecting **Delete**.
To edit a label after you create it, select (**{pencil}**).
To delete a project label, select (**{ellipsis_v}**) next to the **Subscribe** button
and select **Delete** or select **Delete** when you edit a label.
WARNING:
If you delete a label, it is permanently deleted. All references to the label are removed from the system and you cannot undo the deletion.
......
......@@ -42,4 +42,6 @@ FactoryBot.define do
factory :group_label, traits: [:base_label] do
group
end
factory :admin_label, traits: [:base_label], class: 'Label'
end
......@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'admin issues labels' do
include Spec::Support::Helpers::ModalHelpers
let!(:bug_label) { Label.create!(title: 'bug', template: true) }
let!(:feature_label) { Label.create!(title: 'feature', template: true) }
......@@ -99,5 +101,19 @@ RSpec.describe 'admin issues labels' do
expect(page).to have_content('fix')
end
end
it 'allows user to delete label', :js do
visit edit_admin_label_path(bug_label)
click_button 'Delete'
within_modal do
expect(page).to have_content("#{bug_label.title} will be permanently deleted. This cannot be undone.")
click_link 'Delete label'
end
expect(page).to have_content('Label was removed')
end
end
end
......@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Edit group label' do
include Spec::Support::Helpers::ModalHelpers
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:label) { create(:group_label, group: group) }
......@@ -20,4 +22,16 @@ RSpec.describe 'Edit group label' do
expect(current_path).to eq(root_path)
expect(label.reload.title).to eq('new label name')
end
it 'allows user to delete label', :js do
click_button 'Delete'
within_modal do
expect(page).to have_content("#{label.title} will be permanently deleted from #{group.name}. This cannot be undone.")
click_link 'Delete label'
end
expect(page).to have_content("#{label.title} deleted permanently")
end
end
......@@ -3,6 +3,8 @@
require "spec_helper"
RSpec.describe "User edits labels" do
include Spec::Support::Helpers::ModalHelpers
let_it_be(:project) { create(:project_empty_repo, :public) }
let_it_be(:label) { create(:label, project: project) }
let_it_be(:user) { create(:user) }
......@@ -24,4 +26,16 @@ RSpec.describe "User edits labels" do
expect(page).to have_content(new_title).and have_no_content(label.title)
end
end
it 'allows user to delete label', :js do
click_button 'Delete'
within_modal do
expect(page).to have_content("#{label.title} will be permanently deleted from #{project.name}. This cannot be undone.")
click_link 'Delete label'
end
expect(page).to have_content('Label was removed')
end
end
......@@ -13,6 +13,10 @@ describe('DeleteLabelModal', () => {
subjectName: 'GitLab Org',
destroyPath: `${TEST_HOST}/2`,
},
{
labelName: 'admin label',
destroyPath: `${TEST_HOST}/3`,
},
];
beforeEach(() => {
......@@ -22,8 +26,12 @@ describe('DeleteLabelModal', () => {
const button = document.createElement('button');
button.setAttribute('class', 'js-delete-label-modal-button');
button.setAttribute('data-label-name', x.labelName);
button.setAttribute('data-subject-name', x.subjectName);
button.setAttribute('data-destroy-path', x.destroyPath);
if (x.subjectName) {
button.setAttribute('data-subject-name', x.subjectName);
}
button.innerHTML = 'Action';
buttonContainer.appendChild(button);
});
......@@ -62,6 +70,7 @@ describe('DeleteLabelModal', () => {
index
${0}
${1}
${2}
`(`when multiple buttons exist`, ({ index }) => {
beforeEach(() => {
initDeleteLabelModal();
......@@ -69,14 +78,22 @@ describe('DeleteLabelModal', () => {
});
it('correct props are passed to gl-modal', () => {
expect(findModal().querySelector('.modal-title').innerHTML).toContain(
buttons[index].labelName,
);
expect(findModal().querySelector('.modal-body').innerHTML).toContain(
buttons[index].subjectName,
);
const button = buttons[index];
expect(findModal().querySelector('.modal-title').innerHTML).toContain(button.labelName);
if (button.subjectName) {
expect(findModal().querySelector('.modal-body').textContent).toContain(
`${button.labelName} will be permanently deleted from ${button.subjectName}. This cannot be undone.`,
);
} else {
expect(findModal().querySelector('.modal-body').textContent).toContain(
`${button.labelName} will be permanently deleted. This cannot be undone.`,
);
}
expect(findModal().querySelector('.modal-footer .btn-danger').href).toContain(
buttons[index].destroyPath,
button.destroyPath,
);
});
});
......
......@@ -10,6 +10,7 @@ RSpec.describe LabelPresenter do
let(:label) { build_stubbed(:label, project: project).present(issuable_subject: project) }
let(:group_label) { build_stubbed(:group_label, group: group).present(issuable_subject: project) }
let(:admin_label) { build_stubbed(:admin_label).present(issuable_subject: nil) }
describe '#edit_path' do
context 'with group label' do
......@@ -23,6 +24,12 @@ RSpec.describe LabelPresenter do
it { is_expected.to eq(edit_project_label_path(project, label)) }
end
context 'with an admin label' do
subject { admin_label.edit_path }
it { is_expected.to eq(edit_admin_label_path(admin_label)) }
end
end
describe '#destroy_path' do
......@@ -37,6 +44,12 @@ RSpec.describe LabelPresenter do
it { is_expected.to eq(project_label_path(project, label)) }
end
context 'with an admin label' do
subject { admin_label.destroy_path }
it { is_expected.to eq(admin_label_path(admin_label)) }
end
end
describe '#filter_path' do
......@@ -91,6 +104,12 @@ RSpec.describe LabelPresenter do
it { is_expected.to eq(label.project.name) }
end
context 'with an admin label' do
subject { admin_label.subject_name }
it { is_expected.to be_nil }
end
end
describe '#subject_full_name' do
......@@ -105,5 +124,11 @@ RSpec.describe LabelPresenter do
it { is_expected.to eq(label.project.full_name) }
end
context 'with an admin label' do
subject { admin_label.subject_full_name }
it { is_expected.to be_nil }
end
end
end
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