Revision 1297:0a574315af3e .svn/pristine/b0

View differences:

.svn/pristine/b0/b0017ec26c9070575c2b102bc7db593493d5910c.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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 Board < ActiveRecord::Base
19
  include Redmine::SafeAttributes
20
  belongs_to :project
21
  has_many :topics, :class_name => 'Message', :conditions => "#{Message.table_name}.parent_id IS NULL", :order => "#{Message.table_name}.created_on DESC"
22
  has_many :messages, :dependent => :destroy, :order => "#{Message.table_name}.created_on DESC"
23
  belongs_to :last_message, :class_name => 'Message', :foreign_key => :last_message_id
24
  acts_as_tree :dependent => :nullify
25
  acts_as_list :scope => '(project_id = #{project_id} AND parent_id #{parent_id ? "= #{parent_id}" : "IS NULL"})'
26
  acts_as_watchable
27

  
28
  validates_presence_of :name, :description
29
  validates_length_of :name, :maximum => 30
30
  validates_length_of :description, :maximum => 255
31
  validate :validate_board
32

  
33
  scope :visible, lambda {|*args| { :include => :project,
34
                                          :conditions => Project.allowed_to_condition(args.shift || User.current, :view_messages, *args) } }
35

  
36
  safe_attributes 'name', 'description', 'parent_id', 'move_to'
37

  
38
  def visible?(user=User.current)
39
    !user.nil? && user.allowed_to?(:view_messages, project)
40
  end
41

  
42
  def reload(*args)
43
    @valid_parents = nil
44
    super
45
  end
46

  
47
  def to_s
48
    name
49
  end
50

  
51
  def valid_parents
52
    @valid_parents ||= project.boards - self_and_descendants
53
  end
54

  
55
  def reset_counters!
56
    self.class.reset_counters!(id)
57
  end
58

  
59
  # Updates topics_count, messages_count and last_message_id attributes for +board_id+
60
  def self.reset_counters!(board_id)
61
    board_id = board_id.to_i
62
    update_all("topics_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id} AND parent_id IS NULL)," +
63
               " messages_count = (SELECT COUNT(*) FROM #{Message.table_name} WHERE board_id=#{board_id})," +
64
               " last_message_id = (SELECT MAX(id) FROM #{Message.table_name} WHERE board_id=#{board_id})",
65
               ["id = ?", board_id])
66
  end
67

  
68
  def self.board_tree(boards, parent_id=nil, level=0)
69
    tree = []
70
    boards.select {|board| board.parent_id == parent_id}.sort_by(&:position).each do |board|
71
      tree << [board, level]
72
      tree += board_tree(boards, board.id, level+1)
73
    end
74
    if block_given?
75
      tree.each do |board, level|
76
        yield board, level
77
      end
78
    end
79
    tree
80
  end
81

  
82
  protected
83

  
84
  def validate_board
85
    if parent_id && parent_id_changed?
86
      errors.add(:parent_id, :invalid) unless valid_parents.include?(parent)
87
    end
88
  end
89
end
.svn/pristine/b0/b068921bb34f750331c44877f44180d7da10bc0f.svn-base
1
<%= form_tag({:action => 'edit', :tab => 'authentication'}) do %>
2

  
3
<div class="box tabular settings">
4
<p><%= setting_check_box :login_required %></p>
5

  
6
<p><%= setting_select :autologin, [[l(:label_disabled), 0]] + [1, 7, 30, 365].collect{|days| [l('datetime.distance_in_words.x_days', :count => days), days.to_s]} %></p>
7

  
8
<p><%= setting_select :self_registration, [[l(:label_disabled), "0"],
9
                                           [l(:label_registration_activation_by_email), "1"],
10
                                           [l(:label_registration_manual_activation), "2"],
11
                                           [l(:label_registration_automatic_activation), "3"]] %></p>
12

  
13
<p><%= setting_check_box :unsubscribe %></p>
14

  
15
<p><%= setting_text_field :password_min_length, :size => 6 %></p>
16

  
17
<p><%= setting_check_box :lost_password, :label => :label_password_lost %></p>
18

  
19
<p><%= setting_check_box :openid, :disabled => !Object.const_defined?(:OpenID) %></p>
20

  
21
<p><%= setting_check_box :rest_api_enabled %></p>
22
</div>
23

  
24
<fieldset class="box">
25
  <legend><%= l(:label_session_expiration) %></legend>
26

  
27
  <div class="tabular settings">
28
    <p><%= setting_select :session_lifetime, [[l(:label_disabled), 0]] + [1, 7, 30, 60, 365].collect{|days| [l('datetime.distance_in_words.x_days', :count => days), (days * 60 * 24).to_s]} %></p>
29
    <p><%= setting_select :session_timeout, [[l(:label_disabled), 0]] + [1, 2, 4, 8, 12, 24, 48].collect{|hours| [l('datetime.distance_in_words.x_hours', :count => hours), (hours * 60).to_s]} %></p>
30
  </div>
31
  
32
  <p><em class="info"><%= l(:text_session_expiration_settings) %></em></p>
33
</fieldset>
34

  
35
<%= submit_tag l(:button_save) %>
36
<% end %>
.svn/pristine/b0/b08b8359ba61a19a3531e1766fc73fb2077273a2.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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
module Redmine
19
  module Acts
20
    module Customizable
21
      def self.included(base)
22
        base.extend ClassMethods
23
      end
24

  
25
      module ClassMethods
26
        def acts_as_customizable(options = {})
27
          return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
28
          cattr_accessor :customizable_options
29
          self.customizable_options = options
30
          has_many :custom_values, :as => :customized,
31
                                   :include => :custom_field,
32
                                   :order => "#{CustomField.table_name}.position",
33
                                   :dependent => :delete_all,
34
                                   :validate => false
35
          send :include, Redmine::Acts::Customizable::InstanceMethods
36
          validate :validate_custom_field_values
37
          after_save :save_custom_field_values
38
        end
39
      end
40

  
41
      module InstanceMethods
42
        def self.included(base)
43
          base.extend ClassMethods
44
        end
45

  
46
        def available_custom_fields
47
          CustomField.find(:all, :conditions => "type = '#{self.class.name}CustomField'",
48
                                 :order => 'position')
49
        end
50

  
51
        # Sets the values of the object's custom fields
52
        # values is an array like [{'id' => 1, 'value' => 'foo'}, {'id' => 2, 'value' => 'bar'}]
53
        def custom_fields=(values)
54
          values_to_hash = values.inject({}) do |hash, v|
55
            v = v.stringify_keys
56
            if v['id'] && v.has_key?('value')
57
              hash[v['id']] = v['value']
58
            end
59
            hash
60
          end
61
          self.custom_field_values = values_to_hash
62
        end
63

  
64
        # Sets the values of the object's custom fields
65
        # values is a hash like {'1' => 'foo', 2 => 'bar'}
66
        def custom_field_values=(values)
67
          values = values.stringify_keys
68

  
69
          custom_field_values.each do |custom_field_value|
70
            key = custom_field_value.custom_field_id.to_s
71
            if values.has_key?(key)
72
              value = values[key]
73
              if value.is_a?(Array)
74
                value = value.reject(&:blank?).uniq
75
                if value.empty?
76
                  value << ''
77
                end
78
              end
79
              custom_field_value.value = value
80
            end
81
          end
82
          @custom_field_values_changed = true
83
        end
84

  
85
        def custom_field_values
86
          @custom_field_values ||= available_custom_fields.collect do |field|
87
            x = CustomFieldValue.new
88
            x.custom_field = field
89
            x.customized = self
90
            if field.multiple?
91
              values = custom_values.select { |v| v.custom_field == field }
92
              if values.empty?
93
                values << custom_values.build(:customized => self, :custom_field => field, :value => nil)
94
              end
95
              x.value = values.map(&:value)
96
            else
97
              cv = custom_values.detect { |v| v.custom_field == field }
98
              cv ||= custom_values.build(:customized => self, :custom_field => field, :value => nil)
99
              x.value = cv.value
100
            end
101
            x
102
          end
103
        end
104

  
105
        def visible_custom_field_values
106
          custom_field_values.select(&:visible?)
107
        end
108

  
109
        def custom_field_values_changed?
110
          @custom_field_values_changed == true
111
        end
112

  
113
        def custom_value_for(c)
114
          field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
115
          custom_values.detect {|v| v.custom_field_id == field_id }
116
        end
117

  
118
        def custom_field_value(c)
119
          field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
120
          custom_field_values.detect {|v| v.custom_field_id == field_id }.try(:value)
121
        end
122

  
123
        def validate_custom_field_values
124
          if new_record? || custom_field_values_changed?
125
            custom_field_values.each(&:validate_value)
126
          end
127
        end
128

  
129
        def save_custom_field_values
130
          target_custom_values = []
131
          custom_field_values.each do |custom_field_value|
132
            if custom_field_value.value.is_a?(Array)
133
              custom_field_value.value.each do |v|
134
                target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field && cv.value == v}
135
                target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field, :value => v)
136
                target_custom_values << target
137
              end
138
            else
139
              target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field}
140
              target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field)
141
              target.value = custom_field_value.value
142
              target_custom_values << target
143
            end
144
          end
145
          self.custom_values = target_custom_values
146
          custom_values.each(&:save)
147
          @custom_field_values_changed = false
148
          true
149
        end
150

  
151
        def reset_custom_values!
152
          @custom_field_values = nil
153
          @custom_field_values_changed = true
154
        end
155

  
156
        module ClassMethods
157
        end
158
      end
159
    end
160
  end
161
end
.svn/pristine/b0/b09c0572e3793383576d19f17f4abdf1d9495a71.svn-base
1
scope1:
2
  id: 1
3
  body: Top Level
4
  lft: 1
5
  rgt: 10
6
  notable_id: 1
7
  notable_type: Category
8
child_1:
9
  id: 2
10
  body: Child 1
11
  parent_id: 1
12
  lft: 2
13
  rgt: 3
14
  notable_id: 1
15
  notable_type: Category
16
child_2:
17
  id: 3
18
  body: Child 2
19
  parent_id: 1
20
  lft: 4
21
  rgt: 7
22
  notable_id: 1
23
  notable_type: Category
24
child_3:
25
  id: 4
26
  body: Child 3
27
  parent_id: 1
28
  lft: 8
29
  rgt: 9
30
  notable_id: 1
31
  notable_type: Category
32
scope2:
33
  id: 5
34
  body: Top Level 2
35
  lft: 1
36
  rgt: 2
37
  notable_id: 1
38
  notable_type: Departments
.svn/pristine/b0/b0bccc208d7807b84f7eb5ca0db0c75765ec033a.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2012  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 CommentTest < ActiveSupport::TestCase
21
  fixtures :users, :news, :comments, :projects, :enabled_modules
22

  
23
  def setup
24
    @jsmith = User.find(2)
25
    @news = News.find(1)
26
  end
27

  
28
  def test_create
29
    comment = Comment.new(:commented => @news, :author => @jsmith, :comments => "my comment")
30
    assert comment.save
31
    @news.reload
32
    assert_equal 2, @news.comments_count
33
  end
34

  
35
  def test_create_should_send_notification
36
    Watcher.create!(:watchable => @news, :user => @jsmith)
37

  
38
    with_settings :notified_events => %w(news_comment_added) do
39
      assert_difference 'ActionMailer::Base.deliveries.size' do
40
        Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment")
41
      end
42
    end
43
  end
44

  
45
  def test_validate
46
    comment = Comment.new(:commented => @news)
47
    assert !comment.save
48
    assert_equal 2, comment.errors.count
49
  end
50

  
51
  def test_destroy
52
    comment = Comment.find(1)
53
    assert comment.destroy
54
    @news.reload
55
    assert_equal 0, @news.comments_count
56
  end
57
end
.svn/pristine/b0/b0dd7f2e6e380d76ce0d76b315917633345e67d4.svn-base
1
<div class="contextual">
2
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time-add' %>
3
</div>
4

  
5
<%= render_timelog_breadcrumb %>
6

  
7
<h2><%= l(:label_spent_time) %></h2>
8

  
9
<%= form_tag({:controller => 'timelog', :action => 'report',
10
              :project_id => @project, :issue_id => @issue},
11
            :method => :get, :id => 'query_form') do %>
12
  <% @report.criteria.each do |criterion| %>
13
    <%= hidden_field_tag 'criteria[]', criterion, :id => nil %>
14
  <% end %>
15
  <%= render :partial => 'timelog/date_range' %>
16

  
17
  <p><label for='columns'><%= l(:label_details) %></label>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
18
                                                                            [l(:label_month), 'month'],
19
                                                                            [l(:label_week), 'week'],
20
                                                                            [l(:label_day_plural).titleize, 'day']], @report.columns),
21
                                                        :onchange => "this.form.submit();" %>
22

  
23
  <label for='criterias'><%= l(:button_add) %></label>: <%= select_tag('criteria[]', options_for_select([[]] + (@report.available_criteria.keys - @report.criteria).collect{|k| [l_or_humanize(@report.available_criteria[k][:label]), k]}),
24
                                                          :onchange => "this.form.submit();",
25
                                                          :style => 'width: 200px',
26
                                                          :id => nil,
27
                                                          :disabled => (@report.criteria.length >= 3), :id => "criterias") %>
28
     <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue, :period_type => params[:period_type], :period => params[:period], :from => @from, :to => @to, :columns => @report.columns}, :class => 'icon icon-reload' %></p>
29
<% end %>
30

  
31
<% unless @report.criteria.empty? %>
32
<div class="total-hours">
33
<p><%= l(:label_total) %>: <%= html_hours(l_hours(@report.total_hours)) %></p>
34
</div>
35

  
36
<% unless @report.hours.empty? %>
37
<div class="autoscroll">
38
<table class="list" id="time-report">
39
<thead>
40
<tr>
41
<% @report.criteria.each do |criteria| %>
42
  <th><%= l_or_humanize(@report.available_criteria[criteria][:label]) %></th>
43
<% end %>
44
<% columns_width = (40 / (@report.periods.length+1)).to_i %>
45
<% @report.periods.each do |period| %>
46
  <th class="period" width="<%= columns_width %>%"><%= period %></th>
47
<% end %>
48
  <th class="total" width="<%= columns_width %>%"><%= l(:label_total) %></th>
49
</tr>
50
</thead>
51
<tbody>
52
<%= render :partial => 'report_criteria', :locals => {:criterias => @report.criteria, :hours => @report.hours, :level => 0} %>
53
  <tr class="total">
54
  <td><%= l(:label_total) %></td>
55
  <%= ('<td></td>' * (@report.criteria.size - 1)).html_safe %>
56
  <% total = 0 -%>
57
  <% @report.periods.each do |period| -%>
58
    <% sum = sum_hours(select_hours(@report.hours, @report.columns, period.to_s)); total += sum -%>
59
    <td class="hours"><%= html_hours("%.2f" % sum) if sum > 0 %></td>
60
  <% end -%>
61
  <td class="hours"><%= html_hours("%.2f" % total) if total > 0 %></td>
62
  </tr>
63
</tbody>
64
</table>
65
</div>
66

  
67
<% other_formats_links do |f| %>
68
  <%= f.link_to 'CSV', :url => params %>
69
<% end %>
70
<% end %>
71
<% end %>
72

  
73
<% html_title l(:label_spent_time), l(:label_report) %>
74

  

Also available in: Unified diff