Revision 1298:4f746d8966dd .svn/pristine/48
| .svn/pristine/48/4829d2fe162c5f9c318c8ff9b05ff5fc25513144.svn-base | ||
|---|---|---|
| 1 |
# encoding: utf-8 |
|
| 2 |
# |
|
| 3 |
# Redmine - project management software |
|
| 4 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 5 |
# |
|
| 6 |
# This program is free software; you can redistribute it and/or |
|
| 7 |
# modify it under the terms of the GNU General Public License |
|
| 8 |
# as published by the Free Software Foundation; either version 2 |
|
| 9 |
# of the License, or (at your option) any later version. |
|
| 10 |
# |
|
| 11 |
# This program is distributed in the hope that it will be useful, |
|
| 12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 14 |
# GNU General Public License for more details. |
|
| 15 |
# |
|
| 16 |
# You should have received a copy of the GNU General Public License |
|
| 17 |
# along with this program; if not, write to the Free Software |
|
| 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 19 |
|
|
| 20 |
module WelcomeHelper |
|
| 21 |
end |
|
| .svn/pristine/48/482dc54fc612e4f812361911050f6c949928488f.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
class CustomFieldValue |
|
| 19 |
attr_accessor :custom_field, :customized, :value |
|
| 20 |
|
|
| 21 |
def custom_field_id |
|
| 22 |
custom_field.id |
|
| 23 |
end |
|
| 24 |
|
|
| 25 |
def true? |
|
| 26 |
self.value == '1' |
|
| 27 |
end |
|
| 28 |
|
|
| 29 |
def editable? |
|
| 30 |
custom_field.editable? |
|
| 31 |
end |
|
| 32 |
|
|
| 33 |
def visible? |
|
| 34 |
custom_field.visible? |
|
| 35 |
end |
|
| 36 |
|
|
| 37 |
def required? |
|
| 38 |
custom_field.is_required? |
|
| 39 |
end |
|
| 40 |
|
|
| 41 |
def to_s |
|
| 42 |
value.to_s |
|
| 43 |
end |
|
| 44 |
|
|
| 45 |
def validate_value |
|
| 46 |
custom_field.validate_field_value(value).each do |message| |
|
| 47 |
customized.errors.add(:base, custom_field.name + ' ' + message) |
|
| 48 |
end |
|
| 49 |
end |
|
| 50 |
end |
|
| .svn/pristine/48/4852f1cf9dc40b28e85de8175f26734a857d7d04.svn-base | ||
|---|---|---|
| 1 |
class SharedEngineController < ApplicationController |
|
| 2 |
def an_action |
|
| 3 |
render_class_and_action 'from alpha_engine' |
|
| 4 |
end |
|
| 5 |
end |
|
| .svn/pristine/48/4881b5ad6e4efa4165188246776dbe492c56e6df.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
class Principal < ActiveRecord::Base |
|
| 19 |
self.table_name = "#{table_name_prefix}users#{table_name_suffix}"
|
|
| 20 |
|
|
| 21 |
# Account statuses |
|
| 22 |
STATUS_ANONYMOUS = 0 |
|
| 23 |
STATUS_ACTIVE = 1 |
|
| 24 |
STATUS_REGISTERED = 2 |
|
| 25 |
STATUS_LOCKED = 3 |
|
| 26 |
|
|
| 27 |
has_many :members, :foreign_key => 'user_id', :dependent => :destroy |
|
| 28 |
has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status<>#{Project::STATUS_ARCHIVED}", :order => "#{Project.table_name}.name"
|
|
| 29 |
has_many :projects, :through => :memberships |
|
| 30 |
has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify |
|
| 31 |
|
|
| 32 |
# Groups and active users |
|
| 33 |
scope :active, lambda { where(:status => STATUS_ACTIVE) }
|
|
| 34 |
|
|
| 35 |
scope :like, lambda {|q|
|
|
| 36 |
q = q.to_s |
|
| 37 |
if q.blank? |
|
| 38 |
where({})
|
|
| 39 |
else |
|
| 40 |
pattern = "%#{q}%"
|
|
| 41 |
sql = %w(login firstname lastname mail).map {|column| "LOWER(#{table_name}.#{column}) LIKE LOWER(:p)"}.join(" OR ")
|
|
| 42 |
params = {:p => pattern}
|
|
| 43 |
if q =~ /^(.+)\s+(.+)$/ |
|
| 44 |
a, b = "#{$1}%", "#{$2}%"
|
|
| 45 |
sql << " OR (LOWER(#{table_name}.firstname) LIKE LOWER(:a) AND LOWER(#{table_name}.lastname) LIKE LOWER(:b))"
|
|
| 46 |
sql << " OR (LOWER(#{table_name}.firstname) LIKE LOWER(:b) AND LOWER(#{table_name}.lastname) LIKE LOWER(:a))"
|
|
| 47 |
params.merge!(:a => a, :b => b) |
|
| 48 |
end |
|
| 49 |
where(sql, params) |
|
| 50 |
end |
|
| 51 |
} |
|
| 52 |
|
|
| 53 |
# Principals that are members of a collection of projects |
|
| 54 |
scope :member_of, lambda {|projects|
|
|
| 55 |
projects = [projects] unless projects.is_a?(Array) |
|
| 56 |
if projects.empty? |
|
| 57 |
where("1=0")
|
|
| 58 |
else |
|
| 59 |
ids = projects.map(&:id) |
|
| 60 |
active.uniq.joins(:members).where("#{Member.table_name}.project_id IN (?)", ids)
|
|
| 61 |
end |
|
| 62 |
} |
|
| 63 |
# Principals that are not members of projects |
|
| 64 |
scope :not_member_of, lambda {|projects|
|
|
| 65 |
projects = [projects] unless projects.is_a?(Array) |
|
| 66 |
if projects.empty? |
|
| 67 |
where("1=0")
|
|
| 68 |
else |
|
| 69 |
ids = projects.map(&:id) |
|
| 70 |
where("#{Principal.table_name}.id NOT IN (SELECT DISTINCT user_id FROM #{Member.table_name} WHERE project_id IN (?))", ids)
|
|
| 71 |
end |
|
| 72 |
} |
|
| 73 |
scope :sorted, lambda { order(*Principal.fields_for_order_statement)}
|
|
| 74 |
|
|
| 75 |
before_create :set_default_empty_values |
|
| 76 |
|
|
| 77 |
def name(formatter = nil) |
|
| 78 |
to_s |
|
| 79 |
end |
|
| 80 |
|
|
| 81 |
def <=>(principal) |
|
| 82 |
if principal.nil? |
|
| 83 |
-1 |
|
| 84 |
elsif self.class.name == principal.class.name |
|
| 85 |
self.to_s.downcase <=> principal.to_s.downcase |
|
| 86 |
else |
|
| 87 |
# groups after users |
|
| 88 |
principal.class.name <=> self.class.name |
|
| 89 |
end |
|
| 90 |
end |
|
| 91 |
|
|
| 92 |
# Returns an array of fields names than can be used to make an order statement for principals. |
|
| 93 |
# Users are sorted before Groups. |
|
| 94 |
# Examples: |
|
| 95 |
def self.fields_for_order_statement(table=nil) |
|
| 96 |
table ||= table_name |
|
| 97 |
columns = ['type DESC'] + (User.name_formatter[:order] - ['id']) + ['lastname', 'id'] |
|
| 98 |
columns.uniq.map {|field| "#{table}.#{field}"}
|
|
| 99 |
end |
|
| 100 |
|
|
| 101 |
protected |
|
| 102 |
|
|
| 103 |
# Make sure we don't try to insert NULL values (see #4632) |
|
| 104 |
def set_default_empty_values |
|
| 105 |
self.login ||= '' |
|
| 106 |
self.hashed_password ||= '' |
|
| 107 |
self.firstname ||= '' |
|
| 108 |
self.lastname ||= '' |
|
| 109 |
self.mail ||= '' |
|
| 110 |
true |
|
| 111 |
end |
|
| 112 |
end |
|
| .svn/pristine/48/48978cef54e6b0d716c9ba5b5c6c5a3e24326336.svn-base | ||
|---|---|---|
| 1 |
# encoding: utf-8 |
|
| 2 |
# |
|
| 3 |
# Redmine - project management software |
|
| 4 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 5 |
# |
|
| 6 |
# This program is free software; you can redistribute it and/or |
|
| 7 |
# modify it under the terms of the GNU General Public License |
|
| 8 |
# as published by the Free Software Foundation; either version 2 |
|
| 9 |
# of the License, or (at your option) any later version. |
|
| 10 |
# |
|
| 11 |
# This program is distributed in the hope that it will be useful, |
|
| 12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 14 |
# GNU General Public License for more details. |
|
| 15 |
# |
|
| 16 |
# You should have received a copy of the GNU General Public License |
|
| 17 |
# along with this program; if not, write to the Free Software |
|
| 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 19 |
|
|
| 20 |
module TimelogHelper |
|
| 21 |
include ApplicationHelper |
|
| 22 |
|
|
| 23 |
def render_timelog_breadcrumb |
|
| 24 |
links = [] |
|
| 25 |
links << link_to(l(:label_project_all), {:project_id => nil, :issue_id => nil})
|
|
| 26 |
links << link_to(h(@project), {:project_id => @project, :issue_id => nil}) if @project
|
|
| 27 |
if @issue |
|
| 28 |
if @issue.visible? |
|
| 29 |
links << link_to_issue(@issue, :subject => false) |
|
| 30 |
else |
|
| 31 |
links << "##{@issue.id}"
|
|
| 32 |
end |
|
| 33 |
end |
|
| 34 |
breadcrumb links |
|
| 35 |
end |
|
| 36 |
|
|
| 37 |
# Returns a collection of activities for a select field. time_entry |
|
| 38 |
# is optional and will be used to check if the selected TimeEntryActivity |
|
| 39 |
# is active. |
|
| 40 |
def activity_collection_for_select_options(time_entry=nil, project=nil) |
|
| 41 |
project ||= @project |
|
| 42 |
if project.nil? |
|
| 43 |
activities = TimeEntryActivity.shared.active |
|
| 44 |
else |
|
| 45 |
activities = project.activities |
|
| 46 |
end |
|
| 47 |
|
|
| 48 |
collection = [] |
|
| 49 |
if time_entry && time_entry.activity && !time_entry.activity.active? |
|
| 50 |
collection << [ "--- #{l(:actionview_instancetag_blank_option)} ---", '' ]
|
|
| 51 |
else |
|
| 52 |
collection << [ "--- #{l(:actionview_instancetag_blank_option)} ---", '' ] unless activities.detect(&:is_default)
|
|
| 53 |
end |
|
| 54 |
activities.each { |a| collection << [a.name, a.id] }
|
|
| 55 |
collection |
|
| 56 |
end |
|
| 57 |
|
|
| 58 |
def select_hours(data, criteria, value) |
|
| 59 |
if value.to_s.empty? |
|
| 60 |
data.select {|row| row[criteria].blank? }
|
|
| 61 |
else |
|
| 62 |
data.select {|row| row[criteria].to_s == value.to_s}
|
|
| 63 |
end |
|
| 64 |
end |
|
| 65 |
|
|
| 66 |
def sum_hours(data) |
|
| 67 |
sum = 0 |
|
| 68 |
data.each do |row| |
|
| 69 |
sum += row['hours'].to_f |
|
| 70 |
end |
|
| 71 |
sum |
|
| 72 |
end |
|
| 73 |
|
|
| 74 |
def options_for_period_select(value) |
|
| 75 |
options_for_select([[l(:label_all_time), 'all'], |
|
| 76 |
[l(:label_today), 'today'], |
|
| 77 |
[l(:label_yesterday), 'yesterday'], |
|
| 78 |
[l(:label_this_week), 'current_week'], |
|
| 79 |
[l(:label_last_week), 'last_week'], |
|
| 80 |
[l(:label_last_n_weeks, 2), 'last_2_weeks'], |
|
| 81 |
[l(:label_last_n_days, 7), '7_days'], |
|
| 82 |
[l(:label_this_month), 'current_month'], |
|
| 83 |
[l(:label_last_month), 'last_month'], |
|
| 84 |
[l(:label_last_n_days, 30), '30_days'], |
|
| 85 |
[l(:label_this_year), 'current_year']], |
|
| 86 |
value) |
|
| 87 |
end |
|
| 88 |
|
|
| 89 |
def format_criteria_value(criteria_options, value) |
|
| 90 |
if value.blank? |
|
| 91 |
"[#{l(:label_none)}]"
|
|
| 92 |
elsif k = criteria_options[:klass] |
|
| 93 |
obj = k.find_by_id(value.to_i) |
|
| 94 |
if obj.is_a?(Issue) |
|
| 95 |
obj.visible? ? "#{obj.tracker} ##{obj.id}: #{obj.subject}" : "##{obj.id}"
|
|
| 96 |
else |
|
| 97 |
obj |
|
| 98 |
end |
|
| 99 |
else |
|
| 100 |
format_value(value, criteria_options[:format]) |
|
| 101 |
end |
|
| 102 |
end |
|
| 103 |
|
|
| 104 |
def report_to_csv(report) |
|
| 105 |
decimal_separator = l(:general_csv_decimal_separator) |
|
| 106 |
export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| |
|
| 107 |
# Column headers |
|
| 108 |
headers = report.criteria.collect {|criteria| l(report.available_criteria[criteria][:label]) }
|
|
| 109 |
headers += report.periods |
|
| 110 |
headers << l(:label_total_time) |
|
| 111 |
csv << headers.collect {|c| Redmine::CodesetUtil.from_utf8(
|
|
| 112 |
c.to_s, |
|
| 113 |
l(:general_csv_encoding) ) } |
|
| 114 |
# Content |
|
| 115 |
report_criteria_to_csv(csv, report.available_criteria, report.columns, report.criteria, report.periods, report.hours) |
|
| 116 |
# Total row |
|
| 117 |
str_total = Redmine::CodesetUtil.from_utf8(l(:label_total_time), l(:general_csv_encoding)) |
|
| 118 |
row = [ str_total ] + [''] * (report.criteria.size - 1) |
|
| 119 |
total = 0 |
|
| 120 |
report.periods.each do |period| |
|
| 121 |
sum = sum_hours(select_hours(report.hours, report.columns, period.to_s)) |
|
| 122 |
total += sum |
|
| 123 |
row << (sum > 0 ? ("%.2f" % sum).gsub('.',decimal_separator) : '')
|
|
| 124 |
end |
|
| 125 |
row << ("%.2f" % total).gsub('.',decimal_separator)
|
|
| 126 |
csv << row |
|
| 127 |
end |
|
| 128 |
export |
|
| 129 |
end |
|
| 130 |
|
|
| 131 |
def report_criteria_to_csv(csv, available_criteria, columns, criteria, periods, hours, level=0) |
|
| 132 |
decimal_separator = l(:general_csv_decimal_separator) |
|
| 133 |
hours.collect {|h| h[criteria[level]].to_s}.uniq.each do |value|
|
|
| 134 |
hours_for_value = select_hours(hours, criteria[level], value) |
|
| 135 |
next if hours_for_value.empty? |
|
| 136 |
row = [''] * level |
|
| 137 |
row << Redmine::CodesetUtil.from_utf8( |
|
| 138 |
format_criteria_value(available_criteria[criteria[level]], value).to_s, |
|
| 139 |
l(:general_csv_encoding) ) |
|
| 140 |
row += [''] * (criteria.length - level - 1) |
|
| 141 |
total = 0 |
|
| 142 |
periods.each do |period| |
|
| 143 |
sum = sum_hours(select_hours(hours_for_value, columns, period.to_s)) |
|
| 144 |
total += sum |
|
| 145 |
row << (sum > 0 ? ("%.2f" % sum).gsub('.',decimal_separator) : '')
|
|
| 146 |
end |
|
| 147 |
row << ("%.2f" % total).gsub('.',decimal_separator)
|
|
| 148 |
csv << row |
|
| 149 |
if criteria.length > level + 1 |
|
| 150 |
report_criteria_to_csv(csv, available_criteria, columns, criteria, periods, hours_for_value, level + 1) |
|
| 151 |
end |
|
| 152 |
end |
|
| 153 |
end |
|
| 154 |
end |
|
| .svn/pristine/48/48b2840db60b271c593d21c38917c44a5158b68b.svn-base | ||
|---|---|---|
| 1 |
# Rails <2.x doesn't define #except |
|
| 2 |
class Hash #:nodoc: |
|
| 3 |
# Returns a new hash without the given keys. |
|
| 4 |
def except(*keys) |
|
| 5 |
clone.except!(*keys) |
|
| 6 |
end unless method_defined?(:except) |
|
| 7 |
|
|
| 8 |
# Replaces the hash without the given keys. |
|
| 9 |
def except!(*keys) |
|
| 10 |
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
|
|
| 11 |
keys.each { |key| delete(key) }
|
|
| 12 |
self |
|
| 13 |
end unless method_defined?(:except!) |
|
| 14 |
end |
|
| 15 |
|
|
| 16 |
# NamedScope is new to Rails 2.1 |
|
| 17 |
unless defined? ActiveRecord::NamedScope |
|
| 18 |
require 'awesome_nested_set/named_scope' |
|
| 19 |
ActiveRecord::Base.class_eval do |
|
| 20 |
include CollectiveIdea::NamedScope |
|
| 21 |
end |
|
| 22 |
end |
|
| 23 |
|
|
| 24 |
# Rails 1.2.x doesn't define #quoted_table_name |
|
| 25 |
class ActiveRecord::Base #:nodoc: |
|
| 26 |
def self.quoted_table_name |
|
| 27 |
self.connection.quote_column_name(self.table_name) |
|
| 28 |
end unless methods.include?('quoted_table_name')
|
|
| 29 |
end |
|
| .svn/pristine/48/48b4396c87b793f88c5ab4bc586ea45f81977244.svn-base | ||
|---|---|---|
| 1 |
<%= error_messages_for 'message' %> |
|
| 2 |
<% replying ||= false %> |
|
| 3 |
|
|
| 4 |
<div class="box"> |
|
| 5 |
<!--[form:message]--> |
|
| 6 |
<p><label for="message_subject"><%= l(:field_subject) %></label><br /> |
|
| 7 |
<%= f.text_field :subject, :size => 120, :id => "message_subject" %> |
|
| 8 |
|
|
| 9 |
<% if !replying && User.current.allowed_to?(:edit_messages, @project) %> |
|
| 10 |
<label><%= f.check_box :sticky %><%= l(:label_board_sticky) %></label> |
|
| 11 |
<label><%= f.check_box :locked %><%= l(:label_board_locked) %></label> |
|
| 12 |
<% end %> |
|
| 13 |
</p> |
|
| 14 |
|
|
| 15 |
<% if !replying && !@message.new_record? && User.current.allowed_to?(:edit_messages, @project) %> |
|
| 16 |
<p><label><%= l(:label_board) %></label><br /> |
|
| 17 |
<%= f.select :board_id, @project.boards.collect {|b| [b.name, b.id]} %></p>
|
|
| 18 |
<% end %> |
|
| 19 |
|
|
| 20 |
<p> |
|
| 21 |
<%= label_tag "message_content", l(:description_message_content), :class => "hidden-for-sighted" %> |
|
| 22 |
<%= f.text_area :content, :cols => 80, :rows => 15, :class => 'wiki-edit', :id => 'message_content' %></p> |
|
| 23 |
<%= wikitoolbar_for 'message_content' %> |
|
| 24 |
<!--[eoform:message]--> |
|
| 25 |
|
|
| 26 |
<p><%= l(:label_attachment_plural) %><br /> |
|
| 27 |
<%= render :partial => 'attachments/form' %></p> |
|
| 28 |
</div> |
|
Also available in: Unified diff