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,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