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.
- checksums.yaml +4 -4
- data/README.md +128 -83
- data/app/models/notification_settings/subscription.rb +1 -2
- data/lib/generators/notification_settings/install_generator.rb +2 -1
- data/lib/generators/templates/install/initializer.rb +18 -6
- data/lib/generators/templates/install/notifications_migration.rb.erb +11 -13
- data/lib/notification-settings.rb +10 -5
- data/lib/notification_settings/category_preferences_form.rb +13 -0
- data/lib/notification_settings/configuration.rb +15 -7
- data/lib/notification_settings/delivery_method_preferences_form.rb +15 -0
- data/lib/notification_settings/engine.rb +1 -1
- data/lib/notification_settings/notification_lib.rb +168 -0
- data/lib/notification_settings/notification_scopes.rb +1 -5
- data/lib/notification_settings/preferences_form.rb +11 -0
- data/lib/notification_settings/settings.rb +28 -0
- data/lib/notification_settings/{setting_library.rb → status.rb} +15 -11
- data/lib/notification_settings/subscribable.rb +10 -12
- data/lib/notification_settings/subscriber.rb +6 -7
- data/lib/notification_settings/target.rb +2 -15
- metadata +106 -21
- data/app/models/notification_settings/setting.rb +0 -15
- data/lib/notification_settings/notification_library.rb +0 -144
- data/lib/notification_settings/subscription_library.rb +0 -23
@@ -1,15 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module NotificationSettings
|
4
|
-
|
4
|
+
require_relative 'notification_settings/configuration'
|
5
5
|
|
6
|
-
|
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 :
|
12
|
-
autoload :
|
13
|
-
autoload :
|
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
|
-
|
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 :
|
24
|
+
attr_accessor :do_not_deliver_statuses
|
20
25
|
|
21
26
|
def initialize
|
22
|
-
@
|
23
|
-
@
|
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
|
-
@
|
27
|
-
|
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
|
@@ -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
|
-
|
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,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
|
6
|
+
module Status
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
included do
|
10
|
-
|
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
|
-
|
25
|
+
'idle'
|
17
26
|
elsif offline?
|
18
|
-
|
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
|
45
|
-
NotificationSettings.configuration.last_seen
|
46
|
-
)
|
50
|
+
return unless respond_to?(NotificationSettings.configuration.last_seen)
|
47
51
|
|
48
|
-
Time.now -
|
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 :
|
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
|
-
|
24
|
-
notification_subscribers&.each do |
|
25
|
-
|
21
|
+
subscriptions = notify_dependents(options.delete(:dependents))
|
22
|
+
notification_subscribers&.each do |subscription|
|
23
|
+
subscriptions << subscription
|
26
24
|
end
|
27
|
-
|
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
|
-
|
31
|
+
subscriptions = []
|
34
32
|
dependents ||= notification_dependents
|
35
33
|
dependents&.each do |dependent|
|
36
|
-
dependent.notification_subscribers&.each do |
|
37
|
-
|
34
|
+
dependent.notification_subscribers&.each do |subscription|
|
35
|
+
subscriptions << subscription
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
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 :
|
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
|
-
|
23
|
-
|
20
|
+
notification_subscribables.create(
|
21
|
+
options.merge(subscribable: subscribable)
|
22
|
+
)
|
24
23
|
end
|
25
24
|
|
26
25
|
def unsubscribe(subscribable)
|
27
|
-
subscription =
|
26
|
+
subscription = notification_subscribables.find_by(
|
28
27
|
subscribable_id: subscribable.id,
|
29
28
|
subscribable_type: subscribable.class.name
|
30
29
|
)
|
31
|
-
subscription
|
30
|
+
subscription&.destroy
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|