drg_cms 0.6.0.1 → 0.6.1.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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +454 -145
  3. data/app/assets/javascripts/drg_cms_application.js +1 -1
  4. data/app/assets/stylesheets/drg_cms/drg_cms.css +635 -244
  5. data/app/assets/stylesheets/drg_cms/select-multiple.css +18 -12
  6. data/app/assets/stylesheets/drg_cms_cms.css +1 -1
  7. data/app/controllers/cmsedit_controller.rb +515 -335
  8. data/app/controllers/dc_application_controller.rb +378 -111
  9. data/app/controllers/dc_common_controller.rb +105 -14
  10. data/app/{controllers → controls}/browse_models_control.rb +0 -0
  11. data/app/controls/dc_help_control.rb +126 -0
  12. data/app/{controllers → controls}/dc_page_control.rb +24 -8
  13. data/app/controls/dc_poll_result_control.rb +88 -0
  14. data/app/controls/dc_report.rb +223 -0
  15. data/app/{controllers → controls}/design_element_settings_control.rb +0 -0
  16. data/app/forms/all_options.yml +44 -9
  17. data/app/forms/cms_menu.yml +28 -18
  18. data/app/forms/dc_ad.yml +11 -22
  19. data/app/forms/dc_big_table.yml +1 -0
  20. data/app/forms/dc_big_table_value.yml +1 -0
  21. data/app/forms/dc_category.yml +2 -1
  22. data/app/forms/dc_design.yml +20 -16
  23. data/app/forms/dc_filter.yml +3 -6
  24. data/app/forms/dc_help_1.yml +109 -0
  25. data/app/forms/dc_journal.yml +3 -1
  26. data/app/forms/dc_json_ld.yml +59 -0
  27. data/app/forms/dc_key_value.yml +32 -0
  28. data/app/forms/dc_link.yml +1 -1
  29. data/app/forms/dc_menu.yml +2 -0
  30. data/app/forms/dc_menu_item.yml +2 -0
  31. data/app/forms/dc_page.yml +3 -5
  32. data/app/forms/dc_part.yml +1 -0
  33. data/app/forms/dc_piece.yml +1 -0
  34. data/app/forms/dc_poll.yml +15 -5
  35. data/app/forms/dc_poll_item.yml +2 -1
  36. data/app/forms/dc_poll_result.yml +83 -0
  37. data/app/forms/dc_poll_result_export.yml +35 -0
  38. data/app/forms/dc_seo.yml +33 -0
  39. data/app/forms/dc_simple_menu.yml +2 -0
  40. data/app/forms/dc_site.yml +4 -12
  41. data/app/forms/dc_user.yml +27 -11
  42. data/app/forms/dc_user_role.yml +3 -0
  43. data/app/forms/json_ld_schema.yml +168 -0
  44. data/app/helpers/cms_common_helper.rb +375 -0
  45. data/app/helpers/cms_edit_helper.rb +506 -0
  46. data/app/helpers/cms_helper.rb +268 -0
  47. data/app/helpers/cms_index_helper.rb +580 -0
  48. data/app/helpers/dc_application_helper.rb +218 -306
  49. data/app/models/concerns/dc_page_concern.rb +40 -6
  50. data/app/models/concerns/dc_policy_rule_concern.rb +20 -8
  51. data/app/models/concerns/dc_seo_concern.rb +66 -0
  52. data/app/models/concerns/dc_site_concern.rb +67 -44
  53. data/app/models/concerns/dc_user_concern.rb +57 -18
  54. data/app/models/dc_design.rb +30 -18
  55. data/app/models/dc_filter.rb +22 -13
  56. data/app/models/dc_json_ld.rb +152 -0
  57. data/app/models/dc_key_value.rb +48 -0
  58. data/app/models/dc_key_value_store.rb +1 -0
  59. data/app/models/dc_memory.rb +8 -1
  60. data/app/models/dc_page.rb +0 -1
  61. data/app/models/dc_permission.rb +49 -9
  62. data/app/models/dc_policy.rb +25 -14
  63. data/app/models/dc_policy_role.rb +22 -11
  64. data/app/models/dc_poll.rb +39 -19
  65. data/app/models/dc_poll_result.rb +46 -0
  66. data/app/models/dc_temp.rb +140 -0
  67. data/app/models/dc_user_role.rb +2 -2
  68. data/app/models/drgcms_form_fields.rb +12 -1
  69. data/app/models/drgcms_form_fields/action.rb +61 -0
  70. data/app/models/drgcms_form_fields/comment.rb +8 -4
  71. data/app/models/drgcms_form_fields/date_picker.rb +11 -9
  72. data/app/models/drgcms_form_fields/date_select.rb +1 -1
  73. data/app/models/drgcms_form_fields/datetime_picker.rb +12 -10
  74. data/app/models/drgcms_form_fields/datetime_select.rb +1 -1
  75. data/app/models/drgcms_form_fields/drgcms_field.rb +55 -9
  76. data/app/models/drgcms_form_fields/embedded.rb +26 -16
  77. data/app/models/drgcms_form_fields/file_field.rb +52 -0
  78. data/app/models/drgcms_form_fields/file_select.rb +2 -2
  79. data/app/models/drgcms_form_fields/hash_field.rb +90 -0
  80. data/app/models/drgcms_form_fields/hidden_field.rb +1 -1
  81. data/app/models/drgcms_form_fields/html_field.rb +1 -1
  82. data/app/models/drgcms_form_fields/link_to.rb +2 -2
  83. data/app/models/drgcms_form_fields/method.rb +66 -0
  84. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +23 -14
  85. data/app/models/drgcms_form_fields/number_field.rb +15 -6
  86. data/app/models/drgcms_form_fields/radio.rb +96 -0
  87. data/app/models/drgcms_form_fields/readonly.rb +2 -2
  88. data/app/models/drgcms_form_fields/select.rb +92 -29
  89. data/app/models/drgcms_form_fields/text_area.rb +1 -1
  90. data/app/models/drgcms_form_fields/text_autocomplete.rb +31 -17
  91. data/app/models/drgcms_form_fields/text_field.rb +1 -1
  92. data/app/models/drgcms_form_fields/text_with_select.rb +6 -3
  93. data/app/models/drgcms_form_fields/tree_select.rb +15 -4
  94. data/app/{helpers → renderers}/dc_ad_renderer.rb +0 -0
  95. data/app/{helpers → renderers}/dc_big_menu_renderer.rb +1 -0
  96. data/app/{helpers → renderers}/dc_captcha_renderer.rb +0 -0
  97. data/app/{helpers → renderers}/dc_common_renderer.rb +0 -0
  98. data/app/{helpers → renderers}/dc_gallery_renderer.rb +1 -0
  99. data/app/{helpers → renderers}/dc_menu_renderer.rb +11 -4
  100. data/app/{helpers → renderers}/dc_page_renderer.rb +1 -0
  101. data/app/{helpers → renderers}/dc_part_renderer.rb +5 -4
  102. data/app/{helpers → renderers}/dc_piece_renderer.rb +1 -1
  103. data/app/{helpers → renderers}/dc_poll_renderer.rb +91 -64
  104. data/app/{helpers → renderers}/dc_renderer.rb +1 -0
  105. data/app/{helpers → renderers}/dc_simple_menu_renderer.rb +1 -0
  106. data/app/views/cmsedit/{remove_edit_stuff.js.erb → __remove_edit_stuff.js.erb} +0 -0
  107. data/app/views/cmsedit/{show.html.erb → __show.html.erb} +0 -0
  108. data/app/views/cmsedit/_edit_stuff.html.erb +4 -25
  109. data/app/views/cmsedit/_form.html.erb +4 -3
  110. data/app/views/cmsedit/_result.html.erb +2 -3
  111. data/app/views/cmsedit/edit.html.erb +4 -1
  112. data/app/views/cmsedit/index.html.erb +7 -1
  113. data/app/views/cmsedit/new.html.erb +3 -1
  114. data/app/views/dc_common/_help.html.erb +17 -0
  115. data/app/views/layouts/models.html.erb +2 -1
  116. data/config/locales/drgcms_en.yml +27 -3
  117. data/config/locales/drgcms_sl.yml +32 -5
  118. data/config/locales/models_en.yml +65 -17
  119. data/config/locales/models_sl.yml +69 -18
  120. data/drg_cms.gemspec +1 -1
  121. data/lib/drg_cms.rb +61 -1
  122. data/lib/drg_cms/version.rb +1 -1
  123. data/lib/generators/new_drg_form/new_drg_form_generator.rb +9 -2
  124. data/lib/tasks/database.rake +6 -56
  125. metadata +73 -54
  126. data/app/assets/stylesheets/drg_cms/__jquery-ui.css +0 -339
  127. data/app/helpers/application_helper.rb +0 -2
  128. data/app/helpers/cmsedit_helper.rb +0 -888
  129. data/app/models/dc_dummy.rb +0 -102
  130. data/test/fixtures/drg_cms_test_data.rb +0 -87
@@ -0,0 +1,506 @@
1
+ #--
2
+ # Copyright (c) 2012+ 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
+ #
26
+ # CmseditHelper module defines helper methods used by cmsedit actions. Output is controlled by
27
+ # data found in 3 major sections of DRG CMS form: index, result_set and form sections.
28
+ #
29
+ ###########################################################################
30
+ module CmsEditHelper
31
+
32
+ ############################################################################
33
+ # Will return value when internal or additional parameters are defined in action
34
+ # Subroutine of dc_actions_for_form.
35
+ ############################################################################
36
+ def dc_value_for_parameter(param, current_document = nil)#:nodoc:
37
+ if param.class == Hash
38
+ dc_internal_var(param['object'] ||= 'record', param['method'], current_document)
39
+ elsif param.to_s.match(/record|document/)
40
+ current_document ? current_document : @record
41
+ else
42
+ param
43
+ end
44
+ end
45
+
46
+ ############################################################################
47
+ # Creates actions div for edit form.
48
+ #
49
+ # Displaying readonly form turned out to be challenge. For now when readonly parameter
50
+ # has value 2, back link will force readonly form. Value 1 or not set will result in
51
+ # normal link.
52
+ ############################################################################
53
+ def dc_is_action_active?(options)
54
+ if options['when_new']
55
+ dc_deprecate("when_option will be deprecated and replaced by active: not_new_record! Form #{params[:form_name]}")
56
+ return !(dc_dont?(options['when_new']) && @record.new_record?)
57
+ end
58
+ return true unless options['active']
59
+
60
+ # alias record and document so both can be used in eval
61
+ record = document = @record
62
+ option = options['active']
63
+ case
64
+ # usually only for test
65
+ when option.class == TrueClass || option['eval'].class == TrueClass then true
66
+ when option.class == String then
67
+ if option.match(/new_record/i)
68
+ (@record.new_record? && option == 'new_record') || (!@record.new_record? && option == 'not_new_record')
69
+ elsif option.match(/\./)
70
+ # shortcut for method and eval option
71
+ dc_process_eval(option, self)
72
+ else
73
+ eval(option['eval'])
74
+ end
75
+ # direct evaluate expression
76
+ when option['eval'] then
77
+ eval(option['eval'])
78
+ when option['method'] then
79
+ # if record present send record otherwise send self as parameter
80
+ dc_process_eval(option['method'], self)
81
+ else
82
+ false
83
+ end
84
+ end
85
+
86
+ ############################################################################
87
+ # Creates actions div for edit form.
88
+ #
89
+ # Displaying readonly form turned out to be challenge. For now when readonly parameter
90
+ # has value 2, back link will force readonly form. Value 1 or not set will result in
91
+ # normal link.
92
+ ############################################################################
93
+ def dc_actions_for_form(position)
94
+ # create standard actions
95
+ std_actions = {1 => 'back', 2 => {'type' => 'submit', 'caption' => 'drgcms.save'},
96
+ 3 => {'type' => 'submit', 'caption' => 'drgcms.save&back'} }
97
+ # when edit only
98
+ unless @record.try(:id).nil?
99
+ std_actions.merge!({6 => 'new'} )
100
+ std_actions.merge!(@record.active ? {5 => 'disable'} : {5 => 'enable'} ) if @record.respond_to?('active')
101
+ std_actions.merge!({7 => 'refresh'} )
102
+ end
103
+ actions = @form['form']['actions']
104
+ # shortcut for actions: standard
105
+ actions = nil if actions.class == String && actions == 'standard'
106
+ # standard actions
107
+ actions = std_actions if actions.nil?
108
+ # readonly
109
+ actions = {1 => 'back'} if @form['readonly']
110
+ actions = {1 => 'close'} if params[:window_close]
111
+ # Actions are strictly forbidden
112
+ if @form['form']['actions'] and dc_dont?(@form['form']['actions'])
113
+ actions = []
114
+ elsif actions['standard']
115
+ actions.merge!(std_actions)
116
+ actions['standard'] = nil
117
+ end
118
+ # Update save and save&back
119
+ actions.each do |k,v|
120
+ if v.class == String
121
+ if v.match(/save\&back/i)
122
+ actions[k] = {'type' => 'submit', 'caption' => 'drgcms.save&back'}
123
+ elsif v == 'save'
124
+ actions[k] = {'type' => 'submit', 'caption' => 'drgcms.save'}
125
+ end
126
+ end
127
+ end
128
+ # remove standard option and sort so that standard actions come first
129
+ actions.delete('standard')
130
+ actions = actions.to_a.sort {|x,y| x[0] <=> y[0]}
131
+ # Add spinner to the beginning
132
+ html = %Q[<span class="dc-spinner">#{fa_icon('spinner lg spin')}</span><ul class="dc-menu #{position}">]
133
+
134
+ actions.each do |key, options|
135
+ session[:form_processing] = "form:actions: #{key} #{options}"
136
+ next if options.nil? # yes it happends
137
+ parms = @parms.clone
138
+ if options.class == String
139
+ next if params[:readonly] and !options.match(/back|close/)
140
+
141
+ html << '<li class="dc-link dc-animate">'
142
+ html << case
143
+ when (options == 'back' or options == 'cancle') then
144
+ # If return_to is present link directly to URL
145
+ if parms['xreturn_to'] # disabled for now
146
+ dc_link_to( 'drgcms.back','arrow-left', parms['return_to'] )
147
+ else
148
+ parms['action'] = 'index'
149
+ parms['readonly'] = parms['readonly'].to_s.to_i < 2 ? nil : 1
150
+ dc_link_to( 'drgcms.back','arrow-left', parms )
151
+ end
152
+
153
+ when options == 'delete' then
154
+ parms['operation'] = options
155
+ parms['id'] = @record.id
156
+ dc_link_to( 'drgcms.delete','remove', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete )
157
+
158
+ when options == 'new' then
159
+ parms['action'] = options
160
+ dc_link_to( 'drgcms.new', 'plus', parms)
161
+
162
+ when (options == 'enable' or options == 'disable') then
163
+ parms['operation'] = options
164
+ parms['id'] = @record.id
165
+ icon = (options == 'enable' ? 'thumbs-o-up' : 'thumbs-o-down')
166
+ dc_link_to( "drgcms.#{options}",icon, parms, method: :delete )
167
+
168
+ when options == 'edit' then
169
+ parms['operation'] = options
170
+ parms['id'] = @record.id
171
+ dc_link_to( "drgcms.#{options}",options, parms )
172
+
173
+ when options == 'refresh' then
174
+ "<div onclick='window.location.href=window.location.href;'>#{fa_icon('refresh')} #{t('drgcms.refresh')}</div></li>"
175
+
176
+ when options == 'close' then
177
+ close = params[:window_close].to_i
178
+ if close < 2
179
+ "<div onclick='window.close();'>#{fa_icon('close')} #{t('drgcms.close')}</div></li>"
180
+ else
181
+ "<div onclick='history.back();'>#{fa_icon('close')} #{t('drgcms.close')}</div></li>"
182
+ end
183
+ else
184
+ "err1 #{key}=>#{options}"
185
+ end
186
+ html << '</td>'
187
+ # non standard actions
188
+ else
189
+ options['title'] = t("#{options['title'].downcase}", options['title']) if options['title']
190
+ html << case
191
+ # submit button
192
+ when options['type'] == 'submit'
193
+ caption = options['caption'] || 'drgcms.save'
194
+ icon = options['icon'] || 'save'
195
+ prms = {}
196
+ options['params'].each { |k,v| prms[k] = dc_value_for_parameter(v) } if options['params']
197
+ if dc_is_action_active?(options)
198
+ '<li class="dc-link-submit dc-animate">' +
199
+ dc_submit_tag(caption, icon, {:data => prms, :title => options['title'] }) +
200
+ '</li>'
201
+ else
202
+ "<li class=\"dc-link-no\">#{fa_icon(icon)} #{caption}</li>"
203
+ end
204
+
205
+ # delete with some sugar added
206
+ when options['type'] == 'delete'
207
+ parms['id'] = @record.id
208
+ parms.merge!(options['params'])
209
+ caption = options['caption'] || 'drgcms.delete'
210
+ icon = options['icon'] || 'remove'
211
+ '<li class="dc-link dc-animate">' +
212
+ dc_link_to( caption, icon, parms, data: t('drgcms.confirm_delete'), method: :delete ) +
213
+ '</li>'
214
+
215
+ # ajax or link button
216
+ when %w(ajax link window).include?(options['type'])
217
+ dc_link_ajax_window_submit_action(options, @record)
218
+
219
+ # Javascript action
220
+ when options['type'] == 'script'
221
+ dc_script_action(options)
222
+ else
223
+ '<li>err2</li>'
224
+ end
225
+ end
226
+ end
227
+ (html << '</ul>').html_safe
228
+ end
229
+
230
+ ############################################################################
231
+ # Create background div and table definitions for result set.
232
+ ############################################################################
233
+ def dc_background_for_result(start)
234
+ if start == :start
235
+ html = '<div class="dc-result-div" '
236
+ html << (@form['result_set']['table_style'] ? 'style="overflow-x: scroll;" >' : '>')
237
+
238
+ html << "\n<div class=\"dc-result #{@form['result_set']['table_class']}\" "
239
+ html << (@form['result_set']['table_style'] ? "style=\"#{@form['result_set']['table_style']}\" >" : '>')
240
+ else
241
+ html = '</div></div>'
242
+ end
243
+ html.html_safe
244
+ end
245
+
246
+ ############################################################################
247
+ # Checks if value is defined and sets default. If values are sent it also checks
248
+ # if value is found in values. If not it will report error and set value to default.
249
+ # Subroutine of dc_fields_for_tab.
250
+ ############################################################################
251
+ def dc_check_and_default(value, default, values=nil) #:nodoc:
252
+ return default if value.nil?
253
+ # check if value is within allowed values
254
+ if values
255
+ if !values.index(value)
256
+ # parameters should be in downcase. Check downcase version.
257
+ if n = values.index(value.downcase)
258
+ return values[n]
259
+ else
260
+ logger.error("DRG Forms: Value #{value} not within values [#{values.join(',')}]. Default #{default} used!")
261
+ return default
262
+ end
263
+ end
264
+ end
265
+ value
266
+ end
267
+
268
+ ############################################################################
269
+ # Creates input fields for one tab. Subroutine of dc_fields_for_form.
270
+ ############################################################################
271
+ def dc_fields_for_tab(fields_on_tab) #:nodoc:
272
+ html = '<div class="dc-form">'
273
+ labels_pos = dc_check_and_default(@form['form']['labels_pos'], 'right', ['top', 'left', 'right'])
274
+ hidden_fields, odd_even = '', nil
275
+ group_option, group_count = 0, 0
276
+ reset_cycle()
277
+ # Select form fields and sort them by key
278
+ form_fields = fields_on_tab.select {|field| field.class == Integer }
279
+ form_fields.to_a.sort.each do |number, options|
280
+ session[:form_processing] = "form:fields: #{number}=#{options}"
281
+ # ignore if edit_only singe field is required
282
+ next if params[:edit_only] and params[:edit_only] != options['name']
283
+ # hidden_fields. Add them at the end
284
+ if options['type'] == 'hidden_field'
285
+ hidden_fields << DrgcmsFormFields::HiddenField.new(self, @record, options).render
286
+ next
287
+ end
288
+ # label
289
+ field_html,label,help = dc_field_label_help(options)
290
+ # Line separator
291
+ html << dc_top_bottom_line(:top, options)
292
+ # Beginning of new row
293
+ if group_count == 0
294
+ html << '<div class="row-div">'
295
+ odd_even = cycle('odd','even')
296
+ group_count = options['group'] || 1
297
+ group_option = options['group'] || 1
298
+ end
299
+ #
300
+ html << if labels_pos == 'top'
301
+ %Q[
302
+ <div class="dc-form-label-top dc-color-#{odd_even} dc-align-left" title="#{help}">
303
+ <label for="record_#{options['name']}">#{label} </label>
304
+ <div id="td_record_#{options['name']}">#{field_html}</div>
305
+ </div> ]
306
+ else
307
+ # no label
308
+ if dc_dont?(options['caption'])
309
+ label = ''
310
+ label_width = 0
311
+ data_width = 100
312
+ elsif group_option > 1
313
+ label_width = group_option != group_count ? 10 : 14
314
+ data_width = 21
315
+ else
316
+ label_width = 14
317
+ data_width = 85
318
+ end
319
+ %Q[
320
+ <div class="dc-form-label dc-color-#{odd_even} dc-align-#{labels_pos} dc-width-#{label_width}" title="#{help}">
321
+ <label for="record_#{options['name']}">#{label} </label>
322
+ </div>
323
+ <div id="td_record_#{options['name']}" class="dc-form-field dc-color-#{odd_even} dc-width-#{data_width}">#{field_html}</div>
324
+ ]
325
+ end
326
+ # check if group end
327
+ if (group_count -= 1) == 0
328
+ html << '</div>'
329
+ # insert dummy div when only two fields in group
330
+ html << '<div></div>' if group_option == 2
331
+ end
332
+
333
+ html << dc_top_bottom_line(:bottom, options)
334
+ end
335
+ html << '</div>' << hidden_fields
336
+ end
337
+
338
+ ############################################################################
339
+ # Creates edit form from fields or tabs options
340
+ ############################################################################
341
+ def dc_fields_for_form
342
+ html, tabs, tab_data = '',[], ''
343
+ @js ||= ''
344
+ @css ||= ''
345
+ # Only fields defined
346
+ if (form_fields = @form['form']['fields'])
347
+ html << "<div id='data_fields' " + (@form['form']['height'] ? "style=\"height: #{@form['form']['height']}px;\">" : '>')
348
+ html << dc_fields_for_tab(form_fields) + '</div>'
349
+ else
350
+ # there are multiple tabs on form
351
+ first = true # first tab
352
+ @form['form']['tabs'].keys.sort.each do |tab_name|
353
+ next if tab_name.match('actions')
354
+ # Tricky when editing single field. If field is not present on the tab skip to next tab
355
+ if params[:edit_only]
356
+ is_on_tab = false
357
+ @form['form']['tabs'][tab_name].each { |k, v| is_on_tab = true if params[:edit_only] == v['name'] }
358
+ next unless is_on_tab
359
+ end
360
+ # first div is displayed, all others are hidden
361
+ tab_data << "<div id=\"data_#{tab_name.delete("\s\n")}\""
362
+ tab_data << ' class="div-hidden"' unless first
363
+ tab_data << " style=\"height: #{@form['form']['height']}px;\"" if @form['form']['height']
364
+ tab_data << ">#{dc_fields_for_tab(@form['form']['tabs'][tab_name])}</div>"
365
+
366
+ tab_label, tab_title = dc_tab_label_help(tab_name)
367
+ tabs << [tab_name, tab_label, tab_title]
368
+ first = false
369
+ end
370
+ # make it all work together
371
+ html << '<ul class="dc-form-ul" >'
372
+ first = true # first tab must be selected
373
+ tabs.each do |tab_name, tab_label, tab_title|
374
+ html << %(<li id="li_#{tab_name}" data-div="#{tab_name.delete("\s\n")}" title="#{tab_title}" class="dc-form-li)
375
+ html << ' dc-form-li-selected' if first
376
+ html << "\">#{tab_label}</li>"
377
+ first = false
378
+ end
379
+ html << '</ul>'
380
+ html << tab_data
381
+ end
382
+ # add last_updated_at hidden field so controller can check if record was updated in db during editing
383
+ html << hidden_field(nil, :last_updated_at, value: @record.updated_at.to_i) if @record.respond_to?(:updated_at)
384
+ # add form time stamp to prevent double form submit
385
+ html << hidden_field(nil, :form_time_stamp, value: Time.now.to_i)
386
+ # add javascript code if defined by form
387
+ @js << "\n#{@form['script']}"
388
+ @css << "\n#{@form['css']}"
389
+ html.html_safe
390
+ end
391
+
392
+ ############################################################################
393
+ # Creates head form div. Head form div is used to display header data usefull
394
+ # to be seen even when tabs are switched.
395
+ ############################################################################
396
+ def dc_head_for_form
397
+ @css ||= ''
398
+ head = @form['form']['head']
399
+ return '' if head.nil?
400
+ html = %(<div class="dc-head #{head['class']}">\n<div class="dc-row">)
401
+ split = head['split'] || 4
402
+ percent = 100/split
403
+ current = 0
404
+ head_fields = head.select {|field| field.class == Integer }
405
+ head_fields.to_a.sort.each do |number, options|
406
+ session[:form_processing] = "form: head: #{number}=#{options}"
407
+ # Label
408
+ caption = options['caption']
409
+ span = options['span'] || 1
410
+ @css << "\n#{options['css']}" unless options['css'].blank?
411
+ label = if caption.blank?
412
+ ''
413
+ elsif options['name'] == caption
414
+ t_name(options['name'], options['name'].capitalize.gsub('_',' ') )
415
+ else
416
+ t(caption, caption)
417
+ end
418
+ # Field value
419
+ begin
420
+ field = if options['eval']
421
+ dc_process_column_eval(options, @record)
422
+ else
423
+ @record.send(options['name'])
424
+ end
425
+ rescue Exception => e
426
+ dc_log_exception(e, 'dc_head_for_form')
427
+ field = '!!!Error'
428
+ end
429
+ #
430
+ klass = dc_style_or_class(nil, options['class'], field, @record)
431
+ style = dc_style_or_class(nil, options['style'], field, @record)
432
+ html << %Q[<div class="dc-column #{klass}" style="width:#{percent*span}%;#{style}">
433
+ #{label.blank? ? '' : "<span class=\"label\">#{label}</span>"}
434
+ <span id="head-#{options['name']}" class="field">#{field}</span>
435
+ </div>]
436
+ current += span
437
+ if current == split
438
+ html << %Q[</div>\n<div class="dc-row">]
439
+ current = 0
440
+ end
441
+ end
442
+ html << '</div></div>'
443
+ html.html_safe
444
+ end
445
+
446
+ ############################################################################
447
+ # Returns username for id. Subroutine of dc_document_statistics
448
+ ###########################################################################
449
+ def dc_document_user_for(field_name) #:nodoc:
450
+ if @record[field_name]
451
+ u = DcUser.find(@record[field_name])
452
+ return u ? u.name : @record[field_name]
453
+ end
454
+ # nil
455
+ end
456
+
457
+ ############################################################################
458
+ # Creates current document statistics div (created_by, created_at, ....) at the bottom of edit form.
459
+ # + lots of more. At the moment also adds icon for dumping current document as json text.
460
+ ############################################################################
461
+ def dc_document_statistics
462
+ return '' if @record.new_record? or dc_dont?(@form['form']['info'])
463
+ html = %Q[<div id="dc-document-info">#{fa_icon('info-circle lg')}</div> <div id="dc-document-info-popup" class="div-hidden"> ]
464
+ #
465
+ u = dc_document_user_for('created_by')
466
+ html << %Q[<div><span>#{t('drgcms.created_by', 'Created by')}: </span><span>#{u}</span></div>] if u
467
+ u = dc_document_user_for('updated_by')
468
+ html << %Q[<div><span>#{t('drgcms.updated_by', 'Updated by')}: </span><span>#{u}</span></div>] if u
469
+ html << %Q[<div><span>#{t('drgcms.created_at', 'Created at')}: </span><span>#{dc_format_value(@record.created_at)}</span></div>] if @record['created_at']
470
+ html << %Q[<div><span>#{t('drgcms.updated_at', 'Updated at')}: </span><span>#{dc_format_value(@record.updated_at)}</span></div>] if @record['updated_at']
471
+ # copy to clipboard icon
472
+ parms = params.clone
473
+ parms[:controller] = 'dc_common'
474
+ parms[:action] = 'copy_clipboard'
475
+ url = url_for(parms.permit!)
476
+ html << fa_icon('copy lg', class: 'dc-link-img dc-link-ajax dc-animate',
477
+ 'data-url' => url, 'data-request' => 'get', title: t('drgcms.doc_copy_clipboard') )
478
+
479
+ url = url_for(controller: :cmsedit, action: :index, table: 'dc_journal', filter: 'on',
480
+ filter_oper: 'eq', filter_field: 'doc_id', filter_value: @record.id)
481
+ html << fa_icon('history lg', class: 'dc-link-img dc-animate dc-window-open',
482
+ 'data-url' => url, title: t('helpers.label.dc_journal.tabletitle') )
483
+
484
+ (html << '</div></div>').html_safe
485
+ end
486
+
487
+ private
488
+
489
+ ############################################################################
490
+ # Creates top or bottom horizontal line on form.
491
+ #
492
+ # @param [String] location (top or bottom)
493
+ # @param [Object] options yaml field definition
494
+ #
495
+ # @return [String] html code for drawing a line
496
+ ############################################################################
497
+ def dc_top_bottom_line(location, options)
498
+ if options["#{location}-line"] || options['line'].to_s == location.to_s
499
+ '<div class="dc-separator"></div>'
500
+ else
501
+ ''
502
+ end
503
+ end
504
+
505
+
506
+ end