Commit 7f7bafe3 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'display-ops-ff-iid' into 'master'

Display Feature Flag Internal Ids

See merge request gitlab-org/gitlab!23914
parents a612646e 749a3f0b
---
title: Display operations feature flag internal ids
merge_request: 23914
author:
type: added
...@@ -42,13 +42,10 @@ export default { ...@@ -42,13 +42,10 @@ export default {
'active', 'active',
]), ]),
title() { title() {
return this.hasFeatureFlagsIID return this.iid
? `^${this.iid} ${this.name}` ? `^${this.iid} ${this.name}`
: sprintf(s__('Edit %{name}'), { name: this.name }); : sprintf(s__('Edit %{name}'), { name: this.name });
}, },
hasFeatureFlagsIID() {
return this.glFeatures.featureFlagIID && this.iid;
},
}, },
created() { created() {
this.setPath(this.path); this.setPath(this.path);
......
...@@ -37,9 +37,6 @@ export default { ...@@ -37,9 +37,6 @@ export default {
permissions() { permissions() {
return this.glFeatures.featureFlagPermissions; return this.glFeatures.featureFlagPermissions;
}, },
hasIIDs() {
return this.glFeatures.featureFlagIID;
},
modalTitle() { modalTitle() {
return sprintf( return sprintf(
s__('FeatureFlags|Delete %{name}?'), s__('FeatureFlags|Delete %{name}?'),
...@@ -83,6 +80,9 @@ export default { ...@@ -83,6 +80,9 @@ export default {
return `${displayName}${displayPercentage}`; return `${displayName}${displayPercentage}`;
}, },
featureFlagIidText(featureFlag) {
return featureFlag.iid ? `^${featureFlag.iid}` : '';
},
canDeleteFlag(flag) { canDeleteFlag(flag) {
return !this.permissions || (flag.scopes || []).every(scope => scope.can_update); return !this.permissions || (flag.scopes || []).every(scope => scope.can_update);
}, },
...@@ -107,7 +107,7 @@ export default { ...@@ -107,7 +107,7 @@ export default {
<template> <template>
<div class="table-holder js-feature-flag-table"> <div class="table-holder js-feature-flag-table">
<div class="gl-responsive-table-row table-row-header" role="row"> <div class="gl-responsive-table-row table-row-header" role="row">
<div v-if="hasIIDs" class="table-section section-10"> <div class="table-section section-10">
{{ s__('FeatureFlags|ID') }} {{ s__('FeatureFlags|ID') }}
</div> </div>
<div class="table-section section-10" role="columnheader"> <div class="table-section section-10" role="columnheader">
...@@ -123,9 +123,11 @@ export default { ...@@ -123,9 +123,11 @@ export default {
<template v-for="featureFlag in featureFlags"> <template v-for="featureFlag in featureFlags">
<div :key="featureFlag.id" class="gl-responsive-table-row" role="row"> <div :key="featureFlag.id" class="gl-responsive-table-row" role="row">
<div v-if="hasIIDs" class="table-section section-10" role="gridcell"> <div class="table-section section-10" role="gridcell">
<div class="table-mobile-header" role="rowheader">{{ s__('FeatureFlags|ID') }}</div> <div class="table-mobile-header" role="rowheader">{{ s__('FeatureFlags|ID') }}</div>
<div class="table-mobile-content js-feature-flag-id">^{{ featureFlag.iid }}</div> <div class="table-mobile-content js-feature-flag-id">
{{ featureFlagIidText(featureFlag) }}
</div>
</div> </div>
<div class="table-section section-10" role="gridcell"> <div class="table-section section-10" role="gridcell">
<div class="table-mobile-header" role="rowheader">{{ s__('FeatureFlags|Status') }}</div> <div class="table-mobile-header" role="rowheader">{{ s__('FeatureFlags|Status') }}</div>
......
...@@ -4,6 +4,7 @@ class FeatureFlagEntity < Grape::Entity ...@@ -4,6 +4,7 @@ class FeatureFlagEntity < Grape::Entity
include RequestAwareEntity include RequestAwareEntity
expose :id expose :id
expose :iid
expose :active expose :active
expose :created_at expose :created_at
expose :updated_at expose :updated_at
......
...@@ -121,6 +121,14 @@ describe Projects::FeatureFlagsController do ...@@ -121,6 +121,14 @@ describe Projects::FeatureFlagsController do
expect(feature_flag_json['active']).to eq(false) expect(feature_flag_json['active']).to eq(false)
end end
it 'returns the feature flag iid' do
subject
feature_flag_json = json_response['feature_flags'].first
expect(feature_flag_json['iid']).to eq(feature_flag_active.iid)
end
context 'when scope is specified' do context 'when scope is specified' do
let(:view_params) do let(:view_params) do
{ namespace_id: project.namespace, project_id: project, scope: scope } { namespace_id: project.namespace, project_id: project, scope: scope }
......
...@@ -29,6 +29,7 @@ describe 'User sees feature flag list', :js do ...@@ -29,6 +29,7 @@ describe 'User sees feature flag list', :js do
it 'user sees the first flag' do it 'user sees the first flag' do
within_feature_flag_row(1) do within_feature_flag_row(1) do
expect(page.find('.js-feature-flag-id')).to have_content('^1')
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace') expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect(page).to have_css('.js-feature-flag-status button:not(.is-checked)') expect(page).to have_css('.js-feature-flag-status button:not(.is-checked)')
...@@ -43,6 +44,7 @@ describe 'User sees feature flag list', :js do ...@@ -43,6 +44,7 @@ describe 'User sees feature flag list', :js do
it 'user sees the second flag' do it 'user sees the second flag' do
within_feature_flag_row(2) do within_feature_flag_row(2) do
expect(page.find('.js-feature-flag-id')).to have_content('^2')
expect(page.find('.feature-flag-name')).to have_content('drop_legacy_artifacts') expect(page.find('.feature-flag-name')).to have_content('drop_legacy_artifacts')
expect(page).to have_css('.js-feature-flag-status button:not(.is-checked)') expect(page).to have_css('.js-feature-flag-status button:not(.is-checked)')
...@@ -55,6 +57,7 @@ describe 'User sees feature flag list', :js do ...@@ -55,6 +57,7 @@ describe 'User sees feature flag list', :js do
it 'user sees the third flag' do it 'user sees the third flag' do
within_feature_flag_row(3) do within_feature_flag_row(3) do
expect(page.find('.js-feature-flag-id')).to have_content('^3')
expect(page.find('.feature-flag-name')).to have_content('mr_train') expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect(page).to have_css('.js-feature-flag-status button.is-checked') expect(page).to have_css('.js-feature-flag-status button.is-checked')
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
], ],
"properties" : { "properties" : {
"id": { "type": "integer" }, "id": { "type": "integer" },
"iid": { "type": ["integer", "null"] },
"created_at": { "type": "date" }, "created_at": { "type": "date" },
"updated_at": { "type": "date" }, "updated_at": { "type": "date" },
"name": { "type": "string" }, "name": { "type": "string" },
......
...@@ -29,11 +29,6 @@ describe('Edit feature flag form', () => { ...@@ -29,11 +29,6 @@ describe('Edit feature flag form', () => {
path: '/feature_flags', path: '/feature_flags',
environmentsEndpoint: 'environments.json', environmentsEndpoint: 'environments.json',
}, },
provide: {
glFeatures: {
featureFlagIID: true,
},
},
store, store,
}); });
}; };
......
...@@ -12,6 +12,7 @@ const getDefaultProps = () => ({ ...@@ -12,6 +12,7 @@ const getDefaultProps = () => ({
featureFlags: [ featureFlags: [
{ {
id: 1, id: 1,
iid: 1,
active: true, active: true,
name: 'flag name', name: 'flag name',
description: 'flag description', description: 'flag description',
...@@ -56,10 +57,7 @@ describe('Feature flag table', () => { ...@@ -56,10 +57,7 @@ describe('Feature flag table', () => {
describe('with an active scope and a standard rollout strategy', () => { describe('with an active scope and a standard rollout strategy', () => {
beforeEach(() => { beforeEach(() => {
props.featureFlags[0].iid = 1; createWrapper(props);
createWrapper(props, {
provide: { glFeatures: { featureFlagIID: true } },
});
}); });
it('Should render a table', () => { it('Should render a table', () => {
...@@ -160,4 +158,12 @@ describe('Feature flag table', () => { ...@@ -160,4 +158,12 @@ describe('Feature flag table', () => {
expect(trimText(envColumn.find('.badge-inactive').text())).toBe('scope'); expect(trimText(envColumn.find('.badge-inactive').text())).toBe('scope');
}); });
}); });
it('renders a feature flag without an iid', () => {
delete props.featureFlags[0].iid;
createWrapper(props);
expect(wrapper.find('.js-feature-flag-id').exists()).toBe(true);
expect(trimText(wrapper.find('.js-feature-flag-id').text())).toBe('');
});
}); });
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