marty 1.0.20 → 1.0.22

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