diff options
Diffstat (limited to 'app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue')
-rw-r--r-- | app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue | 126 |
1 files changed, 96 insertions, 30 deletions
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue index 288d6711682..07cc0ce46bc 100644 --- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue +++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue @@ -20,6 +20,7 @@ import axios from '~/lib/utils/axios_utils'; import csrf from '~/lib/utils/csrf'; import { redirectTo } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; +import validation from '~/vue_shared/directives/validation'; const PRIVATE_VISIBILITY = 'private'; const INTERNAL_VISIBILITY = 'internal'; @@ -31,6 +32,13 @@ const ALLOWED_VISIBILITY = { public: [INTERNAL_VISIBILITY, PRIVATE_VISIBILITY, PUBLIC_VISIBILITY], }; +const initFormField = ({ value, required = true, skipValidation = false }) => ({ + value, + required, + state: skipValidation ? true : null, + feedback: null, +}); + export default { components: { GlForm, @@ -46,6 +54,9 @@ export default { GlFormRadioGroup, GlFormSelect, }, + directives: { + validation: validation(), + }, inject: { newGroupPath: { default: '', @@ -77,7 +88,8 @@ export default { }, projectDescription: { type: String, - required: true, + required: false, + default: '', }, projectVisibility: { type: String, @@ -85,16 +97,30 @@ export default { }, }, data() { + const form = { + state: false, + showValidation: false, + fields: { + namespace: initFormField({ + value: null, + }), + name: initFormField({ value: this.projectName }), + slug: initFormField({ value: this.projectPath }), + description: initFormField({ + value: this.projectDescription, + required: false, + skipValidation: true, + }), + visibility: initFormField({ + value: this.projectVisibility, + skipValidation: true, + }), + }, + }; return { isSaving: false, namespaces: [], - selectedNamespace: {}, - fork: { - name: this.projectName, - slug: this.projectPath, - description: this.projectDescription, - visibility: this.projectVisibility, - }, + form, }; }, computed: { @@ -106,7 +132,7 @@ export default { }, namespaceAllowedVisibility() { return ( - ALLOWED_VISIBILITY[this.selectedNamespace.visibility] || + ALLOWED_VISIBILITY[this.form.fields.namespace.value?.visibility] || ALLOWED_VISIBILITY[PUBLIC_VISIBILITY] ); }, @@ -139,16 +165,17 @@ export default { }, }, watch: { - selectedNamespace(newVal) { + // eslint-disable-next-line func-names + 'form.fields.namespace.value': function (newVal) { const { visibility } = newVal; if (this.projectAllowedVisibility.includes(visibility)) { - this.fork.visibility = visibility; + this.form.fields.visibility.value = visibility; } }, // eslint-disable-next-line func-names - 'fork.name': function (newVal) { - this.fork.slug = kebabCase(newVal); + 'form.fields.name.value': function (newVal) { + this.form.fields.slug.value = kebabCase(newVal); }, }, mounted() { @@ -166,19 +193,25 @@ export default { ); }, async onSubmit() { + this.form.showValidation = true; + + if (!this.form.state) { + return; + } + this.isSaving = true; + this.form.showValidation = false; const { projectId } = this; - const { name, slug, description, visibility } = this.fork; - const { id: namespaceId } = this.selectedNamespace; + const { name, slug, description, visibility, namespace } = this.form.fields; const postParams = { id: projectId, - name, - namespace_id: namespaceId, - path: slug, - description, - visibility, + name: name.value, + namespace_id: namespace.value.id, + path: slug.value, + description: description.value, + visibility: visibility.value, }; const forkProjectPath = `/api/:version/projects/:id/fork`; @@ -198,16 +231,34 @@ export default { </script> <template> - <gl-form method="POST" @submit.prevent="onSubmit"> + <gl-form novalidate method="POST" @submit.prevent="onSubmit"> <input type="hidden" name="authenticity_token" :value="$options.csrf.token" /> - <gl-form-group label="Project name" label-for="fork-name"> - <gl-form-input id="fork-name" v-model="fork.name" data-testid="fork-name-input" required /> + <gl-form-group + :label="__('Project name')" + label-for="fork-name" + :invalid-feedback="form.fields.name.feedback" + > + <gl-form-input + id="fork-name" + v-model="form.fields.name.value" + v-validation:[form.showValidation] + name="name" + data-testid="fork-name-input" + :state="form.fields.name.state" + required + /> </gl-form-group> <div class="gl-md-display-flex"> <div class="gl-flex-basis-half"> - <gl-form-group label="Project URL" label-for="fork-url" class="gl-md-mr-3"> + <gl-form-group + :label="__('Project URL')" + label-for="fork-url" + class="gl-md-mr-3" + :state="form.fields.namespace.state" + :invalid-feedback="s__('ForkProject|Please select a namespace')" + > <gl-form-input-group> <template #prepend> <gl-input-group-text> @@ -216,9 +267,12 @@ export default { </template> <gl-form-select id="fork-url" - v-model="selectedNamespace" + v-model="form.fields.namespace.value" + v-validation:[form.showValidation] + name="namespace" data-testid="fork-url-input" data-qa-selector="fork_namespace_dropdown" + :state="form.fields.namespace.state" required > <template slot="first"> @@ -232,11 +286,19 @@ export default { </gl-form-group> </div> <div class="gl-flex-basis-half"> - <gl-form-group label="Project slug" label-for="fork-slug" class="gl-md-ml-3"> + <gl-form-group + :label="__('Project slug')" + label-for="fork-slug" + class="gl-md-ml-3" + :invalid-feedback="form.fields.slug.feedback" + > <gl-form-input id="fork-slug" - v-model="fork.slug" + v-model="form.fields.slug.value" + v-validation:[form.showValidation] data-testid="fork-slug-input" + name="slug" + :state="form.fields.slug.state" required /> </gl-form-group> @@ -250,11 +312,13 @@ export default { </gl-link> </p> - <gl-form-group label="Project description (optional)" label-for="fork-description"> + <gl-form-group :label="__('Project description (optional)')" label-for="fork-description"> <gl-form-textarea id="fork-description" - v-model="fork.description" + v-model="form.fields.description.value" data-testid="fork-description-textarea" + name="description" + :state="form.fields.description.state" /> </gl-form-group> @@ -266,8 +330,9 @@ export default { </gl-link> </label> <gl-form-radio-group - v-model="fork.visibility" + v-model="form.fields.visibility.value" data-testid="fork-visibility-radio-group" + name="visibility" required > <gl-form-radio @@ -291,6 +356,7 @@ export default { type="submit" category="primary" variant="confirm" + class="js-no-auto-disable" data-testid="submit-button" data-qa-selector="fork_project_button" :loading="isSaving" |