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-10-05 21:08:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-05 21:08:51 +0300
commitec18750aa8538712b952b8265581fc3b3e037923 (patch)
tree7eaf59fe40401415fde3c994bffae0031e2ffd23 /app/assets/javascripts/feature_flags
parent61265b9f01c7db3d4f6e1266d165b1c85be7b9e7 (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/feature_flags_table.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/form.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/default.vue10
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue63
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue22
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue68
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/users_with_id.vue47
-rw-r--r--app/assets/javascripts/feature_flags/components/strategy.vue188
-rw-r--r--app/assets/javascripts/feature_flags/components/strategy_parameters.vue51
-rw-r--r--app/assets/javascripts/feature_flags/constants.js21
-rw-r--r--app/assets/javascripts/feature_flags/store/modules/helpers.js2
-rw-r--r--app/assets/javascripts/feature_flags/utils.js2
12 files changed, 313 insertions, 165 deletions
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags_table.vue b/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
index 7881ae523fc..c4e2be50d34 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
@@ -3,7 +3,7 @@ import { GlBadge, GlButton, GlTooltipDirective, GlModal, GlToggle, GlIcon } from
import { sprintf, s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { ROLLOUT_STRATEGY_PERCENT_ROLLOUT, NEW_VERSION_FLAG, LEGACY_FLAG } from '../constants';
-import labelForStrategy from '../utils';
+import { labelForStrategy } from '../utils';
export default {
components: {
diff --git a/app/assets/javascripts/feature_flags/components/form.vue b/app/assets/javascripts/feature_flags/components/form.vue
index 04bea2d80d4..8d065933316 100644
--- a/app/assets/javascripts/feature_flags/components/form.vue
+++ b/app/assets/javascripts/feature_flags/components/form.vue
@@ -477,7 +477,7 @@ export default {
<label class="sr-only" :for="rolloutPercentageId(index)">
{{ s__('FeatureFlags|Rollout Percentage') }}
</label>
- <div class="w-3rem">
+ <div class="gl-w-9">
<input
:id="rolloutPercentageId(index)"
v-model="scope.rolloutPercentage"
diff --git a/app/assets/javascripts/feature_flags/components/strategies/default.vue b/app/assets/javascripts/feature_flags/components/strategies/default.vue
new file mode 100644
index 00000000000..cb8ffbddfbd
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/components/strategies/default.vue
@@ -0,0 +1,10 @@
+<script>
+export default {
+ mounted() {
+ this.$emit('change', { parameters: {} });
+ },
+ render() {
+ return this.$slots.default;
+ },
+};
+</script>
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
new file mode 100644
index 00000000000..b13bd86e900
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
@@ -0,0 +1,63 @@
+<script>
+import { GlFormSelect } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import ParameterFormGroup from './parameter_form_group.vue';
+
+export default {
+ components: {
+ GlFormSelect,
+ ParameterFormGroup,
+ },
+ props: {
+ strategy: {
+ required: true,
+ type: Object,
+ },
+ userLists: {
+ required: false,
+ type: Array,
+ default: () => [],
+ },
+ },
+ translations: {
+ rolloutUserListLabel: s__('FeatureFlag|List'),
+ rolloutUserListDescription: s__('FeatureFlag|Select a user list'),
+ rolloutUserListNoListError: s__('FeatureFlag|There are no configured user lists'),
+ },
+ computed: {
+ userListOptions() {
+ return this.userLists.map(({ name, id }) => ({ value: id, text: name }));
+ },
+ hasUserLists() {
+ return this.userListOptions.length > 0;
+ },
+ userListId() {
+ return this.strategy?.userListId ?? '';
+ },
+ },
+ methods: {
+ onUserListChange(list) {
+ this.$emit('change', {
+ userListId: list,
+ });
+ },
+ },
+};
+</script>
+<template>
+ <parameter-form-group
+ :state="hasUserLists"
+ :invalid-feedback="$options.translations.rolloutUserListNoListError"
+ :label="$options.translations.rolloutUserListLabel"
+ :description="$options.translations.rolloutUserListDescription"
+ >
+ <template #default="{ inputId }">
+ <gl-form-select
+ :id="inputId"
+ :value="userListId"
+ :options="userListOptions"
+ @change="onUserListChange"
+ />
+ </template>
+ </parameter-form-group>
+</template>
diff --git a/app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue b/app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue
new file mode 100644
index 00000000000..7f2c6d55db8
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue
@@ -0,0 +1,22 @@
+<script>
+import { uniqueId } from 'lodash';
+import { GlFormGroup } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlFormGroup,
+ },
+ props: {
+ inputId: {
+ required: false,
+ type: String,
+ default: () => uniqueId('feature_flag_strategies_'),
+ },
+ },
+};
+</script>
+<template>
+ <gl-form-group :label-for="inputId" v-bind="$attrs">
+ <slot v-bind="{ inputId }"></slot>
+ </gl-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
new file mode 100644
index 00000000000..9311589c364
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/components/strategies/percent_rollout.vue
@@ -0,0 +1,68 @@
+<script>
+import { GlFormInput } from '@gitlab/ui';
+import { s__, __ } from '~/locale';
+import { PERCENT_ROLLOUT_GROUP_ID } from '../../constants';
+import ParameterFormGroup from './parameter_form_group.vue';
+
+export default {
+ components: {
+ GlFormInput,
+ ParameterFormGroup,
+ },
+ props: {
+ strategy: {
+ required: true,
+ type: Object,
+ },
+ },
+ translations: {
+ rolloutPercentageDescription: __('Enter a whole number between 0 and 100'),
+ rolloutPercentageInvalid: s__(
+ 'FeatureFlags|Percent rollout must be a whole number between 0 and 100',
+ ),
+ rolloutPercentageLabel: s__('FeatureFlag|Percentage'),
+ },
+ computed: {
+ isValid() {
+ return Number(this.percentage) >= 0 && Number(this.percentage) <= 100;
+ },
+ percentage() {
+ return this.strategy?.parameters?.percentage ?? '';
+ },
+ },
+ methods: {
+ onPercentageChange(value) {
+ this.$emit('change', {
+ parameters: {
+ percentage: value,
+ groupId: PERCENT_ROLLOUT_GROUP_ID,
+ },
+ });
+ },
+ },
+};
+</script>
+<template>
+ <parameter-form-group
+ :label="$options.translations.rolloutPercentageLabel"
+ :description="$options.translations.rolloutPercentageDescription"
+ :invalid-feedback="$options.translations.rolloutPercentageInvalid"
+ :state="isValid"
+ >
+ <template #default="{ inputId }">
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-form-input
+ :id="inputId"
+ :value="percentage"
+ :state="isValid"
+ class="rollout-percentage gl-text-right gl-w-9"
+ type="number"
+ min="0"
+ max="100"
+ @input="onPercentageChange"
+ />
+ <span class="gl-ml-2">%</span>
+ </div>
+ </template>
+ </parameter-form-group>
+</template>
diff --git a/app/assets/javascripts/feature_flags/components/strategies/users_with_id.vue b/app/assets/javascripts/feature_flags/components/strategies/users_with_id.vue
new file mode 100644
index 00000000000..094127fb710
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/components/strategies/users_with_id.vue
@@ -0,0 +1,47 @@
+<script>
+import { GlFormTextarea } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+
+import ParameterFormGroup from './parameter_form_group.vue';
+
+export default {
+ components: {
+ ParameterFormGroup,
+ GlFormTextarea,
+ },
+ props: {
+ strategy: {
+ required: true,
+ type: Object,
+ },
+ },
+ translations: {
+ rolloutUserIdsDescription: __('Enter one or more user ID separated by commas'),
+ rolloutUserIdsLabel: s__('FeatureFlag|User IDs'),
+ },
+ computed: {
+ userIds() {
+ return this.strategy?.parameters?.userIds ?? '';
+ },
+ },
+ methods: {
+ onUserIdsChange(value) {
+ this.$emit('change', {
+ parameters: {
+ userIds: value,
+ },
+ });
+ },
+ },
+};
+</script>
+<template>
+ <parameter-form-group
+ :label="$options.translations.rolloutUserIdsLabel"
+ :description="$options.translations.rolloutUserIdsDescription"
+ >
+ <template #default="{ inputId }">
+ <gl-form-textarea :id="inputId" :value="userIds" @input="onUserIdsChange" />
+ </template>
+ </parameter-form-group>
+</template>
diff --git a/app/assets/javascripts/feature_flags/components/strategy.vue b/app/assets/javascripts/feature_flags/components/strategy.vue
index 3f10ec00aa5..c83e2c897e3 100644
--- a/app/assets/javascripts/feature_flags/components/strategy.vue
+++ b/app/assets/javascripts/feature_flags/components/strategy.vue
@@ -1,42 +1,23 @@
<script>
import Vue from 'vue';
import { isNumber } from 'lodash';
-import {
- GlButton,
- GlFormSelect,
- GlFormInput,
- GlFormTextarea,
- GlFormGroup,
- GlIcon,
- GlLink,
- GlToken,
-} from '@gitlab/ui';
+import { GlButton, GlFormSelect, GlFormGroup, GlIcon, GlLink, GlToken } from '@gitlab/ui';
import { s__, __ } from '~/locale';
-import {
- PERCENT_ROLLOUT_GROUP_ID,
- ROLLOUT_STRATEGY_ALL_USERS,
- ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
- ROLLOUT_STRATEGY_USER_ID,
- ROLLOUT_STRATEGY_GITLAB_USER_LIST,
-} from '../constants';
+import { EMPTY_PARAMETERS, STRATEGY_SELECTIONS } from '../constants';
import NewEnvironmentsDropdown from './new_environments_dropdown.vue';
+import StrategyParameters from './strategy_parameters.vue';
export default {
components: {
GlButton,
GlFormGroup,
- GlFormInput,
- GlFormTextarea,
GlFormSelect,
GlIcon,
GlLink,
GlToken,
NewEnvironmentsDropdown,
- },
- model: {
- prop: 'strategy',
- event: 'change',
+ StrategyParameters,
},
inject: {
strategyTypeDocsPagePath: {
@@ -66,86 +47,35 @@ export default {
default: () => [],
},
},
- ROLLOUT_STRATEGY_ALL_USERS,
- ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
- ROLLOUT_STRATEGY_USER_ID,
- ROLLOUT_STRATEGY_GITLAB_USER_LIST,
i18n: {
allEnvironments: __('All environments'),
environmentsLabel: __('Environments'),
- environmentsSelectDescription: __('Select the environment scope for this feature flag.'),
- rolloutPercentageDescription: __('Enter a whole number between 0 and 100'),
- rolloutPercentageInvalid: s__(
- 'FeatureFlags|Percent rollout must be a whole number between 0 and 100',
- ),
- rolloutPercentageLabel: s__('FeatureFlag|Percentage'),
- rolloutUserIdsDescription: __('Enter one or more user ID separated by commas'),
- rolloutUserIdsLabel: s__('FeatureFlag|User IDs'),
rolloutUserListLabel: s__('FeatureFlag|List'),
rolloutUserListDescription: s__('FeatureFlag|Select a user list'),
rolloutUserListNoListError: s__('FeatureFlag|There are no configured user lists'),
strategyTypeDescription: __('Select strategy activation method.'),
strategyTypeLabel: s__('FeatureFlag|Type'),
+ environmentsSelectDescription: s__(
+ 'FeatureFlag|Select the environment scope for this feature flag.',
+ ),
},
+ strategies: STRATEGY_SELECTIONS,
+
data() {
return {
environments: this.strategy.scopes || [],
formStrategy: { ...this.strategy },
- formPercentage:
- this.strategy.name === ROLLOUT_STRATEGY_PERCENT_ROLLOUT
- ? this.strategy.parameters.percentage
- : '',
- formUserIds:
- this.strategy.name === ROLLOUT_STRATEGY_USER_ID ? this.strategy.parameters.userIds : '',
- formUserListId:
- this.strategy.name === ROLLOUT_STRATEGY_GITLAB_USER_LIST ? this.strategy.userListId : '',
- strategies: [
- {
- value: ROLLOUT_STRATEGY_ALL_USERS,
- text: __('All users'),
- },
- {
- value: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
- text: __('Percent of users'),
- },
- {
- value: ROLLOUT_STRATEGY_USER_ID,
- text: __('User IDs'),
- },
- {
- value: ROLLOUT_STRATEGY_GITLAB_USER_LIST,
- text: __('User List'),
- },
- ],
};
},
computed: {
strategyTypeId() {
return `strategy-type-${this.index}`;
},
- strategyPercentageId() {
- return `strategy-percentage-${this.index}`;
- },
- strategyUserIdsId() {
- return `strategy-user-ids-${this.index}`;
- },
- strategyUserListId() {
- return `strategy-user-list-${this.index}`;
- },
environmentsDropdownId() {
return `environments-dropdown-${this.index}`;
},
- isPercentRollout() {
- return this.isStrategyType(ROLLOUT_STRATEGY_PERCENT_ROLLOUT);
- },
- isUserWithId() {
- return this.isStrategyType(ROLLOUT_STRATEGY_USER_ID);
- },
- isUserList() {
- return this.isStrategyType(ROLLOUT_STRATEGY_GITLAB_USER_LIST);
- },
appliesToAllEnvironments() {
return (
this.filteredEnvironments.length === 1 &&
@@ -155,12 +85,6 @@ export default {
filteredEnvironments() {
return this.environments.filter(e => !e.shouldBeDestroyed);
},
- userListOptions() {
- return this.userLists.map(({ name, id }) => ({ value: id, text: name }));
- },
- hasUserLists() {
- return this.userListOptions.length > 0;
- },
},
methods: {
addEnvironment(environment) {
@@ -169,33 +93,19 @@ export default {
allEnvironmentsScope.shouldBeDestroyed = true;
}
this.environments.push({ environmentScope: environment });
- this.onStrategyChange();
+ this.onStrategyChange({ ...this.formStrategy, scopes: this.environments });
},
- onStrategyChange() {
- const parameters = {};
- const strategy = {
+ onStrategyTypeChange(name) {
+ this.onStrategyChange({
...this.formStrategy,
- scopes: this.environments,
- };
- switch (this.formStrategy.name) {
- case ROLLOUT_STRATEGY_PERCENT_ROLLOUT:
- parameters.percentage = this.formPercentage;
- parameters.groupId = PERCENT_ROLLOUT_GROUP_ID;
- break;
- case ROLLOUT_STRATEGY_USER_ID:
- parameters.userIds = this.formUserIds;
- break;
- case ROLLOUT_STRATEGY_GITLAB_USER_LIST:
- strategy.userListId = this.formUserListId;
- break;
- default:
- break;
- }
- this.$emit('change', {
- ...strategy,
- parameters,
+ ...EMPTY_PARAMETERS,
+ name,
});
},
+ onStrategyChange(s) {
+ this.$emit('change', s);
+ this.formStrategy = s;
+ },
removeScope(environment) {
if (isNumber(environment.id)) {
Vue.set(environment, 'shouldBeDestroyed', true);
@@ -205,10 +115,7 @@ export default {
if (this.filteredEnvironments.length === 0) {
this.environments.push({ environmentScope: '*' });
}
- this.onStrategyChange();
- },
- isStrategyType(type) {
- return this.formStrategy.name === type;
+ this.onStrategyChange({ ...this.formStrategy, scopes: this.environments });
},
},
};
@@ -224,60 +131,19 @@ export default {
</gl-link>
<gl-form-select
:id="strategyTypeId"
- v-model="formStrategy.name"
- :options="strategies"
- @change="onStrategyChange"
+ :value="formStrategy.name"
+ :options="$options.strategies"
+ @change="onStrategyTypeChange"
/>
</gl-form-group>
</div>
<div data-testid="strategy">
- <gl-form-group
- v-if="isPercentRollout"
- :label="$options.i18n.rolloutPercentageLabel"
- :description="$options.i18n.rolloutPercentageDescription"
- :label-for="strategyPercentageId"
- :invalid-feedback="$options.i18n.rolloutPercentageInvalid"
- >
- <div class="gl-display-flex gl-align-items-center">
- <gl-form-input
- :id="strategyPercentageId"
- v-model="formPercentage"
- class="rollout-percentage gl-text-right gl-w-9"
- type="number"
- @input="onStrategyChange"
- />
- <span class="gl-ml-2">%</span>
- </div>
- </gl-form-group>
-
- <gl-form-group
- v-if="isUserWithId"
- :label="$options.i18n.rolloutUserIdsLabel"
- :description="$options.i18n.rolloutUserIdsDescription"
- :label-for="strategyUserIdsId"
- >
- <gl-form-textarea
- :id="strategyUserIdsId"
- v-model="formUserIds"
- @input="onStrategyChange"
- />
- </gl-form-group>
- <gl-form-group
- v-if="isUserList"
- :state="hasUserLists"
- :invalid-feedback="$options.i18n.rolloutUserListNoListError"
- :label="$options.i18n.rolloutUserListLabel"
- :description="$options.i18n.rolloutUserListDescription"
- :label-for="strategyUserListId"
- >
- <gl-form-select
- :id="strategyUserListId"
- v-model="formUserListId"
- :options="userListOptions"
- @change="onStrategyChange"
- />
- </gl-form-group>
+ <strategy-parameters
+ :strategy="strategy"
+ :user-lists="userLists"
+ @change="onStrategyChange"
+ />
</div>
<div
diff --git a/app/assets/javascripts/feature_flags/components/strategy_parameters.vue b/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
new file mode 100644
index 00000000000..6953095daff
--- /dev/null
+++ b/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
@@ -0,0 +1,51 @@
+<script>
+import {
+ ROLLOUT_STRATEGY_ALL_USERS,
+ ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ ROLLOUT_STRATEGY_USER_ID,
+ ROLLOUT_STRATEGY_GITLAB_USER_LIST,
+} from '../constants';
+
+import Default from './strategies/default.vue';
+import PercentRollout from './strategies/percent_rollout.vue';
+import UsersWithId from './strategies/users_with_id.vue';
+import GitlabUserList from './strategies/gitlab_user_list.vue';
+
+const STRATEGIES = Object.freeze({
+ [ROLLOUT_STRATEGY_ALL_USERS]: Default,
+ [ROLLOUT_STRATEGY_PERCENT_ROLLOUT]: PercentRollout,
+ [ROLLOUT_STRATEGY_USER_ID]: UsersWithId,
+ [ROLLOUT_STRATEGY_GITLAB_USER_LIST]: GitlabUserList,
+});
+
+export default {
+ props: {
+ strategy: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ strategyComponent() {
+ return STRATEGIES[(this.strategy?.name)];
+ },
+ },
+ methods: {
+ onChange(value) {
+ this.$emit('change', {
+ ...this.strategy,
+ ...value,
+ });
+ },
+ },
+};
+</script>
+<template>
+ <component
+ :is="strategyComponent"
+ v-if="strategyComponent"
+ :strategy="strategy"
+ v-bind="$attrs"
+ @change="onChange"
+ />
+</template>
diff --git a/app/assets/javascripts/feature_flags/constants.js b/app/assets/javascripts/feature_flags/constants.js
index f59414ab1a7..79bd6d8fe43 100644
--- a/app/assets/javascripts/feature_flags/constants.js
+++ b/app/assets/javascripts/feature_flags/constants.js
@@ -26,3 +26,24 @@ export const NEW_FLAG_ALERT = s__(
export const FEATURE_FLAG_SCOPE = 'featureFlags';
export const USER_LIST_SCOPE = 'userLists';
+
+export const EMPTY_PARAMETERS = { parameters: {}, userListId: undefined };
+
+export const STRATEGY_SELECTIONS = [
+ {
+ value: ROLLOUT_STRATEGY_ALL_USERS,
+ text: s__('FeatureFlags|All users'),
+ },
+ {
+ value: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
+ text: s__('FeatureFlags|Percent of users'),
+ },
+ {
+ value: ROLLOUT_STRATEGY_USER_ID,
+ text: s__('FeatureFlags|User IDs'),
+ },
+ {
+ value: ROLLOUT_STRATEGY_GITLAB_USER_LIST,
+ text: s__('FeatureFlags|User List'),
+ },
+];
diff --git a/app/assets/javascripts/feature_flags/store/modules/helpers.js b/app/assets/javascripts/feature_flags/store/modules/helpers.js
index 5a8d7bc6af3..bbde3cad7cd 100644
--- a/app/assets/javascripts/feature_flags/store/modules/helpers.js
+++ b/app/assets/javascripts/feature_flags/store/modules/helpers.js
@@ -182,7 +182,7 @@ export const mapStrategiesToViewModel = strategiesFromRails =>
const mapStrategiesParametersToRails = params => {
if (params.userIds) {
- return { ...params, userIds: params.userIds.split(', ').join(',') };
+ return { ...params, userIds: params.userIds.replace(/\s*,\s*/g, ',') };
}
return params;
};
diff --git a/app/assets/javascripts/feature_flags/utils.js b/app/assets/javascripts/feature_flags/utils.js
index 1017a3d0c2a..ccb6ac17792 100644
--- a/app/assets/javascripts/feature_flags/utils.js
+++ b/app/assets/javascripts/feature_flags/utils.js
@@ -30,7 +30,7 @@ const badgeTextByType = {
const scopeName = ({ environment_scope: scope }) =>
scope === ALL_ENVIRONMENTS_NAME ? s__('FeatureFlags|All Environments') : scope;
-export default strategy => {
+export const labelForStrategy = strategy => {
const { name, parameters } = badgeTextByType[strategy.name];
if (parameters) {