lipsiadmin 4.1.3 → 4.1.4

Sign up to get free protection for your applications and to get access to all the features.
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