Commit 304f8405 authored by Angelo Gulina's avatar Angelo Gulina Committed by Nicolò Maria Mezzopera

Add docs links to Feature Flags strategy settings

parent 0a020f7a
...@@ -11,4 +11,6 @@ ...@@ -11,4 +11,6 @@
user_callouts_path: user_callouts_path, user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION, user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION,
show_user_callout: show_feature_flags_new_version?.to_s, show_user_callout: show_feature_flags_new_version?.to_s,
strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'),
feature_flag_issues_endpoint: feature_flag_issues_links_endpoint(@project, @feature_flag, current_user) } } feature_flag_issues_endpoint: feature_flag_issues_links_endpoint(@project, @feature_flag, current_user) } }
...@@ -9,4 +9,6 @@ ...@@ -9,4 +9,6 @@
user_callouts_path: user_callouts_path, user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION, user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION,
show_user_callout: show_feature_flags_new_version?.to_s, show_user_callout: show_feature_flags_new_version?.to_s,
strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'),
project_id: @project.id } } project_id: @project.id } }
...@@ -107,7 +107,7 @@ export default { ...@@ -107,7 +107,7 @@ export default {
), ),
newHelpText: s__( newHelpText: s__(
'FeatureFlags|Enable features for specific users and specific environments by defining feature flag strategies.', 'FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies.',
), ),
noStrategiesText: s__('FeatureFlags|Feature Flag has no strategies'), noStrategiesText: s__('FeatureFlags|Feature Flag has no strategies'),
}, },
......
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
import Vue from 'vue'; import Vue from 'vue';
import { isNumber } from 'lodash'; import { isNumber } from 'lodash';
import { import {
GlButton,
GlFormSelect, GlFormSelect,
GlFormInput, GlFormInput,
GlFormTextarea, GlFormTextarea,
GlFormGroup, GlFormGroup,
GlIcon,
GlLink,
GlToken, GlToken,
GlButton,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import { import {
...@@ -22,18 +24,28 @@ import NewEnvironmentsDropdown from './new_environments_dropdown.vue'; ...@@ -22,18 +24,28 @@ import NewEnvironmentsDropdown from './new_environments_dropdown.vue';
export default { export default {
components: { components: {
GlButton,
GlFormGroup, GlFormGroup,
GlFormInput, GlFormInput,
GlFormTextarea, GlFormTextarea,
GlFormSelect, GlFormSelect,
GlIcon,
GlLink,
GlToken, GlToken,
GlButton,
NewEnvironmentsDropdown, NewEnvironmentsDropdown,
}, },
model: { model: {
prop: 'strategy', prop: 'strategy',
event: 'change', event: 'change',
}, },
inject: {
strategyTypeDocsPagePath: {
type: String,
},
environmentsScopeDocsPath: {
type: String,
},
},
props: { props: {
strategy: { strategy: {
type: Object, type: Object,
...@@ -59,9 +71,10 @@ export default { ...@@ -59,9 +71,10 @@ export default {
ROLLOUT_STRATEGY_USER_ID, ROLLOUT_STRATEGY_USER_ID,
ROLLOUT_STRATEGY_GITLAB_USER_LIST, ROLLOUT_STRATEGY_GITLAB_USER_LIST,
translations: { i18n: {
allEnvironments: __('All environments'), allEnvironments: __('All environments'),
environmentsLabel: __('Environments'), environmentsLabel: __('Environments'),
environmentsSelectDescription: __('Select the environment scope for this feature flag.'),
rolloutPercentageDescription: __('Enter a whole number between 0 and 100'), rolloutPercentageDescription: __('Enter a whole number between 0 and 100'),
rolloutPercentageInvalid: s__( rolloutPercentageInvalid: s__(
'FeatureFlags|Percent rollout must be a whole number between 0 and 100', 'FeatureFlags|Percent rollout must be a whole number between 0 and 100',
...@@ -72,7 +85,7 @@ export default { ...@@ -72,7 +85,7 @@ export default {
rolloutUserListLabel: s__('FeatureFlag|List'), rolloutUserListLabel: s__('FeatureFlag|List'),
rolloutUserListDescription: s__('FeatureFlag|Select a user list'), rolloutUserListDescription: s__('FeatureFlag|Select a user list'),
rolloutUserListNoListError: s__('FeatureFlag|There are no configured user lists'), rolloutUserListNoListError: s__('FeatureFlag|There are no configured user lists'),
strategyTypeDescription: __('Select strategy activation method'), strategyTypeDescription: __('Select strategy activation method.'),
strategyTypeLabel: s__('FeatureFlag|Type'), strategyTypeLabel: s__('FeatureFlag|Type'),
}, },
...@@ -199,14 +212,14 @@ export default { ...@@ -199,14 +212,14 @@ export default {
}; };
</script> </script>
<template> <template>
<div class="border-top py-4"> <div class="gl-border-t-solid gl-border-t-1 gl-border-t-gray-100 gl-py-6">
<div class="flex flex-column flex-md-row flex-md-wrap"> <div class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row flex-md-wrap">
<div class="mr-5"> <div class="mr-5">
<gl-form-group <gl-form-group :label="$options.i18n.strategyTypeLabel" :label-for="strategyTypeId">
:label="$options.translations.strategyTypeLabel" <p class="gl-display-inline-block ">{{ $options.i18n.strategyTypeDescription }}</p>
:description="$options.translations.strategyTypeDescription" <gl-link :href="strategyTypeDocsPagePath" target="_blank">
:label-for="strategyTypeId" <gl-icon name="question" />
> </gl-link>
<gl-form-select <gl-form-select
:id="strategyTypeId" :id="strategyTypeId"
v-model="formStrategy.name" v-model="formStrategy.name"
...@@ -219,27 +232,27 @@ export default { ...@@ -219,27 +232,27 @@ export default {
<div data-testid="strategy"> <div data-testid="strategy">
<gl-form-group <gl-form-group
v-if="isPercentRollout" v-if="isPercentRollout"
:label="$options.translations.rolloutPercentageLabel" :label="$options.i18n.rolloutPercentageLabel"
:description="$options.translations.rolloutPercentageDescription" :description="$options.i18n.rolloutPercentageDescription"
:label-for="strategyPercentageId" :label-for="strategyPercentageId"
:invalid-feedback="$options.translations.rolloutPercentageInvalid" :invalid-feedback="$options.i18n.rolloutPercentageInvalid"
> >
<div class="flex align-items-center"> <div class="gl-display-flex gl-align-items-center">
<gl-form-input <gl-form-input
:id="strategyPercentageId" :id="strategyPercentageId"
v-model="formPercentage" v-model="formPercentage"
class="rollout-percentage text-right w-3rem" class="rollout-percentage gl-text-right gl-w-9"
type="number" type="number"
@input="onStrategyChange" @input="onStrategyChange"
/> />
<span class="ml-1">%</span> <span class="gl-ml-2">%</span>
</div> </div>
</gl-form-group> </gl-form-group>
<gl-form-group <gl-form-group
v-if="isUserWithId" v-if="isUserWithId"
:label="$options.translations.rolloutUserIdsLabel" :label="$options.i18n.rolloutUserIdsLabel"
:description="$options.translations.rolloutUserIdsDescription" :description="$options.i18n.rolloutUserIdsDescription"
:label-for="strategyUserIdsId" :label-for="strategyUserIdsId"
> >
<gl-form-textarea <gl-form-textarea
...@@ -251,9 +264,9 @@ export default { ...@@ -251,9 +264,9 @@ export default {
<gl-form-group <gl-form-group
v-if="isUserList" v-if="isUserList"
:state="hasUserLists" :state="hasUserLists"
:invalid-feedback="$options.translations.rolloutUserListNoListError" :invalid-feedback="$options.i18n.rolloutUserListNoListError"
:label="$options.translations.rolloutUserListLabel" :label="$options.i18n.rolloutUserListLabel"
:description="$options.translations.rolloutUserListDescription" :description="$options.i18n.rolloutUserListDescription"
:label-for="strategyUserListId" :label-for="strategyUserListId"
> >
<gl-form-select <gl-form-select
...@@ -265,7 +278,9 @@ export default { ...@@ -265,7 +278,9 @@ export default {
</gl-form-group> </gl-form-group>
</div> </div>
<div class="align-self-end align-self-md-stretch order-first offset-md-0 order-md-0 ml-auto"> <div
class="align-self-end align-self-md-stretch order-first offset-md-0 order-md-0 gl-ml-auto"
>
<gl-button <gl-button
data-testid="delete-strategy-button" data-testid="delete-strategy-button"
variant="danger" variant="danger"
...@@ -274,23 +289,31 @@ export default { ...@@ -274,23 +289,31 @@ export default {
/> />
</div> </div>
</div> </div>
<div class="flex flex-column"> <label class="gl-display-block" :for="environmentsDropdownId">{{
<label :for="environmentsDropdownId">{{ $options.translations.environmentsLabel }}</label> $options.i18n.environmentsLabel
<div class="flex flex-column flex-md-row align-items-start align-items-md-center"> }}</label>
<p class="gl-display-inline-block">{{ $options.i18n.environmentsSelectDescription }}</p>
<gl-link :href="environmentsScopeDocsPath" target="_blank">
<gl-icon name="question" />
</gl-link>
<div class="gl-display-flex gl-flex-direction-column">
<div
class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row align-items-start gl-md-align-items-center"
>
<new-environments-dropdown <new-environments-dropdown
:id="environmentsDropdownId" :id="environmentsDropdownId"
:endpoint="endpoint" :endpoint="endpoint"
class="mr-2" class="gl-mr-3"
@add="addEnvironment" @add="addEnvironment"
/> />
<span v-if="appliesToAllEnvironments" class="text-secondary mt-2 mt-md-0 ml-md-3"> <span v-if="appliesToAllEnvironments" class="text-secondary gl-mt-3 mt-md-0 ml-md-3">
{{ $options.translations.allEnvironments }} {{ $options.i18n.allEnvironments }}
</span> </span>
<div v-else class="flex align-items-center"> <div v-else class="gl-display-flex gl-align-items-center">
<gl-token <gl-token
v-for="environment in filteredEnvironments" v-for="environment in filteredEnvironments"
:key="environment.id" :key="environment.id"
class="mt-2 mr-2 mt-md-0 mr-md-0 ml-md-2 rounded-pill" class="gl-mt-3 gl-mr-3 mt-md-0 mr-md-0 ml-md-2 rounded-pill"
@close="removeScope(environment)" @close="removeScope(environment)"
> >
{{ environment.environmentScope }} {{ environment.environmentScope }}
......
...@@ -4,12 +4,17 @@ import { parseBoolean } from '~/lib/utils/common_utils'; ...@@ -4,12 +4,17 @@ import { parseBoolean } from '~/lib/utils/common_utils';
export default () => { export default () => {
const el = document.querySelector('#js-edit-feature-flag'); const el = document.querySelector('#js-edit-feature-flag');
const { environmentsScopeDocsPath, strategyTypeDocsPagePath } = el.dataset;
return new Vue({ return new Vue({
el, el,
components: { components: {
EditFeatureFlag, EditFeatureFlag,
}, },
provide: {
environmentsScopeDocsPath,
strategyTypeDocsPagePath,
},
render(createElement) { render(createElement) {
return createElement('edit-feature-flag', { return createElement('edit-feature-flag', {
props: { props: {
......
...@@ -4,12 +4,17 @@ import { parseBoolean } from '~/lib/utils/common_utils'; ...@@ -4,12 +4,17 @@ import { parseBoolean } from '~/lib/utils/common_utils';
export default () => { export default () => {
const el = document.querySelector('#js-new-feature-flag'); const el = document.querySelector('#js-new-feature-flag');
const { environmentsScopeDocsPath, strategyTypeDocsPagePath } = el.dataset;
return new Vue({ return new Vue({
el, el,
components: { components: {
NewFeatureFlag, NewFeatureFlag,
}, },
provide: {
environmentsScopeDocsPath,
strategyTypeDocsPagePath,
},
render(createElement) { render(createElement) {
return createElement('new-feature-flag', { return createElement('new-feature-flag', {
props: { props: {
......
---
title: Add explanation text to FF create/edit sections
merge_request: 41910
author:
type: changed
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlFormSelect, GlFormTextarea, GlFormInput, GlToken, GlButton } from '@gitlab/ui'; import { GlFormSelect, GlFormTextarea, GlFormInput, GlLink, GlToken, GlButton } from '@gitlab/ui';
import { import {
PERCENT_ROLLOUT_GROUP_ID, PERCENT_ROLLOUT_GROUP_ID,
ROLLOUT_STRATEGY_ALL_USERS, ROLLOUT_STRATEGY_ALL_USERS,
...@@ -12,10 +12,16 @@ import NewEnvironmentsDropdown from 'ee/feature_flags/components/new_environment ...@@ -12,10 +12,16 @@ import NewEnvironmentsDropdown from 'ee/feature_flags/components/new_environment
import { userList } from '../mock_data'; import { userList } from '../mock_data';
const provide = {
strategyTypeDocsPagePath: 'link-to-strategy-docs',
environmentsScopeDocsPath: 'link-scope-docs',
};
describe('Feature flags strategy', () => { describe('Feature flags strategy', () => {
let wrapper; let wrapper;
const findStrategy = () => wrapper.find('[data-testid="strategy"]'); const findStrategy = () => wrapper.find('[data-testid="strategy"]');
const findDocsLinks = () => wrapper.findAll(GlLink);
const factory = ( const factory = (
opts = { opts = {
...@@ -25,6 +31,7 @@ describe('Feature flags strategy', () => { ...@@ -25,6 +31,7 @@ describe('Feature flags strategy', () => {
endpoint: '', endpoint: '',
userLists: [userList], userLists: [userList],
}, },
provide,
}, },
) => { ) => {
if (wrapper) { if (wrapper) {
...@@ -41,6 +48,18 @@ describe('Feature flags strategy', () => { ...@@ -41,6 +48,18 @@ describe('Feature flags strategy', () => {
} }
}); });
describe('helper links', () => {
const propsData = { strategy: {}, index: 0, endpoint: '', userLists: [userList] };
factory({ propsData, provide });
it('should display 2 helper links', () => {
const links = findDocsLinks();
expect(links.exists()).toBe(true);
expect(links.at(0).attributes('href')).toContain('docs');
expect(links.at(1).attributes('href')).toContain('docs');
});
});
describe.each` describe.each`
name | parameter | value | newValue | input name | parameter | value | newValue | input
${ROLLOUT_STRATEGY_ALL_USERS} | ${null} | ${null} | ${null} | ${null} ${ROLLOUT_STRATEGY_ALL_USERS} | ${null} | ${null} | ${null} | ${null}
...@@ -56,7 +75,7 @@ describe('Feature flags strategy', () => { ...@@ -56,7 +75,7 @@ describe('Feature flags strategy', () => {
} }
strategy = { name, parameters }; strategy = { name, parameters };
propsData = { strategy, index: 0, endpoint: '' }; propsData = { strategy, index: 0, endpoint: '' };
factory({ propsData }); factory({ propsData, provide });
}); });
it('should set the select to match the strategy name', () => { it('should set the select to match the strategy name', () => {
...@@ -86,13 +105,14 @@ describe('Feature flags strategy', () => { ...@@ -86,13 +105,14 @@ describe('Feature flags strategy', () => {
}); });
} }
}); });
describe('with strategy gitlabUserList', () => { describe('with strategy gitlabUserList', () => {
let propsData; let propsData;
let strategy; let strategy;
beforeEach(() => { beforeEach(() => {
strategy = { name: ROLLOUT_STRATEGY_GITLAB_USER_LIST, userListId: '2', parameters: {} }; strategy = { name: ROLLOUT_STRATEGY_GITLAB_USER_LIST, userListId: '2', parameters: {} };
propsData = { strategy, index: 0, endpoint: '', userLists: [userList] }; propsData = { strategy, index: 0, endpoint: '', userLists: [userList] };
factory({ propsData }); factory({ propsData, provide });
}); });
it('should set the select to match the strategy name', () => { it('should set the select to match the strategy name', () => {
...@@ -150,7 +170,7 @@ describe('Feature flags strategy', () => { ...@@ -150,7 +170,7 @@ describe('Feature flags strategy', () => {
scopes: [{ environmentScope: '*' }], scopes: [{ environmentScope: '*' }],
}; };
const propsData = { strategy, index: 0, endpoint: '' }; const propsData = { strategy, index: 0, endpoint: '' };
factory({ propsData }); factory({ propsData, provide });
}); });
it('should change the parameters if a different strategy is chosen', () => { it('should change the parameters if a different strategy is chosen', () => {
...@@ -225,7 +245,7 @@ describe('Feature flags strategy', () => { ...@@ -225,7 +245,7 @@ describe('Feature flags strategy', () => {
scopes: [], scopes: [],
}; };
const propsData = { strategy, index: 0, endpoint: '' }; const propsData = { strategy, index: 0, endpoint: '' };
factory({ propsData }); factory({ propsData, provide });
}); });
it('should display selected scopes', () => { it('should display selected scopes', () => {
......
...@@ -10779,7 +10779,7 @@ msgstr "" ...@@ -10779,7 +10779,7 @@ msgstr ""
msgid "FeatureFlags|Edit User List" msgid "FeatureFlags|Edit User List"
msgstr "" msgstr ""
msgid "FeatureFlags|Enable features for specific users and specific environments by defining feature flag strategies." msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
msgstr "" msgstr ""
msgid "FeatureFlags|Environment Spec" msgid "FeatureFlags|Environment Spec"
...@@ -22656,7 +22656,7 @@ msgstr "" ...@@ -22656,7 +22656,7 @@ msgstr ""
msgid "Select status" msgid "Select status"
msgstr "" msgstr ""
msgid "Select strategy activation method" msgid "Select strategy activation method."
msgstr "" msgstr ""
msgid "Select subscription" msgid "Select subscription"
...@@ -22671,6 +22671,9 @@ msgstr "" ...@@ -22671,6 +22671,9 @@ msgstr ""
msgid "Select the custom project template source group." msgid "Select the custom project template source group."
msgstr "" msgstr ""
msgid "Select the environment scope for this feature flag."
msgstr ""
msgid "Select timeframe" msgid "Select timeframe"
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment