drg_cms 0.5.52.12 → 0.5.52.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/app/assets/javascripts/drg_cms/drg_cms.js +17 -2
  3. data/app/assets/stylesheets/drg_cms/drg_cms.css +16 -3
  4. data/app/assets/stylesheets/drg_cms/select-multiple.css +1 -1
  5. data/app/controllers/cmsedit_controller.rb +56 -16
  6. data/app/controllers/dc_application_controller.rb +83 -1
  7. data/app/controllers/dc_common_controller.rb +2 -52
  8. data/app/forms/all_options.yml +27 -4
  9. data/app/forms/cms_menu.yml +5 -0
  10. data/app/forms/dc_gallery.yml +53 -0
  11. data/app/forms/dc_link.yml +16 -10
  12. data/app/forms/dc_menu_item.yml +5 -0
  13. data/app/forms/dc_page.yml +1 -2
  14. data/app/forms/dc_removed_url.yml +42 -0
  15. data/app/helpers/cmsedit_helper.rb +63 -22
  16. data/app/helpers/dc_application_helper.rb +35 -11
  17. data/app/helpers/dc_gallery_renderer.rb +94 -0
  18. data/app/helpers/dc_page_renderer.rb +20 -3
  19. data/app/helpers/dc_poll_renderer.rb +6 -7
  20. data/app/models/concerns/dc_page_concern.rb +1 -1
  21. data/app/models/dc_filter.rb +15 -7
  22. data/app/models/dc_gallery.rb +64 -0
  23. data/app/models/dc_link.rb +1 -0
  24. data/app/models/dc_memory.rb +19 -4
  25. data/app/models/dc_page.rb +1 -1
  26. data/app/models/dc_removed_url.rb +54 -0
  27. data/app/models/drgcms_form_fields.rb +5 -1649
  28. data/app/models/drgcms_form_fields/check_box.rb +69 -0
  29. data/app/models/drgcms_form_fields/comment.rb +49 -0
  30. data/app/models/drgcms_form_fields/date_picker.rb +102 -0
  31. data/app/models/drgcms_form_fields/date_select.rb +68 -0
  32. data/app/models/drgcms_form_fields/date_time_picker.rb +87 -0
  33. data/app/models/drgcms_form_fields/datetime_select.rb +73 -0
  34. data/app/models/drgcms_form_fields/drgcms_field.rb +241 -0
  35. data/app/models/drgcms_form_fields/drgcms_form_fields.rb +25 -0
  36. data/app/models/drgcms_form_fields/embedded.rb +84 -0
  37. data/app/models/drgcms_form_fields/file_select.rb +70 -0
  38. data/app/models/drgcms_form_fields/hidden_field.rb +52 -0
  39. data/app/models/drgcms_form_fields/html_field.rb +70 -0
  40. data/app/models/drgcms_form_fields/journal_diff.rb +60 -0
  41. data/app/models/drgcms_form_fields/link_to.rb +69 -0
  42. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +195 -0
  43. data/app/models/drgcms_form_fields/number_field.rb +83 -0
  44. data/app/models/drgcms_form_fields/password_field.rb +62 -0
  45. data/app/models/drgcms_form_fields/readonly.rb +79 -0
  46. data/app/models/drgcms_form_fields/select.rb +164 -0
  47. data/app/models/drgcms_form_fields/submit_tag.rb +58 -0
  48. data/app/models/drgcms_form_fields/text_area.rb +68 -0
  49. data/app/models/drgcms_form_fields/text_autocomplete.rb +143 -0
  50. data/app/models/drgcms_form_fields/text_field.rb +56 -0
  51. data/app/models/drgcms_form_fields/text_with_select.rb +92 -0
  52. data/app/models/drgcms_form_fields/tree_select.rb +150 -0
  53. data/config/locales/drgcms_en.yml +1 -0
  54. data/config/locales/drgcms_sl.yml +2 -1
  55. data/config/locales/models_en.yml +42 -6
  56. data/config/locales/models_sl.yml +38 -3
  57. data/lib/drg_cms.rb +1 -1
  58. data/lib/drg_cms/version.rb +1 -1
  59. data/lib/tasks/dc_cleanup.rake +1 -1
  60. metadata +33 -4
@@ -49,6 +49,25 @@ end
49
49
 
50
50
  #########################################################################
51
51
  # Render IFrame part if defined on page
52
+ #
53
+ # Parameters forwarded to iframe are defined in if_params field as yaml as:
54
+ # param_name:
55
+ # object: internal object name (params, session, site, page)
56
+ # method: method name (variable) holding the value of parameter
57
+ #
58
+ # example: Forward id parameter to iframe
59
+ # id:
60
+ # object: params
61
+ # method: id
62
+ #
63
+ # example: Forward user id and edit_mode to iframe
64
+ # user_id:
65
+ # object: session
66
+ # method: user_id
67
+ # edit:
68
+ # object: session
69
+ # method: edit_mode
70
+ #
52
71
  #########################################################################
53
72
  def iframe
54
73
  return '' if @page.if_url.blank?
@@ -64,7 +83,7 @@ def iframe
64
83
  params = YAML.load(@page.if_params) rescue {}
65
84
  params = {} unless params.class == Hash
66
85
  params.each do |key, value|
67
- val = @parent.dc_internal_var(value['object'], value['variable'])
86
+ val = @parent.dc_internal_var(value['object'], value['method'])
68
87
  parameters << "&#{key}=#{val}" if val # only when not nil
69
88
  end
70
89
  url = @page.if_url + (parameters.size > 1 ? parameters : '')
@@ -92,8 +111,6 @@ def default
92
111
  end
93
112
  # also add iframe
94
113
  html << iframe()
95
- html
96
-
97
114
  end
98
115
 
99
116
  #########################################################################
@@ -67,7 +67,7 @@ def do_one_item(poll, yaml)
67
67
  # Just add text if comment and go to next one
68
68
  if yaml['type'] == 'comment'
69
69
  html << if poll.display == 'lr'
70
- "<tr><td colspan='2' class='poll-data-text'>#{text}</td></tr>"
70
+ "<div class='row-div'><div class='dc-form-label poll-data-text'>#{text}</div></div>"
71
71
  else
72
72
  "<div class='poll-data-text'>#{text}</div>"
73
73
  end
@@ -98,7 +98,7 @@ def do_one_item(poll, yaml)
98
98
  # There can be more than one links on form. End the data at first link or submit.
99
99
  if !@end_of_data
100
100
  html << if poll.display == 'lr'
101
- "</table><br>\n"
101
+ "</div><br>\n"
102
102
  else
103
103
  "</div>\n"
104
104
  end
@@ -117,9 +117,9 @@ def do_one_item(poll, yaml)
117
117
  # other elements
118
118
  else
119
119
  html << if poll.display == 'lr'
120
- "<tr><td class='poll-data-text'>#{text}</td><td class='poll-data-field #{yaml['class']}'>#{field_html}</td></tr>\n"
120
+ "<div class='row-div'><div class='dc-form-label poll-data-text #{yaml['class']}'>#{text}</div><div class='dc-form-field poll-data-field #{yaml['class']}'>#{field_html}</div></div>\n"
121
121
  else
122
- "<div class='poll-data-text'>#{text}</div><div class='poll-data-field #{yaml['class']}'>#{field_html}#{yaml['separator']}</div>\n"
122
+ "<div class='poll-data-text #{yaml['class']}'>#{text}</div><div class='poll-data-field #{yaml['class']}'>#{field_html}#{yaml['separator']}</div>\n"
123
123
  end
124
124
  end
125
125
  end
@@ -149,9 +149,8 @@ def default
149
149
  return message unless continue
150
150
  html << message if message
151
151
  end
152
-
153
152
  # there might be more than one poll displayed on page. Check if messages and values are for me
154
- if @parent.flash[:poll_id].nil? or @parent.flash[:poll_id] == poll_id
153
+ if @parent.flash[:poll_id].nil? or @parent.flash[:poll_id].to_s == poll_id.to_s
155
154
  # If flash[:record] is present copy content to params record hash
156
155
  @parent.flash[:record].each {|k,v| @parent.params["p_#{k}"] = v } if @parent.flash[:record]
157
156
  # Error during procesing request
@@ -178,7 +177,7 @@ def default
178
177
  html << "<div class='poll-title'>#{poll.title}</div>" unless poll.title[0] == '-' # - on first position will not display title
179
178
  html << poll.sub_text.to_s # if poll.sub_text.to_s.size > 5
180
179
  html << if poll.display == 'lr'
181
- "\n" + '<table class="poll-data-table">'
180
+ "\n" + '<div class="poll-data-table">'
182
181
  else
183
182
  '<div class="poll-data-div">' + "\n"
184
183
  end
@@ -38,7 +38,7 @@ field :subject_link, type: String, default: ''
38
38
  field :alt_link, type: String, default: ''
39
39
  field :sub_subject, type: String, default: ''
40
40
  field :picture, type: String
41
- field :gallery, type: String
41
+ field :gallery, type: Boolean, default: false
42
42
  field :body, type: String, default: ''
43
43
  field :css, type: String, default: ''
44
44
  field :script, type: String, default: ''
@@ -55,10 +55,14 @@ def self.get_filter(filter)
55
55
  yaml = YAML.load(filter) rescue nil
56
56
  return yaml if yaml.nil?
57
57
  return nil if yaml['table'].nil? # old data
58
- #
58
+ #
59
59
  model = yaml['table'].classify.constantize
60
60
  field = yaml['field'] == 'id' ? '_id' : yaml['field'] # must be
61
- # if empty required
61
+ # evaluate
62
+ if yaml['operation'] == 'eval' and model.respond_to?(yaml['field'])
63
+ return model.send( yaml['field'] )
64
+ end
65
+ # if empty
62
66
  if yaml['operation'] == 'empty'
63
67
  return model.in(field => [nil,''])
64
68
  end
@@ -155,7 +159,8 @@ def self.menu_filter(parent)
155
159
  table = parent.form['table']
156
160
  documents = self.where(table: table, active: true).to_a
157
161
  documents.each do |document|
158
- html << "<li data-filter=\"\">#{document.description}</li>"
162
+ description = document.description.match('.') ? I18n.t(document.description) : document.description
163
+ html << "<li data-filter=\"#{document.id}\">#{description}</li>"
159
164
  end
160
165
 
161
166
  # add filters defined in model
@@ -176,7 +181,6 @@ def self.menu_filter(parent)
176
181
  end
177
182
  # divide standard and custom filter options
178
183
  html << '<hr>' if html.size > 30 #
179
- # html << '<li onclick="$(\'#drgcms_filter\').toggle(300);">' + I18n.t('drgcms.filter_set') + '</li>'
180
184
  html << '<li id="open_drgcms_filter">' + I18n.t('drgcms.filter_set') + '</li>'
181
185
  html << '</ul>'
182
186
  end
@@ -189,10 +193,14 @@ def self.title4_filter_off(filter_yaml)
189
193
  filter = YAML.load(filter_yaml)
190
194
  operations = I18n.t('drgcms.choices4_filter_operators').chomp.split(',').inject([]) {|r,v| r << v.split(':') }
191
195
  operation = ''
192
- operations.each{|a| (operation = a.first; break) if a.last == filter['operation']}
196
+ if filter['operation'] == 'eval'
197
+ filter['field']
198
+ else
199
+ operations.each{|a| (operation = a.first; break) if a.last == filter['operation']}
193
200
  #
194
- '[ ' + I18n.t("helpers.label.#{filter['table']}.#{filter['field']}") +
195
- " ] #{operation} [ #{filter['value'].to_s} ] : #{I18n.t('drgcms.filter_off')}"
201
+ '[ ' + I18n.t("helpers.label.#{filter['table']}.#{filter['field']}") +
202
+ " ] #{operation} [ #{filter['value'].to_s} ] : #{I18n.t('drgcms.filter_off')}"
203
+ end
196
204
  end
197
205
 
198
206
  end
@@ -0,0 +1,64 @@
1
+ #--
2
+ # Copyright (c) 2019+ 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
+ # == Schema information
26
+ #
27
+ # Collection name: dc_gallery : Pictures gallery
28
+ #
29
+ # _id BSON::ObjectId _id
30
+ # doc_id BSON::ObjectId Document id of the gallery
31
+ # title String Title name for picture
32
+ # description String Short description
33
+ # picture String Picture filename
34
+ # thumbnail String Picture thumbnail
35
+ #
36
+ # active Mongoid::Boolean Picture is active
37
+ # created_by BSON::ObjectId created_by
38
+ # updated_by BSON::ObjectId updated_by
39
+ # created_at Time created_at
40
+ # updated_at Time updated_at
41
+ #
42
+ # Picture gallery collection holds data about picture galleries for
43
+ # different types of documents.
44
+ #########################################################################
45
+ class DcGallery
46
+ include Mongoid::Document
47
+ include Mongoid::Timestamps
48
+
49
+ field :title, type: String
50
+ field :description, type: String
51
+ field :picture, type: String
52
+ field :thumbnail, type: String
53
+ field :doc_id, type: BSON::ObjectId
54
+ field :order, type: Integer, default: 10
55
+
56
+ field :active, type: Boolean, default: true
57
+ field :created_by, type: BSON::ObjectId
58
+ field :updated_by, type: BSON::ObjectId
59
+
60
+ index doc_id: 1
61
+
62
+ validates :picture, presence: true
63
+ validates :doc_id, presence: true
64
+ end
@@ -47,6 +47,7 @@ class DcLink
47
47
  field :name, type: String
48
48
  field :params, type: String
49
49
  field :active, type: Boolean, default: true
50
+ field :redirect, type: String
50
51
  field :page_id, type: BSON::ObjectId
51
52
  field :created_by, type: BSON::ObjectId
52
53
  field :updated_by, type: BSON::ObjectId
@@ -25,8 +25,6 @@
25
25
  # == Schema information
26
26
  #
27
27
  # Collection name: dc_memory : Collection name used when form does not belong to database model.
28
- #
29
- # _id BSON::ObjectId _id
30
28
  #
31
29
  # Which is not collection at all. DcMemory model is used for entering data on forms
32
30
  # where data will not be saved to database but will instead be saved only to memory as
@@ -67,6 +65,21 @@
67
65
  class DcMemory
68
66
  include Mongoid::Document
69
67
 
68
+ ########################################################################
69
+ # Initilize object
70
+ ########################################################################
71
+ def initialize(parms = {})
72
+ @internals = {}
73
+ parms.each { |key, value| @internals[key.to_s] = value } if parms
74
+ end
75
+
76
+ ########################################################################
77
+ # Respond_to should always return true.
78
+ ########################################################################
79
+ def id()
80
+ @internals['id']
81
+ end
82
+
70
83
  ########################################################################
71
84
  # Respond_to should always return true.
72
85
  ########################################################################
@@ -75,7 +88,7 @@ def respond_to?(m)
75
88
  end
76
89
 
77
90
  ########################################################################
78
- # Redefine send method. Send is used to assign value by cmsedit controller.
91
+ # Redefine send method. Send is used to assign or access value by cmsedit controller.
79
92
  ########################################################################
80
93
  def send(field,value=nil)
81
94
  field = field.to_s
@@ -83,6 +96,8 @@ def send(field,value=nil)
83
96
  field.chomp!('=')
84
97
  @internals ||= {}
85
98
  @internals[field] = value
99
+ else
100
+ @internals[field]
86
101
  end
87
102
  end
88
103
 
@@ -106,7 +121,7 @@ end
106
121
  # For debugging purposes
107
122
  ########################################################################
108
123
  def to_s
109
- "DcMemory: @internals=#{@internals}"
124
+ "DcMemory: @internals=#{@internals.size} #{@internals}"
110
125
  end
111
126
 
112
127
  ########################################################################
@@ -36,7 +36,7 @@
36
36
  # alt_link String Alternative link, by which page could be found
37
37
  # sub_subject String Sub subject, short description of text
38
38
  # picture String Picture used in conjunction with page
39
- # gallery String Gallery pictures are defined in parts of page. Value defines name of parts which hold data about pictures in gallary.
39
+ # gallery Boolean Picture gallery defined on page. Picture data is saved to document parts with id gallery.
40
40
  # body String Content of this page
41
41
  # css String CSS only for this menu page
42
42
  # script String Javascript only for this page
@@ -0,0 +1,54 @@
1
+ #--
2
+ # Copyright (c) 2018+ 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
+ # == Schema information
26
+ #
27
+ # Collection name: dc_removed_url : List of URL-s removed from site
28
+ #
29
+ # _id BSON::ObjectId _id
30
+ # created_at Time created_at
31
+ # updated_at Time updated_at
32
+ # url String URL that is no longer active
33
+ # dc_site_id Object URL is valid only for the site
34
+ #
35
+ # List of URLs removed from site so web crawlers will also remove them from their
36
+ # indexes. Usefull when creating sitemaps.
37
+ #
38
+ ##########################################################################
39
+ class DcRemovedUrl
40
+ include Mongoid::Document
41
+ include Mongoid::Timestamps
42
+
43
+ field :url, type: String
44
+ field :description, type: String
45
+
46
+ field :created_by, type: BSON::ObjectId
47
+ field :updated_by, type: BSON::ObjectId
48
+
49
+ belongs_to :dc_site, optional: true
50
+
51
+ index( dc_site: 1 )
52
+
53
+ validates :url, presence: true
54
+ end
@@ -20,1654 +20,10 @@
20
20
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
+ ##############################################################
24
+ # Require all files in drgcms_form_fields directory.
25
+ ###############################################################
23
26
 
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 for creating custom DRG CMS form field.
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 for custom form field already implemented.
62
- ###########################################################################
63
- class DrgcmsField
64
- attr_reader :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
- if @yaml['size'] # move size to html element if not already there
84
- @yaml['html'] ||= {}
85
- @yaml['html']['size'] ||= @yaml['size']
86
- end
87
- @html = ''
88
- @js = ''
89
- @css = @yaml['css']
90
- self
91
- end
92
-
93
- ####################################################################
94
- # Returns html code together with CSS code.
95
- ####################################################################
96
- def html
97
- @html + (@css ? "\n<style type=\"text/css\">#{@css}</style>" : '')
98
- end
99
-
100
- ####################################################################
101
- # Wrapper for i18 t method, with some spice added. If translation is not found English
102
- # translation value will be returned. And if still not found default value will be returned if passed.
103
- #
104
- # Parameters:
105
- # [key] String. String to be translated into locale.
106
- # [default] String. Value returned if translation is not found.
107
- #
108
- # Example:
109
- # t('translate.this','Enter text for ....')
110
- #
111
- # Returns:
112
- # String. Translated text.
113
- ####################################################################
114
- def t(key, default='')
115
- c = I18n.t(key)
116
- if c.match( 'translation missing' )
117
- c = I18n.t(key, locale: 'en')
118
- # Still not found. Return default if set
119
- c = default unless default.blank?
120
- end
121
- c
122
- end
123
-
124
- ####################################################################
125
- # Standard code for returning readonly field.
126
- ####################################################################
127
- def ro_standard(value=nil)
128
- value = @record[@yaml['name']] if value.nil? and @record.respond_to?(@yaml['name'])
129
- @html << (value.blank? ? '' : "<div class='dc-readonly'>#{value}</div>")
130
- self
131
- end
132
-
133
- ####################################################################
134
- # Set initial value of the field when initial value is set in url parameters..
135
- #
136
- # Example: Form has field named picture. Field can be initialized by
137
- # setting value of param p_picture.
138
- # params['p_picture'] = '/path/to_picture'
139
- #
140
- # When multiple initial values are assigned it is more convinient to assign them
141
- # through flash object.
142
- # flash[:record] = {}
143
- # flash[:record]['picture'] = '/path/to_picture'
144
- ####################################################################
145
- def set_initial_value(opt1='html', opt2='value')
146
- @yaml['html'] ||= {}
147
- value_send_as = 'p_' + @yaml['name']
148
- if @parent.params[value_send_as]
149
- @yaml[opt1][opt2] = @parent.params[value_send_as]
150
- elsif @parent.flash[:record] and @parent.flash[:record][@yaml['name']]
151
- @yaml[opt1][opt2] = @parent.flash[:record][@yaml['name']]
152
- end
153
- end
154
-
155
- ####################################################################
156
- # Returns style html code for DRGForm object if style directive is present in field definition.
157
- # Otherwiese returns empty string.
158
- #
159
- # Style may be defined like:
160
- # style:
161
- # height: 400px
162
- # width: 800px
163
- # padding: 10px 20px
164
- #
165
- # or
166
- #
167
- # style: "height:400px; width:800px; padding: 10px 20px;"
168
- #
169
- # Style directive may also be defined under html directive.
170
- # html:
171
- # style:
172
- # height: 400px
173
- # width: 800px
174
- #
175
- #
176
- ####################################################################
177
- def set_style()
178
- style = @yaml['html']['style'] || @yaml['style']
179
- case
180
- when style.nil? then ''
181
- when style.class == String then "style=\"#{style}\""
182
- when style.class == Hash then
183
- value = style.to_a.inject([]) {|r,v| r << "#{v[0]}: #{v[1]}" }.join(';')
184
- "style=\"#{value}\""
185
- else ''
186
- end
187
- end
188
-
189
- ####################################################################
190
- # Will return ruby hash formated as javascript string which can be used
191
- # for passing parameters in javascript code.
192
- #
193
- # Parameters:
194
- # [Hash] Hash. Ruby hash parameters.
195
- #
196
- # Form example: As used in forms
197
- # options:
198
- # height: 400
199
- # width: 800
200
- # toolbar: "'basic'"
201
- #
202
- # => "height:400, width:800, toolbar:'basic'"
203
- #
204
- # Return:
205
- # String: Options formated as javascript options.
206
- #
207
- ####################################################################
208
- def hash_to_options(hash)
209
- hash.to_a.inject([]) {|r,v| r << "#{v[0]}: #{v[1]}" }.join(',')
210
- end
211
-
212
- ####################################################################
213
- # Checks if field name exists in document and alters record parameters if necesary.
214
- # Method was added after fields that do not belong to current edited document
215
- # were added to forms. Valid nonexisting form field names must start with underscore (_) letter.
216
- #
217
- # Return:
218
- # String: 'record' or '_record' when valid nonexisting field is used
219
- ####################################################################
220
- def record_text_for(name)
221
- (!@record.respond_to?(name) and name[0,1] == '_') ? '_record' : 'record'
222
- end
223
-
224
-
225
- ###########################################################################
226
- # Default get_data method for retrieving data from parameters. Class method is called
227
- # for every entry field defined on form before field value is saved to database.
228
- #
229
- # Parameters:
230
- # [params] Controllers params object.
231
- # [name] Field name
232
- #
233
- # Most of classes will use this default method which returns params['record'][name].
234
- # When field data is more complex class should implement its own get_data method.
235
- ###########################################################################
236
- def self.get_data(params, name)
237
- params['record'][name]
238
- end
239
-
240
- end
241
-
242
- ###########################################################################
243
- # Implementation of readonly DRG CMS form field.
244
- #
245
- # Readonly field value is just painted on form.
246
- #
247
- # ===Form options:
248
- # * +name:+ field name
249
- # * +type:+ readonly
250
- # * +eval:+ value will be provided by evaluating expression. Usually dc_name4_id helper
251
- # can be used to get value. Example: dc_name4_id,model_name_in_lower_case,field_name
252
- #
253
- # * +readonly:+ yes (can be applied to any field type)
254
- #
255
- # Form example:
256
- # 10:
257
- # name: user
258
- # type: readonly
259
- # html:
260
- # size: 50
261
- # 20:
262
- # name: created_by
263
- # type: readonly
264
- # eval: dc_name4_id,dc_user,name
265
- ###########################################################################
266
- class Readonly < DrgcmsField
267
- ###########################################################################
268
- # Render readonly field html code
269
- ###########################################################################
270
- def render
271
- @html << @parent.hidden_field('record', @yaml['name']) # retain field as hidden field
272
- @html << '<div class="dc-readonly">'
273
-
274
- @html << if @yaml['eval']
275
- if @yaml['eval'].match('dc_name4_id')
276
- a = @yaml['eval'].split(',')
277
- if a.size == 3
278
- @parent.dc_name4_id(a[1], a[2], nil, @record[ @yaml['name'] ])
279
- else
280
- @parent.dc_name4_id(a[1], a[2], a[3], @record[ @yaml['name'] ])
281
- end
282
-
283
- # @parent.dc_name4_id(a[1], a[2], @record[ @yaml['name'] ])
284
- else
285
- eval( "#{@yaml['eval']} '#{@record[ @yaml['name'] ]}'")
286
- end
287
- else
288
- @parent.dc_format_value(@record[@yaml['name']],@yaml['format'])
289
- end
290
- @html << '</div>'
291
- self
292
- end
293
- end
294
-
295
- ###########################################################################
296
- # Implementation of hidden DRG CMS form field.
297
- #
298
- # Will create hidden_field on form.
299
- #
300
- # ===Form options:
301
- # * +name:+ field name
302
- # * +type:+ hidden_field
303
- #
304
- # Form example:
305
- # 10:
306
- # name: im_hidden
307
- # type: hidden_field
308
- ###########################################################################
309
- class HiddenField < DrgcmsField
310
- ###########################################################################
311
- # Render hidden_field field html code
312
- ###########################################################################
313
- def render
314
- set_initial_value
315
- value = @yaml['html']['value'] ? @yaml['html']['value'] : @record[@yaml['name']]
316
- record = record_text_for(@yaml['name'])
317
- @parent.hidden_field(record, @yaml['name'], value: value)
318
- end
319
- end
320
-
321
- ###########################################################################
322
- # Implementation of embedded DRG CMS form field.
323
- #
324
- # Creates html required to paint embedded object on form.
325
- #
326
- # ===Form options:
327
- # * +name:+ field name (required)
328
- # * +type:+ embedded (required)
329
- # * +form_name:+ name of form which will be used for editing
330
- # * +html:+ html options (optional)
331
- # * +height:+ height of embedded object in pixels (1000)
332
- # * +width:+ width of embedded object in pixels (500)
333
- #
334
- # Form example:
335
- # 10:
336
- # name: dc_parts
337
- # type: embedded
338
- # form_name: dc_part
339
- # html:
340
- # height: 1000
341
- ###########################################################################
342
- class Embedded < DrgcmsField
343
- ###########################################################################
344
- # Render embedded field html code
345
- ###########################################################################
346
- def render
347
- return self if @record.new_record? # would be in error otherwise
348
- # HTML defaults. Some must be set
349
- @yaml['html'] ||= {}
350
- @yaml['html']['height'] ||= 300
351
- @yaml['html']['width'] ||= '99%'
352
- # defaults both way
353
- @yaml['table'] ||= @yaml['form_name'] if @yaml['form_name']
354
- @yaml['form_name'] ||= @yaml['table'] if @yaml['table']
355
- #
356
- html = ''
357
- @yaml['html'].each {|k,v| html << "#{k}=\"#{v}\" "}
358
- #
359
- if @yaml['name'] == @yaml['table']
360
- tables = @yaml['table']
361
- ids = @record._id
362
- else
363
- tables = @parent.tables.inject('') { |r,v| r << "#{v[1]};" } + @yaml['table']
364
- ids = @parent.ids.inject('') { |r,v| r << "#{v};" } + @record._id
365
- end
366
- opts = { controller: 'cmsedit', action: 'index', ids: ids, table: tables, form_name: @yaml['form_name'],
367
- field_name: @yaml['name'], iframe: "if_#{@yaml['name']}", readonly: @readonly }
368
- @html << "<iframe class='iframe_embedded' id='if_#{@yaml['name']}' name='if_#{@yaml['name']}' #{html}></iframe>"
369
- @js = <<EOJS
370
- $(document).ready( function() {
371
- $('#if_#{@yaml['name']}').attr('src', '#{@parent.url_for(opts)}');
372
- });
373
- EOJS
374
- self
375
- end
376
-
377
- end
378
-
379
- ###########################################################################
380
- # Implementation of journal_diff DRG CMS form field. journal_diff field is used to
381
- # show differences between two fields in DcJournal collection.
382
- #
383
- # ===Form options:
384
- # * +name:+ field name (required)
385
- # * +type:+ journal_diff (required)
386
- #
387
- # Form example:
388
- # 10:
389
- # name: diff
390
- # type: journal_diff
391
- # html:
392
- # size: 100x25
393
- ###########################################################################
394
- class JournalDiff < DrgcmsField
395
- ###########################################################################
396
- # Render journal_diff field html code
397
- ###########################################################################
398
- def render
399
- @yaml['name'] = 'old' if @record[@yaml['name']].nil?
400
- @html << '<div class="dc-journal">'
401
- JSON.parse(@record[@yaml['name']]).each do |k,v|
402
- old_value = v.class == Array ? v[0] : v
403
- new_value = v.class == Array ? v[1] : v
404
- @html << "<div style='background-color: #eee;'>#{@parent.check_box('select', k)} #{k}</div>
405
- <div style='background-color: #fcc;'>-<br>#{old_value}</div>
406
- <div style='background-color: #cfc;'>+<br>#{new_value}</div><br>"
407
- end
408
- @html << '</div>'
409
- self
410
- end
411
- end
412
-
413
- ###########################################################################
414
- # Implementation of multitext_autocomplete DRG CMS form field.
415
- #
416
- # multitext_autocomplete field is complex data entry field which uses autocomplete
417
- # function when selecting multiple values for MongoDB Array field. Array typically holds
418
- # id's of selected documents and control typically displays value of the field name
419
- # defined by search options.
420
- #
421
- # ===Form options:
422
- # * +name:+ field name (required)
423
- # * +type:+ multitext_autocomplete (required)
424
- # * +table+ Collection (table) name. When defined search must contain field name
425
- # * +search:+ Search may consist of three parameters from which are separated either by dot (.) or comma(,)
426
- # * search_field_name; when table option is defined search must define field name which will be used for search query
427
- # * collection_name.search_field_name; Same as above except that table options must be ommited.
428
- # * collection_name.search_field_name.method_name; When searching is more complex custom search
429
- # method may be defined in CollectionName model which will provide result set for search.
430
- #
431
- # Form example:
432
- # 90:
433
- # name: kats
434
- # type: multitext_autocomplete
435
- # search: dc_category.name
436
- # html:
437
- # size: 30
438
- ###########################################################################
439
- class MultitextAutocomplete < DrgcmsField
440
-
441
- ###########################################################################
442
- # Returns value for readonly field
443
- ###########################################################################
444
- def ro_standard(table, search)
445
- result = ''
446
- table = table.classify.constantize
447
- return self if @record[@yaml['name']].nil?
448
- # when field name and method are defined together
449
- search = search.split('.').first if search.match('.')
450
- @record[@yaml['name']].each do |element|
451
- result << table.find(element)[search] + '<br>'
452
- end
453
- super(result)
454
- end
455
-
456
- ###########################################################################
457
- # Render multitext_autocomplete field html code
458
- ###########################################################################
459
- def render
460
- # search field name
461
- if @yaml['search'].class == Hash
462
- table = @yaml['search']['table']
463
- field_name = @yaml['search']['field']
464
- method = @yaml['search']['method']
465
- search = method.nil? ? field_name : "#{field_name}.#{method}"
466
- elsif @yaml['search'].to_s.match(/\./)
467
- table, field_name, method = @yaml['search'].split(/\.|\,/)
468
- search = method.nil? ? field_name : "#{field_name}.#{method}"
469
- else # search and table name are separated
470
- search = field_name = @yaml['search']
471
- end
472
- # determine table name
473
- if @yaml['table']
474
- table = if @yaml['table'].class == String
475
- @yaml['table']
476
- # eval(how_to_get_my_table_name)
477
- elsif @yaml['table']['eval']
478
- eval @yaml['table']['eval']
479
- else
480
- p "Field #{@yaml['name']}: Invalid table parameter!"
481
- nil
482
- end
483
- end
484
- unless (table and search)
485
- @html << 'Table or search field not defined!'
486
- return self
487
- end
488
- #
489
- return ro_standard(table, search) if @readonly
490
- # TODO check if table exists
491
- collection = table.classify.constantize
492
- unless @record.respond_to?(@yaml['name'])
493
- @html << "Invalid field name: #{@yaml['name']}"
494
- return self
495
- end
496
- # put field to enter search data on form
497
- @yaml['html'] ||= {}
498
- @yaml['html']['value'] = '' # must be. Otherwise it will look into record and return error
499
- @yaml['html']['placeholder'] = t('drgcms.search_placeholder')
500
- _name = '_' + @yaml['name']
501
- @html << '<div class="ui-autocomplete-border">'
502
- @html << @parent.link_to(@parent.fa_icon('plus-square lg', class: 'dc-animate dc-green'), '#',onclick: 'return false;') # dummy add. But it is usefull.
503
-
504
- record = record_text_for(@yaml['name'])
505
- @html << ' ' << @parent.text_field(record, _name, @yaml['html']) # text field for autocomplete
506
- @html << "<div id =\"#{record}#{@yaml['name']}\">" # div to list active records
507
- # find value for each field inside categories
508
- unless @record[@yaml['name']].nil?
509
- @record[@yaml['name']].each do |element|
510
- # this is quick and dirty trick. We have model dc_big_table which can be used for retrive
511
- # more complicated options
512
- # TODO retrieve choices from big_table
513
- rec = if table == 'dc_big_table'
514
- collection.find(@yaml['name'], @parent.session)
515
- else
516
- collection.find(element)
517
- end
518
- # Related data is missing. It happends.
519
- @html << if rec
520
- link = @parent.link_to(@parent.fa_icon('remove lg', class: 'dc-animate dc-red'), '#',
521
- onclick: "$('##{rec.id}').hide(); var v = $('##{record}_#{@yaml['name']}_#{rec.id}'); v.val(\"-\" + v.val());return false;")
522
- field = @parent.hidden_field(record, "#{@yaml['name']}_#{rec.id}", value: element)
523
- "<div id=\"#{rec.id}\" style=\"padding:4px;\">#{link} #{rec.send(field_name)}<br>#{field}</div>"
524
- else
525
- '** error **'
526
- end
527
- end
528
- end
529
- @html << "</div></div>"
530
- # Create text for div to be added when new category is selected
531
- link = @parent.link_to(@parent.fa_icon('remove lg', class: 'dc-animate dc-red'), '#',
532
- onclick: "$('#rec_id').hide(); var v = $('##{record}_#{@yaml['name']}_rec_id'); v.val(\"-\" + v.val());return false;")
533
- field = @parent.hidden_field(record, "#{@yaml['name']}_rec_id", value: 'rec_id')
534
- one_div = "<div id=\"rec_id\" style=\"padding:4px;\">#{link} rec_search<br>#{field}</div>"
535
-
536
- # JS stuff
537
- @js << <<EOJS
538
- $(document).ready(function() {
539
- $("##{record}_#{_name}").autocomplete( {
540
- source: function(request, response) {
541
- $.ajax({
542
- url: "#{ @parent.url_for( controller: 'dc_common', action: 'autocomplete' )}",
543
- type: "POST",
544
- dataType: "json",
545
- data: { input: request.term, table: "#{table}", search: "#{search}" #{(',id: "'+@yaml['id'] + '"') if @yaml['id']} },
546
- success: function(data) {
547
- response( $.map( data, function(key) {
548
- return key;
549
- }));
550
- }
551
- });
552
- },
553
- change: function (event, ui) {
554
- var div = '#{one_div}';
555
- div = div.replace(/rec_id/g, ui.item.id)
556
- div = div.replace('rec_search', ui.item.value)
557
- $("##{record}#{@yaml['name']}").append(div);
558
- $("##{record}_#{_name}").val('');
559
- $("##{record}_#{_name}").focus();
560
- },
561
- minLength: 2
562
- });
563
- });
564
- EOJS
565
-
566
- self
567
- end
568
-
569
- ###########################################################################
570
- # Class method for retrieving data from multitext_autocomplete form field.
571
- ###########################################################################
572
- def self.get_data(params, name)
573
- r = []
574
- params['record'].each do |k,v|
575
- # if it starts with - then it was removed
576
- r << BSON::ObjectId.from_string(v) if k.match("#{name}_") and v[0,1] != '-'
577
- end
578
- r.uniq!
579
- r
580
- end
581
-
582
- end
583
-
584
- ###########################################################################
585
- # Implementation of select DRG CMS form field.
586
- #
587
- # ===Form options:
588
- # * +name:+ field name (required)
589
- # * +type:+ select (required)
590
- # * +choices:+ Values for choices separated by comma. Values can also be specified like description:value.
591
- # In the example description will be shown to user, but value will be saved to document.
592
- # choices: 'OK:0,Ready:1,Error:2'
593
- # choices: Ruby,Pyton,PHP
594
- # * +eval:+ Choices will be provided by evaluating expression
595
- # * eval: dc_choices4('model_name','description_field_name','_id'); dc_choices4 helper will provide data for select field.
596
- # * eval: ModelName.choices4_field; ModelName class will define method choices4_field which
597
- # will provide data for select field.
598
- # * collection_name.search_field_name.method_name; When searching is more complex custom search
599
- # method may be defined in CollectionName model which will provide result set for search.
600
- # * If choices or eval is not defined choices will be provided from translation helpers. For example:
601
- # Collection has field status choices for field may be provided by en.helpers.model_name.choices4_status
602
- # entry of english translation. English is of course default translation. If you provide translations in
603
- # your local language then select choices will be localized.
604
- # en.helpers.model_name.choices4_status: 'OK:0,Ready:1,Error:2'
605
- # sl.helpers.model_name.choices4_status: 'V redu:0,Pripravljen:1,Napaka:2'
606
- # * +html:+ html options which apply to select field (optional)
607
- #
608
- # Form example:
609
- # 30:
610
- # name: type
611
- # type: select
612
- # 40:
613
- # name: parent
614
- # type: select
615
- # eval: DcCategory.values_for_parent
616
- # html:
617
- # include_blank: true
618
- ###########################################################################
619
- class Select < DrgcmsField
620
-
621
- ###########################################################################
622
- # Return values, when choices options will be returned by evaluating expression
623
- ###########################################################################
624
- def do_eval(e)
625
- e.strip!
626
- method = e.split(/\ |\(/).first
627
- return eval(e) if respond_to?(method) # id method defined here
628
- return eval('@parent.'+e) if @parent.respond_to?(method) # is method defined in helpers
629
- # eval whatever it is
630
- eval e
631
- end
632
-
633
- ###########################################################################
634
- # Create choices array for select field.
635
- ###########################################################################
636
- def get_choices
637
- begin
638
- choices = case
639
- when @yaml['choices'] then
640
- (@yaml['choices'].match('helpers.') ) ? t(@yaml['choices']) : @yaml['choices']
641
- when @yaml['eval'] then
642
- do_eval(@yaml['eval'])
643
- else
644
- c = t('helpers.label.' + @form['table'] + '.choices4_' + @yaml['name'] )
645
- c = 'Error' if c.match( 'translation missing' )
646
- c
647
- end
648
- # Convert string to Array
649
- choices.class == String ?
650
- choices.chomp.split(',').inject([]) {|r,v| r << (v.match(':') ? v.split(':') : v )} :
651
- choices
652
- rescue Exception => e
653
- Rails.logger.debug "Error in select eval. #{e.message}\n"
654
- ['error'] # return empty array when error occures
655
- end
656
- end
657
-
658
- ###########################################################################
659
- # Return value when readonly is required
660
- ###########################################################################
661
- def ro_standard
662
- value = @record.respond_to?(@yaml['name']) ? @record[@yaml['name']] : nil
663
- return self if value.nil?
664
- #
665
- choices = get_choices()
666
- if value.class == Array # multiple choices
667
- html = ''
668
- value.each do |element|
669
- choices.each do |choice|
670
- if choice.to_s == element.to_s
671
- html << '<br>' if html.size > 0
672
- html << "#{element.to_s}"
673
- end
674
- end
675
- end
676
- return super(html)
677
- else
678
- choices.each do |choice|
679
- if choice.class == Array
680
- return super(choice.first) if choice.last.to_s == value.to_s
681
- else
682
- return super(choice) if choice.to_s == value.to_s
683
- end
684
- end
685
- end
686
- super('')
687
- end
688
-
689
- ###########################################################################
690
- # Render select field html code
691
- ###########################################################################
692
- def render
693
- return ro_standard if @readonly
694
- set_initial_value('html','selected')
695
- #
696
- @yaml['html'].symbolize_keys!
697
- record = record_text_for(@yaml['name'])
698
- if @yaml['multiple']
699
- @html << @parent.select(record, @yaml['name'], get_choices, @yaml['html'], {multiple: true})
700
- @js << "$('##{record}_#{@yaml['name']}').selectMultiple();"
701
- else
702
- @html << @parent.select(record, @yaml['name'], get_choices, @yaml['html'])
703
- end
704
- self
705
- end
706
-
707
- ###########################################################################
708
- # Return value.
709
- ###########################################################################
710
- def self.get_data(params, name)
711
- if params['record'][name].class == Array
712
- params['record'][name].delete_if {|e| e.blank? }
713
- return nil if params['record'][name].size == 0
714
- # convert to BSON objects
715
- is_id = BSON::ObjectId.legal?(params['record'][name].first)
716
- return params['record'][name].map{ |e| BSON::ObjectId.from_string(e) } if is_id
717
- return params['record'][name]
718
- end
719
- params['record'][name]
720
- end
721
-
722
- end
723
-
724
- ###########################################################################
725
- # Implementation of check_box DRG CMS form field.
726
- #
727
- # ===Form options:
728
- # * +name:+ field name (required)
729
- # * +type:+ check_box (required)
730
- # * +choices:+ Values check_box separated by comma (1,0) (yes,no)
731
- # * +checked_value:+ 1 or yes or approved
732
- # * +unchecked_value:+ 0 or no or not approved
733
- # * +html:+ html options which apply to check_box field (optional)
734
- #
735
- # Form example:
736
- # 30:
737
- # name: active
738
- # type: check_box
739
- # 40:
740
- # name: status
741
- # type: check_box
742
- # choices: yes,no
743
- ###########################################################################
744
- class CheckBox < DrgcmsField
745
-
746
- ###########################################################################
747
- # Render check_box field html code
748
- ###########################################################################
749
- def render
750
- set_initial_value('html','default')
751
- # checked flag must be set
752
- @yaml['html']['checked'] = !@parent.dc_dont?(@yaml['html']['default']) if @yaml['html']['default']
753
- # disable it if readonly
754
- @yaml['html']['disabled'] = @readonly ? true : nil
755
- # If choices are present split them to set checked and unchecked value
756
- @yaml['checked_value'], @yaml['unchecked_value'] = @yaml['choices'].split(',') if @yaml['choices']
757
- @yaml['html'].symbolize_keys!
758
- record = record_text_for(@yaml['name'])
759
- @html << if @yaml['checked_value']
760
- @parent.check_box(record, @yaml['name'], @yaml['html'], @yaml['checked_value'], @yaml['unchecked_value'] || '0')
761
- else
762
- @parent.check_box(record, @yaml['name'], @yaml['html'])
763
- end
764
- self
765
- end
766
- end
767
-
768
- ###########################################################################
769
- # Implementation of comment DRG CMS form field. Comments may also be written
770
- # on the place of form field.
771
- #
772
- # ===Form options:
773
- # * +text:+ any text. Text will be translated if key is found in translations. (required)
774
- # * +type:+ comment (required)
775
- #
776
- # Form example:
777
- # 30:
778
- # name: active
779
- # type: check_box
780
-
781
- ###########################################################################
782
- class Comment < DrgcmsField
783
-
784
- ###########################################################################
785
- # Render comment field html code
786
- ###########################################################################
787
- def render
788
- @html << t(@yaml['comment'], @yaml['comment'])
789
- self
790
- end
791
- end
792
-
793
- ###########################################################################
794
- # Implementation of link_to DRG CMS form field. link_to form field is mostly used by polls but can
795
- # be also incorporated anywhere on the form.
796
- #
797
- # ===Form options:
798
- # * +type:+ link_to (required)
799
- # * +caption:+ Link caption
800
- # * +icon:+ Link icon
801
- # * +url:+ direct url link
802
- # * +controller:+ controller name
803
- # * +action:+ action name
804
- # * +html:+ html options which apply to link_to (optional)
805
- #
806
- # Form example:
807
- # 30:
808
- # type: link_to
809
- # caption: Some action
810
- # icon: cogs
811
- # controller: my_controller
812
- # action: my_action
813
- # id: id # will be replaced by record._id
814
- ###########################################################################
815
- class LinkTo < DrgcmsField
816
-
817
- ###########################################################################
818
- # Render link_to field html code
819
- ###########################################################################
820
- def render
821
- @yaml['html'] ||= {}
822
- @yaml['html']['class'] ||= 'dc-link dc-animate'
823
- @yaml['html'].symbolize_keys!
824
- #
825
- @yaml[:id] = record._id if @yaml[:id] == 'id'
826
- url = @yaml['url'] || "#{@yaml[:controller]}/#{@yaml[:action]}/#{@yaml[:id]}"
827
- url.gsub!('//','/') # no action and id
828
- url = '/' + @yaml['url'] unless url[0,1] == '/' # no leading /
829
- url.chop if url[0,-1] == '/' # remove trailing /
830
- #
831
- caption = @yaml['caption'] || @yaml['text']
832
- @html << @parent.dc_link_to(caption, @yaml['icon'], url, @yaml['html'])
833
- self
834
- end
835
- end
836
-
837
- ###########################################################################
838
- # Create submit_tag form field. submit_tag form field is mostly used by polls but can
839
- # be also incorporated in the middle of form.
840
- #
841
- # ===Form options:
842
- # * +type:+ submit_tag (required)
843
- # * +caption:+ Submit field caption
844
- # * +icon:+ Icon
845
- # * +html:+ html options which apply to link_to (optional)
846
- #
847
- # Form example:
848
- # 40:
849
- # type: submit_tag
850
- # caption: translate.this
851
- # icon: check
852
- ###########################################################################
853
- class SubmitTag < DrgcmsField
854
-
855
- ###########################################################################
856
- # Render submit_tag field html code
857
- ###########################################################################
858
- def render
859
- @yaml['html'] ||= {}
860
- @yaml['html']['class'] ||= 'dc-submit'
861
- @yaml['html'].symbolize_keys!
862
- text = @yaml['caption'] || @yaml['text']
863
- text = t(@yaml['text']) if text.match(/\./)
864
-
865
- @html << @parent.submit_tag(text, @yaml['html'])
866
- self
867
- end
868
- end
869
-
870
- ###########################################################################
871
- # Implementation of password DRG CMS form field.
872
- #
873
- # ===Form options:
874
- # * +type:+ password_field (required)
875
- # * +name:+ Field name (required)
876
- # * +html:+ html options which apply to password field (optional)
877
- #
878
- # Form example:
879
- # 20:
880
- # name: password
881
- # type: pasword_field
882
- # html:
883
- # size: 20
884
- #
885
- # 30:
886
- # name: password_confirmation
887
- # type: pasword_field
888
- # html:
889
- # size: 20
890
- #
891
- ###########################################################################
892
- class PasswordField < DrgcmsField
893
-
894
- ###########################################################################
895
- # Render password field html code
896
- #
897
- ###########################################################################
898
- def render
899
- return self if @readonly
900
- @yaml['html'] ||= {}
901
- record = record_text_for(@yaml['name'])
902
- @html << @parent.password_field(record, @yaml['name'], @yaml['html'])
903
- self
904
- end
905
- end
906
-
907
- ###########################################################################
908
- # Implementation of date_select DRG CMS form field.
909
- #
910
- # ===Form options:
911
- # * +type:+ date_select (required)
912
- # * +name:+ Field name (required)
913
- # * +options:+ options which apply to date_select field (optional)
914
- # * +html:+ html options which apply to password field (optional)
915
- #
916
- # Form example:
917
- # 50:
918
- # name: valid_from
919
- # type: date_select
920
- # options:
921
- # include_blank: true
922
- # html:
923
- # class: my-date-class
924
- ###########################################################################
925
- class DateSelect < DrgcmsField
926
-
927
- ###########################################################################
928
- # Render date_select field html code
929
- ###########################################################################
930
- def render
931
- return ro_standard( @parent.dc_format_value(@record[@yaml['name']])) if @readonly
932
- #
933
- @yaml['options'] ||= {}
934
- set_initial_value('options','default')
935
- @yaml['options'].symbolize_keys!
936
- @yaml['html'].symbolize_keys!
937
- record = record_text_for(@yaml['name'])
938
- @html << @parent.date_select(record, @yaml['name'], @yaml['options'], @yaml['html'])
939
- self
940
- end
941
-
942
- ###########################################################################
943
- # DatetimeSelect get_data method.
944
- ###########################################################################
945
- def self.get_data(params, name)
946
- DatetimeSelect.get_data(params, name).to_date rescue nil
947
- end
948
-
949
-
950
- end
951
-
952
- ###########################################################################
953
- # Create datetime_select form field
954
- #
955
- # ===Form options:
956
- # * +type:+ datetime_select (required)
957
- # * +name:+ Field name (required)
958
- # * +options:+ options which apply to date_select field (optional)
959
- # * +html:+ html options which apply to password field (optional)
960
- #
961
- # Form example:
962
- # 60:
963
- # name: end_time
964
- # type: datetime_select
965
- # options:
966
- # include_blank: true
967
- ###########################################################################
968
- class DatetimeSelect < DrgcmsField
969
-
970
- ###########################################################################
971
- # Render datetime_select field html code
972
- ###########################################################################
973
- def render
974
- return ro_standard( @parent.dc_format_value(@record[@yaml['name']])) if @readonly
975
- #
976
- @yaml['options'] ||= {}
977
- set_initial_value('options','default')
978
- @yaml['options'].symbolize_keys!
979
- @yaml['html'].symbolize_keys!
980
- #
981
- record = record_text_for(@yaml['name'])
982
- @html << @parent.datetime_select(record, @yaml['name'], @yaml['options'], @yaml['html'])
983
- self
984
- end
985
-
986
- ####################################################################
987
- # DatetimeSelect get_data method.
988
- ####################################################################
989
- def self.get_data(params, name)
990
- begin
991
- attrs = (1..5).map { |i| params['record']["#{name}(#{i}i)"]}
992
- Time.zone.local(*attrs)
993
- rescue
994
- nil
995
- end
996
- end
997
-
998
- end
999
-
1000
- ###########################################################################
1001
- # Implementation of date_picker DRG CMS form field with help of jQuery DateTimePicker plugin.
1002
- #
1003
- # Since javascript date(time) format differs from ruby date(time) format localization
1004
- # must be provided in order for date_picker object works as expected. For example:
1005
- #
1006
- # en:
1007
- # datetimepicker:
1008
- # formats:
1009
- # date: 'Y/m/d'
1010
- # datetime: 'Y/m/d H:i'
1011
- #
1012
- # sl:
1013
- # datetimepicker:
1014
- # formats:
1015
- # date: 'd.m.Y'
1016
- # datetime: 'd.m.Y H:i'
1017
- #
1018
- # ===Form options:
1019
- # * +type:+ date_picker (required)
1020
- # * +name:+ Field name (required)
1021
- # * +options:+ options which apply to date_picker field. All options can be found here http://xdsoft.net/jqplugins/datetimepicker/ .
1022
- # Options can be defined in single line like:
1023
- # * options: 'inline: true,lang: "sl"' or
1024
- #
1025
- # * options:
1026
- # * inline: true
1027
- # * lang: '"sl"'
1028
- #
1029
- # * +html:+ html options which apply to date_picker field (optional)
1030
- #
1031
- # Form example:
1032
- # 10:
1033
- # name: created
1034
- # type: date_picker
1035
- # options: 'inline: true,lang: "sl"'
1036
- ###########################################################################
1037
- class DatePicker < DrgcmsField
1038
-
1039
- ###########################################################################
1040
- # Render date_picker field html code
1041
- ###########################################################################
1042
- def render
1043
- value = (@record and @record[@yaml['name']]) ? I18n.localize(@record[@yaml['name']].to_date) : nil
1044
- return ro_standard( @parent.dc_format_value(value)) if @readonly
1045
- #
1046
- @yaml['options'] ||= {}
1047
- set_initial_value
1048
- @yaml['html']['size'] ||= 10
1049
- @yaml['html']['value'] = value
1050
- #
1051
- @yaml['options']['lang'] ||= "'#{I18n.locale}'"
1052
- @yaml['options']['format'] ||= "'#{t('datetimepicker.formats.date')}'"
1053
- @yaml['options']['timepicker'] = false
1054
- #
1055
- record = record_text_for(@yaml['name'])
1056
- @html << @parent.text_field(record, @yaml['name'], @yaml['html'])
1057
- @js << <<EOJS
1058
- $(document).ready(function() {
1059
- $("##{record}_#{@yaml['name']}").datetimepicker( {
1060
- #{hash_to_options(@yaml['options'])}
1061
- });
1062
- });
1063
- EOJS
1064
-
1065
- self
1066
- end
1067
-
1068
- ###########################################################################
1069
- # DatePicker get_data method.
1070
- ###########################################################################
1071
- def self.get_data(params, name)
1072
- t = params['record'][name] ? params['record'][name].to_datetime : nil
1073
- t ? Time.zone.local(t.year, t.month, t.day) : nil
1074
- end
1075
-
1076
- end
1077
- ###########################################################################
1078
- # Implementation of date_time_picker DRG CMS form field with help of jQuery DateTimePicker plugin
1079
- #
1080
- # ===Form options:
1081
- # * +type:+ datetime_picker (required)
1082
- # * +name:+ Field name (required)
1083
- # * +options:+ options which apply to date_picker field. All options can be found here http://xdsoft.net/jqplugins/datetimepicker/ .
1084
- # Options can be defined in single line like:
1085
- # * options: 'step: 15,inline: true,lang: "sl"' or
1086
- #
1087
- # * options:
1088
- # * step: 15
1089
- # * inline: true
1090
- # * lang: '"sl"'
1091
- #
1092
- # * +html:+ html options which apply to date_time_picker field (optional)
1093
- #
1094
- # Form example:
1095
- # 10:
1096
- # name: valid_to
1097
- # type: datetime_picker
1098
- # options: 'step: 60'
1099
- ###########################################################################
1100
- class DatetimePicker < DrgcmsField
1101
-
1102
- ###########################################################################
1103
- # Render date_time_picker field html code
1104
- ###########################################################################
1105
- def render
1106
- value = (@record and @record[@yaml['name']]) ? I18n.localize(@record[@yaml['name']].localtime) : nil
1107
- return ro_standard( @parent.dc_format_value(value)) if @readonly
1108
- #
1109
- @yaml['options'] ||= {}
1110
- set_initial_value
1111
- @yaml['html']['size'] ||= 14
1112
- @yaml['html']['value'] = value if @record[@yaml['name']]
1113
- #
1114
- @yaml['options']['lang'] ||= "'#{I18n.locale}'"
1115
- @yaml['options']['format'] ||= "'#{t('datetimepicker.formats.datetime')}'"
1116
- #
1117
- record = record_text_for(@yaml['name'])
1118
- @html << @parent.text_field(record, @yaml['name'], @yaml['html'])
1119
- @js << <<EOJS
1120
- $(document).ready(function() {
1121
- $("##{record}_#{@yaml['name']}").datetimepicker( {
1122
- #{hash_to_options(@yaml['options'])}
1123
- });
1124
- });
1125
- EOJS
1126
-
1127
- self
1128
- end
1129
-
1130
- ###########################################################################
1131
- # DateTimePicker get_data method.
1132
- ###########################################################################
1133
- def self.get_data(params, name)
1134
- t = params['record'][name] ? params['record'][name].to_datetime : nil
1135
- t ? Time.zone.local(t.year, t.month, t.day, t.hour, t.min) : nil
1136
- end
1137
-
1138
- end
1139
-
1140
- ###########################################################################
1141
- # Implementation of text_autocomplete DRG CMS form field.
1142
- #
1143
- # ===Form options:
1144
- # * +name:+ field name (required)
1145
- # * +type:+ text_autocomplete (required)
1146
- # * +table+ Collection (table) name. When defined search must contain field name
1147
- # * +search:+ Search may consist of three parameters from which are separated either by dot (.)
1148
- # * search_field_name; when table option is defined search must define field name which will be used for search query
1149
- # * collection_name.search_field_name; Same as above except that table options must be ommited.
1150
- # * collection_name.search_field_name.method_name; When searching is more complex custom search
1151
- # method may be defined in CollectionName model which will provide result set for search.
1152
- #
1153
- # Form example:
1154
- # 10:
1155
- # name: user_id
1156
- # type: text_autocomplete
1157
- # search: dc_user.name
1158
- # html:
1159
- # size: 30
1160
- ###########################################################################
1161
- class TextAutocomplete < DrgcmsField
1162
-
1163
- ###########################################################################
1164
- # Render text_autocomplete field html code
1165
- ###########################################################################
1166
- def render
1167
- # Return descriptive text and put it into input field
1168
- # search field name
1169
- if @yaml['search'].class == Hash
1170
- table = @yaml['search']['table']
1171
- ret_name = @yaml['search']['field']
1172
- method = @yaml['search']['method']
1173
- elsif @yaml['search'].match(/\./)
1174
- table, ret_name, method = @yaml['search'].split('.')
1175
- else
1176
- ret_name = @yaml['search']
1177
- end
1178
- # determine table name
1179
- if @yaml['table']
1180
- table = if @yaml['table'].class == String
1181
- @yaml['table']
1182
- # eval(how_to_get_my_table_name)
1183
- elsif @yaml['table']['eval']
1184
- eval @yaml['table']['eval']
1185
- else
1186
- p "Field #{@yaml['name']}: Invalid table parameter!"
1187
- nil
1188
- end
1189
- end
1190
- return 'Table or field keyword not defined!' unless (table and ret_name)
1191
- # TODO check if table exists
1192
- t = table.classify.constantize
1193
- # find record and return value of field
1194
- value_send_as = 'p_' + @yaml['name']
1195
- value = if @parent.params[value_send_as]
1196
- @parent.params[value_send_as]
1197
- elsif @record and @record[@yaml['name']]
1198
- @record[@yaml['name']]
1199
- end
1200
- # Found value to be written in field. If field is not found write out value.
1201
- if value
1202
- record = t.find(value)
1203
- value_displayed = record ? record.send(ret_name) : value
1204
- end
1205
- # return if readonly
1206
- return ro_standard(value_displayed) if @readonly
1207
- # Add method back, so autocomplete will know that it must search for method inside class
1208
- ret_name = "#{ret_name}.#{method}" if method
1209
- @yaml['html'] ||= {}
1210
- @yaml['html']['value'] = value_displayed
1211
- @yaml['html']['placeholder'] ||= t('drgcms.search_placeholder') || nil
1212
- #
1213
- _name = '_' + @yaml['name']
1214
- record = record_text_for(@yaml['name'])
1215
- @html << @parent.text_field(record, _name, @yaml['html'])
1216
- if @yaml['with_new']
1217
- @html << ' ' +
1218
- @parent.fa_icon('plus-square lg', class: 'in-edit-add', title: t('drgcms.new'),
1219
- style: "vertical-align: top;", 'data-table' => @yaml['with_new'] )
1220
- end
1221
- @html << @parent.hidden_field(record, @yaml['name'], value: value) # actual value will be in hidden field
1222
- # JS stuff
1223
- @js << <<EOJS
1224
- $(document).ready(function() {
1225
- $("##{record}_#{_name}").autocomplete( {
1226
- source: function(request, response) {
1227
- $.ajax({
1228
- url: '/dc_common/autocomplete',
1229
- type: "POST",
1230
- dataType: "json",
1231
- data: { input: request.term, table: "#{table}", search: "#{ret_name}" #{(',id: "'+@yaml['id'] + '"') if @yaml['id']} },
1232
- success: function(data) {
1233
- response( $.map( data, function(key) {
1234
- return key;
1235
- }));
1236
- }
1237
- });
1238
- },
1239
- change: function (event, ui) {
1240
- $("##{record}_#{@yaml['name']}").val(ui.item.id);
1241
- },
1242
- minLength: 2
1243
- });
1244
- });
1245
- EOJS
1246
-
1247
- self
1248
- end
1249
-
1250
- ###########################################################################
1251
- # Return value. Return nil if input field is empty
1252
- ###########################################################################
1253
- def self.get_data(params, name)
1254
- params['record']["_#{name}"].blank? ? nil : params['record'][name]
1255
- end
1256
- end
1257
-
1258
- ###########################################################################
1259
- # Implementation of text_area DRG CMS form field.
1260
- #
1261
- # ===Form options:
1262
- # * +type:+ text_area (required)
1263
- # * +name:+ Field name (required)
1264
- # * +html:+ html options which apply to text_area field (optional)
1265
- #
1266
- # Form example:
1267
- # 10:
1268
- # name: css
1269
- # type: text_area
1270
- # html:
1271
- # size: 100x30
1272
- ###########################################################################
1273
- class TextArea < DrgcmsField
1274
-
1275
- ###########################################################################
1276
- # Return value for readonly field
1277
- ###########################################################################
1278
- def ro_standard
1279
- value = @record[@yaml['name']]
1280
- @html << "<div class='dc-readonly'>#{value.gsub("\n",'<br>')}</div>" unless value.blank?
1281
- self
27
+ Dir[File.join(__dir__, "drgcms_form_fields/*.rb")].each do |file|
28
+ require file
1282
29
  end
1283
-
1284
- ###########################################################################
1285
- # Render text_area field html code
1286
- ###########################################################################
1287
- def render
1288
- return ro_standard if @readonly
1289
- set_initial_value
1290
- #
1291
- # @yaml['html'] ||= {}
1292
- # value_send_as = 'p_' + @yaml['name']
1293
- # @yaml['html']['value'] = @parent.params[value_send_as] if @parent.params[value_send_as]
1294
-
1295
- record = record_text_for(@yaml['name'])
1296
- @html << @parent.text_area(record, @yaml['name'], @yaml['html'])
1297
- self
1298
- end
1299
- end
1300
-
1301
- ###########################################################################
1302
- # Implementation of text_field DRG CMS form field.
1303
- #
1304
- # ===Form options:
1305
- # * +type:+ text_field (required)
1306
- # * +name:+ Field name (required)
1307
- # * +html:+ html options which apply to text_field field (optional)
1308
- #
1309
- # Form example:
1310
- # 10:
1311
- # name: title
1312
- # type: text_field
1313
- # size: 30
1314
- # html:
1315
- # required: yes
1316
- ###########################################################################
1317
- class TextField < DrgcmsField
1318
-
1319
- ###########################################################################
1320
- # Render text_field field html code
1321
- ###########################################################################
1322
- def render
1323
- return ro_standard if @readonly
1324
- set_initial_value
1325
- #
1326
- record = record_text_for(@yaml['name'])
1327
- @html << @parent.text_field( record, @yaml['name'], @yaml['html'])
1328
- self
1329
- end
1330
- end
1331
-
1332
- ###########################################################################
1333
- # Implementation of number_field DRG CMS form field. Number fields can be
1334
- # formated for display with thousands delimiters and decimal separators and
1335
- # can have currency symbol.
1336
- #
1337
- # ===Form options:
1338
- # * +type:+ number_field (required)
1339
- # * +name:+ Field name (required)
1340
- # * +format:+ Format options
1341
- # * +decimals:+ No of decimal places
1342
- # * +separator:+ decimal separator (yes no , .) Default yes if decimals > 0
1343
- # * +delimiter:+ Thousands delimiter (yes no , .) Default defind by locals
1344
- # * +currency:+ Currency sign (yes no sign) Default no. If yes defined by locals
1345
- # * +html:+ html options which apply to text_field field (optional)
1346
- #
1347
- # Form example:
1348
- # 10:
1349
- # name: title
1350
- # type: number_field
1351
- # size: 10
1352
- # format:
1353
- # decimals: 2
1354
- # delimiter: false
1355
- ###########################################################################
1356
- class NumberField < DrgcmsField
1357
-
1358
- ###########################################################################
1359
- # Render text_field field html code
1360
- ###########################################################################
1361
- def render
1362
- return ro_standard if @readonly
1363
- set_initial_value
1364
- #
1365
- record = record_text_for(@yaml['name'])
1366
- @yaml['html'] ||= {}
1367
- @yaml['html']['class'] = 'dc-number'
1368
- @yaml['html']['data-decimal'] = @yaml.dig('format','decimal') || 2
1369
- @yaml['html']['data-delimiter'] = @yaml.dig('format','delimiter') || I18n.t('number.currency.format.delimiter')
1370
- @yaml['html']['data-separator'] = @yaml.dig('format','separator') || I18n.t('number.currency.format.separator')
1371
- # @yaml['html']['data-currency'] = @yaml.dig('format','currency') == 'yes' ? I18n.t('number.currency.format.currency') : @yaml.dig('format','currency')
1372
- value = @record[@yaml['name']] || 0
1373
-
1374
- @html << @parent.hidden_field( record, @yaml['name'], value: value )
1375
-
1376
- @yaml['html']['value'] = @parent.dc_format_number(value, @yaml['html']['data-decimal'], @yaml['html']['data-separator'], @yaml['html']['data-delimiter'] )
1377
- @html << @parent.text_field( nil,"record_#{@yaml['name']}1", @yaml['html'])
1378
- self
1379
- end
1380
-
1381
- ###########################################################################
1382
- # Return value. Return nil if input field is empty
1383
- ###########################################################################
1384
- def self.get_data(params, name)
1385
- return 0 if params['record'][name].blank?
1386
- params['record'][name].match('.') ? BigDecimal.new(params['record'][name]) : Integer.new(params['record'][name])
1387
- end
1388
- end
1389
-
1390
- ###########################################################################
1391
- # Implementation of text_with_select DRG CMS form field. Field will provide
1392
- # text_field entry field with select dropdown box with optional values for the field.
1393
- # Form options are mostly same as in select field.
1394
- #
1395
- # ===Form options:
1396
- # * +name:+ field name (required)
1397
- # * +type:+ text_with_select (required)
1398
- # * +choices:+ Values for choices separated by comma. Values can also be specified like description:value.
1399
- # In this case description will be shown to user, but value will be saved to document.
1400
- # choices: 'OK:0,Ready:1,Error:2'
1401
- # choices: Ruby,Pyton,PHP
1402
- # * +eval:+ Choices will be provided by evaluating expression
1403
- # eval: dc_choices4('model_name','description_field_name','_id'); dc_choices4 helper will provide data for select field.
1404
- # eval: ModelName.choices4_field; ModelName class will define method choices4_field which
1405
- # will provide data for select field. Since expression is evaluated in the context of Form Field object
1406
- # Even session session variables can be accessed.
1407
- # eval: 'MyClass.method(@parent.session[:user_id])'
1408
- # When searching is more complex custom search method may be defined in CollectionName
1409
- # model which will provide result set for search.
1410
- # eval: collection_name.search_field_name.method_name;
1411
- # If choices or eval is not defined choices will be provided from translation helpers. For example:
1412
- # Collection has field status. Choices for field will be provided by en.helpers.model_name.choices4_status
1413
- # entry of english translation. English is of course default translation. If you provide translations in
1414
- # your local language then select choices will be localized.
1415
- # en.helpers.model_name.choices4_status: 'OK:0,Ready:1,Error:2'
1416
- # sl.helpers.model_name.choices4_status: 'V redu:0,Pripravljen:1,Napaka:2'
1417
- # * +html:+ html options which apply to select and text_field fields (optional)
1418
- #
1419
- # Form example:
1420
- # 10:
1421
- # name: link
1422
- # type: text_with_select
1423
- # eval: '@parent.dc_page_class.all_pages_for_site(@parent.dc_get_site)'
1424
- # html:
1425
- # size: 50
1426
- ###########################################################################
1427
- class TextWithSelect < Select
1428
-
1429
- ###########################################################################
1430
- # Render text_with_select field html code
1431
- ###########################################################################
1432
- def render
1433
- return ro_standard if @readonly
1434
- set_initial_value('html','value')
1435
-
1436
- record = record_text_for(@yaml['name'])
1437
- @html << @parent.text_field( record, @yaml['name'], @yaml['html'])
1438
- @yaml['html']['class'] = 'text-with-select'
1439
- @yaml['html'].symbolize_keys!
1440
- @html << @parent.select( @yaml['name'] + '_', nil, get_choices, { include_blank: true }, { class: 'text-with-select' })
1441
-
1442
- # javascript to update text field if new value is selected in select field
1443
- @js =<<EOJS
1444
- $(document).ready(function() {
1445
- $('##{@yaml['name']}_').change( function() {
1446
- if ($(this).val().toString().length > 0) {
1447
- $('##{record}_#{@yaml['name']}').val( $(this).val() );
1448
- }
1449
- $('##{record}_#{@yaml['name']}').focus();
1450
- });
1451
- });
1452
- EOJS
1453
- self
1454
- end
1455
- end
1456
-
1457
- ###########################################################################
1458
- # Implementation of tree_select DRG CMS form field. Field will provides
1459
- # multiple select functionality displayed as a tree. Might be used for selecting
1460
- # multiple categories in a parent-child tree view.#
1461
- #
1462
- # ===Form options:
1463
- # * +name:+ field name (required)
1464
- # * +type:+ tree_select (required)
1465
- # * +choices:+ Values for choices separated by comma. Values can also be specified like description:value.
1466
- # In this case description will be shown to user, but value will be saved to document.
1467
- # choices: 'OK:0,Ready:1,Error:2'
1468
- # choices: Ruby,Pyton,PHP
1469
- # * +eval:+ Choices will be provided by evaluating expression
1470
- # eval: ModelName.choices4_field; Model class should define method which will provide data for field.
1471
- # Data returned must be of type Array and have 3 elements.
1472
- # 1 - description text
1473
- # 2 - id value
1474
- # 3 - parent id
1475
- # * +html:+ html options which apply to select and text_field fields (optional)
1476
- #
1477
- # Form example:
1478
- # 10:
1479
- # name: categories
1480
- # type: tree_select
1481
- # eval: 'Categories.all_categories'
1482
- # html:
1483
- # size: 50x10
1484
- ###########################################################################
1485
- class TreeSelect < Select
1486
-
1487
- ###########################################################################
1488
- # Prepare choices for tree data rendering.
1489
- ###########################################################################
1490
- def make_tree(parent)
1491
- return '' unless @choices[parent.to_s]
1492
- @html << '<ul>'
1493
- choices = if @choices[parent.to_s].first[3] != 0
1494
- @choices[parent.to_s].sort_by {|e| e[3].to_i } # sort by order if first is not 0
1495
- # @choices[parent.to_s].sort_alphabetical_by(&:first) # use UTF-8 sort
1496
- else
1497
- @choices[parent.to_s].sort_alphabetical_by(&:first) # use UTF-8 sort
1498
- end
1499
- choices.each do |choice|
1500
- jstree = %Q[{"selected" : #{choice.last ? 'true' : 'false'} }]
1501
- # data-jstree must be singe quoted
1502
- @html << %Q[<li data-id="#{choice[1]}" data-jstree='#{jstree}'>#{choice.first}\n]
1503
- # call recursively for children
1504
- make_tree(choice[1]) if @choices[ choice[1].to_s ]
1505
- @html << "</li>"
1506
- end
1507
- @html << '</ul>'
1508
- end
1509
-
1510
- ###########################################################################
1511
- # Render tree_select field html code
1512
- ###########################################################################
1513
- def render
1514
- return ro_standard if @readonly
1515
- set_initial_value('html','value')
1516
- require 'sort_alphabetical'
1517
-
1518
- record = record_text_for(@yaml['name'])
1519
- @html << "<div id=\"#{@yaml['name']}\" class=\"tree-select\" #{set_style()} >"
1520
- # Fill @choices hash. The key is parent object id
1521
- @choices = {}
1522
- do_eval(@yaml['eval']).each {|data| @choices[ data[2].to_s ] ||= []; @choices[ data[2].to_s ] << (data << false)}
1523
- # put current values hash with. To speed up selection when there is a lot of categories
1524
- current_values = {}
1525
- current = @record[@yaml['name']] || []
1526
- current = [current] unless current.class == Array # non array fields
1527
- current.each {|e| current_values[e.to_s] = true}
1528
- # set third element of @choices when selected
1529
- @choices.keys.each do |key|
1530
- 0.upto( @choices[key].size - 1 ) do |i|
1531
- choice = @choices[key][i]
1532
- choice[choice.size - 1] = true if current_values[ choice[1].to_s ]
1533
- end
1534
- end
1535
- make_tree(nil)
1536
- @html << '</ul></div>'
1537
- # add hidden communication field
1538
- @html << @parent.hidden_field(record, @yaml['name'], value: current.join(','))
1539
- # save multiple indicator for data processing on return
1540
- @html << @parent.hidden_field(record, "#{@yaml['name']}_multiple", value: 1) if @yaml['multiple']
1541
- # javascript to update hidden record field when tree looses focus
1542
- @js =<<EOJS
1543
- $(function(){
1544
- $("##{@yaml['name']}").jstree( {
1545
- "checkbox" : {"three_state" : false},
1546
- "core" : { "themes" : { "icons": false },
1547
- "multiple" : #{@yaml['multiple'] ? 'true' : 'false'} },
1548
- "plugins" : ["checkbox"]
1549
- });
1550
- });
1551
-
1552
- $(document).ready(function() {
1553
- $('##{@yaml['name']}').on('focusout', function(e) {
1554
- var checked_ids = [];
1555
- var checked = $('##{@yaml['name']}').jstree("get_checked", true);
1556
- $.each(checked, function() {
1557
- checked_ids.push( this.data.id );
1558
- });
1559
- $('#record_#{@yaml['name']}').val( checked_ids.join(",") );
1560
- });
1561
- });
1562
- EOJS
1563
- self
1564
- end
1565
-
1566
- ###########################################################################
1567
- # Return value. Return nil if input field is empty
1568
- ###########################################################################
1569
- def self.get_data(params, name)
1570
- return nil if params['record'][name].blank?
1571
- #
1572
- result = params['record'][name].split(',')
1573
- result.delete_if {|e| e.blank? }
1574
- return nil if result.size == 0
1575
- # convert to BSON objects if is BSON object ID
1576
- result = result.map{ |e| BSON::ObjectId.from_string(e) } if BSON::ObjectId.legal?(result.first)
1577
- # return only first element if multiple values select was not alowed
1578
- params['record']["#{name}_multiple"] == '1' ? result : result.first
1579
- end
1580
-
1581
- end
1582
-
1583
- ###########################################################################
1584
- # Implementation of html_field DRG CMS form field.
1585
- #
1586
- # HtmlField class only implements code for calling actual html edit field code.
1587
- # This is by default drg_default_html_editor gem which uses CK editor javascript plugin
1588
- # or any other plugin. Which plugin will be used as html editor is defined by
1589
- # dc_site.settings html_editor setting.
1590
- #
1591
- # Example of dc_site.setting used for drg_default_html_editor gem.
1592
- # html_editor: ckeditor
1593
- # ck_editor:
1594
- # config_file: /files/ck_config.js
1595
- # css_file: /files/ck_css.css
1596
- # file_select: elfinder
1597
- #
1598
- # Form example:
1599
- # 10:
1600
- # name: body
1601
- # type: html_field
1602
- # options: "height: 500, width: 550, toolbar: 'basic'"
1603
- ###########################################################################
1604
- class HtmlField < DrgcmsField
1605
-
1606
- ###########################################################################
1607
- # Render html_field field html code
1608
- ###########################################################################
1609
- def render
1610
- return ro_standard if @readonly
1611
- # retrieve html editor from page settings
1612
- editor_string = @parent.dc_get_site.params['html_editor'] if @parent.dc_get_site
1613
- editor_string ||= 'ckeditor'
1614
- #
1615
- klas_string = editor_string.camelize
1616
- if DrgcmsFormFields.const_defined?(klas_string)
1617
- klas = DrgcmsFormFields::const_get(klas_string)
1618
- o = klas.new(@parent, @record, @yaml).render
1619
- @js << o.js
1620
- @html << o.html
1621
- else
1622
- @html << "HTML editor not defined. Check site.settings or include drgcms_default_html_editor gem."
1623
- end
1624
- self
1625
- end
1626
- end
1627
-
1628
- ###########################################################################
1629
- # Implementation of file_select DRG CMS form field.
1630
- #
1631
- # FileSelect like HtmlField implements redirection for calling document manager edit field code.
1632
- # This can be drg_default_html_editor's elfinder or any other code defined
1633
- # by dc_site.settings file_select setting.
1634
- #
1635
- # Example of dc_site.setting used for drg_default_html_editor gem.
1636
- # html_editor: ckeditor
1637
- # ck_editor:
1638
- # config_file: /files/ck_config.js
1639
- # css_file: /files/ck_css.css
1640
- # file_select: elfinder
1641
- #
1642
- # Form example:
1643
- # 60:
1644
- # name: picture
1645
- # type: file_select
1646
- # html:
1647
- # size: 50
1648
- ###########################################################################
1649
- class FileSelect < DrgcmsField
1650
-
1651
- ###########################################################################
1652
- # Render file_select field html code
1653
- ###########################################################################
1654
- def render
1655
- return ro_standard if @readonly
1656
- # retrieve html editor from page settings
1657
- selector_string = @parent.dc_get_site.params['file_select'] if @parent.dc_get_site
1658
- selector_string ||= 'elfinder'
1659
- #
1660
- klas_string = selector_string.camelize
1661
- if DrgcmsFormFields.const_defined?(klas_string)
1662
- klas = DrgcmsFormFields::const_get(klas_string)
1663
- o = klas.new(@parent, @record, @yaml).render
1664
- @js << o.js
1665
- @html << o.html
1666
- else
1667
- @html << "File select component not defined. Check site.settings or include drgcms_default_html_editor gem."
1668
- end
1669
- self
1670
- end
1671
- end
1672
-
1673
- end