diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-24 15:13:01 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-24 15:13:01 +0300 |
commit | 552e85a58645e5321b33dacc8d410fa88fb75a85 (patch) | |
tree | 1a75b860851c45f970cf13a35001ce9caded3fa5 /app/assets/javascripts/feature_flags | |
parent | b0d6a7fbff3f97a4b2b56b672902a21e0fc29195 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/feature_flags')
-rw-r--r-- | app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue | 119 | ||||
-rw-r--r-- | app/assets/javascripts/feature_flags/components/strategy.vue | 97 |
2 files changed, 95 insertions, 121 deletions
diff --git a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue index 348af1ad03e..89400bc4742 100644 --- a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue +++ b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue @@ -1,22 +1,27 @@ <script> -import { GlTokenSelector } from '@gitlab/ui'; +import { + GlDropdown, + GlDropdownDivider, + GlDropdownItem, + GlIcon, + GlLoadingIcon, + GlSearchBoxByType, +} from '@gitlab/ui'; import { debounce } from 'lodash'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; -import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; import { __, sprintf } from '~/locale'; export default { components: { - GlTokenSelector, + GlDropdown, + GlDropdownDivider, + GlDropdownItem, + GlSearchBoxByType, + GlIcon, + GlLoadingIcon, }, inject: ['environmentsEndpoint'], - props: { - selected: { - type: Array, - required: true, - }, - }, data() { return { environmentSearch: '', @@ -27,54 +32,24 @@ export default { translations: { addEnvironmentsLabel: __('Add environment'), noResultsLabel: __('No matching results'), - loadingResultsLabel: __('Loading...'), - allEnvironments: __('All environments'), }, computed: { createEnvironmentLabel() { return sprintf(__('Create %{environment}'), { environment: this.environmentSearch }); }, - selectedEnvironmentNames() { - return this.selected.map(({ name }) => name); - }, - dropdownItems() { - return this.results.filter(({ name }) => !this.isSelected(name)); - }, - hasNoSearchResults() { - return !this.dropdownItems.length; - }, - searchItemAlreadySelected() { - return this.isSelected(this.environmentSearch); - }, - }, - created() { - this.debouncedHandleSearch = debounce(this.handleSearch, DEFAULT_DEBOUNCE_AND_THROTTLE_MS); - }, - destroyed() { - this.debouncedHandleSearch.cancel(); }, methods: { - isSelected(name) { - return this.selectedEnvironmentNames.includes(name); - }, - addEnvironment({ name }) { - this.$emit('add', name); - this.environmentSearch = ''; - }, - removeEnvironment({ name }) { - this.$emit('remove', name); + addEnvironment(newEnvironment) { + this.$emit('add', newEnvironment); this.environmentSearch = ''; + this.results = []; }, - handleSearch(query = '') { - this.environmentSearch = query; - this.fetchEnvironments(); - }, - async fetchEnvironments() { + fetchEnvironments: debounce(function debouncedFetchEnvironments() { this.isLoading = true; - await axios + axios .get(this.environmentsEndpoint, { params: { query: this.environmentSearch } }) - .then(({ data = [] }) => { - this.results = data.map((text, index) => ({ id: index, name: text })); + .then(({ data }) => { + this.results = data || []; }) .catch(() => { createAlert({ @@ -84,28 +59,44 @@ export default { .finally(() => { this.isLoading = false; }); + }, 250), + setFocus() { + this.$refs.searchBox.focusInput(); }, }, }; </script> <template> - <gl-token-selector - data-testid="new-environment-selector" - :selected-tokens="selected" - :label-text="$options.translations.addEnvironmentsLabel" - :dropdown-items="dropdownItems" - :loading="isLoading" - :hide-dropdown-with-no-items="searchItemAlreadySelected && hasNoSearchResults" - :allow-user-defined-tokens="!searchItemAlreadySelected" - @focus.once="fetchEnvironments" - @text-input="debouncedHandleSearch" - @token-add="addEnvironment" - @token-remove="removeEnvironment" - > - <template #user-defined-token-content> - {{ createEnvironmentLabel }} + <gl-dropdown class="js-new-environments-dropdown" @shown="setFocus"> + <template #button-content> + <span class="d-md-none mr-1"> + {{ $options.translations.addEnvironmentsLabel }} + </span> + <gl-icon class="d-none d-md-inline-flex gl-mr-1" name="plus" /> + </template> + <gl-search-box-by-type + ref="searchBox" + v-model.trim="environmentSearch" + @focus="fetchEnvironments" + @keyup="fetchEnvironments" + /> + <gl-loading-icon v-if="isLoading" size="sm" /> + <gl-dropdown-item + v-for="environment in results" + v-else-if="results.length" + :key="environment" + @click="addEnvironment(environment)" + > + {{ environment }} + </gl-dropdown-item> + <template v-else-if="environmentSearch.length"> + <span ref="noResults" class="text-secondary gl-p-3"> + {{ $options.translations.noMatchingResults }} + </span> + <gl-dropdown-divider /> + <gl-dropdown-item @click="addEnvironment(environmentSearch)"> + {{ createEnvironmentLabel }} + </gl-dropdown-item> </template> - <template #no-results-content>{{ $options.translations.noResultsLabel }}</template> - <template #loading-content>{{ $options.translations.loadingResultsLabel }}</template> - </gl-token-selector> + </gl-dropdown> </template> diff --git a/app/assets/javascripts/feature_flags/components/strategy.vue b/app/assets/javascripts/feature_flags/components/strategy.vue index 347281dc127..1d7a79f926a 100644 --- a/app/assets/javascripts/feature_flags/components/strategy.vue +++ b/app/assets/javascripts/feature_flags/components/strategy.vue @@ -1,13 +1,12 @@ <script> -import { GlAlert, GlButton, GlFormSelect, GlFormGroup, GlIcon, GlLink } from '@gitlab/ui'; -import { isNumber, uniqueId } from 'lodash'; +import { GlAlert, GlButton, GlFormSelect, GlFormGroup, GlIcon, GlLink, GlToken } from '@gitlab/ui'; +import { isNumber } from 'lodash'; import Vue from 'vue'; import { s__, __ } from '~/locale'; import { EMPTY_PARAMETERS, STRATEGY_SELECTIONS, ROLLOUT_STRATEGY_PERCENT_ROLLOUT, - ALL_ENVIRONMENTS_NAME, } from '../constants'; import NewEnvironmentsDropdown from './new_environments_dropdown.vue'; @@ -21,6 +20,7 @@ export default { GlFormSelect, GlIcon, GlLink, + GlToken, NewEnvironmentsDropdown, StrategyParameters, }, @@ -79,23 +79,12 @@ export default { appliesToAllEnvironments() { return ( this.filteredEnvironments.length === 1 && - this.filteredEnvironments[0].environmentScope === ALL_ENVIRONMENTS_NAME + this.filteredEnvironments[0].environmentScope === '*' ); }, filteredEnvironments() { return this.environments.filter((e) => !e.shouldBeDestroyed); }, - selectableEnvironments() { - return this.environments.filter( - (e) => !e.shouldBeDestroyed && e.environmentScope !== ALL_ENVIRONMENTS_NAME, - ); - }, - filteredEnvironmentsOptions() { - return this.selectableEnvironments.map(({ id, environmentScope: name }) => ({ - id: id || uniqueId('env_'), - name, - })); - }, isPercentUserRollout() { return this.formStrategy.name === ROLLOUT_STRATEGY_PERCENT_ROLLOUT; }, @@ -103,21 +92,12 @@ export default { methods: { addEnvironment(environment) { const allEnvironmentsScope = this.environments.find( - (scope) => scope.environmentScope === ALL_ENVIRONMENTS_NAME, + (scope) => scope.environmentScope === '*', ); if (allEnvironmentsScope) { allEnvironmentsScope.shouldBeDestroyed = true; } - - const foundEnv = this.environments.find( - ({ environmentScope }) => environmentScope === environment, - ); - if (isNumber(foundEnv?.id)) { - Vue.set(foundEnv, 'shouldBeDestroyed', false); - } else { - this.environments.push({ environmentScope: environment }); - } - + this.environments.push({ environmentScope: environment }); this.onStrategyChange({ ...this.formStrategy, scopes: this.environments }); }, onStrategyTypeChange(name) { @@ -131,15 +111,11 @@ export default { this.$emit('change', s); this.formStrategy = s; }, - removeScope(target) { - const environment = this.environments.find( - ({ environmentScope }) => environmentScope === target, - ); - - if (isNumber(environment?.id)) { + removeScope(environment) { + if (isNumber(environment.id)) { Vue.set(environment, 'shouldBeDestroyed', true); } else { - this.environments = this.environments.filter((e) => e.environmentScope !== target); + this.environments = this.environments.filter((e) => e !== environment); } if (this.filteredEnvironments.length === 0) { this.environments.push({ environmentScope: '*' }); @@ -157,7 +133,7 @@ export default { <div class="gl-border-t-solid gl-border-t-1 gl-border-t-gray-100 gl-py-6"> <div class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row flex-md-wrap"> - <div class="gl-mr-7"> + <div class="mr-5"> <gl-form-group :label="$options.i18n.strategyTypeLabel" :label-for="strategyTypeId"> <template #description> {{ $options.i18n.strategyTypeDescription }} @@ -195,32 +171,39 @@ export default { </div> </div> - <gl-form-group :label="$options.i18n.environmentsLabel" :label-for="environmentsDropdownId"> - <div class="row"> - <div class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-w-full"> - <div class="gl-w-full gl-md-w-auto col-md-4"> - <new-environments-dropdown - :id="environmentsDropdownId" - :selected="filteredEnvironmentsOptions" - @remove="removeScope" - @add="addEnvironment" - /> - </div> - <span - v-if="appliesToAllEnvironments" - class="gl-flex-gl-text-secondary gl-mt-2 gl-pl-5 gl-md-pl-0" + <label class="gl-display-block" :for="environmentsDropdownId">{{ + $options.i18n.environmentsLabel + }}</label> + <div class="gl-display-flex gl-flex-direction-column"> + <div + class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-md-align-items-center" + > + <new-environments-dropdown + :id="environmentsDropdownId" + class="gl-mr-3" + @add="addEnvironment" + /> + <span v-if="appliesToAllEnvironments" class="text-secondary gl-mt-3 mt-md-0 ml-md-3"> + {{ $options.i18n.allEnvironments }} + </span> + <div v-else class="gl-display-flex gl-align-items-center gl-flex-wrap"> + <gl-token + v-for="environment in filteredEnvironments" + :key="environment.id" + class="gl-mt-3 gl-mr-3 gl-mb-3 mt-md-0 mr-md-0 ml-md-2 rounded-pill" + @close="removeScope(environment)" > - {{ $options.i18n.allEnvironments }} - </span> + {{ environment.environmentScope }} + </gl-token> </div> </div> - <template #description> - {{ $options.i18n.environmentsSelectDescription }} - <gl-link :href="environmentsScopeDocsPath" target="_blank"> - <gl-icon name="question" /> - </gl-link> - </template> - </gl-form-group> + </div> + <span class="gl-display-inline-block gl-py-3"> + {{ $options.i18n.environmentsSelectDescription }} + </span> + <gl-link :href="environmentsScopeDocsPath" target="_blank"> + <gl-icon name="question" /> + </gl-link> </div> </div> </template> |