Created a new model to represent an RSS feed element, named feed. Added
unit tests to ensure that the title and content for the feed is present.
Added a new image to represent the RSS link. On the product details page
this link is present at the bottom of the details section. Clicking on
that link takes the user to the /product/1/rss path.
Entries are added to the product's RSS feed when:
* the product is created, or its details updated
* a new sprint is created or updated
* a sprint is planned, started, completed or cancelled
* a sprint is populated
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/application.rb | 7 +++
app/controllers/products_controller.rb | 17 +++++-
app/controllers/sprints_controller.rb | 78 +++++++++++++++++++--------
app/models/feed.rb | 27 +++++++++
app/models/product.rb | 1 +
app/views/products/rss.rxml | 19 +++++++
app/views/products/show.html.erb | 6 ++
config/routes.rb | 5 ++
db/migrate/020_create_feeds.rb | 35 ++++++++++++
db/migrate/021_create_feeds_products.rb | 33 +++++++++++
doc/ChangeLog | 1 +
doc/Credits | 7 +++
public/images/icons/add.png | Bin 733 -> 0 bytes
public/images/icons/approve.png | Bin 619 -> 0 bytes
public/images/icons/back.png | Bin 680 -> 0 bytes
public/images/icons/delete.png | Bin 610 -> 0 bytes
public/images/icons/edit.png | Bin 703 -> 0 bytes
public/images/icons/email.png | Bin 647 -> 0 bytes
public/images/icons/healthy.png | Bin 725 -> 0 bytes
public/images/icons/item_accept.png | Bin 592 -> 0 bytes
public/images/icons/item_complete.png | Bin 781 -> 0 bytes
public/images/icons/item_drop.png | Bin 605 -> 0 bytes
public/images/icons/item_reopen.png | Bin 625 -> 0 bytes
public/images/icons/item_user_story.png | Bin 476 -> 0 bytes
public/images/icons/new.png | Bin 899 -> 0 bytes
public/images/icons/password.png | Bin 744 -> 0 bytes
public/images/icons/product_join.png | Bin 746 -> 0 bytes
public/images/icons/product_members.png | Bin 753 -> 0 bytes
public/images/icons/reject.png | Bin 601 -> 0 bytes
public/images/icons/role_delete.png | Bin 767 -> 0 bytes
public/images/icons/roles.png | Bin 770 -> 0 bytes
public/images/icons/rss.png | Bin 0 -> 530 bytes
public/images/icons/sprint_add.png | Bin 820 -> 0 bytes
public/images/icons/sprint_cancel.png | Bin 700 -> 0 bytes
public/images/icons/sprint_complete.png | Bin 623 -> 0 bytes
public/images/icons/sprint_plan.png | Bin 631 -> 0 bytes
public/images/icons/sprint_start.png | Bin 670 -> 0 bytes
public/images/icons/story_add.png | Bin 619 -> 0 bytes
public/images/icons/story_view.png | Bin 465 -> 0 bytes
public/images/icons/unhealthy.png | Bin 723 -> 0 bytes
public/images/icons/user.png | Bin 741 -> 0 bytes
public/images/icons/view.png | Bin 464 -> 0 bytes
test/fixtures/feeds.yml | 7 +++
test/fixtures/product_feeds.yml | 3 +
test/functional/products_controller_test.rb | 24 +++++++-
test/functional/sprints_controller_test.rb | 28 ++++++++--
test/unit/feed_test.rb | 68 +++++++++++++++++++++++
47 files changed, 333 insertions(+), 33 deletions(-)
create mode 100644 app/models/feed.rb
create mode 100644 app/views/products/rss.rxml
create mode 100644 db/migrate/020_create_feeds.rb
create mode 100644 db/migrate/021_create_feeds_products.rb
create mode 100644 doc/Credits
delete mode 100755 public/images/icons/add.png
delete mode 100644 public/images/icons/approve.png
delete mode 100755 public/images/icons/back.png
delete mode 100755 public/images/icons/delete.png
delete mode 100755 public/images/icons/edit.png
delete mode 100644 public/images/icons/email.png
delete mode 100755 public/images/icons/healthy.png
delete mode 100755 public/images/icons/item_accept.png
delete mode 100644 public/images/icons/item_complete.png
delete mode 100755 public/images/icons/item_drop.png
delete mode 100755 public/images/icons/item_reopen.png
delete mode 100755 public/images/icons/item_user_story.png
delete mode 100755 public/images/icons/new.png
delete mode 100755 public/images/icons/password.png
delete mode 100755 public/images/icons/product_join.png
delete mode 100755 public/images/icons/product_members.png
delete mode 100644 public/images/icons/reject.png
delete mode 100755 public/images/icons/role_delete.png
delete mode 100755 public/images/icons/roles.png
create mode 100644 public/images/icons/rss.png
delete mode 100755 public/images/icons/sprint_add.png
delete mode 100644 public/images/icons/sprint_cancel.png
delete mode 100644 public/images/icons/sprint_complete.png
delete mode 100755 public/images/icons/sprint_plan.png
delete mode 100644 public/images/icons/sprint_start.png
delete mode 100755 public/images/icons/story_add.png
delete mode 100644 public/images/icons/story_view.png
delete mode 100755 public/images/icons/unhealthy.png
delete mode 100755 public/images/icons/user.png
delete mode 100755 public/images/icons/view.png
create mode 100644 test/fixtures/feeds.yml
create mode 100644 test/fixtures/product_feeds.yml
create mode 100644 test/unit/feed_test.rb
diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index b82613a..899db21 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -66,6 +66,13 @@ class ApplicationController < ActionController::Base
@breadcrumbs << Breadcrumb.new(text, url)
end
+ def create_rss_entry(title, link, content, author=nil)
+ Feed.new(:title => title,
+ :link => link,
+ :content => content,
+ :author => author ? author : @user)
+ end
+
# Redirects the user to the error page and displays
# the provided message.
def report_error(message)
diff --git a/app/controllers/products_controller.rb
b/app/controllers/products_controller.rb
index e24d268..6cb4799 100644
--- a/app/controllers/products_controller.rb
+++ b/app/controllers/products_controller.rb
@@ -19,13 +19,20 @@
# +Product+.
#
class ProductsController < ApplicationController
- before_filter :authenticated, :except => [:index, :show]
+ before_filter :authenticated, :except => [:rss, :index, :show]
before_filter :load_project, :only => [:new, :create]
before_filter :is_approved, :only => [:new, :create]
- before_filter :load_product, :only => [:show, :edit, :update, :join]
+ before_filter :load_product, :only => [:rss, :show, :edit, :update, :join]
before_filter :path_to_one, :only => [:show, :edit, :update, :join]
before_filter :path_to_list, :only => [:index, :new, :create]
+ # GET /products/1/rss
+ def rss
+ @entries = @product.rss_entries
+
+ render :layout => false
+ end
+
# GET /products
def index
project_id = params[:project]
@@ -94,6 +101,9 @@ class ProductsController < ApplicationController
Product.transaction do
@product = Product.new(params[:product])
@product.project = @project
+ @product.rss_entries << create_rss_entry("New product created:
#{(a)product.name}",
+ product_url(@product),
+ "A new product was
created:\r#{@product.description}}")
if @product.project.can_create_products?(@user)
if @product.save
@@ -126,6 +136,9 @@ class ProductsController < ApplicationController
begin
Product.transaction do
@product.update_attributes(params[:product])
+ @product.rss_entries << create_rss_entry("Details updated:
#{(a)product.name}",
+ product_url(@product),
+ "The product's details
have been updated...")
if @product.save
flash[:message] = "#{(a)product.name} successfully updated."
diff --git a/app/controllers/sprints_controller.rb
b/app/controllers/sprints_controller.rb
index 409c546..31c3d66 100644
--- a/app/controllers/sprints_controller.rb
+++ b/app/controllers/sprints_controller.rb
@@ -63,16 +63,21 @@ class SprintsController < ApplicationController
# POST /sprints
def create
add_breadcrumb "New"
- if @product.can_create_sprints?(@user)
- @sprint = Sprint.new(params[:sprint])
- @sprint.product = @product
- @selected = params[:selected]
- @selected = Array.new unless @selected # if no members were selected, use an empty
array
- add_users_to_sprint(@selected)
+ Sprint.transaction do
+ if @product.can_create_sprints?(@user)
+ @sprint = Sprint.new(params[:sprint])
+ @sprint.product = @product
+ @selected = params[:selected]
+ @selected = Array.new unless @selected # if no members were selected, use an
empty array
+ add_users_to_sprint(@selected)
+ @product.sprints << @sprint
+
+ @product.rss_entries << create_rss_entry("New sprint created.",
+ sprint_url(@sprint),
+ "A new sprint was defined. The
goals for this sprint are:\r#{@sprint.goals}")
- Sprint.transaction do
respond_to do |format|
- if @sprint.save
+ if @product.save
flash[:message] = "Sprint successfully created!"
format.html { redirect_to plan_sprint_path(@sprint) }
else
@@ -81,25 +86,28 @@ class SprintsController < ApplicationController
format.html { render :action => :edit }
end
end
+ else
+ report_error "You cannot create a sprint for this product."
end
- else
- report_error "You cannot create a sprint for this product."
end
end
# PUT /sprints/1
def update
- add_breadcrumb "Edit"
- @sprint.update_attributes(params[:sprint])
- # empty the member list
- @sprint.sprint_members.clear
- @selected = params[:selected]
- @selected = Array.new unless @selected
- add_users_to_sprint(@selected)
-
Sprint.transaction do
+ add_breadcrumb "Edit"
+ @sprint.update_attributes(params[:sprint])
+ # empty the member list
+ @sprint.sprint_members.clear
+ @selected = params[:selected]
+ @selected = Array.new unless @selected
+ add_users_to_sprint(@selected)
+ @product.rss_entries << create_rss_entry("Sprint updated:
#{(a)sprint.title}",
+ sprint_url(@sprint),
+ "The details for the sprint have been
changed.")
+
respond_to do |format|
- if @sprint.save
+ if @sprint.save && @product.save
flash[:message] = "Sprint updated successfully."
format.html { redirect_to params[:url] ? params[:url] : sprints_path(:product
=> @product) }
else
@@ -113,8 +121,14 @@ class SprintsController < ApplicationController
# DELETE /sprints/1/destroy
def destroy
- if @sprint.can_delete?(@user)
- if @sprint.destroy
+ Product.transaction do
+ if @sprint.can_delete?(@user)
+ @product = @sprint.product
+ @product.sprints.delete(@sprint)
+ @product.rss_entries << create_rss_entry("Sprint deleted:
#{(a)sprint.title}",
+ sprints_url(:product => @product),
+ "This sprint has been
deleted.")
+ if @product.save
respond_to do |format|
flash[:message] = "Sprint deleted successfully."
format.html { redirect_to sprints_path(:product => @product) }
@@ -125,13 +139,18 @@ class SprintsController < ApplicationController
else
report_error "You are not allowed to delete this sprint."
end
+ end
end
# PUT /sprints/1/planning
def planning
Sprint.transaction do
if @sprint.can_plan?
+ @sprint.product.rss_entries << create_rss_entry("Sprint in planning:
#{(a)sprint.title}",
+ sprint_url(@sprint),
+ "This sprint has been moved
to the planning state.")
@sprint.plan
+ @sprint.product.save!
respond_to do |format|
flash[:message] = "The sprint is now moved to the planning state."
format.html {redirect_to sprint_path(@sprint)}
@@ -146,7 +165,11 @@ class SprintsController < ApplicationController
def start
Sprint.transaction do
if @sprint.can_start?
+ @sprint.product.rss_entries << create_rss_entry("Sprint started:
#{(a)sprint.title}",
+ sprint_url(@sprint),
+ "This sprint has been
started.")
@sprint.start
+ @sprint.product.save!
respond_to do |format|
flash[:message] = "This sprint is now started."
format.html {redirect_to sprint_path(@sprint)}
@@ -161,7 +184,11 @@ class SprintsController < ApplicationController
def complete
Sprint.transaction do
if @sprint.can_complete?
+ @sprint.product.rss_entries << create_rss_entry("Sprint completed:
#{(a)sprint.title}",
+ sprint_url(@sprint),
+ "This sprint has been marked
as completed.")
@sprint.complete
+ @sprint.product.save!
respond_to do |format|
flash[:message] = "This sprint is now completed."
format.html {redirect_to sprint_path(@sprint)}
@@ -176,7 +203,11 @@ class SprintsController < ApplicationController
def cancel
Sprint.transaction do
if @sprint.can_cancel?
+ @sprint.product.rss_entries << create_rss_entry("Sprint cancelled:
#{(a)sprint.title}",
+ sprint_url(@sprint),
+ "This sprint has been
cancelled.")
@sprint.cancel
+ @sprint.product.save!
respond_to do |format|
flash[:message] = "This sprint has been cancelled."
format.html {redirect_to sprint_path(@sprint)}
@@ -225,7 +256,10 @@ class SprintsController < ApplicationController
end
respond_to do |format|
- if @sprint.save
+ @sprint.product.rss_entries << create_rss_entry("Sprint has been
populated: #{(a)sprint.title}",
+ sprint_url(@sprint),
+ "Total stories:
#{(a)sprint.backlog_items.size}\nTotal hours: #{(a)sprint.estimated_hours}")
+ if @sprint.save! && @sprint.product.save!
flash[:message] = "Sprint backlog has been updated with
#{(a)sprint.backlog_items.size} items."
format.html { redirect_to sprint_path(@sprint) }
else
diff --git a/app/models/feed.rb b/app/models/feed.rb
new file mode 100644
index 0000000..583f540
--- /dev/null
+++ b/app/models/feed.rb
@@ -0,0 +1,27 @@
+# feed.rb
+# Copyright (C) 2009, Darryl L. Pierce <mcpierce(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
+#
+
+class Feed < ActiveRecord::Base
+ validates_presence_of :title
+ validates_presence_of :link
+ validates_presence_of :author
+ validates_presence_of :content
+
+ belongs_to :author, :class_name => 'User'
+
+ named_scope :default, {:order => 'created_at DESC'}
+end
diff --git a/app/models/product.rb b/app/models/product.rb
index afd28f4..9abcb8d 100644
--- a/app/models/product.rb
+++ b/app/models/product.rb
@@ -42,6 +42,7 @@ class Product < ActiveRecord::Base
has_many :users, :through => :product_roles
has_many :user_stories, :dependent => :destroy
has_many :sprints, :dependent => :destroy
+ has_and_belongs_to_many :rss_entries, :class_name => 'Feed', :join_table
=> :product_feeds, :order => 'created_at DESC'
named_scope :default, { :group => 'project_id' }
named_scope :for_project, lambda { |project_id|
diff --git a/app/views/products/rss.rxml b/app/views/products/rss.rxml
new file mode 100644
index 0000000..cfe8d52
--- /dev/null
+++ b/app/views/products/rss.rxml
@@ -0,0 +1,19 @@
+xml.instruct! :xml, :version=>"1.0"
+xml.rss(:version=>"2.0"){
+ xml.channel{
+ xml.title((a)product.name)
+ xml.link(root_url)
+ xml.description("What your site is all about.")
+ xml.language('en-us')
+ for entry in @product.rss_entries
+ xml.item do
+ xml.title(entry.title)
+ xml.description(RedCloth.new(entry.content).to_html)
+ xml.author(entry.author.display_name)
+ xml.pubDate(entry.created_at.strftime("%a, %d %b %Y %H:%M:%S %z"))
+ xml.link(entry.link)
+ xml.guid(entry.link)
+ end
+ end
+ }
+}
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb
index 5c2d36d..0a0cb33 100644
--- a/app/views/products/show.html.erb
+++ b/app/views/products/show.html.erb
@@ -18,6 +18,9 @@
<dd><%= RedCloth.new((a)product.description).to_html %></dd>
<% end %>
</dl>
+
+ <%= link_to(image_tag("/images/icons/rss.png", :title =>
"Product activity feed"), rss_product_path(@product)) %>
+
</div>
</div>
@@ -41,4 +44,7 @@
<%= link_to "View sprints (#{(a)product.sprints.size} total)",
sprints_path(:product => @product), :class => "command" %>
+
+ <%= link_to "RSS feed...",
+ rss_product_path(@product), :class => "command" %>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 1d4c143..79f0cc1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -42,6 +42,11 @@ ActionController::Routing::Routes.draw do |map|
map.resources :stories
+ map.resources :products, :member =>
+ {
+ :rss => :get
+ }
+
map.resources :products do |product|
product.resources :roles
end
diff --git a/db/migrate/020_create_feeds.rb b/db/migrate/020_create_feeds.rb
new file mode 100644
index 0000000..20d4f4a
--- /dev/null
+++ b/db/migrate/020_create_feeds.rb
@@ -0,0 +1,35 @@
+# 020_create_item_block_messages.rb
+# Copyright (C) 2009, Darryl L. Pierce <mcpierce(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
+#
+class CreateFeeds < ActiveRecord::Migration
+ def self.up
+ create_table :feeds do |t|
+ t.string :title, :null => false, :limit => 128
+ t.string :link, :null => false, :limit => 255
+ t.integer :author_id, :null => false
+ t.text :content, :null => false
+
+ t.timestamps
+ end
+
+ execute 'alter table feeds add constraint fk_feeds_author
+ foreign key (author_id) references users(id)'
+ end
+
+ def self.down
+ drop_table :feeds
+ end
+end
diff --git a/db/migrate/021_create_feeds_products.rb
b/db/migrate/021_create_feeds_products.rb
new file mode 100644
index 0000000..9711388
--- /dev/null
+++ b/db/migrate/021_create_feeds_products.rb
@@ -0,0 +1,33 @@
+# 021_create_feeds_products.rb
+# Copyright (C) 2009, Darryl L. Pierce <mcpierce(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
+#
+class CreateFeedsProducts < ActiveRecord::Migration
+ def self.up
+ create_table :product_feeds do |t|
+ t.integer :product_id, :null => false
+ t.integer :feed_id, :null => false, :unique => true
+ end
+
+ execute 'alter table product_feeds add constraint fk_product_feeds_product_id
+ foreign key (product_id) references products(id)'
+ execute 'alter table product_feeds add constraint fk_product_feeds_feed_id
+ foreign key (feed_id) references feeds(id)'
+ end
+
+ def self.down
+ drop_table :product_feeds
+ end
+end
diff --git a/doc/ChangeLog b/doc/ChangeLog
index d345eee..236373f 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,6 +1,7 @@
Change Log (0.3.0):
* #156 - Backlog items can be marked as blocked.
* #157 - Items can be marked completed when a task is added.
+ * #159 - Users can watch an RSS feed of product activity.
* #167 - Blocker messages are included in the daily updates email.
* #173 - Backlog items can be dropped from an active sprint.
* #174 - Deferred backlog items can be re-added to the active sprint.
diff --git a/doc/Credits b/doc/Credits
new file mode 100644
index 0000000..8b630c4
--- /dev/null
+++ b/doc/Credits
@@ -0,0 +1,7 @@
+GRAPHICS USED BY THIS PROJECT
+=============================
+
+ProjXP would like to thank the following groups and individuals for the graphics
+we're using:
+
+http://www.famfamfam.com/
\ No newline at end of file
diff --git a/public/images/icons/add.png b/public/images/icons/add.png
deleted file mode 100755
index 6332fefea4be19eeadf211b0b202b272e8564898..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 733
zcmV<30wVp1P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!Z%IT!R5;6}
zlj}>9VHk(~TedF+gQSL8D5xnVSSWAVY>J9b+m>@{iq7_KE}go~11+5s4;8hc+i0Xa
zI1j@EX5!S+Me6HNqKzU5YQwL;-W5$p%ZMKMeR<%zp69-~?<4?8|C8S?bklXr4v&Ov
zb&06v2|-x?qB`90yn>Qi%Sh2^G4n)$ZdyvTPf9}1)_buUT7>`e2G&2VU@~Bb(o+Mz
zi4)>IxlSY${Dj4k={-9RzU^W5g9|2V5RZ2Zu<x6&^l=W_1sO_5@*~{AJR(k@osu$W
zIOyKBVDIZThPU;2xYmJgUn>lL9s2xQbZ@r6eP9Ra5u(s|C0Nj#&4>wTSkb?%#=9?@
z^oxDy-O@tyN{L@by(WWvQ3%CyEu8x{+#Jb4-h&K9Owi)2p<DqQ{Z%tMS5;_RkwZ2s
ziU|ZZE*fUaAe}14z#AR(OU=04okqn3igEs-_q_}KZ*?@>gg+heWDyked|3R$$kL@A
z#sp1v-r+=G4B8D6DqsDH0@7OztA7aT9qc1Py{()w`m``?Y0&gi2=ROcc-9+nU^I6<
zT=e_Y=<?pf1$FXK3F5I5#ceAAN5BHvd?h5_(jPS+7l@o3)VYh{*frx)Pb%2=Sw~G2
znu{1!PYZ*jM}To^G}f>vSnG@?3Ue{BW5ONFttcE!R-R_W4O01|0-|K-YNXLo2`4Qv
z`r1LxR6#yf3FB%T95gJnaKKivA~Z}S9A(ZxE<qS_Liq!k=vg3Per<qx!vKx95m{X+
zQ8;uQPPk0h^qI`uo^&$1^CFd@NeQR5pADaHJwu&SvB+fQDdu0d@n7>DK}O3T04USJ
P00000NkvXXu0mjf^IS-S
diff --git a/public/images/icons/approve.png b/public/images/icons/approve.png
deleted file mode 100644
index 2bd16ccf294bd944c6bf17fa0345885469980820..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 619
zcmV-x0+juUP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz{YgYYR5;6(
zlR;|}Q4q%ywK*uB`~V(A58^?=k7B`|1LCO_4}zCs4T7aDg-Qh#6xy2?LjyqywQXvQ
z8xl6Gq05F18+Mmnc701Wq*CjlKM!whj5W|6=J4Lk|2H#l=B0qtk*RS8HF|(<f#xj_
z`9|3Ah2~wNX<NiS(9NHy&dlims<?m_yv6q+?ty0Zsk##<2S5rXy3KCu7f}~N0g9=z
z>EAdBAPt<OvwxAAGlT2MDr_6d)@wGr^P>T3aD}=*%{NbB*ZGcS?IC*5jinhDl=TC)
z^a(zA>EnR9^9j#^IEMZn^!id5#SnEtL|{9h>X0|4DCpP8H?Ix=ni&xHWU$qNT21yZ
z5^*RX2qmP^fMQ*vP*nzi&BkZ)YfvhI(E`_#urPuk5&HpnzVw-Gc(=*`uwjl<Z^+W4
zt_<kL65xm61>h!P+m)3pz5ENXE;8&W2W*v~T!vOF>0KmQeQ*+S#{tWRxh00jSgfv7
zu5dK}P{{s0ADkp>$Chu@w&3}~KY;h%H7W`eKSHG<MIw^f|A^ZiXtklK!{hlM!+;g{
z3@eR06bfJ%QXB{gGEDfQ!0h57xmn2OV(#Xw<E#A2NHbr*#oXF9Z&nX^u?*8s;Nhcv
z?oWN?-eivK<W0t(j*(p$`~P2%D}5Ho@NDsNavu4aegpALNqNzBB)0$n002ovPDHLk
FV1f!F7%cz*
diff --git a/public/images/icons/back.png b/public/images/icons/back.png
deleted file mode 100755
index 2e53c6980f00026b22e0d3710edf048e021b4da5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 680
zcmV;Z0$2TsP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!I!Q!9R5;6}
zQ%z`7K@k34@)BZ7HC0S1Cb8BOF|<`u6qSHhu!5*4=utsv!5(@PJXiz;kDkQ}9tu`0
zLJ<|>r3gZ6sTvbKG`S=Qf*6}Nf4;Z7Z{zN!O--ANbYb~sXZM@=W_MPrR;$>|(APVL
z9?v<)29FSdeXBlhS+G{-_{fQm(s$|pt3F04wDk%Eai0K>nDfCMZg4J%Tm>-+#q|66
z8(eUXMZynJwbm5eoE>%wcnw@1t#WGynhm$k?XL&soFn!ri`4f$cVy<%2mLsExU->z
zZx*xss|zVtj$|^aY{nS+ySuS>yS}Tnbt?kCHpJucS_vZi7oW4eS02jdvmho#X{ij;
zASmWb3g!Cg&?GXM48q|syk4&gstfW5ufx~d(b5UV8T>6lg%x6ea*97xpv5pT@eDFq
zp-_Nnno3<Nm4Ys0Q>HNxizp%!hp9l*G6j*sWM<7rm?Hgq>7h^v`h)1B=y2@X=W?ZT
z$YtMx?9VKI<#P?vWl4;(2C}r%>Gaw&UVVOfffyvn3OyrEa&l~WX&F<uFTgMiRVyI`
zxm*s3L;{gW1c5+6`RcDA$UP$COMCJ7S7xgb<Z!uM^^9(}8y=5GO<mXFa5y$L()qhn
zN9{IkX7TqTC?%qHx`H+PV)TFtHvVQ-`02)0)_@;!qht5ZroI2--JH6QGXwq2|ALe*
zGiD0KrV849Ue#E!x6?|2_CLR|>&m?+<#OqiY~^j9wuSWM=zzA_@B9}<+jo_mWWEvr
O0000<MNUMnLSTZ{95urL
diff --git a/public/images/icons/delete.png b/public/images/icons/delete.png
deleted file mode 100755
index 0a335acf67423fd5a17caf2d18a67e66e870611f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 610
zcmV-o0-gPdP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz^hrcPR2Uhh
z!B1$<aU93-=lk>hj32+Ia2PFSwHp_;8^u8>r6{e*krHy43#H^jT&z}Wa&xpokqZtA
z<tUdO<j+sGk=nuRH}?I$-!J>FR&Fehhe_gp*x{i&XLj%HzdqAeQvxDT1Rjn;gaWw}
z5^~2QShuR2o0yn9fA7Y?Xzt(DKhn`?rmhAn(VT1h2r!!4rBZw52P-vSDzPZb#g$`y
ztkj8XEoxZ`Y73PkKp{LJ5D~&7@Je_kT)~2i-c6l&IJJyK&5~gfN`_2W7%3TM2{XqE
zQA8qFq861?%N|ZG0Wt%FLJ$TKq7Wo2$Odl0Q&0;JYFQzcn1MtBWCjLiAQxdE1Cmih
zK`p|m<p^h)nXyD70Wu@9kt3LTc$4XeW3)fLrK78x9jo^M2gy}gvcwDnBw=QVMG^^^
zesqi3SL5tFa-7w@+nIm!m^IIz@?>Af*(48Y1z>=gVSoY2jATaZ?l66O4$*k`47+`l
zweRoK+p__ghH^x(%m8DN8Gl-sYSGx#3kS}zEMMMC5w<N)erS!K8ZHOIo$$cji3q$b
zi3mbsps}9z>qj&noaWd37uvw=_X01NGD-Z+i^1;8t2&z(w`{C(PM?|mR`Ky`;pI<V
wGD-Z4mxEg`%*{-lEZlm$(4=5&|KsZFZ(v3gV*E=9oB#j-07*qoM6N<$f@e4h(EtDd
diff --git a/public/images/icons/edit.png b/public/images/icons/edit.png
deleted file mode 100755
index fb2efb8775442af862ef0ef111f371e5857928d3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 703
zcmV;w0zmzVP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!QAtEWR2Uhh
z!QE@kaU8($_vd$h=UC3>FxeKF=OosmQ6jmTLP{}-6iF>nO8f(+aY2!Xm^*5Av6NhR
zD0!Nar%`rnu~v@R4hO^8&iS41=VQN>+65QO>m_E!|B#IbuI^pAy5?9WYjHC`6;s8j
z!_-hy%sJEya}KA<gjn#aqa$^=^+eqnzh*_vsc2E$D=%U!;=i))6mZ7R2IgfmKN+jR
zz&wWe=8T4Ia~Z4MjXi{XGbNNSI1Df~oPuJg8cr2gFkHb1KHnw#{4$Z^D)yD#<JH;y
zJABLti6@8|<_RW-sNi{mh=+(nGuMgsKBb~+JBe9~`PMz3<gKRTzEelY155-2A_gj;
zYD5eQ>D$C|Z-~!ZLFQctG09Uhp@QPcl?mU}7$E{?cz}t3fC%LK?;}5+keI!OTyHb6
z@j}nbBm-HHT&CJnb^IYBAVSCka_RdNzT74;XDve?FCx*eM2ky^TZSvC<t*LT+UXU7
zfDs~y2q6)nFL|BphnpnkZeS>N4lf#zADBt{VLMZ58~8Xlk&tIj2}J+_M1=n24SuBB
zC|kIW{HG=&F(WrHgY=^pRBSp=QTYN)m5{Hh{2@SBTQi04uPMk>dS9PrQdx|l%yhmz
zOH#Sz0@1`YLTX0HPj&aS)SnFM)H&2CwbI1q`b)fRK1k<-HpW#}^Sv*{jiIgdH9W>t
zQ6<#EFflVmJF;g{aA;S(kLP%K=NdiTT|X03N>|n%ZExo<#LO72ZdK{vlG)|{vIVoS
lXs&IrKfQB(<E!`l!*8ZVD9)Bs;gA3T002ovPDHLkV1o10Km-5)
diff --git a/public/images/icons/email.png b/public/images/icons/email.png
deleted file mode 100644
index 2c3c46f44d10e2663721c57f0a0c70689326508a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 647
zcmV;20(kw2P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!DM>^@RCwCdRXs=?K@@(o=MN`F674J!
z)GC!t;6kuSWuuKY7Ul|rSfz*{gh+@hq)-T?FqMTCC&D#a*;rYKc#tNQm6i&^DVT7$
zJGV1=Z)Rs_FWFP?ugK%x?#+AizHjEe**8o|39S?dS}bk!V2puWn_YsG;{t0CF~E$J
z1DCzuSf=bSm7<kt4c^y_l*p;FR%_~*`T;Kk6pKhCT==-Xtabn;PlJ~@;`*p{*2Q6(
zs3VOeS1t}h0?*UTq>U6EQw<9n0AJr~OjBg;;i`RKJ2|gkDL!1VPnd=v;5gvg0E=5#
zBwo8xoDn1o$Yu$`6&U%P#~ty9E6q3ZX;KsL7=bW5_%LQCe%Ybi-LEvy2*oSAuQ8(?
z#8)#vY6DjH?p`_hjZj?7r!fDifzfxbZQ!^4N}o}(8=?6XeotdYDe}Wp6xX>|7U26q
zrH{r&XkJ3R!i?`g`U$I?d0~OpkF<^6M#!JAyCBr47X@L}SyCT*GYqM%pZfpi58HCk
zo+R|03T!jx6t$Thlre7(e&$IeV(K}x=TGc0$8j}qN#GKqQ=|x<rUm@=d1XuaOZdbP
zbnTu(3E$Phtq^8J0FNbfO93~(v{6)PH8<nW9@LV09${&_q$Ma^+~zX9m)V|yet^!7
z#_j{^LFeaCxDvSx^*?nfFgAER;<%Y7EZdA*tZ*%JFAs%_*k^`-?1QL7O}Z&hQP1p+
h_CH_xEhqRRzyRjXu;TWwPKf{j002ovPDHLkV1oGXB*p*$
diff --git a/public/images/icons/healthy.png b/public/images/icons/healthy.png
deleted file mode 100755
index ade431851b0b6546eb6bee5cd85716df7f67e077..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 725
zcmV;`0xJE9P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!XGugsR5;6}
zlg&%iVGzeZ&u?wj-EDm-p$H5kii)Tx)-Ga1Q4}5Y(8ZJ8>L_^0`U`~aor)ql1d5Pg
z6owrVjF7Of7j1n54cD~V+Wq~W=b7nXZIaQU<}$-D^Wh8g9iyuJPn7-MaF0z&l@1k7
zi;z(T6-GoDP~qCfbDCc}Z`LYsk4>`*H%xtJgQ?D-@mf%i7IOIIQNnlKSrOW6T6Aa~
zzzv!ft#0lKwzQ#%D*U(CNVtT$BA5z-ik%o65YF5q{4ms7cV2r-06S=ERhf?MznhZa
zGrpJw`vq|!>WixoQA~L~vGV<V8orPhVf)rL{TKkK&=G9!N@*M<%!2#MU|$X-0w3|@
zA&AZ6K9AwUNfLXyQsU_V2mnMlYib&iVit7;R4m8NRH9;0Z)s}IqY|Pvk6U?8S@kZ&
zb9OCYFXd^(t(2BjEb1cEM?Y$d`UnYgK#2D=lmIFe)D^)y9`!zD>h0X>qPIVC$n@kA
zgAe9Vv7m|wv0n;2S!@A_bF_Ik?_SL^JGp@R5EaWzcA1Gc%VZkUm>_}pGHl31$w(sf
z+uZ2Ept_z!a-O424U9dTV*JG{cuTU<kjYe$OvETlAE1z%#zyp)&bZuT>O^>-YP_8i
z`v#vMN1_$fg^2rkMu;VMV$!FWzJD?AEISTe*2Mszrd1b3X#X~G3v?T?bR#BKi;99M
zL3}eC>Q11E<1D@G!$!0px~z-qtUQ0moD|RX<lfGP_@;dX8v+oA3q4=w-?A{=opqK=
zhp*_sAAbR0_NGaRr&EN}-ji_=ILnB$3^+^ok*j}srhkd=tpkg_#{ZgA00000NkvXX
Hu0mjf#l%Z_
diff --git a/public/images/icons/item_accept.png b/public/images/icons/item_accept.png
deleted file mode 100755
index 28c2175e691b5bd77d51e0ff19df587d3cd0b8c2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 592
zcmV-W0<ZmvP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz;z>k7R5;6}
zlg(=rK^VsO-|*I>7Z08a{s)Rsf(J|SV_Rz!8yef7kVJ&ghD4GkA*3yaw3HgOrMaY5
zCEF^>3bs|O#wgl0$9$0`oBc>UmB*RcC2f(EL>GQM^S=AeGc)h*Z~(affwPP)k4&ZW
zy8GEaTu%wfT{sti;{L*S+?&tAF_*=7d<S<Qe};YLBW$rPxZ>}1I*%E6Q~85vri^Z}
zN8TMU1G@6RU=6$lGjJvM&}=rl=7#UJVc>l73ynqtIzxx9>ufBFVp|%dhW84l0cn`3
zs_37{w$MmS3)?-Krs10Bm0>`;T~`z+b%IhiRXNdszQ6MDg<(KHRjnpNmSv_4xkj``
za)urv8+pROgH^-8k@yNpl2A3FW2q|rb?$g7jPaSPu!j1;KROSKbIdTX&wfIsQaRQG
z8XrBv^AAh#tPEl;H;pev0payKxEwx%-jP#5ZZx)yQmI5Jn`&^>U?^|_>2DFFe?(av
z+_;JG#w}{_o3lkXQ79A%1r!N|7R8ocbf3k`T;f<GSF_X90Q4>_-wuiF&l>i>!Ju~?
z*C#Th%WJGr{q8i**?JHVhTs!;Hrbcq4|mYXjU$DVmx8A;B@DBbsnVGBpwnwhiv0wY
eZrfBp&Hn+e<03_si;HOh0000<MNUMnLSTYC4GRna
diff --git a/public/images/icons/item_complete.png
b/public/images/icons/item_complete.png
deleted file mode 100644
index 89c8129a490b329f3165f32fa0781701aab417ea..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 781
zcmV+o1M>WdP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!pGibPR5;6}
zlj}=UVI0T(J9f@?Yy$~oL?MENP<s_55<8j=#k?#_)7`z&He=XKi!yRv#z-kGv(##H
zPHpPc=GK%laoJHq%)RMCwPAFzZ|CgAOcEn{;0q5A&*$@du5ke3{wIG76!;E_a;FdK
zvpp$H#^e2A>4-QibtN)VXQDpczE`xXAkUjh%RI>;okxb7K@0kpyQ1k_Y(|Oe7$m(^
zNYX>mI||sUbmn+c<m#Le&eeX{US5M~t}+^~?^x|a<4hF}*!YoT8=u}L$nm5IGu=t+
z9L!Cu36!D2Ujog{8R*!Qv#Iu-h5hwCT%4+a*g~$0uam-<K;}*|sK&CQl{uILRo+uj
zOcz2iRRHx=A>3<&FnE=4u#()KBS^SH8e)Qs5i!#lY=$-1gbH6VluzU=m=EP78&5vQ
z-?+fFP-G2l&l_QzYealK$;1Rl?FkzXR&Jv<pn=v~#I9rjiy!8pnkdBB+E5h!vH2Zs
z&o03*QH;J|Cj>@fBPNjCr#AYRyJ7UJQ0v#?)7Ott=>3<sG1xL&549^BdiQDc2Rk6B
z`CZUMF*oL$(7tdPx=A_AzG_6ieU8GLKR01{dI4q5ENECkOP~(zUNfjFVrvVjw*&_H
zKpN~TcTqhdhuVD-b<^codbfbK*#?vj9*4ql0y<|7?610!ZaoaDlGr-LWGi2|kG&eR
zM}vpV9aN6yK|7oS)sPHI2Nw>`#-pV!7>9}>Q1jL)H6h&gkP@3nI=+F3nA~M>u#(n*
z8T!#8oEw&-mED4!h4s!N@Jo3S7N&Q6%6l3}nlcd~X@>;uelvPsSkXIgg~e+^T1zSf
z3SNj(5%jK~i8@b;C<CFVY6wQ4<%I<*UYM=Ou+dYcgy^ro@n7=`XV9$WdAihN00000
LNkvXXu0mjf{u*Ke
diff --git a/public/images/icons/item_drop.png b/public/images/icons/item_drop.png
deleted file mode 100755
index cd305ec83b6a7560de21a287fa7a780bad893efe..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 605
zcmV-j0;2tiP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz?@2^KR2Uhh
z!M{t?aU93-=jZOLT^;=*N<-?@Xu1}|ts5eOAZVyTq&X}M5nBq15Q?BBQ4p#A0wWxR
z7Hf!pKr~piSVO4c9ZH~*dRE_izhC)91cQD_k4KQi{|KkM1}_$lHs78tD=Pu+$Q^S-
zE?kbxa0!`V?rf`$m&V45mxu1O^heD{n)|9U*;Gx2jmR#Qtq<sr%CS=A*+n*LIaZ1l
zkxX1WQ^!Vi^iGn9Bu5e=ArKG(Z$?M?ox@E{m>Y=*2{WUucY-zdJL^dl3I%>;ad8o^
z7>UT-aEZGeIS2v;T;fmM9XBTt$%UH}0?1h*2qK@)Ge19v#5w^G0dO}Gk-On;h*g0V
zg0c5w{A6?(dp$&D`V;BhwH(@f3^+wpiDS%+&U-Vg>20eaQ79BhObrh(SA506v+ZnZ
z$g})zgzWPtJU(945y>2Pr{~-rKqTCq^~N9e(A;`~%*Utj>?T{b@1P-<WAuZ%B6r7K
zfD-_*s<H6^rBVq9d@oIqscnFhmsk^Z?<MV_J}Qn+KDaR$x40Q@j+x=^SRCW-xI{~4
zC*`+~$PTyjZF!n9u<#{~r6~nT{LPEjy6)<&*{l0@RiY?0#lq(b6EkUxzv_CB#J_mi
ry8p`3Z0UU3LeA1E3I<M$RBrtMF3c7U8sGJe00000NkvXXu0mjf%W((U
diff --git a/public/images/icons/item_reopen.png b/public/images/icons/item_reopen.png
deleted file mode 100755
index fdc394c7c59b83cc2b876abc41064c75eb365877..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 625
zcmV-%0*?KOP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!14%?dR5;6}
zl21sKQ540`H;#r{q+@0|4upc#+Evt|+}NrKW)TGuWV=voQ3}~o$dv_d+C|VJ!=QvV
zg=H;rBZXmqaGb$ppf*{NV|@3V`?b()L>FZj9*=u@@4&g|7erBn|Ebu&JU%m$={t4j
zMA?=F80s{QH%n(hsfF%mohhehBz1^t6ID+NGJzBtYm#sZbA{ZEu?vrT)(Lb!?K~){
zH(Aw`uB}X<y1W|kSR9H3xx-yxB$$Xd*=b}y&J8@d^rAlw0A1tfQZDb^pE!_isNRER
z77+`|Ko_)nJknZkM$lLR0C4~il}T=IO4nEI2Av2=WIw+{{!<=n7K~`zm4qbB&F6+E
zuDrZlD$ucWTMde~1j#Y}c6>q9=*Zczi=_)|A3QuQ<J3g|WY@YBNVQd#S0O+Qg)arr
zxZ(3k3cPE^^QE&m0MH1E2!a46f+07J@%h!sflWbTsHw#ti&(ZI5<BW(#>}znM~D7~
zjUb95oV<O!r?ECU)Uvk)iX2PJOPHOXMSdX<+8+)?t@ILRhCc*r7R)%BE98z;lvSkb
z6AcIvqP4jd&HGy5k>Kv23l4|e@$lZ*dJFeEA1zqO!B_8JKbXnR;M>>lDE=(2>_dXN
zph(~<P@*<Rx&7Lq6ipeD9Wu3%s*@=u3X<dZ?Q-O9%?BF<wo<<UiN|Q`jamP@00000
LNkvXXu0mjf7Wxxg
diff --git a/public/images/icons/item_user_story.png
b/public/images/icons/item_user_story.png
deleted file mode 100755
index 6a93cdaa78cc42caed19920ae622af7e35f6067a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 476
zcmV<20VDp2P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzZb?KzR5;6}
zlif?gU=)Y_7o{kP=!2pHrIkZrGlB>yh(bgPr6Nj-nT19X7DZ8zeUKOl_Tl|>1YLMH
z=jlD?b+Sb_xgR_*#(SP~INR$20GAV7?rFuloUPPDd!HchGLr8gZI>aqRf53gD~KB}
z;7=4_D*g<@>Ld7K_aG;3>sUvEaJphdb1M87A#!by06TZW*wPh{Ku&%@CmC6|-~wsq
zjb0RsMFKOF(Fjbu5Fwh)ru|I#tR-Lz>qIaxcgh90?Z1KrCWc|y!1T|aZ~=a*-(Ag4
zSPUtVz{2m+IDzS#IpP9w-9EN;RO;3eG#U+?z$0h4Kv;Wfk8B+i3#{n6-UibhNOQqt
z?12jeFM)^6#o@C#4HjCL*d?a8z!%N)t>y1HEak5ffl*Zzs?{nz*J?G;G`=UdUjg$j
zC=)9;^k<DOUczwr90uoeY|F>AC{HL0z0x7{1P|EQ`>eA9tOij?;P^H=75o6^EkKQu
SuK{QP0000<MNUMnLSTYmlE&o#
diff --git a/public/images/icons/new.png b/public/images/icons/new.png
deleted file mode 100755
index 9c8a9da4ae49b7fb02af2eaf6e03e0f6c91ba01a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 899
zcmV-}1AP36P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#6-h)vR5;6Z
zlS^n^br?s_otZmxC(V#aQqnZlD5Pl<W74DuN*^ky*$8b)6(R`rfi4u?6r~iG78I%o
z2E~eqZp4igq$XCQAx&GONeiL2d5mcuO(xAGoy_~r-1&c>i-HS{zx9u^IUGw>*=$qi
z4z(fju8Kxf<gL~t{Z}{pS^ox1_aClP(Kl7(_1dN*QBzps&fH*DML$y`A3oSSxV$M~
zW}wGb)fZIc?Z}Sqo!eTU!6$}nd<;9}XEip&#;x&r6*;XUUvwTDDf|PN9_Z;t^qo+3
z=fQ0)M{%l~K}(dAGu#|H#k~*g$5(M5#ax2hv2ikq8>4E>slBg^es4|nAN~@NV_SFj
zT24(nZf1>C;s&Oa#mmJBSw-p_cY~Y6U)hMyiI9#@b2~OpJ~{tQK#e@V>&ZUL%dC-&
z4<V&Ap?rdTI!=0ViM_oaV~4juZVt`Gu+r1iHgr%`16O{SeKw#XImN09Iw2x8jT92s
zsi=+;tqv0=5AFh(Ah=6VSR}tPN_OrN&izMGBe{TzfB;qyyQ&#G6v15`L$a&bez5X?
zfln!|{7fdjK{*_SU<mcfs0aZy!d(vrv<QJMICWi=gJB$Z9a;H_l$W9GRANFABwvEE
zBBe5F3;{Lfu23}~9!MUvNT6~Dk@{Vv?u_C294;({xV#o7?YflQ6bF+Nv=||vB4M9x
z17RqygA_qrFhy`0C@cK35M;`(<?%-!;+~pje*N<-=dWF0a>K3ksgdE?;g2XJ7a-IC
z{t7T9P!AB)6MkIq=xo`8@fr4Pe+pxHJkq|8i#gBoi7`)S7Dry495@-9|NUzWL5S=I
zI}8e@=#j{*V_TIRYJCHM<4>HSsjdT~`23%KH*e}YU%C<>JM(QmG2_K2&b4Ftok-)u
zSoT&#!hAJ4MD=!?;n}ksXzJm;^DmMqtaEL0%KcAFfAn>=sgaW^@?6tnFI$DxIX=HQ
z$n|KMeH{mAuJ2-I<tmpZM!0n|^?~(&IbS~A)~zBZ5DBWt`^T4a`+?Vh2#^6j`K@pH
Z#NQ7iuPIaGhb;gA002ovPDHLkV1nv&k?{Zk
diff --git a/public/images/icons/password.png b/public/images/icons/password.png
deleted file mode 100755
index 30b0dc316e52dba388d88112d4c1cc32672fffbb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 744
zcmV<E0vG*>P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!dPzh<R5;6x
zlU+!YVHk$LRU{on2NEG99t4gN<(k<vgSIj~$mk$~eksv@gmxl=Ow(;Fr^B3}b5Lr_
z2G&-MqzD~`qBeg)s5vYXON+MJpPSp<&)xfdS}mK_2lvVQa$nE=JkR@40I2o!$#_If
zgcYe*-~X369QeQ}9^~I<-#CKyR)jn~<T%PeX7qx)>jGlUfiHCke$)P}4*HwX@?mb`
zzgiE#M5fLDxtj=lZ6q=+Lkt2$!wyVqxC~@X03De&Gn$t$kdWJig()R`(|L#ldNHNi
zi?tK@-;xA1zab1r3XkO&T;m5wdrx2~XU8>fpl4v~7ZF1h+!NXGy*rQ6jw}?mrNKGI
zL&zzIrIL-VTRiLE`+jy5wt-SCISiy4pO}x6>V>$`&V{7&3{GoOF)87oTao_ek0H|L
zXxL5q?8f4p7$RLZL=Q4>?LH3$EqhS@^b{VAG@wL(0y*{DquI)BECvw!(t<WU7OeSj
z4slT2o&n>y8jr^s8DqzY3Mx|xw6AM%RhNVG>V(j48H=@2*+n87;k63kFsH&hc^Czx
zU)p@TON5%2#gM-!LRIG_NS|MUrcZ`*_YPuLB^9Iro+W2D85SRofmAHM&xik`9B1#a
z@o-oLow*L$!CJHqC<x>_n){?E(&Zwhf|^V!qqZ#X+&c)jMMwsg3*W31W<{FoWOGV1
zuOTTStWS(&DYr&0v}HowTZPN*IY_RcCU%rj3Cs*;4T3Shy&sFSmGFOV!%!{P*`>;C
zSiN43jAg&56(U(ojS}<bU;n~z%OUZEdjI^WYM*^X$^G8flvN$?agoUOo#Ks1ETcBX
ap8o(~AJmyDx~^sb0000<MNUMnLSTY)_fHN0
diff --git a/public/images/icons/product_join.png b/public/images/icons/product_join.png
deleted file mode 100755
index deae99bcff9815d8530a920e754d743700ddd5fb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 746
zcmV<G0u}v<P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!d`Uz>R5;6}
zkbg*1Q547RkCGx=+ZrJV#zL@SQK$qJV#CSW)Px1IG~1R<ooFb9Gk=6-&6YZ`Y^yDm
z;e1;&Lsyz}WRQ`CmeV2hmrxcVG_cf#%KP@-D?~x2(1j1@+{-<mbM6fR5b{5)d8moo
zRZ%DA%r;1OLN8{aLdc%Wh~ZUlNRSi5DY>7@Ce7&_JfOHMV?!rlp(uU_DLu%oT329{
zvd}^m>Zu}~l!lF)$vj*+!9ivWYi3=6E`B>+7|Su$tH+R~2!#ne6eorwU&M#{7<<90
zO$iMuFlR;n2z>v9nKwp!?XQQ|aSfBtZ^J)10wQ<s%vh^tOHe^$#{NP7`*utZJ25{>
zP}rH=KSJQ4N-!Ms3A?4X%~8iSR-zylzlSXd_?|M%f3%_Vax4V#xlec^^VT&5JP8rX
z6}RO@h&}Lqo`s_<751_e20DK|@e2`2FToK$y2KTlwyhFyPdYY*B{>w4$%B}fnn&9d
zQ0xQp-T@b00q1)Ft+NxwMg`RMry#!}42Vk(RW1t-$ePm<PwU|vT7t<76uc#oJ3u14
zk3?1%38k4pl~ajlz9x)*bHmWDf!rX#k^JylM)09LdTH9F#l2=16unees-v=-#JLU<
zXKYlgk)Uh50bLV~pjWNuA`G4!S`c6a-im#s-+dkF>K0V@&mp4&IBO>%w~~-qNF<jX
zMvu>em8*NKi5C3*h;eH{=}2kRqEdNlF-|c6B{jNg1xE|{xZ_qq=T<Pqx<19~31}wm
zd0~}TtGRp9T&Bo`)-Qa~<2im(#{xgmxgd~dF3M`7QRmKPI@6KfFaN<tpf1-?{G`YJ
c7i;MAKSmLw1Kmc8Pyhe`07*qoM6N<$f(U9xs{jB1
diff --git a/public/images/icons/product_members.png
b/public/images/icons/product_members.png
deleted file mode 100755
index 7fb4e1f1e1cd6ee67d33ffd24f09ddd5c3478bec..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 753
zcmV<N0uKF&P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!gGod|R5;6x
z(M?R!aU2G4>(G`SI(6vnfMgxg){D+Lwutc1Si0swhN#FwOv#}l83ts6rCW;r!9Q9l
zl<41549yYiq6clJ;(J(YgF_14nmKFB@QK(mo6I~sr{BJxJ$rsp0HSt^ntND0Z;o48
z>O2Ckm9}n?$F`*>$L{;{zT>f+bCm7tpaqw^4q<CrW%R~f0d1m##ByIE{H}a_8>@%k
z&cHHt3=3xZmt6rQ_dtDM#)Xwp66-Thu=<9?(zFvpy0gAr0U4Z3smE5f@pZNr!NoqT
zEjSPuCQzMw(H;?yvf{+e;!7(;4hv)+d%cjKFiBL%egy0aeCof8z<>rLEjMsF|CBRH
z86WcxAYvS6H;Yq)jY1Z-rrjWiu~m;clLmJlDAE7UhMJ*jBxp}s&nQkrZvqDXxsiv3
zSJ78>4W2GFIu$$+Ic&5Pq{1?zhIy(24enCZy35e>z6~XgVx$x%k(+>tPw)9SL~R?4
zs${`1bqjTFC3F)dxIIw>)!QP7$vk+;^#2c5r{lsjtwKYnfnn+<nnEcblp)KI1^=Tf
ze}TQ{n^Y!M@wUO@dF7DUvT?mzfC5SYNk=9w=ovnxw5rN$5eUP_dl=o44264j_%m?t
zxgDBz3QEF?$K&6jG%aC&O1CwJ*%}?`tD|U~79LMNxHhmDgx&+>j{~{GK;|I8rvPFU
z5NbS#W7m)ofjNER&&ggR6fXi0xd4%4143#8JZlhXW+2TN#8b=5@L&-EUlY^cTT=>w
zb_~+jfcRCYfdj}H0J49#sP#gtxE~%YBJiQ3AjMgoQJKuMITA}Iz|zizG7pw|7R*XF
j=$D`QjOCK>V3B}dL4UFUkhgq600000NkvXXu0mjf1x-zB
diff --git a/public/images/icons/reject.png b/public/images/icons/reject.png
deleted file mode 100644
index 3c832d4c83cc0f7869a83f88833699daff52fcf2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 601
zcmV-f0;c_mP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz>q$gGR5;6x
zld)?PVHk%KwHXvA{{RQkK^zqPQ*`Jo3NFS)5G+C!og7>$D6NEu!3M;jM7RtZQ)9g&
zq2Y3PT)1!{94U9^xG!8xj6)xXFPclGw!?4uK6oB}yu5D$NbE`yI1Hp{cTP^<iM=xa
zQIC=|1{W~BPdM%loi11{Fs(6$`4z*wk8Yetvlr0pg?WKCIz%J5M5_g12;&Ki#xNX#
z7=RyuZtP%MP&WmemNPHd9G#)v0Yw2-1<#X$Xb2*bl2FL_0lY5#m=}~ACF)xe2!#ZO
zBN)WsKtK>eKY;ujW&%y5(3%q}8&Iu+Z9^2vgn!@=`cv5NLoOc^Y;-QuG-PEVz;+}o
zcENrCULQOkUgTneivF3xTc}jz)O*_!j#u{k5_Y%2vSBq76X>=lfe@Sy)M^rlSN41<
zFBak9y3SHYoe91;AFxb0c`@LxEMB>3K(+u^@@dlfv)n11o(YQ9DYCV@ysWAe)bA*@
zA?~zt*M)Z<VJR~qy|&2pYI3hlOaez}1ji{^%UIvQ?LoN=x7VL>wRm*@RfYubyBDcy
zzi@ld(BZ+WEz+fP2fGEuIfi0A$28@nAFW2*$}b-Lm=yg4isoRq;qlX-+{iBf5B^t>
nvr??6H@Wu&uC1-?2Lp-UJe5p>RuR>I00000NkvXXu0mjfVs`!d
diff --git a/public/images/icons/role_delete.png b/public/images/icons/role_delete.png
deleted file mode 100755
index acbb5630e51a12a1cd30ea799d659b309e7041cd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 767
zcmV<b0s#GqP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!kx4{BR5;6}
zlWR!RQ5c7nxulD&ZH)?y<x0xJzNnunv9-S}=R`8lGA~oHsjN^e?@3}x3qvf^@-~LH
zt(jKh-LlBa#95XIeW+2c2&0AMrl_4?XZs)qqCy8A&f$gM^S+0}aRK1+KP+2J4cJ;x
zCgn|+%eFu*<)A>!wMF|0iq|AK>&MHw6~-ksQ9RtH+=$?!G=zinz|BN<kbikqL6wYy
z1{ze;P^ruT7gs_BxNww*Gk%<@RRyJio6uF24@;*SgSF{67bHN2WCzk15t0va=d{^!
z_Z0;-vBIA--#=jLMHRmGUdO1R5a#x)u$oQKDR)o3)1<CjQBV=Rf519)7n8$A*x%|X
zdgs|{(&0{m@9>IO*d}XYdmm2K>Qw%i9j?X9SgRBJn<lhm`olL+d0)WPtY20j2+_Io
zrHv_`(msrRnT8=R4Ej8|6UX`a_-}XyKLJl%cb+e<-tdorf85~e5p0MTh7MrdVn?F|
z$QT1sUIU3wfw&GpQ(lQ@F+S)Ov+;o0XzgIwxr>4W5%uAclWG_T7f?M4s9q5$`w5b|
z31S}-Tq~-?NahjDw3mU5cfqF5z)+g+pPplGDyLv1f8WAnTQ+Xiw;{fhcBLH^j|gI#
z2~IT;7{m9#PQ$2>16f?4#0x*vLFksSJ~;)W1wO>uQ-rAG1{C+&5Zw%%))Pc(2_k9<
z`smoi)Pkk!SK)SAcOy>0d#x(Rl;b_GP?XFE#P>r%M^9Kn>j@#I>k<JPn!V@(E9JA2
zg>HsrS$qYvKE>lwZZUsXcw4nFNHZZ~?%71a&2u7&aV|47ZvJKBUVO{)!ekB`ACp}1
xSnjsa#jtYM{A~v!cV^R$X2;lcpKyd7^}lwPp>~q=QF{OY002ovPDHLkV1lJ{Vb%Zu
diff --git a/public/images/icons/roles.png b/public/images/icons/roles.png
deleted file mode 100755
index 0eaa571757dcb6c6fde9f194cabf3bf2d1863903..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 770
zcmV+d1O5DoP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!lu1NER5;6h
zlkIEObr{A!-{0?SXJ=04#D>G16ocaoM?$_R#KKptL1a;2QYaEZL?ZqH!+`{1Z+cmQ
zQ1}3XixLgQQmBz(W@=0D%tV*%@ux?(vz_nL)r+<|qt*=<H{ADqUEJIcMiTS(?%ADs
zp|hJy*#JS25W^fIK6*B;*u<gFKjo`E=gd4OM~!*siTbNJ#DI@+&i?~zeJzD#fq?Z$
z;6lI#Plx@3m!~gagTsfpT-7Zu;H)Q4Bl)BO7d%f_hv-TZ9+{mWpB5;n31|Obpl|Tj
zudL2@&??dHCP<cVVdK;=k2Msz^z&t$^?i#99C^LJ_x#{DePhEJo2ig%dyQn-Gjz?|
zVf4m0r!So9`|-e)-dc{4g!^tyK}w5?N~7SwQ0v<}R#)CyS=<dtJ@)o7j{bD{%U9a#
z_DKmbir^~aZLf~qHj=RC+lJNHxk>^_D2k+IGc>M2?jCYw+~gHPWej16&S4+k!e$e1
z8c9@6m=~ktaJufDrrfG+$c_;0J)+AXR6rg~4wG9-^p5hyBV-q^eL<e>X8w@MpP7yr
zI9b1TYcYNFC1gjDpGL8Q!VH)cpWS8T^zmRH(%bc+_AeM>^BXFW=c(D>`upR9L6DHD
zC{{rhL(1sa$1_)@d!GESEwpUYlqoDZ<H{vu07VQ26i|$iGPVAo&Mdk{0MXD>*YYIB
z<dFB+>@KEmIZ1sp^{p%0ukJJJYwH*M!esx7LKIulW$P&a@Bxzp10@XKE-7~GSi1H(
z@@-F$4UO~wSO2qv5d5>I>G8t&$-Ru98~DgOHgvwPo%gSox^JHN<aaw`nVqI*Vaw9r
z82*@DrTyHzwuk3y<C6IPJ(|yM=g_IG{8AhL6JNfO&mH|mQUCw|07*qoM6N<$g1S(B
AoB#j-
diff --git a/public/images/icons/rss.png b/public/images/icons/rss.png
new file mode 100644
index 0000000000000000000000000000000000000000..1dc6ff30ba5020600aa4ba2646beb9eb25dc978f
GIT binary patch
literal 530
zcmV+t0`2{YP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzq)9|UR5;7U
zlh2FIQ5eQQ=iKi%S0M{YQdTBO%#<YmfLKjqL6az1varH}n&s@21*I%(Y(`xhnuR7i
z%0#hKQ-dt5Xz054{bg~^oiehz3vZpykIwnj^E~fK5y3c>8MDR)G%QU0LxY1jsDL`i
z5Y)<<0mFa+Gyv?I-SF1`9OhtF)?#(7@ZwPg0IYohcf#rgRl*cR36-)JAyh$ycISTR
z#|RJ*0Y`3-+O5RfdxRPJ@Fmbb_UtP8<ZV*hMVID@Pj5h^0#u8(aA>y?FXu?dZjo$&
zzrG9R<fE5Cej-n<&^dG#U0q%WWJC(U19Agf_JS+%{WJOab@J3j{KFz?#{|vk`}oIK
z;6);XAk+U<^tl6&4qhNu7Gb!CJ)R{9@_`xT!72QGkLJW&F;lGq23lzD;DRsTAx%uf
zkFRuQ9+JA-v3Co!=X-P}&!A6lR)B&)iuv8a<T-+G#dTFeiqj$0{ZR_4U`Cj+Y4aZF
zJ*S}`AVRV(X%wMZ$v&#N*`Z^Q0va!g)k<+~S0J(8Sy;eu!>p9<^S_%m{rBJa8vxT8
UVM82oKL7v#07*qoM6N<$f={^a^#A|>
literal 0
HcmV?d00001
diff --git a/public/images/icons/sprint_add.png b/public/images/icons/sprint_add.png
deleted file mode 100755
index d4195ff80251f62483a2759d15559b4393fdf7bd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 820
zcmV-41Izr0P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!#z{m$R5;6}
zlU+#DQ5eQ|-$iyAb=5_6Qy?T=*o8<SQIepL)<sJ!MG*;#%n#JIwdtmt-ybc?g{ApD
zb+)OPn3maxt!aMsg(;b+shO$Uex1KlF)F&~z{B~U|9PM1dCz;^BLigrgUt_DbMroD
zV`KDcU0u?0RaMwhdAZld-dthfj@j(&m}#wc?2A&_@i{s9_%8x3izU|C&@kg{vEpoN
zWu?BB#nMv8g3;(bS5UBb)?l!IGu>vjyOSSQ3)AUp#^U1ce29wLCXoZ3<~rO%128fK
z0}dD+W~IH2x%~W(GkSghlGw*#her=Vh)6Lr`b^%+<x1JA*=%(`e+n<3K~p1`%}`S#
z*1foTyK#03Qg093x&=3HLQxTvnQ%UR%y4MvxNNz)`jdNP5UkBmC!A^pxv~=O-t`DR
zXab{ApacpE1o9x;fa^&YZ-RmrWTIGK+=Km4FUS=YP<{_gCXZvuIw?<(a&iPw4;dMt
zQRC`tr~lZoIoYDgH0pA^f@<MfdfSuc1~E4m3<l8YAUz#aD!7&g*A=+BI<WiuFUS^d
z+$dhIz7IWJp7gf5X|=*p14<>Nrb2QOT)rfZSjMDEL7%U0vFvMJ-kzDPtoKWjh)|`Z
z(BmXQaZM0Y)`(VBB$snfb0O;_=Tt}0h8_C;!pCRVS|3cQ)dwe2Q+wyLGjT~*RU-<R
za1|00ApQysDQ8KmJV&D=pS}qj`j%);=?`!?W~Xkm6DQ*1w~t-CsQ4HiJwI<OhGub{
z$wDM9mT*k~^{)-o4~V0Qp=&*lzBN)3So*EE--U-C8aZ?3@l=u^x7(oA!ihw0EDj@E
zhuNMl3H<qi426Vv4Fm?}IsyXR;}LR>#O!uzZQ-bG@-?#BD*t;1TVeO}3l^1*6M@QL
y-F`A{5o^xUEUka3!M`AaH3IWe+Uv7M`u`JQP3y$y8AIa$0000<MNUMnLSTaOZhBz=
diff --git a/public/images/icons/sprint_cancel.png
b/public/images/icons/sprint_cancel.png
deleted file mode 100644
index 0cfd585963d255190b8855a7689e8da1c4d7cf6b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 700
zcmV;t0z>_YP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!PDw;TR5;6}
zl08pUK@^6c-MfIG7zy&ZdO=W0RM5go6AL;JW9dJzHAaJtjTV}aNP&t#jK9E25`KYJ
z7-190qI|g^MC3yjcJIA2b7#h4m*qn(j3+rcCzCnP`_AM<thM}4#10;;z8Sh6DK2^%
ziAG(kwZIsx(Ir;M1)a$}vRV(<KX@qr2v`|>*?Fk0YVb%?UEFajs1S?+YtYiPrjx0+
z+4<Bxpm%2`vh#$MS1&q>YbyJXwz!SX#yqTlhtNQ%Ku9=RNm$j)&+(}lZ!UGGp|@|O
z09YA#-dR#rIaGe;MBLe!ht*}!c?U}6YT!dfHDO%~>xtx&Klk-^WB==sC_vP4ddg4L
z#GN10u$+QGf$!(i3&8VpF6O6+ef~&gQ#>AVqCJH_utvKMAuOeG%3%mn<<%9)yb~#4
zHc70e5sYyQ03$?zFUko7D1Bg1=6jXvg#bUm1b(pVKuC*}koEKGdj<=zd<p?lVuY}}
z02!2`6>M#RWsl+kfRf;OU^G_BQh+Fc$z&F_AHuQYu(b)<Z0@4xK{j7~54O@!dlDrz
zdV71Z08s1e-K%5C<<PwV6}7OL&Ox&ILC?pe)0lb}|Ke4?jgBveYir&67HRs{%^PJ6
zZeR7KbB#q~?_p*Ntij5VPzbEsjJkY{l@Ft{naPQ}ZHX_#`v3q_9qnD^r<(?<&!3GK
z8HH8~V@z(R46J^dAd^VkZ=0Nb_S-7&M6&%#ms585NhIdDHVlQ)nus+e+V>aq=H_Fx
idDl8IBmWBc*Z2i=4uSP&;Q8VJ0000<MNUMnLSTZ|>p<iH
diff --git a/public/images/icons/sprint_complete.png
b/public/images/icons/sprint_complete.png
deleted file mode 100644
index 0156c266e4e1fbcd1263fab2c2dd1f3712553d14..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 623
zcmV-#0+9WQP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!0ZBwbR5;6}
zlif?xQ5eU)^D^-Kemg@D!Y+!S3;%@vf@v>Wtv3@TMo36t?!us(ut2(qE`#u;Y2=pT
zq@2~2T~yXyeA(Qqy5;+9o4@n>4e8r+MnSPzjxHXahjaKm&-eRqP6dF9|A~@^;+?rt
z=H0jE_T4vTwd@82LFU{PN7lpd$oktP$3Gho==lu{2>(S8IKK0m@1<YyO?kI9VLH0$
zHr14Dke%Y+Gaio2BoF0Nk03)2cS29x1A#6Au`zB!kph~=3A`n1nuh$>#{_mk%-f(Z
z+<+0WLyL4{ZOnvyEl7}LBImWjh~I^nZG{LlL-;RKT!Im`W9MTdQZ5xqr;6nfwX(<p
z$xIhy(^L_-S^zcQd1&6Vq~;oO!43iyXORN(=9b<vGZ&Cg_Cn0HK`v19og?@Rv@aG?
zWF;H7vGLx5_;UrZVWp}_!Rn~`Fzde#J=jj5gijY>&09}<xQX>?3!+0xOT@w2!VY%$
zj|Qoisx?Xewm&q%SbjiFY^0(I!gmV#q77T0t|0EJMfe#*$tA9gs83{GdZFA;x{o96
zB^%K$7%@AxKer&}ti|FWs}2pYzTg0Ry6;OQZ&K!w#ON`Q%*5Js144tWhd>1Tnd7f7
zk-!t=?~tr%T0tsJ(--<#x2)&;s)i5r7k+}jpgM|^Wqqb{;s;8N-ZpQB0Ez$r002ov
JPDHLkV1fyHAhiGh
diff --git a/public/images/icons/sprint_plan.png b/public/images/icons/sprint_plan.png
deleted file mode 100755
index d88e2b9ab7ab168e884a7e1eb12891f426cdbfb6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 631
zcmV--0*L*IP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!2}wjjR5;6x
zlTS#~VHn3h@9+0p4ojI9p`$<@LItU96)GNTAykJ!r=Xjsu-2sryjLVax9HHN({3Gt
zz*s>dIT>^aD;pwFhvkBWZF9u_yzl#T7>be(A9#6qA9z0R_kI2#BJAblMn+_(xWgXp
z)x^Y(aU~*~mrN!j#u&8LY<R6T`Fx&KDn&3DBoqn}i^bGNj<=Oouh;48>jPjbSVV|M
zqlgH}WOAE=Z2+w`0JF=DpBVvT!HUHgxOhTStyXsj)M_<EgmBlN9SaG8y#dnM4y;(T
zZ79$NtQD>dX)2XUa{$1Z?%%t#v!l6!YPE`pF!!SqBZ9VIO`{fKg{!CQ%@q_)0TE&B
zX#T&~KYW{G`o%n@)&kcaoG%s1Yma6gF5ce++)YpR><jq0B$u()l1L<Q90#Qo>n%B2
zd;W56>?}t*`<Y#O*_QtD{@!pr7}%UdYi+ONbIBAxBO-X7M>rfN5{Z!0D-0bQ#5jh*
z?s1H&GkkIs;HCp`J9WJsquw3#9pY{FHP%`@&%^UP9LHg;oX4jQ5IcSgfIAnS5js2o
z;P(KGHj_qMSt&28{k3+I*%_?Q;<_$MDGH@EmR1*7T%BiX{5jKaCh)s002L)7#N%;k
zwn#tuirbrGbYP7Bu2Zc1`pCkkd9vS&kGCyTGaHTvr-2(l8?X*MO+Q(k`Ug*NS(ok0
R0GI#(002ovPDHLkV1m!b5pn<k
diff --git a/public/images/icons/sprint_start.png b/public/images/icons/sprint_start.png
deleted file mode 100644
index b88c8578956ceec4ff17f81995b8652f6aa2b58d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 670
zcmV;P0%84$P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!FiAu~R5;6(
zlFdt$Q543Xd*AoIGtP{SV`!p;RDLwHXb}ZrB5nE)LV~1K+h`F41>rx?szq&Dw38OK
zY!^{rCAFy_2z8TV&4=Ube7+y|oYO*02OOyb5BD7I^ZdAQt`ZS+tMaFrb6^=AxbXHx
zH;=|4CCm%L{PZwSS3v3G^sH+#W3JcR_xs(&`Tqt8^J9}d0<R|rCcamAect<LKyh(u
z-Xya*?IZvI#_Kg=`Po5URsKAa5tggMd<86Lg=N(AWK)TBKRBv@gF2Kug0^2o*!0^%
zQV`;=!u&>vU#im5^f#04JL4qMaI^<NL$QE@B5bn&i7f;fXfpzdEhq|M!vJyELfEQR
zl!&1Cerm<b^q)*-kAa)3;BX6UEhM(!9Z5_OQgBj}2pXGc*Q>seoYDXwB>7;oyw=|M
z1!ayym?6XvqV3ae_f95{py8ukt2TxB^!VIzRRh4#rNu~y^X+P>L{SXo3_|Qqm>9wY
zz(9!5s#OBElpmj4DRyjO`0`RiEIkUg%7D)8y}}Ye3}prow;JG>UQOIs{kfZSJ9bYz
zskMPbH9)1H6FDf)1=ZKVfe+;jf`a(O{!9meiN~~d0iA$0qX=t0D6Ydx4#RO76h@#R
z9_k7Z;$fv6G>QeZ{Yu0n&xL4%!?l}UPj4!j&Vs@?dl=y8#_IQ`5I-5a_T$dJtJ_~5
z4&186>klZh{hfba<gb<&Ca&+F57N^8<m`vL#@n6$02)Sf{tFKxDF6Tf07*qoM6N<$
Eg88vBhX4Qo
diff --git a/public/images/icons/story_add.png b/public/images/icons/story_add.png
deleted file mode 100755
index 2e945076cf7686b3b408d6eb2cf913992100da15..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 619
zcmV-x0+juUP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz{YgYYR5;6}
zlRaouQ4oc{x$i|6ViYViE@^@WwJ=dwVMziCl2XAYjg?@diG^4guvJ*W9|*?6#==Sw
zF(3#bphXM;5ses9ScHJPip9o7vyr@=8H@K;W0%DX1E;ur_nbR3;_m#<k<*tRjSL<y
z+^E*Q-5oH)%}`U^9CO1}F?U=QHDmjhWOZ?|eC6rw;fc5~P#AB^wTIogmL6_jt?M{2
z5!VwB_3F=-t*<2>0Ag3?`k8$#1J0F}NdayEtTz+~+#EG995YAF(1xew#=1J)ogJuY
z3Lxu(1VP;KAh<YULI{FLKtz$qi7XH|()-rP08LT=Tm%Fn2NN)JB8MOmv4D!BA$4qO
zSp>`GKm^?X0f~UCV*)Nf5F(3GKr=#9qzp;L29U)<Y{vB4NnXuAr?$F6(nwg-{lH1$
zMw0w-Ab`6gBKQW-i#JbrU!LOFz)`w(_V9Ay8FL?}DURlE2G6oYfMhNt(?NtF!sP3R
z96r#82BmM$5Go19L;V0F!OZ?f$UZZO5N)V$-@ni%+c<UbA^?|9+-L8uUVvO&URr*9
z{!TJ%s+bz8ikYEFf|+6NRBJ0NRA!m4%rG|efYQ`ia?w_RU$U8PERN={b#?E!+TS}!
zPv;RneSOF5hZ#OE)o#gV*SR>FF98>T4&VoHZ|-ho>^FRq4ws;uOVa=V002ovPDHLk
FV1kR43LgLf
diff --git a/public/images/icons/story_view.png b/public/images/icons/story_view.png
deleted file mode 100644
index 3bc0bd32fceb21d70368f7842a00a53d6369ba48..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 465
zcmV;?0WSWDP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzV@X6oR5;6}
zlif?gU=+sv7bPi)=!3$7q?JQqQvwMoh(bhK+J{k6%rsgQVNn!z(HBXQkd^mAH(hwA
z^Yotc=4S08nh!j@F!ub;!`WU30603a!#SmnFKE?TaOVx=ZRYd~NSn_P*eHX4{Rzai
z68Mrum`pr?uyhCB_zlR(s~YAA5Xn~cSpFUUYax26696aMv1k4Q2q33l!H$M!&p1HZ
zs?dXQ!8A(HJcd!rMboIk$jLW=EvyAdm3{&e#VDQ4W|M-siV5fsA9Db1`>zJNu3H-P
zO&@UpeyZQXi7jKe-Hk?r-sue;aDce_XqkvXP+W#F_*ot`jB?BS93Uw71|U^ZjLH<w
zh;-sq3Vy5@0GB_@0Tc0CO9QIe)}UUmTN-qU84mEqu5JAXPM->`yP%FO7U<6!nLCG}
z$SDlW<k^-FX;JQ=20hXqbO&;*_AZ;O0?VLP0(5*EI|Y0J3Jfj)lKW#`00000NkvXX
Hu0mjf{J_IH
diff --git a/public/images/icons/unhealthy.png b/public/images/icons/unhealthy.png
deleted file mode 100755
index fd5d030ef773ddbd3f18925487a870ae7679b08b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 723
zcmV;^0xbQBP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!Wl2OqR5;6}
zlTApJVGzfE&%3(ouAAvrkQRy|fr?lZdJ3a&k`8w0;>nI31uuPEx(b2EPDKzMg2IC!
z1S@@jQACFdqKw6YEZj=hS9jm{d7haL#U>dYYEHv2^W)FV{Ee#eKT-30!OfVgDx)f#
z5TQ>MRCpr7v<g=?ozif9zge%q&6oidu9?=ccGK90CUc-3Ef?|Mo)f(tFNiSGG^F=8
z09@V-Y2(11VEZtd*^FO%jYMBiR{>K;P}hO60nz*0M4#`U-gZXsRsl9|a;nTHdTwPU
zDB&vwuq%j*P+$205yhlhNu+vMo;@3i(AGSxUjqOYMuWBsSxtgO1#qk6CyO94_?QRx
zKx~LBy}(EB$aG%Fif0rc01#o&H1#8u0_w`BSPq^{qhe8SIWQ2S5}`K4Ej^>AaW~=_
zTo33X)quFA>X3>>U5xtpXKqm+BT*5E@SgVS8C58&t0eIbd`!4p;>FWBO5Z{dM}5Z7
z-Q7SY<xv7qMTEpJ1)c)73?vDcSD4MeqGd;x!^d}V=vW)gEomM<S|D60V}cCgYp@Y>
zRRtnU+2Zp(L1QcF+PCx%bW&eiMtlYJ5j$Iw<eGa)`;XK#^inR)V`HY)E0|b&bveXs
zB9ZMRn+BB#d|cf}+J7Wb-+`ujS$KFkv=I|kK+|bm6k%j-?gr=%5)J*BL=F`NQG(=F
zYPTIhGl%%{auOReviH0$Zg}N|o93u^uGV*rwI{c96VwJE4i|Y=7vAt`cD&#$=k{IH
z=|6e_;KOy370;LmC%mW6#o#PYoMqZs#`j<Pi<$l<z5@{@b~pE3oM`|6002ovPDHLk
FV1ngnJVyWk
diff --git a/public/images/icons/user.png b/public/images/icons/user.png
deleted file mode 100755
index 79f35ccbdad44489dbf07d1bf688c411aa3b612c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 741
zcmV<B0vi2^P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!cS%G+R5;6}
zlWj=TQ51&_D(S`6wpIkfYAK|mU(`?4(513DT?37*m2E2Kj9H4|>z1iyEv%?$mbQ(#
zwJpuiQJP8?X_`#S8b+U_G6=zi<fcr$zy3;$1erx29ynai?>YB!xPAcq{)ZJ0bECH@
zYx#`n8^Wzn^J!4>=q^bltNO15ry?0ecSLkjpT@vlid!jk)Fjf7&)q_V5zGs#3N%6*
zbW~7Hg=&P0&~Y(|g>$hC9FL?;ttzPDZbpZu9OLb33^e2;FNTGJxScp1&q4M+y2ntQ
z?C(=hpU$3~`Thx0eHwi0x`q+!d5k@|0_WHe%sG3e-s^MM`xM-ig!VcIA7H}X1ot~L
zg=MLB4w-Q;Bi!!u2|I+Qb;0{{4Q53YX6+4_aXena{nmt*!YG7ua~`qc>o=?@U?rOU
znS7%>klzi*muXnbM6i@4FR@s^8vTjDgy&%J?w?`u>NYMDFa_2%0SQ(qJE<3=<8Bzo
zfdU60e*<K`08TyyDqaGwKf1vd^kEZME2qV3)_MhDDOzz{sv1oL^QapE6#WD_Jp@_L
z2+~^#j#>y(^$RF%r$kl)p7=7tlCDa<g5mPL^AomW+}7G4rJ6FSiLy3=6U|iEM3ACg
zfJj4duokGi-i^r)75WQ9JYK<wGK4rgE0LD1Lv@!6l4jr-HT8&r3O5iOZUn?Sptxlg
ziRniC=&r(GQ7G{WJ{S}wLnXm;GTEiMXlV~*)YUWoK=zv;K`RtlrLJLB#4MGmTDFBT
zi#$M8TFu-gw$-s?^j|sg4_%yuW)CN>$+J7w>}DU(O#~fk>pYuRvHi1E9^msg{tLeV
XM&GIRvfA7%00000NkvXXu0mjf&%8>|
diff --git a/public/images/icons/view.png b/public/images/icons/view.png
deleted file mode 100755
index 1dee9e366094e87db68c606d0522d72d4b939818..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 464
zcmV;>0WbcEP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzVo5|nR2Uhh
z!69yxQ5c2c_uP9SO&YLZNmxQ12)2N!!D0vs#R^Ek(4<KhK?U2XBo(z)bV&OD-#N^k
zFa|g2^C$@qp|_uYe0=@p<lF5g#|dB)n{p8c$D|4;q>8e6`gpm!y1M!N^ZV(=IC*t)
z{^;nqJv-tM$9J1L2QJ2DN!#51=1_l@G`2=6e0lehL%sic%`_4--LFM}IF!KzJCseW
zq1I3__Z40|e?qyK1__gzP(qrBf-G7SQbQ`#Lw94WVe(o`qg+f4hy;Qju)q#I(9{`%
zQmAGomzhQ!b|gq>KqL@IkO~$=Koi}a$u6d07kiS}NoYVMJjAeZpaB*;wwcDdEbK@K
zNP;B7RzhQ|H9AlUO<`J>m1(5R)Pb-iLBb@7Jp)}LHdAb-VVgYxVoTzGoqu{~a>6uj
zeqCRFI9pC#h09bGwy9;oHcp6(RB%jeY^F=Ll!S+9JkVe4nDG7tJMQiP0000<MNUMn
GLSTZz`@eVq
diff --git a/test/fixtures/feeds.yml b/test/fixtures/feeds.yml
new file mode 100644
index 0000000..9c12786
--- /dev/null
+++ b/test/fixtures/feeds.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at
http://ar.rubyonrails.org/classes/Fixtures.html
+
+feed_one:
+ title: This is the first item in our list!
+ link:
http://localhost/
+ author_id: <%= Fixtures.identify(:mcpierce) %>
+ content: We got a lot of stuff going on right now!
diff --git a/test/fixtures/product_feeds.yml b/test/fixtures/product_feeds.yml
new file mode 100644
index 0000000..f5d6042
--- /dev/null
+++ b/test/fixtures/product_feeds.yml
@@ -0,0 +1,3 @@
+projxp_web_feed_one:
+ product_id: <%= Fixtures.identify(:projxp_web) %>
+ feed_id: <%= Fixtures.identify(:feed_one) %>
diff --git a/test/functional/products_controller_test.rb
b/test/functional/products_controller_test.rb
index 07f9d4b..74b489d 100644
--- a/test/functional/products_controller_test.rb
+++ b/test/functional/products_controller_test.rb
@@ -245,8 +245,9 @@ class ProductsControllerTest < ActionController::TestCase
{:user_id => @project_owner.id}
assert_redirected_to product_path(assigns['product'])
- assert Product.find_by_name(@new_product[:name]),
- "Failed to create the actual product."
+ 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."
end
# Ensures that anonymous users can't update a product.
@@ -277,7 +278,8 @@ class ProductsControllerTest < ActionController::TestCase
end
# Ensures that updating a product works for the project owner.
- def test_update_as_project_owner
+ def test_update
+ count = @existing_product.rss_entries.size
put :update,
{:id => @existing_product.id,
:product => @product_update},
@@ -287,6 +289,7 @@ class ProductsControllerTest < ActionController::TestCase
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."
end
# Ensures that anonymous users can't delete.
@@ -302,4 +305,19 @@ class ProductsControllerTest < ActionController::TestCase
assert_redirected_to error_path
end
+
+ # Ensures that the RSS feed requires a valid product.
+ def test_rss_with_invalid_product
+ get :rss
+
+ assert_redirected_to error_path
+ end
+
+ # Ensures that the RSS feed does not require authentication.
+ def test_rss
+ get :rss, {:id => @existing_product.id}
+
+ assert_response :success
+ assert assigns['entries'], "Failed to load any feed content."
+ end
end
diff --git a/test/functional/sprints_controller_test.rb
b/test/functional/sprints_controller_test.rb
index 3247a5f..d184fbc 100644
--- a/test/functional/sprints_controller_test.rb
+++ b/test/functional/sprints_controller_test.rb
@@ -212,6 +212,7 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that creating a sprint works as expected.
def test_create
+ rss_count = @product_with_no_sprints.rss_entries.size
post :create,{:product => @product_with_no_sprints.id, :sprint => @new_sprint,
:selected => [@member.id]},
{:user_id => @product_with_no_sprints.owner_id}
@@ -220,6 +221,7 @@ class SprintsControllerTest < ActionController::TestCase
assert result, "Failed to save the sprint."
assert_equal 1, result.members.size, "Did not populate the sprint team
correctly."
assert_equal @member.id, result.members.first.id, "Did not put the right person
in the team."
+ assert_equal rss_count + 1, result.product.rss_entries.size, "Failed to add RSS
entry for sprint creation."
end
# Ensures that anonymous users cannot update a sprint.
@@ -257,10 +259,9 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that updating a sprint works as expected.
def test_update
+ count = @active_sprint.product.rss_entries.size
sprint = {:title => "Do it!"}
- put :update,
- {:product => @product.id, :id => @active_sprint.id,
- :sprint => sprint, :selected => [@other_member.id]},
+ put :update, {:id => @active_sprint.id,:sprint => sprint, :selected =>
[@other_member.id]},
{:user_id => @product.owner_id}
assert_redirected_to sprints_path(:product => @product)
@@ -269,11 +270,13 @@ class SprintsControllerTest < ActionController::TestCase
"Sprint should have been updated."
assert_equal 1, result.members.size, "Failed to populate the sprint."
assert_equal @other_member.id, result.members.first.id, "Failed to populate the
sprint correctly."
+ assert_equal count + 1, result.product.rss_entries.size, "Failed to add an rss
entry."
end
# Ensures that updating with a specified return URL sends the browser back
# to that URL.
def test_update_with_url
+ count = @active_sprint.product.rss_entries.size
sprint = {:title => "Do it!"}
put :update, {:id => @active_sprint.id, :sprint => sprint, :url =>
sprint_path(@active_sprint)},
{:user_id => @product.owner_id}
@@ -282,6 +285,7 @@ class SprintsControllerTest < ActionController::TestCase
result = Sprint.find_by_id((a)active_sprint.id)
assert_equal sprint[:title], result.title,
"Sprint should have been updated."
+ assert_equal count + 1, result.product.rss_entries.size, "Failed to insert an
RSS entry."
end
# Ensures anonymous users can't delete sprins.
@@ -309,15 +313,16 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that deletion works as expected.
def test_delete
- delete :destroy,
- {:product => @product.id, :id => @active_sprint.id},
- {:user_id => @product.owner_id}
+ count = @active_sprint.product.rss_entries.size
+ delete :destroy, {:id => @active_sprint.id}, {:user_id => @product.owner_id}
assert_redirected_to sprints_path(:product => @product.id)
assert !Sprint.find_by_id((a)active_sprint.id),
"Sprint should have been deleted."
assert BacklogItem.find_all_by_sprint_id((a)active_sprint.id).empty?,
"All backlog items should have been deleted for this sprint."
+ product = Product.find_by_id((a)active_sprint.product_id)
+ assert_equal count + 1, product.rss_entries.size, "Failed to add an RSS
entry."
end
# Ensures that an anonymous user cannot move sprints to the planning state.
@@ -350,11 +355,13 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that a sprint can be moved to the planned state.
def test_planning
+ count = @plannable_sprint.product.rss_entries.size
put :planning, {:id => @plannable_sprint.id}, {:user_id =>
@plannable_sprint.team_lead_id}
assert_redirected_to sprint_path(@plannable_sprint)
result = Sprint.find_by_id((a)plannable_sprint.id)
assert result.planning?, "Sprint should have been put into the planning
state."
+ assert_equal count + 1, result.product.rss_entries.size, "Failed to add an RSS
entry."
end
# Ensures that anonymous users can't start a sprint.
@@ -387,11 +394,13 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that starting a sprint work.s
def test_start
+ count = @startable_sprint.product.rss_entries.size
put :start, {:id => @startable_sprint.id}, {:user_id =>
@startable_sprint.team_lead_id}
assert_redirected_to sprint_path(@startable_sprint)
result = Sprint.find_by_id((a)startable_sprint.id)
assert result.active?, "Sprint should have been started."
+ assert_equal count + 1, result.product.rss_entries.size, "Failed to add an RSS
entry."
end
# Ensures that an anonymous user cannot complete a sprint.
@@ -424,11 +433,13 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that a sprint can be completed.
def test_complete
+ count = @active_sprint.product.rss_entries.size
put :complete, {:id => @active_sprint.id}, {:user_id =>
@active_sprint.team_lead_id}
assert_redirected_to sprint_path(@active_sprint)
result = Sprint.find_by_id((a)active_sprint.id)
assert result.completed?, "Sprint was not moved to the completed state."
+ assert_equal count + 1, result.product.rss_entries.size, "Failed to add an RSS
entry."
end
# Ensures that anonymous users can't cancel a sprint.
@@ -461,11 +472,13 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that cancelling a sprint works.
def test_cancel
+ count = @active_sprint.product.rss_entries.size
put :cancel, {:id => @active_sprint.id}, {:user_id =>
@active_sprint.team_lead_id}
assert_redirected_to sprint_path(@active_sprint)
result = Sprint.find_by_id((a)active_sprint.id)
assert result.cancelled?, "Sprint should have been marked cancelled."
+ assert_equal count + 1, result.product.rss_entries.size, "Failed to add an RSS
entry."
end
# Ensures that a valid sprint is required.
@@ -539,12 +552,15 @@ class SprintsControllerTest < ActionController::TestCase
# Ensures that populating works.
def test_populate
+ count = @planned_sprint.product.rss_entries.size
post :populate, {:id => @planned_sprint.id,:estimates => @estimates, :selected
=> @selected},
{:user_id => @planned_sprint.product.owner_id}
assert_redirected_to sprint_path(@planned_sprint)
assert
BacklogItem.find_by_sprint_id_and_user_story_id(@planned_sprint.id,(a)user_story.id),
"Backlog item should have been created"
+ product = Product.find_by_id((a)planned_sprint.product_id)
+ assert_equal count + 1, product.rss_entries.size, "Failed to add an RSS
entry."
end
# Ensures that a valid product is required.
diff --git a/test/unit/feed_test.rb b/test/unit/feed_test.rb
new file mode 100644
index 0000000..88cff35
--- /dev/null
+++ b/test/unit/feed_test.rb
@@ -0,0 +1,68 @@
+# feeds_test.rb
+# Copyright (C) 2009, Darryl L. Pierce <mcpierce(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
+#
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class FeedTest < ActiveSupport::TestCase
+ def setup
+ @new_feed = Feed.new(:title => "Test title",
+ :link => "http://localhost/",
+ :author => users(:mcpierce),
+ :content => "Yo yo yo")
+ end
+
+ # Ensures a feed requires a title.
+ def test_valid_fails_without_title
+ @new_feed.title = nil
+ flunk "A feed must have a title." if @new_feed.valid?
+ end
+
+ # Ensures that the title must have text.
+ def test_valid_fails_for_empty_title
+ @new_feed.title = ""
+ flunk "A feed title must have text." if @new_feed.valid?
+ end
+
+ # Ensures that the feed must have a link.
+ def test_valid_fails_without_link
+ @new_feed.link = nil
+ flunk "A feed needs a link." if @new_feed.valid?
+ end
+
+ # Ensures that the feed must have an author.
+ def test_valid_fails_without_author
+ @new_feed.author = nil
+ flunk "A feed requires an author." if @new_feed.valid?
+ end
+
+ # Ensures that a feed has content.
+ def test_valid_fails_without_content
+ @new_feed.content = nil
+ flunk "A feed must have content." if @new_feed.valid?
+ end
+
+ # Ensures that content cannot be empty.
+ def test_valid_fails_with_empty_content
+ @new_feed.content = ""
+ flunk "A feed must have content." if @new_feed.valid?
+ end
+
+ # Ensures that a well-formed feed is allowed.
+ def test_valid
+ flunk "There is a general validation error." unless @new_feed.valid?
+ end
+end
--
1.6.0.6