diff options
Diffstat (limited to 'app/assets/javascripts/environments/components/environment_flux_resource_selector.vue')
-rw-r--r-- | app/assets/javascripts/environments/components/environment_flux_resource_selector.vue | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/app/assets/javascripts/environments/components/environment_flux_resource_selector.vue b/app/assets/javascripts/environments/components/environment_flux_resource_selector.vue new file mode 100644 index 00000000000..cad6752da94 --- /dev/null +++ b/app/assets/javascripts/environments/components/environment_flux_resource_selector.vue @@ -0,0 +1,210 @@ +<script> +import { GlFormGroup, GlCollapsibleListbox, GlAlert } from '@gitlab/ui'; +import { __, s__ } from '~/locale'; +import fluxKustomizationsQuery from '../graphql/queries/flux_kustomizations.query.graphql'; +import fluxHelmReleasesQuery from '../graphql/queries/flux_helm_releases.query.graphql'; +import { + HELM_RELEASES_RESOURCE_TYPE, + KUSTOMIZATIONS_RESOURCE_TYPE, + KUSTOMIZATION, + HELM_RELEASE, +} from '../constants'; + +export default { + components: { + GlFormGroup, + GlCollapsibleListbox, + GlAlert, + }, + props: { + configuration: { + required: true, + type: Object, + }, + namespace: { + required: true, + type: String, + }, + fluxResourcePath: { + required: false, + type: String, + default: '', + }, + }, + i18n: { + fluxResourceLabel: s__('Environments|Select Flux resource (optional)'), + kustomizationsGroupLabel: s__('Environments|Kustomizations'), + helmReleasesGroupLabel: s__('Environments|HelmReleases'), + fluxResourcesHelpText: s__('Environments|Select Flux resource'), + errorTitle: s__( + 'Environments|Unable to access the following resources from this environment. Check your authorization on the following and try again:', + ), + reset: __('Reset'), + }, + data() { + return { + fluxResourceSearchTerm: '', + kustomizationsError: '', + helmReleasesError: '', + }; + }, + apollo: { + fluxKustomizations: { + query: fluxKustomizationsQuery, + variables() { + return { + configuration: this.configuration, + namespace: this.namespace, + }; + }, + skip() { + return !this.namespace; + }, + update(data) { + return data?.fluxKustomizations || []; + }, + error() { + this.kustomizationsError = KUSTOMIZATION; + }, + result(result) { + if (!result?.error && !result.errors?.length) { + this.kustomizationsError = ''; + } + }, + }, + fluxHelmReleases: { + query: fluxHelmReleasesQuery, + variables() { + return { + configuration: this.configuration, + namespace: this.namespace, + }; + }, + skip() { + return !this.namespace; + }, + update(data) { + return data?.fluxHelmReleases || []; + }, + error() { + this.helmReleasesError = HELM_RELEASE; + }, + result(result) { + if (!result?.error && !result.errors?.length) { + this.helmReleasesError = ''; + } + }, + }, + }, + computed: { + variables() { + return { + configuration: this.configuration, + namespace: this.namespace, + }; + }, + loadingFluxResourcesList() { + return this.$apollo.loading; + }, + kubernetesErrors() { + const errors = []; + if (this.kustomizationsError) { + errors.push(this.kustomizationsError); + } + if (this.helmReleasesError) { + errors.push(this.helmReleasesError); + } + return errors; + }, + fluxResourcesDropdownToggleText() { + const selectedResourceParts = this.fluxResourcePath ? this.fluxResourcePath.split('/') : []; + return selectedResourceParts.length + ? selectedResourceParts.at(-1) + : this.$options.i18n.fluxResourcesHelpText; + }, + fluxKustomizationsList() { + return ( + this.fluxKustomizations?.map((item) => { + return { + value: `${item.apiVersion}/namespaces/${item.metadata.namespace}/${KUSTOMIZATIONS_RESOURCE_TYPE}/${item.metadata.name}`, + text: item.metadata.name, + }; + }) || [] + ); + }, + fluxHelmReleasesList() { + return ( + this.fluxHelmReleases?.map((item) => { + return { + value: `${item.apiVersion}/namespaces/${item.metadata.namespace}/${HELM_RELEASES_RESOURCE_TYPE}/${item.metadata.name}`, + text: item.metadata.name, + }; + }) || [] + ); + }, + filteredKustomizationsList() { + const lowerCasedSearchTerm = this.fluxResourceSearchTerm.toLowerCase(); + return this.fluxKustomizationsList.filter((item) => + item.text.toLowerCase().includes(lowerCasedSearchTerm), + ); + }, + filteredHelmResourcesList() { + const lowerCasedSearchTerm = this.fluxResourceSearchTerm.toLowerCase(); + return this.fluxHelmReleasesList.filter((item) => + item.text.toLowerCase().includes(lowerCasedSearchTerm), + ); + }, + fluxResourcesList() { + const list = []; + if (this.filteredKustomizationsList?.length) { + list.push({ + text: this.$options.i18n.kustomizationsGroupLabel, + options: this.filteredKustomizationsList, + }); + } + + if (this.filteredHelmResourcesList?.length) { + list.push({ + text: this.$options.i18n.helmReleasesGroupLabel, + options: this.filteredHelmResourcesList, + }); + } + return list; + }, + }, + methods: { + onChange(event) { + this.$emit('change', event); + }, + onSearch(search) { + this.fluxResourceSearchTerm = search; + }, + }, +}; +</script> +<template> + <gl-form-group :label="$options.i18n.fluxResourceLabel" label-for="environment_flux_resource"> + <gl-alert v-if="kubernetesErrors.length" variant="warning" :dismissible="false" class="gl-mb-5"> + {{ $options.i18n.errorTitle }} + <ul class="gl-mb-0 gl-pl-6"> + <li v-for="(error, index) of kubernetesErrors" :key="index">{{ error }}</li> + </ul> + </gl-alert> + + <gl-collapsible-listbox + id="environment_flux_resource_path" + class="gl-w-full" + block + :selected="fluxResourcePath" + :items="fluxResourcesList" + :loading="loadingFluxResourcesList" + :toggle-text="fluxResourcesDropdownToggleText" + :header-text="$options.i18n.fluxResourcesHelpText" + :reset-button-label="$options.i18n.reset" + searchable + @search="onSearch" + @select="onChange" + @reset="onChange(null)" + /> + </gl-form-group> +</template> |