drg_cms 0.5.52.16 → 0.6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +446 -144
  3. data/app/assets/javascripts/drg_cms/jstree.min.js +6 -6
  4. data/app/assets/javascripts/drg_cms_application.js +1 -1
  5. data/app/assets/stylesheets/drg_cms/drg_cms.css +625 -243
  6. data/app/assets/stylesheets/drg_cms/jstree.css +6 -12
  7. data/app/assets/stylesheets/drg_cms/select-multiple.css +18 -12
  8. data/app/assets/stylesheets/drg_cms_cms.css +1 -1
  9. data/app/controllers/cmsedit_controller.rb +536 -331
  10. data/app/controllers/dc_application_controller.rb +380 -117
  11. data/app/controllers/dc_common_controller.rb +105 -14
  12. data/app/{controllers → controls}/browse_models_control.rb +0 -0
  13. data/app/controls/dc_help_control.rb +126 -0
  14. data/app/{controllers → controls}/dc_page_control.rb +24 -8
  15. data/app/controls/dc_poll_result_control.rb +88 -0
  16. data/app/controls/dc_report.rb +225 -0
  17. data/app/{controllers → controls}/design_element_settings_control.rb +0 -0
  18. data/app/forms/all_options.yml +50 -9
  19. data/app/forms/cms_menu.yml +28 -18
  20. data/app/forms/dc_ad.yml +11 -22
  21. data/app/forms/dc_big_table.yml +1 -0
  22. data/app/forms/dc_big_table_value.yml +1 -0
  23. data/app/forms/dc_category.yml +2 -1
  24. data/app/forms/dc_design.yml +20 -16
  25. data/app/forms/dc_filter.yml +3 -6
  26. data/app/forms/dc_help_1.yml +109 -0
  27. data/app/forms/dc_journal.yml +3 -1
  28. data/app/forms/dc_json_ld.yml +59 -0
  29. data/app/forms/dc_key_value.yml +32 -0
  30. data/app/forms/dc_link.yml +1 -1
  31. data/app/forms/dc_menu.yml +2 -0
  32. data/app/forms/dc_menu_item.yml +2 -0
  33. data/app/forms/dc_page.yml +3 -5
  34. data/app/forms/dc_part.yml +1 -0
  35. data/app/forms/dc_piece.yml +1 -0
  36. data/app/forms/dc_poll.yml +19 -9
  37. data/app/forms/dc_poll_item.yml +2 -1
  38. data/app/forms/dc_poll_result.yml +83 -0
  39. data/app/forms/dc_poll_result_export.yml +35 -0
  40. data/app/forms/dc_seo.yml +33 -0
  41. data/app/forms/dc_simple_menu.yml +2 -0
  42. data/app/forms/dc_site.yml +4 -12
  43. data/app/forms/dc_user.yml +27 -11
  44. data/app/forms/dc_user_role.yml +3 -0
  45. data/app/forms/json_ld_schema.yml +168 -0
  46. data/app/helpers/cms_common_helper.rb +376 -0
  47. data/app/helpers/cms_edit_helper.rb +506 -0
  48. data/app/helpers/cms_helper.rb +268 -0
  49. data/app/helpers/cms_index_helper.rb +576 -0
  50. data/app/helpers/dc_application_helper.rb +183 -271
  51. data/app/models/concerns/dc_page_concern.rb +40 -6
  52. data/app/models/concerns/dc_policy_rule_concern.rb +20 -8
  53. data/app/models/concerns/dc_seo_concern.rb +66 -0
  54. data/app/models/concerns/dc_site_concern.rb +67 -44
  55. data/app/models/concerns/dc_user_concern.rb +62 -21
  56. data/app/models/dc_design.rb +30 -18
  57. data/app/models/dc_filter.rb +22 -13
  58. data/app/models/dc_json_ld.rb +152 -0
  59. data/app/models/dc_key_value.rb +48 -0
  60. data/app/models/dc_key_value_store.rb +1 -0
  61. data/app/models/dc_memory.rb +8 -1
  62. data/app/models/dc_page.rb +0 -1
  63. data/app/models/dc_permission.rb +49 -9
  64. data/app/models/dc_policy.rb +25 -14
  65. data/app/models/dc_policy_role.rb +22 -11
  66. data/app/models/dc_poll.rb +39 -19
  67. data/app/models/{drgcms_form_fields/drgcms_form_fields.rb → dc_poll_result.rb} +23 -2
  68. data/app/models/dc_temp.rb +140 -0
  69. data/app/models/dc_user_role.rb +2 -2
  70. data/app/models/drgcms_form_fields.rb +14 -6
  71. data/app/models/drgcms_form_fields/action.rb +61 -0
  72. data/app/models/drgcms_form_fields/check_box.rb +3 -0
  73. data/app/models/drgcms_form_fields/comment.rb +8 -4
  74. data/app/models/drgcms_form_fields/date_picker.rb +11 -9
  75. data/app/models/drgcms_form_fields/date_select.rb +1 -1
  76. data/app/models/drgcms_form_fields/{date_time_picker.rb → datetime_picker.rb} +12 -10
  77. data/app/models/drgcms_form_fields/datetime_select.rb +1 -1
  78. data/app/models/drgcms_form_fields/drgcms_field.rb +55 -9
  79. data/app/models/drgcms_form_fields/embedded.rb +26 -16
  80. data/app/models/drgcms_form_fields/file_field.rb +52 -0
  81. data/app/models/drgcms_form_fields/file_select.rb +2 -2
  82. data/app/models/drgcms_form_fields/hash_field.rb +90 -0
  83. data/app/models/drgcms_form_fields/hidden_field.rb +1 -1
  84. data/app/models/drgcms_form_fields/html_field.rb +1 -1
  85. data/app/models/drgcms_form_fields/link_to.rb +2 -2
  86. data/app/models/drgcms_form_fields/method.rb +66 -0
  87. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +23 -14
  88. data/app/models/drgcms_form_fields/number_field.rb +15 -6
  89. data/app/models/drgcms_form_fields/radio.rb +96 -0
  90. data/app/models/drgcms_form_fields/readonly.rb +2 -2
  91. data/app/models/drgcms_form_fields/select.rb +92 -29
  92. data/app/models/drgcms_form_fields/text_area.rb +1 -1
  93. data/app/models/drgcms_form_fields/text_autocomplete.rb +29 -17
  94. data/app/models/drgcms_form_fields/text_field.rb +1 -1
  95. data/app/models/drgcms_form_fields/text_with_select.rb +6 -3
  96. data/app/models/drgcms_form_fields/tree_select.rb +29 -10
  97. data/app/{helpers → renderers}/dc_ad_renderer.rb +0 -0
  98. data/app/{helpers → renderers}/dc_big_menu_renderer.rb +1 -0
  99. data/app/{helpers → renderers}/dc_captcha_renderer.rb +0 -0
  100. data/app/{helpers → renderers}/dc_common_renderer.rb +0 -0
  101. data/app/{helpers → renderers}/dc_gallery_renderer.rb +1 -0
  102. data/app/{helpers → renderers}/dc_menu_renderer.rb +11 -4
  103. data/app/{helpers → renderers}/dc_page_renderer.rb +1 -0
  104. data/app/{helpers → renderers}/dc_part_renderer.rb +5 -4
  105. data/app/{helpers → renderers}/dc_piece_renderer.rb +1 -1
  106. data/app/{helpers → renderers}/dc_poll_renderer.rb +84 -48
  107. data/app/{helpers → renderers}/dc_renderer.rb +1 -0
  108. data/app/{helpers → renderers}/dc_simple_menu_renderer.rb +1 -0
  109. data/app/views/cmsedit/{remove_edit_stuff.js.erb → __remove_edit_stuff.js.erb} +0 -0
  110. data/app/views/cmsedit/{show.html.erb → __show.html.erb} +0 -0
  111. data/app/views/cmsedit/_edit_stuff.html.erb +4 -25
  112. data/app/views/cmsedit/_form.html.erb +4 -3
  113. data/app/views/cmsedit/_result.html.erb +2 -3
  114. data/app/views/cmsedit/edit.html.erb +4 -1
  115. data/app/views/cmsedit/index.html.erb +7 -1
  116. data/app/views/cmsedit/new.html.erb +3 -1
  117. data/app/views/dc_common/_help.html.erb +8 -0
  118. data/app/views/layouts/models.html.erb +2 -1
  119. data/config/locales/drgcms_en.yml +26 -3
  120. data/config/locales/drgcms_sl.yml +31 -5
  121. data/config/locales/models_en.yml +66 -18
  122. data/config/locales/models_sl.yml +71 -20
  123. data/drg_cms.gemspec +3 -3
  124. data/lib/drg_cms.rb +63 -1
  125. data/lib/drg_cms/version.rb +2 -2
  126. data/lib/generators/new_drg_form/new_drg_form_generator.rb +9 -2
  127. data/lib/tasks/database.rake +6 -56
  128. metadata +81 -63
  129. data/app/assets/stylesheets/drg_cms/__jquery-ui.css +0 -339
  130. data/app/helpers/application_helper.rb +0 -2
  131. data/app/helpers/cmsedit_helper.rb +0 -885
  132. data/app/models/dc_dummy.rb +0 -102
  133. data/test/fixtures/drg_cms_test_data.rb +0 -87
@@ -1,2 +0,0 @@
1
- module ApplicationHelper
2
- end
@@ -1,885 +0,0 @@
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
- # javascript part created by form helpers
32
- attr_reader :js
33
-
34
- ############################################################################
35
- # Get standard actions when actions directive contains single line.
36
- # Subroutine of dc_actions_for_index
37
- #
38
- # Allows for actions: new, filter, standard syntax
39
- ############################################################################
40
- def define_standard_actions(actions_params, standard)
41
- actions = {}
42
- actions_params.split(',').each do |an_action|
43
- an_action.strip!
44
- if an_action == 'standard'
45
- actions.merge!(standard)
46
- else
47
- standard.each do |index, action|
48
- (actions[index] = action; break) if action == an_action
49
- end
50
- end
51
- end
52
- actions
53
- end
54
-
55
- ############################################################################
56
- # Creates action div for cmsedit index action.
57
- ############################################################################
58
- def dc_actions_for_index()
59
- return '' if @form['index'].nil? or @form['readonly']
60
- actions = @form['index']['actions']
61
- return '' if actions.nil? or actions.size == 0
62
- std_actions = {2 => 'new', 3 => 'sort', 4 => 'filter' }
63
- if actions.class == String
64
- actions = define_standard_actions(actions, std_actions)
65
- elsif actions['standard']
66
- actions.merge!(std_actions)
67
- actions['standard'] = nil
68
- end
69
-
70
- # start div with hidden spinner image
71
- html = <<EOT
72
- <div id="dc-action-menu">
73
- <span class="dc-spinner div-hidden">#{fa_icon('spinner lg spin')}</span>
74
- <ul class="dc-action-menu">
75
- EOT
76
- # Remove actions settings and sort
77
- only_actions = []
78
- actions.each { |key, value| only_actions << [key, value] if key.class == Integer }
79
- only_actions.sort_by!(&:first)
80
- only_actions.each do |element|
81
- k,v = element
82
- session[:form_processing] = "index:actions: #{k}=#{v}"
83
- next if v.nil? # must be
84
- url = @parms.clone
85
- yaml = v.class == String ? {'type' => v} : v # if single definition simulate type parameter
86
- action = yaml['type'].to_s.downcase
87
- if action == 'url'
88
- dc_deprecate "action: url will be deprecated. Use action: link in index: actions"
89
- action = 'link'
90
- end
91
- # if return_to is present link directly to URL
92
- if action == 'link' and yaml['url']
93
- url = yaml['url']
94
- else
95
- url['controller'] = yaml['controller'] if yaml['controller']
96
- url['action'] = yaml['action'] || action
97
- url['table'] = yaml['table'] if yaml['table']
98
- url['form_name'] = yaml['form_name'] if yaml['form_name']
99
- end
100
- # html link options
101
- yhtml = yaml['html'] || {}
102
- yhtml['title'] = yaml['title'] if yaml['title']
103
- html << '<li class="dc-animate">'
104
- #
105
- html << case
106
- # sort
107
- when action == 'sort' then
108
- choices = [['id','id']]
109
- if @form['index']['sort']
110
- @form['index']['sort'].split(',').each do |s|
111
- s.strip!
112
- choices << [ t("helpers.label.#{@form['table']}.#{s}"), s ]
113
- end
114
- end
115
- fa_icon('sort-alpha-asc') + ' ' + t('drgcms.sort') + ' ' +
116
- select('sort', 'sort', choices, { include_blank: true },
117
- { class: 'drgcms_sort', 'data-table' => @form['table']} )
118
- # filter
119
- when action == 'filter' then
120
- caption = t('drgcms.filter')
121
- caption << '&nbsp;' + fa_icon('caret-down lg') + DcFilter.menu_filter(self)
122
- # add filter OFF link
123
- s = session[@form['table']]
124
- if s and s[:filter]
125
- caption << '&nbsp;&nbsp;' + dc_link_to(nil,'remove lg', {controller: 'cmsedit',
126
- filter: 'off', table: @form['table']}, { title: DcFilter.title4_filter_off(s[:filter]) })
127
- end
128
- caption
129
- # new
130
- when action == 'new' then
131
- caption = yaml['caption'] || 'drgcms.new'
132
- dc_link_to(caption,'plus', url, yhtml )
133
- # menu
134
- when action == 'menu' then
135
- caption = t(v['caption'], v['caption']) + '&nbsp;' + fa_icon('caret-down lg')
136
- caption + eval(v['eval'])
137
- =begin
138
- # reorder
139
- when action == 'reorder' then
140
- caption = t('drgcms.reorder')
141
- parms = @parms.clone
142
- parms['operation'] = v
143
- parms['id'] = params[:ids]
144
- parms['table'] = @form['table']
145
- dc_link_to( caption, 'reorder', parms, method: :delete )
146
- =end
147
- else
148
- caption = yaml['caption'] || yaml['text']
149
- icon = yaml['icon'] ? yaml['icon'] : action
150
- dc_link_to(caption, icon, url, yhtml)
151
- end
152
- html << '</li>'
153
- end
154
- html << '</ul>'
155
- html << DcFilter.get_filter_field(self)
156
- html << '</div>'
157
- html.html_safe
158
- end
159
-
160
- ############################################################################
161
- # Creates filter div for cmsedit index/filter action.
162
- ############################################################################
163
- def dc_div_filter()
164
- choices = []
165
- filter = (@form['index'] and @form['index']['filter']) ? @form['index']['filter'] + ',' : ''
166
- filter << 'id as text_field' # filter id is added by default
167
- filter.split(',').each do |f|
168
- f.strip!
169
- name = f.match(' as ') ? f.split(' ').first : f
170
- # like another field on the form
171
- if f.match(' like ')
172
- a = f.split(' ')
173
- name = a.first
174
- f = a.last
175
- end
176
- choices << [ t("helpers.label.#{@form['table']}.#{name}", name), f ]
177
- end
178
- choices4_operators = t('drgcms.choices4_filter_operators').chomp.split(',').inject([]) {|r,v| r << (v.match(':') ? v.split(':') : v )}
179
- # currently selected options
180
- if session[@form['table']] and session[@form['table']][:filter]
181
- field_name, operators_value, dummy = session[@form['table']][:filter].split("\t")
182
- else
183
- field_name, operators_value = nil, nil
184
- end
185
- #{ form_tag :table => @form['table'], filter: :on, filter_input: 1, action: :index, method: :post }
186
- url = url_for(table: @form['table'],form_name: params['form_name'], filter: :on, filter_input: 1, action: :index, controller: :cmsedit)
187
- html =<<EOT
188
- <div id="drgcms_filter" class="div-hidden">
189
- <h1>#{t('drgcms.filter_set')}</h1>
190
-
191
- #{ select(nil, 'filter_field1', options_for_select(choices, field_name), { include_blank: true }) }
192
- #{ select(nil, 'filter_oper', options_for_select(choices4_operators, operators_value)) }
193
- <div class="dc-menu">
194
- <div class="dc-link dc-animate drgcms_popup_submit" data-url="#{url}">#{fa_icon('check-square-o')} #{t('drgcms.filter_on')}</div>
195
- <div class="dc-link dc-animate">#{dc_link_to('drgcms.filter_off','close', {action: :index, filter: 'off', table: @form['table'], form_name: params['form_name']}) }</div>
196
- </div>
197
- </div>
198
- EOT
199
- html.html_safe
200
- end
201
-
202
- ############################################################################
203
- # Creates title div for cmsedit index result set records. Title div also includes paging
204
- # options.
205
- ############################################################################
206
- def dc_table_title_for_result(result=nil)
207
- title = if @form['title'] # form has title section
208
- t(@form['title'],@form['title'])
209
- else # get name from translations
210
- t('helpers.label.' + @form['table'] + '.tabletitle', @form['table'])
211
- end
212
- dc_table_title(title, result)
213
- end
214
-
215
- ############################################################################
216
- # Creates code for link or ajax action type. Subroutine of dc_actions_for_result.
217
- ############################################################################
218
- def dc_link_or_ajax(yaml, parms) #:nodoc:
219
- rest = {}
220
- rest['method'] = yaml['method'] || yaml['request'] || 'get'
221
- rest['caption'] = yaml['caption'] || yaml['text']
222
- # rest['class'] = (yaml['type'] == 'link' ? 'dc-link' : 'dc-link-ajax') + ' dc-animate'
223
- rest['class'] = 'dc-animate'
224
- rest['title'] = yaml['title']
225
-
226
- dc_deprecate "Form: result_set:action:text directive will be deprecated. Use caption instead of text." if yaml['text']
227
- if yaml['type'] == 'link'
228
- dc_link_to(yaml['caption'], yaml['icon'], parms, rest )
229
- else
230
- rest['data-url'] = url_for(parms)
231
- rest['class'] << " fa fa-#{yaml['icon']}"
232
- fa_icon(yaml['icon'], rest )
233
- end
234
- end
235
-
236
- ############################################################################
237
- # Determines actions and width of actions column
238
- ############################################################################
239
- def dc_actions_column()
240
- actions = @form['result_set']['actions']
241
- # standard actions
242
- actions = {'standard' => true} if actions.class == String && actions == 'standard'
243
- std_actions = {' 2' => 'edit', ' 3' => 'delete'}
244
- actions.merge!(std_actions) if actions['standard']
245
- #
246
- width = @form['result_set']['actions_width'] || 20*actions.size
247
- [ actions, "<div class=\"actions\" style=\"width: #{width}px;\">" ]
248
- end
249
-
250
- ############################################################################
251
- # Creates actions that could be performed on single row of result set.
252
- ############################################################################
253
- def dc_actions_for_result(document)
254
- actions = @form['result_set']['actions']
255
- return '' if actions.nil? or @form['readonly']
256
- #
257
- actions, html = dc_actions_column()
258
- actions.each do |k,v|
259
- session[:form_processing] = "result_set:actions: #{k}=#{v}"
260
- next if k == 'standard' # ignore standard definition
261
- parms = @parms.clone
262
- yaml = v.class == String ? {'type' => v} : v # if single definition simulate type parameter
263
- html << case
264
- when yaml['type'] == 'edit' then
265
- parms['action'] = 'edit'
266
- parms['id'] = document.id
267
- dc_link_to( nil, 'pencil lg', parms )
268
- when yaml['type'] == 'duplicate' then
269
- parms['id'] = document.id
270
- # duplicate string will be added to these fields.
271
- parms['dup_fields'] = yaml['dup_fields']
272
- parms['action'] = 'create'
273
- dc_link_to( nil, 'copy lg', parms, data: { confirm: t('drgcms.confirm_dup') }, method: :post )
274
- when yaml['type'] == 'delete' then
275
- parms['action'] = 'destroy'
276
- parms['id'] = document.id
277
- dc_link_to( nil, 'remove lg', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete )
278
- # undocumented so far
279
- when yaml['type'] == 'edit_embedded'
280
- parms['controller'] = 'cmsedit'
281
- parms['table'] += ";#{yaml['table']}"
282
- parms['ids'] ||= ''
283
- parms['ids'] += "#{document.id};"
284
- dc_link_to( nil, 'table lg', parms, method: :get )
285
- when yaml['type'] == 'link' || yaml['type'] == 'ajax' then
286
- if yaml['url']
287
- parms['controller'] = yaml['url']
288
- parms['idr'] = document.id
289
- else
290
- parms['id'] = document.id
291
- end
292
- parms['controller'] = yaml['controller'] if yaml['controller']
293
- parms['action'] = yaml['action'] if yaml['action']
294
- parms['table'] = yaml['table'] if yaml['table']
295
- parms['form_name'] = yaml['form_name'] if yaml['form_name']
296
- parms['target'] = yaml['target'] if yaml['target']
297
- dc_link_or_ajax(yaml, parms)
298
- else # error.
299
- yaml['type'].to_s
300
- end
301
- end
302
- html << '</div>'
303
- html.html_safe
304
- end
305
-
306
- ############################################################################
307
- # Creates header div for result set.
308
- ############################################################################
309
- def dc_header_for_result()
310
- html = '<div class="dc-result-header">'
311
- if @form['result_set']['actions'] and !@form['readonly']
312
- ignore, code = dc_actions_column()
313
- html << code + '</div>'
314
- end
315
- # preparation for sort icon
316
- sort_field, sort_direction = nil, nil
317
- if session[@form['table']]
318
- sort_field, sort_direction = session[@form['table']][:sort].to_s.split(' ')
319
- end
320
- #
321
- if (columns = @form['result_set']['columns'])
322
- columns.each do |k,v|
323
- session[:form_processing] = "result_set:columns: #{k}=#{v}"
324
- #
325
- th = %Q[<div class="th" style="width: #{v['width'] || '15%'};text-align: #{v['align'] || 'left'};"]
326
- v = {'name' => v} if v.class == String
327
- caption = v['caption'] || t("helpers.label.#{@form['table']}.#{v['name']}")
328
- # no sorting when embedded documents or custom filter is active
329
- sort_ok = @form['result_set'].nil? || (@form['result_set'] && @form['result_set']['filter'].nil?)
330
- sort_ok = sort_ok || (@form['index'] && @form['index']['sort'])
331
- if @tables.size == 1 and sort_ok
332
- icon = 'sort lg'
333
- if v['name'] == sort_field
334
- icon = sort_direction == '1' ? 'sort-alpha-asc lg' : 'sort-alpha-desc lg'
335
- end
336
- th << ">#{dc_link_to(caption, icon, sort: v['name'], table: params[:table], form_name: params[:form_name], action: :index, icon_pos: :last )}</div>"
337
- else
338
- th << ">#{caption}</div>"
339
- end
340
- html << "<div class=\"spacer\"></div>" + th
341
- end
342
- end
343
- (html << '</div>').html_safe
344
- end
345
-
346
- ############################################################################
347
- # Creates link for single or double click on result column
348
- ############################################################################
349
- def dc_clicks_for_result(document)
350
- html = ''
351
- if @form['result_set']['dblclick']
352
- yaml = @form['result_set']['dblclick']
353
- opts = {}
354
- opts[:controller] = yaml['controller'] || 'cmsedit'
355
- opts[:action] = yaml['action']
356
- opts[:table] = yaml['table']
357
- opts[:form_name] = yaml['form_name']
358
- opts[:method] = yaml['method'] || 'get'
359
- opts[:id] = document['id']
360
- html << ' data-dblclick=' + url_for(opts)
361
- else
362
- html << (' data-dblclick=' +
363
- url_for(action: 'show', controller: 'cmsedit', id: document.id,
364
- readonly: (params[:readonly] ? 2 : 1), table: params[:table],
365
- form_name: params[:form_name], ids: params[:ids]) ) if @form['form']
366
- end
367
- html
368
- end
369
-
370
- ############################################################################
371
- # Formats value according to format supplied or data type. There is lots of things missing here.
372
- ############################################################################
373
- def dc_format_value(value, format=nil)
374
- # :TODO: Enable formating numbers.
375
- return '' if value.nil?
376
- klass = value.class.to_s
377
- case when klass.match('Time') then
378
- format ||= t('time.formats.default')
379
- value.strftime(format)
380
- when klass.match('Date') then
381
- format ||= t('date.formats.default')
382
- value.strftime(format)
383
- when format.to_s[0] == 'N' then
384
- dec = format[1].blank? ? nil : format[1].to_i
385
- sep = format[2].blank? ? nil : format[2]
386
- del = format[3].blank? ? nil : format[3]
387
- cur = format[4].blank? ? nil : format[4]
388
- dc_format_number(value, dec, sep, del, cur)
389
- else
390
- value.to_s
391
- end
392
- end
393
-
394
- ############################################################################
395
- # Defines style or class for row (tr) or column (td)
396
- ############################################################################
397
- def dc_style_or_class(selector, yaml, value, record)
398
- return '' if yaml.nil?
399
- # alias record and value so both names can be used in eval
400
- field = value
401
- document = record
402
- html = selector ? "#{selector}=\"" : ''
403
- html << if yaml.class == String
404
- yaml
405
- else
406
- (yaml['eval'] ? eval(yaml['eval']) : '') rescue 'background-color:red;'
407
- end
408
- html << '"' if selector
409
- html
410
- end
411
-
412
- ############################################################################
413
- # Creates tr code for each row of result set.
414
- ############################################################################
415
- def dc_row_for_result(document)
416
- clas = "dc-#{cycle('odd','even')} " + dc_style_or_class(nil, @form['result_set']['tr_class'], nil, document)
417
- style = dc_style_or_class('style', @form['result_set']['tr_style'], nil, document)
418
- "<div class=\"dc-result-data #{clas}\" #{dc_clicks_for_result(document)} #{style}>".html_safe
419
- end
420
-
421
- ############################################################################
422
- # Creates column for each field of result set document.
423
- ############################################################################
424
- def dc_columns_for_result(document)
425
- html = ''
426
- return html unless @form['result_set']['columns']
427
- #
428
- @form['result_set']['columns'].each do |k,v|
429
- session[:form_processing] = "result_set:columns: #{k}=#{v}"
430
- # convert shortcut to hash
431
- v = {'name' => v} if v.class == String
432
- # eval
433
- value = if v['eval']
434
- if v['eval'].match('dc_name4_id')
435
- a = v['eval'].split(',')
436
- if a.size == 3
437
- dc_name4_id(a[1], a[2], nil, document[ v['name'] ])
438
- else
439
- dc_name4_id(a[1], a[2], a[3], document[ v['name'] ])
440
- end
441
- elsif v['eval'].match('dc_name4_value')
442
- dc_name4_value( @form['table'], v['name'], document[ v['name'] ] )
443
- elsif v['eval'].match('eval ')
444
- # evaluate with specified parameters
445
- else
446
- if v['params']
447
- if v['params'] == 'document' # pass document as parameter when all
448
- eval( "#{v['eval']} document")
449
- else # list of fields delimeted by ,
450
- params = v['params'].chomp.split(',').inject('') do |result,e|
451
- result << (e.match(/\.|\:|\(/) ? e : "document['#{e.strip}']") + ','
452
- end
453
- params.chomp!(',')
454
- eval( "#{v['eval']} #{params}")
455
- end
456
- else
457
- eval( "#{v['eval']} '#{document[ v['name'] ]}'")
458
- end
459
- end
460
- # as field
461
- elsif document.respond_to?(v['name'])
462
- dc_format_value(document.send( v['name'] ), v['format'])
463
- # as hash (dc_memory)
464
- elsif document.class == Hash
465
- document[ v['name'] ]
466
- # error
467
- else
468
- "!!! #{v['name']}"
469
- end
470
- #
471
- td = '<div class="spacer"></div><div class="td" '
472
- td << dc_style_or_class('class', v['td_class'], value, document)
473
-
474
- width_align = %Q[width: #{v['width'] || '15%'};text-align: #{v['align'] || 'left'};]
475
- style = dc_style_or_class('style', v['td_style'] || v['style'], value, document)
476
- style = if style.size > 1
477
- # remove trailing " add width and add trailing " back
478
- style.slice(0..-1) + width_align + '"'
479
- else
480
- # create style string
481
- "style=\"#{width_align}\""
482
- end
483
- html << "#{td} #{style}>#{value}</div>"
484
- end
485
- html.html_safe
486
- end
487
-
488
- ############################################################################
489
- # Will return value for parameter required on form
490
- ############################################################################
491
- def dc_value_for_parameter(param)
492
- if param.class == Hash
493
- dc_internal_var(param['object'] || 'record', param['method'])
494
- else
495
- param
496
- end
497
- end
498
-
499
- ############################################################################
500
- # Creates actions div for edit form.
501
- #
502
- # Displaying readonly form turned out to be challenge. For now when readonly parameter
503
- # has value 2, back link will force readonly form. Value 1 or not set will result in
504
- # normal link.
505
- ############################################################################
506
- def dc_actions_for_form()
507
- # create standard actions
508
- std_actions = {' 1' => 'back', ' 2' => {'type' => 'submit', 'caption' => 'drgcms.save'},
509
- ' 3' => {'type' => 'submit', 'caption' => 'drgcms.save&back'} }
510
- # when edit only
511
- unless @record.id.nil?
512
- std_actions.merge!({' 6' => 'new'} )
513
- std_actions.merge!(@record.active ? {' 5' => 'disable'} : {' 5' => 'enable'} ) if @record.respond_to?('active')
514
- std_actions.merge!({' 7' => 'refresh'} )
515
- end
516
- actions = @form['form']['actions']
517
- # shortcut for actions: standard
518
- actions = nil if actions.class == String && actions == 'standard'
519
- # standard actions
520
- actions = std_actions if actions.nil?
521
- # readonly
522
- actions = {' 1' => 'back'} if @form['readonly']
523
- # Actions are strictly forbidden
524
- if @form['form']['actions'] and dc_dont?(@form['form']['actions'])
525
- actions = []
526
- elsif actions['standard']
527
- actions.merge!(std_actions)
528
- actions['standard'] = nil
529
- end
530
- # Update save and save&back
531
- actions.each do |k,v|
532
- if v.class == String
533
- if v.match(/save\&back/i)
534
- actions[k] = {'type' => 'submit', 'caption' => 'drgcms.save&back'}
535
- elsif v == 'save'
536
- actions[k] = {'type' => 'submit', 'caption' => 'drgcms.save'}
537
- end
538
- end
539
- end
540
- # Sort so that standard actions come first
541
- actions = actions.to_a.sort {|x,y| x[0].to_s <=> y[0].to_s}
542
- # Add spinner to the beginning
543
- c = %Q[<span class="dc-spinner div-hidden">#{fa_icon('spinner lg spin')}</span><ul class="dc-menu">]
544
-
545
- actions.each do |element|
546
- session[:form_processing] = "form:actions: #{element}"
547
- v = element[1]
548
- next if v.nil? # yes it happends
549
- p "Using text option in actions_for form is replaced with caption. Table #{@form['table']}" if v['text']
550
- # on_save_ok should't go inside td tags
551
- if (element[0] == 'on_save_ok') then
552
- c << hidden_field_tag(:on_save_ok, v)
553
- next
554
- end
555
- #
556
- action_active = !(dc_dont?(v['when_new']) and @record.new_record?)
557
- # p [v['caption'], action_active]
558
- parms = @parms.clone
559
- if v.class == String
560
- next if params[:readonly] and !(v == 'back')
561
-
562
- c << '<li class="dc-link dc-animate">'
563
- c << case
564
- when (v == 'back' or v == 'cancle') then
565
- # If return_to is present link directly to URL
566
- if parms['xreturn_to'] # disabled for now
567
- dc_link_to( 'drgcms.back','arrow-left', parms['return_to'] )
568
- else
569
- parms['action'] = 'index'
570
- parms['readonly'] = parms['readonly'].to_s.to_i < 2 ? nil : 1
571
- dc_link_to( 'drgcms.back','arrow-left', parms )
572
- end
573
- when v == 'delete' then
574
- parms['operation'] = v
575
- parms['id'] = @record.id
576
- dc_link_to( 'drgcms.delete','remove', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete )
577
- when v == 'new' then
578
- parms['action'] = v
579
- dc_link_to( 'drgcms.new', 'plus', parms)
580
- when (v == 'enable' or v == 'disable') then
581
- parms['operation'] = v
582
- parms['id'] = @record.id
583
- icon = (v == 'enable' ? 'thumbs-o-up' : 'thumbs-o-down')
584
- dc_link_to( "drgcms.#{v}",icon, parms, method: :delete )
585
- when v == 'edit' then
586
- parms['operation'] = v
587
- parms['id'] = @record.id
588
- dc_link_to( "drgcms.#{v}",v, parms )
589
- when v == 'refresh' then
590
- "<span onclick='window.location.href=window.location.href;'>#{fa_icon('refresh')} #{t('drgcms.refresh')}</span></li>"
591
- else
592
- "err1 #{element[0]}=>#{v}"
593
- end
594
- c << '</td>'
595
- # non standard actions
596
- else
597
- c << case
598
- # submit button
599
- when v['type'] == 'submit'
600
- caption = v['caption'] || 'drgcms.save'
601
- icon = v['icon'] || 'save'
602
- if action_active
603
- '<li class="dc-link-submit dc-animate">' +
604
- dc_submit_tag(caption, icon, {:data => v['params'], :title => v['title'] }) +
605
- '</li>'
606
- else
607
- "<li class=\"dc-link-no\">#{fa_icon(icon)} #{caption}</li>"
608
- end
609
-
610
- # delete with some sugar added
611
- when v['type'] == 'delete'
612
- parms['id'] = @record.id
613
- parms.merge!(v['params'])
614
- caption = v['caption'] || 'drgcms.delete'
615
- icon = v['icon'] || 'remove'
616
- '<li class="dc-link dc-animate">' +
617
- dc_link_to( caption, icon, parms, data: t('drgcms.confirm_delete'), method: :delete ) +
618
- '</li>'
619
-
620
- # ajax or link button
621
- when v['type'] == 'ajax' || v['type'] == 'link' || v['type'] == 'window'
622
- parms = {}
623
- # direct url
624
- if v['url']
625
- parms['controller'] = v['url']
626
- parms['idr'] = dc_document_path(@record)
627
- # make url from action controller
628
- else
629
- parms['controller'] = v['controller']
630
- parms['action'] = v['action']
631
- parms['table'] = v['table']
632
- parms['form_name'] = v['form_name']
633
- end
634
- # add current id to parameters
635
- parms['id'] = dc_document_path(@record)
636
- # additional parameters
637
- v['params'].each { |k,v| parms[k] = dc_value_for_parameter(v) } if v['params']
638
- # Error if controller parameter is missing
639
- if parms['controller'].nil?
640
- "<li>#{t('drgcms.error')}</li>"
641
- else
642
- v['caption'] ||= v['text']
643
- caption = t("#{v['caption'].downcase}", v['caption'])
644
- #
645
- url = url_for(parms) rescue ''
646
- request = v['request'] || v['method'] || 'get'
647
- icon = v['icon'] ? "#{fa_icon(v['icon'])} " : ''
648
- if v['type'] == 'ajax' # ajax button
649
- clas = action_active ? "dc-link-ajax dc-animate" : "dc-link-no"
650
- %Q[<li class="#{clas}" data-url="#{action_active ? url : ''}"
651
- data-request="#{request}" title="#{v['title']}">#{icon}#{caption}</li>]
652
- elsif v['type'] == 'link' # link button
653
- clas = action_active ? "dc-link dc-animate" : "dc-link-no"
654
- %Q[<li class="#{clas}">#{action_active ? dc_link_to(v['caption'],v['icon'], parms, {target: v['target']} ) : caption}</li>]
655
- elsif v['type'] == 'window'
656
- clas = action_active ? "dc-link dc-animate dc-window-open" : "dc-link-no"
657
- %Q[<li class="#{clas}" data-url="#{action_active ? url : ''}">#{icon}#{caption}</li>]
658
- else
659
- 'Action Type error'
660
- end
661
- end
662
-
663
- # Javascript action
664
- when v['type'] == 'script'
665
- # v['caption'] ||= 'Caption missing!'
666
- # caption = t("#{v['caption'].downcase}", v['caption'])
667
- data = {'request' => 'script', 'script' => v['js']}
668
- %Q[<li class="dc-link-ajax dc-animate">#{ dc_link_to(v['caption'],v['icon'], '#', data: data ) }</li>]
669
- else
670
- '<li>err2</li>'
671
- end
672
- end
673
- end
674
- (c << '</ul>').html_safe
675
- end
676
-
677
- ############################################################################
678
- # Create background div and table definitions for result set.
679
- ############################################################################
680
- def dc_background_for_result(start)
681
- if start == :start
682
- html = '<div class="dc-result-div" '
683
- html << (@form['result_set']['table_style'] ? 'style="overflow-x: scroll;" >' : '>')
684
- #
685
- html << "\n<div class=\"dc-result #{@form['result_set']['table_class']}\" "
686
- html << (@form['result_set']['table_style'] ? "style=\"#{@form['result_set']['table_style']}\" >" : '>')
687
- else
688
- html = '</div></div>'
689
- end
690
- html.html_safe
691
- end
692
-
693
- ############################################################################
694
- # Checks if value is defined and sets default. If values are sent it also checks
695
- # if value is found in values. If not it will report error and set value to default.
696
- # Subroutine of dc_fields_for_tab.
697
- ############################################################################
698
- def dc_check_and_default(value, default, values=nil) #:nodoc:
699
- return default if value.nil?
700
- # check if value is within allowed values
701
- if values
702
- if !values.index(value)
703
- # parameters should be in downcase. Check downcase version.
704
- if n = values.index(value.downcase)
705
- return values[n]
706
- else
707
- logger.error("DRG Forms: Value #{value} not within values [#{values.join(',')}]. Default #{default} used!")
708
- return default
709
- end
710
- end
711
- end
712
- value
713
- end
714
-
715
- ############################################################################
716
- # Creates top or bottom horizontal line on form.
717
- ############################################################################
718
- def top_bottom_line(yaml, columns=2)
719
- '<div class="dc-separator"></div>'
720
- end
721
-
722
- ############################################################################
723
- # Creates input fields for one tab. Subroutine of dc_fields_for_form.
724
- ############################################################################
725
- def dc_fields_for_tab(fields_on_tab) #:nodoc:
726
- @js ||= ''
727
- html = '<div class="dc-form">'
728
- labels_pos = dc_check_and_default(@form['form']['labels_pos'], 'right', ['top','left','right'])
729
- hidden_fields = ''
730
- odd_even = nil
731
- group_option, group_count = 0, 0
732
- reset_cycle()
733
- # options and fields must be separated before sorting
734
- # form_options = fields.select {|field| field.class != Integer }
735
- # columns = form_options.try(:[],'columns') || 1
736
- # Select form fields and sort them by key
737
- form_fields = fields_on_tab.select {|field| field.class == Integer }
738
- form_fields.to_a.sort.each do |element|
739
- options = element.last
740
- session[:form_processing] = "form:fields: #{element.first}=#{options}"
741
- # ignore if edit_only singe field is required
742
- next if params[:edit_only] and params[:edit_only] != options['name']
743
- # hidden_fields. Add them at the end
744
- if options['type'] == 'hidden_field'
745
- hidden_fields << DrgcmsFormFields::HiddenField.new(self, @record, options).render
746
- next
747
- end
748
- # label
749
- text = if options['text']
750
- t(options['text'], options['text'])
751
- elsif options['name']
752
- t_name(options['name'], options['name'].capitalize.gsub('_',' ') )
753
- end
754
- # help text can be defined in form or in translations starting with helpers. or as helpers.help.collection.field
755
- help = if options['help']
756
- options['help'].match('helpers.') ? t(options['help']) : options['help']
757
- end
758
- help ||= t('helpers.help.' + @form['table'] + '.' + options['name'],' ') if options['name']
759
- # create field object from class and call its render method
760
- klas_string = options['type'].camelize
761
- field_html = if DrgcmsFormFields.const_defined?(klas_string) # check if field type is defined
762
- klas = DrgcmsFormFields.const_get(klas_string)
763
- field = klas.new(self, @record, options).render
764
- @js << field.js
765
- field.html
766
- else # litle error string
767
- "Error: Code for field type #{options['type']} not defined!"
768
- end
769
- # Line separator
770
- html << top_bottom_line(options['top-line']) if options['top-line']
771
- # Begining of new row
772
- if group_count == 0
773
- html << '<div class="row-div">'
774
- odd_even = cycle('odd','even')
775
- group_count = options['group'] || 1
776
- group_option = options['group'] || 1
777
- end
778
- #
779
- html << if labels_pos == 'top'
780
- %Q[
781
- <div class="dc-form-label-top dc-color-#{odd_even} dc-align-left" title="#{help}">
782
- <label for="record_#{options['name']}">#{text} </label>
783
- <div id="td_record_#{options['name']}">#{field_html}</div>
784
- </div> ]
785
- else
786
- label_width = 14
787
- # less place for label when more then 1 field per row
788
- label_width = 10 if group_option > 1 and group_option != group_count
789
- data_width = (94 - 10*group_option)/group_option
790
- %Q[
791
- <div class="dc-form-label dc-color-#{odd_even} dc-align-#{labels_pos}" style="width:#{label_width}%;" title="#{help}">
792
- <label for="record_#{options['name']}">#{text} </label>
793
- </div>
794
- <div id="td_record_#{options['name']}" class="dc-form-field dc-color-#{odd_even}" style="width:#{data_width}%;">#{field_html}</div>
795
- ]
796
- end
797
- # check if must go to next row
798
- group_count -= 1
799
- html << '</div>' if group_count == 0
800
- html << top_bottom_line(options['bottom-line']) if options['bottom-line']
801
- end
802
- html << '</div>' << hidden_fields
803
- end
804
-
805
- ############################################################################
806
- # Creates edit form div.
807
- ############################################################################
808
- def dc_fields_for_form()
809
- html, tabs, tdata = '',[], ''
810
- # Only fields defined
811
- if (form_fields = @form['form']['fields'])
812
- html << "<div id='data_fields' " + (@form['form']['height'] ? "style=\"height: #{@form['form']['height']}px;\">" : '>')
813
- html << dc_fields_for_tab(form_fields) + '</div>'
814
- else
815
- # there are multiple tabs on form
816
- first = true # first tab
817
- @form['form']['tabs'].keys.sort.each do |tabname|
818
- next if tabname.match('actions')
819
- # Tricky. If field name is not on the tab skip to next tab
820
- if params[:edit_only]
821
- is_on_tab = false
822
- @form['form']['tabs'][tabname].each {|k,v| is_on_tab = true if params[:edit_only] == v['name'] }
823
- next unless is_on_tab
824
- end
825
- # first div is displayed all other are hidden
826
- tdata << "<div id='data_#{tabname.delete("\s\n")}'"
827
- tdata << ' class="div-hidden"' unless first
828
- tdata << " style=\"height: #{@form['form']['height']}px;\"" if @form['form']['height']
829
- tdata << ">#{dc_fields_for_tab(@form['form']['tabs'][tabname])}</div>"
830
- tabs << tabname
831
- first = false
832
- end
833
- # make it all work together
834
- html << '<ul class="dc-form-ul" >'
835
- first = true # first tab must be selected
836
- tabs.each do |tab|
837
- 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>"
838
- first = false
839
- end
840
- html << '</ul>'
841
- html << tdata
842
- end
843
- # add last_updated_at hidden field so controller can check if record was updated in during editing
844
- html << hidden_field(nil, :last_updated_at, value: @record.updated_at.to_i) if @record.respond_to?(:updated_at)
845
- # add form time stamp to prevent double form submit
846
- html << hidden_field(nil, :form_time_stamp, value: Time.now.to_i)
847
- html.html_safe
848
- end
849
-
850
- ############################################################################
851
- # Returns username for id. Subroutine of dc_document_statistics
852
- ############################################################################
853
- def _get_user_for(field_name) #:nodoc:
854
- if @record[field_name]
855
- u = DcUser.find(@record[field_name])
856
- return u ? u.name : @record[field_name]
857
- end
858
- # nil
859
- end
860
-
861
- ############################################################################
862
- # Creates current document statistics div (created_by, created_at, ....) at the bottom of edit form.
863
- # + lots of more. At the moment also adds icon for dumping current document as json text.
864
- ############################################################################
865
- def dc_document_statistics
866
- return '' if @record.new_record? or dc_dont?(@form['form']['info'])
867
- html = %Q[<div id="dc-document-info">#{fa_icon('info-circle lg')}</div> <div id="dc-document-info-popup" class="div-hidden"> ]
868
- #
869
- u = _get_user_for('created_by')
870
- html << %Q[<div><span>#{t('drgcms.created_by', 'Created by')}: </span><span>#{u}</span></div>] if u
871
- u = _get_user_for('updated_by')
872
- html << %Q[<div><span>#{t('drgcms.updated_by', 'Updated by')}: </span><span>#{u}</span></div>] if u
873
- html << %Q[<div><span>#{t('drgcms.created_at', 'Created at')}: </span><span>#{dc_format_value(@record.created_at)}</span></div>] if @record['created_at']
874
- html << %Q[<div><span>#{t('drgcms.updated_at', 'Updated at')}: </span><span>#{dc_format_value(@record.updated_at)}</span></div>] if @record['updated_at']
875
- # copy to clipboard icon
876
- parms = params.clone
877
- parms[:controller] = 'dc_common'
878
- parms[:action] = 'copy_clipboard'
879
- url = url_for(parms.permit!)
880
- html << fa_icon('copy 2x', class: 'dc-link-img dc-link-ajax dc-animate',
881
- 'data-url' => url, 'data-request' => 'get', title: t('drgcms.doc_copy_clipboard') )
882
- (html << '</div></div>').html_safe
883
- end
884
-
885
- end