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
|
# frozen_string_literal: true
class UserPreference < ApplicationRecord
# We could use enums, but Rails 4 doesn't support multiple
# enum options with same name for multiple fields, also it creates
# extra methods that aren't really needed here.
NOTES_FILTERS = { all_notes: 0, only_comments: 1, only_activity: 2 }.freeze
TIME_DISPLAY_FORMATS = { system: 0, non_iso_format: 1, iso_format: 2 }.freeze
belongs_to :user
belongs_to :home_organization, class_name: "Organizations::Organization", optional: true
scope :with_user, -> { joins(:user) }
scope :gitpod_enabled, -> { where(gitpod_enabled: true) }
validates :issue_notes_filter, :merge_request_notes_filter, inclusion: { in: NOTES_FILTERS.values }, presence: true
validates :tab_width, numericality: {
only_integer: true,
greater_than_or_equal_to: Gitlab::TabWidth::MIN,
less_than_or_equal_to: Gitlab::TabWidth::MAX
}
validates :diffs_deletion_color, :diffs_addition_color,
format: { with: ColorsHelper::HEX_COLOR_PATTERN },
allow_blank: true
validates :time_display_relative, allow_nil: false, inclusion: { in: [true, false] }
validates :render_whitespace_in_code, allow_nil: false, inclusion: { in: [true, false] }
validates :pass_user_identities_to_ci_jwt, allow_nil: false, inclusion: { in: [true, false] }
validates :pinned_nav_items, json_schema: { filename: 'pinned_nav_items' }
validates :time_display_format, inclusion: { in: TIME_DISPLAY_FORMATS.values }, presence: true
validate :user_belongs_to_home_organization, if: :home_organization_changed?
attribute :tab_width, default: -> { Gitlab::TabWidth::DEFAULT }
attribute :time_display_relative, default: true
attribute :time_display_format, default: 0
attribute :render_whitespace_in_code, default: false
attribute :project_shortcut_buttons, default: true
attribute :keyboard_shortcuts_enabled, default: true
attribute :dpop_enabled, default: false
enum :visibility_pipeline_id_type, { id: 0, iid: 1 }, scopes: false
enum text_editor_type: { plain_text_editor: 1, rich_text_editor: 2 }
enum extensions_marketplace_opt_in_status: Enums::WebIde::ExtensionsMarketplaceOptInStatus.statuses
enum organization_groups_projects_display: { projects: 0, groups: 1 }
class << self
def notes_filters
{
s_('Notes|Show all activity') => NOTES_FILTERS[:all_notes],
s_('Notes|Show comments only') => NOTES_FILTERS[:only_comments],
s_('Notes|Show history only') => NOTES_FILTERS[:only_activity]
}
end
end
def set_notes_filter(filter_id, issuable)
# No need to update the column if the value is already set.
if filter_id && NOTES_FILTERS.value?(filter_id)
field = notes_filter_field_for(issuable)
self[field] = filter_id
save if attribute_changed?(field)
end
notes_filter_for(issuable)
end
# Returns the current discussion filter for a given issuable
# or issuable type.
def notes_filter_for(resource)
self[notes_filter_field_for(resource)]
end
class << self
def time_display_formats
{
s_('Time Display|System') => TIME_DISPLAY_FORMATS[:system],
s_('Time Display|12-hour: 2:34 PM') => TIME_DISPLAY_FORMATS[:non_iso_format],
s_('Time Display|24-hour: 14:34') => TIME_DISPLAY_FORMATS[:iso_format]
}
end
end
def early_access_event_tracking?
early_access_program_participant? && early_access_program_tracking?
end
# NOTE: Despite this returning a boolean, it does not end in `?` out of
# symmetry with the other integration fields like `gitpod_enabled`
def extensions_marketplace_enabled
extensions_marketplace_opt_in_status == "enabled"
end
def extensions_marketplace_enabled=(value)
status = ActiveRecord::Type::Boolean.new.cast(value) ? 'enabled' : 'disabled'
self.extensions_marketplace_opt_in_status = status
end
def dpop_enabled=(value)
if value.nil?
default = self.class.column_defaults['dpop_enabled']
super(default)
else
super(value)
end
end
def text_editor
text_editor_type || (Feature.enabled?(:rich_text_editor_as_default, user) ? :rich_text_editor : :plain_text_editor)
end
def text_editor=(value)
self.text_editor_type = value
end
private
def user_belongs_to_home_organization
# If we don't ignore the default organization id below then all users need to have their corresponding entry
# with default organization id as organization id in the `organization_users` table.
# Otherwise, the user won't be able to set the default organization as the home organization.
return if home_organization.default?
return if home_organization.user?(user)
errors.add(:user, _("is not part of the given organization"))
end
def notes_filter_field_for(resource)
field_key =
if resource.is_a?(Issuable)
resource.model_name.param_key
else
resource
end
"#{field_key}_notes_filter"
end
end
UserPreference.prepend_mod_with('UserPreference')
|