drg_cms 0.4.39

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +39 -0
  5. data/app/assets/images/drg_cms/add.png +0 -0
  6. data/app/assets/images/drg_cms/arrow_in.png +0 -0
  7. data/app/assets/images/drg_cms/arrow_out.png +0 -0
  8. data/app/assets/images/drg_cms/checkbox-checked.png +0 -0
  9. data/app/assets/images/drg_cms/checkbox-unchecked.png +0 -0
  10. data/app/assets/images/drg_cms/cols.png +0 -0
  11. data/app/assets/images/drg_cms/copy.png +0 -0
  12. data/app/assets/images/drg_cms/edit.png +0 -0
  13. data/app/assets/images/drg_cms/edit_design.png +0 -0
  14. data/app/assets/images/drg_cms/edit_page.png +0 -0
  15. data/app/assets/images/drg_cms/edit_site.png +0 -0
  16. data/app/assets/images/drg_cms/html.png +0 -0
  17. data/app/assets/images/drg_cms/pin.png +0 -0
  18. data/app/assets/images/drg_cms/printer.png +0 -0
  19. data/app/assets/images/drg_cms/reload.png +0 -0
  20. data/app/assets/images/drg_cms/search_16.png +0 -0
  21. data/app/assets/images/drg_cms/spinner.gif +0 -0
  22. data/app/assets/images/drg_cms/view_tile.png +0 -0
  23. data/app/assets/images/drg_cms/x.png +0 -0
  24. data/app/assets/javascripts/drg_cms/drg_cms.js +449 -0
  25. data/app/assets/javascripts/drg_cms/jquery-migrate.js +511 -0
  26. data/app/assets/javascripts/drg_cms/jquery.datetimepicker.js +1353 -0
  27. data/app/assets/javascripts/drg_cms/some_scripts.js +33 -0
  28. data/app/assets/javascripts/drg_cms_application.js +11 -0
  29. data/app/assets/javascripts/drg_cms_cms.js +28 -0
  30. data/app/assets/stylesheets/drg_cms/drg_cms.css +632 -0
  31. data/app/assets/stylesheets/drg_cms/jquery-ui.css +339 -0
  32. data/app/assets/stylesheets/drg_cms/jquery.datetimepicker.css +304 -0
  33. data/app/assets/stylesheets/drg_cms/th-bg.png +0 -0
  34. data/app/assets/stylesheets/drg_cms/theme.css +49 -0
  35. data/app/assets/stylesheets/drg_cms_application.css +12 -0
  36. data/app/assets/stylesheets/drg_cms_cms.css +26 -0
  37. data/app/controllers/cmsedit_controller.rb +673 -0
  38. data/app/controllers/dc_application_controller.rb +385 -0
  39. data/app/controllers/dc_at_the_beginning_controller.rb +120 -0
  40. data/app/controllers/dc_common_controller.rb +314 -0
  41. data/app/controllers/dc_mail_controller.rb +89 -0
  42. data/app/controllers/dc_main_controller.rb +40 -0
  43. data/app/controllers/drgcms_controls/dc_page_controls.rb +40 -0
  44. data/app/forms/all_options.yml +176 -0
  45. data/app/forms/cms_forms.yml +93 -0
  46. data/app/forms/cms_menu.yml +142 -0
  47. data/app/forms/dc_ad.yml +130 -0
  48. data/app/forms/dc_big_table.yml +59 -0
  49. data/app/forms/dc_big_table_locale.yml +41 -0
  50. data/app/forms/dc_big_table_value.yml +47 -0
  51. data/app/forms/dc_category.yml +57 -0
  52. data/app/forms/dc_design.yml +68 -0
  53. data/app/forms/dc_folder_permission.yml +49 -0
  54. data/app/forms/dc_forum_cat.yml +54 -0
  55. data/app/forms/dc_forum_forum.yml +53 -0
  56. data/app/forms/dc_forum_msg.yml +124 -0
  57. data/app/forms/dc_forum_privmsg.yml +125 -0
  58. data/app/forms/dc_forum_topic.yml +131 -0
  59. data/app/forms/dc_journal.yml +85 -0
  60. data/app/forms/dc_link.yml +55 -0
  61. data/app/forms/dc_mail.yml +88 -0
  62. data/app/forms/dc_mail_address.yml +56 -0
  63. data/app/forms/dc_mail_list.yml +44 -0
  64. data/app/forms/dc_mail_list_member.yml +42 -0
  65. data/app/forms/dc_menu.yml +62 -0
  66. data/app/forms/dc_menu_item.yml +81 -0
  67. data/app/forms/dc_page.yml +145 -0
  68. data/app/forms/dc_part.yml +102 -0
  69. data/app/forms/dc_permission.yml +50 -0
  70. data/app/forms/dc_piece.yml +105 -0
  71. data/app/forms/dc_policy.yml +57 -0
  72. data/app/forms/dc_policy_role.yml +42 -0
  73. data/app/forms/dc_policy_rule.yml +38 -0
  74. data/app/forms/dc_policy_rule_nocms.yml +38 -0
  75. data/app/forms/dc_poll.yml +113 -0
  76. data/app/forms/dc_poll_item.yml +76 -0
  77. data/app/forms/dc_simple_menu.yml +64 -0
  78. data/app/forms/dc_simple_menu_item.yml +80 -0
  79. data/app/forms/dc_site.yml +149 -0
  80. data/app/forms/dc_user.yml +142 -0
  81. data/app/forms/dc_user_role.yml +54 -0
  82. data/app/forms/drgcms_cms.yml +28 -0
  83. data/app/helpers/cmsedit_helper.rb +698 -0
  84. data/app/helpers/dc_ad_renderer.rb +206 -0
  85. data/app/helpers/dc_application_helper.rb +704 -0
  86. data/app/helpers/dc_big_menu_renderer.rb +180 -0
  87. data/app/helpers/dc_captcha_renderer.rb +100 -0
  88. data/app/helpers/dc_common_renderer.rb +132 -0
  89. data/app/helpers/dc_mail_renderer.rb +76 -0
  90. data/app/helpers/dc_menu_renderer.rb +143 -0
  91. data/app/helpers/dc_page_renderer.rb +80 -0
  92. data/app/helpers/dc_part_renderer.rb +162 -0
  93. data/app/helpers/dc_piece_renderer.rb +124 -0
  94. data/app/helpers/dc_poll_renderer.rb +219 -0
  95. data/app/helpers/dc_renderer.rb +56 -0
  96. data/app/helpers/dc_simple_menu_renderer.rb +244 -0
  97. data/app/helpers/drgcms_form_field.rb +863 -0
  98. data/app/models/__dc_global_data.rb +44 -0
  99. data/app/models/dc_ad.rb +52 -0
  100. data/app/models/dc_ad_stat.rb +34 -0
  101. data/app/models/dc_big_menu.rb +89 -0
  102. data/app/models/dc_big_table.rb +63 -0
  103. data/app/models/dc_big_table_locale.rb +35 -0
  104. data/app/models/dc_big_table_value.rb +38 -0
  105. data/app/models/dc_category.rb +48 -0
  106. data/app/models/dc_design.rb +48 -0
  107. data/app/models/dc_dummy.rb +30 -0
  108. data/app/models/dc_folder_permission.rb +43 -0
  109. data/app/models/dc_global_data.rb +44 -0
  110. data/app/models/dc_journal.rb +39 -0
  111. data/app/models/dc_key_value_store.rb +90 -0
  112. data/app/models/dc_link.rb +39 -0
  113. data/app/models/dc_mail.rb +64 -0
  114. data/app/models/dc_mail_address.rb +69 -0
  115. data/app/models/dc_mail_list.rb +48 -0
  116. data/app/models/dc_mail_list_member.rb +34 -0
  117. data/app/models/dc_menu.rb +59 -0
  118. data/app/models/dc_menu_item.rb +40 -0
  119. data/app/models/dc_page.rb +123 -0
  120. data/app/models/dc_part.rb +28 -0
  121. data/app/models/dc_permission.rb +58 -0
  122. data/app/models/dc_piece.rb +57 -0
  123. data/app/models/dc_policy.rb +94 -0
  124. data/app/models/dc_policy_role.rb +47 -0
  125. data/app/models/dc_policy_rule.rb +65 -0
  126. data/app/models/dc_poll.rb +46 -0
  127. data/app/models/dc_poll_item.rb +40 -0
  128. data/app/models/dc_sendmail.rb +48 -0
  129. data/app/models/dc_simple_menu.rb +58 -0
  130. data/app/models/dc_simple_menu_item.rb +39 -0
  131. data/app/models/dc_site.rb +92 -0
  132. data/app/models/dc_stat.rb +36 -0
  133. data/app/models/dc_user.rb +91 -0
  134. data/app/models/dc_user_role.rb +36 -0
  135. data/app/models/dc_visit.rb +35 -0
  136. data/app/views/cmsedit/_edit_stuff.html.erb +59 -0
  137. data/app/views/cmsedit/_edit_stuff.js.erb +6 -0
  138. data/app/views/cmsedit/_form.html.erb +21 -0
  139. data/app/views/cmsedit/_result.html.erb +20 -0
  140. data/app/views/cmsedit/edit.html.erb +6 -0
  141. data/app/views/cmsedit/error.html.erb +2 -0
  142. data/app/views/cmsedit/index.html.erb +6 -0
  143. data/app/views/cmsedit/new.html.erb +5 -0
  144. data/app/views/cmsedit/show.html.erb +21 -0
  145. data/app/views/dc_at_the_beginning/create.html.erb +9 -0
  146. data/app/views/dc_at_the_beginning/index.html.erb +19 -0
  147. data/app/views/dc_common/paste_clipboard.html.erb +17 -0
  148. data/app/views/dc_mail/subscribe.html.erb +7 -0
  149. data/app/views/dc_mail/unsubscribe.html.erb +19 -0
  150. data/app/views/layouts/cms.html.erb +17 -0
  151. data/app/views/layouts/cmsedit.html.erb +16 -0
  152. data/app/views/layouts/content.html.erb +16 -0
  153. data/config/initializers/kaminari_patch.rb +36 -0
  154. data/config/locales/datetimepicker.yml +13 -0
  155. data/config/locales/drgcms_en.yml +96 -0
  156. data/config/locales/drgcms_sl.yml +97 -0
  157. data/config/locales/en.yml +7 -0
  158. data/config/locales/kaminari.yml +26 -0
  159. data/config/locales/models_en.yml +790 -0
  160. data/config/locales/models_sl.yml +805 -0
  161. data/config/locales/mongoid_sl.yml +60 -0
  162. data/config/locales/sl.yml +211 -0
  163. data/config/routes.rb +2 -0
  164. data/drg_cms.gemspec +28 -0
  165. data/lib/drg_cms.rb +45 -0
  166. data/lib/drg_cms/engine.rb +30 -0
  167. data/lib/drg_cms/version.rb +3 -0
  168. data/lib/tasks/at_the_beginning.yml +26 -0
  169. data/lib/tasks/dc_cleanup.rake +94 -0
  170. data/lib/tasks/drg_cms_tasks.rake +118 -0
  171. data/lib/tasks/send_mail.rake +253 -0
  172. data/lib/tasks/site_statistics.rake +80 -0
  173. data/test/drg_cms_test.rb +7 -0
  174. data/test/dummy/README.rdoc +261 -0
  175. data/test/dummy/Rakefile +7 -0
  176. data/test/dummy/app/assets/javascripts/application.js +15 -0
  177. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  178. data/test/dummy/app/controllers/application_controller.rb +3 -0
  179. data/test/dummy/app/helpers/application_helper.rb +2 -0
  180. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  181. data/test/dummy/config.ru +4 -0
  182. data/test/dummy/config/application.rb +59 -0
  183. data/test/dummy/config/boot.rb +10 -0
  184. data/test/dummy/config/database.yml +25 -0
  185. data/test/dummy/config/environment.rb +5 -0
  186. data/test/dummy/config/environments/development.rb +37 -0
  187. data/test/dummy/config/environments/production.rb +67 -0
  188. data/test/dummy/config/environments/test.rb +37 -0
  189. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  190. data/test/dummy/config/initializers/inflections.rb +15 -0
  191. data/test/dummy/config/initializers/mime_types.rb +5 -0
  192. data/test/dummy/config/initializers/secret_token.rb +7 -0
  193. data/test/dummy/config/initializers/session_store.rb +8 -0
  194. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  195. data/test/dummy/config/locales/en.yml +5 -0
  196. data/test/dummy/config/routes.rb +58 -0
  197. data/test/dummy/public/404.html +26 -0
  198. data/test/dummy/public/422.html +26 -0
  199. data/test/dummy/public/500.html +25 -0
  200. data/test/dummy/public/favicon.ico +0 -0
  201. data/test/dummy/script/rails +6 -0
  202. data/test/integration/navigation_test.rb +10 -0
  203. data/test/test_helper.rb +15 -0
  204. metadata +375 -0
@@ -0,0 +1,206 @@
1
+ #--
2
+ # Copyright (c) 2012-2013 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 BUTe 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
+ #
26
+ ########################################################################
27
+ class DcAdRenderer
28
+
29
+ include DcApplicationHelper
30
+
31
+ ########################################################################
32
+ #
33
+ ########################################################################
34
+ def initialize( parent, opts={} )
35
+ @parent = parent
36
+ @opts = opts
37
+ @css = ''
38
+ self
39
+ end
40
+
41
+ ########################################################################
42
+ #
43
+ ########################################################################
44
+ def find_ads_multi()
45
+ ads = DcAd.where( position: @opts[:position], active: true).to_a#, :valid_to.gt => Time.now, :valid_from.lt => Time.now).to_a
46
+ #p @opts, ads.size, '*-*-*-*'
47
+ ads.delete_if { |ad| (ad.valid_to and ad.valid_to < Time.now) or
48
+ (ad.valid_from and ad.valid_from > Time.now) or
49
+ (ad.displays > 0 and ad.displayed >= ad.displays) or
50
+ (ad.clicks > 0 and ad.clicked >= ad.clicks) }
51
+
52
+ ads
53
+ end
54
+
55
+ ########################################################################
56
+ # Default method for rendering ads
57
+ ########################################################################
58
+ def multi
59
+ return '' if @parent.session[:is_robot] # don't bother if robot
60
+ html = "<div id='ad-#{@opts[:position]}-div'>"
61
+ n = 0
62
+ find_ads_multi.each do |ad|
63
+ div = "ad-#{@opts[:position]}-#{n+=1}"
64
+ html << "<div id='#{div}' style='position: absolute; display: none;'>"
65
+ # all except first are hidden
66
+ # html << n == 1 ? '>' : 'style="display: none;">'
67
+ html << case ad.type
68
+ when 1 then # picture
69
+ picture_link ad
70
+ when 2 then # flash
71
+ flash_link ad
72
+ when 3 then # script
73
+ ad.script
74
+ else
75
+ 'Error. Wrong ad type!'
76
+ end
77
+ html << '</div>'
78
+ end
79
+ #
80
+ html << '</div>'
81
+ if n > 0
82
+ js = <<EOJS
83
+ dc_ad_next_slide = function(div, index, max, timeout) {
84
+ index = index + 1;
85
+ div_show = div + index.toString();
86
+ index_h = index - 1;
87
+ if (index_h == 0) index_h = max;
88
+ div_hide = div + index_h.toString();
89
+ $('#' + div_show).fadeIn(1500);
90
+ $('#' + div_hide).fadeOut(1500);
91
+
92
+ if (index == max) index = 0;
93
+ setTimeout( function () { dc_ad_next_slide(div, index, max, timeout); }, timeout);
94
+ }
95
+
96
+ $(document).ready(function () {
97
+ dc_ad_next_slide("ad-#{@opts[:position]}-", 0, #{n}, 5000)
98
+ });
99
+ EOJS
100
+ html << @parent.javascript_tag(js)
101
+ end
102
+ html
103
+ end
104
+
105
+ ########################################################################
106
+ #
107
+ ########################################################################
108
+ def find_ad_to_display()
109
+ ads = DcAd.where( dc_site_id: @parent.site._id, position: @opts[:position], active: true).to_a#, :valid_to.gt => Time.now, :valid_from.lt => Time.now).to_a
110
+ #p @opts, ads.size, '*-*-*-*'
111
+ ads.delete_if { |ad| (ad.valid_to and ad.valid_to < Time.now) or
112
+ (ad.valid_from and ad.valid_from > Time.now) or
113
+ (ad.displays > 0 and ad.displayed >= ad.displays) or
114
+ (ad.clicks > 0 and ad.clicked >= ad.clicks) }
115
+ return nil if ads.size == 0
116
+ # Determine ad to display, based on priority. This is of course not totaly accurate,
117
+ # but it will have to do.
118
+ sum = ads.inject(0) {|r, e| r += e.priority}
119
+ rnd = Random.rand(sum)
120
+ r = 0
121
+ ads.each do |e|
122
+ return e if rnd >= r and rnd < r + e.priority
123
+ r += e.priority
124
+ end
125
+ ads.last # we really shouldn't be here
126
+ end
127
+
128
+ ########################################################################
129
+ # Create flash link for ad
130
+ ########################################################################
131
+ def flash_link(ad)
132
+ click_tag = ad.link.to_s.size > 5 ? "flashvars=\"clickTag=#{ad.link}\"" : ''
133
+ <<EOT
134
+ <div class="link_to_track" id="#{ad.id}">
135
+ <object>
136
+ <param name="wmode" value="transparent" />
137
+ <embed width="#{ad.width}" height="#{ad.height}" src="#{ad.file}" #{click_tag}
138
+ wmode=transparent allowfullscreen='true' allowscriptaccess='always' type="application/x-shockwave-flash"></embed>
139
+ </object>
140
+ </div>
141
+
142
+ <script type='text/javascript'>
143
+ $('##{ad.id}').mousedown(function (e){
144
+ $.post('/dc_common/ad_click', { id: this.id });
145
+ return true;
146
+ });
147
+ </script>
148
+ EOT
149
+ end
150
+
151
+ ########################################################################
152
+ # Create picture link for ad
153
+ ########################################################################
154
+ def picture_link(ad)
155
+ @parent.link_to @parent.image_tag(ad.file), ad.link, id: ad.id, class: 'link_to_track', target: ad.link_target
156
+ end
157
+
158
+ ########################################################################
159
+ # Default method for rendering ads
160
+ ########################################################################
161
+ def default
162
+ return '' if @parent.session[:is_robot] # don't bother if robot
163
+ html = ''
164
+ if (ad = find_ad_to_display)
165
+ # save to statistics, if not in cms
166
+ if @opts[:edit_mode] < 1
167
+ DcAdStat.create!(dc_ad_id: ad.id, ip: @parent.request.ip, type: 1 )
168
+ # save display counter
169
+ ad.displayed += 1
170
+ ad.save
171
+ end
172
+ html << case ad.type
173
+ when 1 then # picture
174
+ picture_link ad
175
+ when 2 then # flash
176
+ flash_link ad
177
+ when 3 then # script
178
+ ad.script
179
+ else
180
+ 'Error. Wrong ad type!'
181
+ end
182
+ end
183
+ html
184
+ end
185
+
186
+ ########################################################################
187
+ # Render HTML
188
+ ########################################################################
189
+ def render_html
190
+ method = @opts[:method] || 'default'
191
+ html = if method and self.respond_to?(method)
192
+ send(method)
193
+ else
194
+ "DcAdRenderer: method #{method} not defined!"
195
+ end
196
+ html
197
+ end
198
+
199
+ ########################################################################
200
+ # Render CSS
201
+ ########################################################################
202
+ def render_css
203
+ @css
204
+ end
205
+
206
+ end
@@ -0,0 +1,704 @@
1
+ #coding: utf-8
2
+ #--
3
+ # Copyright (c) 2012+ Damjan Rems
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #++
24
+
25
+ module DcApplicationHelper
26
+ attr_reader :page, :design, :site, :tables, :ids, :form, :options
27
+ attr_accessor :parts
28
+
29
+ ############################################################################
30
+ # Calls part renderer to return part of design.
31
+ ############################################################################
32
+ def dc_render(renderer, opts={})
33
+ type = renderer.to_s.downcase
34
+ opts[:edit_mode] = session[:edit_mode]
35
+ # TODO Check why did I always put return_to into link and will this break something
36
+ # opts[:editparams] = { return_to: request.url }
37
+ opts[:editparams] = {}
38
+ opts = @options.merge(opts) # merge options with parameters passed on site, page, design ...
39
+ opts.symbolize_keys! # this makes lots of things easier
40
+ # Create renderer object
41
+ klass = (type + '_renderer').classify
42
+ obj = Kernel.const_get(klass, Class.new).new(self, opts)
43
+ #
44
+ html = obj.render_html
45
+ @css << obj.render_css.to_s
46
+ html.nil? ? '' : html.html_safe # nil can happened
47
+ end
48
+
49
+ ########################################################################
50
+ # Used for designs with lots of common code and one part which is different.
51
+ #
52
+ # Example: As used in design. Backslashing < and % is important \<\%
53
+ # <% part = "<div class='some-class'>\<\%= dc_render(:my_renderer, method: 'render_method') \%\></div>" %>
54
+ # <%= dc_replace_in_design(piece: 'piece_name', replace: '[main]', with: part) %>
55
+ #
56
+ # Want to replace more than one part. Use array.
57
+ # <%= dc_replace_in_design(replace: ['[part1]','[part2]'], with: [part1, part2]) %>
58
+ #
59
+ # This helper is replacement for 'script' method defined in dc_piece_renderer,
60
+ # but it can also use design defined in site document if piece parameter is not set.
61
+ ########################################################################
62
+ def dc_replace_in_design(opts={})
63
+ design = opts[:piece] ? DcPiece.find(name: opts[:piece]).script : dc_get_site.design
64
+ if opts[:replace]
65
+ # replace more than one part of code
66
+ if opts[:replace].class == Array
67
+ 0.upto(opts[:replace].size - 1) {|i| design.sub!(opts[:replace][i], opts[:with][i])}
68
+ else
69
+ design.sub!(opts[:replace], opts[:with])
70
+ end
71
+ end
72
+ render(inline: design, layout: opts[:layout])
73
+ end
74
+
75
+ ########################################################################
76
+ ########################################################################
77
+ def dc_render_design(opts={}) #NODOC
78
+ p "dc_render_design will be deprecated. Use dc_replace_in_design instead."
79
+ dc_replace_in_design(opts)
80
+ end
81
+
82
+ ############################################################################
83
+ # Creates title for dialog. Title also has pagination link on its right side.
84
+ ############################################################################
85
+ def dc_table_title(text, result=nil)
86
+ c = "<table width='100%' cellspacing='0' cellpadding='1' class='dc-title'><tr><td>#{text}</td>"
87
+ if result and result.respond_to?(:current_page)
88
+ c << "<td align='right' style='font-size: 0.8em;'> #{paginate(result, :params => {:action => 'index'})}</td>"
89
+ end
90
+ c << '<tr></table>'
91
+ c.html_safe
92
+ end
93
+
94
+ ############################################################################
95
+ # Creates title for cmsedit edit dialog.
96
+ ############################################################################
97
+ def dc_edit_title()
98
+ c = "#{t('drgcms.edit')} : "
99
+ c << (@form['title'] ? t( @form['title'], @form['title'] ) : t_tablename(@form['table'])) + ' : '
100
+ title = @form['form']['edit_title'] || @form['edit_title'] # edit_title bo šel ven
101
+ c << "#{@record[ title ]} : " if title and @record.respond_to?(title)
102
+ c << @record._id
103
+ end
104
+
105
+ ############################################################################
106
+ # Creates title for cmsedit new dialog.
107
+ ############################################################################
108
+ def dc_new_title()
109
+ if @form['table'] == 'dc_dummy'
110
+ t( @form['title'], @form['title'] )
111
+ else
112
+ "#{t('drgcms.new')} : #{t_tablename(@form['table'])}"
113
+ end
114
+ end
115
+
116
+ ####################################################################
117
+ # Creates label for edit dialog.
118
+ ####################################################################
119
+ def dc_label_for(input_html, label)
120
+ c =<<eot
121
+ <tr>
122
+ <td class="dc-edit-label">#{label}</td>
123
+ <td class="dc-edit-field">#{input_html}</td>
124
+ </tr>
125
+ eot
126
+ c.html_safe
127
+ end
128
+
129
+ ####################################################################
130
+ # Returns messages saved in flash formated for display.
131
+ ####################################################################
132
+ def dc_flash_messages()
133
+ err = @parent ? @parent.flash[:error] : flash[:error]
134
+ war = @parent ? @parent.flash[:warning] : flash[:warning]
135
+ inf = @parent ? @parent.flash[:info] : flash[:info]
136
+ note = @parent ? @parent.flash[:note] : flash[:note]
137
+ unless err.nil? and war.nil? and inf.nil? and note.nil?
138
+ c = ''
139
+ c << "<div class=\"dc-form-error\">#{err}</div>" if err
140
+ c << "<div class=\"dc-form-warning\">#{war}</div>" if war
141
+ c << "<div class=\"dc-form-info\">#{inf}</div>" if inf
142
+ c << note if note
143
+ if @parent
144
+ @parent.flash[:error] = nil
145
+ @parent.flash[:warning] = nil
146
+ @parent.flash[:info] = nil
147
+ @parent.flash[:note] = nil
148
+ else
149
+ flash[:error] = nil
150
+ flash[:warning] = nil
151
+ flash[:info] = nil
152
+ flash[:note] = nil
153
+ end
154
+ c.html_safe
155
+ end
156
+ end
157
+
158
+ ########################################################################
159
+ # Decamelizes string. This probably doesn't work very good with non ascii chars.
160
+ # Therefore it is very unwise to use non ascii chars for table (collection) names.
161
+ ########################################################################
162
+ def decamelize_type(st)
163
+ return nil if st.nil?
164
+ r = ''
165
+ st.to_s.each_char do |c|
166
+ r << case
167
+ when r.size == 0 then c.downcase
168
+ when c.downcase != c then '_' + c.downcase
169
+ else c
170
+ end
171
+ end
172
+ r
173
+ end
174
+
175
+ ####################################################################
176
+ # return error messages for the record
177
+ ####################################################################
178
+ def dc_error_messages_for(r)
179
+ return '' unless r.errors.any?
180
+ msgs = ''
181
+ r.errors.each do |attribute, errors_array|
182
+ label = t("helpers.label.#{decamelize_type(r.class)}.#{attribute}", attribute)
183
+ msgs << "<li>#{label} : #{errors_array}</li>"
184
+ end
185
+
186
+ c = <<eot
187
+ <div class="dc-form-error">
188
+ <h2>#{t('drgcms.errors_no')} #{r.errors.size}</h2>
189
+ <ul>#{msgs}</ul>
190
+ </div>
191
+ eot
192
+ c.html_safe
193
+ end
194
+
195
+ ####################################################################
196
+ # return true if in edit mode
197
+ ####################################################################
198
+ def dc_edit_mode?
199
+ (@parent ? @parent.session[:edit_mode] : session[:edit_mode]) > 1
200
+ end
201
+
202
+ ####################################################################
203
+ # Return create link for drg_cms
204
+ ####################################################################
205
+ def dc_link_for_create(opts)
206
+ title = opts.delete(:title) #
207
+ target = opts.delete(:target) || 'iframe_cms'
208
+ opts[:action] = 'new'
209
+ url = @parent ? @parent.url_for(opts) : url_for(opts)
210
+ js = "$('##{target}').attr('src', '#{url}'); return false;"
211
+ html = if @parent
212
+ @parent.image_tag('drg_cms/add.png', { onclick: js, style: 'cursor: pointer;', title: title, alt: 'Create'})
213
+ else
214
+ image_tag('drg_cms/add.png', { onclick: js, style: 'cursor: pointer;', title: title, alt: 'Create'})
215
+ end
216
+ html.html_safe
217
+ end
218
+
219
+ ####################################################################
220
+ #
221
+ ####################################################################
222
+ def dc_link_for_edit(opts)
223
+ title = opts.delete(:title) #
224
+ target = opts.delete(:target) || 'iframe_cms'
225
+ opts[:action] = 'edit'
226
+ opts[:controller] ||= 'cmsedit'
227
+ url = @parent ? @parent.url_for(opts) : url_for(opts)
228
+ js = "$('##{target}').attr('src', '#{url}'); return false;"
229
+ html = if @parent
230
+ @parent.image_tag('drg_cms/edit.png', { onclick: js, style: 'cursor: pointer;', title: title, alt: 'Edit'})
231
+ else
232
+ image_tag('drg_cms/edit.png', { onclick: js, style: 'cursor: pointer;', title: title, alt: 'Edit'})
233
+ end
234
+ html.html_safe
235
+ end
236
+
237
+ ####################################################################
238
+ # Create edit link for drg_cms
239
+ ####################################################################
240
+ def dc_link_menu_tag(title)
241
+ html =<<EOT
242
+ <dl>
243
+ <dt><div class='drgcms_popmenu' href="#"><span><img style="cursor:pointer;" src="/assets/drg_cms/edit.png" title="#{title}"></span></div></dt>
244
+ <dd>
245
+ <ul class=' div-hidden drgcms_popmenu_class'>
246
+ EOT
247
+ yield html
248
+ html << "</ul></dd></dl>"
249
+ end
250
+
251
+ ####################################################################
252
+ # Create one option in page edit link
253
+ ####################################################################
254
+ def dc_link_for_edit1(opts, link_text) #NODOC
255
+ url = @parent.url_for(opts)
256
+ "<li><div class='drgcms_popmenu_item' style='cursor: pointer;' data-url='#{url}'>#{link_text}</div></li>\n"
257
+ end
258
+
259
+ ########################################################################
260
+ # Create edit menu for dc_page document.
261
+ ########################################################################
262
+ def dc_page_edit_menu()
263
+ return '' if @opts[:edit_mode] < 2
264
+ # save some data to cookie. This can not go to session.
265
+ t = @parent.site.page_table
266
+ kukis = { "#{t}.dc_design_id" => @page.dc_design_id,
267
+ "#{t}.menu_id" => @page.menu_id,
268
+ "#{t}.kats" => @page.kats,
269
+ "#{t}.page_id" => @page.id,
270
+ "#{t}.dc_site_id" => @parent.site.id
271
+ }
272
+ @parent.cookies[:record] = Marshal.dump(kukis)
273
+ title = "#{t('drgcms.edit')}: #{@page.subject}"
274
+ dc_link_menu_tag(title) do |html|
275
+ @opts[:editparams].merge!( :controller => 'cmsedit', :action => 'edit' )
276
+ @opts[:editparams].merge!( :id => @page.id, :table => @parent.site.page_table, formname: nil, edit_only: 'body' )
277
+ html << dc_link_for_edit1( @opts[:editparams], t('drgcms.edit_content') )
278
+
279
+ @opts[:editparams][:edit_only] = nil
280
+ html << dc_link_for_edit1( @opts[:editparams], t('drgcms.edit_advanced') )
281
+
282
+ @opts[:editparams][:action] = 'new'
283
+ html << dc_link_for_edit1( @opts[:editparams], t('drgcms.edit_new_page') )
284
+
285
+ @opts[:editparams].merge!(ids: @page.id, formname: 'dc_part', table: "#{@parent.site.page_table};dc_part" )
286
+ html << dc_link_for_edit1( @opts[:editparams], t('drgcms.edit_new_part') )
287
+ end
288
+ end
289
+
290
+ ########################################################################
291
+ # Return page class (from site record) which defines page_class table (collection)
292
+ # used for saving page data.
293
+ #
294
+ # Mostly used by forms, when some method must be called from page model.
295
+ #
296
+ # @example usage from form description:
297
+ # 30:
298
+ # name: link
299
+ # type: text_with_select
300
+ # eval: 'DcPageClass.all_pages_for_site(@parent.dc_get_site)'
301
+ ########################################################################
302
+ def dc_page_class()
303
+ dc_get_site.page_class.classify.constantize
304
+ end
305
+
306
+ ####################################################################
307
+ # Wrapper for i18 t method, with some spice added
308
+ ####################################################################
309
+ def t(key, default='')
310
+ c = I18n.t(key)
311
+ if c.class == Hash or c.match( 'translation missing' )
312
+ c = I18n.t(key, locale: 'en')
313
+ # Still not found. Return default if set
314
+ c = default unless default.blank?
315
+ end
316
+ c
317
+ end
318
+
319
+ ####################################################################
320
+ # Returns translated tablename.
321
+ ####################################################################
322
+ def t_tablename(tablename, default=nil)
323
+ t('helpers.label.' + tablename + '.tabletitle', default || tablename)
324
+ end
325
+
326
+ ############################################################################
327
+ # Translation for field name label.
328
+ ############################################################################
329
+ def t_name(name, default='')
330
+ c = t("helpers.label.#{@form['table']}.#{name}", default)
331
+ c = name.capitalize.gsub('_',' ') if c.match( 'translation missing' )
332
+ c
333
+ end
334
+
335
+ ############################################################################
336
+ # Return name (description) for specified field in document
337
+ #
338
+ # @example usage from program
339
+ # dc_name4_value('dc_user', 'name', text.id)
340
+ #
341
+ # @example usage from form description
342
+ # columns:
343
+ # 2:
344
+ # name: site_id
345
+ # eval: dc_name4_value('site','name',@record['site_id'])
346
+ #
347
+ # @param [ model ] table (collection) model name.
348
+ # @param [ field ] field name to return
349
+ # @param [ id ] id to search for
350
+ #
351
+ ############################################################################
352
+ def dc_name4_value(model, field, value)
353
+ return '' if value.nil?
354
+ c = t('helpers.label.' + model + '.choices4_' + field )
355
+ a = c.chomp.split(',').inject([]) {|r,v| r << v.split(':') }
356
+ a.each {|e| return e.first if e.last.to_s == value.to_s }
357
+ ''
358
+ end
359
+
360
+ ############################################################################
361
+ # Return name (description) for specified table and id
362
+ #
363
+ # @example usage from program
364
+ # dc_name4_id('dc_user', 'name', text.id)
365
+ #
366
+ # @example usage from form description
367
+ # columns:
368
+ # 2:
369
+ # name: site_id
370
+ # eval: name4_id('site','name',@record['site_id'])
371
+ #
372
+ # @param [ model ] table (collection) model name.
373
+ # @param [ field ] field name to return
374
+ # @param [ id ] id to search for
375
+ #
376
+ ############################################################################
377
+ def dc_name4_id(model, field, id)
378
+ return '' if id.nil?
379
+ model = model.classify.constantize if model.class == String
380
+ rec = model.find_by(id: id)
381
+ rec.nil? ? '' : rec[field]
382
+ end
383
+
384
+ ############################################################################
385
+ # Return icon representation for boolean value. Icon is a picture of checked or unchecked box.
386
+ #
387
+ # @example usage from program
388
+ # dc_icon4_boolean(some_value)
389
+ #
390
+ # @example usage from form description
391
+ # columns:
392
+ # 10:
393
+ # name: active
394
+ # eval: dc_icon4_boolean
395
+ #
396
+ # @param [ value ] value
397
+ ############################################################################
398
+ def dc_icon4_boolean(val)
399
+ dc_dont?(val) ? image_tag('drg_cms/checkbox-unchecked.png') : image_tag('drg_cms/checkbox-checked.png')
400
+ end
401
+
402
+ ############################################################################
403
+ # Safely output date/time value in desired format. Will return '' if value is nil.
404
+ #
405
+ # Mostly used for calling from views.
406
+ ############################################################################
407
+ def dc_date_time(val, default=nil)
408
+ return '' if val.nil?
409
+ default = ( val.class == Date ? t('date.formats.default') : t('time.formats.default') ) if default.nil?
410
+ val.strftime(default)
411
+ end
412
+
413
+ ####################################################################
414
+ # Determine and return site record from url. Site record will be cached in
415
+ # @site variable.
416
+ ####################################################################
417
+ def dc_get_site()
418
+ return @site if @site # already cached
419
+ #
420
+ req = @parent ? @parent.request.url : request.url # different when called from renderer
421
+ uri = URI.parse(req)
422
+ @site = DcSite.find_by(name: uri.host)
423
+ # Site can be aliased
424
+ if @site and !@site.alias_for.blank?
425
+ @site = DcSite.find_by(name: @site.alias_for)
426
+ end
427
+ # Development environment. Check if site with name test exists and use
428
+ # homepagelink field as pointer to real site name.
429
+ if @site.nil? and ENV["RAILS_ENV"] != 'production'
430
+ @site = DcSite.find_by(name: 'test')
431
+ @site = DcSite.find_by(name: @site.alias_for) if @site
432
+ end
433
+ @site = nil if @site and !@site.active # site is disabled
434
+ @site
435
+ end
436
+
437
+ ############################################################################
438
+ # Return array of policies defined in a site document formated to be used
439
+ # as choices select field, where policy_id field is defined in document.
440
+ #
441
+ # @example (as used in forms)
442
+ # name: policy_id
443
+ # type: select
444
+ # eval: dc_choices4_site_policies
445
+ # html:
446
+ # include_blank: true
447
+ ############################################################################
448
+ def dc_choices4_site_policies()
449
+ site = dc_get_site()
450
+ site.dc_policies.all.inject([]) { |r, policy| r << [ policy.name, policy.id] if policy.active }
451
+ end
452
+
453
+ ############################################################################
454
+ # Returns list of table names (collections) as array of choices for use in select field
455
+ # on data permission form. Method gets list of available collections from
456
+ # cms_menu.yml menu definition file.
457
+ #
458
+ # @example (as used in forms)
459
+ # eval: dc_choices4_tables_list
460
+ ############################################################################
461
+ def dc_choices4_tables_list
462
+ menus = []
463
+ DrgCms.paths(:forms).reverse.each do |path|
464
+ f = "#{path}/cms_menu.yml"
465
+ menus << YAML.load_file(f)['menu'] if File.exist?(f)
466
+ end
467
+ #
468
+ choices = [] #['Default permission','Default permission']]
469
+ menus.each do |section|
470
+ section['items'].each do |e|
471
+ c = t(e['caption'], e['caption'])
472
+ choices << ["#{c} - #{e['params']['table']}", e['params']['table']]
473
+ end
474
+ end
475
+ choices
476
+ end
477
+
478
+ ##########################################################################
479
+ # Returns available choices used by collection edit select field on CMS top menu.
480
+ #
481
+ # @example: dc_choices4_cmsmenu
482
+ #
483
+ # Returns 2d array ready for use in select field.
484
+ ##########################################################################
485
+ def dc_choices4_cmsmenu()
486
+ menus = []
487
+ DrgCms.paths(:forms).reverse.each do |path|
488
+ f = "#{path}/cms_menu.yml"
489
+ menus << YAML.load_file(f)['menu'] if File.exist?(f)
490
+ end
491
+ #
492
+ choices = []
493
+ menus.each do |v|
494
+ choices << ["--- #{ t(v['section'], v['section']) }",'#']
495
+ v['items'].each do |i|
496
+ opts = { controller: i['controller'], action: i['action'] }
497
+ i['params'].each {|k,v| opts.merge!(k => v) }
498
+ choices << [ t(i['caption'],i['caption']), url_for( opts ) ]
499
+ end
500
+ end
501
+ choices
502
+ end
503
+
504
+ ############################################################################
505
+ # Returns list of directories as array of choices for use in select field
506
+ # on folder permission form.
507
+ #
508
+ # @example (as used in forms)
509
+ # eval: dc_choices4_folders_list
510
+ ############################################################################
511
+ def dc_choices4_folders_list
512
+ public = File.join(Rails.root,'public')
513
+ home = File.join(public,dc_get_site.files_directory)
514
+ choices = Dir.glob(home + '/**/*/').select { |fn| File.directory?(fn) }
515
+ choices << home # add home
516
+ choices.collect! {|e| e.gsub(public,'')} # remove public part
517
+ choices.sort
518
+ end
519
+
520
+ ############################################################################
521
+ # Returns choices for select input filed.
522
+ #
523
+ # @example
524
+ # dc_choices4('dc_mail_list', 'name', '_id', :site_only => true)
525
+ #
526
+ # @param [ model ] table (collection) model name.
527
+ # @param [ name ] field name with description
528
+ # @param [ id ] field name with id field. Default value is '_id'
529
+ #
530
+ ############################################################################
531
+ def dc_choices4(model, name, id='_id', options = {})
532
+ qry = model.classify.constantize.only(id, name).sort(name => 1)
533
+ qry = qry.where(dc_site_id: dc_get_site()) if options[:site_only]
534
+ r = []
535
+ qry.each {|v| r << [ v[name], v[id] ] }
536
+ r
537
+ end
538
+
539
+ ############################################################################
540
+ # Adds new key to record cookie, thus preparing some initial values for creating
541
+ # new record on the next call.
542
+ #
543
+ # @example
544
+ # dc_add2_record_cookie(hash)
545
+ #
546
+ # @param [ hash ] hash of cookies to add
547
+ ############################################################################
548
+ def dc_add2_record_cookie(hash)
549
+ kukis = if @parent.cookies[:record] and @parent.cookies[:record].size > 0
550
+ Marshal.load(@parent.cookies[:record])
551
+ else
552
+ {}
553
+ end
554
+ hash.each {|k,v| kukis[k] = v }
555
+ @parent.cookies[:record] = Marshal.dump(kukis)
556
+ end
557
+
558
+ ############################################################################
559
+ # Returns true if access_policy allows user to view cms part
560
+ # Returns false and message if access is not allowed
561
+ #
562
+ # @example
563
+ # dc_user_can_view(@parent, @page)
564
+ # dc_user_can_view(@parent, @page.policy_id)
565
+ #
566
+ # @param [ ctrl ] Controller object or object which holds methods to access session.
567
+ # @param [ policy_id ] Policy id to check. If record is send as parameter, method will
568
+ # check for policy_id field and use that field.
569
+ ############################################################################
570
+ def dc_user_can_view(ctrl, policy_id)
571
+ policy_id = policy_id.policy_id if policy_id and policy_id.respond_to?(:policy_id)
572
+ # Eventualy object without policy_id will be checked. This is to prevent error
573
+ policy_id = nil unless policy_id.class == BSON::ObjectId
574
+ #
575
+ site = ctrl.site
576
+ policies = site.dc_policies
577
+ # permission defined by default policy
578
+ default_policy = policies.find_by(is_default: true)
579
+ return false, 'Default accsess policy not found for the site!' unless default_policy
580
+ h = {}
581
+ default_policy.dc_policy_rules.to_a.each { |v| h[v.dc_policy_role_id] = v.permission }
582
+ # update permissions with defined policy
583
+ part_policy = nil
584
+ if policy_id
585
+ part_policy = policies.find(policy_id)
586
+ return false, 'Access policy not found for part!' unless part_policy
587
+ part_policy.dc_policy_rules.to_a.each { |v| h[v.dc_policy_role_id] = v.permission }
588
+ end
589
+ # p h
590
+ # apply guest role if user has no roles defined
591
+ if ctrl.session[:user_roles].nil?
592
+ role = DcPolicyRole.find_by(system_name: 'guest', active: true)
593
+ return false, 'System guest role not defined!' unless role
594
+ ctrl.session[:user_roles] = [role.id]
595
+ end
596
+ # Check if user has any role that allows him to view part
597
+ can_view, msg = false,''
598
+ ctrl.session[:user_roles].each do |role|
599
+ next unless h[role] # role not yet defined. Will die in next line.
600
+ if h[role] > 0
601
+ can_view = true
602
+ break
603
+ end
604
+ end
605
+ msg = if !can_view
606
+ part_policy ? t(part_policy.message,part_policy.message) : t(default_policy.message,default_policy.message)
607
+ end
608
+ return can_view, msg
609
+ end
610
+
611
+ ####################################################################
612
+ # Return true if user has required role.
613
+ # @example
614
+ # dc_user_has_role('decision_maker', session[:user_id), session[:user_roles]) => true
615
+ #
616
+ # @param [ role ] Role. Can be passed as string or role object.
617
+ # @param [ user ] User id. If not passed session[:user_id] will be used.
618
+ # @param [ roles ] Array of roles that will be searched. If not passed session[:user_roles] will be used.
619
+ ####################################################################
620
+ def dc_user_has_role( role, user=nil, roles=nil )
621
+ if roles.nil?
622
+ roles = (@parent ? @parent.session : session)[:user_roles]
623
+ end
624
+ if user.nil?
625
+ user = (@parent ? @parent.session : session)[:user_id]
626
+ end
627
+ return false if user.nil?
628
+ #
629
+ if role.class == String
630
+ rol = role
631
+ role = DcPolicyRole.find_by(name: rol)
632
+ role = DcPolicyRole.find_by(system_name: rol) if role.nil?
633
+ end
634
+ return false if role.nil?
635
+ # role is included in roles array
636
+ roles.include?(role._id)
637
+ end
638
+
639
+ ####################################################################
640
+ # Returns true if parameter has value of 0, false, no or -. Returns default
641
+ # if parameter has nil value.
642
+ #
643
+ # @example
644
+ # dc_dont?('no') => true
645
+ # dc_dont?(1) => false
646
+ #
647
+ # @param [ string ] String to be examined
648
+ # @param [ default ] Default value when not set. false by default.
649
+ ####################################################################
650
+ def dc_dont?(what, default=false)
651
+ return default if what.nil?
652
+ %w(0 no - false).include?(what.to_s.downcase.strip)
653
+ end
654
+
655
+ ############################################################################
656
+ # Truncates string to the size and takes care, that words are not broken.
657
+ #
658
+ # @example
659
+ # dc_limit_string(description, 100)
660
+ #
661
+ # @param [ string ] Input string
662
+ # @param [ size ] Maximal size of the string
663
+ ############################################################################
664
+ def dc_limit_string(string, size)
665
+ return string if string.size < size
666
+ string = string[0,size]
667
+ string.chop! until (string[-1,1] == ' ' or string == '')
668
+ string << '...'
669
+ end
670
+
671
+ ############################################################################
672
+ # Returns key defined in BigTable as array of choices for use in select fields.
673
+ # It first checks if key is defined only for current site and then if site
674
+ # is not defined.
675
+ #
676
+ # @example
677
+ # eval: dc_big_table 'some-key' # as used on form
678
+ #
679
+ # @param [ string ] Key to be returned
680
+ ############################################################################
681
+ def dc_big_table(key)
682
+ ret = []
683
+ bt = DcBigTable.find_by(key: key, site: dc_get_site._id, active: true)
684
+ bt = DcBigTable.find_by(key: key, site: nil, active: true) if bt.nil?
685
+ return ret if bt.nil?
686
+ #
687
+ locale = I18n.locale.to_s
688
+ bt.dc_big_table_values.each do |v| # iterate each value
689
+ next unless v.active
690
+ desc = ''
691
+ v.dc_big_table_locales.each do |l| # iterate each locale
692
+ if l.locale == locale
693
+ desc = l.description
694
+ break
695
+ end
696
+ end
697
+ desc = v.description if desc.blank? # get description from value description
698
+ desc = v.value if desc.blank? # still blank. Use value as description
699
+ ret << [desc, v.value]
700
+ end
701
+ ret
702
+ end
703
+
704
+ end