diff options
Diffstat (limited to 'app/assets/javascripts/integrations/edit')
5 files changed, 285 insertions, 18 deletions
diff --git a/app/assets/javascripts/integrations/edit/components/active_toggle.vue b/app/assets/javascripts/integrations/edit/components/active_toggle.vue index 8b95b04d93c..dc89e139320 100644 --- a/app/assets/javascripts/integrations/edit/components/active_toggle.vue +++ b/app/assets/javascripts/integrations/edit/components/active_toggle.vue @@ -1,12 +1,15 @@ <script> import eventHub from '../event_hub'; -import { GlToggle } from '@gitlab/ui'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import { GlFormGroup, GlToggle } from '@gitlab/ui'; export default { name: 'ActiveToggle', components: { + GlFormGroup, GlToggle, }, + mixins: [glFeatureFlagsMixin()], props: { initialActivated: { type: Boolean, @@ -33,7 +36,17 @@ export default { </script> <template> - <div> + <div v-if="glFeatures.integrationFormRefactor"> + <gl-form-group :label="__('Enable integration')" label-for="service[active]"> + <gl-toggle + v-model="activated" + name="service[active]" + class="gl-display-block gl-line-height-0" + @change="onToggle" + /> + </gl-form-group> + </div> + <div v-else> <div class="form-group row" role="group"> <label for="service[active]" class="col-form-label col-sm-2">{{ __('Active') }}</label> <div class="col-sm-10 pt-1"> diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue new file mode 100644 index 00000000000..29318d6aaa8 --- /dev/null +++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue @@ -0,0 +1,172 @@ +<script> +import eventHub from '../event_hub'; +import { capitalize, lowerCase, isEmpty } from 'lodash'; +import { __, sprintf } from '~/locale'; +import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui'; + +export default { + name: 'DynamicField', + components: { + GlFormGroup, + GlFormCheckbox, + GlFormInput, + GlFormSelect, + GlFormTextarea, + }, + props: { + choices: { + type: Array, + required: false, + default: null, + }, + help: { + type: String, + required: false, + default: null, + }, + name: { + type: String, + required: true, + }, + placeholder: { + type: String, + required: false, + default: null, + }, + required: { + type: Boolean, + required: false, + }, + title: { + type: String, + required: false, + default: null, + }, + type: { + type: String, + required: true, + }, + value: { + type: String, + required: false, + default: null, + }, + }, + data() { + return { + model: this.value, + validated: false, + }; + }, + computed: { + isCheckbox() { + return this.type === 'checkbox'; + }, + isPassword() { + return this.type === 'password'; + }, + isSelect() { + return this.type === 'select'; + }, + isTextarea() { + return this.type === 'textarea'; + }, + isNonEmptyPassword() { + return this.isPassword && !isEmpty(this.value); + }, + label() { + if (this.isNonEmptyPassword) { + return sprintf(__('Enter new %{field_title}'), { + field_title: this.humanizedTitle, + }); + } + return this.humanizedTitle; + }, + humanizedTitle() { + return this.title || capitalize(lowerCase(this.name)); + }, + passwordRequired() { + return isEmpty(this.value) && this.required; + }, + options() { + return this.choices.map(choice => { + return { + value: choice[1], + text: choice[0], + }; + }); + }, + fieldId() { + return `service_${this.name}`; + }, + fieldName() { + return `service[${this.name}]`; + }, + sharedProps() { + return { + id: this.fieldId, + name: this.fieldName, + }; + }, + valid() { + return !this.required || !isEmpty(this.model) || !this.validated; + }, + }, + created() { + if (this.isNonEmptyPassword) { + this.model = null; + } + eventHub.$on('validateForm', this.validateForm); + }, + beforeDestroy() { + eventHub.$off('validateForm', this.validateForm); + }, + methods: { + validateForm() { + this.validated = true; + }, + }, +}; +</script> + +<template> + <gl-form-group + :label="label" + :label-for="fieldId" + :invalid-feedback="__('This field is required.')" + :state="valid" + :description="help" + > + <template v-if="isCheckbox"> + <input :name="fieldName" type="hidden" value="false" /> + <gl-form-checkbox v-model="model" v-bind="sharedProps"> + {{ humanizedTitle }} + </gl-form-checkbox> + </template> + <gl-form-select v-else-if="isSelect" v-model="model" v-bind="sharedProps" :options="options" /> + <gl-form-textarea + v-else-if="isTextarea" + v-model="model" + v-bind="sharedProps" + :placeholder="placeholder" + :required="required" + /> + <gl-form-input + v-else-if="isPassword" + v-model="model" + v-bind="sharedProps" + :type="type" + autocomplete="new-password" + :placeholder="placeholder" + :required="passwordRequired" + /> + <gl-form-input + v-else + v-model="model" + v-bind="sharedProps" + :type="type" + :placeholder="placeholder" + :required="required" + /> + </gl-form-group> +</template> diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue index fbe58c30b13..ef7a4d44b20 100644 --- a/app/assets/javascripts/integrations/edit/components/integration_form.vue +++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue @@ -2,6 +2,7 @@ import ActiveToggle from './active_toggle.vue'; import JiraTriggerFields from './jira_trigger_fields.vue'; import TriggerFields from './trigger_fields.vue'; +import DynamicField from './dynamic_field.vue'; export default { name: 'IntegrationForm', @@ -9,6 +10,7 @@ export default { ActiveToggle, JiraTriggerFields, TriggerFields, + DynamicField, }, props: { activeToggleProps: { @@ -28,6 +30,11 @@ export default { required: false, default: () => [], }, + fields: { + type: Array, + required: false, + default: () => [], + }, type: { type: String, required: true, @@ -46,5 +53,6 @@ export default { <active-toggle v-if="showActive" v-bind="activeToggleProps" /> <jira-trigger-fields v-if="isJira" v-bind="triggerFieldsProps" /> <trigger-fields v-else-if="triggerEvents.length" :events="triggerEvents" :type="type" /> + <dynamic-field v-for="field in fields" :key="field.name" v-bind="field" /> </div> </template> diff --git a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue index 70278e401ce..64e5789764f 100644 --- a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue +++ b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue @@ -1,12 +1,31 @@ <script> -import { GlFormCheckbox, GlFormRadio } from '@gitlab/ui'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import { s__ } from '~/locale'; +import { GlFormGroup, GlFormCheckbox, GlFormRadio } from '@gitlab/ui'; + +const commentDetailOptions = [ + { + value: 'standard', + label: s__('Integrations|Standard'), + help: s__('Integrations|Includes commit title and branch'), + }, + { + value: 'all_details', + label: s__('Integrations|All details'), + help: s__( + 'Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs', + ), + }, +]; export default { name: 'JiraTriggerFields', components: { + GlFormGroup, GlFormCheckbox, GlFormRadio, }, + mixins: [glFeatureFlagsMixin()], props: { initialTriggerCommit: { type: Boolean, @@ -32,13 +51,71 @@ export default { triggerMergeRequest: this.initialTriggerMergeRequest, enableComments: this.initialEnableComments, commentDetail: this.initialCommentDetail, + commentDetailOptions, }; }, + computed: { + showEnableComments() { + return this.triggerCommit || this.triggerMergeRequest; + }, + }, }; </script> <template> - <div class="form-group row pt-2" role="group"> + <div v-if="glFeatures.integrationFormRefactor"> + <gl-form-group + :label="__('Trigger')" + label-for="service[trigger]" + :description=" + s__( + 'Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created.', + ) + " + > + <input name="service[commit_events]" type="hidden" value="false" /> + <gl-form-checkbox v-model="triggerCommit" name="service[commit_events]"> + {{ __('Commit') }} + </gl-form-checkbox> + + <input name="service[merge_requests_events]" type="hidden" value="false" /> + <gl-form-checkbox v-model="triggerMergeRequest" name="service[merge_requests_events]"> + {{ __('Merge request') }} + </gl-form-checkbox> + </gl-form-group> + + <gl-form-group + v-show="showEnableComments" + :label="s__('Integrations|Comment settings:')" + data-testid="comment-settings" + > + <input name="service[comment_on_event_enabled]" type="hidden" value="false" /> + <gl-form-checkbox v-model="enableComments" name="service[comment_on_event_enabled]"> + {{ s__('Integrations|Enable comments') }} + </gl-form-checkbox> + </gl-form-group> + + <gl-form-group + v-show="showEnableComments && enableComments" + :label="s__('Integrations|Comment detail:')" + data-testid="comment-detail" + > + <gl-form-radio + v-for="commentDetailOption in commentDetailOptions" + :key="commentDetailOption.value" + v-model="commentDetail" + :value="commentDetailOption.value" + name="service[comment_detail]" + > + {{ commentDetailOption.label }} + <template #help> + {{ commentDetailOption.help }} + </template> + </gl-form-radio> + </gl-form-group> + </div> + + <div v-else class="form-group row pt-2" role="group"> <label for="service[trigger]" class="col-form-label col-sm-2 pt-0">{{ __('Trigger') }}</label> <div class="col-sm-10"> <label class="weight-normal mb-2"> @@ -76,20 +153,16 @@ export default { <label> {{ s__('Integrations|Comment detail:') }} </label> - <gl-form-radio v-model="commentDetail" value="standard" name="service[comment_detail]"> - {{ s__('Integrations|Standard') }} - <template #help> - {{ s__('Integrations|Includes commit title and branch') }} - </template> - </gl-form-radio> - <gl-form-radio v-model="commentDetail" value="all_details" name="service[comment_detail]"> - {{ s__('Integrations|All details') }} + <gl-form-radio + v-for="commentDetailOption in commentDetailOptions" + :key="commentDetailOption.value" + v-model="commentDetail" + :value="commentDetailOption.value" + name="service[comment_detail]" + > + {{ commentDetailOption.label }} <template #help> - {{ - s__( - 'Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs', - ) - }} + {{ commentDetailOption.help }} </template> </gl-form-radio> </div> diff --git a/app/assets/javascripts/integrations/edit/index.js b/app/assets/javascripts/integrations/edit/index.js index 2ae1342a558..21b5ca17951 100644 --- a/app/assets/javascripts/integrations/edit/index.js +++ b/app/assets/javascripts/integrations/edit/index.js @@ -15,7 +15,7 @@ export default el => { return result; } - const { type, commentDetail, triggerEvents, ...booleanAttributes } = el.dataset; + const { type, commentDetail, triggerEvents, fields, ...booleanAttributes } = el.dataset; const { showActive, activated, @@ -41,6 +41,7 @@ export default el => { initialCommentDetail: commentDetail, }, triggerEvents: JSON.parse(triggerEvents), + fields: JSON.parse(fields), }, }); }, |