drg_cms 0.5.52.12 → 0.5.52.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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