marty 0.5.15 → 0.5.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +27 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +23 -0
  5. data/Gemfile +23 -0
  6. data/INDEPENDENCE_ISSUES.md +23 -0
  7. data/app/assets/images/marty/.gitkeep +0 -0
  8. data/app/components/marty/report_form.rb +9 -4
  9. data/gemini_deprecations.md +6 -0
  10. data/lib/marty/data_change.rb +99 -0
  11. data/lib/marty/data_conversion.rb +11 -3
  12. data/lib/marty/data_exporter.rb +9 -0
  13. data/lib/marty/version.rb +1 -1
  14. data/marty.gemspec +35 -0
  15. data/script/rails +8 -0
  16. data/spec/controllers/application_controller_spec.rb +52 -0
  17. data/spec/controllers/job_controller_spec.rb +226 -0
  18. data/spec/controllers/rpc_controller_spec.rb +379 -0
  19. data/spec/controllers/rpc_import_spec.rb +45 -0
  20. data/spec/dummy/README.rdoc +261 -0
  21. data/spec/dummy/Rakefile +7 -0
  22. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  23. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  24. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  25. data/spec/dummy/app/controllers/components_controller.rb +7 -0
  26. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  27. data/spec/dummy/app/mailers/.gitkeep +0 -0
  28. data/spec/dummy/app/models/.gitkeep +0 -0
  29. data/spec/dummy/app/models/gemini/amortization_type.rb +5 -0
  30. data/spec/dummy/app/models/gemini/bud_category.rb +7 -0
  31. data/spec/dummy/app/models/gemini/entity.rb +2 -0
  32. data/spec/dummy/app/models/gemini/extras/data_import.rb +5 -0
  33. data/spec/dummy/app/models/gemini/extras/settlement_import.rb +28 -0
  34. data/spec/dummy/app/models/gemini/fannie_bup.rb +29 -0
  35. data/spec/dummy/app/models/gemini/grouping.rb +8 -0
  36. data/spec/dummy/app/models/gemini/grouping_head_version.rb +14 -0
  37. data/spec/dummy/app/models/gemini/head.rb +7 -0
  38. data/spec/dummy/app/models/gemini/head_version.rb +14 -0
  39. data/spec/dummy/app/models/gemini/helper.rb +44 -0
  40. data/spec/dummy/app/models/gemini/loan_program.rb +11 -0
  41. data/spec/dummy/app/models/gemini/mortgage_type.rb +5 -0
  42. data/spec/dummy/app/models/gemini/simple.rb +6 -0
  43. data/spec/dummy/app/models/gemini/streamline_type.rb +16 -0
  44. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  45. data/spec/dummy/config.ru +4 -0
  46. data/spec/dummy/config/application.rb +82 -0
  47. data/spec/dummy/config/boot.rb +10 -0
  48. data/spec/dummy/config/database.yml.example +10 -0
  49. data/spec/dummy/config/environment.rb +5 -0
  50. data/spec/dummy/config/environments/development.rb +35 -0
  51. data/spec/dummy/config/environments/production.rb +69 -0
  52. data/spec/dummy/config/environments/test.rb +39 -0
  53. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  54. data/spec/dummy/config/initializers/delayed_job.rb +5 -0
  55. data/spec/dummy/config/initializers/inflections.rb +15 -0
  56. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  57. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  58. data/spec/dummy/config/initializers/session_store.rb +8 -0
  59. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  60. data/spec/dummy/config/locales/en.yml +5 -0
  61. data/spec/dummy/config/routes.rb +12 -0
  62. data/spec/dummy/db/migrate/20140801000000_create_groupings.rb +11 -0
  63. data/spec/dummy/db/migrate/20150406171536_create_categories.rb +27 -0
  64. data/spec/dummy/db/migrate/20150408200916_create_loan_programs.rb +26 -0
  65. data/spec/dummy/db/migrate/20150408201429_create_types.rb +21 -0
  66. data/spec/dummy/db/migrate/20150420000001_create_heads.rb +14 -0
  67. data/spec/dummy/db/migrate/20150420000002_create_head_versions.rb +15 -0
  68. data/spec/dummy/db/migrate/20150420000003_create_grouping_head_versions.rb +12 -0
  69. data/spec/dummy/db/migrate/20151023000001_create_simple.rb +12 -0
  70. data/spec/dummy/db/seeds.rb +8 -0
  71. data/spec/dummy/delorean/blame_report.dl +171 -0
  72. data/spec/dummy/delorean/data_report.dl +105 -0
  73. data/spec/dummy/delorean/fields.dl +52 -0
  74. data/spec/dummy/delorean/styles.dl +134 -0
  75. data/spec/dummy/lib/assets/.gitkeep +0 -0
  76. data/spec/dummy/lib/class_list.rb +3 -0
  77. data/spec/dummy/log/.gitkeep +0 -0
  78. data/spec/dummy/public/404.html +26 -0
  79. data/spec/dummy/public/422.html +26 -0
  80. data/spec/dummy/public/500.html +25 -0
  81. data/spec/dummy/public/favicon.ico +0 -0
  82. data/spec/dummy/public/icons/READ.txt +3 -0
  83. data/spec/dummy/public/icons/application_cascade.png +0 -0
  84. data/spec/dummy/public/icons/application_delete.png +0 -0
  85. data/spec/dummy/public/icons/application_put.png +0 -0
  86. data/spec/dummy/public/icons/application_view_detail.png +0 -0
  87. data/spec/dummy/public/icons/arrow_in.png +0 -0
  88. data/spec/dummy/public/icons/arrow_refresh.png +0 -0
  89. data/spec/dummy/public/icons/database_save.png +0 -0
  90. data/spec/dummy/public/icons/door_in.png +0 -0
  91. data/spec/dummy/public/icons/door_out.png +0 -0
  92. data/spec/dummy/public/icons/group.png +0 -0
  93. data/spec/dummy/public/icons/page_lightning.png +0 -0
  94. data/spec/dummy/public/icons/printer.png +0 -0
  95. data/spec/dummy/public/icons/report_disk.png +0 -0
  96. data/spec/dummy/public/icons/report_go.png +0 -0
  97. data/spec/dummy/public/icons/report_magnify.png +0 -0
  98. data/spec/dummy/public/icons/script.png +0 -0
  99. data/spec/dummy/public/icons/script_add.png +0 -0
  100. data/spec/dummy/public/icons/script_go.png +0 -0
  101. data/spec/dummy/public/icons/script_key.png +0 -0
  102. data/spec/dummy/public/icons/table_go.png +0 -0
  103. data/spec/dummy/public/icons/time.png +0 -0
  104. data/spec/dummy/public/icons/time_add.png +0 -0
  105. data/spec/dummy/public/icons/time_go.png +0 -0
  106. data/spec/dummy/public/icons/timeline_marker.png +0 -0
  107. data/spec/dummy/public/icons/user_add.png +0 -0
  108. data/spec/dummy/public/icons/user_delete.png +0 -0
  109. data/spec/dummy/public/icons/user_edit.png +0 -0
  110. data/spec/dummy/public/icons/wrench.png +0 -0
  111. data/spec/dummy/script/delayed_job +6 -0
  112. data/spec/dummy/script/rails +6 -0
  113. data/spec/features/javascripts/job_dashboard_live_search.js.coffee +8 -0
  114. data/spec/features/javascripts/login.js.coffee +8 -0
  115. data/spec/features/jobs_dashboard_netzke_spec.rb +24 -0
  116. data/spec/features/jobs_dashboard_spec.rb +49 -0
  117. data/spec/fixtures/scripts/load_tests/script1.dl +2 -0
  118. data/spec/fixtures/scripts/load_tests/script2.dl +2 -0
  119. data/spec/job_helper.rb +102 -0
  120. data/spec/lib/data_exporter_spec.rb +71 -0
  121. data/spec/lib/data_importer_spec.rb +461 -0
  122. data/spec/lib/xl_spec.rb +198 -0
  123. data/spec/lib/xl_styles_spec.rb +115 -0
  124. data/spec/models/api_auth_spec.rb +187 -0
  125. data/spec/models/posting_spec.rb +107 -0
  126. data/spec/models/promise_spec.rb +65 -0
  127. data/spec/models/script_spec.rb +187 -0
  128. data/spec/models/user_spec.rb +68 -0
  129. data/spec/requests/routes_spec.rb +12 -0
  130. data/spec/spec_helper.rb +61 -0
  131. data/spec/support/clean_db_helpers.rb +18 -0
  132. data/spec/support/delayed_job_helpers.rb +12 -0
  133. data/spec/support/user_helpers.rb +12 -0
  134. metadata +139 -89
  135. data/app/components/marty/auth_app.rb~ +0 -51
  136. data/app/components/marty/auth_app/javascripts/auth_app.js~ +0 -91
  137. data/app/components/marty/cm_form_panel.rb~ +0 -5
  138. data/app/components/marty/cm_grid_panel.rb~ +0 -35
  139. data/app/components/marty/data_import_view.rb~ +0 -142
  140. data/app/components/marty/extras/layout.rb~ +0 -46
  141. data/app/components/marty/live_search_grid_panel.rb~ +0 -49
  142. data/app/components/marty/main_auth_app.rb~ +0 -238
  143. data/app/components/marty/mcfly_grid_panel.rb~ +0 -80
  144. data/app/components/marty/new_posting_form.rb~ +0 -46
  145. data/app/components/marty/new_posting_window.rb~ +0 -21
  146. data/app/components/marty/pivot_grid.rb +0 -52
  147. data/app/components/marty/pivot_grid/endpoints.rb +0 -45
  148. data/app/components/marty/pivot_grid/javascripts/extensions.js +0 -150
  149. data/app/components/marty/pivot_grid/javascripts/pivot_grid.js +0 -86
  150. data/app/components/marty/pivot_grid/services.rb +0 -44
  151. data/app/components/marty/posting_grid.rb~ +0 -140
  152. data/app/components/marty/promise_view.rb~ +0 -157
  153. data/app/components/marty/promise_view/stylesheets/promise_view.css~ +0 -15
  154. data/app/components/marty/report_form.rb~ +0 -217
  155. data/app/components/marty/report_select.rb~ +0 -133
  156. data/app/components/marty/reporting.rb~ +0 -39
  157. data/app/components/marty/script_detail.rb~ +0 -430
  158. data/app/components/marty/script_form.rb~ +0 -233
  159. data/app/components/marty/script_form/javascripts/Ext.ux.form.field.CodeMirror.js~ +0 -909
  160. data/app/components/marty/script_grid.rb~ +0 -99
  161. data/app/components/marty/script_tester.rb~ +0 -213
  162. data/app/components/marty/scripting.rb~ +0 -124
  163. data/app/components/marty/select_report.rb~ +0 -143
  164. data/app/components/marty/simple_app.rb~ +0 -101
  165. data/app/components/marty/tag_grid.rb~ +0 -89
  166. data/app/components/marty/tree_panel.rb~ +0 -256
  167. data/app/components/marty/tree_panel/javascripts/tree_panel.js~ +0 -317
  168. data/app/components/marty/user_pivot.rb +0 -128
  169. data/app/components/marty/user_view.rb~ +0 -188
  170. data/app/controllers/marty/application_controller.rb~ +0 -133
  171. data/app/controllers/marty/components_controller.rb~ +0 -37
  172. data/app/controllers/marty/job_controller.rb~ +0 -28
  173. data/app/controllers/marty/rpc_controller.rb~ +0 -61
  174. data/app/helpers/marty/script_set.rb~ +0 -59
  175. data/app/models/marty/api_auth.rb~ +0 -48
  176. data/app/models/marty/data_change.rb~ +0 -141
  177. data/app/models/marty/enum.rb~ +0 -16
  178. data/app/models/marty/import_type.rb~ +0 -48
  179. data/app/models/marty/poop.rb~ +0 -169
  180. data/app/models/marty/posting.rb~ +0 -86
  181. data/app/models/marty/posting_type.rb~ +0 -21
  182. data/app/models/marty/promise.rb~ +0 -196
  183. data/app/models/marty/role.rb~ +0 -10
  184. data/app/models/marty/script.rb~ +0 -62
  185. data/app/models/marty/tag.rb~ +0 -91
  186. data/app/models/marty/user.rb~ +0 -148
  187. data/app/models/marty/user_role.rb~ +0 -13
  188. data/app/views/layouts/marty/application.html.erb~ +0 -11
  189. data/config/routes.rb~ +0 -10
  190. data/db/migrate/019_create_marty_postings.rb~ +0 -19
  191. data/db/migrate/095_create_marty_tags.rb~ +0 -19
  192. data/lib/marty.rb~ +0 -13
  193. data/lib/marty/content_handler.rb~ +0 -93
  194. data/lib/marty/data_exporter.rb~ +0 -137
  195. data/lib/marty/data_importer.rb~ +0 -114
  196. data/lib/marty/data_row_processor.rb~ +0 -206
  197. data/lib/marty/drop_folder_hook.rb~ +0 -17
  198. data/lib/marty/folder_hook.rb~ +0 -9
  199. data/lib/marty/lazy_column_loader.rb~ +0 -47
  200. data/lib/marty/mcfly_query.rb~ +0 -188
  201. data/lib/marty/migrations.rb~ +0 -65
  202. data/lib/marty/monkey.rb~ +0 -160
  203. data/lib/marty/permissions.rb~ +0 -69
  204. data/lib/marty/promise.rb~ +0 -41
  205. data/lib/marty/promise_job.rb~ +0 -121
  206. data/lib/marty/promise_proxy.rb~ +0 -69
  207. data/lib/marty/util.rb~ +0 -80
  208. data/lib/marty/version.rb~ +0 -3
  209. data/lib/marty/xl.rb~ +0 -526
  210. data/lib/pyxll/README.txt~ +0 -16
  211. data/lib/pyxll/gemini.py~ +0 -110
  212. data/lib/pyxll/pyxll.cfg~ +0 -12
@@ -1,101 +0,0 @@
1
- module Netzke
2
- module Basepack
3
- # Basis for a Ext.container.Viewport-based one-page application.
4
- #
5
- # == Features:
6
- # * dynamic loading of components
7
- # * browser history support (press the "Back"-button to go to the previously loaded component)
8
- # * AJAX activity indicator
9
- #
10
- # == Extending SimpleApp
11
- # You may want to extend SimpleApp to provide a custom layout. Make sure you create three regions with predefined itemId's that will be used by SimpleApp. You can use the following methods defined by SimpleApp: main_panel_config, status_bar_config, and menu_bar_config, e.g.:
12
- #
13
- # class MySimpleApp < Netzke::Basepack::SimpleApp
14
- #
15
- # def configuration
16
- # super.merge(
17
- # :items => [my_custom_navigation_config, main_panel_config, menu_bar_config, status_bar_config]
18
- # )
19
- # end
20
- #
21
- # def my_custom_navigation_config
22
- # {
23
- # :item_id => 'navigation',
24
- # :region => :east,
25
- # :width => 200
26
- # }
27
- # end
28
- #
29
- # ...
30
- # end
31
- #
32
- # The JS side of the component will have those regions referenced as this.mainPanel, this.statusBar, and this.menuBar.
33
- class SimpleApp < Base
34
- js_configure do |c|
35
- c.extend = "Ext.container.Viewport"
36
- c.layout = :border
37
- c.require Netzke::Core.ext_path.join("examples", "ux/statusbar/StatusBar.js"), :statusbar_ext
38
- c.mixin
39
- end
40
-
41
- def configure(c)
42
- super
43
- c.items = [main_panel_config, menu_bar_config, status_bar_config]
44
- end
45
-
46
- # In Ext 4.1 calling `render` on a viewport causes an error
47
- def js_component_render
48
- ""
49
- end
50
-
51
- # Override for custom menu
52
- def menu
53
- []
54
- end
55
-
56
- # Config for the main panel, which will contain dynamically loaded components.
57
- def main_panel_config(overrides = {})
58
- {
59
- :itemId => 'main_panel',
60
- :region => 'center',
61
- :layout => 'fit'
62
- }.merge(overrides)
63
- end
64
-
65
- # Config for the status bar
66
- def status_bar_config(overrides = {})
67
- {
68
- :itemId => 'status_bar',
69
- :xtype => 'statusbar',
70
- :region => 'south',
71
- :height => 22,
72
- :statusAlign => 'right',
73
- :busyText => 'Busy...',
74
- :default_text => "Ready",
75
- :default_icon_cls => ""
76
- }.merge(overrides)
77
- end
78
-
79
- # Config for the menu bar
80
- def menu_bar_config(overrides = {})
81
- {
82
- :itemId => 'menu_bar',
83
- :xtype => 'toolbar',
84
- :region => 'north',
85
- :height => 28,
86
- :items => menu
87
- }.merge(overrides)
88
- end
89
-
90
- # Html required for Ext.History to work
91
- def js_component_html
92
- super << %Q{
93
- <form id="history-form" class="x-hidden">
94
- <input type="hidden" id="x-history-field" />
95
- <iframe id="x-history-frame"></iframe>
96
- </form>
97
- }
98
- end
99
- end
100
- end
101
- end
@@ -1,89 +0,0 @@
1
- class Marty::TagGrid < Marty::CmGridPanel
2
- has_marty_permissions read: :any,
3
- create: :dev
4
-
5
- def configure(c)
6
- super
7
-
8
- c.header = false
9
- c.model = "Marty::Tag"
10
- c.columns ||= [:name, :created_dt, :user__name, :comment]
11
- c.data_store.sorters = {
12
- property: :created_dt,
13
- direction: 'DESC',
14
- }
15
- end
16
-
17
- js_configure do |c|
18
- c.init_component = <<-JS
19
- function() {
20
- this.callParent();
21
- // Set single selection mode. FIXME: can this be done on config?
22
- this.getSelectionModel().setSelectionMode('SINGLE');
23
- }
24
- JS
25
- end
26
-
27
- endpoint :add_window__add_form__netzke_submit do |params, this|
28
- data = ActiveSupport::JSON.decode(params[:data])
29
-
30
- return this.netzke_feedback("Permission Denied") if
31
- config[:prohibit_create]
32
-
33
- # FIXME: disallow tag creation when no script has been modified?
34
-
35
- tag = Marty::Tag.do_create(nil, data["comment"])
36
-
37
- if tag.valid?
38
- this.success = true
39
- this.on_submit_success
40
- return
41
- end
42
-
43
- data_adapter.errors_array(tag).each do |error|
44
- flash :error => error
45
- end
46
-
47
- this.netzke_feedback(@flash)
48
- end
49
-
50
- action :add_in_form do |a|
51
- a.text = "New Tag"
52
- a.tooltip = "New Tag"
53
- a.icon = :time_add
54
- a.disabled = config[:prohibit_create]
55
- end
56
-
57
- def default_bbar
58
- [:add_in_form]
59
- end
60
-
61
- def default_context_menu
62
- []
63
- end
64
-
65
- def default_fields_for_forms
66
- [:comment]
67
- end
68
-
69
- column :name do |c|
70
- end
71
-
72
- column :created_dt do |c|
73
- c.text = "Date/Time"
74
- c.format = "Y-m-d H:i"
75
- c.hidden = true
76
- end
77
-
78
- column :user__name do |c|
79
- c.width = 100
80
- end
81
-
82
- column :comment do |c|
83
- c.width = 100
84
- c.flex = 1
85
- end
86
-
87
- end
88
-
89
- TagGrid = Marty::TagGrid
@@ -1,256 +0,0 @@
1
- # Ext.tree.TreePanel-based component
2
- #
3
- # ATTRIBUTION: this code is based on the netzke-extension module found at:
4
- # https://github.com/phgrey/netzke-extension
5
- # TODO: Add documentation for usage
6
-
7
- class Marty::TreePanel < Netzke::Base
8
- include ::Netzke::Basepack::DataAccessor
9
- include ::Netzke::Basepack::Columns
10
-
11
- self.default_instance_config = {
12
- indicate_leafs: true,
13
- auto_scroll: false,
14
- root_visible: false,
15
- load_inline_data: false,
16
- enable_pagination: false,
17
- rows_per_page: 30,
18
- treecolumn: 'tree' # default name for tree column
19
- }
20
-
21
- def js_configure(c) #:nodoc:
22
- super
23
- c.bbar = bbar
24
- end
25
-
26
- js_configure do |c|
27
- c.extend = "Ext.tree.TreePanel"
28
- c.mixin
29
- c.root_visible = false
30
- end
31
-
32
- # Configure dynamic JS properties for instantiation
33
- def js_config
34
- super.tap do |c|
35
- # Hand over inline data to the js config hash
36
- c[:inline_data] = get_data if config[:load_inline_data]
37
- end
38
- end
39
-
40
- def configure(c) #:nodoc:
41
- super
42
- c.title ||= self.class.js_config.properties[:title] ||
43
- data_class.name.pluralize
44
- c.columns = final_columns(with_meta: true)
45
-
46
- # Set it to the primary key if not given and camelize it Setting
47
- # it to anything else than the primary key is especially useful
48
- # when instances of different class are shown in one tree because
49
- # the primary key MUST be unique!
50
- c.pri = (c.pri || data_class.primary_key).to_s.camelize(:lower)
51
-
52
- # Add extra fields for a tree: A method ':name(r)' is called for
53
- # every record to retrieve the value
54
- c.extra_fields ||= []
55
-
56
- # This will call leaf?(r) for every record
57
- c.extra_fields << {name: 'leaf', type: 'boolean'}
58
-
59
- # This will call expanded?(r) for every record
60
- c.extra_fields << {name: 'expanded', type: 'boolean'}
61
-
62
- # only if the node id property is different from the data class'
63
- # primary key, we need to add and extra field
64
- c.extra_fields << {name: c.pri.to_s.camelize(:lower), type: 'string'} if
65
- c.pri != data_class.primary_key
66
- end
67
-
68
- def config
69
- @config ||= ActiveSupport::OrderedOptions.new.tap do |c|
70
- # extend with data_store convenient config object
71
- c.data_store = ActiveSupport::OrderedOptions.new
72
- end
73
- end
74
-
75
- def bbar
76
- config[:bbar]
77
- end
78
-
79
- # Sets the xtype to 'treecolumn' for the column with name equal to
80
- # the :treecolumn value of the config
81
- def set_default_xtype(c)
82
- c[:xtype] = 'treecolumn' if c[:name].to_s == config[:treecolumn].to_s
83
- end
84
-
85
- # Set data_index -- The name of the field configuration of the Ext
86
- # JS model will be set to this value This is neccessary since the
87
- # data is serialized as a hash (with camelized keys) so the
88
- # data_index must also be camelized
89
- def set_default_data_index(c)
90
- c[:data_index] = c[:name].camelize(:lower)
91
- end
92
-
93
- # Call super and then set the data_index
94
- def augment_column_config(c)
95
- super
96
- set_default_data_index(c)
97
- set_default_xtype c
98
- end
99
-
100
- # @!method get_data_endpoint
101
- #
102
- # Returns something like:
103
- # [
104
- # { 'id'=> 1, 'text'=> 'A folder Node', 'leaf'=> false },
105
- # { 'id'=> 2, 'text'=> 'A leaf Node', 'leaf'=> true }
106
- # ]
107
- #
108
- # @param [Hash] params
109
- endpoint :get_data do |params, this|
110
- this.merge! get_data(params)
111
- end
112
-
113
- # Method that is called by the get_data endpoint
114
- # Calls the get_children method and returns the serialized records
115
- #
116
- # @param [] *args takes any arguments
117
- # @return [Hash] all the serialized data
118
- def get_data(*args)
119
- params = args.first || {} # params are optional!
120
-
121
- sortp = params["sort"]
122
-
123
- # Giant hack to fix property field used in sort. Not sure why
124
- # this is coming in camelized.
125
- if sortp.is_a?(Array)
126
- sortp.each { |h|
127
- h["property"] = h["property"].underscore if
128
- h.is_a?(Hash) && h["property"]
129
- }
130
- end
131
-
132
- if !config[:prohibit_read]
133
- {}.tap do |res|
134
- # set children to an instance variable in order to access them later
135
- @records = get_children(params)
136
-
137
- # Serialize children
138
- res[:data] = serialize_data(@records)
139
-
140
- res[:total] = count_records(params) if
141
- config[:enable_pagination] &&
142
- (params[:id].nil? || params[:id] == 'root')
143
- end
144
- else
145
- flash :error => "You don't have permissions to read data"
146
- { :netzke_feedback => @flash }
147
- end
148
- end
149
-
150
- # Serializes an array of objects
151
- #
152
- # @param [Array] records
153
- # @return [Array] the serialized data
154
- def serialize_data(records)
155
- records.map { |r|
156
- data_adapter.record_to_hash(r, final_columns(:with_meta => true)).tap { |h|
157
-
158
- config[:extra_fields].each do |f|
159
- name = f[:name].underscore.to_sym
160
- h[name] = send("#{name}#{f[:type] == 'boolean' ? '?' : ''}", r)
161
- end
162
-
163
- inline_children = get_inline_children(r)
164
- h[:data] = serialize_data(inline_children) unless inline_children.nil?
165
- h
166
- }
167
- }
168
- end
169
-
170
- # Retrieves all children for a node
171
- # Note: It's recommended to override this method
172
- #
173
- # @param [Hash] params
174
- # @return [Array] array of records
175
- def get_children(params)
176
- scope_data_class(params) do
177
- params[:limit] = config[:rows_per_page] if
178
- config[:enable_pagination] && (params[:id].nil? || params[:id] == 'root')
179
- params[:scope] = config[:scope]
180
- data_adapter.get_records(params, final_columns)
181
- end
182
- end
183
-
184
- # Scopes the data class depending on the config of the parent_key and the node
185
- #
186
- # @param [Hash] params
187
- def scope_data_class(params, &block)
188
- if config[:parent_key]
189
- # The value of the pri property of the expanded node is passed
190
- # as params[:id] ('root' for the root collection)
191
- if params[:id].nil? || params[:id] == 'root'
192
- data_class.where(config[:parent_key] => nil).scoping do
193
- yield
194
- end
195
- else
196
- data_class.where(config[:parent_key] => params[:id]).scoping do
197
- yield
198
- end
199
- end
200
- else
201
- yield
202
- end
203
- end
204
-
205
- # Counts the total records
206
- #
207
- # @param [Hash] params
208
- # @return [Fixnum] The number of records
209
- def count_records(params)
210
- scope_data_class(params) do
211
- params[:scope] = config[:scope]
212
- data_adapter.count_records(params, final_columns)
213
- end
214
- end
215
-
216
- # Should return all children of the record that should also be
217
- # serialized in the current request
218
- # Note: It's recommended to override this method
219
- #
220
- # @param [Object] r The record for which the inline children should be loaded
221
- # @return [NilClass, Array] If nil is returned, the tree doesn't
222
- # know anything about any children, so opening the node will cause
223
- # another request. If an empty array is returned, the tree assumes
224
- # that there are no children available for this node (and thus you
225
- # can't open it!)
226
- def get_inline_children(r)
227
- nil
228
- end
229
-
230
- # Is the record a leaf or not?
231
- # Note: It's recommended to override this method
232
- #
233
- # @param [Object] r
234
- # @return [Boolean] Whether the node is a leaf or not
235
- def leaf?(r)
236
- r.children.empty?
237
- end
238
-
239
- # Is the record a expanded or not?
240
- # Note: It's recommended to override this method
241
- #
242
- # @param [Object] r
243
- # @return [Boolean] Whether the node is expanded or not
244
- def expanded?(r)
245
- false
246
- end
247
-
248
- # Is the record a leaf or not?
249
- # Note: It's recommended to override this method
250
- #
251
- # @param [Object] r
252
- # @return [Boolean] Whether the node is a leaf or not
253
- def node_id(r)
254
- r.send(data_class.primary_key)
255
- end
256
- end
@@ -1,317 +0,0 @@
1
- // This is a hacked up version of 0.8.4 grid.js to work with
2
- // TreePanel. FIXME: perhaps we can patch up grid.js dynamically
3
- // rather than copying all the code?
4
- {
5
- trackMouseOver: true,
6
- loadMask: true,
7
-
8
- componentLoadMask: {msg: "Loading..."},
9
- deleteMaskMsg: "Deleting...",
10
-
11
- initComponent: function(){
12
- var metaColumn;
13
- var fields = this.extraFields; // field configs for the underlying data model
14
-
15
- this.plugins = this.plugins || [];
16
- this.features = this.features || [];
17
-
18
- // Run through columns and set up different configuration for each
19
- Ext.each(this.columns, function(c, i){
20
-
21
- this.normalizeRenderer(c);
22
-
23
- // Build the field configuration for this column
24
- var fieldConfig = {name: c.dataIndex, defaultValue: c.defaultValue, useNull: true};
25
-
26
- if (c.name !== 'meta') fieldConfig.type = this.fieldTypeForAttrType(c.attrType); // field type (grid editors need this to function well)
27
-
28
- if (c.attrType == 'datetime') {
29
- fieldConfig.dateFormat = 'Y-m-d H:i:s'; // set the format in which we receive datetime from the server (so that the model can parse it)
30
-
31
- // While for 'date' columns the renderer is set up automatically (through using column's xtype), there's no appropriate xtype for our custom datetime column.
32
- // Thus, we need to set the renderer manually.
33
- // NOTE: for Ext there's no distinction b/w date and datetime; date fields can include time.
34
- if (!c.renderer) {
35
- // format in which the data will be rendered; if c.format is nil, Ext.Date.defaultFormat extended with time will be used
36
- c.renderer = Ext.util.Format.dateRenderer(c.format || Ext.Date.defaultFormat + " H:i:s");
37
- }
38
- };
39
-
40
- // because checkcolumn doesn't care about editor (not) being set, we need to explicitely set readOnly here
41
- if (c.xtype == 'checkcolumn' && !c.editor) {
42
- c.readOnly = true;
43
- }
44
-
45
- fields.push(fieldConfig);
46
-
47
- // We will not use meta columns as actual columns (not even hidden) - only to create the records
48
- if (c.meta) {
49
- metaColumn = c;
50
- return;
51
- }
52
-
53
- // Set rendeder for association columns (the one displaying associations by the specified method instead of id)
54
- if (c.assoc) {
55
- // Editor for association column
56
- c.editor = Ext.apply({
57
- parentId: this.id,
58
- name: c.name,
59
- selectOnFocus: true // ?
60
- }, c.editor);
61
-
62
- // Renderer for association column
63
- this.normalizeAssociationRenderer(c);
64
- }
65
-
66
- if (c.editor) {
67
- Ext.applyIf(c.editor, {selectOnFocus: true});
68
- }
69
-
70
- // Setting the default filter type
71
- if (c.filterable && !c.filter) {
72
- c.filter = {type: this.fieldTypeForAttrType(c.attrType)};
73
- }
74
-
75
- // HACK: somehow this is not set by Ext (while it should be)
76
- // if (c.xtype == 'datecolumn') c.format = c.format || Ext.util.Format.dateFormat;
77
- // setting dataIndex
78
- // c.dataIndex = c.name;
79
-
80
- }, this);
81
- /* ... and done with the columns */
82
-
83
- // Define the model
84
- Ext.define(this.id, {
85
- extend: 'Ext.data.Model',
86
- idProperty: this.pri, // Primary key
87
- fields: fields
88
- });
89
-
90
- // After we created the record (model), we can get rid of the meta column
91
- Ext.Array.remove(this.columns, metaColumn);
92
-
93
- // Prepare column model config with columns in the correct order; columns out of order go to the end.
94
- var colModelConfig = [];
95
- var columns = this.columns;
96
-
97
- Ext.each(this.columns, function(c) {
98
- var mainColConfig;
99
- Ext.each(this.columns, function(oc) {
100
- if (c.name === oc.name) {
101
- mainColConfig = Ext.apply({}, oc);
102
- return false;
103
- }
104
- });
105
-
106
- colModelConfig.push(Ext.apply(mainColConfig, c));
107
- }, this);
108
-
109
- // We don't need original columns any longer
110
- delete this.columns;
111
-
112
- // ... instead, define own column model
113
- this.columns = colModelConfig;
114
-
115
- // DirectProxy that uses our Ext.direct provider
116
- var proxy = Ext.create('Ext.data.proxy.Direct', {
117
-
118
- directFn: Netzke.providers[this.id].getData,
119
- // reader: Ext.create('Ext.data.reader.Array', {root: 'data', totalProperty: 'total'}),
120
- reader: {
121
- type: 'json',
122
- root: 'data'
123
- },
124
- listeners: {
125
- exception: {
126
- fn: this.loadExceptionHandler,
127
- scope: this
128
- },
129
- load: { // Netzke-introduced event; this will also be fired when an exception occurs.
130
- fn: function(proxy, response, operation) {
131
- // besides getting data into the store, we may also get commands to execute
132
- response = response.result;
133
-
134
- if (response) { // or did we have an exception?
135
- Ext.each(['data', 'total', 'success'], function(property){delete response[property];});
136
- this.netzkeBulkExecute(response);
137
- }
138
- },
139
- scope: this
140
- }
141
- }
142
- })
143
-
144
- // Create the netzke PagingTreeStore
145
-
146
- this.store = Ext.create('Ext.data.TreeStore', Ext.apply({
147
- model: this.id,
148
- proxy: proxy,
149
- autoLoad: !this.loadInlineData,
150
- // root: this.inlineData || {data: [{tree:'root', id:0}]}
151
- }, this.dataStore));
152
- delete this.dataStore;
153
-
154
- this.store.load();
155
- // HACK: we must let the store now totalCount
156
- // this.store.setTotalCount(this.inlineData && this.inlineData[this.store.getProxy().getReader().totalProperty]);
157
-
158
- // Drag'n'Drop
159
- if (this.enableRowsReordering){
160
- this.ddPlugin = new Ext.ux.dd.GridDragDropRowOrder({
161
- scrollable: true // enable scrolling support (default is false)
162
- });
163
- this.plugins.push(this.ddPlugin);
164
- }
165
-
166
- // Cell editing
167
- if (!this.prohibitUpdate) {
168
- this.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {pluginId: 'celleditor'}));
169
- }
170
-
171
- // Toolbar
172
- this.dockedItems = this.dockedItems || [];
173
- if (this.enablePagination) {
174
- this.dockedItems.push({
175
- xtype: 'pagingtoolbar',
176
- dock: 'bottom',
177
- store: this.store,
178
- // append the old bbar. TODO: get rid of it.
179
- items: this.bbar && ["-"].concat(this.bbar)
180
- });
181
- } else if (this.bbar) {
182
- this.dockedItems.push({
183
- xtype: 'toolbar',
184
- dock: 'bottom',
185
- items: this.bbar
186
- });
187
- }
188
-
189
- delete this.bbar;
190
-
191
- // Now let Ext.grid.EditorGridPanel do the rest (original initComponent)
192
- this.callParent();
193
-
194
- // Context menu
195
- if (this.contextMenu) {
196
- this.on('itemcontextmenu', this.onItemContextMenu, this);
197
- }
198
-
199
- // Disabling/enabling editInForm button according to current selection
200
- if (this.enableEditInForm && !this.prohibitUpdate) {
201
- this.getSelectionModel().on('selectionchange', function(selModel, selected){
202
- var disabled;
203
- if (selected.length === 0) { // empty?
204
- disabled = true;
205
- } else {
206
- // Disable "edit in form" button if new record is present in selection
207
- Ext.each(selected, function(r){
208
- if (r.isNew) { disabled = true; return false; }
209
- });
210
- };
211
- this.actions.editInForm.setDisabled(disabled);
212
- }, this);
213
- }
214
-
215
-
216
- // Drag n Drop event
217
- if (this.enableRowsReordering){
218
- this.ddPlugin.on('afterrowmove', this.onAfterRowMove, this);
219
- }
220
-
221
- // WIP: GridView
222
- this.getView().getRowClass = this.defaultGetRowClass;
223
-
224
- // When starting editing as assocition column, pre-load the combobox store from the meta column, so that we don't see the real value of this cell (the id of the associated record), but rather the associated record by the configured method.
225
- this.on('beforeedit', function(e){
226
- return false;
227
- }, this);
228
-
229
- this.on('afterrender', function() {
230
- // Persistence-related events (afterrender to avoid blank event firing on render)
231
- if (this.persistence) {
232
- // Inform the server part about column operations
233
- this.on('columnresize', this.onColumnResize, this);
234
- this.on('columnmove', this.onColumnMove, this);
235
- this.on('columnhide', this.onColumnHide, this);
236
- this.on('columnshow', this.onColumnShow, this);
237
- }
238
- }, this);
239
- },
240
-
241
- fieldTypeForAttrType: function(attrType){
242
- var map = {
243
- integer : 'int',
244
- decimal : 'float',
245
- datetime : 'date',
246
- date : 'date',
247
- string : 'string',
248
- text : 'string',
249
- 'boolean' : 'boolean'
250
- };
251
- return map[attrType] || 'string';
252
- },
253
-
254
- // Normalizes the renderer for a column.
255
- // Renderer may be:
256
- // 1) a string that contains the name of the function to be used as renderer.
257
- // 2) an array, where the first element is the function name, and the rest - the arguments
258
- // that will be passed to that function along with the value to be rendered.
259
- // The function is searched in the following objects: 1) Ext.util.Format, 2) this.
260
- // If not found, it is simply evaluated. Handy, when as renderer we receive an inline JS function,
261
- // or reference to a function in some other scope.
262
- // So, these will work:
263
- // * "uppercase"
264
- // * ["ellipsis", 10]
265
- // * ["substr", 3, 5]
266
- // * "myRenderer" (if this.myRenderer is a function)
267
- // * ["Some.scope.Format.customRenderer", 10, 20, 30] (if Some.scope.Format.customRenderer is a function)
268
- // * "function(v){ return 'Value: ' + v; }"
269
- normalizeRenderer: function(c) {
270
- if (!c.renderer) return;
271
-
272
- var name, args = [];
273
-
274
- if ('string' === typeof c.renderer) {
275
- name = c.renderer.camelize(true);
276
- } else {
277
- name = c.renderer[0];
278
- args = c.renderer.slice(1);
279
- }
280
-
281
- // First check whether Ext.util.Format has it
282
- if (Ext.isFunction(Ext.util.Format[name])) {
283
- c.renderer = Ext.Function.bind(Ext.util.Format[name], this, args, 1);
284
- } else if (Ext.isFunction(this[name])) {
285
- // ... then if our own class has it
286
- c.renderer = Ext.Function.bind(this[name], this, args, 1);
287
- } else {
288
- // ... and, as last resort, evaluate it (allows passing inline javascript function as renderer)
289
- eval("c.renderer = " + c.renderer + ";");
290
- }
291
- },
292
-
293
- /*
294
- Set a renderer that displayes association values instead of association record ID.
295
- The association values are passed in the meta-column under associationValues hash.
296
- */
297
- normalizeAssociationRenderer: function(c) {
298
- c.scope = this;
299
- var passedRenderer = c.renderer; // renderer we got from normalizeRenderer
300
- c.renderer = function(value, a, r, ri, ci){
301
- var column = this.headerCt.items.getAt(ci),
302
- editor = column.getEditor && column.getEditor(),
303
- recordFromStore = editor && editor.isXType('combobox') && editor.getStore().findRecord('value', value),
304
- renderedValue;
305
-
306
- if (recordFromStore) {
307
- renderedValue = recordFromStore.get('text');
308
- } else if (c.assoc && r.get('meta')) {
309
- renderedValue = r.get('meta').associationValues[c.name] || c.emptyText;
310
- } else {
311
- renderedValue = value;
312
- }
313
-
314
- return passedRenderer ? passedRenderer.call(this, renderedValue) : renderedValue;
315
- };
316
- }
317
- }