Skip to content

Revamp group deletion protection settings

Problem to solve

As part of &7568 (closed) we want to make the group deletion protection setting easier to understand.

Proposal

Group settings

  • Move setting outside of Permissions into its own group Deletion protection
  • Change the description based on who is allowed to delete projects
  • Use radio buttons to change selection rather than a checkbox
    • 🔘 Keep project for X days
    • ️ None, delete immediately
  • When enforcement is ️ for subgroups, disable the radio buttons and show a locked setting.

Design

Before After
image image
Enforced by group Set to none in Admin Area
Enforced_deletion None_delete_immediately

Open Figma →

Implementation plan

frontend estimated weight of 3️⃣

  1. frontend Update _delayed_project_removal.html.haml to match the designs:

    1. Add the subheading Deletion protection
    2. When the settings are locked, render a lock icon with a popover next to the subheading.
      1. When locked by an admin, show the admin message.
      2. When locked by a group owner, show the group message.
    3. Add the help text Owners and administrators can delete projects.
      1. When locked by admin set the text to Only administrators can delete projects.. And when set to delete immediately, add All projects are deleted immediately. to the help text.
      2. Add a Learn more. link to the help path.
    4. When deletion is not limited to just administrators:
      1. Render the delayed_project_removal setting with radio buttons.
      2. Render the enforcement_checkbox and when the setting is locked disable the checkbox instead.
  2. Update docs.

  3. Update specs.

Note: Here is a rough patch with the interface changes. group_settings.patch

Patch contents
diff --git a/app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml b/app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml
index cfa87351689..bbcb4f3a3cd 100644
--- a/app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml
+++ b/app/views/shared/namespaces/cascading_settings/_enforcement_checkbox.html.haml
@@ -2,7 +2,7 @@
 - group = local_assigns.fetch(:group, nil)
 - form = local_assigns.fetch(:form, nil)
 - setting_locked = local_assigns.fetch(:setting_locked, false)
-- help_text = local_assigns.fetch(:help_text, s_('CascadingSettings|Subgroups cannot change this setting.'))
+- disabled = local_assigns.fetch(:disabled, false)
 
 - return unless attribute && group && form
 - return if setting_locked
@@ -10,9 +10,7 @@
 - lock_attribute = "lock_#{attribute}"
 
 .gl-form-checkbox.custom-control.custom-checkbox
-  = form.check_box lock_attribute, checked: group.namespace_settings.public_send(lock_attribute), class: 'custom-control-input', data: { testid: 'enforce-for-all-subgroups-checkbox' }
-  = form.label lock_attribute, class: 'custom-control-label' do
+  = form.check_box lock_attribute, checked: group.namespace_settings.public_send(lock_attribute), class: 'custom-control-input', data: { testid: 'enforce-for-all-subgroups-checkbox' }, disabled: disabled
+  = form.label lock_attribute, class: 'custom-control-label', aria: { disabled: disabled } do
     %span
-      = yield.presence || s_('CascadingSettings|Enforce for all subgroups')
-    %p.help-text
-      = help_text
+      = yield.presence || s_('CascadingSettings|Enforce deletion protection for all subgroups')
diff --git a/ee/app/views/groups/settings/_delayed_project_removal.html.haml b/ee/app/views/groups/settings/_delayed_project_removal.html.haml
index e6b625a6a51..4e8948f5c56 100644
--- a/ee/app/views/groups/settings/_delayed_project_removal.html.haml
+++ b/ee/app/views/groups/settings/_delayed_project_removal.html.haml
@@ -2,18 +2,29 @@
 
 - setting_locked = cascading_namespace_setting_locked?(:delayed_project_removal, group)
 
+%h5.gl-mb-2.gl-display-flex
+  = _('Deletion protection')
+  - if setting_locked
+    %span.gl-outline-0.gl-ml-3{ tabindex: "0", data: { container: "body",
+      toggle: "popover",
+      placement: "top",
+      html: "true",
+      trigger: "focus",
+      title: _('Setting enforced'),
+      content: _('This setting has been enforced by an instance administrator.')
+    } }
+      = sprite_icon('lock', size: 16)
+%p.form-text.text-muted{ class: 'gl-mb-4!' }
+  = delayed_project_removal_help_text
+  = link_to _('Learn more.'), '#', target: '_blank', rel: 'noopener noreferrer'
 .form-group{ data: { testid: 'delayed-project-removal-form-group' } }
-  .gl-form-checkbox.custom-control.custom-checkbox
-    = f.check_box :delayed_project_removal, checked: group.namespace_settings.delayed_project_removal?, disabled: setting_locked, class: 'custom-control-input', data: { testid: 'delayed-project-removal-checkbox' }
-    = render 'shared/namespaces/cascading_settings/setting_label_checkbox', attribute: :delayed_project_removal,
-        group: group,
-        form: f,
-        setting_locked: setting_locked,
-        settings_path_helper: -> (locked_ancestor) { edit_group_path(locked_ancestor, anchor: 'js-permissions-settings') },
-        help_text: delayed_project_removal_help_text do
-      = s_('GroupSettings|Enable delayed project deletion')
-    = render 'shared/namespaces/cascading_settings/enforcement_checkbox',
-        attribute: :delayed_project_removal,
-        group: group,
-        form: f,
-        setting_locked: setting_locked
+  = render 'shared/namespaces/cascading_settings/deletion_protection',
+    attribute: :delayed_project_removal,
+    group: group,
+    form: f,
+    setting_locked: setting_locked
+  = render 'shared/namespaces/cascading_settings/enforcement_checkbox',
+      attribute: :delayed_project_removal,
+      group: group,
+      form: f,
+      disabled: setting_locked
Edited by Jiaan Louw