drg_cms 0.6.0.3 → 0.6.0.6

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +259 -102
  3. data/app/assets/javascripts/drg_cms_cms.js +1 -1
  4. data/app/assets/stylesheets/drg_cms/drg_cms.css +314 -142
  5. data/app/assets/stylesheets/drg_cms/select-multiple.css +11 -2
  6. data/app/controllers/cmsedit_controller.rb +313 -236
  7. data/app/controllers/dc_application_controller.rb +29 -4
  8. data/app/controllers/dc_common_controller.rb +19 -16
  9. data/app/{controllers → controls}/browse_models_control.rb +0 -0
  10. data/app/{controllers → controls}/dc_page_control.rb +24 -8
  11. data/app/controls/dc_poll_result_control.rb +88 -0
  12. data/app/{controllers → controls}/design_element_settings_control.rb +0 -0
  13. data/app/forms/all_options.yml +11 -3
  14. data/app/forms/cms_menu.yml +22 -18
  15. data/app/forms/dc_design.yml +6 -3
  16. data/app/forms/dc_filter.yml +3 -6
  17. data/app/forms/dc_poll_result.yml +74 -0
  18. data/app/forms/dc_poll_result_export.yml +35 -0
  19. data/app/helpers/cmsedit_edit_helper.rb +471 -0
  20. data/app/helpers/cmsedit_helper.rb +151 -821
  21. data/app/helpers/cmsedit_index_helper.rb +567 -0
  22. data/app/helpers/dc_application_helper.rb +48 -31
  23. data/app/models/{dc_dummy.rb → __dc_dummy.rb} +0 -0
  24. data/app/models/dc_filter.rb +12 -5
  25. data/app/models/dc_memory.rb +8 -1
  26. data/app/models/dc_poll.rb +38 -19
  27. data/app/models/dc_poll_result.rb +44 -0
  28. data/app/models/dc_temp.rb +137 -0
  29. data/app/models/drgcms_form_fields/action.rb +61 -0
  30. data/app/models/drgcms_form_fields/comment.rb +8 -4
  31. data/app/models/drgcms_form_fields/date_picker.rb +7 -6
  32. data/app/models/drgcms_form_fields/date_select.rb +1 -1
  33. data/app/models/drgcms_form_fields/datetime_picker.rb +8 -7
  34. data/app/models/drgcms_form_fields/datetime_select.rb +1 -1
  35. data/app/models/drgcms_form_fields/drgcms_field.rb +39 -7
  36. data/app/models/drgcms_form_fields/embedded.rb +7 -2
  37. data/app/models/drgcms_form_fields/file_field.rb +52 -0
  38. data/app/models/drgcms_form_fields/html_field.rb +1 -1
  39. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +7 -4
  40. data/app/models/drgcms_form_fields/number_field.rb +15 -6
  41. data/app/models/drgcms_form_fields/radio.rb +91 -0
  42. data/app/models/drgcms_form_fields/readonly.rb +1 -1
  43. data/app/models/drgcms_form_fields/select.rb +14 -2
  44. data/app/models/drgcms_form_fields/text_area.rb +1 -1
  45. data/app/models/drgcms_form_fields/text_autocomplete.rb +1 -1
  46. data/app/models/drgcms_form_fields/text_field.rb +1 -1
  47. data/app/models/drgcms_form_fields/text_with_select.rb +6 -3
  48. data/app/models/drgcms_form_fields/tree_select.rb +11 -3
  49. data/app/renderers/dc_poll_renderer.rb +29 -11
  50. data/app/views/cmsedit/{remove_edit_stuff.js.erb → __remove_edit_stuff.js.erb} +0 -0
  51. data/app/views/cmsedit/{show.html.erb → __show.html.erb} +0 -0
  52. data/app/views/cmsedit/_edit_stuff.html.erb +2 -4
  53. data/app/views/cmsedit/_form.html.erb +4 -3
  54. data/app/views/cmsedit/_result.html.erb +2 -3
  55. data/app/views/cmsedit/edit.html.erb +2 -1
  56. data/app/views/cmsedit/index.html.erb +6 -1
  57. data/app/views/cmsedit/new.html.erb +1 -1
  58. data/config/locales/drgcms_en.yml +7 -0
  59. data/config/locales/drgcms_sl.yml +8 -1
  60. data/config/locales/models_en.yml +13 -4
  61. data/config/locales/models_sl.yml +13 -2
  62. data/drg_cms.gemspec +1 -1
  63. data/lib/drg_cms.rb +1 -0
  64. data/lib/drg_cms/version.rb +1 -1
  65. data/lib/generators/new_drg_form/new_drg_form_generator.rb +7 -2
  66. metadata +20 -13
  67. data/app/assets/stylesheets/drg_cms/__jquery-ui.css +0 -339
  68. data/test/fixtures/drg_cms_test_data.rb +0 -87
@@ -0,0 +1,567 @@
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 CmseditIndexHelper
31
+
32
+ ############################################################################
33
+ # Get standard actions when actions directive contains single line.
34
+ # Subroutine of dc_actions_for_index
35
+ #
36
+ # Allows for actions: new, filter, standard syntax
37
+ ############################################################################
38
+ def define_standard_actions(actions_params, standard)
39
+ actions = {}
40
+ actions_params.split(',').each do |an_action|
41
+ an_action.strip!
42
+ if an_action == 'standard'
43
+ actions.merge!(standard)
44
+ else
45
+ standard.each do |index, action|
46
+ (actions[index] = action; break) if action == an_action
47
+ end
48
+ end
49
+ end
50
+ actions
51
+ end
52
+
53
+ ############################################################################
54
+ # Creates action div for cmsedit index action.
55
+ ############################################################################
56
+ def dc_actions_for_index()
57
+ @js = @form['script'] || @form['js'] || ''
58
+ @css = @form['css'] || ''
59
+ return '' if @form['index'].nil? or @form['readonly']
60
+ actions = @form['index']['actions']
61
+ return '' if actions.blank?
62
+
63
+ std_actions = {2 => 'new', 3 => 'sort', 4 => 'filter' }
64
+ if actions.class == String
65
+ actions = define_standard_actions(actions, std_actions)
66
+ elsif actions['standard']
67
+ actions.merge!(std_actions)
68
+ actions['standard'] = nil
69
+ end
70
+
71
+ # start div with hidden spinner image
72
+ html = <<EOT
73
+ <form id="dc-action-menu">
74
+ <span class="dc-spinner">#{fa_icon('spinner lg spin')}</span>
75
+ <ul class="dc-action-menu">
76
+ EOT
77
+ # Remove actions settings and sort
78
+ only_actions = []
79
+ actions.each { |key, value| only_actions << [key, value] if key.class == Integer }
80
+ only_actions.sort_by!(&:first)
81
+ only_actions.each do |key, options|
82
+ session[:form_processing] = "index:actions: #{key}=#{options}"
83
+ next if options.nil? # must be
84
+ url = @parms.clone
85
+ yaml = options.class == String ? {'type' => options} : options # 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! Form #{params['form_name']}"
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
+ url['control'] = yaml['control'] if yaml['control']
100
+ end
101
+ # html link options
102
+ yhtml = yaml['html'] || {}
103
+ yhtml['title'] = yaml['title'] if yaml['title']
104
+ code = case
105
+ # sort
106
+ when action == 'sort' then
107
+ choices = [['id','id']]
108
+ if @form['index']['sort']
109
+ @form['index']['sort'].split(',').each do |s|
110
+ s.strip!
111
+ choices << [ t("helpers.label.#{@form['table']}.#{s}"), s ]
112
+ end
113
+ end
114
+ fa_icon('sort-alpha-asc') + ' ' + t('drgcms.sort') + ' ' +
115
+ select('sort', 'sort', choices, { include_blank: true },
116
+ { class: 'drgcms_sort', 'data-table' => @form['table']} )
117
+ # filter
118
+ when action == 'filter' then
119
+ caption = t('drgcms.filter')
120
+ caption << '&nbsp;' + fa_icon('caret-down lg') + DcFilter.menu_filter(self)
121
+ # add filter OFF link
122
+ sess = session[@form['table']]
123
+ if sess and sess[:filter]
124
+ caption << '&nbsp;&nbsp;' + dc_link_to(nil,'remove lg', {controller: 'cmsedit',
125
+ filter: 'off', table: @form['table']}, { title: DcFilter.title4_filter_off(sess[:filter]) })
126
+ end
127
+ caption
128
+ # new
129
+ when action == 'new' then
130
+ caption = yaml['caption'] || 'drgcms.new'
131
+ dc_link_to(caption,'plus', url, yhtml )
132
+ # menu
133
+ when action == 'menu' then
134
+ caption = t(options['caption'], options['caption']) + '&nbsp;' + fa_icon('caret-down lg')
135
+ caption + eval(options['eval'])
136
+ =begin
137
+ # reorder
138
+ when action == 'reorder' then
139
+ caption = t('drgcms.reorder')
140
+ parms = @parms.clone
141
+ parms['operation'] = v
142
+ parms['id'] = params[:ids]
143
+ parms['table'] = @form['table']
144
+ dc_link_to( caption, 'reorder', parms, method: :delete )
145
+ =end
146
+ when action == 'script'
147
+ html << dc_script_action(options)
148
+ next
149
+ when action == 'field'
150
+ html << dc_field_action(yaml)
151
+ next
152
+ when %w(ajax link window submit).include?(action)
153
+ html << dc_link_ajax_window_submit_action(options, nil)
154
+ next
155
+ else
156
+ caption = yaml['caption'] || yaml['text']
157
+ icon = yaml['icon'] ? yaml['icon'] : action
158
+ dc_link_to(caption, icon, url, yhtml)
159
+ end
160
+ html << "<li class=\"dc-link dc-animate\">#{code}</li>"
161
+ html << DcFilter.get_filter_field(self) if action == 'filter'
162
+ end
163
+ html << '</ul>'
164
+ html << '</form>'
165
+ html.html_safe
166
+ end
167
+
168
+ ############################################################################
169
+ # Creates filter div for cmsedit index/filter action.
170
+ ############################################################################
171
+ def dc_div_filter()
172
+ choices = []
173
+ filter = (@form['index'] and @form['index']['filter']) ? @form['index']['filter'] + ',' : ''
174
+ filter << 'id as text_field' # filter id is added by default
175
+ filter.split(',').each do |f|
176
+ f.strip!
177
+ name = f.match(' as ') ? f.split(' ').first : f
178
+ # like another field on the form
179
+ if f.match(' like ')
180
+ a = f.split(' ')
181
+ name = a.first
182
+ f = a.last
183
+ end
184
+ choices << [ t("helpers.label.#{@form['table']}.#{name}", name), f ]
185
+ end
186
+ choices4_operators = t('drgcms.choices4_filter_operators').chomp.split(',').inject([]) {|r,v| r << (v.match(':') ? v.split(':') : v )}
187
+ # currently selected options
188
+ if session[@form['table']] and session[@form['table']][:filter]
189
+ field_name, operators_value, dummy = session[@form['table']][:filter].split("\t")
190
+ else
191
+ field_name, operators_value = nil, nil
192
+ end
193
+ #{ form_tag :table => @form['table'], filter: :on, filter_input: 1, action: :index, method: :post }
194
+ url = url_for(table: @form['table'],form_name: params['form_name'], filter: :on, filter_input: 1, action: :index, controller: :cmsedit)
195
+ html =<<EOT
196
+ <div id="drgcms_filter" class="div-hidden">
197
+ <h1>#{t('drgcms.filter_set')}</h1>
198
+
199
+ #{ select(nil, 'filter_field1', options_for_select(choices, field_name), { include_blank: true }) }
200
+ #{ select(nil, 'filter_oper', options_for_select(choices4_operators, operators_value)) }
201
+ <div class="dc-menu">
202
+ <div class="dc-link dc-animate drgcms_popup_submit" data-url="#{url}">#{fa_icon('check-square-o')} #{t('drgcms.filter_on')}</div>
203
+ <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>
204
+ </div>
205
+ </div>
206
+ EOT
207
+ html.html_safe
208
+ end
209
+
210
+ ############################################################################
211
+ # Creates popup div for setting filter on result set header.
212
+ ############################################################################
213
+ def dc_filter_popup()
214
+ html = %Q[<div class="filter-popup" style="display: none;">
215
+ <div>#{t('drgcms.filter_set')}</div>
216
+ <ul>]
217
+ url = url_for(table: @form['table'],form_name: params['form_name'], filter: :on, filter_input: 1, action: :index, controller: :cmsedit)
218
+ t('drgcms.choices4_filter_operators').chomp.split(',').each do |operator_choice|
219
+ caption,choice = operator_choice.split(':')
220
+ html << %Q[<li data-operator="#{choice}" data-url="#{url}">#{caption}</li>]
221
+ end
222
+ html << "</ul></div>"
223
+ html.html_safe
224
+ end
225
+
226
+ ############################################################################
227
+ # Creates title div for cmsedit index result set records. Title div also includes paging
228
+ # options.
229
+ ############################################################################
230
+ def dc_table_title_for_result(result=nil)
231
+ title = if @form['title'] # form has title section
232
+ t(@form['title'], @form['title'])
233
+ else # get name from translations
234
+ t("helpers.label.#{@form['table']}.tabletitle", @form['table'])
235
+ end
236
+ dc_table_title(title, result)
237
+ end
238
+
239
+ ############################################################################
240
+ # Creates code for link or ajax action type. Subroutine of dc_actions_for_result.
241
+ ############################################################################
242
+ def __dc_link_or_ajax_action(yaml, parms) #:nodoc:
243
+ rest = {}
244
+ rest['method'] = yaml['method'] || yaml['request'] || 'get'
245
+ rest['caption'] = yaml['caption'] || yaml['text']
246
+ rest['class'] = 'dc-animate'
247
+ rest['title'] = yaml['title']
248
+
249
+ if yaml['type'] == 'link'
250
+ dc_link_to(yaml['caption'], yaml['icon'], parms, rest )
251
+ else
252
+ rest['data-url'] = url_for(parms)
253
+ rest['class'] << " fa fa-#{yaml['icon']}"
254
+ fa_icon(yaml['icon'], rest )
255
+ end
256
+ end
257
+
258
+ ############################################################################
259
+ # Determines actions and width of actions column
260
+ ############################################################################
261
+ def dc_actions_column()
262
+ actions = @form['result_set']['actions']
263
+ return [{},0] if actions.nil? or dc_dont?(actions)
264
+ # standard actions
265
+ actions = {'standard' => true} if actions.class == String && actions == 'standard'
266
+ std_actions = {' 2' => 'edit', ' 3' => 'delete'}
267
+ if actions['standard']
268
+ actions.merge!(std_actions)
269
+ actions.delete('standard')
270
+ end
271
+ #
272
+ width = @form['result_set']['actions_width'] || 18*actions.size
273
+ [ actions, width ]
274
+ end
275
+
276
+ ############################################################################
277
+ # Calculates (blank) space required for actions when @record_footer is rendered
278
+ ############################################################################
279
+ def dc_actions_column_for_footer()
280
+ return '' unless @form['result_set']['actions']
281
+ ignore, width = dc_actions_column
282
+ %Q[<div class="actions" style="width: #{width}px;"></div>].html_safe
283
+ end
284
+
285
+
286
+ ############################################################################
287
+ # Creates actions that could be performed on single row of result set.
288
+ ############################################################################
289
+ def dc_actions_for_result(document)
290
+ actions = @form['result_set']['actions']
291
+ return '' if actions.nil? or @form['readonly']
292
+ #
293
+ actions, width = dc_actions_column()
294
+ html = %Q[<ul class="actions" style="width: #{width}px;">]
295
+ actions.each do |k,v|
296
+ session[:form_processing] = "result_set:actions: #{k}=#{v}"
297
+ next if k == 'standard' # ignore standard definition
298
+ parms = @parms.clone
299
+ # if single definition simulate type parameter
300
+ yaml = v.class == String ? {'type' => v} : v
301
+ # code already includes li tag
302
+ if %w(ajax link window submit).include?(yaml['type']) then
303
+ @record = document # otherwise document fields can't be used as parameters
304
+ html << dc_link_ajax_window_submit_action(yaml,document)
305
+ else
306
+ html << '<li class="dc-link">'
307
+ html << case
308
+ when yaml['type'] == 'edit' then
309
+ parms['action'] = 'edit'
310
+ parms['id'] = document.id
311
+ dc_link_to( nil, 'pencil lg', parms )
312
+ when yaml['type'] == 'duplicate' then
313
+ parms['id'] = document.id
314
+ # duplicate string will be added to these fields.
315
+ parms['dup_fields'] = yaml['dup_fields']
316
+ parms['action'] = 'create'
317
+ dc_link_to( nil, 'copy lg', parms, data: { confirm: t('drgcms.confirm_dup') }, method: :post )
318
+ when yaml['type'] == 'delete' then
319
+ parms['action'] = 'destroy'
320
+ parms['id'] = document.id
321
+ parms['return_to'] = request.url
322
+ dc_link_to( nil, 'remove lg', parms, data: { confirm: t('drgcms.confirm_delete') }, method: :delete )
323
+ # undocumented so far
324
+ when yaml['type'] == 'edit_embedded'
325
+ parms['controller'] = 'cmsedit'
326
+ parms['table'] += ";#{yaml['table']}"
327
+ parms['ids'] ||= ''
328
+ parms['ids'] += "#{document.id};"
329
+ dc_link_to( nil, 'table lg', parms, method: :get )
330
+ =begin
331
+ when yaml['type'] == 'link' || yaml['type'] == 'ajax' then
332
+ if yaml['url']
333
+ parms['controller'] = yaml['url']
334
+ parms['idr'] = document.id
335
+ else
336
+ parms['id'] = document.id
337
+ end
338
+ parms['controller'] = yaml['controller'] if yaml['controller']
339
+ parms['action'] = yaml['action'] if yaml['action']
340
+ parms['table'] = yaml['table'] if yaml['table']
341
+ parms['form_name'] = yaml['form_name'] if yaml['form_name']
342
+ parms['target'] = yaml['target'] if yaml['target']
343
+ dc_link_or_ajax_action(yaml, parms)
344
+ =end
345
+ else # error.
346
+ yaml['type'].to_s
347
+ end
348
+ html << '</li>'
349
+ end
350
+ end
351
+ html << '</ul>'
352
+ html.html_safe
353
+ end
354
+
355
+ ############################################################################
356
+ # Creates header div for result set.
357
+ ############################################################################
358
+ def dc_header_for_result()
359
+ html = '<div class="dc-result-header">'
360
+ if @form['result_set']['actions'] and !@form['readonly']
361
+ ignore, width = dc_actions_column()
362
+ html << %Q[<div class="actions" style="width: #{width}px;"></div>]
363
+ end
364
+ # preparation for sort icon
365
+ sort_field, sort_direction = nil, nil
366
+ if session[@form['table']]
367
+ sort_field, sort_direction = session[@form['table']][:sort].to_s.split(' ')
368
+ end
369
+ #
370
+ if (columns = @form['result_set']['columns'])
371
+ columns.sort.each do |k,v|
372
+ session[:form_processing] = "result_set:columns: #{k}=#{v}"
373
+ th = %Q[<div class="th" style="width: #{v['width'] || '15%'};text-align: #{v['align'] || 'left'};" data-name="#{v['name']}"]
374
+ # when no caption or name is defined it might be just spacer
375
+ if (caption = v['caption']).nil?
376
+ caption = v['name'] ? t("helpers.label.#{@form['table']}.#{v['name']}") : ''
377
+ end
378
+ # no sorting when embedded documents or custom filter is active
379
+ sort_ok = @form['result_set'].nil? || (@form['result_set'] && @form['result_set']['filter'].nil?)
380
+ sort_ok = sort_ok || (@form['index'] && @form['index']['sort'])
381
+ if @tables.size == 1 and sort_ok
382
+ icon = 'sort lg'
383
+ if v['name'] == sort_field
384
+ icon = sort_direction == '1' ? 'sort-alpha-asc lg' : 'sort-alpha-desc lg'
385
+ end
386
+ th << ">#{dc_link_to(caption, icon, sort: v['name'], table: params[:table], form_name: params[:form_name], action: :index, icon_pos: :last )}</div>"
387
+ else
388
+ th << ">#{caption}</div>"
389
+ end
390
+ html << "<div class=\"spacer\"></div>" + th
391
+ end
392
+ end
393
+ (html << '</div>').html_safe
394
+ end
395
+
396
+ ############################################################################
397
+ # Creates link for single or double click on result column
398
+ ############################################################################
399
+ def dc_clicks_for_result(document)
400
+ html = ''
401
+ if @form['result_set']['dblclick']
402
+ yaml = @form['result_set']['dblclick']
403
+ opts = {}
404
+ opts[:controller] = yaml['controller'] || 'cmsedit'
405
+ opts[:action] = yaml['action']
406
+ opts[:table] = yaml['table']
407
+ opts[:form_name] = yaml['form_name']
408
+ opts[:method] = yaml['method'] || 'get'
409
+ opts[:id] = document['id']
410
+ html << ' data-dblclick=' + url_for(opts)
411
+ else
412
+ html << (' data-dblclick=' +
413
+ url_for(action: 'show', controller: 'cmsedit', id: document.id,
414
+ readonly: (params[:readonly] ? 2 : 1), table: params[:table],
415
+ form_name: params[:form_name], ids: params[:ids]) ) if @form['form']
416
+ end
417
+ html
418
+ end
419
+
420
+ ############################################################################
421
+ # Formats value according to format supplied or data type. There is lots of things missing here.
422
+ ############################################################################
423
+ def dc_format_value(value, format=nil)
424
+ return '' if value.nil?
425
+ klass = value.class.to_s
426
+ case when klass.match('Time') then
427
+ format ||= t('time.formats.default')
428
+ value.strftime(format)
429
+ when klass.match('Date') then
430
+ format ||= t('date.formats.default')
431
+ value.strftime(format)
432
+ when format.to_s[0] == 'N' then
433
+ dec = format[1].blank? ? nil : format[1].to_i
434
+ sep = format[2].blank? ? nil : format[2]
435
+ del = format[3].blank? ? nil : format[3]
436
+ cur = format[4].blank? ? nil : format[4]
437
+ dc_format_number(value, dec, sep, del, cur)
438
+ else
439
+ value.to_s
440
+ end
441
+ end
442
+
443
+ ############################################################################
444
+ # Defines style or class for row (tr) or column (td)
445
+ ############################################################################
446
+ def dc_style_or_class(selector, yaml, value, record)
447
+ return '' if yaml.nil?
448
+ # alias record and value so both names can be used in eval
449
+ field, document = value, record
450
+ html = selector ? "#{selector}=\"" : ''
451
+ html << if yaml.class == String
452
+ yaml
453
+ # direct evaluate expression
454
+ elsif yaml['eval']
455
+ eval(yaml['eval']) rescue 'background-color:red;'
456
+ elsif yaml['method']
457
+ dc_process_eval(yaml['method'],record)
458
+ end
459
+ html << '"' if selector
460
+ html
461
+ end
462
+
463
+ ############################################################################
464
+ # Creates tr code for each row of result set.
465
+ ############################################################################
466
+ def dc_row_for_result(document)
467
+ clas = "dc-#{cycle('odd','even')} " + dc_style_or_class(nil, @form['result_set']['tr_class'], nil, document)
468
+ style = dc_style_or_class('style', @form['result_set']['tr_style'], nil, document)
469
+ "<div id=\"#{document.id}\" class=\"dc-result-data #{clas}\" #{dc_clicks_for_result(document)} #{style}>".html_safe
470
+ end
471
+
472
+ ############################################################################
473
+ # Process eval. Breaks eval option and calls with send method.
474
+ # Parameters:
475
+ # evaluate : String : Expression to be evaluated
476
+ # parameters : Array : array of parameters which will be send to method
477
+ ############################################################################
478
+ def dc_process_eval(evaluate, parameters)
479
+ # evaluate by calling send method
480
+ clas, method = evaluate.split('.')
481
+ if method.nil?
482
+ send(clas, *parameters)
483
+ else
484
+ klass = clas.camelize.constantize
485
+ klass.send(method, *parameters)
486
+ end
487
+ end
488
+
489
+ ############################################################################
490
+ # Process eval option for field value.
491
+ # Used for processing single field column on result_set or form head.
492
+ ############################################################################
493
+ def dc_process_column_eval(yaml, document)
494
+ # dc_name4_id
495
+ if yaml['eval'].match('dc_name4_id')
496
+ a = yaml['eval'].split(/\ |\,/)
497
+ if a.size == 3
498
+ dc_name4_id(a[1], a[2], nil, document[ yaml['name'] ])
499
+ else
500
+ dc_name4_id(a[1], a[2], a[3], document[ yaml['name'] ])
501
+ end
502
+ # dc_name4_value
503
+ elsif yaml['eval'].match('dc_name4_value')
504
+ dc_name4_value( @form['table'], yaml['name'], document[ yaml['name'] ] )
505
+ elsif yaml['eval'].match('eval ')
506
+ # TO DO evaluate with specified parameters
507
+ else
508
+ parameters = if yaml['params']
509
+ # pass document as parameter
510
+ if yaml['params'] == 'document' or yaml['params'] == 'record'
511
+ document
512
+ else
513
+ yaml['params'].chomp.split(',').inject([]) do |result,e|
514
+ result << document[e.strip]
515
+ end
516
+ end
517
+ else
518
+ document[ yaml['name'] ]
519
+ end
520
+ # evaluate by calling send method
521
+ dc_process_eval(yaml['eval'], parameters)
522
+ end
523
+ end
524
+
525
+ ############################################################################
526
+ # Creates column for each field of result set document.
527
+ ############################################################################
528
+ def dc_columns_for_result(document)
529
+ return '' unless @form['result_set']['columns']
530
+ html = ''
531
+ @form['result_set']['columns'].sort.each do |k,v|
532
+ session[:form_processing] = "result_set:columns: #{k}=#{v}"
533
+ # convert shortcut to hash
534
+ v = {'name' => v} if v.class == String
535
+ begin
536
+ # eval
537
+ value = if v['eval']
538
+ dc_process_column_eval(v, document)
539
+ # as field
540
+ elsif document.respond_to?(v['name'])
541
+ dc_format_value(document.send( v['name'] ), v['format'])
542
+ # as hash (dc_memory)
543
+ elsif document.class == Hash
544
+ dc_format_value(document[ v['name'] ], v['format'])
545
+ # error
546
+ else
547
+ "!!! #{v['name']}"
548
+ end
549
+ rescue Exception => e
550
+ dc_log_exception(e)
551
+ value = '!!!Error'
552
+ end
553
+ html << '<div class="spacer"></div>'
554
+ # set class
555
+ clas = dc_style_or_class(nil, v['td_class'], value, document)
556
+ # set width and align an additional style
557
+ style = dc_style_or_class(nil, v['td_style'] || v['style'], value, document)
558
+ width_align = %Q[width: #{v['width'] || '15%'};text-align: #{v['align'] || 'left'};]
559
+ style = "#{width_align}#{style}"
560
+
561
+ html << "<div class=\"td #{clas}\" style=\"#{style}\">#{value}</div>"
562
+ end
563
+ html.html_safe
564
+ end
565
+
566
+
567
+ end