drg_cms 0.4.39

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 (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,49 @@
1
+ /**
2
+ * MacOS X like theme for elFinder.
3
+ * Required jquery ui "smoothness" theme.
4
+ *
5
+ * @author Dmitry (dio) Levashov
6
+ **/
7
+
8
+ /* dialogs */
9
+ .std42-dialog, .std42-dialog .ui-widget-content { background-color:#ededed; background-image:none; background-clip: content-box; }
10
+
11
+ /* navbar */
12
+ .elfinder .elfinder-navbar { background:#dde4eb; }
13
+ .elfinder-navbar .ui-state-hover { background:transparent; border-color:transparent; }
14
+ .elfinder-navbar .ui-state-active { background: #3875d7; border-color:#3875d7; color:#fff; }
15
+ /* disabled elfinder */
16
+ .elfinder-disabled .elfinder-navbar .ui-state-active { background: #dadada; border-color:#aaa; color:#fff; }
17
+
18
+
19
+ /* current directory */
20
+ /* selected file in "icons" view */
21
+ .elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover { background:#ccc; }
22
+ /* list view*/
23
+ .elfinder-cwd table tr:nth-child(odd) { background-color:#edf3fe; }
24
+ .elfinder-cwd table tr { border-top:1px solid #fff; }
25
+
26
+ /* common selected background/color */
27
+ .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover,
28
+ .elfinder-cwd table td.ui-state-hover,
29
+ .elfinder-button-menu .ui-state-hover { background: #3875d7; color:#fff;}
30
+ /* disabled elfinder */
31
+ .elfinder-disabled .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover,
32
+ .elfinder-disabled .elfinder-cwd table td.ui-state-hover { background:#dadada;}
33
+
34
+ /* statusbar */
35
+ .elfinder .elfinder-statusbar { color:#555; }
36
+ .elfinder .elfinder-statusbar a { text-decoration:none; color:#555;}
37
+
38
+
39
+ .std42-dialog .elfinder-help, .std42-dialog .elfinder-help .ui-widget-content { background:#fff;}
40
+
41
+ /* contextmenu */
42
+ .elfinder-contextmenu .ui-state-hover { background: #3875d7; color:#fff; }
43
+ .elfinder-contextmenu .ui-state-hover .elfinder-contextmenu-arrow { background-image:url('../img/arrows-active.png'); }
44
+
45
+
46
+
47
+
48
+
49
+
@@ -0,0 +1,12 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require drg_cms/drg_cms
12
+ */
@@ -0,0 +1,26 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require drg_cms/drg_cms
12
+ *= require drg_cms/jquery.datetimepicker.css
13
+ *= #require jquery-ui/all
14
+ *= require jquery-ui/tooltip
15
+ *= require jquery-ui/autocomplete
16
+ *= #require ../javascripts/drg_cms/elfinder/css/elfinder.min.css
17
+ *= #require ../javascripts/drg_cms/elfinder/css/theme.css
18
+ */
19
+
20
+
21
+ /* IMPORTANT
22
+
23
+ Don't forget to update elfinder.min.css and replace all occurences of ../img/ with /assets/elfinder/
24
+ and copy elfinder/img to images/elfinder folder.
25
+
26
+ */
@@ -0,0 +1,673 @@
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
+ class CmseditController < DcApplicationController
26
+ #before_filter :check_authorization, :except => [:login]
27
+ before_action :check_authorization, :except => [:show, :login]
28
+
29
+ ########################################################################
30
+ # check_sort_options
31
+ ########################################################################
32
+ def check_sort_options()
33
+ table_name = @tables.first[1]
34
+ old_sort = session[table_name][:sort].to_s
35
+ sort, direction = old_sort.split(' ')
36
+ # sort is requested
37
+ if params['sort']
38
+ # reverse sort if same selected
39
+ if params['sort'] == sort
40
+ direction = (direction == '1') ? '-1' : '1'
41
+ end
42
+ direction ||= 1
43
+ sort = params[:sort]
44
+ session[table_name][:sort] = "#{params['sort']} #{direction}"
45
+ session[table_name][:page] = 1
46
+ end
47
+ @records.sort( sort => direction.to_i ) if session[table_name][:sort]
48
+ params['sort'] = nil # otherwise there is problem with other links
49
+ end
50
+
51
+ ########################################################################
52
+ # check_filter_options. As simple as possible
53
+ ########################################################################
54
+ def check_filter_options()
55
+ table_name = @tables.first[1]
56
+ session[table_name] ||= {}
57
+ # process page
58
+ session[table_name][:page] = params[:page] if params[:page]
59
+ # new filter is applied
60
+ if params[:filter]
61
+ session[table_name][:filter] =
62
+ if params[:filter] == 'off' # clear all values
63
+ nil
64
+ else
65
+ [ params[:filter_field], params[:filter_oper], params[:record][params[:filter_field]] ].join("\t")
66
+ end
67
+ session[table_name][:page] = 1
68
+ params[:filter] = nil # must be. Otherwise kaminari includes parameter on paging and everything goes wrong
69
+ end
70
+ # if data model has field dc_site_id ensure that only records which belong to the site
71
+ # are selected.
72
+ t = @tables.first[0]
73
+ site_id = dc_get_site._id if dc_get_site
74
+ # dont't filter site if no dc_site_id field or user is ADMIN
75
+ site_id = nil if !t.method_defined?('dc_site_id') or dc_user_can(DcPermission::CAN_ADMIN)
76
+ if session[table_name][:filter]
77
+ field, oper, value = session[table_name][:filter].split( "\t")
78
+ value = /#{value}/ if oper == 'like' # change to regex if like
79
+ @records = if site_id
80
+ t.where(dc_site_id: site_id, field => value)
81
+ else
82
+ t.where(field => value)
83
+ end
84
+ else
85
+ @records = if site_id
86
+ t.where(dc_site_id: site_id)
87
+ else
88
+ t
89
+ end
90
+ end
91
+ # pagination if required
92
+ per_page = (@form['result_set']['per_page'] || 30).to_i
93
+ if per_page > 0
94
+ @records = @records.page(session[table_name][:page]).per(per_page)
95
+ end
96
+ end
97
+
98
+ ########################################################################
99
+ # Index action.
100
+ ########################################################################
101
+ def index
102
+ # If result_set is not defined on form, then it will fail. :return_to should know where to go
103
+ return process_return_to(params[:return_to]) if @form['result_set'].nil?
104
+ #
105
+ if @form['result_set']['filter']
106
+ if respond_to?(@form['result_set']['filter'])
107
+ @records = send @form['result_set']['filter']
108
+ else
109
+ p "Error: result_set:filter: #{@form['result_set']['filter']} not found in controls!"
110
+ end
111
+ else
112
+ if @tables.size == 1 # for now enable only filtering of main tables
113
+ check_filter_options()
114
+ check_sort_options()
115
+ else
116
+ rec = @tables.first[0].find(@ids.first) # top most document.id
117
+ 1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
118
+ @records = rec.send(@tables.last[1].pluralize) # current embedded set
119
+ # sort by order if order field is present in model
120
+ if @tables.last[1].classify.constantize.respond_to?(:order)
121
+ @records = @records.order_by('order asc')
122
+ end
123
+ end
124
+ end
125
+ #
126
+ respond_to do |format|
127
+ format.html { render action: :index }
128
+ format.js { render partial: :result }
129
+ end
130
+ end
131
+
132
+ ########################################################################
133
+ # Filter
134
+ ########################################################################
135
+ def filter
136
+ index
137
+ end
138
+
139
+ ########################################################################
140
+ # Show is (ab)used to do some usefull things
141
+ ########################################################################
142
+ def show
143
+ case
144
+ when params[:id].in?(%w(login logout)) then # show login menu
145
+ session[:edit_mode] = 0
146
+ # dc_collect_menu_forms
147
+ render action: 'show', layout: 'cms'
148
+ # when params[:id] == 'copy_clipboard'
149
+ # return copy_clipboard
150
+ # when params[:id] == 'paste_clipboard'
151
+ # return paste_clipboard
152
+ end
153
+ end
154
+
155
+ ########################################################################
156
+ # Show is used to display menu
157
+ ########################################################################
158
+ def login
159
+ # session[:edit_mode] = 0 if params[:id].in? %w(login logout) # show login menu
160
+ # dc_collect_menu_forms
161
+ render action: 'show', layout: 'cms'
162
+ end
163
+
164
+ ########################################################################
165
+ # New action
166
+ ########################################################################
167
+ def new
168
+ if (m = callback_method('before_new') )
169
+ ret = call_callback_method(m)
170
+ # Don't do anything if return is false
171
+ return index if ret.class == FalseClass
172
+ end
173
+ # clear flash messages.
174
+ flash[:error] = flash[:warning] = flash[:info] = nil
175
+ create_new_empty_record
176
+ table = @tables.last[1] + '.'
177
+ # initial values set on page
178
+ if cookies[:record] and cookies[:record].size > 0
179
+ Marshal.load(cookies[:record]).each do |k,v|
180
+ k = k.to_s
181
+ if k.match(table)
182
+ field = k.split('.').last
183
+ @record.send("#{field}=", v) if @record.respond_to?(field)
184
+ end
185
+ end
186
+ end
187
+ # initial values set in url
188
+ params.each do |k,v|
189
+ if k.match(table)
190
+ field = k.split('.').last
191
+ @record.send("#{field}=", v) if @record.respond_to?(field)
192
+ end
193
+ end
194
+ # This is how we set default values for new record
195
+ dc_new_record() if respond_to?('dc_new_record')
196
+ @parms['action'] = 'create'
197
+ end
198
+
199
+ ########################################################################
200
+ # duplicate_record. For now not needed
201
+ ########################################################################
202
+ =begin
203
+ def duplicate_record(source, dest)
204
+ # params['dup_fields'] += ',' if params['dup_fields'] # for easier field matching
205
+ source.attribute_names.each do |attr_name|
206
+ next if attr_name == '_id'
207
+ p [attr_name, source[attr_name].class]
208
+ if source[attr_name].class == Array
209
+ # dest.save
210
+ source[attr_name].each do |a|
211
+ p a
212
+ rec = dest.send(source[attr_name]).new
213
+ duplicate_record(a, rec)
214
+ rec.save!
215
+ end
216
+ else
217
+ # if duplicate string must be added. Usefull for unique attributes
218
+ add_duplicate = params['dup_fields'].to_s.match(attr_name + ',')
219
+ p ["*",add_duplicate]
220
+ dest.send("#{attr_name}=", source[attr_name])# + (add_duplicate ? ' duplicate' : '')) if source[attr_name] # can be nil
221
+ end
222
+ end
223
+ dest.save!
224
+ end
225
+ =end
226
+
227
+ ########################################################################
228
+ # Create or duplicate action
229
+ ########################################################################
230
+ def create
231
+ # abusing create for turning filter on
232
+ return index if params[:filter].to_s == 'on'
233
+ # not authorized
234
+ unless dc_user_can(DcPermission::CAN_CREATE)
235
+ flash[:error] = t('drgcms.not_authorized')
236
+ return index
237
+ end
238
+ #
239
+ if params['id'].nil? # create record
240
+ create_new_empty_record
241
+ params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
242
+ if save_data
243
+ @parms['action'] = 'update'
244
+ @parms['id'] = @record.id # must be set, for proper update link
245
+ flash[:info] = t('drgcms.doc_saved')
246
+ return process_return_to(params[:return_to]) if params[:return_to]
247
+ render action: :edit
248
+ else
249
+ render action: :new
250
+ end
251
+ else # duplicate record
252
+ find_record
253
+ #create_new_empty_record
254
+ #duplicate_record(@source, @record)
255
+ dup = @record.dup
256
+ dup.created_at = Time.now if dup.respond_to?('created_at') # yep it is also duplicated
257
+
258
+ params['dup_fields'].to_s.split(',').each do |df|
259
+ dup[df] = dup[df] + ' duplicate' if dup.respond_to?(df) # avoid errors
260
+ end
261
+ update_standards(dup)
262
+ dup.save!
263
+ index
264
+ end
265
+ end
266
+
267
+ ########################################################################
268
+ # Edit action.
269
+ ########################################################################
270
+ def edit
271
+ find_record
272
+ if (m = callback_method('before_edit') )
273
+ ret = call_callback_method(m)
274
+ # Don't do anything if return is false
275
+ return index if ret.class == FalseClass
276
+ end
277
+ @parms['action'] = 'update'
278
+ end
279
+
280
+ =begin
281
+ ########################################################################
282
+ # TODO Think of better way for loginng and displaying menu
283
+ # Show action.
284
+ ########################################################################
285
+ def show
286
+ find_record
287
+ # @parms['action'] = 'show'
288
+ end
289
+ =end
290
+
291
+ ########################################################################
292
+ # Update action.
293
+ ########################################################################
294
+ def update
295
+ find_record
296
+ if dc_user_can(DcPermission::CAN_EDIT_ALL) or
297
+ ( @record.respond_to?('created_by') and
298
+ @record.created_by == session[:user_id] and
299
+ dc_user_can(DcPermission::CAN_EDIT) )
300
+ #
301
+ if save_data
302
+ params[:return_to] = 'index' if params[:commit] == t('drgcms.save&back') # save & back
303
+ @parms['action'] = 'update'
304
+ end
305
+ # Process return_to link
306
+ return process_return_to(params[:return_to]) if params[:return_to]
307
+ else
308
+ flash[:error] = t('drgcms.not_authorized')
309
+ end
310
+ render action: :edit
311
+ end
312
+
313
+ ########################################################################
314
+ # Destroy document
315
+ ########################################################################
316
+ def destroy
317
+ find_record
318
+ # Which permission is required to delete
319
+ permission = if params['operation'].nil?
320
+ if @record.respond_to?('created_by') # needs can_delete_all if created_by is present and not owner
321
+ (@record.created_by == session[:user_id]) ? DcPermission::CAN_DELETE : DcPermission::CAN_DELETE_ALL
322
+ else
323
+ DcPermission::CAN_DELETE # by default
324
+ end
325
+ else # enable or disable record
326
+ if @record.respond_to?('created_by')
327
+ (@record.created_by == session[:user_id]) ? DcPermission::CAN_EDIT : DcPermission::CAN_EDIT_ALL
328
+ else
329
+ DcPermission::CAN_EDIT # by default
330
+ end
331
+ end
332
+ ok2delete = dc_user_can(permission)
333
+ #
334
+ case
335
+ # not authorized
336
+ when !ok2delete then
337
+ flash[:error] = t('drgcms.not_authorized')
338
+ return index
339
+ when params['operation'].nil? then
340
+ # Process before delete callback
341
+ if (m = callback_method('before_delete') )
342
+ ret = call_callback_method(m)
343
+ # Don't do anything if return is false
344
+ return index if ret.class == FalseClass
345
+ end
346
+ # document deleted
347
+ if @record.destroy
348
+ save_journal(:delete)
349
+ flash[:info] = t('drgcms.record_deleted')
350
+ # Process after delete callback
351
+ if (m = callback_method('after_delete') ) then call_callback_method(m) end
352
+ # Process return_to link
353
+ return process_return_to(params[:return_to]) if params[:return_to]
354
+ else
355
+ flash[:error] = dc_error_messages_for(@record)
356
+ end
357
+ return index
358
+ # deaktivate document
359
+ when params['operation'] == 'disable' then
360
+ if @record.respond_to?('active')
361
+ @record.active = false
362
+ save_journal(:update, @record.changes)
363
+ update_standards()
364
+ @record.save
365
+ flash[:info] = t('drgcms.doc_disabled')
366
+ end
367
+ # reaktivate document
368
+ when params['operation'] == 'enable' then
369
+ if @record.respond_to?('active')
370
+ @record.active = true
371
+ update_standards()
372
+ save_journal(:update, @record.changes)
373
+ @record.save
374
+ flash[:info] = t('drgcms.doc_enabled')
375
+ end
376
+ end
377
+ #
378
+ @parms['action'] = 'update'
379
+ render action: :edit
380
+ end
381
+
382
+ protected
383
+
384
+ ########################################################################
385
+ # Processes on_save_ok form directive. Data is saved to session for
386
+ # safety reasons.
387
+ ########################################################################
388
+ def process_on_save_ok
389
+ session[:on_save_ok_id] = @record_id
390
+ session[:on_save_ok_commit] = params[:commit]
391
+ eval(params[:on_save_ok])
392
+ end
393
+
394
+ ########################################################################
395
+ # Merges two forms. With a little help of https://www.ruby-forum.com/topic/142809
396
+ ########################################################################
397
+ def forms_merge(hash1, hash2)
398
+ target = hash1.dup
399
+ hash2.keys.each do |key|
400
+ if hash2[key].is_a? Hash and hash1[key].is_a? Hash
401
+ target[key] = forms_merge(hash1[key], hash2[key])
402
+ next
403
+ end
404
+ target[key] = hash2[key] == '/' ? nil : hash2[key]
405
+ end
406
+ # delete keys with nil value
407
+ target.delete_if{ |k,v| v.nil? }
408
+ end
409
+
410
+ ########################################################################
411
+ # Read yaml form file
412
+ ########################################################################
413
+ def read_yaml
414
+ table_name = decamelize_type(params[:table].strip)
415
+ @tables = table_name.split(';').inject([]) { |r,v| r << [v.classify.constantize, v] }
416
+ # split ids passed when embedded document
417
+ ids = params[:ids].to_s.strip.downcase
418
+ @ids = ids.split(';').inject([]) { |r,v| r << v }
419
+ # formname defaults to last table specified
420
+ formname = params[:formname] || @tables.last[1]
421
+ @form = YAML.load_file( dc_find_form_file(formname) )
422
+ # when form extends another form file.
423
+ if @form['extend']
424
+ form = YAML.load_file( dc_find_form_file(@form['extend']) )
425
+ @form = forms_merge(form, @form)
426
+ end
427
+ # add readonly key to form if readonly parameter is passed
428
+ @form['readonly'] = 1 if @form['readonly'] and %w(1 yes true).include?(@form['readonly'].to_s.downcase.strip)
429
+ # p '2',@form
430
+ # !!!!!! Always use strings for key names since @parms['table'] != @parms[:table]
431
+ @parms = { 'table' => table_name, 'ids' => ids, 'formname' => formname,
432
+ 'return_to' => params['return_to'], 'edit_only' => params['edit_only'] }
433
+ end
434
+
435
+ ############################################################################
436
+ # Check if user is authorized for the action.
437
+ # If everything is OK it also loads form definition.
438
+ ############################################################################
439
+ def check_authorization
440
+ # Extend class with methods defined in drgcms_controls module. May include embedded forms therefor ; => _
441
+ controls_string = params[:table].gsub(';','_') + '_control'
442
+ controls = ("DrgcmsControls::#{controls_string.classify}".constantize rescue nil)
443
+ extend controls if controls
444
+ # Just show menu
445
+ return show if params[:action] == 'show'
446
+ # request shouldn't pass
447
+ if session[:user_roles].nil? or params[:table].to_s.strip.downcase.size < 3
448
+ return render(action: 'error', locals: { error: t('drgcms.not_authorized')} )
449
+ end
450
+
451
+ # If user has permission to view table (collection) load form
452
+ if dc_user_can(DcPermission::CAN_VIEW)
453
+ read_yaml
454
+ # Permissions can be also defined on form
455
+ return if @form['permissions'].nil? or @form['permissions']['can_view'].nil?
456
+ return if dc_user_has_role(@form['permissions']['can_view'])
457
+ end
458
+ render(action: 'error', locals: {error: t('drgcms.not_authorized')} )
459
+ end
460
+
461
+ ########################################################################
462
+ # Find record for edit, update or delete.
463
+ ########################################################################
464
+ def find_record
465
+ if @tables.size == 1
466
+ @record = @tables.first[0].find(params[:id])
467
+ else
468
+ rec = @tables.first[0].find(@ids.first) # top most record
469
+ 1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
470
+ @record = rec.send(@tables.last[1].pluralize).find(params[:id]) # record to edit
471
+ end
472
+ end
473
+
474
+ ########################################################################
475
+ # Creates new empty record for new and create action.
476
+ ########################################################################
477
+ def create_new_empty_record
478
+ if @tables.size == 1
479
+ @record = @tables.first[0].new
480
+ else
481
+ rec = @tables.first[0].find(@ids.first) # top most record
482
+ 1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
483
+ @record = rec.send(@tables.last[1].pluralize).new # new record
484
+ end
485
+ end
486
+ =begin
487
+ ########################################################################
488
+ # Get data for multitext_autocomplete field. That is field which is saved as record[kats_****]
489
+ #
490
+ # @param [ name ] Name of field
491
+ ########################################################################
492
+ def get_data_multitext_autocomplete(name)
493
+ r = []
494
+ params['record'].each do |k,v|
495
+ # if it starts with - then it was removed
496
+ r << BSON::ObjectId(v) if k.match("#{name}_") and v[0,1] != '-'
497
+ end
498
+ r.uniq!
499
+ r
500
+ end
501
+ =end
502
+ ########################################################################
503
+ # update_standard fields like updated_by, created_by
504
+ ########################################################################
505
+ def update_standards(record = @record)
506
+ record.updated_by = session[:user_id] if record.respond_to?('updated_by')
507
+ if record.new_record?
508
+ record.created_by = session[:user_id] if record.respond_to?('created_by')
509
+ # set this only initialy. Allow to be set to nil on updates. This documents can then belong to all sites
510
+ # and will be directly visible only to admins
511
+ record.dc_site_id = dc_get_site._id if record.respond_to?('dc_site_id') and record.dc_site_id.nil?
512
+ end
513
+ end
514
+
515
+ ########################################################################
516
+ # Since tabs have been introduced on form it is a little more complicated
517
+ # to get all active field names on form. This method does it.
518
+ ########################################################################
519
+ def fields_on_form()
520
+ fields = []
521
+ if @form['form']['fields']
522
+ # second element of array is hash. Get only hash element
523
+ @form['form']['fields'].each {|field| fields << field[1]}
524
+ else
525
+ @form['form']['tabs'].keys.each do |key|
526
+ @form['form']['tabs'][key].each {|field| fields << field[1]}
527
+ end
528
+ end
529
+ fields
530
+ end
531
+
532
+ ########################################################################
533
+ # Save changes to journal table. Saves all parameters to retrive record if needed.
534
+ #
535
+ # @example usage before save
536
+ # save_journal(@record.changes)
537
+ # @example usage on delete
538
+ # save_journal(true)
539
+ #
540
+ # @param [ changes ] Changes for the record
541
+ ########################################################################
542
+ def save_journal(operation, changes = {})
543
+ # return unless session[:save_journal]
544
+ if operation == :delete
545
+ @record.attributes.each {|k,v| changes[k] = v}
546
+ # elsif operation == :new
547
+ # changes = {}
548
+ end
549
+ #
550
+ if (operation != :update) or changes.size > 0
551
+ # determine site_id
552
+ site_id = @record.site_id if @record.respond_to?('site_id')
553
+ site_id = dc_get_site._id if site_id.nil? and dc_get_site
554
+ DcJournal.create(site_id: site_id,
555
+ operation: operation,
556
+ user_id: session[:user_id],
557
+ tables: params[:table],
558
+ ids: params[:ids],
559
+ doc_id: params[:id],
560
+ ip: request.remote_ip,
561
+ time: Time.now,
562
+ diff: changes.to_json)
563
+ end
564
+ end
565
+
566
+ ########################################################################
567
+ # Determines if callback method is defined in parameters or in model.
568
+ # Returns callback method name or nil if not defined.
569
+ ########################################################################
570
+ def callback_method(key)
571
+ data_key = key.gsub('_','-') # data fields translate _ to -
572
+ cb = case
573
+ when params['data'] && params['data'][data_key] then params['data'][data_key]
574
+ # if dc_ + key method is present in model then it will be called automatically
575
+ when respond_to?('dc_' + key) then 'dc_' + key
576
+ when params[key] then params[key]
577
+ else nil
578
+ end
579
+ # p [ '***********************',key, cb, params['data'],params['key']]
580
+ #
581
+ ret = case
582
+ when cb.nil? then cb # otherwise there will be errors in next lines
583
+ when cb.match('eval ') then cb.sub('eval ','')
584
+ when cb.match('return_to ')
585
+ params[:return_to] = cb.sub('return_to ','')
586
+ return nil
587
+ else cb
588
+ end
589
+ ret
590
+ end
591
+
592
+ ########################################################################
593
+ # Calls callback method.
594
+ ########################################################################
595
+ def call_callback_method(m)
596
+ send(m) if respond_to?(m)
597
+ end
598
+
599
+ ########################################################################
600
+ # Same as javascript_tag helper
601
+ ########################################################################
602
+ def js_tag(script)
603
+ "<script type=\"text/javascript\">#{script}</script>"
604
+ end
605
+
606
+ ########################################################################
607
+ # Process return_to parameter when set on a form or set by callbacks.
608
+ ########################################################################
609
+ def process_return_to(return_to)
610
+ script = case
611
+ when return_to == 'index' then return index
612
+ when return_to.match(/parent\.reload/i) then 'parent.location.href=parent.location.href;'
613
+ when return_to.match(/reload/i) then 'location.href=location.href;'
614
+ else "location.href='#{return_to}'"
615
+ end
616
+ render text: js_tag(script)
617
+ end
618
+
619
+ ########################################################################
620
+ # Save_data. Save only fields on form.
621
+ ########################################################################
622
+ def save_data
623
+ fields = fields_on_form()
624
+ p fields
625
+ return true unless fields.size > 0
626
+ #
627
+ fields.each do |v|
628
+ next if v['type'].match('embedded') # don't wipe embedded fields
629
+ next if params[:edit_only] and params[:edit_only] != v['name'] # otherwise other fields would be wiped
630
+ next unless @record.respond_to?(v['name']) # there can be temporary fields on the form
631
+ #
632
+ # TODO I used to ignore readonly fields. check if this is OK
633
+ # next if v['type'] == 'readonly' or v['readonly'] # ignore readonly fields
634
+ # return value from form field definition
635
+ value = DrgcmsFormField.const_get(v['type'].camelize).get_data(params, v['name'])
636
+ @record.send("#{v['name']}=", value)
637
+ end
638
+ #
639
+ update_standards()
640
+ operation = @record.new_record? ? :new : :update
641
+ # callback methods
642
+ if (m = callback_method('before_save') )
643
+ ret = call_callback_method(m)
644
+ # dont's save if callback method returns false
645
+ return false if ret.class == FalseClass
646
+ end
647
+ # check if model has dc_before_save method
648
+ @record.dc_before_save(self) if @record.respond_to?('dc_before_save')
649
+ #
650
+ changes = @record.changes
651
+ if (saved = @record.save)
652
+ save_journal(operation, changes)
653
+ # callback methods
654
+ if (m = callback_method('after_save') ) then call_callback_method(m) end
655
+ # check if model has dc_after_save method
656
+ @record.dc_after_save(self) if @record.respond_to?('dc_after_save')
657
+ end
658
+ saved
659
+ end
660
+
661
+ ########################################################################
662
+ # Returns true if model has field defined. This might be defined by mongoid,
663
+ # but I didn't found method.
664
+ #
665
+ # @param [model] Model object
666
+ # @param [field_name] Field name to be checked
667
+ ########################################################################
668
+ def model_has_field?(model, field_name)
669
+ model.fields.each {|f| return true if f.first == field_name.to_s}
670
+ false
671
+ end
672
+
673
+ end