diff --git a/.gitignore b/.gitignore
index 0b625b2e..bafc8e6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
/config/configuration.yml
/config/database.yml
/config/email.yml
+/config/setup_load_paths.rb
/config/initializers/session_store.rb
/coverage
/db/*.db
diff --git a/Gemfile b/Gemfile
index 904673e4..6ec56e28 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,11 +1,14 @@
+# -*- coding: utf-8 -*-
source :rubygems
gem "rails", "2.3.14"
-gem "coderay", "~> 0.9.7"
+gem "coderay", "~> 1.0.0"
gem "i18n", "~> 0.4.2"
gem "rubytree", "~> 0.5.2", :require => 'tree'
gem "rdoc", ">= 2.4.2"
+gem "liquid", "~> 2.3.0"
+gem "acts-as-taggable-on", "= 2.1.0"
# Needed only on RUBY_VERSION = 1.8, ruby 1.9+ compatible interpreters should bring their csv
gem "fastercsv", "~> 1.5.0", :platforms => [:ruby_18, :jruby, :mingw_18]
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 0b63d0f9..66a0294b 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -19,6 +19,10 @@ class AdminController < ApplicationController
include SortHelper
+ menu_item :projects, :only => [:projects]
+ menu_item :plugins, :only => [:plugins]
+ menu_item :info, :only => [:info]
+
def index
@no_configuration_data = Redmine::DefaultData::Loader::no_data?
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 6e8dc46e..c5200d58 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -65,6 +65,9 @@ class ApplicationController < ActionController::Base
filter_parameter_logging :password
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
+ # FIXME: This doesn't work with Rails >= 3.0 anymore
+ # Possible workaround: https://github.com/rails/rails/issues/671#issuecomment-1780159
+ rescue_from ActionController::RoutingError, :with => proc{render_404}
include Redmine::Search::Controller
include Redmine::MenuManager::MenuController
@@ -75,8 +78,6 @@ class ApplicationController < ActionController::Base
end
def user_setup
- # Check the settings cache for each request
- Setting.check_cache
# Find the current user
User.current = find_current_user
end
diff --git a/app/controllers/auto_completes_controller.rb b/app/controllers/auto_completes_controller.rb
index 36fd4f2e..ad138666 100644
--- a/app/controllers/auto_completes_controller.rb
+++ b/app/controllers/auto_completes_controller.rb
@@ -13,7 +13,8 @@
#++
class AutoCompletesController < ApplicationController
- before_filter :find_project
+ before_filter :find_project, :only => :issues
+ before_filter :require_admin, :only => :projects
def issues
@issues = []
@@ -33,6 +34,38 @@ class AutoCompletesController < ApplicationController
render :layout => false
end
+ def users
+ if params[:remove_group_members].present?
+ @group = Group.find(params[:remove_group_members])
+ @removed_users = @group.users
+ end
+
+ if params[:remove_watchers].present? && params[:klass].present?
+ watcher_class = params[:klass].constantize
+ if watcher_class.included_modules.include?(Redmine::Acts::Watchable) # check class is a watching class
+ @object = watcher_class.find(params[:remove_watchers])
+ @removed_users = @object.watcher_users
+ end
+ end
+
+ @removed_users ||= []
+
+ if params[:include_groups]
+ user_finder = Principal
+ else
+ user_finder = User
+ end
+
+ @users = user_finder.active.like(params[:q]).find(:all, :limit => 100) - @removed_users
+ render :layout => false
+ end
+
+ def projects
+ @principal = Principal.find(params[:id])
+ @projects = Project.active.like(params[:q]).find(:all, :limit => 100) - @principal.projects
+ render :layout => false
+ end
+
private
def find_project
diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb
index 56bddc28..b0e35ad0 100644
--- a/app/controllers/documents_controller.rb
+++ b/app/controllers/documents_controller.rb
@@ -44,19 +44,32 @@ class DocumentsController < ApplicationController
def new
@document = @project.documents.build(params[:document])
- if request.post? and @document.save
- attachments = Attachment.attach_files(@document, params[:attachments])
- render_attachment_warning_if_needed(@document)
- flash[:notice] = l(:notice_successful_create)
- redirect_to :action => 'index', :project_id => @project
+ if request.post?
+ if User.current.allowed_to?(:add_document_watchers, @project) && params[:document]['watcher_user_ids'].present?
+ @document.watcher_user_ids = params[:document]['watcher_user_ids']
+ end
+
+ if @document.save
+ attachments = Attachment.attach_files(@document, params[:attachments])
+ render_attachment_warning_if_needed(@document)
+ flash[:notice] = l(:notice_successful_create)
+ redirect_to :action => 'index', :project_id => @project
+ end
end
end
def edit
@categories = DocumentCategory.all
- if request.post? and @document.update_attributes(params[:document])
- flash[:notice] = l(:notice_successful_update)
- redirect_to :action => 'show', :id => @document
+
+ if request.post?
+ if User.current.allowed_to?(:add_document_watchers, @project) && params[:document]['watcher_user_ids'].present?
+ @document.watcher_user_ids = params[:document]['watcher_user_ids']
+ end
+
+ if @document.update_attributes(params[:document])
+ flash[:notice] = l(:notice_successful_update)
+ redirect_to :action => 'show', :id => @document
+ end
end
end
@@ -69,7 +82,12 @@ class DocumentsController < ApplicationController
attachments = Attachment.attach_files(@document, params[:attachments])
render_attachment_warning_if_needed(@document)
- Mailer.deliver_attachments_added(attachments[:files]) if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
+ if attachments.present? && attachments[:files].present? && Setting.notified_events.include?('document_added')
+ # TODO: refactor
+ attachments.first.container.recipients.each do |recipient|
+ Mailer.deliver_attachments_added(attachments[:files], recipient)
+ end
+ end
redirect_to :action => 'show', :id => @document
end
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index 2608ae9e..8966fed9 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -42,7 +42,11 @@ class FilesController < ApplicationController
render_attachment_warning_if_needed(container)
if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
- Mailer.deliver_attachments_added(attachments[:files])
+ # TODO: refactor
+ recipients = attachments[:files].first.container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
+ recipients.each do |recipient|
+ Mailer.deliver_attachments_added(attachments[:files], recipient)
+ end
end
redirect_to project_files_path(@project)
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 6097b4cf..901b4e30 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -126,16 +126,19 @@ class GroupsController < ApplicationController
end
end
- def autocomplete_for_user
- @group = Group.find(params[:id])
- @users = User.active.not_in_group(@group).like(params[:q]).all(:limit => 100)
- render :layout => false
- end
-
def edit_membership
@group = Group.find(params[:id])
- @membership = Member.edit_membership(params[:membership_id], params[:membership], @group)
- @membership.save if request.post?
+
+ if params[:project_ids] # Multiple memberships, one per project
+ params[:project_ids].each do |project_id|
+ @membership = Member.edit_membership(params[:membership_id], (params[:membership]|| {}).merge(:project_id => project_id), @group)
+ @membership.save if request.post?
+ end
+ else # Single membership
+ @membership = Member.edit_membership(params[:membership_id], params[:membership], @group)
+ @membership.save if request.post?
+ end
+
respond_to do |format|
if @membership.valid?
format.html { redirect_to :controller => 'groups', :action => 'edit', :id => @group, :tab => 'memberships' }
diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb
index cb248971..8bf2fe3c 100644
--- a/app/controllers/journals_controller.rb
+++ b/app/controllers/journals_controller.rb
@@ -12,6 +12,8 @@
# See doc/COPYRIGHT.rdoc for more details.
#++
+require 'diff'
+
class JournalsController < ApplicationController
before_filter :find_journal, :only => [:edit, :diff]
before_filter :find_issue, :only => [:new]
@@ -84,6 +86,22 @@ class JournalsController < ApplicationController
end
end
+ def diff
+ if valid_field?(params[:field])
+ from = @journal.changes[params[:field]][0]
+ to = @journal.changes[params[:field]][1]
+
+ @diff = Redmine::Helpers::Diff.new(to, from)
+ @issue = @journal.journaled
+ respond_to do |format|
+ format.html { }
+ format.js { render :layout => false }
+ end
+ else
+ render_404
+ end
+ end
+
private
def find_journal
@@ -100,4 +118,9 @@ class JournalsController < ApplicationController
rescue ActiveRecord::RecordNotFound
render_404
end
+
+ # Is this a valid field for diff'ing?
+ def valid_field?(field)
+ field.to_s.strip == "description"
+ end
end
diff --git a/app/controllers/ldap_auth_sources_controller.rb b/app/controllers/ldap_auth_sources_controller.rb
index 71bc7f30..dc586600 100644
--- a/app/controllers/ldap_auth_sources_controller.rb
+++ b/app/controllers/ldap_auth_sources_controller.rb
@@ -14,6 +14,7 @@
class LdapAuthSourcesController < AuthSourcesController
+ menu_item :ldap_authentication, :only => [:index]
protected
def auth_source_class
diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb
index f7b50e87..39df123f 100644
--- a/app/controllers/messages_controller.rb
+++ b/app/controllers/messages_controller.rb
@@ -110,7 +110,7 @@ class MessagesController < ApplicationController
content = "#{ll(Setting.default_language, :text_user_wrote, user)}\\n> "
content << text.to_s.strip.gsub(%r{
((.|\s)*?)
}m, '[...]').gsub('"', '\"').gsub(/(\r?\n|\r\n?)/, "\\n> ") + "\\n\\n"
render(:update) { |page|
- page << "$('reply_subject').value = \"#{subject}\";"
+ page << "$('message_subject').value = \"#{subject}\";"
page.<< "$('message_content').value = \"#{content}\";"
page.show 'reply'
page << "Form.Element.focus('message_content');"
diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb
index fdfedbbd..f301c469 100644
--- a/app/controllers/queries_controller.rb
+++ b/app/controllers/queries_controller.rb
@@ -20,6 +20,7 @@ class QueriesController < ApplicationController
def new
@query = Query.new(params[:query])
@query.project = params[:query_is_for_all] ? nil : @project
+ @query.display_subprojects = params[:display_subprojects] if params[:display_subprojects].present?
@query.user = User.current
@query.is_public = false unless User.current.allowed_to?(:manage_public_queries, @project) || User.current.admin?
diff --git a/app/controllers/time_entry_reports_controller.rb b/app/controllers/time_entry_reports_controller.rb
index 18eebd41..ba9b7833 100644
--- a/app/controllers/time_entry_reports_controller.rb
+++ b/app/controllers/time_entry_reports_controller.rb
@@ -72,8 +72,7 @@ class TimeEntryReportsController < ApplicationController
@periods = []
# Date#at_beginning_of_ not supported in Rails 1.2.x
date_from = @from.to_time
- # 100 columns max
- while date_from <= @to.to_time && @periods.length < 100
+ while date_from <= @to.to_time
case @columns
when 'year'
@periods << "#{date_from.year}"
@@ -161,6 +160,9 @@ class TimeEntryReportsController < ApplicationController
@available_criterias = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id",
:klass => Project,
:label => :label_project},
+ 'status' => {:sql => "#{Issue.table_name}.status_id",
+ :klass => IssueStatus,
+ :label => :field_status},
'version' => {:sql => "#{Issue.table_name}.fixed_version_id",
:klass => Version,
:label => :label_version},
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index f4fb70d2..4dc95652 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -197,8 +197,16 @@ class UsersController < ApplicationController
def edit_membership
- @membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
- @membership.save if request.post?
+ if params[:project_ids] # Multiple memberships, one per project
+ params[:project_ids].each do |project_id|
+ @membership = Member.edit_membership(params[:membership_id], (params[:membership] || {}).merge(:project_id => project_id), @user)
+ @membership.save if request.post?
+ end
+ else # Single membership
+ @membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
+ @membership.save if request.post?
+ end
+
respond_to do |format|
if @membership.valid?
format.html { redirect_to :controller => 'users', :action => 'edit', :id => @user, :tab => 'memberships' }
diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb
index e6b4625e..8b6e414c 100644
--- a/app/controllers/watchers_controller.rb
+++ b/app/controllers/watchers_controller.rb
@@ -16,6 +16,7 @@ class WatchersController < ApplicationController
before_filter :find_project
before_filter :require_login, :check_project_privacy, :only => [:watch, :unwatch]
before_filter :authorize, :only => [:new, :destroy]
+ before_filter :authorize_access_to_object, :only => [:new, :destroy]
verify :method => :post,
:only => [ :watch, :unwatch ],
@@ -34,9 +35,12 @@ class WatchersController < ApplicationController
end
def new
- @watcher = Watcher.new(params[:watcher])
- @watcher.watchable = @watched
- @watcher.save if request.post?
+ params[:user_ids].each do |user_id|
+ @watcher = Watcher.new((params[:watcher] || {}).merge({:user_id => user_id}))
+ @watcher.watchable = @watched
+ @watcher.save if request.post?
+ end if params[:user_ids].present?
+
respond_to do |format|
format.html { redirect_to :back }
format.js do
@@ -50,7 +54,7 @@ class WatchersController < ApplicationController
end
def destroy
- @watched.set_watcher(User.find(params[:user_id]), false) if request.post?
+ @watched.set_watcher(Principal.find(params[:user_id]), false) if request.post?
respond_to do |format|
format.html { redirect_to :back }
format.js do
@@ -94,4 +98,24 @@ private
rescue ::ActionController::RedirectBackError
render :text => (watching ? 'Watcher added.' : 'Watcher removed.'), :layout => true
end
+
+ def authorize_access_to_object
+ permission = ''
+ case params[:action]
+ when 'new'
+ permission << 'add_'
+ when 'destroy'
+ permission << 'delete_'
+ end
+
+ # Ends up like: :delete_wiki_page_watchers
+ permission << "#{@watched.class.name.underscore}_watchers"
+
+ if User.current.allowed_to?(permission.to_sym, @project)
+ return true
+ else
+ deny_access
+ end
+ end
+
end
diff --git a/app/drops/base_drop.rb b/app/drops/base_drop.rb
new file mode 100644
index 00000000..5204b92a
--- /dev/null
+++ b/app/drops/base_drop.rb
@@ -0,0 +1,37 @@
+#-- encoding: UTF-8
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2012 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class BaseDrop < Liquid::Drop
+ def initialize(object)
+ @object = object unless object.respond_to?(:visible?) && !object.visible?
+ end
+
+ # Defines a Liquid method on the drop that is allowed to call the
+ # Ruby method directly. Best used for attributes.
+ #
+ # Based on Module#liquid_methods
+ def self.allowed_methods(*allowed_methods)
+ class_eval do
+ allowed_methods.each do |sym|
+ define_method sym do
+ if @object.respond_to?(:public_send)
+ @object.public_send(sym) rescue nil
+ else
+ @object.send(sym) rescue nil
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/drops/issue_drop.rb b/app/drops/issue_drop.rb
new file mode 100644
index 00000000..bdec63cd
--- /dev/null
+++ b/app/drops/issue_drop.rb
@@ -0,0 +1,79 @@
+#-- encoding: UTF-8
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2012 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class IssueDrop < BaseDrop
+ allowed_methods :id
+ allowed_methods :subject
+ allowed_methods :description
+ allowed_methods :project
+ allowed_methods :tracker
+ allowed_methods :status
+ allowed_methods :due_date
+ allowed_methods :category
+ allowed_methods :assigned_to
+ allowed_methods :priority
+ allowed_methods :fixed_version
+ allowed_methods :author
+ allowed_methods :created_on
+ allowed_methods :updated_on
+ allowed_methods :start_date
+ allowed_methods :done_ratio
+ allowed_methods :estimated_hours
+ allowed_methods :parent
+
+ def custom_field(name)
+ return '' unless name.present?
+ custom_field = IssueCustomField.find_by_name(name.strip)
+ return '' unless custom_field.present?
+ custom_value = @object.custom_value_for(custom_field)
+ if custom_value.present?
+ return custom_value.value
+ else
+ return ''
+ end
+ end
+
+ # TODO: both required, method_missing for Ruby and before_method for Liquid
+
+ # Allows accessing custom fields by their name:
+ #
+ # - issue.the_name_of_player => CustomField(:name => "The name Of Player")
+ #
+ def before_method(method_sym)
+ if custom_field_with_matching_name = has_custom_field_with_matching_name?(method_sym)
+ custom_field(custom_field_with_matching_name.name)
+ else
+ super
+ end
+ end
+
+ # Allows accessing custom fields by their name:
+ #
+ # - issue.the_name_of_player => CustomField(:name => "The name Of Player")
+ #
+ def method_missing(method_sym, *arguments, &block)
+ if custom_field_with_matching_name = has_custom_field_with_matching_name?(method_sym)
+ custom_field(custom_field_with_matching_name.name)
+ else
+ super
+ end
+ end
+
+private
+ def has_custom_field_with_matching_name?(method_sym)
+ custom_field_with_matching_name = @object.available_custom_fields.detect {|custom_field|
+ custom_field.name.downcase.underscore.gsub(' ','_') == method_sym.to_s
+ }
+ end
+end
diff --git a/app/drops/issue_status_drop.rb b/app/drops/issue_status_drop.rb
new file mode 100644
index 00000000..30d0cf85
--- /dev/null
+++ b/app/drops/issue_status_drop.rb
@@ -0,0 +1,17 @@
+#-- encoding: UTF-8
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2012 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class IssueStatusDrop < BaseDrop
+ allowed_methods :name
+end
diff --git a/app/drops/principal_drop.rb b/app/drops/principal_drop.rb
new file mode 100644
index 00000000..7751a478
--- /dev/null
+++ b/app/drops/principal_drop.rb
@@ -0,0 +1,17 @@
+#-- encoding: UTF-8
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2012 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class PrincipalDrop < BaseDrop
+ allowed_methods :name
+end
diff --git a/app/drops/project_drop.rb b/app/drops/project_drop.rb
new file mode 100644
index 00000000..9d8dd345
--- /dev/null
+++ b/app/drops/project_drop.rb
@@ -0,0 +1,17 @@
+#-- encoding: UTF-8
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2012 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class ProjectDrop < BaseDrop
+ allowed_methods :name, :identifier
+end
diff --git a/app/drops/tracker_drop.rb b/app/drops/tracker_drop.rb
new file mode 100644
index 00000000..e5671ef1
--- /dev/null
+++ b/app/drops/tracker_drop.rb
@@ -0,0 +1,17 @@
+#-- encoding: UTF-8
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2012 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class TrackerDrop < BaseDrop
+ allowed_methods :name
+end
diff --git a/app/drops/wiki_page_drop.rb b/app/drops/wiki_page_drop.rb
new file mode 100644
index 00000000..7c1fc597
--- /dev/null
+++ b/app/drops/wiki_page_drop.rb
@@ -0,0 +1,17 @@
+#-- encoding: UTF-8
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2012 the ChiliProject Team
+#
+# 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.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+class WikiPageDrop < BaseDrop
+ allowed_methods :title
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index e3573ac4..7503437c 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -16,7 +16,6 @@ require 'forwardable'
require 'cgi'
module ApplicationHelper
- include Redmine::WikiFormatting::Macros::Definitions
include Redmine::I18n
include GravatarHelper::PublicMethods
@@ -224,17 +223,15 @@ module ApplicationHelper
end
# Renders the project quick-jump box
- def render_project_jump_box
- projects = User.current.memberships.collect(&:project).compact.uniq
+ def render_project_jump_box(projects = [], html_options = {})
+ projects ||= User.current.memberships.collect(&:project).compact.uniq
if projects.any?
- s = ''
- s
+ # option_tags = content_tag :option, l(:label_jump_to_a_project), :value => ""
+ option_tags = (content_tag :option, "", :value => "" )
+ option_tags << project_tree_options_for_select(projects, :selected => @project) do |p|
+ { :value => url_for(:controller => 'projects', :action => 'show', :id => p, :jump => current_menu_item) }
+ end
+ select_tag "", option_tags, html_options.merge({ :onchange => "if (this.value != \'\') { window.location = this.value; }" })
end
end
@@ -288,7 +285,15 @@ module ApplicationHelper
def principals_check_box_tags(name, principals)
s = ''
principals.sort.each do |principal|
- s << "\n"
+ s << "\n"
+ end
+ s
+ end
+
+ def projects_check_box_tags(name, projects)
+ s = ''
+ projects.each do |project|
+ s << "\n"
end
s
end
@@ -389,7 +394,9 @@ module ApplicationHelper
end
def page_header_title
- if @project.nil? || @project.new_record?
+ if @page_header_title.present?
+ h(@page_header_title)
+ elsif @project.nil? || @project.new_record?
h(Setting.app_title)
else
b = []
@@ -429,8 +436,8 @@ module ApplicationHelper
css << 'theme-' + theme.name
end
- css << 'controller-' + params[:controller]
- css << 'action-' + params[:action]
+ css << 'controller-' + params[:controller] if params[:controller]
+ css << 'action-' + params[:action] if params[:action]
css.join(' ')
end
@@ -447,19 +454,51 @@ module ApplicationHelper
case args.size
when 1
obj = options[:object]
- text = args.shift
+ input_text = args.shift
when 2
obj = args.shift
attr = args.shift
- text = obj.send(attr).to_s
+ input_text = obj.send(attr).to_s
else
raise ArgumentError, 'invalid arguments to textilizable'
end
- return '' if text.blank?
+ return '' if input_text.blank?
project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
only_path = options.delete(:only_path) == false ? false : true
- text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr) { |macro, args| exec_macro(macro, obj, args) }
+ begin
+ text = ChiliProject::Liquid::Legacy.run_macros(input_text)
+ liquid_template = ChiliProject::Liquid::Template.parse(text)
+ liquid_variables = get_view_instance_variables_for_liquid
+ liquid_variables.merge!({'current_user' => User.current})
+ liquid_variables.merge!({'toc' => '{{toc}}'}) # Pass toc through to replace later
+ liquid_variables.merge!(ChiliProject::Liquid::Variables.all)
+
+ # Pass :view in a register so this view (with helpers) can be used inside of a tag
+ text = liquid_template.render(liquid_variables, :registers => {:view => self, :object => obj, :attribute => attr})
+
+ # Add Liquid errors to the log
+ if Rails.logger && Rails.logger.debug?
+ msg = ""
+ liquid_template.errors.each do |exception|
+ msg << "[Liquid Error] #{exception.message}\n:\n#{exception.backtrace.join("\n")}"
+ msg << "\n\n"
+ end
+ Rails.logger.debug msg
+ end
+ rescue Liquid::SyntaxError => exception
+ msg = "[Liquid Syntax Error] #{exception.message}"
+ if Rails.logger && Rails.logger.debug?
+ log_msg = "#{msg}\n"
+ log_msg << exception.backtrace.collect{ |str| " #{str}" }.join("\n")
+ log_msg << "\n\n"
+ Rails.logger.debug log_msg
+ end
+
+ # Skip Liquid if there is a syntax error
+ text = content_tag(:div, msg, :class => "flash error")
+ text << h(input_text)
+ end
@parsed_headings = []
text = parse_non_pre_blocks(text) do |text|
@@ -712,7 +751,7 @@ module ApplicationHelper
end
end
- TOC_RE = /
Code highlightment relies on CodeRay, a fast syntax highlighting library written completely in Ruby. It currently supports c, cpp, css, delphi, groovy, html, java, javascript, json, php, python, rhtml, ruby, scheme, sql, xml and yaml languages.
+
The default code highlighting relies on CodeRay, a fast syntax highlighting library written completely in Ruby. It currently supports c, cpp, css, delphi, groovy, html, java, javascript, json, php, python, rhtml, ruby, scheme, sql, xml and yaml languages.
You can highlight code in your wiki page using this syntax:
@@ -248,15 +250,14 @@ To go live, all you need to add is a database and a web server.