Added "Issues" dashboard
This shows issues assigned to you, across all your projects, in one place. References #173
This commit is contained in:
parent
2552a877df
commit
f512418b27
14 changed files with 165 additions and 20 deletions
3
app/assets/javascripts/user_issues.js.coffee
Normal file
3
app/assets/javascripts/user_issues.js.coffee
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Place all the behaviors and hooks related to the matching controller here.
|
||||
# All this logic will automatically be available in application.js.
|
||||
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
|
|
@ -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));
|
||||
|
|
3
app/assets/stylesheets/user_issues.css.scss
Normal file
3
app/assets/stylesheets/user_issues.css.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
// Place all the styles related to the user_issues controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
25
app/controllers/user_issues_controller.rb
Normal file
25
app/controllers/user_issues_controller.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
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
|
||||
|
||||
def search
|
||||
|
||||
end
|
||||
|
||||
end
|
2
app/helpers/user_issues_helper.rb
Normal file
2
app/helpers/user_issues_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
module UserIssuesHelper
|
||||
end
|
|
@ -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})
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
<%= link_to dashboard_path, :class => current_page?(root_path) ? "current dashboard" : "dashboard" do %>
|
||||
<span></span>Dashboard
|
||||
<% end %>
|
||||
<%= link_to issues_path, :class => current_page?(issues_path) ? "current issues" : "issues" do %>
|
||||
<span></span>Issues
|
||||
<% end %>
|
||||
<%= link_to projects_path, :class => current_page?(projects_path) ? "current project" : "project" do %>
|
||||
<span></span>Projects
|
||||
<% end %>
|
||||
|
|
27
app/views/layouts/user.html.haml
Normal file
27
app/views/layouts/user.html.haml
Normal file
|
@ -0,0 +1,27 @@
|
|||
!!!
|
||||
%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?(:controller => "user_issues", :action => "index") ? "current" : nil do
|
||||
Issues
|
||||
- unless current_user.assigned_issues.empty?
|
||||
%span{ :class => "number" }= current_user.assigned_issues.count
|
||||
|
||||
.project-content
|
||||
= yield
|
||||
|
24
app/views/user_issues/index.atom.builder
Normal file
24
app/views/user_issues/index.atom.builder
Normal file
|
@ -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
|
||||
|
9
app/views/user_issues/index.html.haml
Normal file
9
app/views/user_issues/index.html.haml
Normal file
|
@ -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
|
|
@ -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,8 @@ 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 "profile/:id", :to => "profile#show"
|
||||
|
||||
resources :projects, :only => [:new, :create, :index]
|
||||
|
|
12
db/schema.rb
12
db/schema.rb
|
@ -13,18 +13,6 @@
|
|||
|
||||
ActiveRecord::Schema.define(:version => 20111206222316) 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"
|
||||
|
|
53
spec/requests/user_issues_spec.rb
Normal file
53
spec/requests/user_issues_spec.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
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)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue