drg_cms 0.4.58 → 0.4.61

Sign up to get free protection for your applications and to get access to all the features.
@@ -536,7 +536,7 @@ end
536
536
  def dc_name4_id(model, field, id)
537
537
  return '' if id.nil?
538
538
  model = model.classify.constantize if model.class == String
539
- rec = model.find_by(id: id)
539
+ rec = Mongoid::QueryCache.cache { model.find_by(id: id) }
540
540
  rec.nil? ? '' : rec[field]
541
541
  end
542
542
 
@@ -557,7 +557,7 @@ end
557
557
  # eval: dc_icon4_boolean
558
558
  ############################################################################
559
559
  def dc_icon4_boolean(value)
560
- dc_dont?(value) ? image_tag('drg_cms/checkbox-unchecked.png') : image_tag('drg_cms/checkbox-checked.png')
560
+ dc_dont?(value) ? fa_icon('square-o lg') : fa_icon('check-square-o lg')
561
561
  end
562
562
 
563
563
  ############################################################################
@@ -79,8 +79,8 @@ def do_one_item(poll, yaml)
79
79
  end
80
80
  # create form_field object and retrieve html code
81
81
  clas_string = yaml['type'].camelize
82
- field_html = if DrgcmsFormField.const_defined?(clas_string)
83
- clas = DrgcmsFormField.const_get(clas_string)
82
+ field_html = if DrgcmsFormFields.const_defined?(clas_string)
83
+ clas = DrgcmsFormFields.const_get(clas_string)
84
84
  o = clas.new(@parent, @record, yaml).render
85
85
  #TODO collect all javascript and add it at the end
86
86
  o.html + (o.js.size > 0 ? @parent.javascript_tag(o.js) : '')
@@ -59,7 +59,7 @@ end
59
59
  ########################################################################
60
60
  # Mongoid::Document model for dc_piece documents.
61
61
  #
62
- # DcPiece model is used for documents or pieces of web site which are common to site
62
+ # DcPiece collection is used for documents or pieces of web site which are common to site
63
63
  # or perhaps to all sites in database. For example page footer is a good candidate
64
64
  # to be saved in a dc_piece collection.
65
65
  #
@@ -50,7 +50,7 @@ def self.values_for_permissions
50
50
  key = 'helpers.label.dc_policy_rule.choices4_permission'
51
51
  c = I18n.t(key)
52
52
  c = I18n.t(key, locale: 'en') if c.class == Hash or c.match( 'translation missing' )
53
- c.split(',').inject([]) {|r,e| r << e.split(':')}
53
+ c.split(',').inject([]) {|r,e| r << (ar = e.split(':'); [ar.first, ar.last.to_i]) }
54
54
  end
55
55
 
56
56
  #########################################################################
@@ -114,7 +114,7 @@ end
114
114
  ####################################################################
115
115
  def ro_standard(value=nil)
116
116
  value = @record[@yaml['name']] if value.nil? and @record.respond_to?(@yaml['name'])
117
- @html << "<table class='dc-readonly'><td>#{value}</td></table>"
117
+ @html << (value.to_s.size == 0 ? '' : "<table class='dc-readonly'><td>#{value}</td></table>")
118
118
  self
119
119
  end
120
120
 
@@ -241,7 +241,7 @@ class Embedded < DrgcmsField
241
241
  # Render embedded field html code
242
242
  ###########################################################################
243
243
  def render
244
- return self if @record.new_record? # would be in error
244
+ return self if @record.new_record? # would be in error otherwise
245
245
  # HTML defaults. Some must be set
246
246
  @yaml['html'] ||= {}
247
247
  @yaml['html']['height'] ||= 300
@@ -316,7 +316,7 @@ class MultitextAutocomplete < DrgcmsField
316
316
  def ro_standard(table, search)
317
317
  result = ''
318
318
  table = table.classify.constantize
319
- return super('') if @record[@yaml['name']].nil?
319
+ return self if @record[@yaml['name']].nil?
320
320
  @record[@yaml['name']].each do |element|
321
321
  result << table.find(element)[search] + '<br>'
322
322
  end
@@ -507,9 +507,10 @@ end
507
507
  ###########################################################################
508
508
  def ro_standard
509
509
  value = @record.respond_to?(@yaml['name']) ? @record[@yaml['name']] : nil
510
- return super('') if value.nil?
510
+ return self if value.nil?
511
511
  #
512
512
  get_choices.each do |choice|
513
+ p choice, value
513
514
  if choice.class == Array
514
515
  return super(choice.first) if choice.last == value
515
516
  else
@@ -0,0 +1,1027 @@
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
+ # DrgcmsFormFields module contains definitions of classes used for
26
+ # rendering data entry fields on DRG CMS forms.
27
+ #
28
+ # Every data entry field type written in lowercase in form must have its class
29
+ # defined in CamelCase in DrgcmsFormFields module.
30
+ #
31
+ # Each class must have at least render method implemented. All classes can
32
+ # inherit from DrgcmsField class which acts as abstract template class and implements
33
+ # most of surrounding code.
34
+ #
35
+ # Render method must create html and javascript code which must be
36
+ # saved to internal @html and @js variables. Field code is then retrived by accessing
37
+ # these two internal variables.
38
+ #
39
+ # Example. How the field code is generated in form renderer:
40
+ # klas_string = yaml['type'].camelize
41
+ # if DrgcmsFormFields.const_defined?(klas_string) # check if field type class is defined
42
+ # klas = DrgcmsFormFields.const_get(klas_string)
43
+ # field = klas.new(self, @record, options).render
44
+ # javascript << field.js
45
+ # html << field.html
46
+ # end
47
+ #
48
+ # Example. How to mix DRG CMS field code in Rails views:
49
+ # <div>User:
50
+ # <%=
51
+ # opts = {'name' => 'user', 'eval' => "dc_choices4('dc_user','name')",
52
+ # 'html' => { 'include_blank' => true } }
53
+ # dt = DrgcmsFormFields::Select.new(self, {}, opts).render
54
+ # (dt.html + javascript_tag(dt.js)).html_safe
55
+ # %></div>
56
+ ###########################################################################
57
+ module DrgcmsFormFields
58
+
59
+ ###########################################################################
60
+ # Template method for DRG CMS form field definition. This is abstract class with
61
+ # most of the common code already implemented.
62
+ ###########################################################################
63
+ class DrgcmsField
64
+ attr_reader :html, :js
65
+
66
+ ####################################################################
67
+ # DrgcmsField initialization code.
68
+ #
69
+ # Parameters:
70
+ # [parent] Controller object. Controller object from where object is created. Usually self is send.
71
+ # [record] Document object. Document object which holds fields data.
72
+ # [yaml] Hash. Hash object holding field definition data.
73
+ #
74
+ # Returns:
75
+ # Self
76
+ ####################################################################
77
+ def initialize( parent, record, yaml )
78
+ @parent = parent
79
+ @record = record
80
+ @yaml = yaml
81
+ @form = parent.form
82
+ @readonly = (@yaml and @yaml['readonly']) || (@form and @form['readonly'])
83
+ @html = ''
84
+ @js = ''
85
+ self
86
+ end
87
+
88
+ ####################################################################
89
+ # Wrapper for i18 t method, with some spice added. If translation is not found English
90
+ # translation value will be returned. And if still not found default value will be returned if passed.
91
+ #
92
+ # Parameters:
93
+ # [key] String. String to be translated into locale.
94
+ # [default] String. Value returned if translation is not found.
95
+ #
96
+ # Example:
97
+ # t('translate.this','Enter text for ....')
98
+ #
99
+ # Returns:
100
+ # String. Translated text.
101
+ ####################################################################
102
+ def t(key, default='')
103
+ c = I18n.t(key)
104
+ if c.match( 'translation missing' )
105
+ c = I18n.t(key, locale: 'en')
106
+ # Still not found. Return default if set
107
+ c = default unless default.blank?
108
+ end
109
+ c
110
+ end
111
+
112
+ ####################################################################
113
+ # Standard code for returning readonly field.
114
+ ####################################################################
115
+ def ro_standard(value=nil)
116
+ value = @record[@yaml['name']] if value.nil? and @record.respond_to?(@yaml['name'])
117
+ @html << (value.to_s.size == 0 ? '' : "<table class='dc-readonly'><td>#{value}</td></table>")
118
+ self
119
+ end
120
+
121
+ ####################################################################
122
+ # Set initial value of the field when initial value is set in url parameters..
123
+ #
124
+ # Example: Form has field named picture. Field can be initialized by
125
+ # setting value of param p_picture.
126
+ ####################################################################
127
+ def set_initial_value(opt1='html', opt2='value')
128
+ @yaml['html'] ||= {}
129
+ value_send_as = 'p_' + @yaml['name']
130
+ @yaml[opt1][opt2] = @parent.params[value_send_as] if @parent.params[value_send_as]
131
+ end
132
+
133
+ ####################################################################
134
+ # Will return ruby hash formated as javascript string which can be used
135
+ # for passing parameters in javascript code.
136
+ #
137
+ # Parameters:
138
+ # [Hash] Hash. Ruby hash parameters.
139
+ #
140
+ # Example: As used in forms
141
+ # options:
142
+ # height: 400
143
+ # width: 800
144
+ # toolbar: "'basic'"
145
+ #
146
+ # => "height:400, width:800, toolbar:'basic'"
147
+ #
148
+ # Return:
149
+ # String: Options formated as javascript options.
150
+ #
151
+ ####################################################################
152
+ def hash_to_options(hash)
153
+ options = hash.to_a.inject('') do |r,v|
154
+ r << "#{v[0]}: #{v[1]},"
155
+ end
156
+ options.chomp(',')
157
+ end
158
+
159
+ ####################################################################
160
+ # Checks if field name exists in document and alters record parameters if necesary.
161
+ # Method was added after fields that do not belong to current edited document
162
+ # were added to forms. Valid nonexisting form field names must start with underscore (_) letter.
163
+ #
164
+ # Return:
165
+ # String: 'record' or '_record' when valid nonexisting field is used
166
+ ####################################################################
167
+ def record_text_for(name)
168
+ (!@record.respond_to?(name) and name[0,1] == '_') ? '_record' : 'record'
169
+ end
170
+
171
+
172
+ ###########################################################################
173
+ # Default get_data method for retrieving data from parameters. Class method is called
174
+ # for every entry field defined on form before field value is saved to database.
175
+ #
176
+ # Parameters:
177
+ # [params] Controllers params object.
178
+ # [name] Field name
179
+ #
180
+ # Most of classes will use this default method which returns params['record'][name].
181
+ # When field data is more complex class should implement its own get_data method.
182
+ ###########################################################################
183
+ def self.get_data(params, name)
184
+ params['record'][name]
185
+ end
186
+
187
+ end
188
+
189
+ ###########################################################################
190
+ # Implementation of readonly DRG CMS form field.
191
+ #
192
+ # Readonly field value is just painted on form.
193
+ ###########################################################################
194
+ class Readonly < DrgcmsField
195
+ ###########################################################################
196
+ # Render readonly field html code
197
+ ###########################################################################
198
+ def render
199
+ @html << @parent.hidden_field('record', @yaml['name']) # retain field as hidden field
200
+ @html << '<table class="dc-readonly"><td>'
201
+
202
+ @html << if @yaml['eval']
203
+ if @yaml['eval'].match('dc_name4_id')
204
+ a = @yaml['eval'].split(',')
205
+ @parent.dc_name4_id(a[1], a[2], @record[ @yaml['name'] ])
206
+ else
207
+ eval( "#{@yaml['eval']} '#{@record[ @yaml['name'] ]}'")
208
+ end
209
+ else
210
+ @parent.dc_format_value(@record[@yaml['name']],@yaml['format'])
211
+ end
212
+ @html << '</td></table>'
213
+ self
214
+ end
215
+ end
216
+
217
+ ###########################################################################
218
+ # Implementation of hidden DRG CMS form field.
219
+ #
220
+ # Will create hidden_field on form.
221
+ ###########################################################################
222
+ class HiddenField < DrgcmsField
223
+ ###########################################################################
224
+ # Render hidden_field field html code
225
+ ###########################################################################
226
+ def render
227
+ set_initial_value
228
+ value = @yaml['html']['value'] ? @yaml['html']['value'] : @record[@yaml['name']]
229
+ record = record_text_for(@yaml['name'])
230
+ @parent.hidden_field(record, @yaml['name'], value: value)
231
+ end
232
+ end
233
+
234
+ ###########################################################################
235
+ # Implementation of embedded DRG CMS form field.
236
+ #
237
+ # Creates html required to paint embedded object on form.
238
+ ###########################################################################
239
+ class Embedded < DrgcmsField
240
+ ###########################################################################
241
+ # Render embedded field html code
242
+ ###########################################################################
243
+ def render
244
+ return self if @record.new_record? # would be in error otherwise
245
+ # HTML defaults. Some must be set
246
+ @yaml['html'] ||= {}
247
+ @yaml['html']['height'] ||= 300
248
+ @yaml['html']['width'] ||= '99%'
249
+ # defaults both way
250
+ @yaml['table'] ||= @yaml['formname'] if @yaml['formname']
251
+ @yaml['formname'] ||= @yaml['table'] if @yaml['table']
252
+ #
253
+ html = ''
254
+ @yaml['html'].each {|k,v| html << "#{k}=\"#{v}\" "}
255
+ #
256
+ tables = @parent.tables.inject('') { |r,v| r << "#{v[1]};" } + @yaml['table']
257
+ ids = @parent.ids.inject('') { |r,v| r << "#{v};" } + @record._id
258
+ opts = { controller: 'cmsedit', action: 'index', ids: ids, table: tables, formname: @yaml['formname'],
259
+ field_name: @yaml['name'], iframe: "if_#{@yaml['name']}", readonly: @readonly }
260
+ @html << "<iframe class='iframe_embedded' id='if_#{@yaml['name']}' name='if_#{@yaml['name']}' #{html}></iframe>"
261
+ @js = <<EOJS
262
+ $(document).ready( function() {
263
+ $('#if_#{@yaml['name']}').attr('src', '#{@parent.url_for(opts)}');
264
+ });
265
+ EOJS
266
+ self
267
+ end
268
+
269
+ end
270
+
271
+ ###########################################################################
272
+ # Implementation of journal_diff DRG CMS form field.
273
+ #
274
+ # journal_diff field is used to show differences between two fields in DcJournal collection.
275
+ ###########################################################################
276
+ class JournalDiff < DrgcmsField
277
+ ###########################################################################
278
+ # Render journal_diff field html code
279
+ ###########################################################################
280
+ def render
281
+ @yaml['name'] = 'old' if @record[@yaml['name']].nil?
282
+ @html << '<table width="99%">'
283
+ JSON.parse(@record[@yaml['name']]).each do |k,v|
284
+ @html << "<tr><td style='background-color: #654ddd;'>#{@parent.check_box('select', k)} #{k}:</td></tr>
285
+ <tr><td style='background-color: #ffe;'>#{v[0]}</td></tr>
286
+ <tr><td style='background-color: #eff;'>#{v[1]}</td></tr>"
287
+ end
288
+ @html << '</table>'
289
+ self
290
+ end
291
+ end
292
+
293
+ ###########################################################################
294
+ # Implementation of multitext_autocomplete DRG CMS form field.
295
+ #
296
+ # multitext_autocomplete field is complex data entry field which uses autocomplete
297
+ # function when selecting multiple values for MongoDB Array field. Array typically holds
298
+ # id's of selected documents and control typically displays value of the field name
299
+ # defined by search options.
300
+ #
301
+ # Form options:
302
+ # [name] field name
303
+ # [table] Collection (table) name
304
+ # [search] Search may consist of three parameters from which last is not required. Parameters
305
+ # can be separated either by dot (.) or comma(,) table_name.display_field_name.(table_name_search_method)
306
+ # table_name is name of collection, display_field_name will be used for displaying value of selected
307
+ # document ids on screen. Optional search method can be defined when searched documents are
308
+ # only subset of all documents and additional query is required.
309
+ # [html] Various html options which can be applied to input object.
310
+ ###########################################################################
311
+ class MultitextAutocomplete < DrgcmsField
312
+
313
+ ###########################################################################
314
+ # Returns value for readonly field
315
+ ###########################################################################
316
+ def ro_standard(table, search)
317
+ result = ''
318
+ table = table.classify.constantize
319
+ return self if @record[@yaml['name']].nil?
320
+ @record[@yaml['name']].each do |element|
321
+ result << table.find(element)[search] + '<br>'
322
+ end
323
+ super(result)
324
+ end
325
+
326
+ ###########################################################################
327
+ # Render multitext_autocomplete field html code
328
+ ###########################################################################
329
+ def render
330
+ # search field name
331
+ if @yaml['search'].to_s.match(/\./)
332
+ table, field_name, method = @yaml['search'].split(/\.|\,/)
333
+ search = method.nil? ? field_name : "#{field_name}.#{method}"
334
+ else # search and table name are separated
335
+ search = field_name = @yaml['search']
336
+ end
337
+ # determine table name
338
+ if @yaml['table']
339
+ table = if @yaml['table'].class == String
340
+ @yaml['table']
341
+ # eval(how_to_get_my_table_name)
342
+ elsif @yaml['table']['eval']
343
+ eval @yaml['table']['eval']
344
+ else
345
+ p "Field #{@yaml['name']}: Invalid table parameter!"
346
+ nil
347
+ end
348
+ end
349
+ unless (table and search)
350
+ @html << 'Table or search field not defined!'
351
+ return self
352
+ end
353
+ #
354
+ return ro_standard(table, search) if @readonly
355
+ # TODO check if table exists
356
+ collection = table.classify.constantize
357
+ unless @record.respond_to?(@yaml['name'])
358
+ @html << "Invalid field name: #{@yaml['name']}"
359
+ return self
360
+ end
361
+ # put field to enter search data on form
362
+ @yaml['html'] ||= {}
363
+ @yaml['html']['value'] = '' # must be. Otherwise it will look into record and return error
364
+ _name = '_' + @yaml['name']
365
+ @html << '<table class="ui-autocomplete-table"><td>'
366
+ @html << @parent.link_to(@parent.fa_icon('plus-square lg', class: 'dc-animate dc-green'), '#',onclick: 'return false;') # dummy add. But it is usefull.
367
+
368
+ record = record_text_for(@yaml['name'])
369
+ @html << ' ' << @parent.text_field(record, _name, @yaml['html']) # text field for autocomplete
370
+ @html << "<div id =\"#{record}#{@yaml['name']}\">" # div to list active records
371
+ # find value for each field inside categories
372
+ unless @record[@yaml['name']].nil?
373
+ @record[@yaml['name']].each do |element|
374
+ # this is quick and dirty trick. We have model dc_big_table which can be used for retrive
375
+ # more complicated options
376
+ # TODO retrieve choices from big_table
377
+ rec = if table == 'dc_big_table'
378
+ collection.find(@yaml['name'], @parent.session)
379
+ else
380
+ collection.find(element)
381
+ end
382
+ # Related data is missing. It happends.
383
+ @html << if rec
384
+ link = @parent.link_to(@parent.fa_icon('remove lg', class: 'dc-animate dc-red'), '#',
385
+ onclick: "$('##{rec.id}').hide(); var v = $('##{record}_#{@yaml['name']}_#{rec.id}'); v.val(\"-\" + v.val());return false;")
386
+ field = @parent.hidden_field(record, "#{@yaml['name']}_#{rec.id}", value: element)
387
+ "<div id=\"#{rec.id}\" style=\"padding:2px;\">#{link} #{rec[field_name]}<br>#{field}</div>"
388
+ else
389
+ '** error **'
390
+ end
391
+ end
392
+ end
393
+ @html << "</div></td></table>"
394
+ # Create text for div to be added when new category is selected
395
+ link = @parent.link_to(@parent.fa_icon('remove lg', class: 'dc-animate dc-red'), '#',
396
+ onclick: "$('#rec_id').hide(); var v = $('##{record}_#{@yaml['name']}_rec_id'); v.val(\"-\" + v.val());return false;")
397
+ field = @parent.hidden_field(record, "#{@yaml['name']}_rec_id", value: 'rec_id')
398
+ one_div = "<div id=\"rec_id\" style=\"padding:2px;\">#{link} rec_search<br>#{field}</div>"
399
+
400
+ # JS stuff
401
+ @js << <<EOJS
402
+ $(document).ready(function() {
403
+ $("##{record}_#{_name}").autocomplete( {
404
+ source: function(request, response) {
405
+ $.ajax({
406
+ url: "#{ @parent.url_for( controller: 'dc_common', action: 'autocomplete' )}",
407
+ type: "POST",
408
+ dataType: "json",
409
+ data: { input: request.term, table: "#{table}", search: "#{search}" #{(',id: "'+@yaml['id'] + '"') if @yaml['id']} },
410
+ success: function(data) {
411
+ response( $.map( data, function(key) {
412
+ return key;
413
+ }));
414
+ }
415
+ });
416
+ },
417
+ change: function (event, ui) {
418
+ var div = '#{one_div}';
419
+ div = div.replace(/rec_id/g, ui.item.id)
420
+ div = div.replace('rec_search', ui.item.value)
421
+ $("##{record}#{@yaml['name']}").append(div);
422
+ $("##{record}_#{_name}").val('');
423
+ },
424
+ minLength: 2
425
+ });
426
+ });
427
+ EOJS
428
+
429
+ self
430
+ end
431
+
432
+ ###########################################################################
433
+ # Class method for retrieving data from multitext_autocomplete form field.
434
+ ###########################################################################
435
+ def self.get_data(params, name)
436
+ r = []
437
+ params['record'].each do |k,v|
438
+ # if it starts with - then it was removed
439
+ r << BSON::ObjectId.from_string(v) if k.match("#{name}_") and v[0,1] != '-'
440
+ end
441
+ r.uniq!
442
+ r
443
+ end
444
+
445
+ end
446
+
447
+ ###########################################################################
448
+ # Implementation of select DRG CMS form field.
449
+ #
450
+ # Form options:
451
+ # [name] field name
452
+ # [choices] Values for choices separated by comma. Values can also be specified like description:value.
453
+ # In this case description will be shown to user, but value will be saved to document.
454
+ # choices: 'OK:0,Ready:1,Error:2'
455
+ # choices: Ruby,Pyton,PHP
456
+ # [eval] Choices will be provided by evaluating expression
457
+ # eval: dc_choices4('model_name','description_field_name','_id') # call dc_choices4 method
458
+ # eval: DcPolicyRole.choices4_roles # call class method choices4_roles in DcPolicyRole class definition.
459
+ # If choices or eval is not defined choices will be provided from translation helpers. If you have
460
+ # field status on a form choices may be provided by en.helpers.model_name.choices4_status entry of
461
+ # english translation. English is of course default translation. If you provide translations in
462
+ # your own language then select choices will be localized.
463
+ # sl.helpers.model_name.choices4_status: 'V redu:0,Pripravljen:1,Napaka:2'
464
+ #
465
+ # [html] html options which can be applied to select field.
466
+ ###########################################################################
467
+ class Select < DrgcmsField
468
+
469
+ ###########################################################################
470
+ # Return values, when choices options will be returned by evaluating expression
471
+ ###########################################################################
472
+ def do_eval(e)
473
+ e.strip!
474
+ method = e.split(/\ |\(/).first
475
+ return eval(e) if respond_to?(method) # id method defined here
476
+ return eval('@parent.'+e) if @parent.respond_to?(method) # is method defined in helpers
477
+ # eval whatever it is
478
+ eval e
479
+ end
480
+
481
+ ###########################################################################
482
+ # Create choices array for select field.
483
+ ###########################################################################
484
+ def get_choices
485
+ begin
486
+ choices = case
487
+ when @yaml['choices'] then @yaml['choices']
488
+ when @yaml['eval'] then
489
+ do_eval(@yaml['eval'])
490
+ else
491
+ c = t('helpers.label.' + @form['table'] + '.choices4_' + @yaml['name'] )
492
+ c = 'Error' if c.match( 'translation missing' )
493
+ c
494
+ end
495
+ # Convert string to Array
496
+ choices.class == String ?
497
+ choices.chomp.split(',').inject([]) {|r,v| r << (v.match(':') ? v.split(':') : v )} :
498
+ choices
499
+ rescue Exception => e
500
+ p "Error in select eval. #{e.message}"
501
+ ['error'] # return empty array when error occures
502
+ end
503
+ end
504
+
505
+ ###########################################################################
506
+ # Return value when readonly is required
507
+ ###########################################################################
508
+ def ro_standard
509
+ value = @record.respond_to?(@yaml['name']) ? @record[@yaml['name']] : nil
510
+ return self if value.nil?
511
+ #
512
+ get_choices.each do |choice|
513
+ p choice, value
514
+ if choice.class == Array
515
+ return super(choice.first) if choice.last == value
516
+ else
517
+ return super(choice) if choice == value
518
+ end
519
+ end
520
+ super('')
521
+ end
522
+
523
+ ###########################################################################
524
+ # Render select field html code
525
+ ###########################################################################
526
+ def render
527
+ return ro_standard if @readonly
528
+ set_initial_value('html','selected')
529
+ #
530
+ @yaml['html'].symbolize_keys!
531
+ record = record_text_for(@yaml['name'])
532
+ @html << @parent.select(record, @yaml['name'], get_choices, @yaml['html'])
533
+ self
534
+ end
535
+
536
+ end
537
+
538
+ ###########################################################################
539
+ # Implementation of check_box DRG CMS form field.
540
+ ###########################################################################
541
+ class CheckBox < DrgcmsField
542
+
543
+ ###########################################################################
544
+ # Render check_box field html code
545
+ ###########################################################################
546
+ def render
547
+ set_initial_value('html','default')
548
+ # checked flag must be set
549
+ @yaml['html']['checked'] = !@parent.dc_dont?(@yaml['html']['default']) if @yaml['html']['default']
550
+ # disable it if readonly
551
+ @yaml['html']['disabled'] = @readonly ? true : nil
552
+ # If choices are present split them to set checked and unchecked value
553
+ @yaml['checked_value'], @yaml['unchecked_value'] = @yaml['choices'].split(',') if @yaml['choices']
554
+ @yaml['html'].symbolize_keys!
555
+ record = record_text_for(@yaml['name'])
556
+ @html << if @yaml['checked_value']
557
+ @parent.check_box(record, @yaml['name'], @yaml['html'], @yaml['checked_value'], @yaml['unchecked_value'] || '0')
558
+ else
559
+ @parent.check_box(record, @yaml['name'], @yaml['html'])
560
+ end
561
+ self
562
+ end
563
+ end
564
+
565
+ ###########################################################################
566
+ # Implementation of comment DRG CMS form field.
567
+ ###########################################################################
568
+ class Comment < DrgcmsField
569
+
570
+ ###########################################################################
571
+ # Render comment field html code
572
+ ###########################################################################
573
+ def render
574
+ @html << @yaml['text']
575
+ self
576
+ end
577
+ end
578
+
579
+ ###########################################################################
580
+ # Implementation of link_to DRG CMS form field. link_to form field is mostly used by polls but can
581
+ # be also incorporated in the middle of form.
582
+ ###########################################################################
583
+ class LinkTo < DrgcmsField
584
+
585
+ ###########################################################################
586
+ # Render link_to field html code
587
+ ###########################################################################
588
+ def render
589
+ @yaml['html'] ||= {}
590
+ @yaml['html']['class'] ||= 'dc-link dc-animate'
591
+ @yaml['html'].symbolize_keys!
592
+ #
593
+ url = @yaml['url'] || "#{@yaml[:controller]}/#{@yaml[:action]}/#{@yaml[:id]}"
594
+ url.gsub!('//','/') # no action and id
595
+ url = '/' + @yaml['url'] unless url[0,1] == '/' # no leading /
596
+ url.chop if url[0,-1] == '/' # remove trailing /
597
+ #
598
+ caption = @yaml['caption'] || @yaml['text']
599
+ @html << @parent.link_to(caption, url, @yaml['html'])
600
+ self
601
+ end
602
+ end
603
+
604
+ ###########################################################################
605
+ # Create submit_tag form field. submit_tag form field is mostly used by polls but can
606
+ # be also incorporated in the middle of form.
607
+ ###########################################################################
608
+ class SubmitTag < DrgcmsField
609
+
610
+ ###########################################################################
611
+ # Render submit_tag field html code
612
+ ###########################################################################
613
+ def render
614
+ @yaml['html'] ||= {}
615
+ @yaml['html']['class'] ||= 'dc-submit'
616
+ @yaml['html'].symbolize_keys!
617
+ text = @yaml['caption'] || @yaml['text']
618
+ text = t(@yaml['text']) if text.match(/\./)
619
+
620
+ @html << @parent.submit_tag(text, @yaml['html'])
621
+ self
622
+ end
623
+ end
624
+
625
+ ###########################################################################
626
+ # Implementation of password DRG CMS form field.
627
+ ###########################################################################
628
+ class PasswordField < DrgcmsField
629
+
630
+ ###########################################################################
631
+ # Render password field html code
632
+ ###########################################################################
633
+ def render
634
+ return self if @readonly
635
+ @yaml['html'] ||= {}
636
+ record = record_text_for(@yaml['name'])
637
+ @html << @parent.password_field(record, @yaml['name'], @yaml['html'])
638
+ self
639
+ end
640
+ end
641
+
642
+ ###########################################################################
643
+ # Implementation of date_select DRG CMS form field.
644
+ ###########################################################################
645
+ class DateSelect < DrgcmsField
646
+
647
+ ###########################################################################
648
+ # Render date_select field html code
649
+ ###########################################################################
650
+ def render
651
+ # return ro_standard if @readonly
652
+ return ro_standard( @parent.dc_format_value(@record[@yaml['name']])) if @readonly
653
+
654
+ #
655
+ @yaml['options'] ||= {}
656
+ set_initial_value('options','default')
657
+ @yaml['options'].symbolize_keys!
658
+ @yaml['html'].symbolize_keys!
659
+ record = record_text_for(@yaml['name'])
660
+ @html << @parent.date_select(record, @yaml['name'], @yaml['options'], @yaml['html'])
661
+ self
662
+ end
663
+
664
+ ####################################################################
665
+ # Get data for DateSelect field
666
+ # According to https://gist.github.com/315227
667
+ ####################################################################
668
+ def self.get_data(params, name)
669
+ attrs = params['record'].collect do |key, value|
670
+ if key =~ /^#{Regexp.escape(name.to_s)}\((\d+)(\w)\)$/
671
+ [$1.to_i, value.send("to_#$2")]
672
+ end
673
+ end.compact.sort_by(&:first).map(&:last)
674
+ # Return nil if error
675
+ begin
676
+ Time.zone.local(*attrs) #unless attrs.empty?
677
+ rescue
678
+ nil
679
+ end
680
+ end
681
+
682
+ end
683
+
684
+ ###########################################################################
685
+ # Create datetime_select form field
686
+ ###########################################################################
687
+ class DatetimeSelect < DrgcmsField
688
+
689
+ ###########################################################################
690
+ # Render datetime_select field html code
691
+ ###########################################################################
692
+ def render
693
+ return ro_standard( @parent.dc_format_value(@record[@yaml['name']])) if @readonly
694
+ #
695
+ @yaml['options'] ||= {}
696
+ set_initial_value('options','default')
697
+ @yaml['options'].symbolize_keys!
698
+ @yaml['html'].symbolize_keys!
699
+ #
700
+ record = record_text_for(@yaml['name'])
701
+ @html << @parent.datetime_select(record, @yaml['name'], @yaml['options'], @yaml['html'])
702
+ self
703
+ end
704
+
705
+ ###########################################################################
706
+ # DatetimeSelect get_data method.
707
+ ###########################################################################
708
+ def self.get_data(params, name)
709
+ DateSelect.get_data(params, name)
710
+ end
711
+
712
+ end
713
+
714
+ ###########################################################################
715
+ # Implementation of date_picker DRG CMS form field.
716
+ ###########################################################################
717
+ class DatePicker < DrgcmsField
718
+
719
+ ###########################################################################
720
+ # Render date_picker field html code
721
+ ###########################################################################
722
+ def render
723
+ # return ro_standard if @readonly
724
+ return ro_standard( @parent.dc_format_value(@record[@yaml['name']])) if @readonly
725
+ #
726
+ @yaml['options'] ||= {}
727
+ set_initial_value
728
+ @yaml['html']['size'] ||= 10
729
+ @yaml['html']['value'] = I18n.localize(@record[@yaml['name']].localtime.to_date) if @record[@yaml['name']]
730
+ #
731
+ @yaml['options']['lang'] ||= "'#{I18n.locale}'"
732
+ @yaml['options']['format'] ||= "'#{t('datetimepicker.formats.date')}'"
733
+ @yaml['options']['timepicker'] = false
734
+ #
735
+ record = record_text_for(@yaml['name'])
736
+ @html << @parent.text_field(record, @yaml['name'], @yaml['html'])
737
+ @js << <<EOJS
738
+ $(document).ready(function() {
739
+ $("##{record}_#{@yaml['name']}").datetimepicker( {
740
+ #{hash_to_options(@yaml['options'])}
741
+ });
742
+ });
743
+ EOJS
744
+
745
+ self
746
+ end
747
+
748
+ ###########################################################################
749
+ # DatePicker get_data method.
750
+ ###########################################################################
751
+ def self.get_data(params, name)
752
+ t = params['record'][name] ? params['record'][name].to_datetime : nil
753
+ t ? Time.zone.local(t.year, t.month, t.day) : nil
754
+ end
755
+
756
+ end
757
+ ###########################################################################
758
+ # Implementation of date_time_picker DRG CMS form field.
759
+ ###########################################################################
760
+ class DatetimePicker < DrgcmsField
761
+
762
+ ###########################################################################
763
+ # Render date_time_picker field html code
764
+ ###########################################################################
765
+ def render
766
+ # return ro_standard if @readonly
767
+ return ro_standard( @parent.dc_format_value(@record[@yaml['name']])) if @readonly
768
+ #
769
+ @yaml['options'] ||= {}
770
+ set_initial_value
771
+ @yaml['html']['size'] ||= 12
772
+ @yaml['html']['value'] = I18n.localize(@record[@yaml['name']].localtime) if @record[@yaml['name']]
773
+ #
774
+ @yaml['options']['lang'] ||= "'#{I18n.locale}'"
775
+ @yaml['options']['format'] ||= "'#{t('datetimepicker.formats.datetime')}'"
776
+ #
777
+ record = record_text_for(@yaml['name'])
778
+ @html << @parent.text_field(record, @yaml['name'], @yaml['html'])
779
+ @js << <<EOJS
780
+ $(document).ready(function() {
781
+ $("##{record}_#{@yaml['name']}").datetimepicker( {
782
+ #{hash_to_options(@yaml['options'])}
783
+ });
784
+ });
785
+ EOJS
786
+
787
+ self
788
+ end
789
+
790
+ ###########################################################################
791
+ # DateTimePicker get_data method.
792
+ ###########################################################################
793
+ def self.get_data(params, name)
794
+ t = params['record'][name] ? params['record'][name].to_datetime : nil
795
+ t ? Time.zone.local(t.year, t.month, t.day, t.hour, t.min) : nil
796
+ end
797
+
798
+ end
799
+
800
+ ###########################################################################
801
+ # Implementation of text_autocomplete DRG CMS form field.
802
+ ###########################################################################
803
+ class TextAutocomplete < DrgcmsField
804
+
805
+ ###########################################################################
806
+ # Render text_autocomplete field html code
807
+ ###########################################################################
808
+ def render
809
+ # Return descriptive text and put it into input field
810
+ # search field name
811
+ if @yaml['search'].class == Hash
812
+ table = @yaml['search']['table']
813
+ ret_name = @yaml['search']['field']
814
+ method = @yaml['search']['method']
815
+ elsif @yaml['search'].match(/\./)
816
+ table, ret_name, method = @yaml['search'].split('.')
817
+ else
818
+ ret_name = @yaml['search']
819
+ end
820
+ # determine table name
821
+ if @yaml['table']
822
+ table = if @yaml['table'].class == String
823
+ @yaml['table']
824
+ # eval(how_to_get_my_table_name)
825
+ elsif @yaml['table']['eval']
826
+ eval @yaml['table']['eval']
827
+ else
828
+ p "Field #{@yaml['name']}: Invalid table parameter!"
829
+ nil
830
+ end
831
+ end
832
+ return 'Table or field keyword not defined!' unless (table and ret_name)
833
+ # TODO check if table exists
834
+ t = table.classify.constantize
835
+ # find record and return value of field
836
+ value_send_as = 'p_' + @yaml['name']
837
+ value = if @parent.params[value_send_as]
838
+ @parent.params[value_send_as]
839
+ elsif @record and @record[@yaml['name']]
840
+ @record[@yaml['name']]
841
+ end
842
+ # Found value to be written in field
843
+ if value
844
+ record = t.find(value)
845
+ value_displayed = record[ret_name] if record
846
+ end
847
+ # return if readonly
848
+ return ro_standard(value_displayed) if @readonly
849
+ # Add method back, so autocomplete will know that it must search for method inside class
850
+ ret_name = "#{ret_name}.#{method}" if method
851
+ @yaml['html'] ||= {}
852
+ @yaml['html']['value'] = value_displayed
853
+ #
854
+ _name = '_' + @yaml['name']
855
+ record = record_text_for(@yaml['name'])
856
+ @html << @parent.text_field(record, _name, @yaml['html'])
857
+ if @yaml['with_new']
858
+ @html << @parent.image_tag('drg_cms/add.png', class: 'in-edit-add', title: t('drgcms.new'),
859
+ style: "vertical-align: top;", 'data-table' => @yaml['with_new'] )
860
+ end
861
+ @html << @parent.hidden_field(record, @yaml['name'], value: value) # actual value will be in hidden field
862
+ # JS stuff
863
+ @js << <<EOJS
864
+ $(document).ready(function() {
865
+ $("##{record}_#{_name}").autocomplete( {
866
+ source: function(request, response) {
867
+ $.ajax({
868
+ url: '/dc_common/autocomplete',
869
+ type: "POST",
870
+ dataType: "json",
871
+ data: { input: request.term, table: "#{table}", search: "#{ret_name}" #{(',id: "'+@yaml['id'] + '"') if @yaml['id']} },
872
+ success: function(data) {
873
+ response( $.map( data, function(key) {
874
+ return key;
875
+ }));
876
+ }
877
+ });
878
+ },
879
+ change: function (event, ui) {
880
+ $("##{record}_#{@yaml['name']}").val(ui.item.id);
881
+ },
882
+ minLength: 2
883
+ });
884
+ });
885
+ EOJS
886
+
887
+ self
888
+ end
889
+ end
890
+
891
+ ###########################################################################
892
+ # Implementation of text_area DRG CMS form field.
893
+ ###########################################################################
894
+ class TextArea < DrgcmsField
895
+
896
+ ###########################################################################
897
+ # Render text_area field html code
898
+ ###########################################################################
899
+ def render
900
+ return ro_standard if @readonly
901
+ #
902
+ @yaml['html'] ||= {}
903
+ value_send_as = 'p_' + @yaml['name']
904
+ @yaml['html']['value'] = @parent.params[value_send_as] if @parent.params[value_send_as]
905
+
906
+ record = record_text_for(@yaml['name'])
907
+ @html << @parent.text_area(record, @yaml['name'], @yaml['html'])
908
+ self
909
+ end
910
+ end
911
+
912
+ ###########################################################################
913
+ # Implementation of text_field DRG CMS form field.
914
+ ###########################################################################
915
+ class TextField < DrgcmsField
916
+
917
+ ###########################################################################
918
+ # Render text_field field html code
919
+ ###########################################################################
920
+ def render
921
+ return ro_standard if @readonly
922
+ set_initial_value
923
+ #
924
+ record = record_text_for(@yaml['name'])
925
+ @html << @parent.text_field( record, @yaml['name'], @yaml['html'])
926
+ self
927
+ end
928
+ end
929
+
930
+ ###########################################################################
931
+ # Implementation of text_with_select DRG CMS form field.
932
+ #
933
+ # Create text_field with select dropdown box with optional values for the field
934
+ ###########################################################################
935
+ class TextWithSelect < Select
936
+
937
+ ###########################################################################
938
+ # Render text_with_select field html code
939
+ ###########################################################################
940
+ def render
941
+ return ro_standard if @readonly
942
+ set_initial_value('html','value')
943
+
944
+ record = record_text_for(@yaml['name'])
945
+ @html << @parent.text_field( record, @yaml['name'], @yaml['html'])
946
+ @yaml['html']['class'] = 'text-with-select'
947
+ @yaml['html'].symbolize_keys!
948
+ @html << @parent.select( @yaml['name'] + '_', nil, get_choices, { include_blank: true }, { class: 'text-with-select' })
949
+
950
+ # javascript to update text field if new value is selected in select field
951
+ @js =<<EOJS
952
+ $(document).ready(function() {
953
+ $('##{@yaml['name']}_').change( function() {
954
+ if ($(this).val().toString().length > 0) {
955
+ $('##{record}_#{@yaml['name']}').val( $(this).val() );
956
+ }
957
+ $('##{record}_#{@yaml['name']}').focus();
958
+ });
959
+ });
960
+ EOJS
961
+ self
962
+ end
963
+ end
964
+
965
+ ###########################################################################
966
+ # Implementation of html_field DRG CMS form field.
967
+ #
968
+ # HtmlField class implements redirection for calling actual html edit field code.
969
+ # This can be drg_default_html_editor's ckeditor or any other code defined
970
+ # by dc_site.settings html_editor setting.
971
+ ###########################################################################
972
+ class HtmlField < DrgcmsField
973
+
974
+ ###########################################################################
975
+ # Render html_field field html code
976
+ ###########################################################################
977
+ def render
978
+ return ro_standard if @readonly
979
+ # retrieve html editor from page settings
980
+ editor_string = @parent.dc_get_site.params['html_editor'] if @parent.dc_get_site
981
+ editor_string ||= 'ckeditor'
982
+ #
983
+ klas_string = editor_string.camelize
984
+ if DrgcmsFormFields.const_defined?(klas_string)
985
+ klas = DrgcmsFormFields::const_get(klas_string)
986
+ o = klas.new(@parent, @record, @yaml).render
987
+ @js << o.js
988
+ @html << o.html
989
+ else
990
+ @html << "HTML editor not defined. Check site.settings or include drgcms_default_html_editor gem."
991
+ end
992
+ self
993
+ end
994
+ end
995
+
996
+ ###########################################################################
997
+ # Implementation of file_select DRG CMS form field.
998
+ #
999
+ # FileSelect like HtmlField implements redirection for calling document manager edit field code.
1000
+ # This can be drg_default_html_editor's elfinder or any other code defined
1001
+ # by dc_site.settings file_select setting.
1002
+ ###########################################################################
1003
+ class FileSelect < DrgcmsField
1004
+
1005
+ ###########################################################################
1006
+ # Render file_select field html code
1007
+ ###########################################################################
1008
+ def render
1009
+ return ro_standard if @readonly
1010
+ # retrieve html editor from page settings
1011
+ selector_string = @parent.dc_get_site.params['file_select'] if @parent.dc_get_site
1012
+ selector_string ||= 'elfinder'
1013
+ #
1014
+ klas_string = selector_string.camelize
1015
+ if DrgcmsFormFields.const_defined?(klas_string)
1016
+ klas = DrgcmsFormFields::const_get(klas_string)
1017
+ o = klas.new(@parent, @record, @yaml).render
1018
+ @js << o.js
1019
+ @html << o.html
1020
+ else
1021
+ @html << "File select component not defined. Check site.settings or include drgcms_default_html_editor gem."
1022
+ end
1023
+ self
1024
+ end
1025
+ end
1026
+
1027
+ end