drg_cms 0.6.0.1 → 0.6.0.3

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +54 -7
  3. data/app/assets/javascripts/drg_cms_application.js +1 -1
  4. data/app/assets/javascripts/drg_cms_cms.js +1 -1
  5. data/app/assets/stylesheets/drg_cms/drg_cms.css +32 -1
  6. data/app/controllers/cmsedit_controller.rb +49 -18
  7. data/app/controllers/dc_application_controller.rb +82 -21
  8. data/app/controllers/dc_common_controller.rb +64 -5
  9. data/app/forms/all_options.yml +2 -0
  10. data/app/forms/dc_ad.yml +11 -22
  11. data/app/forms/dc_design.yml +13 -13
  12. data/app/forms/dc_json_ld.yml +59 -0
  13. data/app/forms/dc_key_value.yml +32 -0
  14. data/app/forms/dc_menu_item.yml +1 -0
  15. data/app/forms/dc_page.yml +1 -5
  16. data/app/forms/dc_seo.yml +33 -0
  17. data/app/forms/json_ld_schema.yml +168 -0
  18. data/app/helpers/cmsedit_helper.rb +29 -24
  19. data/app/helpers/dc_application_helper.rb +105 -4
  20. data/app/models/concerns/dc_page_concern.rb +30 -5
  21. data/app/models/concerns/dc_seo_concern.rb +66 -0
  22. data/app/models/dc_design.rb +2 -0
  23. data/app/models/dc_json_ld.rb +152 -0
  24. data/app/models/dc_key_value.rb +48 -0
  25. data/app/models/dc_page.rb +0 -1
  26. data/app/models/drgcms_form_fields/hash_field.rb +86 -0
  27. data/app/models/drgcms_form_fields/select.rb +48 -15
  28. data/app/models/drgcms_form_fields/text_autocomplete.rb +14 -2
  29. data/app/models/drgcms_form_fields/tree_select.rb +4 -1
  30. data/app/{helpers → renderers}/dc_ad_renderer.rb +0 -0
  31. data/app/{helpers → renderers}/dc_big_menu_renderer.rb +0 -0
  32. data/app/{helpers → renderers}/dc_captcha_renderer.rb +0 -0
  33. data/app/{helpers → renderers}/dc_common_renderer.rb +0 -0
  34. data/app/{helpers → renderers}/dc_gallery_renderer.rb +0 -0
  35. data/app/{helpers → renderers}/dc_menu_renderer.rb +10 -4
  36. data/app/{helpers → renderers}/dc_page_renderer.rb +0 -0
  37. data/app/{helpers → renderers}/dc_part_renderer.rb +4 -4
  38. data/app/{helpers → renderers}/dc_piece_renderer.rb +0 -0
  39. data/app/{helpers → renderers}/dc_poll_renderer.rb +13 -5
  40. data/app/{helpers → renderers}/dc_renderer.rb +0 -0
  41. data/app/{helpers → renderers}/dc_simple_menu_renderer.rb +0 -0
  42. data/app/views/cmsedit/_edit_stuff.html.erb +3 -22
  43. data/config/locales/drgcms_en.yml +3 -1
  44. data/config/locales/drgcms_sl.yml +2 -0
  45. data/config/locales/models_en.yml +38 -6
  46. data/config/locales/models_sl.yml +39 -7
  47. data/lib/drg_cms.rb +2 -1
  48. data/lib/drg_cms/version.rb +1 -1
  49. metadata +22 -14
@@ -206,9 +206,9 @@ end
206
206
  ############################################################################
207
207
  def dc_table_title_for_result(result=nil)
208
208
  title = if @form['title'] # form has title section
209
- t(@form['title'],@form['title'])
209
+ t(@form['title'], @form['title'])
210
210
  else # get name from translations
211
- t('helpers.label.' + @form['table'] + '.tabletitle', @form['table'])
211
+ t("helpers.label.#{@form['table']}.tabletitle", @form['table'])
212
212
  end
213
213
  dc_table_title(title, result)
214
214
  end
@@ -281,6 +281,7 @@ def dc_actions_for_result(document)
281
281
  when yaml['type'] == 'delete' then
282
282
  parms['action'] = 'destroy'
283
283
  parms['id'] = document.id
284
+ parms['return_to'] = request.url
284
285
  dc_link_to( nil, 'remove lg', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete )
285
286
  # undocumented so far
286
287
  when yaml['type'] == 'edit_embedded'
@@ -552,7 +553,6 @@ def dc_actions_for_form()
552
553
  session[:form_processing] = "form:actions: #{element}"
553
554
  v = element[1]
554
555
  next if v.nil? # yes it happends
555
- p "Using text option in actions_for form is replaced with caption. Table #{@form['table']}" if v['text']
556
556
  # on_save_ok should't go inside td tags
557
557
  if (element[0] == 'on_save_ok') then
558
558
  c << hidden_field_tag(:on_save_ok, v)
@@ -639,9 +639,10 @@ def dc_actions_for_form()
639
639
  end
640
640
  # add current id to parameters
641
641
  parms['id'] = dc_document_path(@record)
642
- # additional parameters
642
+ # overwrite with or add additional parameters when params defined
643
643
  v['params'].each { |k,v| parms[k] = dc_value_for_parameter(v) } if v['params']
644
- # Error if controller parameter is missing
644
+ parms['table'] = parms['table'].underscore if parms['table'] # might be CamelCase
645
+ # error if controller parameter is missing
645
646
  if parms['controller'].nil?
646
647
  "<li>#{t('drgcms.error')}</li>"
647
648
  else
@@ -718,7 +719,7 @@ end
718
719
  ############################################################################
719
720
  # Creates top or bottom horizontal line on form.
720
721
  ############################################################################
721
- def top_bottom_line(yaml, columns=2)
722
+ def top_bottom_line(options)
722
723
  '<div class="dc-separator"></div>'
723
724
  end
724
725
 
@@ -749,8 +750,9 @@ def dc_fields_for_tab(fields_on_tab) #:nodoc:
749
750
  next
750
751
  end
751
752
  # label
752
- text = if options['text']
753
- t(options['text'], options['text'])
753
+ caption = options['caption'] || options['text']
754
+ label = if !caption.blank?
755
+ t(caption, caption)
754
756
  elsif options['name']
755
757
  t_name(options['name'], options['name'].capitalize.gsub('_',' ') )
756
758
  end
@@ -782,7 +784,7 @@ def dc_fields_for_tab(fields_on_tab) #:nodoc:
782
784
  html << if labels_pos == 'top'
783
785
  %Q[
784
786
  <div class="dc-form-label-top dc-color-#{odd_even} dc-align-left" title="#{help}">
785
- <label for="record_#{options['name']}">#{text} </label>
787
+ <label for="record_#{options['name']}">#{label} </label>
786
788
  <div id="td_record_#{options['name']}">#{field_html}</div>
787
789
  </div> ]
788
790
  else
@@ -792,7 +794,7 @@ def dc_fields_for_tab(fields_on_tab) #:nodoc:
792
794
  data_width = (94 - 10*group_option)/group_option
793
795
  %Q[
794
796
  <div class="dc-form-label dc-color-#{odd_even} dc-align-#{labels_pos}" style="width:#{label_width}%;" title="#{help}">
795
- <label for="record_#{options['name']}">#{text} </label>
797
+ <label for="record_#{options['name']}">#{label} </label>
796
798
  </div>
797
799
  <div id="td_record_#{options['name']}" class="dc-form-field dc-color-#{odd_even}" style="width:#{data_width}%;">#{field_html}</div>
798
800
  ]
@@ -809,7 +811,7 @@ end
809
811
  # Creates edit form div.
810
812
  ############################################################################
811
813
  def dc_fields_for_form()
812
- html, tabs, tdata = '',[], ''
814
+ html, tabs, tab_data = '',[], ''
813
815
  # Only fields defined
814
816
  if (form_fields = @form['form']['fields'])
815
817
  html << "<div id='data_fields' " + (@form['form']['height'] ? "style=\"height: #{@form['form']['height']}px;\">" : '>')
@@ -817,33 +819,36 @@ def dc_fields_for_form()
817
819
  else
818
820
  # there are multiple tabs on form
819
821
  first = true # first tab
820
- @form['form']['tabs'].keys.sort.each do |tabname|
821
- next if tabname.match('actions')
822
+ @form['form']['tabs'].keys.sort.each do |tab_name|
823
+ next if tab_name.match('actions')
822
824
  # Tricky. If field name is not on the tab skip to next tab
823
825
  if params[:edit_only]
824
826
  is_on_tab = false
825
- @form['form']['tabs'][tabname].each {|k,v| is_on_tab = true if params[:edit_only] == v['name'] }
827
+ @form['form']['tabs'][tab_name].each {|k,v| is_on_tab = true if params[:edit_only] == v['name'] }
826
828
  next unless is_on_tab
827
829
  end
828
- # first div is displayed all other are hidden
829
- tdata << "<div id='data_#{tabname.delete("\s\n")}'"
830
- tdata << ' class="div-hidden"' unless first
831
- tdata << " style=\"height: #{@form['form']['height']}px;\"" if @form['form']['height']
832
- tdata << ">#{dc_fields_for_tab(@form['form']['tabs'][tabname])}</div>"
833
- tabs << tabname
830
+ # first div is displayed, all others are hidden
831
+ tab_data << "<div id=\"data_#{tab_name.delete("\s\n")}\""
832
+ tab_data << ' class="div-hidden"' unless first
833
+ tab_data << " style=\"height: #{@form['form']['height']}px;\"" if @form['form']['height']
834
+ tab_data << ">#{dc_fields_for_tab(@form['form']['tabs'][tab_name])}</div>"
835
+ tab_label = @form['form']['tabs'][tab_name]['caption'] || tab_name
836
+ tabs << [tab_name, tab_label]
834
837
  first = false
835
838
  end
836
839
  # make it all work together
837
840
  html << '<ul class="dc-form-ul" >'
838
841
  first = true # first tab must be selected
839
- tabs.each do |tab|
840
- html << "<li id='li_#{tab}' data-div='#{tab.delete("\s\n")}' class='dc-form-li #{'dc-form-li-selected' if first }'>#{t_name(tab, tab)}</li>"
842
+ tabs.each do |tab_name, tab_label|
843
+ html << "<li id=\"li_#{tab_name}\" data-div=\"#{tab_name.delete("\s\n")}\" class=\"dc-form-li"
844
+ html << ' dc-form-li-selected' if first
845
+ html << "\">#{t(tab_label, t_name(tab_label))}</li>"
841
846
  first = false
842
847
  end
843
848
  html << '</ul>'
844
- html << tdata
849
+ html << tab_data
845
850
  end
846
- # add last_updated_at hidden field so controller can check if record was updated in during editing
851
+ # add last_updated_at hidden field so controller can check if record was updated in db during editing
847
852
  html << hidden_field(nil, :last_updated_at, value: @record.updated_at.to_i) if @record.respond_to?(:updated_at)
848
853
  # add form time stamp to prevent double form submit
849
854
  html << hidden_field(nil, :form_time_stamp, value: Time.now.to_i)
@@ -58,6 +58,8 @@ attr_accessor :parts
58
58
  attr_accessor :record
59
59
  #
60
60
  attr_accessor :record_footer
61
+ # json_ld
62
+ attr_reader :json_ld
61
63
 
62
64
  ############################################################################
63
65
  # When @parent is present then helper methods are called from parent class otherwise
@@ -575,7 +577,7 @@ def dc_page_edit_menu(opts=@opts)
575
577
  return '' if opts[:edit_mode] < 2
576
578
  # save some data to cookie. This can not go to session.
577
579
  page = opts[:page] || @page
578
- table = _origin.site.page_table
580
+ table = _origin.site.page_class.underscore
579
581
  kukis = { "#{table}.dc_design_id" => page.dc_design_id,
580
582
  # "#{table}.menu_id" => page.menu_id,
581
583
  "#{table}.kats" => page.kats,
@@ -587,7 +589,7 @@ def dc_page_edit_menu(opts=@opts)
587
589
  opts[:editparams] ||= {}
588
590
  dc_link_menu_tag(title) do |html|
589
591
  opts[:editparams].merge!( controller: 'cmsedit', action: 'edit', 'icon' => 'edit' )
590
- opts[:editparams].merge!( :id => page.id, :table => _origin.site.page_table, form_name: opts[:form_name], edit_only: 'body' )
592
+ opts[:editparams].merge!( :id => page.id, :table => _origin.site.page_class.underscore, form_name: opts[:form_name], edit_only: 'body' )
591
593
  html << dc_link_for_edit1( opts[:editparams], t('drgcms.edit_content') )
592
594
 
593
595
  # opts[:editparams][:edit_only] = nil
@@ -599,7 +601,7 @@ def dc_page_edit_menu(opts=@opts)
599
601
  html << dc_link_for_edit1( opts[:editparams], t('drgcms.edit_new_page') )
600
602
 
601
603
  opts[:editparams].merge!(ids: page.id, form_name: 'dc_part', 'icon' => 'plus-square-o',
602
- table: "#{_origin.site.page_table};dc_part" )
604
+ table: "#{_origin.site.page_class.underscore};dc_part" )
603
605
  html << dc_link_for_edit1( opts[:editparams], t('drgcms.edit_new_part') )
604
606
  end.html_safe
605
607
  end
@@ -618,7 +620,7 @@ end
618
620
  ########################################################################
619
621
  def dc_page_class()
620
622
  # dc_get_site.page_class.classify.constantize
621
- dc_get_site.page_table.classify.constantize
623
+ dc_get_site.page_klass
622
624
  end
623
625
 
624
626
  ########################################################################
@@ -1335,4 +1337,103 @@ def dc_document_path(document)
1335
1337
  path.reverse.join(';')
1336
1338
  end
1337
1339
 
1340
+ ########################################################################
1341
+ # Will return formated code for embedding json+ld data into page
1342
+ #
1343
+ # Returns:
1344
+ # HTML data to be embedded into page header
1345
+ #######################################################################
1346
+ def dc_get_json_ld()
1347
+ return '' if @json_ld.nil? or @json_ld.size == 0
1348
+
1349
+ %Q[
1350
+ <script type="application/ld+json">
1351
+ #{JSON.pretty_generate({'@context' => 'http://schema.org', '@graph' => @json_ld})}
1352
+ </script>
1353
+ ].html_safe
1354
+ end
1355
+
1356
+ ########################################################################
1357
+ # Will add new element to json_ld structure
1358
+ #
1359
+ # Parameters:
1360
+ # [element] Hash or Array of hashes: json+ld element
1361
+ #######################################################################
1362
+ def dc_add_json_ld(element)
1363
+ @json_ld ||= []
1364
+ if element.class == Array
1365
+ @json_ld += element
1366
+ else
1367
+ @json_ld << element
1368
+ end
1369
+ end
1370
+
1371
+ ########################################################################
1372
+ # Will return meta data for SEO optimizations
1373
+ #
1374
+ # Returns:
1375
+ # HTML data to be embedded into page header
1376
+ #######################################################################
1377
+ def dc_get_seo_meta_tags()
1378
+ html = ''
1379
+ html << "<link rel=\"canonical\" href=\"#{@page.canonical_link}\">\n " unless @page&.canonical_link.blank?
1380
+
1381
+ html << @meta_tags.inject('') do |r, hash|
1382
+ r << "<meta #{hash.first} content=\"#{hash.last}\">\n "
1383
+ end if @meta_tags
1384
+ html.html_safe
1385
+ end
1386
+
1387
+ ########################################################################
1388
+ # Will add a meta tag to internal hash structure. If meta tag already exists it
1389
+ # will be overwritten.
1390
+ #
1391
+ # Parameters:
1392
+ # [name] String: meta name
1393
+ # [content] String: meta content
1394
+ ########################################################################
1395
+ def dc_add_meta_tag(type, name, content)
1396
+ return if content.blank?
1397
+ @meta_tags ||= {}
1398
+ key = "#{type}=\"#{name}\""
1399
+ @meta_tags[key] = content
1400
+ end
1401
+
1402
+ #######################################################################
1403
+ # Will return alt image option when text is provided. When text is blank
1404
+ # it will extract alt name from picture file_name. This method returns
1405
+ # together with alt="image-tag" tag.
1406
+ #
1407
+ # Parameters:
1408
+ # [file_name] String: Filename of a picture
1409
+ # [text] String: Alt text name
1410
+ #
1411
+ # Returns:
1412
+ # [String] alt="image-tag"
1413
+ #######################################################################
1414
+ def dc_img_alt_tag(file_name, text=nil)
1415
+ " alt=\"#{dc_img_alt(file_name, text)}\" ".html_safe
1416
+ end
1417
+
1418
+ #######################################################################
1419
+ # Will return alt image option when text is provided. When text is blank
1420
+ # it will extract alt name from picture file_name. This method returns just
1421
+ # alt name.
1422
+ #
1423
+ # Parameters:
1424
+ # [file_name] String: Filename of a picture
1425
+ # [text] String: Alt text name
1426
+ #
1427
+ # Returns:
1428
+ # [String] alt_image_name
1429
+ #######################################################################
1430
+ def dc_img_alt(file_name, text=nil)
1431
+ if text.blank?
1432
+ name = File.basename(file_name.to_s)
1433
+ text = name[0,name.index('.')].downcase rescue name
1434
+ end
1435
+ text
1436
+ end
1437
+
1438
+
1338
1439
  end
@@ -33,7 +33,6 @@ include Mongoid::Document
33
33
  include Mongoid::Timestamps
34
34
 
35
35
  field :subject, type: String, default: ''
36
- field :title, type: String
37
36
  field :subject_link, type: String, default: ''
38
37
  field :alt_link, type: String, default: ''
39
38
  field :sub_subject, type: String, default: ''
@@ -56,16 +55,19 @@ field :active, type: Boolean, default: true
56
55
  field :created_by, type: BSON::ObjectId
57
56
  field :updated_by, type: BSON::ObjectId
58
57
  field :kats, type: Array # Categories
59
-
58
+ # IFRAME
60
59
  field :if_url, type: String
61
60
  field :if_border, type: Integer, default: 0
62
61
  field :if_width, type: Integer
63
62
  field :if_height, type: Integer
64
63
  field :if_scroll, type: String
65
64
  field :if_id, type: String
66
- field :if_class, type: String
65
+ field :if_class, type: String
67
66
  field :if_params, type: String
68
67
 
68
+ # SEO
69
+ include DcSeoConcern
70
+
69
71
  field :policy_id, type: BSON::ObjectId
70
72
 
71
73
  embeds_many :dc_parts
@@ -80,6 +82,7 @@ index alt_link: 1
80
82
  before_save :do_before_save
81
83
 
82
84
  validates :publish_date, presence: true
85
+ validate :validate_images_alt_present
83
86
 
84
87
  ######################################################################
85
88
  # Will return subject_link. Field name link should be common for all documents
@@ -88,7 +91,15 @@ validates :publish_date, presence: true
88
91
  def link
89
92
  subject_link
90
93
  end
91
-
94
+
95
+ ######################################################################
96
+ # Will return validation error if all images in body field do not have
97
+ # alt attribute pressent.
98
+ ######################################################################
99
+ def validate_images_alt_present
100
+ errors.add('body', I18n.t('drgcms.img_alt_not_present')) unless DcPage.images_alt_present?(self.body)
101
+ end
102
+
92
103
  protected
93
104
 
94
105
  ######################################################################
@@ -109,7 +120,7 @@ end
109
120
  # than link size is not larger than 100 chars.
110
121
  ######################################################################
111
122
  def self.clear_link(link)
112
- link.gsub!(/\.|\?|\!\&|»|«|\,|\"|\'|\:/,'')
123
+ link.gsub!(/\.|\?|\!\&|\||»|«|\,|\"|\'|\:/,'')
113
124
  link.gsub!('<br>','')
114
125
  link.gsub!('–','-')
115
126
  link.gsub!(' ','-')
@@ -144,6 +155,20 @@ def self.dc_filters
144
155
  'field' => 'dc_site_id', 'value' => '@current_site'}
145
156
  end
146
157
 
158
+ ######################################################################
159
+ # Clears subject link of chars that shouldn't be there and also takes care
160
+ # than link size is not larger than 100 chars.
161
+ ######################################################################
162
+ def self.images_alt_present?(text)
163
+ return true if text.blank?
164
+ #
165
+ document = Nokogiri::HTML.parse(text)
166
+ document.xpath('//img').each do |image|
167
+ return false if !image.attributes['alt'] or image.attributes['alt'].text.blank?
168
+ end
169
+ true
170
+ end
171
+
147
172
  end
148
173
 
149
174
  end
@@ -0,0 +1,66 @@
1
+ #--
2
+ # Copyright (c) 2019+ Damjan Rems
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ ##########################################################################
25
+ # dc_seo_concern, ads SEO optimization fields to any model.
26
+ #
27
+ # title String Browser title. Optimization for SEO.
28
+ # meta_description String SEO optimised page description
29
+ # meta_additional String Additional meta page data. Enter as meta_name=meta data
30
+ # dc_json_lds Embedded:DcJsonLd Page structure data
31
+ #
32
+ # If you want to add SEO optimization data to your document add:
33
+ #
34
+ # "include DcSeoConcern" to your model definition
35
+ #
36
+ # and
37
+ #
38
+ # "include: dc_seo" option to top of DRGCMS edit form for your document.
39
+ ##########################################################################
40
+ module DcSeoConcern
41
+ extend ActiveSupport::Concern
42
+
43
+ included do
44
+ field :title, type: String
45
+ field :meta_description, type: String
46
+ field :canonical_link, type: String
47
+ embeds_many :dc_json_lds # JSON-LD structure
48
+
49
+ ######################################################################
50
+ # Will return JSON LD data if defined for the page
51
+ ######################################################################
52
+ def get_json_ld()
53
+ parent_data = {'datePublished' => self.created_at, 'dateModified' => self.updated_at}
54
+ data = []
55
+ if dc_json_lds.size > 0
56
+ dc_json_lds.where(active: true).each do |element|
57
+ dta = element.get_json_ld(parent_data)
58
+ data << dta if dta.size > 0
59
+ end
60
+ end
61
+ data
62
+ end
63
+ end
64
+
65
+
66
+ end
@@ -31,6 +31,7 @@
31
31
  # updated_at Time updated_at
32
32
  # description String Short description of design
33
33
  # body String Body of design which will be rendered like any Rails view
34
+ # params String Parameters used by design
34
35
  # css String CSS for design
35
36
  # rails_view String Rails view (file) name which will be used to render design
36
37
  # author String Creater if design
@@ -94,6 +95,7 @@ class DcDesign
94
95
  field :css, type: String, default: ''
95
96
  field :rails_view, type: String, default: ''
96
97
  field :control, type: String, default: ''
98
+ field :params, type: String, default: ''
97
99
  field :control_method, type: String, default: ''
98
100
  field :author, type: String
99
101
  field :active, type: Boolean, default: true
@@ -0,0 +1,152 @@
1
+ #--
2
+ # Copyright (c) 2019+ Damjan Rems
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ ########################################################################
25
+ # == Schema information
26
+ #
27
+ # Collection name: dc_json_ld : JSON_LD data for site optimization
28
+ #
29
+ # _id BSON::ObjectId _id
30
+ # type String Type of structure
31
+ # data String Structure data in YAML
32
+ # dc_json_lds Object Can embed substructure
33
+ # created_at Time created_at
34
+ # updated_at Time Last updated at
35
+ # created_by BSON::ObjectId created_by
36
+ # updated_by BSON::ObjectId Last updated by
37
+ #
38
+ ########################################################################
39
+ class DcJsonLd
40
+ include Mongoid::Document
41
+ include Mongoid::Timestamps
42
+
43
+ field :name, type: String
44
+ field :type, type: String
45
+ field :data, type: String
46
+ field :active, type: Boolean, default: true
47
+
48
+ embeds_many :dc_json_lds, :cyclic => true
49
+
50
+ field :created_by, type: BSON::ObjectId
51
+ field :updated_by, type: BSON::ObjectId
52
+
53
+ validates :name, presence: true
54
+ validates :type, presence: true
55
+
56
+ ##########################################################################
57
+ # Returns JSON LD data as YAML
58
+ ##########################################################################
59
+ def get_json_ld(parent_data)
60
+ yaml = (YAML.load(self.data) rescue nil) || {}
61
+ yaml['@type'] = self.type if yaml.size > 0
62
+ if dc_json_lds.size > 0
63
+ dc_json_lds.where(active: true).each do |element|
64
+ yml = element.get_json_ld(parent_data)
65
+ if yml.size > 0
66
+ yaml[element.name] ||= []
67
+ yaml[element.name] << yml
68
+ end
69
+ end
70
+ end
71
+ yaml
72
+ end
73
+
74
+ ########################################################################
75
+ # Searches forms path for file_name and returns full file name or nil if not found.
76
+ #
77
+ # @param [String] Form file name. File name can be passed as gem_name.filename. This can
78
+ # be useful when you are extending form but want to retain same name as original form
79
+ # For example. You are extending dc_user form from drg_cms gem and want to
80
+ # retain same dc_user name. This can be done by setting drg_cms.dc_user to extend option.
81
+ #
82
+ # @return [String] Form file name including path or nil if not found.
83
+ ########################################################################
84
+ def self.dc_find_form_file(form_file)
85
+ form_path=nil
86
+ if form_file.match(/\.|\//)
87
+ form_path,form_file=form_file.split(/\.|\//)
88
+ end
89
+ DrgCms.paths(:forms).reverse.each do |path|
90
+ f = "#{path}/#{form_file}.yml"
91
+ return f if File.exist?(f) and (form_path.nil? or path.to_s.match(/\/#{form_path}\//i))
92
+ end
93
+ p "Form file #{form_file} not found!"
94
+ nil
95
+ end
96
+
97
+ ########################################################################
98
+ # Find document by ids when document are embedded into main d even if embedded
99
+ #
100
+ # @param [tables] Tables parameter as send in url. Tables are separated by ;
101
+ # @param [ids] ids as send in url. ids are separated by ;
102
+ #
103
+ # @return [Document]
104
+ ########################################################################
105
+ def self.find_document_by_ids(tables, ids)
106
+ collection = tables.split(';').first.classify.constantize
107
+ ar_ids = ids.split(';')
108
+ # Find top document
109
+ document = collection.find(ar_ids.shift)
110
+ # Search for embedded document
111
+ ar_ids.each {|id| document = document.dc_json_lds.find(id) }
112
+ document
113
+ end
114
+
115
+ #########################################################################
116
+ # Returns possible options for type select field on form.
117
+ #########################################################################
118
+ def self.choices4_type()
119
+ yaml = YAML.load_file( dc_find_form_file('json_ld_schema') )
120
+
121
+ yaml.inject([]) {|result, schema_name| result << schema_name.first }
122
+ end
123
+
124
+ #########################################################################
125
+ # Create menu to add schema element. Called from DRGCMS Form action.
126
+ #########################################################################
127
+ def self.add_schema_menu(parent)
128
+ yaml = YAML.load_file( dc_find_form_file('json_ld_schema') )
129
+ if (level = parent.params['ids'].split(';').size) == 1
130
+ # select only top level elements
131
+ yaml.delete_if { |schema_name, schema_data| schema_data['level'].nil? }
132
+ else
133
+ # select only elemets which are subelements of type
134
+ parent_type = self.find_document_by_ids(parent.params['table'],parent.params['ids']).type
135
+ _yaml = []
136
+ yaml[parent_type].each do |name, data|
137
+ next unless data.class == Hash
138
+ _yaml << [data['type'], yaml[data['type']] ] if data['type'] and yaml[data['type']]
139
+ end
140
+ yaml = _yaml
141
+ end
142
+ # create menu code
143
+ html = '<ul>'
144
+ yaml.each do |schema_name, schema_data|
145
+ next if level == 1 and schema_data['level'].nil?
146
+ url = "/dc_common/add_json_ld_schema?table=#{parent.params['table']}&ids=#{parent.params['ids']}&schema=#{schema_name}&url=#{parent.request.url}"
147
+ html << %Q[<li class="dc-link-ajax dc-animate" data-url="#{url}">#{schema_name}</li>]
148
+ end
149
+ html << '</ul>'
150
+ end
151
+
152
+ end