marty 8.0.0 → 8.2.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/.gitlab-ci.yml +7 -0
- data/app/assets/javascripts/marty/cable.js +12 -0
- data/app/assets/stylesheets/marty/codemirror/notifications.css +4 -0
- data/app/channels/application_cable/channel.rb +4 -0
- data/app/channels/application_cable/connection.rb +17 -0
- data/app/channels/marty/notification_channel.rb +8 -0
- data/app/components/marty/auth_app.rb +54 -6
- data/app/components/marty/auth_app/client/auth_app.js +53 -0
- data/app/components/marty/main_auth_app.rb +47 -1
- data/app/components/marty/notifications/config_view.rb +56 -0
- data/app/components/marty/notifications/deliveries_view.rb +50 -0
- data/app/components/marty/notifications/grid_view.rb +56 -0
- data/app/components/marty/notifications/window.rb +23 -0
- data/app/components/marty/promise_view.rb +13 -1
- data/app/components/marty/promise_view/client/promise_view.js +18 -0
- data/app/components/marty/{schedule_jobs_dashboard/client/schedule_jobs_dashboard.js → schedule_jobs_grid/client/schedule_jobs_grid.js} +0 -0
- data/app/components/marty/simple_app/client/simple_app.js +5 -1
- data/app/components/marty/users/user_view.rb +177 -0
- data/app/controllers/marty/application_controller.rb +13 -0
- data/app/models/marty/data_grid.rb +1 -1
- data/app/models/marty/notifications.rb +4 -0
- data/app/models/marty/notifications/config.rb +25 -0
- data/app/models/marty/notifications/delivery.rb +56 -0
- data/app/models/marty/notifications/event_type.rb +11 -0
- data/app/models/marty/notifications/notification.rb +25 -0
- data/app/models/marty/promise.rb +1 -0
- data/app/models/marty/user.rb +14 -0
- data/app/services/marty/notifications/create.rb +39 -0
- data/app/services/marty/notifications/create_deliveries.rb +25 -0
- data/app/services/marty/notifications/process_delivery.rb +11 -0
- data/app/services/marty/notifications/processors/email.rb +13 -0
- data/app/services/marty/notifications/processors/sms.rb +13 -0
- data/app/services/marty/notifications/processors/web.rb +27 -0
- data/app/services/marty/promises/cancel.rb +37 -0
- data/app/services/marty/promises/delorean/create.rb +4 -0
- data/app/services/marty/promises/ruby/create.rb +4 -1
- data/app/views/marty/diagnostic/op.html.erb +4 -0
- data/db/migrate/514_remove_marty_events.rb +1 -1
- data/db/migrate/519_create_marty_notifications_event_types.rb +16 -0
- data/db/migrate/520_create_marty_notifications.rb +11 -0
- data/db/migrate/521_create_marty_notifications_deliveries.rb +22 -0
- data/db/migrate/522_create_marty_notifications_config.rb +21 -0
- data/db/sql/lookup_grid_distinct_v1.sql +6 -6
- data/lib/marty.rb +2 -0
- data/lib/marty/diagnostic/version.rb +36 -26
- data/lib/marty/engine.rb +7 -1
- data/lib/marty/mcfly_model.rb +27 -6
- data/lib/marty/railtie.rb +1 -0
- data/lib/marty/version.rb +1 -1
- data/marty.gemspec +3 -0
- data/spec/controllers/diagnostic/controller_spec.rb +1 -1
- data/spec/dummy/app/models/gemini/fannie_bup.rb +27 -13
- data/spec/dummy/app/models/gemini/helper.rb +62 -0
- data/spec/features/notifications_spec.rb +224 -0
- data/spec/job_helper.rb +14 -1
- data/spec/lib/mcfly_model_spec.rb +14 -7
- data/spec/models/promise_spec.rb +121 -0
- data/spec/services/notifications/create_spec.rb +82 -0
- metadata +73 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef38a20a14482c03a791b80eb8743f9764151a8e8d09c682c76ffeea62d76828
|
4
|
+
data.tar.gz: 480f31e3d956e235fd4941be08c209c05a7c338d3fbdeb6d2b85a4d4af7b0c28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5263a4562cfa44272654a399ef3f5e2f52cb95e27fd027c130b0477b93dad83d1b83631d5efc8946344ed5485ef5b654980282882580fd472687fd99d6b71ddc
|
7
|
+
data.tar.gz: 07e53433346be6dbd718fa631aa7535179ec944139ebbcb6fd69ef9b5182a175dad233df397ca14300581da995d553a667dbb0126e6f988ea3e5339e4fc365aa
|
data/.gitlab-ci.yml
CHANGED
@@ -10,7 +10,14 @@ before_script:
|
|
10
10
|
- RAILS_ENV=test bundle exec rails db:create db:migrate
|
11
11
|
|
12
12
|
.base-test:
|
13
|
+
# Cancel if new commits where pushed
|
14
|
+
interruptible: true
|
15
|
+
# Run only when there is an MR
|
16
|
+
only:
|
17
|
+
- merge_requests
|
18
|
+
|
13
19
|
stage: test
|
20
|
+
|
14
21
|
# Use only the following CI runners
|
15
22
|
tags:
|
16
23
|
- gitlabci-runner-eks-shared-dev
|
@@ -0,0 +1,12 @@
|
|
1
|
+
//= require action_cable
|
2
|
+
//= require_self
|
3
|
+
|
4
|
+
(function() {
|
5
|
+
this.RailsApp || (this.RailsApp = {});
|
6
|
+
|
7
|
+
if (window.location.port === "") {
|
8
|
+
RailsApp.cable = ActionCable.createConsumer(`ws://${window.location.hostname}/cable`);
|
9
|
+
} else {
|
10
|
+
RailsApp.cable = ActionCable.createConsumer(`ws://${window.location.hostname}:${window.location.port}/cable`);
|
11
|
+
}
|
12
|
+
}).call(this);
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ApplicationCable
|
2
|
+
class Connection < ::ActionCable::Connection::Base
|
3
|
+
identified_by :current_user
|
4
|
+
|
5
|
+
def connect
|
6
|
+
self.current_user = find_verified_user
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def find_verified_user
|
12
|
+
return unless cookies.signed[:user_id].present?
|
13
|
+
|
14
|
+
::Marty::User.find_by(id: cookies.signed[:user_id])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
#
|
3
3
|
# == Extending Marty::AuthApp
|
4
4
|
# DOCFIX
|
5
|
+
require 'marty/notifications/window'
|
6
|
+
|
5
7
|
class Marty::AuthApp < Marty::SimpleApp
|
6
8
|
client_class do |c|
|
7
9
|
c.include :auth_app
|
@@ -12,22 +14,54 @@ class Marty::AuthApp < Marty::SimpleApp
|
|
12
14
|
[].tap do |menu|
|
13
15
|
user = Mcfly.whodunnit
|
14
16
|
if !user.nil?
|
15
|
-
menu <<
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
name: 'sign_out',
|
20
|
-
}
|
17
|
+
menu <<
|
18
|
+
'->' <<
|
19
|
+
notification_menu_item <<
|
20
|
+
current_user_menu_item(user)
|
21
21
|
else
|
22
22
|
menu << '->' << :sign_in
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def notification_menu_item
|
28
|
+
:notifications_window
|
29
|
+
end
|
30
|
+
|
31
|
+
def current_user_menu_item(user)
|
32
|
+
{
|
33
|
+
text: user.name,
|
34
|
+
tooltip: 'Current user',
|
35
|
+
menu: user_menu,
|
36
|
+
name: 'sign_out',
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
27
40
|
def user_menu
|
28
41
|
[:sign_out, :toggle_dark_mode]
|
29
42
|
end
|
30
43
|
|
44
|
+
def unread_notifications_count
|
45
|
+
user = Mcfly.whodunnit
|
46
|
+
|
47
|
+
return 0 unless user.present?
|
48
|
+
|
49
|
+
user.unread_web_notifications_count
|
50
|
+
end
|
51
|
+
|
52
|
+
action :notifications_window do |c|
|
53
|
+
c.icon_cls = 'fa fa-bell gylph '
|
54
|
+
c.tooltip = 'Show notifications'
|
55
|
+
|
56
|
+
c.text = nil
|
57
|
+
|
58
|
+
notifications_count = unread_notifications_count
|
59
|
+
|
60
|
+
next if notifications_count.zero?
|
61
|
+
|
62
|
+
c.text = "<span class='notification-counter'>#{notifications_count}</span>"
|
63
|
+
end
|
64
|
+
|
31
65
|
action :sign_in do |c|
|
32
66
|
c.icon_cls = 'fa fa-sign-in-alt gylph'
|
33
67
|
end
|
@@ -58,4 +92,18 @@ class Marty::AuthApp < Marty::SimpleApp
|
|
58
92
|
endpoint :toggle_dark_mode do
|
59
93
|
Netzke::Base.controller.toggle_dark_mode
|
60
94
|
end
|
95
|
+
|
96
|
+
endpoint :mark_web_notifications_delivered do
|
97
|
+
user = Mcfly.whodunnit
|
98
|
+
deliveries = user.notification_deliveries.where(
|
99
|
+
delivery_type: :web,
|
100
|
+
state: [:sent]
|
101
|
+
)
|
102
|
+
|
103
|
+
deliveries.each(&:set_delivered!)
|
104
|
+
end
|
105
|
+
|
106
|
+
component :notifications_window do |c|
|
107
|
+
c.klass = ::Marty::Notifications::Window
|
108
|
+
end
|
61
109
|
end
|
@@ -91,5 +91,58 @@
|
|
91
91
|
|
92
92
|
netzkeOnToggleDarkMode: function() {
|
93
93
|
this.server.toggleDarkMode(() => { window.location.href = "/" });
|
94
|
+
},
|
95
|
+
|
96
|
+
netzkeOnNotificationsWindow: function () {
|
97
|
+
this.netzkeLoadComponent("notifications_window", {
|
98
|
+
callback: function (w) {
|
99
|
+
w.show();
|
100
|
+
|
101
|
+
this.server.markWebNotificationsDelivered();
|
102
|
+
|
103
|
+
var notificationsButton = this.menuBar.items.items.find(
|
104
|
+
function(item) { return item.name === "notificationsWindow" }
|
105
|
+
);
|
106
|
+
|
107
|
+
notificationsButton.setText(''); // Remove the counter
|
108
|
+
},
|
109
|
+
});
|
110
|
+
},
|
111
|
+
|
112
|
+
netzkeInitComponentCallback: function() {
|
113
|
+
try {
|
114
|
+
var subscription = RailsApp.cable.subscriptions.subscriptions.find(
|
115
|
+
(sub) => sub.identifier === '{"channel":"Marty::NotificationChannel"}'
|
116
|
+
)
|
117
|
+
|
118
|
+
// In case if component is initialized twice
|
119
|
+
if (subscription) {
|
120
|
+
return
|
121
|
+
}
|
122
|
+
|
123
|
+
RailsApp.cable.subscriptions.create(
|
124
|
+
'Marty::NotificationChannel',
|
125
|
+
{
|
126
|
+
received: (data) => {
|
127
|
+
var notificationsButton = this.menuBar.items.items.find(
|
128
|
+
function(item) { return item.name === "notificationsWindow" }
|
129
|
+
);
|
130
|
+
|
131
|
+
if (data.unread_notifications_count > 0) {
|
132
|
+
notificationsButton.setText(
|
133
|
+
`<span class='notification-counter'>${data.unread_notifications_count}</span>`
|
134
|
+
);
|
135
|
+
} else {
|
136
|
+
notificationsButton.setText('');
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
);
|
141
|
+
}
|
142
|
+
catch(error) {
|
143
|
+
console.log('ActionCable connection failed')
|
144
|
+
console.error(error);
|
145
|
+
}
|
94
146
|
}
|
95
147
|
}
|
148
|
+
|
@@ -13,6 +13,8 @@ require 'marty/promise_view'
|
|
13
13
|
require 'marty/reporting'
|
14
14
|
require 'marty/scripting'
|
15
15
|
require 'marty/user_view'
|
16
|
+
require 'marty/notifications/config_view'
|
17
|
+
require 'marty/notifications/deliveries_view'
|
16
18
|
|
17
19
|
class Marty::MainAuthApp < Marty::AuthApp
|
18
20
|
extend ::Marty::Permissions
|
@@ -86,7 +88,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
86
88
|
:config_view,
|
87
89
|
:reload_scripts,
|
88
90
|
:load_seed,
|
89
|
-
] + background_jobs_menu + log_menu + api_menu
|
91
|
+
] + background_jobs_menu + notifications_menu + log_menu + api_menu
|
90
92
|
}
|
91
93
|
end
|
92
94
|
|
@@ -121,6 +123,22 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
121
123
|
]
|
122
124
|
end
|
123
125
|
|
126
|
+
def notifications_menu
|
127
|
+
disabled = !(self.class.has_perm?(:admin) ||
|
128
|
+
self.class.has_perm?(:user_manager))
|
129
|
+
[
|
130
|
+
{
|
131
|
+
text: 'Notifications',
|
132
|
+
icon_cls: 'fa fa-bell glyph',
|
133
|
+
disabled: disabled,
|
134
|
+
menu: [
|
135
|
+
:notifications_config_view,
|
136
|
+
:notifications_deliveries_view,
|
137
|
+
]
|
138
|
+
},
|
139
|
+
]
|
140
|
+
end
|
141
|
+
|
124
142
|
def warped
|
125
143
|
Marty::Util.warped?
|
126
144
|
end
|
@@ -319,6 +337,25 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
319
337
|
a.disabled = !self.class.has_perm?(:admin)
|
320
338
|
end
|
321
339
|
|
340
|
+
# action 'Notifications::ConfigView' do |a|
|
341
|
+
action :notifications_config_view do |a|
|
342
|
+
a.text = 'User Notification Rules'
|
343
|
+
a.tooltip = 'Configure notification rules for users'
|
344
|
+
a.handler = :netzke_load_component_by_action
|
345
|
+
a.icon_cls = 'fa fa-sliders-h glyph'
|
346
|
+
a.disabled = !(self.class.has_perm?(:admin) ||
|
347
|
+
self.class.has_perm?(:user_manager))
|
348
|
+
end
|
349
|
+
|
350
|
+
action :notifications_deliveries_view do |a|
|
351
|
+
a.text = 'Notificaiton messages'
|
352
|
+
a.tooltip = 'Show all notification messages'
|
353
|
+
a.handler = :netzke_load_component_by_action
|
354
|
+
a.icon_cls = 'fa fa-list glyph'
|
355
|
+
a.disabled = !(self.class.has_perm?(:admin) ||
|
356
|
+
self.class.has_perm?(:dev))
|
357
|
+
end
|
358
|
+
|
322
359
|
######################################################################
|
323
360
|
|
324
361
|
def bg_command(subcmd)
|
@@ -408,6 +445,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
408
445
|
component :config_view
|
409
446
|
|
410
447
|
component :data_grid_view
|
448
|
+
|
411
449
|
component :data_grid_user_view
|
412
450
|
|
413
451
|
component :import_type_view
|
@@ -420,6 +458,14 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
420
458
|
c.disabled = Marty::Util.warped? || !self.class.has_posting_perm?
|
421
459
|
end
|
422
460
|
|
461
|
+
component :notifications_config_view do |c|
|
462
|
+
c.klass = ::Marty::Notifications::ConfigView
|
463
|
+
end
|
464
|
+
|
465
|
+
component :notifications_deliveries_view do |c|
|
466
|
+
c.klass = ::Marty::Notifications::DeliveriesView
|
467
|
+
end
|
468
|
+
|
423
469
|
component :posting_window
|
424
470
|
|
425
471
|
component :promise_view
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Marty
|
2
|
+
module Notifications
|
3
|
+
class ConfigView < Marty::Grid
|
4
|
+
include Marty::Extras::Layout
|
5
|
+
|
6
|
+
has_marty_permissions create: [:admin, :user_manager],
|
7
|
+
read: [:admin, :user_manager],
|
8
|
+
update: [:admin, :user_manager],
|
9
|
+
delete: [:admin, :user_manager]
|
10
|
+
|
11
|
+
def configure(c)
|
12
|
+
super
|
13
|
+
|
14
|
+
c.attributes = [:event_type, :recipient__name, :delivery_type, :state, :text]
|
15
|
+
|
16
|
+
c.title ||= I18n.t('notifications_config', default: 'Notifications Configuration')
|
17
|
+
c.model = 'Marty::Notifications::Config'
|
18
|
+
c.editing = :in_form
|
19
|
+
c.paging = :pagination
|
20
|
+
c.store_config.merge!(
|
21
|
+
sorters: [{ property: :id, direction: 'DESC', }]
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
attribute :event_type do |c|
|
26
|
+
c.width = 200
|
27
|
+
enum_column(c, ::Marty::Notifications::EventType, nil, false)
|
28
|
+
end
|
29
|
+
|
30
|
+
attribute :recipient__name do |c|
|
31
|
+
c.width = 200
|
32
|
+
end
|
33
|
+
|
34
|
+
attribute :delivery_type do |c|
|
35
|
+
enum_column(c, model::AVAILABLE_TYPES, nil, false)
|
36
|
+
c.width = 70
|
37
|
+
end
|
38
|
+
|
39
|
+
attribute :state do |c|
|
40
|
+
enum_column(c, model.state_machines[:state].states.map(&:value), nil, false)
|
41
|
+
c.width = 70
|
42
|
+
c.label = I18n.t('notifications_config_state', default: 'On/Off')
|
43
|
+
end
|
44
|
+
|
45
|
+
attribute :text do |c|
|
46
|
+
c.width = 400
|
47
|
+
c.label = I18n.t('notifications_config_text', default: 'Message text')
|
48
|
+
c.setter = lambda do |record, value|
|
49
|
+
next record.text = '' if value.nil?
|
50
|
+
|
51
|
+
record.text = value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Marty
|
2
|
+
module Notifications
|
3
|
+
class DeliveriesView < Marty::Grid
|
4
|
+
ROLES_WITH_ACCESS = [:admin, :dev]
|
5
|
+
|
6
|
+
has_marty_permissions read: ROLES_WITH_ACCESS,
|
7
|
+
create: nil,
|
8
|
+
update: nil,
|
9
|
+
delete: ROLES_WITH_ACCESS
|
10
|
+
|
11
|
+
def configure(c)
|
12
|
+
super
|
13
|
+
|
14
|
+
c.header = false
|
15
|
+
c.model = 'Marty::Notifications::Delivery'
|
16
|
+
c.attributes = [:created_at, :notification__event_type, :recipient__name,
|
17
|
+
:state, :delivery_type, :text, :error_text]
|
18
|
+
c.store_config.merge!(
|
19
|
+
sorters: [{ property: :id, direction: 'DESC' }],
|
20
|
+
page_size: 30
|
21
|
+
)
|
22
|
+
|
23
|
+
c.scope = ->(arel) { arel.includes(:notification).includes(:recipient) }
|
24
|
+
end
|
25
|
+
|
26
|
+
attribute :notification__event_type do |config|
|
27
|
+
config.width = 150
|
28
|
+
config.label = 'Event'
|
29
|
+
end
|
30
|
+
|
31
|
+
attribute :recipient__name do |config|
|
32
|
+
config.width = 150
|
33
|
+
config.label = 'Recipient'
|
34
|
+
end
|
35
|
+
|
36
|
+
attribute :text do |config|
|
37
|
+
config.width = 400
|
38
|
+
|
39
|
+
config.getter = lambda do |record|
|
40
|
+
[record.notification.text, record.text].join(', ')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
attribute :error_text do |config|
|
45
|
+
config.width = 300
|
46
|
+
config.label = 'Error'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Marty
|
2
|
+
module Notifications
|
3
|
+
class GridView < Marty::Grid
|
4
|
+
has_marty_permissions read: :any,
|
5
|
+
create: nil,
|
6
|
+
update: nil,
|
7
|
+
delete: nil
|
8
|
+
|
9
|
+
def configure(c)
|
10
|
+
super
|
11
|
+
|
12
|
+
c.header = false
|
13
|
+
c.model = 'Marty::Notifications::Delivery'
|
14
|
+
c.attributes = [:created_at, :notification__event_type, :text, :error_text]
|
15
|
+
c.store_config.merge!(
|
16
|
+
sorters: [{ property: :created_at, direction: 'DESC' }],
|
17
|
+
page_size: 30
|
18
|
+
)
|
19
|
+
|
20
|
+
c.scope = ->(arel) { arel.includes(:notification) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_records(params)
|
24
|
+
model.where(
|
25
|
+
delivery_type: :web,
|
26
|
+
state: [:sent, :delivered],
|
27
|
+
recipient_id: Mcfly.whodunnit
|
28
|
+
).scoping do
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_bbar
|
34
|
+
[]
|
35
|
+
end
|
36
|
+
|
37
|
+
attribute :notification__event_type do |config|
|
38
|
+
config.width = 150
|
39
|
+
config.label = 'Event'
|
40
|
+
end
|
41
|
+
|
42
|
+
attribute :text do |config|
|
43
|
+
config.width = 300
|
44
|
+
|
45
|
+
config.getter = lambda do |record|
|
46
|
+
[record.notification.text, record.text].join(', ')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
attribute :error_text do |config|
|
51
|
+
config.width = 300
|
52
|
+
config.label = 'Error'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|