branston 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,44 +13,42 @@
13
13
  # along with Branston. If not, see <http://www.gnu.org/licenses/>.
14
14
 
15
15
  class StoriesController < ApplicationController
16
-
16
+
17
17
  layout 'main'
18
18
  before_filter :login_required, :except => [:show, :generate_feature]
19
- before_filter :retrieve_iterations, :except => [:generate_feature]
19
+ before_filter :retrieve_iterations, :except => [:generate_feature, :show]
20
20
  before_filter :load_iteration, :except => [:generate_feature, :show]
21
-
22
21
  in_place_edit_for :story, :title
23
22
  in_place_edit_for :story, :description
24
23
  in_place_edit_for :story, :points
25
-
24
+
26
25
  def generate_feature
27
26
  @story = Story.find_by_slug(params[:id])
28
27
  if @story.nil?
29
- @story = Story.find(:first, :include => :scenarios,
30
- :conditions => ['slug LIKE ?', "%#{id}%"] )
28
+ @story = Story.find(:first, :include => :scenarios, :conditions => ['slug LIKE ?', "%#{id}%"] )
31
29
  end
32
30
  @story.generate(@story)
33
31
  render :text => 'done'
34
32
  end
35
-
33
+
36
34
  # GET /stories
37
35
  # GET /stories.xml
38
36
  def index
39
37
  @current_stories = Story.for_iteration(@iteration.id).in_progress
40
38
  @backlog_stories = Story.for_iteration(@iteration.id).unassigned
41
39
  @completed_stories = Story.for_iteration(@iteration.id).completed
42
-
40
+
43
41
  respond_to do |format|
44
42
  format.html # index.html.erb
45
43
  format.xml { render :xml => @stories }
46
44
  end
47
45
  end
48
-
46
+
49
47
  # GET /stories/1
50
48
  # GET /stories/1.xml
51
49
  def show
52
50
  @story = Story.find_by_slug(params[:id])
53
-
51
+
54
52
  respond_to do |format|
55
53
  if @story
56
54
  format.html {
@@ -60,86 +58,102 @@ class StoriesController < ApplicationController
60
58
  render :xml => (@story.to_xml :include => { :scenarios => {
61
59
  :include => [:preconditions, :outcomes] } } ) }
62
60
  format.js { @active = true }
63
- else
64
- format.html { render_optional_error_file 404 }
61
+ else
62
+ format.html {
63
+ @iteration = load_iteration
64
+ render_optional_error_file 404
65
+ }
65
66
  format.all { render :nothing => true, :status => 404 }
67
+ end
66
68
  end
67
69
  end
68
- end
69
-
70
- # GET /stories/new
71
- # GET /stories/new.xml
72
- def new
73
- @story = Story.new
74
-
75
- respond_to do |format|
76
- format.html # new.html.erb
77
- format.xml { render :xml => @story }
70
+
71
+ # GET /stories/new
72
+ # GET /stories/new.xml
73
+ def new
74
+ @story = Story.new(:iteration => @iteration)
75
+
76
+ respond_to do |format|
77
+ format.html # new.html.erb
78
+ format.xml { render :xml => @story }
79
+ end
78
80
  end
79
- end
80
-
81
- # GET /stories/1/edit
82
- def edit
83
- @story = Story.find_by_slug(params[:id])
84
- end
85
-
86
- # POST /stories
87
- # POST /stories.xml
88
- def create
89
- @story = Story.new(params[:story])
90
- @story.author = current_user
91
- @story.iteration = @iteration
92
-
93
- respond_to do |format|
94
- if @story.save
95
- flash[:notice] = 'Story was successfully created.'
96
- format.html { redirect_to iteration_stories_url(@iteration) }
97
- format.xml { render :xml => @story, :status => :created, :location => @story }
98
- else
99
- format.html { render :action => "new" }
100
- format.xml { render :xml => @story.errors, :status => :unprocessable_entity }
81
+
82
+ # GET /stories/1/edit
83
+ def edit
84
+ @story = Story.find_by_slug(params[:id])
85
+ end
86
+
87
+ # POST /stories
88
+ # POST /stories.xml
89
+ def create
90
+ @story = Story.new(params[:story])
91
+ @story.author = current_user
92
+ @story.iteration = @iteration
93
+
94
+ respond_to do |format|
95
+ if @story.save
96
+ flash[:notice] = 'Story was successfully created.'
97
+ format.html { redirect_to iteration_stories_path(@iteration) }
98
+ format.xml { render :xml => @story, :status => :created, :location => @story }
99
+ else
100
+ format.html { render :action => "new" }
101
+ format.xml { render :xml => @story.errors, :status => :unprocessable_entity }
102
+ end
101
103
  end
102
104
  end
103
- end
104
-
105
- # PUT /stories/1
106
- # PUT /stories/1.xml
107
- def update
108
- @story = Story.find_by_slug(params[:id])
109
- respond_to do |format|
110
- if @story.update_attributes(params[:story])
111
- flash[:notice] = 'Story was successfully updated.'
112
- format.html { redirect_to iteration_story_path(@iteration, @story) }
105
+
106
+ # PUT /stories/"1
107
+ # PUT /stories/1.xml
108
+ def update
109
+ @story = Story.find_by_slug(params[:id])
110
+
111
+ if params[:story] and params[:story][:status]
112
+ if params[:story][:status] == 'in_progress'
113
+ @story.assign
114
+ end
115
+
116
+ if params[:story][:status] == 'completed'
117
+ @story.finish
118
+ end
119
+ end
120
+
121
+ respond_to do |format|
122
+ if @story.update_attributes(params[:story])
123
+ flash[:notice] = 'Story was successfully updated.'
124
+ format.html { redirect_to iteration_story_path(@iteration, @story) }
125
+ format.xml { head :ok }
126
+ format.js { redirect_to iteration_stories_path(@iteration) }
127
+ else
128
+ format.html { render :action => "edit" }
129
+ format.xml { render :xml => @story.errors, :status => :unprocessable_entity }
130
+ end
131
+ end
132
+
133
+
134
+ end
135
+
136
+ # DELETE /stories/1
137
+ # DELETE /stories/1.xml
138
+ def destroy
139
+ @story = Story.find_by_slug(params[:id])
140
+ @story.destroy
141
+
142
+ respond_to do |format|
143
+ format.html { redirect_to iteration_stories_path(@iteration) }
113
144
  format.xml { head :ok }
114
- format.js { redirect_to iteration_stories_path(@iteration) }
115
- else
116
- format.html { render :action => "edit" }
117
- format.xml { render :xml => @story.errors, :status => :unprocessable_entity }
118
145
  end
119
146
  end
120
- end
121
-
122
- # DELETE /stories/1
123
- # DELETE /stories/1.xml
124
- def destroy
125
- @story = Story.find_by_slug(params[:id])
126
- @story.destroy
127
-
128
- respond_to do |format|
129
- format.html { redirect_to iteration_stories_path(@iteration) }
130
- format.xml { head :ok }
147
+
148
+
149
+ private
150
+
151
+ def retrieve_iterations
152
+ @iterations = Iteration.all
131
153
  end
154
+
155
+ def load_iteration
156
+ @iteration = Iteration.find(params[:iteration_id])
157
+ end
132
158
  end
133
159
 
134
-
135
- private
136
-
137
- def retrieve_iterations
138
- @iterations = Iteration.all
139
- end
140
-
141
- def load_iteration
142
- @iteration = Iteration.find(params[:iteration_id])
143
- end
144
- end
145
-
@@ -1,40 +1,46 @@
1
1
  module IterationsHelper
2
-
2
+
3
3
  # TODO: Untested!
4
4
  #
5
5
  def burndown_chart(iteration, data)
6
-
7
- total_points = 0
8
- points_data = []
9
-
6
+
7
+ total_points = iteration.velocity
8
+ running_total = 0
9
+
10
10
  unless data.nil? or data.empty?
11
- total_points = data[0].total_points.to_i
12
- points_data = data.collect{|d| d.points.to_i}
13
- end
14
-
15
- work_days = []
16
- (iteration.start_date.to_date..iteration.end_date.to_date).to_a.each do |date|
17
- work_days.push date.strftime('%d/%m') unless date.wday == 0 or date.wday == 6
18
- end
19
-
20
- # Keep adding the last value to flatline the chart
21
- while work_days.length > data.length
22
- data.push data[data.length - 1]
23
- end
24
-
25
- # Make some gradations for the y axis labels
26
- y_scale = [0]
27
- [4, 2, 1.5, 1.25, 1].each do |n|
28
- unit = (total_points / n).floor
29
- y_scale.push unit if unit > 0
11
+ points_data = data.map { |d|
12
+ running_total += d.points.to_i
13
+ total_points - running_total
14
+ }
15
+
16
+
17
+ points_data = [total_points] + points_data unless points_data.nil?
18
+
19
+ work_days = [nil]
20
+ (iteration.start_date.to_date..iteration.end_date.to_date).to_a.each do |date|
21
+ work_days.push date.strftime('%d/%m') unless date.wday == 0 or date.wday == 6
22
+ end
23
+
24
+ # Keep adding the last value to flatline the chart
25
+ while work_days.length > points_data.length
26
+ points_data.push points_data.last
27
+ end
28
+
29
+ # Make some gradations for the y axis labels
30
+ y_scale = [0]
31
+ [4, 2, 1.5, 1.25, 1].each do |n|
32
+ unit = (total_points / n).floor
33
+ y_scale.push unit if unit > 0
34
+ end
35
+
36
+ image_tag Gchart.line(:size => '800x360',
37
+ :title => "Iteration #{iteration.name} burndown",
38
+ :data => points_data, :axis_with_labels => 'x,y',
39
+ :axis_labels => [work_days, y_scale])
40
+
41
+ end
42
+
30
43
  end
31
-
32
- image_tag Gchart.line(:size => '500x300',
33
- :title => "#{iteration.name} burndown",
34
- :data => points_data, :axis_with_labels => 'x,y',
35
- :axis_labels => [work_days, y_scale])
36
-
44
+
37
45
  end
38
46
 
39
- end
40
-
@@ -28,14 +28,14 @@ class Iteration < ActiveRecord::Base
28
28
  belongs_to :release
29
29
 
30
30
  def burndown_data
31
- Iteration.find_by_sql [
32
- "SELECT SUM(points) AS total_points,
33
- COUNT(points) AS points,
31
+ Story.find_by_sql [
32
+ "SELECT SUM(points) AS points,
34
33
  completed_date
35
34
  FROM stories
36
35
  WHERE iteration_id = ?
37
36
  AND status = 'completed'
38
- GROUP BY completed_date", id
37
+ GROUP BY completed_date
38
+ ORDER bY completed_date", id
39
39
  ]
40
40
  end
41
41
 
@@ -62,6 +62,8 @@ class Story < ActiveRecord::Base
62
62
  story.completed_date = Date.today
63
63
  end
64
64
  end
65
+
66
+ attr_protected :status
65
67
 
66
68
  def to_param
67
69
  title.parameterize
@@ -1,44 +1,50 @@
1
- <div style="width:38%;float:left">
2
- <p>
3
- <b>Velocity:</b>
4
- <%=h @iteration.velocity %>
5
- </p>
6
-
7
- <p>
8
- <b>Name:</b>
9
- <%=h @iteration.name %>
10
- </p>
11
-
12
- <p>
13
- <b>Start date:</b>
14
- <%=h @iteration.start_date %>
15
- </p>
16
-
17
- <p>
18
- <b>End date:</b>
19
- <%=h @iteration.end_date %>
20
- </p>
21
-
22
- <p>
23
- <b>Release:</b>
24
- <%=h @iteration.release.release_date if @iteration.release %>
25
- </p>
26
-
27
- <% unless @iteration.stories.empty? %>
28
- <b>Stories</b>
29
- <ul>
30
- <% @iteration.stories.each do |story| %>
31
-
32
- <li><%= story.description %> | <%= story.points %></li>
33
-
34
- <% end %>
35
- </ul>
36
- <% end %>
37
- <%= link_to 'Edit', edit_iteration_path(@iteration) %> |
38
- <%= link_to 'Back', iterations_path %>
1
+ <div id="burndown_chart">
2
+ <%= burndown_chart @iteration, @iteration_data %>
39
3
  </div>
40
4
 
41
- <div style="width:58%;float:right">
42
- <%= burndown_chart @iteration, @iteration_data %>
5
+ <div id="iteration_stats">
6
+ <h3>Iteration Stats</h3>
7
+
8
+ <p>
9
+ <b>Velocity:</b>
10
+ <%=h @iteration.velocity %>
11
+ </p>
12
+
13
+ <p>
14
+ <b>Name:</b>
15
+ <%=h @iteration.name %>
16
+ </p>
17
+
18
+ <p>
19
+ <b>Start date:</b>
20
+ <%=h @iteration.start_date %>
21
+ </p>
22
+
23
+ <p>
24
+ <b>End date:</b>
25
+ <%=h @iteration.end_date %>
26
+ </p>
27
+
28
+ <p>
29
+ <b>Release:</b>
30
+ <%=h @iteration.release.release_date if @iteration.release %>
31
+ </p>
32
+
33
+ <% unless @iteration.stories.empty? %>
34
+ <b>Stories</b>
35
+ <ul>
36
+ <% @iteration.stories.each do |story| %>
37
+
38
+ <li><%= story.description %> | <%= story.points %></li>
39
+
40
+ <% end %>
41
+ </ul>
42
+ <% end %>
43
43
  </div>
44
+
45
+ <%= link_to 'Edit', edit_iteration_path(@iteration) %> |
46
+ <%= link_to 'Back', iterations_path %> |
47
+ <%=link_to 'Stories', iteration_stories_path(@iteration) %>
48
+
49
+
44
50
 
@@ -72,3 +72,5 @@ div.preconditions ol li, div.outcomes ol li { margin:2px; font-size:0.95em;}
72
72
  div.story-props {display:block;height:30px;border-bottom:1px dotted grey;padding-top:4px;}
73
73
  div.story-props div {display:inline-block;float:left;margin-left:20px;line-height:25px;}
74
74
 
75
+ #burndown_chart { margin-left:auto; margin-right:auto; width:800px; }
76
+ #iteration_stats { margin-top : 30px; }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: branston
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - dave.hrycyszyn@headlondon.com
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2010-01-07 00:00:00 +00:00
14
+ date: 2010-01-13 00:00:00 +00:00
15
15
  default_executable: branston
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency