Commit 0d7c8ca2 authored by Mike Greiling's avatar Mike Greiling

Merge branch 'port-configure-ff-modal-to-vue' into 'master'

Port Configure Feature Flags Modal to Vue

See merge request gitlab-org/gitlab-ee!13432
parents dbacf097 74a02fde
<script>
import { GlModal, GlButton } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
export default {
modalTitle: s__('FeatureFlags|Configure feature flags'),
apiUrlLabelText: s__('FeatureFlags|API URL'),
apiUrlCopyText: __('Copy URL to clipboard'),
instanceIdLabelText: s__('FeatureFlags|Instance ID'),
instanceIdCopyText: __('Copy ID to clipboard'),
components: {
GlModal,
GlButton,
ModalCopyButton,
},
props: {
helpPath: {
type: String,
required: true,
},
helpAnchor: {
type: String,
required: true,
},
apiUrl: {
type: String,
required: true,
},
instanceId: {
type: String,
required: true,
},
modalId: {
type: String,
required: false,
default: 'configure-feature-flags',
},
},
computed: {
helpText() {
return sprintf(
s__(
'FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}',
),
{
docs_link_anchored_start: `<a href="${this.helpAnchor}">`,
docs_link_anchored_end: '</a>',
docs_link_start: `<a href="${this.helpPath}">`,
docs_link_end: '</a>',
},
false,
);
},
},
};
</script>
<template>
<gl-modal :modal-id="modalId" :hide-footer="true">
<template #modal-title>
{{ $options.modalTitle }}
</template>
<p v-html="helpText"></p>
<div class="form-group">
<label for="api_url" class="label-bold">{{ $options.apiUrlLabelText }}</label>
<div class="input-group">
<input
id="api_url"
:value="apiUrl"
readonly
class="form-control"
type="text"
name="api_url"
/>
<span class="input-group-append">
<modal-copy-button
:text="apiUrl"
:title="$options.apiUrlCopyText"
:modal-id="modalId"
class="input-group-text btn btn-default"
/>
</span>
</div>
</div>
<div class="form-group">
<label for="instance_id" class="label-bold">{{ $options.instanceIdLabelText }}</label>
<div class="input-group">
<input
id="instance_id"
:value="instanceId"
class="form-control"
type="text"
name="instance_id"
readonly
/>
<span class="input-group-append">
<modal-copy-button
:text="instanceId"
:title="$options.instanceIdCopyText"
:modal-id="modalId"
class="input-group-text btn btn-default"
/>
</span>
</div>
</div>
</gl-modal>
</template>
<script> <script>
import { createNamespacedHelpers } from 'vuex'; import { createNamespacedHelpers } from 'vuex';
import _ from 'underscore'; import _ from 'underscore';
import { GlEmptyState, GlLoadingIcon, GlButton } from '@gitlab/ui'; import { GlEmptyState, GlLoadingIcon, GlButton, GlModalDirective } from '@gitlab/ui';
import FeatureFlagsTable from './feature_flags_table.vue'; import FeatureFlagsTable from './feature_flags_table.vue';
import store from '../store'; import store from '../store';
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
...@@ -13,6 +13,8 @@ import { ...@@ -13,6 +13,8 @@ import {
buildUrlWithCurrentLocation, buildUrlWithCurrentLocation,
} from '~/lib/utils/common_utils'; } from '~/lib/utils/common_utils';
import ConfigureFeatureFlagsModal from './configure_feature_flags_modal.vue';
const { mapState, mapActions } = createNamespacedHelpers('index'); const { mapState, mapActions } = createNamespacedHelpers('index');
export default { export default {
...@@ -24,6 +26,10 @@ export default { ...@@ -24,6 +26,10 @@ export default {
GlEmptyState, GlEmptyState,
GlLoadingIcon, GlLoadingIcon,
GlButton, GlButton,
ConfigureFeatureFlagsModal,
},
directives: {
GlModal: GlModalDirective,
}, },
props: { props: {
endpoint: { endpoint: {
...@@ -42,6 +48,18 @@ export default { ...@@ -42,6 +48,18 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
featureFlagsAnchoredHelpPagePath: {
type: String,
required: true,
},
unleashApiUrl: {
type: String,
required: true,
},
unleashApiInstanceId: {
type: String,
required: true,
},
canUserConfigure: { canUserConfigure: {
type: Boolean, type: Boolean,
required: true, required: true,
...@@ -160,15 +178,22 @@ export default { ...@@ -160,15 +178,22 @@ export default {
</script> </script>
<template> <template>
<div> <div>
<configure-feature-flags-modal
v-if="canUserConfigure"
:help-path="featureFlagsHelpPagePath"
:help-anchor="featureFlagsAnchoredHelpPagePath"
:api-url="unleashApiUrl"
:instance-id="unleashApiInstanceId"
modal-id="configure-feature-flags"
/>
<h3 class="page-title with-button"> <h3 class="page-title with-button">
{{ s__('FeatureFlags|Feature Flags') }} {{ s__('FeatureFlags|Feature Flags') }}
<div class="pull-right"> <div class="pull-right">
<button <button
v-if="canUserConfigure" v-if="canUserConfigure"
v-gl-modal="'configure-feature-flags'"
type="button" type="button"
class="js-ff-configure append-right-8 btn-inverted btn btn-primary" class="js-ff-configure append-right-8 btn-inverted btn btn-primary"
data-toggle="modal"
data-target="#configure-feature-flags-modal"
> >
{{ s__('FeatureFlags|Configure') }} {{ s__('FeatureFlags|Configure') }}
</button> </button>
......
...@@ -19,6 +19,9 @@ export default () => ...@@ -19,6 +19,9 @@ export default () =>
endpoint: this.dataset.endpoint, endpoint: this.dataset.endpoint,
errorStateSvgPath: this.dataset.errorStateSvgPath, errorStateSvgPath: this.dataset.errorStateSvgPath,
featureFlagsHelpPagePath: this.dataset.featureFlagsHelpPagePath, featureFlagsHelpPagePath: this.dataset.featureFlagsHelpPagePath,
featureFlagsAnchoredHelpPagePath: this.dataset.featureFlagsAnchoredHelpPagePath,
unleashApiUrl: this.dataset.unleashApiUrl,
unleashApiInstanceId: this.dataset.unleashApiInstanceId || '',
csrfToken: csrf.token, csrfToken: csrf.token,
canUserConfigure: this.dataset.canUserAdminFeatureFlag, canUserConfigure: this.dataset.canUserAdminFeatureFlag,
newFeatureFlagPath: this.dataset.newFeatureFlagPath, newFeatureFlagPath: this.dataset.newFeatureFlagPath,
......
- if can?(current_user, :admin_feature_flag, @project)
#configure-feature-flags-modal.modal{ tabindex: -1,
role: 'dialog' }
.modal-dialog{ role: 'document' }
.modal-content
.modal-header
%h4.modal-title
= s_('FeatureFlags|Configure feature flags')
%button.close{ type: 'button', data: { dismiss: 'modal' }, aria: { label: _('Close') } }
%span{ "aria-hidden": true } &times;
.modal-body
%p
- client_libraries_url = help_page_path("user/project/operations/feature_flags", anchor: "client-libraries")
= s_('FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup.').html_safe % { docs_link_start: %Q{<a href="#{client_libraries_url}">}.html_safe,
docs_link_end: '</a>'.html_safe }
= link_to s_('FeatureFlags|More information'), help_page_path("user/project/operations/feature_flags")
.form-group
= label_tag :api_url, s_('FeatureFlags|API URL'), class: 'label-bold'
.input-group
= text_field_tag :api_url,
unleash_api_url(@project),
readonly: true,
class: "form-control js-select-on-focus"
%span.input-group-append
= clipboard_button(target: '#api_url',
title: _("Copy URL to clipboard"),
placement: "left",
container: '#configure-feature-flags-modal',
class: "input-group-text btn btn-default")
.form-group
= label_tag :instance_id, s_('FeatureFlags|Instance ID'), class: 'label-bold'
.input-group
= text_field_tag :instance_id,
unleash_api_instance_id(@project),
readonly: true,
class: "form-control js-select-on-focus"
%span.input-group-append
= clipboard_button(target: '#instance_id',
title: _("Copy ID to clipboard"),
placement: "left",
container: '#configure-feature-flags-modal',
class: "input-group-text btn btn-default")
- page_title s_('FeatureFlags|Feature Flags') - page_title s_('FeatureFlags|Feature Flags')
= render 'configure_feature_flags_modal'
#feature-flags-vue{ data: { endpoint: project_feature_flags_path(@project, format: :json), #feature-flags-vue{ data: { endpoint: project_feature_flags_path(@project, format: :json),
"error-state-svg-path" => image_path('illustrations/feature_flag.svg'), "error-state-svg-path" => image_path('illustrations/feature_flag.svg'),
"feature-flags-help-page-path" => help_page_path("user/project/operations/feature_flags"), "feature-flags-help-page-path" => help_page_path("user/project/operations/feature_flags"),
"feature-flags-anchored-help-page-path" => help_page_path("user/project/operations/feature_flags", anchor: "client-libraries"),
"unleash-api-url" => (unleash_api_url(@project) if can?(current_user, :admin_feature_flag, @project)),
"unleash-api-instance-id" => (unleash_api_instance_id(@project) if can?(current_user, :admin_feature_flag, @project)),
"can-user-admin-feature-flag" => can?(current_user, :admin_feature_flag, @project), "can-user-admin-feature-flag" => can?(current_user, :admin_feature_flag, @project),
"new-feature-flag-path" => can?(current_user, :create_feature_flag, @project) ? new_project_feature_flag_path(@project): nil } } "new-feature-flag-path" => can?(current_user, :create_feature_flag, @project) ? new_project_feature_flag_path(@project): nil } }
...@@ -12,6 +12,9 @@ describe('Feature Flags', () => { ...@@ -12,6 +12,9 @@ describe('Feature Flags', () => {
csrfToken: 'testToken', csrfToken: 'testToken',
errorStateSvgPath: '/assets/illustrations/feature_flag.svg', errorStateSvgPath: '/assets/illustrations/feature_flag.svg',
featureFlagsHelpPagePath: '/help/feature-flags', featureFlagsHelpPagePath: '/help/feature-flags',
featureFlagsAnchoredHelpPagePath: '/help/feature-flags#unleash-clients',
unleashApiUrl: `${TEST_HOST}/api/unleash`,
unleashApiInstanceId: 'oP6sCNRqtRHmpy1gw2-F',
canUserConfigure: true, canUserConfigure: true,
newFeatureFlagPath: 'feature-flags/new', newFeatureFlagPath: 'feature-flags/new',
}; };
...@@ -38,6 +41,9 @@ describe('Feature Flags', () => { ...@@ -38,6 +41,9 @@ describe('Feature Flags', () => {
errorStateSvgPath: '/assets/illustrations/feature_flag.svg', errorStateSvgPath: '/assets/illustrations/feature_flag.svg',
featureFlagsHelpPagePath: '/help/feature-flags', featureFlagsHelpPagePath: '/help/feature-flags',
canUserConfigure: false, canUserConfigure: false,
featureFlagsAnchoredHelpPagePath: '/help/feature-flags#unleash-clients',
unleashApiUrl: `${TEST_HOST}/api/unleash`,
unleashApiInstanceId: 'oP6sCNRqtRHmpy1gw2-F',
}; };
beforeEach(done => { beforeEach(done => {
......
...@@ -5482,7 +5482,7 @@ msgstr "" ...@@ -5482,7 +5482,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}" msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr "" msgstr ""
msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup." msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr "" msgstr ""
msgid "FeatureFlags|Instance ID" msgid "FeatureFlags|Instance ID"
...@@ -5494,9 +5494,6 @@ msgstr "" ...@@ -5494,9 +5494,6 @@ msgstr ""
msgid "FeatureFlags|More Information" msgid "FeatureFlags|More Information"
msgstr "" msgstr ""
msgid "FeatureFlags|More information"
msgstr ""
msgid "FeatureFlags|Name" msgid "FeatureFlags|Name"
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