marty 8.0.0 → 8.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|