Commit c4c919e5 authored by Jacob Schatz's avatar Jacob Schatz

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
parents a12ac9c0 15bc1a01
...@@ -50,3 +50,19 @@ class @Project ...@@ -50,3 +50,19 @@ class @Project
$('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>") $('#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' $(@).parents('ul').find('li.active').removeClass 'active'
$(@).parent().addClass '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
...@@ -376,11 +376,11 @@ table { ...@@ -376,11 +376,11 @@ table {
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
} }
.new-project-item-select-holder { .project-item-select-holder {
display: inline-block; display: inline-block;
position: relative; position: relative;
.new-project-item-select { .project-item-select {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
......
...@@ -73,7 +73,6 @@ header { ...@@ -73,7 +73,6 @@ header {
.title { .title {
margin: 0; margin: 0;
overflow: hidden;
font-size: 19px; font-size: 19px;
line-height: $header-height; line-height: $header-height;
font-weight: normal; font-weight: normal;
...@@ -88,6 +87,13 @@ header { ...@@ -88,6 +87,13 @@ header {
text-decoration: underline; text-decoration: underline;
} }
} }
.dropdown-toggle-caret {
position: relative;
top: -2px;
margin-left: 5px;
font-size: 10px;
}
} }
.navbar-collapse { .navbar-collapse {
......
...@@ -53,15 +53,20 @@ module ProjectsHelper ...@@ -53,15 +53,20 @@ module ProjectsHelper
link_to(simple_sanitize(owner.name), user_path(owner)) link_to(simple_sanitize(owner.name), user_path(owner))
end 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 = namespace_link + ' / ' + project_link
full_title += ' &middot; '.html_safe + link_to(simple_sanitize(name), url) if name full_title += ' &middot; '.html_safe + link_to(simple_sanitize(name), url) if name
content_tag :span do
full_title full_title
end end
end
def remove_project_message(project) def remove_project_message(project)
"You are going to remove #{project.name_with_namespace}.\n Removed project CANNOT be restored!\n Are you ABSOLUTELY sure?" "You are going to remove #{project.name_with_namespace}.\n Removed project CANNOT be restored!\n Are you ABSOLUTELY sure?"
......
- if @projects.any? - if @projects.any?
.prepend-left-10.new-project-item-select-holder .prepend-left-10.project-item-select-holder
= project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] } = 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 %a.btn.btn-new.new-project-item-select-button
= icon('plus') = icon('plus')
= local_assigns[:label] = local_assigns[:label]
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
:javascript :javascript
$('.new-project-item-select-button').on('click', function() { $('.new-project-item-select-button').on('click', function() {
$('.new-project-item-select').select2('open'); $('.project-item-select').select2('open');
}); });
var relativePath = '#{local_assigns[:path]}'; var relativePath = '#{local_assigns[:path]}';
$('.new-project-item-select').on('click', function() { $('.project-item-select').on('click', function() {
window.location = $(this).val() + '/' + relativePath; window.location = $(this).val() + '/' + relativePath;
}); });
......
...@@ -86,6 +86,25 @@ feature 'Project', feature: true do ...@@ -86,6 +86,25 @@ feature 'Project', feature: true do
end end
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
def remove_with_confirm(button_text, confirm_with) def remove_with_confirm(button_text, confirm_with)
click_button button_text click_button button_text
fill_in 'confirm_name_input', with: confirm_with fill_in 'confirm_name_input', with: confirm_with
......
%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"}
[{"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}}}]
#= 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')
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