drg_cms 0.6.0.3 → 0.6.0.6

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