drg_cms 0.7.0.8 → 0.7.1.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +50 -20
  3. data/app/assets/stylesheets/drg_cms/drg_cms.css +89 -31
  4. data/app/assets/stylesheets/drg_cms/select-multiple.css +5 -6
  5. data/app/controllers/cmsedit_controller.rb +57 -24
  6. data/app/controllers/dc_application_controller.rb +18 -21
  7. data/app/controls/dc_poll_result_control.rb +36 -36
  8. data/app/controls/dc_setup_control.rb +53 -0
  9. data/app/forms/all_options.yml +3 -3
  10. data/app/forms/cms_menu.yml +7 -0
  11. data/app/forms/dc_image_search.yml +2 -2
  12. data/app/forms/dc_poll.yml +2 -1
  13. data/app/forms/dc_poll_result.yml +10 -7
  14. data/app/forms/dc_setup.yml +45 -0
  15. data/app/forms/dc_steps_template.yml +4 -1
  16. data/app/helpers/cms_common_helper.rb +14 -10
  17. data/app/helpers/cms_helper.rb +8 -7
  18. data/app/helpers/cms_index_helper.rb +56 -42
  19. data/app/helpers/dc_application_helper.rb +46 -16
  20. data/app/helpers/dc_image_helper.rb +2 -2
  21. data/app/models/concerns/dc_user_concern.rb +1 -1
  22. data/app/models/dc_big_table.rb +1 -1
  23. data/app/models/dc_filter.rb +5 -9
  24. data/app/models/dc_image.rb +1 -1
  25. data/app/models/dc_memory.rb +2 -2
  26. data/app/models/dc_setup.rb +111 -0
  27. data/app/models/drgcms_form_fields/datetime_picker.rb +1 -1
  28. data/app/models/drgcms_form_fields/embedded.rb +17 -9
  29. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +44 -36
  30. data/app/models/drgcms_form_fields/select.rb +21 -5
  31. data/app/renderers/dc_big_menu_renderer.rb +18 -20
  32. data/app/renderers/dc_menu_renderer.rb +21 -58
  33. data/app/renderers/dc_simple_menu_renderer.rb +1 -1
  34. data/app/views/cmsedit/_edit_stuff.html.erb +3 -0
  35. data/config/locales/drgcms_en.yml +8 -0
  36. data/config/locales/drgcms_sl.yml +12 -4
  37. data/config/locales/models_en.yml +17 -1
  38. data/config/locales/models_sl.yml +17 -1
  39. data/lib/drg_cms/version.rb +1 -1
  40. data/lib/drg_cms.rb +22 -23
  41. data/lib/generators/new_drg_form/new_drg_form_generator.rb +32 -14
  42. metadata +5 -2
@@ -855,10 +855,10 @@ def dc_user_can_view(ctrl, policy_id)
855
855
  policies = if site.inherit_policy.blank?
856
856
  site.dc_policies
857
857
  else
858
- Mongoid::QueryCache.cache { DcSite.find(site.inherit_policy) }.dc_policies
858
+ Mongo::QueryCache.cache { DcSite.find(site.inherit_policy) }.dc_policies
859
859
  end
860
860
  # permission defined by default policy
861
- default_policy = Mongoid::QueryCache.cache { policies.find_by(is_default: true) }
861
+ default_policy = Mongo::QueryCache.cache { policies.find_by(is_default: true) }
862
862
  return cache_add(policy_id, false, 'Default access policy not found for the site!') unless default_policy
863
863
 
864
864
  permissions = {}
@@ -866,14 +866,14 @@ def dc_user_can_view(ctrl, policy_id)
866
866
  # update permissions with defined policy
867
867
  part_policy = nil
868
868
  if policy_id
869
- part_policy = Mongoid::QueryCache.cache { policies.find(policy_id) }
869
+ part_policy = Mongo::QueryCache.cache { policies.find(policy_id) }
870
870
  return cache_add(policy_id, false, 'Access policy not found for part!') unless part_policy
871
871
 
872
872
  part_policy.dc_policy_rules.to_a.each { |v| permissions[v.dc_policy_role_id] = v.permission }
873
873
  end
874
874
  # apply guest role if no roles defined
875
875
  if ctrl.session[:user_roles].nil?
876
- role = Mongoid::QueryCache.cache { DcPolicyRole.find_by(system_name: 'guest', active: true) }
876
+ role = Mongo::QueryCache.cache { DcPolicyRole.find_by(system_name: 'guest', active: true) }
877
877
  return cache_add(policy_id, false, 'System guest role not defined!') unless role
878
878
 
879
879
  ctrl.session[:user_roles] = [role.id]
@@ -999,7 +999,15 @@ def dc_big_table(key)
999
999
  desc = v.value if desc.blank? # still blank. Use value as description
1000
1000
  ret << [desc, v.value]
1001
1001
  end
1002
- ret
1002
+ ret.sort_alphabetical_by(&:first)
1003
+ end
1004
+
1005
+ ########################################################################
1006
+ # Will return name for value defined in dc_big_table
1007
+ ########################################################################
1008
+ def dc_big_table_name_for_value(key, value)
1009
+ dc_big_table(key).each { |k, val| return k if val.to_s == value.to_s}
1010
+ '???'
1003
1011
  end
1004
1012
 
1005
1013
  ########################################################################
@@ -1110,12 +1118,12 @@ end
1110
1118
  # Returns:
1111
1119
  # HTML data to be embedded into page header
1112
1120
  #######################################################################
1113
- def dc_get_json_ld()
1114
- return '' if @json_ld.nil? or @json_ld.size == 0
1121
+ def dc_get_json_ld
1122
+ return '' if @json_ld.blank?
1115
1123
 
1116
1124
  %(
1117
1125
  <script type="application/ld+json">
1118
- #{JSON.pretty_generate({'@context' => 'http://schema.org', '@graph' => @json_ld})}
1126
+ #{JSON.pretty_generate({ '@context' => 'http://schema.org', '@graph' => @json_ld })}
1119
1127
  </script>).html_safe
1120
1128
  end
1121
1129
 
@@ -1135,21 +1143,40 @@ def dc_add_json_ld(element)
1135
1143
  end
1136
1144
 
1137
1145
  ########################################################################
1138
- # Will return meta data for SEO optimizations
1146
+ # Will return meta data for SEO optimizations.
1147
+ # It will also create special link rel="canonical" tag if defined in meta tags or page document.
1139
1148
  #
1140
1149
  # Returns:
1141
1150
  # HTML data to be embedded into page header
1142
1151
  #######################################################################
1143
1152
  def dc_get_seo_meta_tags
1144
1153
  html = ''
1145
- html << %(<link rel="canonical" href="#{@page.canonical_link}">\n ) if @page&.canonical_link.present?
1146
-
1147
- html << @meta_tags.inject('') do |r, hash|
1148
- r << %(<meta #{hash.first} content="#{hash.last}">\n )
1154
+ has_canonical = false
1155
+ html << @meta_tags.inject('') do |r, tag|
1156
+ r << if tag.first.match('canonical')
1157
+ has_canonical = true
1158
+ dc_get_link_canonical_tag(tag.last)
1159
+ else
1160
+ %(<meta #{tag.first} content="#{tag.last}">\n )
1161
+ end
1149
1162
  end if @meta_tags
1163
+ html << dc_get_link_canonical_tag(@page&.canonical_link) unless has_canonical
1150
1164
  html.html_safe
1151
1165
  end
1152
1166
 
1167
+ ########################################################################
1168
+ # helper for setting canonical link on the page
1169
+ #######################################################################
1170
+ def dc_get_link_canonical_tag(href = nil)
1171
+ return %(<link rel="canonical" href="#{request.url}">\n) if href.blank?
1172
+
1173
+ unless href.match(/^http/i)
1174
+ uri = URI.parse(request.url)
1175
+ href = "#{uri.scheme}://#{uri.host}/#{href.delete_prefix('/')}"
1176
+ end
1177
+ %(<link rel="canonical" href="#{href}">\n)
1178
+ end
1179
+
1153
1180
  ########################################################################
1154
1181
  # Will add a meta tag to internal hash structure. If meta tag already exists it
1155
1182
  # will be overwritten.
@@ -1178,7 +1205,7 @@ end
1178
1205
  # Returns:
1179
1206
  # [String] alt="image-tag"
1180
1207
  #######################################################################
1181
- def dc_img_alt_tag(file_name, text=nil)
1208
+ def dc_img_alt_tag(file_name, text = nil)
1182
1209
  %( alt="#{dc_img_alt(file_name, text)}" ).html_safe
1183
1210
  end
1184
1211
 
@@ -1194,7 +1221,7 @@ end
1194
1221
  # Returns:
1195
1222
  # [String] alt_image_name
1196
1223
  #######################################################################
1197
- def dc_img_alt(file_name, text=nil)
1224
+ def dc_img_alt(file_name, text = nil)
1198
1225
  return text if text.present?
1199
1226
 
1200
1227
  name = File.basename(file_name.to_s)
@@ -1203,7 +1230,10 @@ end
1203
1230
 
1204
1231
  private
1205
1232
 
1206
- # will cache dc_user_can_view response
1233
+ ########################################################################
1234
+ # To cache localy dc_user_can_view response for a single call. It has large gains on sites
1235
+ # with large menus.
1236
+ ########################################################################
1207
1237
  def cache_add(id, can_view, msg)
1208
1238
  @can_view_cache[id] = [can_view, msg]
1209
1239
  end
@@ -71,7 +71,7 @@ end
71
71
  ############################################################################
72
72
  # Will return code for previewing image on top of dc_image entry form
73
73
  ############################################################################
74
- def dc_image_first(document, *parms)
74
+ def first_dc_image(document, *parms)
75
75
  src = "/#{dc_get_site.params.dig('dc_image', 'location')}/#{document.first_available_image}"
76
76
  %(<span class="dc-image-preview"><img src="#{src}"></img></span><span id="dc-image-preview">).html_safe
77
77
  end
@@ -79,7 +79,7 @@ end
79
79
  ######################################################################
80
80
  # Will format qry result as html code for selecting image
81
81
  ######################################################################
82
- def dc_image_select_links(doc, *parms)
82
+ def select_links_for_dc_image(doc, *parms)
83
83
  %w[o s m l].inject('') { | r,size| r << dc_image_link_for_select(doc, size) }.html_safe
84
84
  end
85
85
 
@@ -149,7 +149,7 @@ end
149
149
  # Will return list of available groups
150
150
  ##########################################################################
151
151
  def self.groups_for_select
152
- where(group: true, active: true).order_by(name: 1).inject([]) { |r, e| r << [e.name, e.id] }
152
+ where(group: true, active: true).order_by(name: 1).map { [_1.name, _1.id] }
153
153
  end
154
154
 
155
155
  private
@@ -94,7 +94,7 @@ def self.choices4(key, site = nil, locale = nil)
94
94
  end
95
95
  # Error if empty
96
96
  result = [[I18n.t('drgcms.error'),I18n.t('drgcms.error')]] if result.size == 0
97
- result
97
+ result.sort_alphabetical_by(&:first)
98
98
  end
99
99
 
100
100
  end
@@ -114,7 +114,7 @@ def self.get_filter_field(parent)
114
114
  return '' if filter.nil?
115
115
 
116
116
  filter = YAML.load(filter) rescue nil
117
- return '' if filter.nil?
117
+ return '' if filter.nil? || filter['operation'].to_s == 'eval'
118
118
 
119
119
  field = get_field_form_definition(filter['field'], parent)
120
120
  return '' if field.nil? && filter['input'].nil?
@@ -186,14 +186,10 @@ def self.menu_filter(parent)
186
186
  # only single defined. Convert to array.
187
187
  filters = [filters] if filters.class == Hash
188
188
  filters.each do |filter|
189
- url = parent.dc_link_to(filter['title'], nil, controller: 'cmsedit', action: :run, t: table,
190
- f: CmsHelper.form_param(parent.params),
191
- control: 'cmsedit.filter_on',
192
- filter_field: filter['field'],
193
- filter_oper: filter['operation'],
194
- filter_value: filter['value'])
195
-
196
- url = parent.url_for(controller: 'cmsedit', action: :run, t: table, f: CmsHelper.form_param(parent.params),
189
+ url = parent.url_for(controller: :cmsedit,
190
+ action: :run,
191
+ table: table,
192
+ form_name: CmsHelper.form_param(parent.params),
197
193
  control: 'cmsedit.filter_on',
198
194
  filter_field: filter['field'],
199
195
  filter_oper: filter['operation'],
@@ -59,7 +59,7 @@ field :size_s, type: String
59
59
  field :categories, type: Array, default: []
60
60
  field :created_by, type: BSON::ObjectId
61
61
 
62
- belongs_to :dc_user
62
+ belongs_to :dc_site
63
63
 
64
64
  index dc_site_id: 1
65
65
  index created_by: 1
@@ -63,8 +63,8 @@
63
63
  # As result report.pdf file will be opened in new browser window.
64
64
  ########################################################################
65
65
  class DcMemory
66
- include Mongoid::Document
67
-
66
+ include Mongoid::Document
67
+
68
68
  ########################################################################
69
69
  # Initilize object
70
70
  ########################################################################
@@ -0,0 +1,111 @@
1
+ #--
2
+ # Copyright (c) 2024+ 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
+ # DcSetup collection is used for settings, that are specific to the application,
26
+ # or part of application (gem). It consists of data dafinitions and form for editing data.
27
+ # Data is saved internaly in YAML format.
28
+ #
29
+ # When editing, admin can see and edit form definition (adding new data to application setup), while user
30
+ # sees only data entry form.
31
+ #
32
+ # Usage:
33
+ # my_app_settings = DcSetup.find_by(name: 'my_app')
34
+ # my_app_settings = DcSetup.get('my_app')
35
+ # company = my_app_settings.company_name
36
+ # company, ceo = my_app_settings[:company_name, 'ceo_name']
37
+ #
38
+ ##############################################################################
39
+ class DcSetup
40
+ include Mongoid::Document
41
+ include Mongoid::Timestamps
42
+
43
+ attr_reader :my_data
44
+ attr_reader :my_fields
45
+
46
+ field :name, type: String, default: ''
47
+ field :data, type: String, default: ''
48
+ field :form, type: String, default: ''
49
+ field :editors, type: Array, default: []
50
+
51
+ field :created_by, type: BSON::ObjectId
52
+ field :updated_by, type: BSON::ObjectId
53
+
54
+ index name: 1
55
+
56
+ validates_length_of :name, minimum: 3
57
+
58
+ before_save do
59
+ self.data = my_data.to_yaml
60
+ end
61
+
62
+ ##############################################################################
63
+ # Will return settings record for specified application.
64
+ #
65
+ # @param [String] app_name The name of the application
66
+ # @return [Object, nil] The settings record if found, nil otherwise
67
+ ##############################################################################
68
+ def self.get(app_name)
69
+ DcSetup.find_by(name: app_name.to_s)
70
+ end
71
+
72
+ ##############################################################################
73
+ # Will return value for single setting if called as method.
74
+ ##############################################################################
75
+ def method_missing(m, *args, &block)
76
+ m = m.to_s
77
+ if m.match('=')
78
+ m.chomp!('=')
79
+ my_data[m] = args.first
80
+ else
81
+ my_data[m]
82
+ end
83
+ end
84
+
85
+ ##############################################################################
86
+ # Will return value for single setting. Called as parameter in square brackets.
87
+ # If more then one parameter is passed it will return them as array.
88
+ ##############################################################################
89
+ def [](*keys)
90
+ return my_data[keys.first.to_s] if keys.size == 1
91
+
92
+ keys.inject([]) { |r, k| r << my_data[k.to_s] }
93
+ end
94
+
95
+ ##############################################################################
96
+ # Will return true if setting is defined on the form
97
+ ##############################################################################
98
+ def respond_to?(field_name)
99
+ return true #if my_fields[field_name.to_s]
100
+
101
+ super.respond_to?(field_name)
102
+ end
103
+
104
+ ##############################################################################
105
+ #
106
+ ##############################################################################
107
+ def my_data
108
+ @my_data ||= (YAML.unsafe_load(data)) || {}
109
+ end
110
+
111
+ end
@@ -81,7 +81,7 @@ end
81
81
  ###########################################################################
82
82
  def self.get_data(params, name)
83
83
  t = params['record'][name] ? params['record'][name].to_datetime : nil
84
- t ? Time.zone.local(t.year, t.month, t.day, t.hour, t.min) : nil
84
+ t ? Time.new(t.year, t.month, t.day, t.hour, t.min) : nil
85
85
  end
86
86
 
87
87
  end
@@ -53,19 +53,26 @@ def render
53
53
  # HTML defaults. Some must be set
54
54
  @yaml['html'] ||= {}
55
55
  @yaml['html']['width'] ||= '99%'
56
+ # message when new record
57
+ if @record.new_record?
58
+ @yaml['html']['srcdoc'] = %(
59
+ <div style='font-family: helvetica; font-size: 1.7rem; font-weight: bold; color: #ddd; padding: 1rem'>
60
+ #{I18n.t('drgcms.iframe_save_to_view')}
61
+ </div>)
62
+ end
56
63
  html = @yaml['html'].inject('') { |r, val| r << "#{val.first}=\"#{val.last}\" " }
57
64
 
58
65
  @yaml['action'] ||= 'index'
59
66
  # defaults both way
60
- @yaml['table'] ||= @yaml['form_name'] if @yaml['form_name']
61
- @yaml['form_name'] ||= @yaml['table'] if @yaml['table']
67
+ @yaml['table'] ||= @yaml['form_name']
68
+ @yaml['form_name'] ||= @yaml['table']
62
69
 
63
- if @yaml['name'] == @yaml['table'] or @yaml['table'] == 'dc_memory'
70
+ if @yaml['name'] == @yaml['table'] || @yaml['table'] == 'dc_memory'
64
71
  tables = @yaml['table']
65
72
  ids = @record.id
66
73
  else
67
- tables = @parent.tables.inject('') { |r,v| r << "#{v[1]};" } + @yaml['table']
68
- ids = @parent.ids.inject('') { |r,v| r << "#{v};" } + @record.id
74
+ tables = (@parent.tables.map(&:first) + [@yaml['table']]).join(';')
75
+ ids = (@parent.ids + [@record.id]).join(';')
69
76
  end
70
77
  # edit enabled embedded form on a readonly form
71
78
  readonly = @yaml['readonly'].class == FalseClass ? nil : @readonly
@@ -73,11 +80,12 @@ def render
73
80
  ids: ids, table: tables, form_name: @yaml['form_name'],
74
81
  field_name: @yaml['name'], iframe: "if_#{@yaml['name']}", readonly: readonly }
75
82
  # additional parameters if specified
76
- @yaml['params'].each { |k,v| opts[k] = @parent.dc_value_for_parameter(v) } if @yaml['params']
77
-
83
+ @yaml['params'].each { |k, v| opts[k] = @parent.dc_value_for_parameter(v) } if @yaml['params']
84
+
78
85
  @html << "<iframe class='iframe_embedded' id='if_#{@yaml['name']}' name='if_#{@yaml['name']}' #{html}></iframe>"
79
- unless @record.new_record?
80
- url = @parent.url_for(opts)
86
+ if @record.new_record?
87
+ else
88
+ url = @parent.url_for(opts)
81
89
  attributes = case
82
90
  when @yaml['load'].nil? || @yaml['load'].match('default')
83
91
  "'src', '#{url}'"
@@ -55,16 +55,13 @@ class MultitextAutocomplete < DrgcmsField
55
55
  # Returns value for readonly field
56
56
  ###########################################################################
57
57
  def ro_standard(table, search)
58
- return self if @record[@yaml['name']].nil?
58
+ current_values = @record.send(@yaml['name'])
59
+ return self if current_values.blank?
59
60
 
60
- result = ''
61
61
  table = table.classify.constantize
62
- # when field name and method are defined together
63
- search = search.split('.').first if search.match('.')
64
- @record[@yaml['name']].each do |element|
65
- result << table.find(element)[search] + '<br>'
66
- end
67
- super(result)
62
+ search = search.split(/\.|\,/).first if search.match(/\.|\,/)
63
+ html = current_values.inject('') { |r, element| r << table.find(element)[search] + '<br>' }
64
+ super(html)
68
65
  end
69
66
 
70
67
  ###########################################################################
@@ -73,11 +70,11 @@ end
73
70
  def render
74
71
  # get field name
75
72
  if @yaml['search'].class == Hash
76
- table = @yaml['search']['table']
73
+ table = @yaml['search']['table']
77
74
  field_name = @yaml['search']['field']
78
- method = @yaml['search']['method']
79
- search = method.nil? ? field_name : "#{field_name}.#{method}"
80
- elsif @yaml['search'].to_s.match(/\./)
75
+ method = @yaml['search']['method']
76
+ search = method.nil? ? field_name : "#{field_name}.#{method}"
77
+ elsif @yaml['search'].to_s.match(/\.|\,/)
81
78
  table, field_name, method = @yaml['search'].split(/\.|\,/).map(&:strip)
82
79
  search = method.nil? ? field_name : "#{field_name}.#{method}"
83
80
  else # search and table name are separated
@@ -101,60 +98,71 @@ def render
101
98
  return self
102
99
  end
103
100
 
104
- # TODO check if table exists
105
- collection = table.classify.constantize
101
+ # does collection exists
102
+ collection = table.classify.constantize rescue nil
103
+ if collection.nil?
104
+ @html << "Invalid table name: #{table}"
105
+ return self
106
+ end
107
+
108
+ # does field exists
106
109
  unless @record.respond_to?(@yaml['name'])
107
110
  @html << "Invalid field name: #{@yaml['name']}"
108
111
  return self
109
112
  end
110
- # put field to enter search data on form
113
+
114
+ # search data entry
111
115
  @yaml['html'] ||= {}
112
116
  @yaml['html']['value'] = '' # must be. Otherwise it will look into record and return error
113
117
  @yaml['html']['placeholder'] = t('drgcms.search_placeholder')
114
118
  _name = '_' + @yaml['name']
115
119
  @html << '<div class="ui-autocomplete-border">'
116
- @html << @parent.link_to(@parent.fa_icon('plus-square-o', class: 'dc-green'), '#',onclick: 'return false;') # dummy add. But it is usefull.
120
+ @html << @parent.link_to(@parent.mi_icon('plus-square-o green'), '#', onclick: 'return false;') # dummy add. But it is usefull.
117
121
 
122
+ # text_field for autocomplete
118
123
  record = record_text_for(@yaml['name'])
119
- # text field for autocomplete
120
124
  @html << '<span class="dc-text-autocomplete">' << @parent.text_field(record, _name, @yaml['html']) << '<span></span></span>'
121
- # direct link for adding new documents to collection
125
+
126
+ # link for adding new documents to searched collection
122
127
  if @yaml['with_new'] && !@readonly
123
128
  @html << ' ' +
124
- @parent.fa_icon('plus-square-o', class: 'in-edit-add', title: t('drgcms.new'),
129
+ @parent.mi_icon('plus-square-o', class: 'in-edit-add', title: t('drgcms.new'),
125
130
  style: "vertical-align: top;", 'data-table' => @yaml['with_new'] )
126
131
  end
132
+
127
133
  # div to list active selections
128
134
  @html << "<div id =\"#{record}#{@yaml['name']}\">"
129
- # find value for each field inside categories
130
- unless @record[@yaml['name']].nil?
131
- @record[@yaml['name']].each do |element|
135
+ # fill with current values
136
+ current_values = @record.send(@yaml['name'])
137
+ unless current_values.nil?
138
+ current_values.each do |element|
132
139
  # this is quick and dirty trick. We have model dc_big_table which can be used for retrive
133
140
  # more complicated options
134
141
  # TODO retrieve choices from big_table
135
142
  rec = if table == 'dc_big_table'
136
- collection.find(@yaml['name'], @parent.session)
137
- else
138
- collection.find(element)
139
- end
140
- # Related data is missing. It happends.
143
+ collection.find(@yaml['name'], @parent.session)
144
+ else
145
+ collection.find(element)
146
+ end
147
+
141
148
  @html << if rec
142
- link = @parent.link_to(@parent.fa_icon('remove_circle', class: 'dc-red'), '#',
143
- onclick: %($('##{rec.id}').hide(); var v = $('##{record}_#{@yaml['name']}_#{rec.id}'); v.val("-" + v.val());return false;))
144
- link = @parent.fa_icon('check', class: 'dc-green') if @readonly
149
+ link = @parent.link_to(@parent.mi_icon('remove_circle red'), '#',
150
+ onclick: %($('##{rec.id}').hide(); let v = $('##{record}_#{@yaml['name']}_#{rec.id}'); v.val("-" + v.val());return false;))
151
+ link = @parent.mi_icon('check green') if @readonly
145
152
  field = @parent.hidden_field(record, "#{@yaml['name']}_#{rec.id}", value: element)
146
153
  %(<div id="#{rec.id}" style="padding:4px;">#{link} #{rec.send(field_name)}<br>#{field}</div>)
147
154
  else
148
- '** error **'
155
+ '** error **' # Related data is missing. It happends.
149
156
  end
150
157
  end
151
158
  end
152
159
  @html << "</div></div>"
160
+
153
161
  # Create text for div to be added when new category is selected
154
- link = @parent.link_to(@parent.fa_icon('remove_circle', class: 'dc-red'), '#',
155
- onclick: "$('#rec_id').hide(); var v = $('##{record}_#{@yaml['name']}_rec_id'); v.val(\"-\" + v.val());return false;")
162
+ link = @parent.link_to(@parent.mi_icon('remove_circle red'), '#',
163
+ onclick: %($('#rec_id').hide(); let v = $('##{record}_#{@yaml['name']}_rec_id'); v.val("-" + v.val());return false;"))
156
164
  field = @parent.hidden_field(record, "#{@yaml['name']}_rec_id", value: 'rec_id')
157
- one_div = "<div id=\"rec_id\" style=\"padding:4px;\">#{link} rec_search<br>#{field}</div>"
165
+ one_div = %(<div id="rec_id" style="padding:4px;">#{link} rec_search<br>#{field}</div>)
158
166
 
159
167
  # JS stuff
160
168
  @js << <<EOJS
@@ -174,7 +182,7 @@ $(document).ready(function() {
174
182
  });
175
183
  },
176
184
  change: function (event, ui) {
177
- var div = '#{one_div}';
185
+ let div = '#{one_div}';
178
186
  if (ui.item != null) {
179
187
  div = div.replace(/rec_id/g, ui.item.id)
180
188
  div = div.replace('rec_search', ui.item.value)
@@ -197,7 +205,7 @@ end
197
205
  ###########################################################################
198
206
  def self.get_data(params, name)
199
207
  r = []
200
- params['record'].each do |k, v|
208
+ params['record'].each do |k, v| # inject does not work on params
201
209
  # if it starts with - then it was removed
202
210
  r << BSON::ObjectId.from_string(v) if k.starts_with?("#{name}_") && v[0] != '-'
203
211
  end
@@ -47,7 +47,9 @@ module DrgcmsFormFields
47
47
  # * +depend:+ Select options may depend on a value in some other field. If depend option is specified
48
48
  # then chices must be provided by class method and defined in eval option.
49
49
  # * +html:+ html options which apply to select field (optional)
50
- #
50
+ # * +with_new:+ model_name.form_name will invoke view dialog for selected option
51
+ # * +with_edit:+ model_name.form_name will invoke edit dialog for selected option
52
+ #
51
53
  # Form example:
52
54
  # 30:
53
55
  # name: type
@@ -150,9 +152,21 @@ end
150
152
  def add_view_code
151
153
  return '' if (data = @record.send(@yaml['name'])).blank?
152
154
 
153
- table, form_name = @yaml['view'].split(/\ |\,/).delete_if { |e| e.blank? }
155
+ table, form_name = @yaml['with_view'].split(/\ |\,/).delete_if(&:blank)
154
156
  url = @parent.url_for(controller: 'cmsedit', id: data, action: :edit, table: table, form_name: form_name, readonly: true, window_close: 1 )
155
- icon = @parent.mi_icon('eye-o md-18')
157
+ icon = @parent.mi_icon('visibility-o md-18')
158
+ %(<span class="dc-window-open" data-url="#{url}"> #{icon}</span>)
159
+ end
160
+
161
+ ###########################################################################
162
+ # Will add code to view more data about selected option in a window
163
+ ###########################################################################
164
+ def add_edit_code
165
+ return '' if (data = @record.send(@yaml['name'])).blank?
166
+
167
+ table, form_name = @yaml['view'].split(/\ |\,/).delete_if(&:blank)
168
+ url = @parent.url_for(controller: 'cmsedit', id: data, action: :edit, table: table, form_name: form_name, window_close: 1 )
169
+ icon = @parent.mi_icon('edit-o md-18')
156
170
  %(<span class="dc-window-open" data-url="#{url}"> #{icon}</span>)
157
171
  end
158
172
 
@@ -182,7 +196,7 @@ def ro_standard
182
196
  (html = choice; break) if choice.to_s == value.to_s
183
197
  end
184
198
  end
185
- html << add_view_code if @yaml['view']
199
+ html << add_view_code if @yaml['with_view']
186
200
  end
187
201
  super(html)
188
202
  end
@@ -202,12 +216,14 @@ def render
202
216
 
203
217
  record = record_text_for(@yaml['name'])
204
218
  if @yaml['html'][:multiple]
219
+ @yaml['html']['class'] = "#{@yaml['html']['class']} select-multiple"
205
220
  @html << @parent.select(record, @yaml['name'], get_choices, options_part, @yaml['html'])
206
221
  @js << "$('##{record}_#{@yaml['name']}').selectMultiple();"
207
222
  else
208
223
  @html << @parent.select(record, @yaml['name'], get_choices, options_part, @yaml['html'])
209
224
  # add code for view more data
210
- @html << add_view_code() if @yaml['view']
225
+ @html << view_code_add() if @yaml['with_view']
226
+ @html << edit_code_add() if @yaml['with_edit'] && !@readonly
211
227
  end
212
228
  self
213
229
  end