Commit 77a98f10 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'djadmin-improve-ux-site-profile' into 'master'

Add help text and tooltips - Dast site profile form

See merge request gitlab-org/gitlab!55728
parents 24c65e64 2e9320d3
...@@ -7,19 +7,24 @@ import { ...@@ -7,19 +7,24 @@ import {
GlFormInput, GlFormInput,
GlModal, GlModal,
GlFormTextarea, GlFormTextarea,
GlFormText,
} from '@gitlab/ui'; } from '@gitlab/ui';
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { returnToPreviousPageFactory } from 'ee/security_configuration/dast_profiles/redirect'; import { returnToPreviousPageFactory } from 'ee/security_configuration/dast_profiles/redirect';
import { initFormField } from 'ee/security_configuration/utils'; import { initFormField } from 'ee/security_configuration/utils';
import { serializeFormObject } from '~/lib/utils/forms'; import { serializeFormObject } from '~/lib/utils/forms';
import { __, s__ } from '~/locale'; import { __, s__, n__, sprintf } from '~/locale';
import validation from '~/vue_shared/directives/validation'; import validation from '~/vue_shared/directives/validation';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import tooltipIcon from '../../dast_scanner_profiles/components/tooltip_icon.vue';
import dastSiteProfileCreateMutation from '../graphql/dast_site_profile_create.mutation.graphql'; import dastSiteProfileCreateMutation from '../graphql/dast_site_profile_create.mutation.graphql';
import dastSiteProfileUpdateMutation from '../graphql/dast_site_profile_update.mutation.graphql'; import dastSiteProfileUpdateMutation from '../graphql/dast_site_profile_update.mutation.graphql';
import DastSiteAuthSection from './dast_site_auth_section.vue'; import DastSiteAuthSection from './dast_site_auth_section.vue';
const MAX_CHAR_LIMIT_EXCLUDED_URLS = 2048;
const MAX_CHAR_LIMIT_REQUEST_HEADERS = 2048;
export default { export default {
name: 'DastSiteProfileForm', name: 'DastSiteProfileForm',
components: { components: {
...@@ -31,6 +36,8 @@ export default { ...@@ -31,6 +36,8 @@ export default {
GlModal, GlModal,
GlFormTextarea, GlFormTextarea,
DastSiteAuthSection, DastSiteAuthSection,
GlFormText,
tooltipIcon,
}, },
directives: { directives: {
validation: validation(), validation: validation(),
...@@ -111,6 +118,23 @@ export default { ...@@ -111,6 +118,23 @@ export default {
okTitle: __('Discard'), okTitle: __('Discard'),
cancelTitle: __('Cancel'), cancelTitle: __('Cancel'),
}, },
excludedUrls: {
label: s__('DastProfiles|Excluded URLs (Optional)'),
description: s__('DastProfiles|Enter URLs in a comma-separated list.'),
tooltip: s__(
'DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs.',
),
placeholder: 'https://example.com/logout, https://example.com/send_mail',
},
requestHeaders: {
label: s__('DastProfiles|Additional request headers (Optional)'),
description: s__('DastProfiles|Enter headers in a comma-separated list.'),
tooltip: s__(
'DastProfiles|Request header names and values. Headers are added to every request made by DAST.',
),
// eslint-disable-next-line @gitlab/require-i18n-strings
placeholder: 'Cache-control: no-cache, User-Agent: DAST/1.0',
},
}; };
}, },
formTouched() { formTouched() {
...@@ -200,8 +224,17 @@ export default { ...@@ -200,8 +224,17 @@ export default {
this.errors = []; this.errors = [];
this.hasAlert = false; this.hasAlert = false;
}, },
getCharacterLimitText(value, limit) {
return value.length
? n__('%d character remaining', '%d characters remaining', limit - value.length)
: sprintf(__('Maximum character limit - %{limit}'), {
limit,
});
},
}, },
modalId: 'deleteDastProfileModal', modalId: 'deleteDastProfileModal',
MAX_CHAR_LIMIT_EXCLUDED_URLS,
MAX_CHAR_LIMIT_REQUEST_HEADERS,
}; };
</script> </script>
...@@ -265,21 +298,45 @@ export default { ...@@ -265,21 +298,45 @@ export default {
:invalid-feedback="form.fields.excludedUrls.feedback" :invalid-feedback="form.fields.excludedUrls.feedback"
class="col-md-6" class="col-md-6"
> >
<template #label>
{{ i18n.excludedUrls.label }}
<tooltip-icon :title="i18n.excludedUrls.tooltip" />
<gl-form-text class="gl-mt-3">{{ i18n.excludedUrls.description }}</gl-form-text>
</template>
<gl-form-textarea <gl-form-textarea
v-model="form.fields.excludedUrls.value" v-model="form.fields.excludedUrls.value"
:maxlength="$options.MAX_CHAR_LIMIT_EXCLUDED_URLS"
:placeholder="i18n.excludedUrls.placeholder"
:no-resize="false"
data-testid="excluded-urls-input" data-testid="excluded-urls-input"
/> />
<gl-form-text>{{
getCharacterLimitText(
form.fields.excludedUrls.value,
$options.MAX_CHAR_LIMIT_EXCLUDED_URLS,
)
}}</gl-form-text>
</gl-form-group> </gl-form-group>
<gl-form-group <gl-form-group :invalid-feedback="form.fields.requestHeaders.feedback" class="col-md-6">
:label="s__('DastProfiles|Additional request headers (Optional)')" <template #label>
:invalid-feedback="form.fields.requestHeaders.feedback" {{ i18n.requestHeaders.label }}
class="col-md-6" <tooltip-icon :title="i18n.requestHeaders.tooltip" />
> <gl-form-text class="gl-mt-3">{{ i18n.requestHeaders.description }}</gl-form-text>
</template>
<gl-form-textarea <gl-form-textarea
v-model="form.fields.requestHeaders.value" v-model="form.fields.requestHeaders.value"
:maxlength="$options.MAX_CHAR_LIMIT_REQUEST_HEADERS"
:placeholder="i18n.requestHeaders.placeholder"
:no-resize="false"
data-testid="request-headers-input" data-testid="request-headers-input"
/> />
<gl-form-text>{{
getCharacterLimitText(
form.fields.requestHeaders.value,
$options.MAX_CHAR_LIMIT_REQUEST_HEADERS,
)
}}</gl-form-text>
</gl-form-group> </gl-form-group>
</div> </div>
......
...@@ -168,6 +168,11 @@ describe('DastSiteProfileForm', () => { ...@@ -168,6 +168,11 @@ describe('DastSiteProfileForm', () => {
expect(findExcludedUrlsInput().exists()).toBe(true); expect(findExcludedUrlsInput().exists()).toBe(true);
expect(findRequestHeadersInput().exists()).toBe(true); expect(findRequestHeadersInput().exists()).toBe(true);
}); });
it('should have maxlength constraint', () => {
expect(findExcludedUrlsInput().attributes('maxlength')).toBe('2048');
expect(findRequestHeadersInput().attributes('maxlength')).toBe('2048');
});
}); });
describe.each` describe.each`
......
...@@ -120,6 +120,11 @@ msgid_plural "%d changed files" ...@@ -120,6 +120,11 @@ msgid_plural "%d changed files"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "%d character remaining"
msgid_plural "%d characters remaining"
msgstr[0] ""
msgstr[1] ""
msgid "%d child epic" msgid "%d child epic"
msgid_plural "%d child epics" msgid_plural "%d child epics"
msgstr[0] "" msgstr[0] ""
...@@ -9437,6 +9442,12 @@ msgstr "" ...@@ -9437,6 +9442,12 @@ msgstr ""
msgid "DastProfiles|Enable Authentication" msgid "DastProfiles|Enable Authentication"
msgstr "" msgstr ""
msgid "DastProfiles|Enter URLs in a comma-separated list."
msgstr ""
msgid "DastProfiles|Enter headers in a comma-separated list."
msgstr ""
msgid "DastProfiles|Error Details" msgid "DastProfiles|Error Details"
msgstr "" msgstr ""
...@@ -9497,6 +9508,9 @@ msgstr "" ...@@ -9497,6 +9508,9 @@ msgstr ""
msgid "DastProfiles|Profile name" msgid "DastProfiles|Profile name"
msgstr "" msgstr ""
msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
msgstr ""
msgid "DastProfiles|Request headers" msgid "DastProfiles|Request headers"
msgstr "" msgstr ""
...@@ -9566,6 +9580,9 @@ msgstr "" ...@@ -9566,6 +9580,9 @@ msgstr ""
msgid "DastProfiles|URL" msgid "DastProfiles|URL"
msgstr "" msgstr ""
msgid "DastProfiles|URLs to skip during the authenticated scan. Use regular expression syntax to match multiple URLs."
msgstr ""
msgid "DastProfiles|Username" msgid "DastProfiles|Username"
msgstr "" msgstr ""
...@@ -18626,6 +18643,9 @@ msgstr "" ...@@ -18626,6 +18643,9 @@ msgstr ""
msgid "Maximum capacity" msgid "Maximum capacity"
msgstr "" msgstr ""
msgid "Maximum character limit - %{limit}"
msgstr ""
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation." msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
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