Commit 3d65ccc6 authored by Sri's avatar Sri

Frontend for project/google_cloud Page

- With mocked dataset
- Tabs for configuration, deployments and services
- Service accounts section under configuration
    - Empty state
    - Tabled list
    - `Create service account` button
parent 60f908a2
<script>
import { GlTab, GlTabs } from '@gitlab/ui';
import IncubationBanner from './incubation_banner.vue';
import ServiceAccounts from './service_accounts.vue';
export default {
components: { GlTab, GlTabs, IncubationBanner, ServiceAccounts },
props: {
serviceAccounts: {
type: Array,
required: true,
},
createServiceAccountUrl: {
type: String,
required: true,
},
emptyIllustrationUrl: {
type: String,
required: true,
},
},
methods: {
feedbackUrl(template) {
return `https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/meta/-/issues/new?issuable_template=${template}`;
},
},
};
</script>
<template>
<div>
<incubation-banner
:share-feedback-url="feedbackUrl('general_feedback')"
:report-bug-url="feedbackUrl('report_bug')"
:feature-request-url="feedbackUrl('feature_request')"
/>
<gl-tabs>
<gl-tab :title="__('Configuration')">
<service-accounts
class="gl-mx-3"
:list="serviceAccounts"
:create-url="createServiceAccountUrl"
:empty-illustration-url="emptyIllustrationUrl"
/>
</gl-tab>
<gl-tab :title="__('Deployments')" disabled />
<gl-tab :title="__('Services')" disabled />
</gl-tabs>
</div>
</template>
<script>
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
export default {
components: { GlAlert, GlLink, GlSprintf },
props: {
shareFeedbackUrl: {
required: true,
type: String,
},
reportBugUrl: {
required: true,
type: String,
},
featureRequestUrl: {
required: true,
type: String,
},
},
};
</script>
<template>
<gl-alert :dismissible="false" variant="info">
{{ __('This is an experimental feature developed by GitLab Incubation Engineering.') }}
<gl-sprintf
:message="
__(
'We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}',
)
"
>
<template #featureLink="{ content }">
<gl-link :href="featureRequestUrl">{{ content }}</gl-link>
</template>
<template #bugLink="{ content }">
<gl-link :href="reportBugUrl">{{ content }}</gl-link>
</template>
<template #feedbackLink="{ content }">
<gl-link :href="shareFeedbackUrl">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</template>
<script>
import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
components: { GlButton, GlEmptyState, GlTable },
props: {
list: {
type: Array,
required: true,
},
createUrl: {
type: String,
required: true,
},
emptyIllustrationUrl: {
type: String,
required: true,
},
},
data() {
return {
tableFields: [
{ key: 'environment', label: __('Environment'), sortable: true },
{ key: 'gcp_project', label: __('Google Cloud Project'), sortable: true },
{ key: 'service_account_exists', label: __('Service Account'), sortable: true },
{ key: 'service_account_key_exists', label: __('Service Account Key'), sortable: true },
],
};
},
};
</script>
<template>
<div>
<gl-empty-state
v-if="list.length === 0"
:title="__('No service accounts')"
:description="
__('Service Accounts keys authorize GitLab to deploy your Google Cloud project')
"
:primary-button-link="createUrl"
:primary-button-text="__('Create service account')"
:svg-path="emptyIllustrationUrl"
/>
<div v-else>
<h2 class="gl-font-size-h2">{{ __('Service Accounts') }}</h2>
<p>{{ __('Service Accounts keys authorize GitLab to deploy your Google Cloud project') }}</p>
<gl-table :items="list" :fields="tableFields">
<template #cell(service_account_exists)="{ value }">
{{ value ? '' : __('Not found') }}
</template>
<template #cell(service_account_key_exists)="{ value }">
{{ value ? '' : __('Not found') }}
</template>
</gl-table>
<gl-button :href="createUrl" category="primary" variant="info">
{{ __('Create service account') }}
</gl-button>
</div>
</div>
</template>
import Vue from 'vue';
import App from './components/app.vue';
const elementRenderer = (element, props = {}) => (createElement) =>
createElement(element, { props });
export default () => {
const root = document.querySelector('#js-google-cloud');
// uncomment this once backend is ready
// const dataset = JSON.parse(root.getAttribute('data'));
const mockDataset = {
createServiceAccountUrl: '#create-url',
serviceAccounts: [],
emptyIllustrationUrl:
'https://gitlab.com/gitlab-org/gitlab-svgs/-/raw/main/illustrations/pipelines_empty.svg',
};
return new Vue({ el: root, render: elementRenderer(App, mockDataset) });
};
import initGoogleCloud from '~/google_cloud/index';
initGoogleCloud();
......@@ -9742,6 +9742,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
msgid "Create service account"
msgstr ""
msgid "Create snippet"
msgstr ""
......@@ -16034,6 +16037,9 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
msgid "Google Cloud Project"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr ""
......@@ -23369,6 +23375,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
msgid "No service accounts"
msgstr ""
msgid "No severity matches the provided parameter"
msgstr ""
......@@ -23464,6 +23473,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
msgid "Not found"
msgstr ""
msgid "Not found."
msgstr ""
......@@ -31285,6 +31297,18 @@ msgstr ""
msgid "Service"
msgstr ""
msgid "Service Account"
msgstr ""
msgid "Service Account Key"
msgstr ""
msgid "Service Accounts"
msgstr ""
msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
msgstr ""
......@@ -31339,6 +31363,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
msgid "Services"
msgstr ""
msgid "Session ID"
msgstr ""
......@@ -35113,6 +35140,9 @@ msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
msgid "This is an experimental feature developed by GitLab Incubation Engineering."
msgstr ""
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
......@@ -38359,6 +38389,9 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
msgstr ""
msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
msgstr ""
......
import { shallowMount } from '@vue/test-utils';
import { GlTab, GlTabs } from '@gitlab/ui';
import App from '~/google_cloud/components/app.vue';
import IncubationBanner from '~/google_cloud/components/incubation_banner.vue';
import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
describe('google_cloud App component', () => {
let wrapper;
const findIncubationBanner = () => wrapper.findComponent(IncubationBanner);
const findTabs = () => wrapper.findComponent(GlTabs);
const findTabItems = () => findTabs().findAllComponents(GlTab);
const findConfigurationTab = () => findTabItems().at(0);
const findDeploymentTab = () => findTabItems().at(1);
const findServicesTab = () => findTabItems().at(2);
const findServiceAccounts = () => findConfigurationTab().findComponent(ServiceAccounts);
beforeEach(() => {
const propsData = {
serviceAccounts: [{}, {}],
createServiceAccountUrl: '#url-create-service-account',
emptyIllustrationUrl: '#url-empty-illustration',
};
wrapper = shallowMount(App, { propsData });
});
afterEach(() => {
wrapper.destroy();
});
it('should contain incubation banner', () => {
expect(findIncubationBanner().exists()).toBe(true);
});
describe('google_cloud App tabs', () => {
it('should contain tabs', () => {
expect(findTabs().exists()).toBe(true);
});
it('should contain three tab items', () => {
expect(findTabItems().length).toBe(3);
});
describe('configuration tab', () => {
it('should exist', () => {
expect(findConfigurationTab().exists()).toBe(true);
});
it('should contain service accounts component', () => {
expect(findServiceAccounts().exists()).toBe(true);
});
});
describe('deployments tab', () => {
it('should exist', () => {
expect(findDeploymentTab().exists()).toBe(true);
});
});
describe('services tab', () => {
it('should exist', () => {
expect(findServicesTab().exists()).toBe(true);
});
});
});
});
import { mount } from '@vue/test-utils';
import { GlAlert, GlLink } from '@gitlab/ui';
import IncubationBanner from '~/google_cloud/components/incubation_banner.vue';
describe('IncubationBanner component', () => {
let wrapper;
const findAlert = () => wrapper.findComponent(GlAlert);
const findLinks = () => wrapper.findAllComponents(GlLink);
const findFeatureRequestLink = () => findLinks().at(0);
const findReportBugLink = () => findLinks().at(1);
const findShareFeedbackLink = () => findLinks().at(2);
beforeEach(() => {
const propsData = {
shareFeedbackUrl: 'url_general_feedback',
reportBugUrl: 'url_report_bug',
featureRequestUrl: 'url_feature_request',
};
wrapper = mount(IncubationBanner, { propsData });
});
afterEach(() => {
wrapper.destroy();
});
it('contains alert', () => {
expect(findAlert().exists()).toBe(true);
});
it('contains relevant text', () => {
expect(findAlert().text()).toContain(
'This is an experimental feature developed by GitLab Incubation Engineering.',
);
});
describe('has relevant gl-links', () => {
it('three in total', () => {
expect(findLinks().length).toBe(3);
});
it('contains feature request link', () => {
const link = findFeatureRequestLink();
expect(link.text()).toBe('request a feature');
expect(link.attributes('href')).toBe('url_feature_request');
});
it('contains report bug link', () => {
const link = findReportBugLink();
expect(link.text()).toBe('report a bug');
expect(link.attributes('href')).toBe('url_report_bug');
});
it('contains share feedback link', () => {
const link = findShareFeedbackLink();
expect(link.text()).toBe('share feedback');
expect(link.attributes('href')).toBe('url_general_feedback');
});
});
});
import { mount } from '@vue/test-utils';
import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
describe('ServiceAccounts component', () => {
describe('when the project does not have any service accounts', () => {
let wrapper;
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findButtonInEmptyState = () => findEmptyState().findComponent(GlButton);
beforeEach(() => {
const propsData = {
list: [],
createUrl: '#create-url',
emptyIllustrationUrl: '#empty-illustration-url',
};
wrapper = mount(ServiceAccounts, { propsData });
});
afterEach(() => {
wrapper.destroy();
});
it('shows the empty state component', () => {
expect(findEmptyState().exists()).toBe(true);
});
it('shows the link to create new service accounts', () => {
const button = findButtonInEmptyState();
expect(button.exists()).toBe(true);
expect(button.text()).toBe('Create service account');
expect(button.attributes('href')).toBe('#create-url');
});
});
describe('when three service accounts are passed via props', () => {
let wrapper;
const findTitle = () => wrapper.find('h2');
const findDescription = () => wrapper.find('p');
const findTable = () => wrapper.findComponent(GlTable);
const findRows = () => findTable().findAll('tr');
const findButton = () => wrapper.findComponent(GlButton);
beforeEach(() => {
const propsData = {
list: [{}, {}, {}],
createUrl: '#create-url',
emptyIllustrationUrl: '#empty-illustration-url',
};
wrapper = mount(ServiceAccounts, { propsData });
});
it('shows the title', () => {
expect(findTitle().text()).toBe('Service Accounts');
});
it('shows the description', () => {
expect(findDescription().text()).toBe(
'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
);
});
it('shows the table', () => {
expect(findTable().exists()).toBe(true);
});
it('table must have three rows + header row', () => {
expect(findRows().length).toBe(4);
});
it('shows the link to create new service accounts', () => {
const button = findButton();
expect(button.exists()).toBe(true);
expect(button.text()).toBe('Create service account');
expect(button.attributes('href')).toBe('#create-url');
});
});
});
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