usefull_table 1.0.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.md +12 -0
- data/Gemfile +27 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +234 -0
- data/Rakefile +31 -0
- data/app/controllers/usefull_table/table_controller.rb +34 -0
- data/app/helpers/usefull_table_helper.rb +323 -0
- data/app/views/usefull_table/table/create.xlsx.maker +17 -0
- data/config/routes.rb +8 -0
- data/lib/generators/usefull_table/install/install_generator.rb +47 -0
- data/lib/generators/usefull_table/install/templates/config/locales/usefull_table.it.yml +42 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_destroy.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_download.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_edit.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_false.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_show.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_true.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/stylesheets/usefull_table.css +101 -0
- data/lib/generators/usefull_table/scaffold/scaffold_generator.rb +12 -0
- data/lib/generators/usefull_table/scaffold/templates/lib/templates/erb/scaffold/index.html.erb +15 -0
- data/lib/generators/usefull_table/scaffold/templates/lib/templates/erb/scaffold/show.html.erb +12 -0
- data/lib/generators/usefull_table/scaffold/templates/lib/templates/rails/scaffold_controller/controller.rb +84 -0
- data/lib/usefull_table/engine.rb +17 -0
- data/lib/usefull_table/exceptions.rb +17 -0
- data/lib/usefull_table/table_builder.rb +522 -0
- data/lib/usefull_table/version.rb +3 -0
- data/lib/usefull_table.rb +13 -0
- metadata +123 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
ToDo
|
2
|
+
- Autodetection in table data of: boolean and 'true' and 'false'. To render with red and green traffic-light image.
|
3
|
+
- Add tip to cell
|
4
|
+
- Add option :excel => false to column to remove from excel export
|
5
|
+
- Add option [:export][:type] => :xls, :xlsx, :pdf, :all, [:xls, :xlsx]
|
6
|
+
|
7
|
+
BugToFix
|
8
|
+
1.0.1 (June 29, 2012)
|
9
|
+
- First working release
|
10
|
+
|
11
|
+
0.1.0 (June 18, 2012)
|
12
|
+
- first Release
|
data/Gemfile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
#remove in production
|
4
|
+
#gem "acts_as_xls", :path => "/home/apps/rails_apps/gems/acts_as_xls"
|
5
|
+
#gem "acts_as_monitor", :path => "/home/apps/rails_apps/gems/acts_as_monitor"
|
6
|
+
gem "rails", "3.0.9"
|
7
|
+
#gem "in_place_editing"
|
8
|
+
|
9
|
+
group :development do
|
10
|
+
gem "acts_as_monitor", :path => "/home/apps/rails_apps/gems/acts_as_monitor"
|
11
|
+
gem "acts_as_xls", :path => "/home/apps/rails_apps/gems/acts_as_xls"
|
12
|
+
gem "meta_search"
|
13
|
+
gem "will_paginate"
|
14
|
+
gem "ruby-debug"
|
15
|
+
end
|
16
|
+
|
17
|
+
group :test do
|
18
|
+
gem "acts_as_monitor", :path => "/home/apps/rails_apps/gems/acts_as_monitor"
|
19
|
+
gem "acts_as_xls", :path => "/home/apps/rails_apps/gems/acts_as_xls"
|
20
|
+
gem "capybara", ">= 0.4.0"
|
21
|
+
gem "meta_search"
|
22
|
+
gem "will_paginate"
|
23
|
+
gem "ruby-debug"
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
gemspec
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
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/README.rdoc
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
=UsefullTable
|
2
|
+
table_for generate a full-optionals table, with excel export, columns ordering, links, inline edit and monitoring (ActsAsMonitor https://github.com/skylord73/acts_as_monitor)
|
3
|
+
but don't warry because a rich set of defaults, make its use very simple
|
4
|
+
|
5
|
+
for a working sample please refer to test/dummy
|
6
|
+
|
7
|
+
==Setup
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
gem 'usefull_table'
|
10
|
+
|
11
|
+
then execute
|
12
|
+
$ bundle install
|
13
|
+
|
14
|
+
or install it yourself as:
|
15
|
+
$ sudo gem install usefull_table
|
16
|
+
|
17
|
+
copy icons, javascript and stylesheets:
|
18
|
+
$ rails g usefull_table:install
|
19
|
+
|
20
|
+
modify default scaffold to use usefull_table, meta_search and will_paginate (controller and index.html.erb):
|
21
|
+
$ rails g usefull_table:scaffold
|
22
|
+
|
23
|
+
|
24
|
+
==Usage
|
25
|
+
Write few lines in your controller
|
26
|
+
app/controllers/home_controller.rb
|
27
|
+
def index
|
28
|
+
@search = Item.search(params[:search])
|
29
|
+
...
|
30
|
+
respond_to do |format|
|
31
|
+
format.html { @items = @search.paginate(:page => params[:page]) }
|
32
|
+
end
|
33
|
+
...
|
34
|
+
end
|
35
|
+
|
36
|
+
and in your view
|
37
|
+
app/views/home/my_view.html.erb
|
38
|
+
<%= table_for @items, @search, options = {} do |t| %>
|
39
|
+
<% t.show :url => Proc.new { |item| item_path(item)} %>
|
40
|
+
<% t.edit :url => Proc.new { |item| edit_item_path(item)}%>
|
41
|
+
<% t.destroy :url => Proc.new { |item| item_path(item)}, :link_options => {:method => delete, :confirm => "are you sure?"} %>
|
42
|
+
<% t.download :url => Proc.new { |item| download_item_path(item)} %>
|
43
|
+
<% t.col :name %>
|
44
|
+
<% t.col "user.name" %>
|
45
|
+
<% t.status %>
|
46
|
+
<% end %>
|
47
|
+
|
48
|
+
==Options
|
49
|
+
default values in *bold*
|
50
|
+
|
51
|
+
===Paginator
|
52
|
+
options[:paginator][:visible] = *true* | false _note_: false if @items not present
|
53
|
+
options[:paginator][:class] = *"usefull_table_paginator"*
|
54
|
+
|
55
|
+
===Container
|
56
|
+
options[:html] = *{:class => "usefull_table_container"}*
|
57
|
+
|
58
|
+
===Excel
|
59
|
+
options[:export][:visible] = *true* | false
|
60
|
+
options[:export][:filter] = *true* | false _note:_ false if @search not present
|
61
|
+
options[:export][:human] = *true* | false
|
62
|
+
options[:export][:worksheet] = *object.class.name.gsub(/::/,"#")* _note:_ class name with namespace separator #
|
63
|
+
options[:export][:url] = Custom Url and format
|
64
|
+
|
65
|
+
===Table
|
66
|
+
options[:table][:div_html] = *{:class => "usefull_table"}*
|
67
|
+
options[:table][:header_html] = *{:class => "first_row"}*
|
68
|
+
options[:table][:header_type] = *:sort* _note:_ :human if @search not present (no sorting possible)
|
69
|
+
:plain bare column name from ActiveRecord
|
70
|
+
:human column name humanized by ActiveRecord
|
71
|
+
:nil no column name
|
72
|
+
|
73
|
+
==Localization
|
74
|
+
Uses standard ActiveRecord localization to render tables and columns names
|
75
|
+
it:
|
76
|
+
activerecord:
|
77
|
+
attributes:
|
78
|
+
item:
|
79
|
+
name: Name
|
80
|
+
type: Type
|
81
|
+
user:
|
82
|
+
name: Name
|
83
|
+
models:
|
84
|
+
item:
|
85
|
+
one: Item
|
86
|
+
other: Items
|
87
|
+
user:
|
88
|
+
one: User
|
89
|
+
other: Users
|
90
|
+
|
91
|
+
#config/usefull_table.it.yml
|
92
|
+
it:
|
93
|
+
usefull_table:
|
94
|
+
submit_excel: Excel
|
95
|
+
header_error: Errore
|
96
|
+
body_error: Errore
|
97
|
+
|
98
|
+
icons:
|
99
|
+
show: "usefull_table_show.png"
|
100
|
+
edit: "usefull_table_edit.png"
|
101
|
+
destroy: "usefull_table_destroy.png"
|
102
|
+
download: "usefull_table_download.png"
|
103
|
+
|
104
|
+
=Column Types
|
105
|
+
==col
|
106
|
+
Render column value
|
107
|
+
|
108
|
+
===Usage
|
109
|
+
<% t.col :name %> #render column :name ( t.col "name" is ok)
|
110
|
+
<% t.col "user.name" %> #render column name of the user collection in item (item.user.name)
|
111
|
+
|
112
|
+
===Options
|
113
|
+
|
114
|
+
:header_type =>
|
115
|
+
- *:sort* #Header is MetaSearch#sort_link of columns_name
|
116
|
+
- :human #Header is plain text humanized with ActiveRecord column name
|
117
|
+
- :nil #No header
|
118
|
+
|
119
|
+
:label =>
|
120
|
+
- "Custom Name" #plain text without localization
|
121
|
+
- :custom_name #localized text in lazy context (.)
|
122
|
+
|
123
|
+
:data_type => #default get class name from object to render
|
124
|
+
- :Date
|
125
|
+
- :Time
|
126
|
+
- :DateTime
|
127
|
+
- :Currency
|
128
|
+
- :Bool #Transform value in boolean
|
129
|
+
- :Bool_reverse #Transform vale in boolean and reverse the vale
|
130
|
+
|
131
|
+
:url =>
|
132
|
+
- "static_path"
|
133
|
+
- Proc #Proc expose the object instance of the current row
|
134
|
+
|
135
|
+
:inline =>
|
136
|
+
- *false*
|
137
|
+
- true #enable inline editing for the column, works also with nested fields (no controller add-on required)
|
138
|
+
|
139
|
+
==label
|
140
|
+
Render static label
|
141
|
+
|
142
|
+
===Usage
|
143
|
+
<% t.label object %> #render object.inspect
|
144
|
+
<% t.label Proc.new {|item| item.name.capitalize} %> #Evaluate proc with item instance of the corresponding row
|
145
|
+
|
146
|
+
==monitor
|
147
|
+
Render a tri-state icon to monitor model status
|
148
|
+
* Red : Error
|
149
|
+
* Yellow: Warning
|
150
|
+
* Green: Status ok
|
151
|
+
|
152
|
+
Enable only if acts_as_monitor gem is required (https://github.com/skylord73/acts_as_monitor)
|
153
|
+
|
154
|
+
==Usage
|
155
|
+
<% t.monitor %>
|
156
|
+
|
157
|
+
Clicking the icon you get the comlete problem description pushed by Ajaxs script (no page reload)
|
158
|
+
|
159
|
+
==link
|
160
|
+
Create a link to something, using Icons or CustomText
|
161
|
+
|
162
|
+
===Usage
|
163
|
+
<% t.show :url => Proc.new {|object| home_path(object) }"%>
|
164
|
+
<% t.destroy :url => Proc.new {|object| home_path(object) }"%>
|
165
|
+
<% t.link :name => "Custom Link", :url => Proc.new {|object| my_link_home_path(object) }"%> #text link (Custom Link) to url
|
166
|
+
<% t.link :name => "Custom Link", :body_typ => :icon, :url => Proc.new {|object| my_link_home_path(object) }"%> #icon link with icon name = usefull_table_cusom_link.png or localization in usefull_table.icons.custom_link
|
167
|
+
|
168
|
+
===Options
|
169
|
+
|
170
|
+
:url =>
|
171
|
+
- Proc
|
172
|
+
- "my_custom_static_url"
|
173
|
+
|
174
|
+
:label =>
|
175
|
+
- :show_doc #localized in lazy contest (.)
|
176
|
+
- "Show Doc" #printed without localization
|
177
|
+
|
178
|
+
:link_options =>
|
179
|
+
- *nil*
|
180
|
+
- {:method => delete, :confirm => "sicuro?"} if name == :destroy
|
181
|
+
|
182
|
+
:name =>
|
183
|
+
- :symbol
|
184
|
+
- "string" #if method_name == :link the name is used as link_text (localized if symbol), ignored elsewhere
|
185
|
+
|
186
|
+
==bool
|
187
|
+
Create a boolean value using images to represent status.
|
188
|
+
Images name can be changed in locales
|
189
|
+
|
190
|
+
===Usage
|
191
|
+
<% t.bool :name %>
|
192
|
+
<% t.bool :name, :reverse => true%>
|
193
|
+
|
194
|
+
===Options
|
195
|
+
:header_type =>
|
196
|
+
- *:sort* #Header is MetaSearch#sort_link of columns_name
|
197
|
+
- :human #Header is plain text humanized with ActiveRecord column name
|
198
|
+
- :nil #No header
|
199
|
+
|
200
|
+
:label =>
|
201
|
+
- "Custom Name" #plain text without localization in header
|
202
|
+
- :custom_name #localized text in lazy context (.) in header
|
203
|
+
|
204
|
+
:url =>
|
205
|
+
- "my_custom_static_url"
|
206
|
+
- Proc #Proc expose the object instance of the current row
|
207
|
+
|
208
|
+
:reverse =>
|
209
|
+
- *false*
|
210
|
+
- true #reverse boolean value
|
211
|
+
|
212
|
+
==Personalization
|
213
|
+
|
214
|
+
Feel free to modify the following files:
|
215
|
+
|
216
|
+
- public/stylesheets/usefull_table.css
|
217
|
+
- config/locales/usefull_table.it.yml
|
218
|
+
|
219
|
+
==Contributing
|
220
|
+
|
221
|
+
1. Fork it
|
222
|
+
2. Create your feature branch (git checkout -b my-new-feature)
|
223
|
+
3. Commit your changes (git commit -am 'Added some feature')
|
224
|
+
4. Push to the branch (git push origin my-new-feature)
|
225
|
+
5. Create new Pull Request
|
226
|
+
|
227
|
+
==Thanks
|
228
|
+
|
229
|
+
Many thanks to :
|
230
|
+
- MetaSearch
|
231
|
+
- WillPaginate
|
232
|
+
- Spreadsheet
|
233
|
+
- Axlsx
|
234
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
require "bundler/gem_tasks"
|
6
|
+
rescue LoadError
|
7
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake'
|
11
|
+
require 'rake/testtask'
|
12
|
+
require 'rdoc/task'
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
Rake::TestTask.new(:test) do |t|
|
17
|
+
t.libs << 'lib'
|
18
|
+
t.libs << 'test'
|
19
|
+
t.pattern = 'test/**/*_test.rb'
|
20
|
+
t.verbose = false
|
21
|
+
end
|
22
|
+
|
23
|
+
task :default => :test
|
24
|
+
|
25
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
26
|
+
rdoc.rdoc_dir = 'rdoc'
|
27
|
+
rdoc.title = 'UsefullTable'
|
28
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
29
|
+
rdoc.rdoc_files.include('README.rdoc')
|
30
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
31
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module UsefullTable
|
2
|
+
class TableController < ::ApplicationController
|
3
|
+
|
4
|
+
def create
|
5
|
+
usefull_table = HashWithIndifferentAccess.new(ActiveSupport::JSON.decode(params[:usefull_table]))
|
6
|
+
#Rails::logger.info("MonitorsController back=#{usefull_table[:paths].inspect}")
|
7
|
+
if usefull_table[:class_name].present?
|
8
|
+
if usefull_table[:search].present?
|
9
|
+
@object = usefull_table[:class_name].constantize.search(usefull_table[:search]).relation
|
10
|
+
else
|
11
|
+
@object = usefull_table[:class_name].constantize.all
|
12
|
+
end
|
13
|
+
@params = usefull_table[:params]
|
14
|
+
end
|
15
|
+
|
16
|
+
respond_to do |format|
|
17
|
+
format.html
|
18
|
+
format.xlsx { render :xlsx => "create", :template => select_path(usefull_table[:paths],"xlsx.maker") }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def update
|
23
|
+
#usefull_table = HashWithIndifferentAccess.new(ActiveSupport::JSON.decode(params[:usefull_table]))
|
24
|
+
Rails::logger.info("TableController#update params=#{params.inspect}")
|
25
|
+
if params[:class_name].present? && params[:attribute_name].present?
|
26
|
+
@item = params[:class_name].to_s.camelize.constantize.find(params[:id])
|
27
|
+
@item.update_attribute(params[:attribute_name], params[:value])
|
28
|
+
render :text => CGI::escapeHTML(@item.send(params[:attribute_name]).to_s)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,323 @@
|
|
1
|
+
module UsefullTableHelper
|
2
|
+
#=UsefullTable
|
3
|
+
#table_for generate a full-optionals table, with excel export, columns ordering, links, inline edit and monitoring (ActsAsMonitor gem)
|
4
|
+
#but don't warry because of a rich set of defaults, make its use very simple
|
5
|
+
#
|
6
|
+
#==Setup
|
7
|
+
#Add this line to your application's Gemfile:
|
8
|
+
# gem 'usefull_table'
|
9
|
+
#
|
10
|
+
#then execute
|
11
|
+
# $ bundle install
|
12
|
+
#
|
13
|
+
#or install it yourself as:
|
14
|
+
# $ sudo gem install usefull_table
|
15
|
+
#
|
16
|
+
#copy icons, javascript and stylesheets:
|
17
|
+
# $ rails g usefull_table:install
|
18
|
+
#
|
19
|
+
#==Usage table_for
|
20
|
+
#Write few lines in your controller
|
21
|
+
# app/controllers/home_controller.rb
|
22
|
+
# def index
|
23
|
+
# @search = Item.search(params[:search])
|
24
|
+
# ...
|
25
|
+
# respond_to do |format|
|
26
|
+
# format.html { @items = @search.paginate(:page => params[:page]) }
|
27
|
+
# end
|
28
|
+
# ...
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
#and in your view
|
32
|
+
# app/views/home/my_view.html.erb
|
33
|
+
# <%= table_for @items, @search, options = {} do |t| %>
|
34
|
+
# <% t.show :url => Proc.new { |item| item_path(item)} %>
|
35
|
+
# <% t.edit :url => Proc.new { |item| edit_item_path(item)}%>
|
36
|
+
# <% t.destroy :url => Proc.new { |item| item_path(item)}, :link_options => {:method => delete, :confirm => "are you sure?"} %>
|
37
|
+
# <% t.download :url => Proc.new { |item| download_item_path(item)} %>
|
38
|
+
# <% t.col :name %>
|
39
|
+
# <% t.col "user.name" %>
|
40
|
+
# <% t.status %>
|
41
|
+
# <% end %>
|
42
|
+
#
|
43
|
+
#==Options
|
44
|
+
#default values in *bold*
|
45
|
+
#
|
46
|
+
#===Paginator
|
47
|
+
# options[:paginator][:visible] = *true* | false _note_: false if @items not present
|
48
|
+
# options[:paginator][:class] = *"usefull_table_paginator"*
|
49
|
+
#
|
50
|
+
#===Container
|
51
|
+
# options[:html] = *{:class => "usefull_table_container"}*
|
52
|
+
#
|
53
|
+
#===Excel
|
54
|
+
# options[:export][:visible] = *true* | false
|
55
|
+
# options[:export][:filter] = *true* | false _note:_ false if @search not present
|
56
|
+
# options[:export][:human] = *true* | false
|
57
|
+
# options[:export][:worksheet] = *object.class.name.gsub(/::/,"#")* _note:_ class name with namespace separator #
|
58
|
+
# options[:export][:url] = custom url
|
59
|
+
#===Table
|
60
|
+
# options[:table][:div_html] = *{:class => "usefull_table"}*
|
61
|
+
# options[:table][:header_html] = *{:class => "first_row"}*
|
62
|
+
# options[:table][:header_type] = *:sort* _note:_ :human if @search not present (no sorting possible)
|
63
|
+
# :plain bare column name from ActiveRecord
|
64
|
+
# :human column name humanized by ActiveRecord
|
65
|
+
# :nil no column name
|
66
|
+
#
|
67
|
+
#==Localization
|
68
|
+
#Uses standard ActiveRecord localization to render tables and columns names
|
69
|
+
# it:
|
70
|
+
# activerecord:
|
71
|
+
# attributes:
|
72
|
+
# item:
|
73
|
+
# name: Name
|
74
|
+
# type: Type
|
75
|
+
# user:
|
76
|
+
# name: Name
|
77
|
+
# models:
|
78
|
+
# item:
|
79
|
+
# one: Item
|
80
|
+
# other: Items
|
81
|
+
# user:
|
82
|
+
# one: User
|
83
|
+
# other: Users
|
84
|
+
#
|
85
|
+
# #config/usefull_table.it.yml
|
86
|
+
# it:
|
87
|
+
# usefull_table:
|
88
|
+
# submit_excel: Excel
|
89
|
+
# header_error: Errore
|
90
|
+
# body_error: Errore
|
91
|
+
#
|
92
|
+
# icons:
|
93
|
+
# show: "usefull_table_show.png"
|
94
|
+
# edit: "usefull_table_edit.png"
|
95
|
+
# destroy: "usefull_table_destroy.png"
|
96
|
+
# download: "usefull_table_download.png"
|
97
|
+
#
|
98
|
+
def table_for(obj, *args, &block)
|
99
|
+
#Rails::logger.info("table_for START args=#{args.inspect}")
|
100
|
+
unless obj.blank?
|
101
|
+
search = args.shift if args[0].kind_of?(MetaSearch::Builder)
|
102
|
+
#Rails::logger.info("table_for START(1) search=#{search.inspect}")
|
103
|
+
options = args.extract_options!
|
104
|
+
raise UsefullTable::MissingBlock unless block_given?
|
105
|
+
|
106
|
+
if obj.kind_of?(MetaSearch::Builder)
|
107
|
+
search = obj
|
108
|
+
object = obj.relation
|
109
|
+
search_attributes = search.search_attributes
|
110
|
+
else
|
111
|
+
object = obj
|
112
|
+
end
|
113
|
+
|
114
|
+
builder = UsefullTable::TableBuilder.new(object, search, options, self, &block)
|
115
|
+
options = builder.options
|
116
|
+
|
117
|
+
out = ""
|
118
|
+
out << monitor_tag_js if options[:monitor][:visible] == true
|
119
|
+
out << stylesheet_link_tag('usefull_table.css')
|
120
|
+
out << content_tag(:div, options[:html]) do
|
121
|
+
ext = ''
|
122
|
+
ext << usefull_table_paginator_for(object, options[:paginator])
|
123
|
+
ext << usefull_table_export_for(object,search,builder, options[:export])
|
124
|
+
ext << usefull_table_for(builder, object, search, options[:table])
|
125
|
+
ext << usefull_table_paginator_for(object, options[:paginator])
|
126
|
+
ext.html_safe
|
127
|
+
end
|
128
|
+
out.html_safe
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
#Instantiate builder with data info and render arrays for every line
|
133
|
+
#
|
134
|
+
#==Usage
|
135
|
+
#If you can use params to clone an existing table (builder.to_param) and return an array of Arrays
|
136
|
+
# $ array = export_for(@object, @params)
|
137
|
+
#
|
138
|
+
#You can build a new table passing a block (see ::table_for
|
139
|
+
def export_for(object, params = nil, &block)
|
140
|
+
builder = UsefullTable::TableBuilder.new(object, nil, nil, self, :params => params, &block)
|
141
|
+
builder.to_a
|
142
|
+
end
|
143
|
+
|
144
|
+
#Draw inline edit field
|
145
|
+
def inline_field(object, id, method, value, id_relation, tag_options = {}, in_place_editor_options = {})
|
146
|
+
Rails::logger.info("table_for#inline_field : oject=#{object.inspect}, method=#{method.inspect}, id=#{id.inspect}")
|
147
|
+
tag_options = { :tag => "span",
|
148
|
+
:id => "#{object.name.underscore.gsub("/","_")}_#{method}_#{id}_#{id_relation}_in_place_editor",
|
149
|
+
:class => "in_place_editor_field"}
|
150
|
+
id_relation = id if id_relation.nil?
|
151
|
+
in_place_editor_options[:url] = url_for({:action => "update", :controller=>"usefull_table/table", :id => id_relation})
|
152
|
+
in_place_editor_options[:parameters] = { :class_name => object.name.underscore, :attribute_name => method}
|
153
|
+
tag = content_tag(tag_options.delete(:tag), h(value),tag_options)
|
154
|
+
return tag + in_place_editor(tag_options[:id], in_place_editor_options)
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
#==Paginator
|
160
|
+
#Add pagination to Table
|
161
|
+
#===Parameters
|
162
|
+
# :paginator => {
|
163
|
+
# :visible => true | false #Default: true
|
164
|
+
# :class => ""usefull_table_paginator"
|
165
|
+
#}
|
166
|
+
def usefull_table_paginator_for(object, options = {})
|
167
|
+
if options[:visible] == true
|
168
|
+
#Rails::logger.info("table_for#paginator_tag : enter object=#{object.inspect}, options=#{options.inspect}")
|
169
|
+
content_tag :div, :class => options[:class] do
|
170
|
+
content_tag(:div, page_entries_info(object), :class => 'page_info') +
|
171
|
+
will_paginate(object, :container => false)
|
172
|
+
end
|
173
|
+
else
|
174
|
+
""
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
#==Export
|
179
|
+
#Export table content to excel file
|
180
|
+
#
|
181
|
+
#Send to controller the following parameters to rebuild the table in excel format
|
182
|
+
#* Search filters
|
183
|
+
#* Columns (@data)
|
184
|
+
#* Values (evenif calculated locally)
|
185
|
+
#===Parameters
|
186
|
+
# :excel => {
|
187
|
+
# :visible => true | false #default: true
|
188
|
+
# :columns => :all #Export all model columns, if not present exports only table columns
|
189
|
+
# :url => "documents_path" #Url to controller returning xls file
|
190
|
+
# :human => true | false #default: true , Humanize column names
|
191
|
+
# :filter => true | false #default: true, export filtered data
|
192
|
+
#
|
193
|
+
def usefull_table_export_for(object,search,builder,options)
|
194
|
+
if options[:visible] == true
|
195
|
+
if options[:search] == true
|
196
|
+
@params = {}
|
197
|
+
@params[:search] = search.search_attributes unless search.blank?
|
198
|
+
@params[:class_name] = object.first.class.name
|
199
|
+
@params[:params] = builder.to_param
|
200
|
+
@params[:paths] = view_paths.map {|path| "#{path.to_path}/#{controller_name}/#{action_name}.xlsx.maker"}
|
201
|
+
#Rails::logger.info("table_for#excel_tag @path=#{self.controller_name}, action=#{action_name}, path=#{view_paths.first.to_path}\n\n")
|
202
|
+
content_tag(:div, :class => options[:class]) do
|
203
|
+
form_tag( options[:url] , :method => :post) do
|
204
|
+
hidden_field_tag("usefull_table", @params.to_json) +
|
205
|
+
submit_tag(I18n.t(:submit_excel, :scope => :usefull_table))
|
206
|
+
end
|
207
|
+
end
|
208
|
+
else
|
209
|
+
content_tag(:div, :class => options[:class]) do
|
210
|
+
form_tag( options[:url], :method => :get ) do
|
211
|
+
submit_tag(I18n.t(:submit_excel, :scope => :usefull_table))
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
else
|
216
|
+
#If "" the next div magically disappear...
|
217
|
+
" "
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
#==Table
|
222
|
+
#Draw Table
|
223
|
+
#===Parameters
|
224
|
+
# :table => {
|
225
|
+
# :div_html => {:class => "usefull_table"} #HTML options of <div> container
|
226
|
+
# :header_html] => {:class => "first_row"} #HTML options of Headers <tr>
|
227
|
+
# :html => {} #HTML options of <table>
|
228
|
+
# }
|
229
|
+
def usefull_table_for(builder, object, search, options = {})
|
230
|
+
#Rails::logger.info("TableHelper#usefull_table_for ")
|
231
|
+
content_tag(:div, options[:div_html]) do
|
232
|
+
content_tag(:table, options[:html]) do
|
233
|
+
builder.render_header +
|
234
|
+
builder.render_body
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def select_path(paths, extension)
|
240
|
+
Rails::logger.info("select_path @path=#{paths.inspect}\n\n")
|
241
|
+
paths.delete_if {|path| !File.exists?(path)}
|
242
|
+
Rails::logger.info("select_path(dopo) @path=#{paths.inspect}\n\n")
|
243
|
+
paths.blank? ? nil : paths.first
|
244
|
+
end
|
245
|
+
|
246
|
+
# Makes an HTML element specified by the DOM ID +field_id+ become an in-place
|
247
|
+
# editor of a property.
|
248
|
+
#
|
249
|
+
# A form is automatically created and displayed when the user clicks the element,
|
250
|
+
# something like this:
|
251
|
+
# <form id="myElement-in-place-edit-form" target="specified url">
|
252
|
+
# <input name="value" text="The content of myElement"/>
|
253
|
+
# <input type="submit" value="ok"/>
|
254
|
+
# <a onclick="javascript to cancel the editing">cancel</a>
|
255
|
+
# </form>
|
256
|
+
#
|
257
|
+
# The form is serialized and sent to the server using an AJAX call, the action on
|
258
|
+
# the server should process the value and return the updated value in the body of
|
259
|
+
# the reponse. The element will automatically be updated with the changed value
|
260
|
+
# (as returned from the server).
|
261
|
+
#
|
262
|
+
# Required +options+ are:
|
263
|
+
# <tt>:url</tt>:: Specifies the url where the updated value should
|
264
|
+
# be sent after the user presses "ok".
|
265
|
+
#
|
266
|
+
# Addtional +options+ are:
|
267
|
+
# <tt>:rows</tt>:: Number of rows (more than 1 will use a TEXTAREA)
|
268
|
+
# <tt>:cols</tt>:: Number of characters the text input should span (works for both INPUT and TEXTAREA)
|
269
|
+
# <tt>:size</tt>:: Synonym for :cols when using a single line text input.
|
270
|
+
# <tt>:cancel_text</tt>:: The text on the cancel link. (default: "cancel")
|
271
|
+
# <tt>:save_text</tt>:: The text on the save link. (default: "ok")
|
272
|
+
# <tt>:loading_text</tt>:: The text to display while the data is being loaded from the server (default: "Loading...")
|
273
|
+
# <tt>:saving_text</tt>:: The text to display when submitting to the server (default: "Saving...")
|
274
|
+
# <tt>:external_control</tt>:: The id of an external control used to enter edit mode.
|
275
|
+
# <tt>:load_text_url</tt>:: URL where initial value of editor (content) is retrieved.
|
276
|
+
# <tt>:options</tt>:: Pass through options to the AJAX call (see prototype's Ajax.Updater)
|
277
|
+
# <tt>:parameters</tt>:: Pass through post
|
278
|
+
# <tt>:with</tt>:: JavaScript snippet that should return what is to be sent
|
279
|
+
# in the AJAX call, +form+ is an implicit parameter
|
280
|
+
# <tt>:script</tt>:: Instructs the in-place editor to evaluate the remote JavaScript response (default: false)
|
281
|
+
# <tt>:click_to_edit_text</tt>::The text shown during mouseover the editable text (default: "Click to edit")
|
282
|
+
def in_place_editor(field_id, options = {})
|
283
|
+
function = "new Ajax.InPlaceEditor("
|
284
|
+
function << "'#{field_id}', "
|
285
|
+
function << "'#{url_for(options[:url])}'"
|
286
|
+
|
287
|
+
js_options = {}
|
288
|
+
|
289
|
+
if protect_against_forgery?
|
290
|
+
options[:with] ||= "Form.serialize(form)"
|
291
|
+
options[:with] += " + '&authenticity_token=' + encodeURIComponent('#{form_authenticity_token}')"
|
292
|
+
options[:parameters].each_pair {|k,v| options[:with] += " + '&#{k.to_s}=' + encodeURIComponent('#{v.to_s}')"} if options[:parameters]
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
js_options['cancelText'] = %('#{options[:cancel_text]}') if options[:cancel_text]
|
298
|
+
js_options['okText'] = %('#{options[:save_text]}') if options[:save_text]
|
299
|
+
js_options['loadingText'] = %('#{options[:loading_text]}') if options[:loading_text]
|
300
|
+
js_options['savingText'] = %('#{options[:saving_text]}') if options[:saving_text]
|
301
|
+
js_options['rows'] = options[:rows] if options[:rows]
|
302
|
+
js_options['cols'] = options[:cols] if options[:cols]
|
303
|
+
js_options['size'] = options[:size] if options[:size]
|
304
|
+
js_options['externalControl'] = "'#{options[:external_control]}'" if options[:external_control]
|
305
|
+
js_options['loadTextURL'] = "'#{url_for(options[:load_text_url])}'" if options[:load_text_url]
|
306
|
+
js_options['ajaxOptions'] = options[:options] if options[:options]
|
307
|
+
js_options['htmlResponse'] = !options[:script] if options[:script]
|
308
|
+
js_options['callback'] = "function(form) { return #{options[:with]} }" if options[:with]
|
309
|
+
js_options['clickToEditText'] = %('#{options[:click_to_edit_text]}') if options[:click_to_edit_text]
|
310
|
+
js_options['textBetweenControls'] = %('#{options[:text_between_controls]}') if options[:text_between_controls]
|
311
|
+
js_options['onComplete'] = %('#{options[:on_complete]}') if options[:on_complete]
|
312
|
+
js_options['onFailure'] = %('#{options[:on_failure]}') if options[:on_failure]
|
313
|
+
function << (', ' + options_for_javascript(js_options)) unless js_options.empty?
|
314
|
+
|
315
|
+
function << ')'
|
316
|
+
|
317
|
+
javascript_tag(function)
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
|
322
|
+
|
323
|
+
end
|