Compare commits
116 Commits
0.6.0
...
0.6-stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13ec81598b | ||
|
|
a677817003 | ||
|
|
abaeecbaa9 | ||
|
|
75d652d9e5 | ||
|
|
7e9dd78de8 | ||
|
|
bd7542cf98 | ||
|
|
a2c18b2037 | ||
|
|
eb86e5e7e1 | ||
|
|
fc26668cd9 | ||
|
|
2b42e3fc50 | ||
|
|
b4eafd9ea8 | ||
|
|
2bcd448dda | ||
|
|
1af9c47a27 | ||
|
|
ea35fff5bf | ||
|
|
124ef65c1f | ||
|
|
361c50c1f4 | ||
|
|
27d6334afa | ||
|
|
963b1283c2 | ||
|
|
777edc13c1 | ||
|
|
d1a3fbea40 | ||
|
|
58610ec52a | ||
|
|
38b185f1dc | ||
|
|
e69631f26c | ||
|
|
47f399104b | ||
|
|
86319feef2 | ||
|
|
eb7cbd481e | ||
|
|
17c7886791 | ||
|
|
48949f979a | ||
|
|
86d756d22d | ||
|
|
ab4ff48abc | ||
|
|
63ef594033 | ||
|
|
bd8eded670 | ||
|
|
d5cc40c9b6 | ||
|
|
76ed8cc200 | ||
|
|
3539bef96b | ||
|
|
e29539df9c | ||
|
|
7e9c454478 | ||
|
|
c00b8fd12e | ||
|
|
6d9490ddcc | ||
|
|
f58db70bde | ||
|
|
51adc242a3 | ||
|
|
7fae4b0892 | ||
|
|
6239e319ac | ||
|
|
60c82a03db | ||
|
|
36c0ab196c | ||
|
|
a7c2b63fb6 | ||
|
|
5e38bd9363 | ||
|
|
a79cf8d574 | ||
|
|
3c44aac1f5 | ||
|
|
355289fa67 | ||
|
|
b536f4c657 | ||
|
|
d00014221e | ||
|
|
3b4cfe0ba8 | ||
|
|
056e3703da | ||
|
|
92a23c05bb | ||
|
|
7d8af70a63 | ||
|
|
8c65cc4712 | ||
|
|
e4724c7626 | ||
|
|
6e74a06808 | ||
|
|
bc060b31ae | ||
|
|
aebcfb1eda | ||
|
|
457c9a8e72 | ||
|
|
3f2f7153a9 | ||
|
|
f5d68cf688 | ||
|
|
81ada666bb | ||
|
|
db002edabd | ||
|
|
3baf086e2d | ||
|
|
2cf11bd64e | ||
|
|
bf6e02c739 | ||
|
|
233990dac3 | ||
|
|
c383486d71 | ||
|
|
508b0bbb8e | ||
|
|
3937caeb3c | ||
|
|
f2a12d9eb5 | ||
|
|
acad206063 | ||
|
|
f80f04e379 | ||
|
|
fde4a42e2a | ||
|
|
29b3614bcb | ||
|
|
866e9e2503 | ||
|
|
c21ee95ade | ||
|
|
7704e2d919 | ||
|
|
0634591b3d | ||
|
|
5e6fa147da | ||
|
|
8d91afc33e | ||
|
|
987a5aa221 | ||
|
|
99f9aea80a | ||
|
|
deb182337d | ||
|
|
a1f3497ec4 | ||
|
|
9c9ae21771 | ||
|
|
f8aa2dc9b7 | ||
|
|
bb2de53d93 | ||
|
|
e2c606e974 | ||
|
|
9ad79612fe | ||
|
|
1469a4c8df | ||
|
|
76cdef46f2 | ||
|
|
e4ce95c3a1 | ||
|
|
4951676172 | ||
|
|
b0a8888e35 | ||
|
|
833c7bd659 | ||
|
|
5944696b6d | ||
|
|
a727f0d25a | ||
|
|
0fe5c7b3e0 | ||
|
|
843d04f0e3 | ||
|
|
8a8f819d27 | ||
|
|
a8419c1425 | ||
|
|
362364fd6f | ||
|
|
b0bb1baeaa | ||
|
|
1454a711ca | ||
|
|
fa95501fe5 | ||
|
|
a069c4afcf | ||
|
|
cc8220dde8 | ||
|
|
63ceea2e21 | ||
|
|
ad68a82be1 | ||
|
|
8509cf80f0 | ||
|
|
26a1ae4808 | ||
|
|
040cfa6ae2 |
@@ -21,7 +21,7 @@ class AccountController < ApplicationController
|
||||
include CustomFieldsHelper
|
||||
|
||||
# prevents login action to be filtered by check_if_login_required application scope filter
|
||||
skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register]
|
||||
skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register, :activate]
|
||||
|
||||
# Show user's account
|
||||
def show
|
||||
@@ -30,7 +30,7 @@ class AccountController < ApplicationController
|
||||
|
||||
# show only public projects and private projects that the logged in user is also a member of
|
||||
@memberships = @user.memberships.select do |membership|
|
||||
membership.project.is_public? || (User.current.role_for_project(membership.project))
|
||||
membership.project.is_public? || (User.current.member_of?(membership.project))
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
@@ -106,40 +106,62 @@ class AccountController < ApplicationController
|
||||
# User self-registration
|
||||
def register
|
||||
redirect_to(home_url) && return unless Setting.self_registration?
|
||||
if params[:token]
|
||||
token = Token.find_by_action_and_value("register", params[:token])
|
||||
redirect_to(home_url) && return unless token and !token.expired?
|
||||
user = token.user
|
||||
redirect_to(home_url) && return unless user.status == User::STATUS_REGISTERED
|
||||
user.status = User::STATUS_ACTIVE
|
||||
if user.save
|
||||
token.destroy
|
||||
flash[:notice] = l(:notice_account_activated)
|
||||
redirect_to :action => 'login'
|
||||
return
|
||||
end
|
||||
if request.get?
|
||||
@user = User.new(:language => Setting.default_language)
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
|
||||
else
|
||||
if request.get?
|
||||
@user = User.new(:language => Setting.default_language)
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
|
||||
else
|
||||
@user = User.new(params[:user])
|
||||
@user.admin = false
|
||||
@user.login = params[:user][:login]
|
||||
@user.status = User::STATUS_REGISTERED
|
||||
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
|
||||
@user.custom_values = @custom_values
|
||||
@user = User.new(params[:user])
|
||||
@user.admin = false
|
||||
@user.login = params[:user][:login]
|
||||
@user.status = User::STATUS_REGISTERED
|
||||
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x,
|
||||
:customized => @user,
|
||||
:value => (params["custom_fields"] ? params["custom_fields"][x.id.to_s] : nil)) }
|
||||
@user.custom_values = @custom_values
|
||||
case Setting.self_registration
|
||||
when '1'
|
||||
# Email activation
|
||||
token = Token.new(:user => @user, :action => "register")
|
||||
if @user.save and token.save
|
||||
Mailer.deliver_register(token)
|
||||
flash[:notice] = l(:notice_account_register_done)
|
||||
redirect_to :controller => 'account', :action => 'login'
|
||||
redirect_to :action => 'login'
|
||||
end
|
||||
when '3'
|
||||
# Automatic activation
|
||||
@user.status = User::STATUS_ACTIVE
|
||||
if @user.save
|
||||
flash[:notice] = l(:notice_account_activated)
|
||||
redirect_to :action => 'login'
|
||||
end
|
||||
else
|
||||
# Manual activation by the administrator
|
||||
if @user.save
|
||||
# Sends an email to the administrators
|
||||
Mailer.deliver_account_activation_request(@user)
|
||||
flash[:notice] = l(:notice_account_pending)
|
||||
redirect_to :action => 'login'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Token based account activation
|
||||
def activate
|
||||
redirect_to(home_url) && return unless Setting.self_registration? && params[:token]
|
||||
token = Token.find_by_action_and_value('register', params[:token])
|
||||
redirect_to(home_url) && return unless token and !token.expired?
|
||||
user = token.user
|
||||
redirect_to(home_url) && return unless user.status == User::STATUS_REGISTERED
|
||||
user.status = User::STATUS_ACTIVE
|
||||
if user.save
|
||||
token.destroy
|
||||
flash[:notice] = l(:notice_account_activated)
|
||||
end
|
||||
redirect_to :action => 'login'
|
||||
end
|
||||
|
||||
private
|
||||
def logged_user=(user)
|
||||
if user && user.is_a?(User)
|
||||
|
||||
@@ -48,8 +48,9 @@ class AdminController < ApplicationController
|
||||
def mail_options
|
||||
@notifiables = %w(issue_added issue_updated news_added document_added file_added message_posted)
|
||||
if request.post?
|
||||
Setting.notified_events = (params[:notified_events] || [])
|
||||
Setting.emails_footer = params[:emails_footer] if params[:emails_footer]
|
||||
settings = (params[:settings] || {}).dup.symbolize_keys
|
||||
settings[:notified_events] ||= []
|
||||
settings.each { |name, value| Setting[name] = value }
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :controller => 'admin', :action => 'mail_options'
|
||||
end
|
||||
|
||||
@@ -23,10 +23,6 @@ class ApplicationController < ActionController::Base
|
||||
require_dependency "repository/#{scm.underscore}"
|
||||
end
|
||||
|
||||
def logged_in_user
|
||||
User.current.logged? ? User.current : nil
|
||||
end
|
||||
|
||||
def current_role
|
||||
@current_role ||= User.current.role_for_project(@project)
|
||||
end
|
||||
@@ -148,6 +144,19 @@ class ApplicationController < ActionController::Base
|
||||
def accept_key_auth_actions
|
||||
self.class.read_inheritable_attribute('accept_key_auth_actions') || []
|
||||
end
|
||||
|
||||
# TODO: move to model
|
||||
def attach_files(obj, files)
|
||||
attachments = []
|
||||
if files && files.is_a?(Array)
|
||||
files.each do |file|
|
||||
next unless file.size > 0
|
||||
a = Attachment.create(:container => obj, :file => file, :author => User.current)
|
||||
attachments << a unless a.new_record?
|
||||
end
|
||||
end
|
||||
attachments
|
||||
end
|
||||
|
||||
# qvalues http header parser
|
||||
# code taken from webrick
|
||||
|
||||
@@ -32,7 +32,6 @@ class BoardsController < ApplicationController
|
||||
if @boards.size == 1
|
||||
@board = @boards.first
|
||||
show
|
||||
render :action => 'show'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,11 +41,11 @@ class BoardsController < ApplicationController
|
||||
|
||||
@topic_count = @board.topics.count
|
||||
@topic_pages = Paginator.new self, @topic_count, 25, params['page']
|
||||
@topics = @board.topics.find :all, :order => sort_clause,
|
||||
@topics = @board.topics.find :all, :order => "#{Message.table_name}.sticky DESC, #{sort_clause}",
|
||||
:include => [:author, {:last_reply => :author}],
|
||||
:limit => @topic_pages.items_per_page,
|
||||
:offset => @topic_pages.current.offset
|
||||
render :action => 'show', :layout => false if request.xhr?
|
||||
render :action => 'show', :layout => !request.xhr?
|
||||
end
|
||||
|
||||
verify :method => :post, :only => [ :destroy ], :redirect_to => { :action => :index }
|
||||
|
||||
@@ -45,7 +45,7 @@ class CustomFieldsController < ApplicationController
|
||||
end
|
||||
if request.post? and @custom_field.save
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to :action => 'list', :tab => @custom_field.type
|
||||
redirect_to :action => 'list', :tab => @custom_field.class.name
|
||||
end
|
||||
@trackers = Tracker.find(:all, :order => 'position')
|
||||
end
|
||||
@@ -57,14 +57,29 @@ class CustomFieldsController < ApplicationController
|
||||
@custom_field.trackers = params[:tracker_ids] ? Tracker.find(params[:tracker_ids]) : []
|
||||
end
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'list', :tab => @custom_field.type
|
||||
redirect_to :action => 'list', :tab => @custom_field.class.name
|
||||
end
|
||||
@trackers = Tracker.find(:all, :order => 'position')
|
||||
end
|
||||
|
||||
def move
|
||||
@custom_field = CustomField.find(params[:id])
|
||||
case params[:position]
|
||||
when 'highest'
|
||||
@custom_field.move_to_top
|
||||
when 'higher'
|
||||
@custom_field.move_higher
|
||||
when 'lower'
|
||||
@custom_field.move_lower
|
||||
when 'lowest'
|
||||
@custom_field.move_to_bottom
|
||||
end if params[:position]
|
||||
redirect_to :action => 'list', :tab => @custom_field.class.name
|
||||
end
|
||||
|
||||
def destroy
|
||||
@custom_field = CustomField.find(params[:id]).destroy
|
||||
redirect_to :action => 'list', :tab => @custom_field.type
|
||||
redirect_to :action => 'list', :tab => @custom_field.class.name
|
||||
rescue
|
||||
flash[:error] = "Unable to delete custom field"
|
||||
redirect_to :action => 'list'
|
||||
|
||||
@@ -39,20 +39,14 @@ class DocumentsController < ApplicationController
|
||||
def download
|
||||
@attachment = @document.attachments.find(params[:attachment_id])
|
||||
@attachment.increment_download
|
||||
send_file @attachment.diskfile, :filename => @attachment.filename
|
||||
send_file @attachment.diskfile, :filename => @attachment.filename, :type => @attachment.content_type
|
||||
rescue
|
||||
render_404
|
||||
end
|
||||
|
||||
def add_attachment
|
||||
# Save the attachments
|
||||
@attachments = []
|
||||
params[:attachments].each { |file|
|
||||
next unless file.size > 0
|
||||
a = Attachment.create(:container => @document, :file => file, :author => logged_in_user)
|
||||
@attachments << a unless a.new_record?
|
||||
} if params[:attachments] and params[:attachments].is_a? Array
|
||||
Mailer.deliver_attachments_added(@attachments) if !@attachments.empty? && Setting.notified_events.include?('document_added')
|
||||
attachments = attach_files(@document, params[:attachments])
|
||||
Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('document_added')
|
||||
redirect_to :action => 'show', :id => @document
|
||||
end
|
||||
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
# 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.
|
||||
|
||||
class FeedsController < ApplicationController
|
||||
before_filter :find_scope
|
||||
session :off
|
||||
|
||||
helper :issues
|
||||
include IssuesHelper
|
||||
helper :custom_fields
|
||||
include CustomFieldsHelper
|
||||
|
||||
# news feeds
|
||||
def news
|
||||
News.with_scope(:find => @find_options) do
|
||||
@news = News.find :all, :order => "#{News.table_name}.created_on DESC", :include => [ :author, :project ]
|
||||
end
|
||||
headers["Content-Type"] = "application/rss+xml"
|
||||
render :action => 'news_atom' if 'atom' == params[:format]
|
||||
end
|
||||
|
||||
# issue feeds
|
||||
def issues
|
||||
if @project && params[:query_id]
|
||||
query = Query.find(params[:query_id])
|
||||
query.executed_by = @user
|
||||
# ignore query if it's not valid
|
||||
query = nil unless query.valid?
|
||||
# override with query conditions
|
||||
@find_options[:conditions] = query.statement if query.valid? and @project == query.project
|
||||
end
|
||||
|
||||
Issue.with_scope(:find => @find_options) do
|
||||
@issues = Issue.find :all, :include => [:project, :author, :tracker, :status],
|
||||
:order => "#{Issue.table_name}.created_on DESC"
|
||||
end
|
||||
@title = (@project ? @project.name : Setting.app_title) + ": " + (query ? query.name : l(:label_reported_issues))
|
||||
headers["Content-Type"] = "application/rss+xml"
|
||||
render :action => 'issues_atom' if 'atom' == params[:format]
|
||||
end
|
||||
|
||||
# issue changes feeds
|
||||
def history
|
||||
if @project && params[:query_id]
|
||||
query = Query.find(params[:query_id])
|
||||
query.executed_by = @user
|
||||
# ignore query if it's not valid
|
||||
query = nil unless query.valid?
|
||||
# override with query conditions
|
||||
@find_options[:conditions] = query.statement if query.valid? and @project == query.project
|
||||
end
|
||||
|
||||
Journal.with_scope(:find => @find_options) do
|
||||
@journals = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ],
|
||||
:order => "#{Journal.table_name}.created_on DESC"
|
||||
end
|
||||
|
||||
@title = (@project ? @project.name : Setting.app_title) + ": " + (query ? query.name : l(:label_changes_details))
|
||||
headers["Content-Type"] = "application/rss+xml"
|
||||
render :action => 'history_atom' if 'atom' == params[:format]
|
||||
end
|
||||
|
||||
private
|
||||
# override for feeds specific authentication
|
||||
def check_if_login_required
|
||||
@user = User.find_by_rss_key(params[:key])
|
||||
render(:nothing => true, :status => 403) and return false if !@user && Setting.login_required?
|
||||
end
|
||||
|
||||
def find_scope
|
||||
if params[:project_id]
|
||||
# project feed
|
||||
# check if project is public or if the user is a member
|
||||
@project = Project.find(params[:project_id])
|
||||
render(:nothing => true, :status => 403) and return false unless @project.is_public? || (@user && @user.role_for_project(@project))
|
||||
scope = ["#{Project.table_name}.id=?", params[:project_id].to_i]
|
||||
else
|
||||
# global feed
|
||||
scope = ["#{Project.table_name}.is_public=?", true]
|
||||
end
|
||||
@find_options = {:conditions => scope, :limit => Setting.feeds_limit.to_i}
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -16,9 +16,10 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
class IssuesController < ApplicationController
|
||||
layout 'base', :except => :export_pdf
|
||||
before_filter :find_project, :authorize, :except => [:index, :preview]
|
||||
accept_key_auth :index
|
||||
layout 'base'
|
||||
before_filter :find_project, :authorize, :except => [:index, :changes, :preview]
|
||||
before_filter :find_optional_project, :only => [:index, :changes]
|
||||
accept_key_auth :index, :changes
|
||||
|
||||
cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ]
|
||||
|
||||
@@ -37,47 +38,65 @@ class IssuesController < ApplicationController
|
||||
helper :queries
|
||||
helper :sort
|
||||
include SortHelper
|
||||
include IssuesHelper
|
||||
|
||||
def index
|
||||
sort_init "#{Issue.table_name}.id", "desc"
|
||||
sort_update
|
||||
retrieve_query
|
||||
if @query.valid?
|
||||
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
|
||||
@issue_pages = Paginator.new self, @issue_count, 25, params['page']
|
||||
limit = %w(pdf csv).include?(params[:format]) ? Setting.issues_export_limit.to_i : 25
|
||||
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
|
||||
@issue_pages = Paginator.new self, @issue_count, limit, params['page']
|
||||
@issues = Issue.find :all, :order => sort_clause,
|
||||
:include => [ :assigned_to, :status, :tracker, :project, :priority, :category ],
|
||||
:include => [ :assigned_to, :status, :tracker, :project, :priority, :category, :fixed_version ],
|
||||
:conditions => @query.statement,
|
||||
:limit => @issue_pages.items_per_page,
|
||||
:offset => @issue_pages.current.offset
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html { render :layout => false if request.xhr? }
|
||||
format.atom { render_feed(@issues, :title => l(:label_issue_plural)) }
|
||||
:limit => limit,
|
||||
:offset => @issue_pages.current.offset
|
||||
respond_to do |format|
|
||||
format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
|
||||
format.atom { render_feed(@issues, :title => l(:label_issue_plural)) }
|
||||
format.csv { send_data(issues_to_csv(@issues, @project).read, :type => 'text/csv; header=present', :filename => 'export.csv') }
|
||||
format.pdf { send_data(render(:template => 'issues/index.rfpdf', :layout => false), :type => 'application/pdf', :filename => 'export.pdf') }
|
||||
end
|
||||
else
|
||||
# Send html if the query is not valid
|
||||
render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
|
||||
end
|
||||
end
|
||||
|
||||
def changes
|
||||
sort_init "#{Issue.table_name}.id", "desc"
|
||||
sort_update
|
||||
retrieve_query
|
||||
if @query.valid?
|
||||
@changes = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ],
|
||||
:conditions => @query.statement,
|
||||
:limit => 25,
|
||||
:order => "#{Journal.table_name}.created_on DESC"
|
||||
end
|
||||
@title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
|
||||
render :layout => false, :content_type => 'application/atom+xml'
|
||||
end
|
||||
|
||||
def show
|
||||
@custom_values = @issue.custom_values.find(:all, :include => :custom_field)
|
||||
@custom_values = @issue.custom_values.find(:all, :include => :custom_field, :order => "#{CustomField.table_name}.position")
|
||||
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
|
||||
|
||||
if params[:format]=='pdf'
|
||||
@options_for_rfpdf ||= {}
|
||||
@options_for_rfpdf[:file_name] = "#{@project.identifier}-#{@issue.id}.pdf"
|
||||
render :template => 'issues/show.rfpdf', :layout => false
|
||||
else
|
||||
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
|
||||
render :template => 'issues/show.rhtml'
|
||||
@status_options = @issue.status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)
|
||||
respond_to do |format|
|
||||
format.html { render :template => 'issues/show.rhtml' }
|
||||
format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@priorities = Enumeration::get_values('IPRI')
|
||||
@custom_values = []
|
||||
if request.get?
|
||||
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
|
||||
else
|
||||
begin
|
||||
@issue.init_journal(self.logged_in_user)
|
||||
@issue.init_journal(User.current)
|
||||
# Retrieve custom fields and values
|
||||
if params["custom_fields"]
|
||||
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
|
||||
@@ -97,13 +116,8 @@ class IssuesController < ApplicationController
|
||||
|
||||
def add_note
|
||||
journal = @issue.init_journal(User.current, params[:notes])
|
||||
params[:attachments].each { |file|
|
||||
next unless file.size > 0
|
||||
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
|
||||
journal.details << JournalDetail.new(:property => 'attachment',
|
||||
:prop_key => a.id,
|
||||
:value => a.filename) unless a.new_record?
|
||||
} if params[:attachments] and params[:attachments].is_a? Array
|
||||
attachments = attach_files(@issue, params[:attachments])
|
||||
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)}
|
||||
if journal.save
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
|
||||
@@ -114,25 +128,18 @@ class IssuesController < ApplicationController
|
||||
end
|
||||
|
||||
def change_status
|
||||
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
|
||||
@status_options = @issue.status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)
|
||||
@new_status = IssueStatus.find(params[:new_status_id])
|
||||
if params[:confirm]
|
||||
begin
|
||||
journal = @issue.init_journal(self.logged_in_user, params[:notes])
|
||||
journal = @issue.init_journal(User.current, params[:notes])
|
||||
@issue.status = @new_status
|
||||
if @issue.update_attributes(params[:issue])
|
||||
# Save attachments
|
||||
params[:attachments].each { |file|
|
||||
next unless file.size > 0
|
||||
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
|
||||
journal.details << JournalDetail.new(:property => 'attachment',
|
||||
:prop_key => a.id,
|
||||
:value => a.filename) unless a.new_record?
|
||||
} if params[:attachments] and params[:attachments].is_a? Array
|
||||
|
||||
attachments = attach_files(@issue, params[:attachments])
|
||||
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)}
|
||||
# Log time
|
||||
if current_role.allowed_to?(:log_time)
|
||||
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
|
||||
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
|
||||
@time_entry.attributes = params[:time_entry]
|
||||
@time_entry.save
|
||||
end
|
||||
@@ -152,13 +159,13 @@ class IssuesController < ApplicationController
|
||||
|
||||
def destroy
|
||||
@issue.destroy
|
||||
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
|
||||
redirect_to :action => 'index', :project_id => @project
|
||||
end
|
||||
|
||||
def destroy_attachment
|
||||
a = @issue.attachments.find(params[:attachment_id])
|
||||
a.destroy
|
||||
journal = @issue.init_journal(self.logged_in_user)
|
||||
journal = @issue.init_journal(User.current)
|
||||
journal.details << JournalDetail.new(:property => 'attachment',
|
||||
:prop_key => a.id,
|
||||
:old_value => a.filename)
|
||||
@@ -176,6 +183,7 @@ class IssuesController < ApplicationController
|
||||
:change_status => User.current.allowed_to?(:change_issue_status, @project),
|
||||
:add => User.current.allowed_to?(:add_issues, @project),
|
||||
:move => User.current.allowed_to?(:move_issues, @project),
|
||||
:copy => (@project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)),
|
||||
:delete => User.current.allowed_to?(:delete_issues, @project)}
|
||||
render :layout => false
|
||||
end
|
||||
@@ -195,23 +203,37 @@ private
|
||||
render_404
|
||||
end
|
||||
|
||||
def find_optional_project
|
||||
return true unless params[:project_id]
|
||||
@project = Project.find(params[:project_id])
|
||||
authorize
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
# Retrieve query from session or build a new query
|
||||
def retrieve_query
|
||||
if params[:set_filter] or !session[:query] or session[:query].project_id
|
||||
# Give it a name, required to be valid
|
||||
@query = Query.new(:name => "_", :executed_by => logged_in_user)
|
||||
if params[:fields] and params[:fields].is_a? Array
|
||||
params[:fields].each do |field|
|
||||
@query.add_filter(field, params[:operators][field], params[:values][field])
|
||||
end
|
||||
else
|
||||
@query.available_filters.keys.each do |field|
|
||||
@query.add_short_filter(field, params[field]) if params[field]
|
||||
end
|
||||
end
|
||||
if params[:query_id]
|
||||
@query = Query.find(params[:query_id], :conditions => {:project_id => (@project ? @project.id : nil)})
|
||||
session[:query] = @query
|
||||
else
|
||||
@query = session[:query]
|
||||
if params[:set_filter] or !session[:query] or session[:query].project != @project
|
||||
# Give it a name, required to be valid
|
||||
@query = Query.new(:name => "_")
|
||||
@query.project = @project
|
||||
if params[:fields] and params[:fields].is_a? Array
|
||||
params[:fields].each do |field|
|
||||
@query.add_filter(field, params[:operators][field], params[:values][field])
|
||||
end
|
||||
else
|
||||
@query.available_filters.keys.each do |field|
|
||||
@query.add_short_filter(field, params[field]) if params[field]
|
||||
end
|
||||
end
|
||||
session[:query] = @query
|
||||
else
|
||||
@query = session[:query]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,44 +17,81 @@
|
||||
|
||||
class MessagesController < ApplicationController
|
||||
layout 'base'
|
||||
before_filter :find_project, :authorize
|
||||
before_filter :find_board, :only => :new
|
||||
before_filter :find_message, :except => :new
|
||||
before_filter :authorize
|
||||
|
||||
verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show }
|
||||
|
||||
helper :attachments
|
||||
include AttachmentsHelper
|
||||
|
||||
# Show a topic and its replies
|
||||
def show
|
||||
@reply = Message.new(:subject => "RE: #{@message.subject}")
|
||||
render :action => "show", :layout => false if request.xhr?
|
||||
end
|
||||
|
||||
# Create a new topic
|
||||
def new
|
||||
@message = Message.new(params[:message])
|
||||
@message.author = logged_in_user
|
||||
@message.board = @board
|
||||
@message.author = User.current
|
||||
@message.board = @board
|
||||
if params[:message] && User.current.allowed_to?(:edit_messages, @project)
|
||||
@message.locked = params[:message]['locked']
|
||||
@message.sticky = params[:message]['sticky']
|
||||
end
|
||||
if request.post? && @message.save
|
||||
params[:attachments].each { |file|
|
||||
next unless file.size > 0
|
||||
Attachment.create(:container => @message, :file => file, :author => logged_in_user)
|
||||
} if params[:attachments] and params[:attachments].is_a? Array
|
||||
attach_files(@message, params[:attachments])
|
||||
redirect_to :action => 'show', :id => @message
|
||||
end
|
||||
end
|
||||
|
||||
# Reply to a topic
|
||||
def reply
|
||||
@reply = Message.new(params[:reply])
|
||||
@reply.author = logged_in_user
|
||||
@reply.author = User.current
|
||||
@reply.board = @board
|
||||
@message.children << @reply
|
||||
redirect_to :action => 'show', :id => @message
|
||||
@topic.children << @reply
|
||||
if !@reply.new_record?
|
||||
attach_files(@reply, params[:attachments])
|
||||
end
|
||||
redirect_to :action => 'show', :id => @topic
|
||||
end
|
||||
|
||||
# Edit a message
|
||||
def edit
|
||||
if params[:message] && User.current.allowed_to?(:edit_messages, @project)
|
||||
@message.locked = params[:message]['locked']
|
||||
@message.sticky = params[:message]['sticky']
|
||||
end
|
||||
if request.post? && @message.update_attributes(params[:message])
|
||||
attach_files(@message, params[:attachments])
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'show', :id => @topic
|
||||
end
|
||||
end
|
||||
|
||||
# Delete a messages
|
||||
def destroy
|
||||
@message.destroy
|
||||
redirect_to @message.parent.nil? ?
|
||||
{ :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } :
|
||||
{ :action => 'show', :id => @message.parent }
|
||||
end
|
||||
|
||||
private
|
||||
def find_project
|
||||
def find_message
|
||||
find_board
|
||||
@message = @board.messages.find(params[:id], :include => :parent)
|
||||
@topic = @message.root
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
def find_board
|
||||
@board = Board.find(params[:board_id], :include => :project)
|
||||
@project = @board.project
|
||||
@message = @board.topics.find(params[:id]) if params[:id]
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
@@ -44,7 +44,7 @@ class MyController < ApplicationController
|
||||
|
||||
# Show user's page
|
||||
def page
|
||||
@user = self.logged_in_user
|
||||
@user = User.current
|
||||
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
|
||||
end
|
||||
|
||||
@@ -56,6 +56,7 @@ class MyController < ApplicationController
|
||||
@user.attributes = params[:user]
|
||||
@user.mail_notification = (params[:notification_option] == 'all')
|
||||
@user.pref.attributes = params[:pref]
|
||||
@user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
|
||||
if @user.save
|
||||
@user.pref.save
|
||||
@user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
|
||||
@@ -75,7 +76,7 @@ class MyController < ApplicationController
|
||||
|
||||
# Manage user's password
|
||||
def password
|
||||
@user = self.logged_in_user
|
||||
@user = User.current
|
||||
flash[:error] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id
|
||||
if request.post?
|
||||
if @user.check_password?(params[:password])
|
||||
@@ -101,7 +102,7 @@ class MyController < ApplicationController
|
||||
|
||||
# User's page layout configuration
|
||||
def page_layout
|
||||
@user = self.logged_in_user
|
||||
@user = User.current
|
||||
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
|
||||
session[:page_layout] = @blocks
|
||||
%w(top left right).each {|f| session[:page_layout][f] ||= [] }
|
||||
@@ -115,7 +116,7 @@ class MyController < ApplicationController
|
||||
def add_block
|
||||
block = params[:block]
|
||||
render(:nothing => true) and return unless block && (BLOCKS.keys.include? block)
|
||||
@user = self.logged_in_user
|
||||
@user = User.current
|
||||
# remove if already present in a group
|
||||
%w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
|
||||
# add it on top
|
||||
@@ -150,7 +151,7 @@ class MyController < ApplicationController
|
||||
|
||||
# Save user's page layout
|
||||
def page_layout_save
|
||||
@user = self.logged_in_user
|
||||
@user = User.current
|
||||
@user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout]
|
||||
@user.pref.save
|
||||
session[:page_layout] = nil
|
||||
|
||||
@@ -17,8 +17,22 @@
|
||||
|
||||
class NewsController < ApplicationController
|
||||
layout 'base'
|
||||
before_filter :find_project, :authorize
|
||||
|
||||
before_filter :find_project, :authorize, :except => :index
|
||||
before_filter :find_optional_project, :only => :index
|
||||
accept_key_auth :index
|
||||
|
||||
def index
|
||||
@news_pages, @newss = paginate :news,
|
||||
:per_page => 10,
|
||||
:conditions => (@project ? {:project_id => @project.id} : Project.visible_by(User.current)),
|
||||
:include => [:author, :project],
|
||||
:order => "#{News.table_name}.created_on DESC"
|
||||
respond_to do |format|
|
||||
format.html { render :layout => false if request.xhr? }
|
||||
format.atom { render_feed(@newss, :title => (@project ? @project.name : Setting.app_title) + ": #{l(:label_news_plural)}") }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
@@ -31,7 +45,7 @@ class NewsController < ApplicationController
|
||||
|
||||
def add_comment
|
||||
@comment = Comment.new(params[:comment])
|
||||
@comment.author = logged_in_user
|
||||
@comment.author = User.current
|
||||
if @news.comments << @comment
|
||||
flash[:notice] = l(:label_comment_added)
|
||||
redirect_to :action => 'show', :id => @news
|
||||
@@ -47,7 +61,7 @@ class NewsController < ApplicationController
|
||||
|
||||
def destroy
|
||||
@news.destroy
|
||||
redirect_to :controller => 'projects', :action => 'list_news', :id => @project
|
||||
redirect_to :action => 'index', :project_id => @project
|
||||
end
|
||||
|
||||
private
|
||||
@@ -56,5 +70,13 @@ private
|
||||
@project = @news.project
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
end
|
||||
|
||||
def find_optional_project
|
||||
return true unless params[:project_id]
|
||||
@project = Project.find(params[:project_id])
|
||||
authorize
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'csv'
|
||||
|
||||
class ProjectsController < ApplicationController
|
||||
layout 'base'
|
||||
before_filter :find_project, :except => [ :index, :list, :add ]
|
||||
@@ -50,7 +48,7 @@ class ProjectsController < ApplicationController
|
||||
# Lists visible projects
|
||||
def list
|
||||
projects = Project.find :all,
|
||||
:conditions => Project.visible_by(logged_in_user),
|
||||
:conditions => Project.visible_by(User.current),
|
||||
:include => :parent
|
||||
@project_tree = projects.group_by {|p| p.parent || p}
|
||||
@project_tree.each_key {|p| @project_tree[p] -= [p]}
|
||||
@@ -58,15 +56,19 @@ class ProjectsController < ApplicationController
|
||||
|
||||
# Add a new project
|
||||
def add
|
||||
@custom_fields = IssueCustomField.find(:all)
|
||||
@root_projects = Project.find(:all, :conditions => "parent_id IS NULL AND status = #{Project::STATUS_ACTIVE}")
|
||||
@custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
|
||||
@trackers = Tracker.all
|
||||
@root_projects = Project.find(:all,
|
||||
:conditions => "parent_id IS NULL AND status = #{Project::STATUS_ACTIVE}",
|
||||
:order => 'name')
|
||||
@project = Project.new(params[:project])
|
||||
@project.enabled_module_names = Redmine::AccessControl.available_project_modules
|
||||
if request.get?
|
||||
@custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
|
||||
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
|
||||
@project.trackers = Tracker.all
|
||||
else
|
||||
@project.custom_fields = CustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
|
||||
@custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
|
||||
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
|
||||
@project.custom_values = @custom_values
|
||||
if @project.save
|
||||
@project.enabled_module_names = params[:enabled_modules]
|
||||
@@ -78,11 +80,11 @@ class ProjectsController < ApplicationController
|
||||
|
||||
# Show @project
|
||||
def show
|
||||
@custom_values = @project.custom_values.find(:all, :include => :custom_field)
|
||||
@custom_values = @project.custom_values.find(:all, :include => :custom_field, :order => "#{CustomField.table_name}.position")
|
||||
@members_by_role = @project.members.find(:all, :include => [:user, :role], :order => 'position').group_by {|m| m.role}
|
||||
@subprojects = @project.active_children
|
||||
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
|
||||
@trackers = Tracker.find(:all, :order => 'position')
|
||||
@trackers = @project.trackers
|
||||
@open_issues_by_tracker = Issue.count(:group => :tracker, :joins => "INNER JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{Issue.table_name}.status_id", :conditions => ["project_id=? and #{IssueStatus.table_name}.is_closed=?", @project.id, false])
|
||||
@total_issues_by_tracker = Issue.count(:group => :tracker, :conditions => ["project_id=?", @project.id])
|
||||
@total_hours = @project.time_entries.sum(:hours)
|
||||
@@ -90,11 +92,14 @@ class ProjectsController < ApplicationController
|
||||
end
|
||||
|
||||
def settings
|
||||
@root_projects = Project::find(:all, :conditions => ["parent_id IS NULL AND status = #{Project::STATUS_ACTIVE} AND id <> ?", @project.id])
|
||||
@root_projects = Project.find(:all,
|
||||
:conditions => ["parent_id IS NULL AND status = #{Project::STATUS_ACTIVE} AND id <> ?", @project.id],
|
||||
:order => 'name')
|
||||
@custom_fields = IssueCustomField.find(:all)
|
||||
@issue_category ||= IssueCategory.new
|
||||
@member ||= @project.members.new
|
||||
@custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
|
||||
@trackers = Tracker.all
|
||||
@custom_values ||= ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
|
||||
@repository ||= @project.repository
|
||||
@wiki ||= @project.wiki
|
||||
end
|
||||
@@ -104,7 +109,7 @@ class ProjectsController < ApplicationController
|
||||
if request.post?
|
||||
@project.custom_fields = IssueCustomField.find(params[:custom_field_ids]) if params[:custom_field_ids]
|
||||
if params[:custom_fields]
|
||||
@custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
|
||||
@custom_values = ProjectCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
|
||||
@project.custom_values = @custom_values
|
||||
end
|
||||
@project.attributes = params[:project]
|
||||
@@ -176,10 +181,7 @@ class ProjectsController < ApplicationController
|
||||
def add_document
|
||||
@document = @project.documents.build(params[:document])
|
||||
if request.post? and @document.save
|
||||
# Save the attachments
|
||||
params[:attachments].each { |a|
|
||||
Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
|
||||
} if params[:attachments] and params[:attachments].is_a? Array
|
||||
attach_files(@document, params[:attachments])
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
Mailer.deliver_document_added(@document) if Setting.notified_events.include?('document_added')
|
||||
redirect_to :action => 'list_documents', :id => @project
|
||||
@@ -209,7 +211,7 @@ class ProjectsController < ApplicationController
|
||||
@issue = params[:copy_from] ? Issue.new.copy_from(params[:copy_from]) : Issue.new(params[:issue])
|
||||
@issue.project = @project
|
||||
@issue.author = User.current
|
||||
@issue.tracker ||= Tracker.find(params[:tracker_id])
|
||||
@issue.tracker ||= @project.trackers.find(params[:tracker_id])
|
||||
|
||||
default_status = IssueStatus.default
|
||||
unless default_status
|
||||
@@ -218,7 +220,7 @@ class ProjectsController < ApplicationController
|
||||
return
|
||||
end
|
||||
@issue.status = default_status
|
||||
@allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker))if logged_in_user
|
||||
@allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker))
|
||||
|
||||
if request.get?
|
||||
@issue.start_date ||= Date.today
|
||||
@@ -232,124 +234,16 @@ class ProjectsController < ApplicationController
|
||||
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
|
||||
@issue.custom_values = @custom_values
|
||||
if @issue.save
|
||||
if params[:attachments] && params[:attachments].is_a?(Array)
|
||||
# Save attachments
|
||||
params[:attachments].each {|a| Attachment.create(:container => @issue, :file => a, :author => User.current) unless a.size == 0}
|
||||
end
|
||||
attach_files(@issue, params[:attachments])
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
Mailer.deliver_issue_add(@issue) if Setting.notified_events.include?('issue_added')
|
||||
redirect_to :action => 'list_issues', :id => @project
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project
|
||||
return
|
||||
end
|
||||
end
|
||||
@priorities = Enumeration::get_values('IPRI')
|
||||
end
|
||||
|
||||
# Show filtered/sorted issues list of @project
|
||||
def list_issues
|
||||
sort_init "#{Issue.table_name}.id", "desc"
|
||||
sort_update
|
||||
|
||||
retrieve_query
|
||||
|
||||
@results_per_page_options = [ 15, 25, 50, 100 ]
|
||||
if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
|
||||
@results_per_page = params[:per_page].to_i
|
||||
session[:results_per_page] = @results_per_page
|
||||
else
|
||||
@results_per_page = session[:results_per_page] || 25
|
||||
end
|
||||
|
||||
if @query.valid?
|
||||
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
|
||||
@issue_pages = Paginator.new self, @issue_count, @results_per_page, params['page']
|
||||
@issues = Issue.find :all, :order => sort_clause,
|
||||
:include => [ :assigned_to, :status, :tracker, :project, :priority, :category ],
|
||||
:conditions => @query.statement,
|
||||
:limit => @issue_pages.items_per_page,
|
||||
:offset => @issue_pages.current.offset
|
||||
end
|
||||
|
||||
render :layout => false if request.xhr?
|
||||
end
|
||||
|
||||
# Export filtered/sorted issues list to CSV
|
||||
def export_issues_csv
|
||||
sort_init "#{Issue.table_name}.id", "desc"
|
||||
sort_update
|
||||
|
||||
retrieve_query
|
||||
render :action => 'list_issues' and return unless @query.valid?
|
||||
|
||||
@issues = Issue.find :all, :order => sort_clause,
|
||||
:include => [ :assigned_to, :author, :status, :tracker, :priority, :project, {:custom_values => :custom_field} ],
|
||||
:conditions => @query.statement,
|
||||
:limit => Setting.issues_export_limit.to_i
|
||||
|
||||
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
|
||||
export = StringIO.new
|
||||
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
|
||||
# csv header fields
|
||||
headers = [ "#", l(:field_status),
|
||||
l(:field_project),
|
||||
l(:field_tracker),
|
||||
l(:field_priority),
|
||||
l(:field_subject),
|
||||
l(:field_assigned_to),
|
||||
l(:field_author),
|
||||
l(:field_start_date),
|
||||
l(:field_due_date),
|
||||
l(:field_done_ratio),
|
||||
l(:field_created_on),
|
||||
l(:field_updated_on)
|
||||
]
|
||||
for custom_field in @project.all_custom_fields
|
||||
headers << custom_field.name
|
||||
end
|
||||
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
|
||||
# csv lines
|
||||
@issues.each do |issue|
|
||||
fields = [issue.id, issue.status.name,
|
||||
issue.project.name,
|
||||
issue.tracker.name,
|
||||
issue.priority.name,
|
||||
issue.subject,
|
||||
(issue.assigned_to ? issue.assigned_to.name : ""),
|
||||
issue.author.name,
|
||||
issue.start_date ? l_date(issue.start_date) : nil,
|
||||
issue.due_date ? l_date(issue.due_date) : nil,
|
||||
issue.done_ratio,
|
||||
l_datetime(issue.created_on),
|
||||
l_datetime(issue.updated_on)
|
||||
]
|
||||
for custom_field in @project.all_custom_fields
|
||||
fields << (show_value issue.custom_value_for(custom_field))
|
||||
end
|
||||
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
|
||||
end
|
||||
end
|
||||
export.rewind
|
||||
send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
|
||||
end
|
||||
|
||||
# Export filtered/sorted issues to PDF
|
||||
def export_issues_pdf
|
||||
sort_init "#{Issue.table_name}.id", "desc"
|
||||
sort_update
|
||||
|
||||
retrieve_query
|
||||
render :action => 'list_issues' and return unless @query.valid?
|
||||
|
||||
@issues = Issue.find :all, :order => sort_clause,
|
||||
:include => [ :author, :status, :tracker, :priority, :project ],
|
||||
:conditions => @query.statement,
|
||||
:limit => Setting.issues_export_limit.to_i
|
||||
|
||||
@options_for_rfpdf ||= {}
|
||||
@options_for_rfpdf[:file_name] = "export.pdf"
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# Bulk edit issues
|
||||
def bulk_edit_issues
|
||||
if request.post?
|
||||
@@ -383,7 +277,7 @@ class ProjectsController < ApplicationController
|
||||
else
|
||||
flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, issues.size, '#' + unsaved_issue_ids.join(', #'))
|
||||
end
|
||||
redirect_to :action => 'list_issues', :id => @project
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project
|
||||
return
|
||||
end
|
||||
if current_role && User.current.allowed_to?(:change_issue_status, @project)
|
||||
@@ -399,70 +293,54 @@ class ProjectsController < ApplicationController
|
||||
|
||||
def move_issues
|
||||
@issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
|
||||
redirect_to :action => 'list_issues', :id => @project and return unless @issues
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project and return unless @issues
|
||||
|
||||
@projects = []
|
||||
# find projects to which the user is allowed to move the issue
|
||||
User.current.memberships.each {|m| @projects << m.project if m.role.allowed_to?(:controller => 'projects', :action => 'move_issues')}
|
||||
# issue can be moved to any tracker
|
||||
@trackers = Tracker.find(:all)
|
||||
if request.post? and params[:new_project_id] and params[:new_tracker_id]
|
||||
new_project = Project.find_by_id(params[:new_project_id])
|
||||
new_tracker = Tracker.find_by_id(params[:new_tracker_id])
|
||||
@issues.each do |i|
|
||||
if new_project && i.project_id != new_project.id
|
||||
# issue is moved to another project
|
||||
i.category = nil
|
||||
i.fixed_version = nil
|
||||
# delete issue relations
|
||||
i.relations_from.clear
|
||||
i.relations_to.clear
|
||||
i.project = new_project
|
||||
end
|
||||
if new_tracker
|
||||
i.tracker = new_tracker
|
||||
end
|
||||
i.save
|
||||
end
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'list_issues', :id => @project
|
||||
if User.current.admin?
|
||||
# admin is allowed to move issues to any active (visible) project
|
||||
@projects = Project.find(:all, :conditions => Project.visible_by(User.current), :order => 'name')
|
||||
else
|
||||
User.current.memberships.each {|m| @projects << m.project if m.role.allowed_to?(:move_issues)}
|
||||
end
|
||||
@target_project = @projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
|
||||
@target_project ||= @project
|
||||
@trackers = @target_project.trackers
|
||||
if request.post?
|
||||
new_tracker = params[:new_tracker_id].blank? ? nil : @target_project.trackers.find_by_id(params[:new_tracker_id])
|
||||
unsaved_issue_ids = []
|
||||
@issues.each do |issue|
|
||||
unsaved_issue_ids << issue.id unless issue.move_to(@target_project, new_tracker)
|
||||
end
|
||||
if unsaved_issue_ids.empty?
|
||||
flash[:notice] = l(:notice_successful_update) unless @issues.empty?
|
||||
else
|
||||
flash[:error] = l(:notice_failed_to_save_issues, unsaved_issue_ids.size, @issues.size, '#' + unsaved_issue_ids.join(', #'))
|
||||
end
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project
|
||||
return
|
||||
end
|
||||
render :layout => false if request.xhr?
|
||||
end
|
||||
|
||||
# Add a news to @project
|
||||
def add_news
|
||||
@news = News.new(:project => @project)
|
||||
@news = News.new(:project => @project, :author => User.current)
|
||||
if request.post?
|
||||
@news.attributes = params[:news]
|
||||
@news.author_id = self.logged_in_user.id if self.logged_in_user
|
||||
if @news.save
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
Mailer.deliver_news_added(@news) if Setting.notified_events.include?('news_added')
|
||||
redirect_to :action => 'list_news', :id => @project
|
||||
redirect_to :controller => 'news', :action => 'index', :project_id => @project
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Show news list of @project
|
||||
def list_news
|
||||
@news_pages, @newss = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "#{News.table_name}.created_on DESC"
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render :layout => false if request.xhr? }
|
||||
format.atom { render_feed(@newss, :title => "#{@project.name}: #{l(:label_news_plural)}") }
|
||||
end
|
||||
end
|
||||
|
||||
def add_file
|
||||
if request.post?
|
||||
@version = @project.versions.find_by_id(params[:version_id])
|
||||
# Save the attachments
|
||||
@attachments = []
|
||||
params[:attachments].each { |file|
|
||||
next unless file.size > 0
|
||||
a = Attachment.create(:container => @version, :file => file, :author => logged_in_user)
|
||||
@attachments << a unless a.new_record?
|
||||
} if params[:attachments] and params[:attachments].is_a? Array
|
||||
Mailer.deliver_attachments_added(@attachments) if !@attachments.empty? && Setting.notified_events.include?('file_added')
|
||||
attachments = attach_files(@version, params[:attachments])
|
||||
Mailer.deliver_attachments_added(attachments) if !attachments.empty? && Setting.notified_events.include?('file_added')
|
||||
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
|
||||
end
|
||||
@versions = @project.versions.sort
|
||||
@@ -474,13 +352,13 @@ class ProjectsController < ApplicationController
|
||||
|
||||
# Show changelog for @project
|
||||
def changelog
|
||||
@trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position')
|
||||
@trackers = @project.trackers.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position')
|
||||
retrieve_selected_tracker_ids(@trackers)
|
||||
@versions = @project.versions.sort
|
||||
end
|
||||
|
||||
def roadmap
|
||||
@trackers = Tracker.find(:all, :conditions => ["is_in_roadmap=?", true], :order => 'position')
|
||||
@trackers = @project.trackers.find(:all, :conditions => ["is_in_roadmap=?", true])
|
||||
retrieve_selected_tracker_ids(@trackers)
|
||||
@versions = @project.versions.sort
|
||||
@versions = @versions.select {|v| !v.completed? } unless params[:completed]
|
||||
@@ -507,20 +385,22 @@ class ProjectsController < ApplicationController
|
||||
@date_to = @date_from >> 1
|
||||
end
|
||||
|
||||
@event_types = %w(issues news files documents wiki_pages changesets)
|
||||
@event_types = %w(issues news files documents changesets wiki_pages messages)
|
||||
@event_types.delete('wiki_pages') unless @project.wiki
|
||||
@event_types.delete('changesets') unless @project.repository
|
||||
@event_types.delete('messages') unless @project.boards.any?
|
||||
# only show what the user is allowed to view
|
||||
@event_types = @event_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, @project)}
|
||||
|
||||
@scope = @event_types.select {|t| params["show_#{t}"]}
|
||||
# default events if none is specified in parameters
|
||||
@scope = (@event_types - %w(wiki_pages))if @scope.empty?
|
||||
@scope = (@event_types - %w(wiki_pages messages))if @scope.empty?
|
||||
|
||||
@events = []
|
||||
|
||||
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')
|
||||
@@ -550,7 +430,13 @@ class ProjectsController < ApplicationController
|
||||
end
|
||||
|
||||
if @scope.include?('changesets')
|
||||
@events += @project.repository.changesets.find(:all, :conditions => ["#{Changeset.table_name}.committed_on BETWEEN ? AND ?", @date_from, @date_to])
|
||||
@events += Changeset.find(:all, :include => :repository, :conditions => ["#{Repository.table_name}.project_id = ? AND #{Changeset.table_name}.committed_on BETWEEN ? AND ?", @project.id, @date_from, @date_to])
|
||||
end
|
||||
|
||||
if @scope.include?('messages')
|
||||
@events += Message.find(:all,
|
||||
:include => [:board, :author],
|
||||
:conditions => ["#{Board.table_name}.project_id=? AND #{Message.table_name}.parent_id IS NULL AND #{Message.table_name}.created_on BETWEEN ? AND ?", @project.id, @date_from, @date_to])
|
||||
end
|
||||
|
||||
@events_by_day = @events.group_by(&:event_date)
|
||||
@@ -659,31 +545,4 @@ private
|
||||
@selected_tracker_ids = selectable_trackers.collect {|t| t.id.to_s }
|
||||
end
|
||||
end
|
||||
|
||||
# Retrieve query from session or build a new query
|
||||
def retrieve_query
|
||||
if params[:query_id]
|
||||
@query = @project.queries.find(params[:query_id])
|
||||
@query.executed_by = logged_in_user
|
||||
session[:query] = @query
|
||||
else
|
||||
if params[:set_filter] or !session[:query] or session[:query].project_id != @project.id
|
||||
# Give it a name, required to be valid
|
||||
@query = Query.new(:name => "_", :executed_by => logged_in_user)
|
||||
@query.project = @project
|
||||
if params[:fields] and params[:fields].is_a? Array
|
||||
params[:fields].each do |field|
|
||||
@query.add_filter(field, params[:operators][field], params[:values][field])
|
||||
end
|
||||
else
|
||||
@query.available_filters.keys.each do |field|
|
||||
@query.add_short_filter(field, params[field]) if params[field]
|
||||
end
|
||||
end
|
||||
session[:query] = @query
|
||||
else
|
||||
@query = session[:query]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,14 +22,13 @@ class QueriesController < ApplicationController
|
||||
def index
|
||||
@queries = @project.queries.find(:all,
|
||||
:order => "name ASC",
|
||||
:conditions => ["is_public = ? or user_id = ?", true, (logged_in_user ? logged_in_user.id : 0)])
|
||||
:conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
|
||||
end
|
||||
|
||||
def new
|
||||
@query = Query.new(params[:query])
|
||||
@query.project = @project
|
||||
@query.user = logged_in_user
|
||||
@query.executed_by = logged_in_user
|
||||
@query.user = User.current
|
||||
@query.is_public = false unless current_role.allowed_to?(:manage_public_queries)
|
||||
@query.column_names = nil if params[:default_columns]
|
||||
|
||||
@@ -39,7 +38,7 @@ class QueriesController < ApplicationController
|
||||
|
||||
if request.post? && params[:confirm] && @query.save
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query
|
||||
return
|
||||
end
|
||||
render :layout => false if request.xhr?
|
||||
@@ -57,7 +56,7 @@ class QueriesController < ApplicationController
|
||||
|
||||
if @query.save
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => @query
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project, :query_id => @query
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -71,9 +70,8 @@ private
|
||||
def find_project
|
||||
if params[:id]
|
||||
@query = Query.find(params[:id])
|
||||
@query.executed_by = logged_in_user
|
||||
@project = @query.project
|
||||
render_403 unless @query.editable_by?(logged_in_user)
|
||||
render_403 unless @query.editable_by?(User.current)
|
||||
else
|
||||
@project = Project.find(params[:project_id])
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ class ReportsController < ApplicationController
|
||||
case params[:detail]
|
||||
when "tracker"
|
||||
@field = "tracker_id"
|
||||
@rows = Tracker.find :all, :order => 'position'
|
||||
@rows = @project.trackers
|
||||
@data = issues_by_tracker
|
||||
@report_title = l(:field_tracker)
|
||||
render :template => "reports/issue_report_details"
|
||||
@@ -60,7 +60,7 @@ class ReportsController < ApplicationController
|
||||
@report_title = l(:field_subproject)
|
||||
render :template => "reports/issue_report_details"
|
||||
else
|
||||
@trackers = Tracker.find(:all, :order => 'position')
|
||||
@trackers = @project.trackers
|
||||
@versions = @project.versions.sort
|
||||
@priorities = Enumeration::get_values('IPRI')
|
||||
@categories = @project.issue_categories
|
||||
|
||||
@@ -19,6 +19,9 @@ require 'SVG/Graph/Bar'
|
||||
require 'SVG/Graph/BarHorizontal'
|
||||
require 'digest/sha1'
|
||||
|
||||
class ChangesetNotFound < Exception
|
||||
end
|
||||
|
||||
class RepositoriesController < ApplicationController
|
||||
layout 'base'
|
||||
before_filter :find_repository, :except => :edit
|
||||
@@ -89,24 +92,44 @@ class RepositoriesController < ApplicationController
|
||||
show_error and return unless @content
|
||||
if 'raw' == params[:format]
|
||||
send_data @content, :filename => @path.split('/').last
|
||||
else
|
||||
# Prevent empty lines when displaying a file with Windows style eol
|
||||
@content.gsub!("\r\n", "\n")
|
||||
end
|
||||
end
|
||||
|
||||
def annotate
|
||||
@annotate = @repository.scm.annotate(@path, @rev)
|
||||
show_error and return if @annotate.nil? || @annotate.empty?
|
||||
end
|
||||
|
||||
def revision
|
||||
@changeset = @repository.changesets.find_by_revision(@rev)
|
||||
show_error and return unless @changeset
|
||||
raise ChangesetNotFound unless @changeset
|
||||
@changes_count = @changeset.changes.size
|
||||
@changes_pages = Paginator.new self, @changes_count, 150, params['page']
|
||||
@changes = @changeset.changes.find(:all,
|
||||
:limit => @changes_pages.items_per_page,
|
||||
:offset => @changes_pages.current.offset)
|
||||
|
||||
render :action => "revision", :layout => false if request.xhr?
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js {render :layout => false}
|
||||
end
|
||||
rescue ChangesetNotFound
|
||||
show_error
|
||||
end
|
||||
|
||||
def diff
|
||||
@rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
|
||||
@diff_type = ('sbs' == params[:type]) ? 'sbs' : 'inline'
|
||||
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
|
||||
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
|
||||
|
||||
# Save diff type as user preference
|
||||
if User.current.logged? && @diff_type != User.current.pref[:diff_type]
|
||||
User.current.pref[:diff_type] = @diff_type
|
||||
User.current.preference.save
|
||||
end
|
||||
|
||||
@cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
|
||||
unless read_fragment(@cache_key)
|
||||
|
||||
@@ -33,7 +33,8 @@ class RolesController < ApplicationController
|
||||
end
|
||||
|
||||
def new
|
||||
@role = Role.new(params[:role])
|
||||
# Prefills the form with 'Non member' role permissions
|
||||
@role = Role.new(params[:role] || {:permissions => Role.non_member.permissions})
|
||||
if request.post? && @role.save
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to :action => 'list'
|
||||
@@ -93,7 +94,7 @@ class RolesController < ApplicationController
|
||||
end
|
||||
@roles = Role.find(:all, :order => 'builtin, position')
|
||||
@trackers = Tracker.find(:all, :order => 'position')
|
||||
@statuses = IssueStatus.find(:all, :include => :workflows, :order => 'position')
|
||||
@statuses = IssueStatus.find(:all, :order => 'position')
|
||||
end
|
||||
|
||||
def report
|
||||
|
||||
@@ -31,7 +31,7 @@ class SearchController < ApplicationController
|
||||
begin; offset = params[:offset].to_time if params[:offset]; rescue; end
|
||||
|
||||
# quick jump to an issue
|
||||
if @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(logged_in_user))
|
||||
if @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(User.current))
|
||||
redirect_to :controller => "issues", :action => "show", :id => $1
|
||||
return
|
||||
end
|
||||
@@ -52,8 +52,11 @@ class SearchController < ApplicationController
|
||||
@object_types = @scope = %w(projects)
|
||||
end
|
||||
|
||||
# extract tokens from the question
|
||||
# eg. hello "bye bye" => ["hello", "bye bye"]
|
||||
@tokens = @question.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect {|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')}
|
||||
# tokens must be at least 3 character long
|
||||
@tokens = @question.split.uniq.select {|w| w.length > 2 }
|
||||
@tokens = @tokens.uniq.select {|w| w.length > 2 }
|
||||
|
||||
if !@tokens.empty?
|
||||
# no more than 5 tokens to search for
|
||||
@@ -87,13 +90,13 @@ class SearchController < ApplicationController
|
||||
end
|
||||
else
|
||||
operator = @all_words ? ' AND ' : ' OR '
|
||||
Project.with_scope(:find => {:conditions => Project.visible_by(logged_in_user)}) do
|
||||
@results += Project.find(:all, :limit => limit, :conditions => [ (["(LOWER(name) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'projects'
|
||||
end
|
||||
@results += Project.find(:all,
|
||||
:limit => limit,
|
||||
:conditions => [ (["(#{Project.visible_by(User.current)}) AND (LOWER(name) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort]
|
||||
) if @scope.include? 'projects'
|
||||
# if only one project is found, user is redirected to its overview
|
||||
redirect_to :controller => 'projects', :action => 'show', :id => @results.first and return if @results.size == 1
|
||||
end
|
||||
@question = @tokens.join(" ")
|
||||
else
|
||||
@question = ""
|
||||
end
|
||||
|
||||
@@ -54,7 +54,7 @@ class TimelogController < ApplicationController
|
||||
begin; @date_to = params[:date_to].to_date; rescue; end
|
||||
end
|
||||
@date_from ||= Date.civil(Date.today.year, 1, 1)
|
||||
@date_to ||= Date.civil(Date.today.year, Date.today.month+1, 1) - 1
|
||||
@date_to ||= (Date.civil(Date.today.year, Date.today.month, 1) >> 1) - 1
|
||||
|
||||
unless @criterias.empty?
|
||||
sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
|
||||
@@ -107,15 +107,15 @@ class TimelogController < ApplicationController
|
||||
@entries = (@issue ? @issue : @project).time_entries.find(:all, :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause)
|
||||
|
||||
@total_hours = @entries.inject(0) { |sum,entry| sum + entry.hours }
|
||||
@owner_id = logged_in_user ? logged_in_user.id : 0
|
||||
@owner_id = User.current.id
|
||||
|
||||
send_csv and return if 'csv' == params[:export]
|
||||
render :action => 'details', :layout => false if request.xhr?
|
||||
end
|
||||
|
||||
def edit
|
||||
render_404 and return if @time_entry && @time_entry.user != logged_in_user
|
||||
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
|
||||
render_404 and return if @time_entry && @time_entry.user != User.current
|
||||
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
|
||||
@time_entry.attributes = params[:time_entry]
|
||||
if request.post? and @time_entry.save
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
|
||||
@@ -37,8 +37,10 @@ class TrackersController < ApplicationController
|
||||
if request.post? and @tracker.save
|
||||
# workflow copy
|
||||
if !params[:copy_workflow_from].blank? && (copy_from = Tracker.find_by_id(params[:copy_workflow_from]))
|
||||
copy_from.workflows.each do |w|
|
||||
@tracker.workflows << w.clone
|
||||
Workflow.transaction do
|
||||
copy_from.workflows.find(:all, :include => [:role, :old_status, :new_status]).each do |w|
|
||||
Workflow.create(:tracker_id => @tracker.id, :role => w.role, :old_status => w.old_status, :new_status => w.new_status)
|
||||
end
|
||||
end
|
||||
end
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
|
||||
@@ -52,13 +52,13 @@ class UsersController < ApplicationController
|
||||
def add
|
||||
if request.get?
|
||||
@user = User.new(:language => Setting.default_language)
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
|
||||
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @user) }
|
||||
else
|
||||
@user = User.new(params[:user])
|
||||
@user.admin = params[:user][:admin] || false
|
||||
@user.login = params[:user][:login]
|
||||
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
|
||||
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => (params[:custom_fields] ? params["custom_fields"][x.id.to_s] : nil)) }
|
||||
@user.custom_values = @custom_values
|
||||
if @user.save
|
||||
Mailer.deliver_account_information(@user, params[:password]) if params[:send_information]
|
||||
@@ -72,13 +72,13 @@ class UsersController < ApplicationController
|
||||
def edit
|
||||
@user = User.find(params[:id])
|
||||
if request.get?
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
|
||||
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| @user.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
|
||||
else
|
||||
@user.admin = params[:user][:admin] if params[:user][:admin]
|
||||
@user.login = params[:user][:login] if params[:user][:login]
|
||||
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id
|
||||
if params[:custom_fields]
|
||||
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
|
||||
@custom_values = UserCustomField.find(:all, :order => "#{CustomField.table_name}.position").collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
|
||||
@user.custom_values = @custom_values
|
||||
end
|
||||
if @user.update_attributes(params[:user])
|
||||
@@ -109,12 +109,4 @@ class UsersController < ApplicationController
|
||||
end
|
||||
redirect_to :action => 'edit', :id => @user and return
|
||||
end
|
||||
|
||||
def destroy
|
||||
User.find(params[:id]).destroy
|
||||
redirect_to :action => 'list'
|
||||
rescue
|
||||
flash[:error] = "Unable to delete user"
|
||||
redirect_to :action => 'list'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,6 +21,9 @@ class VersionsController < ApplicationController
|
||||
|
||||
cache_sweeper :version_sweeper, :only => [ :edit, :destroy ]
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def edit
|
||||
if request.post? and @version.update_attributes(params[:version])
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
@@ -39,7 +42,7 @@ class VersionsController < ApplicationController
|
||||
def download
|
||||
@attachment = @version.attachments.find(params[:attachment_id])
|
||||
@attachment.increment_download
|
||||
send_file @attachment.diskfile, :filename => @attachment.filename
|
||||
send_file @attachment.diskfile, :filename => @attachment.filename, :type => @attachment.content_type
|
||||
rescue
|
||||
render_404
|
||||
end
|
||||
@@ -49,6 +52,13 @@ class VersionsController < ApplicationController
|
||||
flash[:notice] = l(:notice_successful_delete)
|
||||
redirect_to :controller => 'projects', :action => 'list_files', :id => @project
|
||||
end
|
||||
|
||||
def status_by
|
||||
respond_to do |format|
|
||||
format.html { render :action => 'show' }
|
||||
format.js { render(:update) {|page| page.replace_html 'status_by', render_issue_status_by(@version, params[:status_by])} }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def find_project
|
||||
|
||||
@@ -19,7 +19,7 @@ class WelcomeController < ApplicationController
|
||||
layout 'base'
|
||||
|
||||
def index
|
||||
@news = News.latest logged_in_user
|
||||
@projects = Project.latest logged_in_user
|
||||
@news = News.latest User.current
|
||||
@projects = Project.latest User.current
|
||||
end
|
||||
end
|
||||
|
||||
@@ -69,7 +69,7 @@ class WikiController < ApplicationController
|
||||
#@content.text = params[:content][:text]
|
||||
#@content.comments = params[:content][:comments]
|
||||
@content.attributes = params[:content]
|
||||
@content.author = logged_in_user
|
||||
@content.author = User.current
|
||||
# if page is new @page.save will also save content, but not if page isn't a new record
|
||||
if (@page.new_record? ? @page.save : @content.save)
|
||||
redirect_to :action => 'index', :id => @project, :page => @page.title
|
||||
@@ -154,11 +154,7 @@ class WikiController < ApplicationController
|
||||
|
||||
def add_attachment
|
||||
@page = @wiki.find_page(params[:page])
|
||||
# Save the attachments
|
||||
params[:attachments].each { |file|
|
||||
next unless file.size > 0
|
||||
a = Attachment.create(:container => @page, :file => file, :author => logged_in_user)
|
||||
} if params[:attachments] and params[:attachments].is_a? Array
|
||||
attach_files(@page, params[:attachments])
|
||||
redirect_to :action => 'index', :page => @page.title
|
||||
end
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class WikisController < ApplicationController
|
||||
def edit
|
||||
@wiki = @project.wiki || Wiki.new(:project => @project)
|
||||
@wiki.attributes = params[:wiki]
|
||||
@wiki.save if @request.post?
|
||||
@wiki.save if request.post?
|
||||
render(:update) {|page| page.replace_html "tab-content-wiki", :partial => 'projects/settings/wiki'}
|
||||
end
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module ApplicationHelper
|
||||
include Redmine::WikiFormatting::Macros::Definitions
|
||||
|
||||
def current_role
|
||||
@current_role ||= User.current.role_for_project(@project)
|
||||
@@ -33,7 +34,7 @@ module ApplicationHelper
|
||||
|
||||
# Display a link to user's account page
|
||||
def link_to_user(user)
|
||||
link_to user.name, :controller => 'account', :action => 'show', :id => user
|
||||
user ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
|
||||
end
|
||||
|
||||
def link_to_issue(issue)
|
||||
@@ -70,20 +71,28 @@ module ApplicationHelper
|
||||
|
||||
def format_date(date)
|
||||
return nil unless date
|
||||
@date_format ||= (Setting.date_format.to_i == 0 ? l(:general_fmt_date) : "%Y-%m-%d")
|
||||
# "Setting.date_format.size < 2" is a temporary fix (content of date_format setting changed)
|
||||
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
|
||||
date.strftime(@date_format)
|
||||
end
|
||||
|
||||
def format_time(time)
|
||||
def format_time(time, include_date = true)
|
||||
return nil unless time
|
||||
@date_format_setting ||= Setting.date_format.to_i
|
||||
time = time.to_time if time.is_a?(String)
|
||||
@date_format_setting == 0 ? l_datetime(time) : (time.strftime("%Y-%m-%d") + ' ' + l_time(time))
|
||||
zone = User.current.time_zone
|
||||
if time.utc?
|
||||
local = zone ? zone.adjust(time) : time.getlocal
|
||||
else
|
||||
local = zone ? zone.adjust(time.getutc) : time
|
||||
end
|
||||
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
|
||||
@time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
|
||||
include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
|
||||
end
|
||||
|
||||
def authoring(created, author)
|
||||
time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
|
||||
l(:label_added_time_by, author.name, time_tag)
|
||||
l(:label_added_time_by, author || 'Anonymous', time_tag)
|
||||
end
|
||||
|
||||
def day_name(day)
|
||||
@@ -130,15 +139,28 @@ module ApplicationHelper
|
||||
:preview => 'r',
|
||||
:quick_search => 'f',
|
||||
:search => '4',
|
||||
}.freeze
|
||||
}.freeze unless const_defined?(:ACCESSKEYS)
|
||||
|
||||
def accesskey(s)
|
||||
ACCESSKEYS[s]
|
||||
end
|
||||
|
||||
# format text according to system settings
|
||||
def textilizable(text, options = {})
|
||||
return "" if text.blank?
|
||||
# Formats text according to system settings.
|
||||
# 2 ways to call this method:
|
||||
# * with a String: textilizable(text, options)
|
||||
# * with an object and one of its attribute: textilizable(issue, :description, options)
|
||||
def textilizable(*args)
|
||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
case args.size
|
||||
when 1
|
||||
obj = nil
|
||||
text = args.shift || ''
|
||||
when 2
|
||||
obj = args.shift
|
||||
text = obj.send(args.shift)
|
||||
else
|
||||
raise ArgumentError, 'invalid arguments to textilizable'
|
||||
end
|
||||
|
||||
# when using an image link, try to use an attachment, if possible
|
||||
attachments = options[:attachments]
|
||||
@@ -158,7 +180,8 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
text = (Setting.text_formatting == 'textile') ?
|
||||
Redmine::WikiFormatting.to_html(text) : simple_format(auto_link(h(text)))
|
||||
Redmine::WikiFormatting.to_html(text) { |macro, args| exec_macro(macro, obj, args) } :
|
||||
simple_format(auto_link(h(text)))
|
||||
|
||||
# different methods for formatting wiki links
|
||||
case options[:wiki_links]
|
||||
@@ -208,7 +231,7 @@ module ApplicationHelper
|
||||
# example:
|
||||
# #52 -> <a href="/issues/show/52">#52</a>
|
||||
# r52 -> <a href="/repositories/revision/6?rev=52">r52</a> (project.id is 6)
|
||||
text = text.gsub(%r{([\s,-^])(#|r)(\d+)(?=[[:punct:]]|\s|<|$)}) do |m|
|
||||
text = text.gsub(%r{([\s\(,-^])(#|r)(\d+)(?=[[:punct:]]|\s|<|$)}) do |m|
|
||||
leading, otype, oid = $1, $2, $3
|
||||
link = nil
|
||||
if otype == 'r'
|
||||
@@ -276,7 +299,7 @@ module ApplicationHelper
|
||||
|
||||
def lang_options_for_select(blank=true)
|
||||
(blank ? [["(auto)", ""]] : []) +
|
||||
GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.first <=> y.first }
|
||||
GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
|
||||
end
|
||||
|
||||
def label_tag_for(name, option_tags = nil, options = {})
|
||||
@@ -296,6 +319,21 @@ module ApplicationHelper
|
||||
link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
|
||||
end
|
||||
|
||||
def progress_bar(pcts, options={})
|
||||
pcts = [pcts, pcts] unless pcts.is_a?(Array)
|
||||
pcts[1] = pcts[1] - pcts[0]
|
||||
pcts << (100 - pcts[1] - pcts[0])
|
||||
width = options[:width] || '100px;'
|
||||
legend = options[:legend] || ''
|
||||
content_tag('table',
|
||||
content_tag('tr',
|
||||
(pcts[0] > 0 ? content_tag('td', '', :width => "#{pcts[0].floor}%;", :class => 'closed') : '') +
|
||||
(pcts[1] > 0 ? content_tag('td', '', :width => "#{pcts[1].floor}%;", :class => 'done') : '') +
|
||||
(pcts[2] > 0 ? content_tag('td', '', :width => "#{pcts[2].floor}%;", :class => 'todo') : '')
|
||||
), :class => 'progress', :style => "width: #{width};") +
|
||||
content_tag('p', legend, :class => 'pourcent')
|
||||
end
|
||||
|
||||
def context_menu_link(name, url, options={})
|
||||
options[:class] ||= ''
|
||||
if options.delete(:selected)
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'csv'
|
||||
|
||||
module IssuesHelper
|
||||
include ApplicationHelper
|
||||
|
||||
def render_issue_tooltip(issue)
|
||||
@cached_label_start_date ||= l(:field_start_date)
|
||||
@@ -101,4 +104,56 @@ module IssuesHelper
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def issues_to_csv(issues, project = nil)
|
||||
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
|
||||
export = StringIO.new
|
||||
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
|
||||
# csv header fields
|
||||
headers = [ "#",
|
||||
l(:field_status),
|
||||
l(:field_project),
|
||||
l(:field_tracker),
|
||||
l(:field_priority),
|
||||
l(:field_subject),
|
||||
l(:field_assigned_to),
|
||||
l(:field_category),
|
||||
l(:field_fixed_version),
|
||||
l(:field_author),
|
||||
l(:field_start_date),
|
||||
l(:field_due_date),
|
||||
l(:field_done_ratio),
|
||||
l(:field_created_on),
|
||||
l(:field_updated_on)
|
||||
]
|
||||
# Export project custom fields if project is given
|
||||
# otherwise export custom fields marked as "For all projects"
|
||||
custom_fields = project.nil? ? IssueCustomField.for_all : project.all_custom_fields
|
||||
custom_fields.each {|f| headers << f.name}
|
||||
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
|
||||
# csv lines
|
||||
issues.each do |issue|
|
||||
fields = [issue.id,
|
||||
issue.status.name,
|
||||
issue.project.name,
|
||||
issue.tracker.name,
|
||||
issue.priority.name,
|
||||
issue.subject,
|
||||
issue.assigned_to,
|
||||
issue.category,
|
||||
issue.fixed_version,
|
||||
issue.author.name,
|
||||
format_date(issue.start_date),
|
||||
format_date(issue.due_date),
|
||||
issue.done_ratio,
|
||||
format_time(issue.created_on),
|
||||
format_time(issue.updated_on)
|
||||
]
|
||||
custom_fields.each {|f| fields << show_value(issue.custom_value_for(f)) }
|
||||
csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
|
||||
end
|
||||
end
|
||||
export.rewind
|
||||
export
|
||||
end
|
||||
end
|
||||
|
||||
@@ -179,9 +179,9 @@ module ProjectsHelper
|
||||
end
|
||||
|
||||
# today red line
|
||||
if Date.today >= @date_from and Date.today <= @date_to
|
||||
if Date.today >= date_from and Date.today <= date_to
|
||||
gc.stroke('red')
|
||||
x = (Date.today-@date_from+1)*zoom + subject_width
|
||||
x = (Date.today-date_from+1)*zoom + subject_width
|
||||
gc.line(x, headers_heigth, x, headers_heigth + g_height-1)
|
||||
end
|
||||
|
||||
@@ -190,7 +190,7 @@ module ProjectsHelper
|
||||
end if Object.const_defined?(:Magick)
|
||||
|
||||
def new_issue_selector
|
||||
trackers = Tracker.find(:all, :order => 'position')
|
||||
trackers = @project.trackers
|
||||
# can't use form tag inside helper
|
||||
content_tag('form',
|
||||
select_tag('tracker_id', '<option></option>' + options_from_collection_for_select(trackers, 'id', 'name'), :onchange => "if (this.value != '') {this.form.submit()}"),
|
||||
|
||||
@@ -22,24 +22,30 @@ module QueriesHelper
|
||||
end
|
||||
|
||||
def column_header(column)
|
||||
if column.sortable
|
||||
sort_header_tag(column.sortable, :caption => l("field_#{column.name}"))
|
||||
else
|
||||
content_tag('th', l("field_#{column.name}"))
|
||||
end
|
||||
column.sortable ? sort_header_tag(column.sortable, :caption => column.caption) : content_tag('th', column.caption)
|
||||
end
|
||||
|
||||
def column_content(column, issue)
|
||||
value = issue.send(column.name)
|
||||
if value.is_a?(Date)
|
||||
format_date(value)
|
||||
elsif value.is_a?(Time)
|
||||
format_time(value)
|
||||
elsif column.name == :subject
|
||||
((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') +
|
||||
link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
|
||||
if column.is_a?(QueryCustomFieldColumn)
|
||||
cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
|
||||
show_value(cv)
|
||||
else
|
||||
h(value)
|
||||
value = issue.send(column.name)
|
||||
if value.is_a?(Date)
|
||||
format_date(value)
|
||||
elsif value.is_a?(Time)
|
||||
format_time(value)
|
||||
else
|
||||
case column.name
|
||||
when :subject
|
||||
h((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') +
|
||||
link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
|
||||
when :done_ratio
|
||||
progress_bar(value, :width => '80px')
|
||||
else
|
||||
h(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,7 +62,10 @@ module RepositoriesHelper
|
||||
content_tag('p', form.text_field(:url, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) +
|
||||
'<br />(http://, https://, svn://, file:///)') +
|
||||
content_tag('p', form.text_field(:login, :size => 30)) +
|
||||
content_tag('p', form.password_field(:password, :size => 30))
|
||||
content_tag('p', form.password_field(:password, :size => 30, :name => 'ignore',
|
||||
:value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)),
|
||||
:onfocus => "this.value=''; this.name='repository[password]';",
|
||||
:onchange => "this.name='repository[password]';"))
|
||||
end
|
||||
|
||||
def darcs_field_tags(form, repository)
|
||||
@@ -77,4 +80,8 @@ module RepositoriesHelper
|
||||
content_tag('p', form.text_field(:root_url, :label => 'CVSROOT', :size => 60, :required => true, :disabled => !repository.new_record?)) +
|
||||
content_tag('p', form.text_field(:url, :label => 'Module', :size => 30, :required => true, :disabled => !repository.new_record?))
|
||||
end
|
||||
|
||||
def bazaar_field_tags(form, repository)
|
||||
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.new_record?)))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,4 +16,32 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
module VersionsHelper
|
||||
|
||||
STATUS_BY_CRITERIAS = %w(category tracker priority author assigned_to)
|
||||
|
||||
def render_issue_status_by(version, criteria)
|
||||
criteria ||= 'category'
|
||||
raise 'Unknown criteria' unless STATUS_BY_CRITERIAS.include?(criteria)
|
||||
|
||||
h = Hash.new {|k,v| k[v] = [0, 0]}
|
||||
begin
|
||||
# Total issue count
|
||||
Issue.count(:group => criteria,
|
||||
:conditions => ["#{Issue.table_name}.fixed_version_id = ?", version.id]).each {|c,s| h[c][0] = s}
|
||||
# Open issues count
|
||||
Issue.count(:group => criteria,
|
||||
:include => :status,
|
||||
:conditions => ["#{Issue.table_name}.fixed_version_id = ? AND #{IssueStatus.table_name}.is_closed = ?", version.id, false]).each {|c,s| h[c][1] = s}
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
# When grouping by an association, Rails throws this exception if there's no result (bug)
|
||||
end
|
||||
counts = h.keys.compact.sort.collect {|k| {:group => k, :total => h[k][0], :open => h[k][1], :closed => (h[k][0] - h[k][1])}}
|
||||
max = counts.collect {|c| c[:total]}.max
|
||||
|
||||
render :partial => 'issue_counts', :locals => {:version => version, :criteria => criteria, :counts => counts, :max => max}
|
||||
end
|
||||
|
||||
def status_by_options_for_select(value)
|
||||
options_for_select(STATUS_BY_CRITERIAS.collect {|criteria| [l("field_#{criteria}".to_sym), criteria]}, value)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ class Attachment < ActiveRecord::Base
|
||||
belongs_to :container, :polymorphic => true
|
||||
belongs_to :author, :class_name => "User", :foreign_key => "author_id"
|
||||
|
||||
validates_presence_of :container, :filename
|
||||
validates_presence_of :container, :filename, :author
|
||||
validates_length_of :filename, :maximum => 255
|
||||
validates_length_of :disk_filename, :maximum => 255
|
||||
|
||||
@@ -82,14 +82,9 @@ class Attachment < ActiveRecord::Base
|
||||
def increment_download
|
||||
increment!(:downloads)
|
||||
end
|
||||
|
||||
# returns last created projects
|
||||
def self.most_downloaded
|
||||
find(:all, :limit => 5, :order => "downloads DESC")
|
||||
end
|
||||
|
||||
def project
|
||||
container.is_a?(Project) ? container : container.project
|
||||
container.project
|
||||
end
|
||||
|
||||
def image?
|
||||
|
||||
@@ -20,6 +20,10 @@ class AuthSource < ActiveRecord::Base
|
||||
|
||||
validates_presence_of :name
|
||||
validates_uniqueness_of :name
|
||||
validates_length_of :name, :host, :maximum => 60
|
||||
validates_length_of :account_password, :maximum => 60, :allow_nil => true
|
||||
validates_length_of :account, :base_dn, :maximum => 255
|
||||
validates_length_of :attr_login, :attr_firstname, :attr_lastname, :attr_mail, :maximum => 30
|
||||
|
||||
def authenticate(login, password)
|
||||
end
|
||||
|
||||
@@ -27,6 +27,7 @@ class AuthSourceLdap < AuthSource
|
||||
end
|
||||
|
||||
def authenticate(login, password)
|
||||
return nil if login.blank? || password.blank?
|
||||
attrs = []
|
||||
# get user's DN
|
||||
ldap_con = initialize_ldap_con(self.account, self.account_password)
|
||||
|
||||
@@ -63,6 +63,14 @@ class Changeset < ActiveRecord::Base
|
||||
return if kw_regexp.blank?
|
||||
|
||||
referenced_issues = []
|
||||
|
||||
if ref_keywords.delete('*')
|
||||
# find any issue ID in the comments
|
||||
target_issue_ids = []
|
||||
comments.scan(%r{([\s\(,-^])#(\d+)(?=[[:punct:]]|\s|<|$)}).each { |m| target_issue_ids << m[1] }
|
||||
referenced_issues += repository.project.issues.find_all_by_id(target_issue_ids)
|
||||
end
|
||||
|
||||
comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
|
||||
action = match[0]
|
||||
target_issue_ids = match[1].scan(/\d+/)
|
||||
@@ -80,6 +88,17 @@ class Changeset < ActiveRecord::Base
|
||||
end
|
||||
referenced_issues += target_issues
|
||||
end
|
||||
|
||||
self.issues = referenced_issues.uniq
|
||||
end
|
||||
|
||||
# Returns the previous changeset
|
||||
def previous
|
||||
@previous ||= Changeset.find(:first, :conditions => ['revision < ? AND repository_id = ?', self.revision, self.repository_id], :order => 'revision DESC')
|
||||
end
|
||||
|
||||
# Returns the next changeset
|
||||
def next
|
||||
@next ||= Changeset.find(:first, :conditions => ['revision > ? AND repository_id = ?', self.revision, self.repository_id], :order => 'revision ASC')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
class CustomField < ActiveRecord::Base
|
||||
has_many :custom_values, :dependent => :delete_all
|
||||
acts_as_list :scope => 'type = \'#{self.class}\''
|
||||
serialize :possible_values
|
||||
|
||||
FIELD_FORMATS = { "string" => { :name => :label_string, :order => 1 },
|
||||
@@ -42,6 +43,9 @@ class CustomField < ActiveRecord::Base
|
||||
def before_validation
|
||||
# remove empty values
|
||||
self.possible_values = self.possible_values.collect{|v| v unless v.empty?}.compact
|
||||
# make sure these fields are not searchable
|
||||
self.searchable = false if %w(int float date bool).include?(field_format)
|
||||
true
|
||||
end
|
||||
|
||||
def validate
|
||||
@@ -51,6 +55,10 @@ class CustomField < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def <=>(field)
|
||||
position <=> field.position
|
||||
end
|
||||
|
||||
# to move in project_custom_field
|
||||
def self.for_all
|
||||
find(:all, :conditions => ["is_for_all=?", true])
|
||||
|
||||
@@ -31,9 +31,9 @@ protected
|
||||
when 'float'
|
||||
begin; !value.blank? && Kernel.Float(value); rescue; errors.add(:value, :activerecord_error_invalid) end
|
||||
when 'date'
|
||||
errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.empty?
|
||||
errors.add(:value, :activerecord_error_not_a_date) unless value =~ /^\d{4}-\d{2}-\d{2}$/ or value.blank?
|
||||
when 'list'
|
||||
errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include? value or value.empty?
|
||||
errors.add(:value, :activerecord_error_inclusion) unless custom_field.possible_values.include?(value) or value.blank?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,6 +22,7 @@ class Document < ActiveRecord::Base
|
||||
|
||||
acts_as_searchable :columns => ['title', 'description']
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_document)}: #{o.title}"},
|
||||
:author => Proc.new {|o| (a = o.attachments.find(:first, :order => "#{Attachment.table_name}.created_on ASC")) ? a.author : nil },
|
||||
:url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}}
|
||||
|
||||
validates_presence_of :project, :title, :category
|
||||
|
||||
@@ -40,7 +40,7 @@ class Issue < ActiveRecord::Base
|
||||
acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"},
|
||||
:url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}
|
||||
|
||||
validates_presence_of :subject, :description, :priority, :tracker, :author, :status
|
||||
validates_presence_of :subject, :description, :priority, :project, :tracker, :author, :status
|
||||
validates_length_of :subject, :maximum => 255
|
||||
validates_inclusion_of :done_ratio, :in => 0..100
|
||||
validates_numericality_of :estimated_hours, :allow_nil => true
|
||||
@@ -61,6 +61,32 @@ class Issue < ActiveRecord::Base
|
||||
self
|
||||
end
|
||||
|
||||
# Move an issue to a new project and tracker
|
||||
def move_to(new_project, new_tracker = nil)
|
||||
transaction do
|
||||
if new_project && project_id != new_project.id
|
||||
# delete issue relations
|
||||
self.relations_from.clear
|
||||
self.relations_to.clear
|
||||
# issue is moved to another project
|
||||
self.category = nil
|
||||
self.fixed_version = nil
|
||||
self.project = new_project
|
||||
end
|
||||
if new_tracker
|
||||
self.tracker = new_tracker
|
||||
end
|
||||
if save
|
||||
# Manually update project_id on related time entries
|
||||
TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
|
||||
else
|
||||
rollback_db_transaction
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def priority_id=(pid)
|
||||
self.priority = nil
|
||||
write_attribute(:priority_id, pid)
|
||||
@@ -80,6 +106,10 @@ class Issue < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def validate_on_create
|
||||
errors.add :tracker_id, :activerecord_error_invalid unless project.trackers.include?(tracker)
|
||||
end
|
||||
|
||||
def before_create
|
||||
# default assignment based on category
|
||||
if assigned_to.nil? && category && category.assigned_to
|
||||
|
||||
@@ -35,5 +35,9 @@ class IssueCategory < ActiveRecord::Base
|
||||
destroy_without_reassign
|
||||
end
|
||||
|
||||
def <=>(category)
|
||||
name <=> category.name
|
||||
end
|
||||
|
||||
def to_s; name end
|
||||
end
|
||||
|
||||
@@ -29,8 +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}" + ((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
|
||||
|
||||
@@ -88,6 +88,14 @@ class Mailer < ActionMailer::Base
|
||||
:password => password,
|
||||
:login_url => url_for(:controller => 'account', :action => 'login')
|
||||
end
|
||||
|
||||
def account_activation_request(user)
|
||||
# Send the email to all active administrators
|
||||
recipients User.find_active(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
|
||||
subject l(:mail_subject_account_activation_request)
|
||||
body :user => user,
|
||||
:url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
|
||||
end
|
||||
|
||||
def lost_password(token)
|
||||
set_language_if_valid(token.user.language)
|
||||
@@ -102,7 +110,7 @@ class Mailer < ActionMailer::Base
|
||||
recipients token.user.mail
|
||||
subject l(:mail_subject_register)
|
||||
body :token => token,
|
||||
:url => url_for(:controller => 'account', :action => 'register', :token => token.value)
|
||||
:url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
|
||||
end
|
||||
|
||||
def test(user)
|
||||
@@ -121,10 +129,32 @@ class Mailer < ActionMailer::Base
|
||||
default_url_options[:protocol] = Setting.protocol
|
||||
end
|
||||
|
||||
# Overrides the create_mail method
|
||||
def create_mail
|
||||
# Removes the current user from the recipients and cc
|
||||
# if he doesn't want to receive notifications about what he does
|
||||
if User.current.pref[:no_self_notified]
|
||||
recipients.delete(User.current.mail) if recipients
|
||||
cc.delete(User.current.mail) if cc
|
||||
end
|
||||
# Blind carbon copy recipients
|
||||
if Setting.bcc_recipients?
|
||||
bcc([recipients, cc].flatten.compact.uniq)
|
||||
recipients []
|
||||
cc []
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
# Renders a message with the corresponding layout
|
||||
def render_message(method_name, body)
|
||||
layout = method_name.match(%r{text\.html\.(rhtml|rxml)}) ? 'layout.text.html.rhtml' : 'layout.text.plain.rhtml'
|
||||
body[:content_for_layout] = render(:file => method_name, :body => body)
|
||||
ActionView::Base.new(File.join(template_root, 'mailer'), body, self).render(:file => layout)
|
||||
ActionView::Base.new(template_root, body, self).render(:file => "mailer/#{layout}")
|
||||
end
|
||||
|
||||
# Makes partial rendering work with Rails 1.2 (retro-compatibility)
|
||||
def self.controller_path
|
||||
''
|
||||
end unless respond_to?('controller_path')
|
||||
end
|
||||
|
||||
@@ -30,9 +30,15 @@ class Message < ActiveRecord::Base
|
||||
:description => :content,
|
||||
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id, :id => o.id}}
|
||||
|
||||
attr_protected :locked, :sticky
|
||||
validates_presence_of :subject, :content
|
||||
validates_length_of :subject, :maximum => 255
|
||||
|
||||
def validate_on_create
|
||||
# Can not reply to a locked topic
|
||||
errors.add_to_base 'Topic is locked' if root.locked?
|
||||
end
|
||||
|
||||
def after_create
|
||||
board.update_attribute(:last_message_id, self.id)
|
||||
board.increment! :messages_count
|
||||
@@ -43,6 +49,18 @@ class Message < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def after_destroy
|
||||
# The following line is required so that the previous counter
|
||||
# updates (due to children removal) are not overwritten
|
||||
board.reload
|
||||
board.decrement! :messages_count
|
||||
board.decrement! :topics_count unless parent
|
||||
end
|
||||
|
||||
def sticky?
|
||||
sticky == 1
|
||||
end
|
||||
|
||||
def project
|
||||
board.project
|
||||
end
|
||||
|
||||
@@ -20,10 +20,11 @@ class Project < ActiveRecord::Base
|
||||
STATUS_ACTIVE = 1
|
||||
STATUS_ARCHIVED = 9
|
||||
|
||||
has_many :members, :dependent => :delete_all, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
|
||||
has_many :members, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
|
||||
has_many :users, :through => :members
|
||||
has_many :custom_values, :dependent => :delete_all, :as => :customized
|
||||
has_many :enabled_modules, :dependent => :delete_all
|
||||
has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
|
||||
has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker]
|
||||
has_many :issue_changes, :through => :issues, :source => :journals
|
||||
has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
|
||||
@@ -36,7 +37,13 @@ class Project < ActiveRecord::Base
|
||||
has_one :repository, :dependent => :destroy
|
||||
has_many :changesets, :through => :repository
|
||||
has_one :wiki, :dependent => :destroy
|
||||
has_and_belongs_to_many :custom_fields, :class_name => 'IssueCustomField', :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", :association_foreign_key => 'custom_field_id'
|
||||
# Custom field for the project issues
|
||||
has_and_belongs_to_many :custom_fields,
|
||||
:class_name => 'IssueCustomField',
|
||||
:order => "#{CustomField.table_name}.position",
|
||||
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
|
||||
:association_foreign_key => 'custom_field_id'
|
||||
|
||||
acts_as_tree :order => "name", :counter_cache => true
|
||||
|
||||
acts_as_searchable :columns => ['name', 'description'], :project_key => 'id'
|
||||
@@ -50,12 +57,13 @@ class Project < ActiveRecord::Base
|
||||
validates_associated :custom_values, :on => :update
|
||||
validates_associated :repository, :wiki
|
||||
validates_length_of :name, :maximum => 30
|
||||
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
|
||||
validates_length_of :description, :maximum => 255
|
||||
validates_length_of :homepage, :maximum => 60
|
||||
validates_length_of :identifier, :in => 3..12
|
||||
validates_length_of :identifier, :in => 3..20
|
||||
validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
|
||||
|
||||
before_destroy :delete_all_members
|
||||
|
||||
def identifier=(identifier)
|
||||
super unless identifier_frozen?
|
||||
end
|
||||
@@ -71,11 +79,22 @@ class Project < ActiveRecord::Base
|
||||
conditions = ["#{Issue.table_name}.project_id IN (#{ids.join(',')})"]
|
||||
end
|
||||
conditions ||= ["#{Issue.table_name}.project_id = ?", id]
|
||||
Issue.with_scope :find => { :conditions => conditions } do
|
||||
# Quick and dirty fix for Rails 2 compatibility
|
||||
Issue.send(:with_scope, :find => { :conditions => conditions }) do
|
||||
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)
|
||||
@@ -113,9 +132,14 @@ class Project < ActiveRecord::Base
|
||||
children.select {|child| child.active?}
|
||||
end
|
||||
|
||||
# Deletes all project's members
|
||||
def delete_all_members
|
||||
Member.delete_all(['project_id = ?', id])
|
||||
end
|
||||
|
||||
# Users issues can be assigned to
|
||||
def assignable_users
|
||||
members.select {|m| m.role.assignable?}.collect {|m| m.user}
|
||||
members.select {|m| m.role.assignable?}.collect {|m| m.user}.sort
|
||||
end
|
||||
|
||||
# Returns the mail adresses of users that should be always notified on project events
|
||||
@@ -134,7 +158,7 @@ class Project < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def <=>(project)
|
||||
name <=> project.name
|
||||
name.downcase <=> project.name.downcase
|
||||
end
|
||||
|
||||
def allows_to?(action)
|
||||
|
||||
@@ -17,13 +17,34 @@
|
||||
|
||||
class QueryColumn
|
||||
attr_accessor :name, :sortable
|
||||
include GLoc
|
||||
|
||||
def initialize(name, options={})
|
||||
self.name = name
|
||||
self.sortable = options[:sortable]
|
||||
end
|
||||
|
||||
def default?; default end
|
||||
def caption
|
||||
set_language_if_valid(User.current.language)
|
||||
l("field_#{name}")
|
||||
end
|
||||
end
|
||||
|
||||
class QueryCustomFieldColumn < QueryColumn
|
||||
|
||||
def initialize(custom_field)
|
||||
self.name = "cf_#{custom_field.id}".to_sym
|
||||
self.sortable = false
|
||||
@cf = custom_field
|
||||
end
|
||||
|
||||
def caption
|
||||
@cf.name
|
||||
end
|
||||
|
||||
def custom_field
|
||||
@cf
|
||||
end
|
||||
end
|
||||
|
||||
class Query < ActiveRecord::Base
|
||||
@@ -33,7 +54,6 @@ class Query < ActiveRecord::Base
|
||||
serialize :column_names
|
||||
|
||||
attr_protected :project, :user
|
||||
attr_accessor :executed_by
|
||||
|
||||
validates_presence_of :name, :on => :save
|
||||
validates_length_of :name, :maximum => 255
|
||||
@@ -79,6 +99,7 @@ class Query < ActiveRecord::Base
|
||||
QueryColumn.new(:assigned_to, :sortable => "#{User.table_name}.lastname"),
|
||||
QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on"),
|
||||
QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name"),
|
||||
QueryColumn.new(:fixed_version),
|
||||
QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"),
|
||||
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
|
||||
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"),
|
||||
@@ -90,11 +111,7 @@ class Query < ActiveRecord::Base
|
||||
def initialize(attributes = nil)
|
||||
super attributes
|
||||
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
|
||||
end
|
||||
|
||||
def executed_by=(user)
|
||||
@executed_by = user
|
||||
set_language_if_valid(user.language) if user
|
||||
set_language_if_valid(User.current.language)
|
||||
end
|
||||
|
||||
def validate
|
||||
@@ -126,12 +143,12 @@ class Query < ActiveRecord::Base
|
||||
"done_ratio" => { :type => :integer, :order => 13 }}
|
||||
|
||||
user_values = []
|
||||
user_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
|
||||
if project
|
||||
user_values += project.users.collect{|s| [s.name, s.id.to_s] }
|
||||
elsif executed_by
|
||||
user_values << ["<< #{l(:label_me)} >>", "me"] if executed_by
|
||||
user_values += project.users.sort.collect{|s| [s.name, s.id.to_s] }
|
||||
else
|
||||
# members of the user's projects
|
||||
user_values += executed_by.projects.collect(&:users).flatten.uniq.sort.collect{|s| [s.name, s.id.to_s] }
|
||||
user_values += User.current.projects.collect(&:users).flatten.uniq.sort.collect{|s| [s.name, s.id.to_s] }
|
||||
end
|
||||
@available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
|
||||
@available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty?
|
||||
@@ -145,8 +162,6 @@ class Query < ActiveRecord::Base
|
||||
end
|
||||
@project.all_custom_fields.select(&:is_filter?).each do |field|
|
||||
case field.field_format
|
||||
when "string", "int"
|
||||
options = { :type => :string, :order => 20 }
|
||||
when "text"
|
||||
options = { :type => :text, :order => 20 }
|
||||
when "list"
|
||||
@@ -155,6 +170,8 @@ class Query < ActiveRecord::Base
|
||||
options = { :type => :date, :order => 20 }
|
||||
when "bool"
|
||||
options = { :type => :list, :values => [[l(:general_text_yes), "1"], [l(:general_text_no), "0"]], :order => 20 }
|
||||
else
|
||||
options = { :type => :string, :order => 20 }
|
||||
end
|
||||
@available_filters["cf_#{field.id}"] = options.merge({ :name => field.name })
|
||||
end
|
||||
@@ -203,7 +220,12 @@ class Query < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def available_columns
|
||||
cols = Query.available_columns
|
||||
return @available_columns if @available_columns
|
||||
@available_columns = Query.available_columns
|
||||
@available_columns += (project ?
|
||||
project.custom_fields :
|
||||
IssueCustomField.find(:all, :conditions => {:is_for_all => true})
|
||||
).collect {|cf| QueryCustomFieldColumn.new(cf) }
|
||||
end
|
||||
|
||||
def columns
|
||||
@@ -243,7 +265,7 @@ class Query < ActiveRecord::Base
|
||||
elsif project
|
||||
clause << "#{Issue.table_name}.project_id=%d" % project.id
|
||||
else
|
||||
clause << Project.visible_by(executed_by)
|
||||
clause << Project.visible_by(User.current)
|
||||
end
|
||||
|
||||
# filters clauses
|
||||
@@ -268,7 +290,7 @@ class Query < ActiveRecord::Base
|
||||
|
||||
# "me" value subsitution
|
||||
if %w(assigned_to_id author_id).include?(field)
|
||||
v.push(executed_by ? executed_by.id.to_s : "0") if v.delete("me")
|
||||
v.push(User.current.logged? ? User.current.id.to_s : "0") if v.delete("me")
|
||||
end
|
||||
|
||||
case operator_for field
|
||||
|
||||
@@ -33,6 +33,10 @@ class Repository < ActiveRecord::Base
|
||||
def supports_cat?
|
||||
scm.supports_cat?
|
||||
end
|
||||
|
||||
def supports_annotate?
|
||||
scm.supports_annotate?
|
||||
end
|
||||
|
||||
def entries(path=nil, identifier=nil)
|
||||
scm.entries(path, identifier)
|
||||
|
||||
86
app/models/repository/bazaar.rb
Normal file
86
app/models/repository/bazaar.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
# 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 'redmine/scm/adapters/bazaar_adapter'
|
||||
|
||||
class Repository::Bazaar < Repository
|
||||
attr_protected :root_url
|
||||
validates_presence_of :url
|
||||
|
||||
def scm_adapter
|
||||
Redmine::Scm::Adapters::BazaarAdapter
|
||||
end
|
||||
|
||||
def self.scm_name
|
||||
'Bazaar'
|
||||
end
|
||||
|
||||
def entries(path=nil, identifier=nil)
|
||||
entries = scm.entries(path, identifier)
|
||||
if entries
|
||||
entries.each do |e|
|
||||
next if e.lastrev.revision.blank?
|
||||
c = Change.find(:first,
|
||||
:include => :changeset,
|
||||
:conditions => ["#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?", e.lastrev.revision, id],
|
||||
:order => "#{Changeset.table_name}.revision DESC")
|
||||
if c
|
||||
e.lastrev.identifier = c.changeset.revision
|
||||
e.lastrev.name = c.changeset.revision
|
||||
e.lastrev.author = c.changeset.committer
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_changesets
|
||||
scm_info = scm.info
|
||||
if scm_info
|
||||
# latest revision found in database
|
||||
db_revision = latest_changeset ? latest_changeset.revision : 0
|
||||
# latest revision in the repository
|
||||
scm_revision = scm_info.lastrev.identifier.to_i
|
||||
if db_revision < scm_revision
|
||||
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
|
||||
identifier_from = db_revision + 1
|
||||
while (identifier_from <= scm_revision)
|
||||
# loads changesets by batches of 200
|
||||
identifier_to = [identifier_from + 199, scm_revision].min
|
||||
revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
|
||||
transaction do
|
||||
revisions.reverse_each do |revision|
|
||||
changeset = Changeset.create(:repository => self,
|
||||
:revision => revision.identifier,
|
||||
:committer => revision.author,
|
||||
:committed_on => revision.time,
|
||||
:scmid => revision.scmid,
|
||||
:comments => revision.message)
|
||||
|
||||
revision.paths.each do |change|
|
||||
Change.create(:changeset => changeset,
|
||||
:action => change[:action],
|
||||
:path => change[:path],
|
||||
:revision => change[:revision])
|
||||
end
|
||||
end
|
||||
end unless revisions.nil?
|
||||
identifier_from = identifier_to + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -17,6 +17,23 @@
|
||||
|
||||
class Setting < ActiveRecord::Base
|
||||
|
||||
DATE_FORMATS = [
|
||||
'%Y-%m-%d',
|
||||
'%d/%m/%Y',
|
||||
'%d.%m.%Y',
|
||||
'%d-%m-%Y',
|
||||
'%m/%d/%Y',
|
||||
'%d %b %Y',
|
||||
'%d %B %Y',
|
||||
'%b %d, %Y',
|
||||
'%B %d, %Y'
|
||||
]
|
||||
|
||||
TIME_FORMATS = [
|
||||
'%H:%M',
|
||||
'%I:%M %p'
|
||||
]
|
||||
|
||||
cattr_accessor :available_settings
|
||||
@@available_settings = YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml"))
|
||||
Redmine::Plugin.registered_plugins.each do |id, plugin|
|
||||
|
||||
@@ -29,6 +29,14 @@ class Tracker < ActiveRecord::Base
|
||||
|
||||
def to_s; name end
|
||||
|
||||
def <=>(tracker)
|
||||
name <=> tracker.name
|
||||
end
|
||||
|
||||
def self.all
|
||||
find(:all, :order => 'position')
|
||||
end
|
||||
|
||||
private
|
||||
def check_integrity
|
||||
raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id])
|
||||
|
||||
@@ -19,6 +19,7 @@ require "digest/sha1"
|
||||
|
||||
class User < ActiveRecord::Base
|
||||
# Account statuses
|
||||
STATUS_ANONYMOUS = 0
|
||||
STATUS_ACTIVE = 1
|
||||
STATUS_REGISTERED = 2
|
||||
STATUS_LOCKED = 3
|
||||
@@ -36,17 +37,16 @@ class User < ActiveRecord::Base
|
||||
# Prevents unauthorized assignments
|
||||
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
|
||||
|
||||
validates_presence_of :login, :firstname, :lastname, :mail
|
||||
validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
|
||||
validates_uniqueness_of :login, :mail
|
||||
# Login must contain lettres, numbers, underscores only
|
||||
validates_format_of :login, :with => /^[a-z0-9_\-@\.]+$/i
|
||||
validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
|
||||
validates_length_of :login, :maximum => 30
|
||||
validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i
|
||||
validates_length_of :firstname, :lastname, :maximum => 30
|
||||
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
|
||||
validates_length_of :mail, :maximum => 60
|
||||
# Password length between 4 and 12
|
||||
validates_length_of :password, :in => 4..12, :allow_nil => true
|
||||
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true
|
||||
validates_length_of :mail, :maximum => 60, :allow_nil => true
|
||||
validates_length_of :password, :minimum => 4, :allow_nil => true
|
||||
validates_confirmation_of :password, :allow_nil => true
|
||||
validates_associated :custom_values, :on => :update
|
||||
|
||||
@@ -74,6 +74,8 @@ class User < ActiveRecord::Base
|
||||
|
||||
# Returns the user that matches provided login and password, or nil
|
||||
def self.try_to_login(login, password)
|
||||
# Make sure no one can sign in with an empty password
|
||||
return nil if password.to_s.empty?
|
||||
user = find(:first, :conditions => ["login=?", login])
|
||||
if user
|
||||
# user is already in local database
|
||||
@@ -130,6 +132,10 @@ class User < ActiveRecord::Base
|
||||
self.preference ||= UserPreference.new(:user => self)
|
||||
end
|
||||
|
||||
def time_zone
|
||||
self.pref.time_zone.nil? ? nil : TimeZone[self.pref.time_zone]
|
||||
end
|
||||
|
||||
# Return user's RSS key (a 40 chars long string), used to access feeds
|
||||
def rss_key
|
||||
token = self.rss_token || Token.create(:user => self, :action => 'feeds')
|
||||
@@ -159,7 +165,7 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def <=>(user)
|
||||
lastname == user.lastname ? firstname <=> user.firstname : lastname <=> user.lastname
|
||||
user.nil? ? -1 : (lastname == user.lastname ? firstname <=> user.firstname : lastname <=> user.lastname)
|
||||
end
|
||||
|
||||
def to_s
|
||||
@@ -174,14 +180,16 @@ class User < ActiveRecord::Base
|
||||
def role_for_project(project)
|
||||
# No role on archived projects
|
||||
return nil unless project && project.active?
|
||||
# Find project membership
|
||||
membership = memberships.detect {|m| m.project_id == project.id}
|
||||
if membership
|
||||
membership.role
|
||||
elsif logged?
|
||||
Role.non_member
|
||||
if logged?
|
||||
# Find project membership
|
||||
membership = memberships.detect {|m| m.project_id == project.id}
|
||||
if membership
|
||||
membership.role
|
||||
else
|
||||
@role_non_member ||= Role.non_member
|
||||
end
|
||||
else
|
||||
Role.anonymous
|
||||
@role_anonymous ||= Role.anonymous
|
||||
end
|
||||
end
|
||||
|
||||
@@ -212,11 +220,17 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def self.current
|
||||
@current_user ||= AnonymousUser.new
|
||||
@current_user ||= User.anonymous
|
||||
end
|
||||
|
||||
def self.anonymous
|
||||
AnonymousUser.new
|
||||
return @anonymous_user if @anonymous_user
|
||||
anonymous_user = AnonymousUser.find(:first)
|
||||
if anonymous_user.nil?
|
||||
anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
|
||||
raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
|
||||
end
|
||||
@anonymous_user = anonymous_user
|
||||
end
|
||||
|
||||
private
|
||||
@@ -227,12 +241,17 @@ private
|
||||
end
|
||||
|
||||
class AnonymousUser < User
|
||||
def logged?
|
||||
false
|
||||
|
||||
def validate_on_create
|
||||
# There should be only one AnonymousUser in the database
|
||||
errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
|
||||
end
|
||||
|
||||
# Anonymous user has no RSS key
|
||||
def rss_key
|
||||
nil
|
||||
end
|
||||
# Overrides a few properties
|
||||
def logged?; false end
|
||||
def admin; false end
|
||||
def name; 'Anonymous' end
|
||||
def mail; nil end
|
||||
def time_zone; nil end
|
||||
def rss_key; nil end
|
||||
end
|
||||
|
||||
@@ -39,6 +39,24 @@ class Version < ActiveRecord::Base
|
||||
effective_date && (effective_date <= Date.today) && (open_issues_count == 0)
|
||||
end
|
||||
|
||||
def completed_pourcent
|
||||
if fixed_issues.count == 0
|
||||
0
|
||||
elsif open_issues_count == 0
|
||||
100
|
||||
else
|
||||
(closed_issues_count * 100 + Issue.sum('done_ratio', :include => 'status', :conditions => ["fixed_version_id = ? AND is_closed = ?", id, false]).to_f) / fixed_issues.count
|
||||
end
|
||||
end
|
||||
|
||||
def closed_pourcent
|
||||
if fixed_issues.count == 0
|
||||
0
|
||||
else
|
||||
closed_issues_count * 100.0 / fixed_issues.count
|
||||
end
|
||||
end
|
||||
|
||||
# Returns true if the version is overdue: due date reached and some open issues
|
||||
def overdue?
|
||||
effective_date && (effective_date < Date.today) && (open_issues_count > 0)
|
||||
|
||||
@@ -25,8 +25,8 @@ class WikiContent < ActiveRecord::Base
|
||||
|
||||
acts_as_versioned
|
||||
class Version
|
||||
belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id'
|
||||
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
|
||||
belongs_to :page, :class_name => '::WikiPage', :foreign_key => 'page_id'
|
||||
belongs_to :author, :class_name => '::User', :foreign_key => 'author_id'
|
||||
attr_protected :data
|
||||
|
||||
acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="box tabular">
|
||||
<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
|
||||
<%= password_field_tag 'new_password', nil, :size => 25 %><br />
|
||||
<em><%= l(:text_length_between, 4, 12) %></em></p>
|
||||
<em><%= l(:text_caracters_minimum, 4) %></em></p>
|
||||
|
||||
<p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
|
||||
<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p>
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<%= text_field 'user', 'login', :size => 25 %></p>
|
||||
|
||||
<p><label for="password"><%=l(:field_password)%> <span class="required">*</span></label>
|
||||
<%= password_field_tag 'password', nil, :size => 25 %></p>
|
||||
<%= password_field_tag 'password', nil, :size => 25 %><br />
|
||||
<em><%= l(:text_caracters_minimum, 4) %></em></p>
|
||||
|
||||
<p><label for="password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
|
||||
<%= password_field_tag 'password_confirmation', nil, :size => 25 %></p>
|
||||
@@ -29,9 +30,6 @@
|
||||
<% for @custom_value in @custom_values %>
|
||||
<p><%= custom_field_tag_with_label @custom_value %></p>
|
||||
<% end %>
|
||||
|
||||
<p><label for="user_mail_notification"><%=l(:field_mail_notification)%></label>
|
||||
<%= check_box 'user', 'mail_notification' %></p>
|
||||
<!--[eoform:user]-->
|
||||
</div>
|
||||
|
||||
|
||||
@@ -42,4 +42,6 @@
|
||||
|
||||
<p class="icon22 icon22-info">
|
||||
<%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
<% set_html_title l(:label_administration) -%>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<h3 class="icon22 icon22-plugin">Plugins</h3>
|
||||
<table class="list">
|
||||
<% @plugins.keys.sort.each do |plugin| %>
|
||||
<% @plugins.keys.sort {|x,y| x.to_s <=> y.to_s}.each do |plugin| %>
|
||||
<tr class="<%= cycle('odd', 'even') %>">
|
||||
<td><%=h @plugins[plugin].name %></td>
|
||||
<td><%=h @plugins[plugin].description %></td>
|
||||
@@ -23,3 +23,5 @@
|
||||
<% end %>
|
||||
</table>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title(l(:label_information_plural)) -%>
|
||||
|
||||
@@ -6,17 +6,28 @@
|
||||
|
||||
<% form_tag({:action => 'mail_options'}, :id => 'mail-options-form') do %>
|
||||
|
||||
<fieldset class="box tabular settings"><legend><%=l(:label_settings)%></legend>
|
||||
<p><label><%= l(:setting_mail_from) %></label>
|
||||
<%= text_field_tag 'settings[mail_from]', Setting.mail_from, :size => 60 %></p>
|
||||
|
||||
<p><label><%= l(:setting_bcc_recipients) %></label>
|
||||
<%= check_box_tag 'settings[bcc_recipients]', 1, Setting.bcc_recipients? %>
|
||||
<%= hidden_field_tag 'settings[bcc_recipients]', 0 %></p>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="box"><legend><%=l(:text_select_mail_notifications)%></legend>
|
||||
<% @notifiables.each do |notifiable| %>
|
||||
<label><%= check_box_tag "notified_events[]", notifiable, Setting.notified_events.include?(notifiable) %>
|
||||
<label><%= check_box_tag 'settings[notified_events][]', notifiable, Setting.notified_events.include?(notifiable) %>
|
||||
<%= notifiable.humanize %></label><br />
|
||||
<% end %>
|
||||
<p><%= check_all_links('mail-options-form') %></p>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="box"><legend><%= l(:setting_emails_footer) %></legend>
|
||||
<%= text_area_tag 'emails_footer', Setting.emails_footer, :class => 'wiki-edit', :rows => 5 %>
|
||||
<%= text_area_tag 'settings[emails_footer]', Setting.emails_footer, :class => 'wiki-edit', :rows => 5 %>
|
||||
</fieldset>
|
||||
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title(l(:field_mail_notification)) -%>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<tbody>
|
||||
<% for project in @projects %>
|
||||
<tr class="<%= cycle("odd", "even") %>">
|
||||
<td><%= project.active? ? link_to(project.name, :controller => 'projects', :action => 'settings', :id => project) : h(project.name) %>
|
||||
<td><%= project.active? ? link_to(h(project.name), :controller => 'projects', :action => 'settings', :id => project) : h(project.name) %>
|
||||
<td><%= textilizable project.description, :project => project %>
|
||||
<td align="center"><%= image_tag 'true.png' if project.is_public? %>
|
||||
<td align="center"><%= project.children.size %>
|
||||
@@ -47,3 +47,5 @@
|
||||
|
||||
<p><%= pagination_links_full @project_pages, :status => @status %>
|
||||
[ <%= @project_pages.current.first_item %> - <%= @project_pages.current.last_item %> / <%= @project_count %> ]</p>
|
||||
|
||||
<% set_html_title l(:label_project_plural) -%>
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
<%= text_field 'auth_source', 'account' %></p>
|
||||
|
||||
<p><label for="auth_source_account_password"><%=l(:field_password)%></label>
|
||||
<%= password_field 'auth_source', 'account_password' %></p>
|
||||
<%= password_field 'auth_source', 'account_password', :name => 'ignore',
|
||||
:value => ((@auth_source.new_record? || @auth_source.account_password.blank?) ? '' : ('x'*15)),
|
||||
:onfocus => "this.value=''; this.name='auth_source[account_password]';",
|
||||
:onchange => "this.name='auth_source[account_password]';" %></p>
|
||||
|
||||
<p><label for="auth_source_base_dn"><%=l(:field_base_dn)%> <span class="required">*</span></label>
|
||||
<%= text_field 'auth_source', 'base_dn', :size => 60 %></p>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<td>
|
||||
<small>
|
||||
<% if board.last_message %>
|
||||
<%= board.last_message.author.name %>, <%= format_time(board.last_message.created_on) %><br />
|
||||
<%= authoring board.last_message.created_on, board.last_message.author %><br />
|
||||
<%= link_to_message board.last_message %>
|
||||
<% end %>
|
||||
</small>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<h2><%=h @board.name %></h2>
|
||||
|
||||
<% if @topics.any? %>
|
||||
<table class="list">
|
||||
<table class="list messages">
|
||||
<thead><tr>
|
||||
<th><%= l(:field_subject) %></th>
|
||||
<th><%= l(:field_author) %></th>
|
||||
@@ -28,18 +28,16 @@
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<% @topics.each do |topic| %>
|
||||
<tr class="<%= cycle 'odd', 'even' %>">
|
||||
<td><%= link_to h(topic.subject), :controller => 'messages', :action => 'show', :board_id => @board, :id => topic %></td>
|
||||
<td align="center"><%= link_to_user topic.author %></td>
|
||||
<td align="center"><%= format_time(topic.created_on) %></td>
|
||||
<td align="center"><%= topic.replies_count %></td>
|
||||
<td>
|
||||
<small>
|
||||
<tr class="message <%= cycle 'odd', 'even' %> <%= topic.sticky? ? 'sticky' : '' %> <%= topic.locked? ? 'locked' : '' %>">
|
||||
<td class="subject"><%= link_to h(topic.subject), { :controller => 'messages', :action => 'show', :board_id => @board, :id => topic }, :class => 'icon' %></td>
|
||||
<td class="author" align="center"><%= topic.author %></td>
|
||||
<td class="created_on" align="center"><%= format_time(topic.created_on) %></td>
|
||||
<td class="replies" align="center"><%= topic.replies_count %></td>
|
||||
<td class="last_message">
|
||||
<% if topic.last_reply %>
|
||||
<%= topic.last_reply.author.name %>, <%= format_time(topic.last_reply.created_on) %><br />
|
||||
<%= authoring topic.last_reply.created_on, topic.last_reply.author %><br />
|
||||
<%= link_to_message topic.last_reply %>
|
||||
<% end %>
|
||||
</small>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
@@ -7,21 +7,32 @@ function toggle_custom_field_format() {
|
||||
p_length = $("custom_field_min_length");
|
||||
p_regexp = $("custom_field_regexp");
|
||||
p_values = $("custom_field_possible_values");
|
||||
p_searchable = $("custom_field_searchable");
|
||||
switch (format.value) {
|
||||
case "list":
|
||||
Element.hide(p_length.parentNode);
|
||||
Element.hide(p_regexp.parentNode);
|
||||
Element.show(p_searchable.parentNode);
|
||||
Element.show(p_values);
|
||||
break;
|
||||
case "date":
|
||||
case "bool":
|
||||
Element.hide(p_length.parentNode);
|
||||
Element.hide(p_regexp.parentNode);
|
||||
Element.hide(p_searchable.parentNode);
|
||||
Element.hide(p_values);
|
||||
break;
|
||||
case "float":
|
||||
case "int":
|
||||
Element.show(p_length.parentNode);
|
||||
Element.show(p_regexp.parentNode);
|
||||
Element.hide(p_searchable.parentNode);
|
||||
Element.hide(p_values);
|
||||
break;
|
||||
default:
|
||||
Element.show(p_length.parentNode);
|
||||
Element.show(p_regexp.parentNode);
|
||||
Element.show(p_searchable.parentNode);
|
||||
Element.hide(p_values);
|
||||
break;
|
||||
}
|
||||
@@ -47,7 +58,6 @@ function deleteValueField(e) {
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<!--[form:custom_field]-->
|
||||
<div class="box">
|
||||
<p><%= f.text_field :name, :required => true %></p>
|
||||
<p><%= f.select :field_format, custom_field_formats_for_select, {}, :onchange => "toggle_custom_field_format();" %></p>
|
||||
@@ -59,11 +69,8 @@ function deleteValueField(e) {
|
||||
<% (@custom_field.possible_values.to_a + [""]).each do |value| %>
|
||||
<span><%= text_field_tag 'custom_field[possible_values][]', value, :size => 30 %> <%= image_to_function "delete.png", "deleteValueField(this);return false" %><br /></span>
|
||||
<% end %>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<%= javascript_tag "toggle_custom_field_format();" %>
|
||||
<!--[eoform:custom_field]-->
|
||||
|
||||
<div class="box">
|
||||
<% case @custom_field.type.to_s
|
||||
@@ -78,6 +85,7 @@ when "IssueCustomField" %>
|
||||
<p><%= f.check_box :is_required %></p>
|
||||
<p><%= f.check_box :is_for_all %></p>
|
||||
<p><%= f.check_box :is_filter %></p>
|
||||
<p><%= f.check_box :searchable %></p>
|
||||
|
||||
<% when "UserCustomField" %>
|
||||
<p><%= f.check_box :is_required %></p>
|
||||
@@ -87,3 +95,4 @@ when "IssueCustomField" %>
|
||||
|
||||
<% end %>
|
||||
</div>
|
||||
<%= javascript_tag "toggle_custom_field_format();" %>
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
<th><%=l(:field_is_for_all)%></th>
|
||||
<th><%=l(:label_used_by)%></th>
|
||||
<% end %>
|
||||
<th><%=l(:button_sort)%></th>
|
||||
<th width="10%"></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<% for custom_field in (@custom_fields_by_type[type] || []) %>
|
||||
<% for custom_field in (@custom_fields_by_type[type] || []).sort %>
|
||||
<tr class="<%= cycle("odd", "even") %>">
|
||||
<td><%= link_to custom_field.name, :action => 'edit', :id => custom_field %></td>
|
||||
<td align="center"><%= l(CustomField::FIELD_FORMATS[custom_field.field_format][:name]) %></td>
|
||||
@@ -31,6 +32,12 @@
|
||||
<td align="center"><%= image_tag 'true.png' if custom_field.is_for_all? %></td>
|
||||
<td align="center"><%= custom_field.projects.count.to_s + ' ' + lwr(:label_project, custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %></td>
|
||||
<% end %>
|
||||
<td align="center" style="width:15%;">
|
||||
<%= link_to image_tag('2uparrow.png', :alt => l(:label_sort_highest)), {:action => 'move', :id => custom_field, :position => 'highest'}, :method => :post, :title => l(:label_sort_highest) %>
|
||||
<%= link_to image_tag('1uparrow.png', :alt => l(:label_sort_higher)), {:action => 'move', :id => custom_field, :position => 'higher'}, :method => :post, :title => l(:label_sort_higher) %> -
|
||||
<%= link_to image_tag('1downarrow.png', :alt => l(:label_sort_lower)), {:action => 'move', :id => custom_field, :position => 'lower'}, :method => :post, :title => l(:label_sort_lower) %>
|
||||
<%= link_to image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), {:action => 'move', :id => custom_field, :position => 'lowest'}, :method => :post, :title => l(:label_sort_lowest) %>
|
||||
</td>
|
||||
<td align="center">
|
||||
<%= button_to l(:button_delete), { :action => 'destroy', :id => custom_field }, :confirm => l(:text_are_you_sure), :class => "button-small" %>
|
||||
</td>
|
||||
@@ -43,4 +50,6 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= javascript_tag "showTab('#{@tab}');" %>
|
||||
<%= javascript_tag "showTab('#{@tab}');" %>
|
||||
|
||||
<% set_html_title(l(:label_custom_field_plural)) -%>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<%= link_to_if_authorized l(:button_delete), {:controller => 'documents', :action => 'destroy', :id => @document}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
|
||||
</div>
|
||||
|
||||
<h2><%= @document.title %></h2>
|
||||
<h2><%=h @document.title %></h2>
|
||||
|
||||
<p><em><%= @document.category.name %><br />
|
||||
<p><em><%=h @document.category.name %><br />
|
||||
<%= format_date @document.created_on %></em></p>
|
||||
<%= textilizable @document.description, :attachments => @document.attachments %>
|
||||
<br />
|
||||
@@ -34,3 +34,5 @@
|
||||
<%= submit_tag l(:button_add) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title h(@document.title) -%>
|
||||
|
||||
@@ -24,3 +24,5 @@
|
||||
|
||||
<p><%= link_to l(:label_enumeration_new), { :action => 'new', :opt => option } %></p>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title(l(:label_enumerations)) -%>
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
xml.instruct!
|
||||
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
|
||||
xml.channel do
|
||||
xml.title @title
|
||||
xml.link url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.pubDate CGI.rfc1123_date(@journals.first ? @journals.first.created_on : Time.now)
|
||||
xml.description l(:label_changes_details)
|
||||
@journals.each do |journal|
|
||||
issue = journal.issue
|
||||
xml.item do
|
||||
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
|
||||
url = url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
|
||||
xml.link url
|
||||
xml.description do
|
||||
xml.text! h(journal.notes)
|
||||
xml.text! "<ul>"
|
||||
journal.details.each do |detail|
|
||||
xml.text! "<li>" + show_detail(detail, false) + "</li>"
|
||||
end
|
||||
xml.text! "</ul>"
|
||||
end
|
||||
xml.pubDate CGI.rfc1123_date(journal.created_on)
|
||||
xml.guid url
|
||||
xml.author h(journal.user.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
xml.instruct!
|
||||
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
|
||||
xml.channel do
|
||||
xml.title @title
|
||||
xml.link url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.pubDate CGI.rfc1123_date(@issues.first ? @issues.first.created_on : Time.now)
|
||||
xml.description l(:label_reported_issues)
|
||||
@issues.each do |issue|
|
||||
xml.item do
|
||||
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
|
||||
url = url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
|
||||
xml.link url
|
||||
xml.description h(issue.description)
|
||||
xml.pubDate CGI.rfc1123_date(issue.created_on)
|
||||
xml.guid url
|
||||
xml.author h(issue.author.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,22 +0,0 @@
|
||||
xml.instruct!
|
||||
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
||||
xml.title @title
|
||||
xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'issues', :format => 'atom', :only_path => false)
|
||||
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.id url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.updated CGI.rfc1123_date(@issues.first.updated_on) if @issues.any?
|
||||
xml.author { xml.name "#{Setting.app_title}" }
|
||||
@issues.each do |issue|
|
||||
xml.entry do
|
||||
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
|
||||
xml.link "rel" => "alternate", "href" => url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
|
||||
xml.id url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
|
||||
xml.updated CGI.rfc1123_date(issue.updated_on)
|
||||
xml.author { xml.name issue.author.name }
|
||||
xml.summary issue.description
|
||||
xml.content "type" => "html" do
|
||||
xml.text! issue.description
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
xml.instruct!
|
||||
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
|
||||
xml.channel do
|
||||
xml.title "#{Setting.app_title}: #{l(:label_news_latest)}"
|
||||
xml.link url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.pubDate CGI.rfc1123_date(@news.first ? @news.first.created_on : Time.now)
|
||||
xml.description l(:label_news_latest)
|
||||
@news.each do |news|
|
||||
xml.item do
|
||||
xml.title "#{news.project.name}: #{news.title}"
|
||||
news_url = url_for(:controller => 'news' , :action => 'show', :id => news, :only_path => false)
|
||||
xml.link news_url
|
||||
xml.description h(news.summary)
|
||||
xml.pubDate CGI.rfc1123_date(news.created_on)
|
||||
xml.guid news_url
|
||||
xml.author h(news.author.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,22 +0,0 @@
|
||||
xml.instruct!
|
||||
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
||||
xml.title "#{Setting.app_title}: #{l(:label_news_latest)}"
|
||||
xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'news', :format => 'atom', :only_path => false)
|
||||
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.id url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.updated CGI.rfc1123_date(@news.first.created_on) if @news.any?
|
||||
xml.author { xml.name "#{Setting.app_title}" }
|
||||
@news.each do |news|
|
||||
xml.entry do
|
||||
xml.title news.title
|
||||
xml.link "rel" => "alternate", "href" => url_for(:controller => 'news' , :action => 'show', :id => news, :only_path => false)
|
||||
xml.id url_for(:controller => 'news' , :action => 'show', :id => news, :only_path => false)
|
||||
xml.updated CGI.rfc1123_date(news.created_on)
|
||||
xml.author { xml.name news.author.name }
|
||||
xml.summary h(news.summary)
|
||||
xml.content "type" => "html" do
|
||||
xml.text! news.description
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -32,4 +32,6 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= pagination_links_full @issue_status_pages %>
|
||||
<%= pagination_links_full @issue_status_pages %>
|
||||
|
||||
<% set_html_title(l(:label_issue_status_plural)) -%>
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<% for issue in issues %>
|
||||
<tr class="<%= cycle("odd", "even") %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>">
|
||||
<tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>">
|
||||
<td class="id">
|
||||
<%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %>
|
||||
</td>
|
||||
<td><p class="small"><%= issue.project.name %> - <%= issue.tracker.name %><br />
|
||||
<%= issue.status.name %> - <%= format_time(issue.updated_on) %></p></td>
|
||||
<td>
|
||||
<p class="small"><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></p>
|
||||
<td><%=h issue.project.name %> - <%= issue.tracker.name %><br />
|
||||
<%= issue.status.name %> - <%= format_time(issue.updated_on) %></td>
|
||||
<td class="subject">
|
||||
<%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<% if authorize_for('projects', 'add_issue') %>
|
||||
<% if authorize_for('projects', 'add_issue') && @project.trackers.any? %>
|
||||
<h3><%= l(:label_issue_new) %></h3>
|
||||
<%= l(:label_tracker) %>: <%= new_issue_selector %>
|
||||
<% end %>
|
||||
|
||||
<h3><%= l(:label_issue_plural) %></h3>
|
||||
<%= link_to l(:label_issue_view_all), :controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1 %><br />
|
||||
<%= link_to l(:label_issue_view_all), { :controller => 'issues', :action => 'index', :project_id => @project, :set_filter => 1 } %><br />
|
||||
<%= link_to l(:field_summary), :controller => 'reports', :action => 'issue_report', :id => @project %><br />
|
||||
<%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %>
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
:order => "name ASC",
|
||||
:conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
|
||||
queries.each do |query| %>
|
||||
<%= link_to query.name, :controller => 'projects', :action => 'list_issues', :id => @project, :query_id => query %><br />
|
||||
<%= link_to query.name, :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query %><br />
|
||||
<% end %>
|
||||
|
||||
@@ -29,11 +29,9 @@
|
||||
<p><label for="notes"><%= l(:field_notes) %></label>
|
||||
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %></p>
|
||||
|
||||
<% if authorize_for('issues', 'add_attachment') %>
|
||||
<p id="attachments_p"><label><%=l(:label_attachment_new)%>
|
||||
<%= image_to_function "add.png", "addFileField();return false" %></label>
|
||||
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= submit_tag l(:button_save) %>
|
||||
|
||||
@@ -4,24 +4,26 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
||||
xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'history', :format => 'atom', :only_path => false)
|
||||
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.id url_for(:controller => 'welcome', :only_path => false)
|
||||
xml.updated CGI.rfc1123_date(@journals.first.created_on) if @journals.any?
|
||||
xml.updated((@changes.first ? @changes.first.event_datetime : Time.now).xmlschema)
|
||||
xml.author { xml.name "#{Setting.app_title}" }
|
||||
@journals.each do |journal|
|
||||
issue = journal.issue
|
||||
@changes.each do |change|
|
||||
issue = change.issue
|
||||
xml.entry do
|
||||
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
|
||||
xml.link "rel" => "alternate", "href" => url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
|
||||
xml.id url_for(:controller => 'issues' , :action => 'show', :id => issue, :only_path => false)
|
||||
xml.updated CGI.rfc1123_date(journal.created_on)
|
||||
xml.author { xml.name journal.user.name }
|
||||
xml.summary journal.notes
|
||||
xml.id url_for(:controller => 'issues' , :action => 'show', :id => issue, :journal_id => change, :only_path => false)
|
||||
xml.updated change.created_on.xmlschema
|
||||
xml.author do
|
||||
xml.name change.user.name
|
||||
xml.email(change.user.mail)
|
||||
end
|
||||
xml.content "type" => "html" do
|
||||
xml.text! journal.notes if journal.notes
|
||||
xml.text! "<ul>"
|
||||
journal.details.each do |detail|
|
||||
xml.text! "<li>" + show_detail(detail, false) + "</li>"
|
||||
xml.text! '<ul>'
|
||||
change.details.each do |detail|
|
||||
xml.text! '<li>' + show_detail(detail, false) + '</li>'
|
||||
end
|
||||
xml.text! "</ul>"
|
||||
xml.text! '</ul>'
|
||||
xml.text! textilizable(change.notes) unless change.notes.blank?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
<% back_to = url_for(:controller => 'projects', :action => 'list_issues', :id => @project) %>
|
||||
<% back_to = url_for(:controller => 'issues', :action => 'index', :project_id => @project) %>
|
||||
<ul>
|
||||
<li><%= context_menu_link l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue},
|
||||
:class => 'icon-edit', :disabled => !@can[:edit] %></li>
|
||||
@@ -32,7 +32,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
<li><%= context_menu_link l(:button_copy), {:controller => 'projects', :action => 'add_issue', :id => @project, :copy_from => @issue},
|
||||
:class => 'icon-copy', :disabled => !@can[:add] %></li>
|
||||
:class => 'icon-copy', :disabled => !@can[:copy] %></li>
|
||||
<li><%= context_menu_link l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id },
|
||||
:class => 'icon-move', :disabled => !@can[:move] %>
|
||||
<li><%= context_menu_link l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue},
|
||||
|
||||
@@ -1,49 +1,50 @@
|
||||
<% pdf=IfpdfHelper::IFPDF.new(current_language)
|
||||
pdf.SetTitle("#{@project.name} - #{l(:label_issue_plural)}")
|
||||
pdf.AliasNbPages
|
||||
pdf.footer_date = format_date(Date.today)
|
||||
pdf.AddPage("L")
|
||||
row_height = 7
|
||||
|
||||
#
|
||||
# title
|
||||
#
|
||||
pdf.SetFontStyle('B',11)
|
||||
pdf.Cell(190,10, "#{@project.name} - #{l(:label_issue_plural)}")
|
||||
pdf.Ln
|
||||
|
||||
#
|
||||
# headers
|
||||
#
|
||||
pdf.SetFontStyle('B',10)
|
||||
pdf.SetFillColor(230, 230, 230)
|
||||
pdf.Cell(15, row_height, "#", 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, l(:field_tracker), 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, l(:field_status), 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, l(:field_priority), 0, 0, 'L', 1)
|
||||
pdf.Cell(40, row_height, l(:field_author), 0, 0, 'L', 1)
|
||||
pdf.Cell(25, row_height, l(:field_updated_on), 0, 0, 'L', 1)
|
||||
pdf.Cell(0, row_height, l(:field_subject), 0, 0, 'L', 1)
|
||||
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
|
||||
pdf.Ln
|
||||
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
|
||||
pdf.SetY(pdf.GetY() + 1)
|
||||
|
||||
#
|
||||
# rows
|
||||
#
|
||||
pdf.SetFontStyle('',9)
|
||||
pdf.SetFillColor(255, 255, 255)
|
||||
@issues.each do |issue|
|
||||
pdf.Cell(15, row_height, issue.id.to_s, 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, issue.tracker.name, 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, issue.status.name, 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, issue.priority.name, 0, 0, 'L', 1)
|
||||
pdf.Cell(40, row_height, issue.author.name, 0, 0, 'L', 1)
|
||||
pdf.Cell(25, row_height, format_date(issue.updated_on), 0, 0, 'L', 1)
|
||||
pdf.MultiCell(0, row_height, (@project == issue.project ? issue.subject : "#{issue.project.name} - #{issue.subject}"))
|
||||
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
|
||||
pdf.SetY(pdf.GetY() + 1)
|
||||
end
|
||||
%>
|
||||
<% pdf=IfpdfHelper::IFPDF.new(current_language)
|
||||
title = @project ? "#{@project.name} - #{l(:label_issue_plural)}" : "#{l(:label_issue_plural)}"
|
||||
pdf.SetTitle(title)
|
||||
pdf.AliasNbPages
|
||||
pdf.footer_date = format_date(Date.today)
|
||||
pdf.AddPage("L")
|
||||
row_height = 7
|
||||
|
||||
#
|
||||
# title
|
||||
#
|
||||
pdf.SetFontStyle('B',11)
|
||||
pdf.Cell(190,10, title)
|
||||
pdf.Ln
|
||||
|
||||
#
|
||||
# headers
|
||||
#
|
||||
pdf.SetFontStyle('B',10)
|
||||
pdf.SetFillColor(230, 230, 230)
|
||||
pdf.Cell(15, row_height, "#", 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, l(:field_tracker), 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, l(:field_status), 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, l(:field_priority), 0, 0, 'L', 1)
|
||||
pdf.Cell(40, row_height, l(:field_assigned_to), 0, 0, 'L', 1)
|
||||
pdf.Cell(25, row_height, l(:field_updated_on), 0, 0, 'L', 1)
|
||||
pdf.Cell(0, row_height, l(:field_subject), 0, 0, 'L', 1)
|
||||
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
|
||||
pdf.Ln
|
||||
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
|
||||
pdf.SetY(pdf.GetY() + 1)
|
||||
|
||||
#
|
||||
# rows
|
||||
#
|
||||
pdf.SetFontStyle('',9)
|
||||
pdf.SetFillColor(255, 255, 255)
|
||||
@issues.each do |issue|
|
||||
pdf.Cell(15, row_height, issue.id.to_s, 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, issue.tracker.name, 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, issue.status.name, 0, 0, 'L', 1)
|
||||
pdf.Cell(30, row_height, issue.priority.name, 0, 0, 'L', 1)
|
||||
pdf.Cell(40, row_height, issue.assigned_to ? issue.assigned_to.name : '', 0, 0, 'L', 1)
|
||||
pdf.Cell(25, row_height, format_date(issue.updated_on), 0, 0, 'L', 1)
|
||||
pdf.MultiCell(0, row_height, (@project == issue.project ? issue.subject : "#{issue.project.name} - #{issue.subject}"))
|
||||
pdf.Line(10, pdf.GetY, 287, pdf.GetY)
|
||||
pdf.SetY(pdf.GetY() + 1)
|
||||
end
|
||||
%>
|
||||
<%= pdf.Output %>
|
||||
@@ -1,35 +1,73 @@
|
||||
<h2><%=l(:label_issue_plural)%></h2>
|
||||
<% if @query.new_record? %>
|
||||
<h2><%=l(:label_issue_plural)%></h2>
|
||||
<% set_html_title l(:label_issue_plural) %>
|
||||
|
||||
<% form_tag({}, :id => 'query_form') do %>
|
||||
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
||||
<% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
|
||||
<%= hidden_field_tag('project_id', @project.id) if @project %>
|
||||
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
||||
<div class="contextual">
|
||||
<%= link_to_remote l(:button_apply),
|
||||
{ :url => { :set_filter => 1 },
|
||||
:update => "content",
|
||||
:with => "Form.serialize('query_form')"
|
||||
}, :class => 'icon icon-checked' %>
|
||||
|
||||
<%= link_to_remote l(:button_clear),
|
||||
{ :url => { :set_filter => 1 },
|
||||
:update => "content",
|
||||
}, :class => 'icon icon-reload' %>
|
||||
|
||||
<% if current_role && current_role.allowed_to?(:save_queries) %>
|
||||
<%= link_to l(:button_save), {}, :onclick => "$('query_form').submit(); return false;", :class => 'icon icon-save' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="contextual">
|
||||
<% if @query.editable_by?(User.current) %>
|
||||
<%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => @query}, :class => 'icon icon-edit' %>
|
||||
<%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => @query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<h2><%= @query.name %></h2>
|
||||
<div id="query_form"></div>
|
||||
<% set_html_title @query.name %>
|
||||
<% end %>
|
||||
<div class="contextual">
|
||||
<%= link_to_remote l(:button_apply),
|
||||
{ :url => { :set_filter => 1 },
|
||||
:update => "content",
|
||||
:with => "Form.serialize('query_form')"
|
||||
}, :class => 'icon icon-edit' %>
|
||||
|
||||
<%= link_to_remote l(:button_clear),
|
||||
{ :url => { :set_filter => 1 },
|
||||
:update => "content",
|
||||
}, :class => 'icon icon-reload' %>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<%= error_messages_for 'query' %>
|
||||
<% if @query.valid? %>
|
||||
<% if @issues.empty? %>
|
||||
<p><i><%= l(:label_no_data) %></i></p>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% else %>
|
||||
|
||||
<% form_tag({:controller => 'projects', :action => 'bulk_edit_issues', :id => @project}, :id => 'issues_form', :onsubmit => "if (!checkBulkEdit(this)) {alert('#{l(:notice_no_issue_selected)}'); return false;}" ) do %>
|
||||
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
|
||||
|
||||
<div class="contextual">
|
||||
<%= l(:label_export_to) %>
|
||||
<%= link_to 'CSV', {:format => 'csv'}, :class => 'icon icon-csv' %>,
|
||||
<%= link_to 'PDF', {:format => 'pdf'}, :class => 'icon icon-pdf' %>
|
||||
</div>
|
||||
<p><%= pagination_links_full @issue_pages %>
|
||||
[ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% content_for :sidebar do %>
|
||||
<%= render :partial => 'issues/sidebar' %>
|
||||
<% end if @project%>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %>
|
||||
<%= auto_discovery_link_tag(:atom, {:query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_issue_plural)) %>
|
||||
<%= auto_discovery_link_tag(:atom, {:action => 'changes', :query_id => @query, :format => 'atom', :page => nil, :key => User.current.rss_key}, :title => l(:label_changes_details)) %>
|
||||
<%= javascript_include_tag 'calendar/calendar' %>
|
||||
<%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
|
||||
<%= javascript_include_tag 'calendar/calendar-setup' %>
|
||||
<%= stylesheet_link_tag 'calendar' %>
|
||||
<%= javascript_include_tag 'context_menu' %>
|
||||
<%= stylesheet_link_tag 'context_menu' %>
|
||||
<% end %>
|
||||
|
||||
<div id="context-menu" style="display: none;"></div>
|
||||
<%= javascript_tag 'new ContextMenu({})' %>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
|
||||
|
||||
<div class="issue">
|
||||
<div class="issue <%= "status-#{@issue.status.position} priority-#{@issue.priority.position}" %>">
|
||||
<h3><%=h @issue.subject %></h3>
|
||||
<p class="author">
|
||||
<%= authoring @issue.created_on, @issue.author %>.
|
||||
@@ -28,7 +28,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td>
|
||||
<td><b><%=l(:field_done_ratio)%> :</b></td><td><%= @issue.done_ratio %> %</td>
|
||||
<td><b><%=l(:field_done_ratio)%> :</b></td><td><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b><%=l(:field_category)%> :</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td>
|
||||
@@ -64,7 +64,7 @@ end %>
|
||||
<% end %>
|
||||
|
||||
<p><strong><%=l(:field_description)%></strong></p>
|
||||
<%= textilizable @issue.description, :attachments => @issue.attachments %>
|
||||
<%= textilizable @issue, :description, :attachments => @issue.attachments %>
|
||||
|
||||
<% if @issue.attachments.any? %>
|
||||
<%= link_to_attachments @issue.attachments, :delete_url => (authorize_for('issues', 'destroy_attachment') ? {:controller => 'issues', :action => 'destroy_attachment', :id => @issue} : nil) %>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<% user_projects_by_root = User.current.projects.find(:all, :include => :parent).group_by(&:root) %>
|
||||
<select onchange="if (this.value != '') { window.location = this.value; }">
|
||||
<option selected><%= l(:label_jump_to_a_project) %></option>
|
||||
<option disabled>---</option>
|
||||
<option selected="selected"><%= l(:label_jump_to_a_project) %></option>
|
||||
<option disabled="disabled">---</option>
|
||||
<% user_projects_by_root.keys.sort.each do |root| %>
|
||||
<%= content_tag('option', root.name, :value => url_for(:controller => 'projects', :action => 'show', :id => root)) %>
|
||||
<%= content_tag('option', h(root.name), :value => url_for(:controller => 'projects', :action => 'show', :id => root)) %>
|
||||
<% user_projects_by_root[root].sort.each do |project| %>
|
||||
<% next if project == root %>
|
||||
<%= content_tag('option', ('» ' + project.name), :value => url_for(:controller => 'projects', :action => 'show', :id => project)) %>
|
||||
<%= content_tag('option', ('» ' + h(project.name)), :value => url_for(:controller => 'projects', :action => 'show', :id => project)) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</select>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<title><%=h html_title %></title>
|
||||
@@ -22,18 +22,18 @@
|
||||
<div id="account">
|
||||
<% if User.current.logged? %>
|
||||
<%=l(:label_logged_as)%> <%= User.current.login %> -
|
||||
<%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' } %>
|
||||
<%= link_to l(:label_logout), { :controller => 'account', :action => 'logout' } %>
|
||||
<%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' }, :class => 'myaccount' %>
|
||||
<%= link_to l(:label_logout), { :controller => 'account', :action => 'logout' }, :class => 'logout' %>
|
||||
<% else %>
|
||||
<%= link_to l(:label_login), { :controller => 'account', :action => 'login' } %>
|
||||
<%= link_to(l(:label_register), :controller => 'account',:action => 'register') if Setting.self_registration? %>
|
||||
<%= link_to l(:label_login), { :controller => 'account', :action => 'login' }, :class => 'signin' %>
|
||||
<%= link_to(l(:label_register), { :controller => 'account',:action => 'register' }, :class => 'register') if Setting.self_registration? %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= link_to l(:label_home), home_url %>
|
||||
<%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'} if User.current.logged? %>
|
||||
<%= link_to l(:label_project_plural), { :controller => 'projects' } %>
|
||||
<%= link_to l(:label_administration), { :controller => 'admin' } if User.current.admin? %>
|
||||
<%= link_to l(:label_help), Redmine::Info.help_url %>
|
||||
<%= link_to l(:label_home), home_url, :class => 'home' %>
|
||||
<%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'}, :class => 'mypage' if User.current.logged? %>
|
||||
<%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => 'projects' %>
|
||||
<%= link_to l(:label_administration), { :controller => 'admin' }, :class => 'admin' if User.current.admin? %>
|
||||
<%= link_to l(:label_help), Redmine::Info.help_url, :class => 'help' %>
|
||||
</div>
|
||||
|
||||
<div id="header">
|
||||
@@ -73,7 +73,7 @@
|
||||
<div id="ajax-indicator" style="display:none;"><span><%= l(:label_loading) %></span></div>
|
||||
|
||||
<div id="footer">
|
||||
Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> <%= Redmine::VERSION %> © 2006-2007 Jean-Philippe Lang
|
||||
Powered by <%= link_to Redmine::Info.app_name, Redmine::Info.url %> <%= Redmine::VERSION %> © 2006-2007 Jean-Philippe Lang
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<p><%= l(:mail_body_account_activation_request, @user.login) %></p>
|
||||
<p><%= link_to @url, @url %></p>
|
||||
@@ -0,0 +1,2 @@
|
||||
<%= l(:mail_body_account_activation_request, @user.login) %>
|
||||
<%= @url %>
|
||||
@@ -1,3 +1,3 @@
|
||||
<%= l(:text_issue_added, "##{@issue.id}") %>
|
||||
<hr />
|
||||
<%= render :file => "_issue_text_html", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
<%= render :partial => "issue_text_html", :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<%= l(:text_issue_added, "##{@issue.id}") %>
|
||||
----------------------------------------
|
||||
<%= render :file => "_issue_text_plain", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
<%= render :partial => "issue_text_plain", :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
</ul>
|
||||
<%= textilizable(@journal.notes) %>
|
||||
<hr />
|
||||
<%= render :file => "_issue_text_html", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
<%= render :partial => "issue_text_html", :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
<% end %>
|
||||
<%= @journal.notes if @journal.notes? %>
|
||||
----------------------------------------
|
||||
<%= render :file => "_issue_text_plain", :use_full_path => true, :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
<%= render :partial => "issue_text_plain", :locals => { :issue => @issue, :issue_url => @issue_url } %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<h1><%=h @message.board.project.name %> - <%=h @message.board.name %>: <%= link_to @message.subject, @message_url %></h1>
|
||||
<em><%= @message.author.name %></em>
|
||||
<em><%= @message.author %></em>
|
||||
|
||||
<%= textilizable @message.content %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%= @message_url %>
|
||||
<%= @message.author.name %>
|
||||
<%= @message.author %>
|
||||
|
||||
<%= @message.content %>
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
<div class="box">
|
||||
<!--[form:message]-->
|
||||
<p><label><%= l(:field_subject) %></label><br />
|
||||
<%= f.text_field :subject, :required => true, :size => 120 %></p>
|
||||
<%= f.text_field :subject, :required => true, :size => 120 %>
|
||||
|
||||
<p><%= f.text_area :content, :required => true, :cols => 80, :rows => 15, :class => 'wiki-edit' %></p>
|
||||
<% if User.current.allowed_to?(:edit_messages, @project) %>
|
||||
<label><%= f.check_box :sticky %> Sticky</label>
|
||||
<label><%= f.check_box :locked %> Locked</label>
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
<p><%= f.text_area :content, :required => true, :cols => 80, :rows => 15, :class => 'wiki-edit', :id => 'message_content' %></p>
|
||||
<%= wikitoolbar_for 'message_content' %>
|
||||
<!--[eoform:message]-->
|
||||
|
||||
<span class="tabular">
|
||||
<%= render :partial => 'attachments/form' %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
6
app/views/messages/edit.rhtml
Normal file
6
app/views/messages/edit.rhtml
Normal file
@@ -0,0 +1,6 @@
|
||||
<h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> » <%=h @message.subject %></h2>
|
||||
|
||||
<% form_for :message, @message, :url => {:action => 'edit'}, :html => {:multipart => true} do |f| %>
|
||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<% end %>
|
||||
@@ -1,27 +1,39 @@
|
||||
<h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> » <%=h @message.subject %></h2>
|
||||
|
||||
<p><span class="author"><%= authoring @message.created_on, @message.author %></span></p>
|
||||
<div class="wiki">
|
||||
<%= textilizable(@message.content, :attachments => @message.attachments) %>
|
||||
<div class="contextual">
|
||||
<%= link_to_if_authorized l(:button_edit), {:action => 'edit', :id => @topic}, :class => 'icon icon-edit' %>
|
||||
<%= link_to_if_authorized l(:button_delete), {:action => 'destroy', :id => @topic}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del' %>
|
||||
</div>
|
||||
|
||||
<h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> » <%=h @topic.subject %></h2>
|
||||
|
||||
<div class="message">
|
||||
<p><span class="author"><%= authoring @topic.created_on, @topic.author %></span></p>
|
||||
<div class="wiki">
|
||||
<%= textilizable(@topic.content, :attachments => @topic.attachments) %>
|
||||
</div>
|
||||
<%= link_to_attachments @topic.attachments, :no_author => true %>
|
||||
</div>
|
||||
<%= link_to_attachments @message.attachments, :no_author => true %>
|
||||
<br />
|
||||
|
||||
<h3 class="icon22 icon22-comment"><%= l(:label_reply_plural) %></h3>
|
||||
<% @message.children.each do |message| %>
|
||||
<% @topic.children.each do |message| %>
|
||||
<a name="<%= "message-#{message.id}" %>"></a>
|
||||
<h4><%=h message.subject %> - <%= message.author.name %>, <%= format_time(message.created_on) %></h4>
|
||||
<div class="contextual">
|
||||
<%= link_to_if_authorized l(:button_edit), {:action => 'edit', :id => message}, :class => 'icon icon-edit' %>
|
||||
<%= link_to_if_authorized l(:button_delete), {:action => 'destroy', :id => message}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del' %>
|
||||
</div>
|
||||
<div class="message reply">
|
||||
<h4><%=h message.subject %> - <%= authoring message.created_on, message.author %></h4>
|
||||
<div class="wiki"><%= textilizable message.content %></div>
|
||||
<%= link_to_attachments message.attachments, :no_author => true %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if authorize_for('messages', 'reply') %>
|
||||
<p><%= toggle_link l(:button_reply), "reply", :focus => "reply_content" %></p>
|
||||
<% if !@topic.locked? && authorize_for('messages', 'reply') %>
|
||||
<p><%= toggle_link l(:button_reply), "reply", :focus => 'message_content' %></p>
|
||||
<div id="reply" style="display:none;">
|
||||
<%= error_messages_for 'message' %>
|
||||
<% form_for :reply, @reply, :url => {:action => 'reply', :id => @message} do |f| %>
|
||||
<p><%= f.text_field :subject, :required => true, :size => 60 %></p>
|
||||
<p><%= f.text_area :content, :required => true, :cols => 80, :rows => 10 %></p>
|
||||
<p><%= submit_tag l(:button_submit) %></p>
|
||||
<% form_for :reply, @reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true} do |f| %>
|
||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
<%= submit_tag l(:button_submit) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
<h2><%=l(:label_my_account)%></h2>
|
||||
<%= error_messages_for 'user' %>
|
||||
|
||||
<% form_for :user, @user, :url => { :action => "account" }, :builder => TabularFormBuilder, :lang => current_language do |f| %>
|
||||
<% form_for :user, @user, :url => { :action => "account" },
|
||||
:builder => TabularFormBuilder,
|
||||
:lang => current_language,
|
||||
:html => { :id => 'my_account_form' } do |f| %>
|
||||
<div class="splitcontentleft">
|
||||
<h3><%=l(:label_information_plural)%></h3>
|
||||
<div class="box tabular">
|
||||
@@ -14,6 +17,7 @@
|
||||
<p><%= f.select :language, lang_options_for_select %></p>
|
||||
|
||||
<% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %>
|
||||
<p><%= pref_fields.select :time_zone, TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p>
|
||||
<p><%= pref_fields.check_box :hide_mail %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -28,10 +32,11 @@
|
||||
:onchange => 'if ($("notification_option").value == "selected") {Element.show("notified-projects")} else {Element.hide("notified-projects")}' %>
|
||||
<% content_tag 'div', :id => 'notified-projects', :style => (@notification_option == 'selected' ? '' : 'display:none;') do %>
|
||||
<p><% User.current.projects.each do |project| %>
|
||||
<label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%= project.name %></label><br />
|
||||
<label><%= check_box_tag 'notified_project_ids[]', project.id, @user.notified_projects_ids.include?(project.id) %> <%=h project.name %></label><br />
|
||||
<% end %></p>
|
||||
<p><em><%= l(:text_user_mail_option) %></em></p>
|
||||
<% end %>
|
||||
<p><label><%= check_box_tag 'no_self_notified', 1, @user.pref[:no_self_notified] %> <%= l(:label_user_mail_no_self_notified) %></label></p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -39,3 +44,5 @@
|
||||
<% content_for :sidebar do %>
|
||||
<%= render :partial => 'sidebar' %>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title l(:label_my_account) -%>
|
||||
|
||||
@@ -31,3 +31,12 @@
|
||||
<% end if @blocks['right'] %>
|
||||
</div>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'context_menu' %>
|
||||
<%= stylesheet_link_tag 'context_menu' %>
|
||||
<% end %>
|
||||
|
||||
<div id="context-menu" style="display: none;"></div>
|
||||
<%= javascript_tag 'new ContextMenu({})' %>
|
||||
|
||||
<% set_html_title l(:label_my_page) -%>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
|
||||
<%= password_field_tag 'new_password', nil, :size => 25 %><br />
|
||||
<em><%= l(:text_length_between, 4, 12) %></em></p>
|
||||
<em><%= l(:text_caracters_minimum, 4) %></em></p>
|
||||
|
||||
<p><label for="new_password_confirmation"><%=l(:field_password_confirmation)%> <span class="required">*</span></label>
|
||||
<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %></p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<p><%= link_to(h(news.project.name), :controller => 'projects', :action => 'show', :id => news.project) + ': ' unless @project %>
|
||||
<%= link_to h(news.title), :controller => 'news', :action => 'show', :id => news %>
|
||||
<%= "(#{news.comments_count} #{lwr(:label_comment, news.comments_count).downcase})" if news.comments_count > 0 %></span>
|
||||
<%= "(#{news.comments_count} #{lwr(:label_comment, news.comments_count).downcase})" if news.comments_count > 0 %>
|
||||
<br />
|
||||
<% unless news.summary.blank? %><span class="summary"><%=h news.summary %></span><br /><% end %>
|
||||
<span class="author"><%= authoring news.created_on, news.author %></p>
|
||||
<span class="author"><%= authoring news.created_on, news.author %></span></p>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<div class="contextual">
|
||||
<%= link_to_if_authorized l(:label_news_new),
|
||||
<%= link_to_if_authorized(l(:label_news_new),
|
||||
{:controller => 'projects', :action => 'add_news', :id => @project},
|
||||
:class => 'icon icon-add',
|
||||
:onclick => 'Element.show("add-news"); return false;' %>
|
||||
:onclick => 'Element.show("add-news"); return false;') if @project %>
|
||||
</div>
|
||||
|
||||
<div id="add-news" style="display:none;">
|
||||
<h2><%=l(:label_news_new)%></h2>
|
||||
<% labelled_tabular_form_for :news, @news, :url => { :action => "add_news", :id => @project } do |f| %>
|
||||
<% labelled_tabular_form_for :news, @news, :url => { :controller => 'projects', :action => "add_news", :id => @project } do |f| %>
|
||||
<%= render :partial => 'news/form', :locals => { :f => f } %>
|
||||
<%= submit_tag l(:button_create) %>
|
||||
<%= link_to l(:button_cancel), "#", :onclick => 'Element.hide("add-news")' %>
|
||||
<% end %>
|
||||
<% end if @project %>
|
||||
</div>
|
||||
|
||||
<h2><%=l(:label_news_plural)%></h2>
|
||||
@@ -20,7 +20,8 @@
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% else %>
|
||||
<% @newss.each do |news| %>
|
||||
<h3><%= link_to h(news.title), :controller => 'news', :action => 'show', :id => news %>
|
||||
<h3><%= link_to(h(news.project.name), :controller => 'projects', :action => 'show', :id => news.project) + ': ' unless news.project == @project %>
|
||||
<%= link_to h(news.title), :controller => 'news', :action => 'show', :id => news %>
|
||||
<%= "(#{news.comments_count} #{lwr(:label_comment, news.comments_count).downcase})" if news.comments_count > 0 %></h3>
|
||||
<p class="author"><%= authoring news.created_on, news.author %></p>
|
||||
<%= textilizable(news.description) %>
|
||||
@@ -31,3 +32,5 @@
|
||||
<% content_for :header_tags do %>
|
||||
<%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title l(:label_news_plural) -%>
|
||||
@@ -26,18 +26,21 @@
|
||||
<h3 class="icon22 icon22-comment"><%= l(:label_comment_plural) %></h3>
|
||||
<% @news.comments.each do |comment| %>
|
||||
<% next if comment.new_record? %>
|
||||
<h4><%= format_time(comment.created_on) %> - <%= comment.author.name %></h4>
|
||||
<h4><%= authoring comment.created_on, comment.author %></h4>
|
||||
<div class="contextual">
|
||||
<%= link_to_if_authorized l(:button_delete), {:controller => 'news', :action => 'destroy_comment', :id => @news, :comment_id => comment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
|
||||
</div>
|
||||
<%= simple_format(auto_link(h comment.comments))%>
|
||||
<%= textilizable(comment.comments) %>
|
||||
<% end if @news.comments_count > 0 %>
|
||||
</div>
|
||||
|
||||
<% if authorize_for 'news', 'add_comment' %>
|
||||
<p><%= toggle_link l(:label_comment_add), "add_comment_form", :focus => "comment_comments" %></p>
|
||||
<% form_tag({:action => 'add_comment', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %>
|
||||
<%= text_area 'comment', 'comments', :cols => 60, :rows => 6 %>
|
||||
<%= text_area 'comment', 'comments', :cols => 80, :rows => 15, :class => 'wiki-edit' %>
|
||||
<%= wikitoolbar_for 'comment_comments' %>
|
||||
<p><%= submit_tag l(:button_add) %></p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title(h(@news.title)) -%>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<% end %>
|
||||
|
||||
<p><%= f.text_area :description, :required => true, :cols => 60, :rows => 5 %><em><%= l(:text_caracters_maximum, 255) %></em></p>
|
||||
<p><%= f.text_field :identifier, :required => true, :size => 15, :disabled => @project.identifier_frozen? %><br /><em><%= l(:text_length_between, 3, 12) %> <%= l(:text_project_identifier_info) unless @project.identifier_frozen? %></em></p>
|
||||
<p><%= f.text_field :identifier, :required => true, :disabled => @project.identifier_frozen? %><br /><em><%= l(:text_length_between, 3, 20) %> <%= l(:text_project_identifier_info) unless @project.identifier_frozen? %></em></p>
|
||||
<p><%= f.text_field :homepage, :size => 40 %></p>
|
||||
<p><%= f.check_box :is_public %></p>
|
||||
<%= wikitoolbar_for 'project_description' %>
|
||||
@@ -17,16 +17,32 @@
|
||||
<% for @custom_value in @custom_values %>
|
||||
<p><%= custom_field_tag_with_label @custom_value %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% unless @trackers.empty? %>
|
||||
<fieldset class="box"><legend><%=l(:label_tracker_plural)%></legend>
|
||||
<% @trackers.each do |tracker| %>
|
||||
<label class="floating">
|
||||
<%= check_box_tag 'project[tracker_ids][]', tracker.id, @project.trackers.include?(tracker) %>
|
||||
<%= tracker %>
|
||||
</label>
|
||||
<% end %>
|
||||
<%= hidden_field_tag 'project[tracker_ids][]', '' %>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% unless @custom_fields.empty? %>
|
||||
<p><label><%=l(:label_custom_field_plural)%></label>
|
||||
<fieldset class="box"><legend><%=l(:label_custom_field_plural)%></legend>
|
||||
<% for custom_field in @custom_fields %>
|
||||
<label class="floating">
|
||||
<%= check_box_tag "custom_field_ids[]", custom_field.id, ((@project.custom_fields.include? custom_field) or custom_field.is_for_all?), (custom_field.is_for_all? ? {:disabled => "disabled"} : {}) %>
|
||||
<%= custom_field.name %>
|
||||
<% end %></p>
|
||||
<%= custom_field.name %>
|
||||
</label>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
<!--[eoform:project]-->
|
||||
</div>
|
||||
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'calendar/calendar' %>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<h3><%= day_name(day.cwday) %> <%= day.day %></h3>
|
||||
<ul>
|
||||
<% @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 />
|
||||
<li><p><%= format_time(e.event_datetime, false) %> <%= 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 %>
|
||||
@@ -39,3 +39,5 @@
|
||||
<p><%= submit_tag l(:button_apply), :class => 'button-small' %></p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% set_html_title l(:label_activity) -%>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<% labelled_tabular_form_for :project, @project, :url => { :action => "add" } do |f| %>
|
||||
<%= render :partial => 'form', :locals => { :f => f } %>
|
||||
|
||||
<div class="box">
|
||||
<p><label><%= l(:label_module_plural) %></label>
|
||||
<fieldset class="box"><legend><%= l(:label_module_plural) %></legend>
|
||||
<% Redmine::AccessControl.available_project_modules.each do |m| %>
|
||||
<%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) %> <%= m.to_s.humanize %>
|
||||
<% end %></p>
|
||||
</div>
|
||||
|
||||
<label class="floating">
|
||||
<%= check_box_tag 'enabled_modules[]', m, @project.module_enabled?(m) %> <%= m.to_s.humanize %>
|
||||
</label>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<% end %>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user