diff --git a/app/assets/stylesheets/style.scss b/app/assets/stylesheets/style.scss
index b56a5d3c..ca17f04a 100644
--- a/app/assets/stylesheets/style.scss
+++ b/app/assets/stylesheets/style.scss
@@ -351,7 +351,7 @@ header h1.logo a{
text-indent: -1000em;
}
-header nav{border-radius: 4px; box-shadow: 0 1px 2px black; width: 294px; margin: auto;
+header nav{border-radius: 4px; box-shadow: 0 1px 2px black; width: 392px; margin: auto;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595d63), to(#31363e));
background-image: -webkit-linear-gradient(#595d63 6.6%, #31363e);
background-image: -moz-linear-gradient(#595d63 6.6%, #31363e);
@@ -398,6 +398,7 @@ header nav a span{width: 20px; height: 20px; display: inline-block; background:
header nav a.dashboard span{background: url('images.png') no-repeat -161px 0;}
header nav a.admin span{background: url('images.png') no-repeat -184px 0;}
header nav a.project span{background: url('images.png') no-repeat -209px -1px; top: 7px}
+header nav a.issues span{background: url('images.png') no-repeat -209px -1px; top: 7px}
header .login-top{float: right; width: 180px;
background-image: -webkit-gradient(linear, 0 0, 0 62, color-stop(0.032, #464c56), to(#363c45));
diff --git a/app/controllers/user_issues_controller.rb b/app/controllers/user_issues_controller.rb
new file mode 100644
index 00000000..4b2245a4
--- /dev/null
+++ b/app/controllers/user_issues_controller.rb
@@ -0,0 +1,21 @@
+class UserIssuesController < ApplicationController
+ before_filter :authenticate_user!
+
+ layout "user"
+
+ respond_to :js, :html
+
+ def index
+ @user = current_user
+ @issues = current_user.assigned_issues.opened
+
+ @issues = @issues.includes(:author, :project)
+
+ respond_to do |format|
+ format.html
+ format.js
+ format.atom { render :layout => false }
+ end
+ end
+
+end
diff --git a/app/controllers/user_merge_requests_controller.rb b/app/controllers/user_merge_requests_controller.rb
new file mode 100644
index 00000000..7b6710d5
--- /dev/null
+++ b/app/controllers/user_merge_requests_controller.rb
@@ -0,0 +1,9 @@
+class UserMergeRequestsController < ApplicationController
+ before_filter :authenticate_user!
+
+ layout "user"
+
+ def index
+ @merge_requests = current_user.assigned_merge_requests
+ end
+end
diff --git a/app/helpers/user_issues_helper.rb b/app/helpers/user_issues_helper.rb
new file mode 100644
index 00000000..aca7d5b8
--- /dev/null
+++ b/app/helpers/user_issues_helper.rb
@@ -0,0 +1,2 @@
+module UserIssuesHelper
+end
diff --git a/app/helpers/user_merge_requests_helper.rb b/app/helpers/user_merge_requests_helper.rb
new file mode 100644
index 00000000..6e5db315
--- /dev/null
+++ b/app/helpers/user_merge_requests_helper.rb
@@ -0,0 +1,3 @@
+module UserMergeRequestsHelper
+end
+
diff --git a/app/models/user.rb b/app/models/user.rb
index 8967859d..de0bb637 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -25,6 +25,15 @@ class User < ActiveRecord::Base
:foreign_key => :assignee_id,
:dependent => :destroy
+ has_many :merge_requests,
+ :foreign_key => :author_id,
+ :dependent => :destroy
+
+ has_many :assigned_merge_requests,
+ :class_name => "MergeRequest",
+ :foreign_key => :assignee_id,
+ :dependent => :destroy
+
before_create :ensure_authentication_token
alias_attribute :private_token, :authentication_token
scope :not_in_project, lambda { |project| where("id not in (:ids)", :ids => project.users.map(&:id) ) }
diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml
index eb0cae66..bf863a2d 100644
--- a/app/views/issues/_issues.html.haml
+++ b/app/views/issues/_issues.html.haml
@@ -1,5 +1,5 @@
- @issues.critical.each do |issue|
- = render(:partial => 'show', :locals => {:issue => issue})
+ = render(:partial => 'issues/show', :locals => {:issue => issue})
- @issues.non_critical.each do |issue|
- = render(:partial => 'show', :locals => {:issue => issue})
+ = render(:partial => 'issues/show', :locals => {:issue => issue})
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index ecb0afd1..a68659d5 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -1,4 +1,4 @@
-%tr{ :id => dom_id(issue), :class => "issue #{issue.critical ? "critical" : ""}", :url => project_issue_path(@project, issue) }
+%tr{ :id => dom_id(issue), :class => "issue #{issue.critical ? "critical" : ""}", :url => project_issue_path(issue.project, issue) }
%td
%strong.issue-number{:class => sort_class}= "##{issue.id}"
%span
@@ -6,6 +6,9 @@
%br
%br
%div.note-author
+ - if not @project.present?
+ %strong= issue.project.name
+ = '-'
%strong= issue.assignee.name
%cite.cgray
= time_ago_in_words(issue.created_at)
@@ -17,10 +20,10 @@
.right.action-links
- if can? current_user, :write_issue, issue
- if issue.closed
- = link_to 'Reopen', project_issue_path(@project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "cgray", :remote => true
+ = link_to 'Reopen', project_issue_path(issue.project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "cgray", :remote => true
- else
- = link_to 'Resolve', project_issue_path(@project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "cgray", :remote => true
+ = link_to 'Resolve', project_issue_path(issue.project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "cgray", :remote => true
- if can? current_user, :write_issue, issue
- = link_to 'Edit', edit_project_issue_path(@project, issue), :class => "cgray edit-issue-link", :remote => true
+ = link_to 'Edit', edit_project_issue_path(issue.project, issue), :class => "cgray edit-issue-link", :remote => true
- if can?(current_user, :admin_issue, @project) || issue.author == current_user
- = link_to 'Remove', [@project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-issue negative", :id => "destroy_issue_#{issue.id}"
+ = link_to 'Remove', [issue.project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-issue negative", :id => "destroy_issue_#{issue.id}"
diff --git a/app/views/layouts/_head_panel.html.erb b/app/views/layouts/_head_panel.html.erb
index 5ad82ecd..5110c184 100644
--- a/app/views/layouts/_head_panel.html.erb
+++ b/app/views/layouts/_head_panel.html.erb
@@ -25,6 +25,9 @@
<%= link_to dashboard_path, :class => current_page?(root_path) ? "current dashboard" : "dashboard" do %>
Dashboard
<% end %>
+ <%= link_to issues_path, :class => current_page?(issues_path) ? "current issues" : "issues" do %>
+ Issues
+ <% end %>
<%= link_to projects_path, :class => current_page?(projects_path) ? "current project" : "project" do %>
Projects
<% end %>
diff --git a/app/views/layouts/user.html.haml b/app/views/layouts/user.html.haml
new file mode 100644
index 00000000..5a936450
--- /dev/null
+++ b/app/views/layouts/user.html.haml
@@ -0,0 +1,31 @@
+!!!
+%html
+ %head
+ %title
+ GitLab #{" - #{current_user.name}"}
+ = stylesheet_link_tag "application"
+ = javascript_include_tag "application"
+ = csrf_meta_tags
+ = javascript_tag do
+ REQ_URI = "#{request.env["REQUEST_URI"]}";
+ REQ_REFFER = "#{request.env["HTTP_REFERER"]}";
+ %body{ :class => body_class('project-page'), :id => yield(:boyd_id)}
+ = render :partial => "layouts/flash"
+ #container
+ = render :partial => "layouts/head_panel"
+ .project-container
+ .project-sidebar
+ .fixed
+ %aside
+ = link_to issues_path, :class => current_page?(issues_path) ? "current" : nil do
+ Issues
+ - unless current_user.assigned_issues.empty?
+ %span{ :class => "number" }= current_user.assigned_issues.count
+ = link_to merge_requests_path, :class => current_page?(merge_requests_path) ? "current" : nil do
+ Merge Requests
+ - unless current_user.assigned_merge_requests.empty?
+ %span{ :class => "number" }= current_user.assigned_merge_requests.count
+
+ .project-content
+ = yield
+
diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml
index c5bcf779..ef290833 100644
--- a/app/views/merge_requests/_merge_request.html.haml
+++ b/app/views/merge_requests/_merge_request.html.haml
@@ -1,8 +1,11 @@
-%a.update-item{:href => project_merge_request_path(@project, merge_request)}
+%a.update-item{:href => project_merge_request_path(merge_request.project, merge_request)}
= image_tag gravatar_icon(merge_request.author_email), :class => "left", :width => 40
%span.update-title
= merge_request.title
%span.update-author
+ - if not @project.present?
+ %strong= merge_request.project.name
+ = '-'
%strong= merge_request.author_name
authored
= time_ago_in_words(merge_request.created_at)
diff --git a/app/views/user_issues/index.atom.builder b/app/views/user_issues/index.atom.builder
new file mode 100644
index 00000000..42fc5245
--- /dev/null
+++ b/app/views/user_issues/index.atom.builder
@@ -0,0 +1,24 @@
+xml.instruct!
+xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
+ xml.title "#{@user.name} issues"
+ xml.link :href => issues_url(:atom, :private_token => @user.private_token), :rel => "self", :type => "application/atom+xml"
+ xml.link :href => issues_url(:private_token => @user.private_token), :rel => "alternate", :type => "text/html"
+ xml.id issues_url(:private_token => @user.private_token)
+ xml.updated @issues.first.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") if @issues.any?
+
+ @issues.each do |issue|
+ xml.entry do
+ xml.id project_issue_url(issue.project, issue)
+ xml.link :href => project_issue_url(issue.project, issue)
+ xml.title truncate(issue.title, :length => 80)
+ xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
+ xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
+ xml.author do |author|
+ xml.name issue.author_name
+ xml.email issue.author_email
+ end
+ xml.summary issue.title
+ end
+ end
+end
+
diff --git a/app/views/user_issues/index.html.haml b/app/views/user_issues/index.html.haml
new file mode 100644
index 00000000..bf05ca5e
--- /dev/null
+++ b/app/views/user_issues/index.html.haml
@@ -0,0 +1,9 @@
+%div#issues-table-holder
+ %table.round-borders#issues-table
+ %thead
+ %th
+ .top_panel_issues
+ %h2 Issues assigned to me
+
+ = render 'issues/issues'
+ %br
diff --git a/app/views/user_merge_requests/index.html.haml b/app/views/user_merge_requests/index.html.haml
new file mode 100644
index 00000000..cf1c4143
--- /dev/null
+++ b/app/views/user_merge_requests/index.html.haml
@@ -0,0 +1,10 @@
+- if @merge_requests.opened.count > 0
+ %div{ :class => "update-data ui-box ui-box-small ui-box-big" }
+ %h3
+ %span.tag.open Open
+ .data
+ = render @merge_requests.opened
+
+ .clear
+ %br
+
diff --git a/config/routes.rb b/config/routes.rb
index ad8b0b31..a49aa7a2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,7 @@
Gitlab::Application.routes.draw do
+ get "user_issues/index"
+
get 'tags'=> 'tags#index'
get 'tags/:tag' => 'projects#index'
@@ -21,6 +23,9 @@ Gitlab::Application.routes.draw do
put "profile/edit", :to => "profile#social_update"
get "profile", :to => "profile#show"
get "dashboard", :to => "dashboard#index"
+ get "issues", :to => "user_issues#index", :as => "issues"
+ get "merge_requests", :to => "user_merge_requests#index", :as => "merge_requests"
+
#get "profile/:id", :to => "profile#show"
resources :projects, :only => [:new, :create, :index]
diff --git a/db/schema.rb b/db/schema.rb
index 17246a61..613b65cb 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -13,18 +13,6 @@
ActiveRecord::Schema.define(:version => 20111207211728) do
- create_table "features", :force => true do |t|
- t.string "name"
- t.string "branch_name"
- t.integer "assignee_id"
- t.integer "author_id"
- t.integer "project_id"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "version"
- t.integer "status", :default => 0, :null => false
- end
-
create_table "issues", :force => true do |t|
t.string "title"
t.integer "assignee_id"
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 4e1f1308..3a3ac7c9 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -6,6 +6,8 @@ describe User do
it { should have_many(:users_projects) }
it { should have_many(:issues) }
it { should have_many(:assigned_issues) }
+ it { should have_many(:merge_requests) }
+ it { should have_many(:assigned_merge_requests) }
end
describe "Respond to" do
diff --git a/spec/requests/merge_requests_spec.rb b/spec/requests/merge_requests_spec.rb
index b03ab219..bdbc8909 100644
--- a/spec/requests/merge_requests_spec.rb
+++ b/spec/requests/merge_requests_spec.rb
@@ -50,7 +50,7 @@ describe "MergeRequests" do
end
describe "GET /merge_requests/new" do
- before do
+ before do
visit new_project_merge_request_path(project)
fill_in "merge_request_title", :with => "Merge Request Title"
select "master", :from => "merge_request_source_branch"
diff --git a/spec/requests/user_issues_spec.rb b/spec/requests/user_issues_spec.rb
new file mode 100644
index 00000000..bd29eae3
--- /dev/null
+++ b/spec/requests/user_issues_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe "User Issues Dashboard" do
+ describe "GET /issues" do
+ before do
+
+ login_as :user
+
+ @project1 = Factory :project,
+ :path => "project1",
+ :code => "TEST1"
+
+ @project2 = Factory :project,
+ :path => "project2",
+ :code => "TEST2"
+
+ @project1.add_access(@user, :read, :write)
+ @project2.add_access(@user, :read, :write)
+
+ @issue1 = Factory :issue,
+ :author => @user,
+ :assignee => @user,
+ :project => @project1
+
+ @issue2 = Factory :issue,
+ :author => @user,
+ :assignee => @user,
+ :project => @project2
+
+ visit issues_path
+ end
+
+ subject { page }
+
+ it { should have_content(@issue1.title) }
+ it { should have_content(@issue1.project.name) }
+ it { should have_content(@issue1.assignee.name) }
+
+ it { should have_content(@issue2.title) }
+ it { should have_content(@issue2.project.name) }
+ it { should have_content(@issue2.assignee.name) }
+
+ it "should render atom feed via private token" do
+ logout
+ visit issues_path(:atom, :private_token => @user.private_token)
+
+ page.response_headers['Content-Type'].should have_content("application/atom+xml")
+ page.body.should have_selector("title", :text => "#{@user.name} issues")
+ page.body.should have_selector("author email", :text => @issue1.author_email)
+ page.body.should have_selector("entry summary", :text => @issue1.title)
+ page.body.should have_selector("author email", :text => @issue2.author_email)
+ page.body.should have_selector("entry summary", :text => @issue2.title)
+ end
+ end
+end
diff --git a/spec/requests/user_merge_requests_spec.rb b/spec/requests/user_merge_requests_spec.rb
new file mode 100644
index 00000000..fb47f3dd
--- /dev/null
+++ b/spec/requests/user_merge_requests_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe "User MergeRequests" do
+ describe "GET /issues" do
+ before do
+
+ login_as :user
+
+ @project1 = Factory :project,
+ :path => "project1",
+ :code => "TEST1"
+
+ @project2 = Factory :project,
+ :path => "project2",
+ :code => "TEST2"
+
+ @project1.add_access(@user, :read, :write)
+ @project2.add_access(@user, :read, :write)
+
+ @merge_request1 = Factory :merge_request,
+ :author => @user,
+ :assignee => @user,
+ :project => @project1
+
+ @merge_request2 = Factory :merge_request,
+ :author => @user,
+ :assignee => @user,
+ :project => @project2
+
+ visit merge_requests_path
+ end
+
+ subject { page }
+
+ it { should have_content(@merge_request1.title) }
+ it { should have_content(@merge_request1.project.name) }
+ it { should have_content(@merge_request1.target_branch) }
+ it { should have_content(@merge_request1.source_branch) }
+ it { should have_content(@merge_request1.assignee.name) }
+
+ it { should have_content(@merge_request2.title) }
+ it { should have_content(@merge_request2.project.name) }
+ it { should have_content(@merge_request2.target_branch) }
+ it { should have_content(@merge_request2.source_branch) }
+ it { should have_content(@merge_request2.assignee.name) }
+ end
+end