Added issues status changes on the activity view (initial patch by Cyril Mougel).

git-svn-id: http://redmine.rubyforge.org/svn/trunk@892 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2007-11-08 19:00:37 +00:00
parent a069c4afcf
commit fa95501fe5
9 changed files with 199 additions and 115 deletions

View File

@ -405,6 +405,7 @@ class ProjectsController < ApplicationController
if @scope.include?('issues')
@events += @project.issues.find(:all, :include => [:author, :tracker], :conditions => ["#{Issue.table_name}.created_on>=? and #{Issue.table_name}.created_on<=?", @date_from, @date_to] )
@events += @project.issues_status_changes(@date_from, @date_to)
end
if @scope.include?('news')

View File

@ -29,12 +29,19 @@ class Journal < ActiveRecord::Base
:project_key => "#{Issue.table_name}.project_id",
:date_column => "#{Issue.table_name}.created_on"
acts_as_event :title => Proc.new {|o| "#{o.issue.tracker.name} ##{o.issue.id}: #{o.issue.subject}"},
acts_as_event :title => Proc.new {|o| "#{o.issue.tracker.name} ##{o.issue.id}: #{o.issue.subject}" + ((s = o.new_status) ? " (#{s})" : '') },
:description => :notes,
:author => :user,
:url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.issue.id}}
def save
# Do not save an empty journal
(details.empty? && notes.blank?) ? false : super
end
# Returns the new status if the journal contains a status change, otherwise nil
def new_status
c = details.detect {|detail| detail.prop_key == 'status_id'}
(c && c.value) ? IssueStatus.find_by_id(c.value.to_i) : nil
end
end

View File

@ -75,7 +75,17 @@ class Project < ActiveRecord::Base
yield
end
end
# Return all issues status changes for the project between the 2 given dates
def issues_status_changes(from, to)
Journal.find(:all, :include => [:issue, :details, :user],
:conditions => ["#{Journal.table_name}.journalized_type = 'Issue'" +
" AND #{Issue.table_name}.project_id = ?" +
" AND #{JournalDetail.table_name}.prop_key = 'status_id'" +
" AND #{Journal.table_name}.created_on BETWEEN ? AND ?",
id, from, to+1])
end
# returns latest created projects
# non public projects will be returned only if user is a member of those
def self.latest(user=nil, count=5)

View File

@ -6,7 +6,7 @@
<% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| %>
<li><p><%= e.event_datetime.strftime("%H:%M") %> <%= link_to truncate(e.event_title, 100), e.event_url %><br />
<% unless e.event_description.blank? %><em><%= truncate(e.event_description, 500) %></em><br /><% end %>
<span class="author"><%= e.event_author if e.respond_to?(:author) %></span></p></li>
<span class="author"><%= e.event_author if e.respond_to?(:event_author) %></span></p></li>
<% end %>
</ul>
<% end %>

View File

@ -1,8 +1,8 @@
---
issues_001:
created_on: 2006-07-19 21:02:17 +02:00
created_on: <%= 3.days.ago.to_date.to_s(:db) %>
project_id: 1
updated_on: 2006-07-19 21:04:30 +02:00
updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
priority_id: 4
subject: Can't print recipes
id: 1
@ -55,4 +55,4 @@ issues_004:
assigned_to_id:
author_id: 2
status_id: 1

View File

@ -1,6 +1,6 @@
---
journals_001:
created_on: 2007-01-26 19:58:40 +01:00
created_on: <%= 2.days.ago.to_date.to_s(:db) %>
notes: "Journal notes"
id: 1
journalized_type: Issue

View File

@ -22,7 +22,7 @@ require 'projects_controller'
class ProjectsController; def rescue_action(e) raise e end; end
class ProjectsControllerTest < Test::Unit::TestCase
fixtures :projects, :users, :roles, :members, :issues, :enabled_modules, :enumerations
fixtures :projects, :users, :roles, :members, :issues, :journals, :journal_details, :trackers, :issue_statuses, :enabled_modules, :enumerations
def setup
@controller = ProjectsController.new
@ -93,6 +93,24 @@ class ProjectsControllerTest < Test::Unit::TestCase
assert_response :success
assert_template 'activity'
assert_not_nil assigns(:events_by_day)
assert_tag :tag => "h3",
:content => /#{2.days.ago.to_date.day}/,
:sibling => { :tag => "ul",
:child => { :tag => "li",
:child => { :tag => "p",
:content => /(#{IssueStatus.find(2).name})/,
}
}
}
assert_tag :tag => "h3",
:content => /#{3.day.ago.to_date.day}/,
:sibling => { :tag => "ul", :child => { :tag => "li",
:child => { :tag => "p",
:content => /#{Issue.find(1).subject}/,
}
}
}
end
def test_archive

39
test/unit/journal_test.rb Normal file
View File

@ -0,0 +1,39 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.dirname(__FILE__) + '/../test_helper'
class JournalTest < Test::Unit::TestCase
fixtures :issues, :issue_statuses, :journals, :journal_details
def setup
@journal = Journal.find 1
end
def test_journalized_is_an_issue
issue = @journal.issue
assert_kind_of Issue, issue
assert_equal 1, issue.id
end
def test_new_status
status = @journal.new_status
assert_not_nil status
assert_kind_of IssueStatus, status
assert_equal 2, status.id
end
end

View File

@ -1,107 +1,116 @@
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.dirname(__FILE__) + '/../test_helper'
class ProjectTest < Test::Unit::TestCase
fixtures :projects
def setup
@ecookbook = Project.find(1)
@ecookbook_sub1 = Project.find(3)
end
def test_truth
assert_kind_of Project, @ecookbook
assert_equal "eCookbook", @ecookbook.name
end
def test_update
assert_equal "eCookbook", @ecookbook.name
@ecookbook.name = "eCook"
assert @ecookbook.save, @ecookbook.errors.full_messages.join("; ")
@ecookbook.reload
assert_equal "eCook", @ecookbook.name
end
def test_validate
@ecookbook.name = ""
assert !@ecookbook.save
assert_equal 1, @ecookbook.errors.count
assert_equal "activerecord_error_blank", @ecookbook.errors.on(:name)
end
def test_public_projects
public_projects = Project.find(:all, :conditions => ["is_public=?", true])
assert_equal 3, public_projects.length
assert_equal true, public_projects[0].is_public?
end
def test_archive
user = @ecookbook.members.first.user
@ecookbook.archive
@ecookbook.reload
assert !@ecookbook.active?
assert !user.projects.include?(@ecookbook)
# Subproject are also archived
assert !@ecookbook.children.empty?
assert @ecookbook.active_children.empty?
end
def test_unarchive
user = @ecookbook.members.first.user
@ecookbook.archive
# A subproject of an archived project can not be unarchived
assert !@ecookbook_sub1.unarchive
# Unarchive project
assert @ecookbook.unarchive
@ecookbook.reload
assert @ecookbook.active?
assert user.projects.include?(@ecookbook)
# Subproject can now be unarchived
@ecookbook_sub1.reload
assert @ecookbook_sub1.unarchive
end
def test_destroy
@ecookbook.destroy
assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) }
end
def test_subproject_ok
sub = Project.find(2)
sub.parent = @ecookbook
assert sub.save
assert_equal @ecookbook.id, sub.parent.id
@ecookbook.reload
assert_equal 3, @ecookbook.children.size
end
def test_subproject_invalid
sub = Project.find(2)
sub.parent = @ecookbook_sub1
assert !sub.save
end
def test_subproject_invalid_2
sub = @ecookbook
sub.parent = Project.find(2)
assert !sub.save
end
end
# redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.dirname(__FILE__) + '/../test_helper'
class ProjectTest < Test::Unit::TestCase
fixtures :projects, :issues, :issue_statuses, :journals, :journal_details
def setup
@ecookbook = Project.find(1)
@ecookbook_sub1 = Project.find(3)
end
def test_truth
assert_kind_of Project, @ecookbook
assert_equal "eCookbook", @ecookbook.name
end
def test_update
assert_equal "eCookbook", @ecookbook.name
@ecookbook.name = "eCook"
assert @ecookbook.save, @ecookbook.errors.full_messages.join("; ")
@ecookbook.reload
assert_equal "eCook", @ecookbook.name
end
def test_validate
@ecookbook.name = ""
assert !@ecookbook.save
assert_equal 1, @ecookbook.errors.count
assert_equal "activerecord_error_blank", @ecookbook.errors.on(:name)
end
def test_public_projects
public_projects = Project.find(:all, :conditions => ["is_public=?", true])
assert_equal 3, public_projects.length
assert_equal true, public_projects[0].is_public?
end
def test_archive
user = @ecookbook.members.first.user
@ecookbook.archive
@ecookbook.reload
assert !@ecookbook.active?
assert !user.projects.include?(@ecookbook)
# Subproject are also archived
assert !@ecookbook.children.empty?
assert @ecookbook.active_children.empty?
end
def test_unarchive
user = @ecookbook.members.first.user
@ecookbook.archive
# A subproject of an archived project can not be unarchived
assert !@ecookbook_sub1.unarchive
# Unarchive project
assert @ecookbook.unarchive
@ecookbook.reload
assert @ecookbook.active?
assert user.projects.include?(@ecookbook)
# Subproject can now be unarchived
@ecookbook_sub1.reload
assert @ecookbook_sub1.unarchive
end
def test_destroy
@ecookbook.destroy
assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) }
end
def test_subproject_ok
sub = Project.find(2)
sub.parent = @ecookbook
assert sub.save
assert_equal @ecookbook.id, sub.parent.id
@ecookbook.reload
assert_equal 3, @ecookbook.children.size
end
def test_subproject_invalid
sub = Project.find(2)
sub.parent = @ecookbook_sub1
assert !sub.save
end
def test_subproject_invalid_2
sub = @ecookbook
sub.parent = Project.find(2)
assert !sub.save
end
def test_issues_status_changes
journals = @ecookbook.issues_status_changes 3.days.ago.to_date, Date.today
assert_equal 1, journals.size
assert_kind_of Journal, journals.first
journals = @ecookbook.issues_status_changes 30.days.ago.to_date, 10.days.ago.to_date
assert_equal 0, journals.size
end
end