Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 18:40:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-07-20 18:40:28 +0300
commitb595cb0c1dec83de5bdee18284abe86614bed33b (patch)
tree8c3d4540f193c5ff98019352f554e921b3a41a72 /app/assets/javascripts/google_cloud
parent2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff)
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'app/assets/javascripts/google_cloud')
-rw-r--r--app/assets/javascripts/google_cloud/components/app.vue63
-rw-r--r--app/assets/javascripts/google_cloud/components/errors/gcp_error.vue29
-rw-r--r--app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue26
-rw-r--r--app/assets/javascripts/google_cloud/components/google_cloud_menu.vue85
-rw-r--r--app/assets/javascripts/google_cloud/components/home.vue81
-rw-r--r--app/assets/javascripts/google_cloud/components/incubation_banner.vue28
-rw-r--r--app/assets/javascripts/google_cloud/configuration/index.js11
-rw-r--r--app/assets/javascripts/google_cloud/configuration/panel.vue88
-rw-r--r--app/assets/javascripts/google_cloud/databases/cloudsql/create_instance_form.vue132
-rw-r--r--app/assets/javascripts/google_cloud/databases/cloudsql/instance_table.vue75
-rw-r--r--app/assets/javascripts/google_cloud/databases/index.js11
-rw-r--r--app/assets/javascripts/google_cloud/databases/panel.vue38
-rw-r--r--app/assets/javascripts/google_cloud/databases/service_table.vue221
-rw-r--r--app/assets/javascripts/google_cloud/deployments/index.js11
-rw-r--r--app/assets/javascripts/google_cloud/deployments/panel.vue50
-rw-r--r--app/assets/javascripts/google_cloud/deployments/service_table.vue (renamed from app/assets/javascripts/google_cloud/components/deployments_service_table.vue)0
-rw-r--r--app/assets/javascripts/google_cloud/gcp_regions/form.vue (renamed from app/assets/javascripts/google_cloud/components/gcp_regions_form.vue)0
-rw-r--r--app/assets/javascripts/google_cloud/gcp_regions/index.js11
-rw-r--r--app/assets/javascripts/google_cloud/gcp_regions/list.vue (renamed from app/assets/javascripts/google_cloud/components/gcp_regions_list.vue)0
-rw-r--r--app/assets/javascripts/google_cloud/index.js12
-rw-r--r--app/assets/javascripts/google_cloud/service_accounts/form.vue (renamed from app/assets/javascripts/google_cloud/components/service_accounts_form.vue)0
-rw-r--r--app/assets/javascripts/google_cloud/service_accounts/index.js11
-rw-r--r--app/assets/javascripts/google_cloud/service_accounts/list.vue (renamed from app/assets/javascripts/google_cloud/components/service_accounts_list.vue)0
23 files changed, 757 insertions, 226 deletions
diff --git a/app/assets/javascripts/google_cloud/components/app.vue b/app/assets/javascripts/google_cloud/components/app.vue
deleted file mode 100644
index b3d773e6bee..00000000000
--- a/app/assets/javascripts/google_cloud/components/app.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-<script>
-import { __ } from '~/locale';
-
-import Home from './home.vue';
-import IncubationBanner from './incubation_banner.vue';
-import ServiceAccountsForm from './service_accounts_form.vue';
-import GcpRegionsForm from './gcp_regions_form.vue';
-import NoGcpProjects from './errors/no_gcp_projects.vue';
-import GcpError from './errors/gcp_error.vue';
-
-const SCREEN_GCP_ERROR = 'gcp_error';
-const SCREEN_HOME = 'home';
-const SCREEN_NO_GCP_PROJECTS = 'no_gcp_projects';
-const SCREEN_SERVICE_ACCOUNTS_FORM = 'service_accounts_form';
-const SCREEN_GCP_REGIONS_FORM = 'gcp_regions_form';
-
-export default {
- components: {
- IncubationBanner,
- },
- inheritAttrs: false,
- props: {
- screen: {
- required: true,
- type: String,
- },
- },
- computed: {
- mainComponent() {
- switch (this.screen) {
- case SCREEN_HOME:
- return Home;
- case SCREEN_GCP_ERROR:
- return GcpError;
- case SCREEN_NO_GCP_PROJECTS:
- return NoGcpProjects;
- case SCREEN_SERVICE_ACCOUNTS_FORM:
- return ServiceAccountsForm;
- case SCREEN_GCP_REGIONS_FORM:
- return GcpRegionsForm;
- default:
- throw new Error(__('Unknown screen'));
- }
- },
- },
- methods: {
- feedbackUrl(template) {
- return `https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/feedback/-/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')"
- />
- <component :is="mainComponent" v-bind="$attrs" />
- </div>
-</template>
diff --git a/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue b/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue
deleted file mode 100644
index 90aa0e1ae68..00000000000
--- a/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-<script>
-import { GlAlert } from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export default {
- components: { GlAlert },
- props: {
- error: {
- type: String,
- required: true,
- },
- },
- i18n: {
- title: __('Google Cloud project misconfigured'),
- description: __(
- 'GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:',
- ),
- },
-};
-</script>
-
-<template>
- <gl-alert :dismissible="false" variant="warning" :title="$options.i18n.title">
- {{ $options.i18n.description }}
- <blockquote>
- <code>{{ error }}</code>
- </blockquote>
- </gl-alert>
-</template>
diff --git a/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue b/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue
deleted file mode 100644
index da229ac3f0e..00000000000
--- a/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue
+++ /dev/null
@@ -1,26 +0,0 @@
-<script>
-import { GlAlert, GlButton } from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export default {
- components: { GlAlert, GlButton },
- i18n: {
- title: __('Google Cloud project required'),
- description: __(
- 'You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page.',
- ),
- createLabel: __('Create Google Cloud project'),
- },
-};
-</script>
-
-<template>
- <gl-alert :dismissible="false" variant="warning" :title="$options.i18n.title">
- {{ $options.i18n.description }}
- <template #actions>
- <gl-button href="https://console.cloud.google.com/projectcreate" target="_blank">
- {{ $options.i18n.createLabel }}
- </gl-button>
- </template>
- </gl-alert>
-</template>
diff --git a/app/assets/javascripts/google_cloud/components/google_cloud_menu.vue b/app/assets/javascripts/google_cloud/components/google_cloud_menu.vue
new file mode 100644
index 00000000000..d6b7c702b54
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/google_cloud_menu.vue
@@ -0,0 +1,85 @@
+<script>
+import { s__ } from '~/locale';
+
+const CONFIGURATION_KEY = 'configuration';
+const DEPLOYMENTS_KEY = 'deployments';
+const DATABASES_KEY = 'databases';
+
+const i18n = {
+ configuration: { title: s__('CloudSeed|Configuration') },
+ deployments: { title: s__('CloudSeed|Deployments') },
+ databases: { title: s__('CloudSeed|Databases') },
+};
+
+export default {
+ props: {
+ active: {
+ type: String,
+ required: true,
+ },
+ configurationUrl: {
+ type: String,
+ required: true,
+ },
+ deploymentsUrl: {
+ type: String,
+ required: true,
+ },
+ databasesUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ isConfigurationActive() {
+ return this.active === CONFIGURATION_KEY;
+ },
+ isDeploymentsActive() {
+ return this.active === DEPLOYMENTS_KEY;
+ },
+ isDatabasesActive() {
+ return this.active === DATABASES_KEY;
+ },
+ },
+ i18n,
+};
+</script>
+<template>
+ <div class="tabs gl-tabs">
+ <ul role="tablist" class="nav gl-tabs-nav">
+ <li role="presentation" class="nav-item">
+ <a
+ data-testid="configurationLink"
+ role="tab"
+ :href="configurationUrl"
+ class="nav-link gl-tab-nav-item"
+ :class="{ 'gl-tab-nav-item-active': isConfigurationActive }"
+ >
+ {{ $options.i18n.configuration.title }}</a
+ >
+ </li>
+ <li role="presentation" class="nav-item">
+ <a
+ data-testid="deploymentsLink"
+ role="tab"
+ :href="deploymentsUrl"
+ class="nav-link gl-tab-nav-item"
+ :class="{ 'gl-tab-nav-item-active': isDeploymentsActive }"
+ >
+ {{ $options.i18n.deployments.title }}
+ </a>
+ </li>
+ <li role="presentation" class="nav-item">
+ <a
+ data-testid="databasesLink"
+ role="tab"
+ :href="databasesUrl"
+ class="nav-link gl-tab-nav-item"
+ :class="{ 'gl-tab-nav-item-active': isDatabasesActive }"
+ >
+ {{ $options.i18n.databases.title }}
+ </a>
+ </li>
+ </ul>
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/home.vue b/app/assets/javascripts/google_cloud/components/home.vue
deleted file mode 100644
index e41337e2679..00000000000
--- a/app/assets/javascripts/google_cloud/components/home.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-<script>
-import { GlTabs, GlTab } from '@gitlab/ui';
-import DeploymentsServiceTable from './deployments_service_table.vue';
-import RevokeOauth from './revoke_oauth.vue';
-import ServiceAccountsList from './service_accounts_list.vue';
-import GcpRegionsList from './gcp_regions_list.vue';
-
-export default {
- components: {
- GlTabs,
- GlTab,
- DeploymentsServiceTable,
- RevokeOauth,
- ServiceAccountsList,
- GcpRegionsList,
- },
- props: {
- serviceAccounts: {
- type: Array,
- required: true,
- },
- createServiceAccountUrl: {
- type: String,
- required: true,
- },
- configureGcpRegionsUrl: {
- type: String,
- required: true,
- },
- emptyIllustrationUrl: {
- type: String,
- required: true,
- },
- enableCloudRunUrl: {
- type: String,
- required: true,
- },
- enableCloudStorageUrl: {
- type: String,
- required: true,
- },
- gcpRegions: {
- type: Array,
- required: true,
- },
- revokeOauthUrl: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <gl-tabs>
- <gl-tab :title="__('Configuration')">
- <service-accounts-list
- class="gl-mx-4"
- :list="serviceAccounts"
- :create-url="createServiceAccountUrl"
- :empty-illustration-url="emptyIllustrationUrl"
- />
- <hr />
- <gcp-regions-list
- class="gl-mx-4"
- :empty-illustration-url="emptyIllustrationUrl"
- :create-url="configureGcpRegionsUrl"
- :list="gcpRegions"
- />
- <hr v-if="revokeOauthUrl" />
- <revoke-oauth v-if="revokeOauthUrl" :url="revokeOauthUrl" />
- </gl-tab>
- <gl-tab :title="__('Deployments')">
- <deployments-service-table
- :cloud-run-url="enableCloudRunUrl"
- :cloud-storage-url="enableCloudStorageUrl"
- />
- </gl-tab>
- <gl-tab :title="__('Services')" disabled />
- </gl-tabs>
-</template>
diff --git a/app/assets/javascripts/google_cloud/components/incubation_banner.vue b/app/assets/javascripts/google_cloud/components/incubation_banner.vue
index 652b8c1aecb..128b3dcb1d9 100644
--- a/app/assets/javascripts/google_cloud/components/incubation_banner.vue
+++ b/app/assets/javascripts/google_cloud/components/incubation_banner.vue
@@ -1,22 +1,20 @@
<script>
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
+const FEATURE_REQUEST_KEY = 'feature_request';
+const REPORT_BUG_KEY = 'report_bug';
+const GENERAL_FEEDBACK_KEY = 'general_feedback';
+
export default {
components: { GlAlert, GlLink, GlSprintf },
- props: {
- shareFeedbackUrl: {
- required: true,
- type: String,
- },
- reportBugUrl: {
- required: true,
- type: String,
- },
- featureRequestUrl: {
- required: true,
- type: String,
+ methods: {
+ feedbackUrl(template) {
+ return `https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/feedback/-/issues/new?issuable_template=${template}`;
},
},
+ FEATURE_REQUEST_KEY,
+ REPORT_BUG_KEY,
+ GENERAL_FEEDBACK_KEY,
};
</script>
@@ -31,13 +29,13 @@ export default {
"
>
<template #featureLink="{ content }">
- <gl-link :href="featureRequestUrl">{{ content }}</gl-link>
+ <gl-link :href="feedbackUrl($options.FEATURE_REQUEST_KEY)">{{ content }}</gl-link>
</template>
<template #bugLink="{ content }">
- <gl-link :href="reportBugUrl">{{ content }}</gl-link>
+ <gl-link :href="feedbackUrl($options.REPORT_BUG_KEY)">{{ content }}</gl-link>
</template>
<template #feedbackLink="{ content }">
- <gl-link :href="shareFeedbackUrl">{{ content }}</gl-link>
+ <gl-link :href="feedbackUrl($options.GENERAL_FEEDBACK_KEY)">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
diff --git a/app/assets/javascripts/google_cloud/configuration/index.js b/app/assets/javascripts/google_cloud/configuration/index.js
new file mode 100644
index 00000000000..580315588d0
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/configuration/index.js
@@ -0,0 +1,11 @@
+import Vue from 'vue';
+import Panel from './panel.vue';
+
+export default (containerId = '#js-google-cloud-configuration') => {
+ const element = document.querySelector(containerId);
+ const { ...attrs } = JSON.parse(element.getAttribute('data'));
+ return new Vue({
+ el: element,
+ render: (createElement) => createElement(Panel, { attrs }),
+ });
+};
diff --git a/app/assets/javascripts/google_cloud/configuration/panel.vue b/app/assets/javascripts/google_cloud/configuration/panel.vue
new file mode 100644
index 00000000000..ee046eb1988
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/configuration/panel.vue
@@ -0,0 +1,88 @@
+<script>
+import GcpRegionsList from '../gcp_regions/list.vue';
+import GoogleCloudMenu from '../components/google_cloud_menu.vue';
+import IncubationBanner from '../components/incubation_banner.vue';
+import RevokeOauth from '../components/revoke_oauth.vue';
+import ServiceAccountsList from '../service_accounts/list.vue';
+
+export default {
+ components: {
+ GcpRegionsList,
+ GoogleCloudMenu,
+ IncubationBanner,
+ RevokeOauth,
+ ServiceAccountsList,
+ },
+ props: {
+ configurationUrl: {
+ type: String,
+ required: true,
+ },
+ deploymentsUrl: {
+ type: String,
+ required: true,
+ },
+ databasesUrl: {
+ type: String,
+ required: true,
+ },
+ serviceAccounts: {
+ type: Array,
+ required: true,
+ },
+ createServiceAccountUrl: {
+ type: String,
+ required: true,
+ },
+ emptyIllustrationUrl: {
+ type: String,
+ required: true,
+ },
+ configureGcpRegionsUrl: {
+ type: String,
+ required: true,
+ },
+ gcpRegions: {
+ type: Array,
+ required: true,
+ },
+ revokeOauthUrl: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <incubation-banner />
+
+ <google-cloud-menu
+ active="configuration"
+ :configuration-url="configurationUrl"
+ :deployments-url="deploymentsUrl"
+ :databases-url="databasesUrl"
+ />
+
+ <service-accounts-list
+ class="gl-mx-4"
+ :list="serviceAccounts"
+ :create-url="createServiceAccountUrl"
+ :empty-illustration-url="emptyIllustrationUrl"
+ />
+
+ <hr />
+
+ <gcp-regions-list
+ class="gl-mx-4"
+ :empty-illustration-url="emptyIllustrationUrl"
+ :create-url="configureGcpRegionsUrl"
+ :list="gcpRegions"
+ />
+
+ <hr v-if="revokeOauthUrl" />
+
+ <revoke-oauth v-if="revokeOauthUrl" :url="revokeOauthUrl" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/databases/cloudsql/create_instance_form.vue b/app/assets/javascripts/google_cloud/databases/cloudsql/create_instance_form.vue
new file mode 100644
index 00000000000..0ac561b6132
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/databases/cloudsql/create_instance_form.vue
@@ -0,0 +1,132 @@
+<script>
+import { GlButton, GlFormCheckbox, GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+const i18n = {
+ gcpProjectLabel: s__('CloudSeed|Google Cloud project'),
+ gcpProjectDescription: s__(
+ 'CloudSeed|Database instance is generated within the selected Google Cloud project',
+ ),
+ refsLabel: s__('CloudSeed|Refs'),
+ refsDescription: s__(
+ 'CloudSeed|Generated database instance is linked to the selected branch or tag',
+ ),
+ databaseVersionLabel: s__('CloudSeed|Database version'),
+ tierLabel: s__('CloudSeed|Machine type'),
+ tierDescription: s__('CloudSeed|Determines memory and virtual cores available to your instance'),
+ checkboxLabel: s__(
+ 'CloudSeed|I accept Google Cloud pricing and responsibilities involved with managing database instances',
+ ),
+ cancelLabel: s__('CloudSeed|Cancel'),
+ submitLabel: s__('CloudSeed|Create instance'),
+ all: s__('CloudSeed|All'),
+};
+
+export default {
+ ALL_REFS: '*',
+ components: {
+ GlButton,
+ GlFormCheckbox,
+ GlFormGroup,
+ GlFormSelect,
+ },
+ props: {
+ cancelPath: { required: true, type: String },
+ gcpProjects: { required: true, type: Array },
+ refs: { required: true, type: Array },
+ formTitle: { required: true, type: String },
+ formDescription: { required: true, type: String },
+ databaseVersions: { required: true, type: Array },
+ tiers: { required: true, type: Array },
+ },
+ i18n,
+};
+</script>
+<template>
+ <div>
+ <header class="gl-my-5 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid">
+ <h2 class="gl-font-size-h1">{{ formTitle }}</h2>
+ <p>{{ formDescription }}</p>
+ </header>
+
+ <gl-form-group
+ data-testid="form_group_gcp_project"
+ label-for="gcp_project"
+ :label="$options.i18n.gcpProjectLabel"
+ :description="$options.i18n.gcpProjectDescription"
+ >
+ <gl-form-select id="gcp_project" data-testid="select_gcp_project" name="gcp_project" required>
+ <option
+ v-for="gcpProject in gcpProjects"
+ :key="gcpProject.project_id"
+ :value="gcpProject.project_id"
+ >
+ {{ gcpProject.name }}
+ </option>
+ </gl-form-select>
+ </gl-form-group>
+
+ <gl-form-group
+ data-testid="form_group_environments"
+ label-for="ref"
+ :label="$options.i18n.refsLabel"
+ :description="$options.i18n.refsDescription"
+ >
+ <gl-form-select id="ref" data-testid="select_environments" name="ref" required>
+ <option :value="$options.ALL_REFS">{{ $options.i18n.all }}</option>
+ <option v-for="ref in refs" :key="ref" :value="ref">
+ {{ ref }}
+ </option>
+ </gl-form-select>
+ </gl-form-group>
+
+ <gl-form-group
+ data-testid="form_group_tier"
+ label-for="tier"
+ :label="$options.i18n.tierLabel"
+ :description="$options.i18n.tierDescription"
+ >
+ <gl-form-select id="tier" data-testid="select_tier" name="tier" required>
+ <option v-for="tier in tiers" :key="tier.value" :value="tier.value">
+ {{ tier.label }}
+ </option>
+ </gl-form-select>
+ </gl-form-group>
+
+ <gl-form-group
+ data-testid="form_group_database_version"
+ label-for="database-version"
+ :label="$options.i18n.databaseVersionLabel"
+ >
+ <gl-form-select
+ id="database-version"
+ data-testid="select_database_version"
+ name="database_version"
+ required
+ >
+ <option
+ v-for="databaseVersion in databaseVersions"
+ :key="databaseVersion.value"
+ :value="databaseVersion.value"
+ >
+ {{ databaseVersion.label }}
+ </option>
+ </gl-form-select>
+ </gl-form-group>
+
+ <gl-form-group>
+ <gl-form-checkbox name="confirmation" required>
+ {{ $options.i18n.checkboxLabel }}
+ </gl-form-checkbox>
+ </gl-form-group>
+
+ <div class="form-actions row">
+ <gl-button type="submit" category="primary" variant="confirm" data-testid="submit-button">
+ {{ $options.i18n.submitLabel }}
+ </gl-button>
+ <gl-button class="gl-ml-1" :href="cancelPath" data-testid="cancel-button">{{
+ $options.i18n.cancelLabel
+ }}</gl-button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/databases/cloudsql/instance_table.vue b/app/assets/javascripts/google_cloud/databases/cloudsql/instance_table.vue
new file mode 100644
index 00000000000..823895214df
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/databases/cloudsql/instance_table.vue
@@ -0,0 +1,75 @@
+<script>
+import { GlEmptyState, GlLink, GlTable } from '@gitlab/ui';
+import { encodeSaferUrl, setUrlParams } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+
+const i18n = {
+ noInstancesTitle: s__('CloudSeed|No instances'),
+ noInstancesDescription: s__('CloudSeed|There are no instances to display.'),
+ title: s__('CloudSeed|Instances'),
+ description: s__('CloudSeed|Database instances associated with this project'),
+};
+
+export default {
+ components: { GlEmptyState, GlLink, GlTable },
+ props: {
+ cloudsqlInstances: {
+ type: Array,
+ required: true,
+ },
+ emptyIllustrationUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ tableData() {
+ return this.cloudsqlInstances.filter((instance) => instance.instance_name);
+ },
+ },
+ methods: {
+ gcpProjectUrl(id) {
+ return setUrlParams({ project: id }, 'https://console.cloud.google.com/sql/instances');
+ },
+ instanceUrl(name, id) {
+ const saferName = encodeSaferUrl(name);
+
+ return setUrlParams(
+ { project: id },
+ `https://console.cloud.google.com/sql/instances/${saferName}/overview`,
+ );
+ },
+ },
+ fields: [
+ { key: 'ref', label: s__('CloudSeed|Environment') },
+ { key: 'gcp_project', label: s__('CloudSeed|Google Cloud Project') },
+ { key: 'instance_name', label: s__('CloudSeed|CloudSQL Instance') },
+ { key: 'version', label: s__('CloudSeed|Version') },
+ ],
+ i18n,
+};
+</script>
+
+<template>
+ <div class="gl-mx-3">
+ <gl-empty-state
+ v-if="tableData.length === 0"
+ :title="$options.i18n.noInstancesTitle"
+ :description="$options.i18n.noInstancesDescription"
+ :svg-path="emptyIllustrationUrl"
+ />
+
+ <div v-else>
+ <h2 class="gl-font-size-h2">{{ $options.i18n.title }}</h2>
+ <p>{{ $options.i18n.description }}</p>
+ <gl-table :fields="$options.fields" :items="tableData">
+ <template #cell(gcp_project)="{ value }">
+ <gl-link :href="gcpProjectUrl(value)">{{ value }}</gl-link>
+ </template>
+ <template #cell(instance_name)="{ item: { instance_name, gcp_project } }">
+ <a :href="instanceUrl(instance_name, gcp_project)">{{ instance_name }}</a>
+ </template>
+ </gl-table>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/databases/index.js b/app/assets/javascripts/google_cloud/databases/index.js
new file mode 100644
index 00000000000..e240a1116e8
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/databases/index.js
@@ -0,0 +1,11 @@
+import Vue from 'vue';
+import Panel from './panel.vue';
+
+export default (containerId = '#js-google-cloud-databases') => {
+ const element = document.querySelector(containerId);
+ const { ...attrs } = JSON.parse(element.getAttribute('data'));
+ return new Vue({
+ el: element,
+ render: (createElement) => createElement(Panel, { attrs }),
+ });
+};
diff --git a/app/assets/javascripts/google_cloud/databases/panel.vue b/app/assets/javascripts/google_cloud/databases/panel.vue
new file mode 100644
index 00000000000..e2f18c286a5
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/databases/panel.vue
@@ -0,0 +1,38 @@
+<script>
+import GoogleCloudMenu from '../components/google_cloud_menu.vue';
+import IncubationBanner from '../components/incubation_banner.vue';
+
+export default {
+ components: {
+ IncubationBanner,
+ GoogleCloudMenu,
+ },
+ props: {
+ configurationUrl: {
+ type: String,
+ required: true,
+ },
+ deploymentsUrl: {
+ type: String,
+ required: true,
+ },
+ databasesUrl: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <incubation-banner />
+
+ <google-cloud-menu
+ active="databases"
+ :configuration-url="configurationUrl"
+ :deployments-url="deploymentsUrl"
+ :databases-url="databasesUrl"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/databases/service_table.vue b/app/assets/javascripts/google_cloud/databases/service_table.vue
new file mode 100644
index 00000000000..80bd6ef28fb
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/databases/service_table.vue
@@ -0,0 +1,221 @@
+<script>
+import { GlAlert, GlButton, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { s__ } from '~/locale';
+
+const KEY_CLOUDSQL_POSTGRES = 'cloudsql-postgres';
+const KEY_CLOUDSQL_MYSQL = 'cloudsql-mysql';
+const KEY_CLOUDSQL_SQLSERVER = 'cloudsql-sqlserver';
+const KEY_ALLOYDB_POSTGRES = 'alloydb-postgres';
+const KEY_MEMORYSTORE_REDIS = 'memorystore-redis';
+const KEY_FIRESTORE = 'firestore';
+
+const i18n = {
+ columnService: s__('CloudSeed|Service'),
+ columnDescription: s__('CloudSeed|Description'),
+ cloudsqlPostgresTitle: s__('CloudSeed|Cloud SQL for Postgres'),
+ cloudsqlPostgresDescription: s__(
+ 'CloudSeed|Fully managed relational database service for PostgreSQL',
+ ),
+ cloudsqlMysqlTitle: s__('CloudSeed|Cloud SQL for MySQL'),
+ cloudsqlMysqlDescription: s__('CloudSeed|Fully managed relational database service for MySQL'),
+ cloudsqlSqlserverTitle: s__('CloudSeed|Cloud SQL for SQL Server'),
+ cloudsqlSqlserverDescription: s__(
+ 'CloudSeed|Fully managed relational database service for SQL Server',
+ ),
+ alloydbPostgresTitle: s__('CloudSeed|AlloyDB for Postgres'),
+ alloydbPostgresDescription: s__(
+ 'CloudSeed|Fully managed PostgreSQL-compatible service for high-demand workloads',
+ ),
+ memorystoreRedisTitle: s__('CloudSeed|Memorystore for Redis'),
+ memorystoreRedisDescription: s__(
+ 'CloudSeed|Scalable, secure, and highly available in-memory service for Redis',
+ ),
+ firestoreTitle: s__('CloudSeed|Cloud Firestore'),
+ firestoreDescription: s__(
+ 'CloudSeed|Flexible, scalable NoSQL cloud database for client- and server-side development',
+ ),
+ createInstance: s__('CloudSeed|Create instance'),
+ createCluster: s__('CloudSeed|Create cluster'),
+ createDatabase: s__('CloudSeed|Create database'),
+ title: s__('CloudSeed|Services'),
+ description: s__('CloudSeed|Available database services through which instances may be created'),
+ pricingAlert: s__(
+ 'CloudSeed|Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} and %{firestorePricingStart}Firestore%{firestorePricingEnd}.',
+ ),
+ secretManagersDescription: s__(
+ 'CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}',
+ ),
+};
+
+const helpUrlSecrets = helpPagePath('ee/ci/secrets');
+
+export default {
+ components: { GlAlert, GlButton, GlLink, GlSprintf, GlTable },
+ props: {
+ cloudsqlPostgresUrl: {
+ type: String,
+ required: true,
+ },
+ cloudsqlMysqlUrl: {
+ type: String,
+ required: true,
+ },
+ cloudsqlSqlserverUrl: {
+ type: String,
+ required: true,
+ },
+ alloydbPostgresUrl: {
+ type: String,
+ required: true,
+ },
+ memorystoreRedisUrl: {
+ type: String,
+ required: true,
+ },
+ firestoreUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ actionUrl(key) {
+ switch (key) {
+ case KEY_CLOUDSQL_POSTGRES:
+ return this.cloudsqlPostgresUrl;
+ case KEY_CLOUDSQL_MYSQL:
+ return this.cloudsqlMysqlUrl;
+ case KEY_CLOUDSQL_SQLSERVER:
+ return this.cloudsqlSqlserverUrl;
+ case KEY_ALLOYDB_POSTGRES:
+ return this.alloydbPostgresUrl;
+ case KEY_MEMORYSTORE_REDIS:
+ return this.memorystoreRedisUrl;
+ case KEY_FIRESTORE:
+ return this.firestoreUrl;
+ default:
+ return '#';
+ }
+ },
+ },
+ fields: [
+ { key: 'title', label: i18n.columnService },
+ { key: 'description', label: i18n.columnDescription },
+ { key: 'action', label: '' },
+ ],
+ items: [
+ {
+ title: i18n.cloudsqlPostgresTitle,
+ description: i18n.cloudsqlPostgresDescription,
+ action: {
+ key: KEY_CLOUDSQL_POSTGRES,
+ title: i18n.createInstance,
+ testId: 'button-cloudsql-postgres',
+ },
+ },
+ {
+ title: i18n.cloudsqlMysqlTitle,
+ description: i18n.cloudsqlMysqlDescription,
+ action: {
+ disabled: false,
+ key: KEY_CLOUDSQL_MYSQL,
+ title: i18n.createInstance,
+ testId: 'button-cloudsql-mysql',
+ },
+ },
+ {
+ title: i18n.cloudsqlSqlserverTitle,
+ description: i18n.cloudsqlSqlserverDescription,
+ action: {
+ disabled: false,
+ key: KEY_CLOUDSQL_SQLSERVER,
+ title: i18n.createInstance,
+ testId: 'button-cloudsql-sqlserver',
+ },
+ },
+ {
+ title: i18n.alloydbPostgresTitle,
+ description: i18n.alloydbPostgresDescription,
+ action: {
+ disabled: true,
+ key: KEY_ALLOYDB_POSTGRES,
+ title: i18n.createCluster,
+ testId: 'button-alloydb-postgres',
+ },
+ },
+ {
+ title: i18n.memorystoreRedisTitle,
+ description: i18n.memorystoreRedisDescription,
+ action: {
+ disabled: true,
+ key: KEY_MEMORYSTORE_REDIS,
+ title: i18n.createInstance,
+ testId: 'button-memorystore-redis',
+ },
+ },
+ {
+ title: i18n.firestoreTitle,
+ description: i18n.firestoreDescription,
+ action: {
+ disabled: true,
+ key: KEY_FIRESTORE,
+ title: i18n.createDatabase,
+ testId: 'button-firestore',
+ },
+ },
+ ],
+ helpUrlSecrets,
+ i18n,
+};
+</script>
+
+<template>
+ <div class="gl-mx-3">
+ <h2 class="gl-font-size-h2">{{ $options.i18n.title }}</h2>
+ <p>{{ $options.i18n.description }}</p>
+
+ <gl-table :fields="$options.fields" :items="$options.items">
+ <template #cell(action)="{ value }">
+ <gl-button
+ block
+ :disabled="value.disabled"
+ :href="actionUrl(value.key)"
+ :data-testid="value.testId"
+ category="secondary"
+ variant="confirm"
+ >
+ {{ value.title }}
+ </gl-button>
+ </template>
+ </gl-table>
+
+ <gl-alert class="gl-mt-5" :dismissible="false" variant="tip">
+ <gl-sprintf :message="$options.i18n.pricingAlert">
+ <template #cloudsqlPricing="{ content }">
+ <gl-link href="https://cloud.google.com/sql/pricing">{{ content }}</gl-link>
+ </template>
+ <template #alloydbPricing="{ content }">
+ <gl-link href="https://cloud.google.com/alloydb/pricing">{{ content }}</gl-link>
+ </template>
+ <template #memorystorePricing="{ content }">
+ <gl-link href="https://cloud.google.com/memorystore/docs/redis/pricing">{{
+ content
+ }}</gl-link>
+ </template>
+ <template #firestorePricing="{ content }">
+ <gl-link href="https://cloud.google.com/firestore/pricing">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+
+ <gl-alert class="gl-mt-5" :dismissible="false" variant="tip">
+ <gl-sprintf :message="$options.i18n.secretManagersDescription">
+ <template #docLink="{ content }">
+ <gl-link :href="$options.helpUrlSecrets">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/deployments/index.js b/app/assets/javascripts/google_cloud/deployments/index.js
new file mode 100644
index 00000000000..fcbb2209c40
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/deployments/index.js
@@ -0,0 +1,11 @@
+import Vue from 'vue';
+import Panel from './panel.vue';
+
+export default (containerId = '#js-google-cloud-deployments') => {
+ const element = document.querySelector(containerId);
+ const { ...attrs } = JSON.parse(element.getAttribute('data'));
+ return new Vue({
+ el: element,
+ render: (createElement) => createElement(Panel, { attrs }),
+ });
+};
diff --git a/app/assets/javascripts/google_cloud/deployments/panel.vue b/app/assets/javascripts/google_cloud/deployments/panel.vue
new file mode 100644
index 00000000000..89db132ad5e
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/deployments/panel.vue
@@ -0,0 +1,50 @@
+<script>
+import GoogleCloudMenu from '../components/google_cloud_menu.vue';
+import IncubationBanner from '../components/incubation_banner.vue';
+import ServiceTable from './service_table.vue';
+
+export default {
+ components: {
+ ServiceTable,
+ IncubationBanner,
+ GoogleCloudMenu,
+ },
+ props: {
+ configurationUrl: {
+ type: String,
+ required: true,
+ },
+ deploymentsUrl: {
+ type: String,
+ required: true,
+ },
+ databasesUrl: {
+ type: String,
+ required: true,
+ },
+ enableCloudRunUrl: {
+ type: String,
+ required: true,
+ },
+ enableCloudStorageUrl: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <incubation-banner />
+
+ <google-cloud-menu
+ active="deployments"
+ :configuration-url="configurationUrl"
+ :deployments-url="deploymentsUrl"
+ :databases-url="databasesUrl"
+ />
+
+ <service-table :cloud-run-url="enableCloudRunUrl" :cloud-storage-url="enableCloudStorageUrl" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/deployments_service_table.vue b/app/assets/javascripts/google_cloud/deployments/service_table.vue
index 26c9fd14dc6..26c9fd14dc6 100644
--- a/app/assets/javascripts/google_cloud/components/deployments_service_table.vue
+++ b/app/assets/javascripts/google_cloud/deployments/service_table.vue
diff --git a/app/assets/javascripts/google_cloud/components/gcp_regions_form.vue b/app/assets/javascripts/google_cloud/gcp_regions/form.vue
index 23011e5a5b0..23011e5a5b0 100644
--- a/app/assets/javascripts/google_cloud/components/gcp_regions_form.vue
+++ b/app/assets/javascripts/google_cloud/gcp_regions/form.vue
diff --git a/app/assets/javascripts/google_cloud/gcp_regions/index.js b/app/assets/javascripts/google_cloud/gcp_regions/index.js
new file mode 100644
index 00000000000..da37c612805
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/gcp_regions/index.js
@@ -0,0 +1,11 @@
+import Vue from 'vue';
+import Form from './form.vue';
+
+export default (containerId = '#js-google-cloud-gcp-regions') => {
+ const element = document.querySelector(containerId);
+ const { ...attrs } = JSON.parse(element.getAttribute('data'));
+ return new Vue({
+ el: element,
+ render: (createElement) => createElement(Form, { attrs }),
+ });
+};
diff --git a/app/assets/javascripts/google_cloud/components/gcp_regions_list.vue b/app/assets/javascripts/google_cloud/gcp_regions/list.vue
index 5d403d5cd65..5d403d5cd65 100644
--- a/app/assets/javascripts/google_cloud/components/gcp_regions_list.vue
+++ b/app/assets/javascripts/google_cloud/gcp_regions/list.vue
diff --git a/app/assets/javascripts/google_cloud/index.js b/app/assets/javascripts/google_cloud/index.js
deleted file mode 100644
index ab9e8227812..00000000000
--- a/app/assets/javascripts/google_cloud/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import Vue from 'vue';
-import App from './components/app.vue';
-
-export default () => {
- const root = '#js-google-cloud';
- const element = document.querySelector(root);
- const { screen, ...attrs } = JSON.parse(element.getAttribute('data'));
- return new Vue({
- el: element,
- render: (createElement) => createElement(App, { props: { screen }, attrs }),
- });
-};
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue b/app/assets/javascripts/google_cloud/service_accounts/form.vue
index faec94e735b..faec94e735b 100644
--- a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
+++ b/app/assets/javascripts/google_cloud/service_accounts/form.vue
diff --git a/app/assets/javascripts/google_cloud/service_accounts/index.js b/app/assets/javascripts/google_cloud/service_accounts/index.js
new file mode 100644
index 00000000000..5207b44deac
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/service_accounts/index.js
@@ -0,0 +1,11 @@
+import Vue from 'vue';
+import Form from './form.vue';
+
+export default (containerId = '#js-google-cloud-service-accounts') => {
+ const element = document.querySelector(containerId);
+ const { ...attrs } = JSON.parse(element.getAttribute('data'));
+ return new Vue({
+ el: element,
+ render: (createElement) => createElement(Form, { attrs }),
+ });
+};
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue b/app/assets/javascripts/google_cloud/service_accounts/list.vue
index 4b580c594f5..4b580c594f5 100644
--- a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
+++ b/app/assets/javascripts/google_cloud/service_accounts/list.vue