summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js12
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue21
-rw-r--r--app/assets/javascripts/clusters/components/knative_domain_editor.vue105
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js9
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/clone_dropdown.vue89
6 files changed, 212 insertions, 32 deletions
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index da34c5030f9..1b11ec355bb 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -259,7 +259,7 @@ export default class Clusters {
eventHub.$on('installApplication', this.installApplication);
eventHub.$on('updateApplication', data => this.updateApplication(data));
eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
- eventHub.$on('setKnativeHostname', data => this.setKnativeHostname(data));
+ eventHub.$on('setKnativeDomain', data => this.setKnativeDomain(data));
eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
eventHub.$on('setCrossplaneProviderStack', data => this.setCrossplaneProviderStack(data));
eventHub.$on('setIngressModSecurityEnabled', data => this.setIngressModSecurityEnabled(data));
@@ -275,7 +275,7 @@ export default class Clusters {
eventHub.$off('installApplication', this.installApplication);
eventHub.$off('updateApplication', this.updateApplication);
eventHub.$off('saveKnativeDomain');
- eventHub.$off('setKnativeHostname');
+ eventHub.$off('setKnativeDomain');
eventHub.$off('setCrossplaneProviderStack');
eventHub.$off('uninstallApplication');
eventHub.$off('setIngressModSecurityEnabled');
@@ -521,10 +521,10 @@ export default class Clusters {
});
}
- setKnativeHostname(data) {
- const appId = data.id;
- this.store.updateAppProperty(appId, 'isEditingHostName', true);
- this.store.updateAppProperty(appId, 'hostname', data.hostname);
+ setKnativeDomain({ id: appId, domain, domainId }) {
+ this.store.updateAppProperty(appId, 'isEditingDomain', true);
+ this.store.updateAppProperty(appId, 'hostname', domain);
+ this.store.updateAppProperty(appId, 'pagesDomain', domainId ? { id: domainId, domain } : null);
}
setCrossplaneProviderStack(data) {
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 219825b1c01..723030c5b8b 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -240,16 +240,20 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
this.helmInstallIllustration = helmInstallIllustration;
},
methods: {
- saveKnativeDomain(hostname) {
+ saveKnativeDomain() {
eventHub.$emit('saveKnativeDomain', {
id: 'knative',
- params: { hostname },
+ params: {
+ hostname: this.applications.knative.hostname,
+ pages_domain_id: this.applications.knative.pagesDomain?.id,
+ },
});
},
- setKnativeHostname(hostname) {
- eventHub.$emit('setKnativeHostname', {
+ setKnativeDomain({ domainId, domain }) {
+ eventHub.$emit('setKnativeDomain', {
id: 'knative',
- hostname,
+ domainId,
+ domain,
});
},
setCrossplaneProviderStack(stack) {
@@ -591,7 +595,10 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
:request-reason="applications.knative.requestReason"
:installed="applications.knative.installed"
:install-failed="applications.knative.installFailed"
- :install-application-request-params="{ hostname: applications.knative.hostname }"
+ :install-application-request-params="{
+ hostname: applications.knative.hostname,
+ pages_domain_id: applications.knative.pagesDomain && applications.knative.pagesDomain.id,
+ }"
:installed-via="installedVia"
:uninstallable="applications.knative.uninstallable"
:uninstall-successful="applications.knative.uninstallSuccessful"
@@ -628,7 +635,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity
:knative="knative"
:ingress-dns-help-path="ingressDnsHelpPath"
@save="saveKnativeDomain"
- @set="setKnativeHostname"
+ @set="setKnativeDomain"
/>
</div>
</application-row>
diff --git a/app/assets/javascripts/clusters/components/knative_domain_editor.vue b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
index 30efbe2e0f7..8136704d13b 100644
--- a/app/assets/javascripts/clusters/components/knative_domain_editor.vue
+++ b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
@@ -1,5 +1,12 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlSprintf,
+} from '@gitlab/ui';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import { __, s__ } from '~/locale';
@@ -13,6 +20,11 @@ export default {
LoadingButton,
ClipboardButton,
GlLoadingIcon,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlSearchBoxByType,
+ GlSprintf,
},
props: {
knative: {
@@ -25,6 +37,11 @@ export default {
required: false,
},
},
+ data() {
+ return {
+ searchQuery: '',
+ };
+ },
computed: {
saveButtonDisabled() {
return [UNINSTALLING, UPDATING].includes(this.knative.status);
@@ -49,9 +66,22 @@ export default {
return this.knative.hostname;
},
set(hostname) {
- this.$emit('set', hostname);
+ this.selectCustomDomain(hostname);
},
},
+ domainDropdownText() {
+ return this.knativeHostname || s__('ClusterIntegration|Select existing domain or use new');
+ },
+ availableDomains() {
+ return this.knative.availableDomains || [];
+ },
+ filteredDomains() {
+ const query = this.searchQuery.toLowerCase();
+ return this.availableDomains.filter(({ domain }) => domain.toLowerCase().includes(query));
+ },
+ showDomainsDropdown() {
+ return this.availableDomains.length > 0;
+ },
},
watch: {
knativeUpdateSuccessful(updateSuccessful) {
@@ -60,6 +90,14 @@ export default {
}
},
},
+ methods: {
+ selectDomain({ id, domain }) {
+ this.$emit('set', { domain, domainId: id });
+ },
+ selectCustomDomain(domain) {
+ this.$emit('set', { domain, domainId: null });
+ },
+ },
};
</script>
@@ -72,22 +110,55 @@ export default {
{{ s__('ClusterIntegration|Something went wrong while updating Knative domain name.') }}
</div>
- <template>
- <div
- :class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
- class="form-group col-sm-12 mb-0"
+ <div
+ :class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
+ class="form-group col-sm-12 mb-0"
+ >
+ <label for="knative-domainname">
+ <strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
+ </label>
+
+ <gl-dropdown
+ v-if="showDomainsDropdown"
+ :text="domainDropdownText"
+ toggle-class="dropdown-menu-toggle"
+ class="w-100 mb-2"
>
- <label for="knative-domainname">
- <strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
- </label>
- <input
- id="knative-domainname"
- v-model="knativeHostname"
- type="text"
- class="form-control js-knative-domainname"
+ <gl-search-box-by-type
+ v-model.trim="searchQuery"
+ :placeholder="s__('ClusterIntegration|Search domains')"
+ class="m-2"
/>
- </div>
- </template>
+ <gl-dropdown-item
+ v-for="domain in filteredDomains"
+ :key="domain.id"
+ @click="selectDomain(domain)"
+ >
+ <span class="ml-1">{{ domain.domain }}</span>
+ </gl-dropdown-item>
+ <template v-if="searchQuery">
+ <gl-dropdown-divider />
+ <gl-dropdown-item key="custom-domain" @click="selectCustomDomain(searchQuery)">
+ <span class="ml-1">
+ <gl-sprintf :message="s__('ClusterIntegration|Use %{query}')">
+ <template #query>
+ <code>{{ searchQuery }}</code>
+ </template>
+ </gl-sprintf>
+ </span>
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+
+ <input
+ v-else
+ id="knative-domainname"
+ v-model="knativeHostname"
+ type="text"
+ class="form-control js-knative-domainname"
+ />
+ </div>
+
<template v-if="knativeInstalled">
<div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
<label for="knative-endpoint">
@@ -144,7 +215,7 @@ export default {
:loading="saving"
:disabled="saveButtonDisabled"
:label="saveButtonLabel"
- @click="$emit('save', knativeHostname)"
+ @click="$emit('save')"
/>
</template>
</div>
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 8685e3decc5..b09fd6800b6 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -93,7 +93,7 @@ export default class ClusterStore {
...applicationInitialState,
title: s__('ClusterIntegration|Knative'),
hostname: null,
- isEditingHostName: false,
+ isEditingDomain: false,
externalIp: null,
externalHostname: null,
updateSuccessful: false,
@@ -234,7 +234,12 @@ export default class ClusterStore {
'jupyter',
);
} else if (appId === KNATIVE) {
- if (!this.state.applications.knative.isEditingHostName) {
+ if (serverAppEntry.available_domains) {
+ this.state.applications.knative.availableDomains = serverAppEntry.available_domains;
+ }
+ if (!this.state.applications.knative.isEditingDomain) {
+ this.state.applications.knative.pagesDomain =
+ serverAppEntry.pages_domain || this.state.applications.knative.pagesDomain;
this.state.applications.knative.hostname =
serverAppEntry.hostname || this.state.applications.knative.hostname;
}
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 1ff4f7bab97..a495d2040d3 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -318,3 +318,11 @@ export const setUrlParams = (params, url = window.location.href, clearParams = f
export function urlIsDifferent(url, compare = String(window.location)) {
return url !== compare;
}
+
+export function getHTTPProtocol(url) {
+ if (!url) {
+ return window.location.protocol.slice(0, -1);
+ }
+ const protocol = url.split(':');
+ return protocol.length > 1 ? protocol[0] : undefined;
+}
diff --git a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
new file mode 100644
index 00000000000..3b9b9f37f52
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
@@ -0,0 +1,89 @@
+<script>
+import {
+ GlNewDropdown,
+ GlNewDropdownHeader,
+ GlFormInputGroup,
+ GlNewButton,
+ GlIcon,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
+import { getHTTPProtocol } from '~/lib/utils/url_utility';
+
+export default {
+ components: {
+ GlNewDropdown,
+ GlNewDropdownHeader,
+ GlFormInputGroup,
+ GlNewButton,
+ GlIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ sshLink: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ httpLink: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ httpLabel() {
+ const protocol = this.httpLink ? getHTTPProtocol(this.httpLink)?.toUpperCase() : '';
+ return sprintf(__('Clone with %{protocol}'), { protocol });
+ },
+ },
+ labels: {
+ defaultLabel: __('Clone'),
+ ssh: __('Clone with SSH'),
+ },
+ copyURLTooltip: __('Copy URL'),
+};
+</script>
+<template>
+ <gl-new-dropdown :text="$options.labels.defaultLabel" category="primary" variant="info">
+ <div class="pb-2 mx-1">
+ <template v-if="sshLink">
+ <gl-new-dropdown-header>{{ $options.labels.ssh }}</gl-new-dropdown-header>
+
+ <div class="mx-3">
+ <gl-form-input-group :value="sshLink" readonly select-on-click>
+ <template #append>
+ <gl-new-button
+ v-gl-tooltip.hover
+ :title="$options.copyURLTooltip"
+ :data-clipboard-text="sshLink"
+ >
+ <gl-icon name="copy-to-clipboard" :title="$options.copyURLTooltip" />
+ </gl-new-button>
+ </template>
+ </gl-form-input-group>
+ </div>
+ </template>
+
+ <template v-if="httpLink">
+ <gl-new-dropdown-header>{{ httpLabel }}</gl-new-dropdown-header>
+
+ <div class="mx-3">
+ <gl-form-input-group :value="httpLink" readonly select-on-click>
+ <template #append>
+ <gl-new-button
+ v-gl-tooltip.hover
+ :title="$options.copyURLTooltip"
+ :data-clipboard-text="httpLink"
+ >
+ <gl-icon name="copy-to-clipboard" :title="$options.copyURLTooltip" />
+ </gl-new-button>
+ </template>
+ </gl-form-input-group>
+ </div>
+ </template>
+ </div>
+ </gl-new-dropdown>
+</template>