[PATCH] Fixed the sorting of recent activity posts. #235
by Darryl L. Pierce
The posts are re-sorted into descending order by posting date. Then the
10 latest are displayed, which is how it should be.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/views/users/show.html.erb | 3 ++-
doc/ChangeLog | 1 +
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 40be67f..f15189c 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -48,7 +48,8 @@
<% if @this_user.posts.empty? %>
<tr class="odd"><td><b>This user has posted no messages.</b></td></tr>
<% else %>
- <% @this_user.posts.slice(0..9).each do |post| %>
+ <% posts = @this_user.posts.sort { |first, second| second.posted <=> first.posted }
+ posts.slice(0..9).each do |post| %>
<tr class="<%= cycle('odd', 'even') %>">
<td><%= link_to "#{get_first_sentence(RedCloth.new(post.body).to_html) }", message_path(post) %></td>
</tr>
diff --git a/doc/ChangeLog b/doc/ChangeLog
index fe54823..070818c 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -60,6 +60,7 @@ Change Log (0.3.0):
* #230 - Sprint not started but no error message is shown. (BUG)
* #231 - Fix the breadcrumb trail for the task page. (BUG)
* #234 - Fix the URL for user registration. (BUG)
+ * #235 - Recent activity is actually oldest activity. (BUG)
Change Log (0.2.0):
* #97 - Users can request new projects.
--
1.6.2.5
14 years, 6 months
[PATCH] Fixed the user registration URL. #234
by Darryl L. Pierce
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/views/users/_edit.html.erb | 3 ++-
doc/ChangeLog | 1 +
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/app/views/users/_edit.html.erb b/app/views/users/_edit.html.erb
index 110e9bc..7429ed3 100644
--- a/app/views/users/_edit.html.erb
+++ b/app/views/users/_edit.html.erb
@@ -1,6 +1,7 @@
<div id="content-no-sidebar">
<% html = @this_user.new_record? ? {:method => :post} : {:method => :put} %>
- <% form_for(:user, @this_user, :url => users_path(@this_user), :html => html) do |form| %>
+ <% url = @this_user.new_record? ? users_path : user_path(@this_user) %>
+ <% form_for(:user, @this_user, :url => url, :html => html) do |form| %>
<table class="edit">
<caption><%= "#{(a)this_user.new_record? ? 'Create' : 'Edit'} User Account" %></caption>
<tbody>
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 471a238..b9571ac 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -58,6 +58,7 @@ Change Log (0.3.0):
* #229 - Fixed when nil.name showed up when viewing sprints. (BUG)
* #230 - Sprint not started but no error message is shown. (BUG)
* #231 - Fix the breadcrumb trail for the task page. (BUG)
+ * #234 - Fix the URL for user registration. (BUG)
Change Log (0.2.0):
* #97 - Users can request new projects.
--
1.6.2.5
14 years, 6 months
[PATCH] Incorrect breadcrumb trail on tasks pages. #231
by Darryl L. Pierce
Added correct breadcrumb trail to both the list and individual task
pages. Now if viewing for a backlog item, the trail leads back to the
project. If viewing for a user, then the patch goes back to the user.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/tasks_controller.rb | 21 ++++++++++++++++++---
doc/ChangeLog | 1 +
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 622f8d3..869689e 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -176,17 +176,32 @@ class TasksController < ApplicationController
end
def path_to_list
+ if @backlog_item
+ @sprint = Sprint.find_by_id(params[:sprint]) unless @sprint
+ @product = @sprint.product
+ @project = @product.project
+
+ add_breadcrumb "Projects", projects_path
+ add_breadcrumb "#{(a)project.id}", project_path(@project)
+ add_breadcrumb "Products", products_path(:project => @project.id)
+ add_breadcrumb "#{(a)product.id}", product_path(@product)
+ add_breadcrumb "Sprints", sprints_path(:product => @product)
+ add_breadcrumb "#{(a)sprint.id}", sprint_path(@sprint)
+ add_breadcrumb "Items", items_path(:sprint => @sprint)
+ add_breadcrumb "#{(a)backlog_item.id}", item_path(@backlog_item)
+ end
+
if @this_user
add_breadcrumb "Users", users_path
add_breadcrumb "#{(a)this_user.id}", user_path(@this_user)
- add_breadcrumb "Tasks", tasks_path(:user => @this_user)
- else
- add_breadcrumb "Tasks", tasks_path
end
+
+ add_breadcrumb "Tasks", tasks_path(:item => @backlog_item)
end
def path_to_one
path_to_list
+
add_breadcrumb "#{(a)task.id}", task_path(@task)
end
end
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 5b69c79..471a238 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -57,6 +57,7 @@ Change Log (0.3.0):
* #228 - Fixed the URL in the product creation RSS entry. (BUG)
* #229 - Fixed when nil.name showed up when viewing sprints. (BUG)
* #230 - Sprint not started but no error message is shown. (BUG)
+ * #231 - Fix the breadcrumb trail for the task page. (BUG)
Change Log (0.2.0):
* #97 - Users can request new projects.
--
1.6.2.5
14 years, 6 months
[PATCH] No error message shown when a sprint is not started. #230
by Darryl L. Pierce
The problem was that, when using the ApplicationController::report_error
method on a failure, the message was assigned to flash[:error]. But on
the default layout flash[:error] is never displayed.
So the change was to check and, if not going to the error page, the
message is now assigned to flash[:message].
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/application_controller.rb | 6 +++++-
app/views/layouts/default.html.erb | 2 +-
doc/ChangeLog | 1 +
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index dd60773..b11ae08 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -76,7 +76,11 @@ class ApplicationController < ActionController::Base
# Redirects the user to the error page and displays
# the provided message.
def report_error(message, url=nil)
- flash[:error] = message
+ if url
+ flash[:message] = message
+ else
+ flash[:error] = message
+ end
respond_to do |format|
format.html { redirect_to url ? url : error_path }
diff --git a/app/views/layouts/default.html.erb b/app/views/layouts/default.html.erb
index ac8b12a..9b5a4b3 100644
--- a/app/views/layouts/default.html.erb
+++ b/app/views/layouts/default.html.erb
@@ -64,7 +64,7 @@
<% if flash[:message] %>
- <%# if javascript iss disabled, show a standard message box %>
+ <%# if javascript is disabled, show a standard message box %>
<noscript>
<div id="message-box-nojs">
<div id="message-box-text">
diff --git a/doc/ChangeLog b/doc/ChangeLog
index ee43aa4..5b69c79 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -56,6 +56,7 @@ Change Log (0.3.0):
* #226 - The sprint status text is not shown on the sprint list page. (BUG)
* #228 - Fixed the URL in the product creation RSS entry. (BUG)
* #229 - Fixed when nil.name showed up when viewing sprints. (BUG)
+ * #230 - Sprint not started but no error message is shown. (BUG)
Change Log (0.2.0):
* #97 - Users can request new projects.
--
1.6.2.5
14 years, 6 months
[PATCH] Fixes when editing/creating user stories. #223
by Darryl L. Pierce
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/views/stories/_edit.html.erb | 5 ++---
doc/ChangeLog | 1 +
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/views/stories/_edit.html.erb b/app/views/stories/_edit.html.erb
index 22b312b..0fec1e8 100644
--- a/app/views/stories/_edit.html.erb
+++ b/app/views/stories/_edit.html.erb
@@ -1,8 +1,7 @@
<div id="content-no-sidebar">
<% html = @user_story.new_record? ? {:method => :post} : {:method => :put} %>
-
- <% form_for(:user_story, @user_story,
- :url => stories_path(@user_story), :html => html) do |form| %>
+ <% url = @user_story.new_record? ? stories_path(:product => @product) : story_path(@user_story) %>
+ <% form_for(:user_story, @user_story, :url => url, :html => html) do |form| %>
<%= hidden_field_tag :product, @product.id %>
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 1f992fe..ee43aa4 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -52,6 +52,7 @@ Change Log (0.3.0):
* #220 - When a user has project admin rights, then the link will say "Create" not "Request". (BUG)
* #221 - When requesting a product role, the URL is broken. (BUG)
* #222 - Fixed creating/editing products using the wrong URL. (BUG)
+ * #223 - Fixed creating/editing user stories using the wrong URL. (BUG)
* #226 - The sprint status text is not shown on the sprint list page. (BUG)
* #228 - Fixed the URL in the product creation RSS entry. (BUG)
* #229 - Fixed when nil.name showed up when viewing sprints. (BUG)
--
1.6.2.5
14 years, 6 months
[PATCH] The product owner has an automatic role. #215
by Darryl L. Pierce
When a product is created, the user marked as the owner is given an
automatic role as a Developer.
When a product is modified, and the owner is changed, then the old
owner's product role is removed and the new owner is assigned a product
role instead.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/products_controller.rb | 19 ++++++++++++++++
doc/ChangeLog | 1 +
test/functional/products_controller_test.rb | 31 ++++++++++++++++++++------
3 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb
index c8d8190..f2075fe 100644
--- a/app/controllers/products_controller.rb
+++ b/app/controllers/products_controller.rb
@@ -104,6 +104,7 @@ class ProductsController < ApplicationController
if @product.project.can_create_products?(@user)
if @product.save
+ create_role_for_owner
flash[:message] = "Product created successfully."
format.html { redirect_to product_path(@product) }
add_rss_entry(create_rss_entry("New product created: #{(a)product.name}",
@@ -135,9 +136,16 @@ class ProductsController < ApplicationController
if @product.can_edit?(@user)
begin
Product.transaction do
+ old_owner = @product.owner
@product.update_attributes(params[:product])
if @product.save
+ # create a new product role if the owner changed
+ if (@product.owner_id != old_owner.id)
+ old_role = ProductRole.for_product((a)product).for_user(old_owner)
+ ProductRole.delete(old_role)
+ end
+ create_role_for_owner
add_rss_entry(create_rss_entry("Details updated: #{(a)product.name}",
product_url(@product),
"The product's details have been updated..."))
@@ -207,6 +215,17 @@ class ProductsController < ApplicationController
end
end
+ def create_role_for_owner
+ owner = User.find_by_id((a)product.owner_id)
+ unless @product.is_member?(owner)
+ ProductRole.create(:product => @product,
+ :user_id => @product.owner_id,
+ :role => Role.find_by_name("Developer"),
+ :pending => false,
+ :approved => true)
+ end
+ end
+
def path_to_list
@project = Project.find_by_id(params[:project]) if params[:project]
if @project
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 514f40f..1f992fe 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -45,6 +45,7 @@ Change Log (0.3.0):
* #212 - Task events show up in the product's RSS feed.
* #213 - Users can disable receiving emails when replies are posted.
* #214 - The product activity list is shown in the sidebar. (BUG)
+ * #215 - Product roles are automatically created for product owners. (BUG)
* #216 - The user's most recent postings are displayed on their details page.
* #217 - All of a user's posts can be viewed.
* #218 - Sprints need a new stage called "proposed". (backed out)
diff --git a/test/functional/products_controller_test.rb b/test/functional/products_controller_test.rb
index 74b489d..c2559b6 100644
--- a/test/functional/products_controller_test.rb
+++ b/test/functional/products_controller_test.rb
@@ -37,8 +37,9 @@ class ProductsControllerTest < ActionController::TestCase
@existing_product = products(:projxp_web)
@product_owner = @existing_product.owner
- @non_product_owner = users(:mcpierce)
+ @non_product_owner = users(:jdonuts)
raise "Owner and nonowner cannot be the same user!" if @product_owner.id == @non_product_owner.id
+ raise "Non-product owner can't have a product role!" if @existing_product.is_member?(@non_product_owner)
@member = users(:mcpierce)
@nonmember = users(:jdonuts)
@@ -248,6 +249,9 @@ class ProductsControllerTest < ActionController::TestCase
result = Product.find_by_name(@new_product[:name])
assert result, "Failed to create the actual product."
assert !result.rss_entries.empty?, "Product should have an RSS entry for its creation."
+ assert result.is_member?(result.owner), "The product owner should have been made a product team member."
+ role = ProductRole.find_by_product_id_and_user_id(result.id, result.owner_id)
+ assert !role.pending, "The role should not be pending."
end
# Ensures that anonymous users can't update a product.
@@ -280,16 +284,29 @@ class ProductsControllerTest < ActionController::TestCase
# Ensures that updating a product works for the project owner.
def test_update
count = @existing_product.rss_entries.size
- put :update,
- {:id => @existing_product.id,
- :product => @product_update},
- {:user_id => @project_owner.id}
+ put :update,{:id => @existing_product.id,:product => @product_update},{:user_id => @project_owner.id}
+
+ assert_redirected_to product_path(@existing_product)
+ result = Product.find_by_id((a)existing_product.id)
+ assert_equal @product_update[:name], result.name, "Name should have been updaed."
+ assert_equal count + 1, result.rss_entries.size, "Failed to add a new rss entry."
+ assert result.is_member?(result.owner), "The product owner should not have lost his role."
+ end
+
+ # Ensures that changing the product owner removes the old owner's product
+ # role and creates a role for the new owner.
+ def test_update_with_owner_change
+ count = @existing_product.rss_entries.size
+ old_owner = @existing_product.owner
+ @product_update[:owner_id] = @non_product_owner.id
+ put :update,{:id => @existing_product.id,:product => @product_update},{:user_id => @project_owner.id}
assert_redirected_to product_path(@existing_product)
result = Product.find_by_id((a)existing_product.id)
- assert_equal @product_update[:name], result.name,
- "Name should have been updaed."
+ assert_equal @product_update[:name], result.name, "Name should have been updaed."
assert_equal count + 1, result.rss_entries.size, "Failed to add a new rss entry."
+ assert result.is_member?(result.owner), "The owner should have a product role."
+ assert !result.is_member?(old_owner), "The old owner's role should have been removed."
end
# Ensures that anonymous users can't delete.
--
1.6.2.5
14 years, 7 months
[PATCH] Moves RSS feed to the sidebar for products. #214
by Darryl L. Pierce
The list was not inside of the sidebar's div tag. So it's now fixed.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/views/products/show.html.erb | 36 ++++++++++++++++++------------------
1 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb
index 7eb017a..e4bf755 100644
--- a/app/views/products/show.html.erb
+++ b/app/views/products/show.html.erb
@@ -45,23 +45,23 @@
<%= link_to "RSS feed...",
rss_product_path(@product), :class => "command" %>
-<% end %>
-
-<div id="activity">
- <table>
- <caption>Recent Activity</caption>
- <thead>
- <%= link_to(image_tag("/images/icons/rss.png", :title => "Product activity feed"), rss_product_path(@product)) %>
- </thead>
- <tbody>
- <% @product.rss_entries.each_with_index do |entry, index| %>
- <tr>
- <% if index < 25 %>
- <td><%= link_to entry.title, entry.link %></td>
+ <div id="activity">
+ <table>
+ <caption>Recent Activity</caption>
+ <thead>
+ <%= link_to(image_tag("/images/icons/rss.png", :title => "Product activity feed"), rss_product_path(@product)) %>
+ </thead>
+ <tbody>
+ <% @product.rss_entries.each_with_index do |entry, index| %>
+ <tr>
+ <% if index < 25 %>
+ <td><%= link_to entry.title, entry.link %></td>
+ <% end %>
+ </tr>
<% end %>
- </tr>
- <% end %>
- </tbody>
- </table>
-</div>
+ </tbody>
+ </table>
+ </div>
+
+<% end %>
--
1.6.2.5
14 years, 7 months
[PATCH] Task events are now added to the product's RSS feed. #212
by Darryl L. Pierce
When a user adds, edits or deletes a task, then an entry is added to the
product's RSS feed.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/tasks_controller.rb | 17 ++++++++++++++---
app/views/tasks/_edit.html.erb | 3 ++-
doc/ChangeLog | 1 +
test/functional/tasks_controller_test.rb | 12 ++++++++++++
4 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 13ccb0e..622f8d3 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -70,7 +70,9 @@ class TasksController < ApplicationController
report_error "Backup must be a member of the sprint team."
else
respond_to do |format|
- if @task.save && @task.backlog_item.save
+ add_product_rss_entry("#{(a)user.display_name} added a new #{(a)task.hours} hour task.",
+ "#{(a)task.description}")
+ if @task.save && @task.backlog_item.save && @task.backlog_item.sprint.product.save
flash[:message] = "Recorded #{(a)task.hours} hours against this backlog item."
format.html { redirect_to task_path(@task) }
else
@@ -89,7 +91,9 @@ class TasksController < ApplicationController
@task.update_attributes(params[:task])
respond_to do |format|
- if @task.save
+ add_product_rss_entry("#{(a)user.display_name} updated task #{(a)task.id}.",
+ "#{(a)task.description}")
+ if @task.save && @task.backlog_item.sprint.product.save
flash[:message] = "Task successfully updated."
format.html { redirect_to task_path(@task) }
else
@@ -104,7 +108,9 @@ class TasksController < ApplicationController
# DELETE /tasks/1
def destroy
Task.transaction do
- if @task.destroy
+ add_product_rss_entry("#{(a)user.display_name} deleted task #{(a)task.id}.",
+ "#{(a)task.description}")
+ if @task.destroy && @task.backlog_item.sprint.product.save
flash[:message] = "Task has been deleted."
respond_to do |format|
format.html { redirect_to tasks_path(:user => @user) }
@@ -164,6 +170,11 @@ class TasksController < ApplicationController
@users = User.for_sprint((a)sprint.id)
end
+ def add_product_rss_entry(title, content)
+ product = @task.backlog_item.sprint.product
+ product.rss_entries << create_rss_entry(title, item_path((a)task.backlog_item), content, @user)
+ end
+
def path_to_list
if @this_user
add_breadcrumb "Users", users_path
diff --git a/app/views/tasks/_edit.html.erb b/app/views/tasks/_edit.html.erb
index cd189d0..f5c9b52 100644
--- a/app/views/tasks/_edit.html.erb
+++ b/app/views/tasks/_edit.html.erb
@@ -1,6 +1,7 @@
<div id="content-no-sidebar">
<% html = @task.new_record? ? {:method => :post} : {:method => :put} %>
- <% form_for(:task, @task, :url => @task.new_record? ? tasks_path(:item => @backlog_item) : tasks_path(@task), :html => html) do |form| %>
+ <% url = @task.new_record? ? tasks_path(:item => @backlog_item) : task_path(@task) %>
+ <% form_for(:task, @task, :url => url, :html => html) do |form| %>
<%= hidden_field_tag :item, @backlog_item.id %>
<table class="edit">
<caption><%= "#{(a)task.new_record? ? 'Create' : 'Edit'} A Task" %></caption>
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 9e1aaa8..5567684 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -42,6 +42,7 @@ Change Log (0.3.0):
* #209 - A blocked item is shown in a different color on the item list page.
* #210 - Epics with no user stories should only be deleted. (BUG)
* #211 - Backlog item events show up in the product's RSS feed.
+ * #212 - Task events show up in the product's RSS feed.
* #213 - Users can disable receiving emails when replies are posted.
* #216 - The user's most recent postings are displayed on their details page.
* #217 - All of a user's posts can be viewed.
diff --git a/test/functional/tasks_controller_test.rb b/test/functional/tasks_controller_test.rb
index 24eaa29..fd6c726 100644
--- a/test/functional/tasks_controller_test.rb
+++ b/test/functional/tasks_controller_test.rb
@@ -221,22 +221,28 @@ class TasksControllerTest < ActionController::TestCase
# Ensures that creating a task works as expected.
def test_create
+ count = @item.sprint.product.rss_entries.size
post :create, { :item => @item.id, :task => @new_task }, { :user_id => @owner.id }
result = Task.find_by_description(@new_task[:description])
assert result, "Task should have been created."
assert_redirected_to task_path(result)
assert !result.backlog_item.completed?, "Backlog item should not have been marked completed."
+ newcount = Product.find_by_id((a)item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "A new RSS entry should have been added."
end
# Ensures that creating a task that marks the item completed works as expected.
def test_create_and_complete
+ count = @item.sprint.product.rss_entries.size
post :create, {:item => @item.id, :task => @new_task, :completed => true}, {:user_id => @owner.id}
result = Task.find_by_description(@new_task[:description])
assert result, "Task should have been created."
assert_redirected_to task_path(result)
assert result.backlog_item.completed?, "Item should have been marked as completed."
+ newcount = Product.find_by_id((a)item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "A new RSS entry should have been added."
end
# Ensures anonymous users can't update a task.
@@ -272,11 +278,14 @@ class TasksControllerTest < ActionController::TestCase
# Ensures that an update works.
def test_update
+ count = @item.sprint.product.rss_entries.size
put :update, { :id => @task.id, :task => { :hours => 12.5 }}, { :user_id => @owner.id }
assert_redirected_to task_path(@task)
assert_equal 12.5, Task.find_by_id((a)task.id).hours,
"Hours hould have been updated."
+ newcount = Product.find_by_id((a)item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "A new RSS entry should have been added."
end
# Ensures that anonymous users cannot delete tasks.
@@ -302,9 +311,12 @@ class TasksControllerTest < ActionController::TestCase
# Ensures that delete a task works as expected.
def test_delete
+ count = @item.sprint.product.rss_entries.size
delete :destroy, { :id => @task.id }, { :user_id => @owner.id }
assert_redirected_to tasks_path(:user => @owner.id)
assert !Task.find_by_id((a)task.id), "Task should have been deleted."
+ newcount = Product.find_by_id((a)item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "A new RSS entry should have been added."
end
end
--
1.6.2.5
14 years, 7 months
[PATCH] Backlog item events now show up in the product RSS feed. #211
by Darryl L. Pierce
When a user estimates the remaining hours on a backlog item,
accepts, drops, completes, reopens, defers or marks an item as
blocked, then the product's RSS feed is updated.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/items_controller.rb | 32 +++++++++++---
app/views/items/show.html.erb | 18 ++++++++
doc/ChangeLog | 1 +
test/functional/items_controller_test.rb | 60 ++++-----------------------
test/functional/user_items_test.rb | 65 ++++++++++++++++++++++++++++++
5 files changed, 118 insertions(+), 58 deletions(-)
diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb
index 29addad..6ed0e74 100644
--- a/app/controllers/items_controller.rb
+++ b/app/controllers/items_controller.rb
@@ -97,9 +97,11 @@ class ItemsController < ApplicationController
BacklogItem.transaction do
if @backlog_item.user_can_accept?(@user)
@backlog_item.assign_to_user(@user)
- if @backlog_item.save
+ add_product_rss_entry("Backlog item ##{(a)backlog_item.id} accepted.",
+ "#{(a)user.display_name} accepted \"#{(a)backlog_item.user_story.title}\".")
+ if @backlog_item.save && @backlog_item.sprint.product.save
respond_to do |format|
- flash[:message] = "This backlog item is now owned by #{(a)backlog_item.owner.display_name}."
+ flash[:message] = "This backlog item is now owned by #{(a)user.display_name}."
format.html {redirect_to params[:source] ? params[:source] : item_path(@backlog_item)}
end
else
@@ -115,7 +117,9 @@ class ItemsController < ApplicationController
def drop
BacklogItem.transaction do
if @backlog_item.user_can_drop?(@user)
- if @backlog_item.drop
+ add_product_rss_entry("Backlog item ##{(a)backlog_item.id} dropped.",
+ "#{(a)user.display_name} dropped \"#{(a)backlog_item.user_story.title}\".")
+ if @backlog_item.drop && @backlog_item.sprint.product.save
flash[:message] = "This item has been dropped."
respond_to do |format|
format.html {redirect_to items_path(:sprint => @backlog_item.sprint)}
@@ -133,7 +137,9 @@ class ItemsController < ApplicationController
def complete
BacklogItem.transaction do
if @backlog_item.user_can_complete?(@user)
- if @backlog_item.complete
+ add_product_rss_entry("Backlog item ##{(a)backlog_item.id} completed.",
+ "#{(a)user.display_name} completed \"#{(a)backlog_item.user_story.title}\".")
+ if @backlog_item.complete && @backlog_item.sprint.product.save
respond_to do |format|
flash[:message] = "This item is now marked as completed."
format.html {redirect_to items_path(:sprint => @backlog_item.sprint)}
@@ -151,7 +157,9 @@ class ItemsController < ApplicationController
def reopen
BacklogItem.transaction do
if @backlog_item.user_can_reopen?(@user)
- if @backlog_item.reopen
+ add_product_rss_entry("Backlog item ##{(a)backlog_item.id} reopened.",
+ "#{(a)user.display_name} reopened \"#{(a)backlog_item.user_story.title}\".")
+ if @backlog_item.reopen && @backlog_item.sprint.product.save
flash[:message] = "This backlog item has been reopened."
respond_to do |format|
format.html {redirect_to params[:source] ? params[:source] : item_path(@backlog_item)}
@@ -169,7 +177,8 @@ class ItemsController < ApplicationController
def defer
BacklogItem.transaction do
@backlog_item.defer
-
+ add_product_rss_entry("Backlog item ##{(a)backlog_item.id} deferred.",
+ "#{(a)user.display_name} deferred \"#{(a)backlog_item.user_story.title}\".")
if @backlog_item.save
flash[:message] = "Item has been deferred."
respond_to do |format|
@@ -186,8 +195,10 @@ class ItemsController < ApplicationController
if @backlog_item.can_estimate?(@user)
old_hours = @backlog_item.remaining_hours
@backlog_item.update_remaining_hours((a)hours.to_f, @user)
+ add_product_rss_entry("Backlog item estimate changed.",
+ "Hours changed from #{old_hours} to #{(a)hours.to_f} by #{(a)user.display_name}.")
BacklogItem.transaction do
- if @backlog_item.save
+ if @backlog_item.save and @backlog_item.sprint.product.save
respond_to do |format|
flash[:message] = "Estimated hours updated from #{old_hours} to #{@hours} hours."
format.html { redirect_to item_path(@backlog_item) }
@@ -229,6 +240,8 @@ class ItemsController < ApplicationController
flash[:message] = "Item blocked status unchanged."
end
end
+ add_product_rss_entry("Backlog item ##{(a)backlog_item.id} is blocked.",
+ "#{(a)user.display_name} has marked this item as blocked: \"#{(a)backlog_item.user_story.title}\".")
if @backlog_item.save && @message.save
respond_to do |format|
format.html {redirect_to item_path(@backlog_item)}
@@ -301,6 +314,11 @@ class ItemsController < ApplicationController
report_error "You may not mark this item as blocked." unless @backlog_item.can_mark_blocked?(@user)
end
+ def add_product_rss_entry(title, content)
+ product = @backlog_item.sprint.product
+ product.rss_entries << create_rss_entry(title, item_path(@backlog_item), content, @user)
+ end
+
def path_to_list
if @sprint || params[:sprint]
@sprint = Sprint.find_by_id(params[:sprint]) unless @sprint
diff --git a/app/views/items/show.html.erb b/app/views/items/show.html.erb
index 87f30ae..dc64d13 100644
--- a/app/views/items/show.html.erb
+++ b/app/views/items/show.html.erb
@@ -26,6 +26,24 @@
</dd>
<% end %>
</dl>
+
+ <% if @backlog_item.can_estimate?(@user) %>
+ <div>
+ <%= form_tag(estimate_item_path(@backlog_item)) %>
+ <table class="edit">
+ <caption>Update estimated hours</caption>
+ <tbody>
+ <tr>
+ <td class="label">Hours</td>
+ <td class="value"><%= text_field_tag :hours, @backlog_item.remaining_hours %></td>
+ </tr>
+ <tr>
+ <td class="buttons" colspan="2"><%= submit_tag "Update" %></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <% end %>
</div>
<% if @backlog_item.blocked? %>
diff --git a/doc/ChangeLog b/doc/ChangeLog
index b1de50a..9e1aaa8 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -41,6 +41,7 @@ Change Log (0.3.0):
* #208 - Blocker history is shown for backlog items.
* #209 - A blocked item is shown in a different color on the item list page.
* #210 - Epics with no user stories should only be deleted. (BUG)
+ * #211 - Backlog item events show up in the product's RSS feed.
* #213 - Users can disable receiving emails when replies are posted.
* #216 - The user's most recent postings are displayed on their details page.
* #217 - All of a user's posts can be viewed.
diff --git a/test/functional/items_controller_test.rb b/test/functional/items_controller_test.rb
index ca721a6..ff2c074 100644
--- a/test/functional/items_controller_test.rb
+++ b/test/functional/items_controller_test.rb
@@ -217,56 +217,6 @@ class ItemsControllerTest < ActionController::TestCase
assert !BacklogItem.find_by_id((a)pending_item.id), "Item should have been deleted."
end
- # Ensures that anonymous users can't update estimaetes.
- def test_estimate_as_anonymous
- post :estimate
-
- assert_redirected_to login_path
- end
-
- # Ensures that a valid item id is required.
- def test_estimate_with_invalid_item
- post :estimate, {}, {:user_id => @item_owner.id}
-
- assert_redirected_to error_path
- end
-
- # Ensures that an hours estimate is required.
- def test_estimate_without_hours
- post :estimate, {:id => @item.id}, {:user_id => @item_owner.id}
-
- assert_redirected_to error_path
- assert_equal @item.remaining_hours, BacklogItem.find_by_id((a)item.id).remaining_hours,
- "Hours should not have been updated."
- end
-
- # Ensures that the sprint must be active for an estimate to be updated.
- def test_estimate_on_planned_sprint
- post :estimate, {:id => @pending_item.id}, {:user_id => @item_owner.id}
-
- assert_redirected_to error_path
- assert_equal @pending_item.remaining_hours, BacklogItem.find_by_id((a)pending_item.id).remaining_hours,
- "Remaining hours should not have been updated!"
- end
-
- # Ensures that only the item owner can update the estimate hours.
- def test_estimate_as_nonowner
- post :estimate, {:id => @item.id, :hours => @item.remaining_hours + 1}, {:user_id => @item_nonowner.id}
-
- assert_redirected_to error_path
- assert_equal @item.remaining_hours, BacklogItem.find_by_id((a)item.id).remaining_hours,
- "Remaining hours should not have been updated."
- end
-
- # Ensures that updating an estimate works as expected.
- def test_estimate
- post :estimate, {:id => @item.id, :hours => 1.7}, {:user_id => @item_owner.id}
-
- assert_redirected_to item_path(@item)
- assert_equal 1.7, BacklogItem.find_by_id((a)item.id).remaining_hours.to_f,
- "Hours should have been updated."
- end
-
# Ensures that anonymous users can't set the blocked status for an item.
def test_blocked_as_anonymous
get :blocked
@@ -354,12 +304,17 @@ class ItemsControllerTest < ActionController::TestCase
# Ensures that update the item's status works as expected.
def test_update_blocked
- put :update_blocked, {:id => @item.id, :blocked => true, :message => {:posted => Time.current, :body => 'Message', :author_id => @item.owner_id}}, {:user_id => @item.owner_id}
+ count = @item.sprint.product.rss_entries.size
+ put :update_blocked,
+ {:id => @item.id, :blocked => true, :message => {:posted => Time.current, :body => 'Message', :author_id => @item.owner_id}},
+ {:user_id => @item.owner_id}
assert_redirected_to item_path(@item)
result = BacklogItem.find_by_id((a)item.id)
assert result.blocked, "Item should have been marked as blocked."
assert_equal "Message", result.blocker_message.body, "The message was not properly saved."
+ newcount = Product.find_by_id((a)item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "An RSS entry should have been created for this event."
end
# Ensures that anonymous users cannot defer items.
@@ -385,10 +340,13 @@ class ItemsControllerTest < ActionController::TestCase
# Ensure that deferring works as expected.
def test_defer
+ count = @item.sprint.product.rss_entries.size
put :defer, {:id => @item.id}, {:user_id => @team_lead.id}
assert_redirected_to items_path(:sprint => @item.sprint)
result = BacklogItem.find_by_id((a)item.id)
assert result.deferred?, "Item should have been deferred."
+ newcount = Product.find_by_id((a)item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "An RSS entry should have been created for this event."
end
end
diff --git a/test/functional/user_items_test.rb b/test/functional/user_items_test.rb
index b1dbf18..7db7d91 100644
--- a/test/functional/user_items_test.rb
+++ b/test/functional/user_items_test.rb
@@ -73,6 +73,59 @@ class UserItemsTest < ActionController::TestCase
raise "user is a member!" if @other_product.is_member?(@nonmember)
end
+ # Ensures that anonymous users can't update estimaetes.
+ def test_estimate_as_anonymous
+ post :estimate
+
+ assert_redirected_to login_path
+ end
+
+ # Ensures that a valid item id is required.
+ def test_estimate_with_invalid_item
+ post :estimate, {}, {:user_id => @owned_item.owner_id}
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that an hours estimate is required.
+ def test_estimate_without_hours
+ post :estimate, {:id => @owned_item.id}, {:user_id => @owned_item.owner_id}
+
+ assert_redirected_to error_path
+ assert_equal @owned_item.remaining_hours, BacklogItem.find_by_id((a)owned_item.id).remaining_hours,
+ "Hours should not have been updated."
+ end
+
+ # Ensures that the sprint must be active for an estimate to be updated.
+ def test_estimate_on_planned_sprint
+ post :estimate, {:id => @pending_item.id}, {:user_id => @member.id}
+
+ assert_redirected_to error_path
+ assert_equal @pending_item.remaining_hours, BacklogItem.find_by_id((a)pending_item.id).remaining_hours,
+ "Remaining hours should not have been updated!"
+ end
+
+ # Ensures that only the item owner can update the estimate hours.
+ def test_estimate_as_nonowner
+ post :estimate, {:id => @owned_item.id, :hours => @owned_item.remaining_hours + 1}, {:user_id => @nonmember.id}
+
+ assert_redirected_to error_path
+ assert_equal @owned_item.remaining_hours, BacklogItem.find_by_id((a)owned_item.id).remaining_hours,
+ "Remaining hours should not have been updated."
+ end
+
+ # Ensures that updating an estimate works as expected.
+ def test_estimate
+ count = @owned_item.sprint.product.rss_entries.size
+ post :estimate, {:id => @owned_item.id, :hours => 1.7}, {:user_id => @owned_item.owner_id}
+
+ assert_redirected_to item_path(@owned_item)
+ assert_equal 1.7, BacklogItem.find_by_id((a)owned_item.id).remaining_hours.to_f,
+ "Hours should have been updated."
+ newcount = Product.find_by_id((a)owned_item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "A new RSS entry should have been added."
+ end
+
# Ensures that you have to be logged in.
def test_accept_as_anonymous
get :accept
@@ -123,12 +176,15 @@ class UserItemsTest < ActionController::TestCase
# Ensures that accepting works as expected.
def test_accept
+ count = @unowned_item.sprint.product.rss_entries.size
get :accept,{:id => @unowned_item.id},{:user_id => @member.id}
assert_redirected_to item_path(@unowned_item)
result = BacklogItem.find_by_id((a)unowned_item.id)
assert_equal @member.id, result.owner_id, "Owner should have been assigned."
assert result.assigned?, "Item should be marked as assigned."
+ newcount = Product.find_by_id((a)unowned_item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "An RSS entry should have been created for this event."
end
# Ensures an anonymous user can't drop an item.
@@ -156,6 +212,7 @@ class UserItemsTest < ActionController::TestCase
# Ensures that dropping works as expected.
def test_drop
+ count = @owned_item.sprint.product.rss_entries.size
get :drop, {:id => @owned_item.id},{:user_id => @member.id}
assert_redirected_to items_path(:sprint => @sprint)
@@ -163,6 +220,8 @@ class UserItemsTest < ActionController::TestCase
result = BacklogItem.find_by_id((a)owned_item.id)
assert !result.owner_id,"Owner should have been removed."
assert result.pending?, "Items hould be marked as pending."
+ newcount = Product.find_by_id((a)owned_item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "An RSS entry should have been created for this event."
end
# Ensures an anonymous user can't complete an item.
@@ -190,11 +249,14 @@ class UserItemsTest < ActionController::TestCase
# Ensures that completing works as expected.
def test_complete
+ count = @owned_item.sprint.product.rss_entries.size
get :complete,{:id => @owned_item.id}, {:user_id => @owned_item.owner_id}
assert_redirected_to items_path(:sprint => @sprint)
result = BacklogItem.find_by_id((a)owned_item.id)
assert result.completed?, "Item should be marked as completed."
+ newcount = Product.find_by_id((a)owned_item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "An RSS entry should have been created for this event."
end
# Ensures an anonymous user can't reopen an item.
@@ -231,11 +293,14 @@ class UserItemsTest < ActionController::TestCase
# Ensures that reopening works as expected.
def test_reopen
+ count = @closed_item.sprint.product.rss_entries.size
get :reopen,{:id => @closed_item.id},{:user_id => @member.id}
assert_redirected_to item_path(@closed_item)
result = BacklogItem.find_by_id((a)closed_item.id)
assert_nil result.owner_id, "Should not have been reassigned."
assert result.pending?, "Item should be marked as pending."
+ newcount = Product.find_by_id((a)item.sprint.product_id).rss_entries.size
+ assert_equal count + 1, newcount, "An RSS entry should have been created for this event."
end
end
--
1.6.2.5
14 years, 7 months