marty 8.5.0 → 9.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +1 -0
  3. data/.eslintrc.js +26 -0
  4. data/.gitignore +3 -0
  5. data/.gitlab-ci.yml +7 -0
  6. data/.prettierignore +14 -0
  7. data/.rubocop_todo.yml +1 -1
  8. data/Dockerfile.dummy +3 -0
  9. data/Makefile +1 -0
  10. data/app/assets/javascripts/marty/cable.js +7 -3
  11. data/app/assets/javascripts/marty/extjs/extensions/datetime_field/component.js +401 -0
  12. data/app/assets/javascripts/marty/extjs/extensions/datetime_field/field.js +140 -0
  13. data/app/assets/javascripts/marty/extjs/extensions/marty.js +845 -781
  14. data/app/assets/stylesheets/marty/codemirror/codemirror.css +215 -77
  15. data/app/assets/stylesheets/marty/codemirror/delorean.css +2 -2
  16. data/app/assets/stylesheets/marty/dark_mode.css +13 -3
  17. data/app/components/marty/auth_app/client/auth_app.js +107 -102
  18. data/app/components/marty/base_rule_view/client/base_rule_view.js +10 -8
  19. data/app/components/marty/data_grid_view/client/data_grid_edit.js +534 -519
  20. data/app/components/marty/form/client/form.js +3 -3
  21. data/app/components/marty/grid/client/grid.js +110 -87
  22. data/app/components/marty/import_view/client/import_view.js +18 -18
  23. data/app/components/marty/live_search_grid_panel/client/live_search_grid_panel.js +14 -13
  24. data/app/components/marty/main_auth_app/client/main_auth_app.js +42 -42
  25. data/app/components/marty/mcfly_grid_panel/client/mcfly_grid_panel.js +27 -18
  26. data/app/components/marty/new_posting_form/client/new_posting_form.js +3 -3
  27. data/app/components/marty/panel/client/panel.js +3 -3
  28. data/app/components/marty/posting_grid/client/posting_grid.js +24 -18
  29. data/app/components/marty/promise_view/client/promise_view.css +12 -12
  30. data/app/components/marty/promise_view/client/promise_view.js +46 -38
  31. data/app/components/marty/report_form/client/report_form.js +30 -28
  32. data/app/components/marty/report_select/client/report_select.js +28 -23
  33. data/app/components/marty/reporting/client/reporting.js +3 -3
  34. data/app/components/marty/script_form/client/script_form.js +29 -23
  35. data/app/components/marty/script_tester/client/script_tester.js +4 -5
  36. data/app/components/marty/scripting/client/scripting.js +40 -36
  37. data/app/components/marty/simple_app/client/simple_app.js +33 -24
  38. data/app/components/marty/simple_app/client/statusbar_ext.js +1 -1
  39. data/app/controllers/marty/rpc_controller.rb +3 -0
  40. data/app/models/marty/promise.rb +10 -2
  41. data/app/services/marty/data_grid/constraint.rb +2 -1
  42. data/app/services/marty/jobs/schedule.rb +2 -2
  43. data/app/services/marty/promises/delorean/create.rb +9 -2
  44. data/app/services/marty/promises/ruby/create.rb +7 -2
  45. data/config/initializers/delayed_job_config.rb +1 -0
  46. data/delorean/blame_report.dl +50 -58
  47. data/delorean/enum_report.dl +2 -3
  48. data/delorean/{marty_fields.dl → fields.dl} +16 -0
  49. data/delorean/styles.dl +216 -0
  50. data/delorean/table_report.dl +4 -4
  51. data/lib/marty/monkey.rb +17 -0
  52. data/lib/marty/promise_job.rb +9 -0
  53. data/lib/marty/promise_ruby_job.rb +8 -0
  54. data/lib/marty/version.rb +1 -1
  55. data/make-lint.mk +19 -0
  56. data/package.json +16 -0
  57. data/prettier.config.js +6 -0
  58. data/spec/controllers/diagnostic/controller_spec.rb +0 -1
  59. data/spec/controllers/rpc_controller_spec.rb +21 -7
  60. data/spec/dummy/delorean/data_report.dl +4 -4
  61. data/spec/dummy/delorean/fields.dl +1 -0
  62. data/spec/features/data_grid_spec.rb +37 -1
  63. data/spec/job_helper.rb +6 -0
  64. data/spec/lib/data_blame_spec.rb +4 -4
  65. data/spec/lib/data_importer_spec.rb +6 -4
  66. data/spec/models/promise_spec.rb +31 -0
  67. data/spec/spec_helper.rb +8 -0
  68. data/spec/support/download_helper.rb +53 -49
  69. data/spec/support/json_helper.rb +11 -0
  70. data/spec/support/shared_connection_db_helpers.rb +1 -0
  71. data/spec/support/suite.rb +20 -14
  72. data/yarn.lock +967 -0
  73. metadata +16 -4
  74. data/spec/dummy/delorean/marty_fields.dl +0 -1
@@ -1,4 +1,4 @@
1
- import MartyFields
1
+ import Fields
2
2
  import Styles
3
3
 
4
4
  EnumValuesReport:
@@ -7,5 +7,4 @@ EnumValuesReport:
7
7
  raw = Marty::Enums::Report.call()
8
8
  result = Marty::Helper.to_csv(raw)
9
9
  form = []
10
- format = "csv"
11
-
10
+ format = "csv"
@@ -60,3 +60,19 @@ TextField:
60
60
  xtype = ":textfield"
61
61
  field_label = "Text"
62
62
  name = "text_field"
63
+
64
+ ######################################################################
65
+
66
+ DateField:
67
+ field_label = "Date"
68
+ xtype = ":datefield"
69
+ name = "date"
70
+ value = nil
71
+ format = 'Y-m-d'
72
+
73
+ DatetimeField:
74
+ field_label = "Datetime"
75
+ xtype = ":datetimefield"
76
+ name = "datetime"
77
+ value = nil
78
+ format = 'Y-m-d H:i:s'
@@ -0,0 +1,216 @@
1
+ Style:
2
+ digit_0 = {"format_code" : "0"}
3
+ digit_1 = {"format_code" : "0.0"}
4
+ digit_2 = {"format_code" : "0.00"}
5
+ digit_3 = {"format_code" : "0.000"}
6
+ digit_4 = {"format_code" : "0.0000"}
7
+ digit_5 = {"format_code" : "0.00000"}
8
+ digit_6 = {"format_code" : "0.000000"}
9
+ date = {"format_code" : "mm/dd/yy"}
10
+ timestamp = {"format_code" : "m/d/yy h:mm AM/PM"}
11
+ datetime = {"format_code" : "yyyy-mm-dd h:mm:ss"}
12
+ date_w_time = {"format_code" : "mm/dd/yy h:mm:ss"}
13
+ dollars = {"format_code" : "$#,###"}
14
+ dollars_cent = {"format_code" : "$#,###.##"}
15
+ text = {"format_code" : "@"}
16
+
17
+ bg_gray = {"bg_color": "C5D9F1"}
18
+ bg_lightgreen = {"bg_color": "99CC00"}
19
+ bg_tan = {"bg_color": "FFCC66"}
20
+ bg_redish = {"bg_color": "EF5959"}
21
+ bg_lightgray = {"bg_color": "F1F5F5"}
22
+
23
+ quoted = {"quote_prefix": true}
24
+
25
+ gray_digit_3 = bg_gray + digit_3
26
+
27
+ bg_penny = {
28
+ "bg_color": "0D056F",
29
+ "fg_color": "FFFFFF",
30
+ }
31
+
32
+ bg_highlight = {
33
+ "bg_color": "FFFF00",
34
+ "fg_color": "0D056F",
35
+ }
36
+
37
+ bold = {"b": true}
38
+
39
+ penny_bold = bold + bg_penny
40
+
41
+ align_center = {
42
+ "alignment": {
43
+ "horizontal": ":center",
44
+ }
45
+ }
46
+
47
+ align_left = {
48
+ "alignment": {
49
+ "horizontal": ":left",
50
+ }
51
+ }
52
+
53
+ align_right = {
54
+ "alignment": {
55
+ "horizontal": ":right",
56
+ }
57
+ }
58
+
59
+ calibri = {"font_name": "Calibri"}
60
+ sz_14 = {"sz": 14}
61
+ sz_12 = {"sz": 12}
62
+ sz_10 = {"sz": 10}
63
+
64
+ h_hdr = bold + bg_highlight + align_center + calibri + sz_14
65
+ m_hdr = penny_bold + align_center + calibri + sz_14
66
+ s_hdr = penny_bold + align_left + calibri + sz_12
67
+ s_hdr_dt = s_hdr + datetime
68
+ s_hdr_date = s_hdr + date
69
+ s_hdr_dwt = s_hdr + date_w_time
70
+ g_bold = bg_gray + bold
71
+
72
+ border_thin = {
73
+ "style" : ":thin",
74
+ "color" : "000000",
75
+ }
76
+
77
+ ######################################################################
78
+
79
+ m_hdr_style0 = {"style": m_hdr}
80
+ m_hdr_style1 = {"style": [m_hdr]}
81
+
82
+ s_hdr_style2 = {"style": [s_hdr]*2}
83
+ s_hdr_style3 = {"style": [s_hdr]*3}
84
+
85
+ HeatMapFmt:
86
+ color_scale = [
87
+ {"type":":min", "val":0, "color":"FF63BE7B"},
88
+ {"type":":percent", "val":"50", "color":"FFFFEB84"},
89
+ {"type":":max", "val":0, "color":"FFF8696B"}
90
+ ]
91
+
92
+ cfmt = {
93
+ "type": ":colorScale",
94
+ "priority": 1,
95
+ "color_scale": color_scale,
96
+ }
97
+
98
+ ThresholdFmt:
99
+ winner =? 0
100
+ thresh_cell =? '$B$1'
101
+
102
+ cfmt = {
103
+ "type": ":expression",
104
+ "priority": 1,
105
+ "dxfId" : {
106
+ "fg_color": "FFF8696B",
107
+ "type": ":dxf",
108
+ "b": true,
109
+ },
110
+ "formula": 'ABS(INDIRECT("RC", FALSE))>'+thresh_cell,
111
+ }
112
+
113
+ cfmtnot0 = {
114
+ "type" : ":cellIs",
115
+ "operator" : ":notEqual",
116
+ "formula" : "0",
117
+ "dxfId" : {
118
+ "fg_color": "FFF8696B",
119
+ "type": ":dxf",
120
+ "b": true,
121
+ },
122
+ "priority" : 1,
123
+ }
124
+
125
+ cfmtequal = {
126
+ "type" : ":cellIs",
127
+ "operator" : ":equal",
128
+ "formula" : winner.to_s,
129
+ "dxfId" :
130
+ {
131
+ "fg_color": "FFF8696B",
132
+ "type": ":dxf",
133
+ "b": true,
134
+ },
135
+ "priority" : 1,
136
+ }
137
+
138
+ cfmtticks = {
139
+ "type": ":expression",
140
+ "priority": 1,
141
+ "dxfId" : {
142
+ "fg_color": "FFF8696B",
143
+ "type": ":dxf",
144
+ "b": true,
145
+ },
146
+ "formula": 'ABS(LEFT(INDIRECT("RC", FALSE),FIND("-",INDIRECT("RC", FALSE), 2)-1))+MID(SUBSTITUTE(INDIRECT("RC", FALSE),"+",""),FIND("-",INDIRECT("RC", FALSE), 2)+1,9)/32+(RIGHT(INDIRECT("RC", FALSE))="+")/64>'+thresh_cell,
147
+ }
148
+
149
+ Row:
150
+ blank_cells =? 0
151
+ values =? []
152
+ styles =? []
153
+
154
+ blank_styles = [{}]*blank_cells
155
+ blank = ["row", [nil]*blank_cells,
156
+ {"style": blank_styles}]
157
+
158
+ result = ["row", values + blank[1],
159
+ {"style": styles + blank_styles}]
160
+
161
+ Fill:
162
+ rows =?
163
+ fill =? nil
164
+ length =?
165
+
166
+ filled_rows = [
167
+ [r[0],
168
+ (if r[1].length >= length
169
+ then r[1]
170
+ else r[1] + [fill]*(length - r[1].length)
171
+ ),
172
+ {'style': (r[2]['style'] || []) + [{}]*(length - r[1].length)}]
173
+ for r in rows]
174
+
175
+ Merge:
176
+ init =? 0
177
+ rows_a =?
178
+ rows_b =?
179
+ blank_length =?
180
+
181
+ add_options =? {}
182
+
183
+ ra_len = rows_a.length
184
+ rb_len = rows_b.length
185
+
186
+ len = if ra_len >= rb_len then ra_len else rb_len
187
+
188
+ result = [
189
+ ["row",
190
+ ((rows_a[i] || Row(blank_cells=blank_length).blank)[1] +
191
+ (rows_b[i] || Row.blank)[1]),
192
+ {"style": (if rows_a[i][2]
193
+ then rows_a[i][2]['style']
194
+ else Row(blank_cells=blank_length).blank_styles) +
195
+ (if rows_b[i][2]
196
+ then rows_b[i][2]['style']
197
+ else [])
198
+ } + (add_options[i] || {})
199
+ ] for i in Marty::Helper.range_step(init, len-1, 1)]
200
+
201
+ Alternate:
202
+ bg_color_a =? 'F3F3F3'
203
+ bg_color_b =? 'FFFFFF'
204
+
205
+ color = {
206
+ 0: {'bg_color': bg_color_a},
207
+ 1: {'bg_color': bg_color_b},
208
+ }
209
+
210
+ rows =?
211
+
212
+ result = [
213
+ ['row',
214
+ rows[i][1],
215
+ {'style': [(color[i%2] + s) for s in rows[i][2]['style']]}
216
+ ] for i in Marty::Helper.range_step(0, rows.length - 1, 1)]
@@ -1,7 +1,7 @@
1
- import MartyFields
1
+ import Fields
2
2
  import Styles
3
3
 
4
- ReadableField: MartyFields::CheckboxField
4
+ ReadableField: Fields::CheckboxField
5
5
  name = "readable"
6
6
  field_label = "Disable Encoding"
7
7
 
@@ -26,8 +26,8 @@ TableReport:
26
26
  row_count = result_raw.length
27
27
  result = Marty::Helper.to_csv(result_raw, {'readable' : readable})
28
28
  form = [
29
- MartyFields::PostingField,
30
- MartyFields::ClassField,
29
+ Fields::PostingField,
30
+ Fields::ClassField,
31
31
  ReadableField,
32
32
  ]
33
33
  format = "csv"
@@ -376,6 +376,23 @@ module Netzke
376
376
  end
377
377
  end
378
378
 
379
+ module Netzke
380
+ module Core
381
+ class ClientClassConfig
382
+ # FIXME: move to Netzke
383
+ # This fix removes ; in the end of JS code that is required by JS linters
384
+ # And adds new line before closing bracket, so that if there is a comment
385
+ # in the end of file, it won't break the code.
386
+ def override_from_file(path)
387
+ str = File.read(path)
388
+ str.chomp!("\n").chomp!(';')
389
+ %{#{class_name}.override(#{str}
390
+ );}
391
+ end
392
+ end
393
+ end
394
+ end
395
+
379
396
  require 'delayed_cron_job'
380
397
  require_relative './delayed_job/scheduled_job_plugin.rb'
381
398
 
@@ -8,6 +8,7 @@ class Marty::PromiseJob < Struct.new(:promise,
8
8
  :params,
9
9
  :attrs,
10
10
  :hook,
11
+ :max_run_time
11
12
  )
12
13
  # def log(msg)
13
14
  # open('/tmp/dj.out', 'a') { |f| f.puts msg }
@@ -41,10 +42,18 @@ class Marty::PromiseJob < Struct.new(:promise,
41
42
  end
42
43
 
43
44
  # log "DONE #{Process.pid} #{promise.id} #{Time.now.to_f} #{res}"
45
+ rescue ::Delayed::WorkerTimeout => e
46
+ timeout_error = StandardError.new(
47
+ ::Marty::Promise.timeout_message(promise)
48
+ )
49
+ timeout_error.set_backtrace(e.backtrace)
50
+
51
+ res = Delorean::Engine.grok_runtime_exception(timeout_error)
44
52
  rescue StandardError => e
45
53
  res = Delorean::Engine.grok_runtime_exception(e)
46
54
  # log "ERR- #{Process.pid} #{promise.id} #{Time.now.to_f} #{e}"
47
55
  end
56
+
48
57
  promise.set_result(res)
49
58
  process_hook(res)
50
59
  end
@@ -4,6 +4,7 @@ class Marty::PromiseRubyJob < Struct.new(:promise,
4
4
  :method_name,
5
5
  :method_args,
6
6
  :hook,
7
+ :max_run_time
7
8
  )
8
9
 
9
10
  def enqueue(job)
@@ -26,6 +27,13 @@ class Marty::PromiseRubyJob < Struct.new(:promise,
26
27
  ENV['__promise_id'] = promise.id.to_s
27
28
  mod = module_name.constantize
28
29
  res = { 'result' => mod.send(method_name, *method_args) }
30
+ rescue ::Delayed::WorkerTimeout => e
31
+ timeout_error = StandardError.new(
32
+ ::Marty::Promise.timeout_message(promise)
33
+ )
34
+ timeout_error.set_backtrace(e.backtrace)
35
+
36
+ res = Delorean::Engine.grok_runtime_exception(timeout_error)
29
37
  rescue StandardError => e
30
38
  res = ::Marty::Promise.exception_to_result(promise: promise, exception: e)
31
39
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Marty
4
- VERSION = '8.5.0'
4
+ VERSION = '9.3.0'
5
5
  end
@@ -0,0 +1,19 @@
1
+ lint:
2
+ make lint-ruby
3
+ make lint-js
4
+
5
+ lint-fix:
6
+ make lint-ruby-fix
7
+ make lint-js-fix
8
+
9
+ lint-ruby:
10
+ bundle exec rubocop
11
+
12
+ lint-ruby-fix:
13
+ bundle exec rubocop -a
14
+
15
+ lint-js:
16
+ yarn lint
17
+
18
+ lint-js-fix:
19
+ yarn lintfix
@@ -0,0 +1,16 @@
1
+ {
2
+ "private": true,
3
+ "scripts": {
4
+ "lint": "eslint 'app/**/*.{js,jsx}' && prettier --check \"app/**/*.{js,jsx,css,scss}\"",
5
+ "lintfix": "eslint --fix 'app/**/*.{js,jsx}' && prettier --write \"app/**/*.{js,jsx,css,scss}\""
6
+ },
7
+ "dependencies": {
8
+ },
9
+ "devDependencies": {
10
+ "babel-eslint": "^10.0.1",
11
+ "eslint": "^6.0.0",
12
+ "eslint-config-prettier": "^6.0.0",
13
+ "eslint-plugin-prettier": "^3.1.0",
14
+ "prettier": "^1.17.1"
15
+ }
16
+ }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ arrowParens: "always",
3
+ printWidth: 80,
4
+ quoteProps: "consistent",
5
+ semi: true
6
+ };
@@ -8,7 +8,6 @@ end
8
8
  module Marty::Diagnostic
9
9
  RSpec.describe Controller, type: :controller do
10
10
  before(:each) { @routes = Marty::Engine.routes }
11
- let(:json_response) { JSON.parse(response.body) }
12
11
 
13
12
  def my_ip
14
13
  Node.my_ip
@@ -488,6 +488,8 @@ describe Marty::RpcController do
488
488
  let(:p1) { @p1 }
489
489
  let(:p2) { @p2 }
490
490
 
491
+ let(:json_response) { JSON.parse(response.body) }
492
+
491
493
  it 'should be able to post' do
492
494
  post 'evaluate', params: {
493
495
  format: :json,
@@ -511,7 +513,7 @@ describe Marty::RpcController do
511
513
  params: { a: 333, d: 5 }.to_json,
512
514
  background: true,
513
515
  }
514
- res = ActiveSupport::JSON.decode response.body
516
+ res = json_response
515
517
  expect(res).to include('job_id')
516
518
  job_id = res['job_id']
517
519
 
@@ -787,10 +789,10 @@ describe Marty::RpcController do
787
789
  params: params
788
790
  }
789
791
  expect = 'Schema error for M1/A attrs=b: Schema not defined'
790
- res = JSON.parse(response.body)
791
- expect(res.keys.size).to eq(1)
792
- expect(res.keys[0]).to eq('error')
793
- expect(res.values[0]).to eq(expect)
792
+ expect(json_response['backtrace']).to be nil
793
+ expect(json_response.size).to eq(1)
794
+ expect(json_response.keys[0]).to eq('error')
795
+ expect(json_response.values[0]).to eq(expect)
794
796
  end
795
797
 
796
798
  it 'returns an error message on missing attributes in schema script' do
@@ -849,6 +851,7 @@ describe Marty::RpcController do
849
851
  }
850
852
  expect = '[""The property \'#/p\' of type string did not '\
851
853
  'match the following type: integer'
854
+
852
855
  expect(response.body).to include(expect)
853
856
  end
854
857
 
@@ -870,9 +873,10 @@ describe Marty::RpcController do
870
873
  attrs: attr,
871
874
  params: params
872
875
  }
873
- res = JSON.parse(response.body)
874
876
  errpart = 'of type string did not match the following type: integer'
875
- expect(res['error']).to include(errpart)
877
+ expect(json_response['error']).to include(errpart)
878
+ expect(json_response['backtrace']).to be nil
879
+
876
880
  logs = Marty::Log.all
877
881
  expect(logs.count).to eq(1)
878
882
  expect(logs[0].details['error'][0]).to include(errpart)
@@ -1386,41 +1390,51 @@ describe Marty::RpcController do
1386
1390
  it 'returns bad attrs if attr is not a string' do
1387
1391
  get :evaluate, params: { format: :json, attrs: 0 }
1388
1392
  expect(response.body).to match(/"error":"Malformed attrs"/)
1393
+ expect(json_response['backtrace']).to be nil
1389
1394
  end
1390
1395
 
1391
1396
  it 'returns malformed attrs for improperly formatted json' do
1392
1397
  get :evaluate, params: { format: :json, attrs: '{' }
1393
1398
  expect(response.body).to match(/"error":"Malformed attrs"/)
1399
+ expect(json_response['backtrace']).to be nil
1394
1400
  end
1395
1401
 
1396
1402
  it 'returns malformed attrs if attr is not an array of strings' do
1397
1403
  get :evaluate, params: { format: :json, attrs: '{}' }
1398
1404
  expect(response.body).to match(/"error":"Malformed attrs"/)
1405
+ expect(json_response['backtrace']).to be nil
1399
1406
 
1400
1407
  get :evaluate, params: { format: :json, attrs: '[0]' }
1401
1408
  expect(response.body).to match(/"error":"Malformed attrs"/)
1409
+ expect(json_response['backtrace']).to be nil
1402
1410
  end
1403
1411
 
1404
1412
  it 'returns malformed params for improperly formatted json' do
1405
1413
  get :evaluate, params: { format: :json, attrs: 'e', params: '{' }
1406
1414
  expect(response.body).to match(/"error":"Malformed params"/)
1415
+ expect(json_response['backtrace']).to be nil
1407
1416
  end
1408
1417
 
1409
1418
  it 'returns malformed params if params is not a hash' do
1410
1419
  get :evaluate, params: { format: :json, attrs: 'e', params: '[0]' }
1411
1420
  expect(response.body).to match(/"error":"Malformed params"/)
1421
+ expect(json_response['backtrace']).to be nil
1412
1422
  end
1413
1423
 
1414
1424
  it 'returns engine/tag lookup error if script not found' do
1415
1425
  get :evaluate, params: { format: :json, script: 'M1', attrs: 'e', tag: 'invalid' }
1416
1426
  expect(response.body).to match(/bad tag identifier.*invalid/)
1427
+ expect(json_response['backtrace']).to be nil
1428
+
1417
1429
  get :evaluate, params: { format: :json, script: 'Invalid', attrs: 'e', tag: t1.name }
1418
1430
  expect(response.body).to match(/"error":"Can't get engine:/)
1431
+ expect(json_response['backtrace']).to be nil
1419
1432
  end
1420
1433
 
1421
1434
  it 'returns the script runtime error (no node specified)' do
1422
1435
  get :evaluate, params: { format: :json, script: 'M1', attrs: 'e', tag: t1.name }
1423
1436
  expect(response.body).to match(/"error":"bad node/)
1437
+ expect(json_response['backtrace']).to be nil
1424
1438
  end
1425
1439
  end
1426
1440
  end