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>2020-11-19 11:27:35 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 11:27:35 +0300
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /app/assets/javascripts/feature_flags
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/feature_flags')
-rw-r--r--app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue50
-rw-r--r--app/assets/javascripts/feature_flags/components/edit_feature_flag.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/form.vue22
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue73
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue4
-rw-r--r--app/assets/javascripts/feature_flags/edit.js2
-rw-r--r--app/assets/javascripts/feature_flags/new.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/index.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js17
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js11
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js12
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js5
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js19
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js9
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js6
-rw-r--r--app/assets/javascripts/feature_flags/store/helpers.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/new/index.js4
19 files changed, 171 insertions, 83 deletions
diff --git a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
index 686399843dd..bf47d7cf7c0 100644
--- a/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
+++ b/app/assets/javascripts/feature_flags/components/configure_feature_flags_modal.vue
@@ -2,6 +2,7 @@
import {
GlFormGroup,
GlFormInput,
+ GlFormInputGroup,
GlModal,
GlTooltipDirective,
GlLoadingIcon,
@@ -17,6 +18,7 @@ export default {
components: {
GlFormGroup,
GlFormInput,
+ GlFormInputGroup,
GlModal,
ModalCopyButton,
GlIcon,
@@ -167,63 +169,47 @@ export default {
</template>
</gl-sprintf>
</callout>
- <div class="form-group">
- <label for="api_url" class="label-bold">{{ $options.translations.apiUrlLabelText }}</label>
- <div class="input-group">
- <input
- id="api_url"
- :value="unleashApiUrl"
- readonly
- class="form-control"
- type="text"
- name="api_url"
- />
- <span class="input-group-append">
+ <gl-form-group :label="$options.translations.apiUrlLabelText" label-for="api-url">
+ <gl-form-input-group id="api-url" :value="unleashApiUrl" readonly type="text" name="api-url">
+ <template #append>
<modal-copy-button
:text="unleashApiUrl"
:title="$options.translations.apiUrlCopyText"
:modal-id="modalId"
- class="input-group-text"
/>
- </span>
- </div>
- </div>
- <div class="form-group">
- <label for="instance_id" class="label-bold">{{
- $options.translations.instanceIdLabelText
- }}</label>
- <div class="input-group">
- <input
+ </template>
+ </gl-form-input-group>
+ </gl-form-group>
+ <gl-form-group :label="$options.translations.instanceIdLabelText" label-for="instance_id">
+ <gl-form-input-group>
+ <gl-form-input
id="instance_id"
:value="instanceId"
- class="form-control"
type="text"
name="instance_id"
readonly
:disabled="isRotating"
/>
-
<gl-loading-icon
v-if="isRotating"
- class="position-absolute align-self-center instance-id-loading-icon"
+ class="gl-absolute gl-align-self-center gl-right-5 gl-mr-7"
/>
- <div class="input-group-append">
+ <template #append>
<modal-copy-button
:text="instanceId"
:title="$options.translations.instanceIdCopyText"
:modal-id="modalId"
:disabled="isRotating"
- class="input-group-text"
/>
- </div>
- </div>
- </div>
+ </template>
+ </gl-form-input-group>
+ </gl-form-group>
<div
v-if="hasRotateError"
- class="text-danger d-flex align-items-center font-weight-normal mb-2"
+ class="gl-text-red-500 gl-display-flex gl-align-items-center gl-font-weight-normal gl-mb-3"
>
- <gl-icon name="warning" class="mr-1" />
+ <gl-icon name="warning" class="gl-mr-2" />
<span>{{ $options.translations.instanceIdRegenerateError }}</span>
</div>
<callout
diff --git a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
index 26b18f9bf5a..9ec65bb0b43 100644
--- a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
@@ -103,7 +103,7 @@ export default {
>
{{ $options.translations.newFlagAlert }}
</gl-alert>
- <gl-loading-icon v-if="isLoading" />
+ <gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" />
<template v-else-if="!isLoading && !hasError">
<gl-alert v-if="deprecatedAndEditable" variant="warning" :dismissible="false" class="gl-my-5">
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags.vue b/app/assets/javascripts/feature_flags/components/feature_flags.vue
index eb7046a3d9b..340cf68793f 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags.vue
@@ -278,7 +278,7 @@ export default {
/>
</feature-flags-tab>
<template #tabs-end>
- <div
+ <li
class="gl-display-none gl-display-md-flex gl-align-items-center gl-flex-fill-1 gl-justify-content-end"
>
<gl-button
@@ -313,7 +313,7 @@ export default {
>
{{ s__('FeatureFlags|New feature flag') }}
</gl-button>
- </div>
+ </li>
</template>
</gl-tabs>
</div>
diff --git a/app/assets/javascripts/feature_flags/components/form.vue b/app/assets/javascripts/feature_flags/components/form.vue
index 3c1944d91bd..36ebf893486 100644
--- a/app/assets/javascripts/feature_flags/components/form.vue
+++ b/app/assets/javascripts/feature_flags/components/form.vue
@@ -3,7 +3,7 @@ import Vue from 'vue';
import { memoize, isString, cloneDeep, isNumber, uniqueId } from 'lodash';
import {
GlButton,
- GlDeprecatedBadge as GlBadge,
+ GlBadge,
GlTooltip,
GlTooltipDirective,
GlFormTextarea,
@@ -11,10 +11,8 @@ import {
GlSprintf,
GlIcon,
} from '@gitlab/ui';
-import Api from '~/api';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import { s__ } from '~/locale';
-import { deprecatedCreateFlash as flash, FLASH_TYPES } from '~/flash';
import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import EnvironmentsDropdown from './environments_dropdown.vue';
@@ -89,7 +87,6 @@ export default {
},
},
inject: {
- projectId: {},
featureFlagIssuesEndpoint: {
default: '',
},
@@ -124,7 +121,6 @@ export default {
formStrategies: cloneDeep(this.strategies),
newScope: '',
- userLists: [],
};
},
computed: {
@@ -155,17 +151,6 @@ export default {
);
},
},
- mounted() {
- if (this.supportsStrategies) {
- Api.fetchFeatureFlagUserLists(this.projectId)
- .then(({ data }) => {
- this.userLists = data;
- })
- .catch(() => {
- flash(s__('FeatureFlags|There was an error retrieving user lists'), FLASH_TYPES.WARNING);
- });
- }
- },
methods: {
keyFor(strategy) {
if (strategy.id) {
@@ -346,7 +331,6 @@ export default {
:key="keyFor(strategy)"
:strategy="strategy"
:index="index"
- :user-lists="userLists"
@change="onFormStrategyChange($event, index)"
@delete="deleteStrategy(strategy)"
/>
@@ -488,7 +472,9 @@ export default {
:target="rolloutPercentageId(index)"
>
{{
- s__('FeatureFlags|Percent rollout must be a whole number between 0 and 100')
+ s__(
+ 'FeatureFlags|Percent rollout must be an integer number between 0 and 100',
+ )
}}
</gl-tooltip>
<span class="ml-1">%</span>
diff --git a/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue b/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue
index 020a0d43096..4daf8b4e6bf 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/flexible_rollout.vue
@@ -17,8 +17,8 @@ export default {
},
},
i18n: {
- percentageDescription: __('Enter a whole number between 0 and 100'),
- percentageInvalid: __('Percent rollout must be a whole number between 0 and 100'),
+ percentageDescription: __('Enter an integer number number between 0 and 100'),
+ percentageInvalid: __('Percent rollout must be an integer number between 0 and 100'),
percentageLabel: __('Percentage'),
stickinessDescription: __('Consistency guarantee method'),
stickinessLabel: __('Based on'),
diff --git a/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue b/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
index ec97e8b1350..6a57e9a8759 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
@@ -1,11 +1,20 @@
<script>
-import { GlFormSelect } from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { createNamespacedHelpers } from 'vuex';
+import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
import { s__ } from '~/locale';
import ParameterFormGroup from './parameter_form_group.vue';
+const { mapActions, mapGetters, mapState } = createNamespacedHelpers('userLists');
+
+const { fetchUserLists, setFilter } = mapActions(['fetchUserLists', 'setFilter']);
+
export default {
components: {
- GlFormSelect,
+ GlDropdown,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlSearchBoxByType,
ParameterFormGroup,
},
props: {
@@ -13,34 +22,40 @@ export default {
required: true,
type: Object,
},
- userLists: {
- required: false,
- type: Array,
- default: () => [],
- },
},
translations: {
- rolloutUserListLabel: s__('FeatureFlag|List'),
+ rolloutUserListLabel: s__('FeatureFlag|User List'),
rolloutUserListDescription: s__('FeatureFlag|Select a user list'),
rolloutUserListNoListError: s__('FeatureFlag|There are no configured user lists'),
+ defaultDropdownText: s__('FeatureFlags|No user list selected'),
},
computed: {
- userListOptions() {
- return this.userLists.map(({ name, id }) => ({ value: id, text: name }));
- },
- hasUserLists() {
- return this.userListOptions.length > 0;
- },
+ ...mapGetters(['hasUserLists', 'isLoading', 'hasError', 'userListOptions']),
+ ...mapState(['filter', 'userLists']),
userListId() {
- return this.strategy?.userListId ?? '';
+ return this.strategy?.userList?.id ?? '';
},
+ dropdownText() {
+ return this.strategy?.userList?.name ?? this.$options.translations.defaultDropdownText;
+ },
+ },
+ mounted() {
+ fetchUserLists.apply(this);
},
methods: {
+ setFilter: debounce(setFilter, 250),
+ fetchUserLists: debounce(fetchUserLists, 250),
onUserListChange(list) {
this.$emit('change', {
- userListId: list,
+ userList: list,
});
},
+ isSelectedUserList({ id }) {
+ return id === this.userListId;
+ },
+ setFocus() {
+ this.$refs.searchBox.focusInput();
+ },
},
};
</script>
@@ -52,12 +67,26 @@ export default {
:description="hasUserLists ? $options.translations.rolloutUserListDescription : ''"
>
<template #default="{ inputId }">
- <gl-form-select
- :id="inputId"
- :value="userListId"
- :options="userListOptions"
- @change="onUserListChange"
- />
+ <gl-dropdown :id="inputId" :text="dropdownText" @shown="setFocus">
+ <gl-search-box-by-type
+ ref="searchBox"
+ class="gl-m-3"
+ :value="filter"
+ @input="setFilter"
+ @focus="fetchUserLists"
+ @keyup="fetchUserLists"
+ />
+ <gl-loading-icon v-if="isLoading" />
+ <gl-dropdown-item
+ v-for="list in userLists"
+ :key="list.id"
+ :is-checked="isSelectedUserList(list)"
+ is-check-item
+ @click="onUserListChange(list)"
+ >
+ {{ list.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
</template>
</parameter-form-group>
</template>
diff --git a/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue b/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue
index d262769c891..91e1b85d66e 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue
@@ -16,9 +16,9 @@ export default {
},
},
i18n: {
- rolloutPercentageDescription: __('Enter a whole number between 0 and 100'),
+ rolloutPercentageDescription: __('Enter an integer number between 0 and 100'),
rolloutPercentageInvalid: s__(
- 'FeatureFlags|Percent rollout must be a whole number between 0 and 100',
+ 'FeatureFlags|Percent rollout must be an integer number between 0 and 100',
),
rolloutPercentageLabel: s__('FeatureFlag|Percentage'),
},
diff --git a/app/assets/javascripts/feature_flags/edit.js b/app/assets/javascripts/feature_flags/edit.js
index b4d2111acf3..05a9bbce654 100644
--- a/app/assets/javascripts/feature_flags/edit.js
+++ b/app/assets/javascripts/feature_flags/edit.js
@@ -22,7 +22,7 @@ export default () => {
} = el.dataset;
return new Vue({
- store: createStore({ endpoint, path: featureFlagsPath }),
+ store: createStore({ endpoint, projectId, path: featureFlagsPath }),
el,
provide: {
environmentsScopeDocsPath,
diff --git a/app/assets/javascripts/feature_flags/new.js b/app/assets/javascripts/feature_flags/new.js
index a1efbd87ec4..8e18213cc03 100644
--- a/app/assets/javascripts/feature_flags/new.js
+++ b/app/assets/javascripts/feature_flags/new.js
@@ -22,7 +22,7 @@ export default () => {
return new Vue({
el,
- store: createStore({ endpoint, path: featureFlagsPath }),
+ store: createStore({ endpoint, projectId, path: featureFlagsPath }),
provide: {
environmentsScopeDocsPath,
strategyTypeDocsPagePath,
diff --git a/app/assets/javascripts/feature_flags/store/edit/index.js b/app/assets/javascripts/feature_flags/store/edit/index.js
index f737e0517fc..81edc791924 100644
--- a/app/assets/javascripts/feature_flags/store/edit/index.js
+++ b/app/assets/javascripts/feature_flags/store/edit/index.js
@@ -1,4 +1,5 @@
import Vuex from 'vuex';
+import userLists from '../gitlab_user_list';
import state from './state';
import * as actions from './actions';
import mutations from './mutations';
@@ -8,4 +9,7 @@ export default data =>
actions,
mutations,
state: state(data),
+ modules: {
+ userLists: userLists(data),
+ },
});
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js
new file mode 100644
index 00000000000..d4587713fed
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/actions.js
@@ -0,0 +1,17 @@
+import Api from '~/api';
+import * as types from './mutation_types';
+
+const getErrorMessages = error => [].concat(error?.response?.data?.message ?? error.message);
+
+export const fetchUserLists = ({ commit, state: { filter, projectId } }) => {
+ commit(types.FETCH_USER_LISTS);
+
+ return Api.searchFeatureFlagUserLists(projectId, filter)
+ .then(({ data }) => commit(types.RECEIVE_USER_LISTS_SUCCESS, data))
+ .catch(error => commit(types.RECEIVE_USER_LISTS_ERROR, getErrorMessages(error)));
+};
+
+export const setFilter = ({ commit, dispatch }, filter) => {
+ commit(types.SET_FILTER, filter);
+ return dispatch('fetchUserLists');
+};
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js
new file mode 100644
index 00000000000..164b0980120
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/getters.js
@@ -0,0 +1,11 @@
+import statuses from './status';
+
+export const userListOptions = ({ userLists }) =>
+ userLists.map(({ name, id }) => ({ value: id, text: name }));
+
+export const hasUserLists = ({ userLists, status }) =>
+ [statuses.START, statuses.LOADING].indexOf(status) > -1 || userLists.length > 0;
+
+export const isLoading = ({ status }) => status === statuses.LOADING;
+
+export const hasError = ({ status }) => status === statuses.ERROR;
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js
new file mode 100644
index 00000000000..d25b574981f
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js
@@ -0,0 +1,12 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+import * as getters from './getters';
+
+export default data => ({
+ state: state(data),
+ actions,
+ getters,
+ mutations,
+ namespaced: true,
+});
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js
new file mode 100644
index 00000000000..0fe12f06785
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutation_types.js
@@ -0,0 +1,5 @@
+export const FETCH_USER_LISTS = 'FETCH_USER_LISTS';
+export const RECEIVE_USER_LISTS_SUCCESS = 'RECEIVE_USER_LISTS_SUCCESS';
+export const RECEIVE_USER_LISTS_ERROR = 'RECEIVE_USER_LISTS_ERROR';
+
+export const SET_FILTER = 'SET_FILTER';
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js
new file mode 100644
index 00000000000..bd7c6f68009
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js
@@ -0,0 +1,19 @@
+import statuses from './status';
+import * as types from './mutation_types';
+
+export default {
+ [types.FETCH_USER_LISTS](state) {
+ state.status = statuses.LOADING;
+ },
+ [types.RECEIVE_USER_LISTS_SUCCESS](state, lists) {
+ state.userLists = lists;
+ state.status = statuses.IDLE;
+ },
+ [types.RECEIVE_USER_LISTS_ERROR](state, error) {
+ state.error = error;
+ state.status = statuses.ERROR;
+ },
+ [types.SET_FILTER](state, filter) {
+ state.filter = filter;
+ },
+};
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js
new file mode 100644
index 00000000000..2664ec794fc
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/state.js
@@ -0,0 +1,9 @@
+import statuses from './status';
+
+export default ({ projectId }) => ({
+ projectId,
+ userLists: [],
+ filter: '',
+ status: statuses.START,
+ error: '',
+});
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js
new file mode 100644
index 00000000000..67f153eb58e
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/status.js
@@ -0,0 +1,6 @@
+export default {
+ START: 'START',
+ LOADING: 'LOADING',
+ IDLE: 'IDLE',
+ ERROR: 'ERROR',
+};
diff --git a/app/assets/javascripts/feature_flags/store/helpers.js b/app/assets/javascripts/feature_flags/store/helpers.js
index db6da815abf..d42e5c504db 100644
--- a/app/assets/javascripts/feature_flags/store/helpers.js
+++ b/app/assets/javascripts/feature_flags/store/helpers.js
@@ -174,7 +174,7 @@ export const mapStrategiesToViewModel = strategiesFromRails =>
id: s.id,
name: s.name,
parameters: mapStrategiesParametersToViewModel(s.parameters),
- userListId: s.user_list?.id,
+ userList: s.user_list,
// eslint-disable-next-line no-underscore-dangle
shouldBeDestroyed: Boolean(s._destroy),
scopes: mapStrategyScopesToView(s.scopes),
@@ -197,7 +197,7 @@ const mapStrategyToRails = strategy => {
};
if (strategy.name === ROLLOUT_STRATEGY_GITLAB_USER_LIST) {
- mappedStrategy.user_list_id = strategy.userListId;
+ mappedStrategy.user_list_id = strategy.userList.id;
}
return mappedStrategy;
};
diff --git a/app/assets/javascripts/feature_flags/store/new/index.js b/app/assets/javascripts/feature_flags/store/new/index.js
index f737e0517fc..81edc791924 100644
--- a/app/assets/javascripts/feature_flags/store/new/index.js
+++ b/app/assets/javascripts/feature_flags/store/new/index.js
@@ -1,4 +1,5 @@
import Vuex from 'vuex';
+import userLists from '../gitlab_user_list';
import state from './state';
import * as actions from './actions';
import mutations from './mutations';
@@ -8,4 +9,7 @@ export default data =>
actions,
mutations,
state: state(data),
+ modules: {
+ userLists: userLists(data),
+ },
});