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.
- data/CHANGELOG +1 -0
- data/LICENSE +20 -0
- data/Manifest +64 -0
- data/README.mdown +18 -0
- data/Rakefile +11 -0
- data/generators/netzke_basepack/USAGE +8 -0
- data/generators/netzke_basepack/netzke_basepack_generator.rb +8 -0
- data/generators/netzke_basepack/netzke_grid_generator.rb +7 -0
- data/generators/netzke_basepack/templates/create_netzke_grid_columns.rb +21 -0
- data/init.rb +2 -0
- data/install.rb +1 -0
- data/javascripts/basepack.js +41 -0
- data/lib/app/models/netzke_grid_column.rb +23 -0
- data/lib/netzke/accordion.rb +11 -0
- data/lib/netzke/ar_ext.rb +163 -0
- data/lib/netzke/column.rb +43 -0
- data/lib/netzke/container.rb +81 -0
- data/lib/netzke/grid.rb +132 -0
- data/lib/netzke/grid_interface.rb +132 -0
- data/lib/netzke/grid_js_builder.rb +249 -0
- data/lib/netzke/preference_grid.rb +43 -0
- data/lib/netzke/properties_tool.rb +66 -0
- data/lib/netzke/property_grid.rb +60 -0
- data/lib/netzke_basepack.rb +14 -0
- data/netzke_basepack.gemspec +38 -0
- data/tasks/netzke_basepack_tasks.rake +4 -0
- data/test/app_root/app/controllers/application.rb +2 -0
- data/test/app_root/app/models/book.rb +9 -0
- data/test/app_root/app/models/category.rb +2 -0
- data/test/app_root/app/models/city.rb +3 -0
- data/test/app_root/app/models/continent.rb +2 -0
- data/test/app_root/app/models/country.rb +3 -0
- data/test/app_root/app/models/genre.rb +3 -0
- data/test/app_root/config/boot.rb +114 -0
- data/test/app_root/config/database.yml +21 -0
- data/test/app_root/config/environment.rb +13 -0
- data/test/app_root/config/environments/in_memory.rb +0 -0
- data/test/app_root/config/environments/mysql.rb +0 -0
- data/test/app_root/config/environments/postgresql.rb +0 -0
- data/test/app_root/config/environments/sqlite.rb +0 -0
- data/test/app_root/config/environments/sqlite3.rb +0 -0
- data/test/app_root/config/routes.rb +4 -0
- data/test/app_root/db/migrate/20081222033343_create_books.rb +15 -0
- data/test/app_root/db/migrate/20081222033440_create_genres.rb +14 -0
- data/test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb +18 -0
- data/test/app_root/db/migrate/20081223024935_create_categories.rb +13 -0
- data/test/app_root/db/migrate/20081223025635_create_countries.rb +14 -0
- data/test/app_root/db/migrate/20081223025653_create_continents.rb +13 -0
- data/test/app_root/db/migrate/20081223025732_create_cities.rb +15 -0
- data/test/app_root/script/console +7 -0
- data/test/ar_ext_test.rb +39 -0
- data/test/column_test.rb +27 -0
- data/test/console_with_fixtures.rb +4 -0
- data/test/fixtures/books.yml +9 -0
- data/test/fixtures/categories.yml +7 -0
- data/test/fixtures/cities.yml +21 -0
- data/test/fixtures/continents.yml +7 -0
- data/test/fixtures/countries.yml +9 -0
- data/test/fixtures/genres.yml +9 -0
- data/test/grid_test.rb +43 -0
- data/test/netzke_basepack_test.rb +8 -0
- data/test/schema.rb +10 -0
- data/test/test_helper.rb +20 -0
- data/uninstall.rb +1 -0
- 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,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
    
    
    
        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,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
         |