notification-settings 1.2.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NotificationSettings
4
- require 'notification_settings/configuration'
4
+ require_relative 'notification_settings/configuration'
5
5
 
6
- require 'notification_settings/engine'
6
+ require_relative 'notification_settings/engine'
7
7
 
8
8
  autoload :Target, 'notification_settings/target'
9
9
  autoload :Subscriber, 'notification_settings/subscriber'
10
10
  autoload :Subscribable, 'notification_settings/subscribable'
11
- autoload :SettingLibrary, 'notification_settings/setting_library'
12
- autoload :SubscriptionLibrary, 'notification_settings/subscription_library'
13
- autoload :NotificationLibrary, 'notification_settings/notification_library'
11
+ autoload :Settings, 'notification_settings/settings'
12
+ autoload :Status, 'notification_settings/status'
13
+ autoload :NotificationLib, 'notification_settings/notification_lib'
14
14
  autoload :NotificationScopes, 'notification_settings/notification_scopes'
15
+ autoload :CategoryPreferencesForm,
16
+ 'notification_settings/category_preferences_form'
17
+ autoload :DeliveryMethodPreferencesForm,
18
+ 'notification_settings/delivery_method_preferences_form'
19
+ autoload :PreferencesForm, 'notification_settings/preferences_form'
15
20
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ module NotificationSettings
6
+ class CategoryPreferencesForm
7
+ include ActiveModel::Model
8
+
9
+ NotificationSettings.configuration.categories.each do |category|
10
+ attribute category, :boolean, default: true
11
+ end
12
+ end
13
+ end
@@ -2,29 +2,37 @@
2
2
 
3
3
  module NotificationSettings
4
4
  class << self
5
- attr_accessor :configuration
5
+ attr_writer :configuration
6
+
7
+ def configuration
8
+ @configuration ||= Configuration.new
9
+ end
6
10
  end
7
11
 
8
12
  def self.configure
9
- self.configuration ||= Configuration.new
10
13
  yield configuration
11
14
  end
12
15
 
13
16
  class Configuration
17
+ attr_accessor :categories
14
18
  attr_accessor :default_category
15
19
  attr_accessor :last_seen
16
20
  attr_accessor :idle_after
17
21
  attr_accessor :offline_after
22
+ attr_accessor :statuses
18
23
  attr_accessor :do_not_notify_statuses
19
- attr_accessor :do_not_push_statuses
24
+ attr_accessor :do_not_deliver_statuses
20
25
 
21
26
  def initialize
22
- @default_category = 'notification'
23
- @last_seen = 'last_seen'
27
+ @categories = [:notification]
28
+ @default_category = :notification
29
+ @last_seen = :last_seen
24
30
  @idle_after = 10.minutes
25
31
  @offline_after = 3.hours
26
- @do_not_notify_statuses = []
27
- @do_not_push_statuses = ['do not disturb']
32
+ @statuses = ['online', 'idle', 'offline', 'do not notify',
33
+ 'do not disturb']
34
+ @do_not_notify_statuses = ['do not notify']
35
+ @do_not_deliver_statuses = ['do not disturb']
28
36
  end
29
37
  end
30
38
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ module NotificationSettings
6
+ class DeliveryMethodPreferencesForm
7
+ include ActiveModel::Model
8
+
9
+ attribute :enabled, :boolean, default: true
10
+ NotificationPusher.configuration.delivery_methods
11
+ .each do |delivery_method, _|
12
+ attribute delivery_method, :boolean, default: true
13
+ end
14
+ end
15
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails/railtie'
3
+ require 'rails/engine'
4
4
  require 'active_record'
5
5
 
6
6
  module NotificationSettings
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'notification-handler'
4
+ require 'active_support'
5
+
6
+ module NotificationSettings
7
+ module NotificationLib
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ before_create :validate_create
12
+
13
+ validates :category, inclusion: {
14
+ in: NotificationSettings.configuration.categories + [nil]
15
+ }
16
+
17
+ belongs_to :subscription,
18
+ class_name: 'NotificationSettings::Subscription',
19
+ optional: true
20
+
21
+ include NotificationSettings::NotificationLib::InstanceMethods
22
+ end
23
+
24
+ # rubocop:disable Metrics/ModuleLength
25
+ module InstanceMethods
26
+ def category
27
+ self[:category] || NotificationSettings.configuration.default_category
28
+ end
29
+
30
+ def deliver(delivery_methods, delivery_options = {})
31
+ return false unless delivery_allowed?(delivery_methods)
32
+
33
+ super
34
+ end
35
+
36
+ def creation_allowed?
37
+ status_allows_creation? &&
38
+ settings_allow_creation? &&
39
+ category_settings_allow_creation?
40
+ end
41
+
42
+ # delivery_methods may be an array or a single value
43
+ def delivery_allowed?(delivery_methods)
44
+ creation_allowed? &&
45
+ status_allows_delivery? &&
46
+ delivery_methods_allowed?(Array(delivery_methods))
47
+ end
48
+
49
+ private
50
+
51
+ def validate_create
52
+ throw(:abort) unless creation_allowed?
53
+ end
54
+
55
+ def status_allows_creation?
56
+ !do_not_notify_statuses.include?(target.status)
57
+ end
58
+
59
+ def settings_allow_creation?
60
+ target.settings.fetch(:enabled, true) &&
61
+ (subscription.nil? || subscription.settings.fetch(:enabled, true))
62
+ end
63
+
64
+ def category_settings_allow_creation?
65
+ category_settings(target, category).fetch(:enabled, true) &&
66
+ (subscription.nil? ||
67
+ category_settings(subscription, category).fetch(:enabled, true))
68
+ end
69
+
70
+ def delivery_methods_allowed?(delivery_methods)
71
+ delivery_methods.any? do |delivery_method|
72
+ delivery_method_allowed?(delivery_method)
73
+ end
74
+ end
75
+
76
+ def delivery_method_allowed?(delivery_method)
77
+ settings_allow_delivery?(delivery_method) &&
78
+ category_settings_allow_delivery?(delivery_method)
79
+ end
80
+
81
+ def status_allows_delivery?
82
+ !do_not_deliver_statuses.include?(target.status)
83
+ end
84
+
85
+ def settings_allow_delivery?(delivery_method)
86
+ if local_delivery_method_setting?(delivery_method)
87
+ local_settings_allow_delivery?(delivery_method)
88
+ else
89
+ global_settings_allow_delivery?
90
+ end
91
+ end
92
+
93
+ def local_delivery_method_setting?(delivery_method)
94
+ !local_delivery_method_setting(delivery_method).nil?
95
+ end
96
+
97
+ def local_settings_allow_delivery?(delivery_method)
98
+ local_delivery_method_setting(delivery_method, true)
99
+ end
100
+
101
+ def local_delivery_method_setting(delivery_method, default = nil)
102
+ delivery_method_setting(target, delivery_method, default) &&
103
+ (subscription.nil? ||
104
+ delivery_method_setting(subscription, delivery_method, default))
105
+ end
106
+
107
+ def global_settings_allow_delivery?
108
+ delivery_method_setting(target, :enabled, true) &&
109
+ (subscription.nil? ||
110
+ delivery_method_setting(subscription, :enabled, true))
111
+ end
112
+
113
+ def category_settings_allow_delivery?(delivery_method)
114
+ if local_delivery_method_category_setting?(delivery_method)
115
+ local_category_settings_allow_delivery?(delivery_method)
116
+ else
117
+ global_category_settings_allow_delivery?
118
+ end
119
+ end
120
+
121
+ def local_delivery_method_category_setting?(delivery_method)
122
+ !local_delivery_method_category_setting(delivery_method).nil?
123
+ end
124
+
125
+ def local_category_settings_allow_delivery?(delivery_method)
126
+ local_delivery_method_category_setting(delivery_method, true)
127
+ end
128
+
129
+ def local_delivery_method_category_setting(delivery_method, default = nil)
130
+ category_delivery_method_setting(target, category, delivery_method,
131
+ default) &&
132
+ (subscription.nil? ||
133
+ category_delivery_method_setting(subscription, category,
134
+ delivery_method, default))
135
+ end
136
+
137
+ def global_category_settings_allow_delivery?
138
+ category_delivery_method_setting(target, category, :enabled, true) &&
139
+ (subscription.nil? ||
140
+ category_delivery_method_setting(subscription, category, :enabled,
141
+ true))
142
+ end
143
+
144
+ def delivery_method_setting(object, delivery_method, default)
145
+ object.settings.delivery_methods_.fetch(delivery_method.to_s, default)
146
+ end
147
+
148
+ def category_settings(object, category)
149
+ object.settings.categories_.send("#{category}_")
150
+ end
151
+
152
+ def category_delivery_method_setting(object, category, delivery_method,
153
+ default)
154
+ category_settings(object, category).delivery_methods_
155
+ .fetch(delivery_method.to_s, default)
156
+ end
157
+
158
+ def do_not_notify_statuses
159
+ NotificationSettings.configuration.do_not_notify_statuses
160
+ end
161
+
162
+ def do_not_deliver_statuses
163
+ NotificationSettings.configuration.do_not_deliver_statuses
164
+ end
165
+ end
166
+ # rubocop:enable Metrics/ModuleLength
167
+ end
168
+ end
@@ -7,11 +7,7 @@ module NotificationSettings
7
7
  module NotificationScopes
8
8
  extend ActiveSupport::Concern
9
9
 
10
- included do
11
- include NotificationSettings::NotificationScopes::InstanceMethods
12
- end
13
-
14
- module InstanceMethods
10
+ module ClassMethods
15
11
  def method_missing(method, *args)
16
12
  if method.to_s[/(.+)_category/]
17
13
  where(category: $1.singularize.classify)
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ module NotificationSettings
6
+ class PreferencesForm
7
+ include ActiveModel::Model
8
+
9
+ attribute :enabled, :boolean, default: true
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'hashie'
5
+
6
+ module NotificationSettings
7
+ module Settings
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ before_validation :build_settings
12
+
13
+ serialize :settings, Hashie::Mash
14
+
15
+ include NotificationSettings::Settings::InstanceMethods
16
+ end
17
+
18
+ module InstanceMethods
19
+ private
20
+
21
+ def build_settings
22
+ return if settings.present? && settings.is_a?(Hashie::Mash)
23
+
24
+ self.settings = Hashie::Mash.new
25
+ end
26
+ end
27
+ end
28
+ end
@@ -3,27 +3,33 @@
3
3
  require 'active_support'
4
4
 
5
5
  module NotificationSettings
6
- module SettingLibrary
6
+ module Status
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- include NotificationSettings::SettingLibrary::InstanceMethods
10
+ validates :status,
11
+ inclusion: { in: NotificationSettings.configuration.statuses }
12
+
13
+ include NotificationSettings::Status::InstanceMethods
11
14
  end
12
15
 
13
16
  module InstanceMethods
14
17
  def status
18
+ self[:status] || default_status
19
+ end
20
+
21
+ private
22
+
23
+ def default_status
15
24
  if idle? && !offline?
16
- default = 'idle'
25
+ 'idle'
17
26
  elsif offline?
18
- default = 'offline'
27
+ 'offline'
19
28
  else
20
29
  'online'
21
30
  end
22
- self[:status] || default
23
31
  end
24
32
 
25
- private
26
-
27
33
  def idle?
28
34
  return unless time_since_last_seen_round
29
35
 
@@ -41,11 +47,9 @@ module NotificationSettings
41
47
  end
42
48
 
43
49
  def time_since_last_seen
44
- return unless object.respond_to?(
45
- NotificationSettings.configuration.last_seen
46
- )
50
+ return unless respond_to?(NotificationSettings.configuration.last_seen)
47
51
 
48
- Time.now - object.send(NotificationSettings.configuration.last_seen)
52
+ Time.now - send(NotificationSettings.configuration.last_seen)
49
53
  end
50
54
 
51
55
  def idle_after
@@ -7,12 +7,10 @@ module NotificationSettings
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- has_many :notification_subscriptions,
10
+ has_many :notification_subscribers,
11
11
  as: :subscribable,
12
12
  class_name: 'NotificationSettings::Subscription',
13
13
  dependent: :destroy
14
- has_many :notification_subscribers,
15
- through: :notification_subscriptions, source: :subscriber
16
14
 
17
15
  include NotificationSettings::Subscribable::InstanceMethods
18
16
  end
@@ -20,24 +18,24 @@ module NotificationSettings
20
18
  module InstanceMethods
21
19
  def notify_subscribers(options = {})
22
20
  options[:object] = self
23
- subscribers = notify_dependents(options.delete(:dependents))
24
- notification_subscribers&.each do |subscriber|
25
- subscribers << subscriber
21
+ subscriptions = notify_dependents(options.delete(:dependents))
22
+ notification_subscribers&.each do |subscription|
23
+ subscriptions << subscription
26
24
  end
27
- subscribers.to_a.uniq&.each do |subscriber|
28
- subscriber.notify(options)
25
+ subscriptions.to_a.uniq&.each do |subscription|
26
+ subscription.subscriber.notify(options)
29
27
  end
30
28
  end
31
29
 
32
30
  def notify_dependents(dependents)
33
- subscribers = []
31
+ subscriptions = []
34
32
  dependents ||= notification_dependents
35
33
  dependents&.each do |dependent|
36
- dependent.notification_subscribers&.each do |subscriber|
37
- subscribers << subscriber
34
+ dependent.notification_subscribers&.each do |subscription|
35
+ subscriptions << subscription
38
36
  end
39
37
  end
40
- subscribers
38
+ subscriptions
41
39
  end
42
40
 
43
41
  private
@@ -7,28 +7,27 @@ module NotificationSettings
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- has_many :notification_subscriptions,
10
+ has_many :notification_subscribables,
11
11
  as: :subscriber,
12
12
  class_name: 'NotificationSettings::Subscription',
13
13
  dependent: :destroy
14
- has_many :notification_subscribables,
15
- through: :notification_subscriptions, source: :subscribable
16
14
 
17
15
  include NotificationSettings::Subscriber::InstanceMethods
18
16
  end
19
17
 
20
18
  module InstanceMethods
21
19
  def subscribe(subscribable, options = {})
22
- options[:subscribable] = subscribable
23
- notification_subscriptions.create(options)
20
+ notification_subscribables.create(
21
+ options.merge(subscribable: subscribable)
22
+ )
24
23
  end
25
24
 
26
25
  def unsubscribe(subscribable)
27
- subscription = notification_subscriptions.find_by(
26
+ subscription = notification_subscribables.find_by(
28
27
  subscribable_id: subscribable.id,
29
28
  subscribable_type: subscribable.class.name
30
29
  )
31
- subscription.destroy
30
+ subscription&.destroy
32
31
  end
33
32
  end
34
33
  end