lipsiadmin 4.1.3 → 4.1.4

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 CHANGED
@@ -1,3 +1,25 @@
1
+ 2009-05-28
2
+ * Refactored account_access now current_account (account logged) is aviable in our roles
3
+ * Fix a typo in column_model
4
+ * Little refactoring in account model because now mapping is not necessary
5
+ * Improved Ext Components, now for example we can render in the same page multiple components without conflicts
6
+ * Removed some unusued methods
7
+ * Reject nil values from Ext Configuration
8
+ * Fixed raising errors in grid editor
9
+ * Updated controller generator, now accept ajax request
10
+
11
+ 2009-05-27
12
+ * Added new column renderer see: http://api.lipsiadmin.com/classes/Lipsiadmin/Ext/ColumnModel.html
13
+ * Added a new datetime editor
14
+ * Litte fix in AccountAccess.roles now return empty array if no roles instead rescue an error
15
+
16
+ 2009-05-26
17
+ * Fixed validates_attachment_content_type_for, now accepts correctly regex
18
+ * Added a attachment_tag for autogenerate html for upload one file/image
19
+ * Added a attachemnts_tag autogenerate html for upload multiple file/image and order them
20
+ * Added a open_standard_grid for simplify use of ext window with ours grids.
21
+ * Improved attachment generator
22
+
1
23
  2009-05-21
2
24
  * Removed some grids defaults
3
25
  * Added attacher_name in before_save
data/Rakefile CHANGED
@@ -75,7 +75,7 @@ end
75
75
 
76
76
  desc "Publish the API documentation"
77
77
  task :pdoc => [:rdoc] do
78
- Rake::SshDirPublisher.new("root@lipsiasoft.net", "/mnt/www/apps/lipsiadmin/doc", "doc").upload
78
+ Rake::SshDirPublisher.new("root@lipsiasoft.net", "/mnt/www/apps/lipsiasoft/doc", "doc").upload
79
79
  end
80
80
 
81
81
  desc "Publish the release files to RubyForge."
@@ -39,8 +39,10 @@ module Lipsiadmin
39
39
  #
40
40
  # For configure this role please refer to: <tt>Lipsiadmin::AccessControl::Base</tt>
41
41
  def allowed?
42
- allowed = current_account.maps.collect(&:allowed)[0]
43
- denied = current_account.maps.collect(&:denied)[0]
42
+ maps = AccountAccess.maps_for(current_account)
43
+
44
+ allowed = maps.collect(&:allowed).flatten.uniq
45
+ denied = maps.collect(&:denied).flatten.uniq
44
46
 
45
47
  allow = allowed.find do |a|
46
48
  a[:controller] == params[:controller] &&
@@ -80,7 +82,7 @@ module Lipsiadmin
80
82
  format.js { render(:update) { |page| page.alert "You don't allowed to access to this javascript" } }
81
83
  end
82
84
  false
83
- end
85
+ end
84
86
 
85
87
  def store_location#:nodoc:
86
88
  session[:return_to] = request.request_uri
@@ -13,7 +13,7 @@ module Lipsiadmin
13
13
  #
14
14
  # Examples:
15
15
  #
16
- # roles_for :administrator do |role|
16
+ # roles_for :administrator do |role, current_account|
17
17
  # role.allow_all_actions "/backend/base"
18
18
  # role.deny_action_of "/backend/accounts/details"
19
19
  #
@@ -24,6 +24,12 @@ module Lipsiadmin
24
24
  # end
25
25
  # end
26
26
  # end
27
+ #
28
+ # role.project_module :categories do |project|
29
+ # current_account.categories.each do |cat|
30
+ # project.menu cat.name, "/backend/categories/#{cat.id}.js"
31
+ # end
32
+ # end
27
33
  # end
28
34
  #
29
35
  # If a user logged with role administrator or that have a project_module administrator can:
@@ -32,6 +38,7 @@ module Lipsiadmin
32
38
  # - Denied access to ONLY action <tt>"/backend/accounts/details"</tt>
33
39
  # - Access to a project module called Administration
34
40
  # - Access to all actions of the controller "/backend/settings"
41
+ # - Access to all actions of the controller "/backend/categories"
35
42
  # - Access to all actions EXCEPT <tt>details</tt> of controller "/backend/accounts"
36
43
  #
37
44
  class Base
@@ -44,35 +51,17 @@ module Lipsiadmin
44
51
  @mappers ||= []
45
52
  @roles ||= []
46
53
  @roles.concat(roles)
47
- @mappers << Mapper.new(*roles, &block)
48
- end
54
+ @mappers << Proc.new { |account| Mapper.new(account, *roles, &block) }
55
+ end
49
56
 
50
57
  # Returns all roles
51
58
  def roles
52
- @roles.collect(&:to_s)
59
+ @roles.nil? ? [] : @roles.collect(&:to_s)
53
60
  end
54
61
 
55
- # Returns all project modules ids
56
- def project_modules
57
- @mappers.inject([]) do |pm, maps|
58
- pm.concat(maps.project_modules.collect(&:uid))
59
- end.uniq
60
- end
61
-
62
- # Returns maps for a given role
63
- def find_by_role(role)
64
- role = case role
65
- when String then role.downcase.to_sym
66
- when Symbol then role
67
- end
68
- return @mappers.find_all { |m| m.roles.include?(role.to_sym) }
69
- end
70
-
71
- # Returns maps for a given project modules uids
72
- def find_by_project_modules(*uids)
73
- uids.inject([]) do |maps, uid|
74
- maps.concat @mappers.find_all { |m| m.project_modules.collect(&:uid).include?(uid.to_s) }
75
- end
62
+ def maps_for(account)
63
+ @mappers.collect { |m| m.call(account) }.
64
+ reject { |m| !m.allowed? }
76
65
  end
77
66
  end
78
67
 
@@ -82,12 +71,14 @@ module Lipsiadmin
82
71
  include Helper
83
72
  attr_reader :project_modules, :roles
84
73
 
85
- def initialize(*roles, &block)#:nodoc:
74
+ def initialize(account, *roles, &block)#:nodoc:
86
75
  @project_modules = []
87
76
  @allowed = []
88
77
  @denied = []
89
78
  @roles = roles
90
- yield self
79
+ @account = account
80
+ # Mantain backward compatibility
81
+ yield(self, @account) rescue yield(self)
91
82
  end
92
83
 
93
84
  # Create a new project module
@@ -115,15 +106,25 @@ module Lipsiadmin
115
106
  @denied << { :controller => recognize_path(path)[:controller] }
116
107
  end
117
108
 
109
+ # Return true if current_account role is included in given roles
110
+ def allowed?
111
+ @roles.any? { |r| r.to_s.downcase == @account.role.downcase }
112
+ end
113
+
118
114
  # Return allowed actions/controllers
119
115
  def allowed
120
- @project_modules.each { |pm| @allowed.concat pm.allowed }
121
- return @allowed.uniq
116
+ # I know is a double check but is better 2 times that no one.
117
+ if allowed?
118
+ @project_modules.each { |pm| @allowed.concat pm.allowed }
119
+ @allowed.uniq
120
+ else
121
+ []
122
+ end
122
123
  end
123
124
 
124
125
  # Return denied actions/controllers
125
126
  def denied
126
- return @denied.uniq
127
+ @denied.uniq
127
128
  end
128
129
  end
129
130
 
@@ -151,13 +152,13 @@ module Lipsiadmin
151
152
 
152
153
  # Return allowed controllers
153
154
  def allowed
154
- @menus.each { |m| @allowed.concat m.allowed }
155
- return @allowed.uniq
155
+ @menus.each { |m| @allowed.concat(m.allowed) }
156
+ @allowed.uniq
156
157
  end
157
158
 
158
159
  # Return the original name or try to translate or humanize the symbol
159
160
  def human_name
160
- return @name.is_a?(Symbol) ? I18n.t("backend.menus.#{@name}", :default => @name.to_s.humanize) : @name
161
+ @name.is_a?(Symbol) ? I18n.t("backend.menus.#{@name}", :default => @name.to_s.humanize) : @name
161
162
  end
162
163
 
163
164
  # Return a unique id for the given project module
@@ -170,7 +171,7 @@ module Lipsiadmin
170
171
  options = @options.merge(:text => human_name)
171
172
  options.merge!(:menu => @menus.collect(&:config)) if @menus.size > 0
172
173
  options.merge!(:handler => "function(){ Backend.app.load('#{url_for(@url.merge(:only_path => true))}') }".to_l) if @url
173
- return options
174
+ options
174
175
  end
175
176
  end
176
177
 
@@ -199,12 +200,12 @@ module Lipsiadmin
199
200
  # Return allowed controllers
200
201
  def allowed
201
202
  @items.each { |i| @allowed.concat i.allowed }
202
- return @allowed.uniq
203
+ @allowed.uniq
203
204
  end
204
205
 
205
206
  # Return the original name or try to translate or humanize the symbol
206
207
  def human_name
207
- return @name.is_a?(Symbol) ? I18n.t("backend.menus.#{@name}", :default => @name.to_s.humanize) : @name
208
+ @name.is_a?(Symbol) ? I18n.t("backend.menus.#{@name}", :default => @name.to_s.humanize) : @name
208
209
  end
209
210
 
210
211
  # Return a unique id for the given project module
@@ -214,10 +215,14 @@ module Lipsiadmin
214
215
 
215
216
  # Return ExtJs Config for this menu
216
217
  def config
217
- options = @options.merge(:text => human_name)
218
- options.merge!(:menu => @items.collect(&:config)) if @items.size > 0
219
- options.merge!(:handler => "function(){ Backend.app.load('#{url_for(@url.merge(:only_path => true))}') }".to_l) if @url
220
- return options
218
+ if @url.blank?
219
+ options = human_name
220
+ else
221
+ options = @options.merge(:text => human_name)
222
+ options.merge!(:menu => @items.collect(&:config)) if @items.size > 0
223
+ options.merge!(:handler => "function(){ Backend.app.load('#{url_for(@url.merge(:only_path => true))}') }".to_l)
224
+ end
225
+ options
221
226
  end
222
227
  end
223
228
 
@@ -347,8 +347,8 @@ module Lipsiadmin
347
347
  valid_types = []
348
348
  args.each do |variable|
349
349
  case variable
350
- when String then valid_types << variable
351
350
  when Hash then options.merge!(variable)
351
+ else valid_types << variable
352
352
  end
353
353
  end
354
354
  attachment_definitions[name][:validations][:content_type] = lambda do |attachment, instance|
@@ -43,7 +43,6 @@ module Lipsiadmin
43
43
  def options
44
44
  @options ||= {
45
45
  :whiny_thumbnails => false,
46
- :image_magick_path => nil,
47
46
  :command_path => nil,
48
47
  :log => true,
49
48
  :swallow_stderr => true
@@ -83,9 +82,6 @@ module Lipsiadmin
83
82
  end
84
83
 
85
84
  def path_for_command(command)#:nodoc:
86
- if options[:image_magick_path]
87
- warn("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
88
- end
89
85
  path = [options[:command_path] || options[:image_magick_path], command].compact
90
86
  File.join(*path)
91
87
  end
data/lib/version.rb CHANGED
@@ -2,7 +2,7 @@ module Lipsiadmin
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 4
4
4
  MINOR = 1
5
- TINY = 3
5
+ TINY = 4
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -153,12 +153,168 @@ module Lipsiadmin
153
153
 
154
154
  # Generate the menu from the Lispiadmin::AccessControl
155
155
  def backend_menu
156
- config = current_account.maps.collect(&:project_modules)[0].collect(&:config)
156
+ config = AccountAccess.maps_for(current_account).collect(&:project_modules).flatten.uniq.collect(&:config)
157
157
  config << { :text => I18n.t("backend.menus.help", :default => "Help"), :handler => "function() { Backend.app.openHelp() }".to_l }
158
158
  return config.to_json
159
159
  end
160
+
161
+ # Returns html for upload one image or generic file.
162
+ #
163
+ # Options can be one of the following:
164
+ #
165
+ # <tt>:image</tt>:: Indicate if the attachments are ONLY images.
166
+ #
167
+ # Examples:
168
+ #
169
+ # class Category < ActiveRecord::Base
170
+ # has_one_attachments :file, :dependent => :destroy
171
+ # ...
172
+ #
173
+ # Then in our view we can simply add this:
174
+ #
175
+ # attachments_tag(:category, :file)
176
+ #
177
+ # Remember that al labels can be translated. See Locales for Backend.
178
+ #
179
+ def attachment_tag(object_name, method, options={})
180
+ variable = instance_variable_get("@#{object_name}")
181
+ html = []
182
+ html << '<!-- Generated from Lipsiadmin -->'
183
+ html << '<ul id="' + "#{method}-order" + '" class="label">'
184
+
185
+ if attachment = variable.send(method)
186
+ # Create first the remove link
187
+ remove_link = link_to_remote(tl(:remove), :url => "/backend/attachments/#{attachment.id}",
188
+ :method => :delete,
189
+ :success => "$('#{method}_#{attachment.id}').remove();")
190
+
191
+ if options[:image]
192
+ fstyle = "float:left;margin:5px;margin-left:0px;"
193
+ fclass = "box-image"
194
+ ftag = '<div>' + image_tag(attachment.url(:thumb)) + '</div>'
195
+ ftag += '<div style="text-align:center;padding:5px;cursor:pointer">'
196
+ ftag += ' ' + remove_link
197
+ ftag += '</div>'
198
+ else
199
+ fstyle = "padding:5px;border-bottom:1px solid #DDE7F5;"
200
+ fclass = "box-file"
201
+ ftag = '<div style="float:left;cursor:pointer">'
202
+ ftag += ' ' + link_to(attachment.attached_file_name, attachment.url) + ' ' + number_to_human_size(attachment.attached_file_size)
203
+ ftag += '</div>'
204
+ ftag += '<div style="float:right;cursor:pointer">'
205
+ ftag += ' ' + remove_link
206
+ ftag += '</div>'
207
+ ftag += '<br style="clear:both" />'
208
+ end
209
+
210
+ html << '<li id="' + "#{method}_#{attachment.id}" + '" class="' + fclass + '" style="' + fstyle + '">'
211
+ html << ' ' + ftag
212
+ html << '</li>'
213
+ end # End of Loop
214
+
215
+ html << '</ul>'
216
+ html << '<br style="clear:both" />'
217
+
218
+ flbl = options[:image] ? :upload_image : :upload_file
219
+ html << '<div class="label-title">' + tl(flbl) + '</div>'
220
+ html << '<table>'
221
+ rowa = ' <tr class="attachment">'
222
+ rowa << ' <td>' + human_name_for(:attachment, :attached_file_name) + '</td>'
223
+ rowa << ' <td>' + file_field_tag("category[#{method}_attributes][file]", :style => "width:250px") + '</td>'
224
+ rowa << ' </tr>'
225
+ html << rowa
226
+ html << '</table>'
227
+ html.join("\n")
228
+ end
160
229
 
161
- # Open a new windows that can contain a grid that you can reuse
230
+ # Returns html for upload multiple images or generic files.
231
+ #
232
+ # Options can be one of the following:
233
+ #
234
+ # <tt>:image</tt>:: Indicate if the attachments are ONLY images.
235
+ # <tt>:order</tt>:: Indicate if user can order files.
236
+ #
237
+ # Examples:
238
+ #
239
+ # class Category < ActiveRecord::Base
240
+ # has_many_attachments :images, :dependent => :destroy
241
+ # validates_attachment_content_type_for :images, /^image/
242
+ # ...
243
+ #
244
+ # Then in our view we can simply add this:
245
+ #
246
+ # attachments_tag(:category, :images, :image => true, :order => true)
247
+ #
248
+ # Remember that al labels can be translated. See Locales for Backend.
249
+ #
250
+ def attachments_tag(object_name, method, options={})
251
+ variable = instance_variable_get("@#{object_name}")
252
+ html = []
253
+ html << '<!-- Generated from Lipsiadmin -->'
254
+ html << '<ul id="' + "#{method}-order" + '" class="label">'
255
+
256
+ for attachment in variable.send(method).all(:order => :position)
257
+ # Create first the remove link
258
+ remove_link = link_to_remote(tl(:remove), :url => "/backend/attachments/#{attachment.id}",
259
+ :method => :delete,
260
+ :success => "$('#{method}_#{attachment.id}').remove();")
261
+
262
+ if options[:image]
263
+ fstyle = "float:left;margin:5px;margin-left:0px;"
264
+ fstyle += "cursor:move;" if options[:order]
265
+ fclass = "box-image"
266
+ ftag = '<div>' + image_tag(attachment.url(:thumb)) + '</div>'
267
+ ftag += '<div style="text-align:center;padding:5px;cursor:pointer">'
268
+ ftag += ' ' + remove_link
269
+ ftag += '</div>'
270
+ else
271
+ fstyle = "padding:5px;border-bottom:1px solid #DDE7F5;"
272
+ fstyle += "cursor:move;" if options[:order]
273
+ fclass = "box-file"
274
+ ftag = '<div style="float:left;cursor:pointer">'
275
+ ftag += ' ' + link_to(attachment.attached_file_name, attachment.url) + ' ' + number_to_human_size(attachment.attached_file_size)
276
+ ftag += '</div>'
277
+ ftag += '<div style="float:right;cursor:pointer">'
278
+ ftag += ' ' + remove_link
279
+ ftag += '</div>'
280
+ ftag += '<br style="clear:both" />'
281
+ end
282
+
283
+ html << '<li id="' + "#{method}_#{attachment.id}" + '" class="' + fclass + '" style="' + fstyle + '">'
284
+ html << ' ' + ftag
285
+ html << '</li>'
286
+ end # End of Loop
287
+
288
+ html << '</ul>'
289
+ html << '<br style="clear:both" />'
290
+
291
+ if options[:order]
292
+ constraint = options[:image] ? "horizontal" : "vertical"
293
+ html << '<div id="' + "#{method}-message" + '" style="padding:5px">&nbsp;</div>'
294
+ html << sortable_element("#{method}-order", :url => "/backend/attachments/order", :update => "#{method}-message", :constraint => constraint,
295
+ :complete => visual_effect(:highlight, "#{method}-message", :duration => 0.5))
296
+ end
297
+
298
+ flbl = options[:image] ? :upload_images : :upload_files
299
+ html << '<div class="label-title">'+ tl(flbl) +'</div>'
300
+ html << '<table>'
301
+ rowa = ' <tr class="attachment">'
302
+ rowa << ' <td>' + human_name_for(:attachment, :attached_file_name) + '</td>'
303
+ rowa << ' <td>' + file_field_tag("category[#{method}_attributes][][file]", :style => "width:250px") + '</td>'
304
+ rowa << ' <td>' + link_to_function(tl(:remove), "this.up('.attachment').remove()") + '</td>'
305
+ rowa << ' </tr>'
306
+ html << rowa
307
+ html << ' <tr id="' + "add-#{method}" + '">'
308
+ html << ' <td colspan="2">&nbsp;</td>'
309
+ html << ' <td style="padding-top:15px">'
310
+ html << ' ' + link_to_function(tl(:add)) { |page| page.insert_html(:before, "add-#{method}", rowa) }
311
+ html << ' </td>'
312
+ html << ' </tr>'
313
+ html << '</table>'
314
+ html.join("\n")
315
+ end
316
+
317
+ # Build a new windows that can contain an existent grid
162
318
  #
163
319
  # The first argument name is used as the link text.
164
320
  #
@@ -187,12 +343,11 @@ module Lipsiadmin
187
343
  # # }
188
344
  # # }).show();
189
345
  # # return false;" href="#">Select a Category</a>
190
- #
191
- # open_grid "Select a Category", "/backend/categories.js", "gridPanel",
346
+ # build_grid "Select a Category", "/backend/categories.js", "gridPanel",
192
347
  # :update => "$('post_category_ids').value = selections.collect(function(s) { return s.id }).join(',');" +
193
348
  # "$('category_names').innerHTML = selections.collect(function(s) { return s.data['categories.name'] }).join(', ');"
194
349
  #
195
- def open_grid(text, url, grid, options={})
350
+ def build_grid(text, url, grid, options={})
196
351
  options[:before] = options[:before] + ";" if options[:before]
197
352
  javascript = <<-JAVASCRIPT
198
353
  #{options[:before]}
@@ -206,7 +361,45 @@ module Lipsiadmin
206
361
  }
207
362
  }).show()
208
363
  JAVASCRIPT
209
- link_to_function(text, javascript)
364
+ link_to_function(text, javascript.gsub(/\n|\s+/, " "))
365
+ end
366
+ alias_method :open_grid, :build_grid
367
+
368
+ # Open a Standard window that can contain a standard existent grid
369
+ #
370
+ # Options can be one of the following:
371
+ #
372
+ # <tt>:grid</tt>:: The name of the grid var. Default "gridPanel"
373
+ # <tt>:url</tt>:: The url where the grid is stored. Default is autogenerated.
374
+ # <tt>:name</tt>:: The name of the link that open the window grid. Default a image.
375
+ #
376
+ # # Generates: <a onclick="
377
+ # # new Backend.window({
378
+ # # url: '/backend/suppliers.js',
379
+ # # grid: 'gridPanel',
380
+ # # listeners: {
381
+ # # selected: function(win, selections){
382
+ # # $('warehouse_supplier_id').value = selections.first().id;
383
+ # # $('warehouse_supplier_name').innerHTML = selections.first().data['suppliers.name']
384
+ # # }
385
+ # # }
386
+ # # }).show(); return false;">
387
+ # # <img alt="New" src="/images/backend/new.gif?1242655402" style="vertical-align:bottom" /></a>
388
+ # # <input id="warehouse_supplier_id" name="warehouse[supplier_id]" type="hidden" value="16" />
389
+ # open_standard_grid :warehouse, :supplier, :id, :name
390
+ #
391
+ def open_standard_grid(object_name, ext_object, value, display, options={})
392
+ current_value = instance_variable_get("@#{object_name}").send(ext_object).send(display) rescue "Nessuno"
393
+ value_field = value.to_s.downcase == "id" ? "id" : "data['#{ext_object.to_s.pluralize}.#{value}']"
394
+ options[:grid] ||= "gridPanel"
395
+ options[:url] ||= "/backend/#{ext_object.to_s.pluralize}.js"
396
+ options[:name] ||= image_tag("backend/new.gif", :style => "vertical-align:bottom")
397
+ update_function = "$('#{object_name}_#{ext_object}_#{value}').value = selections.first().#{value_field}; " +
398
+ "$('#{object_name}_#{ext_object}_#{display}').innerHTML = selections.first().data['#{ext_object.to_s.pluralize}.#{display}']"
399
+
400
+ content_tag(:span, current_value, :id => "#{object_name}_#{ext_object}_#{display}" ) + ' ' +
401
+ build_grid(options[:name], options[:url], options[:grid], :update => update_function) +
402
+ hidden_field(object_name, "#{ext_object}_#{value}")
210
403
  end
211
404
 
212
405
  # Open a new windows that can contain a form that you can reuse
@@ -250,7 +443,7 @@ module Lipsiadmin
250
443
  }
251
444
  }).show()
252
445
  JAVASCRIPT
253
- link_to_function(text, javascript)
446
+ link_to_function(text, javascript.gsub(/\n/, " "))
254
447
  end
255
448
 
256
449
  # This method call a remote_function and in the same time do a
@@ -35,7 +35,7 @@ module Lipsiadmin
35
35
 
36
36
  # This add automatically fields from an array
37
37
  def fields(fields)
38
- fields.each { |options| add(nil, nil, options) }
38
+ fields.each { |options| add(nil, nil, options); }
39
39
  end
40
40
 
41
41
  # Add columns to a Ext.grid.ColumnModel
@@ -55,8 +55,17 @@ module Lipsiadmin
55
55
  # :renderer => :us_money
56
56
  # # Generates: Ext.util.Format.boolRenderer
57
57
  # :renderer => :boolean
58
+ # ...
59
+ # :render => :capitalize
60
+ # :render => :file_size
61
+ # :render => :downcase
62
+ # :render => :trim
63
+ # :render => :undef
64
+ # :render => :upcase
58
65
  #
59
- # You can pass :edit_with_###
66
+ # For more see http://extjs.com/deploy/dev/docs/?class=Ext.util.Format
67
+ #
68
+ # You can pass :editor
60
69
  #
61
70
  # # Generates: { checkbox: true }
62
71
  # :editor => { :xtype => :checkbox, :someConfig => true }
@@ -88,19 +97,20 @@ module Lipsiadmin
88
97
  #
89
98
  def add(name=nil, data=nil, options={})
90
99
  options[:header] = name if name
91
- options[:dataIndex] = data if date
100
+ options[:dataIndex] = data if data
92
101
 
93
102
  if options[:editor]
94
103
  xtype = options[:editor].delete(:xtype)
95
104
  case xtype
96
- when :checkbox then options.delete(:editor); options.merge!(:checkbox => true)
97
- when :combo then options.merge!(:editor => l("new Ext.form.ComboBox(#{Configuration.new(options[:editor]).to_s(3)})"))
98
- when :datefield then options.merge!(:editor => l("new Ext.form.DateField(#{Configuration.new(options[:editor]).to_s(3)})"))
99
- when :numberfield then options.merge!(:editor => l("new Ext.form.NumberField(#{Configuration.new(options[:editor]).to_s(3)})"))
100
- when :radio then options.merge!(:editor => l("new Ext.form.Radio(#{Configuration.new(options[:editor]).to_s(3)})"))
101
- when :textarea then options.merge!(:editor => l("new Ext.form.TextArea(#{Configuration.new(options[:editor]).to_s(3)})"))
102
- when :textfield then options.merge!(:editor => l("new Ext.form.TextField(#{Configuration.new(options[:editor]).to_s(3)})"))
103
- when :timefield then options.merge!(:editor => l("new Ext.form.TimeField(#{Configuration.new(options[:editor]).to_s(3)})"))
105
+ when :checkbox then options.delete(:editor); options.merge!(:checkbox => true)
106
+ when :combo then options.merge!(:editor => l("new Ext.form.ComboBox(#{Configuration.new(options[:editor]).to_s(3)})"))
107
+ when :datefield then options.merge!(:editor => l("new Ext.form.DateField(#{Configuration.new(options[:editor]).to_s(3)})"))
108
+ when :numberfield then options.merge!(:editor => l("new Ext.form.NumberField(#{Configuration.new(options[:editor]).to_s(3)})"))
109
+ when :radio then options.merge!(:editor => l("new Ext.form.Radio(#{Configuration.new(options[:editor]).to_s(3)})"))
110
+ when :textarea then options.merge!(:editor => l("new Ext.form.TextArea(#{Configuration.new(options[:editor]).to_s(3)})"))
111
+ when :textfield then options.merge!(:editor => l("new Ext.form.TextField(#{Configuration.new(options[:editor]).to_s(3)})"))
112
+ when :timefield then options.merge!(:editor => l("new Ext.form.TimeField(#{Configuration.new(options[:editor]).to_s(3)})"))
113
+ when :datetimefield then options.merge!(:editor => l("new Ext.form.DateTimeField(#{Configuration.new(options[:editor]).to_s(3)})"))
104
114
  end
105
115
  end
106
116
 
@@ -110,10 +120,17 @@ module Lipsiadmin
110
120
  when :eur_money then options.merge!(:renderer => l("Ext.util.Format.eurMoney"))
111
121
  when :us_money then options.merge!(:renderer => l("Ext.util.Format.usMoney"))
112
122
  when :boolean then options.merge!(:renderer => l("Ext.util.Format.boolRenderer"))
123
+ when :capitalize then options.merge!(:renderer => l("Ext.util.Format.capitalize"))
124
+ when :file_size then options.merge!(:renderer => l("Ext.util.Format.fileSize"))
125
+ when :downcase then options.merge!(:renderer => l("Ext.util.Format.lowercase"))
126
+ when :trim then options.merge!(:renderer => l("Ext.util.Format.trim"))
127
+ when :undef then options.merge!(:renderer => l("Ext.util.Format.undef"))
128
+ when :upcase then options.merge!(:renderer => l("Ext.util.Format.uppercase"))
113
129
  end
114
130
 
115
131
  raise ComponentError, "You must provide header and dataIndex for generate a column model" if options[:header].blank? ||
116
132
  options[:dataIndex].blank?
133
+
117
134
  config[:columns] << Configuration.new(options)
118
135
  end
119
136
  end
@@ -17,7 +17,9 @@ module Lipsiadmin#:nodoc:
17
17
  class Component
18
18
 
19
19
  def initialize(klass, options={}, &block)#:nodoc:
20
- @klass = klass
20
+ @klass = klass
21
+ @prefix = options.delete(:prefix)
22
+ @var = options.delete(:var)
21
23
  @config = Configuration.new(options)
22
24
  @before, @after = [], []
23
25
 
@@ -45,10 +47,11 @@ module Lipsiadmin#:nodoc:
45
47
  #
46
48
  def get_var
47
49
  # I will nillify obj if they are blank
48
- @var = nil if @var == ""
49
- @config[:var] if @config[:var] == ""
50
+ @var = nil if @var == ""
51
+ @config.delete(:var) if @config[:var] == ""
50
52
  # Return a correct var
51
- @var || @config[:var] || (@klass.split(".").last.demodulize.slice(0..0).downcase + @klass.split(".").last.demodulize.slice(1..-1))
53
+ current_var = (@var || @config[:var] || build_var)
54
+ @prefix.to_s + current_var.to_s
52
55
  end
53
56
 
54
57
  # Write the the configuration of object from an hash
@@ -71,6 +74,14 @@ module Lipsiadmin#:nodoc:
71
74
  end
72
75
  end
73
76
 
77
+ # Set the prefix for the var of the component.
78
+ # This is usefull when for example we are using two grids
79
+ # for solve conflict problems.
80
+ #
81
+ def prefix=(value)
82
+ @prefix = value
83
+ end
84
+
74
85
  # Returns an array of javascripts to add before component is rendered.
75
86
  #
76
87
  def before
@@ -165,11 +176,6 @@ module Lipsiadmin#:nodoc:
165
176
  alias_method :l, :literal
166
177
 
167
178
  private
168
- def javascript_object_for(object)
169
- object.respond_to?(:to_json) ? object.to_json : object.inspect
170
- end
171
- alias_method :s, :javascript_object_for
172
-
173
179
  def render_javascript(template, assigns)
174
180
  assigns.each { |key, value| instance_variable_set("@#{key}", value) }
175
181
  template = File.read("#{File.dirname(__FILE__)}/templates/#{template}.js.erb")
@@ -178,6 +184,7 @@ module Lipsiadmin#:nodoc:
178
184
 
179
185
  def add_object(name, object)
180
186
  if object.class == Component || object.class.superclass == Component
187
+ object.prefix = get_var
181
188
  @before.delete_if { |b| b.start_with?("var #{object.get_var} = new") }
182
189
  @before << object.to_s
183
190
  @config[name.to_sym] = l(object.get_var)
@@ -185,6 +192,17 @@ module Lipsiadmin#:nodoc:
185
192
  @config[name.to_sym] = object
186
193
  end
187
194
  end
195
+
196
+ def build_var
197
+ returning "" do |val|
198
+ if @prefix.blank?
199
+ val << @klass.split(".").last.demodulize.slice(0..0).downcase
200
+ val << @klass.split(".").last.demodulize.slice(1..-1)
201
+ else
202
+ val << @klass.split(".").last.demodulize
203
+ end
204
+ end
205
+ end
188
206
  end
189
207
  end
190
208
  end
@@ -16,7 +16,7 @@ module Lipsiadmin
16
16
  return if self.empty?
17
17
  i = (" "*indent)
18
18
  s = self.size > 0 ? "\n" : " "
19
- "{#{s}" + self.collect { |k,v| "#{i*2}#{k}: #{s(v)}" if k != :var }.join(",#{s}") + "#{s}#{i}}"
19
+ "{#{s}" + self.reject { |k,v| k.blank? || v.to_s.blank? }.collect { |k,v| "#{i*2}#{k}: #{s(v)}" if k != :var }.join(",#{s}") + "#{s}#{i}}"
20
20
  end
21
21
 
22
22
  private
@@ -48,7 +48,7 @@ module Lipsiadmin
48
48
  # ...
49
49
  #
50
50
  class Grid < Component
51
-
51
+
52
52
  def initialize(options={}, &block)#:nodoc:
53
53
  # Call Super Class for initialize configuration
54
54
  @editable = options.delete(:editable)
@@ -65,7 +65,7 @@ module Lipsiadmin
65
65
  sm :checkbox
66
66
  add_plugin l("new Ext.grid.Search()")
67
67
  view :default
68
-
68
+ render true
69
69
  # We need to add a setTimeout because, we destroy
70
70
  # the grid before loading a new page/js.
71
71
  on(:dblclick) do |p|
@@ -97,8 +97,8 @@ module Lipsiadmin
97
97
  end
98
98
 
99
99
  # Define the title of the grid
100
- def title(title)
101
- before << "Backend.app.setTitle(#{title.to_json});"
100
+ def title(title, global=true)
101
+ global ? (before << "Backend.app.setTitle(#{title.to_json});") : config[:title] = title
102
102
  end
103
103
 
104
104
  # Assign plugins for the current grid
@@ -203,6 +203,15 @@ module Lipsiadmin
203
203
  add_object(:cm, cm)
204
204
  end
205
205
 
206
+
207
+ # Define if the grid need to be added to
208
+ #
209
+ # Backend.app.addItem(#{get_var});
210
+ #
211
+ def render(value)
212
+ @render = value
213
+ end
214
+
206
215
  # The base_path used for ToolBar, it's used for generate [:new, :edit, :destory] urls
207
216
  def base_path(value)
208
217
  @base_path = value
@@ -270,13 +279,13 @@ module Lipsiadmin
270
279
  after << render_javascript(:grid_functions, :var => get_var, :store => config[:store], :sm => config[:sm], :tbar => config[:tbar], :editable => @editable)
271
280
  end
272
281
 
273
- if config[:store]
282
+ if config[:store] && @render
274
283
  after << "#{config[:store]}.on('beforeload', function(){ Backend.app.mask(); });"
275
284
  after << "#{config[:store]}.on('load', function(){ Backend.app.unmask(); });"
276
285
  after << "#{config[:store]}.load();"
277
286
  end
278
287
 
279
- after << "Backend.app.addItem(#{get_var});"
288
+ after << "Backend.app.addItem(#{get_var});" if @render
280
289
 
281
290
  super
282
291
  end
@@ -43,20 +43,20 @@
43
43
  var column = <%= @var %>.getColumnModel().getColumnById(columnId);
44
44
 
45
45
  Ext.Ajax.request({
46
- url: '<%= @base_path %>/'+e.record.id,
46
+ url: '<%= @base_path %>/'+e.record.id+".json",
47
47
  method: 'PUT',
48
48
  params: column.name+'='+e.value,
49
49
  success: function(result, request){
50
- var resultValue = Ext.decode(result.responseText);
50
+ var resultValue = Ext.decode(result.responseText);
51
51
  if (resultValue.success == true){
52
52
  e.record.commit();
53
53
  } else {
54
- Ext.MessageBox.alert(Lipsiadmin.locale.alert.title, resultValue.msg);
54
+ Ext.Msg.alert(Backend.locale.messages.alert.title, resultValue.msg);
55
55
  e.record.reject();
56
56
  }
57
57
  },
58
58
  failure: function(result, request) {
59
- Ext.Msg.alert(Lipsiadmin.locale.alert.title, Lipsiadmin.locale.alert.msg);
59
+ Ext.Msg.alert(Backend.locale.messages.alert.title, Lipsiadmin.locale.alert.msg);
60
60
  e.record.reject();
61
61
  }
62
62
  });
@@ -6,7 +6,11 @@ class AttachmentGenerator < Rails::Generator::Base
6
6
  unless options[:skip_migration]
7
7
  m.migration_template("migration.rb", "db/migrate", :migration_file_name => "create_attachments")
8
8
  end
9
+ m.append("config/routes.rb", " backend.resources :attachments, :collection => { :order => :post }", "map.namespace(:backend) do |backend|")
10
+ m.directory('app/controllers/backend')
11
+ m.directory('app/models')
9
12
  m.template('model.rb', 'app/models/attachment.rb')
13
+ m.template('controller.rb', 'app/controllers/backend/attachments_controller.rb')
10
14
  m.readme "../REMEMBER"
11
15
  end
12
16
  end
@@ -0,0 +1,71 @@
1
+ class Backend::AttachmentsController < BackendController
2
+
3
+ def index
4
+ params[:limit] ||= 50
5
+
6
+ @column_store = column_store_for Attachment do |cm|
7
+ cm.add :attacher_type
8
+ cm.add :attached_file_name
9
+ cm.add :attached_content_type
10
+ cm.add :attached_file_size
11
+ cm.add :position
12
+ cm.add :created_at, :renderer => :datetime
13
+ cm.add :updated_at, :renderer => :datetime
14
+ end
15
+
16
+ respond_to do |format|
17
+ format.js
18
+ format.json do
19
+ render :json => @column_store.store_data(params)
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ def new
26
+ @attachment = Attachment.new
27
+ end
28
+
29
+ def create
30
+ @attachment = Attachment.new(params[:attachment])
31
+ if @attachment.save
32
+ redirect_parent_to(:action => "edit", :id => @attachment)
33
+ else
34
+ render_to_parent(:action => "new")
35
+ end
36
+ end
37
+
38
+ def edit
39
+ @attachment = Attachment.find(params[:id])
40
+ end
41
+
42
+ def update
43
+ @attachment = Attachment.find(params[:id])
44
+ if @attachment.update_attributes(params[:attachment])
45
+ redirect_parent_to(:action => "edit", :id => @attachment)
46
+ else
47
+ render_to_parent(:action => "edit")
48
+ end
49
+ end
50
+
51
+ def order
52
+ # We Need to search the correct params
53
+ ordering = params.find { |k,v| k.to_s =~ /-order$/ }[1]
54
+ ordering.each_with_index do |id, index|
55
+ Attachment.find(id).update_attributes(:position => index)
56
+ end
57
+ render :text => I18n.t("backend.texts.order_updated", :default => "Order Updated!")
58
+ rescue
59
+ render :text => "Params for ordering not found, call it some-order"
60
+ end
61
+
62
+ # Add in your model before_destroy and if the callback returns false,
63
+ # all the later callbacks and the associated action are cancelled.
64
+ def destroy
65
+ if Attachment.find(params[:id]).destroy
66
+ render :json => { :success => true }
67
+ else
68
+ render :json => { :success => false, :msg => I18n.t("backend.general.cantDelete") }
69
+ end
70
+ end
71
+ end
@@ -1,10 +1,12 @@
1
1
  class CreateAttachments < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table :attachments, :force => true do |t|
4
- t.string :attached_file_name, :attached_content_type
4
+ t.string :attached_file_name,
5
+ t.string :attached_content_type
5
6
  t.integer :attached_file_size
6
- t.references :attacher, :polymorphic => true
7
+ t.references :attacher, :polymorphic => true
7
8
  t.string :attacher_name
9
+ t.integer :position, :default => 1
8
10
  t.timestamps
9
11
  end
10
12
  end
@@ -18,6 +18,16 @@ en:
18
18
  list: "List"
19
19
  new: "New"
20
20
  help: "Help"
21
+ labels:
22
+ none: "Nothing"
23
+ add: "Add"
24
+ remove: "Remove"
25
+ upload_file: "Upload File"
26
+ upload_files: "Upload Files"
27
+ upload_image: "Upload Image"
28
+ upload_images: "Upload Images"
29
+ texts:
30
+ order_updated: Order updated!
21
31
  javascripts:
22
32
  buttons:
23
33
  add: "Add"
@@ -17,6 +17,16 @@ it:
17
17
  account: "Account"
18
18
  list: "Elenco"
19
19
  new: "Nuovo"
20
+ labels:
21
+ none: "Nessuno"
22
+ add: "Aggiungi"
23
+ remove: "Rimuovi"
24
+ upload_file: "Carica File"
25
+ upload_files: "Carica Files"
26
+ upload_image: "Carica Immagine"
27
+ upload_images: "Carica Immagini"
28
+ texts:
29
+ order_updated: L'ordine è stato aggiornato!
20
30
  javascripts:
21
31
  buttons:
22
32
  add: "Aggiungi"
@@ -1,4 +1,5 @@
1
1
  require 'digest/sha1'
2
+ require 'openssl'
2
3
  class Account < ActiveRecord::Base
3
4
  # Virtual attribute for the unencrypted password
4
5
  attr_accessor :password
@@ -86,19 +87,6 @@ class Account < ActiveRecord::Base
86
87
  def authenticated?(password)
87
88
  crypted_password.chomp == encrypt(password).chomp rescue false
88
89
  end
89
-
90
- # Gets the project modules for this accounts
91
- def maps
92
- if modules && modules.split(",").size > 0
93
- maps = AccountAccess.find_by_project_modules(modules.split(","))
94
- return maps unless maps.blank?
95
- end
96
-
97
- if !role.blank?
98
- maps = AccountAccess.find_by_role(role)
99
- return maps unless maps.blank?
100
- end
101
- end
102
90
 
103
91
  # Generate Methods takes from AccessControl rules
104
92
  # Example:
@@ -1,6 +1,6 @@
1
1
  class AccountAccess < Lipsiadmin::AccessControl::Base
2
2
 
3
- roles_for :administrator do |role|
3
+ roles_for :administrator do |role, current_account|
4
4
  # Shared Permission
5
5
  role.allow_all_actions "/backend"
6
6
  role.allow_all_actions "/backend/base"
@@ -17,6 +17,8 @@ class AccountAccess < Lipsiadmin::AccessControl::Base
17
17
  #
18
18
  # role.project_module "My Menu Name"
19
19
  #
20
+ # <tt>current_account</tt> is an instance of current logged account
21
+ #
20
22
  role.project_module :account do |project|
21
23
  project.menu :list, "/backend/accounts.js" do |submenu|
22
24
  submenu.add :new, "/backend/accounts/new"
@@ -41,12 +41,19 @@ class Backend::<%= controller_class_name %>Controller < BackendController
41
41
  end
42
42
 
43
43
  def update
44
- @<%= singular_name %> = <%= model_name %>.find(params[:id])
44
+ @<%= singular_name %> = <%= model_name %>.find(params[:id])
45
+
45
46
  if @<%= singular_name %>.update_attributes(params[:<%= singular_name %>])
46
- redirect_parent_to(:action => "edit", :id => @<%= singular_name %>)
47
+ respond_to do |format|
48
+ format.html { redirect_parent_to(:action => "edit", :id => @<%= singular_name %>) }
49
+ format.json { render :json => { :success => true } }
50
+ end
47
51
  else
48
- render_to_parent(:action => "edit")
49
- end
52
+ respond_to do |format|
53
+ format.html { render_to_parent(:action => "edit") }
54
+ format.json { render :json => { :success => false, :msg => @<%= singular_name %>.errors.full_messages.join("<br />") } }
55
+ end
56
+ end
50
57
  end
51
58
 
52
59
  # Add in your model before_destroy and if the callback returns false,
@@ -9,6 +9,7 @@ page.grid do |grid|
9
9
  grid.store do |store|
10
10
  store.url "/backend/<%= plural_name %>.json"
11
11
  store.fields @column_store.store_fields
12
+ # store.sortInfo :field => "<%= plural_name %>.created_at", :direction => "DESC"
12
13
  end
13
14
  grid.columns do |columns|
14
15
  columns.fields @column_store.column_fields
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lipsiadmin
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.3
4
+ version: 4.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Davide D'Agostino
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-21 00:00:00 +02:00
12
+ date: 2009-06-01 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -48,6 +48,7 @@ files:
48
48
  - init.rb
49
49
  - lipsiadmin_generators/attachment/attachment_generator.rb
50
50
  - lipsiadmin_generators/attachment/REMEMBER
51
+ - lipsiadmin_generators/attachment/templates/controller.rb
51
52
  - lipsiadmin_generators/attachment/templates/migration.rb
52
53
  - lipsiadmin_generators/attachment/templates/model.rb
53
54
  - lipsiadmin_generators/backend/backend_generator.rb