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
@@ -65,12 +65,15 @@
65
65
  }
66
66
 
67
67
  .ms-container .ms-selectable li.ms-elem-selectable{
68
- border-bottom: 1px #eee solid;
69
68
  padding: 2px 10px;
70
- color: #555;
69
+ color: #444;
71
70
  font-size: 14px;
72
71
  }
73
72
 
73
+ .ms-container .ms-selectable li:nth-child(odd) {
74
+ background-color: #f4f4f4;
75
+ }
76
+
74
77
  .ms-container .ms-selectable li.ms-hover{
75
78
  cursor: pointer;
76
79
  color: #fff;
@@ -88,6 +91,12 @@
88
91
  display: none;
89
92
  }
90
93
 
94
+
95
+ .ms-container .ms-selected {
96
+ font-weight: bold;
97
+ }
98
+
91
99
  .pull-right.ms-elem-selected{
92
100
  float: right;
101
+ font-size: larger;
93
102
  }
@@ -76,206 +76,12 @@
76
76
  # If filter method returns false user will be presented with flash error.
77
77
  ########################################################################
78
78
  class CmseditController < DcApplicationController
79
- before_action :check_authorization, :except => [:login, :logout, :test]
79
+ before_action :check_authorization, :except => [:login, :logout, :test, :run]
80
80
  before_action :dc_reload_patches if Rails.env.development?
81
+ protect_from_forgery with: :null_session, only: Proc.new { |c| c.request.format.json? }
81
82
 
82
83
  layout 'cms'
83
84
 
84
- ########################################################################
85
- # Will check and set sorting options for current result set. Subroutine of index method.
86
- ########################################################################
87
- def check_sort_options() #:nodoc:
88
- table_name = @tables.first[1]
89
- old_sort = session[table_name][:sort].to_s
90
- sort, direction = old_sort.split(' ')
91
- # sort is requested
92
- if params['sort']
93
- # reverse sort if same selected
94
- if params['sort'] == sort
95
- direction = (direction == '1') ? '-1' : '1'
96
- end
97
- direction ||= 1
98
- sort = params[:sort]
99
- session[table_name][:sort] = "#{params['sort']} #{direction}"
100
- session[table_name][:page] = 1
101
- end
102
- @records.sort( sort => direction.to_i ) if session[table_name][:sort]
103
- params['sort'] = nil # otherwise there is problem with other links
104
- end
105
-
106
- ########################################################################
107
- # Set aditional filter options when filter is defined by filter method in control object.
108
- ########################################################################
109
- def user_filter_options(model) #:nodoc:
110
- table_name = @tables.first[1]
111
- if session[table_name]
112
- DcFilter.get_filter(session[table_name][:filter]) || model
113
- else
114
- model
115
- end
116
- end
117
-
118
- ########################################################################
119
- # Will set session[table_name][:filter] and save last filter settings to session.
120
- # subroutine of check_filter_options.
121
- ########################################################################
122
- def set_session_filter(table_name)
123
- if params[:filter] == 'off' # clear all values
124
- session[table_name][:filter] = nil
125
- return
126
- end
127
-
128
- filter_value = if params[:filter_value].nil?
129
- # NIL indicates that no filtering is needed
130
- '#NIL'
131
- else
132
- if params[:filter_value].class == String and params[:filter_value][0] == '@'
133
- # Internal value. Remove leading @ and evaluate expression
134
- expression = DcInternals.get(params[:filter_value])
135
- eval(expression) rescue nil
136
- else
137
- # No filter when empty
138
- params[:filter_value] == '' ? '#NIL' : params[:filter_value]
139
- end
140
- end
141
- # if filter field parameter is omitted then just set filter value
142
- session[table_name][:filter] =
143
- if params[:filter_field].nil?
144
- saved = YAML.load(session[table_name][:filter])
145
- saved['value'] = filter_value
146
- saved.to_yaml
147
- else
148
- # As field defined. Split name and alternative input field
149
- field = if params[:filter_field].match(' as ')
150
- params[:filter_input] = params[:filter_field].split(' as ').last.strip
151
- params[:filter_field].split(' as ').first.strip
152
- else
153
- params[:filter_field]
154
- end
155
- #
156
- {'field' => field,
157
- 'operation' => params[:filter_oper],
158
- 'value' => filter_value,
159
- 'input' => params[:filter_input],
160
- 'table' => table_name }.to_yaml
161
- end
162
- # must be. Otherwise kaminari includes parameter on paging
163
- params[:filter] = nil
164
- params[:filter_id] = nil
165
- params[:filter_oper] = nil
166
- params[:filter_input] = nil
167
- params[:filter_field] = nil
168
- end
169
-
170
- ########################################################################
171
- # Will check and set current filter options for result set. Subroutine of index method.
172
- ########################################################################
173
- def check_filter_options() #:nodoc:
174
- table_name = @tables.first[1]
175
- model = @tables.first[0]
176
- session[table_name] ||= {}
177
- # process page
178
- session[table_name][:page] = params[:page] if params[:page]
179
- # new filter is applied
180
- if params[:filter]
181
- set_session_filter(table_name)
182
- session[table_name][:page] = 1
183
- end
184
- # if data model has field dc_site_id ensure that only documents which belong to the site are selected.
185
- site_id = dc_get_site._id if dc_get_site
186
- # dont't filter site if no dc_site_id field or user is ADMIN
187
- site_id = nil if !model.method_defined?('dc_site_id') or dc_user_can(DcPermission::CAN_ADMIN)
188
- site_id = nil if session[table_name][:filter].to_s.match('dc_site_id')
189
- #
190
- if @records = DcFilter.get_filter(session[table_name][:filter])
191
- @records = @records.and(dc_site_id: site_id) if site_id
192
- else
193
- @records = if site_id
194
- model.where(dc_site_id: site_id)
195
- else
196
- model
197
- end
198
- end
199
- =begin
200
- # TODO Use only fields requested. Higly experimental but necessary in some scenarios
201
- if (columns = @form['result_set']['columns'])
202
- cols = []
203
- columns.each { |k,v| cols << v['name'] }
204
- p '*',cols,'*'
205
- @records = @records.only(cols)
206
- end
207
- =end
208
- # pagination if required
209
- per_page = (@form['result_set']['per_page'] || 30).to_i
210
- @records = @records.page(session[table_name][:page]).per(per_page) if per_page > 0
211
- end
212
-
213
- ########################################################################
214
- # Process index action for normal collections.
215
- ########################################################################
216
- def process_collections #:nodoc
217
- # If result_set is not defined on form, then it will fail. :return_to should know where to go
218
- if @form['result_set'].nil?
219
- process_return_to(params[:return_to] || 'reload')
220
- return true
221
- end
222
- # for now enable only filtering of top level documents
223
- if @tables.size == 1
224
- check_filter_options()
225
- check_sort_options()
226
- end
227
- # result set is defined by filter method in control object
228
- if @form['result_set']['filter']
229
- if respond_to?(@form['result_set']['filter'])
230
- @records = send @form['result_set']['filter']
231
- # something iz wrong. flash[] should have explanation.
232
- if @records.class == FalseClass
233
- @records = []
234
- render(action: :index)
235
- return true
236
- end
237
- # pagination but only if not already set
238
- unless (@form['table'] == 'dc_memory' or @records.options[:limit])
239
- per_page = (@form['result_set']['per_page'] || 30).to_i
240
- @records = @records.page(params[:page]).per(per_page) if per_page > 0
241
- end
242
- else
243
- Rails.logger.error "Error: result_set:filter: #{@form['result_set']['filter']} not found in controls!"
244
- end
245
- else
246
- if @tables.size > 1
247
- rec = @tables.first[0].find(@ids.first) # top most document.id
248
- 1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
249
- # TO DO. When field name is different then pluralized class name. Not working yet.
250
- embedded_field_name = @tables.last[0] ? @tables.last[1].pluralize : @tables.last[1]
251
- @records = rec.send(embedded_field_name) # current embedded set
252
- # sort by order if order field is present in model
253
- if @tables.last[1].classify.constantize.respond_to?(:order)
254
- @records = @records.order_by('order asc')
255
- end
256
- end
257
- end
258
- false
259
- end
260
-
261
- ########################################################################
262
- # Process index action for in memory data.
263
- ########################################################################
264
- def process_in_memory #:nodoc
265
- @records = []
266
- # result set is defined by filter method in control object
267
- if (method = @form['result_set']['filter'])
268
- send(method) if respond_to?(method)
269
- end
270
- # result set is defined by class method
271
- if (klass_method = @form['result_set']['filter_method'])
272
- _klass, method = klass_method.split('.')
273
- klass = _klass.classify.constantize
274
- @records = klass.send(method) if klass.respond_to?(method)
275
- end
276
- false
277
- end
278
-
279
85
  ########################################################################
280
86
  # Index action
281
87
  ########################################################################
@@ -391,7 +197,8 @@ def new
391
197
  end
392
198
  end
393
199
  # This is how we set default values for new record
394
- dc_new_record() if respond_to?('dc_new_record')
200
+ #dc_new_record() if respond_to?('dc_new_record')
201
+ if (m = callback_method('new_record') ) then call_callback_method(m) end
395
202
  @parms['action'] = 'create'
396
203
  end
397
204
 
@@ -416,6 +223,8 @@ def duplicate_embedded(source) #:nodoc:
416
223
  dest[attribute_name] << ' dup' if add_duplicate
417
224
  end
418
225
  end
226
+ dest['created_at'] = Time.now if dest['created_at']
227
+ dest['updated_at'] = Time.now if dest['updated_at']
419
228
  dest
420
229
  end
421
230
 
@@ -440,6 +249,8 @@ def duplicate_document(source)
440
249
  dest[embedded_name] << duplicate_embedded(embedded)
441
250
  end
442
251
  end
252
+ dest['created_at'] = Time.now if dest['created_at']
253
+ dest['updated_at'] = Time.now if dest['updated_at']
443
254
  dest
444
255
  end
445
256
 
@@ -496,7 +307,7 @@ def edit
496
307
  ret = call_callback_method(m)
497
308
  # Don't do anything if return is false
498
309
  return index if ret.class == FalseClass
499
- end
310
+ end
500
311
  @parms['action'] = 'update'
501
312
  render action: :edit
502
313
  end
@@ -525,6 +336,10 @@ def update
525
336
  # Process return_to link
526
337
  return process_return_to(params[:return_to]) if params[:return_to]
527
338
  else
339
+ # do not forget before_edit callback
340
+ if m = callback_method('before_edit')
341
+ call_callback_method(m)
342
+ end
528
343
  return render action: :edit
529
344
  end
530
345
  else
@@ -613,19 +428,33 @@ def destroy
613
428
  render action: :edit
614
429
  end
615
430
 
616
- protected
617
-
618
- =begin
619
431
  ########################################################################
620
- # Processes on_save_ok form directive. Data is saved to session for
621
- # safety reasons.
432
+ # Run action
622
433
  ########################################################################
623
- def process_on_save_ok
624
- session[:on_save_ok_id] = @record_id
625
- session[:on_save_ok_commit] = params[:commit]
626
- eval(params[:on_save_ok])
434
+ def run
435
+ control_name, method_name = params[:control].split('.')
436
+ if method_name.nil?
437
+ method_name = control_name
438
+ control_name = params[:table]
439
+ end
440
+ extend_with_control_module(control_name)
441
+ if respond_to?(method_name)
442
+ respond_to do |format|
443
+ format.json { send method_name }
444
+ format.html { send method_name }
445
+ end
446
+ else
447
+ # Error message
448
+ text = "Method #{method_name} not defined in #{control_name}_control"
449
+ respond_to do |format|
450
+ format.json { render json: {msg_error: text} }
451
+ format.html { render plain: text }
452
+ end
453
+ end
454
+
627
455
  end
628
- =end
456
+
457
+ protected
629
458
 
630
459
  ########################################################################
631
460
  # Merges two forms when current form extends other form. Subroutine of read_drg_cms_form.
@@ -652,7 +481,9 @@ end
652
481
  # [extend_option] : Value of @form['extend'] option
653
482
  ########################################################################
654
483
  def extend_drg_cms_form(extend_option)
655
- form = YAML.load_file( dc_find_form_file(extend_option) )
484
+ form_file_name = dc_find_form_file(extend_option)
485
+ @form_js << read_js_drg_cms_form(form_file_name)
486
+ form = YAML.load_file( form_file_name )
656
487
  @form = forms_merge(form, @form)
657
488
  # If combined form contains tabs and fields options, merge fields into tabs
658
489
  if @form['form']['tabs'] and @form['form']['fields']
@@ -671,11 +502,24 @@ end
671
502
  def include_drg_cms_form(include_option)
672
503
  includes = include_option.class == Array ? include_option : include_option.split(/\,|\;/)
673
504
  includes.each do |include_file|
674
- form = YAML.load_file( dc_find_form_file(include_file) )
505
+ form_file_name = dc_find_form_file(include_file)
506
+ @form_js << read_js_drg_cms_form(form_file_name)
507
+ form = YAML.load_file(form_file_name)
675
508
  @form = forms_merge(@form, form)
676
509
  end
677
510
  end
678
511
 
512
+ ########################################################################
513
+ # Will read data from form_file_name.js if it exists.
514
+ #
515
+ # [Parameters:]
516
+ # [form_file_name] : Physical form filename
517
+ ########################################################################
518
+ def read_js_drg_cms_form(form_file_name)
519
+ js_form_file_name = form_file_name.sub('.yml','.js')
520
+ File.read(js_form_file_name) rescue ''
521
+ end
522
+
679
523
  ########################################################################
680
524
  # Read drgcms form into yaml object. Subroutine of check_authorization.
681
525
  ########################################################################
@@ -687,15 +531,19 @@ def read_drg_cms_form
687
531
  @ids = ids.split(';').inject([]) { |r,v| r << v }
688
532
  # form_name defaults to last table specified
689
533
  form_name = params[:form_name] || @tables.last[1]
534
+ @form_js = ''
690
535
  # dynamicaly generated form
691
536
  @form = if params[:form_name] == 'method'
692
537
  dc_eval_class_method(params[:form_method], params)
693
538
  else
694
- YAML.load_file( dc_find_form_file(form_name) ) rescue nil
539
+ form_file_name = dc_find_form_file(form_name)
540
+ @form_js = read_js_drg_cms_form(form_file_name)
541
+ YAML.load_file(form_file_name)
695
542
  end
696
543
  # form includes or extends another form file
697
544
  include_drg_cms_form(@form['include']) if @form['include']
698
545
  extend_drg_cms_form(@form['extend']) if @form['extend']
546
+ @form['script'] = (@form['script'].blank? ? @form_js : @form['script'] + @form_js)
699
547
  # add readonly key to form if readonly parameter is passed in url
700
548
  @form['readonly'] = 1 if params['readonly'] #and %w(1 yes true).include?(params['readonly'].to_s.downcase.strip)
701
549
  # !!!!!! Always use strings for key names since @parms['table'] != @parms[:table]
@@ -705,39 +553,49 @@ def read_drg_cms_form
705
553
  }
706
554
  end
707
555
 
556
+ ############################################################################
557
+ # Dynamically extend cmsedit class with methods defined in controls module.
558
+ ############################################################################
559
+ def extend_with_control_module(control_name=@form['controls'])
560
+ # May include embedded forms therefor ; => _
561
+ controls_string = "#{control_name || params[:table].gsub(';','_')}_control"
562
+ controls = "#{controls_string.classify}".constantize rescue nil
563
+ # old version. Will be deprecated
564
+ if controls.nil?
565
+ controls_string = (control_name ? control_name : params[:table].gsub(';','_')) + '_control'
566
+ controls = "DrgcmsControls::#{controls_string.classify}".constantize rescue nil
567
+ dc_deprecate('Putting controls into app/controllers/drgcms_controls directory will be deprecated. Put them into app/controls instead.') if controls
568
+ end
569
+ # Form may be dynamically updated before processed
570
+ if controls
571
+ extend controls
572
+ send(:dc_update_form) if respond_to?(:dc_update_form)
573
+ end
574
+
575
+ end
576
+
708
577
  ############################################################################
709
578
  # Check if user is authorized for the action. If authorization is in order it will also
710
579
  # load DRG form.
711
580
  ############################################################################
712
581
  def check_authorization
713
582
  params[:table] ||= params[:form_name]
714
- # Just show menu
715
- # return show if params[:action] == 'show'
583
+ # Only show menu
716
584
  return login if params[:id].in?(%w(login logout test))
717
585
  table = params[:table].to_s.strip.downcase
718
- # request shouldn't pass
586
+ set_default_guest_user_role if session[:user_roles].nil?
587
+ # request shouldn't pass
719
588
  if table != 'dc_memory' and
720
- (session[:user_roles].nil? or table.size < 3 or !dc_user_can(DcPermission::CAN_VIEW))
589
+ (table.size < 3 or !dc_user_can(DcPermission::CAN_VIEW))
721
590
  return render(action: 'error', locals: { error: t('drgcms.not_authorized')} )
722
591
  end
723
-
724
592
  read_drg_cms_form
725
-
726
- # Permissions can be also defined on form
727
- if @form.nil?
728
- render plain: t('drgcms.form_error')
729
- #TODO So far only can_view is used. Think about if using other permissions has sense
730
- elsif @form['permissions'].nil? or @form['permissions']['can_view'].nil? or
731
- dc_user_has_role(@form['permissions']['can_view'])
732
- # Extend class with methods defined in drgcms_controls module. May include embedded forms therefor ; => _
733
- controls_string = (@form['controls'] ? @form['controls'] : params[:table].gsub(';','_')) + '_control'
734
- controls = "DrgcmsControls::#{controls_string.classify}".constantize rescue nil
735
- # version next
736
- if controls.nil?
737
- controls_string = "#{@form['controls'] || params[:table].gsub(';','_')}_control"
738
- controls = "#{controls_string.classify}".constantize rescue nil
739
- end
740
- extend controls if controls
593
+ return render( plain: t('drgcms.form_error') ) if @form.nil?
594
+ # Permissions can be also defined on form
595
+ #TODO So far only can_view is used. Think about if using other permissions has sense
596
+ can_view = @form.dig('permissions','can_view')
597
+ if can_view.nil? or dc_user_has_role(can_view)
598
+ extend_with_control_module
741
599
  else
742
600
  render(action: 'error', locals: { error: t('drgcms.not_authorized')} )
743
601
  end
@@ -822,6 +680,7 @@ def callback_method(key) #:nodoc:
822
680
  cb = case
823
681
  when params['data'] && params['data'][data_key] then params['data'][data_key]
824
682
  # if dc_ + key method is present in model then it will be called automatically
683
+ when @form['form'][key] then @form['form'][key]
825
684
  when respond_to?('dc_' + key) then 'dc_' + key
826
685
  when params[data_key] then params[data_key]
827
686
  else nil
@@ -897,18 +756,16 @@ def save_data
897
756
  #
898
757
  form_fields.each do |v|
899
758
  session[:form_processing] = v['name'] # for debuging
900
- next if v['type'].nil? or
759
+ next if v['type'].nil? or v['name'].nil? or
901
760
  v['type'].match('embedded') or # don't wipe embedded types
902
761
  (params[:edit_only] and params[:edit_only] != v['name']) or # otherwise other fields would be wiped
903
762
  v['readonly'] or # fields with readonly option don't return value and would be wiped
904
- !@record.respond_to?(v['name']) # there can be temporary fields on the form
763
+ !@record.respond_to?(v['name']) # there are temporary fields on the form
905
764
  # good to know! How to get type of field @record.fields[v['name']].type
906
765
  # return value from form field definition
907
766
  value = DrgcmsFormFields.const_get(v['type'].camelize).get_data(params, v['name'])
908
767
  @record.send("#{v['name']}=", value)
909
768
  end
910
- #
911
- operation = @record.new_record? ? :new : :update
912
769
  # controls callback method
913
770
  if (m = callback_method('before_save') )
914
771
  ret = call_callback_method(m)
@@ -919,11 +776,231 @@ def save_data
919
776
  changes = @record.changes
920
777
  update_standards() if changes.size > 0 # update only if there has been some changes
921
778
  if (saved = @record.save)
779
+ operation = @record.new_record? ? :new : :update
922
780
  save_journal(operation, changes)
923
781
  # callback methods
924
782
  if (m = callback_method('after_save') ) then call_callback_method(m) end
925
783
  end
926
784
  saved
927
785
  end
786
+
787
+ ########################################################################
788
+ # Will return commma separated data (field names) as hash. For usage
789
+ # in select_fields and deny_fields
790
+ ########################################################################
791
+ def separated_to_hash(data)
792
+ data.chomp.split(',').inject([]) {|r,element| r << element.strip.downcase.to_sym }
793
+ end
928
794
 
795
+ ########################################################################
796
+ # Will process select_fields and deny_fields if specified
797
+ ########################################################################
798
+ def process_select_and_deny_fields
799
+ if @form['result_set']['select_fields']
800
+ @records = @records.only( separated_to_hash(@form['result_set']['select_fields']) )
801
+ end
802
+ # deny fields specified
803
+ if @form['result_set']['deny_fields']
804
+ @records = @records.without( separated_to_hash(@form['result_set']['deny_fields']) )
805
+ end
806
+ end
807
+
808
+ ########################################################################
809
+ # Will check and set sorting options for current result set. Subroutine of index method.
810
+ ########################################################################
811
+ def check_sort_options() #:nodoc:
812
+ table_name = @tables.first[1]
813
+ old_sort = session[table_name][:sort].to_s
814
+ sort, direction = old_sort.split(' ')
815
+ # sort is requested
816
+ if params['sort']
817
+ # reverse sort if same selected
818
+ if params['sort'] == sort
819
+ direction = (direction == '1') ? '-1' : '1'
820
+ end
821
+ direction ||= 1
822
+ sort = params[:sort]
823
+ session[table_name][:sort] = "#{params['sort']} #{direction}"
824
+ session[table_name][:page] = 1
825
+ end
826
+ @records.sort( sort => direction.to_i ) if session[table_name][:sort]
827
+ params['sort'] = nil # otherwise there is problem with other links
828
+ end
829
+
830
+ ########################################################################
831
+ # Set aditional filter options when filter is defined by filter method in control object.
832
+ ########################################################################
833
+ def user_filter_options(model) #:nodoc:
834
+ table_name = @tables.first[1]
835
+ if session[table_name]
836
+ DcFilter.get_filter(session[table_name][:filter]) || model
837
+ else
838
+ model
839
+ end
840
+ end
841
+
842
+ ########################################################################
843
+ # Will set session[table_name][:filter] and save last filter settings to session.
844
+ # subroutine of check_filter_options.
845
+ ########################################################################
846
+ def set_session_filter(table_name)
847
+ # models that can not be filtered (for now)
848
+ return if %w(dc_temp dc_memory).include?(params[:table])
849
+
850
+ # clear filter
851
+ if params[:filter] == 'off'
852
+ session[table_name][:filter] = nil
853
+ return
854
+ end
855
+
856
+ filter_value = if params[:filter_value].nil?
857
+ # NIL indicates that no filtering is needed
858
+ '#NIL'
859
+ else
860
+ if params[:filter_value].class == String and params[:filter_value][0] == '@'
861
+ # Internal value. Remove leading @ and evaluate expression
862
+ expression = DcInternals.get(params[:filter_value])
863
+ eval(expression) rescue nil
864
+ else
865
+ # No filter when empty
866
+ params[:filter_value] == '' ? '#NIL' : params[:filter_value]
867
+ end
868
+ end
869
+ # if filter field parameter is omitted then just set filter value
870
+ session[table_name][:filter] =
871
+ if params[:filter_field].nil?
872
+ saved = YAML.load(session[table_name][:filter])
873
+ saved['value'] = filter_value
874
+ saved.to_yaml
875
+ else
876
+ # As field defined. Split name and alternative input field
877
+ field = if params[:filter_field].match(' as ')
878
+ params[:filter_input] = params[:filter_field].split(' as ').last.strip
879
+ params[:filter_field].split(' as ').first.strip
880
+ else
881
+ params[:filter_field]
882
+ end
883
+ #
884
+ {'field' => field,
885
+ 'operation' => params[:filter_oper],
886
+ 'value' => filter_value,
887
+ 'input' => params[:filter_input],
888
+ 'table' => table_name }.to_yaml
889
+ end
890
+ # must be. Otherwise kaminari includes parameter on paging
891
+ params[:filter] = nil
892
+ params[:filter_id] = nil
893
+ params[:filter_oper] = nil
894
+ params[:filter_input] = nil
895
+ params[:filter_field] = nil
896
+ end
897
+
898
+ ########################################################################
899
+ # Will check and set current filter options for result set. Subroutine of index method.
900
+ ########################################################################
901
+ def check_filter_options() #:nodoc:
902
+ table_name = @tables.first[1]
903
+ model = @tables.first[0]
904
+ session[table_name] ||= {}
905
+ # process page
906
+ session[table_name][:page] = params[:page] if params[:page]
907
+ # new filter is applied
908
+ if params[:filter]
909
+ set_session_filter(table_name)
910
+ session[table_name][:page] = 1
911
+ end
912
+ # if data model has field dc_site_id ensure that only documents which belong to the site are selected.
913
+ site_id = dc_get_site._id if dc_get_site
914
+ # dont't filter site if no dc_site_id field or user is ADMIN
915
+ site_id = nil if !model.method_defined?('dc_site_id') or dc_user_can(DcPermission::CAN_ADMIN)
916
+ site_id = nil if session[table_name][:filter].to_s.match('dc_site_id')
917
+ #
918
+ if @records = DcFilter.get_filter(session[table_name][:filter])
919
+ @records = @records.and(dc_site_id: site_id) if site_id
920
+ else
921
+ @records = if site_id
922
+ model.where(dc_site_id: site_id)
923
+ else
924
+ model
925
+ end
926
+ end
927
+ # select only fields or deny fields specified
928
+ process_select_and_deny_fields
929
+ # pagination if required
930
+ per_page = (@form['result_set']['per_page'] || 30).to_i
931
+ @records = @records.page(session[table_name][:page]).per(per_page) if per_page > 0
932
+ end
933
+
934
+ ########################################################################
935
+ # Process index action for normal collections.
936
+ ########################################################################
937
+ def process_collections #:nodoc
938
+ # If result_set is not defined on form, then it will fail. :return_to should know where to go
939
+ if @form['result_set'].nil?
940
+ process_return_to(params[:return_to] || 'reload')
941
+ return true
942
+ end
943
+ # for now enable only filtering of top level documents
944
+ if @tables.size == 1
945
+ check_filter_options()
946
+ check_sort_options()
947
+ end
948
+ # result set is defined by filter method in control object
949
+ if @form['result_set']['filter']
950
+ if respond_to?(@form['result_set']['filter'])
951
+ @records = send @form['result_set']['filter']
952
+ # something went wrong. flash[] should have explanation.
953
+ if @records.class == FalseClass
954
+ @records = []
955
+ render(action: :index)
956
+ return true
957
+ end
958
+ process_select_and_deny_fields
959
+ # pagination but only if not already set
960
+ unless (@form['table'] == 'dc_memory' or @records.options[:limit])
961
+ per_page = (@form['result_set']['per_page'] || 30).to_i
962
+ @records = @records.page(params[:page]).per(per_page) if per_page > 0
963
+ end
964
+ else
965
+ Rails.logger.error "Error: result_set:filter: #{@form['result_set']['filter']} not found in controls!"
966
+ end
967
+ else
968
+ if @tables.size > 1
969
+ rec = @tables.first[0].find(@ids.first) # top most document.id
970
+ 1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
971
+ # TO DO. When field name is different then pluralized class name. Not working yet.
972
+ embedded_field_name = @tables.last[0] ? @tables.last[1].pluralize : @tables.last[1]
973
+ @records = rec.send(embedded_field_name) # current embedded set
974
+ # sort by order if order field is present in model
975
+ if @tables.last[1].classify.constantize.respond_to?(:order)
976
+ @records = @records.order_by('order asc')
977
+ end
978
+ end
979
+ end
980
+ false
981
+ end
982
+
983
+ ########################################################################
984
+ # Process index action for in memory data.
985
+ ########################################################################
986
+ def process_in_memory #:nodoc
987
+ @records = []
988
+ # result set is defined by filter method in control object
989
+ if (method = @form['result_set']['filter'])
990
+ send(method) if respond_to?(method)
991
+ end
992
+ # result set is defined by class method
993
+ if (klass_method = @form['result_set']['filter_method'])
994
+ _klass, method = klass_method.split('.')
995
+ klass = _klass.classify.constantize
996
+ @records = klass.send(method) if klass.respond_to?(method)
997
+ end
998
+ # ensure that record has id field
999
+ if @records.size > 0
1000
+ raise "Exception: id field must be set in dc_memory record!" unless @records.first.id
1001
+ end
1002
+ false
1003
+ end
1004
+
1005
+
929
1006
  end