Commit 1737a7c4 authored by Paul Gascou-Vaillancourt's avatar Paul Gascou-Vaillancourt Committed by Phil Hughes

Add branch selector to on-demand scans form

Add the RefSelector component to the on-demand scans form. It lets user
pick a branch to be associated with the scan. It defaults to the
project's default branch.
parent cbd3726e
...@@ -4,7 +4,6 @@ import { ...@@ -4,7 +4,6 @@ import {
GlDropdownDivider, GlDropdownDivider,
GlSearchBoxByType, GlSearchBoxByType,
GlSprintf, GlSprintf,
GlIcon,
GlLoadingIcon, GlLoadingIcon,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { debounce, isArray } from 'lodash'; import { debounce, isArray } from 'lodash';
...@@ -27,7 +26,6 @@ export default { ...@@ -27,7 +26,6 @@ export default {
GlDropdownDivider, GlDropdownDivider,
GlSearchBoxByType, GlSearchBoxByType,
GlSprintf, GlSprintf,
GlIcon,
GlLoadingIcon, GlLoadingIcon,
RefResultsSection, RefResultsSection,
}, },
...@@ -111,7 +109,10 @@ export default { ...@@ -111,7 +109,10 @@ export default {
return this.enabledRefTypes.length > 1; return this.enabledRefTypes.length > 1;
}, },
toggleButtonClass() { toggleButtonClass() {
return { 'gl-inset-border-1-red-500!': !this.state }; return {
'gl-inset-border-1-red-500!': !this.state,
'gl-font-monospace': Boolean(this.selectedRef),
};
}, },
footerSlotProps() { footerSlotProps() {
return { return {
...@@ -120,6 +121,9 @@ export default { ...@@ -120,6 +121,9 @@ export default {
query: this.lastQuery, query: this.lastQuery,
}; };
}, },
buttonText() {
return this.selectedRef || this.i18n.noRefSelected;
},
}, },
watch: { watch: {
// Keep the Vuex store synchronized if the parent // Keep the Vuex store synchronized if the parent
...@@ -190,19 +194,12 @@ export default { ...@@ -190,19 +194,12 @@ export default {
<gl-dropdown <gl-dropdown
:header-text="i18n.dropdownHeader" :header-text="i18n.dropdownHeader"
:toggle-class="toggleButtonClass" :toggle-class="toggleButtonClass"
:text="buttonText"
class="ref-selector" class="ref-selector"
v-bind="$attrs" v-bind="$attrs"
v-on="$listeners" v-on="$listeners"
@shown="focusSearchBox" @shown="focusSearchBox"
> >
<template #button-content>
<span class="gl-flex-grow-1 gl-ml-2 gl-text-gray-400" data-testid="button-content">
<span v-if="selectedRef" class="gl-font-monospace">{{ selectedRef }}</span>
<span v-else>{{ i18n.noRefSelected }}</span>
</span>
<gl-icon name="chevron-down" />
</template>
<template #header> <template #header>
<gl-search-box-by-type <gl-search-box-by-type
ref="searchBox" ref="searchBox"
......
...@@ -23,6 +23,8 @@ import { convertToGraphQLId } from '~/graphql_shared/utils'; ...@@ -23,6 +23,8 @@ import { convertToGraphQLId } from '~/graphql_shared/utils';
import { serializeFormObject } from '~/lib/utils/forms'; import { serializeFormObject } from '~/lib/utils/forms';
import { redirectTo, queryToObject } from '~/lib/utils/url_utility'; import { redirectTo, queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import RefSelector from '~/ref/components/ref_selector.vue';
import { REF_TYPE_BRANCHES } from '~/ref/constants';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
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';
...@@ -68,9 +70,11 @@ const createProfilesApolloOptions = (name, field, { fetchQuery, fetchError }) => ...@@ -68,9 +70,11 @@ const createProfilesApolloOptions = (name, field, { fetchQuery, fetchError }) =>
export default { export default {
SCAN_TYPE_LABEL, SCAN_TYPE_LABEL,
REF_TYPE_BRANCHES,
saveAndRunScanBtnId: 'scan-submit-button', saveAndRunScanBtnId: 'scan-submit-button',
saveScanBtnId: 'scan-save-button', saveScanBtnId: 'scan-save-button',
components: { components: {
RefSelector,
ProfileSelectorSummaryCell, ProfileSelectorSummaryCell,
ScannerProfileSelector, ScannerProfileSelector,
SiteProfileSelector, SiteProfileSelector,
...@@ -156,6 +160,7 @@ export default { ...@@ -156,6 +160,7 @@ export default {
...savedScansFields, ...savedScansFields,
scannerProfiles: [], scannerProfiles: [],
siteProfiles: [], siteProfiles: [],
selectedBranch: this.dastScan?.branch?.name ?? this.defaultBranch,
selectedScannerProfileId: this.dastScan?.scannerProfileId || null, selectedScannerProfileId: this.dastScan?.scannerProfileId || null,
selectedSiteProfileId: this.dastScan?.siteProfileId || null, selectedSiteProfileId: this.dastScan?.siteProfileId || null,
loading: false, loading: false,
...@@ -277,6 +282,9 @@ export default { ...@@ -277,6 +282,9 @@ export default {
[this.isEdit ? 'runAfterUpdate' : 'runAfterCreate']: runAfter, [this.isEdit ? 'runAfterUpdate' : 'runAfterCreate']: runAfter,
}; };
} }
if (this.glFeatures.dastBranchSelection) {
input.branchName = this.selectedBranch;
}
this.$apollo this.$apollo
.mutate({ .mutate({
...@@ -431,6 +439,21 @@ export default { ...@@ -431,6 +439,21 @@ export default {
/> />
</gl-form-group> </gl-form-group>
</template> </template>
<gl-form-group v-if="glFeatures.dastBranchSelection" :label="__('Branch')">
<ref-selector
v-model="selectedBranch"
data-testid="dast-scan-branch-input"
no-flip
:enabled-ref-types="[$options.REF_TYPE_BRANCHES]"
:project-id="projectPath"
:translations="{
dropdownHeader: __('Select a branch'),
searchPlaceholder: __('Search'),
}"
/>
</gl-form-group>
<scanner-profile-selector <scanner-profile-selector
v-model="selectedScannerProfileId" v-model="selectedScannerProfileId"
class="gl-mb-5" class="gl-mb-5"
......
...@@ -7,6 +7,7 @@ module Projects ...@@ -7,6 +7,7 @@ module Projects
before_action do before_action do
push_frontend_feature_flag(:security_dast_site_profiles_additional_fields, @project, default_enabled: :yaml) push_frontend_feature_flag(:security_dast_site_profiles_additional_fields, @project, default_enabled: :yaml)
push_frontend_feature_flag(:dast_saved_scans, @project, default_enabled: :yaml) push_frontend_feature_flag(:dast_saved_scans, @project, default_enabled: :yaml)
push_frontend_feature_flag(:dast_branch_selection, @project, default_enabled: :yaml)
end end
before_action :authorize_read_on_demand_scans!, only: :index before_action :authorize_read_on_demand_scans!, only: :index
......
...@@ -26918,6 +26918,9 @@ msgstr "" ...@@ -26918,6 +26918,9 @@ msgstr ""
msgid "Select Stack" msgid "Select Stack"
msgstr "" msgstr ""
msgid "Select a branch"
msgstr ""
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes." msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "" msgstr ""
......
...@@ -91,7 +91,7 @@ describe('Ref selector component', () => { ...@@ -91,7 +91,7 @@ describe('Ref selector component', () => {
// //
// Finders // Finders
// //
const findButtonContent = () => wrapper.find('[data-testid="button-content"]'); const findButtonContent = () => wrapper.find('button');
const findNoResults = () => wrapper.find('[data-testid="no-results"]'); const findNoResults = () => wrapper.find('[data-testid="no-results"]');
......
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