skozlov-netzke_basepack 0.1.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 (65) hide show
  1. data/CHANGELOG +1 -0
  2. data/LICENSE +20 -0
  3. data/Manifest +64 -0
  4. data/README.mdown +18 -0
  5. data/Rakefile +11 -0
  6. data/generators/netzke_basepack/USAGE +8 -0
  7. data/generators/netzke_basepack/netzke_basepack_generator.rb +8 -0
  8. data/generators/netzke_basepack/netzke_grid_generator.rb +7 -0
  9. data/generators/netzke_basepack/templates/create_netzke_grid_columns.rb +21 -0
  10. data/init.rb +2 -0
  11. data/install.rb +1 -0
  12. data/javascripts/basepack.js +41 -0
  13. data/lib/app/models/netzke_grid_column.rb +23 -0
  14. data/lib/netzke/accordion.rb +11 -0
  15. data/lib/netzke/ar_ext.rb +163 -0
  16. data/lib/netzke/column.rb +43 -0
  17. data/lib/netzke/container.rb +81 -0
  18. data/lib/netzke/grid.rb +132 -0
  19. data/lib/netzke/grid_interface.rb +132 -0
  20. data/lib/netzke/grid_js_builder.rb +249 -0
  21. data/lib/netzke/preference_grid.rb +43 -0
  22. data/lib/netzke/properties_tool.rb +66 -0
  23. data/lib/netzke/property_grid.rb +60 -0
  24. data/lib/netzke_basepack.rb +14 -0
  25. data/netzke_basepack.gemspec +38 -0
  26. data/tasks/netzke_basepack_tasks.rake +4 -0
  27. data/test/app_root/app/controllers/application.rb +2 -0
  28. data/test/app_root/app/models/book.rb +9 -0
  29. data/test/app_root/app/models/category.rb +2 -0
  30. data/test/app_root/app/models/city.rb +3 -0
  31. data/test/app_root/app/models/continent.rb +2 -0
  32. data/test/app_root/app/models/country.rb +3 -0
  33. data/test/app_root/app/models/genre.rb +3 -0
  34. data/test/app_root/config/boot.rb +114 -0
  35. data/test/app_root/config/database.yml +21 -0
  36. data/test/app_root/config/environment.rb +13 -0
  37. data/test/app_root/config/environments/in_memory.rb +0 -0
  38. data/test/app_root/config/environments/mysql.rb +0 -0
  39. data/test/app_root/config/environments/postgresql.rb +0 -0
  40. data/test/app_root/config/environments/sqlite.rb +0 -0
  41. data/test/app_root/config/environments/sqlite3.rb +0 -0
  42. data/test/app_root/config/routes.rb +4 -0
  43. data/test/app_root/db/migrate/20081222033343_create_books.rb +15 -0
  44. data/test/app_root/db/migrate/20081222033440_create_genres.rb +14 -0
  45. data/test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb +18 -0
  46. data/test/app_root/db/migrate/20081223024935_create_categories.rb +13 -0
  47. data/test/app_root/db/migrate/20081223025635_create_countries.rb +14 -0
  48. data/test/app_root/db/migrate/20081223025653_create_continents.rb +13 -0
  49. data/test/app_root/db/migrate/20081223025732_create_cities.rb +15 -0
  50. data/test/app_root/script/console +7 -0
  51. data/test/ar_ext_test.rb +39 -0
  52. data/test/column_test.rb +27 -0
  53. data/test/console_with_fixtures.rb +4 -0
  54. data/test/fixtures/books.yml +9 -0
  55. data/test/fixtures/categories.yml +7 -0
  56. data/test/fixtures/cities.yml +21 -0
  57. data/test/fixtures/continents.yml +7 -0
  58. data/test/fixtures/countries.yml +9 -0
  59. data/test/fixtures/genres.yml +9 -0
  60. data/test/grid_test.rb +43 -0
  61. data/test/netzke_basepack_test.rb +8 -0
  62. data/test/schema.rb +10 -0
  63. data/test/test_helper.rb +20 -0
  64. data/uninstall.rb +1 -0
  65. metadata +159 -0
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ v0.1.0 Initial release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Sergei Kozlov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,64 @@
1
+ CHANGELOG
2
+ generators/netzke_basepack/netzke_basepack_generator.rb
3
+ generators/netzke_basepack/netzke_grid_generator.rb
4
+ generators/netzke_basepack/templates/create_netzke_grid_columns.rb
5
+ generators/netzke_basepack/USAGE
6
+ init.rb
7
+ install.rb
8
+ javascripts/basepack.js
9
+ lib/app/models/netzke_grid_column.rb
10
+ lib/netzke/accordion.rb
11
+ lib/netzke/ar_ext.rb
12
+ lib/netzke/column.rb
13
+ lib/netzke/container.rb
14
+ lib/netzke/grid.rb
15
+ lib/netzke/grid_interface.rb
16
+ lib/netzke/grid_js_builder.rb
17
+ lib/netzke/preference_grid.rb
18
+ lib/netzke/properties_tool.rb
19
+ lib/netzke/property_grid.rb
20
+ lib/netzke_basepack.rb
21
+ LICENSE
22
+ Manifest
23
+ netzke_basepack.gemspec
24
+ Rakefile
25
+ README.mdown
26
+ tasks/netzke_basepack_tasks.rake
27
+ test/app_root/app/controllers/application.rb
28
+ test/app_root/app/models/book.rb
29
+ test/app_root/app/models/category.rb
30
+ test/app_root/app/models/city.rb
31
+ test/app_root/app/models/continent.rb
32
+ test/app_root/app/models/country.rb
33
+ test/app_root/app/models/genre.rb
34
+ test/app_root/config/boot.rb
35
+ test/app_root/config/database.yml
36
+ test/app_root/config/environment.rb
37
+ test/app_root/config/environments/in_memory.rb
38
+ test/app_root/config/environments/mysql.rb
39
+ test/app_root/config/environments/postgresql.rb
40
+ test/app_root/config/environments/sqlite.rb
41
+ test/app_root/config/environments/sqlite3.rb
42
+ test/app_root/config/routes.rb
43
+ test/app_root/db/migrate/20081222033343_create_books.rb
44
+ test/app_root/db/migrate/20081222033440_create_genres.rb
45
+ test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb
46
+ test/app_root/db/migrate/20081223024935_create_categories.rb
47
+ test/app_root/db/migrate/20081223025635_create_countries.rb
48
+ test/app_root/db/migrate/20081223025653_create_continents.rb
49
+ test/app_root/db/migrate/20081223025732_create_cities.rb
50
+ test/app_root/script/console
51
+ test/ar_ext_test.rb
52
+ test/column_test.rb
53
+ test/console_with_fixtures.rb
54
+ test/fixtures/books.yml
55
+ test/fixtures/categories.yml
56
+ test/fixtures/cities.yml
57
+ test/fixtures/continents.yml
58
+ test/fixtures/countries.yml
59
+ test/fixtures/genres.yml
60
+ test/grid_test.rb
61
+ test/netzke_basepack_test.rb
62
+ test/schema.rb
63
+ test/test_helper.rb
64
+ uninstall.rb
data/README.mdown ADDED
@@ -0,0 +1,18 @@
1
+ NetzkeBasepack
2
+ ==============
3
+
4
+ Introduction goes here.
5
+
6
+
7
+ Example
8
+ =======
9
+
10
+ Example goes here.
11
+
12
+
13
+ Credentials
14
+ ===========
15
+
16
+ Testing with the help of http://github.com/pluginaweek/plugin_test_helper
17
+
18
+ Copyright (c) 2008 Sergei Kozlov, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'echoe'
2
+
3
+ Echoe.new("netzke_basepack") do |p|
4
+ p.author = "Sergei Kozlov"
5
+ p.email = "sergei@writelesscode.com"
6
+ p.summary = "Base Netzke widgets - grid, form, tree, and more"
7
+ p.url = "http://writelesscode.com"
8
+ p.runtime_dependencies = ["searchlogic >=1.6.2", "netzke_core >= 0.1.0"]
9
+ p.development_dependencies = []
10
+ p.test_pattern = 'test/**/*_test.rb'
11
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ ./script/generate netzke_basepack Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,8 @@
1
+ class NetzkeBasepackGenerator < Rails::Generator::NamedBase
2
+ def manifest
3
+ record do |m|
4
+ # m.directory "lib"
5
+ # m.template 'README', "README"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ class NetzkeGridGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'create_netzke_grid_columns.rb', "db/migrate", {:migration_file_name => "create_netzke_grid_columns"}
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ class CreateNetzkeGridColumns < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :netzke_grid_columns do |t|
4
+ t.string :name
5
+ t.string :label
6
+ t.boolean :read_only
7
+ t.integer :position
8
+ t.boolean :hidden
9
+ t.integer :width
10
+ t.string :shows_as, :limit => 32
11
+
12
+ t.integer :layout_id
13
+
14
+ t.timestamps
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ drop_table :netzke_grid_columns
20
+ end
21
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Include hook code here
2
+ require 'netzke_basepack'
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,41 @@
1
+ // Editors for grid cells and form fields
2
+ Ext.netzke.editors = {
3
+ combo_box: function(c, config){
4
+ var row = Ext.data.Record.create([{name:'id'}])
5
+ var store = new Ext.data.Store({
6
+ proxy: new Ext.data.HttpProxy({url:config.interface.getCbChoices, jsonData:{column:c.name}}),
7
+ reader: new Ext.data.ArrayReader({root:'data', id:0}, row)
8
+ })
9
+ return new Ext.form.ComboBox({
10
+ mode: 'remote',
11
+ displayField:'id',
12
+ valueField:'id',
13
+ triggerAction:'all',
14
+ store: store
15
+ })
16
+ },
17
+
18
+ text_field: function(c, config){
19
+ return new Ext.form.TextField({
20
+ selectOnFocus:true
21
+ })
22
+ },
23
+
24
+ checkbox: function(c, config){
25
+ return new Ext.form.TextField({
26
+ selectOnFocus:true
27
+ })
28
+ },
29
+
30
+ number_field: function(c, config){
31
+ return new Ext.form.NumberField({
32
+ selectOnFocus:true
33
+ })
34
+ },
35
+
36
+ datetime: function(c, config){
37
+ return new Ext.form.TextField({
38
+ selectOnFocus:true
39
+ })
40
+ }
41
+ }
@@ -0,0 +1,23 @@
1
+ class NetzkeGridColumn < ActiveRecord::Base
2
+ belongs_to :layout, :class_name => "NetzkeLayout"
3
+
4
+ acts_as_list :scope => :layout
5
+
6
+ # old?
7
+ # def self.create_with_defaults(column_config, klass)
8
+ # create(klass.default_column_config(column_config).stringify_values!)
9
+ # end
10
+
11
+ def self.create_layout_for_widget(widget)
12
+ layout = NetzkeLayout.create(:widget_name => widget.id_name, :items_class => self.name, :user_id => NetzkeLayout.user_id)
13
+
14
+ columns = Netzke::Column.default_columns_for_widget(widget)
15
+
16
+ for c in columns
17
+ config_for_create = c.merge(:layout_id => layout.id).stringify_values!
18
+ create(config_for_create)
19
+ end
20
+
21
+ layout
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module Netzke
2
+ class Accordion < Container
3
+
4
+ def js_default_config
5
+ super.merge({
6
+ :layout => 'accordion'
7
+ })
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,163 @@
1
+ module Netzke
2
+ module ActiveRecordExtensions
3
+ def self.included(base)
4
+ base.extend ActiveRecordClassMethods
5
+ end
6
+
7
+ #
8
+ # Allow nested association acces (assocs separated by "." or "__"), e.g.: proxy_service.send('asset__gui_folder__name')
9
+ # Example:
10
+ # b = Book.first
11
+ # b.genre__name = 'Fantasy' => b.genre = Genre.find_by_name('Fantasy')
12
+ # NOT IMPLEMENTED: ANY USE? b.genre__catalog__name = 'Best sellers' => b.genre_id = b.genre.find_by_catalog_id(Catalog.find_by_name('Best sellers')).id
13
+ #
14
+
15
+ def method_missing(method, *args, &block)
16
+ # if refering to a column, just pass it to the originar method_missing
17
+ return super if self.class.column_names.include?(method.to_s)
18
+
19
+ split = method.to_s.split(/\.|__/)
20
+ if split.size > 1
21
+ if split.last =~ /=$/
22
+ if split.size == 2
23
+ # search for association and assign it to self
24
+ assoc = self.class.reflect_on_association(split.first.to_sym)
25
+ assoc_method = split.last.chop
26
+ if assoc
27
+ assoc_instance = assoc.klass.send("find_by_#{assoc_method}", *args)
28
+ raise ArgumentError, "Couldn't find association #{split.first} by #{assoc_method} '#{args.first}'" unless assoc_instance
29
+ self.send("#{split.first}=", assoc_instance)
30
+ else
31
+ super
32
+ end
33
+ else
34
+ super
35
+ end
36
+ else
37
+ res = self
38
+ split.each do |m|
39
+ if res.respond_to?(m)
40
+ res = res.send(m) unless res.nil?
41
+ else
42
+ res.nil? ? nil : super
43
+ end
44
+ end
45
+ res
46
+ end
47
+ else
48
+ super
49
+ end
50
+ end
51
+
52
+
53
+ module ActiveRecordClassMethods
54
+ def choices_for(column, query = nil)
55
+ if respond_to?("#{column}_choices", query)
56
+ # AR class provides the choices itself
57
+ send("#{column}_choices")
58
+ else
59
+ if (assoc_name, *assoc_method = column.split('__')).size > 1
60
+ # column is an association column
61
+ assoc_method = assoc_method.join('__') # in case we get something like country__continent__name
62
+ association = reflect_on_association(assoc_name.to_sym) || raise(NameError, "Association #{assoc_name} not known for class #{name}")
63
+ association.klass.choices_for(assoc_method, query)
64
+ else
65
+ column = assoc_name
66
+ if self.column_names.include?(column)
67
+ # it's just a column
68
+ records = query.nil? ? find_by_sql("select distinct #{column} from #{table_name}") : find_by_sql("select distinct #{column} from #{table_name} where #{column} like '#{query}%'")
69
+ records.map{|r| r.send(column)}
70
+ else
71
+ # it's a "virtual" column - the least effective search
72
+ records = self.find(:all).map{|r| r.send(column)}.uniq
73
+ query.nil? ? records : records.select{|r| r.send(column).index(/^#{query}/)}
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ # which columns are to be picked up by grids and forms
80
+ def expose_columns(columns, *args)
81
+ if columns == :all
82
+ write_inheritable_attribute(:exposed_columns, self.column_names.map(&:to_sym))
83
+ else
84
+ write_inheritable_attribute(:exposed_columns, columns)
85
+ end
86
+ end
87
+
88
+ def exposed_columns
89
+ read_inheritable_attribute(:exposed_columns) || write_inheritable_attribute(:exposed_columns, expose_columns(:all) + virtual_columns)
90
+ end
91
+
92
+ # virtual "columns" that simply correspond to instance methods of an ActiveRecord class
93
+ def virtual_column(config)
94
+ if config.is_a?(Symbol)
95
+ config = {:name => config}
96
+ else
97
+ config = {:name => config.keys.first}.merge(config.values.first)
98
+ end
99
+ write_inheritable_attribute(:virtual_columns, (read_inheritable_attribute(:virtual_columns) || []) << config)
100
+ end
101
+
102
+ def virtual_columns
103
+ read_inheritable_attribute(:virtual_columns) || []
104
+ end
105
+
106
+ def is_virtual_column?(column)
107
+ read_inheritable_attribute(:virtual_columns).keys.include?(column)
108
+ end
109
+
110
+ #
111
+ # Used by Netzke::Grid
112
+ #
113
+
114
+ DEFAULT_COLUMN_WIDTH = 100
115
+
116
+ def default_column_config(config)
117
+ config = {:name => config} if config.is_a?(Symbol) # optionally we may get only a column name (as Symbol)
118
+ type = (columns_hash[config[:name].to_s] && columns_hash[config[:name].to_s].type) || :virtual
119
+
120
+ # general config
121
+ res = {
122
+ :name => config[:name].to_s || "unnamed",
123
+ :label => config[:label] || config[:name].to_s.humanize,
124
+ :read_only => config[:name] == :id, # make "id" column read-only by default
125
+ :hidden => config[:name] == :id, # hide "id" column by default
126
+ :width => DEFAULT_COLUMN_WIDTH,
127
+ :shows_as => :text_field
128
+ }
129
+
130
+ case type
131
+ when :integer
132
+ res[:shows_as] = :number_field
133
+ when :boolean
134
+ res[:shows_as] = :checkbox
135
+ res[:width] = 50
136
+ when :date
137
+ res[:shows_as] = :date_field
138
+ when :datetime
139
+ res[:shows_as] = :datetime
140
+ when :string
141
+ res[:shows_as] = :text_field
142
+ end
143
+
144
+ res.merge(config) # merge with custom confg (it has the priority)
145
+ end
146
+
147
+ #
148
+ # Used by Netzke::Form
149
+ #
150
+
151
+ DEFAULT_FIELD_WIDTH = 100
152
+ DEFAULT_FIELD_HEIGHT = 50
153
+ def default_field_config(config)
154
+ # TODO
155
+ end
156
+
157
+ end
158
+ end
159
+ end
160
+
161
+ ActiveRecord::Base.class_eval do
162
+ include Netzke::ActiveRecordExtensions
163
+ end
@@ -0,0 +1,43 @@
1
+ module Netzke
2
+ class Column
3
+ def self.default_columns_for_widget(widget)
4
+ raise ArgumentError, "No data_class_name specified for widget #{widget.config[:name]}" if widget.config[:data_class_name].nil?
5
+
6
+ # layout = NetzkeLayout.create(:widget_name => widget.id_name, :items_class => self.name, :user_id => NetzkeLayout.user_id)
7
+
8
+ data_class = widget.config[:data_class_name].constantize
9
+
10
+ exposed_columns = normalize_columns(data_class.exposed_columns) # columns exposed from the data class
11
+
12
+ columns_from_config = widget.config[:columns] && normalize_columns(widget.config[:columns]) # columns specified in widget's config
13
+
14
+ if columns_from_config
15
+ # reverse-merge each column hash from config with each column hash from exposed_columns (columns from config have higher priority)
16
+ for c in columns_from_config
17
+ corresponding_exposed_column = exposed_columns.find{ |k| k[:name] == c[:name] }
18
+ c.reverse_merge!(corresponding_exposed_column) if corresponding_exposed_column
19
+ end
20
+ columns_for_create = columns_from_config
21
+ else
22
+ # we didn't have columns configured in widget's config, so, use the columns from the data class
23
+ columns_for_create = exposed_columns
24
+ end
25
+
26
+ res = []
27
+ for c in columns_for_create
28
+ # finally reverse-merge them with the defaults from the data_class
29
+ res << data_class.default_column_config(c)
30
+ end
31
+
32
+ res
33
+ end
34
+
35
+ protected
36
+
37
+ # like this: [:col1, {:name => :col2}, :col3] => [{:name => :col1}, {:name => :col2}, {:name => :col3}]
38
+ def self.normalize_columns(items)
39
+ items.map{|c| c.is_a?(Symbol) ? {:name => c} : c}
40
+ end
41
+
42
+ end
43
+ end