camaleon_cms 2.4.0 → 2.4.1

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.

Potentially problematic release.


This version of camaleon_cms might be problematic. Click here for more details.

Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/assets/javascripts/camaleon_cms/admin/_custom_fields.js +2 -2
  4. data/app/assets/javascripts/camaleon_cms/admin/_post.js +1 -1
  5. data/app/assets/javascripts/camaleon_cms/admin/form/cropper.min.js +2994 -1
  6. data/app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js.coffee +72 -33
  7. data/app/controllers/camaleon_cms/admin/media_controller.rb +1 -0
  8. data/app/controllers/camaleon_cms/admin/sessions_controller.rb +2 -2
  9. data/app/controllers/camaleon_cms/admin/user_roles_controller.rb +11 -6
  10. data/app/controllers/camaleon_cms/admin/users_controller.rb +1 -1
  11. data/app/controllers/camaleon_cms/apps/plugins_front_controller.rb +1 -1
  12. data/app/controllers/concerns/camaleon_cms/frontend_concern.rb +1 -1
  13. data/app/decorators/camaleon_cms/site_decorator.rb +1 -1
  14. data/app/decorators/camaleon_cms/user_decorator.rb +1 -1
  15. data/app/decorators/camaleon_cms/user_role_decorator.rb +12 -0
  16. data/app/helpers/camaleon_cms/session_helper.rb +1 -1
  17. data/app/helpers/camaleon_cms/short_code_helper.rb +25 -7
  18. data/app/models/concerns/camaleon_cms/user_methods.rb +0 -7
  19. data/app/uploaders/camaleon_cms_aws_uploader.rb +2 -5
  20. data/app/uploaders/camaleon_cms_uploader.rb +6 -2
  21. data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +1 -1
  22. data/app/views/camaleon_cms/admin/settings/custom_fields/form.html.erb +1 -1
  23. data/app/views/camaleon_cms/admin/user_roles/form.html.erb +5 -9
  24. data/app/views/camaleon_cms/admin/user_roles/index.html.erb +3 -3
  25. data/app/views/camaleon_cms/admin/users/form.html.erb +1 -1
  26. data/app/views/camaleon_cms/admin/users/index.html.erb +2 -2
  27. data/config/locales/camaleon_cms/admin/js.yml +2 -0
  28. data/db/migrate/20161215202255_drop_user_relationship_table.rb +5 -0
  29. data/lib/camaleon_cms/version.rb +1 -1
  30. data/spec/dummy/db/schema.rb +1 -11
  31. data/spec/helpers/short_code_helper_spec.rb +64 -0
  32. metadata +6 -3
  33. data/app/models/camaleon_cms/user_relationship.rb +0 -7
@@ -32,6 +32,10 @@ window["cama_init_media"] = (media_panel) ->
32
32
  media_info.html(tpl)
33
33
  media_info.find(".p_thumb").html(item.find(".thumb").html())
34
34
  if data["format"] == "image"
35
+ if item.find('.edit_item') # add button to edit image
36
+ edit_img = $('<button type="button" class="pull-right btn btn-default" title="Edit"><i class="fa fa-pencil"></i></button>').click ->
37
+ item.find('.edit_item').trigger('click')
38
+ media_info.find('.p_footer').append(edit_img)
35
39
  draw_image = ->
36
40
  ww = parseInt(data['dimension'].split("x")[0])
37
41
  hh = parseInt(data['dimension'].split("x")[1])
@@ -46,7 +50,7 @@ window["cama_init_media"] = (media_panel) ->
46
50
  btn.prop('disabled', false)
47
51
  else
48
52
  media_info.find(".cdimension").css("color", 'red')
49
- cut = $("<button class='btn btn-info pull-right'><i class='fa fa-crop'></i> "+I18n("button.crop_image")+"</button>").click(->
53
+ cut = $("<button class='btn btn-info pull-right'><i class='fa fa-crop'></i> "+I18n("button.auto_crop")+"</button>").click(->
50
54
  crop_name = data["name"].split('.')
51
55
  crop_name[crop_name.length-2] += '_' + media_panel.attr("data-dimension")
52
56
  $.fn.upload_url({url: data["url"], name: crop_name.join('.')})
@@ -74,6 +78,10 @@ window["cama_init_media"] = (media_panel) ->
74
78
  media_panel.on("click", ".file_item", ->
75
79
  show_file($(this))
76
80
  return false
81
+ ).on('dblclick', '.file_item', -> ## auto select on double click
82
+ btn = media_info.find('.insert_btn')
83
+ if btn && !btn.attr('disabled') && !btn.attr('readonly')
84
+ btn.trigger('click')
77
85
  )
78
86
 
79
87
  media_files_panel.scroll(->
@@ -85,7 +93,9 @@ window["cama_init_media"] = (media_panel) ->
85
93
  ########## file uploader
86
94
  p_upload = media_panel.find(".cama_media_fileuploader")
87
95
  customFileData = ->
88
- return cama_media_get_custom_params()
96
+ r = cama_media_get_custom_params()
97
+ r['skip_auto_crop'] = true
98
+ return r
89
99
 
90
100
  p_upload.uploadFile({
91
101
  url: p_upload.attr("data-url"),
@@ -156,8 +166,11 @@ window["cama_init_media"] = (media_panel) ->
156
166
  showLoading()
157
167
  $.getJSON(media_panel.attr("data-url"), media_panel.data('last_req_params'), (res)->
158
168
  if data["paginate"]
159
- last_folder = media_files_panel.children('.folder_item:last')
160
- if last_folder.length ==1 then last_folder.after(res.html) else media_files_panel.append(res.html)
169
+ if media_files_panel.children('.file_item').length > 0
170
+ media_files_panel.append(res.html)
171
+ else
172
+ last_folder = media_files_panel.children('.folder_item:last')
173
+ if last_folder.length ==1 then last_folder.after(res.html) else media_files_panel.append(res.html)
161
174
  else
162
175
  media_files_panel.html(res.html)
163
176
  media_files_panel.attr('data-next-page', res.next_page)
@@ -238,8 +251,10 @@ window["cama_init_media"] = (media_panel) ->
238
251
  cropper_data = null
239
252
 
240
253
  edit_callback = (modal)->
254
+ field_width = modal.find('.export_image .with_image')
255
+ field_height = modal.find('.export_image .height_image')
241
256
  save_image = (name, same_name)->
242
- $.fn.upload_url({url: cropper.cropper('getCroppedCanvas').toDataURL('image/jpeg'), name: name, same_name: same_name, callback: (res)->
257
+ $.fn.upload_url({url: cropper.cropper('getCroppedCanvas', { width: field_width.val(), height: field_height.val() }).toDataURL('image/jpeg'), name: name, same_name: same_name, callback: (res)->
243
258
  modal.modal('hide')
244
259
  })
245
260
 
@@ -260,9 +275,11 @@ window["cama_init_media"] = (media_panel) ->
260
275
  )
261
276
 
262
277
  # save editted image
263
- save_btn = $('<button type="button" class="btn btn-default"><i class="fa fa-save"></i> '+I18n('button.save', 'Save Image')+'</button>').click(->
278
+ save_btn = modal.find('.export_image').submit(->
279
+ unless $(this).valid()
280
+ return false
264
281
  save_buttons = (modal2)->
265
- modal2.find('img.preview').attr('src', cropper.cropper('getCroppedCanvas').toDataURL('image/jpeg'))
282
+ modal2.find('img.preview').attr('src', cropper.cropper('getCroppedCanvas', { width: field_width.val(), height: field_height.val() }).toDataURL('image/jpeg'))
266
283
  modal2.find('.save_btn').click(->
267
284
  save_image(data['name'], true)
268
285
  modal2.modal('hide')
@@ -273,9 +290,16 @@ window["cama_init_media"] = (media_panel) ->
273
290
  modal2.modal('hide')
274
291
  return false
275
292
  })
276
- open_modal({zindex: 999992, id: 'media_preview_editted_image', content: '<div class="text-center" style="overflow: auto;"><img class="preview"></div><br><div class="row"><div class="col-md-4">'+(if link.attr('data-permit-overwrite') then '<button class="btn save_btn btn-default">'+I18n('button.replace_image')+'</button>' else '')+'</div><div class="col-md-8"><form class="input-group"><input type="text" class="form-control file_name required" name="file_name"><div class="input-group-btn"><button class="btn btn-primary" type="submit">'+I18n('button.save_new_image')+'</button></div></form></div></div>', callback: save_buttons})
293
+ open_modal({zindex: 999992, modal_size: 'modal-lg', id: 'media_preview_editted_image', content: '<div class="text-center" style="overflow: auto;"><img class="preview"></div><br><div class="row"><div class="col-md-4"><button class="btn save_btn btn-default">'+I18n('button.replace_image')+'</button></div><div class="col-md-8"><form class="input-group"><input type="text" class="form-control file_name required" name="file_name"><div class="input-group-btn"><button class="btn btn-primary" type="submit">'+I18n('button.save_new_image')+'</button></div></form></div></div>', callback: save_buttons})
294
+ return false
295
+ ).validate()
296
+
297
+ # custom sizes auto calculate aspect ratio
298
+ field_width.change(->
299
+ unless field_width.attr("readonly")
300
+ croper_area = modal.find('.cropper-crop-box')
301
+ field_height.val(parseInt((parseInt($(this).val()) / croper_area.width())*croper_area.height()))
277
302
  )
278
- modal.find('.editor_controls').append(save_btn)
279
303
 
280
304
  # show cropper image
281
305
  showLoading()
@@ -283,26 +307,11 @@ window["cama_init_media"] = (media_panel) ->
283
307
  setTimeout(->
284
308
  label = modal.find('.label_dimension')
285
309
  cropper_data = {data: {}, minContainerHeight: 450, modal: true, crop: (e)->
286
- dim = cropper_data['data']['dim']
287
- r = false
288
- if dim && dim[0].search(/\?/) > -1 && parseFloat(dim[0].match(/\d+/)[0]) < e.width # max width
289
- cropper.cropper('setData', {width: parseFloat(dim[0].match(/\d+/)[0])})
290
- r = true
291
-
292
- if dim && dim[1].search(/\?/) > -1 && parseFloat(dim[1].match(/\d+/)[0]) < e.height # max height
293
- cropper.cropper('setData', {height: parseFloat(dim[1].match(/\d+/)[0])})
294
- r = true
295
-
296
- if dim && dim[0] && dim[0].search(/\?/) == -1 && e.width != parseFloat(dim[0]) # same width
297
- cropper.cropper('setData', {width: parseFloat(dim[0])})
298
- r = true
299
-
300
- if dim && dim[1] && dim[1].search(/\?/) == -1 && e.height != parseFloat(dim[1]) # same width
301
- cropper.cropper('setData', {height: parseFloat(dim[1])})
302
- r = true
303
-
304
- unless r
305
- label.html(Math.round(e.width) + " x "+Math.round(e.height))
310
+ label.html(Math.round(e.width) + " x "+Math.round(e.height))
311
+ unless field_width.attr("readonly")
312
+ field_width.val(Math.round(e.width))
313
+ unless field_height.attr("readonly")
314
+ field_height.val(Math.round(e.height))
306
315
  , built: ()->
307
316
  if modal.find('.cropper-canvas img').attr('crossorigin')
308
317
  modal.find('.modal-body').html('<div class="alert alert-danger">'+I18n('msg.cors_error', 'Please verify the following: <ul><li>If the image exist: %{url_img}</li> <li>Check if cors configuration are defined well, only for external images: S3, cloudfront(if you are using cloudfront).</li></ul><br> More information about CORS: <a href="%{url_blog}" target="_blank">here.</a>', {url_img: data['url'], url_blog: 'http://blog.celingest.com/en/2014/10/02/tutorial-using-cors-with-cloudfront-and-s3/'})+'</div>')
@@ -310,20 +319,50 @@ window["cama_init_media"] = (media_panel) ->
310
319
 
311
320
  if media_panel.attr("data-dimension") # TODO: control dimensions
312
321
  dim = media_panel.attr("data-dimension").split('x')
313
- cropper_data['data']['dim'] = dim
314
322
  if dim[0]
315
323
  cropper_data['data']['width'] = parseFloat(dim[0].match(/\d+/)[0])
324
+ field_width.val(cropper_data['data']['width'])
325
+ if dim[0].search(/\?/) > -1
326
+ field_width.attr('min', cropper_data['data']['width'])
327
+ else
328
+ field_width.prop('readonly', true)
316
329
  if dim[1]
317
330
  cropper_data['data']['height'] = parseFloat(dim[1].match(/\d+/)[0])
331
+ field_height.val(cropper_data['data']['height'])
332
+ if dim[1].search(/\?/) > -1
333
+ field_height.attr('min', cropper_data['data']['height'])
334
+ else
335
+ field_height.prop('readonly', true)
318
336
  if dim[0] && dim[0].search(/\?/) == -1 && dim[1] && dim[1].search(/\?/) == -1
319
337
  cropper_data['cropBoxResizable'] = false
320
- cropper_data['zoomable'] = false
321
338
 
322
339
  cropper = modal.find('img.editable').cropper(cropper_data)
323
340
  hideLoading()
324
341
  , 300)
325
342
  )
326
- open_modal({zindex: 999991, id: 'media_panel_editor_image', title: 'Edit Image - ' + data['name'], content: '<div><div class="editable_wrapper"><img style="max-width: 100%;" class="editable" id="media_editable_image" src="'+data['url']+'"></div><div class="editor_controls btn-group"></div><span class="label label-default pull-right label_dimension"></span></div>', callback: edit_callback, modal_size: 'modal-lg'})
343
+ open_modal({
344
+ zindex: 999991,
345
+ id: 'media_panel_editor_image',
346
+ title: I18n('button.edit_image', 'Edit Image')+' - ' + data['name'] + (if media_panel.attr("data-dimension") then " <small><i>("+media_panel.attr("data-dimension")+")</i></small>" else ''),
347
+ content: '<div>' +
348
+ '<div class="editable_wrapper">' +
349
+ '<img style="max-width: 100%;" class="editable" id="media_editable_image" src="'+data['url']+'">' +
350
+ '</div>' +
351
+ '<div class="row" style="margin-top: 5px;">' +
352
+ '<div class="col-md-8">' +
353
+ '<div class="editor_controls btn-group"></div>' +
354
+ '</div>' +
355
+ '<div class="col-md-4">' +
356
+ '<form class="export_image"> ' +
357
+ '<div class="input-group"><input class="form-control with_image data-error-place-parent required number" placeholder="Width"><span class="input-group-addon">x</span>' +
358
+ '<input class="form-control height_image data-error-place-parent required number" placeholder="Height"> ' +
359
+ '<span class="input-group-btn"><button class="btn btn-primary save_image" type="submit"><i class="fa fa-save"></i> '+I18n('button.save', 'Save Image')+'</button> </span> </div>' +
360
+ '</form>' +
361
+ '</div>' +
362
+ '</div>' +
363
+ '<!--span class="label label-default pull-right label_dimension"></span-->' +
364
+ '</div>',
365
+ callback: edit_callback, modal_size: 'modal-lg'})
327
366
  return false
328
367
  )
329
368
 
@@ -331,7 +370,7 @@ window["cama_init_media"] = (media_panel) ->
331
370
  media_panel.find("#cama_media_external").submit( ->
332
371
  unless $(this).valid()
333
372
  return false
334
- $.fn.upload_url({url: $(this).find("input").val(), callback: ->
373
+ $.fn.upload_url({url: $(this).find("input").val(), skip_auto_crop: true, callback: ->
335
374
  media_panel.find("#cama_media_external")[0].reset();
336
375
  })
337
376
  return false
@@ -78,6 +78,7 @@ class CamaleonCms::Admin::MediaController < CamaleonCms::AdminController
78
78
 
79
79
  # upload files from media uploader
80
80
  def upload(settings = {})
81
+ params[:dimension] = nil if params[:skip_auto_crop].present?
81
82
  f = {error: "File not found."}
82
83
  if params[:file_upload].present?
83
84
  f = upload_file(params[:file_upload], {folder: params[:folder], dimension: params['dimension'], formats: params[:formats], versions: params[:versions], thumb_size: params[:thumb_size]}.merge(settings))
@@ -30,7 +30,7 @@ class CamaleonCms::Admin::SessionsController < CamaleonCms::CamaleonController
30
30
  cama_captcha_reset_attack("login")
31
31
  r={user: @user, redirect_to: params[:format] == 'json' ? false : nil}; hooks_run('after_login', r)
32
32
  login_user(@user, params[:remember_me].present?, r[:redirect_to])
33
- render(json: flash.to_hash) if params[:format] == 'json'
33
+ render(json: flash.discard.to_hash) if params[:format] == 'json'
34
34
  return
35
35
  else
36
36
  flash[:error] = t('camaleon_cms.admin.login.message.email_not_validated')
@@ -47,7 +47,7 @@ class CamaleonCms::Admin::SessionsController < CamaleonCms::CamaleonController
47
47
  @user = current_site.users.new(data_user)
48
48
  login if params[:format] != 'json'
49
49
  end
50
- render(json: flash.to_hash) if params[:format] == 'json'
50
+ render(json: flash.discard.to_hash) if params[:format] == 'json'
51
51
  end
52
52
 
53
53
  def logout
@@ -37,9 +37,11 @@ class CamaleonCms::Admin::UserRolesController < CamaleonCms::AdminController
37
37
  end
38
38
 
39
39
  def update
40
- if @user_role.editable? && @user_role.update(params.require(:user_role).permit!)
41
- @user_role.set_meta("_post_type_#{current_site.id.to_s}", defined?(params[:rol_values][:post_type]) ? params[:rol_values][:post_type] : {})
42
- @user_role.set_meta("_manager_#{current_site.id.to_s}", defined?(params[:rol_values][:post_type]) ? params[:rol_values][:manager] : {})
40
+ if @user_role.update(params.require(:user_role).permit!)
41
+ if @user_role.editable?
42
+ @user_role.set_meta("_post_type_#{current_site.id.to_s}", defined?(params[:rol_values][:post_type]) ? params[:rol_values][:post_type] : {})
43
+ @user_role.set_meta("_manager_#{current_site.id.to_s}", defined?(params[:rol_values][:post_type]) ? params[:rol_values][:manager] : {})
44
+ end
43
45
  flash[:notice] = t('camaleon_cms.admin.users.message.rol_updated')
44
46
  redirect_to action: :edit, id: @user_role.id
45
47
  else
@@ -48,8 +50,11 @@ class CamaleonCms::Admin::UserRolesController < CamaleonCms::AdminController
48
50
  end
49
51
 
50
52
  def destroy
51
- @user_role.destroy
52
- flash[:notice] = t('camaleon_cms.admin.users.message.rol_deleted')
53
+ if @user_role.editable? && @user_role.destroy
54
+ flash[:notice] = t('camaleon_cms.admin.users.message.rol_deleted')
55
+ else
56
+ flash[:error] = t('camaleon_cms.admin.users.message.role_can_not_be_deleted', default: 'This role can not be deleted')
57
+ end
53
58
  redirect_to action: :index
54
59
  end
55
60
 
@@ -60,7 +65,7 @@ class CamaleonCms::Admin::UserRolesController < CamaleonCms::AdminController
60
65
 
61
66
  def set_user_roles
62
67
  begin
63
- @user_role = current_site.user_roles.find(params[:id])
68
+ @user_role = current_site.user_roles.find(params[:id]).decorate
64
69
  rescue
65
70
  flash[:error] = t('camaleon_cms.admin.users.message.rol_error')
66
71
  redirect_to action: :index
@@ -5,7 +5,7 @@ class CamaleonCms::Admin::UsersController < CamaleonCms::AdminController
5
5
 
6
6
  def index
7
7
  add_breadcrumb I18n.t("camaleon_cms.admin.users.list_users")
8
- @users = current_site.users.paginate(:page => params[:page], :per_page => current_site.admin_per_page)
8
+ @users = current_site.users.paginate(:page => params[:page], :per_page => current_site.admin_per_page).decorate
9
9
  end
10
10
 
11
11
  def profile
@@ -8,7 +8,7 @@ class CamaleonCms::Apps::PluginsFrontController < CamaleonCms::FrontendControlle
8
8
  @plugin = current_site.plugins.where(slug: plugin_name).first_or_create
9
9
  unless @plugin.active?
10
10
  flash[:error] = t("camaleon_cms.plugin_not_installed", default: "This plugin is not installed, please contact to the administrator.")
11
- params[:format] == 'json' ? render(json: flash.to_hash) : (redirect_to cama_root_url)
11
+ params[:format] == 'json' ? render(json: flash.discard.to_hash) : (redirect_to cama_root_url)
12
12
  return
13
13
  end
14
14
  if !@plugin.settings["gem_mode"].present?
@@ -56,6 +56,6 @@ module CamaleonCms::FrontendConcern extend ActiveSupport::Concern
56
56
  else
57
57
  flash[:error] = t('camaleon_cms.admin.message.unauthorized')
58
58
  end
59
- params[:format] == 'json' ? render(json: flash.to_hash) : redirect_to(:back)
59
+ params[:format] == 'json' ? render(json: flash.discard.to_hash) : redirect_to(:back)
60
60
  end
61
61
  end
@@ -133,7 +133,7 @@ class CamaleonCms::SiteDecorator < CamaleonCms::TermTaxonomyDecorator
133
133
  # return the role_id of current visitor for this site
134
134
  # if the visitor was not logged in, then return -1
135
135
  def visitor_role
136
- h.signin? ? h.cama_current_user.get_role(object).slug : "-1"
136
+ h.signin? ? h.cama_current_user.role : '-1'
137
137
  end
138
138
 
139
139
  # check if plugin_key is already installed for this site
@@ -14,7 +14,7 @@ class CamaleonCms::UserDecorator < CamaleonCms::ApplicationDecorator
14
14
 
15
15
  # return the role title of this user for current site
16
16
  def the_role
17
- object.get_role(h.current_site).name.titleize
17
+ object.get_role(h.current_site).try(:decorate).try(:the_title) || ''
18
18
  end
19
19
 
20
20
  # return the avatar for this user, default: assets/admin/img/no_image.jpg
@@ -0,0 +1,12 @@
1
+ class CamaleonCms::UserRoleDecorator < CamaleonCms::ApplicationDecorator
2
+ include CamaleonCms::CustomFieldsConcern
3
+ delegate_all
4
+
5
+ def the_title
6
+ object.name.to_s.translate(get_locale)
7
+ end
8
+
9
+ def the_content
10
+ object.description.to_s.translate(get_locale)
11
+ end
12
+ end
@@ -110,7 +110,7 @@ module CamaleonCms::SessionHelper
110
110
  # return the role for current user
111
111
  # if not logged in, then return 'public'
112
112
  def cama_current_role
113
- (cama_sign_in?) ? cama_current_user.role : 'public'
113
+ current_site.visitor_role
114
114
  end
115
115
 
116
116
  # return current user logged in
@@ -10,11 +10,15 @@ module CamaleonCms::ShortCodeHelper
10
10
  Sample: [widget widget_key]")
11
11
 
12
12
  shortcode_add("load_libraries",
13
- lambda{|attrs, args| cama_load_libraries(*attrs["data"].to_s.split(",")); return ""; },
13
+ lambda{|attrs, args|
14
+ return args[:shortcode] unless attrs.present?
15
+ cama_load_libraries(*attrs["data"].to_s.split(",")); return "";
16
+ },
14
17
  "Permit to load libraries on demand, sample: [load_libraries data='datepicker,tinymce']")
15
18
 
16
19
  shortcode_add("asset",
17
20
  lambda{|attrs, args|
21
+ return args[:shortcode] unless attrs.present?
18
22
  url = attrs["as_path"].present? ? ActionController::Base.helpers.asset_url(attrs["file"]) : ActionController::Base.helpers.asset_url(attrs["file"])
19
23
  if attrs["image"].present?
20
24
  ActionController::Base.helpers.image_tag(attrs["file"], class: attrs["class"], style: attrs["style"])
@@ -32,7 +36,7 @@ module CamaleonCms::ShortCodeHelper
32
36
 
33
37
  shortcode_add("data",
34
38
  lambda{|attrs, args|
35
- cama_shortcode_data(attrs, args) rescue ""
39
+ attrs.present? ? (cama_shortcode_data(attrs, args) rescue "") : args[:shortcode]
36
40
  },
37
41
  "Permit to generate specific data of a post.
38
42
  Attributes:
@@ -96,8 +100,7 @@ module CamaleonCms::ShortCodeHelper
96
100
  def do_shortcode(content, args = {})
97
101
  args = {owner: args} unless args.is_a?(Hash)
98
102
  content.scan(/#{cama_reg_shortcode}/) do |item|
99
- shortcode, code, space, attrs = item
100
- content = content.sub(shortcode, _eval_shortcode(code, attrs, args))
103
+ content = _cama_replace_shortcode(content, item, args)
101
104
  end
102
105
  content
103
106
  end
@@ -118,20 +121,35 @@ module CamaleonCms::ShortCodeHelper
118
121
  # render_shortcode("asda dasdasdas[owen a='1'] [bbb] sdasdas dasd as das[owen a=213]", "owen", lambda{|attrs, args| puts attrs; return "my test"; })
119
122
  def render_shortcode(text, key, template = nil)
120
123
  text.scan(/#{cama_reg_shortcode(key)}/).each do |item|
121
- shortcode, code, space, attrs = item
122
- text = text.sub(shortcode, _eval_shortcode(code, attrs, {}, template))
124
+ text = _cama_replace_shortcode(text, item, {}, template)
123
125
  end
124
126
  text
125
127
  end
126
128
 
127
129
  private
130
+ # helper to replace shortcodes adding support for closed shortcodes, sample: [title]my title[/title]
131
+ def _cama_replace_shortcode(content, item, args = {}, template = nil)
132
+ shortcode, code, attrs = item
133
+ close_code = "[/#{code}]"
134
+ if content.include?(close_code)
135
+ shortcode_bk = shortcode
136
+ tmp_content = content[content.index(shortcode)..-1]
137
+ shortcode = tmp_content[0..(tmp_content.index(close_code) + close_code.size - 1)]
138
+ args[:shortcode_content] = shortcode.sub(shortcode_bk, '').sub(close_code, '')
139
+ end
140
+ args[:shortcode] = shortcode
141
+ args[:code] = code
142
+ content.sub(shortcode, _eval_shortcode(code, attrs, args, template))
143
+ end
144
+
128
145
  # create the regexpression for shortcodes
129
146
  # codes: (String) shortcode keys separated by |
130
147
  # sample: load_libraries|asset
131
148
  # if empty, codes will be replaced with all registered shortcodes
132
149
  # Return: (String) reg expression string
133
150
  def cama_reg_shortcode(codes = nil)
134
- "(\\[(#{codes || (@_shortcodes || []).join("|")})(\s|\\]){0}(.*?)\\])"
151
+ # "(\\[(#{codes || (@_shortcodes || []).join("|")})(\s|\\]){0}(.*?)\\])" # doesn't support for similar names, like: [media] and [media_gallery]
152
+ "(\\[(#{codes || (@_shortcodes || []).join("|")})((\s)((?!\\]).)*|)\\])"
135
153
  end
136
154
 
137
155
  # determine the content to replace instead the shortcode
@@ -27,8 +27,6 @@ module CamaleonCms::UserMethods extend ActiveSupport::Concern
27
27
  # relations
28
28
 
29
29
  has_many :metas, ->{ where(object_class: 'User')}, :class_name => "CamaleonCms::Meta", foreign_key: :objectid, dependent: :destroy
30
- has_many :user_relationships, class_name: "CamaleonCms::UserRelationship", foreign_key: :user_id, dependent: :destroy#, inverse_of: :user
31
- has_many :term_taxonomies, foreign_key: :term_taxonomy_id, class_name: "CamaleonCms::TermTaxonomy", through: :user_relationships, :source => :term_taxonomies
32
30
  has_many :all_posts, class_name: "CamaleonCms::Post"
33
31
 
34
32
  #scopes
@@ -86,11 +84,6 @@ module CamaleonCms::UserMethods extend ActiveSupport::Concern
86
84
  end
87
85
  end
88
86
 
89
- # DEPRECATED, please use user.the_role
90
- def roleText
91
- User::ROLE[self.role]
92
- end
93
-
94
87
  def created
95
88
  self.created_at.strftime('%d/%m/%Y %H:%M')
96
89
  end
@@ -21,15 +21,12 @@ class CamaleonCmsAwsUploader < CamaleonCmsUploader
21
21
  objects
22
22
  end
23
23
 
24
- def objects(prefix = '/')
24
+ def objects(prefix = '/', sort = 'created_at')
25
25
  if @aws_settings["inner_folder"].present?
26
26
  prefix = "#{@aws_settings["inner_folder"]}/#{prefix}".gsub('//', '/')
27
27
  prefix = prefix[0..-2] if prefix.end_with?('/')
28
28
  end
29
-
30
- prefix = "/#{prefix}" unless prefix.starts_with?('/')
31
- db = @current_site.get_meta(cache_key, nil) || browser_files
32
- db[prefix.gsub('//', '/')] || {files: {}, folders: {}}
29
+ super(prefix, sort)
33
30
  end
34
31
 
35
32
  # parse an AWS file into custom file_object
@@ -18,10 +18,14 @@ class CamaleonCmsUploader
18
18
  # return all files structure, within folder prefix
19
19
  # return json like:
20
20
  # {files: {'file_name': {'name'=> 'a.jpg', key: '/test/a.jpg', url: '', url: '', size: '', format: '', thumb: 'thumb_url', type: '', created_at: '', dimension: '120x120'}}, folders: {'folder name' => {name: 'folder name', key: '/folder name', ...}}}
21
- def objects(prefix = '/')
21
+ # sort: (String, default 'created_at'), accept for: created_at | name | size | type | format
22
+ def objects(prefix = '/', sort = 'created_at')
22
23
  prefix = "/#{prefix}" unless prefix.starts_with?('/')
23
24
  db = @current_site.get_meta(cache_key, nil) || browser_files
24
- db[prefix.gsub('//', '/')] || {files: {}, folders: {}}
25
+ res = db[prefix.gsub('//', '/')] || {files: {}, folders: {}}
26
+ res[:files] = res[:files].sort_by{|k, v| v[sort] }.reverse.to_h
27
+ res[:folders] = res[:folders].sort_by{|k, v| v['name'] }.reverse.to_h
28
+ res
25
29
  end
26
30
 
27
31
  # clean cached of files structure saved into DB