marty 2.1.5 → 2.3.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/Gemfile +2 -0
- data/Gemfile.lock +4 -4
- data/app/components/marty/auth_app.rb +3 -3
- data/app/components/marty/auth_app/client/auth_app.js +1 -3
- data/app/components/marty/base_rule_view.rb +32 -20
- data/app/components/marty/data_grid_view.rb +3 -3
- data/app/components/marty/event_view.rb +0 -5
- data/app/components/marty/form.rb +8 -1
- data/app/components/marty/form/client/form.css +3 -0
- data/app/components/marty/grid.rb +174 -33
- data/app/components/marty/import_view.rb +151 -0
- data/app/components/marty/main_auth_app.rb +28 -28
- data/app/components/marty/mcfly_grid_panel.rb +1 -1
- data/app/components/marty/new_posting_form.rb +3 -3
- data/app/components/marty/new_posting_window.rb +5 -6
- data/app/components/marty/posting_grid.rb +2 -2
- data/app/components/marty/posting_window.rb +1 -2
- data/app/components/marty/promise_view.rb +11 -6
- data/app/components/marty/record_form_window.rb +1 -1
- data/app/components/marty/report_form.rb +4 -4
- data/app/components/marty/report_select.rb +1 -1
- data/app/components/marty/script_form.rb +4 -4
- data/app/components/marty/script_grid.rb +2 -2
- data/app/components/marty/script_tester.rb +1 -1
- data/app/components/marty/simple_app.rb +1 -2
- data/app/components/marty/simple_app/client/statusbar_ext.js +1 -1
- data/app/components/marty/tag_grid.rb +1 -1
- data/app/components/marty/user_view.rb +5 -5
- data/app/controllers/marty/job_controller.rb +5 -1
- data/app/models/marty/base.rb +0 -15
- data/app/models/marty/data_grid.rb +1 -1
- data/app/models/marty/log.rb +1 -0
- data/app/models/marty/promise.rb +27 -84
- data/app/models/marty/vw_promise.rb +72 -0
- data/app/views/layouts/marty/application.html.erb +6 -3
- data/config/locales/en.yml +4 -0
- data/db/migrate/410_jsonb_promise_result.rb +9 -0
- data/db/migrate/411_create_vw_promises.rb +26 -0
- data/lib/marty/data_change.rb +3 -4
- data/lib/marty/data_conversion.rb +1 -2
- data/lib/marty/data_importer.rb +13 -14
- data/lib/marty/javascript/{overrides.js → grid_view_in_form.js} +10 -6
- data/lib/marty/mcfly_model.rb +13 -20
- data/lib/marty/monkey.rb +33 -40
- data/lib/marty/promise_job.rb +8 -2
- data/lib/marty/promise_proxy.rb +6 -11
- data/lib/marty/rule_script_set.rb +5 -2
- data/lib/marty/version.rb +1 -1
- data/marty.gemspec +1 -1
- data/other/marty/diagnostic/delayed_job_workers.rb +8 -5
- data/spec/controllers/job_controller_spec.rb +34 -15
- data/spec/dummy/app/components/gemini/my_rule_view.rb +6 -0
- data/spec/dummy/app/models/gemini/helper.rb +2 -2
- data/spec/dummy/config/application.rb +1 -1
- data/spec/features/rule_spec.rb +100 -5
- data/spec/fixtures/csv/rule/MyRule.csv +1 -1
- data/spec/job_helper.rb +2 -4
- data/spec/lib/data_importer_spec.rb +10 -10
- data/spec/lib/delorean_query_spec.rb +13 -2
- data/spec/lib/logger_spec.rb +16 -14
- data/spec/models/data_grid_spec.rb +4 -10
- data/spec/models/promise_spec.rb +8 -8
- data/spec/models/rule_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -1
- metadata +10 -5
@@ -4,6 +4,7 @@ class Marty::PromiseView < Netzke::Tree::Base
|
|
4
4
|
client_styles do |config|
|
5
5
|
config.require :promise_view
|
6
6
|
end
|
7
|
+
|
7
8
|
client_class do |config|
|
8
9
|
config.default_get_row_class = l(<<-JS)
|
9
10
|
function(record, index, rowParams, ds) {
|
@@ -41,7 +42,7 @@ class Marty::PromiseView < Netzke::Tree::Base
|
|
41
42
|
def configure(config)
|
42
43
|
super
|
43
44
|
config.title = I18n.t("jobs.promise_view")
|
44
|
-
config.model = "Marty::
|
45
|
+
config.model = "Marty::VwPromise"
|
45
46
|
config.attributes = [
|
46
47
|
{name: :title, xtype: :treecolumn},
|
47
48
|
:user__login,
|
@@ -114,20 +115,20 @@ class Marty::PromiseView < Netzke::Tree::Base
|
|
114
115
|
action :clear do |a|
|
115
116
|
a.text = a.tooltip = 'Clear'
|
116
117
|
a.disabled = false
|
117
|
-
a.
|
118
|
+
a.icon_cls = "fa fa-minus glyph"
|
118
119
|
a.hidden = !self.class.has_admin_perm?
|
119
120
|
end
|
120
121
|
|
121
122
|
action :download do |a|
|
122
123
|
a.text = a.tooltip = 'Download'
|
123
124
|
a.disabled = true
|
124
|
-
a.
|
125
|
+
a.icon_cls = "fa fa-download glyph"
|
125
126
|
end
|
126
127
|
|
127
128
|
action :refresh do |a|
|
128
129
|
a.text = a.tooltip = 'Refresh'
|
129
130
|
a.disabled = false
|
130
|
-
a.
|
131
|
+
a.icon_cls = "fa fa-sync-alt glyph"
|
131
132
|
end
|
132
133
|
|
133
134
|
endpoint :clear do |params|
|
@@ -137,7 +138,7 @@ class Marty::PromiseView < Netzke::Tree::Base
|
|
137
138
|
|
138
139
|
def get_records params
|
139
140
|
search_scope = config[:live_search_scope] || :live_search
|
140
|
-
Marty::
|
141
|
+
Marty::VwPromise.children_for_id(params[:id], params[search_scope])
|
141
142
|
end
|
142
143
|
|
143
144
|
attribute :title do |config|
|
@@ -172,7 +173,11 @@ class Marty::PromiseView < Netzke::Tree::Base
|
|
172
173
|
end
|
173
174
|
|
174
175
|
attribute :error do |config|
|
175
|
-
config.getter = ->(record) {
|
176
|
+
config.getter = ->(record) {
|
177
|
+
if !record.status
|
178
|
+
Marty::Promise.find_by(id: record.id).try(:result).to_s
|
179
|
+
end
|
180
|
+
}
|
176
181
|
config.flex = 1
|
177
182
|
end
|
178
183
|
end
|
@@ -4,19 +4,19 @@ class Marty::ReportForm < Marty::Form
|
|
4
4
|
action :apply do |a|
|
5
5
|
a.text = a.tooltip = I18n.t("reporting.background")
|
6
6
|
a.handler = :netzke_on_apply
|
7
|
-
a.
|
7
|
+
a.icon_cls = "fa fa-cloud glyph"
|
8
8
|
a.disabled = false
|
9
9
|
end
|
10
10
|
|
11
11
|
action :foreground do |a|
|
12
12
|
a.text = a.tooltip = I18n.t("reporting.generate")
|
13
|
-
a.
|
13
|
+
a.icon_cls = "fa fa-download glyph"
|
14
14
|
a.disabled = false
|
15
15
|
end
|
16
16
|
|
17
17
|
action :link do |a|
|
18
18
|
a.text = a.tooltip = I18n.t("reporting.link")
|
19
|
-
a.
|
19
|
+
a.icon_cls = "fa fa-link glyph"
|
20
20
|
a.disabled = false
|
21
21
|
end
|
22
22
|
|
@@ -262,7 +262,7 @@ class Marty::ReportForm < Marty::Form
|
|
262
262
|
}
|
263
263
|
}
|
264
264
|
|
265
|
-
c.items = items
|
265
|
+
c.items = add_cls_to_fields(items)
|
266
266
|
c.repformat = format
|
267
267
|
c.title = "Generate: #{title}-#{sset.tag.name}"
|
268
268
|
c.reptitle = title
|
@@ -109,7 +109,7 @@ class Marty::ScriptForm < Marty::Form
|
|
109
109
|
action :apply do |a|
|
110
110
|
a.text = I18n.t("script_form.save")
|
111
111
|
a.tooltip = I18n.t("script_form.save")
|
112
|
-
a.
|
112
|
+
a.icon_cls = "fa fa-save glyph"
|
113
113
|
a.disabled = true
|
114
114
|
end
|
115
115
|
|
@@ -191,9 +191,9 @@ class Marty::ScriptForm < Marty::Form
|
|
191
191
|
######################################################################
|
192
192
|
|
193
193
|
action :do_print do |a|
|
194
|
-
a.text
|
195
|
-
a.tooltip
|
196
|
-
a.
|
194
|
+
a.text = I18n.t("script_form.print")
|
195
|
+
a.tooltip = I18n.t("script_form.print")
|
196
|
+
a.icon_cls = "fa fa-print glyph"
|
197
197
|
end
|
198
198
|
|
199
199
|
######################################################################
|
@@ -34,7 +34,7 @@ class Marty::ScriptGrid < Marty::Grid
|
|
34
34
|
action :delete do |a|
|
35
35
|
a.text = I18n.t("script_grid.delete")
|
36
36
|
a.tooltip = I18n.t("script_grid.delete")
|
37
|
-
a.
|
37
|
+
a.icon_cls = "fa fa-trash glyph"
|
38
38
|
a.disabled = config[:prohibit_delete]
|
39
39
|
end
|
40
40
|
|
@@ -77,7 +77,7 @@ class Marty::ScriptGrid < Marty::Grid
|
|
77
77
|
action :add_in_form do |a|
|
78
78
|
a.text = I18n.t("script_grid.new")
|
79
79
|
a.tooltip = I18n.t("script_grid.new")
|
80
|
-
a.
|
80
|
+
a.icon_cls = "fa fa-plus glyph"
|
81
81
|
a.disabled = !config[:permissions][:create]
|
82
82
|
end
|
83
83
|
|
@@ -66,7 +66,6 @@ class Marty::SimpleApp < Netzke::Base
|
|
66
66
|
:itemId => 'status_bar',
|
67
67
|
:xtype => 'statusbar',
|
68
68
|
:region => 'south',
|
69
|
-
:height => 22,
|
70
69
|
:statusAlign => 'right',
|
71
70
|
:busyText => 'Busy...',
|
72
71
|
:default_text => "Ready",
|
@@ -78,9 +77,9 @@ class Marty::SimpleApp < Netzke::Base
|
|
78
77
|
def menu_bar_config(overrides = {})
|
79
78
|
{
|
80
79
|
:itemId => 'menu_bar',
|
80
|
+
:layout => {overflow_handler: 'Menu'},
|
81
81
|
:xtype => 'toolbar',
|
82
82
|
:region => 'north',
|
83
|
-
:height => 28,
|
84
83
|
:items => menu
|
85
84
|
}.merge(overrides)
|
86
85
|
end
|
@@ -100,19 +100,19 @@ module Marty; class UserView < Marty::Grid
|
|
100
100
|
|
101
101
|
action :add do |a|
|
102
102
|
super(a)
|
103
|
-
a.text
|
104
|
-
a.tooltip
|
105
|
-
a.
|
103
|
+
a.text = I18n.t("user_grid.new")
|
104
|
+
a.tooltip = I18n.t("user_grid.new")
|
105
|
+
a.icon_cls = "fa fa-user-plus glyph"
|
106
106
|
end
|
107
107
|
|
108
108
|
action :edit do |a|
|
109
109
|
super(a)
|
110
|
-
a.
|
110
|
+
a.icon_cls = "fa fa-user-cog glyph"
|
111
111
|
end
|
112
112
|
|
113
113
|
action :delete do |a|
|
114
114
|
super(a)
|
115
|
-
a.
|
115
|
+
a.icon_cls = "fa fa-user-minus glyph"
|
116
116
|
end
|
117
117
|
|
118
118
|
def default_context_menu
|
@@ -6,9 +6,13 @@ class Marty::JobController < ActionController::Base
|
|
6
6
|
|
7
7
|
if promise
|
8
8
|
format = promise.cformat
|
9
|
+
|
10
|
+
# Force result so finalized object is built
|
11
|
+
data = promise.result(true)
|
12
|
+
|
9
13
|
# somewhat hacky: if result has "result" key, it's used as the
|
10
14
|
# content.
|
11
|
-
data =
|
15
|
+
data = data["result"] || data
|
12
16
|
title = promise.title
|
13
17
|
else
|
14
18
|
format = "json"
|
data/app/models/marty/base.rb
CHANGED
@@ -6,21 +6,6 @@ class Marty::Base < ActiveRecord::Base
|
|
6
6
|
tb = self.table_name
|
7
7
|
self.where("#{tb}.obsoleted_dt >= ? AND #{tb}.created_dt < ?", pt, pt)
|
8
8
|
end
|
9
|
-
MCFLY_PT_SIG = [1, 1]
|
10
|
-
|
11
|
-
# FIXME: hacky signatures for AR queries
|
12
|
-
COUNT_SIG = [0, 0]
|
13
|
-
DISTINCT_SIG = [0, 100]
|
14
|
-
FIRST_SIG = [0, 1]
|
15
|
-
GROUP_SIG = [1, 100]
|
16
|
-
JOINS_SIG = [1, 100]
|
17
|
-
LAST_SIG = [0, 1]
|
18
|
-
LIMIT_SIG = [1, 1]
|
19
|
-
NOT_SIG = [1, 100]
|
20
|
-
ORDER_SIG = [1, 100]
|
21
|
-
PLUCK_SIG = [1, 100]
|
22
|
-
SELECT_SIG = [1, 100]
|
23
|
-
WHERE_SIG = [0, 100]
|
24
9
|
|
25
10
|
class << self
|
26
11
|
attr_accessor :struct_attrs
|
@@ -188,7 +188,7 @@ class Marty::DataGrid < Marty::Base
|
|
188
188
|
h = dgh["metadata"].each_with_object({}) do |m, h|
|
189
189
|
attr = m["attr"]
|
190
190
|
inc = h_passed.fetch(attr, :__nf__)
|
191
|
-
next if inc == :__nf__
|
191
|
+
next if inc == :__nf__ || inc.nil?
|
192
192
|
val = (defined? inc.name) ? inc.name : inc
|
193
193
|
h[attr] = val.is_a?(String) ?
|
194
194
|
ActiveRecord::Base.connection.quote(val)[1..-2] : val
|
data/app/models/marty/log.rb
CHANGED
data/app/models/marty/promise.rb
CHANGED
@@ -1,14 +1,4 @@
|
|
1
1
|
class Marty::Promise < Marty::Base
|
2
|
-
class MarshalResult
|
3
|
-
def dump(v)
|
4
|
-
Marshal.dump(v)
|
5
|
-
end
|
6
|
-
|
7
|
-
def load(v)
|
8
|
-
# Marshal.load can't handle nil
|
9
|
-
v ? Marshal.load(v) : {}
|
10
|
-
end
|
11
|
-
end
|
12
2
|
|
13
3
|
# default timeout (seconds) to wait for promise values
|
14
4
|
DEFAULT_PROMISE_TIMEOUT = Rails.configuration.marty.promise_timeout || 30
|
@@ -16,30 +6,38 @@ class Marty::Promise < Marty::Base
|
|
16
6
|
# default timeout (seconds) to wait for jobs to start
|
17
7
|
DEFAULT_JOB_TIMEOUT = Rails.configuration.marty.job_timeout || 10
|
18
8
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
}
|
23
|
-
def result
|
24
|
-
unless has_attribute?(:result)
|
25
|
-
changes_before_reload = self.changes.clone
|
26
|
-
self.reload
|
27
|
-
changes_before_reload.each{
|
28
|
-
|attribute_name, values|
|
29
|
-
self.send("#{attribute_name}=", values[1])
|
30
|
-
}
|
31
|
-
end
|
32
|
-
read_attribute :result
|
9
|
+
def result(force=false)
|
10
|
+
res = super()
|
11
|
+
Marty::Promise.load_result(res, force)
|
33
12
|
end
|
34
13
|
|
35
|
-
|
14
|
+
def self.load_result(obj, force=false)
|
15
|
+
if force && obj.respond_to?(:__force__)
|
16
|
+
obj = obj.__force__
|
17
|
+
end
|
18
|
+
|
19
|
+
case obj
|
20
|
+
when Array
|
21
|
+
obj.map {|x| load_result(x, force)}
|
22
|
+
when Hash
|
23
|
+
p = obj['__promise__']
|
36
24
|
|
37
|
-
|
25
|
+
if p && obj.length==1
|
26
|
+
load_result(Marty::PromiseProxy.new(*p), force)
|
27
|
+
else
|
28
|
+
obj.each_with_object({}) { |(k, v), h| h[k] = load_result(v, force) }
|
29
|
+
end
|
30
|
+
else
|
31
|
+
obj
|
32
|
+
end
|
33
|
+
end
|
38
34
|
|
39
35
|
has_many :children,
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
foreign_key: 'parent_id',
|
37
|
+
class_name: "Marty::Promise",
|
38
|
+
dependent: :destroy
|
39
|
+
|
40
|
+
validates_presence_of :title
|
43
41
|
|
44
42
|
belongs_to :parent, class_name: "Marty::Promise"
|
45
43
|
belongs_to :user, class_name: "Marty::User"
|
@@ -53,43 +51,6 @@ class Marty::Promise < Marty::Base
|
|
53
51
|
end
|
54
52
|
end
|
55
53
|
|
56
|
-
class VirtualRoot
|
57
|
-
def self.primary_key
|
58
|
-
'id'
|
59
|
-
end
|
60
|
-
|
61
|
-
def id
|
62
|
-
'root'
|
63
|
-
end
|
64
|
-
|
65
|
-
def user_id
|
66
|
-
0
|
67
|
-
end
|
68
|
-
alias_method :job_id, :user_id
|
69
|
-
|
70
|
-
def result
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
[:start_dt, :end_dt].each { |m| alias_method m, :result }
|
74
|
-
|
75
|
-
def status
|
76
|
-
true
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.root
|
81
|
-
VirtualRoot.new
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.children_for_id(id, search_order)
|
85
|
-
q = id == 'root' ? where(parent_id: nil) : find(id).children
|
86
|
-
q.live_search(search_order).order(id: :desc).includes(:children, :user)
|
87
|
-
end
|
88
|
-
|
89
|
-
def leaf
|
90
|
-
children.empty?
|
91
|
-
end
|
92
|
-
|
93
54
|
def raw_conn
|
94
55
|
self.class.connection.raw_connection
|
95
56
|
end
|
@@ -242,22 +203,4 @@ class Marty::Promise < Marty::Base
|
|
242
203
|
raw_conn.exec("UNLISTEN promise_#{id}")
|
243
204
|
end
|
244
205
|
end
|
245
|
-
|
246
|
-
# Support UI live search -- FIXME: hacky to have UI scoping here
|
247
|
-
scope :live_search, lambda { |search_text|
|
248
|
-
return if !search_text || search_text.strip.length < 1
|
249
|
-
|
250
|
-
# Searches user login/firstname/lastname
|
251
|
-
query = [
|
252
|
-
"marty_users.login ILIKE ?",
|
253
|
-
"marty_users.firstname ILIKE ?",
|
254
|
-
"marty_users.lastname ILIKE ?",
|
255
|
-
"marty_roles.name ILIKE ?",
|
256
|
-
].join(' OR ')
|
257
|
-
|
258
|
-
st = "%#{search_text}%"
|
259
|
-
# Convert "Role Name" or "Role name" to "role_name" (underscore is key)
|
260
|
-
st2 = "%#{search_text.titleize.gsub(/\s/, '').underscore}%"
|
261
|
-
joins({:user => :roles}).where(query, st, st, st, st2).distinct
|
262
|
-
}
|
263
206
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class Marty::VwPromise < Marty::Base
|
2
|
+
|
3
|
+
has_many :children,
|
4
|
+
foreign_key: 'parent_id',
|
5
|
+
class_name: "Marty::VwPromise",
|
6
|
+
dependent: :destroy
|
7
|
+
|
8
|
+
belongs_to :parent, class_name: "Marty::VwPromise"
|
9
|
+
belongs_to :user, class_name: "Marty::User"
|
10
|
+
|
11
|
+
self.table_name = 'marty_vw_promises'
|
12
|
+
self.primary_key = 'id'
|
13
|
+
|
14
|
+
class VirtualRoot
|
15
|
+
def self.primary_key
|
16
|
+
'id'
|
17
|
+
end
|
18
|
+
|
19
|
+
def id
|
20
|
+
'root'
|
21
|
+
end
|
22
|
+
|
23
|
+
def user_id
|
24
|
+
0
|
25
|
+
end
|
26
|
+
alias_method :job_id, :user_id
|
27
|
+
|
28
|
+
def result
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
[:start_dt, :end_dt].each { |m| alias_method m, :result }
|
32
|
+
|
33
|
+
def status
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.root
|
39
|
+
VirtualRoot.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.children_for_id(id, search_order)
|
43
|
+
q = id == 'root' ? where(parent_id: nil) : find(id).children
|
44
|
+
q.live_search(search_order).order(id: :desc).includes(:children, :user)
|
45
|
+
end
|
46
|
+
|
47
|
+
def leaf
|
48
|
+
children.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
inspect
|
53
|
+
end
|
54
|
+
|
55
|
+
# Support UI live search -- FIXME: hacky to have UI scoping here
|
56
|
+
scope :live_search, lambda { |search_text|
|
57
|
+
return if !search_text || search_text.strip.length < 1
|
58
|
+
|
59
|
+
# Searches user login/firstname/lastname
|
60
|
+
query = [
|
61
|
+
"marty_users.login ILIKE ?",
|
62
|
+
"marty_users.firstname ILIKE ?",
|
63
|
+
"marty_users.lastname ILIKE ?",
|
64
|
+
"marty_roles.name ILIKE ?",
|
65
|
+
].join(' OR ')
|
66
|
+
|
67
|
+
st = "%#{search_text}%"
|
68
|
+
# Convert "Role Name" or "Role name" to "role_name" (underscore is key)
|
69
|
+
st2 = "%#{search_text.titleize.gsub(/\s/, '').underscore}%"
|
70
|
+
joins({:user => :roles}).where(query, st, st, st, st2).distinct
|
71
|
+
}
|
72
|
+
end
|