Commit e3c3c67b25e2601194293885818ff4dfb39885cd
Exists in
master
and in
4 other branches
Merge pull request #2787 from gitlabhq/features/projects_page
Feature: Projects page
Showing
20 changed files
with
173 additions
and
93 deletions
Show diff stats
app/controllers/dashboard_controller.rb
1 | class DashboardController < ApplicationController | 1 | class DashboardController < ApplicationController |
2 | respond_to :html | 2 | respond_to :html |
3 | 3 | ||
4 | - before_filter :projects | ||
5 | - before_filter :event_filter, only: :index | 4 | + before_filter :load_projects |
5 | + before_filter :event_filter, only: :show | ||
6 | 6 | ||
7 | - def index | 7 | + def show |
8 | @groups = current_user.authorized_groups | 8 | @groups = current_user.authorized_groups |
9 | - | ||
10 | @has_authorized_projects = @projects.count > 0 | 9 | @has_authorized_projects = @projects.count > 0 |
11 | - | ||
12 | - @projects = case params[:scope] | ||
13 | - when 'personal' then | ||
14 | - @projects.personal(current_user) | ||
15 | - when 'joined' then | ||
16 | - @projects.joined(current_user) | ||
17 | - else | ||
18 | - @projects | ||
19 | - end | ||
20 | - | ||
21 | @teams = current_user.authorized_teams | 10 | @teams = current_user.authorized_teams |
22 | - | ||
23 | - @projects = @projects.page(params[:page]).per(30) | 11 | + @projects_count = @projects.count |
12 | + @projects = @projects.limit(20) | ||
24 | 13 | ||
25 | @events = Event.in_projects(current_user.authorized_projects.pluck(:id)) | 14 | @events = Event.in_projects(current_user.authorized_projects.pluck(:id)) |
26 | @events = @event_filter.apply_filter(@events) | 15 | @events = @event_filter.apply_filter(@events) |
@@ -35,6 +24,19 @@ class DashboardController < ApplicationController | @@ -35,6 +24,19 @@ class DashboardController < ApplicationController | ||
35 | end | 24 | end |
36 | end | 25 | end |
37 | 26 | ||
27 | + def projects | ||
28 | + @projects = case params[:scope] | ||
29 | + when 'personal' then | ||
30 | + @projects.personal(current_user) | ||
31 | + when 'joined' then | ||
32 | + @projects.joined(current_user) | ||
33 | + else | ||
34 | + @projects | ||
35 | + end | ||
36 | + | ||
37 | + @projects = @projects.page(params[:page]).per(30) | ||
38 | + end | ||
39 | + | ||
38 | # Get authored or assigned open merge requests | 40 | # Get authored or assigned open merge requests |
39 | def merge_requests | 41 | def merge_requests |
40 | @merge_requests = current_user.cared_merge_requests | 42 | @merge_requests = current_user.cared_merge_requests |
@@ -57,7 +59,7 @@ class DashboardController < ApplicationController | @@ -57,7 +59,7 @@ class DashboardController < ApplicationController | ||
57 | 59 | ||
58 | protected | 60 | protected |
59 | 61 | ||
60 | - def projects | 62 | + def load_projects |
61 | @projects = current_user.authorized_projects.sorted_by_activity | 63 | @projects = current_user.authorized_projects.sorted_by_activity |
62 | end | 64 | end |
63 | 65 |
app/helpers/dashboard_helper.rb
@@ -9,9 +9,9 @@ module DashboardHelper | @@ -9,9 +9,9 @@ module DashboardHelper | ||
9 | 9 | ||
10 | case entity | 10 | case entity |
11 | when 'issue' then | 11 | when 'issue' then |
12 | - dashboard_issues_path(options) | 12 | + issues_dashboard_path(options) |
13 | when 'merge_request' | 13 | when 'merge_request' |
14 | - dashboard_merge_requests_path(options) | 14 | + merge_requests_dashboard_path(options) |
15 | end | 15 | end |
16 | end | 16 | end |
17 | 17 |
app/helpers/projects_helper.rb
@@ -55,7 +55,9 @@ module ProjectsHelper | @@ -55,7 +55,9 @@ module ProjectsHelper | ||
55 | 55 | ||
56 | def project_title project | 56 | def project_title project |
57 | if project.group | 57 | if project.group |
58 | - project.name_with_namespace | 58 | + content_tag :span do |
59 | + link_to(project.group.name, group_path(project.group)) + " / " + project.name | ||
60 | + end | ||
59 | else | 61 | else |
60 | project.name | 62 | project.name |
61 | end | 63 | end |
app/views/dashboard/_projects.html.haml
@@ -2,19 +2,12 @@ | @@ -2,19 +2,12 @@ | ||
2 | %h5.title | 2 | %h5.title |
3 | Projects | 3 | Projects |
4 | %small | 4 | %small |
5 | - (#{projects.total_count}) | 5 | + (#{@projects_count}) |
6 | - if current_user.can_create_project? | 6 | - if current_user.can_create_project? |
7 | %span.right | 7 | %span.right |
8 | = link_to new_project_path, class: "btn very_small info" do | 8 | = link_to new_project_path, class: "btn very_small info" do |
9 | %i.icon-plus | 9 | %i.icon-plus |
10 | New Project | 10 | New Project |
11 | - %ul.nav.nav-projects-tabs | ||
12 | - = nav_tab :scope, nil do | ||
13 | - = link_to "All", dashboard_path | ||
14 | - = nav_tab :scope, 'personal' do | ||
15 | - = link_to "Personal", dashboard_path(scope: 'personal') | ||
16 | - = nav_tab :scope, 'joined' do | ||
17 | - = link_to "Joined", dashboard_path(scope: 'joined') | ||
18 | 11 | ||
19 | %ul.well-list | 12 | %ul.well-list |
20 | - projects.each do |project| | 13 | - projects.each do |project| |
@@ -33,4 +26,6 @@ | @@ -33,4 +26,6 @@ | ||
33 | - if projects.blank? | 26 | - if projects.blank? |
34 | %li | 27 | %li |
35 | %h3.nothing_here_message There are no projects here. | 28 | %h3.nothing_here_message There are no projects here. |
36 | - .bottom= paginate projects, theme: "gitlab" | 29 | + - if @projects_count > 20 |
30 | + %li.bottom | ||
31 | + %strong= link_to "show all projects", projects_dashboard_path |
app/views/dashboard/index.atom.builder
@@ -1,30 +0,0 @@ | @@ -1,30 +0,0 @@ | ||
1 | -xml.instruct! | ||
2 | -xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do | ||
3 | - xml.title "Dashboard feed#{" - #{current_user.name}" if current_user.name.present?}" | ||
4 | - xml.link :href => projects_url(:atom), :rel => "self", :type => "application/atom+xml" | ||
5 | - xml.link :href => projects_url, :rel => "alternate", :type => "text/html" | ||
6 | - xml.id projects_url | ||
7 | - xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? | ||
8 | - | ||
9 | - @events.each do |event| | ||
10 | - if event.proper? | ||
11 | - event = EventDecorator.decorate(event) | ||
12 | - xml.entry do | ||
13 | - event_link = event.feed_url | ||
14 | - event_title = event.feed_title | ||
15 | - event_summary = event.feed_summary | ||
16 | - | ||
17 | - xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" | ||
18 | - xml.link :href => event_link | ||
19 | - xml.title truncate(event_title, :length => 80) | ||
20 | - xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
21 | - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email) | ||
22 | - xml.author do |author| | ||
23 | - xml.name event.author_name | ||
24 | - xml.email event.author_email | ||
25 | - end | ||
26 | - xml.summary(:type => "xhtml") { |x| x << event_summary unless event_summary.nil? } | ||
27 | - end | ||
28 | - end | ||
29 | - end | ||
30 | -end |
app/views/dashboard/index.html.haml
app/views/dashboard/index.js.haml
app/views/dashboard/issues.atom.builder
1 | xml.instruct! | 1 | xml.instruct! |
2 | xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do | 2 | xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do |
3 | xml.title "#{current_user.name} issues" | 3 | xml.title "#{current_user.name} issues" |
4 | - xml.link :href => dashboard_issues_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml" | ||
5 | - xml.link :href => dashboard_issues_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html" | ||
6 | - xml.id dashboard_issues_url(:private_token => current_user.private_token) | 4 | + xml.link :href => issues_dashboard_url(:atom, :private_token => current_user.private_token), :rel => "self", :type => "application/atom+xml" |
5 | + xml.link :href => issues_dashboard_url(:private_token => current_user.private_token), :rel => "alternate", :type => "text/html" | ||
6 | + xml.id issues_dashboard_url(:private_token => current_user.private_token) | ||
7 | xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? | 7 | xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? |
8 | 8 | ||
9 | @issues.each do |issue| | 9 | @issues.each do |issue| |
@@ -0,0 +1,56 @@ | @@ -0,0 +1,56 @@ | ||
1 | +%h3.page_title | ||
2 | + Projects | ||
3 | + %span | ||
4 | + (#{@projects.total_count}) | ||
5 | + - if current_user.can_create_project? | ||
6 | + %span.right | ||
7 | + = link_to new_project_path, class: "btn very_small info" do | ||
8 | + %i.icon-plus | ||
9 | + New Project | ||
10 | + | ||
11 | + | ||
12 | +%hr | ||
13 | +.row | ||
14 | + .span3 | ||
15 | + %ul.nav.nav-pills.nav-stacked | ||
16 | + = nav_tab :scope, nil do | ||
17 | + = link_to "All", projects_dashboard_path | ||
18 | + = nav_tab :scope, 'personal' do | ||
19 | + = link_to "Personal", projects_dashboard_path(scope: 'personal') | ||
20 | + = nav_tab :scope, 'joined' do | ||
21 | + = link_to "Joined", projects_dashboard_path(scope: 'joined') | ||
22 | + | ||
23 | + .span9 | ||
24 | + = form_tag projects_dashboard_path, method: 'get' do | ||
25 | + %fieldset.dashboard-search-filter | ||
26 | + = hidden_field_tag "scope", params[:scope] | ||
27 | + = search_field_tag "search", params[:search], { placeholder: 'Search', class: 'left input-xxlarge' } | ||
28 | + = button_tag type: 'submit', class: 'btn' do | ||
29 | + %i.icon-search | ||
30 | + | ||
31 | + %ul.well-list | ||
32 | + - @projects.each do |project| | ||
33 | + %li.clearfix | ||
34 | + .left | ||
35 | + = link_to project_path(project), class: dom_class(project) do | ||
36 | + - if project.namespace | ||
37 | + = project.namespace.human_name | ||
38 | + \/ | ||
39 | + %strong.well-title | ||
40 | + = truncate(project.name, length: 25) | ||
41 | + %br | ||
42 | + %small.light | ||
43 | + %strong Last activity: | ||
44 | + %span= project_last_activity(project) | ||
45 | + .right.light | ||
46 | + - if project.owner == current_user | ||
47 | + %i.icon-wrench | ||
48 | + - tm = project.team.get_tm(current_user.id) | ||
49 | + - if tm | ||
50 | + = tm.project_access_human | ||
51 | + | ||
52 | + - if @projects.blank? | ||
53 | + %li | ||
54 | + %h3.nothing_here_message There are no projects here. | ||
55 | + .bottom= paginate @projects, theme: "gitlab" | ||
56 | + |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +xml.instruct! | ||
2 | +xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do | ||
3 | + xml.title "Dashboard feed#{" - #{current_user.name}" if current_user.name.present?}" | ||
4 | + xml.link :href => projects_url(:atom), :rel => "self", :type => "application/atom+xml" | ||
5 | + xml.link :href => projects_url, :rel => "alternate", :type => "text/html" | ||
6 | + xml.id projects_url | ||
7 | + xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any? | ||
8 | + | ||
9 | + @events.each do |event| | ||
10 | + if event.proper? | ||
11 | + event = EventDecorator.decorate(event) | ||
12 | + xml.entry do | ||
13 | + event_link = event.feed_url | ||
14 | + event_title = event.feed_title | ||
15 | + event_summary = event.feed_summary | ||
16 | + | ||
17 | + xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" | ||
18 | + xml.link :href => event_link | ||
19 | + xml.title truncate(event_title, :length => 80) | ||
20 | + xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") | ||
21 | + xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email) | ||
22 | + xml.author do |author| | ||
23 | + xml.name event.author_name | ||
24 | + xml.email event.author_email | ||
25 | + end | ||
26 | + xml.summary(:type => "xhtml") { |x| x << event_summary unless event_summary.nil? } | ||
27 | + end | ||
28 | + end | ||
29 | + end | ||
30 | +end |
app/views/groups/issues.atom.builder
1 | xml.instruct! | 1 | xml.instruct! |
2 | xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do | 2 | xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do |
3 | xml.title "#{@user.name} issues" | 3 | xml.title "#{@user.name} issues" |
4 | - xml.link :href => dashboard_issues_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml" | ||
5 | - xml.link :href => dashboard_issues_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html" | ||
6 | - xml.id dashboard_issues_url(:private_token => @user.private_token) | 4 | + xml.link :href => issues_dashboard_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml" |
5 | + xml.link :href => issues_dashboard_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html" | ||
6 | + xml.id issues_dashboard_url(:private_token => @user.private_token) | ||
7 | xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? | 7 | xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any? |
8 | 8 | ||
9 | @issues.each do |issue| | 9 | @issues.each do |issue| |
app/views/layouts/application.html.haml
@@ -6,14 +6,17 @@ | @@ -6,14 +6,17 @@ | ||
6 | = render "layouts/head_panel", title: "Dashboard" | 6 | = render "layouts/head_panel", title: "Dashboard" |
7 | .container | 7 | .container |
8 | %ul.main_menu | 8 | %ul.main_menu |
9 | - = nav_link(path: 'dashboard#index', html_options: {class: 'home'}) do | 9 | + = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do |
10 | = link_to "Home", root_path, title: "Home" | 10 | = link_to "Home", root_path, title: "Home" |
11 | + = nav_link(path: 'dashboard#projects') do | ||
12 | + = link_to projects_dashboard_path do | ||
13 | + Projects | ||
11 | = nav_link(path: 'dashboard#issues') do | 14 | = nav_link(path: 'dashboard#issues') do |
12 | - = link_to dashboard_issues_path do | 15 | + = link_to issues_dashboard_path do |
13 | Issues | 16 | Issues |
14 | %span.count= current_user.assigned_issues.opened.count | 17 | %span.count= current_user.assigned_issues.opened.count |
15 | = nav_link(path: 'dashboard#merge_requests') do | 18 | = nav_link(path: 'dashboard#merge_requests') do |
16 | - = link_to dashboard_merge_requests_path do | 19 | + = link_to merge_requests_dashboard_path do |
17 | Merge Requests | 20 | Merge Requests |
18 | %span.count= current_user.cared_merge_requests.opened.count | 21 | %span.count= current_user.cared_merge_requests.opened.count |
19 | = nav_link(path: 'search#show') do | 22 | = nav_link(path: 'search#show') do |
config/routes.rb
@@ -118,9 +118,13 @@ Gitlab::Application.routes.draw do | @@ -118,9 +118,13 @@ Gitlab::Application.routes.draw do | ||
118 | # | 118 | # |
119 | # Dashboard Area | 119 | # Dashboard Area |
120 | # | 120 | # |
121 | - get "dashboard" => "dashboard#index" | ||
122 | - get "dashboard/issues" => "dashboard#issues" | ||
123 | - get "dashboard/merge_requests" => "dashboard#merge_requests" | 121 | + resource :dashboard, controller: "dashboard" do |
122 | + member do | ||
123 | + get :projects | ||
124 | + get :issues | ||
125 | + get :merge_requests | ||
126 | + end | ||
127 | + end | ||
124 | 128 | ||
125 | # | 129 | # |
126 | # Groups Area | 130 | # Groups Area |
@@ -284,5 +288,5 @@ Gitlab::Application.routes.draw do | @@ -284,5 +288,5 @@ Gitlab::Application.routes.draw do | ||
284 | end | 288 | end |
285 | end | 289 | end |
286 | 290 | ||
287 | - root to: "dashboard#index" | 291 | + root to: "dashboard#show" |
288 | end | 292 | end |
features/steps/dashboard/dashboard.rb
@@ -63,6 +63,12 @@ class Dashboard < Spinach::FeatureSteps | @@ -63,6 +63,12 @@ class Dashboard < Spinach::FeatureSteps | ||
63 | @project.team << [current_user, :master] | 63 | @project.team << [current_user, :master] |
64 | end | 64 | end |
65 | 65 | ||
66 | + Then 'I should see projects list' do | ||
67 | + @user.authorized_projects.all.each do |project| | ||
68 | + page.should have_link project.name_with_namespace | ||
69 | + end | ||
70 | + end | ||
71 | + | ||
66 | Then 'I should see groups list' do | 72 | Then 'I should see groups list' do |
67 | Group.all.each do |group| | 73 | Group.all.each do |group| |
68 | page.should have_link group.name | 74 | page.should have_link group.name |
features/steps/shared/paths.rb
@@ -33,12 +33,16 @@ module SharedPaths | @@ -33,12 +33,16 @@ module SharedPaths | ||
33 | visit dashboard_path | 33 | visit dashboard_path |
34 | end | 34 | end |
35 | 35 | ||
36 | + Given 'I visit dashboard projects page' do | ||
37 | + visit projects_dashboard_path | ||
38 | + end | ||
39 | + | ||
36 | Given 'I visit dashboard issues page' do | 40 | Given 'I visit dashboard issues page' do |
37 | - visit dashboard_issues_path | 41 | + visit issues_dashboard_path |
38 | end | 42 | end |
39 | 43 | ||
40 | Given 'I visit dashboard merge requests page' do | 44 | Given 'I visit dashboard merge requests page' do |
41 | - visit dashboard_merge_requests_path | 45 | + visit merge_requests_dashboard_path |
42 | end | 46 | end |
43 | 47 | ||
44 | Given 'I visit dashboard search page' do | 48 | Given 'I visit dashboard search page' do |
spec/requests/atom/dashboard_issues_spec.rb
@@ -10,7 +10,7 @@ describe "Dashboard Issues Feed" do | @@ -10,7 +10,7 @@ describe "Dashboard Issues Feed" do | ||
10 | 10 | ||
11 | describe "atom feed" do | 11 | describe "atom feed" do |
12 | it "should render atom feed via private token" do | 12 | it "should render atom feed via private token" do |
13 | - visit dashboard_issues_path(:atom, private_token: user.private_token) | 13 | + visit issues_dashboard_path(:atom, private_token: user.private_token) |
14 | 14 | ||
15 | page.response_headers['Content-Type'].should have_content("application/atom+xml") | 15 | page.response_headers['Content-Type'].should have_content("application/atom+xml") |
16 | page.body.should have_selector("title", text: "#{user.name} issues") | 16 | page.body.should have_selector("title", text: "#{user.name} issues") |
spec/routing/routing_spec.rb
@@ -146,14 +146,14 @@ describe KeysController, "routing" do | @@ -146,14 +146,14 @@ describe KeysController, "routing" do | ||
146 | end | 146 | end |
147 | end | 147 | end |
148 | 148 | ||
149 | -# dashboard GET /dashboard(.:format) dashboard#index | 149 | +# dashboard GET /dashboard(.:format) dashboard#show |
150 | # dashboard_issues GET /dashboard/issues(.:format) dashboard#issues | 150 | # dashboard_issues GET /dashboard/issues(.:format) dashboard#issues |
151 | # dashboard_merge_requests GET /dashboard/merge_requests(.:format) dashboard#merge_requests | 151 | # dashboard_merge_requests GET /dashboard/merge_requests(.:format) dashboard#merge_requests |
152 | -# root / dashboard#index | 152 | +# root / dashboard#show |
153 | describe DashboardController, "routing" do | 153 | describe DashboardController, "routing" do |
154 | it "to #index" do | 154 | it "to #index" do |
155 | - get("/dashboard").should route_to('dashboard#index') | ||
156 | - get("/").should route_to('dashboard#index') | 155 | + get("/dashboard").should route_to('dashboard#show') |
156 | + get("/").should route_to('dashboard#show') | ||
157 | end | 157 | end |
158 | 158 | ||
159 | it "to #issues" do | 159 | it "to #issues" do |