All list pages have been reworked to eliminate columns and move data
into related columns.
Details pages have had the previous table removed in lieu of a more
flexible system using definition list.
All edit pages have been reworked to be cleaner and more consistent.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/epics_controller.rb | 8 +-
app/controllers/projects_controller.rb | 31 ++---
app/controllers/stories_controller.rb | 2 +-
app/controllers/users_controller.rb | 2 +-
app/models/epic.rb | 5 +
app/models/product.rb | 1 +
app/models/project.rb | 6 +-
app/views/epics/_edit.html.erb | 76 +++++++------
app/views/epics/index.html.erb | 83 +++++++-------
app/views/home/error.html.erb | 5 +
app/views/items/_list.html.erb | 129 ++++++----------------
app/views/items/index.html.erb | 17 +++-
app/views/items/show.html.erb | 132 +++++++++--------------
app/views/layouts/default.html.erb | 77 +++++++-------
app/views/products/_edit.html.erb | 31 +++---
app/views/products/_list.html.erb | 73 ------------
app/views/products/_shortlist.html.erb | 15 +++
app/views/products/index.html.erb | 64 +++++++++++-
app/views/products/show.html.erb | 43 +++++++-
app/views/projects/_details.html.erb | 30 -----
app/views/projects/_edit.html.erb | 111 +++++++++----------
app/views/projects/index.html.erb | 124 +++++++--------------
app/views/projects/show.html.erb | 83 ++++++++-------
app/views/sprints/_edit.html.erb | 131 ++++++++++------------
app/views/sprints/_list.html.erb | 63 -----------
app/views/sprints/index.html.erb | 51 ++++++++-
app/views/sprints/plan.html.erb | 79 ++++++-------
app/views/sprints/show.html.erb | 159 ++++++++++-----------------
app/views/stories/_edit.html.erb | 36 +++----
app/views/stories/index.html.erb | 51 ++++++++-
app/views/stories/show.html.erb | 58 +++-------
app/views/tasks/_edit.html.erb | 117 +++++++++-----------
app/views/tasks/_list.html.erb | 62 ++++-------
app/views/tasks/show.html.erb | 87 +++++----------
app/views/users/_edit.html.erb | 156 ++++++++++++--------------
app/views/users/backlog.html.erb | 11 ++-
app/views/users/index.html.erb | 34 ++++++-
app/views/users/password.html.erb | 68 +++++-------
app/views/users/show.html.erb | 81 ++++++--------
config/routes.rb | 4 +-
db/migrate/003_create_projects.rb | 2 +-
public/stylesheets/details.css | 68 ++----------
public/stylesheets/forms.css | 44 +-------
public/stylesheets/lists.css | 126 ---------------------
public/stylesheets/navbar.css | 5 +-
public/stylesheets/projxp.css | 62 ++++++++---
public/stylesheets/sidebar.css | 40 +++++++
public/stylesheets/tables.css | 123 +++++++++++++++++++++
test/functional/projects_controller_test.rb | 11 --
test/unit/epic_test.rb | 18 +++
test/unit/project_test.rb | 20 ++++
51 files changed, 1353 insertions(+), 1562 deletions(-)
delete mode 100644 app/views/products/_list.html.erb
create mode 100644 app/views/products/_shortlist.html.erb
delete mode 100644 app/views/projects/_details.html.erb
delete mode 100644 app/views/sprints/_list.html.erb
delete mode 100644 public/stylesheets/lists.css
create mode 100644 public/stylesheets/sidebar.css
create mode 100644 public/stylesheets/tables.css
diff --git a/app/controllers/epics_controller.rb b/app/controllers/epics_controller.rb
index 2350e84..b51eb34 100644
--- a/app/controllers/epics_controller.rb
+++ b/app/controllers/epics_controller.rb
@@ -37,7 +37,7 @@ class EpicsController < ApplicationController
# GET /projects/1/epics/new
def new
- if @project.can_edit_epics?(@user)
+ if @project.can_create_epics?(@user)
@title = "Create new epic for #{(a)project.name}"
@epic = Epic.new(:project => @project)
else
@@ -48,7 +48,7 @@ class EpicsController < ApplicationController
# GET /projects/1/epics/1/edit
def edit
- if @project.can_edit_epics?(@user)
+ if @project.can_create_epics?(@user)
@title = "Edit epic for #{(a)project.name}"
else
flash[:error] = "You are not authorized to edit epics for this project."
@@ -59,7 +59,7 @@ class EpicsController < ApplicationController
# POST /projects/1/epics
def create
respond_to do |format|
- if @project.can_edit_epics?(@user)
+ if @project.can_create_epics?(@user)
Epic.transaction do
@epic = Epic.new(params[:epic])
if @epic.save
@@ -81,7 +81,7 @@ class EpicsController < ApplicationController
# PUT /projects/1/epics/1
def update
respond_to do |format|
- if @project.can_edit_epics?(@user)
+ if @epic.can_edit?(@user)
Epic.transaction do
@epic.update_attributes(params[:epic])
if @epic.save
diff --git a/app/controllers/projects_controller.rb
b/app/controllers/projects_controller.rb
index 4b561cc..e13c6e8 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -23,16 +23,15 @@ class ProjectsController < ApplicationController
before_filter :load_project, :except => [:index, :new, :create, :destroy]
before_filter :filter_approved, :only => [:approve, :reject]
before_filter :can_approve, :only => [:approve, :reject]
- before_filter :setup_for_edit, :only => [:new, :create, :edit]
+ before_filter :setup_for_edit, :only => [:new, :create, :edit, :update]
# GET /projects
def index
@title = "All Projects"
- conditions = 'approved = true'
- conditions = "#{conditions} or approved = false" if @user &&
@user.can_create_projects?
+ @order = "id"
@projects = Project.paginate(:page => params[:page],
:per_page => 10,
- :conditions => conditions)
+ :order => @order)
respond_to do |format|
format.html
@@ -96,21 +95,17 @@ class ProjectsController < ApplicationController
def update
respond_to do |format|
if @project.can_edit?(@user)
- begin
- Project.transaction do
- @project.update_attributes(params[:project])
- if @project.save!
- flash[:message] = "Project was successfully updated."
- format.html { redirect_to params[:source] ? params[:source] :
project_path(@project) }
- else
- @title = "#{(a)project.name} (Edit)"
- @project.valid?
- format.html { render :action => 'edit'}
- end
+ @project.update_attributes(params[:project])
+ puts "PROJECT UPDATED"
+ Project.transaction do
+ if @project.save
+ flash[:message] = "Project was successfully updated."
+ format.html { redirect_to params[:source] ? params[:source] :
project_path(@project) }
+ else
+ @title = "#{(a)project.name} (Edit)"
+ @project.valid?
+ format.html { render :action => 'edit'}
end
- rescue Exception => error
- flash[:error] = "ERROR: #{error.message}"
- format.html { redirect_to error_url }
end
else
flash[:error] = "You are not authorized to edit this project."
diff --git a/app/controllers/stories_controller.rb
b/app/controllers/stories_controller.rb
index f18d490..ce606c3 100644
--- a/app/controllers/stories_controller.rb
+++ b/app/controllers/stories_controller.rb
@@ -23,7 +23,7 @@ class StoriesController < ApplicationController
def index
@title = "All User Stories for #{(a)product.name}"
@user_stories = UserStory.paginate(
- :page => params[:user_story_page],
+ :page => params[:page],
:per_page => 10,
:conditions => ['product_id = ?', @product.id],
:order => 'priority ASC')
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 87ca3e2..7ad66c7 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -34,7 +34,7 @@ class UsersController < ApplicationController
@backlog_items = BacklogItem.paginate(
:conditions => ['owner_id = ?', @this_user.id],
:order => '(select priority from user_stories where id = user_story_id)
ASC',
- :page => params[:page],
+ :page => params[:item_page],
:per_page => 10
)
end
diff --git a/app/models/epic.rb b/app/models/epic.rb
index fe0bb5b..e2e33b6 100644
--- a/app/models/epic.rb
+++ b/app/models/epic.rb
@@ -40,6 +40,11 @@ class Epic < ActiveRecord::Base
"#{title} (#{priority})"
end
+ # Returns whether the user can edit this epic.
+ def can_edit?(user)
+ (user != nil) && (user.id == project.owner_id)
+ end
+
# Returns whether this epic can be deleted.
def can_delete?(user)
(user != nil) && (user.id == project.owner_id) &&
user_stories.empty?
diff --git a/app/models/product.rb b/app/models/product.rb
index 10ef7d6..afeaf5e 100644
--- a/app/models/product.rb
+++ b/app/models/product.rb
@@ -43,6 +43,7 @@ class Product < ActiveRecord::Base
:order => 'priority ASC'
has_many :product_roles
has_many :users, :through => :product_roles
+ has_many :user_stories
has_many :sprints
# Returns the set of roles that are active.
diff --git a/app/models/project.rb b/app/models/project.rb
index a984b15..0eec2fb 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -42,12 +42,12 @@ class Project < ActiveRecord::Base
# Returns whether the user can create products for this project.
def can_create_products?(user)
- (user != nil) && (user.id == owner_id)
+ approved && (user != nil) && (user.id == owner_id)
end
# Returns whether the user can create or edit epic stories.
- def can_edit_epics?(user)
- (user != nil) && (user.id == owner_id)
+ def can_create_epics?(user)
+ approved && (user != nil) && (user.id == owner_id)
end
# Returns whether the user can approve the project.
diff --git a/app/views/epics/_edit.html.erb b/app/views/epics/_edit.html.erb
index 9625f17..04800df 100644
--- a/app/views/epics/_edit.html.erb
+++ b/app/views/epics/_edit.html.erb
@@ -1,37 +1,39 @@
-<% html = @epic.new_record? ? {:method => :post} : {:method => :put} %>
-<% form_for :epic, @epic, :url => project_epic_path(@project, @epic), :html =>
html do |form| %>
-<table class="edit">
- <tr>
- <td class="label">For project:</td>
- <td class="value">
- <%= @project.name %>
- <%= hidden_field_tag :project_id, @project.id %>
- <%= form.hidden_field :project_id %>
- </td>
- </tr>
- <tr>
- <td class="label-required">Title:</td>
- <td class="value">
- <%= form.text_field :title, :size => 50, :maxlength => 100 %>
- <%= error_message_on(:epic, :title) %>
- </td>
- </tr>
- <tr>
- <td class="label-required">Priority:</td>
- <td class="value">
- <%= form.text_field :priority, :size => 5, :maxlength => 5 %>
- <% error_message_on(:epic, :priority) %>
- </td>
- </tr>
- <tr>
- <td class="label">
- Description:u<br />
- (you can use wiki markup)
- </td>
- <td class="value"><%= form.text_area :description, :rows => 10,
:cols => 100 %></td>
- </tr>
- <tr>
- <td class="buttons" colspan="2"><%= submit_tag
"Save" %></td>
- </tr>
-</table>
-<% end %>
+<div id="content">
+ <% html = @epic.new_record? ? {:method => :post} : {:method => :put} %>
+ <% form_for :epic, @epic, :url => project_epic_path(@project, @epic), :html =>
html do |form| %>
+ <table class="edit">
+ <tr>
+ <td class="label">For project:</td>
+ <td class="value">
+ <%= @project.name %>
+ <%= hidden_field_tag :project_id, @project.id %>
+ <%= form.hidden_field :project_id %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Title:</td>
+ <td class="value">
+ <%= form.text_field :title, :size => 50, :maxlength => 100 %>
+ <%= error_message_on(:epic, :title) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Priority:</td>
+ <td class="value">
+ <%= form.text_field :priority, :size => 5, :maxlength => 5 %>
+ <% error_message_on(:epic, :priority) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label">
+ Description:<br />
+ (you can use wiki markup)
+ </td>
+ <td class="value"><%= form.text_area :description, :rows =>
10, :cols => 100 %></td>
+ </tr>
+ <tr>
+ <td class="buttons" colspan="2"><%= submit_tag
"Save" %></td>
+ </tr>
+ </table>
+ <% end %>
+</div>
diff --git a/app/views/epics/index.html.erb b/app/views/epics/index.html.erb
index 7653c54..d1a1d35 100644
--- a/app/views/epics/index.html.erb
+++ b/app/views/epics/index.html.erb
@@ -1,46 +1,43 @@
-<div>
- <ul>
- <% if @project.can_edit_epics?(@user) %>
- <li><%= link_to "Add epic", new_project_epic_path(@project)
%></li>
- <% end %>
- </ul>
+<div id="content">
+ <div>
+ <%= will_paginate @epics %>
+ </div>
+ <div>
+ <table class="main-list">
+ <caption><%= "Epic Stories For #{(a)project.name}"
%></caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col">Rank</th>
+ <th scope="col" class="name">Title</th>
+ <th scope="col">Stories</th>
+ <th scope="col">Created</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @epics.each do |epic| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= epic.id %></td>
+ <td><%= epic.priority %></td>
+ <td class="name">
+ <%= link_to "#{epic.title}", project_epic_path(@project, epic) %>
+ <%= RedCloth.new(get_first_sentence epic.description).to_html %>
+ </td>
+ <td><%= epic.user_stories.size %></td>
+ <td><%= show_date epic.created_at %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ </div>
</div>
-<%= will_paginate @epics %>
-
-<table class="main-list">
- <caption><%= "Epic Stories For #{(a)project.name}"
%></caption>
- <thead>
- <tr>
- <th scope="col">#</th>
- <th scope="col">Rank</th>
- <th scope="col" class="name">Title</th>
- <th scope="col">User Stories</th>
- <th scope="col">Created</th>
- <th scope="col">Actions</th>
- </tr>
- </thead>
- <tbody>
- <% @epics.each do |epic| %>
- <tr class="<%= cycle('odd', 'even') %>">
- <td><%= epic.id %></td>
- <td><%= epic.priority %></td>
- <td><%= epic.title %></td>
- <td><%= epic.user_stories.size %></td>
- <td><%= show_date epic.created_at, true %></td>
- <td>
- <% if @project.can_edit_epics?(@user) %>
- <%= link_to(image_tag("/images/icons/edit.png", :title => "Edit
this epic story..."),
- edit_project_epic_path(@project, epic)) %>
- <% end %>
+<div id="sidebar">
+ <%= link_to "View parent project",
+ project_path(@project), :class => "command" %>
- <% if epic.can_delete?(@user) %>
- <%= link_to image_tag("/images/icons/delete.png", :title => "Delete
this epic..."),
- project_epic_path(@project, epic), :method => :delete,
- :confirm => "Delete this epic? Are you sure?" %>
- <% end %>
- </td>
- </tr>
- <% end %>
- </tbody>
-</table>
+ <% if @project.can_create_epics?(@user) %>
+ <%= link_to "Write new epic...",
+ new_project_epic_path(@project), :class => "command" %>
+ <% end %>
+</div>
diff --git a/app/views/home/error.html.erb b/app/views/home/error.html.erb
index 139597f..08ffb82 100644
--- a/app/views/home/error.html.erb
+++ b/app/views/home/error.html.erb
@@ -1,2 +1,7 @@
+<% if flash[:error] %>
+<div id="errors">
+ <%= flash[:error] %>
+</div>
+<% end %>
diff --git a/app/views/items/_list.html.erb b/app/views/items/_list.html.erb
index bb574a3..1ab1b6a 100644
--- a/app/views/items/_list.html.erb
+++ b/app/views/items/_list.html.erb
@@ -1,99 +1,42 @@
-<table class="list">
- <colgroup>
- <col class="row_id" />
- <col class="number" />
- <col class="description" />
-
- <% unless @this_user %>
- <col class="user" />
- <% end %>
-
- <% unless @sprint %>
- <col class="number" />
- <% end %>
-
- <col class="status" />
- <col class="hours" />
- <col class="actions" />
- </colgroup>
-
- <thead>
- <tr>
- <th class="title" colspan="<%= 8 - (@sprint ? 1 : 0) -
(@this_user ? 1 : 0) %>">Backlog Items</th>
- </tr>
- <tr>
- <th>#</th>
- <th><=></th>
- <th>Title</th>
-
- <% unless @this_user %>
- <th>Owner</th>
- <% end %>
-
- <% unless @sprint %>
- <th>Sprint</th>
- <% end %>
+<div>
+ <table class="main-list">
+ <caption><%= "Backlog Item#{@sprint ? ' For @sprint.name' :
''}" %></caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col">Rank</th>
+ <th scope="col" class="name">Title</th>
- <th>Status</th>
- <th>Hours (E/A/R)</th>
- <th>Action</th>
- </tr>
- </thead>
+ <% unless @this_user %>
+ <th scope="col">Owner</th>
+ <% end %>
- <tbody>
- <% if @backlog_items.empty? %>
- <tr>
- <td colspan="<%= @sprint ? 7 : 8 %>">No backlog items
found...</td>
+ <th scope="col">Hours (E/A/R)</th>
</tr>
- <% else %>
- <% @backlog_items.each_with_index do |item, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <% unless item.completed? %>
- <% row_class='overage' if item.actual_hours >= item.estimated_hours
%>
+ </thead>
+
+ <tbody>
+ <% items.each do |item| %>
+ <% sprint = item.sprint %>
+ <% product = sprint.product %>
+
+ <tr class="state-<%= item.state %>">
+ <td><%= "#{item.id}" %></td>
+ <td><%= "#{item.user_story.priority}" %></td>
+ <td class="name">
+ <%= link_to "#{item.user_story.title} (#{item.state_text})",
+ product_sprint_item_path(item.user_story.product, item.sprint, item) %>
+ <%= RedCloth.new(get_first_sentence item.user_story.description).to_html %>
+ <%= link_to "View Sprint", product_sprint_path(item.sprint.product,
item.sprint) %>
+ </td>
+
+ <% unless @this_user %>
+ <td><%= link_to(item.owner.display_name, user_path(item.owner)) if item.owner
%></td>
<% end %>
- <% sprint = item.sprint %>
- <% product = sprint.product %>
-
- <tr class="<%= row_class %>">
- <td><%= "#{item.id}" %></td>
- <td><%= "#{item.user_story.priority}" %></td>
- <td><%= "#{item.user_story.title}" %></td>
- <% unless @this_user %>
- <td><%= link_to(item.owner.display_name, user_path(item.owner)) if
item.owner %></td>
- <% end %>
-
- <% unless @sprint %>
- <td>
- <div style="overflow: hidden">
- (<%= link_to "#{item.sprint.id}",
product_sprint_path(item.sprint.product, item.sprint) %>)
- <%= h item.sprint.title %>
- </div>
- </td>
- <% end %>
-
- <td><%= item.state_text %></td>
- <td><%= show_hours_as_ear(item) %>
- <td>
- <%= link_to(image_tag("icons/view.png", :title => "View
this item..."),
- product_sprint_item_path(product, sprint, item)) %>
- <%= link_to(image_tag("icons/story_view.png", :title =>
"View the user story..."),
- product_story_path(product, item.user_story)) %>
- <%= link_to(image_tag("icons/item_accept.png", :title =>
"Accept this item..."),
- accept_product_sprint_item_path(product, sprint, item,
- :source => request.request_uri)) if item.can_accept?(@user) %>
- <%= link_to(image_tag("icons/item_drop.png", :title =>
"Drop this item..."),
- drop_product_sprint_item_path(product, sprint,item,
- :source => request.request_uri)) if item.can_drop?(@user) %>
- <%= link_to(image_tag("icons/item_complete.png", :title
=>"Mark this item completed..."),
- complete_product_sprint_item_path(product, sprint, item,
- :source => request.request_uri)) if item.can_complete?(@user) %>
- <%= link_to(image_tag("icons/item_reopen.png", :title =>
"Reopen this item..."),
- reopen_product_sprint_item_path(product, sprint, item,
- :source => request.request_uri)) if item.can_reopen?(@user) %>
- </td>
- </tr>
+ <td><%= show_hours_as_ear(item) %>
+ </tr>
<% end %>
- <% end %>
- </tbody>
-</table>
+ </tbody>
+ </table>
+</div>
diff --git a/app/views/items/index.html.erb b/app/views/items/index.html.erb
index b0d99ff..3bc5fcd 100644
--- a/app/views/items/index.html.erb
+++ b/app/views/items/index.html.erb
@@ -1,2 +1,15 @@
-<%= will_paginate @backlog_items %>
-<%= render(:partial => 'list') %>
+<div id="content">
+ <%= render :partial => 'list', :locals => {:items =>
@backlog_items} %>
+</div>
+
+<div id="sidebar">
+ <% if @sprint %>
+ <%= link_to "View sprint",
+ product_sprint_path(@product, @sprint), :class => "command" %>
+
+ <% if @sprint.can_populate?(@user) %>
+ <%= link_to "Populate this sprint...",
+ plan_product_sprint_path(@product, @sprint), :class => "command"
%>
+ <% end %>
+ <% end %>
+</div>
diff --git a/app/views/items/show.html.erb b/app/views/items/show.html.erb
index 9215d7a..c6c1263 100644
--- a/app/views/items/show.html.erb
+++ b/app/views/items/show.html.erb
@@ -1,85 +1,53 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
+<div id="content">
+ <div id="page-details">
+ <dl>
+ <dt><%= "#{(a)backlog_item.user_story.title}
(#{(a)backlog_item.state_text})" %></dt>
- <thead>
- <tr>
- <th class="title" colspan="2"><%=
@backlog_item.user_story.title %></th>
- </tr>
- </thead>
-
- <tbody>
- <tr>
- <td class="toolbar" colspan="2">
- <%= link_to(image_tag("icons/back.png", :title =>
"Back..."),
- product_sprint_path(@product, @sprint)) %>
- <%= link_to(image_tag("icons/new.png", :title => "Add
task..."),
- new_user_task_path(@user, :item => @backlog_item)) if
@backlog_item.can_add_tasks?(@user) %>
- <%= link_to(image_tag("icons/item_accept.png", :title =>
"Accept this item..."),
- accept_product_sprint_item_path(@product, @sprint, @backlog_item,
- :url => request.request_uri)) if @backlog_item.can_accept?(@user) %>
- <%= link_to(image_tag("icons/item_drop.png", :title => "Drop
this item..."),
- drop_product_sprint_item_path(@product, @sprint,@backlog_item,
- :url => request.request_uri)) if @backlog_item.can_drop?(@user) %>
- <%= link_to(image_tag("icons/item_complete.png", :title =>
"Mark this item completed..."),
- complete_product_sprint_item_path(@product, @sprint, @backlog_item,
- :url => request.request_uri)) if @backlog_item.can_complete?(@user) %>
- <%= link_to(image_tag("icons/item_reopen.png", :title =>
"Reopen this item..."),
- reopen_product_sprint_item_path(@product, @sprint, @backlog_item,
- :url => request.request_uri)) if @backlog_item.can_reopen?(@user) %>
- </td>
- </tr>
-
- <tr>
- <td class="label">Owner:</td>
- <td class="value"><%= @backlog_item.owner.display_name if
@backlog_item.owner %>
- </tr>
-
- <tr>
- <td class="label">Project:</td>
- <td class="value"><%= link_to @product.project.name,
project_path((a)product.project) %></td>
- </tr>
-
- <tr>
- <td class="label">Product:</td>
- <td class="value"><%= link_to @product.name,
product_path(@product) %></td>
- </tr>
-
- <tr>
- <td class="label">Sprint:</td>
- <td class="value">
- <%= link_to "(#{(a)sprint.id})", product_sprint_path(@product, @sprint)
%>
- <%= h @sprint.title %>
- </tr>
-
- <tr>
- <td class="label">Hours E/A/R:</td>
- <td class="value"><%= show_hours_as_ear(@backlog_item)
%></td>
- </tr>
-
- <% if @backlog_item.can_estimate?(@user) %>
- <% form_tag(estimate_product_sprint_item_path(@product, @sprint, @backlog_item))
do %>
- <tr>
- <td class="label">Remaining hours:</td>
- <td class="value">
- <%= text_field_tag(:hours, @backlog_item.estimated_hours, :size => 4)
%>
- <%= submit_tag "Update" %>
- </td>
- </tr>
+ <% if @backlog_item.owned? %>
+ <dt><%= "Owned by #{(a)backlog_item.owner.display_name}"
%></dt>
<% end %>
- <% end %>
-
- <tr>
- <td class="label">Priority:</td>
- <td class="value"><%= @backlog_item.user_story.priority
%></td>
- </tr>
-
- <tr>
- <td class="text" colspan="2"><%= simple_format
@backlog_item.user_story.description %></td>
- </tr>
- </tbody>
-</table>
-<%= render(:partial => 'tasks/list', :object => @tasks) %>
+ <dt>Description</dt>
+ <dd><%= RedCloth.new((a)backlog_item.user_story.description).to_html
%></dd>
+ </dl>
+ </div>
+
+ <div id="task-list">
+ <%= render :partial => 'tasks/list', :locals => {:tasks =>
@backlog_item.tasks} %>
+ </div>
+</div>
+
+<div id="sidebar">
+ <%= link_to "View sprint",
+ product_sprint_path(@product, @sprint), :class => "command" %>
+
+ <% if @backlog_item.can_add_tasks?(@user) %>
+ <%= link_to "Add completed task...",
+ new_user_task_path(@user, :item => @backlog_item),
+ :url => request.request_uri, :class => "command" %>
+ <% end %>
+
+ <% if @backlog_item.can_accept?(@user) %>
+ <%= link_to "Accept this item...",
+ accept_product_sprint_item_path(@product, @sprint, @backlog_item,
+ :url => request.request_uri), :confirm => "Accept this item? Are you
sure?", :class => "command" %>
+ <% end %>
+
+ <% if @backlog_item.can_drop?(@user) %>
+ <%= link_to "Drop this item...",
+ drop_product_sprint_item_path(@product, @sprint,@backlog_item,
+ :url => request.request_uri), :confirm => "Drop this item? Are you
sure?", :class => "command" %>
+ <% end %>
+
+ <% if @backlog_item.can_complete?(@user) %>
+ <%= link_to"Mark this item completed...",
+ complete_product_sprint_item_path(@product, @sprint, @backlog_item,
+ :url => request.request_uri), :confirm => "Mark as completed? Are you
sure?", :class => "command" %>
+ <% end %>
+
+ <% if @backlog_item.can_reopen?(@user) %>
+ <%= link_to "Reopen this item...",
+ reopen_product_sprint_item_path(@product, @sprint, @backlog_item,
+ :url => request.request_uri), :confirm => "Reopen this item? Are you
sure?", :class => "command" %>
+ <% end %>
+</div>
diff --git a/app/views/layouts/default.html.erb b/app/views/layouts/default.html.erb
index c765abe..cc36450 100644
--- a/app/views/layouts/default.html.erb
+++ b/app/views/layouts/default.html.erb
@@ -4,55 +4,54 @@
<%= javascript_include_tag :defaults %>
- <%= stylesheet_link_tag "projxp.css" %>
<%= stylesheet_link_tag "navbar.css" %>
- <%= stylesheet_link_tag "lists.css" %>
<%= stylesheet_link_tag "forms.css" %>
<%= stylesheet_link_tag "details.css" %>
+
+ <%= stylesheet_link_tag "projxp.css" %>
+ <%= stylesheet_link_tag "sidebar.css" %>
+ <%= stylesheet_link_tag "tables.css" %>
</head>
<body>
- <ul id="user-bar">
- <% if @user %>
- <li id="t-dashboard"><%= link_to
"#{(a)user.display_name}", dashboard_url %></li>
- <li id="t-logout"><%= link_to "Logout", logout_path
%></li>
- <% else %>
- <li id="t-login"><%= link_to "Login", login_path
%></li>
- <li id="t-register"><%= link_to "Register",
register_path %></li>
+ <div id="wrap">
+ <div id="header">
+ <div id="user-bar">
+ <ul id="user-bar">
+ <% if @user %>
+ <li id="t-dashboard"><%= link_to
"#{(a)user.display_name}", dashboard_url %></li>
+ <li id="t-logout"><%= link_to "Logout", logout_path
%></li>
+ <% else %>
+ <li id="t-login"><%= link_to "Login", login_path
%></li>
+ <li id="t-register"><%= link_to "Register",
register_path %></li>
+ <% end %>
+ </ul>
+ </div>
+
+ <div id="logo-box">
+ <%= link_to "ProjXP", 'http://projxp.fedorahosted.org/' %>
+ </div>
+
+ <ul id="site-nav">
+ <li><%= link_to "Home", :controller => :home %></li>
+ <li><%= link_to "Projects (#{@project_count})", projects_path
%></li>
+ <li><%= link_to "Products (#{@product_count})", products_path
%></li>
+ <li><%= link_to "Users (#{@user_count})", users_path
%></li>
+ <li><%= link_to "Reports", :controller => :report, :action =>
:index %></li>
+ </ul>
+ </div>
+
+ <% if flash[:message] %>
+ <div id="messages">
+ <%= flash[:message] %>
+ </div>
<% end %>
- </ul>
- <div id="logo-box">
- <%= link_to "ProjXP", 'http://projxp.fedorahosted.org/' %>
- </div>
-
- <ul id="site-nav">
- <li><%= link_to "Home", :controller => :home
%></li>
- <li><%= link_to "Projects (#{@project_count})", projects_path
%></li>
- <li><%= link_to "Products (#{@product_count})", products_path
%></li>
- <li><%= link_to "Users (#{@user_count})", users_path
%></li>
- <li><%= link_to "Reports", :controller => :report, :action
=> :index %></li>
- </ul>
-
- <% if flash[:message] %>
- <div id="messages">
- <%= flash[:message] %>
- </div>
- <% end %>
-
- <% if flash[:error] %>
- <div id="errors">
- <%= flash[:error] %>
- </div>
- <% end %>
-
- <div id="content">
<%= yield :layout %>
- </div>
- <div id="footer">
- Copyright © 2006-2008, Darryl L. Pierce. Usage subject to licensing
agreement.
+ <div id="footer">
+ Copyright © 2006-2008, Darryl L. Pierce. Usage subject to licensing agreement.
+ </div>
</div>
-
</body>
</html>
diff --git a/app/views/products/_edit.html.erb b/app/views/products/_edit.html.erb
index 06272d3..9aeed32 100644
--- a/app/views/products/_edit.html.erb
+++ b/app/views/products/_edit.html.erb
@@ -1,6 +1,4 @@
-<fieldset id="product">
- <legend>Edit Product</legend>
-
+<div id="content">
<% html = @product.new_record? ? {:method => :post} : {:method => :put} %>
<% form_for(:product, @product, :url => product_path(@product), :html => html)
do |form| %>
@@ -11,27 +9,23 @@
<%= hidden_field_tag :project, @project.id %>
<table class="edit">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
+ <caption><%= "#{(a)product.new_record? ? 'Create' :
'Edit'} A Product" %></caption>
<tbody>
<tr>
- <td class="label-required">Project</td>
+ <td class="label-required">Project:</td>
<td class="value"><%= @product.project.name
%></td>
</tr>
<tr>
- <td class="label-required">Name</td>
+ <td class="label-required">Name:</td>
<td class="value">
- <%= form.text_field :name %>
+ <%= form.text_field :name, :size => 50, :maxlength => 128 %>
<%= error_message_on(:product, :name) %>
</td>
</tr>
<tr>
- <td class="label-required">Owner</td>
+ <td class="label-required">Owner:</td>
<td class="value">
<% if @product.project.owner && (@user.id ==
@product.project.owner.id) %>
<%= collection_select :product, :owner_id, @users, :id,
@@ -48,14 +42,17 @@
</tr>
<tr>
- <td class="label">Mailing list</td>
- <td class="value"><%= form.text_field :mailing_list
%></td>
+ <td class="label">Mailing list:</td>
+ <td class="value"><%= form.text_field :mailing_list, :size
=> 50, :maxlength => 128 %></td>
</tr>
<tr>
- <td class="label">Description</td>
+ <td class="label">
+ Description:<br />
+ (you may use wiki markup)
+ </td>
<td class="value">
- <%= form.text_area :description %>
+ <%= form.text_area :description, :cols => 100, :rows => 10 %>
<%= error_message_on(:product, :description) %>
</td>
</tr>
@@ -73,4 +70,4 @@
</table>
<% end %>
-</fieldset>
+</div>
diff --git a/app/views/products/_list.html.erb b/app/views/products/_list.html.erb
deleted file mode 100644
index 9baa851..0000000
--- a/app/views/products/_list.html.erb
+++ /dev/null
@@ -1,73 +0,0 @@
-<table class="list">
- <colgroup>
- <col class="row_id" />
-
- <% if @project == nil %>
- <col class="name" />
- <% end %>
-
- <col class="number" />
- <col class="description" />
- <col class="user" />
- <col class="number" />
- <col class="number" />
- <col class="number" />
- <col class="actions" />
- </colgroup>
-
- <thead>
- <tr>
- <th class="title" colspan="9">Products</th>
- </tr>
- <tr>
- <th>#</th>
-
- <% if @project == nil %>
- <th>Project</th>
- <% end %>
-
- <th>Name</th>
- <th>Description</th>
- <th>Owner</th>
- <th>Stories</th>
- <th>Sprints</th>
- <th>Members</th>
- <th>Actions</th>
- </tr>
- </thead>
-
- <tbody>
- <% if @products.empty? %>
- <tr><td colspan="<%= @project == nil ? 9 : 8 %>">No
Products Found</td></tr>
- <% else %>
- <% last_project = 0 %>
- <% @products.each_with_index do |product, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <tr class="<%= row_class %>">
- <td><%= "#{product.id}" %></td>
-
- <% if @project == nil %>
- <td>
- <% if last_project != product.project_id %>
- <% last_project = product.project_id %>
- <%= link_to product.project.name, project_path(product.project)
%>
- <% end %>
- </td>
- <% end %>
-
- <td><%= product.name %></td>
- <td><%= RedCloth.new(get_first_sentence(product.description)).to_html
%></td>
- <td><%= link_to product.owner.display_name,user_path(product.owner)
%></td>
- <td><%= link_to "#{product.backlog.size}",
product_stories_path(product) %></td>
- <td><%= link_to "#{product.sprints.size}",
product_sprints_path(product) %></td>
- <td><%= link_to "#{product.product_roles.size}",
product_roles_path(product) %>
- <td>
- <%= link_to(image_tag("icons/view.png", :title => "View
this product..."),
- product_path(product)) %>
- <%= link_to(image_tag("icons/edit.png", :title => "Edit
this product..."),
- edit_product_path(product)) if product.can_edit?(@user) %>
- </tr>
- <% end %>
- <% end %>
- </tbody>
-</table>
diff --git a/app/views/products/_shortlist.html.erb
b/app/views/products/_shortlist.html.erb
new file mode 100644
index 0000000..0749aba
--- /dev/null
+++ b/app/views/products/_shortlist.html.erb
@@ -0,0 +1,15 @@
+<table>
+ <caption>Product List</caption>
+ <thead>
+ <th scope="col">#</th>
+ <th scope="col" class="name">Name</th>
+ </thead>
+ <tbody>
+ <% @products.each do |product| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= product.id %></td>
+ <td class="name"><%= link_to product.name, product_path(product)
%></td>
+ </tr>
+ <% end %>
+ </tbody>
+</table>
diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb
index 4d2631a..222602e 100644
--- a/app/views/products/index.html.erb
+++ b/app/views/products/index.html.erb
@@ -1,2 +1,62 @@
-<%= will_paginate @products %>
-<%= render :partial => 'list' %>
+<div id="content">
+ <div>
+ <%= will_paginate @products %>
+ </div>
+ <div>
+ <table class="main-list">
+ <caption>
+ <% if @project %>
+ <%= "Product list for #{(a)project.name}" %>
+ <% else %>
+ Product List
+ <% end %>
+ </caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col" class="name">Name</th>
+ <th scope="col">Stories</th>
+ <th scope="col">Sprints</th>
+ <th scope="col">Members</th>
+ <th scope="col">Created</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <% last_project = 0 %>
+ <% @products.each do |product| %>
+
+ <% if last_project != product.project_id %>
+ <% end %>
+
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= "#{product.id}" %></td>
+
+ <td class="name">
+ <%= link_to "#{product.name}", product_path(product) %>
+ <%= RedCloth.new(get_first_sentence(product.description)).to_html %>
+ <%= link_to product.owner.display_name,user_path(product.owner) %>
+ </td>
+ <td><%= link_to "#{product.backlog.size}",
product_stories_path(product) %></td>
+ <td><%= link_to "#{product.sprints.size}",
product_sprints_path(product) %></td>
+ <td><%= link_to "#{product.product_roles.size}",
product_roles_path(product) %>
+ <td><%= show_date product.created_at %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ </div>
+</div>
+
+<div id="sidebar">
+ <% if @project %>
+ <%= link_to "View parent project",
+ project_path(@project), :class => "command" %>
+ <% end %>
+
+ <% if @project && @project.can_create_products?(@user) %>
+ <%= link_to "Add new product...",
+ new_product_path(:project => @project.id), :class => "command"
%>
+ <% end %>
+</div>
+
diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb
index e2493b0..ce3b941 100644
--- a/app/views/products/show.html.erb
+++ b/app/views/products/show.html.erb
@@ -1,7 +1,40 @@
-<%= render :partial => 'product', :object => @product %>
+<div id="content">
+ <div id="page-details">
+ <dl>
+ <dt>Owner</dt>
+ <dd><%= link_to "#{(a)product.owner.display_name}",
user_path((a)product.owner) %></dd>
-<%= will_paginate @user_stories, :param_name => :user_story_page %>
-<%= render :partial => 'stories/list' %>
+ <% if @product.mailing_list %>
+ <dt>Mailing List</dt>
+ <dd><%= mail_to "#{(a)product.mailing_list}",
@product.mailing_list %></dd>
+ <% end %>
-<%= will_paginate @sprints, :param_name => :sprint_page %>
-<%= render :partial => 'sprints/list' %>
+ <% if @product.description %>
+ <dt>Description</dt>
+ <dd><%= RedCloth.new((a)product.description).to_html %></dd>
+ <% end %>
+ </dl>
+ </div>
+</div>
+
+<div id="sidebar">
+ <%= link_to "View parent project",
+ project_path((a)product.project), :class => "command" %>
+
+ <% if @product.can_edit?(@user) %>
+ <%= link_to "Edit this product",
+ edit_product_path(@product), :class => "command" %>
+ <% end %>
+
+ <%= link_to "User stories (#{(a)product.user_stories.size} total)",
+ product_stories_path(@product), :class => "command" %>
+
+ <%= link_to "Sprints (#{(a)product.sprints.size} total)",
+ product_sprints_path(@product), :class => "command" %>
+
+ <div>
+ <dl>
+ <dt>Reports</dt>
+ </dl>
+ </div>
+</div>
diff --git a/app/views/projects/_details.html.erb b/app/views/projects/_details.html.erb
deleted file mode 100644
index 7db053c..0000000
--- a/app/views/projects/_details.html.erb
+++ /dev/null
@@ -1,30 +0,0 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <thead>
- <tr>
- <th class="title" colspan="2"><%= "Details For
#{(a)project.name}" %></th>
- </tr>
- </thead>
-
- <tbody>
- <tr>
- <td class="label">Owner:</td>
- <td class="value"><%= link_to @project.owner.display_name,
user_path((a)project.owner) %></td>
- </tr>
-
- <tr>
- <td class="label">Homepage:</td>
- <td class="value"><%= link_to_homepage @project %>
- </tr>
-
- <tr>
- <td class="text" colspan="2">
- <%= RedCloth.new((a)project.description).to_html %>
- </td>
- </tr>
- </tbody>
-</table>
diff --git a/app/views/projects/_edit.html.erb b/app/views/projects/_edit.html.erb
index 72bd335..48a2062 100644
--- a/app/views/projects/_edit.html.erb
+++ b/app/views/projects/_edit.html.erb
@@ -1,62 +1,55 @@
-<fieldset id="project">
- <legend>Edit Project</legend>
-
+<div id="content">
<% html = @project.new_record? ? {:method => :post} : {:method => :put} %>
-
<% form_for :project, @project, :url => project_path(@project), :html => html
do |form| %>
-
- <%= hidden_field_tag :source, @source if @source %>
-
- <table class="edit">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <tbody>
- <tr>
- <td class="label-required">Project name</td>
- <td class="value">
- <%= form.text_field :name %>
- <%= error_message_on(:project, :name) %>
- </td>
- </tr>
-
- <tr>
- <td class="label">Website</td>
- <td class="value">
- <%= form.text_field :url %>
- <%= error_message_on(:project, :url) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Owner</td>
- <td class="value">
- <%= collection_select :project, :owner_id, @users, :id,
- :display_name, {:include_blank => false} %>
- <%= error_message_on(:project, :owner) %>
- </td>
- </tr>
-
- <tr>
- <td class="label">Description</td>
- <td class="value">
- <%= form.text_area :description %>
- <%= error_message_on(:project, :description) %>
- </td>
- </tr>
-
- <tr>
- <td class="buttons" colspan="2">
- <% if @project.new_record? %>
- <%= submit_tag "Create", :class => 'button' %>
- <% else %>
- <%= submit_tag "Update", :class => 'button' %>
- <% end %>
- </td>
- </tr>
- </tbody>
- </table>
+ <%= hidden_field_tag :source, @source if @source %>
+ <table class="edit">
+ <caption><%= "#{(a)project.new_record? ? 'Create' :
'Edit'} A Project" %></caption>
+ <tbody>
+ <tr>
+ <td class="label-required">Project name:</td>
+ <td class="value">
+ <%= form.text_field :name, :size => 50, :maxlength => 50 %>
+ <%= error_message_on(:project, :name) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label">Website:</td>
+ <td class="value">
+ <%= form.text_field :url, :size => 50, :maxlength => 255 %>
+ <%= error_message_on(:project, :url) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Owner:</td>
+ <td class="value">
+ <%= collection_select :project, :owner_id, @users, :id,
+ :display_name, {:include_blank => false} %>
+ <%= error_message_on(:project, :owner) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label">
+ Description:<br />
+ (You can use wiki markup.)
+ </td>
+ <td class="value">
+ <%= form.text_area :description, :cols => 100, :rows => 10 %>
+ <%= error_message_on(:project, :description) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="buttons" colspan="2">
+ <% if @project.new_record? %>
+ <%= submit_tag "Create", :class => 'button' %>
+ <% else %>
+ <%= submit_tag "Update", :class => 'button' %>
+ <% end %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
<% end %>
-</fieldset>
+</div>
+
+<div class="sidebar">
+</div>
diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb
index 5f196a4..9df2d87 100644
--- a/app/views/projects/index.html.erb
+++ b/app/views/projects/index.html.erb
@@ -1,82 +1,44 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <tbody>
- <tr>
- <td class="toolbar" colspan="2">
- <%= link_to(image_tag("icons/new.png", :title => "Create a
new project..."),
- new_project_path) if @user %>
- </td>
- </tr>
- </tbody>
-</table>
-
-<%= will_paginate @projects %>
-
-<table class="list">
- <colgroup>
- <col class="row_id" />
- <col class="name" />
- <col class="description" />
- <col class="user" />
- <col class="date" />
- <col class="actions" />
- </colgroup>
- <thead>
- <tr>
- <th class="title" colspan="6">Projects</th>
- </tr>
- <tr>
- <th>#</th>
- <th>Name</th>
- <th>Description</th>
- <th>Owner</th>
- <th>Created</th>
- <th>Actions</th>
- </tr>
- </thead>
-
- <tbody>
- <% if @projects.empty? %>
- <tr><td colspan="6">There are no projects
defined.</td></tr>
- <% else %>
- <% @projects.each_with_index do |project, i| %>
- <% row_class = i%2 == 0 ? 'even' : 'odd' %>
-
- <tr class="<%= row_class %>">
- <td class="row_id"><%= "#{project.id}"
%></td>
- <td>
- <%= project.name %>
- <%= project.approved ? "" : " (Pending)" %>
- </td>
- <td><%= RedCloth.new(get_first_sentence(project.description)).to_html
%></td>
- <td><%= link_to project.owner.display_name, user_path(project.owner)
%></td>
- <td><%= show_date(project.created_at) %></td>
- <td>
- <%= link_to(image_tag("icons/view.png", :title => "View
this project..."),
- project_path(project)) %>
-
- <%= link_to(image_tag("icons/edit.png", :title => "Edit
this project..."),
- edit_project_path(project, :source => request.request_uri)) if
project.can_edit?(@user)%>
-
- <% unless project.approved %>
- <%= link_to(image_tag("icons/approve.png", :title => "Approve
this project..."),
- approve_project_path(project), :method => :put,
- :confirm => "Approve this project? Are you sure?") if
project.can_approve?(@user)
- %>
-
- <%= link_to(image_tag("icons/reject.png", :title => "Reject
this project..."),
- reject_project_path(project), :method => :put,
- :confirm => "Reject this project? Are you sure?") if
project.can_approve?(@user)
- %>
+<div id="content">
+ <div>
+ <%= will_paginate @projects %>
+ </div>
+ <div>
+ <table class="main-list">
+ <caption>List Of Projects</caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col" class="name">Project Name</th>
+ <th scope="col">Epics</th>
+ <th scope="col">Products</th>
+ <th scope="col">Owner</th>
+ <th scope="col">Created</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @projects.each do |project| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= project.id %></td>
+ <td class="name">
+ <%= link_to project.name, project_path(project) %>
+ <% if project.description %>
+ <%= RedCloth.new(get_first_sentence(project.description)).to_html %>
<% end %>
- </td>
- </tr>
-
- <% end %>
- <% end %>
- </tbody>
-</table>
+ <% if project.url %><%= link_to "Homepage", project.url
%><% end %>
+ </td>
+ <td>0</td>
+ <td><%= project.products.count %></td>
+ <td><%= link_to project.owner.display_name, user_path(project.owner)
%></td>
+ <td><%= show_date project.created_at %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ </div>
+</div>
+
+<div id="sidebar">
+ <% if @user %>
+ <%= link_to "Request A New Project", new_project_path, :class =>
"command" %>
+ <% end %>
+</div>
diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb
index 01e65d4..9864ef2 100644
--- a/app/views/projects/show.html.erb
+++ b/app/views/projects/show.html.erb
@@ -1,44 +1,51 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
+<div id="content">
+ <div id="page-details">
+ <dl>
+ <dt>Owner</dt>
+ <dd><%= link_to @project.owner.display_name, user_path((a)project.owner)
%></dd>
- <thead>
- <tr>
- <th class="title" colspan="2"><%= "Details For
#{(a)project.name}" %></th>
- </tr>
- </thead>
+ <dt>Project homepage</dt>
+ <dd>
+ <% if @project.url %>
+ <%= link_to @project.url, @project.url %>
+ <% else %>
+ Not provided.
+ <% end %>
+ </dd>
- <tbody>
- <tr>
- <td class="toolbar" colspan="2">
- <%= link_to(image_tag("icons/add.png", :title => "Request a new
project..."), new_project_path) if @user %>
- <%= link_to(image_tag("icons/back.png", :title =>
"Back..."),
- projects_path) %>
- <%= link_to(image_tag("icons/edit.png", :title => "Edit this
project..."),
- edit_project_path(@project)) if @project.can_edit?(@user) %>
- <%= link_to(image_tag("icons/new.png", :title => "Create a
new product..."),
- new_product_path(:project => @project)) if
@project.can_create_products?(@user) && @project.approved %>
- </td>
- </tr>
+ <dt>Description</dt>
+ <dd>
+ <% if @project.description %>
+ <%= RedCloth.new((a)project.description).to_html %>
+ <% end %>
+ </dd>
+ </dl>
+ </div>
+</div>
- <tr>
- <td class="label">Owner:</td>
- <td class="value"><%= link_to @project.owner.display_name,
user_path((a)project.owner) %></td>
- </tr>
+<div id="sidebar">
+ <% if @project.can_edit?(@user) %>
+ <%= link_to "Edit this project",
+ edit_project_path(@project), :class => "command" %>
+ <% end %>
- <tr>
- <td class="label">Homepage:</td>
- <td class="value"><%= link_to_homepage @project %>
- </tr>
+ <%= link_to "Show all epics (#{(a)project.epics.size} total)",
+ project_epics_path(@project), :class => "command" %>
- <tr>
- <td class="text" colspan="2">
- <%= RedCloth.new((a)project.description).to_html %>
- </td>
- </tr>
- </tbody>
-</table>
+ <% if @project.can_create_epics?(@user) %>
+ <%= link_to "Write new epic...",
+ new_project_epic_path(@project), :class => "command" %>
+ <% end %>
-<%= render :partial => 'products/list', :locals => {:project =>
@project} %>
+ <%= link_to "Show all products (#{(a)project.products.size} total)",
+ products_path(:project => @project), :class => "command" %>
+ <div>
+ <dl>
+ <dt>Reports</dt>
+ <dd>
+ <ul class="options">
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
diff --git a/app/views/sprints/_edit.html.erb b/app/views/sprints/_edit.html.erb
index f7b0b77..5d85ec8 100644
--- a/app/views/sprints/_edit.html.erb
+++ b/app/views/sprints/_edit.html.erb
@@ -1,82 +1,73 @@
-<% html = @sprint.new_record? ? {:method => :post} : {:method => :put} %>
-
-<% form_for(:sprint, @sprint, :url => product_sprint_path(@product, @sprint),
+<div id="content">
+ <% html = @sprint.new_record? ? {:method => :post} : {:method => :put} %>
+ <% form_for(:sprint, @sprint, :url => product_sprint_path(@product, @sprint),
:html => html) do |form| %>
+ <table class="edit">
+ <caption><%= "#{(a)sprint.new_record? ? 'Create' : 'Edit'
} A Sprint" %></caption>
+ <tbody>
+ <tr>
+ <td class="label-required">Title:</td>
+ <td class="value">
+ <%= form.text_field :title, :size => 50, :maxlength => 100 %>
+ <%= error_message_on(:sprint, :title) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Team lead:</td>
+ <td class="value">
+ <%= collection_select :sprint, :team_lead_id, @product.users, :id,
+ :display_name, {:include_blank => false} %>
+ <%= error_message_on(:sprint, :team_lead_id) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Starts on:</td>
+ <td class="value">
+ <%= form.date_select :start %>
+ <%= error_message_on(:sprint, :start) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Duration (in days):</td>
+ <td class="value">
+ <%= form.text_field :duration, :size => 3, :maxlength => 5 %>
+ <%= error_message_on(:sprint, :duration) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">
+ Sprint goals:<br />
+ (you can use wiki markup)
+ </td>
+ <td class="value"><%= form.text_area :goals, :cols => 100,
:rows => 10 %>
+ <%= error_message_on(:sprint, :goals) %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
- <fieldset id="sprint">
- <legend>Edit Sprint</legend>
-
- <table class="edit">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <tbody>
- <tr>
- <td class="label-required">Title</td>
- <td class="value">
- <%= form.text_field :title %>
- <%= error_message_on(:sprint, :title) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Team lead</td>
- <td class="value">
- <%= collection_select :sprint, :team_lead_id, @product.users, :id,
- :display_name, {:include_blank => false} %>
- <%= error_message_on(:sprint, :team_lead_id) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Starts on</td>
- <td class="value">
- <%= form.date_select :start %>
- <%= error_message_on(:sprint, :start) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Duration (in days)</td>
- <td class="value">
- <%= form.text_field :duration %>
- <%= error_message_on(:sprint, :duration) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Sprint goals</td>
- <td class="value"><%= form.text_area :goals %>
- <%= error_message_on(:sprint, :goals) %>
- </td>
- </tr>
- </tbody>
- </table>
-
- <table class="list">
- <thead>
- <tr>
- <th>Select Sprint Team Members</th>
- </tr>
+ <table class="main-list">
+ <thead>
+ <tr>
+ <th scope="col" class="name">Select The Sprint
Team</th>
+ </tr>
</thead>
<tbody>
- <% @members.each_with_index do |member, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <tr class="<%= row_class %>">
- <td>
+ <% @members.each do |member| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td class="name">
<%= check_box_tag "selected[]", member.id,
@selected.include?(member.id) %>
<%= label_tag "selected[]", member.display_name %>
</td>
</tr>
<% end %>
+ <tr>
+ <td class="buttons" colspan="2">
+ <%= submit_tag "Save" %>
+ </td>
+ </tr>
</tbody>
</table>
-
- <%= submit_tag "Save" %>
-
- </fieldset>
-
-<% end %>
+ <% end %>
+</div>
diff --git a/app/views/sprints/_list.html.erb b/app/views/sprints/_list.html.erb
deleted file mode 100644
index 5d327bf..0000000
--- a/app/views/sprints/_list.html.erb
+++ /dev/null
@@ -1,63 +0,0 @@
-<table class="list">
- <colgroup>
- <col class="row_id" />
- <col class="name" />
- <col class="description" />
- <col class="number" />
- <col class="status" />
- <col class="date" />
- <col class="date" />
- <col class="hours" />
- <col class="actions" />
- </colgroup>
-
- <thead>
- <tr>
- <th class="title" colspan="9">Sprints</th>
- <tr>
- <th>#</th>
- <th>Team Lead</th>
- <th>Title</th>
- <th>Members</th>
- <th>Status</th>
- <th>Starts</th>
- <th>Ends</th>
- <th>Hours</th>
- <th>Actions</th>
- </tr>
- </thead>
-
- <tbody>
- <% if @sprints.empty? %>
- <tr>
- <td colspan="9">No sprints found...</td>
- </tr>
- <% else %>
- <% @sprints.each_with_index do |sprint, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <tr class="<%= row_class %>">
- <td><%= "#{sprint.id}" %></td>
- <td><%= mail_to sprint.team_lead.email, sprint.team_lead.display_name
%></td>
- <td><%= sprint.title %></td>
- <td><%= sprint.members.size %></td>
- <td><%= sprint.status_text %></td>
- <td><%= show_date(sprint.start) %></td>
- <td><%= "#{show_date(sprint.end_date)} (#{sprint.duration}
days)" %></td>
- <td><%= show_hours_as_ear(sprint) %></td>
- <td>
- <%= link_to(image_tag("icons/view.png", :title => "View
this sprint..."),
- product_sprint_path(@product, sprint)) %>
- <% if sprint.can_edit?(@user) %>
- <%= link_to(
- image_tag("icons/edit.png", :title => "Edit this
sprint..."),
- edit_product_sprint_path(@product, sprint)) %>
- <% end %>
- <%= link_to(image_tag("icons/delete.png", :title =>
"Delete this sprint..."),
- product_sprint_path(@product, sprint), :method => :delete,
- :confirm => "Delete? Are you sure?") if sprint.can_delete?(@user)
%>
- </td>
- </tr>
- <% end %>
- <% end %>
- </tbody>
-</table>
diff --git a/app/views/sprints/index.html.erb b/app/views/sprints/index.html.erb
index e0b2a3a..5087c3f 100644
--- a/app/views/sprints/index.html.erb
+++ b/app/views/sprints/index.html.erb
@@ -1,5 +1,50 @@
-<%= render :partial => 'products/product', :object => @product %>
+<div id="content">
+ <div>
+ <%= will_paginate @sprints %>
+ </div>
+ <div>
+ <table class="main-list">
+ <caption><%= "Sprints For #{(a)product.name}"
%></caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col" class="name">Title</th>
+ <th scope="col">Team Lead</th>
+ <th scope="col">Members</th>
+ <th scope="col">Status</th>
+ <th scope="col">Starts</th>
+ </tr>
+ </thead>
-<%= will_paginate @sprints %>
+ <tbody>
+ <% @sprints.each do |sprint| %>
+ <tr class="<%= "status-#{sprint.status}" %>">
+ <td><%= sprint.id %></td>
+ <td class="name">
+ <%= link_to "#{sprint.title}
(#{Sprint::STATUS_TEXT[sprint.status][0]})",
+ product_sprint_path(@product, sprint) %>
+ <%= RedCloth.new(get_first_sentence sprint.goals).to_html %>
+ </td>
+ <td>
+ <%= link_to sprint.team_lead.display_name,
+ user_path(sprint.team_lead) %>
+ </td>
+ <td><%= sprint.members.size %></td>
+ <td><%= sprint.status_text %></td>
+ <td><%= "#{show_date(sprint.start)} (#{sprint.duration} days)"
%></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ </div>
+</div>
-<%= render :partial => 'list' %>
+<div id="sidebar">
+ <%= link_to "View parent product",
+ product_path(@product), :class => "command" %>
+
+ <% if @product.can_create_sprints?(@user) %>
+ <%= link_to "Create sprint...",
+ new_product_sprint_path(@product), :class => "command" %>
+ <% end %>
+</div>
diff --git a/app/views/sprints/plan.html.erb b/app/views/sprints/plan.html.erb
index ace6139..43e4485 100644
--- a/app/views/sprints/plan.html.erb
+++ b/app/views/sprints/plan.html.erb
@@ -1,42 +1,37 @@
-<%= form_tag populate_product_sprint_path(@product, @sprint), :html => {:method
=> :post} %>
-
-<%= submit_tag "Populate" %>
-
-<table class="list">
- <colgroup>
- <col class="row_id" />
- <col class="priority" />
- <col class="estimate" />
- <col class="description" />
- </colgroup>
-
- <thead>
- <tr>
- <th>#</th>
- <th>P</th>
- <th>Estimate</th>
- <th>Title</th>
- </tr>
- </thead>
-
- <tbody>
- <% @user_stories.each_with_index do |story, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <% backlog_item = @sprint.backlog_items.find_by_user_story_id(story.id) %>
- <tr class="<%= row_class %>">
- <td><%= story.id %></td>
- <td><%= story.priority %></td>
- <td>
- <%= check_box_tag "selected[]", story.id,
- (backlog_item ||
- (params[:selected].include?(story.id.to_s) if params[:selected])) %>
- <%= text_field_tag "estimates['#{story.id}']",
- (params[:estimates]["'#{story.id.to_s}'"] if params[:estimates])
||
- (backlog_item.estimated_hours if backlog_item),
- :size => 4, :maxlength => 4%>
- </td>
- <td><%= story.title %></td>
- </tr>
- <% end %>
- </tbody>
-</table>
+<div id="content">
+ <%= form_tag populate_product_sprint_path(@product, @sprint), :html => {:method
=> :post} %>
+ <%= submit_tag "Populate" %>
+ <table class="main-list">
+ <caption><%= "Plan #{(a)sprint.title}" %><?caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col">Rank</th>
+ <th scope="col" class="Name">Title</th>
+ <th scope="col">Estimate</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @user_stories.each do |story| %>
+ <% backlog_item = @sprint.backlog_items.find_by_user_story_id(story.id) %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= story.id %></td>
+ <td><%= story.priority %></td>
+ <td class="name">
+ <%= link_to story.title, product_story_path(@product, story), :target =>
"_other" %>
+ <%= RedCloth.new(get_first_sentence story.description).to_html %>
+ </td>
+ <td>
+ <%= check_box_tag "selected[]", story.id,
+ (backlog_item ||
+ (params[:selected].include?(story.id.to_s) if params[:selected])) %>
+ <%= text_field_tag "estimates['#{story.id}']",
+ (params[:estimates]["'#{story.id.to_s}'"] if params[:estimates]) ||
+ (backlog_item.estimated_hours if backlog_item),
+ :size => 4, :maxlength => 4%>
+ </td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+</div>
diff --git a/app/views/sprints/show.html.erb b/app/views/sprints/show.html.erb
index 47cbb0b..37f6d7c 100644
--- a/app/views/sprints/show.html.erb
+++ b/app/views/sprints/show.html.erb
@@ -1,109 +1,70 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
+<div id="content">
+ <div id="page-details">
+ <dl>
+ <dt><%= "#{(a)sprint.title} (#{(a)sprint.status_text})"
%></dt>
+ <dd><%= RedCloth.new((a)sprint.goals).to_html %></dd>
+ <dt>Team Lead</dt>
+ <dd>
+ <%= link_to @sprint.team_lead.display_name,
+ user_path((a)sprint.team_lead) %>
+ </dd>
+ <dt>Sprint Dates</dt>
+ <dd>
+ Starts on <%= show_date((a)sprint.start) %> and continues until <%=
show_date((a)sprint.end_date) %>.
+ This sprint is currently in the <%= @sprint.status_text %> state.
+ </dd>
+ </dl>
+ </div>
+</div>
- <thead>
- <tr>
- <th class="title" colspan="2"><%= @sprint.title
%></th>
- </tr>
- </thead>
+<div id="sidebar">
+ <%= link_to "View parent product",
+ product_path(@product), :class => "command" %>
- <tbody>
- <tr>
- <td colspan="2" class="toolbar">
- <%= link_to(
- image_tag("icons/back.png", :title => "Back..."),
- product_sprints_path(@product)) %>
- <% if @sprint.can_edit?(@user) %>
- <%= link_to(
- image_tag("icons/edit.png", :title => "Edit this
sprint"),
- edit_product_sprint_path(@product, @sprint)) %>
- <% end %>
- <% if @sprint.can_populate?(@user) %>
- <%= link_to(
- image_tag("icons/sprint_plan.png", :title => "Plan this
sprint..."),
- plan_product_sprint_path(@product, @sprint)) %>
- <% end %>
- <%= link_to(image_tag("icons/delete.png", :title => "Delete
this sprint..."),
- product_sprint_path(@product, @sprint), :method => :delete,
- :confirm => "Delete? Are you sure?") if @sprint.can_delete?(@user)
%>
- </td>
- </tr>
+ <% if @sprint.can_edit?(@user) %>
+ <%= link_to "Edit this sprint...",
+ edit_product_sprint_path(@product, @sprint), :class => "command"
%>
+ <% end %>
- <tr>
- <td class="label">Switch to:</td>
- <td class="value">
- <%= form_tag show_product_sprint_path(@product) %>
- <%= select_tag("id", options_for_select((a)sprints.collect{ |sprint|
["#{sprint.title} (#{sprint.status_text})", sprint.id] }, @sprint.id)) %>
- <%= submit_tag "Switch" %>
- </td>
- </tr>
+ <% if @sprint.can_edit?(@user) %>
+ <% if @sprint.can_populate?(@user) %>
+ <%= link_to "Plan this sprint...",
+ plan_product_sprint_path(@product, @sprint), :class => "command"
%>
+ <% end %>
- <tr>
- <td class="label">Team lead:</td>
- <td class="value"><%= mail_to @sprint.team_lead.email,
@sprint.team_lead.display_name %></td>
- </tr>
+ <% if @sprint.allowed_status?(Sprint::STATUS_PLANNED) %>
+ <%= link_to "Move sprint back to planning...",
+ status_product_sprint_path(@product, @sprint, :status =>
Sprint::STATUS_PLANNED),
+ :method => :put, :confirm => "Move to planning? Are you sure?",
+ :class => "command" %>
+ <% end %>
- <tr>
- <td class="label">Starts:</td>
- <td class="value"><%= show_date((a)sprint.start) %></td>
- </tr>
+ <% if @sprint.allowed_status?(Sprint::STATUS_ACTIVE) %>
+ <%= link_to "Start this sprint...",
+ status_product_sprint_path(@product, @sprint, :status =>
Sprint::STATUS_ACTIVE),
+ :method => :put, :confirm => "Start this sprint? Are you sure?",
+ :class => "command" %>
+ <% end %>
- <tr>
- <td class="label">Ends:</td>
- <td class="value"><%= "#{show_date((a)sprint.end_date)}
(#{(a)sprint.duration} days)" %>
- </tr>
+ <% if @sprint.allowed_status?(Sprint::STATUS_CLOSED) %>
+ <%= link_to "Close this sprint...",
+ status_product_sprint_path(@product, @sprint, :status =>
Sprint::STATUS_CLOSED),
+ :method => :put, :confirm => "Close this sprint? Are you sure?",
+ :class => "command" %>
+ <% end %>
- <tr>
- <td class="label">Hours E/A/R:</td>
- <td class="value"><%=
"#{@sprint.estimated_hours}/#{@sprint.actual_hours}/#{(a)sprint.remaining_hours}"
%></td>
- </tr>
+ <% if @sprint.allowed_status?(Sprint::STATUS_CANCELED) %>
+ <%= link_to "Cancel this sprint...",
+ status_product_sprint_path(@product, @sprint, :status =>
Sprint::STATUS_CANCELED),
+ :method => :put, :confirm => "Cancel this sprint? Are you sure?",
+ :class => "command" %>
+ <% end %>
- <tr>
- <td class="label">Team Size:</td>
- <td class="value"><%= "#{(a)sprint.members.size}
Developer#{(a)sprint.members.size ==1 ? '' : 's'}" %></td>
- </tr>
- <tr>
- <td class="label">Status:</td>
- <td class="value">
- <%= @sprint.status_text %>
- <% if @sprint.can_edit?(@user) %>
- [
- <%= link_to(image_tag("icons/sprint_plan.png", :title => "Move
sprint back to planning..."),
- status_product_sprint_path(@product, @sprint, :status =>
Sprint::STATUS_PLANNED),
- :method => :put, :confirm => "Move to planning? Are you
sure?") if @sprint.allowed_status?(Sprint::STATUS_PLANNED) %>
- <%= link_to(image_tag("icons/sprint_start.png", :title => "Start
this sprint..."),
- status_product_sprint_path(@product, @sprint, :status => Sprint::STATUS_ACTIVE),
- :method => :put, :confirm => "Start this sprint? Are you
sure?") if @sprint.allowed_status?(Sprint::STATUS_ACTIVE) %>
- <%= link_to(image_tag("icons/sprint_complete.png", :title =>
"Mark this sprint as completed..."),
- status_product_sprint_path(@product, @sprint, :status => Sprint::STATUS_CLOSED),
- :method => :put, :confirm => "Complete this sprint? Are you
sure?") if @sprint.allowed_status?(Sprint::STATUS_CLOSED) %>
- <%= link_to(image_tag("icons/sprint_cancel.png", :title =>
"Cancel this sprint..."),
- status_product_sprint_path(@product, @sprint, :status =>
Sprint::STATUS_CANCELED),
- :method => :put, :confirm => "Cancel this sprint? Are you
sure?") if @sprint.allowed_status?(Sprint::STATUS_CANCELED) %>
- ]
- <% end %>
- </td>
- </tr>
+ <% end %>
- <% if @sprint.can_view_burndown? %>
- <td class="label">Reports:</td>
- <td class="value">
- <%= form_tag(:controller => :report, :action => :burndown, :id =>
@sprint.id) %>
- <%= select_tag :size, options_for_select(ReportController::REPORT_SIZES)
%>
- <%= submit_tag "Burndown" %>
- </td>
- <% end %>
-
- <tr>
- <td class="text" colspan="2"><%=
RedCloth.new((a)sprint.goals).to_html %></td>
- </tr>
-
- </tbody>
-</table>
-
-<%= will_paginate @backlog_items %>
-<%= render(:partial => 'items/list') %>
+ <%= link_to "View sprint members (#{(a)sprint.members.size} total
members)...",
+ members_product_sprint_path(@product, @sprint), :class => "command"
%>
+ <%= link_to "View sprint backlog (#{(a)sprint.backlog_items.size} total
items)...",
+ product_sprint_items_path(@product, @sprint), :class => "command"
%>
+</div>
diff --git a/app/views/stories/_edit.html.erb b/app/views/stories/_edit.html.erb
index 22e606c..e9a32e7 100644
--- a/app/views/stories/_edit.html.erb
+++ b/app/views/stories/_edit.html.erb
@@ -1,6 +1,4 @@
-<fieldset id="user_story">
- <legend>Edit User Story</legend>
-
+<div id="content">
<% html = @user_story.new_record? ? {:method => :post} : {:method => :put}
%>
<% form_for(:user_story, @user_story,
@@ -13,33 +11,28 @@
<% end %>
<table class="edit">
-
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
+ <caption><%= "#{(a)user_story.new_record? ? 'Create' :
'Edit'} A User Story" %></caption>
<tbody>
<tr>
- <td class="label">Project</td>
+ <td class="label">Project:</td>
<td class="value"><%= link_to @product.project.name,
project_path((a)product.project) %></td>
</tr>
<tr>
- <td class="label">Product</td>
+ <td class="label">Product:</td>
<td class="value"><%= link_to @product.name,
product_path(@product) %></td>
</tr>
<tr>
- <td class="label-required">Title</td>
+ <td class="label-required">Title:</td>
<td class="value">
- <%= form.text_field :title %>
+ <%= form.text_field :title, :size => 50, :maxlength => 100 %>
<%= error_message_on(:user_story, :title) %>
</td>
</tr>
<tr>
- <td class="label">Epic Story</td>
+ <td class="label">Epic Story:</td>
<td class="value">
<%= collection_select :user_story, :epic_id, @epics, :id,
:selectable_title, {:include_blank => true} %>
@@ -47,17 +40,20 @@
</tr>
<tr>
- <td class="label-required">Priority</td>
+ <td class="label-required">Priority:</td>
<td class="value">
- <%= form.text_field :priority %>
+ <%= form.text_field :priority, :size => 3, :maxlength => 5 %>
<%= error_message_on(:user_story, :priority) %>
</td>
</tr>
<tr>
- <td class="label">Description</td>
+ <td class="label">
+ Description:<br />
+ (can use wiki markup)
+ </td>
<td class="value">
- <%= form.text_area :description %>
+ <%= form.text_area :description, :cols => 100, :rows => 10 %>
<%= error_message_on(:user_story, :description) %>
</td>
</tr>
@@ -72,6 +68,6 @@
</tr>
</tbody>
</table>
-
<% end %>
-</fieldset>
+</div>
+
diff --git a/app/views/stories/index.html.erb b/app/views/stories/index.html.erb
index b33933c..2c19a5a 100644
--- a/app/views/stories/index.html.erb
+++ b/app/views/stories/index.html.erb
@@ -1,5 +1,50 @@
-<%= render :partial => 'products/product', :object => @product %>
+<div id="content">
+ <div>
+ <%= will_paginate @user_stories %>
+ </div>
+ <div>
+ <table class="main-list">
+ <caption><%= "User Stories For #{(a)product.name}"
%></caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col">Rank</th>
+ <th scope="col" class="name">Title</th>
+ <th scope="col">Epic</th>
+ <th scope="col">Created</th>
+ </tr>
+ </thead>
-<%= will_paginate @user_stories, :param_name => :user_story_page %>
+ <tbody>
+ <% @user_stories.each do |story| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= story.id %></td>
+ <td><%= story.priority %></td>
+ <td class="name">
+ <%= link_to story.title,
+ product_story_path(@product, story) %>
+ <%= RedCloth.new(get_first_sentence story.description).to_html %>
+ </td>
+ <td>
+ <% if story.epic %>
+ <%= link_to "#{story.epic.id}",
+ project_epic_path(@project, story.epic) %>
+ <% end %>
+ </td>
+ <td><%= show_date story.created_at %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ </div>
+</div>
-<%= render :partial => 'list' %>
+<div id="sidebar">
+ <%= link_to "Return to product page...",
+ product_path(@product), :class => "command" %>
+
+ <% if @product.can_create_user_stories?(@user) %>
+ <%= link_to "Write user stories...",
+ new_product_story_path(@product), :class => "command" %>
+ <% end %>
+</div>
diff --git a/app/views/stories/show.html.erb b/app/views/stories/show.html.erb
index e7d6d0c..9e707ea 100644
--- a/app/views/stories/show.html.erb
+++ b/app/views/stories/show.html.erb
@@ -1,44 +1,18 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
+<div id="content">
+ <div id="page-details"
+ <dl>
+ <dt><%= "#{(a)user_story.title} (Ranked #{(a)user_story.priority})"
%></dt>
+ <dd><%= RedCloth.new((a)user_story.description).to_html %></dd>
+ </dl>
+ </div>
+</div>
- <thead>
- <tr>
- <th class="title" colspan="2"><%= @user_story.title
%></th>
- </tr>
- </thead>
+<div id="sidebar">
+ <%= link_to "Return to user stories list...",
+ product_stories_path(@product), :class => "command" %>
- <tbody>
-
- <tr>
- <td class="toolbar" colspan="2">
- <%= link_to(image_tag("icons/back.png", :title =>
"Back..."),
- product_stories_path(@product)) %>
- <%= link_to(image_tag("icons/edit.png", :title => "Edit this
user story..."),
- edit_product_story_path(@product, @user_story,
- :url => request.request_uri)) if @user_story.can_edit?(@user) %>
- </td>
- </tr>
-
- <tr>
- <td class="label">Project:</td>
- <td class="value"><%= link_to @product.project.name,
project_path((a)product.project) %></td>
- </tr>
-
- <tr>
- <td class="label">Product:</td>
- <td class="value"><%= link_to @product.name,
product_path(@product) %></td>
- </tr>
-
- <tr>
- <td class="label">Priority:</td>
- <td class="value"><%= @user_story.priority %></td>
- </tr>
-
- <tr>
- <td class="text" colspan="2"><%=
RedCloth.new((a)user_story.description).to_html %></td>
- </tr>
- </tbody>
-</table>
+ <%if @user_story.can_edit?(@user) %>
+ <%= link_to "Edit user story...",
+ edit_product_story_path(@product, @user_story), :class => "command"
%>
+ <% end %>
+</div>
diff --git a/app/views/tasks/_edit.html.erb b/app/views/tasks/_edit.html.erb
index a095a61..c28da9c 100644
--- a/app/views/tasks/_edit.html.erb
+++ b/app/views/tasks/_edit.html.erb
@@ -1,69 +1,56 @@
-<fieldset id="task">
- <legend>Edit Task</legend>
-
+<div id="content">
<% html = @task.new_record? ? {:method => :post} : {:method => :put} %>
-
<% form_for(:task, @task, :url => user_task_path(@this_user, @task), :html =>
html) do |form| %>
-
- <%= hidden_field_tag :item, @backlog_item.id %>
-
- <table class="edit">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <tbody>
- <tr>
- <td class="label-required">When</td>
- <td class="value">
- <%= form.date_select :when_entered %>
- <%= error_message_on(:task, :when_entered) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Primary</td>
- <td class="value"><%= @task.primary.display_name
%></td>
- </tr>
-
- <tr>
- <td class="label">Backup</td>
- <td class="value">
- <%= collection_select :task, :backup_id, @users, :id,
+ <%= hidden_field_tag :item, @backlog_item.id %>
+ <table class="edit">
+ <caption><%= "#{(a)task.new_record? ? 'Create' : 'Edit'}
A Task" %></caption>
+ <tbody>
+ <tr>
+ <td class="label-required">When:</td>
+ <td class="value">
+ <%= form.date_select :when_entered %>
+ <%= error_message_on(:task, :when_entered) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Primary:</td>
+ <td class="value"><%= @task.primary.display_name
%></td>
+ </tr>
+ <tr>
+ <td class="label">Backup:</td>
+ <td class="value">
+ <%= collection_select :task, :backup_id, @users, :id,
:display_name, {:include_blank => true} %>
- <%= error_message_on(:task, :backup_id) %>
-
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Hours</td>
- <td class="value">
- <%= form.text_field :hours %>
- <%= error_message_on(:task, :hours) %>
-
- </td>
- </tr>
-
- <tr>
- <td class="label">Description</td>
- <td class="value">
- <%= form.text_area :description %>
- <%= error_message_on(:task, :description) %>
- </td>
- </tr>
-
- <tr>
- <td class="buttons" colspan="2">
- <% if @task.new_record? %>
- <%= submit_tag "Create", :class => 'button' %>
- <% else %>
- <%= submit_tag "Update", :class => 'button' %>
- <% end %>
- </td>
- </tr>
- </tbody>
- </table>
+ <%= error_message_on(:task, :backup_id) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Hours:</td>
+ <td class="value">
+ <%= form.text_field :hours, :size => 3, :maxlength => 5 %>
+ <%= error_message_on(:task, :hours) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label">
+ Description:
+ (you can use wiki markup)
+ </td>
+ <td class="value">
+ <%= form.text_area :description, :cols => 100, :rows => 10 %>
+ <%= error_message_on(:task, :description) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="buttons" colspan="2">
+ <% if @task.new_record? %>
+ <%= submit_tag "Create", :class => 'button' %>
+ <% else %>
+ <%= submit_tag "Update", :class => 'button' %>
+ <% end %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
<% end %>
-</fieldset>
+</div>
diff --git a/app/views/tasks/_list.html.erb b/app/views/tasks/_list.html.erb
index 0bff1d0..df4f657 100644
--- a/app/views/tasks/_list.html.erb
+++ b/app/views/tasks/_list.html.erb
@@ -1,49 +1,29 @@
-<table class="list">
- <colspan>
- <col class="row_id" />
- <col class="date" />
- <col class="description" />
- <col class="user" />
- <col class="user" />
- <col class="hours" />
- <col class="actions" />
- </colspan>
-
+<table class="main-list">
+ <caption>Tasks</caption>
<thead>
<tr>
- <th class="title" colspan="7">Tasks</th>
- </tr>
- <tr>
- <th>#</th>
- <th>When</th>
- <th>Description</th>
- <th>Primary</th>
- <th>Backup</th>
- <th>Hours</th>
- <th>Actions</th>
+ <th scope="col">#</th>
+ <th scope="col">Primary</th>
+ <th scope="col">Backup</th>
+ <th scope="col" class="name">Description</th>
+ <th scope="col">Hours</th>
+ <th scope="col">When</th>
</tr>
</thead>
-
<tbody>
- <% @tasks.each_with_index do |task, index| %>
- <% row_class = index%2 == 0 ? 'even' : 'odd' %>
- <tr class="<%= row_class %>">
- <td><%= "#{task.id}" %></td>
- <td><%= show_date(task.when_entered) %></td>
- <td><%= RedCloth.new(get_first_sentence(task.description)).to_html
%></td>
- <td><%= link_to(task.primary.display_name, user_path(task.primary)) if
task.primary %></td>
- <td><%= link_to(task.backup, user_path(task.backup)) if task.backup
%></td>
- <td><%= format "%0.2f", task.hours %>
- <td>
- <%= link_to(image_tag("icons/view.png", :title => "View
this task..."),
- user_task_path(task.primary, task)) %>
- <%= link_to(image_tag("icons/edit.png", :title => "Edit
this task..."),
- edit_user_task_path(task.primary, task)) if task.can_edit?(@user) %>
- <%= link_to(image_tag("icons/delete.png", :title =>
"Delete this task..."),
- user_task_path(task.primary, task), :confirm => "Are you
sure?",
- :method => :delete) if task.can_delete?(@user) %>
- </td>
- </tr>
+ <% @tasks.each do |task| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= link_to "#{task.id}", user_task_path(task.primary, task)
%></td>
+ <td><%= link_to task.primary.display_name, user_path(task.primary)
%></td>
+ <td>
+ <% if task.backup %>
+ <%= link_to task.backup.display_name, user_path(task.backup) %>
+ <% end %>
+ </td>
+ <td class="name"><%= RedCloth.new(task.description).to_html
%></td>
+ <td><%= format "%0.2f", task.hours %></td>
+ <td><%= show_date(task.when_entered) %></td>
+ </tr>
<% end %>
</tbody>
</table>
diff --git a/app/views/tasks/show.html.erb b/app/views/tasks/show.html.erb
index f68fd57..486d7a5 100644
--- a/app/views/tasks/show.html.erb
+++ b/app/views/tasks/show.html.erb
@@ -1,57 +1,30 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <thead>
- <tr>
- <th class="title" colspan="2"><%= get_first_sentence
@task.description %></th>
- </tr>
- </thead>
-
- <tbody>
- <tr>
- <td class="toolbar" colspan="2">
- <%= link_to(image_tag("icons/back.png", :title =>
"Back..."),
- user_tasks_path((a)task.primary)) %>
- <%= link_to(image_tag("icons/edit.png", :title => "Edit this
task..."),
- edit_user_task_path((a)task.primary, @task)) if @task.can_edit?(@user) %>
- <%= link_to(image_tag("icons/delete.png", :title => "Delete
this task..."),
- user_task_path((a)task.primary, @task, :confirm => "Delete? Are you
sure?",
- :html => {:method => :delete})) if @task.can_delete?(@user) %>
- </td>
- </tr>
-
- <tr>
- <td class="label">Description:</td>
- <td class="value"><%= simple_format @task.description
%></td>
- </tr>
-
- <tr>
- <td class="label">When:</td>
- <td class="value"><%= @task.when_entered %></td>
- </tr>
-
- <tr>
- <td class="label">Hours:</td>
- <td class="value"><%= format "%0.2f", @task.hours
%></td>
- </tr>
-
- <tr>
- <td class="label">Primary:</td>
- <td class="value"><%=
link_to(@task.primary.display_name,user_path((a)task.primary)) if @task.primary
%></td>
- </tr>
-
- <tr>
- <td class="label">Backup:</td>
- <td class="label"><%=
link_to(@task.backup.display_name,user_path((a)task.backup)) if @task.backup
%></td>
- </tr>
-
- <tr>
- <td class="text" colspan="2">
- <%= RedCloth.new((a)task.description).to_html %>
- </td>
- </tr>
- </tbody>
-</table>
+<div id="content">
+ <div id="page-details">
+ <dl>
+ <dt><%= "Primary: #{link_to @task.primary.display_name,
user_path((a)task.primary)}" %></dt>
+ <% if @task.backup %>
+ <dt><%= "Backup: #{link_to @task.backup.dipslay_name,
user_path((a)task.backup)}" %></dt>
+ <% end %>
+ <dt>When?</dt>
+ <dd><%= "On #{show_date @task.when_entered}, for #{format
'0.2f', @task.hours} hours." %></dd>
+ <dt>Task Description</dt>
+ <dd><%= RedCloth.new((a)task.description).to_html %></dd>
+ </dl>
+ </div>
+</div>
+
+<div id="sidebar">
+ <%= link_to "View backlog item",
+ product_sprint_item_path(@product, @sprint, @backlog_item), :class =>
"command" %>
+
+ <% if @task.can_edit?(@user) %>
+ <%= link_to "Edit this task",
+ edit_user_task_path((a)task.primary, @task), :class => "command" %>
+ <% end %>
+
+ <% if @task.can_delete?(@user) %>
+ <%= link_to "Delete this task...",
+ user_task_path((a)task.primary, @task), :method => :delete,
+ :confirm => "Delete this task? Are you sure?", :class =>
"command" %>
+ <% end %>
+</div>
diff --git a/app/views/users/_edit.html.erb b/app/views/users/_edit.html.erb
index 14ab203..0d43361 100644
--- a/app/views/users/_edit.html.erb
+++ b/app/views/users/_edit.html.erb
@@ -1,86 +1,74 @@
-<% html = @this_user.new_record? ? {:method => :post} : {:method => :put} %>
-
-<fieldset id="profile">
- <legend><%= "#{(a)this_user.new_record? ? 'Create' :
'Update'} Account" %></legend>
-
+<div id="content">
+ <% html = @this_user.new_record? ? {:method => :post} : {:method => :put}
%>
<% form_for(:user, @this_user, :url => user_path(@this_user), :html => html)
do |form| %>
-
- <table class="edit">
-
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <tbody>
- <tr>
- <td class="label-required">Display name</td>
- <td class="value">
- <%= form.text_field :display_name %>
- <%= error_message_on(@this_user, :display_name) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Email address</td>
- <td class="value">
- <%= form.text_field :email %>
- <%= error_message_on(@this_user, :email) %>
- </td>
- </tr>
-
- <% if @this_user.new_record? %>
- <tr>
- <td class="label-required">Password</td>
- <td class="value">
- <%= form.password_field :password %>
- <%= error_message_on(@this_user, :password) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Password confirmation</td>
- <td class="value">
- <%= form.password_field :password_confirmation %>
- <%= error_message_on(@this_user, :password_confirmation) %>
- </td>
- </tr>
-
- <% end %>
-
- <tr>
- <td class="label"></td>
- <td class="value">
- <%= form.check_box :use_gravatar %>
- <%= form.label :use_gravatar, "Use a Gravatar-hosted image?" %>
- </td>
- </tr>
- <tr>
- <td class="label">Avatar URL/Gravatar email</td>
- <td class="value">
- <%= form.text_field :url_for_avatar %>
- </td>
- </tr>
- <% if @this_user.avatar? %>
- <tr>
- <td /><td id="current_avatar"><%= image_tag
@this_user.avatar_url %></td>
- </tr>
- <% end %>
-
- <tr>
- <td class="label">Introduction</td>
- <td class="value">
- <%= form.text_area :introduction %>
- <%= error_message_on(@this_user, :introduction) %>
- </td>
- </tr>
-
- <tr>
- <td colspan="2">
- <%= submit_tag "#{(a)this_user.new_record? ? 'Save' :
'Update'}" %>
- </td>
- </tr>
- </tbody>
- </table>
+ <table class="edit">
+ <caption><%= "#{(a)this_user.new_record? ? 'Create' :
'Edit'} User Account" %></caption>
+ <tbody>
+ <tr>
+ <td class="label-required">Display name:</td>
+ <td class="value">
+ <%= form.text_field :display_name, :size => 50, :maxlength => 128
%>
+ <%= error_message_on(@this_user, :display_name) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Email address:</td>
+ <td class="value">
+ <%= form.text_field :email, :size => 50, :maxlength => 128 %>
+ <%= error_message_on(@this_user, :email) %>
+ </td>
+ </tr>
+ <% if @this_user.new_record? %>
+ <tr>
+ <td class="label-required">Password:</td>
+ <td class="value">
+ <%= form.password_field :password, :size => 25, :maxlength => 25
%>
+ <%= error_message_on(@this_user, :password) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Password confirmation:</td>
+ <td class="value">
+ <%= form.password_field :password_confirmation, :size => 25, :maxlength
=> 25 %>
+ <%= error_message_on(@this_user, :password_confirmation) %>
+ </td>
+ </tr>
+ <% end %>
+ <tr>
+ <td class="label"></td>
+ <td class="value">
+ <%= form.check_box :use_gravatar %>
+ <%= form.label :use_gravatar, "Use a Gravatar-hosted image?" %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label">Avatar URL/Gravatar email:</td>
+ <td class="value">
+ <%= form.text_field :url_for_avatar, :size => 50, :maxlength => 128 %>
+ </td>
+ </tr>
+ <% if @this_user.avatar? %>
+ <tr>
+ <td class="label"></td>
+ <td class="value" id="current_avatar"><%= image_tag
@this_user.avatar_url %></td>
+ </tr>
+ <% end %>
+ <tr>
+ <td class="label">
+ Introduction:<br />
+ (you can use wiki markup)
+ </td>
+ <td class="value">
+ <%= form.text_area :introduction, :cols => 100, :rows => 10 %>
+ <%= error_message_on(@this_user, :introduction) %>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <%= submit_tag "#{(a)this_user.new_record? ? 'Save' :
'Update'}" %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
<% end %>
-</fieldset>
+</div>
diff --git a/app/views/users/backlog.html.erb b/app/views/users/backlog.html.erb
index 9137a95..69b3631 100644
--- a/app/views/users/backlog.html.erb
+++ b/app/views/users/backlog.html.erb
@@ -1,3 +1,8 @@
-<%= will_paginate @backlog_items %>
-
-<%= render(:partial => 'items/list', :object => @backlog_items) %>
+<div id="content">
+ <div>
+ <%= will_paginate @backlog_items %>
+ </div>
+ <div>
+ <%= render :partial => 'items/list', :locals => {:items =>
@backlog_items } %>
+ </div>
+</div>
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb
index c33de5f..9440abe 100644
--- a/app/views/users/index.html.erb
+++ b/app/views/users/index.html.erb
@@ -1 +1,33 @@
-<%= render(:partial => 'list', :object => @users) %>
+<div id="content">
+ <div>
+ <%= will_paginate @users %>
+ </div>
+ <table class="main-list">
+ <caption>User List</caption>
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col" class="name">Name</th>
+ <th scope="col">Backlog</th>
+ <th scope="col">Since</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @users.each do |user| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td><%= user.id %></td>
+ <td class="name">
+ <%= link_to user.display_name, user_path(user) %>
+ <%= RedCloth.new(get_first_sentence user.introduction).to_html %>
+ </td>
+ <td><%= link_to "#{user.backlog.size}", backlog_user_path(user)
%></td>
+ <td><%= show_date user.created_at %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+</div>
+
+<div id="sidebar">
+</div>
+
diff --git a/app/views/users/password.html.erb b/app/views/users/password.html.erb
index 5660492..16ebaa1 100644
--- a/app/views/users/password.html.erb
+++ b/app/views/users/password.html.erb
@@ -1,40 +1,32 @@
-<fieldset id="password">
- <legend>Change Password</legend>
+<div id="content">
<% form_for(:user, @this_user, :url => change_password_user_path(@this_user)) do
|form| %>
- <table class="edit">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
-
- <tbody>
- <tr>
- <td class="label-required">Current password</td>
- <td class="value"><%= password_field_tag :old_password,
'', :size => 30 %></td>
- </tr>
-
- <tr>
- <td class="label-required">New password</td>
- <td class="value">
- <%= form.password_field :password, :size => 30 %>
- <%= error_message_on(@this_user, :password) %>
- </td>
- </tr>
-
- <tr>
- <td class="label-required">Confirm password</td>
- <td class="value">
- <%= form.password_field :password_confirmation, :size => 30 %>
- <%= error_message_on(@this_user, :password_confirmation) %>
- </td>
- </tr>
-
- <tr>
- <td class="buttons" colspan="2">
- <%= submit_tag "Update" %>
- </td>
- </tr>
- </tbody>
- </table>
+ <table class="edit">
+ <caption><%= "Change Password For #{(a)this_user.display_name}"
%></caption>
+ <tbody>
+ <tr>
+ <td class="label-required">Current password</td>
+ <td class="value"><%= password_field_tag :old_password,
'', :size => 30, :maxlength => 30 %></td>
+ </tr>
+ <tr>
+ <td class="label-required">New password</td>
+ <td class="value">
+ <%= form.password_field :password, :size => 30, :maxlength => 30
%>
+ <%= error_message_on(@this_user, :password) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="label-required">Confirm password</td>
+ <td class="value">
+ <%= form.password_field :password_confirmation, :size => 30, :maxlength
=> 30 %>
+ <%= error_message_on(@this_user, :password_confirmation) %>
+ </td>
+ </tr>
+ <tr>
+ <td class="buttons" colspan="2">
+ <%= submit_tag "Update" %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
<% end %>
-</fieldset>
+</div>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index e32ce69..3c75f53 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -1,51 +1,38 @@
-<table class="detail">
- <colgroup>
- <col class="label" />
- <col class="value" />
- </colgroup>
+<div id="content">
+ <div id="page-details">
+ <dl>
+ <dt><%= mail_to @this_user.email, @this_user.display_name
%></dt>
+ <dd>
+ <% if @this_user.avatar_url %>
+ <%= image_tag @this_user.avatar_url %>
+ <% end %>
+ <%= RedCloth.new((a)this_user.introduction).to_html %>
+ </dd>
+ </dl>
+ </div>
- <thead>
- <tr>
- <td class="title" colspan="2"><%=
"#{(a)this_user.display_name} (#{(a)this_user.email})" %></td>
- </tr>
- </thead>
-
- <tbody>
- <tr>
- <td class="toolbar" colspan="2">
- <%= link_to(image_tag("icons/back.png", :title =>
"Back..."), users_path) %>
- <%= link_to(image_tag("icons/roles.png", :title => "View this
user's roles..."), roles_user_path(@user)) %>
- <%= link_to(image_tag("icons/edit.png", :title => "Edit this
user..."),
- edit_user_path(@this_user)) if @this_user.can_edit?(@user) %>
- <%= link_to(image_tag("icons/password.png", :title =>
"Change the account password..."),
- password_user_path(@this_user)) if @this_user.can_edit?(@user) %>
- </td>
- </tr>
+ <% if @this_user.can_edit?(@user) %>
+ <div>
+ <%= render :partial => 'notifications' %>
+ </div>
+ <% end %>
- <tr>
- <td colspan="2" class="user_details">
- <dl>
- <dt><%= "#{(a)this_user.display_name}" %></dt>
- <% if @this_user.avatar? %>
- <dd>
- <%= image_tag @this_user.avatar_url %>
- </dd>
- <% end %>
- <dd>
- <%= RedCloth.new((a)this_user.introduction).to_html %>
- </dd>
- </dl>
- </td>
- </tr>
- </tbody>
-</table>
+ <div>
+ <div>
+ <%= will_paginate @backlog_items, :param_name => :item_page %>
+ </div>
+ <%= render :partial => 'items/list', :locals => {:items =>
@backlog_items} %>
+ </div>
+</div>
-<% if @this_user.can_edit?(@user) %>
- <fieldset id="notification">
- <legend>Notifications</legend>
- <%= render :partial => 'notifications' %>
- </fieldset>
-<% end %>
+<div id="sidebar">
+ <% if @this_user.can_edit?(@user) %>
+ <%= link_to "Edit #{(a)this_user.id == @user.id ? 'your details' :
'this user'}",
+ edit_user_path(@this_user), :class => "command" %>
+ <% end %>
-<%= will_paginate @backlog_items %>
-<%= render :partial => 'items/list' %>
+ <% if @this_user.can_edit?(@user) %>
+ <%= link_to "Change password",
+ password_user_path(@this_user), :class => "command" %>
+ <% end %>
+</div>
diff --git a/config/routes.rb b/config/routes.rb
index 5f14233..6fe5168 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -41,8 +41,8 @@ ActionController::Routing::Routes.draw do |map|
{
:plan => :get,
:populate => :post,
- :roles => :get,
- :status => :put
+ :status => :put,
+ :members => :get
}
) do |sprint|
sprint.resources :items, :member =>
diff --git a/db/migrate/003_create_projects.rb b/db/migrate/003_create_projects.rb
index 14de0b0..eba15f6 100644
--- a/db/migrate/003_create_projects.rb
+++ b/db/migrate/003_create_projects.rb
@@ -23,7 +23,7 @@ class CreateProjects < ActiveRecord::Migration
t.timestamps
end
-
+
add_index :projects, :name, :unique => true
execute 'alter table projects add constraint fk_project_owner
diff --git a/public/stylesheets/details.css b/public/stylesheets/details.css
index 515b06e..e6b4890 100644
--- a/public/stylesheets/details.css
+++ b/public/stylesheets/details.css
@@ -1,65 +1,21 @@
-table.detail col.label {
- min-width: 25%;
+#page-details {
+ clear: both;
+ margin: 5px;
}
-table.detail col.value {
- width: 90%;
-}
-
-table.detail {
- width: 100%;
- padding: 5px 15px 5px 15px;
-}
-
-table.detail th.title, table.detail td.title {
+#page-details dt {
+ text-transform: uppercase;
+ font-size: larger;
font-weight: bold;
- text-align: center;
- border-bottom: 1px solid #000000;
- background-color: #f3f3f3;
-}
-
-table.detail td.label {
- padding-left: 50px;
- background-color: #ffffff;
- color: #070707;
- font-weight: bold;
- text-align: right;
-}
-
-table.detail td.value {
- width: 100%;
-}
-
-table.detail td.text {
- font-size: 90%;
- padding: 5px 10px 1px 10px;
-}
-
-table.detail td.user_details {
- width: 300px;
- padding: 10px 0;
- border: 2px solid #ccdd2;
-}
-
-table.detail td.user_details dl {
- margin: 10px 20px;
- padding: 0;
+ color: #0e0e0e;
+ font-size: larger;
+ background: #f3f3f3;
}
-table.detail td.user_details dt {
- margin: 0;
- padding: 0;
- font-size: 130%;
- letter-spacing: 1px;
-}
+#page-details dd {
-table.detail td.user_details dd {
- margin: 0;
- padding: 0;
- font-size: 85%;
- line-height: 1.5em;
}
-table.detail td.user_details dd img {
- float:left;
+#page-details dd a {
+ color: #0f0f0f;
}
diff --git a/public/stylesheets/forms.css b/public/stylesheets/forms.css
index 07dc248..d021d2b 100644
--- a/public/stylesheets/forms.css
+++ b/public/stylesheets/forms.css
@@ -1,5 +1,5 @@
.formError {
- color: #ff0000;
+ color: #7f0000;
font-weight: bold;
}
@@ -16,44 +16,4 @@ legend {
color: #ffffff;
padding: 2px 6px;
font-weight: bold;
-}
-
-table.edit {
- table-layout: fixed;
-}
-
-table.edit col.label {
- width: 15em;
-}
-
-table.edit col.value {
- width: 100%;
-}
-
-table.edit {
- width: 700px;
- padding: 5px 15px 5px 15px;
- margin: 15px 0px 0px 15px;
-}
-
-table.edit td.label, table.edit td.label-required {
- text-align: right;
- font-weight: bold;
-
- color: #0f0f0f;
-
- padding: 1px 5px 1px 15px;
-}
-
-table.edit td.label-required:before {
- color: #ff0000;
- content: "* ";
-}
-
-table.edit td.label:after, table.edit td.label-required:after {
- content: ":";
-}
-
-table.edit input {
- border: 1px groove #000000;
-}
+}
\ No newline at end of file
diff --git a/public/stylesheets/lists.css b/public/stylesheets/lists.css
deleted file mode 100644
index fb43bcc..0000000
--- a/public/stylesheets/lists.css
+++ /dev/null
@@ -1,126 +0,0 @@
-table.list {
- table-layout: fixed;
- width: 100%;
-
- padding: 2px 2px 2px 2px;
-}
-
-table.list * td {
- empty-cells: show;
- overflow: hidden;
- width: 100%;
-}
-
-col.row_id {
- width: 5em;
-}
-
-col.priority {
- width: 4em;
-}
-
-col.estimate {
- width: 8em;
-}
-
-col.name {
- width: 10em;
-}
-
-col.description {
- width: 90%;
-}
-
-col.number {
- width: 7em;
-}
-
-col.user {
- width: 10em;
-}
-
-col.status {
- width: 10em;
-}
-
-col.hours {
- width: 11em;
-}
-
-col.actions {
- width: 96px;
- text-align: center;
-}
-
-col.date {
- width: 10em;
- text-align: center;
-}
-
-table.list thead {
- background: #000000;
-}
-
-table.list th, table.list td {
- padding: 5px 10px 5px 10px;
-}
-
-table.list th {
- color: #000000;
- border-width: 1px;
- border-style: solid;
- /*border-color: #ffffd4 #000000 #000000 #ffffd4;*/
- text-transform: uppercase;
- text-align: center;
- background: #7fffd4;
- overflow: auto;
- padding: 1px;
-}
-
-table.list th.title {
- text-align: center;
- font-weight: bold;
-}
-
-table.list th.corner {
- border-style: none;
- background: none;
-}
-
-table.list tbody {
- font-size: 90%;
-}
-
-table.list tbody .actions a {
- color: #ffff00;
-}
-
-table.list tr.separator {
- background-color: #00f7f7;
- text-align: center;
- font-weight: bold;
-}
-
-table.list tr.odd {
- background-color: #f0fdf0;
-}
-
-table.list td.row_id {
-}
-
-table.list tr.even:hover,
-table.list tr.odd:hover {
- background-color: #ffee87;
- color: #000000;
-}
-
-table.list tr.overage {
- background-color: #7f0000;
- color: #ffff00;
- font-weight: bold;
-}
-
-table.list tr.overage a {
- color: #ffffff;
-}
-
diff --git a/public/stylesheets/navbar.css b/public/stylesheets/navbar.css
index 9b3dcd9..a054b8b 100644
--- a/public/stylesheets/navbar.css
+++ b/public/stylesheets/navbar.css
@@ -15,11 +15,11 @@
color: #ffff00;
}
-#user-bar {
+#user-bar ul {
right: 0;
width: auto;
- position: absolute;
list-style: none;
+ right: 0px;
}
#site-nav {
@@ -49,7 +49,6 @@
#logo-box {
padding: 5px 0 10px 25px;
clear: left;
- width: 100%;
font-size: 300%;
font-weight: bold;
background-color: #336699;
diff --git a/public/stylesheets/projxp.css b/public/stylesheets/projxp.css
index d18d5a5..356ed61 100644
--- a/public/stylesheets/projxp.css
+++ b/public/stylesheets/projxp.css
@@ -1,7 +1,7 @@
body {
- height: 100%;
- width: 100%;
+ background: #070707;
margin: 0;
+ padding-left: 50px;
font-family: arial,sans-serif;
font-size: small;
}
@@ -10,29 +10,46 @@ img {
border: 0px;
}
-table {
- border-spacing: 0;
+#wrap {
+ background-color: #fff;
+ margin-left: 5%;
+ width: 90%;
+ min-width: 750px;
+ max-width: 1200px;
}
-tr {
- vertical-align: top;
+#header {
+ background: #369;
}
-td {
- padding: 0px 5px 0px 5px;
+#user-bar {
+ float: right;
}
-table .toolbar {
- text-align: right;
- padding-right: 15px;
+#content {
+ float: left;
+ width: 70%;
+}
+
+#sidebar {
+ float: right;
+ width: 30%;
+}
+
+#content > div, #navigation > div {
+ padding: 5px 10px;
+}
+
+#sidebar table {
+ font-size: smaller;
}
#footer {
- width: 100%;
- border-top: 1px solid #000000;
- font-size: 100%;
- border-top: solid 1px #000000;
+ clear: both;
+ background: #cc9;
+ padding: 5px 0px 10px 0px;
text-align: center;
+ font-weight: bold;
}
div.pagination {
@@ -41,6 +58,21 @@ div.pagination {
font-weight: bold;
}
+#menubar {
+ float: left;
+}
+
+#menubar li {
+ float: left;
+ margin: 0;
+ list-style: none;
+}
+
+#menubar li a {
+ text-decoration: none;
+ padding-left: 25px;
+}
+
div#errors, div#messages {
width: 90%;
margin: 10px 0px 10px 5%;
diff --git a/public/stylesheets/sidebar.css b/public/stylesheets/sidebar.css
new file mode 100644
index 0000000..e5e0444
--- /dev/null
+++ b/public/stylesheets/sidebar.css
@@ -0,0 +1,40 @@
+div#sidebar a.command {
+ text-align: left;
+ text-indent: 25px;
+ text-decoration: none;
+ width: 90%;
+ margin-left: 5%;
+ display: block;
+ padding: 2px 0px 3px 0px;
+ background: #f00;
+ color: #fff;
+ font-weight: bold;
+ border-bottom: 1px solid #000;
+ border-right: 1px solid #000;
+}
+
+div#sidebar a.command:hover {
+ background: #f77;
+ color: #000;
+}
+
+div#sidebar dt {
+ text-align: left;
+ text-indent: 25px;
+ text-transform: uppercase;
+ font-size: larger;
+ width: 90%;
+ margin-left: 5%;
+ padding: 2px 0px 3px 0px;
+ background: #00f;
+ color: #ff0;
+ font-weight: bold;
+}
+
+div#sidebar * ul.options li {
+ list-style: none;
+}
+
+div#sidebar * ul.otpions li a {
+ text-decoration: none;
+}
diff --git a/public/stylesheets/tables.css b/public/stylesheets/tables.css
new file mode 100644
index 0000000..378284c
--- /dev/null
+++ b/public/stylesheets/tables.css
@@ -0,0 +1,123 @@
+tr {
+ vertical-align: top;
+}
+
+td {
+ padding: 2px 5px 1px 5px;
+ text-align: center;
+}
+
+table caption {
+ margin: 0;
+ padding: 8px 20px;
+ text-align: center;
+ border-bottom: none;
+ font-size: larger;
+ font-weight: bold;
+}
+
+table .name {
+ text-align: left;
+ width: 50%;
+}
+
+table tr.odd {
+ background: #f0f0f0;
+}
+
+table tr.even {
+}
+
+table tr.odd:hover, table tr.even:hover {
+ background: #ff0;
+ color: #000;
+}
+
+table td a {
+ display: block;
+ font-weight: bold;
+}
+
+/* lists that are the primary page content */
+
+table.main-list {
+ font-size: 90%;
+ width: 100%;
+ background: #fff;
+}
+
+table.main-list thead tr th {
+ background-color: #7f7fff;
+ font-size: larger;
+}
+
+/* sprint lists */
+
+table.main-list tr.status-0 { /* planned */
+ background: #cf9;
+}
+
+table.main-list tr.status-1 { /* active */
+ background: #f0f0f0;
+}
+
+table.main-list tr.status-2 { /* closed */
+ background: #0ff;
+}
+
+table.main-list tr.status-3 { /* canceled */
+ background: #f00;
+}
+
+/* backlog item states */
+table.main-list tr.state-0 { /* pending */
+ background: #cf9;
+}
+
+table.main-list tr.state-1 { /* assigned */
+ background: #0f0;
+}
+
+table.main-list tr.state-2 { /* completed */
+ background: #0ff;
+}
+
+table.main-list tr.state-3 { /* dropped */
+ background: #cff;
+}
+
+table.main-list tr.state-4 { /* canceled */
+ background: #f00;
+}
+
+/* edit table styles */
+
+table.edit {
+ border: 0;
+ border-collapse: collapse;
+ background-color: #f0f0f0;
+}
+
+table.edit caption {
+ background-color: #f0f0f0;
+ font-weight: bold;
+ text-align: right;
+}
+
+table.edit td.label, table.edit td.label-required {
+ text-align: right;
+ font-size: smaller;
+ font-weight: bold;
+ padding-left: 15px;
+}
+
+table.edit td.label-required:before {
+ color: #ff0000;
+ content: "* ";
+ text-decoration: blink;
+}
+
+table.edit td.value {
+ padding-right: 15px;
+ text-align: left;
+}
diff --git a/test/functional/projects_controller_test.rb
b/test/functional/projects_controller_test.rb
index 81312f3..4092d2f 100644
--- a/test/functional/projects_controller_test.rb
+++ b/test/functional/projects_controller_test.rb
@@ -55,17 +55,6 @@ class ProjectsControllerTest < ActionController::TestCase
assert_response :success
assert assigns['projects'], "Didn't load any projects."
- assigns['projects'].each do |project|
- assert project.approved?, "Unapproved projects should not be shown to normal
users."
- end
- end
-
- # Ensures that admins can see all projects, even those that aren't approved.
- def test_index_as_admin
- get :index, {}, {:user_id => @admin.id}
-
- assert_response :success
- assert assigns['projects'], "Didn't load any projects."
end
# Ensures that showing a single project requires an id.
diff --git a/test/unit/epic_test.rb b/test/unit/epic_test.rb
index f79edc4..bd13745 100644
--- a/test/unit/epic_test.rb
+++ b/test/unit/epic_test.rb
@@ -18,11 +18,19 @@
require File.dirname(__FILE__) + '/../test_helper'
class EpicTest < ActiveSupport::TestCase
+ fixtures :epics
fixtures :projects
+ fixtures :users
def setup
@project = projects(:projxp)
+ @owner = @project.owner
+ @nonowner = users(:mcpierce)
+ raise "Nonowner cannot be the owner!" if @nonowner.id == @owner.id
+
@new_epic = Epic.new(:project => @project, :priority => 1, :title =>
"This is an epic")
+ @epic = epics(:user_stories_epic)
+ raise "Epic must be part of the project!" unless @epic.project_id ==
@project.id
end
# Ensures the project_id field is required.
@@ -71,4 +79,14 @@ class EpicTest < ActiveSupport::TestCase
def test_valid
fail "There is a general problect with validation." unless
@new_epic.valid?
end
+
+ # Ensures that non-admins cannot edit epics.
+ def test_can_edit_as_nonadmin
+ flunk "Non-admins cannot edit epics." if @epic.can_edit?(@nonowner)
+ end
+
+ # Ensures that admins can edit an epic.
+ def test_can_edit
+ flunk "Admins must be able to edit epics." unless @epic.can_edit?(@owner)
+ end
end
diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb
index 120a24e..71e356c 100644
--- a/test/unit/project_test.rb
+++ b/test/unit/project_test.rb
@@ -67,6 +67,11 @@ class ProjectTest < ActiveSupport::TestCase
flunk "There is a general problem with validation." unless
@new_project.valid?
end
+ # Ensures that a non-approved project cannot have producgts.
+ def test_create_products_for_unapproved_projects
+ flunk "Unapproved projects cannot have products." if
@unapproved_project.can_create_products?(@owner)
+ end
+
# Ensures non-owners cannot create products.
def test_create_products_for_nonowners
flunk "Non-owners should not be able to create products!" if
@existing_project.can_create_products?(@nonowner)
@@ -86,4 +91,19 @@ class ProjectTest < ActiveSupport::TestCase
def test_admin_can_approve_projects
flunk "Admins must be able to approve projects." unless
@unapproved_project.can_approve?(@admin)
end
+
+ # Ensures that an unapproved project cannot have epics.
+ def test_create_epics_for_unapproved_project
+ flunk "Unapproved projects cannot have epics." if
@unapproved_project.can_create_epics?(@owner)
+ end
+
+ # Ensures that non-admins cannot create epics.
+ def test_create_epics_for_nonadmins
+ flunk "Non-admins cannot create epics." if
@existing_project.can_create_epics?(@nonowner)
+ end
+
+ # Ensures that creating epics checks is fine.
+ def test_create_epics
+ flunk "A project owner can create epics." unless
@existing_project.can_create_epics?(@owner)
+ end
end
--
1.6.0.6