netzke-basepack 0.7.7 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. data/.travis.yml +15 -10
  2. data/{CHANGELOG.rdoc → CHANGELOG.md} +146 -110
  3. data/LICENSE +7 -1
  4. data/README.md +47 -56
  5. data/Rakefile +5 -5
  6. data/config/before-travis.sh +10 -0
  7. data/javascripts/basepack.js +0 -130
  8. data/javascripts/netzkeremotecombo.js +59 -0
  9. data/lib/netzke/basepack.rb +9 -14
  10. data/lib/netzke/basepack/accordion.rb +45 -0
  11. data/lib/netzke/basepack/active_record.rb +12 -0
  12. data/lib/netzke/basepack/active_record/relation_extensions.rb +27 -0
  13. data/lib/netzke/basepack/columns.rb +309 -0
  14. data/lib/netzke/basepack/data_accessor.rb +22 -12
  15. data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +75 -11
  16. data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +154 -49
  17. data/lib/netzke/basepack/fields.rb +162 -0
  18. data/lib/netzke/basepack/form.rb +136 -0
  19. data/lib/netzke/basepack/{form_panel → form}/javascripts/comma_list_cbg.js +0 -1
  20. data/lib/netzke/basepack/{form_panel/javascripts/form_panel.js → form/javascripts/form.js} +20 -26
  21. data/lib/netzke/basepack/{form_panel → form}/javascripts/n_radio_group.js +0 -1
  22. data/lib/netzke/basepack/{form_panel → form}/javascripts/readonly_mode.js +0 -0
  23. data/lib/netzke/basepack/form/services.rb +115 -0
  24. data/lib/netzke/basepack/{form_panel → form}/stylesheets/readonly_mode.css +0 -0
  25. data/lib/netzke/basepack/grid.rb +355 -0
  26. data/lib/netzke/basepack/{grid_panel → grid}/javascripts/advanced_search.js +1 -1
  27. data/lib/netzke/basepack/{grid_panel → grid}/javascripts/check_column_fix.js +0 -0
  28. data/lib/netzke/basepack/{grid_panel → grid}/javascripts/edit_in_form.js +3 -3
  29. data/lib/netzke/basepack/{grid_panel → grid}/javascripts/event_handling.js +5 -2
  30. data/lib/netzke/basepack/{grid_panel/javascripts/grid_panel.js → grid/javascripts/grid.js} +120 -132
  31. data/lib/netzke/basepack/{grid_panel → grid}/javascripts/misc.js +0 -0
  32. data/lib/netzke/basepack/grid/services.rb +216 -0
  33. data/lib/netzke/basepack/item_persistence.rb +44 -0
  34. data/lib/netzke/basepack/item_persistence/events_plugin.rb +47 -0
  35. data/lib/netzke/basepack/{paging_form_panel.rb → paging_form.rb} +24 -30
  36. data/lib/netzke/basepack/{paging_form_panel/javascripts/paging_form_panel.js → paging_form/javascripts/paging_form.js} +2 -4
  37. data/lib/netzke/basepack/query_builder.rb +44 -73
  38. data/lib/netzke/basepack/query_builder/javascripts/query_builder.js +16 -2
  39. data/lib/netzke/basepack/record_form_window.rb +67 -0
  40. data/lib/netzke/basepack/search_panel.rb +22 -24
  41. data/lib/netzke/basepack/search_panel/javascripts/condition_field.js +2 -2
  42. data/lib/netzke/basepack/search_window.rb +47 -53
  43. data/lib/netzke/basepack/simple_app.rb +10 -13
  44. data/lib/netzke/basepack/simple_app/javascripts/simple_app.js +2 -8
  45. data/lib/netzke/basepack/tab_panel.rb +5 -4
  46. data/lib/netzke/basepack/tab_panel/javascripts/tab_panel.js +5 -5
  47. data/lib/netzke/basepack/version.rb +2 -2
  48. data/lib/netzke/basepack/viewport.rb +16 -0
  49. data/lib/netzke/basepack/window.rb +27 -18
  50. data/lib/netzke/basepack/window/javascripts/window.js +7 -1
  51. data/lib/netzke/basepack/wrap_lazy_loaded.rb +18 -18
  52. data/locales/en.yml +40 -24
  53. data/netzke-basepack.gemspec +51 -82
  54. data/stylesheets/basepack.css +0 -41
  55. data/test/basepack_test_app/Gemfile +9 -46
  56. data/test/basepack_test_app/Gemfile.lock +61 -96
  57. data/test/basepack_test_app/app/components/author_form.rb +8 -5
  58. data/test/basepack_test_app/app/components/author_grid.rb +2 -2
  59. data/test/basepack_test_app/app/components/book_form.rb +34 -31
  60. data/test/basepack_test_app/app/components/book_form_with_defaults.rb +6 -7
  61. data/test/basepack_test_app/app/components/book_form_with_file_upload.rb +10 -0
  62. data/test/basepack_test_app/app/components/book_form_with_nested_attributes.rb +5 -6
  63. data/test/basepack_test_app/app/components/book_grid.rb +19 -8
  64. data/test/basepack_test_app/app/components/book_grid_filtering.rb +4 -7
  65. data/test/basepack_test_app/app/components/book_grid_loader.rb +28 -15
  66. data/test/basepack_test_app/app/components/book_grid_with_custom_columns.rb +45 -21
  67. data/test/basepack_test_app/app/components/book_grid_with_default_values.rb +26 -8
  68. data/test/basepack_test_app/app/components/book_grid_with_excluded_columns.rb +11 -0
  69. data/test/basepack_test_app/app/components/book_grid_with_extra_feedback.rb +2 -2
  70. data/test/basepack_test_app/app/components/book_grid_with_extra_filters.rb +7 -6
  71. data/test/basepack_test_app/app/components/book_grid_with_mass_assignment_security.rb +9 -0
  72. data/test/basepack_test_app/app/components/book_grid_with_nested_attributes.rb +9 -9
  73. data/test/basepack_test_app/app/components/book_grid_with_overridden_columns.rb +5 -3
  74. data/test/basepack_test_app/app/components/book_grid_with_paging.rb +6 -8
  75. data/test/basepack_test_app/app/components/book_grid_with_persistence.rb +6 -4
  76. data/test/basepack_test_app/app/components/book_grid_with_scope.rb +6 -0
  77. data/test/basepack_test_app/app/components/book_grid_with_scoped_authors.rb +10 -7
  78. data/test/basepack_test_app/app/components/book_grid_with_virtual_attributes.rb +21 -13
  79. data/test/basepack_test_app/app/components/book_paging_form.rb +21 -0
  80. data/test/basepack_test_app/app/components/book_query_builder.rb +7 -6
  81. data/test/basepack_test_app/app/components/book_with_custom_primary_key_grid.rb +6 -7
  82. data/test/basepack_test_app/app/components/books_bound_to_author.rb +9 -7
  83. data/test/basepack_test_app/app/components/border_layout_panel_with_persistence.rb +12 -0
  84. data/test/basepack_test_app/app/components/double_book_grid.rb +19 -14
  85. data/test/basepack_test_app/app/components/form_without_model.rb +15 -16
  86. data/test/basepack_test_app/app/components/grid_with_initial_sorting.rb +7 -0
  87. data/test/basepack_test_app/app/components/grid_with_inline_data.rb +7 -0
  88. data/test/basepack_test_app/app/components/paging_form_with_search.rb +2 -2
  89. data/test/basepack_test_app/app/components/panel_with_persistent_regions.rb +35 -0
  90. data/test/basepack_test_app/app/components/query_builder.rb +7 -0
  91. data/test/basepack_test_app/app/components/simple_panel.rb +16 -11
  92. data/test/basepack_test_app/app/components/simple_window.rb +7 -6
  93. data/test/basepack_test_app/app/components/some_accordion.rb +18 -0
  94. data/test/basepack_test_app/app/components/some_auth_app.rb +5 -5
  95. data/test/basepack_test_app/app/components/some_border_layout.rb +20 -20
  96. data/test/basepack_test_app/app/components/some_search_panel.rb +6 -0
  97. data/test/basepack_test_app/app/components/some_simple_app.rb +30 -16
  98. data/test/basepack_test_app/app/components/some_tab_panel.rb +18 -15
  99. data/test/basepack_test_app/app/components/user_form.rb +18 -16
  100. data/test/basepack_test_app/app/components/user_form_with_default_fields.rb +5 -6
  101. data/test/basepack_test_app/app/components/user_grid.rb +11 -6
  102. data/test/basepack_test_app/app/components/user_grid_with_customized_form_fields.rb +5 -3
  103. data/test/basepack_test_app/app/components/window_component_loader.rb +25 -21
  104. data/test/basepack_test_app/app/models/address.rb +0 -26
  105. data/test/basepack_test_app/app/models/author.rb +0 -31
  106. data/test/basepack_test_app/app/models/book.rb +1 -42
  107. data/test/basepack_test_app/app/models/book_with_custom_primary_key.rb +1 -23
  108. data/test/basepack_test_app/app/models/role.rb +0 -21
  109. data/test/basepack_test_app/app/models/user.rb +0 -24
  110. data/test/basepack_test_app/app/views/layouts/components.html.erb +1 -1
  111. data/test/basepack_test_app/config/application.rb +1 -1
  112. data/test/basepack_test_app/config/database.yml.travis +2 -6
  113. data/test/basepack_test_app/config/initializers/netzke.rb +1 -6
  114. data/test/basepack_test_app/db/schema.rb +14 -14
  115. data/test/basepack_test_app/features/accordion_panel.feature +2 -2
  116. data/test/basepack_test_app/features/form_panel.feature +7 -7
  117. data/test/basepack_test_app/features/grid_panel.feature +93 -39
  118. data/test/basepack_test_app/features/grid_panel_with_custom_primary_key.feature +2 -1
  119. data/test/basepack_test_app/features/grid_sorting.feature +30 -6
  120. data/test/basepack_test_app/features/paging_form_panel.feature +7 -7
  121. data/test/basepack_test_app/features/persistent_regions.feature +30 -0
  122. data/test/basepack_test_app/features/search_in_grid.feature +5 -5
  123. data/test/basepack_test_app/features/simple_app.feature +6 -7
  124. data/test/basepack_test_app/features/step_definitions/form_panel_steps.rb +1 -1
  125. data/test/basepack_test_app/features/step_definitions/generic_steps.rb +109 -4
  126. data/test/basepack_test_app/features/step_definitions/grid_panel_steps.rb +8 -10
  127. data/test/basepack_test_app/features/step_definitions/window_steps.rb +27 -0
  128. data/test/basepack_test_app/features/tab_panel.feature +1 -1
  129. data/test/basepack_test_app/features/window.feature +17 -0
  130. data/test/unit/accordion_panel_test.rb +2 -2
  131. data/test/unit/grid_panel_test.rb +4 -4
  132. metadata +57 -83
  133. data/TODO.rdoc +0 -8
  134. data/lib/generators/netzke/basepack_generator.rb +0 -10
  135. data/lib/generators/netzke/templates/assets/ts-checkbox.gif +0 -0
  136. data/lib/generators/netzke/templates/create_netzke_field_lists.rb +0 -18
  137. data/lib/netzke/active_record.rb +0 -20
  138. data/lib/netzke/active_record/attributes.rb +0 -259
  139. data/lib/netzke/active_record/combobox_options.rb +0 -16
  140. data/lib/netzke/active_record/relation_extensions.rb +0 -37
  141. data/lib/netzke/basepack/accordion_panel.rb +0 -39
  142. data/lib/netzke/basepack/action_column.rb +0 -68
  143. data/lib/netzke/basepack/action_column/javascripts/action_column.js +0 -61
  144. data/lib/netzke/basepack/auth_app.rb +0 -159
  145. data/lib/netzke/basepack/basic_app.rb +0 -7
  146. data/lib/netzke/basepack/border_layout_panel.rb +0 -53
  147. data/lib/netzke/basepack/border_layout_panel/javascripts/border_layout_panel.js +0 -40
  148. data/lib/netzke/basepack/data_adapters/data_mapper_adapter.rb +0 -264
  149. data/lib/netzke/basepack/data_adapters/sequel_adapter.rb +0 -260
  150. data/lib/netzke/basepack/form_panel.rb +0 -144
  151. data/lib/netzke/basepack/form_panel/fields.rb +0 -208
  152. data/lib/netzke/basepack/form_panel/javascripts/misc.js +0 -4
  153. data/lib/netzke/basepack/form_panel/services.rb +0 -142
  154. data/lib/netzke/basepack/grid_panel.rb +0 -441
  155. data/lib/netzke/basepack/grid_panel/columns.rb +0 -400
  156. data/lib/netzke/basepack/grid_panel/javascripts/rows-dd.js +0 -281
  157. data/lib/netzke/basepack/grid_panel/record_form_window.rb +0 -41
  158. data/lib/netzke/basepack/grid_panel/services.rb +0 -235
  159. data/lib/netzke/basepack/panel.rb +0 -11
  160. data/lib/netzke/basepack/wrapper.rb +0 -28
  161. data/lib/netzke/data_mapper.rb +0 -18
  162. data/lib/netzke/data_mapper/attributes.rb +0 -273
  163. data/lib/netzke/data_mapper/combobox_options.rb +0 -11
  164. data/lib/netzke/data_mapper/relation_extensions.rb +0 -38
  165. data/lib/netzke/sequel.rb +0 -18
  166. data/lib/netzke/sequel/attributes.rb +0 -274
  167. data/lib/netzke/sequel/combobox_options.rb +0 -10
  168. data/lib/netzke/sequel/relation_extensions.rb +0 -40
  169. data/locales/zh-cn.yml +0 -79
  170. data/test/basepack_test_app/app/components/book_form_with_custom_fields.rb +0 -21
  171. data/test/basepack_test_app/app/components/book_grid_with_column_actions.rb +0 -15
  172. data/test/basepack_test_app/app/components/book_grid_with_defaults.rb +0 -6
  173. data/test/basepack_test_app/app/components/book_paging_form_panel.rb +0 -22
  174. data/test/basepack_test_app/app/components/generic_user_form.rb +0 -12
  175. data/test/basepack_test_app/app/components/simple_accordion.rb +0 -11
  176. data/test/basepack_test_app/app/components/simple_tab_panel.rb +0 -11
  177. data/test/basepack_test_app/app/components/simple_wrapper.rb +0 -7
  178. data/test/basepack_test_app/app/components/some_accordion_panel.rb +0 -22
  179. data/test/basepack_test_app/app/presenters/forms/generic_user.rb +0 -6
  180. data/test/basepack_test_app/app/views/components/loadable_window.html.erb +0 -9
  181. data/test/basepack_test_app/app/views/components/simple_panel.html.erb +0 -1
  182. data/test/basepack_test_app/features/components_in_view.feature +0 -11
  183. data/test/basepack_test_app/features/simple_panel.feature +0 -11
  184. data/test/basepack_test_app/features/validations_in_grid.feature +0 -13
  185. data/test/basepack_test_app/features/virtual_attributes.feature +0 -16
  186. data/test/basepack_test_app/spec/components/form_panel_spec.rb +0 -53
  187. data/test/basepack_test_app/spec/components/grid_panel_spec.rb +0 -10
  188. data/test/basepack_test_app/spec/data_adapter/adapter_spec.rb +0 -68
  189. data/test/basepack_test_app/spec/data_adapter/attributes_spec.rb +0 -56
  190. data/test/basepack_test_app/spec/data_adapter/relation_extensions_spec.rb +0 -125
  191. data/test/basepack_test_app/spec/factories.rb +0 -28
  192. data/test/basepack_test_app/spec/spec_helper.rb +0 -39
@@ -1,400 +0,0 @@
1
- module Netzke
2
- module Basepack
3
- class GridPanel < Netzke::Base
4
- module Columns
5
- extend ActiveSupport::Concern
6
- extend ActiveSupport::Memoizable
7
-
8
- # module ClassMethods
9
- # # Columns to be displayed by the FieldConfigurator, "meta-columns". Each corresponds to a configuration
10
- # # option for each column in the grid.
11
- # def meta_columns
12
- # [
13
- # # Whether the column will be present in the grid, also in :hidden or :meta state. The value for this column will
14
- # # always be sent to/from the JS grid to the server
15
- # {:name => "included", :attr_type => :boolean, :width => 40, :header => "Incl", :default_value => true},
16
- #
17
- # # The name of the column. May be any accessible method or attribute of the data_class.
18
- # {:name => "name", :attr_type => :string, :width => 200},
19
- #
20
- # # The header for the column.
21
- # {:name => "label", :attr_type => :string, :width => 200, :header => "Header"},
22
- #
23
- # # The default value of this column. Is used when a new row in the grid gets created.
24
- # {:name => "default_value", :attr_type => :string, :width => 200},
25
- #
26
- # # Options for drop-downs
27
- # {:name => "combobox_options", :attr_type => :string, :editor => :textarea, :width => 200},
28
- #
29
- # # Whether the column is editable in the grid.
30
- # {:name => "read_only", :attr_type => :boolean, :header => "R/O", :tooltip => "Read-only"},
31
- #
32
- # # Whether the column will be in the hidden state (hide/show columns from the column menu, if it's enabled).
33
- # {:name => "hidden", :attr_type => :boolean},
34
- #
35
- # # Whether the column should have "grid filters" enabled
36
- # # (see here: http://www.extjs.com/deploy/dev/examples/grid-filtering/grid-filter-local.html)
37
- # {:name => "with_filters", :attr_type => :boolean, :default_value => true, :header => "Filters"},
38
- #
39
- # #
40
- # # Below some rarely used parameters, hidden by default (you can always un-hide them from the column menu).
41
- # #
42
- #
43
- # # The column's width
44
- # {:name => "width", :attr_type => :integer, :hidden => true},
45
- #
46
- # # Whether the column should be hideable
47
- # {:name => "hideable", :attr_type => :boolean, :default_value => true, :hidden => true},
48
- #
49
- # # Whether the column should be sortable (why change it? normally it's hardcoded)
50
- # {:name => "sortable", :attr_type => :boolean, :default_value => true, :hidden => true},
51
- # ]
52
- # end
53
- #
54
- # end
55
-
56
- # Normalized columns for the grid, e.g.:
57
- # [{:name => :id, :hidden => true, ...}, {:name => :name, :editable => false, ...}, ...]
58
- # Possible options:
59
- # * +with_excluded+ - when set to true, also excluded columns will be returned (handy for dynamic column configuration)
60
- # * +with_meta+ - when set to true, the meta column will be included as the last column
61
- def columns(options = {})
62
- [].tap do |cols|
63
- if loaded_columns = load_columns
64
- filter_out_excluded_columns(loaded_columns) unless options[:with_excluded]
65
- cols.concat(reverse_merge_equally_named_columns(loaded_columns, initial_columns(options[:with_excluded])))
66
- else
67
- cols.concat(initial_columns(options[:with_excluded]))
68
- end
69
-
70
- append_meta_column(cols) if options[:with_meta]
71
- end
72
- end
73
-
74
- memoize :columns
75
-
76
- def append_meta_column(cols)
77
- cols << {}.tap do |c|
78
- c.merge!(
79
- :name => "meta",
80
- :meta => true,
81
- :getter => lambda do |r|
82
- meta_data(r)
83
- end
84
- )
85
- c[:default_value] = meta_default_data if meta_default_data.present?
86
- end
87
- end
88
-
89
- # default_value for the meta column; used when a new record is being created in the grid
90
- def meta_default_data
91
- get_default_association_values.present? ? { :association_values => get_default_association_values.literalize_keys } : {}
92
- end
93
-
94
- # Override it when you need extra meta data to be passed through the meta column
95
- def meta_data(r)
96
- { :association_values => get_association_values(r).literalize_keys }
97
- end
98
-
99
- # Columns as a hash, for easier access to a specific column
100
- def columns_hash
101
- @columns_hash ||= columns.inject({}){|r,c| r.merge(c[:name].to_sym => c)}
102
- end
103
-
104
- # Columns that we fall back to when neither persistent columns, nor configured columns are present.
105
- # If there's a model-level field configuration, it's being used.
106
- # Otherwise the defaults straight from the ActiveRecord model ("netzke_attributes").
107
- # Override this method if you want to provide a fix set of columns in your subclass.
108
- def default_columns
109
- @default_columns ||= load_model_level_attrs || data_class.netzke_attributes
110
- end
111
-
112
- def set_default_attr_type(c)
113
- c[:attr_type] ||= association_attr?(c) ? :integer : data_adapter.attr_type(c.name)
114
- end
115
-
116
- # Columns that were overridden with :override_columns config option.
117
- def overridden_default_columns
118
- if config[:override_columns].present?
119
- result = []
120
- default_columns.each do |col|
121
- result << col.merge(config[:override_columns][col[:name].to_sym] || {})
122
- end
123
- result
124
- else
125
- default_columns
126
- end
127
- end
128
-
129
- # Columns that represent a smart merge of default_columns and columns passed during the configuration.
130
- def initial_columns(with_excluded = false)
131
- # Normalize here, as from the config we can get symbols (names) instead of hashes
132
- columns_from_config = config[:columns] && normalize_attrs(config[:columns])
133
-
134
- if columns_from_config
135
- # automatically add a column that reflects the primary key (unless specified in the config)
136
- columns_from_config.insert(0, {:name => data_class.primary_key.to_s}) unless columns_from_config.any?{ |c| c[:name] == data_class.primary_key }
137
-
138
- # reverse-merge each column hash from config with each column hash from exposed_attributes
139
- # (columns from config have higher priority)
140
- for c in columns_from_config
141
- corresponding_default_column = overridden_default_columns.find{ |k| k[:name] == c[:name] }
142
- c.reverse_merge!(corresponding_default_column) if corresponding_default_column
143
- end
144
- columns_for_create = columns_from_config
145
- else
146
- # we didn't have columns configured in component's config, so, use the columns from the data class
147
- columns_for_create = overridden_default_columns
148
- end
149
-
150
- filter_out_excluded_columns(columns_for_create) unless with_excluded
151
-
152
- # Make the column config complete with the defaults.
153
- # Note: dup is needed to avoid modifying original hashes.
154
- columns_for_create.map { |c| c.dup.tap { |c| augment_column_config c } }
155
- end
156
-
157
- memoize :initial_columns
158
-
159
- private
160
-
161
- # Based on initial column config, e.g.:
162
- #
163
- # {:name=>"author__name", :attr_type=>:string}
164
- #
165
- # augment it with additional configuration params, e.g.:
166
- #
167
- # {:name=>"author__name", :attr_type=>:string, :editor=>{:xtype=>:netzkeremotecombo}, :assoc=>true, :virtual=>true, :header=>"Author name", :editable=>true, :sortable=>false, :filterable=>false}
168
- #
169
- # It may be handy to override it.
170
- def augment_column_config(c)
171
- # note: the order of these calls is important, as consequent calls may depend on the result of previous ones
172
- set_default_xtype(c)
173
- set_default_virtual(c)
174
- set_default_text(c)
175
- set_default_editable(c)
176
- set_default_editor(c)
177
- set_default_width(c)
178
- set_default_hidden(c)
179
- set_default_sortable(c)
180
- set_default_filterable(c)
181
- c[:assoc] = association_attr?(c)
182
- end
183
-
184
- def set_default_xtype(c)
185
- return if c[:renderer] || c[:editor] # if user set those manually, we don't mess with column xtype
186
- c[:xtype] ||= attr_type_to_xtype_map[c[:attr_type]]
187
- end
188
-
189
- def set_default_text(c)
190
- c[:text] ||= c[:label] || data_class.human_attribute_name(c[:name])
191
- end
192
-
193
- def set_default_editor(c)
194
- # if shouldn't be editable, don't set any default editor; also, specifying xtype takes care of the editor
195
- return if c[:read_only] || c[:editable] == false
196
-
197
- if association_attr?(c)
198
- set_default_association_editor(c)
199
- else
200
- c[:editor] ||= editor_for_attr_type(c[:attr_type])
201
- end
202
-
203
- end
204
-
205
- def set_default_width(c)
206
- c[:width] ||= 50 if c[:attr_type] == :boolean
207
- c[:width] ||= 150 if c[:attr_type] == :datetime
208
- end
209
-
210
- def set_default_hidden(c)
211
- c[:hidden] = true if primary_key_attr?(c) && c[:hidden].nil?
212
- end
213
-
214
- def set_default_editable(c)
215
- if c[:editable].nil?
216
- c[:editable] = is_editable_column?(c)
217
- end
218
- end
219
-
220
- def set_default_sortable(c)
221
- # this *has* to be set to false if we don't want the column to be sortable (it's sortable by default in Ext)
222
- c[:sortable] = !(c[:virtual] && !c[:sorting_scope]) if c[:sortable].nil?
223
- end
224
-
225
- def set_default_filterable(c)
226
- c[:filterable] = !c[:virtual] if c[:filterable].nil?
227
- end
228
-
229
-
230
- # Detects an association column and sets up the proper editor.
231
- def set_default_association_editor(c)
232
- assoc, assoc_method = c[:name].split('__')
233
- return unless assoc
234
-
235
- assoc_method_type = data_adapter.get_assoc_property_type assoc, assoc_method
236
-
237
- # if association column is boolean, display a checkbox (or alike), otherwise - a combobox (or alike)
238
- if c[:nested_attribute]
239
- c[:editor] ||= editor_for_attr_type(assoc_method_type)
240
- else
241
- c[:editor] ||= assoc_method_type == :boolean ? editor_for_attr_type(:boolean) : editor_for_association
242
- end
243
- end
244
-
245
- # If the column should be editable
246
- def is_editable_column?(c)
247
- not_editable_if = primary_key_attr?(c)
248
- not_editable_if ||= c[:virtual] && !association_attr?(c[:name])
249
- not_editable_if ||= c[:read_only]
250
-
251
- editable_if = data_class.column_names.include?(c[:name])
252
- editable_if ||= data_class.instance_methods.map(&:to_s).include?("#{c[:name]}=")
253
- editable_if ||= association_attr?(c[:name])
254
-
255
- editable_if && !not_editable_if
256
- end
257
-
258
- def initial_columns_order
259
- columns.map do |c|
260
- {
261
- :name => c[:name],
262
- :width => c[:width],
263
- :hidden => c[:hidden]
264
- }
265
- end
266
- end
267
-
268
- def columns_order
269
- if config[:persistence]
270
- update_state(:columns_order, initial_columns_order) if columns_have_changed?
271
- state[:columns_order] || initial_columns_order
272
- else
273
- initial_columns_order
274
- end
275
- end
276
-
277
- def columns_have_changed?
278
- init_column_names = initial_columns_order.map{ |c| c[:name].to_s }.sort
279
- stored_column_names = (state[:columns_order] || initial_columns_order).map{ |c| c[:name].to_s }.sort
280
- init_column_names != stored_column_names
281
- end
282
-
283
- def filter_out_excluded_columns(cols)
284
- cols.reject!{ |c| c[:included] == false }
285
- end
286
-
287
- # Stores modified columns in persistent storage
288
- def save_columns!
289
- # NetzkeFieldList.update_list_for_current_authority(global_id, columns(false), original_data_class.name) if persistent_config_enabled?
290
- end
291
-
292
- def load_columns
293
- # NetzkeFieldList.read_list(global_id) if persistent_config_enabled?
294
- end
295
-
296
- def load_model_level_attrs
297
- # NetzkeModelAttrList.read_list(data_class.name) if persistent_config_enabled?
298
- end
299
-
300
- # Column editor config for attribute type.
301
- def editor_for_attr_type(type)
302
- {:xtype => attr_type_to_editor_xtype_map[type] || :textfield}
303
- end
304
-
305
- # Column editor config for one-to-many association
306
- def editor_for_association
307
- {:xtype => :netzkeremotecombo}
308
- end
309
-
310
- # Hash that maps a column type to the editor xtype. Override if you want different editors.
311
- def attr_type_to_editor_xtype_map
312
- {
313
- :integer => :numberfield,
314
- :boolean => :checkbox,
315
- :date => :datefield,
316
- :datetime => :xdatetime,
317
- :text => :textarea,
318
- :string => :textfield
319
- }
320
- end
321
-
322
- def attr_type_to_xtype_map
323
- {
324
- # :integer => :numbercolumn, # don't like the default formatter
325
- :boolean => :checkcolumn,
326
- :date => :datecolumn,
327
- #:datetime => :datecolumn # TODO: replace with datetimepicker
328
- }
329
- end
330
-
331
- # Default fields that will be displayed in the Add/Edit/Search forms
332
- # When overriding this method, keep in mind that the fields inside the layout must be expanded (each field represented by a hash, not just a symbol)
333
- def default_fields_for_forms
334
- selected_columns = columns.select do |c|
335
- data_class.column_names.include?(c[:name]) ||
336
- data_class.instance_methods.include?("#{c[:name]}=") ||
337
- association_attr?(c[:name])
338
- end
339
-
340
- selected_columns.map do |c|
341
- field_config = {
342
- :name => c[:name],
343
- :field_label => c[:text] || c[:header],
344
- :read_only => c[:read_only],
345
- :editable => c[:editable]
346
- }
347
-
348
- # scopes for combobox options
349
- field_config[:scopes] = c[:editor][:scopes] if c[:editor].is_a?(Hash)
350
-
351
- field_config.merge!(c[:editor] || {})
352
-
353
- field_config
354
- end
355
- end
356
-
357
- # default_fields_for_forms extended with default values (for new-record form)
358
- # def default_fields_for_forms_with_default_values
359
- # res = default_fields_for_forms.dup
360
- # each_attr_in(res) do |a|
361
- # attr_name = a[:name].to_sym
362
- # a[:value] = a[:default_value] || columns_hash[attr_name].try(:fetch, :default_value, nil) || data_class.netzke_attribute_hash[attr_name].try(:fetch, :default_value, nil)
363
- # end
364
- # res
365
- # end
366
-
367
- def columns_default_values
368
- columns.inject({}) do |r,c|
369
- assoc_name, assoc_method = c[:name].split '__'
370
- if c[:default_value].nil?
371
- r
372
- else
373
- if assoc_method
374
- r.merge(data_adapter.foreign_key_for(assoc_name) || data_adapter.foreign_key_for(assoc_name) => c[:default_value])
375
- else
376
- r.merge(c[:name] => c[:default_value])
377
- end
378
- end
379
- end
380
- end
381
-
382
- # Recursively traversess items (an array) and yields each found field (a hash with :name set)
383
- def each_attr_in(items)
384
- items.each do |item|
385
- if item.is_a?(Hash)
386
- each_attr_in(item[:items]) if item[:items].is_a?(Array)
387
- yield(item) if item[:name]
388
- end
389
- end
390
- end
391
-
392
- # Receives 2 arrays of columns. Merges the missing config from the +source+ into +dest+, matching columns by name
393
- def reverse_merge_equally_named_columns(dest, source)
394
- dest.each{ |dc| dc.reverse_merge!(source.detect{ |sc| sc[:name] == dc[:name] } || {}) }
395
- end
396
-
397
- end
398
- end
399
- end
400
- end
@@ -1,281 +0,0 @@
1
- Ext.namespace('Ext.ux.dd');
2
-
3
- Ext.ux.dd.GridDragDropRowOrder = Ext.extend(Ext.util.Observable,
4
- {
5
- copy: false,
6
-
7
- scrollable: false,
8
-
9
- constructor : function(config)
10
- {
11
- Ext.ux.dd.GridDragDropRowOrder.superclass.constructor.call(this);
12
- if (config)
13
- Ext.apply(this, config);
14
-
15
- this.addEvents(
16
- {
17
- beforerowmove: true,
18
- afterrowmove: true,
19
- beforerowcopy: true,
20
- afterrowcopy: true
21
- });
22
- },
23
-
24
- init : function (grid)
25
- {
26
- this.grid = grid;
27
- grid.enableDragDrop = true;
28
-
29
- grid.on({
30
- render: { fn: this.onGridRender, scope: this, single: true }
31
- });
32
- },
33
-
34
- onGridRender : function (grid)
35
- {
36
- var self = this;
37
-
38
- this.target = new Ext.dd.DropTarget(grid.getEl(),
39
- {
40
- ddGroup: grid.ddGroup || 'GridDD',
41
- grid: grid,
42
- gridDropTarget: this,
43
-
44
- notifyDrop: function(dd, e, data)
45
- {
46
- // Remove drag lines. The 'if' condition prevents null error when drop occurs without dragging out of the selection area
47
- if (this.currentRowEl)
48
- {
49
- this.currentRowEl.removeClass('grid-row-insert-below');
50
- this.currentRowEl.removeClass('grid-row-insert-above');
51
- }
52
-
53
- // determine the row
54
- var t = Ext.lib.Event.getTarget(e);
55
- var rindex = this.grid.getView().findRowIndex(t);
56
- if (rindex === false || rindex == data.rowIndex)
57
- {
58
- return false;
59
- }
60
- // fire the before move/copy event
61
- if (this.gridDropTarget.fireEvent(self.copy ? 'beforerowcopy' : 'beforerowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections, 123) === false)
62
- {
63
- return false;
64
- }
65
-
66
- // update the store
67
- var ds = this.grid.getStore();
68
-
69
- // Changes for multiselction by Spirit
70
- var selections = new Array();
71
- var keys = ds.data.keys;
72
- for (var key in keys)
73
- {
74
- for (var i = 0; i < data.selections.length; i++)
75
- {
76
- if (keys[key] == data.selections[i].id)
77
- {
78
- // Exit to prevent drop of selected records on itself.
79
- if (rindex == key)
80
- {
81
- return false;
82
- }
83
- selections.push(data.selections[i]);
84
- }
85
- }
86
- }
87
-
88
- // fix rowindex based on before/after move
89
- if (rindex > data.rowIndex && this.rowPosition < 0)
90
- {
91
- rindex--;
92
- }
93
- if (rindex < data.rowIndex && this.rowPosition > 0)
94
- {
95
- rindex++;
96
- }
97
-
98
- // fix rowindex for multiselection
99
- if (rindex > data.rowIndex && data.selections.length > 1)
100
- {
101
- rindex = rindex - (data.selections.length - 1);
102
- }
103
-
104
- // we tried to move this node before the next sibling, we stay in place
105
- if (rindex == data.rowIndex)
106
- {
107
- return false;
108
- }
109
-
110
- // fire the before move/copy event
111
- /* dupe - does it belong here or above???
112
- if (this.gridDropTarget.fireEvent(self.copy ? 'beforerowcopy' : 'beforerowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections, 123) === false)
113
- {
114
- return false;
115
- }
116
- */
117
-
118
- if (!self.copy)
119
- {
120
- for (var i = 0; i < data.selections.length; i++)
121
- {
122
- ds.remove(ds.getById(data.selections[i].id));
123
- }
124
- }
125
-
126
- for (var i = selections.length - 1; i >= 0; i--)
127
- {
128
- var insertIndex = rindex;
129
- ds.insert(insertIndex, selections[i]);
130
- }
131
-
132
- // re-select the row(s)
133
- var sm = this.grid.getSelectionModel();
134
- if (sm)
135
- {
136
- sm.selectRecords(data.selections);
137
- }
138
-
139
- // console.info(this.gridDropTarget);
140
-
141
- // fire the after move/copy event
142
- this.gridDropTarget.fireEvent(self.copy ? 'afterrowcopy' : 'afterrowmove', this.gridDropTarget, data.rowIndex, rindex, data.selections);
143
- return true;
144
- },
145
-
146
- notifyOver: function(dd, e, data)
147
- {
148
- // WIP: todo - rewrite Ext.lib call to Ext 4
149
- var t = Ext.lib.Event.getTarget(e);
150
- var rindex = this.grid.getView().findRowIndex(t);
151
-
152
- // Similar to the code in notifyDrop. Filters for selected rows and quits function if any one row matches the current selected row.
153
- var ds = this.grid.getStore();
154
- var keys = ds.data.keys;
155
- for (var key in keys)
156
- {
157
- for (var i = 0; i < data.selections.length; i++)
158
- {
159
- if (keys[key] == data.selections[i].id)
160
- {
161
- if (rindex == key)
162
- {
163
- if (this.currentRowEl)
164
- {
165
- this.currentRowEl.removeClass('grid-row-insert-below');
166
- this.currentRowEl.removeClass('grid-row-insert-above');
167
- }
168
- return this.dropNotAllowed;
169
- }
170
- }
171
- }
172
- }
173
-
174
- // If on first row, remove upper line. Prevents negative index error as a result of rindex going negative.
175
- if (rindex < 0 || rindex === false)
176
- {
177
- this.currentRowEl.removeClass('grid-row-insert-above');
178
- return this.dropNotAllowed;
179
- }
180
-
181
- try
182
- {
183
- var currentRow = this.grid.getView().getRow(rindex);
184
- // Find position of row relative to page (adjusting for grid's scroll position)
185
- var resolvedRow = new Ext.Element(currentRow).getY() - this.grid.getView().scroller.dom.scrollTop;
186
- var rowHeight = currentRow.offsetHeight;
187
-
188
- // Cursor relative to a row. -ve value implies cursor is above the row's middle and +ve value implues cursor is below the row's middle.
189
- this.rowPosition = e.getPageY() - resolvedRow - (rowHeight/2);
190
-
191
- // Clear drag line.
192
- if (this.currentRowEl)
193
- {
194
- this.currentRowEl.removeClass('grid-row-insert-below');
195
- this.currentRowEl.removeClass('grid-row-insert-above');
196
- }
197
-
198
- if (this.rowPosition > 0)
199
- {
200
- // If the pointer is on the bottom half of the row.
201
- this.currentRowEl = new Ext.Element(currentRow);
202
- this.currentRowEl.addClass('grid-row-insert-below');
203
- }
204
- else
205
- {
206
- // If the pointer is on the top half of the row.
207
- if (rindex - 1 >= 0)
208
- {
209
- var previousRow = this.grid.getView().getRow(rindex - 1);
210
- this.currentRowEl = new Ext.Element(previousRow);
211
- this.currentRowEl.addClass('grid-row-insert-below');
212
- }
213
- else
214
- {
215
- // If the pointer is on the top half of the first row.
216
- this.currentRowEl.addClass('grid-row-insert-above');
217
- }
218
- }
219
- }
220
- catch (err)
221
- {
222
- console.warn(err);
223
- rindex = false;
224
- }
225
- return (rindex === false)? this.dropNotAllowed : this.dropAllowed;
226
- },
227
-
228
- notifyOut: function(dd, e, data)
229
- {
230
- // Remove drag lines when pointer leaves the gridView.
231
- if (this.currentRowEl)
232
- {
233
- this.currentRowEl.removeClass('grid-row-insert-above');
234
- this.currentRowEl.removeClass('grid-row-insert-below');
235
- }
236
- }
237
- });
238
-
239
- if (this.targetCfg)
240
- {
241
- Ext.apply(this.target, this.targetCfg);
242
- }
243
-
244
- if (this.scrollable)
245
- {
246
- Ext.dd.ScrollManager.register(grid.getView().getEditorParent());
247
- grid.on({
248
- beforedestroy: this.onBeforeDestroy,
249
- scope: this,
250
- single: true
251
- });
252
- }
253
- },
254
-
255
- getTarget: function()
256
- {
257
- return this.target;
258
- },
259
-
260
- getGrid: function()
261
- {
262
- return this.grid;
263
- },
264
-
265
- getCopy: function()
266
- {
267
- return this.copy ? true : false;
268
- },
269
-
270
- setCopy: function(b)
271
- {
272
- this.copy = b ? true : false;
273
- },
274
-
275
- onBeforeDestroy : function (grid)
276
- {
277
- // if we previously registered with the scroll manager, unregister
278
- // it (if we don't it will lead to problems in IE)
279
- Ext.dd.ScrollManager.unregister(grid.getView().getEditorParent());
280
- }
281
- });