diff --git a/app/views/profiles/gpg_keys/_form.html.haml b/app/views/profiles/gpg_keys/_form.html.haml
index ffd8bc3de27e179fc3a05c010c0f8d1549c28cb2..2bc977feb24cae3bf123bf347e0f2ae25cf7e63b 100644
--- a/app/views/profiles/gpg_keys/_form.html.haml
+++ b/app/views/profiles/gpg_keys/_form.html.haml
@@ -8,3 +8,5 @@
.gl-mt-3
= f.submit s_('Profiles|Add key'), pajamas_button: true
+ = render Pajamas::ButtonComponent.new(button_options: { type: 'reset', class: 'gl-ml-2 js-toggle-button' }) do
+ = _('Cancel')
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index d8b8dda29dce51673ca0e36fedb972314efbddae..f8520cb430dab983d056578d58c1231908248bdd 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -1,24 +1,29 @@
-%li.key-list-item
- .float-left.gl-mr-3
- = sprite_icon('key', css_class: "settings-list-icon d-none d-sm-block gl-mt-4")
- .key-list-item-info
+%tr.key-list-item
+ %td{ data: { label: s_('Profiles|Key') } }
+ %div{ class: 'gl-display-flex! gl-pl-0!' }
+ = sprite_icon('key', css_class: "settings-list-icon d-none d-sm-inline gl-mr-2")
+ .gl-display-flex.gl-flex-direction-column.gl-text-truncate
+ %p.gl-text-truncate.gl-m-0
+ %code= key.fingerprint
+ - if key.subkeys.present?
+ .subkeys.gl-mt-3{ class: 'gl-text-left!' }
+ %span.gl-font-sm
+ = _('Subkeys:')
+ %ul.subkeys-list
+ - key.subkeys.each do |subkey|
+ %li
+ %p.gl-text-truncate.gl-m-0
+ %code= subkey.fingerprint
+
+ %td{ data: { label: _('Status') } }
- key.emails_with_verified_status.map do |email, verified|
- = render partial: 'shared/email_with_badge', locals: { email: email, verified: verified }
+ %div{ class: 'gl-text-left!' }
+ = render partial: 'shared/email_with_badge', locals: { email: email, verified: verified }
+
+ %td{ data: { label: _('Created') } }
+ = html_escape(s_('Created %{time_ago}')) % { time_ago: time_ago_with_tooltip(key.created_at) }
- %span.text-truncate
- %code= key.fingerprint
- - if key.subkeys.present?
- .subkeys
- %span.bold
- = _('Subkeys')
- = ':'
- %ul.subkeys-list
- - key.subkeys.each do |subkey|
- %li
- %code= subkey.fingerprint
- .float-right
- %span.key-created-at
- = html_escape(s_('Profiles|Created %{time_ago}')) % { time_ago: time_ago_with_tooltip(key.created_at) }
- = link_button_to nil, profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: 'gl-ml-3', variant: :danger, icon: 'remove', 'aria-label': _('Remove')
- = link_button_to revoke_profile_gpg_key_path(key), data: { confirm: _('Are you sure? All commits that were signed with this GPG key will be unverified.') }, method: :put, class: 'gl-ml-3', variant: :danger, 'aria-label': _('Revoke') do
+ %td{ class: 'gl-py-3!', data: { label: _('Actions') } }
+ = link_button_to nil, profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.'), confirm_btn_variant: 'danger' }, method: :delete, class: 'has-tooltip', icon: 'remove', category: :secondary, 'title': _('Remove'), 'aria-label': _('Remove')
+ = link_button_to revoke_profile_gpg_key_path(key), data: { confirm: _('Are you sure? All commits that were signed with this GPG key will be unverified.'), confirm_btn_variant: 'danger' }, method: :put, class: 'gl-ml-3', category: :secondary, variant: :danger, 'aria-label': _('Revoke') do
= _('Revoke')
diff --git a/app/views/profiles/gpg_keys/_key_table.html.haml b/app/views/profiles/gpg_keys/_key_table.html.haml
index ebbd1c8f67233298b1ac8a36bb9356e7a7446031..0a50ce55b5031464c39f2346808e3297dc944d59 100644
--- a/app/views/profiles/gpg_keys/_key_table.html.haml
+++ b/app/views/profiles/gpg_keys/_key_table.html.haml
@@ -1,10 +1,19 @@
- is_admin = local_assigns.fetch(:admin, false)
+- hide_class = local_assigns.fetch(:hide_class, false)
- if @gpg_keys.any?
- %ul.content-list
- = render partial: 'profiles/gpg_keys/key', collection: @gpg_keys, locals: { is_admin: is_admin }
+ .table-holder
+ %table.table.b-table.gl-table.b-table-stacked-md.gl-mt-n1.gl-mb-n2.ssh-keys-list{ data: { qa_selector: 'ssh_keys_list' } }
+ %thead.d-none.d-md-table-header-group
+ %tr
+ %th= s_('Profiles|Key')
+ %th= _('Status')
+ %th= _('Created')
+ %th= _('Actions')
+ = render partial: 'profiles/gpg_keys/key', collection: @gpg_keys, locals: { is_admin: is_admin }
+
- else
- %p.settings-message.text-center
+ %p.gl-new-card-empty.gl-px-5.gl-py-4.js-toggle-content{ class: hide_class }
- if is_admin
= _('There are no GPG keys associated with this account.')
- else
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 2dfd6c7860f8255c40a7addf68b116ea8943a637..7e38771d81d794fc67e485ada30f9b8fe3c0ce27 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -1,6 +1,8 @@
- page_title _('GPG Keys')
- add_page_specific_style 'page_bundles/profile'
- @force_desktop_expanded_sidebar = true
+- add_form_class = 'gl-display-none' if !form_errors(@gpg_key)
+- hide_class = 'gl-display-none' if form_errors(@gpg_key)
.settings-section.js-search-settings-section
.settings-sticky-header
@@ -10,17 +12,24 @@
%p.gl-text-secondary
= _('GPG keys allow you to verify signed commits.')
- %h5.gl-font-lg.gl-mt-0
- = _('Add a GPG key')
- %p
- - help_link_start = ''.html_safe % { url: help_page_path('user/project/repository/gpg_signed_commits/index.md') }
- = _('Add a GPG key for secure access to GitLab. %{help_link_start}Learn more%{help_link_end}.').html_safe % {help_link_start: help_link_start, help_link_end: ''.html_safe }
- = render 'form'
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card js-toggle-container' }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body gl-px-0' }) do |c|
+ - c.with_header do
+ .gl-new-card-title-wrapper
+ %h3.gl-new-card-title
+ = _('Your GPG keys')
+ .gl-new-card-count
+ = sprite_icon('key', css_class: 'gl-mr-2')
+ = @gpg_keys.count
+ .gl-new-card-actions
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: "js-toggle-button js-toggle-content #{hide_class}" }) do
+ = _('Add a GPG key')
+ - c.with_body do
+ .gl-new-card-add-form.gl-m-3.js-toggle-content{ class: add_form_class }
+ %h4.gl-mt-0
+ = _('Add a GPG key')
+ %p
+ - help_link_start = ''.html_safe % { url: help_page_path('user/project/repository/gpg_signed_commits/index.md') }
+ = _('Add a GPG key for secure access to GitLab. %{help_link_start}Learn more%{help_link_end}.').html_safe % {help_link_start: help_link_start, help_link_end: ''.html_safe }
+ = render 'form'
-.settings-section.js-search-settings-section
- .settings-sticky-header
- .settings-sticky-header-inner
- %h4.gl-my-0
- = _('Your GPG keys (%{count})') % { count: @gpg_keys.count }
- .gl-mb-3
- = render 'key_table'
+ = render 'key_table', hide_class: hide_class
diff --git a/app/views/shared/_email_with_badge.html.haml b/app/views/shared/_email_with_badge.html.haml
index a1398f85513d9db75232ea3b5dc507d291893d7c..14201c0d23a5f39101d69eb3969b7b0e1b1f273c 100644
--- a/app/views/shared/_email_with_badge.html.haml
+++ b/app/views/shared/_email_with_badge.html.haml
@@ -1,6 +1,7 @@
- variant = verified ? :success : :danger
- text = verified ? _('Verified') : _('Unverified')
-%span.gl-mr-3
- = email
+- if email
+ %span.gl-mr-2
+ = email
= gl_badge_tag text, { variant: variant, size: :sm }
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d74a9ee1a75189b1461050fb76e7926c071e9ea1..910c33da5b8d3401acc25b88ee81fca6afb09403 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13519,6 +13519,9 @@ msgstr ""
msgid "Created %{timeAgo} by %{author}"
msgstr ""
+msgid "Created %{time_ago}"
+msgstr ""
+
msgid "Created %{timestamp}"
msgstr ""
@@ -35415,9 +35418,6 @@ msgstr ""
msgid "Profiles|Control emails linked to your account"
msgstr ""
-msgid "Profiles|Created %{time_ago}"
-msgstr ""
-
msgid "Profiles|Created%{time_ago}"
msgstr ""
@@ -44774,7 +44774,7 @@ msgstr ""
msgid "Subject Key Identifier:"
msgstr ""
-msgid "Subkeys"
+msgid "Subkeys:"
msgstr ""
msgid "Submit"
@@ -53549,7 +53549,7 @@ msgstr ""
msgid "Your Free top-level group, %{group_name}, has more than %{free_users_limit} users and uses more than %{free_storage_limit} of data. After usage limits are applied to Free top-level groups, projects in this group will be in a %{read_only_link_start}read-only state%{link_end}. You should reduce the number of users or upgrade to a paid tier %{strong_start}before%{strong_end} you manage your storage usage. Otherwise, your Free top-level group will become read-only immediately because the 5-user limit applies. For more information, see our %{faq_link_start}FAQ%{link_end}."
msgstr ""
-msgid "Your GPG keys (%{count})"
+msgid "Your GPG keys"
msgstr ""
msgid "Your GitLab Ultimate free trial lasts for 30 days. After this period, you can maintain a GitLab Free account forever or upgrade to a paid plan."
diff --git a/spec/features/profiles/gpg_keys_spec.rb b/spec/features/profiles/gpg_keys_spec.rb
index f39d9ddaf5615448157cce3bc3754da544afb000..3adda251e40f6f977d0ecdbe5e9241510e8fbd65 100644
--- a/spec/features/profiles/gpg_keys_spec.rb
+++ b/spec/features/profiles/gpg_keys_spec.rb
@@ -15,6 +15,7 @@
end
it 'saves the new key' do
+ click_button('Add a GPG key')
fill_in('Key', with: GpgHelpers::User2.public_key)
click_button('Add key')
@@ -24,6 +25,7 @@
end
it 'with multiple subkeys' do
+ click_button('Add a GPG key')
fill_in('Key', with: GpgHelpers::User3.public_key)
click_button('Add key')
@@ -52,7 +54,10 @@
click_link('Remove')
- expect(page).to have_content('Your GPG keys (0)')
+ expect(page).to have_content('Your GPG keys')
+ page.within('.gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
end
it 'user revokes a key via the key index' do
@@ -63,7 +68,10 @@
click_link('Revoke')
- expect(page).to have_content('Your GPG keys (0)')
+ expect(page).to have_content('Your GPG keys')
+ page.within('.gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
expect(gpg_signature.reload).to have_attributes(
verification_status: 'unknown_key',