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
|