Revision 1297:0a574315af3e app

View differences:

app/controllers/boards_controller.rb
39 39
        sort_init 'updated_on', 'desc'
40 40
        sort_update	'created_on' => "#{Message.table_name}.created_on",
41 41
                    'replies' => "#{Message.table_name}.replies_count",
42
                    'updated_on' => "#{Message.table_name}.updated_on"
42
                    'updated_on' => "COALESCE(last_replies_messages.created_on, #{Message.table_name}.created_on)"
43 43

  
44 44
        @topic_count = @board.topics.count
45 45
        @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page']
46
        @topics =  @board.topics.reorder("#{Message.table_name}.sticky DESC").order(sort_clause).all(
47
                                      :include => [:author, {:last_reply => :author}],
48
                                      :limit  =>  @topic_pages.items_per_page,
49
                                      :offset =>  @topic_pages.current.offset)
46
        @topics =  @board.topics.
47
          reorder("#{Message.table_name}.sticky DESC").
48
          includes(:last_reply).
49
          limit(@topic_pages.items_per_page).
50
          offset(@topic_pages.current.offset).
51
          order(sort_clause).
52
          preload(:author, {:last_reply => :author}).
53
          all
50 54
        @message = Message.new(:board => @board)
51 55
        render :action => 'show', :layout => !request.xhr?
52 56
      }
app/controllers/messages_controller.rb
123 123

  
124 124
private
125 125
  def find_message
126
    find_board
126
    return unless find_board
127 127
    @message = @board.messages.find(params[:id], :include => :parent)
128 128
    @topic = @message.root
129 129
  rescue ActiveRecord::RecordNotFound
......
135 135
    @project = @board.project
136 136
  rescue ActiveRecord::RecordNotFound
137 137
    render_404
138
    nil
138 139
  end
139 140
end
app/controllers/my_controller.rb
182 182
  # params[:block] : id of the block to add
183 183
  def add_block
184 184
    block = params[:block].to_s.underscore
185
    (render :nothing => true; return) unless block && (BLOCKS.keys.include? block)
186
    @user = User.current
187
    layout = @user.pref[:my_page_layout] || {}
188
    # remove if already present in a group
189
    %w(top left right).each {|f| (layout[f] ||= []).delete block }
190
    # add it on top
191
    layout['top'].unshift block
192
    @user.pref[:my_page_layout] = layout
193
    @user.pref.save
185
    if block.present? && BLOCKS.key?(block)
186
      @user = User.current
187
      layout = @user.pref[:my_page_layout] || {}
188
      # remove if already present in a group
189
      %w(top left right).each {|f| (layout[f] ||= []).delete block }
190
      # add it on top
191
      layout['top'].unshift block
192
      @user.pref[:my_page_layout] = layout
193
      @user.pref.save
194
    end
194 195
    redirect_to :action => 'page_layout'
195 196
  end
196 197

  
app/helpers/application_helper.rb
610 610

  
611 611
  def parse_inline_attachments(text, project, obj, attr, only_path, options)
612 612
    # when using an image link, try to use an attachment, if possible
613
    if options[:attachments] || (obj && obj.respond_to?(:attachments))
614
      attachments = options[:attachments] || obj.attachments
613
    attachments = options[:attachments] || []
614
    attachments += obj.attachments if obj.respond_to?(:attachments)
615
    if attachments.present?
615 616
      text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
616 617
        filename, ext, alt, alttext = $1.downcase, $2, $3, $4
617 618
        # search for the picture in attachments
......
716 717
  #     identifier:document:"Some document"
717 718
  #     identifier:version:1.0.0
718 719
  #     identifier:source:some/file
719
  def parse_redmine_links(text, project, obj, attr, only_path, options)
720
    text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m|
720
  def parse_redmine_links(text, default_project, obj, attr, only_path, options)
721
    text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m|
721 722
      leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $2, $3, $4, $5, $10, $11, $8 || $12 || $18, $14 || $19, $15, $17
722 723
      link = nil
724
      project = default_project
723 725
      if project_identifier
724 726
        project = Project.visible.find_by_identifier(project_identifier)
725 727
      end
......
805 807
          when 'commit', 'source', 'export'
806 808
            if project
807 809
              repository = nil
808
              if name =~ %r{^(([a-z0-9\-]+)\|)(.+)$}
810
              if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
809 811
                repo_prefix, repo_identifier, name = $1, $2, $3
810 812
                repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
811 813
              else
......
832 834
            end
833 835
          when 'attachment'
834 836
            attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
835
            if attachments && attachment = attachments.detect {|a| a.filename == name }
837
            if attachments && attachment = Attachment.latest_attach(attachments, name)
836 838
              link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
837 839
                                                     :class => 'attachment'
838 840
            end
app/helpers/issues_helper.rb
350 350
    association = Issue.reflect_on_association(field.to_sym)
351 351
    if association
352 352
      record = association.class_name.constantize.find_by_id(id)
353
      return record.name if record
353
      if record
354
        record.name.force_encoding('UTF-8') if record.name.respond_to?(:force_encoding)
355
        return record.name
356
      end
354 357
    end
355 358
  end
356 359

  
app/helpers/queries_helper.rb
87 87
      format_time(value)
88 88
    when 'Date'
89 89
      format_date(value)
90
    when 'Fixnum', 'Float'
90
    when 'Fixnum'
91 91
      if column.name == :done_ratio
92 92
        progress_bar(value, :width => '80px')
93
      elsif  column.name == :spent_hours
94
        sprintf "%.2f", value
95 93
      else
96
        h(value.to_s)
94
        value.to_s
97 95
      end
96
    when 'Float'
97
      sprintf "%.2f", value
98 98
    when 'User'
99 99
      link_to_user value
100 100
    when 'Project'
app/models/issue.rb
418 418

  
419 419
    if attrs['parent_issue_id'].present?
420 420
      s = attrs['parent_issue_id'].to_s
421
      unless (m = s.match(%r{\A#?(\d+)\z})) && Issue.visible(user).exists?(m[1])
421
      unless (m = s.match(%r{\A#?(\d+)\z})) && (m[1] == parent_id.to_s || Issue.visible(user).exists?(m[1]))
422 422
        @invalid_parent_issue_id = attrs.delete('parent_issue_id')
423 423
      end
424 424
    end
app/models/mail_handler.rb
249 249
  def add_attachments(obj)
250 250
    if email.attachments && email.attachments.any?
251 251
      email.attachments.each do |attachment|
252
        filename = attachment.filename
253
        unless filename.respond_to?(:encoding)
254
          # try to reencode to utf8 manually with ruby1.8
255
          h = attachment.header['Content-Disposition']
256
          unless h.nil?
257
            begin
258
              if m = h.value.match(/filename\*[0-9\*]*=([^=']+)'/)
259
                filename = Redmine::CodesetUtil.to_utf8(filename, m[1])
260
              elsif m = h.value.match(/filename=.*=\?([^\?]+)\?[BbQq]\?/)
261
                # http://tools.ietf.org/html/rfc2047#section-4
262
                filename = Redmine::CodesetUtil.to_utf8(filename, m[1])
263
              end
264
            rescue
265
              # nop
266
            end
267
          end
268
        end
269 252
        obj.attachments << Attachment.create(:container => obj,
270 253
                          :file => attachment.decoded,
271
                          :filename => filename,
254
                          :filename => attachment.filename,
272 255
                          :author => user,
273 256
                          :content_type => attachment.mime_type)
274 257
      end
......
391 374

  
392 375
  def cleaned_up_subject
393 376
    subject = email.subject.to_s
394
    unless subject.respond_to?(:encoding)
395
      # try to reencode to utf8 manually with ruby1.8
396
      begin
397
        if h = email.header[:subject]
398
          # http://tools.ietf.org/html/rfc2047#section-4
399
          if m = h.value.match(/=\?([^\?]+)\?[BbQq]\?/)
400
            subject = Redmine::CodesetUtil.to_utf8(subject, m[1])
401
          end
402
        end
403
      rescue
404
        # nop
405
      end
406
    end
407 377
    subject.strip[0,255]
408 378
  end
409 379

  
app/models/project.rb
751 751
  def copy_wiki(project)
752 752
    # Check that the source project has a wiki first
753 753
    unless project.wiki.nil?
754
      self.wiki ||= Wiki.new
754
      wiki = self.wiki || Wiki.new
755 755
      wiki.attributes = project.wiki.attributes.dup.except("id", "project_id")
756 756
      wiki_pages_map = {}
757 757
      project.wiki.pages.each do |page|
......
763 763
        wiki.pages << new_wiki_page
764 764
        wiki_pages_map[page.id] = new_wiki_page
765 765
      end
766

  
767
      self.wiki = wiki
766 768
      wiki.save
767 769
      # Reproduce page hierarchy
768 770
      project.wiki.pages.each do |page|
app/views/context_menus/issues.html.erb
111 111
        <li><%= bulk_update_custom_field_context_menu_link(field, text, value || text) %></li>
112 112
      <% end %>
113 113
      <% unless field.is_required? %>
114
        <li><%= bulk_update_custom_field_context_menu_link(field, l(:label_none), '') %></li>
114
        <li><%= bulk_update_custom_field_context_menu_link(field, l(:label_none), '__none__') %></li>
115 115
      <% end %>
116 116
      </ul>
117 117
    </li>
app/views/issues/_form.html.erb
18 18
<% end %>
19 19

  
20 20
<% if @issue.safe_attribute? 'subject' %>
21
<p><%= f.text_field :subject, :size => 80, :required => true %></p>
21
<p><%= f.text_field :subject, :size => 80, :maxlength => 255, :required => true %></p>
22 22
<% end %>
23 23

  
24 24
<% if @issue.safe_attribute? 'description' %>
app/views/timelog/_form.html.erb
12 12
	<p><%= f.text_field :issue_id, :size => 6 %> <em><%= h("#{@time_entry.issue.tracker.name} ##{@time_entry.issue.id}: #{@time_entry.issue.subject}") if @time_entry.issue %></em></p>
13 13
	<p><%= f.text_field :spent_on, :size => 10, :required => true %><%= calendar_for('time_entry_spent_on') %></p>
14 14
	<p><%= f.text_field :hours, :size => 6, :required => true %></p>
15
	<p><%= f.text_field :comments, :size => 100 %></p>
15
	<p><%= f.text_field :comments, :size => 100, :maxlength => 255 %></p>
16 16
	<p><%= f.select :activity_id, activity_collection_for_select_options(@time_entry), :required => true %></p>
17 17
	<% @time_entry.custom_field_values.each do |value| %>
18 18
	  <p><%= custom_field_tag_with_label :time_entry, value %></p>

Also available in: Unified diff