Merge branch '334874-convert-table-in-admin-applications-and-admin-deploy-keys-to-pajamas' into 'master'

Setup admin deploy keys Vue application

See merge request gitlab-org/gitlab!73580
This commit is contained in:
Markus Koller 2021-11-10 10:05:41 +00:00
commit 9320a89e52
10 changed files with 232 additions and 32 deletions

View file

@ -0,0 +1,54 @@
<script>
import { GlTable, GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
name: 'DeployKeysTable',
i18n: {
pageTitle: __('Public deploy keys'),
newDeployKeyButtonText: __('New deploy key'),
},
fields: [
{
key: 'title',
label: __('Title'),
},
{
key: 'fingerprint',
label: __('Fingerprint'),
},
{
key: 'projects',
label: __('Projects with write access'),
},
{
key: 'created',
label: __('Created'),
},
{
key: 'actions',
label: __('Actions'),
},
],
components: {
GlTable,
GlButton,
},
inject: ['editPath', 'deletePath', 'createPath', 'emptyStateSvgPath'],
};
</script>
<template>
<div>
<div class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-py-5">
<h4 class="gl-m-0">
{{ $options.i18n.pageTitle }}
</h4>
<gl-button variant="confirm" :href="createPath">{{
$options.i18n.newDeployKeyButtonText
}}</gl-button>
</div>
<gl-table :fields="$options.fields" data-testid="deploy-keys-list" />
</div>
</template>

View file

@ -0,0 +1,23 @@
import Vue from 'vue';
import DeployKeysTable from './components/table.vue';
export const initAdminDeployKeysTable = () => {
const el = document.getElementById('js-admin-deploy-keys-table');
if (!el) return false;
const { editPath, deletePath, createPath, emptyStateSvgPath } = el.dataset;
return new Vue({
el,
provide: {
editPath,
deletePath,
createPath,
emptyStateSvgPath,
},
render(createElement) {
return createElement(DeployKeysTable);
},
});
};

View file

@ -0,0 +1,3 @@
import { initAdminDeployKeysTable } from '~/admin/deploy_keys';
initAdminDeployKeysTable();

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
module Admin
module DeployKeyHelper
def admin_deploy_keys_data
{
edit_path: edit_admin_deploy_key_path(':id'),
delete_path: admin_deploy_key_path(':id'),
create_path: new_admin_deploy_key_path,
empty_state_svg_path: image_path('illustrations/empty-state/empty-deploy-keys-lg.svg')
}
end
end
end

View file

@ -1,33 +1,37 @@
- page_title _('Deploy Keys')
- if @deploy_keys.any?
%h3.page-title.deploy-keys-title
= _('Public deploy keys (%{deploy_keys_count})') % { deploy_keys_count: @deploy_keys.load.size }
= link_to _('New deploy key'), new_admin_deploy_key_path, class: 'float-right btn gl-button btn-confirm btn-md gl-button'
.table-holder.deploy-keys-list
%table.table
%thead
%tr
%th.col-sm-2= _('Title')
%th.col-sm-4= _('Fingerprint')
%th.col-sm-2= _('Projects with write access')
%th.col-sm-2= _('Added at')
%th.col-sm-2
%tbody
- @deploy_keys.each do |deploy_key|
%tr
%td
%strong= deploy_key.title
%td
%code.key-fingerprint= deploy_key.fingerprint
%td
- deploy_key.projects_with_write_access.each do |project|
= link_to project.full_name, admin_project_path(project), class: 'label deploy-project-label'
%td
%span.cgray
= _('added %{created_at_timeago}').html_safe % { created_at_timeago: time_ago_with_tooltip(deploy_key.created_at) }
%td
.float-right
= link_to _('Edit'), edit_admin_deploy_key_path(deploy_key), class: 'btn gl-button btn-sm'
= link_to _('Remove'), admin_deploy_key_path(deploy_key), data: { confirm: _('Are you sure?') }, method: :delete, class: 'gl-button btn btn-sm btn-danger delete-key'
- if Feature.enabled?(:admin_deploy_keys_vue, default_enabled: :yaml)
#js-admin-deploy-keys-table{ data: admin_deploy_keys_data }
- else
= render 'shared/empty_states/deploy_keys'
- if @deploy_keys.any?
%h3.page-title.deploy-keys-title
= _('Public deploy keys (%{deploy_keys_count})') % { deploy_keys_count: @deploy_keys.load.size }
= link_to _('New deploy key'), new_admin_deploy_key_path, class: 'float-right btn gl-button btn-confirm btn-md gl-button'
.table-holder.deploy-keys-list
%table.table
%thead
%tr
%th.col-sm-2= _('Title')
%th.col-sm-4= _('Fingerprint')
%th.col-sm-2= _('Projects with write access')
%th.col-sm-2= _('Added at')
%th.col-sm-2
%tbody
- @deploy_keys.each do |deploy_key|
%tr
%td
%strong= deploy_key.title
%td
%code.key-fingerprint= deploy_key.fingerprint
%td
- deploy_key.projects_with_write_access.each do |project|
= link_to project.full_name, admin_project_path(project), class: 'label deploy-project-label'
%td
%span.cgray
= _('added %{created_at_timeago}').html_safe % { created_at_timeago: time_ago_with_tooltip(deploy_key.created_at) }
%td
.float-right
= link_to _('Edit'), edit_admin_deploy_key_path(deploy_key), class: 'btn gl-button btn-sm'
= link_to _('Remove'), admin_deploy_key_path(deploy_key), data: { confirm: _('Are you sure?') }, method: :delete, class: 'gl-button btn btn-sm btn-danger delete-key'
- else
= render 'shared/empty_states/deploy_keys'

View file

@ -0,0 +1,8 @@
---
name: admin_deploy_keys_vue
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73580
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344855
milestone: '14.5'
type: development
group: group::access
default_enabled: false

View file

@ -28065,6 +28065,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
msgid "Public deploy keys"
msgstr ""
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""

View file

@ -3,11 +3,13 @@
require 'spec_helper'
RSpec.describe 'admin deploy keys' do
let_it_be(:admin) { create(:admin) }
let!(:deploy_key) { create(:deploy_key, public: true) }
let!(:another_deploy_key) { create(:another_deploy_key, public: true) }
before do
admin = create(:admin)
stub_feature_flags(admin_deploy_keys_vue: false)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
end
@ -84,4 +86,18 @@
end
end
end
context 'when `admin_deploy_keys_vue` feature flag is enabled', :js do
before do
stub_feature_flags(admin_deploy_keys_vue: true)
visit admin_deploy_keys_path
end
it 'renders the Vue app', :aggregate_failures do
expect(page).to have_content('Public deploy keys')
expect(page).to have_selector('[data-testid="deploy-keys-list"]')
expect(page).to have_link('New deploy key', href: new_admin_deploy_key_path)
end
end
end

View file

@ -0,0 +1,47 @@
import { merge } from 'lodash';
import { GlTable, GlButton } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import DeployKeysTable from '~/admin/deploy_keys/components/table.vue';
describe('DeployKeysTable', () => {
let wrapper;
const defaultProvide = {
createPath: '/admin/deploy_keys/new',
deletePath: '/admin/deploy_keys/:id',
editPath: '/admin/deploy_keys/:id/edit',
emptyStateSvgPath: '/assets/illustrations/empty-state/empty-deploy-keys.svg',
};
const createComponent = (provide = {}) => {
wrapper = mountExtended(DeployKeysTable, {
provide: merge({}, defaultProvide, provide),
});
};
afterEach(() => {
wrapper.destroy();
});
it('renders page title', () => {
createComponent();
expect(wrapper.findByText(DeployKeysTable.i18n.pageTitle).exists()).toBe(true);
});
it('renders table', () => {
createComponent();
expect(wrapper.findComponent(GlTable).exists()).toBe(true);
});
it('renders `New deploy key` button', () => {
createComponent();
const newDeployKeyButton = wrapper.findComponent(GlButton);
expect(newDeployKeyButton.text()).toBe(DeployKeysTable.i18n.newDeployKeyButtonText);
expect(newDeployKeyButton.attributes('href')).toBe(defaultProvide.createPath);
});
});

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.describe Admin::DeployKeyHelper do
describe '#admin_deploy_keys_data' do
let_it_be(:edit_path) { '/admin/deploy_keys/:id/edit' }
let_it_be(:delete_path) { '/admin/deploy_keys/:id' }
let_it_be(:create_path) { '/admin/deploy_keys/new' }
let_it_be(:empty_state_svg_path) { '/assets/illustrations/empty-state/empty-deploy-keys-lg.svg' }
subject(:result) { helper.admin_deploy_keys_data }
it 'returns correct hash' do
expect(helper).to receive(:edit_admin_deploy_key_path).with(':id').and_return(edit_path)
expect(helper).to receive(:admin_deploy_key_path).with(':id').and_return(delete_path)
expect(helper).to receive(:new_admin_deploy_key_path).and_return(create_path)
expect(helper).to receive(:image_path).with('illustrations/empty-state/empty-deploy-keys-lg.svg').and_return(empty_state_svg_path)
expect(result).to eq({
edit_path: edit_path,
delete_path: delete_path,
create_path: create_path,
empty_state_svg_path: empty_state_svg_path
})
end
end
end