Merged r2109, r2118, r2130, r2131, r2134, r2135, r2136 and r2139 to r2145 from trunk.

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2146 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2008-12-19 11:45:33 +00:00
parent 4570fcb7a2
commit 7389b4bed0
28 changed files with 767 additions and 691 deletions

View File

@ -19,6 +19,7 @@ require 'diff'
class WikiController < ApplicationController class WikiController < ApplicationController
before_filter :find_wiki, :authorize before_filter :find_wiki, :authorize
before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index } verify :method => :post, :only => [:destroy, :destroy_attachment, :protect], :redirect_to => { :action => :index }
@ -91,8 +92,7 @@ class WikiController < ApplicationController
# rename a page # rename a page
def rename def rename
@page = @wiki.find_page(params[:page]) return render_403 unless editable?
return render_403 unless editable?
@page.redirect_existing_links = true @page.redirect_existing_links = true
# used to display the *original* title if some AR validation errors occur # used to display the *original* title if some AR validation errors occur
@original_title = @page.pretty_title @original_title = @page.pretty_title
@ -103,15 +103,12 @@ class WikiController < ApplicationController
end end
def protect def protect
page = @wiki.find_page(params[:page]) @page.update_attribute :protected, params[:protected]
page.update_attribute :protected, params[:protected] redirect_to :action => 'index', :id => @project, :page => @page.title
redirect_to :action => 'index', :id => @project, :page => page.title
end end
# show page history # show page history
def history def history
@page = @wiki.find_page(params[:page])
@version_count = @page.content.versions.count @version_count = @page.content.versions.count
@version_pages = Paginator.new self, @version_count, per_page_option, params['p'] @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
# don't load text # don't load text
@ -125,21 +122,19 @@ class WikiController < ApplicationController
end end
def diff def diff
@page = @wiki.find_page(params[:page])
@diff = @page.diff(params[:version], params[:version_from]) @diff = @page.diff(params[:version], params[:version_from])
render_404 unless @diff render_404 unless @diff
end end
def annotate def annotate
@page = @wiki.find_page(params[:page])
@annotate = @page.annotate(params[:version]) @annotate = @page.annotate(params[:version])
render_404 unless @annotate
end end
# remove a wiki page and its history # remove a wiki page and its history
def destroy def destroy
@page = @wiki.find_page(params[:page]) return render_403 unless editable?
return render_403 unless editable? @page.destroy
@page.destroy if @page
redirect_to :action => 'special', :id => @project, :page => 'Page_index' redirect_to :action => 'special', :id => @project, :page => 'Page_index'
end end
@ -181,7 +176,6 @@ class WikiController < ApplicationController
end end
def add_attachment def add_attachment
@page = @wiki.find_page(params[:page])
return render_403 unless editable? return render_403 unless editable?
attach_files(@page, params[:attachments]) attach_files(@page, params[:attachments])
redirect_to :action => 'index', :page => @page.title redirect_to :action => 'index', :page => @page.title
@ -204,6 +198,12 @@ private
render_404 render_404
end end
# Finds the requested page and returns a 404 error if it doesn't exist
def find_existing_page
@page = @wiki.find_page(params[:page])
render_404 if @page.nil?
end
# Returns true if the current user is allowed to edit the page, otherwise false # Returns true if the current user is allowed to edit the page, otherwise false
def editable?(page = @page) def editable?(page = @page)
page.editable_by?(User.current) page.editable_by?(User.current)

View File

@ -48,8 +48,8 @@ module ApplicationHelper
end end
# Display a link to user's account page # Display a link to user's account page
def link_to_user(user) def link_to_user(user, options={})
(user && !user.anonymous?) ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous' (user && !user.anonymous?) ? link_to(user.name(options[:format]), :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
end end
def link_to_issue(issue, options={}) def link_to_issue(issue, options={})

View File

@ -33,6 +33,13 @@ module IssuesHelper
"<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}" "<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
end end
# Returns a string of css classes that apply to the given issue
def css_issue_classes(issue)
s = "issue status-#{issue.status.position} priority-#{issue.priority.position}"
s << ' overdue' if issue.overdue?
s
end
def sidebar_queries def sidebar_queries
unless @sidebar_queries unless @sidebar_queries
# User can see public queries and his own queries # User can see public queries and his own queries

View File

@ -195,6 +195,11 @@ class Issue < ActiveRecord::Base
self.status.is_closed? self.status.is_closed?
end end
# Returns true if the issue is overdue
def overdue?
!due_date.nil? && (due_date < Date.today)
end
# Users the issue can be assigned to # Users the issue can be assigned to
def assignable_users def assignable_users
project.assignable_users project.assignable_users

View File

@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class MailHandler < ActionMailer::Base class MailHandler < ActionMailer::Base
include ActionView::Helpers::SanitizeHelper
class UnauthorizedAction < StandardError; end class UnauthorizedAction < StandardError; end
class MissingInformation < StandardError; end class MissingInformation < StandardError; end
@ -88,7 +89,7 @@ class MailHandler < ActionMailer::Base
issue.status = status issue.status = status
end end
issue.subject = email.subject.chomp.toutf8 issue.subject = email.subject.chomp.toutf8
issue.description = email.plain_text_body.chomp issue.description = plain_text_body
issue.save! issue.save!
add_attachments(issue) add_attachments(issue)
logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
@ -120,7 +121,7 @@ class MailHandler < ActionMailer::Base
raise UnauthorizedAction unless status.nil? || user.allowed_to?(:edit_issues, issue.project) raise UnauthorizedAction unless status.nil? || user.allowed_to?(:edit_issues, issue.project)
# add the note # add the note
journal = issue.init_journal(user, email.plain_text_body.chomp) journal = issue.init_journal(user, plain_text_body)
add_attachments(issue) add_attachments(issue)
# check workflow # check workflow
if status && issue.new_statuses_allowed_to(user).include?(status) if status && issue.new_statuses_allowed_to(user).include?(status)
@ -156,21 +157,30 @@ class MailHandler < ActionMailer::Base
end end
def get_keyword(attr) def get_keyword(attr)
if @@handler_options[:allow_override].include?(attr.to_s) && email.plain_text_body =~ /^#{attr}:[ \t]*(.+)$/i if @@handler_options[:allow_override].include?(attr.to_s) && plain_text_body =~ /^#{attr}:[ \t]*(.+)$/i
$1.strip $1.strip
elsif !@@handler_options[:issue][attr].blank? elsif !@@handler_options[:issue][attr].blank?
@@handler_options[:issue][attr] @@handler_options[:issue][attr]
end end
end end
end
# Returns the text/plain part of the email
class TMail::Mail # If not found (eg. HTML-only email), returns the body with tags removed
# Returns body of the first plain text part found if any
def plain_text_body def plain_text_body
return @plain_text_body unless @plain_text_body.nil? return @plain_text_body unless @plain_text_body.nil?
p = self.parts.collect {|c| (c.respond_to?(:parts) && !c.parts.empty?) ? c.parts : c}.flatten parts = @email.parts.collect {|c| (c.respond_to?(:parts) && !c.parts.empty?) ? c.parts : c}.flatten
plain = p.detect {|c| c.content_type == 'text/plain'} if parts.empty?
@plain_text_body = plain.nil? ? self.body : plain.body parts << @email
end
plain_text_part = parts.detect {|p| p.content_type == 'text/plain'}
if plain_text_part.nil?
# no text/plain part found, assuming html-only email
# strip html tags and remove doctype directive
@plain_text_body = strip_tags(@email.body.to_s)
@plain_text_body.gsub! %r{^<!DOCTYPE .*$}, ''
else
@plain_text_body = plain_text_part.body.to_s
end
@plain_text_body.strip!
end end
end end

View File

@ -144,7 +144,7 @@ class User < ActiveRecord::Base
end end
def time_zone def time_zone
@time_zone ||= (self.pref.time_zone.blank? ? nil : TimeZone[self.pref.time_zone]) @time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
end end
def wants_comments_in_reverse_order? def wants_comments_in_reverse_order?

View File

@ -11,7 +11,7 @@
</tr></thead> </tr></thead>
<tbody> <tbody>
<% issues.each do |issue| -%> <% issues.each do |issue| -%>
<tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>"> <tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= css_issue_classes(issue) %>">
<td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td> <td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
<td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td> <td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
<% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %> <% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %>

View File

@ -8,7 +8,7 @@
</tr></thead> </tr></thead>
<tbody> <tbody>
<% for issue in issues %> <% for issue in issues %>
<tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>"> <tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= css_issue_classes(issue) %>">
<td class="id"> <td class="id">
<%= check_box_tag("ids[]", issue.id, false, :style => 'display:none;') %> <%= check_box_tag("ids[]", issue.id, false, :style => 'display:none;') %>
<%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %> <%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %>

View File

@ -9,7 +9,7 @@
<h2><%= @issue.tracker.name %> #<%= @issue.id %></h2> <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2>
<div class="issue <%= "status-#{@issue.status.position} priority-#{@issue.priority.position}" %>"> <div class="<%= css_issue_classes(@issue) %>">
<%= avatar(@issue.author, :size => "64") %> <%= avatar(@issue.author, :size => "64") %>
<h3><%=h @issue.subject %></h3> <h3><%=h @issue.subject %></h3>
<p class="author"> <p class="author">

View File

@ -1,6 +1,6 @@
<% form_remote_tag(:url => {}, :html => { :id => "journal-#{@journal.id}-form" }) do %> <% form_remote_tag(:url => {}, :html => { :id => "journal-#{@journal.id}-form" }) do %>
<%= text_area_tag :notes, @journal.notes, :class => 'wiki-edit', <%= text_area_tag :notes, h(@journal.notes), :class => 'wiki-edit',
:rows => (@journal.notes.blank? ? 10 : [[10, @journal.notes.length / 50].max, 100].min) %> :rows => (@journal.notes.blank? ? 10 : [[10, @journal.notes.length / 50].max, 100].min) %>
<%= call_hook(:view_journals_notes_form_after_notes, { :journal => @journal}) %> <%= call_hook(:view_journals_notes_form_after_notes, { :journal => @journal}) %>
<p><%= submit_tag l(:button_save) %> <p><%= submit_tag l(:button_save) %>
<%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " + <%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " +

View File

@ -24,7 +24,7 @@
<div id="account"> <div id="account">
<%= render_menu :account_menu -%> <%= render_menu :account_menu -%>
</div> </div>
<%= content_tag('div', "#{l(:label_logged_as)} #{User.current.login}", :id => 'loggedas') if User.current.logged? %> <%= content_tag('div', "#{l(:label_logged_as)} #{link_to_user(User.current, :format => :username)}", :id => 'loggedas') if User.current.logged? %>
<%= render_menu :top_menu -%> <%= render_menu :top_menu -%>
</div> </div>

View File

@ -38,7 +38,7 @@
<div class="box tabular"> <div class="box tabular">
<% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %> <% fields_for :pref, @user.pref, :builder => TabularFormBuilder, :lang => current_language do |pref_fields| %>
<p><%= pref_fields.check_box :hide_mail %></p> <p><%= pref_fields.check_box :hide_mail %></p>
<p><%= pref_fields.select :time_zone, TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p> <p><%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p>
<p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p> <p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p>
<% end %> <% end %>
</div> </div>

View File

@ -236,7 +236,7 @@ label_register: הרשמה
label_password_lost: אבדה הסיסמה? label_password_lost: אבדה הסיסמה?
label_home: דף הבית label_home: דף הבית
label_my_page: הדף שלי label_my_page: הדף שלי
label_my_account: השבון שלי label_my_account: החשבון שלי
label_my_projects: הפרויקטים שלי label_my_projects: הפרויקטים שלי
label_administration: אדמיניסטרציה label_administration: אדמיניסטרציה
label_login: התחבר label_login: התחבר
@ -292,7 +292,7 @@ label_confirmation: אישור
label_export_to: יצא ל label_export_to: יצא ל
label_read: קרא... label_read: קרא...
label_public_projects: פרויקטים פומביים label_public_projects: פרויקטים פומביים
label_open_issues: פותח label_open_issues: פתוח
label_open_issues_plural: פתוחים label_open_issues_plural: פתוחים
label_closed_issues: סגור label_closed_issues: סגור
label_closed_issues_plural: סגורים label_closed_issues_plural: סגורים
@ -308,7 +308,7 @@ label_used_by: בשימוש ע"י
label_details: פרטים label_details: פרטים
label_add_note: הוסף הערה label_add_note: הוסף הערה
label_per_page: לכל דף label_per_page: לכל דף
label_calendar: לו"ח שנה label_calendar: לוח שנה
label_months_from: חודשים מ label_months_from: חודשים מ
label_gantt: גאנט label_gantt: גאנט
label_internal: פנימי label_internal: פנימי
@ -357,7 +357,7 @@ label_sort_higher: הזז למעלה
label_sort_lower: הזז למטה label_sort_lower: הזז למטה
label_sort_lowest: הזז לתחתית label_sort_lowest: הזז לתחתית
label_roadmap: מפת הדרכים label_roadmap: מפת הדרכים
label_roadmap_due_in: %s נגמר בעוד label_roadmap_due_in: נגמר בעוד %s
label_roadmap_overdue: %s מאחר label_roadmap_overdue: %s מאחר
label_roadmap_no_issues: אין נושאים לגירסא זו label_roadmap_no_issues: אין נושאים לגירסא זו
label_search: חפש label_search: חפש
@ -421,8 +421,8 @@ label_send_information: שלח מידע על חשבון למשתמש
label_year: שנה label_year: שנה
label_month: חודש label_month: חודש
label_week: שבוע label_week: שבוע
label_date_from: מאת label_date_from: מתאריך
label_date_to: אל label_date_to: עד
label_language_based: מבוסס שפה label_language_based: מבוסס שפה
label_sort_by: מין לפי %s label_sort_by: מין לפי %s
label_send_test_email: שלח דו"ל בדיקה label_send_test_email: שלח דו"ל בדיקה
@ -487,7 +487,7 @@ text_journal_set_to: שונה ל %s
text_journal_deleted: נמחק text_journal_deleted: נמחק
text_tip_task_begin_day: מטלה המתחילה היום text_tip_task_begin_day: מטלה המתחילה היום
text_tip_task_end_day: מטלה המסתיימת היום text_tip_task_end_day: מטלה המסתיימת היום
text_tip_task_begin_end_day: מתלה המתחילה ומסתיימת היום text_tip_task_begin_end_day: מטלה המתחילה ומסתיימת היום
text_project_identifier_info: 'אותיות לטיניות (a-z), מספרים ומקפים.<br />ברגע שנשמר, לא ניתן לשנות את המזהה.' text_project_identifier_info: 'אותיות לטיניות (a-z), מספרים ומקפים.<br />ברגע שנשמר, לא ניתן לשנות את המזהה.'
text_caracters_maximum: מקסימום %d תווים. text_caracters_maximum: מקסימום %d תווים.
text_length_between: אורך בין %d ל %d תווים. text_length_between: אורך בין %d ל %d תווים.
@ -618,81 +618,79 @@ label_overall_activity: פעילות כוללת
setting_default_projects_public: פרויקטים חדשים הינם פומביים כברירת מחדל setting_default_projects_public: פרויקטים חדשים הינם פומביים כברירת מחדל
error_scm_annotate: "הכניסה לא קיימת או שלא ניתן לתאר אותה." error_scm_annotate: "הכניסה לא קיימת או שלא ניתן לתאר אותה."
label_planning: תכנון label_planning: תכנון
text_subprojects_destroy_warning: 'Its subproject(s): %s will be also deleted.' text_subprojects_destroy_warning: 'תת הפרויקט\ים: %s ימחקו גם כן.'
label_and_its_subprojects: %s and its subprojects label_and_its_subprojects: %s וכל תת הפרויקטים שלו
mail_body_reminder: "%d issue(s) that are assigned to you are due in the next %d days:" mail_body_reminder: "%d נושאים שמיועדים אליך מיועדים להגשה בתוך %d ימים:"
mail_subject_reminder: "%d issue(s) due in the next days" mail_subject_reminder: "%d נושאים מיעדים להגשה בימים הקרובים"
text_user_wrote: '%s wrote:' text_user_wrote: '%s כתב:'
label_duplicated_by: duplicated by label_duplicated_by: שוכפל ע"י
setting_enabled_scm: Enabled SCM setting_enabled_scm: אפשר SCM
text_enumeration_category_reassign_to: 'Reassign them to this value:' text_enumeration_category_reassign_to: 'הצב מחדש לערך הזה:'
text_enumeration_destroy_question: '%d objects are assigned to this value.' text_enumeration_destroy_question: '%d אוביקטים מוצבים לערך זה.'
label_incoming_emails: Incoming emails label_incoming_emails: דוא"ל נכנס
label_generate_key: Generate a key label_generate_key: יצר מפתח
setting_mail_handler_api_enabled: Enable WS for incoming emails setting_mail_handler_api_enabled: Enable WS for incoming emails
setting_mail_handler_api_key: API key setting_mail_handler_api_key: מפתח API
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
field_parent_title: Parent page field_parent_title: דף אב
label_issue_watchers: Watchers label_issue_watchers: צופים
setting_commit_logs_encoding: Commit messages encoding setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote button_quote: צטט
setting_sequential_project_identifiers: Generate sequential project identifiers setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version notice_unable_delete_version: לא ניתן למחוק גירסא
label_renamed: renamed label_renamed: השם שונה
label_copied: copied label_copied: הועתק
setting_plain_text_mail: plain text only (no HTML) setting_plain_text_mail: טקסט פשוט בלבד (ללא HTML)
permission_view_files: View files permission_view_files: צפה בקבצים
permission_edit_issues: Edit issues permission_edit_issues: ערוך נושאים
permission_edit_own_time_entries: Edit own time logs permission_edit_own_time_entries: ערוך את לוג הזמן של עצמך
permission_manage_public_queries: Manage public queries permission_manage_public_queries: נהל שאילתות פומביות
permission_add_issues: Add issues permission_add_issues: הוסף נושא
permission_log_time: Log spent time permission_log_time: תעד זמן שבוזבז
permission_view_changesets: View changesets permission_view_changesets: צפה בקבוצות שינויים
permission_view_time_entries: View spent time permission_view_time_entries: צפה בזמן שבוזבז
permission_manage_versions: Manage versions permission_manage_versions: נהל גירסאות
permission_manage_wiki: Manage wiki permission_manage_wiki: נהל wiki
permission_manage_categories: Manage issue categories permission_manage_categories: נהל קטגוריות נושאים
permission_protect_wiki_pages: Protect wiki pages permission_protect_wiki_pages: הגן כל דפי wiki
permission_comment_news: Comment news permission_comment_news: הגב על החדשות
permission_delete_messages: Delete messages permission_delete_messages: מחק הודעות
permission_select_project_modules: Select project modules permission_select_project_modules: בחר מודולי פרויקט
permission_manage_documents: Manage documents permission_manage_documents: נהל מסמכים
permission_edit_wiki_pages: Edit wiki pages permission_edit_wiki_pages: ערוך דפי wiki
permission_add_issue_watchers: Add watchers permission_add_issue_watchers: הוסף צופים
permission_view_gantt: View gantt chart permission_view_gantt: צפה בגאנט
permission_move_issues: Move issues permission_move_issues: הזז נושאים
permission_manage_issue_relations: Manage issue relations permission_manage_issue_relations: נהל יחס בין נושאים
permission_delete_wiki_pages: Delete wiki pages permission_delete_wiki_pages: מחק דפי wiki
permission_manage_boards: Manage boards permission_manage_boards: נהל לוחות
permission_delete_wiki_pages_attachments: Delete attachments permission_delete_wiki_pages_attachments: מחק דבוקות
permission_view_wiki_edits: View wiki history permission_view_wiki_edits: צפה בהיסטורית wiki
permission_add_messages: Post messages permission_add_messages: הצב הודעות
permission_view_messages: View messages permission_view_messages: צפה בהודעות
permission_manage_files: Manage files permission_manage_files: נהל קבצים
permission_edit_issue_notes: Edit notes permission_edit_issue_notes: ערוך רשימות
permission_manage_news: Manage news permission_manage_news: נהל חדשות
permission_view_calendar: View calendrier permission_view_calendar: צפה בלוח השנה
permission_manage_members: Manage members permission_manage_members: נהל חברים
permission_edit_messages: Edit messages permission_edit_messages: ערוך הודעות
permission_delete_issues: Delete issues permission_delete_issues: מחק נושאים
permission_view_issue_watchers: View watchers list permission_view_issue_watchers: צפה ברשימה צופים
permission_manage_repository: Manage repository permission_manage_repository: נהל מאגר
permission_commit_access: Commit access permission_commit_access: Commit access
permission_browse_repository: Browse repository permission_browse_repository: סייר במאגר
permission_view_documents: View documents permission_view_documents: צפה במסמכים
permission_edit_project: Edit project permission_edit_project: ערוך פרויקט
permission_add_issue_notes: Add notes permission_add_issue_notes: Add notes
permission_save_queries: Save queries permission_save_queries: שמור שאילתות
permission_view_wiki_pages: View wiki permission_view_wiki_pages: צפה ב-wiki
permission_rename_wiki_pages: Rename wiki pages permission_rename_wiki_pages: שנה שם של דפי wiki
permission_edit_time_entries: Edit time logs permission_edit_time_entries: ערוך רישום זמנים
permission_edit_own_issue_notes: Edit own notes permission_edit_own_issue_notes: Edit own notes
setting_gravatar_enabled: Use Gravatar user icons setting_gravatar_enabled: Use Gravatar user icons
label_example: Example label_example: דוגמא
text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped." text_repository_usernames_mapping: "Select ou update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
permission_edit_own_messages: Edit own messages permission_edit_own_messages: ערוך הודעות של עצמך
permission_delete_own_messages: Delete own messages permission_delete_own_messages: מחק הודעות של עצמך
label_user_activity: "%s's activity" label_user_activity: "הפעילות של %s"
label_updated_time_by: Updated by %s %s ago label_updated_time_by: עודכן ע"י %s לפני %s
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
setting_diff_max_lines_displayed: Max number of diff lines displayed

File diff suppressed because it is too large Load Diff

View File

@ -712,6 +712,6 @@ text_wiki_destroy_confirmation: Jesteś pewien, że chcesz usunąć to wiki i ca
text_workflow_edit: Zaznacz rolę i typ zagadnienia do edycji przepływu text_workflow_edit: Zaznacz rolę i typ zagadnienia do edycji przepływu
label_user_activity: "Aktywność: %s" label_user_activity: "Aktywność: %s"
label_updated_time_by: Updated by %s %s ago label_updated_time_by: Uaktualnione przez %s %s temu
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.' text_diff_truncated: '... Ten plik różnic został przycięty ponieważ jest zbyt długi.'
setting_diff_max_lines_displayed: Max number of diff lines displayed setting_diff_max_lines_displayed: Maksymalna liczba linii różnicy do pokazania

View File

@ -557,7 +557,7 @@ label_theme: 畫面主題
label_default: 預設 label_default: 預設
label_search_titles_only: 僅搜尋標題 label_search_titles_only: 僅搜尋標題
label_user_mail_option_all: "提醒與我的專案有關的所有事件" label_user_mail_option_all: "提醒與我的專案有關的所有事件"
label_user_mail_option_selected: "只醒我所選擇專案中的事件..." label_user_mail_option_selected: "只醒我所選擇專案中的事件..."
label_user_mail_option_none: "只提醒我觀察中或參與中的事件" label_user_mail_option_none: "只提醒我觀察中或參與中的事件"
label_user_mail_no_self_notified: "不提醒我自己所做的變更" label_user_mail_no_self_notified: "不提醒我自己所做的變更"
label_registration_activation_by_email: 透過電子郵件啟用帳戶 label_registration_activation_by_email: 透過電子郵件啟用帳戶

View File

@ -435,12 +435,15 @@ class RedCloth3 < String
# #
# Flexible HTML escaping # Flexible HTML escaping
# #
def htmlesc( str, mode ) def htmlesc( str, mode=:Quotes )
if str
str.gsub!( '&', '&amp;' ) str.gsub!( '&', '&amp;' )
str.gsub!( '"', '&quot;' ) if mode != :NoQuotes str.gsub!( '"', '&quot;' ) if mode != :NoQuotes
str.gsub!( "'", '&#039;' ) if mode == :Quotes str.gsub!( "'", '&#039;' ) if mode == :Quotes
str.gsub!( '<', '&lt;') str.gsub!( '<', '&lt;')
str.gsub!( '>', '&gt;') str.gsub!( '>', '&gt;')
end
str
end end
# Search and replace for Textile glyphs (quotes, dashes, other symbols) # Search and replace for Textile glyphs (quotes, dashes, other symbols)
@ -914,6 +917,7 @@ class RedCloth3 < String
def inline_textile_image( text ) def inline_textile_image( text )
text.gsub!( IMAGE_RE ) do |m| text.gsub!( IMAGE_RE ) do |m|
stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8] stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8]
htmlesc title
atts = pba( atts ) atts = pba( atts )
atts = " src=\"#{ url }\"#{ atts }" atts = " src=\"#{ url }\"#{ atts }"
atts << " title=\"#{ title }\"" if title atts << " title=\"#{ title }\"" if title

View File

@ -63,7 +63,7 @@ module Redmine
logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'" logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
path_with_project="#{url}#{with_leading_slash(path)}" path_with_project="#{url}#{with_leading_slash(path)}"
entries = Entries.new entries = Entries.new
cmd = "#{CVS_BIN} -d #{root_url} rls -ed" cmd = "#{CVS_BIN} -d #{root_url} rls -e"
cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
cmd << " #{shell_quote path_with_project}" cmd << " #{shell_quote path_with_project}"
shellout(cmd) do |io| shellout(cmd) do |io|

View File

@ -55,9 +55,10 @@ h4, .wiki h3 {font-size: 13px;padding: 2px 10px 1px 0px;margin-bottom: 5px; bord
#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; } #sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; } * html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
#content { width: 80%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; height:600px; min-height: 600px;} #content { width: 80%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; }
* html #content{ width: 80%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;} * html #content{ width: 80%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
html>body #content { height: auto; min-height: 600px; overflow: auto; } html>body #content { min-height: 600px; }
* html body #content { height: 600px; } /* IE */
#main.nosidebar #sidebar{ display: none; } #main.nosidebar #sidebar{ display: none; }
#main.nosidebar #content{ width: auto; border-right: 0; } #main.nosidebar #content{ width: auto; border-right: 0; }

View File

@ -0,0 +1,22 @@
x-sender: <jsmith@somenet.foo>
x-receiver: <redmine@somenet.foo>
Received: from [127.0.0.1] ([127.0.0.1]) by somenet.foo with Quick 'n Easy Mail Server SMTP (1.0.0.0);
Sun, 14 Dec 2008 16:18:06 GMT
Message-ID: <494531B9.1070709@somenet.foo>
Date: Sun, 14 Dec 2008 17:18:01 +0100
From: "John Smith" <jsmith@somenet.foo>
User-Agent: Thunderbird 2.0.0.18 (Windows/20081105)
MIME-Version: 1.0
To: redmine@somenet.foo
Subject: HTML email
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body bgcolor="#ffffff" text="#000000">
This is a <b>html-only</b> email.<br>
</body>
</html>

View File

@ -258,4 +258,9 @@ class WikiControllerTest < Test::Unit::TestCase
post :destroy_attachment, :id => 1, :page => 'Page_with_an_inline_image', :attachment_id => 3 post :destroy_attachment, :id => 1, :page => 'Page_with_an_inline_image', :attachment_id => 3
end end
end end
def test_history_of_non_existing_page_should_return_404
get :history, :id => 1, :page => 'Unknown_page'
assert_response 404
end
end end

View File

@ -70,6 +70,8 @@ class ApplicationHelperTest < HelperTestCase
'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>', 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />', 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" style="width:100px;height100px;" alt="" />', 'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" style="width:100px;height100px;" alt="" />',
'with title !http://foo.bar/image.jpg(This is a title)!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a title" alt="This is a title" />',
'with title !http://foo.bar/image.jpg(This is a double-quoted "title")!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a double-quoted &quot;title&quot;" alt="This is a double-quoted &quot;title&quot;" />',
} }
to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
end end

View File

@ -190,4 +190,11 @@ class IssueTest < Test::Unit::TestCase
assert_nil Issue.find_by_id(1) assert_nil Issue.find_by_id(1)
assert_nil TimeEntry.find_by_issue_id(1) assert_nil TimeEntry.find_by_issue_id(1)
end end
def test_overdue
assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
assert !Issue.new(:due_date => Date.today).overdue?
assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
assert !Issue.new(:due_date => nil).overdue?
end
end end

View File

@ -129,6 +129,15 @@ class MailHandlerTest < Test::Unit::TestCase
assert_match /This is reply/, journal.notes assert_match /This is reply/, journal.notes
assert_equal IssueStatus.find_by_name("Resolved"), issue.status assert_equal IssueStatus.find_by_name("Resolved"), issue.status
end end
def test_should_strip_tags_of_html_only_emails
issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
assert issue.is_a?(Issue)
assert !issue.new_record?
issue.reload
assert_equal 'HTML email', issue.subject
assert_equal 'This is a html-only email.', issue.description
end
private private

View File

@ -53,6 +53,12 @@ class RepositoryCvsTest < Test::Unit::TestCase
@repository.fetch_changesets @repository.fetch_changesets
assert_equal 5, @repository.changesets.count assert_equal 5, @repository.changesets.count
end end
def test_deleted_files_should_not_be_listed
entries = @repository.entries('sources')
assert entries.detect {|e| e.name == 'watchers_controller.rb'}
assert_nil entries.detect {|e| e.name == 'welcome_controller.rb'}
end
else else
puts "CVS test repository NOT FOUND. Skipping unit tests !!!" puts "CVS test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end def test_fake; assert true end

View File

@ -1,7 +1,7 @@
require 'action_web_service' require 'action_web_service'
# These need to be in the load path for action_web_service to work # These need to be in the load path for action_web_service to work
Dependencies.load_paths += ["#{RAILS_ROOT}/app/apis"] ActiveSupport::Dependencies.load_paths += ["#{RAILS_ROOT}/app/apis"]
# AWS Test helpers # AWS Test helpers
require 'action_web_service/test_invoke' if ENV['RAILS_ENV'] && ENV['RAILS_ENV'] =~ /^test/ require 'action_web_service/test_invoke' if ENV['RAILS_ENV'] && ENV['RAILS_ENV'] =~ /^test/

View File

@ -97,8 +97,8 @@ module ActionController
"Unknown options: #{unknown_option_keys.join(', ')}" unless "Unknown options: #{unknown_option_keys.join(', ')}" unless
unknown_option_keys.empty? unknown_option_keys.empty?
options[:singular_name] ||= Inflector.singularize(collection_id.to_s) options[:singular_name] ||= ActiveSupport::Inflector.singularize(collection_id.to_s)
options[:class_name] ||= Inflector.camelize(options[:singular_name]) options[:class_name] ||= ActiveSupport::Inflector.camelize(options[:singular_name])
end end
# Returns a paginator and a collection of Active Record model instances # Returns a paginator and a collection of Active Record model instances

View File

@ -140,4 +140,4 @@ module Engines::RailsExtensions::Dependencies
end end
end end
Dependencies.send :include, Engines::RailsExtensions::Dependencies ActiveSupport::Dependencies.send :include, Engines::RailsExtensions::Dependencies