Skip to content

Commit

Permalink
make sprints have_many projects through tickets, sync sprints to mult…
Browse files Browse the repository at this point in the history
…iple lighthouse projects
  • Loading branch information
Sven Fuchs committed Oct 23, 2008
1 parent 60c16e7 commit 64318b9
Show file tree
Hide file tree
Showing 18 changed files with 145 additions and 116 deletions.
3 changes: 3 additions & 0 deletions NOTES
Expand Up @@ -2,6 +2,9 @@ convert hours to minutes
make ticket lists filterable

make sprints not belong_to a release?
» this would mean that a sprint can not be sync'ed up to lighthouse anymore easily
it could be "split" up and sync'ed to all projects it contains tickets from

make it possible to compose a sprint from multiple projects
rake task for regularly synch'ing from lighthouse

Expand Down
19 changes: 19 additions & 0 deletions app/controllers/releases_controller.rb
Expand Up @@ -49,4 +49,23 @@ def set_project
@project = @release.project
end
end

def filter
return '' unless filter = params[:filter]
sql = []
sql << filter_state
sql << filter_association(:release)
sql << filter_association(:sprint)
sql.compact * ' AND '
end

def filter_state
return nil unless states = params[:filter][:state]
'state IN (' + states.map{|state| "'#{state}'"} * ', ' + ')'
end

def filter_association(type)
return nil unless ids = params[:filter][type]
"#{type}_id IN (" + ids * ', ' + ')' if ids
end
end
27 changes: 0 additions & 27 deletions app/models/lighthouse/project.rb
Expand Up @@ -5,32 +5,5 @@ def attributes_from_local(project)
{ :id => project.remote_id, :name => project.name, :body => project.body }
end
end

# def milestone(id, options = {})
# Milestone.find id, :params => options.update(:project_id => id)
# end
#
# def memberships(options = {})
# Membership.find :all, :params => options.update(:project_id => id)
# end

def updated_tickets(since)
if since
tickets :q => "updated:\"since #{time_ago_in_words(since - 1.minute)} ago\""
else
all_tickets
end
end

def all_tickets
page = 1
result = paged = []
while page == 1 or !paged.empty?
paged = tickets(:q => :all, :page => page)
result += paged
page += 1
end
result.compact
end
end
end
5 changes: 0 additions & 5 deletions app/models/milestone.rb
@@ -1,7 +1,2 @@
class Milestone < ActiveRecord::Base
belongs_to :project

def push!
project.synchronizer.push! self
end
end
6 changes: 5 additions & 1 deletion app/models/release.rb
@@ -1,5 +1,9 @@
class Release < Milestone
has_many :sprints
belongs_to :project
has_many :tickets, :include => [:project, :release, :user],
:order => 'tickets.sprint_id DESC, tickets.state, tickets.remote_id DESC, tickets.parent_id'

def push!
project.synchronizer.push! self
end
end
7 changes: 7 additions & 0 deletions app/models/sprint.rb
@@ -1,4 +1,7 @@
class Sprint < Milestone
has_many :projects, :through => :plain_tickets, :uniq => true
has_many :plain_tickets, :class_name => 'Ticket' # TODO find a better name

def ticket_groups(sort)
tickets = self.tickets :order => order(sort)
@groups ||= sort.to_sym == :assigned ? tickets.group_by(&:user) : [[nil, tickets]]
Expand Down Expand Up @@ -36,6 +39,10 @@ def ended?
end_at and end_at < Time.zone.today
end

def push!
projects.each{|project| project.synchronizer.push! self }
end

protected

def order(sort)
Expand Down
47 changes: 4 additions & 43 deletions app/models/synchronizer.rb
Expand Up @@ -10,9 +10,11 @@ def initialize(project)
@lighthouse = Synchronizer::Lighthouse.new(@project)
end

# TODO only update relevant changes to Lighthouse
def push!(local)
push! local.sprint if local.is_a?(Ticket) and local.sprint

if local.remote_id.blank?
# TODO only update relevant changes to Lighthouse
remote = lighthouse.from_local(local)
if remote.save
local.update_attributes :remote_id => remote.id
Expand Down Expand Up @@ -64,45 +66,4 @@ def local_class(object)
object.class.name.demodulize.constantize
end
end
end


# cattr_accessor :sync
# @@sync = true
#
# class << self
# def with_no_sync
# old_sync, self.sync = self.sync, false # TODO not threadsafe
# yield
# self.sync = old_sync
# end
#
# alias :sync? :sync
#
# def no_sync!
# self.sync = false
# end
# end

# def project_id
# @project.id
# end
#
# def push_ticket(ticket)
# return unless self.class.sync?
# attributes = { :number => ticket.remote_id, :project_id => @project.remote_id }
# ticket.changes.each do |name, values|
# case name
# when 'user_id'
# attributes['assigned_user_id'] = ticket.user.remote_id if ticket.user
# when 'sprint_id'
# attributes['milestone_id'] = ticket.sprint.remote_id if ticket.sprint
# when 'release_id'
# attributes['milestone_id'] = ticket.release.remote_id if ticket.release
# end
# end
# return if attributes.keys.size == 2
# ticket = ::Lighthouse::Ticket.new(attributes)
# ticket.save
# end

end
41 changes: 21 additions & 20 deletions app/views/layouts/default.html.erb
Expand Up @@ -39,66 +39,67 @@
position: relative;
width: 80%;
}
#main fieldset {
#main form fieldset {
padding: 0.5em 0;
position: relative;
text-align: left;
border: 0px;
border-bottom: 1px solid #ddd;
width: 99%;
}
#main legend {
#main fieldset legend {
position: relative;
color: #666;
margin-left: 10px;
padding-top: 1em;
}
#main label {
#main fieldset label {
position: absolute;
width: 12%;
padding-top: 1px;
text-align: right;
color: #666;
}
#main input[type=text],
#main select,
#main textarea {
#main fieldset input[type=text],
#main fieldset select,
#main fieldset textarea {
border: 1px solid #ddd;
font-size: 1em;
}
#main input[type=text],
#main textarea {
#main fieldset input[type=text],
#main fieldset textarea {
padding: 2px 5px;
}
#main select {
#main fieldset select {
padding: 2px;
}
#main .small input,
#main .small select {
#main fieldset .small input,
#main fieldset .small select {
width: 100px;
}
#main .medium input,
#main .medium select {
#main fieldset .medium input,
#main fieldset .medium select {
width: 200px;
}
#main .big label {
#main fieldset .big label {
padding-top: 5px;
}
#main .big input {
#main fieldset .big input {
font-size: 1.5em;
padding: 3px 5px;
width: 84%;
}
#main input,
#main textarea,
#main select {
#main .buttons input,
#main fieldset input,
#main fieldset textarea,
#main fieldset select {
margin-left: 15%;
}
#main label.check, label.radio {
#main fieldset label.check, label.radio {
position: relative;
text-align: left;
}
#main textarea.small {
#main fieldset textarea.small {
height: 100px;
}

Expand Down
1 change: 1 addition & 0 deletions app/views/releases/new.html.erb
Expand Up @@ -6,6 +6,7 @@
<h1>New release</h1>

<% form_for(@release) do |f| %>
<%= hidden_field_tag :project_id, @project.id %>
<%= render :partial => 'form', :locals => {:f => f} %>
<p>
<%= f.submit "Create" %> or <%= link_to 'back', @project %>
Expand Down
47 changes: 47 additions & 0 deletions app/views/tickets/_list.html.erb
@@ -1,3 +1,50 @@
<style>
form#filter {
width: 100%;
clear: both;
margin-bottom 1em;
height: 24px;
font-size: 10px;
text-align: right;
color: #999;
}
#filter h5 {
display: inline;
font-size: 10px;
}
#filter label {
margin-right: 10px;
}
#filter input[type=checkbox] {
width: 11px;
height: 11px;
}
#filter input[type=submit] {
font-size: 8px;
}
</style>

<!-- <form id="filter">
<h5>State:</h5>
<%= check_box_tag 'filter[state]', 'resolved', true, :id => 'filter_state' %>
<label for="filter_state">resolved</label>
<h5>Releases:</h5>
<% @project.releases.each do |release| %>
<%= check_box_tag "filter[release]", release.id, true, :id => "filter_release_#{release.id}" %>
<label for="filter_release_<%= release.id %>"><%= release.name %></label>
<% end %>
<%= check_box_tag "filter[release]", 'none', true, :id => "filter_release_none" %>
<label for="filter_release_none>">none</label>
<h5>Sprints:</h5>
<% Sprint.all.each do |sprint| %>
<%= check_box_tag "filter[sprint]", sprint.id, true, :id => "filter_sprint_#{sprint.id}" %>
<label for="filter_sprint_<%= sprint.id %>"><%= sprint.name %></label>
<% end %>
<%= check_box_tag "filter[sprint]", 'none', true, :id => "filter_sprint_none" %>
<label for="filter_sprint_none>">none</label>
<%= submit_tag 'update' %>
</form> -->

<table id="tickets" class="project">
<thead>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion app/views/tickets/new.html.erb
Expand Up @@ -10,7 +10,7 @@
<% form_for(@ticket) do |f| %>
<%= hidden_field_tag :project_id, @project.id %>
<%= render :partial => 'form', :locals => {:f => f} %>
<p>
<p class="buttons">
<%= f.submit "Create" %> or <%= link_to 'back', @project %>
</p>
<% end %>
Expand Down
18 changes: 18 additions & 0 deletions spec/controllers/releases_controller_spec.rb
Expand Up @@ -123,4 +123,22 @@

it_assigns :release
it_redirects_to { project_path(@release.project) }
end

describe ReleasesController, "#filter" do
before :each do
controller.params = {:filter => {:state => ['resolved'], :release => ['1'], :sprint => ['1']}}
end

it "creates a state condition from the request params" do
controller.send(:filter).should =~ /state IN \('resolved'\)/
end

it "creates a release condition from the request params" do
controller.send(:filter).should =~ /release_id IN \(1\)/
end

it "creates a release condition from the request params" do
controller.send(:filter).should =~ /sprint_id IN \(1\)/
end
end
2 changes: 0 additions & 2 deletions spec/factories/general.rb
Expand Up @@ -14,15 +14,13 @@
end

Factory.define :sprint_1, :class => Sprint do |r|
r.project {|a| a.association(:scrumtious) }
r.remote_id 2
r.name '#1'
r.start_at '2008-10-01'
r.end_at '2008-10-07'
end

Factory.define :sprint_2, :class => Sprint do |r|
r.project {|a| a.association(:scrumtious) }
r.remote_id 3
r.name '#2'
r.start_at '2008-10-08'
Expand Down
5 changes: 4 additions & 1 deletion spec/models/sprint_spec.rb
Expand Up @@ -29,9 +29,12 @@
end

describe Sprint, '#push!' do
include TicketScenarios

before do
@project = Factory :scrumtious
@sprint = Factory :sprint_1, :project => @project
@sprint = Factory :sprint_1
@sprint.stub!(:projects).and_return [@project]
end

it "delegates to the projects synchronizer" do
Expand Down
3 changes: 1 addition & 2 deletions test/integration/sprint_create_test.rb
Expand Up @@ -13,11 +13,10 @@ def test_user_creates_a_sprint

will_create_remote_milestone! @project, attributes do

visits edit_project_path(@project)
visits projects_path
clicks_link 'new sprint'

assert_difference 'Sprint.count' do
selects @release_1.name, :from => :release
fills_in :name, :with => attributes[:name]
fills_in :body, :with => attributes[:body]
clicks_button :create
Expand Down

0 comments on commit 64318b9

Please sign in to comment.