Merge branch 'master' into plugin-hooks

Conflicts:

	lib/redmine/plugin.rb
This commit is contained in:
Eric Davis
2008-07-28 16:14:10 -07:00
79 changed files with 702 additions and 219 deletions
+11
View File
@@ -1,5 +1,6 @@
require 'redmine/access_control'
require 'redmine/menu_manager'
require 'redmine/activity'
require 'redmine/mime_type'
require 'redmine/core_ext'
require 'redmine/themes'
@@ -132,3 +133,13 @@ Redmine::MenuManager.map :project_menu do |menu|
:if => Proc.new { |p| p.repository && !p.repository.new_record? }
menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
end
Redmine::Activity.map do |activity|
activity.register :issues, :class_name => %w(Issue Journal)
activity.register :changesets
activity.register :news
activity.register :documents, :class_name => %w(Document Attachment)
activity.register :files, :class_name => 'Attachment'
activity.register :wiki_pages, :class_name => 'WikiContent::Version', :default => false
activity.register :messages, :default => false
end
+46
View File
@@ -0,0 +1,46 @@
# Redmine - project management software
# Copyright (C) 2006-2008 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.
module Redmine
module Activity
mattr_accessor :available_event_types, :default_event_types, :providers
@@available_event_types = []
@@default_event_types = []
@@providers = Hash.new {|h,k| h[k]=[] }
class << self
def map(&block)
yield self
end
# Registers an activity provider
def register(event_type, options={})
options.assert_valid_keys(:class_name, :default)
event_type = event_type.to_s
providers = options[:class_name] || event_type.classify
providers = ([] << providers) unless providers.is_a?(Array)
@@available_event_types << event_type unless @@available_event_types.include?(event_type)
@@default_event_types << event_type unless options[:default] == false
@@providers[event_type] += providers
end
end
end
end
+79
View File
@@ -0,0 +1,79 @@
# Redmine - project management software
# Copyright (C) 2006-2008 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.
module Redmine
module Activity
# Class used to retrieve activity events
class Fetcher
attr_reader :user, :project, :scope
# Needs to be unloaded in development mode
@@constantized_providers = Hash.new {|h,k| h[k] = Redmine::Activity.providers[k].collect {|t| t.constantize } }
def initialize(user, options={})
options.assert_valid_keys(:project, :with_subprojects)
@user = user
@project = options[:project]
@options = options
@scope = event_types
end
# Returns an array of available event types
def event_types
return @event_types unless @event_types.nil?
@event_types = Redmine::Activity.available_event_types
@event_types = @event_types.select {|o| @user.allowed_to?("view_#{o}".to_sym, @project)} if @project
@event_types
end
# Yields to filter the activity scope
def scope_select(&block)
@scope = @scope.select {|t| yield t }
end
# Sets the scope
def scope=(s)
@scope = s & event_types
end
# Resets the scope to the default scope
def default_scope!
@scope = Redmine::Activity.default_event_types
end
# Returns an array of events for the given date range
def events(from, to)
e = []
@scope.each do |event_type|
constantized_providers(event_type).each do |provider|
e += provider.find_events(event_type, @user, from, to, @options)
end
end
e
end
private
def constantized_providers(event_type)
@@constantized_providers[event_type]
end
end
end
end
+26
View File
@@ -128,6 +128,32 @@ module Redmine #:nodoc:
def add_hook(hook_name, method)
Redmine::Plugin::Hook::Manager.add_listener(hook_name, method)
end
# Registers an activity provider.
#
# Options:
# * <tt>:class_name</tt> - one or more model(s) that provide these events (inferred from event_type by default)
# * <tt>:default</tt> - setting this option to false will make the events not displayed by default
#
# A model can provide several activity event types.
#
# Examples:
# register :news
# register :scrums, :class_name => 'Meeting'
# register :issues, :class_name => ['Issue', 'Journal']
#
# Retrieving events:
# Associated model(s) must implement the find_events class method.
# ActiveRecord models can use acts_as_activity_provider as a way to implement this class method.
#
# The following call should return all the scrum events visible by current user that occured in the 5 last days:
# Meeting.find_events('scrums', User.current, 5.days.ago, Date.today)
# Meeting.find_events('scrums', User.current, 5.days.ago, Date.today, :project => foo) # events for project foo only
#
# Note that :view_scrums permission is required to view these events in the activity view.
def activity_provider(*args)
Redmine::Activity.register(*args)
end
# Returns +true+ if the plugin can be configured.
def configurable?
+18 -10
View File
@@ -65,10 +65,22 @@ module Redmine
# Patch to add 'table of content' support to RedCloth
def textile_p_withtoc(tag, atts, cite, content)
if tag =~ /^h(\d)$/
@toc << [$1.to_i, content]
# removes wiki links from the item
toc_item = content.gsub(/(\[\[|\]\])/, '')
# removes styles
# eg. %{color:red}Triggers% => Triggers
toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
# replaces non word caracters by dashes
anchor = toc_item.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
unless anchor.blank?
if tag =~ /^h(\d)$/
@toc << [$1.to_i, anchor, toc_item]
end
atts << " id=\"#{anchor}\""
content = content + "<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a>"
end
content = "<a name=\"#{@toc.length}\" class=\"wiki-page\"></a>" + content
textile_p(tag, atts, cite, content)
end
@@ -82,13 +94,9 @@ module Redmine
div_class << ' right' if $1 == '>'
div_class << ' left' if $1 == '<'
out = "<ul class=\"#{div_class}\">"
@toc.each_with_index do |heading, index|
# remove wiki links from the item
toc_item = heading.last.gsub(/(\[\[|\]\])/, '')
# remove styles
# eg. %{color:red}Triggers% => Triggers
toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'
out << "<li class=\"heading#{heading.first}\"><a href=\"##{index+1}\">#{toc_item}</a></li>\n"
@toc.each do |heading|
level, anchor, toc_item = heading
out << "<li class=\"heading#{level}\"><a href=\"##{anchor}\">#{toc_item}</a></li>\n"
end
out << '</ul>'
out
+6
View File
@@ -77,6 +77,12 @@ module Redmine
content_tag('dl', out)
end
desc "Displays a list of child pages."
macro :child_pages do |obj, args|
raise 'This macro applies to wiki pages only.' unless obj.is_a?(WikiContent)
render_page_hierarchy(obj.page.descendants.group_by(&:parent_id), obj.page.id)
end
desc "Include a wiki page. Example:\n\n !{{include(Foo)}}\n\nor to include a page of a specific project wiki:\n\n !{{include(projectname:Foo)}}"
macro :include do |obj, args|
project = @project