Revision 1298:4f746d8966dd .svn/pristine/20
| .svn/pristine/20/202b3d81f943caf51ec23281dde3cf26313ba319.svn-base | ||
|---|---|---|
| 1 |
<h2><%= link_to l(@enumeration.option_name), :controller => 'enumerations', :action => 'index' %> » <%=l(:label_enumeration_new)%></h2> |
|
| 2 |
|
|
| 3 |
<% form_tag({:action => 'create'}, :class => "tabular") do %>
|
|
| 4 |
<%= render :partial => 'form' %> |
|
| 5 |
<%= submit_tag l(:button_create) %> |
|
| 6 |
<% end %> |
|
| .svn/pristine/20/2087b528196b7332c8234e9ab56b21a9c4114103.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 |
require File.expand_path('../../test_helper', __FILE__)
|
|
| 19 |
|
|
| 20 |
class DefaultDataTest < ActiveSupport::TestCase |
|
| 21 |
include Redmine::I18n |
|
| 22 |
fixtures :roles |
|
| 23 |
|
|
| 24 |
def test_no_data |
|
| 25 |
assert !Redmine::DefaultData::Loader::no_data? |
|
| 26 |
Role.delete_all("builtin = 0")
|
|
| 27 |
Tracker.delete_all |
|
| 28 |
IssueStatus.delete_all |
|
| 29 |
Enumeration.delete_all |
|
| 30 |
assert Redmine::DefaultData::Loader::no_data? |
|
| 31 |
end |
|
| 32 |
|
|
| 33 |
def test_load |
|
| 34 |
valid_languages.each do |lang| |
|
| 35 |
begin |
|
| 36 |
Role.delete_all("builtin = 0")
|
|
| 37 |
Tracker.delete_all |
|
| 38 |
IssueStatus.delete_all |
|
| 39 |
Enumeration.delete_all |
|
| 40 |
assert Redmine::DefaultData::Loader::load(lang) |
|
| 41 |
assert_not_nil DocumentCategory.first |
|
| 42 |
assert_not_nil IssuePriority.first |
|
| 43 |
assert_not_nil TimeEntryActivity.first |
|
| 44 |
rescue ActiveRecord::RecordInvalid => e |
|
| 45 |
assert false, ":#{lang} default data is invalid (#{e.message})."
|
|
| 46 |
end |
|
| 47 |
end |
|
| 48 |
end |
|
| 49 |
end |
|
| .svn/pristine/20/2098d41250dd6484652b4b39b955e37f96aa4bb6.svn-base | ||
|---|---|---|
| 1 |
|
|
| 2 |
require 'active_record' |
|
| 3 |
|
|
| 4 |
module ActiveRecord |
|
| 5 |
class Base |
|
| 6 |
include Redmine::I18n |
|
| 7 |
|
|
| 8 |
# Translate attribute names for validation errors display |
|
| 9 |
def self.human_attribute_name(attr) |
|
| 10 |
l("field_#{attr.to_s.gsub(/_id$/, '')}", :default => attr)
|
|
| 11 |
end |
|
| 12 |
end |
|
| 13 |
end |
|
| 14 |
|
|
| 15 |
module ActiveRecord |
|
| 16 |
class Errors |
|
| 17 |
def full_messages(options = {})
|
|
| 18 |
full_messages = [] |
|
| 19 |
|
|
| 20 |
@errors.each_key do |attr| |
|
| 21 |
@errors[attr].each do |message| |
|
| 22 |
next unless message |
|
| 23 |
|
|
| 24 |
if attr == "base" |
|
| 25 |
full_messages << message |
|
| 26 |
elsif attr == "custom_values" |
|
| 27 |
# Replace the generic "custom values is invalid" |
|
| 28 |
# with the errors on custom values |
|
| 29 |
@base.custom_values.each do |value| |
|
| 30 |
value.errors.each do |attr, msg| |
|
| 31 |
full_messages << value.custom_field.name + ' ' + msg |
|
| 32 |
end |
|
| 33 |
end |
|
| 34 |
else |
|
| 35 |
attr_name = @base.class.human_attribute_name(attr) |
|
| 36 |
full_messages << attr_name + ' ' + message.to_s |
|
| 37 |
end |
|
| 38 |
end |
|
| 39 |
end |
|
| 40 |
full_messages |
|
| 41 |
end |
|
| 42 |
end |
|
| 43 |
end |
|
| 44 |
|
|
| 45 |
module ActionView |
|
| 46 |
module Helpers |
|
| 47 |
module DateHelper |
|
| 48 |
# distance_of_time_in_words breaks when difference is greater than 30 years |
|
| 49 |
def distance_of_date_in_words(from_date, to_date = 0, options = {})
|
|
| 50 |
from_date = from_date.to_date if from_date.respond_to?(:to_date) |
|
| 51 |
to_date = to_date.to_date if to_date.respond_to?(:to_date) |
|
| 52 |
distance_in_days = (to_date - from_date).abs |
|
| 53 |
|
|
| 54 |
I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale| |
|
| 55 |
case distance_in_days |
|
| 56 |
when 0..60 then locale.t :x_days, :count => distance_in_days.round |
|
| 57 |
when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round |
|
| 58 |
else locale.t :over_x_years, :count => (distance_in_days / 365).floor |
|
| 59 |
end |
|
| 60 |
end |
|
| 61 |
end |
|
| 62 |
end |
|
| 63 |
end |
|
| 64 |
end |
|
| 65 |
|
|
| 66 |
ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" }
|
|
| 67 |
|
|
| 68 |
module AsynchronousMailer |
|
| 69 |
# Adds :async_smtp and :async_sendmail delivery methods |
|
| 70 |
# to perform email deliveries asynchronously |
|
| 71 |
%w(smtp sendmail).each do |type| |
|
| 72 |
define_method("perform_delivery_async_#{type}") do |mail|
|
|
| 73 |
Thread.start do |
|
| 74 |
send "perform_delivery_#{type}", mail
|
|
| 75 |
end |
|
| 76 |
end |
|
| 77 |
end |
|
| 78 |
|
|
| 79 |
# Adds a delivery method that writes emails in tmp/emails for testing purpose |
|
| 80 |
def perform_delivery_tmp_file(mail) |
|
| 81 |
dest_dir = File.join(Rails.root, 'tmp', 'emails') |
|
| 82 |
Dir.mkdir(dest_dir) unless File.directory?(dest_dir) |
|
| 83 |
File.open(File.join(dest_dir, mail.message_id.gsub(/[<>]/, '') + '.eml'), 'wb') {|f| f.write(mail.encoded) }
|
|
| 84 |
end |
|
| 85 |
end |
|
| 86 |
|
|
| 87 |
ActionMailer::Base.send :include, AsynchronousMailer |
|
| 88 |
|
|
| 89 |
module TMail |
|
| 90 |
# TMail::Unquoter.convert_to_with_fallback_on_iso_8859_1 introduced in TMail 1.2.7 |
|
| 91 |
# triggers a test failure in test_add_issue_with_japanese_keywords(MailHandlerTest) |
|
| 92 |
class Unquoter |
|
| 93 |
class << self |
|
| 94 |
alias_method :convert_to, :convert_to_without_fallback_on_iso_8859_1 |
|
| 95 |
end |
|
| 96 |
end |
|
| 97 |
|
|
| 98 |
# Patch for TMail 1.2.7. See http://www.redmine.org/issues/8751 |
|
| 99 |
class Encoder |
|
| 100 |
def puts_meta(str) |
|
| 101 |
add_text str |
|
| 102 |
end |
|
| 103 |
end |
|
| 104 |
end |
|
| 105 |
|
|
| 106 |
module ActionController |
|
| 107 |
module MimeResponds |
|
| 108 |
class Responder |
|
| 109 |
def api(&block) |
|
| 110 |
any(:xml, :json, &block) |
|
| 111 |
end |
|
| 112 |
end |
|
| 113 |
end |
|
| 114 |
end |
|
| .svn/pristine/20/20aee30a3886ed67fbcf2637dc7c9a63361c83fd.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 Group < Principal |
|
| 19 |
include Redmine::SafeAttributes |
|
| 20 |
|
|
| 21 |
has_and_belongs_to_many :users, :after_add => :user_added, |
|
| 22 |
:after_remove => :user_removed |
|
| 23 |
|
|
| 24 |
acts_as_customizable |
|
| 25 |
|
|
| 26 |
validates_presence_of :lastname |
|
| 27 |
validates_uniqueness_of :lastname, :case_sensitive => false |
|
| 28 |
validates_length_of :lastname, :maximum => 255 |
|
| 29 |
|
|
| 30 |
before_destroy :remove_references_before_destroy |
|
| 31 |
|
|
| 32 |
scope :sorted, lambda { order("#{table_name}.lastname ASC") }
|
|
| 33 |
scope :named, lambda {|arg| where("LOWER(#{table_name}.lastname) = LOWER(?)", arg.to_s.strip)}
|
|
| 34 |
|
|
| 35 |
safe_attributes 'name', |
|
| 36 |
'user_ids', |
|
| 37 |
'custom_field_values', |
|
| 38 |
'custom_fields', |
|
| 39 |
:if => lambda {|group, user| user.admin?}
|
|
| 40 |
|
|
| 41 |
def to_s |
|
| 42 |
lastname.to_s |
|
| 43 |
end |
|
| 44 |
|
|
| 45 |
def name |
|
| 46 |
lastname |
|
| 47 |
end |
|
| 48 |
|
|
| 49 |
def name=(arg) |
|
| 50 |
self.lastname = arg |
|
| 51 |
end |
|
| 52 |
|
|
| 53 |
def user_added(user) |
|
| 54 |
members.each do |member| |
|
| 55 |
next if member.project.nil? |
|
| 56 |
user_member = Member.find_by_project_id_and_user_id(member.project_id, user.id) || Member.new(:project_id => member.project_id, :user_id => user.id) |
|
| 57 |
member.member_roles.each do |member_role| |
|
| 58 |
user_member.member_roles << MemberRole.new(:role => member_role.role, :inherited_from => member_role.id) |
|
| 59 |
end |
|
| 60 |
user_member.save! |
|
| 61 |
end |
|
| 62 |
end |
|
| 63 |
|
|
| 64 |
def user_removed(user) |
|
| 65 |
members.each do |member| |
|
| 66 |
MemberRole. |
|
| 67 |
includes(:member). |
|
| 68 |
where("#{Member.table_name}.user_id = ? AND #{MemberRole.table_name}.inherited_from IN (?)", user.id, member.member_role_ids).
|
|
| 69 |
all. |
|
| 70 |
each(&:destroy) |
|
| 71 |
end |
|
| 72 |
end |
|
| 73 |
|
|
| 74 |
def self.human_attribute_name(attribute_key_name, *args) |
|
| 75 |
attr_name = attribute_key_name.to_s |
|
| 76 |
if attr_name == 'lastname' |
|
| 77 |
attr_name = "name" |
|
| 78 |
end |
|
| 79 |
super(attr_name, *args) |
|
| 80 |
end |
|
| 81 |
|
|
| 82 |
private |
|
| 83 |
|
|
| 84 |
# Removes references that are not handled by associations |
|
| 85 |
def remove_references_before_destroy |
|
| 86 |
return if self.id.nil? |
|
| 87 |
|
|
| 88 |
Issue.update_all 'assigned_to_id = NULL', ['assigned_to_id = ?', id] |
|
| 89 |
end |
|
| 90 |
end |
|
| .svn/pristine/20/20bbceb95e51f40dbb36d0ff4569d0437a37f449.svn-base | ||
|---|---|---|
| 1 |
// ** I18N |
|
| 2 |
|
|
| 3 |
// Calendar SL language |
|
| 4 |
// Author: Jernej Vidmar, <jernej.vidmar@vidmarboehm.com> |
|
| 5 |
// Encoding: any |
|
| 6 |
// Distributed under the same terms as the calendar itself. |
|
| 7 |
|
|
| 8 |
// For translators: please use UTF-8 if possible. We strongly believe that |
|
| 9 |
// Unicode is the answer to a real internationalized world. Also please |
|
| 10 |
// include your contact information in the header, as can be seen above. |
|
| 11 |
|
|
| 12 |
// full day names |
|
| 13 |
Calendar._DN = new Array |
|
| 14 |
("Nedelja",
|
|
| 15 |
"Ponedeljek", |
|
| 16 |
"Torek", |
|
| 17 |
"Sreda", |
|
| 18 |
"Četrtek", |
|
| 19 |
"Petek", |
|
| 20 |
"Sobota", |
|
| 21 |
"Nedelja"); |
|
| 22 |
|
|
| 23 |
// Please note that the following array of short day names (and the same goes |
|
| 24 |
// for short month names, _SMN) isn't absolutely necessary. We give it here |
|
| 25 |
// for exemplification on how one can customize the short day names, but if |
|
| 26 |
// they are simply the first N letters of the full name you can simply say: |
|
| 27 |
// |
|
| 28 |
// Calendar._SDN_len = N; // short day name length |
|
| 29 |
// Calendar._SMN_len = N; // short month name length |
|
| 30 |
// |
|
| 31 |
// If N = 3 then this is not needed either since we assume a value of 3 if not |
|
| 32 |
// present, to be compatible with translation files that were written before |
|
| 33 |
// this feature. |
|
| 34 |
|
|
| 35 |
// short day names |
|
| 36 |
Calendar._SDN = new Array |
|
| 37 |
("Ned",
|
|
| 38 |
"Pon", |
|
| 39 |
"Tor", |
|
| 40 |
"Sre", |
|
| 41 |
"Čet", |
|
| 42 |
"Pet", |
|
| 43 |
"Sob", |
|
| 44 |
"Ned"); |
|
| 45 |
|
|
| 46 |
// First day of the week. "0" means display Sunday first, "1" means display |
|
| 47 |
// Monday first, etc. |
|
| 48 |
Calendar._FD = 0; |
|
| 49 |
|
|
| 50 |
// full month names |
|
| 51 |
Calendar._MN = new Array |
|
| 52 |
("Januar",
|
|
| 53 |
"Februar", |
|
| 54 |
"Marec", |
|
| 55 |
"April", |
|
| 56 |
"Maj", |
|
| 57 |
"Junij", |
|
| 58 |
"Julij", |
|
| 59 |
"Avgust", |
|
| 60 |
"September", |
|
| 61 |
"Oktober", |
|
| 62 |
"November", |
|
| 63 |
"December"); |
|
| 64 |
|
|
| 65 |
// short month names |
|
| 66 |
Calendar._SMN = new Array |
|
| 67 |
("Jan",
|
|
| 68 |
"Feb", |
|
| 69 |
"Mar", |
|
| 70 |
"Apr", |
|
| 71 |
"Maj", |
|
| 72 |
"Jun", |
|
| 73 |
"Jul", |
|
| 74 |
"Avg", |
|
| 75 |
"Sep", |
|
| 76 |
"Okt", |
|
| 77 |
"Nov", |
|
| 78 |
"Dec"); |
|
| 79 |
|
|
| 80 |
// tooltips |
|
| 81 |
Calendar._TT = {};
|
|
| 82 |
Calendar._TT["INFO"] = "O koledarju"; |
|
| 83 |
|
|
| 84 |
Calendar._TT["ABOUT"] = |
|
| 85 |
"DHTML Date/Time Selector\n" + |
|
| 86 |
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) |
|
| 87 |
"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + |
|
| 88 |
"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + |
|
| 89 |
"\n\n" + |
|
| 90 |
"Izbira datuma:\n" + |
|
| 91 |
"- Uporabite \xab, \xbb gumbe za izbiro leta\n" + |
|
| 92 |
"- Uporabite " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " gumbe za izbiro meseca\n" + |
|
| 93 |
"- Za hitrejšo izbiro držite miškin gumb nad enim od zgornjih gumbov."; |
|
| 94 |
Calendar._TT["ABOUT_TIME"] = "\n\n" + |
|
| 95 |
"Izbira časa:\n" + |
|
| 96 |
"- Kliknite na katerikoli del časa da ga povečate\n" + |
|
| 97 |
"- oziroma kliknite s Shiftom za znižanje\n" + |
|
| 98 |
"- ali kliknite in vlecite za hitrejšo izbiro."; |
|
| 99 |
|
|
| 100 |
Calendar._TT["PREV_YEAR"] = "Prejšnje leto (držite za meni)"; |
|
| 101 |
Calendar._TT["PREV_MONTH"] = "Prejšnji mesec (držite za meni)"; |
|
| 102 |
Calendar._TT["GO_TODAY"] = "Pojdi na danes"; |
|
| 103 |
Calendar._TT["NEXT_MONTH"] = "Naslednji mesec (držite za meni)"; |
|
| 104 |
Calendar._TT["NEXT_YEAR"] = "Naslednje leto (držite za meni)"; |
|
| 105 |
Calendar._TT["SEL_DATE"] = "Izberite datum"; |
|
| 106 |
Calendar._TT["DRAG_TO_MOVE"] = "Povlecite za premik"; |
|
| 107 |
Calendar._TT["PART_TODAY"] = " (danes)"; |
|
| 108 |
|
|
| 109 |
// the following is to inform that "%s" is to be the first day of week |
|
| 110 |
// %s will be replaced with the day name. |
|
| 111 |
Calendar._TT["DAY_FIRST"] = "Najprej prikaži %s"; |
|
| 112 |
|
|
| 113 |
// This may be locale-dependent. It specifies the week-end days, as an array |
|
| 114 |
// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 |
|
| 115 |
// means Monday, etc. |
|
| 116 |
Calendar._TT["WEEKEND"] = "0,6"; |
|
| 117 |
|
|
| 118 |
Calendar._TT["CLOSE"] = "Zapri"; |
|
| 119 |
Calendar._TT["TODAY"] = "Danes"; |
|
| 120 |
Calendar._TT["TIME_PART"] = "(Shift-)klik ali povleči, da spremeniš vrednost"; |
|
| 121 |
|
|
| 122 |
// date formats |
|
| 123 |
Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; |
|
| 124 |
Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; |
|
| 125 |
|
|
| 126 |
Calendar._TT["WK"] = "wk"; |
|
| 127 |
Calendar._TT["TIME"] = "Time:"; |
|
| .svn/pristine/20/20cfc1def6cf64da0d22e9f4697140fef8698ede.svn-base | ||
|---|---|---|
| 1 |
class AddUniqueIndexOnCustomFieldsTrackers < ActiveRecord::Migration |
|
| 2 |
def up |
|
| 3 |
table_name = "#{CustomField.table_name_prefix}custom_fields_trackers#{CustomField.table_name_suffix}"
|
|
| 4 |
duplicates = CustomField.connection.select_rows("SELECT custom_field_id, tracker_id FROM #{table_name} GROUP BY custom_field_id, tracker_id HAVING COUNT(*) > 1")
|
|
| 5 |
duplicates.each do |custom_field_id, tracker_id| |
|
| 6 |
# Removes duplicate rows |
|
| 7 |
CustomField.connection.execute("DELETE FROM #{table_name} WHERE custom_field_id=#{custom_field_id} AND tracker_id=#{tracker_id}")
|
|
| 8 |
# And insert one |
|
| 9 |
CustomField.connection.execute("INSERT INTO #{table_name} (custom_field_id, tracker_id) VALUES (#{custom_field_id}, #{tracker_id})")
|
|
| 10 |
end |
|
| 11 |
|
|
| 12 |
if index_exists? :custom_fields_trackers, [:custom_field_id, :tracker_id] |
|
| 13 |
remove_index :custom_fields_trackers, [:custom_field_id, :tracker_id] |
|
| 14 |
end |
|
| 15 |
add_index :custom_fields_trackers, [:custom_field_id, :tracker_id], :unique => true |
|
| 16 |
end |
|
| 17 |
|
|
| 18 |
def down |
|
| 19 |
if index_exists? :custom_fields_trackers, [:custom_field_id, :tracker_id] |
|
| 20 |
remove_index :custom_fields_trackers, [:custom_field_id, :tracker_id] |
|
| 21 |
end |
|
| 22 |
add_index :custom_fields_trackers, [:custom_field_id, :tracker_id] |
|
| 23 |
end |
|
| 24 |
end |
|
Also available in: Unified diff