From 11f4d0a5b0c4b5d7db47bab26b3bd4c2bd89c87e Mon Sep 17 00:00:00 2001 From: Sascha Eggenberger <seggenberger@gitlab.com> Date: Wed, 7 Aug 2024 11:25:49 +0000 Subject: [PATCH] Migrates token card components to CRUD --- .../components/access_token_table_app.vue | 4 +- app/components/layouts/crud_component.haml | 2 +- app/components/layouts/crud_component.rb | 14 ++-- .../impersonation_tokens/index.html.haml | 48 +++++++------- app/views/admin/labels/index.html.haml | 2 +- .../settings/access_tokens/index.html.haml | 64 +++++++++---------- app/views/projects/pages/_list.html.haml | 2 +- .../settings/access_tokens/index.html.haml | 42 ++++++------ .../personal_access_tokens/index.html.haml | 39 ++++++----- .../components/layouts/crud_component_spec.rb | 2 +- 10 files changed, 99 insertions(+), 120 deletions(-) diff --git a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue index 54b06ac2cbd52..188b5c176527f 100644 --- a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue +++ b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue @@ -108,9 +108,7 @@ export default { <template> <dom-element-listener :selector="$options.FORM_SELECTOR" @[$options.EVENT_SUCCESS]="onSuccess"> <div> - <div - class="gl-new-card-body gl-px-0 gl-overflow-x-auto gl-bg-gray-10 gl-border-l gl-border-r gl-border-b gl-rounded-bottom-base gl-mb-5 gl-md-mb-0" - > + <div> <gl-table data-testid="active-tokens" :empty-text="noActiveTokensMessage" diff --git a/app/components/layouts/crud_component.haml b/app/components/layouts/crud_component.haml index 56c6f7857597d..2ad5a7cb2f2e6 100644 --- a/app/components/layouts/crud_component.haml +++ b/app/components/layouts/crud_component.haml @@ -8,7 +8,7 @@ %span.gl-inline-flex.gl-items-center.gl-gap-2.gl-text-sm.gl-text-subtle{ data: { testid: 'crud-count' } } - if @icon = sprite_icon(@icon, css_class: @icon_class) - %span{ class: @count_class } + %span{ @count_options } = @count - if description? || @description .gl-text-sm.gl-text-subtle.gl-mt-1.gl-mb-0{ data: { testid: 'crud-description' } } diff --git a/app/components/layouts/crud_component.rb b/app/components/layouts/crud_component.rb index 219fa507c8eaf..7635e295dd6ff 100644 --- a/app/components/layouts/crud_component.rb +++ b/app/components/layouts/crud_component.rb @@ -6,25 +6,27 @@ class CrudComponent < ViewComponent::Base # @param [String] description # @param [Number] count # @param [String] icon + # @param [String] icon_class # @param [String] toggle_text # @param [Hash] options + # @param [Hash] count_options # @param [Hash] body_options # @param [Hash] form_options # @param [Hash] toggle_options # @param [Hash] footer_options def initialize( - title, description: nil, count: nil, count_class: nil, icon: nil, - icon_class: nil, toggle_text: nil, options: {}, body_options: {}, + title, description: nil, count: nil, icon: nil, icon_class: nil, + toggle_text: nil, options: {}, count_options: {}, body_options: {}, form_options: {}, toggle_options: {}, footer_options: {} ) @title = title @description = description @count = count - @count_class = count_class @icon = icon @icon_class = icon_class @toggle_text = toggle_text @options = options + @count_options = count_options @body_options = body_options @form_options = form_options @toggle_options = toggle_options @@ -63,11 +65,7 @@ def form_options_attrs def footer_options_attrs default_testid = 'crud-footer' - default_classes = [ - ('js-toggle-content' if @toggle_text), - ('gl-hidden' if @toggle_text && !@form_options[:form_errors]) - ] - @form_options.merge(default_attrs(@form_options, default_testid, default_classes)) + @footer_options.merge(default_attrs(@footer_options, default_testid)) end delegate :sprite_icon, to: :helpers diff --git a/app/views/admin/impersonation_tokens/index.html.haml b/app/views/admin/impersonation_tokens/index.html.haml index 40140e2c4ba4a..3171f019abbee 100644 --- a/app/views/admin/impersonation_tokens/index.html.haml +++ b/app/views/admin/impersonation_tokens/index.html.haml @@ -8,29 +8,27 @@ #js-new-access-token-app{ data: { access_token_type: type } } -= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card gl-border-b-0 gl-rounded-bottom-left-none gl-rounded-bottom-right-none js-toggle-container js-token-card' }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body' }) do |c| - - c.with_header do - .gl-new-card-title-wrapper.gl-flex-direction-column - %h3.gl-new-card-title - = _('Impersonation tokens') - .gl-new-card-count - = sprite_icon('token', css_class: 'gl-mr-2') - %span.js-token-count= @active_impersonation_tokens.size - .gl-new-card-description - = _("To see all the user's personal access tokens you must impersonate them first.") - .gl-new-card-actions - = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do - = _('Add new token') - - c.with_body do - .gl-new-card-add-form.gl-mt-3.gl-hidden.js-toggle-content.js-add-new-token-form - = render 'shared/access_tokens/form', - ajax: true, - type: type, - title: _('Add an impersonation token'), - path: admin_user_impersonation_tokens_path, - impersonation: true, - token: @impersonation_token, - scopes: @scopes, - help_path: help_page_path('api/rest/index', anchor: 'impersonation-tokens') += render ::Layouts::CrudComponent.new(_('Impersonation tokens'), + icon: 'token', + count: @active_impersonation_tokens.size, + count_options: { class: 'js-token-count' }, + toggle_text: _('Add new token'), + toggle_options: { data: { testid: 'add-new-token-button' } }, + form_options: { class: 'js-add-new-token-form' }, + options: { class: 'gl-mt-5 js-token-card' }) do |c| + - c.with_description do + = _("To see all the user's personal access tokens you must impersonate them first.") + + - c.with_form do + = render 'shared/access_tokens/form', + ajax: true, + type: type, + title: _('Add an impersonation token'), + path: admin_user_impersonation_tokens_path, + impersonation: true, + token: @impersonation_token, + scopes: @scopes, + help_path: help_page_path('api/rest/index', anchor: 'impersonation-tokens') -#js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_impersonation_tokens.to_json } } + - c.with_body do + #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_impersonation_tokens.to_json } } diff --git a/app/views/admin/labels/index.html.haml b/app/views/admin/labels/index.html.haml index 86bf67ffe92e4..5989f628096b6 100644 --- a/app/views/admin/labels/index.html.haml +++ b/app/views/admin/labels/index.html.haml @@ -5,7 +5,7 @@ %div{ data: { event_tracking_load: 'true', event_tracking: 'view_admin_labels_pageload' } } - if @labels.present? - = render ::Layouts::CrudComponent.new(_('Labels'), description: page_description, count: number_with_delimiter(@labels.total_count), count_class: 'js-admin-labels-count', icon: 'label', options: { class: 'labels other-labels gl-mt-5 js-admin-labels-container' }) do |c| + = render ::Layouts::CrudComponent.new(_('Labels'), description: page_description, count: number_with_delimiter(@labels.total_count), count_options: { class: 'js-admin-labels-count' }, icon: 'label', options: { class: 'labels other-labels gl-mt-5 js-admin-labels-container' }) do |c| - c.with_actions do = render Pajamas::ButtonComponent.new(variant: :default, size: :small, diff --git a/app/views/groups/settings/access_tokens/index.html.haml b/app/views/groups/settings/access_tokens/index.html.haml index 3695c5a1e2148..b012ba6283f2f 100644 --- a/app/views/groups/settings/access_tokens/index.html.haml +++ b/app/views/groups/settings/access_tokens/index.html.haml @@ -3,7 +3,6 @@ - type = _('group access token') - type_plural = _('group access tokens') - @force_desktop_expanded_sidebar = true -- shared_card_component_classes = "gl-new-card gl-border-b-0 gl-rounded-bottom-left-none gl-rounded-bottom-right-none" .settings-section.js-search-settings-section .settings-sticky-header @@ -26,44 +25,39 @@ #js-new-access-token-app{ data: { access_token_type: type } } - = render Pajamas::CardComponent.new(card_options: { class: "#{shared_card_component_classes} js-toggle-container js-token-card" }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body' }) do |c| - - c.with_header do - .gl-new-card-title-wrapper - %h3.gl-new-card-title - = _('Active group access tokens') - .gl-new-card-count - = sprite_icon('token', css_class: 'gl-mr-2') - %span.js-token-count= @active_access_tokens.size + = render ::Layouts::CrudComponent.new(_('Active group access tokens'), + icon: 'token', + count: @active_access_tokens.size, + count_options: { class: 'js-token-count' }, + form_options: { class: 'gl-hidden js-toggle-content js-add-new-token-form' }, + options: { class: 'gl-mt-5 js-toggle-container js-token-card' }) do |c| + - c.with_actions do - if current_user.can?(:create_resource_access_tokens, @group) - .gl-new-card-actions - = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do - = _('Add new token') - - c.with_body do + = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do + = _('Add new token') + + - c.with_form do - if current_user.can?(:create_resource_access_tokens, @group) - .gl-new-card-add-form.gl-mt-3.gl-hidden.js-toggle-content.js-add-new-token-form - = render 'shared/access_tokens/form', - ajax: true, - type: type, - path: group_settings_access_tokens_path(@group), - resource: @group, - token: @resource_access_token, - scopes: @scopes, - access_levels: access_level_roles_user_can_assign(@group, GroupMember.access_level_roles), - default_access_level: Gitlab::Access::GUEST, - prefix: :resource_access_token, - description_prefix: :group_access_token, - help_path: help_page_path('user/group/settings/group_access_tokens', anchor: 'scopes-for-a-group-access-token') + = render 'shared/access_tokens/form', + ajax: true, + type: type, + path: group_settings_access_tokens_path(@group), + resource: @group, + token: @resource_access_token, + scopes: @scopes, + access_levels: access_level_roles_user_can_assign(@group, GroupMember.access_level_roles), + default_access_level: Gitlab::Access::GUEST, + prefix: :resource_access_token, + description_prefix: :group_access_token, + help_path: help_page_path('user/group/settings/group_access_tokens', anchor: 'scopes-for-a-group-access-token') - #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_access_tokens.to_json, no_active_tokens_message: _('This group has no active access tokens.'), show_role: true } } + - c.with_body do + #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_access_tokens.to_json, no_active_tokens_message: _('This group has no active access tokens.'), show_role: true } } - if Feature.enabled?(:retain_resource_access_token_user_after_revoke, @group.root_ancestor) - = render Pajamas::CardComponent.new(card_options: { class: shared_card_component_classes }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body gl-px-0 gl-bg-gray-10 gl-border-b gl-rounded-bottom-base' }) do |c| - - c.with_header do - .gl-new-card-title-wrapper - %h3.gl-new-card-title - = _('Inactive group access tokens') - .gl-new-card-count - = sprite_icon('token', css_class: 'gl-mr-2') - %span.js-token-count= @inactive_access_tokens.size + = render ::Layouts::CrudComponent.new(_('Inactive group access tokens'), + icon: 'token', + count: @inactive_access_tokens.size, + count_options: { class: 'js-token-count' }) do |c| - c.with_body do #js-inactive-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_inactive_access_tokens: @inactive_access_tokens.to_json, no_inactive_tokens_message: _('This group has no inactive access tokens.')} } diff --git a/app/views/projects/pages/_list.html.haml b/app/views/projects/pages/_list.html.haml index b58cb7f4961a1..f29332a6a7ff6 100644 --- a/app/views/projects/pages/_list.html.haml +++ b/app/views/projects/pages/_list.html.haml @@ -5,7 +5,7 @@ = render ::Layouts::CrudComponent.new(s_('GitLabPages|Domains'), icon: 'earth', count: @domains.size, - count_class: 'js-admin-labels-count', + count_options: { class: 'js-admin-labels-count' }, options: { class: 'gl-mt-5' }) do |c| - c.with_actions do - if can_add_new_domain diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml index 8c33b418b6521..4249fec371788 100644 --- a/app/views/projects/settings/access_tokens/index.html.haml +++ b/app/views/projects/settings/access_tokens/index.html.haml @@ -3,7 +3,6 @@ - type = _('project access token') - type_plural = _('project access tokens') - @force_desktop_expanded_sidebar = true -- shared_card_component_classes = "gl-new-card gl-border-b-0 gl-rounded-bottom-left-none gl-rounded-bottom-right-none" .settings-section.js-search-settings-section .settings-sticky-header @@ -25,33 +24,28 @@ #js-new-access-token-app{ data: { access_token_type: type } } - = render Pajamas::CardComponent.new(card_options: { class: "#{shared_card_component_classes} js-toggle-container js-token-card" }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body' }) do |c| - - c.with_header do - .gl-new-card-title-wrapper - %h3.gl-new-card-title - = _('Active project access tokens') - .gl-new-card-count - = sprite_icon('token', css_class: 'gl-mr-2') - %span.js-token-count= @active_access_tokens.size + = render ::Layouts::CrudComponent.new(_('Active project access tokens'), + icon: 'token', + count: @active_access_tokens.size, + count_options: { class: 'js-token-count' }, + form_options: { class: 'gl-hidden js-toggle-content js-add-new-token-form' }, + options: { class: 'gl-mt-5 js-toggle-container js-token-card' }) do |c| + - c.with_actions do - if current_user.can?(:create_resource_access_tokens, @project) - .gl-new-card-actions - = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do - = _('Add new token') - - c.with_body do + = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do + = _('Add new token') + + - c.with_form do - if current_user.can?(:create_resource_access_tokens, @project) - .gl-new-card-add-form.gl-mt-3.gl-hidden.js-toggle-content.js-add-new-token-form - = render_if_exists 'projects/settings/access_tokens/form', type: type + = render_if_exists 'projects/settings/access_tokens/form', type: type - #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_access_tokens.to_json, no_active_tokens_message: _('This project has no active access tokens.'), show_role: true } } + - c.with_body do + #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_access_tokens.to_json, no_active_tokens_message: _('This project has no active access tokens.'), show_role: true } } - if Feature.enabled?(:retain_resource_access_token_user_after_revoke, @project.root_ancestor) - = render Pajamas::CardComponent.new(card_options: { class: shared_card_component_classes }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body gl-px-0 gl-bg-gray-10 gl-border-b gl-rounded-bottom-base' }) do |c| - - c.with_header do - .gl-new-card-title-wrapper - %h3.gl-new-card-title - = _('Inactive project access tokens') - .gl-new-card-count - = sprite_icon('token', css_class: 'gl-mr-2') - %span.js-token-count= @inactive_access_tokens.size + = render ::Layouts::CrudComponent.new(_('Inactive project access tokens'), + icon: 'token', + count: @inactive_access_tokens.size, + count_options: { class: 'js-token-count' }) do |c| - c.with_body do #js-inactive-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_inactive_access_tokens: @inactive_access_tokens.to_json, no_inactive_tokens_message: _('This project has no inactive access tokens.')} } diff --git a/app/views/user_settings/personal_access_tokens/index.html.haml b/app/views/user_settings/personal_access_tokens/index.html.haml index efb5852093a3a..b7a93df82a699 100644 --- a/app/views/user_settings/personal_access_tokens/index.html.haml +++ b/app/views/user_settings/personal_access_tokens/index.html.haml @@ -16,27 +16,24 @@ #js-new-access-token-app{ data: { access_token_type: type } } - = render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card gl-border-b-0 gl-rounded-bottom-left-none gl-rounded-bottom-right-none js-toggle-container js-token-card' }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body' }) do |c| - - c.with_header do - .gl-new-card-title-wrapper - %h3.gl-new-card-title - = _('Active personal access tokens') - .gl-new-card-count - = sprite_icon('token', css_class: 'gl-mr-2') - %span.js-token-count= @active_access_tokens.size - .gl-new-card-actions - = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do - = _('Add new token') - - c.with_body do - .gl-new-card-add-form.gl-mt-3.gl-hidden.js-toggle-content.js-add-new-token-form - = render 'shared/access_tokens/form', - ajax: true, - type: type, - path: user_settings_personal_access_tokens_path, - token: @personal_access_token, - scopes: @scopes, - help_path: help_page_path('user/profile/personal_access_tokens', anchor: 'personal-access-token-scopes') + = render ::Layouts::CrudComponent.new(_('Active personal access tokens'), + icon: 'token', + count: @active_access_tokens.size, + count_options: { class: 'js-token-count' }, + toggle_text: _('Add new token'), + toggle_options: { data: { testid: 'add-new-token-button' } }, + form_options: { class: 'js-add-new-token-form' }, + options: { class: 'gl-mt-5 js-token-card' }) do |c| + - c.with_form do + = render 'shared/access_tokens/form', + ajax: true, + type: type, + path: user_settings_personal_access_tokens_path, + token: @personal_access_token, + scopes: @scopes, + help_path: help_page_path('user/profile/personal_access_tokens', anchor: 'personal-access-token-scopes') - #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_access_tokens.to_json } } + - c.with_body do + #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_active_access_tokens: @active_access_tokens.to_json } } #js-tokens-app{ data: { tokens_data: tokens_app_data } } diff --git a/spec/components/layouts/crud_component_spec.rb b/spec/components/layouts/crud_component_spec.rb index abaa1b8bf2b55..761b22b712e45 100644 --- a/spec/components/layouts/crud_component_spec.rb +++ b/spec/components/layouts/crud_component_spec.rb @@ -139,7 +139,7 @@ it 'renders footer custom attributes' do render_inline described_class.new(title, - form_options: { class: 'footer-class', data: { testid: 'crud-custom-footer-id' } }) do |c| + footer_options: { class: 'footer-class', data: { testid: 'crud-custom-footer-id' } }) do |c| c.with_footer { footer } end -- GitLab