summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Schatz <jschatz1@gmail.com>2016-02-02 22:15:40 +0000
committerJacob Schatz <jschatz1@gmail.com>2016-02-02 22:15:40 +0000
commitc4c919e59ded2fbf29dc3085b6621e02c0b10f54 (patch)
treeeac5b7cf6dea034dab72c5be22354c11d41aa41d
parenta12ac9c060018071d75c7b1e9d9ee3b90cb4d792 (diff)
parent15bc1a01ab31b4288a3dea429cb7d77d272afbe5 (diff)
downloadgitlab-ce-c4c919e59ded2fbf29dc3085b6621e02c0b10f54.tar.gz
Merge branch 'title-projects-dropdown' into 'master'
Added dropdown to list all projects on project header Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/4212 When clicking the current project name, it shows a dropdown menu with a list of all projects for that group or user. When closed: ![Screen_Shot_2016-01-14_at_19.17.44](/uploads/a7258ba388dba238fc2f0468711fc729/Screen_Shot_2016-01-14_at_19.17.44.png) When open: ![Screen_Shot_2016-01-14_at_19.17.51](/uploads/716533d9eb44b123c5fdff36a4740489/Screen_Shot_2016-01-14_at_19.17.51.png) cc. @jschatz1 See merge request !2438
-rw-r--r--app/assets/javascripts/project.js.coffee16
-rw-r--r--app/assets/stylesheets/framework/common.scss4
-rw-r--r--app/assets/stylesheets/framework/header.scss8
-rw-r--r--app/helpers/projects_helper.rb13
-rw-r--r--app/views/shared/_new_project_item_select.html.haml8
-rw-r--r--spec/features/projects_spec.rb21
-rw-r--r--spec/javascripts/fixtures/project_title.html.haml7
-rw-r--r--spec/javascripts/fixtures/projects.json1
-rw-r--r--spec/javascripts/project_title_spec.js.coffee46
9 files changed, 112 insertions, 12 deletions
diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee
index d7a658f8faa..76bc4ff42a2 100644
--- a/app/assets/javascripts/project.js.coffee
+++ b/app/assets/javascripts/project.js.coffee
@@ -50,3 +50,19 @@ class @Project
$('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>")
$(@).parents('ul').find('li.active').removeClass 'active'
$(@).parent().addClass 'active'
+
+ @projectSelectDropdown()
+
+ projectSelectDropdown: ->
+ new ProjectSelect()
+
+ $('.project-item-select').on 'click', (e) =>
+ @changeProject $(e.currentTarget).val()
+
+ $('.js-projects-dropdown-toggle').on 'click', (e) ->
+ e.preventDefault()
+
+ $('.js-projects-dropdown').select2('open')
+
+ changeProject: (url) ->
+ window.location = url
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 6ea2219073c..ea56d9e12a0 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -376,11 +376,11 @@ table {
margin-bottom: $gl-padding;
}
-.new-project-item-select-holder {
+.project-item-select-holder {
display: inline-block;
position: relative;
- .new-project-item-select {
+ .project-item-select {
position: absolute;
top: 0;
right: 0;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index f875b1460e7..7871a33b6c5 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -73,7 +73,6 @@ header {
.title {
margin: 0;
- overflow: hidden;
font-size: 19px;
line-height: $header-height;
font-weight: normal;
@@ -88,6 +87,13 @@ header {
text-decoration: underline;
}
}
+
+ .dropdown-toggle-caret {
+ position: relative;
+ top: -2px;
+ margin-left: 5px;
+ font-size: 10px;
+ }
}
.navbar-collapse {
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 8c8b355028c..e7e472cbb5b 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -53,14 +53,19 @@ module ProjectsHelper
link_to(simple_sanitize(owner.name), user_path(owner))
end
- project_link = link_to(simple_sanitize(project.name), project_path(project))
+ project_link = link_to project_path(project), { class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}" } do
+ link_output = simple_sanitize(project.name)
+ link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user
+
+ link_output += project_select_tag :project_path, class: "project-item-select js-projects-dropdown", data: { include_groups: false } if current_user
+
+ link_output
+ end
full_title = namespace_link + ' / ' + project_link
full_title += ' &middot; '.html_safe + link_to(simple_sanitize(name), url) if name
- content_tag :span do
- full_title
- end
+ full_title
end
def remove_project_message(project)
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
index c4431d66927..46095912821 100644
--- a/app/views/shared/_new_project_item_select.html.haml
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -1,6 +1,6 @@
- if @projects.any?
- .prepend-left-10.new-project-item-select-holder
- = project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] }
+ .prepend-left-10.project-item-select-holder
+ = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups] }
%a.btn.btn-new.new-project-item-select-button
= icon('plus')
= local_assigns[:label]
@@ -8,12 +8,12 @@
:javascript
$('.new-project-item-select-button').on('click', function() {
- $('.new-project-item-select').select2('open');
+ $('.project-item-select').select2('open');
});
var relativePath = '#{local_assigns[:path]}';
- $('.new-project-item-select').on('click', function() {
+ $('.project-item-select').on('click', function() {
window.location = $(this).val() + '/' + relativePath;
});
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 9a01c89ae2a..ed97b6cb577 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -82,7 +82,26 @@ feature 'Project', feature: true do
it 'click project-settings and find leave project' do
find('#project-settings-button').click
- expect(page).to have_link('Leave Project')
+ expect(page).to have_link('Leave Project')
+ end
+ end
+
+ describe 'project title' do
+ include WaitForAjax
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ before do
+ login_with(user)
+ project.team.add_user(user, Gitlab::Access::MASTER)
+ visit namespace_project_path(project.namespace, project)
+ end
+
+ it 'click toggle and show dropdown', js: true do
+ find('.js-projects-dropdown-toggle').click
+ wait_for_ajax
+ expect(page).to have_css('.select2-results li', count: 1)
end
end
diff --git a/spec/javascripts/fixtures/project_title.html.haml b/spec/javascripts/fixtures/project_title.html.haml
new file mode 100644
index 00000000000..4286d1be669
--- /dev/null
+++ b/spec/javascripts/fixtures/project_title.html.haml
@@ -0,0 +1,7 @@
+%h1.title
+ %a
+ GitLab Org
+ %a.project-item-select-holder.js-projects-dropdown-toggle{href: "/gitlab-org/gitlab-test"}
+ GitLab Test
+ %span.fa.fa-chevron-down.dropdown-toggle-caret
+ %input#project_path.project-item-select.js-projects-dropdown.ajax-project-select{type: "hidden", name: "project_path", "data-include-groups" => "false"}
diff --git a/spec/javascripts/fixtures/projects.json b/spec/javascripts/fixtures/projects.json
new file mode 100644
index 00000000000..84e8d0ba1e4
--- /dev/null
+++ b/spec/javascripts/fixtures/projects.json
@@ -0,0 +1 @@
+[{"id":9,"description":"","default_branch":null,"tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:root/test.git","http_url_to_repo":"http://localhost:3000/root/test.git","web_url":"http://localhost:3000/root/test","owner":{"name":"Administrator","username":"root","id":1,"state":"active","avatar_url":"http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon","web_url":"http://localhost:3000/u/root"},"name":"test","name_with_namespace":"Administrator / test","path":"test","path_with_namespace":"root/test","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-14T19:08:05.364Z","last_activity_at":"2016-01-14T19:08:07.418Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":1,"name":"root","path":"root","owner_id":1,"created_at":"2016-01-13T20:19:44.439Z","updated_at":"2016-01-13T20:19:44.439Z","description":"","avatar":null},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":0,"permissions":{"project_access":null,"group_access":null}},{"id":8,"description":"Voluptatem quae nulla eius numquam ullam voluptatibus quia modi.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:h5bp/html5-boilerplate.git","http_url_to_repo":"http://localhost:3000/h5bp/html5-boilerplate.git","web_url":"http://localhost:3000/h5bp/html5-boilerplate","name":"Html5 Boilerplate","name_with_namespace":"H5bp / Html5 Boilerplate","path":"html5-boilerplate","path_with_namespace":"h5bp/html5-boilerplate","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:57.525Z","last_activity_at":"2016-01-13T20:27:57.280Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":5,"name":"H5bp","path":"h5bp","owner_id":null,"created_at":"2016-01-13T20:19:57.239Z","updated_at":"2016-01-13T20:19:57.239Z","description":"Tempore accusantium possimus aut libero.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":10,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":7,"description":"Modi odio mollitia dolorem qui.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:twitter/typeahead-js.git","http_url_to_repo":"http://localhost:3000/twitter/typeahead-js.git","web_url":"http://localhost:3000/twitter/typeahead-js","name":"Typeahead.Js","name_with_namespace":"Twitter / Typeahead.Js","path":"typeahead-js","path_with_namespace":"twitter/typeahead-js","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:56.212Z","last_activity_at":"2016-01-13T20:27:51.496Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":4,"name":"Twitter","path":"twitter","owner_id":null,"created_at":"2016-01-13T20:19:54.480Z","updated_at":"2016-01-13T20:19:54.480Z","description":"Id voluptatem ipsa maiores omnis repudiandae et et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":4,"permissions":{"project_access":null,"group_access":{"access_level":10,"notification_level":3}}},{"id":6,"description":"Omnis asperiores ipsa et beatae quidem necessitatibus quia.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:twitter/flight.git","http_url_to_repo":"http://localhost:3000/twitter/flight.git","web_url":"http://localhost:3000/twitter/flight","name":"Flight","name_with_namespace":"Twitter / Flight","path":"flight","path_with_namespace":"twitter/flight","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:54.754Z","last_activity_at":"2016-01-13T20:27:50.502Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":4,"name":"Twitter","path":"twitter","owner_id":null,"created_at":"2016-01-13T20:19:54.480Z","updated_at":"2016-01-13T20:19:54.480Z","description":"Id voluptatem ipsa maiores omnis repudiandae et et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":4,"permissions":{"project_access":null,"group_access":{"access_level":10,"notification_level":3}}},{"id":5,"description":"Voluptatem commodi voluptate placeat architecto beatae illum dolores fugiat.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-test.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-test.git","web_url":"http://localhost:3000/gitlab-org/gitlab-test","name":"Gitlab Test","name_with_namespace":"Gitlab Org / Gitlab Test","path":"gitlab-test","path_with_namespace":"gitlab-org/gitlab-test","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:53.202Z","last_activity_at":"2016-01-13T20:27:41.626Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}},{"id":4,"description":"Aut molestias quas est ut aperiam officia quod libero.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-shell.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-shell.git","web_url":"http://localhost:3000/gitlab-org/gitlab-shell","name":"Gitlab Shell","name_with_namespace":"Gitlab Org / Gitlab Shell","path":"gitlab-shell","path_with_namespace":"gitlab-org/gitlab-shell","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:51.882Z","last_activity_at":"2016-01-13T20:27:35.678Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":20,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":3,"description":"Excepturi molestiae quia repellendus omnis est illo illum eligendi.","default_branch":"master","tag_list":[],"public":true,"archived":false,"visibility_level":20,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-ci.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-ci.git","web_url":"http://localhost:3000/gitlab-org/gitlab-ci","name":"Gitlab Ci","name_with_namespace":"Gitlab Org / Gitlab Ci","path":"gitlab-ci","path_with_namespace":"gitlab-org/gitlab-ci","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:50.346Z","last_activity_at":"2016-01-13T20:27:30.115Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":3,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}},{"id":2,"description":"Adipisci quaerat dignissimos enim sed ipsam dolorem quia.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":10,"ssh_url_to_repo":"phil@localhost:gitlab-org/gitlab-ce.git","http_url_to_repo":"http://localhost:3000/gitlab-org/gitlab-ce.git","web_url":"http://localhost:3000/gitlab-org/gitlab-ce","name":"Gitlab Ce","name_with_namespace":"Gitlab Org / Gitlab Ce","path":"gitlab-ce","path_with_namespace":"gitlab-org/gitlab-ce","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:49.065Z","last_activity_at":"2016-01-13T20:26:58.454Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":3,"name":"Gitlab Org","path":"gitlab-org","owner_id":null,"created_at":"2016-01-13T20:19:48.851Z","updated_at":"2016-01-13T20:19:48.851Z","description":"Magni mollitia quod quidem soluta nesciunt impedit.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":{"access_level":30,"notification_level":3},"group_access":{"access_level":50,"notification_level":3}}},{"id":1,"description":"Vel voluptatem maxime saepe ex quia.","default_branch":"master","tag_list":[],"public":false,"archived":false,"visibility_level":0,"ssh_url_to_repo":"phil@localhost:documentcloud/underscore.git","http_url_to_repo":"http://localhost:3000/documentcloud/underscore.git","web_url":"http://localhost:3000/documentcloud/underscore","name":"Underscore","name_with_namespace":"Documentcloud / Underscore","path":"underscore","path_with_namespace":"documentcloud/underscore","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"builds_enabled":true,"snippets_enabled":false,"created_at":"2016-01-13T20:19:45.862Z","last_activity_at":"2016-01-13T20:25:03.106Z","shared_runners_enabled":true,"creator_id":1,"namespace":{"id":2,"name":"Documentcloud","path":"documentcloud","owner_id":null,"created_at":"2016-01-13T20:19:44.464Z","updated_at":"2016-01-13T20:19:44.464Z","description":"Aut impedit perferendis fuga et ipsa repellat cupiditate et.","avatar":{"url":null}},"avatar_url":null,"star_count":0,"forks_count":0,"open_issues_count":5,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}}]
diff --git a/spec/javascripts/project_title_spec.js.coffee b/spec/javascripts/project_title_spec.js.coffee
new file mode 100644
index 00000000000..47c7b7febe3
--- /dev/null
+++ b/spec/javascripts/project_title_spec.js.coffee
@@ -0,0 +1,46 @@
+#= require select2
+#= require api
+#= require project_select
+#= require project
+
+window.gon = {}
+window.gon.api_version = 'v3'
+
+describe 'Project Title', ->
+ fixture.preload('project_title.html')
+ fixture.preload('projects.json')
+
+ beforeEach ->
+ fixture.load('project_title.html')
+ @project = new Project()
+
+ spyOn(@project, 'changeProject').and.callFake (url) ->
+ window.current_project_url = url
+
+ describe 'project list', ->
+ beforeEach =>
+ @projects_data = fixture.load('projects.json')[0]
+
+ spyOn(jQuery, 'ajax').and.callFake (req) =>
+ expect(req.url).toBe('/api/v3/projects.json')
+ d = $.Deferred()
+ d.resolve @projects_data
+ d.promise()
+
+ it 'to show on toggle click', =>
+ $('.js-projects-dropdown-toggle').click()
+
+ expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(true)
+ expect($('.ajax-project-dropdown li').length).toBe(@projects_data.length)
+
+ it 'hide dropdown', ->
+ $("#select2-drop-mask").click()
+
+ expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false)
+
+ it 'change project when clicking item', ->
+ $('.js-projects-dropdown-toggle').click()
+ $('.ajax-project-dropdown li:nth-child(2)').trigger('mouseup')
+
+ expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false)
+ expect(window.current_project_url).toBe('http://localhost:3000/h5bp/html5-boilerplate')