diff options
-rw-r--r-- | app/assets/javascripts/lib/utils/text_utility.js | 10 | ||||
-rw-r--r-- | app/assets/javascripts/projects/project_import_gitlab_project.js | 16 | ||||
-rw-r--r-- | app/assets/javascripts/projects/project_new.js | 29 | ||||
-rw-r--r-- | app/views/import/gitlab_projects/new.html.haml | 9 | ||||
-rw-r--r-- | app/views/projects/_new_project_fields.html.haml | 14 | ||||
-rw-r--r-- | changelogs/unreleased/2934-create-new-project-re-add-project-name-field.yml | 5 | ||||
-rw-r--r-- | locale/gitlab.pot | 6 | ||||
-rw-r--r-- | spec/features/explore/new_menu_spec.rb | 4 | ||||
-rw-r--r-- | spec/features/projects/import_export/import_file_spec.rb | 8 | ||||
-rw-r--r-- | spec/features/projects/new_project_spec.rb | 5 | ||||
-rw-r--r-- | spec/features/projects/user_creates_project_spec.rb | 5 | ||||
-rw-r--r-- | spec/features/projects_spec.rb | 2 | ||||
-rw-r--r-- | spec/javascripts/lib/utils/text_utility_spec.js | 6 | ||||
-rw-r--r-- | spec/javascripts/projects/project_new_spec.js | 30 |
14 files changed, 124 insertions, 25 deletions
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js index 2be3c97bd95..879f94a26ec 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -49,6 +49,16 @@ export const dasherize = str => str.replace(/[_\s]+/g, '-'); export const slugify = str => str.trim().toLowerCase(); /** + * Replaces whitespaces with hyphens and converts to lower case + * @param {String} str + * @returns {String} + */ +export const slugifyWithHyphens = str => { + const regex = new RegExp(/\s+/, 'g'); + return str.toLowerCase().replace(regex, '-'); +}; + +/** * Truncates given text * * @param {String} string diff --git a/app/assets/javascripts/projects/project_import_gitlab_project.js b/app/assets/javascripts/projects/project_import_gitlab_project.js index 4e20fce1460..fbef3a0b059 100644 --- a/app/assets/javascripts/projects/project_import_gitlab_project.js +++ b/app/assets/javascripts/projects/project_import_gitlab_project.js @@ -1,9 +1,19 @@ import $ from 'jquery'; import { getParameterValues } from '../lib/utils/url_utility'; +import projectNew from './project_new'; export default () => { - const path = getParameterValues('path')[0]; + const pathParam = getParameterValues('path')[0]; + const nameParam = getParameterValues('name')[0]; + const $projectPath = $('.js-path-name'); + const $projectName = $('.js-project-name'); - // get the path url and append it in the inputS - $('.js-path-name').val(path); + // get the path url and append it in the input + $projectPath.val(pathParam); + + // get the project name from the URL and set it as input value + $projectName.val(nameParam); + + // generate slug when project name changes + $projectName.keyup(() => projectNew.onProjectNameChange($projectName, $projectPath)); }; diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js index 04badad0f34..8a079b4b38a 100644 --- a/app/assets/javascripts/projects/project_new.js +++ b/app/assets/javascripts/projects/project_new.js @@ -1,5 +1,6 @@ import $ from 'jquery'; import { addSelectOnFocusBehaviour } from '../lib/utils/common_utils'; +import { slugifyWithHyphens } from '../lib/utils/text_utility'; let hasUserDefinedProjectPath = false; @@ -29,18 +30,23 @@ const deriveProjectPathFromUrl = ($projectImportUrl) => { } }; +const onProjectNameChange = ($projectNameInput, $projectPathInput) => { + const slug = slugifyWithHyphens($projectNameInput.val()); + $projectPathInput.val(slug); +}; + const bindEvents = () => { const $newProjectForm = $('#new_project'); const $projectImportUrl = $('#project_import_url'); - const $projectPath = $('#project_path'); + const $projectPath = $('.tab-pane.active #project_path'); const $useTemplateBtn = $('.template-button > input'); const $projectFieldsForm = $('.project-fields-form'); const $selectedTemplateText = $('.selected-template'); const $changeTemplateBtn = $('.change-template'); const $selectedIcon = $('.selected-icon'); - const $templateProjectNameInput = $('#template-project-name #project_path'); const $pushNewProjectTipTrigger = $('.push-new-project-tip'); const $projectTemplateButtons = $('.project-templates-buttons'); + const $projectName = $('.tab-pane.active #project_name'); if ($newProjectForm.length !== 1) { return; @@ -57,7 +63,8 @@ const bindEvents = () => { $('.btn_import_gitlab_project').on('click', () => { const importHref = $('a.btn_import_gitlab_project').attr('href'); - $('.btn_import_gitlab_project').attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&path=${$projectPath.val()}`); + $('.btn_import_gitlab_project') + .attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&name=${$projectName.val()}&path=${$projectPath.val()}`); }); if ($pushNewProjectTipTrigger) { @@ -111,7 +118,15 @@ const bindEvents = () => { const selectedTemplate = templates[value]; $selectedTemplateText.text(selectedTemplate.text); $(selectedTemplate.icon).clone().addClass('d-block').appendTo($selectedIcon); - $templateProjectNameInput.focus(); + + const $activeTabProjectName = $('.tab-pane.active #project_name'); + const $activeTabProjectPath = $('.tab-pane.active #project_path'); + $activeTabProjectName.focus(); + $activeTabProjectName + .keyup(() => { + onProjectNameChange($activeTabProjectName, $activeTabProjectPath); + hasUserDefinedProjectPath = $activeTabProjectPath.val().trim().length > 0; + }); } $useTemplateBtn.on('change', chooseTemplate); @@ -131,9 +146,15 @@ const bindEvents = () => { }); $projectImportUrl.keyup(() => deriveProjectPathFromUrl($projectImportUrl)); + + $projectName.keyup(() => { + onProjectNameChange($projectName, $projectPath); + hasUserDefinedProjectPath = $projectPath.val().trim().length > 0; + }); }; export default { bindEvents, deriveProjectPathFromUrl, + onProjectNameChange, }; diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index 4225ee19217..c4218f3d787 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -8,8 +8,11 @@ = form_tag import_gitlab_project_path, class: 'new_project', multipart: true do .row + .form-group.project-name.col-sm-12 + = label_tag :name, _('Project name'), class: 'label-bold' + = text_field_tag :name, @name, placeholder: "My awesome project", class: "js-project-name form-control input-lg", autofocus: true, required: true .form-group.col-12.col-sm-6 - = label_tag :namespace_id, 'Project path', class: 'label-bold' + = label_tag :namespace_id, _('Project URL'), class: 'label-bold' .form-group .input-group - if current_user.can_select_namespace? @@ -24,8 +27,8 @@ #{user_url(current_user.username)}/ = hidden_field_tag :namespace_id, value: current_user.namespace_id .form-group.col-12.col-sm-6.project-path - = label_tag :path, _('Project name'), class: 'label-bold' - = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true + = label_tag :path, _('Project slug'), class: 'label-bold' + = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, required: true .row .form-group.col-md-12 diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml index ad8c7911fad..3b6090211c0 100644 --- a/app/views/projects/_new_project_fields.html.haml +++ b/app/views/projects/_new_project_fields.html.haml @@ -3,10 +3,13 @@ .row{ id: project_name_id } = f.hidden_field :ci_cd_only, value: ci_cd_only + .form-group.project-name.col-sm-12 + = f.label :name, class: 'label-bold' do + %span= _("Project name") + = f.text_field :name, placeholder: "My awesome project", class: "form-control input-lg", autofocus: true, required: true .form-group.project-path.col-sm-6 = f.label :namespace_id, class: 'label-bold' do - %span - Project path + %span= s_("Project URL") .input-group - if current_user.can_select_namespace? .input-group-prepend.has-tooltip{ title: root_url } @@ -27,13 +30,12 @@ = f.hidden_field :namespace_id, value: current_user.namespace_id .form-group.project-path.col-sm-6 = f.label :path, class: 'label-bold' do - %span - Project name - = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, autofocus: true, required: true + %span= _("Project slug") + = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, required: true - if current_user.can_create_group? .form-text.text-muted Want to house several dependent projects under the same namespace? - = link_to "Create a group", new_group_path + = link_to "Create a group.", new_group_path .form-group = f.label :description, class: 'label-bold' do diff --git a/changelogs/unreleased/2934-create-new-project-re-add-project-name-field.yml b/changelogs/unreleased/2934-create-new-project-re-add-project-name-field.yml new file mode 100644 index 00000000000..ad9136b69c2 --- /dev/null +++ b/changelogs/unreleased/2934-create-new-project-re-add-project-name-field.yml @@ -0,0 +1,5 @@ +--- +title: Re-add project name field on "Create new project" page +merge_request: 21386 +author: +type: other diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e9a92a386cb..7b6c15abd4f 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -4681,6 +4681,9 @@ msgstr "" msgid "Project Badges" msgstr "" +msgid "Project URL" +msgstr "" + msgid "Project access must be granted explicitly to each user." msgstr "" @@ -4708,6 +4711,9 @@ msgstr "" msgid "Project name" msgstr "" +msgid "Project slug" +msgstr "" + msgid "ProjectActivityRSS|Subscribe" msgstr "" diff --git a/spec/features/explore/new_menu_spec.rb b/spec/features/explore/new_menu_spec.rb index 0a88988ea09..11f05b6d220 100644 --- a/spec/features/explore/new_menu_spec.rb +++ b/spec/features/explore/new_menu_spec.rb @@ -20,7 +20,7 @@ describe 'Top Plus Menu', :js do click_topmenuitem("New project") - expect(page).to have_content('Project path') + expect(page).to have_content('Project URL') expect(page).to have_content('Project name') end @@ -92,7 +92,7 @@ describe 'Top Plus Menu', :js do find('.header-new-group-project a').click end - expect(page).to have_content('Project path') + expect(page).to have_content('Project URL') expect(page).to have_content('Project name') end end diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 2936482a1f7..6cd5810325f 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -20,6 +20,7 @@ describe 'Import/Export - project import integration test', :js do context 'when selecting the namespace' do let(:user) { create(:admin) } let!(:namespace) { user.namespace } + let(:project_name) { 'Test Project Name' + SecureRandom.hex } let(:project_path) { 'test-project-path' + SecureRandom.hex } context 'prefilled the path' do @@ -27,12 +28,13 @@ describe 'Import/Export - project import integration test', :js do visit new_project_path select2(namespace.id, from: '#project_namespace_id') + fill_in :project_name, with: project_name, visible: true fill_in :project_path, with: project_path, visible: true click_import_project_tab click_link 'GitLab export' expect(page).to have_content('Import an exported GitLab project') - expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&path=#{project_path}") + expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&name=#{ERB::Util.url_encode(project_name)}&path=#{project_path}") attach_file('file', file) click_on 'Import project' @@ -56,6 +58,7 @@ describe 'Import/Export - project import integration test', :js do click_import_project_tab click_link 'GitLab export' + fill_in :name, with: 'Test Project Name', visible: true fill_in :path, with: 'test-project-path', visible: true attach_file('file', file) @@ -74,7 +77,8 @@ describe 'Import/Export - project import integration test', :js do visit new_project_path select2(user.namespace.id, from: '#project_namespace_id') - fill_in :project_path, with: project.name, visible: true + fill_in :project_name, with: project.name, visible: true + fill_in :project_path, with: project.path, visible: true click_import_project_tab click_link 'GitLab export' attach_file('file', file) diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index bbe08ff83ff..0acd5059385 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -12,8 +12,9 @@ describe 'New project' do it 'shows "New project" page', :js do visit new_project_path - expect(page).to have_content('Project path') expect(page).to have_content('Project name') + expect(page).to have_content('Project URL') + expect(page).to have_content('Project slug') find('#import-project-tab').click @@ -187,7 +188,7 @@ describe 'New project' do collision_project = create(:project, name: 'test-name-collision', namespace: user.namespace) fill_in 'project_import_url', with: collision_project.http_url_to_repo - fill_in 'project_path', with: collision_project.path + fill_in 'project_name', with: collision_project.name click_on 'Create project' diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb index 83d18996f4e..8d7e2883b2a 100644 --- a/spec/features/projects/user_creates_project_spec.rb +++ b/spec/features/projects/user_creates_project_spec.rb @@ -11,7 +11,7 @@ describe 'User creates a project', :js do it 'creates a new project' do visit(new_project_path) - fill_in(:project_path, with: 'Empty') + fill_in(:project_name, with: 'Empty') page.within('#content-body') do click_button('Create project') @@ -37,6 +37,7 @@ describe 'User creates a project', :js do it 'creates a new project' do visit(new_project_path) + fill_in :project_name, with: 'A Subgroup Project' fill_in :project_path, with: 'a-subgroup-project' page.find('.js-select-namespace').click @@ -46,7 +47,7 @@ describe 'User creates a project', :js do click_button('Create project') end - expect(page).to have_content("Project 'a-subgroup-project' was successfully created") + expect(page).to have_content("Project 'A Subgroup Project' was successfully created") project = Project.last diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 22e3a99072f..8e310f38a8c 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -16,7 +16,7 @@ describe 'Project' do it "allows creation from templates", :js do find('#create-from-template-tab').click find("label[for=#{template.name}]").click - fill_in("project_path", with: template.name) + fill_in("project_name", with: template.name) page.within '#content-body' do click_button "Create project" diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js index d60485b1308..ac3270baef5 100644 --- a/spec/javascripts/lib/utils/text_utility_spec.js +++ b/spec/javascripts/lib/utils/text_utility_spec.js @@ -63,6 +63,12 @@ describe('text_utility', () => { }); }); + describe('slugifyWithHyphens', () => { + it('should replaces whitespaces with hyphens and convert to lower case', () => { + expect(textUtils.slugifyWithHyphens('My Input String')).toEqual('my-input-string'); + }); + }); + describe('stripHtml', () => { it('replaces html tag with the default replacement', () => { expect(textUtils.stripHtml('This is a text with <p>html</p>.')).toEqual( diff --git a/spec/javascripts/projects/project_new_spec.js b/spec/javascripts/projects/project_new_spec.js index 84515d2bf97..dace834a3c8 100644 --- a/spec/javascripts/projects/project_new_spec.js +++ b/spec/javascripts/projects/project_new_spec.js @@ -4,12 +4,14 @@ import projectNew from '~/projects/project_new'; describe('New Project', () => { let $projectImportUrl; let $projectPath; + let $projectName; beforeEach(() => { setFixtures(` <div class='toggle-import-form'> <div class='import-url-data'> <input id="project_import_url" /> + <input id="project_name" /> <input id="project_path" /> </div> </div> @@ -17,6 +19,7 @@ describe('New Project', () => { $projectImportUrl = $('#project_import_url'); $projectPath = $('#project_path'); + $projectName = $('#project_name'); }); describe('deriveProjectPathFromUrl', () => { @@ -129,4 +132,31 @@ describe('New Project', () => { }); }); }); + + describe('deriveSlugFromProjectName', () => { + beforeEach(() => { + projectNew.bindEvents(); + $projectName.val('').keyup(); + }); + + it('converts project name to lower case and dash-limited slug', () => { + const dummyProjectName = 'My Awesome Project'; + + $projectName.val(dummyProjectName); + + projectNew.onProjectNameChange($projectName, $projectPath); + + expect($projectPath.val()).toEqual('my-awesome-project'); + }); + + it('does not add additional dashes in the slug if the project name already contains dashes', () => { + const dummyProjectName = 'My-Dash-Delimited Awesome Project'; + + $projectName.val(dummyProjectName); + + projectNew.onProjectNameChange($projectName, $projectPath); + + expect($projectPath.val()).toEqual('my-dash-delimited-awesome-project'); + }); + }); }); |