Commit 835412a0 authored by David O'Regan's avatar David O'Regan

Merge branch '224698-fe-operations' into 'master'

Add toggle to disable Operations in settings

See merge request gitlab-org/gitlab!49919
parents 8d0a8a47 f88f9e92
...@@ -33,6 +33,11 @@ export default { ...@@ -33,6 +33,11 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
showToggle: {
type: Boolean,
required: false,
default: true,
},
}, },
computed: { computed: {
featureEnabled() { featureEnabled() {
...@@ -74,6 +79,7 @@ export default { ...@@ -74,6 +79,7 @@ export default {
> >
<input v-if="name" :name="name" :value="value" type="hidden" /> <input v-if="name" :name="name" :value="value" type="hidden" />
<project-feature-toggle <project-feature-toggle
v-if="showToggle"
class="gl-flex-grow-0 gl-mr-3" class="gl-flex-grow-0 gl-mr-3"
:value="featureEnabled" :value="featureEnabled"
:disabled-input="disabledInput" :disabled-input="disabledInput"
......
...@@ -12,6 +12,7 @@ import { ...@@ -12,6 +12,7 @@ import {
featureAccessLevelMembers, featureAccessLevelMembers,
featureAccessLevelEveryone, featureAccessLevelEveryone,
featureAccessLevel, featureAccessLevel,
featureAccessLevelNone,
} from '../constants'; } from '../constants';
import { toggleHiddenClassBySelector } from '../external'; import { toggleHiddenClassBySelector } from '../external';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
...@@ -140,6 +141,7 @@ export default { ...@@ -140,6 +141,7 @@ export default {
metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS, metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
analyticsAccessLevel: featureAccessLevel.EVERYONE, analyticsAccessLevel: featureAccessLevel.EVERYONE,
requirementsAccessLevel: featureAccessLevel.EVERYONE, requirementsAccessLevel: featureAccessLevel.EVERYONE,
operationsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true, containerRegistryEnabled: true,
lfsEnabled: true, lfsEnabled: true,
requestAccessEnabled: true, requestAccessEnabled: true,
...@@ -167,6 +169,14 @@ export default { ...@@ -167,6 +169,14 @@ export default {
); );
}, },
operationsFeatureAccessLevelOptions() {
if (!this.operationsEnabled) return [featureAccessLevelNone];
return this.featureAccessLevelOptions.filter(
([value]) => value <= this.operationsAccessLevel,
);
},
pagesFeatureAccessLevelOptions() { pagesFeatureAccessLevelOptions() {
const options = [featureAccessLevelMembers]; const options = [featureAccessLevelMembers];
...@@ -186,8 +196,12 @@ export default { ...@@ -186,8 +196,12 @@ export default {
return options; return options;
}, },
metricsOptionsDropdownEnabled() { metricsOptionsDropdownDisabled() {
return this.featureAccessLevelOptions.length < 2; return this.operationsFeatureAccessLevelOptions.length < 2 || !this.operationsEnabled;
},
operationsEnabled() {
return this.operationsAccessLevel > featureAccessLevel.NOT_ENABLED;
}, },
repositoryEnabled() { repositoryEnabled() {
...@@ -250,6 +264,10 @@ export default { ...@@ -250,6 +264,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS, featureAccessLevel.PROJECT_MEMBERS,
this.requirementsAccessLevel, this.requirementsAccessLevel,
); );
this.operationsAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.operationsAccessLevel,
);
if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) { if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) {
// When from Internal->Private narrow access for only members // When from Internal->Private narrow access for only members
this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS; this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS;
...@@ -277,6 +295,8 @@ export default { ...@@ -277,6 +295,8 @@ export default {
this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE; this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE;
if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS) if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.requirementsAccessLevel = featureAccessLevel.EVERYONE; this.requirementsAccessLevel = featureAccessLevel.EVERYONE;
if (this.operationsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.operationsAccessLevel = featureAccessLevel.EVERYONE;
this.highlightChanges(); this.highlightChanges();
} }
...@@ -562,41 +582,34 @@ export default { ...@@ -562,41 +582,34 @@ export default {
/> />
</project-setting-row> </project-setting-row>
<project-setting-row <project-setting-row
ref="metrics-visibility-settings" ref="operations-settings"
:label="__('Metrics Dashboard')" :label="s__('ProjectSettings|Operations')"
:help-text=" :help-text="s__('ProjectSettings|Environments, logs, cluster management, and more')"
s__(
'ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics',
)
"
> >
<div class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0"> <project-feature-setting
<div class="select-wrapper gl-flex-fill-1"> v-model="operationsAccessLevel"
<select :options="featureAccessLevelOptions"
v-model="metricsDashboardAccessLevel" name="project[project_feature_attributes][operations_access_level]"
:disabled="metricsOptionsDropdownEnabled" />
name="project[project_feature_attributes][metrics_dashboard_access_level]"
class="form-control project-repo-select select-control"
>
<option
:value="featureAccessLevelMembers[0]"
:disabled="!visibilityAllowed(visibilityOptions.INTERNAL)"
>{{ featureAccessLevelMembers[1] }}</option
>
<option
:value="featureAccessLevelEveryone[0]"
:disabled="!visibilityAllowed(visibilityOptions.PUBLIC)"
>{{ featureAccessLevelEveryone[1] }}</option
>
</select>
<gl-icon
name="chevron-down"
data-hidden="true"
class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500"
/>
</div>
</div>
</project-setting-row> </project-setting-row>
<div class="project-feature-setting-group gl-pl-7 gl-sm-pl-5">
<project-setting-row
ref="metrics-visibility-settings"
:label="__('Metrics Dashboard')"
:help-text="
s__(
'ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics',
)
"
>
<project-feature-setting
v-model="metricsDashboardAccessLevel"
:show-toggle="false"
:options="operationsFeatureAccessLevelOptions"
name="project[project_feature_attributes][metrics_dashboard_access_level]"
/>
</project-setting-row>
</div>
</div> </div>
<project-setting-row v-if="canDisableEmails" ref="email-settings" class="mb-3"> <project-setting-row v-if="canDisableEmails" ref="email-settings" class="mb-3">
<label class="js-emails-disabled"> <label class="js-emails-disabled">
......
---
title: Add toggle to disable Operations in settings
merge_request: 49919
author:
type: added
...@@ -21862,6 +21862,9 @@ msgstr "" ...@@ -21862,6 +21862,9 @@ msgstr ""
msgid "ProjectSettings|Encourage" msgid "ProjectSettings|Encourage"
msgstr "" msgstr ""
msgid "ProjectSettings|Environments, logs, cluster management, and more"
msgstr ""
msgid "ProjectSettings|Every merge creates a merge commit" msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "" msgstr ""
...@@ -21946,6 +21949,9 @@ msgstr "" ...@@ -21946,6 +21949,9 @@ msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository." msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "" msgstr ""
msgid "ProjectSettings|Operations"
msgstr ""
msgid "ProjectSettings|Packages" msgid "ProjectSettings|Packages"
msgstr "" msgstr ""
......
...@@ -9,6 +9,7 @@ describe('Project Feature Settings', () => { ...@@ -9,6 +9,7 @@ describe('Project Feature Settings', () => {
options: [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]], options: [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5]],
value: 1, value: 1,
disabledInput: false, disabledInput: false,
showToggle: true,
}; };
let wrapper; let wrapper;
...@@ -40,6 +41,14 @@ describe('Project Feature Settings', () => { ...@@ -40,6 +41,14 @@ describe('Project Feature Settings', () => {
}); });
describe('Feature toggle', () => { describe('Feature toggle', () => {
it('should be hidden if "showToggle" is passed false', async () => {
wrapper.setProps({ showToggle: false });
await wrapper.vm.$nextTick();
expect(wrapper.find(projectFeatureToggle).element).toBeUndefined();
});
it('should enable the feature toggle if the value is not 0', () => { it('should enable the feature toggle if the value is not 0', () => {
expect(wrapper.find(projectFeatureToggle).props().value).toBe(true); expect(wrapper.find(projectFeatureToggle).props().value).toBe(true);
}); });
......
...@@ -20,6 +20,7 @@ const defaultProps = { ...@@ -20,6 +20,7 @@ const defaultProps = {
buildsAccessLevel: 20, buildsAccessLevel: 20,
wikiAccessLevel: 20, wikiAccessLevel: 20,
snippetsAccessLevel: 20, snippetsAccessLevel: 20,
operationsAccessLevel: 20,
pagesAccessLevel: 10, pagesAccessLevel: 10,
analyticsAccessLevel: 20, analyticsAccessLevel: 20,
containerRegistryEnabled: true, containerRegistryEnabled: true,
...@@ -68,8 +69,12 @@ describe('Settings Panel', () => { ...@@ -68,8 +69,12 @@ describe('Settings Panel', () => {
}); });
}; };
const overrideCurrentSettings = (currentSettingsProps, extraProps = {}) => { const overrideCurrentSettings = (
return mountComponent({ ...extraProps, currentSettings: currentSettingsProps }); currentSettingsProps,
extraProps = {},
mountFn = shallowMount,
) => {
return mountComponent({ ...extraProps, currentSettings: currentSettingsProps }, mountFn);
}; };
const findLFSSettingsRow = () => wrapper.find({ ref: 'git-lfs-settings' }); const findLFSSettingsRow = () => wrapper.find({ ref: 'git-lfs-settings' });
...@@ -523,28 +528,30 @@ describe('Settings Panel', () => { ...@@ -523,28 +528,30 @@ describe('Settings Panel', () => {
}); });
}); });
it('should set the visibility level description based upon the selected visibility level', () => {
wrapper
.find('[name="project[project_feature_attributes][metrics_dashboard_access_level]"]')
.setValue(visibilityOptions.PUBLIC);
expect(wrapper.vm.metricsDashboardAccessLevel).toBe(visibilityOptions.PUBLIC);
});
it('should contain help text', () => { it('should contain help text', () => {
expect(wrapper.find({ ref: 'metrics-visibility-settings' }).props().helpText).toBe( expect(wrapper.find({ ref: 'metrics-visibility-settings' }).props().helpText).toBe(
'With Metrics Dashboard you can visualize this project performance metrics', 'With Metrics Dashboard you can visualize this project performance metrics',
); );
}); });
it('should disable the metrics visibility dropdown when the project visibility level changes to private', () => { it.each`
wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.PRIVATE }); scenario | selectedOption | selectedOptionLabel
${{ visibilityLevel: visibilityOptions.PRIVATE }} | ${String(featureAccessLevel.PROJECT_MEMBERS)} | ${'Only Project Members'}
${{ operationsAccessLevel: featureAccessLevel.NOT_ENABLED }} | ${String(featureAccessLevel.NOT_ENABLED)} | ${'Enable feature to choose access level'}
`(
'should disable the metrics visibility dropdown when #scenario',
({ scenario, selectedOption, selectedOptionLabel }) => {
wrapper = overrideCurrentSettings(scenario, {}, mount);
const metricsSettingsRow = wrapper.find({ ref: 'metrics-visibility-settings' }); const select = wrapper.find({ ref: 'metrics-visibility-settings' }).find('select');
const option = select.find('option');
expect(wrapper.vm.metricsOptionsDropdownEnabled).toBe(true); expect(select.attributes('disabled')).toBe('disabled');
expect(metricsSettingsRow.find('select').attributes('disabled')).toBe('disabled'); expect(select.element.value).toBe(selectedOption);
}); expect(option.attributes('value')).toBe(selectedOption);
expect(option.text()).toBe(selectedOptionLabel);
},
);
}); });
describe('Settings panel with feature flags', () => { describe('Settings panel with feature flags', () => {
...@@ -568,4 +575,12 @@ describe('Settings Panel', () => { ...@@ -568,4 +575,12 @@ describe('Settings Panel', () => {
expect(findAnalyticsRow().exists()).toBe(true); expect(findAnalyticsRow().exists()).toBe(true);
}); });
}); });
describe('Operations', () => {
it('should show the operations toggle', async () => {
await wrapper.vm.$nextTick();
expect(wrapper.find({ ref: 'operations-settings' }).exists()).toBe(true);
});
});
}); });
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