redesign taskboard

pull/6827/head
Mark Maglana 14 years ago
parent 6657130e92
commit 552a3edf06
  1. 9
      app/helpers/tasks_helper.rb
  2. 49
      app/views/backlogs/show.html.erb
  3. 4
      app/views/tasks/_impediment.html.erb
  4. 4
      app/views/tasks/_task.html.erb
  5. 4
      assets/javascripts/taskboard.js
  6. 115
      assets/stylesheets/task.css
  7. 271
      assets/stylesheets/taskboard.css

@ -1,7 +1,12 @@
module TasksHelper
unloadable
def task_color_or_default(task)
task.nil? || task.assigned_to.nil? ? '#EFEFEF' : task.assigned_to.backlogs_preference(:task_color)
def build_inline_style(task)
task.nil? || task.assigned_to.nil? ? '' : "style='background-color:#{task.assigned_to.backlogs_preference(:task_color)}'"
end
def remaining_hours(item)
item.remaining_hours.nil? || item.remaining_hours==0 ? "" : item.remaining_hours
end
end

@ -1,7 +1,7 @@
<% content_for :header_tags do %>
<%= javascript_include_tag 'show_main', 'board_updater', 'taskboard_updater', 'taskboard', 'story', 'task', 'impediment', :plugin => 'redmine_backlogs' %>
<%= stylesheet_link_tag 'show', 'taskboard', 'task', :plugin => 'redmine_backlogs', :media => 'screen, print' %>
<script type="text/javascript" src="<%= url_for(:action => 'jsvariables', :project_id => @project.id, :sprint_id => @sprint.id) %>"></script>
<%= javascript_include_tag 'show_main', 'board_updater', 'taskboard_updater', 'taskboard', 'story', 'task', 'impediment', :plugin => 'redmine_backlogs' %>
<%= stylesheet_link_tag 'show', 'taskboard', :plugin => 'redmine_backlogs', :media => 'screen, print' %>
<script type="text/javascript" src="<%= url_for(:action => 'jsvariables', :project_id => @project.id, :sprint_id => @sprint.id) %>"></script>
<% end %>
<% content_for :breadcrumbs do %>
@ -15,37 +15,40 @@
<a id="refresh">Refresh</a>
<%- end %>
<div class="meta" id="last_updated"><%= date_string_with_milliseconds( (@last_updated.nil? ? Time.now : @last_updated.updated_on) ) %></div>
<table id="taskboard" cellspacing="0">
<table id="board_header" cellspacing="0">
<tr>
<td class="story_column"><%= l(:backlogs_story) %></td>
<td class="new_task_button_column"> </td>
<td><%= l(:backlogs_story) %></td>
<%- @statuses.each do |status| %>
<td id="status_<%= status.id %>"><%= status.name %></td>
<td class="swimlane"><%= status.name %></td>
<%- end %>
</tr>
</table>
<table id="impediments" class="board" cellspacing="0">
<tr>
<td class="story"><span class="subject"><%= l(:label_sprint_impediments) %></span></td>
<td class="new_impediment_button">+</td>
<td<div class="label_sprint_impediments"><%= l(:label_sprint_impediments) %></div></td>
<td class="add_new">+</td>
<%- @statuses.each do |status| %>
<td class="list <%= status.is_closed? ? 'closed' : '' %>" id="impedimentstatus_<%= status.id %>">
<td class="swimlane list <%= status.is_closed? ? 'closed' : '' %>" id="impstat_<%= status.id %>">
<%= render :partial => "tasks/impediment", :collection => @sprint.impediments.select{|impediment| impediment.status_id==status.id} %>
</td>
<%- end %>
</tr>
</table>
<table id="tasks" class="board" cellspacing="0">
<%- @sprint.stories.each do |story| %>
<tr>
<td class="story <%= mark_if_closed(story) %>"><%= link_to story.id, {:controller => 'issues', :action => 'show', :id => story.id}, { :class => "story_id", :target => "_blank" } %>
<span class="subject"><%= story.subject %></span></td>
<td class="new_task_button">+</td>
<td>
<div class="story <%= mark_if_closed(story) %>">
<div class="id"><%= link_to story.id, {:controller => 'issues', :action => 'show', :id => story.id}, { :target => "_blank" } %></div>
<div class="subject"><%= story.subject %></div>
</div>
</td>
<td class="add_new">+</td>
<%- @statuses.each do |status| %>
<td class="list <%= status.is_closed? ? 'closed' : '' %>" id="<%= story.id %>_<%= status.id %>">
<%- story.children.select{|task| task.status.id==status.id}.each do |task| %>
<%= render :partial => "tasks/task", :object => task %>
<%- end %>
<td class="swimlane list <%= status.is_closed? ? 'closed' : '' %>" id="<%= story.id %>_<%= status.id %>">
<%= render :partial => "tasks/task", :collection => story.children.select{|task| task.status.id==status.id} %>
</td>
<%- end %>
</tr>
@ -54,7 +57,7 @@
<!-- templates -->
<select class="assigned_to_id template" id="assigned_to_id_options">
<option value="" color="<%= task_color_or_default(Task.new) %>"> </option>
<option value=""> </option>
<%- @project.members.each do |member| %>
<option value="<%= member.user_id %>" color="<%= member.user.backlogs_preference(:task_color) %>"><%= member.name %></option>
<%- end %>
@ -67,5 +70,9 @@
</div>
<!-- end of templates -->
<div id="charts">
<div class="meta" id="last_updated"><%= date_string_with_milliseconds( (@last_updated.nil? ? Time.now : @last_updated.updated_on) ) %></div>
<div id="charts"> </div>
<div id="preloader">
<div id="spinner"> </div>
<div id="warning"> </div>
</div>

@ -1,7 +1,7 @@
<div class="task impediment <%= mark_if_closed(impediment) %>" id="impediment_<%= impediment.id %>" style="background-color:<%= task_color_or_default(impediment) %>">
<div class="item impediment <%= mark_if_closed(impediment) %>" id="impediment_<%= impediment.id %>" <%= build_inline_style(impediment) %>>
<div class="id"><%= issue_link_or_empty(impediment) %></div>
<div class="subject editable" fieldtype="textarea" fieldname="subject"><%= impediment.subject %></div>
<div class="remaining_hours editable" fieldname="remaining_hours"><%= impediment.remaining_hours || "0.0" %></div>
<div class="remaining_hours editable" fieldname="remaining_hours"><%= remaining_hours(impediment) %></div>
<div class="assigned_to_id editable" fieldtype="select" fieldname="assigned_to_id">
<div class="t"><%= assignee_name_or_empty(impediment) %></div>
<div class="v"><%= assignee_id_or_empty(impediment) %></div>

@ -1,7 +1,7 @@
<div class="task <%= mark_if_closed(task) %>" id="task_<%= task.id %>" style="background-color:<%= task_color_or_default(task) %>">
<div class="item task <%= mark_if_closed(task) %>" id="task_<%= task.id %>" <%= build_inline_style(task) %>>
<div class="id"><%= issue_link_or_empty(task) %></div>
<div class="subject editable" fieldtype="textarea" fieldname="subject"><%= task.subject %></div>
<div class="remaining_hours editable" fieldname="remaining_hours"><%= task.remaining_hours || "0.0" %></div>
<div class="remaining_hours editable" fieldname="remaining_hours"><%= remaining_hours(task) %></div>
<div class="assigned_to_id editable" fieldtype="select" fieldname="assigned_to_id">
<div class="t"><%= assignee_name_or_empty(task) %></div>
<div class="v"><%= assignee_id_or_empty(task) %></div>

@ -15,7 +15,7 @@ RB.Taskboard = RB.Object.create(RB.Model, {
j.data('this', this);
// Set column widths
this.colWidthUnit = $("#taskboard .list").width();
this.colWidthUnit = $(".swimlane").width();
this.defaultColWidth = 2;
this.loadColWidthPreference();
this.updateColWidths();
@ -135,6 +135,6 @@ RB.Taskboard = RB.Object.create(RB.Model, {
}
$("#col_width input").val(w)
RB.UserPreferences.set('taskboardColWidth', w);
$("#taskboard .list").width(this.colWidthUnit * w).css('min-width', this.colWidthUnit * w);
$(".swimlane").width(this.colWidthUnit * w).css('min-width', this.colWidthUnit * w);
}
});

@ -1,115 +0,0 @@
/* TASK */
.task{
}
.task .id{
display:inline;
float:left;
padding-right:5px;
}
.task .editor{
display:none;
}
.task.editing .editable{
display:none;
}
.task .id{
-moz-border-radius:4px 4px 4px 4px;
background-color:#FFFFFF;
font-size:9px;
height:14px;
left:2px;
opacity:0.7;
overflow:hidden;
position:absolute;
text-align:right;
top:2px;
width:101px;
}
.task, .placeholder{
background-color:rgb(255,253,200);
border:1px solid #CCCCCC;
cursor:move;
display:block;
float:left;
font-size:10px;
height:94px;
margin:10px 0 0 10px;
padding:2px;
position:relative;
width:106px;
}
.task .subject{
height:28px;
margin:17px 0 0 3px;
overflow:hidden;
padding:2px 5px 2px 2px;
width:94px;
}
.placeholder{
background-color:#FFFF00;
border:1px dashed #333300;
}
.task.blank{
cursor:pointer;
}
.task .remaining_hours.editable{
height:15px;
margin:3px 0 0 3px;
overflow:hidden;
padding:1px 2px 2px 3px;
width:96px;
}
.task.editing .remaining_hours.editor{
display:block;
font-family:inherit;
font-size:10px;
height:10px;
left:4px;
position:absolute;
top:53px;
width:96px;
}
.task .assigned_to_id.editable{
height:14px;
margin:3px 0 0 3px;
overflow:hidden;
padding:2px 2px 2px 3px;
width:96px;
}
.task .assigned_to_id .v{
display:none;
}
.task.editing .subject.editor{
display:block;
font-family:inherit;
font-size:10px;
height:28px;
left:1px;
overflow:hidden;
padding:3px 0 0 1px;
position:absolute;
top:0;
width:99px;
}
.task.editing select.assigned_to_id.editor{
display:block;
font-family:inherit;
font-size:10px;
left:4px;
position:absolute;
top:74px;
width:102px;
}
.task.saving .indicator{
background-image:url('../images/indicator.gif');
display:block;
height:16px;
left:3px;
position:absolute;
top:1px;
width:16px;
}
.task.error .indicator{
background-image:url('../images/warning.png');
}

@ -6,69 +6,74 @@
width:20px;
}
/* SPRINT TABLE STYLES */
#taskboard{
background-color:rgb(254,250,248);
/*
swimlane class is used by:
- #board_header
- .board
Also use by the Column Width preference to
determine the unit width of the swimlanes.
See RB.Taskboard.initialize()
*/
.swimlane{
min-width:105px; /* width + (2*margin) + (2*padding) + (2*border) of .item */
padding:5px;
width:105px; /* Must be the same as min-width */
}
/* status labels */
#board_header{
background-color:#EBEBEB;
border:1px solid #CCCCCC;
margin-bottom:10px;
margin-bottom:0;
margin-right:10px;
}
#taskboard td{
#board_header td{
background-color:#EBEBEB;
border-right:1px dotted #CFCFCF;
border-bottom:1px solid #CFCFCF;
padding:0 5px 10px 0;
min-width:125px;
vertical-align:top;
width:125px;
}
#taskboard tr:first-child td{
background-color:rgb(235,235,235);
border-bottom:none;
color:rgb(126,126,126);
color:#7E7E7E;
font-size:14px;
font-weight:bold;
height:30px;
padding:0;
padding-bottom:0;
text-align:center;
vertical-align:middle;
}
#taskboard tr:last-child td{
border-bottom:none;
#board_header td:first-child{
min-width:231px;
padding:10px;
width:231px;
}
#taskboard td:last-child{
#board_header td:last-child{
border-right:none;
}
#taskboard td:first-child{
min-width:137px;
padding:10px;
width:175px;
/* shared #impediments and #tasks */
.board{
background-color:#FCFCFC;
border:1px solid #CCCCCC;
border-top:none;
margin-right:10px;
}
#taskboard td.list.hover{
background-color:#CCCCCC;
.board tr:hover{
background-color:#ffffff;
}
#taskboard td.story,
#taskboard td.story_column,{
font-size:11px;
.board td{
border-right:1px dotted #CFCFCF;
border-bottom:1px dotted #CFCFCF;
vertical-align:top;
}
#taskboard td.story .story_id{
-moz-border-radius:4px 4px 4px 4px;
background-color:#EEEEEE;
float:left;
font-size:9px;
height:14px;
margin:1px 5px 0 0;
overflow:hidden;
padding:0 5px 0 1px;
text-align:right;
width:45px;
.board td:first-child{
min-width:210px;
padding:5px;
width:210px;
}
#taskboard td.story.closed .subject{
text-decoration:line-through;
.board td:last-child{
border-right:none;
}
#taskboard td.new_task_button,
#taskboard td.new_impediment_button,
#taskboard td.new_task_button_column{
.board tr:last-child td{
border-bottom:none;
}
.board .add_new{
margin:0;
min-width:30px;
padding:0;
@ -76,15 +81,183 @@
vertical-align:middle;
width:30px;
}
#taskboard td.new_impediment_button:hover,
#taskboard td.new_task_button:hover{
.board .add_new:hover{
cursor:pointer;
background-color:#ffffcc;
}
#taskboard tr:hover{
background-color:#ffffff;
.story,
.label_sprint_impediments{
-moz-box-shadow: 2px 2px 2px #CCCCCC;
-webkit-box-shadow: 2px 2px 2px #CCCCCC;;
box-shadow: 2px 2px 2px #CCCCCC;;
background-color:#F8F6A5;
border:none;
display:block;
float:left;
font-size:10px;
height:80px;
margin:5px;
padding:5px;
position:relative;
width:190px;
}
.story .id{
-moz-border-radius:4px 4px 4px 4px;
-webkit-border-radius:4px 4px 4px 4px;
border-radius:4px 4px 4px 4px;
background-color:#FFFFFF;
font-size:9px;
opacity:0.8;
overflow:hidden;
padding-bottom:1px;
padding-right:3px;
text-align:right;
width:187px;
}
.story .subject{
height:63px;
line-height:13px;
margin-top:0;
overflow:hidden;
padding:2px;
width:186px;
}
.story.closed .subject{
text-decoration:line-through;
}
/* item styles used by .task and .impediment */
.item, .placeholder{
background-color:#AFAFAF;
border:none;
cursor:move;
display:block;
float:left;
font-size:10px;
height:80px;
margin:5px;
padding:5px;
position:relative;
width:85px;
}
.item{
-moz-box-shadow: 2px 2px 2px #CCCCCC;
-webkit-box-shadow: 2px 2px 2px #CCCCCC;
box-shadow: 2px 2px 2px #CCCCCC;
}
.placeholder{
background-color:#FFFF00;
border:1px dashed #333300;
height:78px;
width:83px;
}
.item .id{
-moz-border-radius:4px 4px 4px 4px;
-webkit-border-radius:4px 4px 4px 4px;
border-radius:4px 4px 4px 4px;
background-color:#FFFFFF;
font-size:9px;
opacity:0.5;
overflow:hidden;
padding-bottom:1px;
padding-right:3px;
text-align:right;
width:82px;
}
.item .id a{
opacity:1.0;
}
.item .editable:hover{
background-color:transparent;
}
.item .subject.editable{
height:52px;
line-height:13px;
margin-top:0;
overflow:hidden;
padding:2px;
width:81px;
}
.item .assigned_to_id.editable{
font-size:9px;
height:10px;
margin-top:2px;
overflow:hidden;
padding:2px;
padding-top:0;
width:81px;
}
.item .assigned_to_id .v{
display:none;
}
.item .remaining_hours.editable{
-moz-border-radius:15px 15px 15px 15px;
-webkit-border-radius:15px 15px 15px 15px;
border-radius:15px 15px 15px 15px;
border:2px solid #FFFFFF;
background-color:#EE0000;
bottom:-5px;
color:#FFFFFF;
font-size:9px;
height:13px;
padding-left:5px;
padding-right:5px;
position:absolute;
right:-5px;
}
.item .remaining_hours.editable:empty{
display:none;
}
.item .indicator{
-moz-border-radius:12px 12px 12px 12px;
-webkit-border-radius:12px 12px 12px 12px;
border-radius:12px 12px 12px 12px;
background-color:#FFFFFF;
background-position:center;
background-repeat:no-repeat;
border:2px solid #000000;
display:none;
height:16px;
left:36px;
padding:2px;
position:absolute;
top:38px;
width:16px;
}
.item.saving .indicator{
background-image:url('../images/indicator.gif');
display:block;
}
.item.error .indicator{
background-image:url('../images/warning.png');
background-position:2px 0;
border-color:#CC0000;
display:block;
}
/* compact view */
.compact .item{
height:20px;
padding:2px;
width:20px;
}
.compact .item *{
display:none;
}
/* others */
#impediment_template,
#task_template{
display:none;
}
#preloader{
left:-500px;
position:absolute;
}
#spinner{
background-image:url('../images/indicator.gif');
}
#warning{
background-image:url('../images/warning.png');
}
Loading…
Cancel
Save