drg_cms 0.7.0.8 → 0.7.1.1

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