You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

user_preference.rb 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. # frozen_string_literal: true
  2. # Redmine - project management software
  3. # Copyright (C) 2006-2023 Jean-Philippe Lang
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU General Public License
  7. # as published by the Free Software Foundation; either version 2
  8. # of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. require 'redmine/my_page'
  19. class UserPreference < ApplicationRecord
  20. include Redmine::SafeAttributes
  21. belongs_to :user
  22. serialize :others
  23. before_save :set_others_hash, :clear_unused_block_settings
  24. safe_attributes(
  25. 'hide_mail',
  26. 'time_zone',
  27. 'comments_sorting',
  28. 'warn_on_leaving_unsaved',
  29. 'no_self_notified',
  30. 'notify_about_high_priority_issues',
  31. 'textarea_font',
  32. 'recently_used_projects',
  33. 'history_default_tab',
  34. 'default_issue_query',
  35. 'default_project_query',
  36. 'toolbar_language_options',
  37. 'auto_watch_on')
  38. TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
  39. 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]
  40. AUTO_WATCH_ON_OPTIONS = %w[issue_created issue_contributed_to]
  41. def initialize(attributes=nil, *args)
  42. super
  43. if new_record?
  44. unless attributes && attributes.key?(:hide_mail)
  45. self.hide_mail = Setting.default_users_hide_mail?
  46. end
  47. unless attributes && attributes.key?(:time_zone)
  48. self.time_zone = Setting.default_users_time_zone
  49. end
  50. unless attributes && attributes.key?(:no_self_notified)
  51. self.no_self_notified = Setting.default_users_no_self_notified
  52. end
  53. unless attributes && attributes.key?(:auto_watch_on)
  54. self.auto_watch_on = AUTO_WATCH_ON_OPTIONS
  55. end
  56. end
  57. self.others ||= {}
  58. end
  59. def set_others_hash
  60. self.others ||= {}
  61. end
  62. def [](attr_name)
  63. if has_attribute? attr_name
  64. super
  65. else
  66. others ? others[attr_name] : nil
  67. end
  68. end
  69. def []=(attr_name, value)
  70. if has_attribute? attr_name
  71. super
  72. else
  73. h = (read_attribute(:others) || {}).dup
  74. h.update(attr_name => value)
  75. write_attribute(:others, h)
  76. value
  77. end
  78. end
  79. def comments_sorting; self[:comments_sorting]; end
  80. def comments_sorting=(order); self[:comments_sorting]=order; end
  81. def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
  82. def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
  83. def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
  84. def no_self_notified=(value); self[:no_self_notified]=value; end
  85. def notify_about_high_priority_issues; (self[:notify_about_high_priority_issues] == true || self[:notify_about_high_priority_issues] == '1'); end
  86. def notify_about_high_priority_issues=(value); self[:notify_about_high_priority_issues]=value; end
  87. def activity_scope; Array(self[:activity_scope]); end
  88. def activity_scope=(value); self[:activity_scope]=value; end
  89. def textarea_font; self[:textarea_font]; end
  90. def textarea_font=(value); self[:textarea_font]=value; end
  91. def recently_used_projects; (self[:recently_used_projects] || 3).to_i; end
  92. def recently_used_projects=(value); self[:recently_used_projects] = value.to_i; end
  93. def history_default_tab; self[:history_default_tab]; end
  94. def history_default_tab=(value); self[:history_default_tab]=value; end
  95. def toolbar_language_options
  96. self[:toolbar_language_options].presence || DEFAULT_TOOLBAR_LANGUAGE_OPTIONS.join(',')
  97. end
  98. def toolbar_language_options=(value)
  99. languages =
  100. value.to_s.delete(' ').split(',').select do |lang|
  101. Redmine::SyntaxHighlighting.language_supported?(lang)
  102. end.compact
  103. self[:toolbar_language_options] = languages.join(',')
  104. end
  105. def default_issue_query; self[:default_issue_query] end
  106. def default_issue_query=(value); self[:default_issue_query]=value; end
  107. def default_project_query; self[:default_project_query] end
  108. def default_project_query=(value); self[:default_project_query]=value; end
  109. def auto_watch_on; self[:auto_watch_on] || []; end
  110. def auto_watch_on=(values); self[:auto_watch_on]=values; end
  111. def auto_watch_on?(action); self.auto_watch_on.include?(action.to_s); end
  112. # Returns the names of groups that are displayed on user's page
  113. # Example:
  114. # preferences.my_page_groups
  115. # # => ['top', 'left, 'right']
  116. def my_page_groups
  117. Redmine::MyPage.groups
  118. end
  119. def my_page_layout
  120. self[:my_page_layout] ||= Redmine::MyPage.default_layout.deep_dup
  121. end
  122. def my_page_layout=(arg)
  123. self[:my_page_layout] = arg
  124. end
  125. def my_page_settings(block=nil)
  126. s = self[:my_page_settings] ||= {}
  127. if block
  128. s[block] ||= {}
  129. else
  130. s
  131. end
  132. end
  133. def my_page_settings=(arg)
  134. self[:my_page_settings] = arg
  135. end
  136. # Removes block from the user page layout
  137. # Example:
  138. # preferences.remove_block('news')
  139. def remove_block(block)
  140. block = block.to_s.underscore
  141. my_page_layout.each_key do |group|
  142. my_page_layout[group].delete(block)
  143. end
  144. my_page_layout
  145. end
  146. # Adds block to the user page layout
  147. # Returns nil if block is not valid or if it's already
  148. # present in the user page layout
  149. def add_block(block)
  150. block = block.to_s.underscore
  151. return unless Redmine::MyPage.valid_block?(block, my_page_layout.values.flatten)
  152. remove_block(block)
  153. # add it to the first group
  154. group = my_page_groups.first
  155. my_page_layout[group] ||= []
  156. my_page_layout[group].unshift(block)
  157. end
  158. # Sets the block order for the given group.
  159. # Example:
  160. # preferences.order_blocks('left', ['issueswatched', 'news'])
  161. def order_blocks(group, blocks)
  162. group = group.to_s
  163. if Redmine::MyPage.groups.include?(group) && blocks.present?
  164. blocks = blocks.map(&:underscore) & my_page_layout.values.flatten
  165. blocks.each {|block| remove_block(block)}
  166. my_page_layout[group] = blocks
  167. end
  168. end
  169. def update_block_settings(block, settings)
  170. block = block.to_s
  171. block_settings = my_page_settings(block).merge(settings.symbolize_keys)
  172. my_page_settings[block] = block_settings
  173. end
  174. def clear_unused_block_settings
  175. blocks = my_page_layout.values.flatten
  176. my_page_settings.keep_if {|block, settings| blocks.include?(block)}
  177. end
  178. private :clear_unused_block_settings
  179. end