marty 1.0.20 → 1.0.22

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ef8c8c7b0bd818fee36e9a1b008e993ee03f0a0
4
- data.tar.gz: 170c2f758a76d4a6dd5b468afddec69b549639bd
3
+ metadata.gz: 86d8dcf6f031cb37849a2835413f01577fe15309
4
+ data.tar.gz: 3230c2099f30abb9f60c6d17d1b7da528e1b928c
5
5
  SHA512:
6
- metadata.gz: fac49a429c93d733c9e80ff8125a6ee384cd8c84e0ef3c935191488f2c8f57ac573182b9a84a69727ba5f2da3bc53dc5aea49093362260bc34e3c3adcda4a9e1
7
- data.tar.gz: 549351e7df063500acb9144d392b61324b22f305abcba00121a6e5e16499db8aefb84ef7f6483d13b9d0f6af3f18398b75e53ac3884181965f36e620ee675245
6
+ metadata.gz: c6ffb9f4a6e963960f7d22254444c937431f4c185a1be67b6161db0b1d50fabfc857cf39cef9c6100db74d622ea406aed702b2d37863ef5c9af6c005d60e1057
7
+ data.tar.gz: 4a0f2d03b75bb07f97f0fb38625a2f3b821a71df0286d27eeae4333965a8d21d6fd3bbfb819f8d47e3d2b6d771f7e33362c42e588b46d0e86f85748c3cc4e3aa
@@ -0,0 +1,203 @@
1
+ module Marty; class DataGridView < McflyGridPanel
2
+ has_marty_permissions create: [:admin, :dev],
3
+ read: :any,
4
+ update: [:admin, :dev],
5
+ delete: [:admin, :dev]
6
+
7
+ include Extras::Layout
8
+
9
+ def self.show_grid_js(options={})
10
+ dg = options[:data_grid] || 'data_grid'
11
+ title_str = options[:title_str] || 'Data Grid'
12
+
13
+ javascript = l(<<-JS)
14
+ function() {
15
+ var sel = this.getSelectionModel().selected.first();
16
+ var record_id = sel && sel.getId();
17
+ this.server.showGrid({record_id: record_id,
18
+ data_grid: "#{dg}",
19
+ title_str: "#{title_str}"});
20
+ }
21
+ JS
22
+ javascript
23
+ end
24
+
25
+ def self.client_show_grid_js
26
+ javascript = l(<<-JS)
27
+ function(count, data, title_str) {
28
+ var columns = [];
29
+ var fields = [];
30
+
31
+ for (var i=0; i<count; i++) {
32
+ fields.push("a" + i);
33
+ columns.push({dataIndex: "a" + i, text: i, flex: 1});
34
+ }
35
+
36
+ Ext.create('Ext.Window', {
37
+ height: "80%",
38
+ width: "80%",
39
+ x: 0,
40
+ y: 0,
41
+ autoWidth: true,
42
+ modal: true,
43
+ autoScroll: true,
44
+ title: title_str,
45
+ items: {
46
+ xtype: 'grid',
47
+ border: false,
48
+ hideHeaders: false,
49
+ columns: columns,
50
+ store: Ext.create('Ext.data.ArrayStore', {
51
+ fields: fields,
52
+ data: data,
53
+ })
54
+ },
55
+ }).show();
56
+ }
57
+ JS
58
+ javascript
59
+ end
60
+
61
+ client_class do |c|
62
+ c.netzke_show_grid = DataGridView.show_grid_js
63
+ c.netzke_client_show_grid = DataGridView.client_show_grid_js
64
+ end
65
+
66
+ def configure(c)
67
+ super
68
+
69
+ c.title = I18n.t('data_grid')
70
+ c.model = "Marty::DataGrid"
71
+ c.attributes =
72
+ [
73
+ :name,
74
+ :vcols,
75
+ :hcols,
76
+ :lenient,
77
+ :data_type,
78
+ :created_dt,
79
+ ]
80
+
81
+ c.store_config.merge!({sorters: [{property: :name, direction: 'ASC'}]})
82
+ c.editing = :in_form
83
+ c.paging = :pagination
84
+ c.multi_select = false
85
+ end
86
+
87
+ endpoint :add_window__add_form__submit do |params|
88
+ data = ActiveSupport::JSON.decode(params[:data])
89
+
90
+ return client.netzke_notify("Permission Denied") if
91
+ !config[:permissions][:create]
92
+
93
+ begin
94
+ DataGrid.create_from_import(data["name"], data["export"])
95
+ client.success = true
96
+ client.netzke_on_submit_success
97
+ rescue => exc
98
+ client.netzke_notify(exc.to_s)
99
+ end
100
+ end
101
+
102
+ endpoint :edit_window__edit_form__submit do |params|
103
+ data = ActiveSupport::JSON.decode(params[:data])
104
+
105
+ dg = DataGrid.find_by_id(data["id"])
106
+
107
+ begin
108
+ dg.update_from_import(data["name"], data["export"])
109
+ client.success = true
110
+ client.netzke_on_submit_success
111
+ rescue => exc
112
+ client.netzke_notify(exc.to_s)
113
+ end
114
+ end
115
+
116
+ action :show_grid do |a|
117
+ a.text = "Show Grid"
118
+ a.icon = :application_view_detail
119
+ a.handler = :netzke_show_grid
120
+ end
121
+
122
+ endpoint :show_grid do |params|
123
+ record_id = params[:record_id]
124
+
125
+ dg = DataGrid.find_by_id(record_id)
126
+
127
+ return client.netzke_notify("No data grid.") unless dg
128
+
129
+ meta_rows_raw, h_key_rows, data_rows = dg.export_array
130
+ meta_rows = meta_rows_raw.map do |row|
131
+ # need to escape for HTML, otherwise characters such as >, <,
132
+ # etc. not displayed properly.
133
+ row.map { |field| CGI::escapeHTML(field) }
134
+ end
135
+ res = meta_rows + [[]] + h_key_rows + data_rows
136
+
137
+ maxcount = res.map(&:length).max
138
+
139
+ client.netzke_client_show_grid maxcount, res, 'Data Grid'
140
+ end
141
+
142
+ def default_bbar
143
+ [:show_grid] + super
144
+ end
145
+
146
+ def default_context_menu
147
+ []
148
+ end
149
+
150
+ def default_form_items
151
+ [
152
+ :name,
153
+ textarea_field(:export, height: 300, hide_label: true),
154
+ ]
155
+ end
156
+
157
+ component :edit_window do |c|
158
+ super(c)
159
+ c.width = 700
160
+ end
161
+
162
+ component :add_window do |c|
163
+ super(c)
164
+ c.width = 700
165
+ end
166
+
167
+ attribute :name do |c|
168
+ c.width = 120
169
+ end
170
+
171
+ attribute :hcols do |c|
172
+ c.label = "Horizontal Attrs"
173
+ c.width = 200
174
+ c.getter = lambda { |r|
175
+ r.dir_infos("h").map {|inf| inf["attr"]}.join(', ')
176
+ }
177
+ end
178
+
179
+ attribute :vcols do |c|
180
+ c.label = "Vertical Attrs"
181
+ c.width = 200
182
+ c.getter = lambda { |r|
183
+ r.dir_infos("v").map {|inf| inf["attr"]}.join(', ')
184
+ }
185
+ end
186
+
187
+ attribute :lenient do |c|
188
+ c.width = 75
189
+ end
190
+
191
+ attribute :data_type do |c|
192
+ c.label = "Data Type"
193
+ c.width = 200
194
+ end
195
+
196
+ attribute :created_dt do |c|
197
+ c.label = I18n.t('updated_at')
198
+ c.format = "Y-m-d H:i"
199
+ c.read_only = true
200
+ end
201
+ end; end
202
+
203
+ DataGridView = Marty::DataGridView
@@ -1,84 +1,151 @@
1
- module Marty
2
- module Extras
3
- module Layout
4
-
5
- def hbox(*args)
6
- params = args.pop
7
- params.merge(layout: { type: :hbox, align: :stretch },
8
- items: args,
9
- )
10
- end
11
-
12
- def vbox(*args)
13
- params = args.pop
14
- params.merge(layout: { type: :vbox, align: :stretch },
15
- items: args,
16
- )
17
- end
18
-
19
- def fieldset(title, *args)
20
- params = args.pop
21
- params.merge(items: args,
22
- xtype: 'fieldset',
23
- defaults: { anchor: '100%' },
24
- title: title,
25
- )
26
- end
27
-
28
- def dispfield(params={})
29
- {
30
- attr_type: :displayfield,
31
- hide_label: !params[:field_label],
32
- read_only: true,
33
- }.merge(params)
34
- end
35
-
36
- def vspacer(params={})
37
- vbox({flex: 1, border: false}.merge(params))
38
- end
39
-
40
- def hspacer(params={})
41
- hbox({flex: 1, border: false}.merge(params))
42
- end
43
-
44
- def textarea_field(name, options={})
45
- {
46
- name: name,
47
- width: "100%",
48
- height: 150,
49
- xtype: :textareafield,
50
- auto_scroll: true,
51
- spellcheck: false,
52
- field_style: {
53
- font_family: 'courier new',
54
- font_size: '12px'
55
- },
56
- } + options
57
- end
58
-
59
- ######################################################################
60
- # PG ENUM field handling
61
-
62
- def enum_column(c, klass)
63
- editor_config = {
64
- trigger_action: :all,
65
- xtype: :combo,
66
-
67
- # hacky: extjs has issues with forceSelection true and clearing combos
68
- store: klass::VALUES + ['---'],
69
- forceSelection: true,
70
- }
71
- c.merge!(
72
- column_config: { editor: editor_config },
73
- field_config: editor_config,
74
- type: :string,
75
- setter: enum_setter(c.name),
76
- )
77
- end
78
-
79
- def enum_setter(name)
80
- lambda {|r, v| r.send("#{name}=", v == '---' || v.empty? ? nil : v)}
81
- end
1
+ module Marty; module Extras
2
+ module Layout
3
+ def hbox(*args)
4
+ params = args.pop
5
+ params.merge(layout: { type: :hbox, align: :stretch },
6
+ items: args,
7
+ )
8
+ end
9
+
10
+ def vbox(*args)
11
+ params = args.pop
12
+ params.merge(layout: { type: :vbox, align: :stretch },
13
+ items: args,
14
+ )
15
+ end
16
+
17
+ def fieldset(title, *args)
18
+ params = args.pop
19
+ params.merge(items: args,
20
+ xtype: 'fieldset',
21
+ defaults: { anchor: '100%' },
22
+ title: title,
23
+ )
24
+ end
25
+
26
+ def dispfield(params={})
27
+ {
28
+ attr_type: :displayfield,
29
+ hide_label: !params[:field_label],
30
+ read_only: true,
31
+ }.merge(params)
32
+ end
33
+
34
+ def vspacer(params={})
35
+ vbox({flex: 1, border: false}.merge(params))
36
+ end
37
+
38
+ def hspacer(params={})
39
+ hbox({flex: 1, border: false}.merge(params))
40
+ end
41
+
42
+ def textarea_field(name, options={})
43
+ {
44
+ name: name,
45
+ width: "100%",
46
+ height: 150,
47
+ xtype: :textareafield,
48
+ auto_scroll: true,
49
+ spellcheck: false,
50
+ field_style: {
51
+ font_family: 'courier new',
52
+ font_size: '12px'
53
+ },
54
+ } + options
55
+ end
56
+
57
+ ######################################################################
58
+ # PG ENUM field handling
59
+
60
+ def enum_column(c, klass)
61
+ editor_config = {
62
+ trigger_action: :all,
63
+ xtype: :combo,
64
+
65
+ # hacky: extjs has issues with forceSelection true and clearing combos
66
+ store: klass::VALUES + ['---'],
67
+ forceSelection: true,
68
+ }
69
+ c.merge!(
70
+ column_config: { editor: editor_config },
71
+ field_config: editor_config,
72
+ type: :string,
73
+ setter: enum_setter(c.name),
74
+ )
75
+ end
76
+
77
+ def enum_setter(name)
78
+ lambda {|r, v| r.send("#{name}=", v == '---' || v.empty? ? nil : v)}
79
+ end
80
+
81
+ ######################################################################
82
+ # employ lots of hakery to implement NULLable boolean field in
83
+ # Netzke 8.x.
84
+
85
+ BOOL_MAP = {
86
+ nil => "---",
87
+ true => "True",
88
+ false => "False",
89
+ }
90
+
91
+ MAP_BOOL = {
92
+ "---" => nil,
93
+ "" => nil,
94
+ "True" => true,
95
+ "False" => false,
96
+ }
97
+
98
+ def bool_getter(name)
99
+ lambda {|r| BOOL_MAP[r.send(name)]}
100
+ end
101
+
102
+ def bool_setter(name)
103
+ lambda {|r, v| r.send("#{name}=", MAP_BOOL[v])}
104
+ end
105
+
106
+ def nullable_bool_column(name)
107
+ editor_config = {
108
+ trigger_action: :all,
109
+ xtype: :combo,
110
+ store: ["True", "False", "---"],
111
+ }
112
+ {
113
+ column_config: { editor: editor_config },
114
+ field_config: editor_config,
115
+ type: :string,
116
+ getter: bool_getter(name),
117
+ setter: bool_setter(name),
118
+ }
119
+ end
120
+
121
+ ######################################################################
122
+ # make sure to validate range vals on the model (e.g. see rule.rb)
123
+
124
+ def range_getter(name)
125
+ lambda { |r|
126
+ Marty::Util.pg_range_to_human(r.send(name))
127
+ }
128
+ end
129
+
130
+ def range_setter(name)
131
+ lambda do |r, v|
132
+ r.send("#{name}=", v && (Marty::Util.human_to_pg_range(v) rescue v))
82
133
  end
83
134
  end
84
- end
135
+
136
+ def range_field(name)
137
+ {
138
+ name: name,
139
+ getter: range_getter(name),
140
+ setter: range_setter(name),
141
+ }
142
+ end
143
+
144
+ def range_column(c, name)
145
+ c.getter = range_getter(name)
146
+ c.setter = range_setter(name)
147
+ c.width = 80
148
+ c.align = 'right'
149
+ end
150
+
151
+ end; end; end
@@ -8,6 +8,7 @@ require 'marty/event_view'
8
8
  require 'marty/promise_view'
9
9
  require 'marty/api_auth_view'
10
10
  require 'marty/config_view'
11
+ require 'marty/data_grid_view'
11
12
 
12
13
  class Marty::MainAuthApp < Marty::AuthApp
13
14
  extend ::Marty::Permissions
@@ -39,10 +40,10 @@ class Marty::MainAuthApp < Marty::AuthApp
39
40
  icon: icon_hack(:time),
40
41
  style: (warped ? "background-color: lightGrey;" : ""),
41
42
  menu: [
42
- :new_posting,
43
- :select_posting,
44
- :select_now,
45
- ],
43
+ :new_posting,
44
+ :select_posting,
45
+ :select_now,
46
+ ],
46
47
  }
47
48
  end
48
49
 
@@ -52,14 +53,14 @@ class Marty::MainAuthApp < Marty::AuthApp
52
53
  icon: icon_hack(:wrench),
53
54
  style: "",
54
55
  menu: [
55
- :import_type_view,
56
- :user_view,
57
- :config_view,
58
- :api_auth_view,
59
- :event_view,
60
- :reload_scripts,
61
- :load_seed,
62
- ] + background_jobs_menu
56
+ :import_type_view,
57
+ :user_view,
58
+ :config_view,
59
+ :api_auth_view,
60
+ :event_view,
61
+ :reload_scripts,
62
+ :load_seed,
63
+ ] + background_jobs_menu
63
64
  }
64
65
  end
65
66
 
@@ -68,25 +69,26 @@ class Marty::MainAuthApp < Marty::AuthApp
68
69
  text: I18n.t("applications"),
69
70
  icon: icon_hack(:application_cascade),
70
71
  menu: [
71
- :reporting,
72
- :scripting,
73
- :promise_view,
74
- ],
72
+ :data_grid_view,
73
+ :reporting,
74
+ :scripting,
75
+ :promise_view,
76
+ ],
75
77
  }
76
78
  end
77
79
 
78
80
  def background_jobs_menu
79
81
  [
80
- {
81
- text: 'Background Jobs',
82
- icon: icon_hack(:clock),
83
- disabled: !self.class.has_admin_perm?,
84
- menu: [
85
- :bg_status,
86
- :bg_stop,
87
- :bg_restart,
88
- ]
89
- },
82
+ {
83
+ text: 'Background Jobs',
84
+ icon: icon_hack(:clock),
85
+ disabled: !self.class.has_admin_perm?,
86
+ menu: [
87
+ :bg_status,
88
+ :bg_stop,
89
+ :bg_restart,
90
+ ]
91
+ },
90
92
  ]
91
93
  end
92
94
 
@@ -191,6 +193,13 @@ class Marty::MainAuthApp < Marty::AuthApp
191
193
  a.disabled = !self.class.has_admin_perm?
192
194
  end
193
195
 
196
+ action :data_grid_view do |a|
197
+ a.text = I18n.t("data_grid_view", default: "Data Grids")
198
+ a.handler = :netzke_load_component_by_action
199
+ a.icon = :table_multiple
200
+ a.disabled = !self.class.has_any_perm?
201
+ end
202
+
194
203
  action :reload_scripts do |a|
195
204
  a.text = 'Reload Scripts'
196
205
  a.tooltip = 'Reload and tag Delorean scripts'
@@ -430,6 +439,7 @@ class Marty::MainAuthApp < Marty::AuthApp
430
439
  component :user_view
431
440
  component :event_view
432
441
  component :config_view
442
+ component :data_grid_view
433
443
  component :api_auth_view do |c|
434
444
  c.disabled = Marty::Util.warped?
435
445
  end
@@ -1,9 +1,8 @@
1
- class Marty::UserView < Marty::Grid
2
- has_marty_permissions \
3
- create: [:admin, :user_manager],
4
- read: :any,
5
- update: [:admin, :user_manager],
6
- delete: [:admin, :user_manager]
1
+ module Marty; class UserView < Marty::Grid
2
+ has_marty_permissions create: [:admin, :user_manager],
3
+ read: :any,
4
+ update: [:admin, :user_manager],
5
+ delete: [:admin, :user_manager]
7
6
 
8
7
  # list of columns to be displayed in the grid view
9
8
  def self.user_columns
@@ -19,15 +18,15 @@ class Marty::UserView < Marty::Grid
19
18
  def configure(c)
20
19
  super
21
20
 
22
- c.title ||= I18n.t('users', default: "Users")
23
- c.model = "Marty::User"
24
- c.editing = :in_form
25
- c.paging = :pagination
26
- c.multi_select = false
27
- c.attributes ||= self.class.user_columns
28
- c.store_config.merge!({sorters: [{property: :login,
29
- direction: 'ASC',
30
- }]}) if c.attributes.include?(:login)
21
+ c.attributes ||= self.class.user_columns
22
+ c.title ||= I18n.t('users', default: "Users")
23
+ c.model = "Marty::User"
24
+ c.editing = :in_form
25
+ c.paging = :pagination
26
+ c.multi_select = false
27
+ c.store_config.merge!(sorters: [{property: :login,
28
+ direction: 'ASC',
29
+ }]) if c.attributes.include?(:login)
31
30
  c.scope = ->(arel) { arel.includes(:roles) }
32
31
  end
33
32
 
@@ -40,14 +39,14 @@ class Marty::UserView < Marty::Grid
40
39
  end
41
40
 
42
41
  # set new roles
43
- user.roles = Marty::Role.select {
42
+ user.roles = Role.select {
44
43
  |r| roles.include? I18n.t("roles.#{r.name}")
45
44
  }
46
45
  end
47
46
 
48
47
  def self.create_edit_user(data)
49
48
  # Creates initial place-holder user object and validate
50
- user = data["id"].nil? ? Marty::User.new : Marty::User.find(data["id"])
49
+ user = data["id"].nil? ? User.new : User.find(data["id"])
51
50
 
52
51
  self.user_columns.each {
53
52
  |c| user.send("#{c}=", data[c.to_s]) unless c == :roles
@@ -101,19 +100,19 @@ class Marty::UserView < Marty::Grid
101
100
 
102
101
  action :add do |a|
103
102
  super(a)
104
- a.text = I18n.t("user_grid.new")
105
- a.tooltip = I18n.t("user_grid.new")
106
- a.icon = :user_add
103
+ a.text = I18n.t("user_grid.new")
104
+ a.tooltip = I18n.t("user_grid.new")
105
+ a.icon = :user_add
107
106
  end
108
107
 
109
108
  action :edit do |a|
110
109
  super(a)
111
- a.icon = :user_edit
110
+ a.icon = :user_edit
112
111
  end
113
112
 
114
113
  action :delete do |a|
115
114
  super(a)
116
- a.icon = :user_delete
115
+ a.icon = :user_delete
117
116
  end
118
117
 
119
118
  def default_context_menu
@@ -121,47 +120,49 @@ class Marty::UserView < Marty::Grid
121
120
  end
122
121
 
123
122
  attribute :login do |c|
124
- c.width = 100
125
- c.label = I18n.t("user_grid.login")
123
+ c.width = 100
124
+ c.label = I18n.t("user_grid.login")
126
125
  end
127
126
 
128
127
  attribute :firstname do |c|
129
- c.width = 100
130
- c.label = I18n.t("user_grid.firstname")
128
+ c.width = 100
129
+ c.label = I18n.t("user_grid.firstname")
131
130
  end
132
131
 
133
132
  attribute :lastname do |c|
134
- c.width = 100
135
- c.label = I18n.t("user_grid.lastname")
133
+ c.width = 100
134
+ c.label = I18n.t("user_grid.lastname")
136
135
  end
137
136
 
138
137
  attribute :active do |c|
139
- c.width = 60
140
- c.label = I18n.t("user_grid.active")
138
+ c.width = 60
139
+ c.label = I18n.t("user_grid.active")
141
140
  end
142
141
 
143
142
  attribute :roles do |c|
144
- c.width = 100
145
- c.flex = 1
143
+ c.width = 100
144
+ c.flex = 1
146
145
  c.label = I18n.t("user_grid.roles")
147
- c.type = :string,
146
+ c.type = :string,
148
147
 
149
148
  c.getter = lambda do |r|
150
149
  r.roles.map { |ur| I18n.t("roles.#{ur.name}") }.sort
151
150
  end
152
- c.editor_config = { multi_select: true,
153
- empty_text: I18n.t("user_grid.select_roles"),
154
- store: Marty::Role.pluck(:name).map {
155
- |n| I18n.t("roles.#{n}")}.sort,
156
- type: :string,
157
- xtype: :combo}
151
+
152
+ c.editor_config = {
153
+ multi_select: true,
154
+ empty_text: I18n.t("user_grid.select_roles"),
155
+ store: Role.pluck(:name).map {|n| I18n.t("roles.#{n}")}.sort,
156
+ type: :string,
157
+ xtype: :combo,
158
+ }
158
159
  end
159
160
 
160
161
  attribute :created_dt do |c|
161
- c.label = I18n.t("user_grid.created_dt")
162
+ c.label = I18n.t("user_grid.created_dt")
162
163
  c.format = "Y-m-d H:i"
163
164
  c.read_only = true
164
165
  end
165
- end
166
+ end; end
166
167
 
167
168
  UserView = Marty::UserView
@@ -4,7 +4,9 @@ module Marty
4
4
 
5
5
  def index
6
6
  if action_methods.include?(params[:testop].to_s)
7
- self.send(params[:testop])
7
+ send(params[:testop])
8
+ elsif params[:testop] == 'env'
9
+ send('environment')
8
10
  else
9
11
  render file: 'public/404', status: 404, layout: false
10
12
  end
@@ -15,6 +17,40 @@ module Marty
15
17
  [Diagnostic.new('Marty Version', true, VERSION)]
16
18
  end
17
19
 
20
+ def environment
21
+ rbv = "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
22
+
23
+ details = [
24
+ Diagnostic.new('Environment', true, Rails.env),
25
+ Diagnostic.new('Rails Version', true, Rails.version),
26
+ Diagnostic.new('Netzke Core Version', true, Netzke::Core::VERSION),
27
+ Diagnostic.new('Netzke Basepack Version', true,
28
+ Netzke::Basepack::VERSION),
29
+ Diagnostic.new('Ruby Version', true, rbv),
30
+ Diagnostic.new('RubyGems Version', true, Gem::VERSION),
31
+ Diagnostic.new('Database Adapter', true,
32
+ ActiveRecord::Base.connection.adapter_name)
33
+ ]
34
+ begin
35
+ status = true
36
+ result = ActiveRecord::Base.connection.execute('SELECT VERSION();')
37
+ message = result[0]['version'] if result
38
+ rescue => e
39
+ status = false
40
+ message = e.message
41
+ end
42
+ details << Diagnostic.new('Database Version', status, message)
43
+
44
+ begin
45
+ status, message = true, ActiveRecord::Migrator.current_version
46
+ rescue => e
47
+ status = false
48
+ message = e.message
49
+ end
50
+ details << Diagnostic.new('Database Schema Version', status, message)
51
+ diag_response details
52
+ end
53
+
18
54
  private
19
55
  def diag_response details
20
56
  if @aggregate_diags
@@ -34,8 +34,8 @@ class Marty::DataGrid < Marty::Base
34
34
  dg.metadata.each do
35
35
  |inf|
36
36
 
37
- attr, type, keys, dir, rs_keep =
38
- inf["attr"], inf["type"], inf["keys"], inf["dir"], inf["rs_keep"]
37
+ attr, type, keys, rs_keep =
38
+ inf["attr"], inf["type"], inf["keys"], inf["rs_keep"]
39
39
 
40
40
  unless rs_keep.nil? || rs_keep.empty?
41
41
  m = /\A *(<|<=|>|>=)? *([a-z_]+) *\z/.match(rs_keep)
@@ -197,35 +197,35 @@ class Marty::DataGrid < Marty::Base
197
197
  # This would prefer more specific rather than wild card
198
198
  # solutions. However, would need to figure out how to preserve
199
199
  # ordering on subsequent INTERSECT operations.
200
- ixq = ix_class.
201
- select(:index).
202
- distinct.
203
- where(data_grid_id: group_id,
204
- created_dt: created_dt,
205
- attr: inf["attr"],
206
- ).
207
- where(q, v).to_sql
200
+ ix_class.
201
+ select(:index).
202
+ distinct.
203
+ where(data_grid_id: group_id,
204
+ created_dt: created_dt,
205
+ attr: inf["attr"],
206
+ ).
207
+ where(q, v).to_sql
208
208
  end.compact
209
209
 
210
210
  sql = sqla.join(" INTERSECT ")
211
211
 
212
- self.class.connection.execute(sql).to_a.map { |h| h["index"].to_i }
212
+ self.class.connection.execute(sql).to_a.map { |hh| hh["index"].to_i }
213
213
  end
214
214
 
215
215
  def lookup_grid_distinct(pt, h, return_grid_data=false, distinct=true)
216
- isets = ["h", "v"].each_with_object({}) do |dir, isets|
216
+ isets = ["h", "v"].each_with_object({}) do |dir, ih|
217
217
  infos = dir_infos(dir)
218
218
 
219
- isets[dir] = query_grid_dir(h, infos)
219
+ ih[dir] = query_grid_dir(h, infos)
220
220
 
221
- unless isets[dir] or return_grid_data
221
+ unless ih[dir] or return_grid_data
222
222
  attrs = infos.map { |inf| inf["attr"] }
223
223
 
224
224
  raise "#{dir} attrs not provided: %s" % attrs.join(',')
225
225
  end
226
226
 
227
- raise "Grid #{name}, (#{isets[dir].count}) #{dir} matches > 1." if
228
- distinct && isets[dir] && isets[dir].count > 1
227
+ raise "Grid #{name}, (#{ih[dir].count}) #{dir} matches > 1." if
228
+ distinct && ih[dir] && ih[dir].count > 1
229
229
  end
230
230
 
231
231
  # deterministic result: pick min index when there's a choice
@@ -349,7 +349,7 @@ class Marty::DataGrid < Marty::Base
349
349
  dt_row = lenient ? ["lenient"] : []
350
350
  dt_row << data_type unless [nil, DEFAULT_DATA_TYPE].member?(data_type)
351
351
 
352
- meta_rows = dt_row.empty? ? [] : [dt_row]
352
+ meta_rows = dt_row.empty? ? [] : [[dt_row.join(' ')]]
353
353
 
354
354
  meta_rows += metadata.map { |inf|
355
355
  [inf["attr"], inf["type"], inf["dir"], inf["rs_keep"] || ""]
@@ -435,7 +435,7 @@ class Marty::DataGrid < Marty::Base
435
435
 
436
436
  def self.maybe_get_klass(type)
437
437
  begin
438
- klass = type.constantize unless INDEX_MAP[type] || type == "float"
438
+ type.constantize unless INDEX_MAP[type] || type == "float"
439
439
  rescue NameError
440
440
  raise "unknown header type/klass: #{type}"
441
441
  end
@@ -620,8 +620,8 @@ class Marty::DataGrid < Marty::Base
620
620
  metadata_copy, data_copy = metadata.deep_dup, data.deep_dup
621
621
 
622
622
  metadata_copy.each do |meta|
623
- dir, attr, keys, type, rs_keep = meta.values_at(
624
- "dir", "attr", "keys", "type", "rs_keep")
623
+ dir, keys, type, rs_keep = meta.values_at(
624
+ "dir", "keys", "type", "rs_keep")
625
625
  next unless rs_keep
626
626
 
627
627
  if type == "numrange" || type == "int4range"
@@ -17,6 +17,8 @@ en:
17
17
  create_posting: Create
18
18
  api_auth: API Authorization
19
19
  event_view: Event View
20
+ data_grid_view: Data Grids
21
+ data_grid: Data Grids
20
22
 
21
23
  roles:
22
24
  viewer: Viewer
@@ -154,3 +156,6 @@ en:
154
156
  api_key: API Key
155
157
  app_name: Application Name
156
158
  script_name: Script Name
159
+ data_grid__name: Data Grid
160
+ breakeven_data_grid__name: Breakeven Data Grid
161
+ data_grid_view: Data Grids
@@ -1,3 +1,3 @@
1
1
  module Marty
2
- VERSION = "1.0.20"
2
+ VERSION = "1.0.22"
3
3
  end
@@ -66,5 +66,37 @@ module Marty
66
66
  end
67
67
  end
68
68
  end
69
+
70
+ describe 'GET #environment' do
71
+ it 'returns http success' do
72
+ get :environment
73
+
74
+ expect(response).to have_http_status(:success)
75
+ end
76
+
77
+ it 'returns the environment details' do
78
+ get :environment
79
+
80
+ aggregate_failures do
81
+ expect(assigns('details').count).to eq(9)
82
+ expect(assigns('details').first.methods)
83
+ .to include(:name, :status, :description)
84
+ expect(assigns('details').first.description).to eq('test')
85
+ end
86
+ end
87
+
88
+ it 'returns the appropriate json' do
89
+ get :environment, format: :json
90
+
91
+ aggregate_failures do
92
+ expect(json_response.first['diag_count']).to eq(9)
93
+ expect(json_response.first['error_count']).to eq(0)
94
+ expect(json_response
95
+ .find { |d| d['name'] == 'Environment' }['description'])
96
+ .to eq('test')
97
+ end
98
+ end
99
+ end
100
+
69
101
  end
70
102
  end
@@ -699,6 +699,15 @@ EOS
699
699
  end
700
700
  end
701
701
 
702
+ describe "exports" do
703
+ it 'should export lenient grids correctly' do
704
+ dg = dg_from_import("Gf", Gf)
705
+ dg2 = dg_from_import("Gf2", dg.export)
706
+
707
+ expect(dg.export).to eq(dg2.export)
708
+ end
709
+ end
710
+
702
711
  describe "updates" do
703
712
  it "should be possible to modify a grid referenced from a multi-grid" do
704
713
  dgb = dg_from_import("Gb", Gb, '1/1/2014')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marty
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.20
4
+ version: 1.0.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arman Bostani
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2017-01-31 00:00:00.000000000 Z
17
+ date: 2017-02-13 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: pg
@@ -178,6 +178,7 @@ files:
178
178
  - app/components/marty/auth_app.rb
179
179
  - app/components/marty/auth_app/client/auth_app.js
180
180
  - app/components/marty/config_view.rb
181
+ - app/components/marty/data_grid_view.rb
181
182
  - app/components/marty/event_view.rb
182
183
  - app/components/marty/extras/layout.rb
183
184
  - app/components/marty/extras/misc.rb