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
data/app/models/marty/promise.rb
CHANGED
data/app/models/marty/user.rb
CHANGED
@@ -9,6 +9,13 @@ class Marty::User < Marty::Base
|
|
9
9
|
|
10
10
|
has_many :user_roles, dependent: :destroy
|
11
11
|
|
12
|
+
has_many(
|
13
|
+
:notification_deliveries,
|
14
|
+
class_name: '::Marty::Notifications::Delivery',
|
15
|
+
dependent: :destroy,
|
16
|
+
foreign_key: :recipient_id
|
17
|
+
)
|
18
|
+
|
12
19
|
scope :active, -> { where(active: true) }
|
13
20
|
|
14
21
|
validate :verify_changes
|
@@ -114,6 +121,13 @@ class Marty::User < Marty::Base
|
|
114
121
|
end
|
115
122
|
end
|
116
123
|
|
124
|
+
def unread_web_notifications_count
|
125
|
+
notification_deliveries.where(
|
126
|
+
delivery_type: :web,
|
127
|
+
state: [:sent]
|
128
|
+
).count
|
129
|
+
end
|
130
|
+
|
117
131
|
private
|
118
132
|
|
119
133
|
def verify_changes
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Marty
|
2
|
+
module Notifications
|
3
|
+
module Create
|
4
|
+
extend Delorean::Functions
|
5
|
+
|
6
|
+
delorean_fn :call do |event_type:, text:|
|
7
|
+
notification, deliveries = ActiveRecord::Base.transaction do
|
8
|
+
notification = ::Marty::Notifications::Notification.create!(
|
9
|
+
event_type: event_type,
|
10
|
+
text: text,
|
11
|
+
state: :pending
|
12
|
+
)
|
13
|
+
|
14
|
+
# FIXME: We should consider processing deliveries in the background
|
15
|
+
deliveries = ::Marty::Notifications::CreateDeliveries.call(
|
16
|
+
notification: notification
|
17
|
+
)
|
18
|
+
|
19
|
+
[notification, deliveries]
|
20
|
+
end
|
21
|
+
|
22
|
+
deliveries.each do |delivery|
|
23
|
+
::Marty::Notifications::ProcessDelivery.call(
|
24
|
+
delivery: delivery
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
notification.set_processed!
|
29
|
+
|
30
|
+
{
|
31
|
+
id: notification.id,
|
32
|
+
event_type: event_type,
|
33
|
+
text: text,
|
34
|
+
state: notification.state,
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Marty
|
2
|
+
module Notifications
|
3
|
+
module CreateDeliveries
|
4
|
+
class << self
|
5
|
+
def call(notification:)
|
6
|
+
configs(notification).map do |config|
|
7
|
+
notification.deliveries.create!(
|
8
|
+
state: :pending,
|
9
|
+
delivery_type: config.delivery_type,
|
10
|
+
recipient: config.recipient,
|
11
|
+
text: config.text
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def configs(notification)
|
17
|
+
Marty::Notifications::Config.where(
|
18
|
+
state: :on,
|
19
|
+
event_type: notification.event_type
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Marty
|
2
|
+
module Notifications
|
3
|
+
module Processors
|
4
|
+
module Web
|
5
|
+
class << self
|
6
|
+
def call(delivery:)
|
7
|
+
delivery.set_sent!
|
8
|
+
notify_websocket(delivery: delivery)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def notify_websocket(delivery:)
|
14
|
+
return unless Rails.application.config.marty.enable_action_cable
|
15
|
+
|
16
|
+
unread_notifications_count = delivery.recipient&.unread_web_notifications_count
|
17
|
+
|
18
|
+
ActionCable.server.broadcast(
|
19
|
+
"marty_notifications_#{delivery.recipient_id}",
|
20
|
+
unread_notifications_count: unread_notifications_count
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Marty::Promises
|
2
|
+
module Cancel
|
3
|
+
class << self
|
4
|
+
def call(id)
|
5
|
+
ids = get_all_ids(id)
|
6
|
+
promises = Marty::Promise.where(id: ids)
|
7
|
+
jobids = promises.map(&:job_id).compact.sort
|
8
|
+
Delayed::Job.where(id: jobids).destroy_all
|
9
|
+
promises.each do |p|
|
10
|
+
p.update!(status: false,
|
11
|
+
end_dt: p.end_dt || Time.zone.now,
|
12
|
+
result: p.result + { error: 'Cancelled' })
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Promises are nodes/leaves on a tree. Given a promise id
|
19
|
+
# from anywhere on the tree, find the ids of all promises
|
20
|
+
# on that tree.
|
21
|
+
def get_all_ids(id)
|
22
|
+
get_base = lambda do |pid|
|
23
|
+
p = Marty::Promise.find_by(id: pid)
|
24
|
+
p.parent_id ? get_base.call(p.parent_id) : pid
|
25
|
+
end
|
26
|
+
base_id = get_base.call(id)
|
27
|
+
get_children = lambda do |pid|
|
28
|
+
children = Marty::Promise.where(parent_id: pid).pluck(:id)
|
29
|
+
children.present? ?
|
30
|
+
(children + children.map { |cid| get_children.call(cid) }).flatten :
|
31
|
+
children
|
32
|
+
end
|
33
|
+
[base_id] + get_children.call(base_id)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -15,9 +15,13 @@ module Marty
|
|
15
15
|
pid = promise_params[:_parent_id]
|
16
16
|
if pid
|
17
17
|
ppr = Marty::Promise.find_by(id: pid)
|
18
|
+
# make sure parent isn't cancelled
|
19
|
+
return if ppr&.result&.[]('error') == 'Cancelled'
|
20
|
+
|
18
21
|
default_priority = ppr.priority if ppr
|
19
22
|
end
|
20
23
|
priority = promise_params['p_priority'] || default_priority
|
24
|
+
|
21
25
|
promise = Marty::Promise.create(
|
22
26
|
title: title,
|
23
27
|
user_id: promise_params[:_user_id],
|
@@ -15,10 +15,13 @@ module Marty
|
|
15
15
|
pid = promise_params[:_parent_id]
|
16
16
|
if pid
|
17
17
|
ppr = Marty::Promise.find_by(id: pid)
|
18
|
+
# make sure parent isn't cancelled
|
19
|
+
return if ppr&.result&.[]('error') == 'Cancelled'
|
20
|
+
|
18
21
|
default_priority = ppr.priority if ppr
|
19
22
|
end
|
20
|
-
|
21
23
|
priority = promise_params['p_priority'] || default_priority
|
24
|
+
|
22
25
|
promise = Marty::Promise.create(
|
23
26
|
title: title,
|
24
27
|
user_id: promise_params[:_user_id],
|
@@ -1,5 +1,9 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
|
+
<% if cookies[:dark_mode] == 'true' %>
|
4
|
+
<%= stylesheet_link_tag 'marty/dark_mode', media: 'all', 'data-turbolinks-track': 'reload' %>
|
5
|
+
<% end %>
|
6
|
+
|
3
7
|
<head>
|
4
8
|
<title><%=Rails.application.class.parent_name%> Diagnostic</title>
|
5
9
|
<style type="text/css">
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateMartyNotificationsEventTypes < ActiveRecord::Migration[4.2]
|
2
|
+
def up
|
3
|
+
values = ::Marty::Notifications::EventType::VALUES
|
4
|
+
str_values = values.map {|v| ActiveRecord::Base.connection.quote v}.join ','
|
5
|
+
|
6
|
+
execute <<-SQL
|
7
|
+
CREATE TYPE marty_notifications_event_types AS ENUM (#{str_values});
|
8
|
+
SQL
|
9
|
+
end
|
10
|
+
|
11
|
+
def down
|
12
|
+
execute <<-SQL
|
13
|
+
DROP TYPE marty_notifications_event_types;
|
14
|
+
SQL
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class CreateMartyNotifications < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :marty_notifications do |t|
|
4
|
+
t.pg_enum :event_type, enum: :marty_notifications_event_types, null: false
|
5
|
+
t.string :state, null: false
|
6
|
+
t.text :text, null: false
|
7
|
+
|
8
|
+
t.timestamps null: false
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class CreateMartyNotificationsDeliveries < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :marty_notifications_deliveries do |t|
|
4
|
+
t.integer :notification_id, null: false
|
5
|
+
t.integer :recipient_id
|
6
|
+
t.string :delivery_type, null: false
|
7
|
+
t.string :state, null: false
|
8
|
+
t.text :text, null: false, default: ''
|
9
|
+
t.string :error_text, null: false, default: ''
|
10
|
+
|
11
|
+
t.timestamps null: false
|
12
|
+
end
|
13
|
+
|
14
|
+
add_foreign_key :marty_notifications_deliveries, :marty_notifications,
|
15
|
+
column: :notification_id, on_delete: :cascade
|
16
|
+
add_foreign_key :marty_notifications_deliveries, :marty_users,
|
17
|
+
column: :recipient_id, on_delete: :nullify
|
18
|
+
|
19
|
+
add_index :marty_notifications_deliveries, [:notification_id, :recipient_id, :delivery_type],
|
20
|
+
unique: true, name: :index_marty_notifications_deliveries_on_n_id_r_id_and_type
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateMartyNotificationsConfig < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :marty_notifications_configs do |t|
|
4
|
+
t.pg_enum :event_type, enum: :marty_notifications_event_types, null: false
|
5
|
+
t.integer :recipient_id
|
6
|
+
t.string :delivery_type, null: false
|
7
|
+
t.string :state, null: false
|
8
|
+
t.text :text, null: false, default: ''
|
9
|
+
|
10
|
+
t.timestamps null: false
|
11
|
+
end
|
12
|
+
|
13
|
+
add_foreign_key :marty_notifications_configs, :marty_users,
|
14
|
+
column: :recipient_id, on_delete: :nullify
|
15
|
+
|
16
|
+
add_index :marty_notifications_configs,
|
17
|
+
[:event_type, :recipient_id, :delivery_type],
|
18
|
+
unique: true,
|
19
|
+
name: :index_marty_notifications_configs_on_event_recipient_delivery
|
20
|
+
end
|
21
|
+
end
|
@@ -37,7 +37,7 @@ DECLARE
|
|
37
37
|
|
38
38
|
result JSONB;
|
39
39
|
return_json JSONB;
|
40
|
-
|
40
|
+
|
41
41
|
error_extra JSONB;
|
42
42
|
|
43
43
|
target RECORD;
|
@@ -58,7 +58,7 @@ BEGIN
|
|
58
58
|
END IF;
|
59
59
|
END LOOP;
|
60
60
|
|
61
|
-
FOREACH direction IN ARRAY directions LOOP
|
61
|
+
FOREACH direction IN ARRAY directions LOOP
|
62
62
|
|
63
63
|
IF direction = 'h' THEN
|
64
64
|
data_grid_metadata_current := data_grid_metadata_h;
|
@@ -89,7 +89,7 @@ BEGIN
|
|
89
89
|
|
90
90
|
query_index_result := empty_jsonb_array;
|
91
91
|
|
92
|
-
-- execute the SQL query that has been received before and
|
92
|
+
-- execute the SQL query that has been received before and
|
93
93
|
-- add it's (possibly multiplt) results to query_index_result variable
|
94
94
|
FOR target IN EXECUTE query_dir_result ->> 0 USING query_dir_result -> 1 LOOP
|
95
95
|
query_index_result := query_index_result || to_jsonb(target.index);
|
@@ -105,7 +105,7 @@ BEGIN
|
|
105
105
|
END IF;
|
106
106
|
|
107
107
|
|
108
|
-
IF dis AND jsonb_array_length(query_index_result) > 1 THEN
|
108
|
+
IF dis AND jsonb_array_length(query_index_result) > 1 THEN
|
109
109
|
RAISE EXCEPTION 'matches > 1';
|
110
110
|
END IF;
|
111
111
|
|
@@ -114,7 +114,7 @@ BEGIN
|
|
114
114
|
vertical_indexes := COALESCE(vertical_indexes, empty_jsonb_array);
|
115
115
|
horizontal_indexes := COALESCE(horizontal_indexes, empty_jsonb_array);
|
116
116
|
|
117
|
-
IF ((jsonb_array_length(vertical_indexes)) = 0
|
117
|
+
IF ((jsonb_array_length(vertical_indexes)) = 0
|
118
118
|
OR (jsonb_array_length(horizontal_indexes)) = 0)
|
119
119
|
AND NOT data_grid_lenient
|
120
120
|
AND NOT return_grid_data THEN
|
@@ -140,7 +140,7 @@ BEGIN
|
|
140
140
|
result := data_grid_data -> vertical_index -> horizontal_index;
|
141
141
|
END IF;
|
142
142
|
|
143
|
-
IF NOT return_grid_data THEN
|
143
|
+
IF NOT return_grid_data THEN
|
144
144
|
data_grid_data := NULL;
|
145
145
|
data_grid_metadata := NULL;
|
146
146
|
END IF;
|
data/lib/marty.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
# Also note that anything required here will need to require in any
|
9
9
|
# classes that they might be overriding methods in
|
10
|
+
require 'action_cable/engine'
|
10
11
|
|
11
12
|
require 'marty/engine'
|
12
13
|
require 'marty/railtie'
|
@@ -22,6 +23,7 @@ require 'marty/rails_app'
|
|
22
23
|
# to the Gemfile
|
23
24
|
require 'net-ldap'
|
24
25
|
require 'delayed_cron_job'
|
26
|
+
require 'state_machines-activerecord'
|
25
27
|
|
26
28
|
require 'pathname'
|
27
29
|
|
@@ -1,30 +1,40 @@
|
|
1
|
-
module Marty::Diagnostic
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Marty::Diagnostic
|
2
|
+
class Version < Base
|
3
|
+
diagnostic_fn do
|
4
|
+
begin
|
5
|
+
submodules = `cd #{Rails.root}; git submodule`.split("\n").map do |s|
|
6
|
+
sha, path, tag = s.split
|
7
|
+
name = File.basename(path)
|
8
|
+
{
|
9
|
+
"#{name}_sha".titleize => sha[0..7],
|
10
|
+
"#{name}_tag".titleize => tag,
|
11
|
+
}
|
12
|
+
end.reduce(&:merge) || {}
|
13
|
+
|
14
|
+
git_tag = `cd #{Rails.root}; git describe --tags --always;`.strip
|
15
|
+
git = { 'Root Git' => git_tag }.merge(submodules)
|
16
|
+
rescue StandardError
|
17
|
+
git = { 'Root Git' => error('Failed accessing git') }
|
18
|
+
end
|
19
|
+
rbv = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
|
20
|
+
{
|
21
|
+
'Marty' => Marty::VERSION,
|
22
|
+
'Delorean' => Delorean::VERSION,
|
23
|
+
'Mcfly' => Mcfly::VERSION,
|
24
|
+
'Rails' => Rails.version,
|
25
|
+
'Netzke Core' => Netzke::Core::VERSION,
|
26
|
+
'Netzke Basepack' => Netzke::Basepack::VERSION,
|
27
|
+
'Ruby' => rbv,
|
28
|
+
'RubyGems' => Gem::VERSION,
|
29
|
+
'Database Schema Version' => db_schema,
|
30
|
+
'Environment' => Rails.env,
|
31
|
+
}.merge(git)
|
7
32
|
end
|
8
|
-
rbv = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
|
9
|
-
{
|
10
|
-
'Marty' => Marty::VERSION,
|
11
|
-
'Delorean' => Delorean::VERSION,
|
12
|
-
'Mcfly' => Mcfly::VERSION,
|
13
|
-
'Git' => message,
|
14
|
-
'Rails' => Rails.version,
|
15
|
-
'Netzke Core' => Netzke::Core::VERSION,
|
16
|
-
'Netzke Basepack' => Netzke::Basepack::VERSION,
|
17
|
-
'Ruby' => rbv,
|
18
|
-
'RubyGems' => Gem::VERSION,
|
19
|
-
'Database Schema Version' => db_schema,
|
20
|
-
'Environment' => Rails.env,
|
21
|
-
}
|
22
|
-
end
|
23
33
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
34
|
+
def self.db_schema
|
35
|
+
Database.db_schema
|
36
|
+
rescue StandardError => e
|
37
|
+
error(e.message)
|
38
|
+
end
|
28
39
|
end
|
29
40
|
end
|
30
|
-
end
|