drg_cms 0.5.6 → 0.5.7

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +17 -2
  3. data/app/assets/stylesheets/drg_cms/drg_cms.css +197 -68
  4. data/app/controllers/cmsedit_controller.rb +3 -3
  5. data/app/controllers/dc_application_controller.rb +71 -43
  6. data/app/forms/cms_menu.yml +42 -55
  7. data/app/forms/dc_page.yml +1 -1
  8. data/app/forms/dc_site.yml +8 -0
  9. data/app/helpers/cmsedit_helper.rb +8 -2
  10. data/app/helpers/dc_application_helper.rb +58 -12
  11. data/app/helpers/dc_common_renderer.rb +5 -4
  12. data/app/helpers/dc_menu_renderer.rb +2 -2
  13. data/app/helpers/dc_page_renderer.rb +3 -1
  14. data/app/helpers/dc_part_renderer.rb +41 -1
  15. data/app/helpers/dc_simple_menu_renderer.rb +2 -1
  16. data/app/models/dc_page.rb +0 -2
  17. data/app/models/dc_site.rb +4 -0
  18. data/app/models/drgcms_form_fields.rb +27 -18
  19. data/app/views/cmsedit/_edit_stuff.html.erb +54 -38
  20. data/app/views/cmsedit/_form.html.erb +1 -1
  21. data/app/views/cmsedit/edit.html.erb +0 -1
  22. data/app/views/cmsedit/login.html.erb +2 -1
  23. data/app/views/cmsedit/{_edit_stuff.js.erb → remove_edit_stuff.js.erb} +0 -0
  24. data/app/views/layouts/{cmsedit.html.erb → __cmsedit.html.erb} +0 -0
  25. data/app/views/layouts/cms.html.erb +3 -1
  26. data/app/views/layouts/content.html.erb +1 -1
  27. data/config/locales/drgcms_en.yml +2 -0
  28. data/config/locales/drgcms_sl.yml +2 -0
  29. data/config/locales/models_en.yml +4 -1
  30. data/config/locales/models_sl.yml +3 -1
  31. data/lib/drg_cms/version.rb +1 -1
  32. data/lib/tasks/dc_at_the_beginning.rake +5 -5
  33. data/lib/tasks/dc_cleanup.rake +8 -2
  34. metadata +4 -4
@@ -425,9 +425,9 @@ def update
425
425
  if save_data
426
426
  params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
427
427
  @parms['action'] = 'update'
428
- end
429
428
  # Process return_to link
430
- return process_return_to(params[:return_to]) if params[:return_to]
429
+ return process_return_to(params[:return_to]) if params[:return_to]
430
+ end
431
431
  else
432
432
  flash[:error] = t('drgcms.not_authorized')
433
433
  end
@@ -756,7 +756,7 @@ def save_data
756
756
  # dont's save if callback method returns false
757
757
  return false if ret.class == FalseClass
758
758
  end
759
- # maybe model has dc_before_save method defined. Call it.
759
+ # maybe model has dc_before_save method defined. Call it. This was before callback
760
760
  @record.dc_before_save(self) if @record.respond_to?('dc_before_save')
761
761
  #
762
762
  changes = @record.changes
@@ -229,13 +229,38 @@ def dc_set_options(parameters)
229
229
  parameters.split("\n").each do |line|
230
230
  line.chomp.split(',').each do |parm|
231
231
  key, value = parm.split(':')
232
- parms[key.strip] = value.to_s.strip.gsub(/\'|\"/,'')
232
+ value = value.to_s.strip.gsub(/\'|\"/,'')
233
+ parms[key.strip] = (value == '/' ? nil : value)
233
234
  end
234
235
  end
235
236
  end
236
237
  @options.merge!(parms)
237
238
  end
238
239
 
240
+ ##########################################################################
241
+ # Check if document(s) has been modified since last visit.
242
+ # [Parameters:]
243
+ # [Documents]: List of documents which are checked against last visit date. If
244
+ # document
245
+ ##########################################################################
246
+ def dc_not_modified?(*documents)
247
+ # request.env.each {|k,v| p k,'*',v}
248
+ return false unless request.env.include? 'HTTP_IF_MODIFIED_SINCE'
249
+
250
+ since_date = Time.parse request.env['HTTP_IF_MODIFIED_SINCE']
251
+ last_modified = since_date
252
+ documents.each do |doc|
253
+ next unless doc.respond_to?(:updated_at)
254
+ last_modified = doc.updated_at if doc.updated_at > last_modified
255
+ end
256
+ # p last_modified, since_date
257
+ if last_modified >= since_date then
258
+ render :nothing => true, :status => 304
259
+ return true
260
+ end
261
+ false
262
+ end
263
+
239
264
  ##########################################################################
240
265
  # This is default page process action. It will search for site, page and
241
266
  # design documents, collect parameters from different objects, add CMS edit code if allowed
@@ -301,20 +326,58 @@ def dc_process_default_request()
301
326
  dc_log_visit()
302
327
  end
303
328
  @page_title = @page.title.blank? ? "#{@site.page_title}-#{@page.subject}" : @page.title
304
- layout = @site.site_layout.to_s.size > 2 ? @site.site_layout : 'content'
329
+ layout = @site.site_layout.blank? ? 'content' : @site.site_layout
330
+ design = @design ? @design.body : @site.design
305
331
  # render view. inline if defined in design
306
- view_filename = ''
307
- view_filename = @design.rails_view.to_s if @design
308
- view_filename = @site.rails_view.to_s if view_filename.size < 5
332
+ view_filename = @design ? @design.rails_view.to_s : ''
333
+ view_filename = @site.rails_view.to_s if view_filename.blank?
309
334
  if view_filename.size < 5
310
- @design.body = "<%= render partial: 'cmsedit/edit_stuff' %>\n" + @design.body if session[:edit_mode] > 0
311
- @design.body << '<style type="text/css"><%= @css.html_safe %></style><%= javascript_tag @js %>'
312
- render(inline: @design.body, layout: layout)
335
+ design = "<%= render partial: 'cmsedit/edit_stuff' %>\n" + design if session[:edit_mode] > 0
336
+ design << '<style type="text/css"><%= @css.html_safe %></style><%= javascript_tag @js %>'
337
+ render(inline: design, layout: layout)
313
338
  else
314
339
  render view_filename, layout: layout
315
340
  end
316
341
  end
317
342
 
343
+ ##########################################################################
344
+ # Single site document kind of request handler.
345
+ #
346
+ # This request handler assumes that all data for the site is saved in the site document.
347
+ #
348
+ # Page data is saved in dc_parts documents embedded into site document.
349
+ # Menus are created from description fields.
350
+ # Menu links are created from link fields.
351
+ #
352
+ # This kind of page may be good candidate for caching.
353
+ # # Just a reminder: request.session_options[:skip] = true
354
+ ##########################################################################
355
+ def dc_single_sitedoc_request
356
+ session[:edit_mode] ||= 0
357
+ @site = dc_get_site
358
+ # @site is not defined. render 404 error
359
+ return dc_render_404('Site!') unless @site
360
+ dc_set_options(@site.settings)
361
+ # HOMEPAGE. When no parameters is set
362
+ params[:path] = @site.homepage_link if params[:path].nil?
363
+ @parts = @site.dc_parts
364
+ @part = @parts.find_by(link: params[:path])
365
+ return dc_render_404('Part!') unless @part
366
+ # Document was not modified since last visit
367
+ # return if dc_not_modified?(@site, @part)
368
+ #
369
+ @page_title = "#{@site.page_title} #{@part.name}"
370
+ @js, @css = '', ''
371
+ layout = @site.site_layout.blank? ? 'content' : @site.site_layout
372
+ if @site.rails_view.blank?
373
+ design = @site.design + '<style type="text/css"><%= @css.html_safe %></style><%= javascript_tag @js %>'
374
+ design = "<%= render partial: 'cmsedit/edit_stuff' %>\n" + design if session[:edit_mode] > 0
375
+ render(inline: design, layout: layout)
376
+ else
377
+ render @site.rails_view, layout: layout
378
+ end
379
+ end
380
+
318
381
  ########################################################################
319
382
  # Decamelizes string. Does oposite from camelize method. It probably doesn't work
320
383
  # very good with non ascii chars. Since this method is used for converting from model
@@ -410,41 +473,6 @@ def dc_call_rake(task, options = {})
410
473
  system "rake #{task} #{args.join(' ')} --trace 2>&1 >> #{Rails.root}/log/rake.log &"
411
474
  end
412
475
 
413
- ######################################################################
414
- # Small helper for rendering ajax return code from controller. When ajax call is
415
- # made from DRG CMS form return may be quite complicated. All ajax return combinations
416
- # can be found in drg_cms.js file.
417
- #
418
- # [Parameters:]
419
- # [Hash opts] Different options
420
- #
421
- # [Return:]
422
- # String. Formatted to be used on ajax return.
423
- #
424
- # [Example:]
425
- # html_code = '<span>Some text</span>'
426
- # dc_render_ajax(div: 'mydiv', prepand: html_code) # Will prepand code to mydiv div
427
- # dc_render_ajax(class: 'myclass', append: html_code) # Will append code to all objects with myclass class
428
- # dc_render_ajax(operation: 'window', value: "/pdf_file.pdf") # will open pdf file in new window.
429
- #
430
- ######################################################################
431
- def dc_render_ajax(opts)
432
- result = {}
433
- if opts[:operation].to_s == 'div' or opts[:operation].to_s == 'class'
434
- selector = opts[:operation].to_s == 'div' ? '#' : '.' # for div . for class
435
- key = case
436
- when opts[:prepend] then "#{selector}+div"
437
- when opts[:append] then "#{selector}div+"
438
- else "#{selector}div"
439
- end
440
- key << '_' + opts[ opts[:operation].to_sym ]
441
- else
442
- key = opts[:operation] + '_'
443
- end
444
- result[key] = opts[:value] || opts[:url] || ''
445
- render inline: result.to_json, formats: 'js'
446
- end
447
-
448
476
  ######################################################################
449
477
  # Small helper for rendering ajax return code from controller. When ajax call is
450
478
  # made from DRG CMS form return may be quite complicated. All ajax return combinations
@@ -22,104 +22,91 @@
22
22
  #++
23
23
 
24
24
  menu:
25
- 50_system_menu:
25
+ 10_system_menu:
26
26
  caption: drgcms.system_menu
27
+ icon: support lg
28
+
27
29
  items:
28
30
  10:
29
31
  caption: helpers.label.dc_site.tabletitle
30
32
  controller: cmsedit
31
- picture: dc_site.png
32
- params:
33
- table: dc_site
33
+ icon: globe lg
34
+ table: dc_site
34
35
  20:
35
36
  caption: helpers.label.dc_design.tabletitle
36
37
  controller: cmsedit
37
- picture: dc_design.png
38
- params:
39
- table: dc_design
38
+ icon: credit-card lg
39
+ table: dc_design
40
40
  30:
41
41
  caption: helpers.label.dc_page.tabletitle
42
42
  controller: cmsedit
43
- picture: dc_page.png
44
- params:
45
- table: dc_page
43
+ icon: file-text-o lg
44
+ table: dc_page
46
45
  40:
47
- caption: helpers.label.dc_category.tabletitle
46
+ caption: helpers.label.dc_user.tabletitle
48
47
  controller: cmsedit
49
- picture: dc_category.png
50
- params:
51
- table: dc_category
48
+ icon: users lg
49
+ table: dc_user
52
50
  50:
53
- caption: helpers.label.dc_user.tabletitle
51
+ caption: helpers.label.dc_piece.tabletitle
54
52
  controller: cmsedit
55
- picture: dc_user.png
56
- params:
57
- table: dc_user
53
+ icon: puzzle-piece lg
54
+ table: dc_piece
58
55
  60:
59
- caption: helpers.label.dc_piece.tabletitle
56
+ caption: helpers.label.dc_link.tabletitle
60
57
  controller: cmsedit
61
- picture: dc_piece.png
62
- params:
63
- table: dc_piece
58
+ icon: link lg
59
+ table: dc_link
64
60
  70:
65
- caption: helpers.label.dc_link.tabletitle
61
+ caption: helpers.label.dc_menu.tabletitle
66
62
  controller: cmsedit
67
- picture: dc_link.png
68
- params:
69
- table: dc_link
63
+ icon: th-list lg
64
+ table: dc_menu
70
65
  80:
71
- caption: helpers.label.dc_menu.tabletitle
66
+ caption: helpers.label.dc_simple_menu.tabletitle
72
67
  controller: cmsedit
73
- picture: dc_menu.png
74
- params:
75
- table: dc_menu
68
+ icon: ellipsis-h lg
69
+ table: dc_simple_menu
76
70
  90:
77
- caption: helpers.label.dc_simple_menu.tabletitle
71
+ caption: helpers.label.dc_category.tabletitle
78
72
  controller: cmsedit
79
- picture: dc_simple_menu.png
80
- params:
81
- table: dc_simple_menu
73
+ icon: list lg
74
+ table: dc_category
75
+
82
76
  100:
83
77
  caption: helpers.label.dc_poll.tabletitle
84
78
  controller: cmsedit
85
- picture: dc_poll.png
86
- params:
87
- table: dc_poll
79
+ icon: list-alt lg
80
+ table: dc_poll
88
81
  110:
89
82
  caption: helpers.label.dc_ad.tabletitle
90
83
  controller: cmsedit
91
- picture: dc_ad.png
92
- params:
93
- table: dc_ad
84
+ icon: money lg
85
+ table: dc_ad
94
86
  120:
95
87
  caption: helpers.label.dc_big_table.tabletitle
96
88
  controller: cmsedit
97
- picture: dc_big_table.png
98
- params:
99
- table: dc_big_table
89
+ icon: table lg
90
+ table: dc_big_table
100
91
  130:
101
92
  caption: helpers.label.dc_policy_role.tabletitle
102
93
  controller: cmsedit
103
- picture: dc_policy_role.png
104
- params:
105
- table: dc_policy_role
94
+ icon: user-secret lg
95
+ table: dc_policy_role
106
96
  140:
107
97
  caption: helpers.label.dc_permission.tabletitle
108
98
  controller: cmsedit
109
- picture: dc_permission.png
110
- params:
111
- table: dc_permission
99
+ icon: shield lg
100
+ table: dc_permission
112
101
  150:
113
102
  caption: helpers.label.dc_folder_permission.tabletitle
114
103
  controller: cmsedit
115
- picture: dc_permission.png
116
- params:
117
- table: dc_folder_permission
104
+ icon: shield lg
105
+ table: dc_folder_permission
118
106
  160:
119
107
  caption: helpers.label.dc_journal.tabletitle
120
108
  controller: cmsedit
121
- picture: dc_journal.png
122
- params:
123
- table: dc_journal
109
+ icon: undo lg
110
+ table: dc_journal
124
111
 
125
112
 
@@ -3,7 +3,7 @@
3
3
  table: dc_page
4
4
 
5
5
  index:
6
- filter: subject, sub_subject as text_field, subject_link, author_name, body as text_field
6
+ filter: subject, sub_subject as text_field, subject_link, author_name, dc_site_id, body as text_field
7
7
  actions: standard
8
8
 
9
9
  result_set:
@@ -156,4 +156,12 @@ form:
156
156
  formname: dc_policy
157
157
  html:
158
158
  height: 800
159
+ 6parts:
160
+ 10:
161
+ name: dc_parts
162
+ type: embedded
163
+ formname: dc_part
164
+ html:
165
+ height: 1000
166
+
159
167
 
@@ -400,7 +400,11 @@ def dc_columns_for_result(document)
400
400
  value = if v['eval']
401
401
  if v['eval'].match('dc_name4_id')
402
402
  a = v['eval'].split(',')
403
- dc_name4_id(a[1], a[2], document[ v['name'] ])
403
+ if a.size == 3
404
+ dc_name4_id(a[1], a[2], nil, document[ v['name'] ])
405
+ else
406
+ dc_name4_id(a[1], a[2], a[3], document[ v['name'] ])
407
+ end
404
408
  elsif v['eval'].match('dc_name4_value')
405
409
  dc_name4_value( @form['table'], v['name'], document[ v['name'] ] )
406
410
  elsif v['eval'].match('eval ')
@@ -563,13 +567,15 @@ def dc_actions_for_form()
563
567
  v['caption'] ||= v['text']
564
568
  caption = t("#{v['caption'].downcase}", v['caption'])
565
569
  url = url_for(parms)
570
+ p url
566
571
  request = v['request'] || v['method'] || 'get'
567
572
  icon = v['icon'] ? "#{fa_icon(v['icon'])} " : ''
568
573
  if v['type'] == 'ajax' # ajax button
569
574
  %Q[<td class="dc-link-ajax dc-animate" id="dc-submit-ajax" data-url="#{url}"
570
575
  data-request="#{request}" title="#{v['title']}">#{icon}#{caption}</td>]
571
576
  else # link button
572
- %Q[<td class="dc-link dc-animate" title="#{v['title']}><a href="#{url}">#{icon}#{caption}</a></td>]
577
+ # %Q[<td class="dc-link dc-animate" title="#{v['title']}><a href="#{url}">#{icon}#{caption}</a></td>]
578
+ %Q[<td class="dc-link dc-animate">#{dc_link_to(v['caption'],v['icon'], parms)}</td>]
573
579
  end
574
580
  end
575
581
  # Javascript action
@@ -43,6 +43,8 @@ attr_reader :ids
43
43
  attr_reader :form
44
44
  # options object
45
45
  attr_reader :options
46
+ # part
47
+ attr_reader :part
46
48
 
47
49
  # page title
48
50
  attr_accessor :page_title
@@ -577,25 +579,32 @@ end
577
579
  # Parameters:
578
580
  # [model] String. Table (collection) model name (lowercase).
579
581
  # [field] String. Field name holding the value of descriptive text.
580
- # [id] BSON Key. Key value.
582
+ # [field_name] String. ID field name. This is by default id, but can be any other
583
+ # (preferred unique) field.
584
+ # [value] Value of id_field. Usually a BSON Key but can be any other data type.
581
585
  #
582
586
  # Example:
583
587
  # # usage in program.
584
- # dc_name4_id('dc_user', 'name', dc_page.created_by)
588
+ # dc_name4_id('dc_user', 'name', nil, dc_page.created_by)
585
589
  #
586
590
  # # usage in form
587
591
  # columns:
588
592
  # 2:
589
593
  # name: site_id
590
594
  # eval: dc_name4_id,site,name
595
+ # # username is saved to document instead of user.id field
596
+ # 5:
597
+ # name: user
598
+ # eval: dc_name4_id,dc_user,name,username
591
599
  #
592
600
  # Returns:
593
601
  # String. Name (descriptive value) for specified key in table.
594
602
  ############################################################################
595
- def dc_name4_id(model, field, id)
603
+ def dc_name4_id(model, field, field_name, id=nil)
596
604
  return '' if id.nil?
605
+ field_name = 'id' if field_name.nil?
597
606
  model = model.classify.constantize if model.class == String
598
- rec = Mongoid::QueryCache.cache { model.find_by(id: id) }
607
+ rec = Mongoid::QueryCache.cache { model.find_by(field_name.to_sym => id) }
599
608
  rec.nil? ? '' : rec[field]
600
609
  end
601
610
 
@@ -712,7 +721,7 @@ def dc_choices4_all_collections
712
721
  next unless section.last['items'] # next if no items
713
722
  section.last['items'].each do |k, v| # look for caption and
714
723
  key = v['params']['table']
715
- choices[key] ||= "#{t(v['caption'], v['caption'])} - #{key}"
724
+ choices[key] ||= "#{key} - #{t(v['caption'], v['caption'])}"
716
725
  end
717
726
  end
718
727
  end
@@ -753,7 +762,7 @@ def dc_choices4_cmsmenu()
753
762
  menus.to_a.sort.each do |one_menu| # sort menus, result is array of sorted hashes
754
763
  menu = one_menu[1] # value is the second (1) element of array
755
764
  next unless menu['caption']
756
- choices << ["--- #{ t(menu['caption'], menu['caption']) }",'#']
765
+ choices << ["--- #{ t(menu['caption'], menu['caption']) } ---",'#']
757
766
  menu['items'].to_a.sort.each do |item| # as above. sort items first
758
767
  key, value = item[0], item[1]
759
768
  opts = { controller: value['controller'], action: value['action'] }
@@ -764,6 +773,39 @@ def dc_choices4_cmsmenu()
764
773
  choices
765
774
  end
766
775
 
776
+ ##########################################################################
777
+ # Returns choices for creating collection edit select field on CMS top menu.
778
+ ##########################################################################
779
+ def dc_choices4_cmsmenu()
780
+ menus = {}
781
+ DrgCms.paths(:forms).reverse.each do |path|
782
+ filename = "#{path}/cms_menu.yml"
783
+ next unless File.exist?(filename)
784
+ menu = YAML.load_file(filename) rescue nil # load menu
785
+ next if menu.nil? or !menu['menu'] # not menu or error
786
+ menus = forms_merge(menu['menu'], menus) # ignore top level part
787
+ end
788
+ #
789
+ html = ''
790
+ menus.to_a.sort.each do |one_menu| # sort menus, result is array of sorted hashes
791
+ menu = one_menu[1] # value is the second (1) element of array
792
+ next unless menu['caption']
793
+ html << "<li>#{fa_icon(menu['icon'])}#{t(menu['caption'])}<ul>"
794
+ menu['items'].to_a.sort.each do |item| # as above. sort items first
795
+ value = item[1]
796
+ opts = { controller: value['controller'],
797
+ action: value['action'],
798
+ table: value['table'],
799
+ formname: value['formname'] || value['table'],
800
+ target: value['target'] || 'iframe_cms'
801
+ }
802
+ html << "<li>#{dc_link_to(t(value['caption']), value['icon'] || '', opts)}</li>"
803
+ end
804
+ html << '</ul></li>'
805
+ end
806
+ html
807
+ end
808
+
767
809
  ############################################################################
768
810
  # Returns list of directories as array of choices for use in select field
769
811
  # on folder permission form. Directory root is determined from dc_site.files_directory field.
@@ -778,7 +820,7 @@ def dc_choices4_folders_list
778
820
  end
779
821
 
780
822
  ############################################################################
781
- # Returns choices for select input field when choices can be generated from
823
+ # Returns choices for select input field when choices are generated from
782
824
  # all documents in collection.
783
825
  #
784
826
  # Parameters:
@@ -795,8 +837,12 @@ end
795
837
  # eval: dc_choices4('dc_poll','name','_id')
796
838
  ############################################################################
797
839
  def dc_choices4(model, name, id='_id', options = {})
798
- qry = model.classify.constantize.only(id, name).sort(name => 1)
799
- qry = qry.where(dc_site_id: dc_get_site()) if options[:site_only]
840
+ model = model.classify.constantize
841
+ qry = model.only(id, name)
842
+ qry = qry.and(dc_site_id: dc_get_site()) if options[:site_only]
843
+ qry = qry.and(active: true) if model.method_defined?(:active)
844
+ qry = qry.sort(name: 1)
845
+ #
800
846
  choices = []
801
847
  qry.each {|v| choices << [ v[name], v[id] ] }
802
848
  choices
@@ -866,7 +912,7 @@ def dc_user_can_view(ctrl, policy_id)
866
912
  site = ctrl.site
867
913
  policies = site.dc_policies
868
914
  # permission defined by default policy
869
- default_policy = policies.find_by(is_default: true)
915
+ default_policy = Mongoid::QueryCache.cache { policies.find_by(is_default: true) }
870
916
  return false, 'Default accsess policy not found for the site!' unless default_policy
871
917
  #
872
918
  permissions = {}
@@ -874,13 +920,13 @@ def dc_user_can_view(ctrl, policy_id)
874
920
  # update permissions with defined policy
875
921
  part_policy = nil
876
922
  if policy_id
877
- part_policy = policies.find(policy_id)
923
+ part_policy = Mongoid::QueryCache.cache { policies.find(policy_id) }
878
924
  return false, 'Access policy not found for part!' unless part_policy
879
925
  part_policy.dc_policy_rules.to_a.each { |v| permissions[v.dc_policy_role_id] = v.permission }
880
926
  end
881
927
  # apply guest role if user has no roles defined
882
928
  if ctrl.session[:user_roles].nil?
883
- role = DcPolicyRole.find_by(system_name: 'guest', active: true)
929
+ role = Mongoid::QueryCache.cache { DcPolicyRole.find_by(system_name: 'guest', active: true) }
884
930
  return false, 'System guest role not defined!' unless role
885
931
  ctrl.session[:user_roles] = [role.id]
886
932
  end