summaryrefslogtreecommitdiffstats
path: root/app/models/user_preference.rb
blob: 930effb6736b1053b52ecbc518a9b5061a5a1419 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# frozen_string_literal: true

# Redmine - project management software
# Copyright (C) 2006-2021  Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

require 'redmine/my_page'

class UserPreference < ActiveRecord::Base
  include Redmine::SafeAttributes

  belongs_to :user
  serialize :others

  before_save :set_others_hash, :clear_unused_block_settings

  safe_attributes(
    'hide_mail',
    'time_zone',
    'comments_sorting',
    'warn_on_leaving_unsaved',
    'no_self_notified',
    'notify_about_high_priority_issues',
    'textarea_font',
    'recently_used_projects',
    'history_default_tab',
    'toolbar_language_options')

  TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
  DEFAULT_TOOLBAR_LANGUAGE_OPTIONS = %w[c cpp csharp css diff go groovy html java javascript objc perl php python r ruby sass scala shell sql swift xml yaml]

  def initialize(attributes=nil, *args)
    super
    if new_record?
      unless attributes && attributes.key?(:hide_mail)
        self.hide_mail = Setting.default_users_hide_mail?
      end
      unless attributes && attributes.key?(:time_zone)
        self.time_zone = Setting.default_users_time_zone
      end
      unless attributes && attributes.key?(:no_self_notified)
        self.no_self_notified = Setting.default_users_no_self_notified
      end
    end
    self.others ||= {}
  end

  def set_others_hash
    self.others ||= {}
  end

  def [](attr_name)
    if has_attribute? attr_name
      super
    else
      others ? others[attr_name] : nil
    end
  end

  def []=(attr_name, value)
    if has_attribute? attr_name
      super
    else
      h = (read_attribute(:others) || {}).dup
      h.update(attr_name => value)
      write_attribute(:others, h)
      value
    end
  end

  def comments_sorting; self[:comments_sorting]; end
  def comments_sorting=(order); self[:comments_sorting]=order; end

  def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
  def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end

  def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
  def no_self_notified=(value); self[:no_self_notified]=value; end

  def notify_about_high_priority_issues; (self[:notify_about_high_priority_issues] == true || self[:notify_about_high_priority_issues] == '1'); end
  def notify_about_high_priority_issues=(value); self[:notify_about_high_priority_issues]=value; end

  def activity_scope; Array(self[:activity_scope]); end
  def activity_scope=(value); self[:activity_scope]=value; end

  def textarea_font; self[:textarea_font]; end
  def textarea_font=(value); self[:textarea_font]=value; end

  def recently_used_projects; (self[:recently_used_projects] || 3).to_i; end
  def recently_used_projects=(value); self[:recently_used_projects] = value.to_i; end
  def history_default_tab; self[:history_default_tab]; end
  def history_default_tab=(value); self[:history_default_tab]=value; end

  def toolbar_language_options
    self[:toolbar_language_options].presence || DEFAULT_TOOLBAR_LANGUAGE_OPTIONS.join(',')
  end

  def toolbar_language_options=(value)
    languages =
      value.to_s.delete(' ').split(',').select do |lang|
        Redmine::SyntaxHighlighting.language_supported?(lang)
      end.compact
    self[:toolbar_language_options] = languages.join(',')
  end

  # Returns the names of groups that are displayed on user's page
  # Example:
  #   preferences.my_page_groups
  #   # => ['top', 'left, 'right']
  def my_page_groups
    Redmine::MyPage.groups
  end

  def my_page_layout
    self[:my_page_layout] ||= Redmine::MyPage.default_layout.deep_dup
  end

  def my_page_layout=(arg)
    self[:my_page_layout] = arg
  end

  def my_page_settings(block=nil)
    s = self[:my_page_settings] ||= {}
    if block
      s[block] ||= {}
    else
      s
    end
  end

  def my_page_settings=(arg)
    self[:my_page_settings] = arg
  end

  # Removes block from the user page layout
  # Example:
  #   preferences.remove_block('news')
  def remove_block(block)
    block = block.to_s.underscore
    my_page_layout.each_key do |group|
      my_page_layout[group].delete(block)
    end
    my_page_layout
  end

  # Adds block to the user page layout
  # Returns nil if block is not valid or if it's already
  # present in the user page layout
  def add_block(block)
    block = block.to_s.underscore
    return unless Redmine::MyPage.valid_block?(block, my_page_layout.values.flatten)

    remove_block(block)
    # add it to the first group
    group = my_page_groups.first
    my_page_layout[group] ||= []
    my_page_layout[group].unshift(block)
  end

  # Sets the block order for the given group.
  # Example:
  #   preferences.order_blocks('left', ['issueswatched', 'news'])
  def order_blocks(group, blocks)
    group = group.to_s
    if Redmine::MyPage.groups.include?(group) && blocks.present?
      blocks = blocks.map(&:underscore) & my_page_layout.values.flatten
      blocks.each {|block| remove_block(block)}
      my_page_layout[group] = blocks
    end
  end

  def update_block_settings(block, settings)
    block = block.to_s
    block_settings = my_page_settings(block).merge(settings.symbolize_keys)
    my_page_settings[block] = block_settings
  end

  def clear_unused_block_settings
    blocks = my_page_layout.values.flatten
    my_page_settings.keep_if {|block, settings| blocks.include?(block)}
  end
  private :clear_unused_block_settings
end