diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-08 15:09:27 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-08 15:09:27 +0300 |
commit | 81f062b841f6062601662061850934a51e77ceea (patch) | |
tree | 0851038895c34776af8603f13b546b50df511e36 /app/assets/javascripts/webhooks | |
parent | e40061efd4c68576da944254567d0b3fbc233ae4 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/webhooks')
-rw-r--r-- | app/assets/javascripts/webhooks/components/form_url_app.vue | 70 | ||||
-rw-r--r-- | app/assets/javascripts/webhooks/components/form_url_mask_item.vue | 26 |
2 files changed, 93 insertions, 3 deletions
diff --git a/app/assets/javascripts/webhooks/components/form_url_app.vue b/app/assets/javascripts/webhooks/components/form_url_app.vue index 45526ff9080..a156b638e21 100644 --- a/app/assets/javascripts/webhooks/components/form_url_app.vue +++ b/app/assets/javascripts/webhooks/components/form_url_app.vue @@ -2,6 +2,7 @@ import { cloneDeep, isEmpty } from 'lodash'; import { GlFormGroup, GlFormInput, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui'; import { __, s__ } from '~/locale'; +import { scrollToElement } from '~/lib/utils/common_utils'; import FormUrlMaskItem from './form_url_mask_item.vue'; @@ -31,9 +32,14 @@ export default { maskEnabled: !isEmpty(this.initialUrlVariables), url: this.initialUrl, items: this.getInitialItems(), + isValidated: false, + formEl: null, }; }, computed: { + urlState() { + return !this.isValidated || !isEmpty(this.url); + }, maskedUrl() { if (!this.url) { return null; @@ -46,13 +52,20 @@ export default { return; } - const replacementExpression = new RegExp(value, 'g'); - maskedUrl = maskedUrl.replace(replacementExpression, `{${key}}`); + maskedUrl = this.maskUrl(maskedUrl, key, value); }); return maskedUrl; }, }, + mounted() { + this.formEl = document.querySelector('.js-webhook-form'); + + this.formEl?.addEventListener('submit', this.handleSubmit); + }, + destroy() { + this.formEl?.removeEventListener('submit', this.handleSubmit); + }, methods: { getInitialItems() { return isEmpty(this.initialUrlVariables) ? [{}] : cloneDeep(this.initialUrlVariables); @@ -64,6 +77,52 @@ export default { return this.initialUrlVariables.some((item) => item.key === key); }, + keyInvalidFeedback(key) { + if (this.isValidated && isEmpty(key)) { + return this.$options.i18n.inputRequired; + } + + return null; + }, + valueInvalidFeedback(key, value) { + if (this.isEditingItem(key)) { + return null; + } + + if (this.isValidated && isEmpty(value)) { + return this.$options.i18n.inputRequired; + } + + return null; + }, + isValid() { + this.isValidated = true; + + if (!this.urlState) { + return false; + } + + if ( + this.maskEnabled && + this.items.some( + ({ key, value }) => this.keyInvalidFeedback(key) || this.valueInvalidFeedback(key, value), + ) + ) { + return false; + } + + return true; + }, + handleSubmit(e) { + if (!this.isValid()) { + scrollToElement(this.$refs.formUrl.$el); + e.preventDefault(); + e.stopPropagation(); + } + }, + maskUrl(url, key, value) { + return url.split(value).join(`{${key}}`); + }, onItemInput({ index, key, value }) { this.$set(this.items, index, { key, value }); }, @@ -76,6 +135,7 @@ export default { }, i18n: { addItem: s__('Webhooks|+ Mask another portion of URL'), + inputRequired: __('This field is required.'), radioFullUrlText: s__('Webhooks|Show full URL'), radioMaskUrlText: s__('Webhooks|Mask portions of URL'), radioMaskUrlHelp: s__('Webhooks|Do not show sensitive data such as tokens in the UI.'), @@ -92,14 +152,18 @@ export default { <template> <div> <gl-form-group + ref="formUrl" :label="$options.i18n.urlLabel" label-for="webhook-url" :description="$options.i18n.urlDescription" + :invalid-feedback="$options.i18n.inputRequired" + :state="urlState" > <gl-form-input id="webhook-url" v-model="url" name="hook[url]" + :state="urlState" :placeholder="$options.i18n.urlPlaceholder" data-testid="form-url" /> @@ -123,6 +187,8 @@ export default { :item-key="key" :item-value="value" :is-editing="isEditingItem(key)" + :key-invalid-feedback="keyInvalidFeedback(key)" + :value-invalid-feedback="valueInvalidFeedback(key, value)" @input="onItemInput" @remove="removeItem" /> diff --git a/app/assets/javascripts/webhooks/components/form_url_mask_item.vue b/app/assets/javascripts/webhooks/components/form_url_mask_item.vue index aa5d9ce57f4..f5f81759719 100644 --- a/app/assets/javascripts/webhooks/components/form_url_mask_item.vue +++ b/app/assets/javascripts/webhooks/components/form_url_mask_item.vue @@ -1,4 +1,5 @@ <script> +import { isEmpty } from 'lodash'; import { GlButton, GlFormGroup, GlFormInput } from '@gitlab/ui'; import { s__ } from '~/locale'; import { MASK_ITEM_VALUE_HIDDEN } from '../constants'; @@ -30,6 +31,16 @@ export default { required: false, default: false, }, + keyInvalidFeedback: { + type: String, + required: false, + default: null, + }, + valueInvalidFeedback: { + type: String, + required: false, + default: null, + }, }, computed: { keyInputId() { @@ -38,6 +49,12 @@ export default { valueInputId() { return this.inputId('value'); }, + keyState() { + return isEmpty(this.keyInvalidFeedback); + }, + valueState() { + return isEmpty(this.valueInvalidFeedback); + }, displayValue() { return this.isEditing ? MASK_ITEM_VALUE_HIDDEN : this.itemValue; }, @@ -67,10 +84,12 @@ export default { </script> <template> - <div class="gl-display-flex gl-align-items-flex-end gl-gap-3 gl-mb-3"> + <div class="gl-display-flex gl-align-items-flex-start gl-gap-3 gl-mb-3"> <gl-form-group :label="$options.i18n.valueLabel" :label-for="valueInputId" + :invalid-feedback="valueInvalidFeedback" + :state="valueState" class="gl-flex-grow-1 gl-mb-0" data-testid="mask-item-value" > @@ -79,12 +98,15 @@ export default { :name="inputName('value')" :value="displayValue" :disabled="isEditing" + :state="valueState" @input="onValueInput" /> </gl-form-group> <gl-form-group :label="$options.i18n.keyLabel" :label-for="keyInputId" + :invalid-feedback="keyInvalidFeedback" + :state="keyState" class="gl-flex-grow-1 gl-mb-0" data-testid="mask-item-key" > @@ -93,6 +115,7 @@ export default { :name="inputName('key')" :value="itemKey" :disabled="isEditing" + :state="keyState" @input="onKeyInput" /> </gl-form-group> @@ -100,6 +123,7 @@ export default { icon="remove" :aria-label="__('Remove')" :disabled="isEditing" + class="gl-mt-6" @click="onRemoveClick" /> </div> |