[PROJXP [PATCH] When populating a sprint, a backlog item cannot have an estimate of 0. #57
by LAN-SUN-LUK Benjamin
I hope that it work now :-).
Signed-off-by: Benjamin LAN-SUN-LUK <benjamin.lan-sun-luk(a)supinfo.com>
---
app/controllers/sprints_controller.rb | 18 ++++++++----------
app/models/backlog_item.rb | 4 ++++
app/views/sprints/plan.html.erb | 6 +++---
3 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/app/controllers/sprints_controller.rb
b/app/controllers/sprints_controller.rb
index df336ad..713d330 100644
--- a/app/controllers/sprints_controller.rb
+++ b/app/controllers/sprints_controller.rb
@@ -130,14 +130,6 @@ class SprintsController < ApplicationController
@title = "Sprint #{(a)sprint.id} (Planning)"
@user_stories = UserStory.find_all_by_product_id((a)product.id)
- @estimates = Hash.new
- @selected = Array.new
-
- BacklogItem.find_all_by_sprint_id((a)sprint.id).each do |item|
- @estimates["#{item.user_story_id}"] = item.estimated_hours
- @selected << item.user_story_id
- end
-
format.html
else
flash[:error] = "You are not allowed to plan this sprint."
@@ -167,7 +159,7 @@ class SprintsController < ApplicationController
@sprint.backlog_items << BacklogItem.new(
:sprint_id => @sprint.id,
:user_story_id => selected,
- :estimated_hours => estimate.to_f)
+ :estimated_hours => estimate)
end
end
@@ -177,8 +169,14 @@ class SprintsController < ApplicationController
else
@title = "Sprint #{(a)sprint.id} (Planning)"
flash[:error] = "There was an error updating the sprint
backlog."
+ @sprint.backlog_items.each do |backlog_item|
+ if backlog_item.errors['estimated_hours']
+ flash[:error] += ' ' +
backlog_item.errors['estimated_hours']
+ break
+ end
+ end
@user_stories = UserStory.find_all_by_product_id((a)product.id)
- format.html { render :action => :plan }
+ format.html { render :action => :plan, :selected =>
params[:selected] }
end
else
flash[:error] = "You are not allowed to plan this sprint."
diff --git a/app/models/backlog_item.rb b/app/models/backlog_item.rb
index d149172..5a88800 100644
--- a/app/models/backlog_item.rb
+++ b/app/models/backlog_item.rb
@@ -24,6 +24,10 @@ class BacklogItem < ActiveRecord::Base
validates_presence_of :user_story_id,
:message => 'You need to specify a user story.'
+ validates_numericality_of :estimated_hours,
+ :greater_than => 0,
+ :message => 'Estimated hours must be numeric and greater than 0.'
+
belongs_to :sprint
belongs_to :user_story
belongs_to :owner, :class_name => 'User', :foreign_key => 'owner_id'
diff --git a/app/views/sprints/plan.html.erb
b/app/views/sprints/plan.html.erb
index ba6bb95..de55d5e 100644
--- a/app/views/sprints/plan.html.erb
+++ b/app/views/sprints/plan.html.erb
@@ -22,13 +22,13 @@
<tbody>
<% @user_stories.each_with_index do |story, index| %>
<% row_class = index%2 == 0 ? 'even' : 'odd' %>
-
+ <% backlog_item =
@sprint.backlog_items.find_by_user_story_id(story.id) %>
<tr class="<%= row_class %>">
<td><%= story.id %></td>
<td><%= story.priority %></td>
<td>
- <%= check_box_tag "selected[]", story.id,
@selected.include?(story.id) %>
- <%= text_field_tag "estimates['#{story.id}']",
@estimates["#{story.id}"],
+ <%= check_box_tag "selected[]", story.id, (backlog_item ||
(params[:selected].include?(story.id.to_s) if params[:selected])) %>
+ <%= text_field_tag "estimates['#{story.id}']",
(backlog_item.estimated_hours if backlog_item),
:size => 4, :maxlength => 4%>
</td>
<td><%= get_first_sentence story.description %></td>
--
1.6.0.2
15 years, 5 months
[PROJXP [PATCH] When populating a sprint, a backlog item cannot have an estimate of 0. #57
by LAN-SUN-LUK Benjamin
Signed-off-by: Benjamin LAN-SUN-LUK <benjamin.lan-sun-luk(a)supinfo.com>
---
app/controllers/sprints_controller.rb | 8 +++++++-
app/models/backlog_item.rb | 4 ++++
2 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/app/controllers/sprints_controller.rb
b/app/controllers/sprints_controller.rb
index df336ad..eaf35e3 100644
--- a/app/controllers/sprints_controller.rb
+++ b/app/controllers/sprints_controller.rb
@@ -167,7 +167,7 @@ class SprintsController < ApplicationController
@sprint.backlog_items << BacklogItem.new(
:sprint_id => @sprint.id,
:user_story_id => selected,
- :estimated_hours => estimate.to_f)
+ :estimated_hours => estimate)
end
end
@@ -177,6 +177,12 @@ class SprintsController < ApplicationController
else
@title = "Sprint #{(a)sprint.id} (Planning)"
flash[:error] = "There was an error updating the sprint
backlog."
+ @sprint.backlog_items.each do |backlog_item|
+ if backlog_item.errors['estimated_hours']
+ flash[:error] += ' ' +
backlog_item.errors['estimated_hours']
+ break
+ end
+ end
@user_stories = UserStory.find_all_by_product_id((a)product.id)
format.html { render :action => :plan }
end
diff --git a/app/models/backlog_item.rb b/app/models/backlog_item.rb
index d149172..5a88800 100644
--- a/app/models/backlog_item.rb
+++ b/app/models/backlog_item.rb
@@ -24,6 +24,10 @@ class BacklogItem < ActiveRecord::Base
validates_presence_of :user_story_id,
:message => 'You need to specify a user story.'
+ validates_numericality_of :estimated_hours,
+ :greater_than => 0,
+ :message => 'Estimated hours must be numeric and greater than 0.'
+
belongs_to :sprint
belongs_to :user_story
belongs_to :owner, :class_name => 'User', :foreign_key => 'owner_id'
--
1.6.0.2
15 years, 5 months
[PROJXP [PATCH] A user cannot delete a backlog item from sprint if that item has tasks. #45
by LAN-SUN-LUK Benjamin
Signed-off-by: Benjamin LAN-SUN-LUK <benjamin.lan-sun-luk(a)supinfo.com>
---
app/views/sprints/plan.html.erb | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/app/views/sprints/plan.html.erb
b/app/views/sprints/plan.html.erb
index ba6bb95..ea388d3 100644
--- a/app/views/sprints/plan.html.erb
+++ b/app/views/sprints/plan.html.erb
@@ -21,15 +21,20 @@
<tbody>
<% @user_stories.each_with_index do |story, index| %>
+ <% backlog_item_has_tasks = false %>
+ <% backlog_item =
@sprint.backlog_items.find_by_user_story_id(story.id) %>
+ <% unless backlog_item.nil? %>
+ <% backlog_item_has_tasks = true if !backlog_item.tasks.empty? %>
+ <% end %>
<% row_class = index%2 == 0 ? 'even' : 'odd' %>
<tr class="<%= row_class %>">
<td><%= story.id %></td>
<td><%= story.priority %></td>
<td>
- <%= check_box_tag "selected[]", story.id,
@selected.include?(story.id) %>
+ <%= check_box_tag "selected[]", story.id,
@selected.include?(story.id), {:disabled => backlog_item_has_tasks } %>
<%= text_field_tag "estimates['#{story.id}']",
@estimates["#{story.id}"],
- :size => 4, :maxlength => 4%>
+ {:size => 4, :maxlength => 4, :disabled =>
backlog_item_has_tasks} %>
</td>
<td><%= get_first_sentence story.description %></td>
</tr>
--
1.6.0.2
15 years, 5 months
[PROJXP [PATCH] When populating a sprint, a backlog item cannot have an estimate of 0. #57
by LAN-SUN-LUK Benjamin
Signed-off-by: Benjamin LAN-SUN-LUK <benjamin.lan-sun-luk(a)supinfo.com>
---
app/controllers/sprints_controller.rb | 8 +++++++-
app/models/backlog_item.rb | 4 ++++
2 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/app/controllers/sprints_controller.rb b/app/controllers/sprints_controller.rb
index df336ad..eaf35e3 100644
--- a/app/controllers/sprints_controller.rb
+++ b/app/controllers/sprints_controller.rb
@@ -167,7 +167,7 @@ class SprintsController < ApplicationController
@sprint.backlog_items << BacklogItem.new(
:sprint_id => @sprint.id,
:user_story_id => selected,
- :estimated_hours => estimate.to_f)
+ :estimated_hours => estimate)
end
end
@@ -177,6 +177,12 @@ class SprintsController < ApplicationController
else
@title = "Sprint #{(a)sprint.id} (Planning)"
flash[:error] = "There was an error updating the sprint backlog."
+ @sprint.backlog_items.each do |backlog_item|
+ if backlog_item.errors['estimated_hours']
+ flash[:error] += ' ' + backlog_item.errors['estimated_hours']
+ break
+ end
+ end
@user_stories = UserStory.find_all_by_product_id((a)product.id)
format.html { render :action => :plan }
end
diff --git a/app/models/backlog_item.rb b/app/models/backlog_item.rb
index d149172..5a88800 100644
--- a/app/models/backlog_item.rb
+++ b/app/models/backlog_item.rb
@@ -24,6 +24,10 @@ class BacklogItem < ActiveRecord::Base
validates_presence_of :user_story_id,
:message => 'You need to specify a user story.'
+ validates_numericality_of :estimated_hours,
+ :greater_than => 0,
+ :message => 'Estimated hours must be numeric and greater than 0.'
+
belongs_to :sprint
belongs_to :user_story
belongs_to :owner, :class_name => 'User', :foreign_key => 'owner_id'
--
1.6.0.2
15 years, 5 months
[PROJXP [PATCH] A user cannot delete a backlog item from sprint if that item has tasks. #45
by LAN-SUN-LUK Benjamin
Signed-off-by: Benjamin LAN-SUN-LUK <benjamin.lan-sun-luk(a)supinfo.com>
---
app/views/sprints/plan.html.erb | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/app/views/sprints/plan.html.erb b/app/views/sprints/plan.html.erb
index ba6bb95..ea388d3 100644
--- a/app/views/sprints/plan.html.erb
+++ b/app/views/sprints/plan.html.erb
@@ -21,15 +21,20 @@
<tbody>
<% @user_stories.each_with_index do |story, index| %>
+ <% backlog_item_has_tasks = false %>
+ <% backlog_item = @sprint.backlog_items.find_by_user_story_id(story.id) %>
+ <% unless backlog_item.nil? %>
+ <% backlog_item_has_tasks = true if !backlog_item.tasks.empty? %>
+ <% end %>
<% row_class = index%2 == 0 ? 'even' : 'odd' %>
<tr class="<%= row_class %>">
<td><%= story.id %></td>
<td><%= story.priority %></td>
<td>
- <%= check_box_tag "selected[]", story.id, @selected.include?(story.id) %>
+ <%= check_box_tag "selected[]", story.id, @selected.include?(story.id), {:disabled => backlog_item_has_tasks } %>
<%= text_field_tag "estimates['#{story.id}']", @estimates["#{story.id}"],
- :size => 4, :maxlength => 4%>
+ {:size => 4, :maxlength => 4, :disabled => backlog_item_has_tasks} %>
</td>
<td><%= get_first_sentence story.description %></td>
</tr>
--
1.6.0.2
15 years, 5 months
[PROJXP [PATCH 0/2] Two patches for showing a subset of product details
by Darryl L. Pierce
These patches can be reviewed together. The second patch depends on the first
being applied first.
Darryl L. Pierce (2):
Product details are show on sprint list page. #59
Viewing a user story list shows the product's details. #60
app/views/products/_product.html.erb | 19 +++++++++++++++++++
app/views/sprints/index.html.erb | 6 +++---
app/views/stories/index.html.erb | 2 +-
3 files changed, 23 insertions(+), 4 deletions(-)
create mode 100644 app/views/products/_product.html.erb
15 years, 5 months
[PROJXP [PATCH] User roles can be viewed. #61
by Darryl L. Pierce
Changed the link on the product details page to point to the
roles url beneath the product page itself.
>From the user page, you can view the user's roles.
>From the user's roles, you can go to the product to view the
other product members.
>From the product's member page, you can select any member and
view their other roles.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/roles_controller.rb | 16 ++++--
app/controllers/users_controller.rb | 10 +++-
app/views/products/show.html.erb | 2 +-
app/views/roles/_list.html.erb | 85 ++++++++++++++++++++++++++++++
app/views/roles/index.html.erb | 44 +---------------
app/views/users/_list.html.erb | 2 +-
app/views/users/roles.html.erb | 2 +
config/routes.rb | 4 +-
test/functional/users_controller_test.rb | 15 +++++
9 files changed, 127 insertions(+), 53 deletions(-)
create mode 100644 app/views/roles/_list.html.erb
create mode 100644 app/views/users/roles.html.erb
diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb
index a768094..51fdbd5 100644
--- a/app/controllers/roles_controller.rb
+++ b/app/controllers/roles_controller.rb
@@ -27,13 +27,17 @@ class RolesController < ApplicationController
def index
@title = "#{(a)product.name} Members"
if @product.can_approve_roles?(@user)
- @product_roles = ProductRole.find_all_by_product_id(@product, :order => 'role_id ASC')
+ @product_roles = ProductRole.paginate(
+ :conditions => ['product_id = ?', @product.id],
+ :order => 'role_id ASC',
+ :page => params[:page],
+ :per_page => 10)
else
- @product_roles = ProductRole.find_all_by_product_id(
- @product,
- :order => 'role_id ASC',
- :conditions => 'is_approved = true'
- )
+ @product_roles = ProductRole.paginate(
+ :conditions => ['product_id = ? and is_approved = true', @product.id],
+ :order => 'role_id ASC',
+ :page => params[:page],
+ :per_page => 10)
end
respond_to do |format|
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 76c5525..1c58dbf 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -16,7 +16,7 @@
# +UsersController+ allows for CRUD operations on instances of +User+.
class UsersController < ApplicationController
- before_filter :authenticated, :except => [:index, :show, :new, :create, :backlog]
+ before_filter :authenticated, :except => [:index, :show, :new, :create, :backlog, :roles]
before_filter :load_this_user, :except => [:index, :new, :create]
# GET /users
@@ -143,6 +143,14 @@ class UsersController < ApplicationController
end
end
+ # GET /users/1/roles
+ def roles
+ @product_roles = ProductRole.paginate(
+ :conditions => ['user_id = ?', @this_user.id],
+ :page => params[:page],
+ :per_page => 10)
+ end
+
private
def load_this_user
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb
index cf4bcd9..66ad0bb 100644
--- a/app/views/products/show.html.erb
+++ b/app/views/products/show.html.erb
@@ -34,7 +34,7 @@
<td class="label">Members:</td>
<td class="value">
<%= link_to "#{(a)product.product_roles.size} Members",
- users_path(:product => @product) %>
+ product_roles_path(@product) %>
</td>
</tr>
diff --git a/app/views/roles/_list.html.erb b/app/views/roles/_list.html.erb
new file mode 100644
index 0000000..8692122
--- /dev/null
+++ b/app/views/roles/_list.html.erb
@@ -0,0 +1,85 @@
+<% columns = 4 - (@this_user ? 1 : 0) + (@product ? 0 : 1) + (@product && @product.can_approve_roles?(@user) ? 1 : 0) %>
+
+<% if @product %>
+ <%= link_to @product.name, product_path(@product) %>
+<% end %>
+
+<table class="list">
+ <colgroup>
+ <col class="row_id" />
+ <% unless @this_user %>
+ <col class="user" />
+ <% end %>
+ <% unless @product %>
+ <col class="name" />
+ <% end %>
+ <col class="description" />
+ <col class="date" />
+
+ <% if @product && @product.can_approve_roles?(@user) %>
+ <col class="actions" />
+ <% end %>
+ </colgroup>
+
+ <thead>
+ <tr>
+ <th class="title" colspan="<%= columns %>">
+ Product Roles
+ </th>
+ </tr>
+ <tr>
+ <th>#</th>
+
+ <% unless @this_user %>
+ <th>User</th>
+ <% end %>
+
+ <% unless @product %>
+ <th>Product</th>
+ <% end %>
+
+ <th>Role</th>
+ <th>Since</th>
+ <% if @product && @product.can_approve_roles?(@user) %>
+ <th>Actions</th>
+ <% end %>
+ </tr>
+ </thead>
+
+ <tbody>
+ <% @product_roles.each_with_index do |role, index| %>
+ <% row_class = index%2 == 0 ? 'even' : 'odd' %>
+ <tr class="<%= row_class %>">
+ <td><%= link_to "#{role.id}", product_role_path(role.product, role) %>
+
+ <% unless @this_user %>
+ <td><%= link_to role.user.display_name,roles_user_path(role.user) %></td>
+ <% end %>
+
+ <% unless @product %>
+ <td><%= link_to role.product.name, product_roles_path(role.product) %>
+ <% end %>
+
+ <td><%= role.role.name %></td>
+ <td><%= show_date role.created_at %></td>
+ <% if @product && @product.can_approve_roles?(@user) %>
+ <td>
+ <% if role.pending %>
+ <% form_for(:product_role, role, :url => product_role_path(role.product,role),
+ :html => {:method => :put}) do |form| %>
+ <%= form.radio_button :approved, true %>Approve
+ <%= form.radio_button :approved, false %>Deny
+ <%= submit_tag "Update" %>
+ <% end %>
+ <% else %>
+ <% form_for(:product_role, role, :url => product_role_path(role.product,role),
+ :html => {:method => :delete}) do |form| %>
+ <%= submit_tag "Delete", :confirm => "Are you sure?" %>
+ <% end %>
+ <% end %>
+ <% end %>
+ </td>
+ </tr>
+ <% end %>
+ </tbody>
+</table>
diff --git a/app/views/roles/index.html.erb b/app/views/roles/index.html.erb
index c96bd6f..c32fe36 100644
--- a/app/views/roles/index.html.erb
+++ b/app/views/roles/index.html.erb
@@ -1,42 +1,2 @@
-<%= link_to @product.name, product_path(@product) %>
-
-<table class="list">
- <thead>
- <tr>
- <th>User</th>
- <th>Role</th>
- <th>Created</th>
- <% if @product.can_approve_roles?(@user) %>
- <th>Actions</th>
- <% end %>
- </tr>
- </thead>
-
- <tbody>
- <% @product_roles.each_with_index do |role, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <tr class="<%= row_class %>">
- <td><%= link_to role.user.display_name,user_path(role.user) %></td>
- <td><%= role.role.name %></td>
- <td><%= role.created_at %></td>
- <% if @product.can_approve_roles?(@user) %>
- <td>
- <% if role.pending %>
- <% form_for(:product_role, role, :url => product_role_path(role.product,role),
- :html => {:method => :put}) do |form| %>
- <%= form.radio_button :approved, true %>Approve
- <%= form.radio_button :approved, false %>Deny
- <%= submit_tag "Update" %>
- <% end %>
- <% else %>
- <% form_for(:product_role, role, :url => product_role_path(role.product,role),
- :html => {:method => :delete}) do |form| %>
- <%= submit_tag "Delete", :confirm => "Are you sure?" %>
- <% end %>
- <% end %>
- <% end %>
- </td>
- </tr>
- <% end %>
- </tbody>
-</table>
+<%= will_paginate @product_roles %>
+<%= render :partial => 'list' %>
diff --git a/app/views/users/_list.html.erb b/app/views/users/_list.html.erb
index 9fc055e..e3101e1 100644
--- a/app/views/users/_list.html.erb
+++ b/app/views/users/_list.html.erb
@@ -33,7 +33,7 @@
<td><%= simple_format user.introduction %></td>
<td><%= link_to user.email, "mailto:#{user.email}" %></td>
<td><%= link_to "#{user.backlog.size} items", backlog_user_path(user) %>
- <td><%= "#{user.product_roles.size} roles" %></td>
+ <td><%= link_to "#{user.product_roles.size} roles", roles_user_path(user) %></td>
<td><%= show_date(user.created_at) %></td>
<td>
<%= link_to(image_tag("icons/view.png", :alt => "View user..."), user_path(user)) %>
diff --git a/app/views/users/roles.html.erb b/app/views/users/roles.html.erb
new file mode 100644
index 0000000..78cf239
--- /dev/null
+++ b/app/views/users/roles.html.erb
@@ -0,0 +1,2 @@
+<%= will_paginate @product_roles %>
+<%= render :partial => 'roles/list' %>
diff --git a/config/routes.rb b/config/routes.rb
index bb87d4c..d4d2ec6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -20,7 +20,7 @@ ActionController::Routing::Routes.draw do |map|
map.resources :products do |product|
product.resources :roles
product.resources :stories
- product.resources(:sprints, :member => {:plan => :get, :populate => :post}) do |sprint|
+ product.resources(:sprints, :member => {:plan => :get, :populate => :post, :roles => :get}) do |sprint|
sprint.resources :items, :member =>
{
:accept => :get,
@@ -30,7 +30,7 @@ ActionController::Routing::Routes.draw do |map|
}
end
end
- map.resources :users, :member => {:backlog => :get} do |user|
+ map.resources :users, :member => {:backlog => :get, :roles => :get} do |user|
user.resources :tasks
end
diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb
index 170541e..7375369 100644
--- a/test/functional/users_controller_test.rb
+++ b/test/functional/users_controller_test.rb
@@ -294,4 +294,19 @@ class UsersControllerTest < ActionController::TestCase
assert User.find_by_id((a)unverified_user.id).verified?,
"User should be verified."
end
+
+ # Ensures that viewing roles requires a valid user id.
+ def test_roles_with_invalid_user_id
+ get :roles
+
+ assert_redirected_to users_path
+ end
+
+ # Ensures that the set of roles are loaded.
+ def test_roles
+ get :roles, {:id => @user.id}
+
+ assert_response :success
+ assert assigns['product_roles'], "Failed to load the user's roles."
+ end
end
--
1.5.6.5
15 years, 5 months
[PROJXP [PATCH] Add links from the backlog list and view to the owning sprint. #62
by Darryl L. Pierce
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/views/items/_list.html.erb | 87 +++++++++++++++++++++++++--------------
app/views/items/show.html.erb | 7 +++
2 files changed, 63 insertions(+), 31 deletions(-)
diff --git a/app/views/items/_list.html.erb b/app/views/items/_list.html.erb
index 639395d..0379bb1 100644
--- a/app/views/items/_list.html.erb
+++ b/app/views/items/_list.html.erb
@@ -3,6 +3,11 @@
<col class="row_id" />
<col class="description" />
<col class="user" />
+
+ <% unless @sprint %>
+ <col class="number" />
+ <% end %>
+
<col class="status" />
<col class="hours" />
<col class="actions" />
@@ -10,12 +15,17 @@
<thead>
<tr>
- <th class="title" colspan="6">Backlog Items</th>
+ <th class="title" colspan="<%= @sprint ? 6 : 7 %>">Backlog Items</th>
</tr>
<tr>
<th>#</th>
<th>Title</th>
<th>Owner</th>
+
+ <% unless @sprint %>
+ <th>Sprint</th>
+ <% end %>
+
<th>Status</th>
<th>Hours (E/A/R)</th>
<th>Action</th>
@@ -23,38 +33,53 @@
</thead>
<tbody>
- <% @backlog_items.each_with_index do |item, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <% sprint = item.sprint %>
- <% product = sprint.product %>
-
- <tr class="<%= row_class %>">
- <td>
- <%= link_to "#{item.id}",
- product_sprint_item_path(product, sprint, item) %>
- </td>
- <td><%= item.user_story.title %></td>
- <td><%= link_to(item.owner.display_name, user_path(item.owner)) if item.owner %></td>
- <td><%= item.state_text %></td>
- <td><%= show_hours_as_ear(item) %>
- <td>
- <%= link_to(image_tag("icons/item_user_story.png"),
- product_story_path(item.sprint.product, item.user_story)) %>
- <%= link_to(image_tag("icons/item_accept.png"),
- accept_product_sprint_item_path(product, sprint, item,
- :source => request.request_uri)) if item.can_accept?(@user) %>
- <%= link_to(image_tag("icons/item_drop.png"),
- drop_product_sprint_item_path(product, sprint,item,
- :source => request.request_uri)) if item.can_drop?(@user) %>
- <%= link_to(image_tag("icons/item_complete.png"),
- complete_product_sprint_item_path(product, sprint, item,
- :source => request.request_uri)) if item.can_complete?(@user) %>
- <%= link_to(image_tag("icons/item_reopen.png"),
- reopen_product_sprint_item_path(product, sprint, item,
- :source => request.request_uri)) if item.can_reopen?(@user) %>
- </td>
+ <% if @backlog_items.empty? %>
+ <tr>
+ <td colspan="<%= @sprint ? 6 : 7 %>">No backlog items found...</td>
</tr>
+ <% else %>
+ <% @backlog_items.each_with_index do |item, index| %>
+ <% row_class = index%2 == 0 ? 'even' : 'odd' %>
+ <% sprint = item.sprint %>
+ <% product = sprint.product %>
+
+ <tr class="<%= row_class %>">
+ <td>
+ <%= link_to "#{item.id}",
+ product_sprint_item_path(product, sprint, item) %>
+ </td>
+ <td><%= item.user_story.title %></td>
+ <td><%= link_to(item.owner.display_name, user_path(item.owner)) if item.owner %></td>
+
+ <% unless @sprint %>
+ <td>
+ <div style="overflow: hidden">
+ (<%= link_to "#{item.sprint.id}", product_sprint_path(item.sprint.product, item.sprint) %>)
+ <%= h item.sprint.title %>
+ </div>
+ </td>
+ <% end %>
+ <td><%= item.state_text %></td>
+ <td><%= show_hours_as_ear(item) %>
+ <td>
+ <%= link_to(image_tag("icons/item_user_story.png"),
+ product_story_path(item.sprint.product, item.user_story)) %>
+ <%= link_to(image_tag("icons/item_accept.png"),
+ accept_product_sprint_item_path(product, sprint, item,
+ :source => request.request_uri)) if item.can_accept?(@user) %>
+ <%= link_to(image_tag("icons/item_drop.png"),
+ drop_product_sprint_item_path(product, sprint,item,
+ :source => request.request_uri)) if item.can_drop?(@user) %>
+ <%= link_to(image_tag("icons/item_complete.png"),
+ complete_product_sprint_item_path(product, sprint, item,
+ :source => request.request_uri)) if item.can_complete?(@user) %>
+ <%= link_to(image_tag("icons/item_reopen.png"),
+ reopen_product_sprint_item_path(product, sprint, item,
+ :source => request.request_uri)) if item.can_reopen?(@user) %>
+ </td>
+ </tr>
+ <% end %>
<% end %>
</tbody>
</table>
diff --git a/app/views/items/show.html.erb b/app/views/items/show.html.erb
index 96f4be3..4c2b7d4 100644
--- a/app/views/items/show.html.erb
+++ b/app/views/items/show.html.erb
@@ -43,6 +43,13 @@
</tr>
<tr>
+ <td class="label">Sprint:</td>
+ <td class="value">
+ <%= link_to "(#{(a)sprint.id})", product_sprint_path(@product, @sprint) %>
+ <%= h @sprint.title %>
+ </tr>
+
+ <tr>
<td class="label">Priority:</td>
<td class="value"><%= @backlog_item.user_story.priority %></td>
</tr>
--
1.6.0.2
15 years, 5 months
[PROJXP [PATCH] Add burndown chart to the sprint view page. #52
by Darryl L. Pierce
Added three report graphic sizes (800x600, 1024x768 and 1280x1024)
and a dropdown to the sprint view page to select the size.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/report_controller.rb | 28 ++++++++++++++++++++++++++--
app/views/report/burndown.html.erb | 5 +++--
app/views/sprints/show.html.erb | 5 +++++
test/functional/report_controller_test.rb | 2 +-
4 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/app/controllers/report_controller.rb b/app/controllers/report_controller.rb
index 6993fd6..e8c9bad 100644
--- a/app/controllers/report_controller.rb
+++ b/app/controllers/report_controller.rb
@@ -20,6 +20,17 @@
class ReportController < ApplicationController
before_filter :load_sprint, :except => [:index, :effort]
before_filter :load_user, :only => [:effort]
+ before_filter :load_size, :only => [:burndown, :burndown_graphic]
+
+ SIZE_SMALL = "800x600"
+ SIZE_MEDIUM = "1024x768"
+ SIZE_LARGE = "1280x1024"
+
+ REPORT_SIZES = {
+ SIZE_SMALL => 0,
+ SIZE_MEDIUM => 1,
+ SIZE_LARGE => 2
+ }.sort_by { |k,v| v }
def index
@title = "Reports"
@@ -28,6 +39,7 @@ class ReportController < ApplicationController
def burndown
@title = "Burndown Chart For Sprint #{(a)sprint.id}"
+ @size = params[:size]
end
def effort
@@ -47,8 +59,8 @@ class ReportController < ApplicationController
if @sprint.can_view_burndown?
@data = @sprint.burndown_data
- g = Gruff::Line.new('800x600')
- g.title = "Burndown Chart For '#{(a)sprint.title}'"
+ g = Gruff::Line.new(@size)
+ g.title = "#{(a)sprint.title}"
g.font = File.expand_path('Courier.ttf', RAILS_ROOT)
g.data("Remaining hours", @data)
@@ -83,4 +95,16 @@ class ReportController < ApplicationController
redirect_to error_url
end
end
+
+ def load_size
+ size = params[:size]
+ if size
+ size = size.to_i
+ if (0...REPORT_SIZES.size).include? params[:size].to_i
+ @size = REPORT_SIZES[size.to_i][0]
+ end
+ end
+
+ @size = REPORT_SIZES[0][0] unless @size
+ end
end
diff --git a/app/views/report/burndown.html.erb b/app/views/report/burndown.html.erb
index b5fa23f..5c788ad 100644
--- a/app/views/report/burndown.html.erb
+++ b/app/views/report/burndown.html.erb
@@ -1,3 +1,4 @@
-<img src="<%= url_for :action => :burndown_graphic, :id => @sprint.id %>"
+<img src="<%= url_for :action => :burndown_graphic, :id => @sprint.id,
+ :size => @size%>"
alt="Burndown"
- align="center" />
\ No newline at end of file
+ align="center" />
diff --git a/app/views/sprints/show.html.erb b/app/views/sprints/show.html.erb
index df475c5..46482c8 100644
--- a/app/views/sprints/show.html.erb
+++ b/app/views/sprints/show.html.erb
@@ -21,6 +21,11 @@
image_tag("icons/sprint_plan.png", :alt => "Plan this sprint"),
plan_product_sprint_path(@product, @sprint)) %>
<% end %>
+ <% if @sprint.can_view_burndown? %>
+ <%= form_tag(:controller => :report, :action => :burndown, :id => @sprint.id) %>
+ <%= select_tag :size, options_for_select(ReportController::REPORT_SIZES) %>
+ <%= submit_tag "Burndown" %>
+ <% end %>
</td>
</tr>
diff --git a/test/functional/report_controller_test.rb b/test/functional/report_controller_test.rb
index 4a0a64a..3948d8f 100644
--- a/test/functional/report_controller_test.rb
+++ b/test/functional/report_controller_test.rb
@@ -46,7 +46,7 @@ class ReportControllerTest < ActionController::TestCase
# Ensures that a burndown chart works as expected.
#
def test_burndown_graphic
- get :burndown_graphic, {:id => @sprint.id}
+ get :burndown_graphic, {:id => @sprint.id, :size => 0}
assert_response :success
assert assigns['data'], "Didn't generate the data needed for a report."
--
1.6.0.2
15 years, 5 months
[PROJXP [PATCH] Add burndown chart to the sprint view page. #52
by Darryl L. Pierce
Added three report graphic sizes (800x600, 1024x768 and 1280x1024)
and a dropdown to the sprint view page to select the size.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/report_controller.rb | 28 ++++++++++++++++++++++++++--
app/views/report/burndown.html.erb | 5 +++--
app/views/sprints/show.html.erb | 5 +++++
test/functional/report_controller_test.rb | 2 +-
4 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/app/controllers/report_controller.rb b/app/controllers/report_controller.rb
index 6993fd6..411518e 100644
--- a/app/controllers/report_controller.rb
+++ b/app/controllers/report_controller.rb
@@ -20,6 +20,17 @@
class ReportController < ApplicationController
before_filter :load_sprint, :except => [:index, :effort]
before_filter :load_user, :only => [:effort]
+ before_filter :load_size, :only => [:burndown]
+
+ SIZE_SMALL = "800x600"
+ SIZE_MEDIUM = "1024x768"
+ SIZE_LARGE = "1280x1024"
+
+ REPORT_SIZES = {
+ SIZE_SMALL => 0,
+ SIZE_MEDIUM => 1,
+ SIZE_LARGE => 2
+ }.sort_by { |k,v| v }
def index
@title = "Reports"
@@ -28,6 +39,7 @@ class ReportController < ApplicationController
def burndown
@title = "Burndown Chart For Sprint #{(a)sprint.id}"
+ @size = params[:size]
end
def effort
@@ -47,8 +59,8 @@ class ReportController < ApplicationController
if @sprint.can_view_burndown?
@data = @sprint.burndown_data
- g = Gruff::Line.new('800x600')
- g.title = "Burndown Chart For '#{(a)sprint.title}'"
+ g = Gruff::Line.new(@size)
+ g.title = "#{(a)sprint.title}"
g.font = File.expand_path('Courier.ttf', RAILS_ROOT)
g.data("Remaining hours", @data)
@@ -83,4 +95,16 @@ class ReportController < ApplicationController
redirect_to error_url
end
end
+
+ def load_size
+ size = params[:size]
+ if size
+ size = size.to_i
+ if (0...REPORT_SIZES.size).include? params[:size].to_i
+ @size = REPORT_SIZES[size.to_i][0]
+ end
+ end
+
+ @size = REPORT_SIZES[0][0] unless @size
+ end
end
diff --git a/app/views/report/burndown.html.erb b/app/views/report/burndown.html.erb
index b5fa23f..5c788ad 100644
--- a/app/views/report/burndown.html.erb
+++ b/app/views/report/burndown.html.erb
@@ -1,3 +1,4 @@
-<img src="<%= url_for :action => :burndown_graphic, :id => @sprint.id %>"
+<img src="<%= url_for :action => :burndown_graphic, :id => @sprint.id,
+ :size => @size%>"
alt="Burndown"
- align="center" />
\ No newline at end of file
+ align="center" />
diff --git a/app/views/sprints/show.html.erb b/app/views/sprints/show.html.erb
index df475c5..46482c8 100644
--- a/app/views/sprints/show.html.erb
+++ b/app/views/sprints/show.html.erb
@@ -21,6 +21,11 @@
image_tag("icons/sprint_plan.png", :alt => "Plan this sprint"),
plan_product_sprint_path(@product, @sprint)) %>
<% end %>
+ <% if @sprint.can_view_burndown? %>
+ <%= form_tag(:controller => :report, :action => :burndown, :id => @sprint.id) %>
+ <%= select_tag :size, options_for_select(ReportController::REPORT_SIZES) %>
+ <%= submit_tag "Burndown" %>
+ <% end %>
</td>
</tr>
diff --git a/test/functional/report_controller_test.rb b/test/functional/report_controller_test.rb
index 4a0a64a..3948d8f 100644
--- a/test/functional/report_controller_test.rb
+++ b/test/functional/report_controller_test.rb
@@ -46,7 +46,7 @@ class ReportControllerTest < ActionController::TestCase
# Ensures that a burndown chart works as expected.
#
def test_burndown_graphic
- get :burndown_graphic, {:id => @sprint.id}
+ get :burndown_graphic, {:id => @sprint.id, :size => 0}
assert_response :success
assert assigns['data'], "Didn't generate the data needed for a report."
--
1.6.0.2
15 years, 5 months