notification-settings 3.0.2 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1e7e1a607828b135d54de95b1ece9e33e82203958bd5333a1c47543312517d2
4
- data.tar.gz: c4c11125679498057707fdb4ff232ccd7003b8490e818890b74a060da5b5baee
3
+ metadata.gz: 81f51d7d4a8dca20f5f20c248b34ea9f9290e8844285dfd93b93111d3f1c27cd
4
+ data.tar.gz: bd923e061018cffba1249a8f728db477acad1a3eea9879f7965bc786245c54ac
5
5
  SHA512:
6
- metadata.gz: eddc817ec775d4a8c7eab2cc99f80390c0461d10cb8b78b61358498b936abada0e4946b79157972f964421de895fee8b6771cdcec88ea110ede32872a5eca08b
7
- data.tar.gz: b456e6e377efd47c3b8397952c4f56773284766961f45103369b21cbb1df0709149f998fdd67c6ee5923d70c2306c9082f8cd547e624abdce87410601e60ccd0
6
+ metadata.gz: b4f50488e3f1d1b4df6f290e02fedbe56a544cbd870e7f7d59b22787da3464663258abe3b4e12ce2c38478cf0753a6973556d0b3fd3e7f73ce7b1facedb097b0
7
+ data.tar.gz: 1c55207dc022117e228e7f39753ae322999d6dae499e53b78cfb3bdf4830eb8404b6b035e9ab19dbb096489430ed9e0abeb3adc6e50b074ba60c8d3ada3bab71
data/README.md CHANGED
@@ -1,316 +1,84 @@
1
- # NotificationSettings
1
+ # notifications-rails
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/notification-settings.svg)](https://badge.fury.io/rb/notification-settings) ![Travis](https://travis-ci.com/jonhue/notifications-rails.svg?branch=master)
3
+ notifications-rails is the most powerful notification library for Rails. It offers not only simple APIs to create and render notifications but also supports user-integration and cross-platform delivery of notifications.
4
4
 
5
- Integrates with your authentication solution to craft a personalized user notification platform.
5
+ ## Philosophy
6
6
 
7
- ---
7
+ notifications-rails has been built with modularity in mind. It currently consists of four components each of which bringing one essential functionality to the integration of notifications in your Rails app.
8
8
 
9
- ## Table of Contents
9
+ **[notification-handler](notification-handler):** Create and modify your notifications through a simple API.
10
10
 
11
- * [Installation](#installation)
12
- * [Usage](#usage)
13
- * [Categories](#categories)
14
- * [Settings](#settings)
15
- * [Category-specific settings](#category-specific-settings)
16
- * [Pusher-specific settings](#pusher-specific-settings)
17
- * [Updating settings](#updating-settings)
18
- * [Subscriptions](#subscriptions)
19
- * [Status](#status)
20
- * [Configuration](#configuration)
21
- * [Status](#status)
22
- * [To Do](#to-do)
23
- * [Contributing](#contributing)
24
- * [Semantic versioning](#semantic-versioning)
11
+ **[notification-renderer](notification-renderer):** Render your notifications in various contexts.
25
12
 
26
- ---
13
+ **[notification-pusher](notification-pusher):** Deliver your notifications to various services, including [Email](notification-pusher/notification-pusher-actionmailer) and [OneSignal](notification-pusher/notification-pusher-onesignal).
27
14
 
28
- ## Installation
29
-
30
- NotificationSettings works with Rails 5 onwards. You can add it to your `Gemfile` with:
31
-
32
- ```ruby
33
- gem 'notification-settings'
34
- ```
35
-
36
- And then execute:
37
-
38
- $ bundle
39
-
40
- Or install it yourself as:
41
-
42
- $ gem install notification-settings
43
-
44
- Now run the generator:
45
-
46
- $ rails g notification_handler:install
47
- $ rails g notification_settings:install
48
-
49
- To wrap things up, migrate the changes to your database:
50
-
51
- $ rails db:migrate
52
-
53
- ---
54
-
55
- ## Usage
56
-
57
- First, you have to add some attributes to every model that acts as a `notification_target`:
58
-
59
- ```ruby
60
- class User
61
- # ...
62
-
63
- notification_target
64
- end
65
- ```
66
-
67
- ```ruby
68
- # A Hashie::Mash object that stores all the settings of a notification target.
69
- add_column :users, :settings, :text
70
-
71
- # A string that describes a notification-relevant state of a notification target.
72
- add_column :users, :status, :string
73
- ```
74
-
75
- ### Categories
76
-
77
- NotificationSettings uses categories to allow your notification targets to define specific preferences. This is how you are able to specify the `category` of a `Notification` record:
78
-
79
- ```ruby
80
- notification = Notification.create(target: User.first, object: Recipe.first, category: :notification)
81
- ```
82
-
83
- **Note:** The `category` attribute of any new `Notification` record will default to the [`default_category` configuration](#configuration).
84
-
85
- You can also scope records by their category:
86
-
87
- ```ruby
88
- # Return records with `'notification'` as category
89
- Notification.notification_category
90
-
91
- # Return records with `'follow'` as category
92
- Notification.follow_category
93
- ```
94
-
95
- ### Settings
96
-
97
- You can completely disable notifications for a given notification target:
98
-
99
- ```ruby
100
- settings = User.first.settings
101
-
102
- settings.enabled = false
103
- ```
104
-
105
- This will prevent you from creating any new notifications with this user as target.
106
-
107
- The default is `true` (enabled) for this setting and the other settings.
108
-
109
- #### Category-specific settings
110
-
111
- A user can also have category-specific settings:
112
-
113
- ```ruby
114
- settings.categories!.send("#{category}!").enabled = false
115
- ```
116
-
117
- #### Delivery-method-specific settings
118
-
119
- He can have global or category-specific delivery method settings:
120
-
121
- ```ruby
122
- settings.delivery_methods!.enabled = false # Prevent delivering via *any* delivery method
123
- settings.delivery_methods!.email!.enabled = false # Prevent delivering via the :email delivery method
124
- settings.categories!.category!.delivery_methods!.email!.enabled = false # Prevent delivering via the :email delivery method for :category
125
- ```
126
-
127
- #### Form objects
128
-
129
- NotificationSettings comes with three form objects that simplify building forms for updating settings.
130
-
131
- ##### PreferencesForm
132
-
133
- The preferences form has just one attribute: `enabled`. It can be used to update the global notification setting.
15
+ **[notification-settings](notification-settings):** Integrates with your authentication solution to craft a personalized user notification platform.
134
16
 
135
- ```ruby
136
- user = User.first
137
-
138
- form = NotificationSettings::PreferencesForm.new(enabled: user.settings.enabled)
139
- form.valid?
140
-
141
- user.settings.enabled = form.enabled
142
- ```
143
-
144
- ##### CategoryPreferencesForm
145
-
146
- The category preferences form has one attribute per category. It can be used to update category-specific settings.
147
-
148
- ```ruby
149
- user = User.first
150
-
151
- form = NotificationSettings::CategoryPreferencesForm.new(user.settings.categories_.to_h)
152
- form.valid?
153
-
154
- form.changed_attributes.each do |category|
155
- user.settings.categories!.send(category, form.send(category))
156
- end
157
- ```
158
-
159
- ##### DeliveryMethodPreferencesForm
160
-
161
- The delivery method preferences form has one attribute per category and a general `enabled` attribute. It can be used to update delivery-method-specific settings or to disable all delivery methods.
162
-
163
- ```ruby
164
- user = User.first
17
+ You may just use the components you actually need, or instead use this gem to bundle everything for a complete notification solution.
165
18
 
166
- form = NotificationSettings::DeliveryMethodPreferencesForm.new(user.settings.delivery_methods_.to_h)
167
- form.valid?
168
-
169
- form.changed_attributes.each do |delivery_method|
170
- user.settings.delivery_methods!.send(delivery_method, form.send(delivery_method))
171
- end
172
- ```
173
-
174
- ### Subscriptions
175
-
176
- Subscriptions are a way to better handle settings for notifications from different objects to one notification target.
177
-
178
- This is how to subscribe/unsubscribe a target to an object:
179
-
180
- ```ruby
181
- User.first.subscribe(Recipe.first)
182
- User.first.unsubscribe(Recipe.first)
183
- ```
184
-
185
- Now you can easily notify all subscribers from the subscribable object:
186
-
187
- ```ruby
188
- Recipe.first.notify_subscribers(delivery_method: :ActionMailer)
189
- ```
190
-
191
- Let's assume that we have a group which has multiple chats. When sending notifications to subscribers of a given chat, we only want them to get notified. But when sending notifications about the group, we want to have everyone notified, that is either subscribed to the group or subscribed to one of its chats. To do that you have to add the `private` method `notification_dependents` to your model (in this case `Group`) and return an array of ActiveRecord objects whose subscribers should receive notifications for objects of this class.
192
-
193
- ```ruby
194
- has_many :chats
195
- has_many :talks
196
-
197
- private
198
-
199
- def notification_dependents
200
- self.chats
201
- end
202
- ```
203
-
204
- It is possible to override that behavior when notifying subscribers:
205
-
206
- ```ruby
207
- # Disable notification dependents
208
- Group.first.notify_subscribers(dependents: nil)
209
-
210
- # Override notification dependents
211
- Group.first.notify_subscribers(dependents: Group.first.chats + Group.first.talks)
212
- ```
213
-
214
- You can customize settings & status for a single subscription just as you would for a notification target:
215
-
216
- ```ruby
217
- user = User.first
218
- subscription = user.notification_subscriptions.first
219
-
220
- subscription.settings.enabled = false
221
- subscription.status = 'online'
222
- subscription.save
223
- ```
224
-
225
- [Learn more](#settings)
19
+ ## Installation
226
20
 
227
- You can add associations to your subscriber/subscribable classes if you need easy access to all their subscriptions:
21
+ You can add notifications-rails to your `Gemfile` with:
228
22
 
229
23
  ```ruby
230
- # For subscribers:
231
- # List all subscriptions of a subscriber
232
- subscriber.notification_subscribables
233
- # List all subscribables of a specific type a subscriber subscribed to
234
- has_many :subscribed_products, through: :notification_subscribables, source: :subscribable, source_type: 'Product'
235
-
236
- # For subscribables:
237
- # List all subscriptions of a subscriber
238
- subscribable.notification_subscribers
239
- # List all subscribers of a specific type that subscribed to a subscribable
240
- has_many :subscribed_users, through: :notification_subscribers, source: :subscriber, source_type: 'User'
24
+ gem 'notifications-rails'
241
25
  ```
242
26
 
243
- ### Status
27
+ And then run:
244
28
 
245
- NotificationSettings comes with a handy feature called Status. The status of a record can temporarily disable the ability to create notifications for or to push notifications of a target.
29
+ $ bundle install
246
30
 
247
- This is how to define a status:
248
-
249
- ```ruby
250
- User.first.update(status: 'do not disturb')
251
- ```
252
-
253
- **Note:** You can set `status` to any string you like.
254
-
255
- `status` has three possible values that are being used as defaults. Normally it defaults to `'online'`. If the `last_seen` [configuration](#configuration) option has been set, it can also default to `'idle'` or `'offline'` depending on the `idle_after` and `offline_after` [configuration](#configuration) options.
31
+ Or install it yourself as:
256
32
 
257
- If you have set `status` to a custom value, you can get back to using the defaults by setting it back to `nil`.
33
+ $ gem install notifications-rails
258
34
 
259
- You can define statuses that prevent creating new notifications for a target and statuses that just prevent delivering them:
35
+ If you always want to be up to date fetch the latest from GitHub in your `Gemfile`:
260
36
 
261
37
  ```ruby
262
- NotificationSettings.configure do |config|
263
- config.do_not_notify_statuses = ['do not notify']
264
- config.do_not_deliver_statuses = ['do not disturb']
265
- end
38
+ gem 'notifications-rails', github: 'jonhue/notifications-rails'
266
39
  ```
267
40
 
268
- ---
269
-
270
- ## Configuration
271
-
272
- You can configure NotificationSettings by passing a block to `configure`. This can be done in `config/initializers/notification-settings.rb`:
273
-
274
- ```ruby
275
- NotificationSettings.configure do |config|
276
- config.categories = [:notification]
277
- end
278
- ```
41
+ ## Usage
279
42
 
280
- **`categories`** Choose your default notification category. Takes an array of symbols. Defaults to `[:notification]`.
43
+ Details on usage are provided in the [documentation](#philosophy) of the specific modules.
281
44
 
282
- **`default_category`** Choose your default notification category. Takes a symbol. Defaults to `:notification`.
45
+ ## Development
283
46
 
284
- ### Status
47
+ To start development you first have to fork this repository and locally clone your fork.
285
48
 
286
- **`idle_after`** Time duration without activity after which the status defaults to `'idle'`. Takes a time. Defaults to `10.minutes`.
49
+ Install the projects dependencies by running:
287
50
 
288
- **`offline_after`** Time duration without activity after which the status defaults to `'offline'`. Takes a time. Defaults to `3.hours`.
51
+ $ bundle install
289
52
 
290
- **`last_seen`** Stringified datetime attribute name of `object` that defines the time of the last activity. Takes a symbol. Defaults to `:last_seen`.
53
+ ### Testing
291
54
 
292
- **`statuses`** Array of all possible statuses. Takes an array of strings. Defaults to `['online', 'idle', 'offline', 'do not notify', 'do not disturb']`.
55
+ Tests are written with RSpec. Integration tests are located in `/spec`, unit tests can be found in `<module>/spec`.
293
56
 
294
- **`do_not_notify_statuses`** Array of possible statuses that will prevent creating notifications for a target. Takes an array of strings. Defaults to `['do not notify']`.
57
+ To run all tests:
295
58
 
296
- **`do_not_deliver_statuses`** Array of possible statuses that will prevent delivering notifications of a target. Takes an array of strings. Defaults to `['do not disturb']`
59
+ $ ./rspec
297
60
 
298
- ---
61
+ To run RuboCop:
299
62
 
300
- ## To Do
63
+ $ bundle exec rubocop
301
64
 
302
- We use [GitHub projects](https://github.com/jonhue/notifications-rails/projects/4) to coordinate the work on this project.
65
+ You can find all commands run by the CI workflow in `.github/workflows/ci.yml`.
303
66
 
304
- To propose your ideas, initiate the discussion by adding a [new issue](https://github.com/jonhue/notifications-rails/issues/new).
67
+ ## Contributing
305
68
 
306
- ---
69
+ We warmly welcome everyone who is intersted in contributing. Please reference our [contributing guidelines](CONTRIBUTING.md) and our [Code of Conduct](CODE_OF_CONDUCT.md).
307
70
 
308
- ## Contributing
71
+ ## Releases
309
72
 
310
- We hope that you will consider contributing to NotificationSettings. Please read this short overview for some information about how to get started:
73
+ [Here](https://github.com/jonhue/notifications-rails/releases) you can find details on all past releases. Unreleased breaking changes that are on the current master can be found [here](CHANGELOG.md).
311
74
 
312
- [Learn more about contributing to this repository](https://github.com/jonhue/notifications-rails/blob/master/CONTRIBUTING.md), [Code of Conduct](https://github.com/jonhue/notifications-rails/blob/master/CODE_OF_CONDUCT.md)
75
+ notifications-rails follows Semantic Versioning 2.0 as defined at http://semver.org. Reference our [security policy](SECURITY.md).
313
76
 
314
- ### Semantic Versioning
77
+ ### Publishing
315
78
 
316
- NotificationSettings follows Semantic Versioning 2.0 as defined at http://semver.org.
79
+ 1. Review breaking changes and deprecations in `CHANGELOG.md`.
80
+ 1. Change the gem version in `VERSION`.
81
+ 1. Reset `CHANGELOG.md`.
82
+ 1. Create a pull request to merge the changes into `master`.
83
+ 1. After the pull request was merged, create a new release listing the breaking changes and commits on `master` since the last release.
84
+ 1. The release workflow will publish the gems to RubyGems.
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'notification-handler'
4
+ require 'notification-renderer'
5
+ require 'notification-pusher'
6
+ require 'notification-settings'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: notification-settings
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.2
4
+ version: 3.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Hübotter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-10 00:00:00.000000000 Z
11
+ date: 2020-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -56,30 +56,36 @@ dependencies:
56
56
  name: hashie
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '3.6'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '5.0'
62
65
  type: :runtime
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
66
- - - "~>"
69
+ - - ">="
67
70
  - !ruby/object:Gem::Version
68
71
  version: '3.6'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: notification-handler
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
79
  - - '='
74
80
  - !ruby/object:Gem::Version
75
- version: 3.0.2
81
+ version: 3.0.3
76
82
  type: :runtime
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - '='
81
87
  - !ruby/object:Gem::Version
82
- version: 3.0.2
88
+ version: 3.0.3
83
89
  - !ruby/object:Gem::Dependency
84
90
  name: railties
85
91
  requirement: !ruby/object:Gem::Requirement
@@ -194,30 +200,14 @@ dependencies:
194
200
  version: '0'
195
201
  description: Integrates with your authentication solution to craft a personalized
196
202
  user notification platform.
197
- email: me@jonhue.me
203
+ email: jonas.huebotter@gmail.com
198
204
  executables: []
199
205
  extensions: []
200
206
  extra_rdoc_files: []
201
207
  files:
202
208
  - LICENSE
203
209
  - README.md
204
- - app/models/notification_settings/subscription.rb
205
- - lib/generators/notification_settings/install_generator.rb
206
- - lib/generators/templates/install/initializer.rb
207
- - lib/generators/templates/install/notifications_migration.rb.erb
208
- - lib/notification-settings.rb
209
- - lib/notification_settings/category_preferences_form.rb
210
- - lib/notification_settings/configuration.rb
211
- - lib/notification_settings/delivery_method_preferences_form.rb
212
- - lib/notification_settings/engine.rb
213
- - lib/notification_settings/notification_lib.rb
214
- - lib/notification_settings/notification_scopes.rb
215
- - lib/notification_settings/preferences_form.rb
216
- - lib/notification_settings/settings.rb
217
- - lib/notification_settings/status.rb
218
- - lib/notification_settings/subscribable.rb
219
- - lib/notification_settings/subscriber.rb
220
- - lib/notification_settings/target.rb
210
+ - lib/notifications-rails.rb
221
211
  homepage: https://github.com/jonhue/notifications-rails/tree/master/notification-settings
222
212
  licenses:
223
213
  - MIT
@@ -238,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
228
  - !ruby/object:Gem::Version
239
229
  version: '0'
240
230
  requirements: []
241
- rubygems_version: 3.0.3
231
+ rubygems_version: 3.1.4
242
232
  signing_key:
243
233
  specification_version: 4
244
234
  summary: Integrates with your authentication solution to craft a personalized user
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NotificationSettings
4
- class Subscription < ActiveRecord::Base
5
- self.table_name = 'notification_settings_subscriptions'
6
-
7
- include NotificationSettings::Settings
8
-
9
- belongs_to :subscriber, polymorphic: true
10
- belongs_to :subscribable, polymorphic: true
11
-
12
- has_many :notifications, class_name: '::Notification'
13
- end
14
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
- require 'rails/generators/migration'
5
-
6
- module NotificationSettings
7
- class InstallGenerator < Rails::Generators::Base
8
- include Rails::Generators::Migration
9
-
10
- source_root(File.join(File.dirname(__FILE__), '../templates/install'))
11
- desc 'Install NotificationSettings'
12
-
13
- def self.next_migration_number(dirname)
14
- if ActiveRecord::Base.timestamped_migrations
15
- Time.now.utc.strftime('%Y%m%d%H%M%S')
16
- else
17
- format('%<migration_number>.3d',
18
- migration_number: current_migration_number(dirname) + 1)
19
- end
20
- end
21
-
22
- def create_initializer
23
- template 'initializer.rb', 'config/initializers/notification_settings.rb'
24
- end
25
-
26
- def create_notifications_migration_file
27
- migration_template(
28
- 'notifications_migration.rb.erb',
29
- 'db/migrate/notification_settings_migration.rb',
30
- migration_version: migration_version
31
- )
32
- end
33
-
34
- private
35
-
36
- def migration_version
37
- return unless Rails.version >= '5.0.0'
38
-
39
- "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
40
- end
41
- end
42
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- NotificationSettings.configure do |config|
4
- # An array of all notification categories. Takes an array of symbols.
5
- # config.categories = [:notification]
6
-
7
- # Choose your default notification category. Takes a symbol.
8
- # config.default_category = :notification
9
-
10
- ### STATUS ###
11
-
12
- # Time duration without activity after which the status defaults to `'idle'`.
13
- # Takes a time.
14
- # config.idle_after = 10.minutes
15
-
16
- # Time duration without activity after which the status defaults to
17
- # `'offline'`. Takes a time.
18
- # config.offline_after = 3.hours
19
-
20
- # Stringified datetime attribute name of `object` that defines the time of the
21
- # last activity. Takes a symbol.
22
- # config.last_seen = :last_seen
23
-
24
- # Array of all possible statuses. Takes an array of strings.
25
- # config.statuses = [
26
- # 'online',
27
- # 'idle',
28
- # 'offline',
29
- # 'do not notify',
30
- # 'do not disturb'
31
- # ]
32
-
33
- # Array of possible statuses that will prevent creating notifications for a
34
- # target. Takes an array of strings.
35
- # config.do_not_notify_statuses = ['do not notify']
36
-
37
- # Array of possible statuses that will prevent pushing notifications of a
38
- # target. Takes an array of strings.
39
- # config.do_not_deliver_statuses = ['do not disturb']
40
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class NotificationSettingsMigration < ActiveRecord::Migration<%= migration_version %>
4
- def change
5
- add_column :notifications, :subscription_id, :bigint, index: true
6
- add_column :notifications, :category, :string, index: true
7
-
8
- create_table :notification_settings_subscriptions do |t|
9
- t.references :subscriber,
10
- polymorphic: true,
11
- index: {
12
- name: 'idx_subscriptions_subscriber_type_subscriber_id'
13
- }
14
- t.references :subscribable,
15
- polymorphic: true,
16
- index: {
17
- name: 'idx_subscriptions_subscribable_type_subscribable_id'
18
- }
19
-
20
- t.text :settings
21
-
22
- t.timestamps
23
- end
24
- end
25
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NotificationSettings
4
- require_relative 'notification_settings/configuration'
5
-
6
- require_relative 'notification_settings/engine'
7
-
8
- autoload :Target, 'notification_settings/target'
9
- autoload :Subscriber, 'notification_settings/subscriber'
10
- autoload :Subscribable, 'notification_settings/subscribable'
11
- autoload :Settings, 'notification_settings/settings'
12
- autoload :Status, 'notification_settings/status'
13
- autoload :NotificationLib, 'notification_settings/notification_lib'
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'
20
- end
@@ -1,13 +0,0 @@
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
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NotificationSettings
4
- class << self
5
- attr_writer :configuration
6
-
7
- def configuration
8
- @configuration ||= Configuration.new
9
- end
10
- end
11
-
12
- def self.configure
13
- yield configuration
14
- end
15
-
16
- class Configuration
17
- attr_accessor :categories
18
- attr_accessor :default_category
19
- attr_accessor :last_seen
20
- attr_accessor :idle_after
21
- attr_accessor :offline_after
22
- attr_accessor :statuses
23
- attr_accessor :do_not_notify_statuses
24
- attr_accessor :do_not_deliver_statuses
25
-
26
- def initialize
27
- @categories = [:notification]
28
- @default_category = :notification
29
- @last_seen = :last_seen
30
- @idle_after = 10.minutes
31
- @offline_after = 3.hours
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']
36
- end
37
- end
38
- end
@@ -1,15 +0,0 @@
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,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/engine'
4
- require 'active_record'
5
-
6
- module NotificationSettings
7
- class Engine < ::Rails::Engine
8
- end
9
- end
@@ -1,168 +0,0 @@
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
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'notification-handler'
4
- require 'active_support'
5
-
6
- module NotificationSettings
7
- module NotificationScopes
8
- extend ActiveSupport::Concern
9
-
10
- module ClassMethods
11
- def method_missing(method, *args)
12
- if method.to_s[/(.+)_category/]
13
- where(category: $1.singularize.classify)
14
- else
15
- super
16
- end
17
- end
18
-
19
- def respond_to_missing?(method, include_private = false)
20
- super || method.to_s[/(.+)_category/]
21
- end
22
- end
23
- end
24
- end
@@ -1,11 +0,0 @@
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
@@ -1,28 +0,0 @@
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
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support'
4
-
5
- module NotificationSettings
6
- module Status
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- validates :status,
11
- inclusion: { in: NotificationSettings.configuration.statuses }
12
-
13
- include NotificationSettings::Status::InstanceMethods
14
- end
15
-
16
- module InstanceMethods
17
- def status
18
- self[:status] || default_status
19
- end
20
-
21
- private
22
-
23
- def default_status
24
- if idle? && !offline?
25
- 'idle'
26
- elsif offline?
27
- 'offline'
28
- else
29
- 'online'
30
- end
31
- end
32
-
33
- def idle?
34
- return unless time_since_last_seen_round
35
-
36
- time_since_last_seen_round >= idle_after
37
- end
38
-
39
- def offline?
40
- return unless time_since_last_seen_round
41
-
42
- time_since_last_seen_round >= offline_after
43
- end
44
-
45
- def time_since_last_seen_round
46
- time_since_last_seen&.round
47
- end
48
-
49
- def time_since_last_seen
50
- return unless respond_to?(NotificationSettings.configuration.last_seen)
51
-
52
- Time.now - send(NotificationSettings.configuration.last_seen)
53
- end
54
-
55
- def idle_after
56
- NotificationSettings.configuration.idle_after
57
- end
58
-
59
- def offline_after
60
- NotificationSettings.configuration.offline_after
61
- end
62
- end
63
- end
64
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support'
4
-
5
- module NotificationSettings
6
- module Subscribable
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- has_many :notification_subscribers,
11
- as: :subscribable,
12
- class_name: 'NotificationSettings::Subscription',
13
- dependent: :destroy
14
-
15
- include NotificationSettings::Subscribable::InstanceMethods
16
- end
17
-
18
- module InstanceMethods
19
- def notify_subscribers(options = {})
20
- options[:object] = self
21
- subscriptions = notify_dependents(options.delete(:dependents))
22
- notification_subscribers&.each do |subscription|
23
- subscriptions << subscription
24
- end
25
- subscriptions.to_a.uniq&.each do |subscription|
26
- subscription.subscriber.notify(options)
27
- end
28
- end
29
-
30
- def notify_dependents(dependents)
31
- subscriptions = []
32
- dependents ||= notification_dependents
33
- dependents&.each do |dependent|
34
- dependent.notification_subscribers&.each do |subscription|
35
- subscriptions << subscription
36
- end
37
- end
38
- subscriptions
39
- end
40
-
41
- private
42
-
43
- def notification_dependents
44
- []
45
- end
46
- end
47
- end
48
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support'
4
-
5
- module NotificationSettings
6
- module Subscriber
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- has_many :notification_subscribables,
11
- as: :subscriber,
12
- class_name: 'NotificationSettings::Subscription',
13
- dependent: :destroy
14
-
15
- include NotificationSettings::Subscriber::InstanceMethods
16
- end
17
-
18
- module InstanceMethods
19
- def subscribe(subscribable, options = {})
20
- notification_subscribables.create(
21
- options.merge(subscribable: subscribable)
22
- )
23
- end
24
-
25
- def unsubscribe(subscribable)
26
- subscription = notification_subscribables.find_by(
27
- subscribable_id: subscribable.id,
28
- subscribable_type: subscribable.class.name
29
- )
30
- subscription&.destroy
31
- end
32
- end
33
- end
34
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support'
4
-
5
- module NotificationSettings
6
- module Target
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- include NotificationSettings::Settings
11
- include NotificationSettings::Status
12
- end
13
- end
14
- end