drg_cms 0.4.39 → 0.4.53

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -0
  3. data/app/assets/images/drg_cms/file_manager.png +0 -0
  4. data/app/assets/javascripts/drg_cms/drg_cms.js +8 -8
  5. data/app/assets/stylesheets/drg_cms/drg_cms.css +22 -20
  6. data/app/controllers/cmsedit_controller.rb +170 -114
  7. data/app/controllers/dc_application_controller.rb +142 -56
  8. data/app/controllers/dc_common_controller.rb +56 -34
  9. data/app/controllers/dc_main_controller.rb +1 -4
  10. data/app/controllers/drgcms_controls/dc_page_controls.rb +3 -0
  11. data/app/forms/all_options.yml +3 -0
  12. data/app/forms/cms_menu.yml +100 -117
  13. data/app/forms/dc_design.yml +1 -1
  14. data/app/forms/dc_ident.yml +37 -0
  15. data/app/forms/dc_menu_item.yml +1 -1
  16. data/app/forms/dc_permission.yml +1 -1
  17. data/app/forms/dc_site.yml +4 -0
  18. data/app/helpers/cmsedit_helper.rb +44 -80
  19. data/app/helpers/dc_ad_renderer.rb +27 -15
  20. data/app/helpers/dc_application_helper.rb +433 -196
  21. data/app/helpers/dc_big_menu_renderer.rb +40 -40
  22. data/app/helpers/dc_captcha_renderer.rb +38 -25
  23. data/app/helpers/dc_common_renderer.rb +15 -48
  24. data/app/helpers/dc_menu_renderer.rb +30 -20
  25. data/app/helpers/dc_page_renderer.rb +14 -18
  26. data/app/helpers/dc_part_renderer.rb +45 -16
  27. data/app/helpers/dc_piece_renderer.rb +23 -29
  28. data/app/helpers/dc_poll_renderer.rb +31 -20
  29. data/app/helpers/dc_renderer.rb +5 -4
  30. data/app/helpers/dc_simple_menu_renderer.rb +90 -68
  31. data/app/models/{__dc_global_data.rb → __dc_stat.rb} +20 -21
  32. data/app/models/dc_ad.rb +13 -1
  33. data/app/models/dc_ad_stat.rb +6 -0
  34. data/app/models/dc_big_menu.rb +15 -2
  35. data/app/models/dc_big_table.rb +27 -4
  36. data/app/models/dc_big_table_locale.rb +7 -0
  37. data/app/models/dc_big_table_value.rb +7 -0
  38. data/app/models/dc_category.rb +9 -3
  39. data/app/models/dc_design.rb +50 -0
  40. data/app/models/dc_dummy.rb +41 -1
  41. data/app/models/dc_folder_permission.rb +9 -2
  42. data/app/models/{dc_global_data.rb → dc_ident.rb} +20 -22
  43. data/app/models/dc_journal.rb +9 -1
  44. data/app/models/dc_key_value_store.rb +41 -4
  45. data/app/models/dc_link.rb +7 -0
  46. data/app/models/dc_menu.rb +20 -3
  47. data/app/models/dc_menu_item.rb +7 -0
  48. data/app/models/dc_page.rb +31 -12
  49. data/app/models/dc_part.rb +34 -4
  50. data/app/models/dc_permission.rb +32 -12
  51. data/app/models/dc_piece.rb +32 -4
  52. data/app/models/dc_policy.rb +17 -11
  53. data/app/models/dc_policy_role.rb +12 -7
  54. data/app/models/dc_policy_rule.rb +32 -4
  55. data/app/models/dc_poll.rb +8 -0
  56. data/app/models/dc_poll_item.rb +6 -0
  57. data/app/models/dc_simple_menu.rb +18 -3
  58. data/app/models/dc_simple_menu_item.rb +20 -2
  59. data/app/models/dc_site.rb +13 -3
  60. data/app/models/dc_stat.rb +8 -1
  61. data/app/models/dc_user.rb +18 -2
  62. data/app/models/dc_user_role.rb +7 -0
  63. data/app/models/dc_visit.rb +5 -0
  64. data/app/{helpers → models}/drgcms_form_field.rb +171 -73
  65. data/app/views/__dc_at_the_beginning/create.html.erb +9 -0
  66. data/app/views/__dc_at_the_beginning/index.html.erb +19 -0
  67. data/app/views/cmsedit/_edit_stuff.html.erb +2 -0
  68. data/app/views/cmsedit/_form.html.erb +0 -1
  69. data/app/views/dc_mail/subscribe.html.erb +0 -0
  70. data/config/initializers/kaminari_patch.rb +5 -4
  71. data/config/locales/drgcms_en.yml +4 -0
  72. data/config/locales/drgcms_sl.yml +1 -0
  73. data/config/locales/models_en.yml +14 -3
  74. data/config/locales/models_sl.yml +13 -4
  75. data/drg_cms.gemspec +4 -4
  76. data/lib/drg_cms.rb +37 -8
  77. data/lib/drg_cms/engine.rb +2 -2
  78. data/lib/drg_cms/version.rb +3 -2
  79. data/lib/tasks/at_the_beginning.yml +0 -0
  80. data/lib/tasks/dc_at_the_beginning.rake +118 -0
  81. data/lib/tasks/dc_cleanup.rake +19 -7
  82. data/lib/tasks/log_statistics.rb +66 -0
  83. data/lib/tasks/site_statistics.rake +29 -12
  84. data/test/dummy/app/controllers/application_controller.rb +1 -1
  85. data/test/dummy/app/helpers/application_helper.rb +1 -1
  86. metadata +15 -26
  87. data/README.rdoc +0 -3
  88. data/app/controllers/dc_at_the_beginning_controller.rb +0 -120
  89. data/app/controllers/dc_mail_controller.rb +0 -89
  90. data/app/forms/dc_forum_cat.yml +0 -54
  91. data/app/forms/dc_forum_forum.yml +0 -53
  92. data/app/forms/dc_forum_msg.yml +0 -124
  93. data/app/forms/dc_forum_privmsg.yml +0 -125
  94. data/app/forms/dc_forum_topic.yml +0 -131
  95. data/app/forms/dc_mail.yml +0 -88
  96. data/app/forms/dc_mail_address.yml +0 -56
  97. data/app/forms/dc_mail_list.yml +0 -44
  98. data/app/forms/dc_mail_list_member.yml +0 -42
  99. data/app/helpers/dc_mail_renderer.rb +0 -76
  100. data/app/models/dc_mail.rb +0 -64
  101. data/app/models/dc_mail_address.rb +0 -69
  102. data/app/models/dc_mail_list.rb +0 -48
  103. data/app/models/dc_mail_list_member.rb +0 -34
  104. data/app/models/dc_sendmail.rb +0 -48
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c72a699a0ff7d2c728862a4704654a2a23e826ba
4
- data.tar.gz: 162273135c2be3ca8e6ed94a6ee56e00eec2255a
3
+ metadata.gz: 2170ac5278d4127c49a981b33ffc4c7971ab2044
4
+ data.tar.gz: 0d227664c634c0169283c71a1cd3dde2b49a8015
5
5
  SHA512:
6
- metadata.gz: 22893cf485499702a541f39f41bb480cae7244a742f05c2ed5c9c29c37a62ccde3bdf622dd8af22f2bc8f3925bb9c2f8c3e073d68d025c7c7d11a4240f82ec64
7
- data.tar.gz: 9d9c0acaf0a7e8eaa27f945ad2e6fbe9e734cc23fc77282de50647bba0f80d98b416be80d993768f2149c3f7be198aefa0b7d07e34966f219afccacf9118d363
6
+ metadata.gz: dad0892b0d68cbaeed030987a03657e4b2fee598fb42f06bf961ed02a1e5b393201167c3fd391eed286270a22b791fc9a7e7aa3ec6a4ec9f1c8da958a573e990
7
+ data.tar.gz: c6a933b22b907d199464fe1099ec205a12800a2841c80d8c92a1f76cee167ad8f2a69db4f3382b8da843f0dd69319632799398e874038143dd8fd095cbc46495
@@ -0,0 +1,49 @@
1
+ # DrgCms
2
+
3
+ DRG CMS is cms build on strong foundations of Ruby on Rails and Mongo DB.
4
+
5
+ Project Tracking
6
+ ----------------
7
+
8
+ * [DrgCms Website and Documentation](http://www.drgcms.org)
9
+ * [DrgCms Testing website](http://test.drgcms.org)
10
+
11
+ Compatibility
12
+ -------------
13
+
14
+ DRG CMS is tested against MRI 1.9.3, 2.0.0, 2.1.0.
15
+
16
+ Documentation
17
+ -------------
18
+
19
+ Please see the DRG CMS website for up-to-date documentation:
20
+ [www.drgcms.org](http://www.drgcms.org)
21
+
22
+ License
23
+ -------
24
+
25
+ Copyright (c) 2012-2015 Damjan Rems
26
+
27
+ Permission is hereby granted, free of charge, to any person obtaining
28
+ a copy of this software and associated documentation files (the
29
+ "Software"), to deal in the Software without restriction, including
30
+ without limitation the rights to use, copy, modify, merge, publish,
31
+ distribute, sublicense, and/or sell copies of the Software, and to
32
+ permit persons to whom the Software is furnished to do so, subject to
33
+ the following conditions:
34
+
35
+ The above copyright notice and this permission notice shall be
36
+ included in all copies or substantial portions of the Software.
37
+
38
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
39
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
41
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
42
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
43
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
44
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45
+
46
+ Credits
47
+ -------
48
+
49
+ Damjan Rems: damjan dot rems at gmail dot com
@@ -40,12 +40,12 @@ dumpAttributes = function(obj) {
40
40
  };
41
41
 
42
42
  /*******************************************************************
43
- * Used for removing background from iframe element.
43
+ * Used for removing background from iframe element. It is of course not working.
44
44
  *******************************************************************/
45
45
  remove_background_from_iframe = function(obj) {
46
46
  var head = obj.head;
47
47
  var css = '<style type="text/css">' +
48
- 'body{background: none;} ' +
48
+ 'body{background: none; background-picture:none; } ' +
49
49
  '</style>';
50
50
  $(head).append(css);
51
51
  };
@@ -226,10 +226,10 @@ $(document).ready( function() {
226
226
  // console.log(this.contentWindow.document.body.offsetHeight);
227
227
  if (this.contentWindow.document.body.offsetHeight > 10) {
228
228
  this.style.height = (this.contentWindow.document.body.offsetHeight + 30) + 'px';
229
- }
230
- remove_background_from_iframe(this.contentWindow.document);
231
229
  // scroll to it
232
- $('#iframe_edit').dc_scroll_view();
230
+ $('#iframe_edit').dc_scroll_view();
231
+ }
232
+ // remove_background_from_iframe(this.contentWindow.document);
233
233
  });
234
234
 
235
235
  /*******************************************************************
@@ -249,7 +249,7 @@ $(document).ready( function() {
249
249
  }
250
250
  else if (req == "post") {
251
251
  data = $('form').serialize();
252
- alert(data);
252
+ // alert(data);
253
253
  }
254
254
  else {
255
255
  data = {};
@@ -412,7 +412,7 @@ element = $(this).find(':first').attr('id');
412
412
  * Force reload of parent page if this div appears
413
413
  *******************************************************************/
414
414
  $('#div-reload-parent').load( function() {
415
- alert('div-reload-parent 1');
415
+ // alert('div-reload-parent 1');
416
416
  parent.location.href=parent.location.href
417
417
  });
418
418
 
@@ -420,7 +420,7 @@ element = $(this).find(':first').attr('id');
420
420
  * Force reload of parent page if this div appears
421
421
  *******************************************************************/
422
422
  $('#div-reload').load( function() {
423
- alert('div-reload 1');
423
+ // alert('div-reload 1');
424
424
  location.href=location.href
425
425
  });
426
426
 
@@ -24,27 +24,25 @@
24
24
  */
25
25
 
26
26
  body {
27
- font-family: helvetica;
28
- font-size: 13px;
29
- margin: 0px;
30
- vertical-align: middle;
31
- }
32
-
33
- .text-with-select {
34
- width: 24px;
27
+ font-family: helvetica;
28
+ font-size: 12px;
29
+ margin: 0px;
30
+ vertical-align: middle;
35
31
  }
36
32
 
37
33
  textarea, input, select {
38
- font-family: helvetica;
39
- font-size: 13px;
40
- padding: 4px;
41
- border: solid 1px #fff;
42
- box-shadow: rgba(0,0,0, 0.1) 0px 0px 4px;
43
- border-radius: 2px;
44
- background: linear-gradient(#ffe 2%, #fff 100%);
45
- color: #222;
34
+ /*font-family: helvetica;
35
+ font-size: 13px; */
36
+ padding: 4px;
37
+ border: solid 1px #888;
38
+ box-shadow: rgba(0,0,0, 0.1) 0px 0px 4px;
39
+ border-radius: 2px;
40
+ background: linear-gradient(#ffd 4%, #fff 100%);
41
+ color: #222;
46
42
  }
47
43
 
44
+ input { padding: 6px;}
45
+
48
46
  select#record_select { padding: 1px;}
49
47
 
50
48
  hr {
@@ -53,7 +51,6 @@ border: none;
53
51
  height: 2px;
54
52
  }
55
53
 
56
-
57
54
  .div {
58
55
  background-color: red;
59
56
  border: 0px;
@@ -78,6 +75,11 @@ a:link, a:active, a:visited { color: #c43; text-decoration: none; background: tr
78
75
  a:hover { text-decoration: none; color: #000; }
79
76
  a img { border: none; }
80
77
 
78
+
79
+ .text-with-select {
80
+ width: 24px;
81
+ }
82
+
81
83
  .no-borders {
82
84
  padding: 0px;
83
85
  border-spacing: 0px;
@@ -346,14 +348,14 @@ a img { border: none; }
346
348
  border-bottom: 1px solid #eee;
347
349
  }
348
350
  .dc-readonly {
349
- margin-left: 4px;
351
+ margin-left: 2px;
350
352
  margin-top: 2px;
351
353
  padding: 3px;
352
- border: solid 1px #ddd;
354
+ border: solid 1px #aaa;
353
355
  border-right: solid 1px #fff;
354
356
  border-bottom: 0px;
355
357
  border-radius: 2px;
356
- background: linear-gradient(#e8e8e8 2%, #fff 100%);
358
+ background: linear-gradient(#eee 1%, #fff 90%);
357
359
  }
358
360
 
359
361
  .dc-color-odd {
@@ -22,14 +22,66 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  #++
24
24
 
25
+ ########################################################################
26
+ # This is main controller for processing actions by DRG forms. It provides
27
+ # CRUD actions for editing MongoDB documents. DRG CMS does not require controller
28
+ # to be made for every document model but centers all actions into single
29
+ # controller. Logic required to control data entry is provided within DRG
30
+ # forms which are loaded dynamically for every action.
31
+ #
32
+ # Most of data entry controls must therefore be done in document models definitions.
33
+ # And there are controls that cannot be done in document models. Like controls
34
+ # which include url parameters or accessing session variables. This is hard to be done
35
+ # in model therefore cmsedit_controls had to be invented. cmsedit_controls are
36
+ # modules with methods that are injected into cmsedit_controller and act in runtime like
37
+ # they are part of cmsedit_controller.
38
+ #
39
+ # Since Ruby and Rails provide some automagic loading of modules DRG CMS controls must be saved
40
+ # into app/controllers/drgcms_controls folder. Every model can have its own controls file.
41
+ # dc_page model's controls live in dc_page_controls.rb file. If model has embedded document
42
+ # its control's would be found in model_embedded_controls.rb. By convention module names
43
+ # are declared in camel case, so our dc_page_controls.rb declares DrgcmsControls::DcPageControls module.
44
+ #
45
+ # Controls (among other) may contain 6 fixed callback methods.
46
+ # These methods are:
47
+ # * dc_new_record
48
+ # * dc_before_edit
49
+ # * dc_before_save
50
+ # * dc_after_save
51
+ # * dc_before_delete
52
+ # * dc_after_delete
53
+ #
54
+ # Methods dc_before_edit, before_save or before_delete may also effect flow of the application. If
55
+ # method return false (not nil but FalseClass) normal flow of the program is interrupted and last operation
56
+ # is canceled.
57
+ #
58
+ # Second control methods that can be declared in DRG CMS controls are filters for
59
+ # viewing and sorting documents. It is often required that dynamic filters are
60
+ # applied to result_set documents.
61
+ #
62
+ # result_set:
63
+ # filter: current_users_documents
64
+ #
65
+ # Example implemented controls method:
66
+ #
67
+ # def current_users_documents
68
+ # if dc_user_can(DcPermission::CAN_READ)
69
+ # dc_page.where(created_by: session[:user_id])
70
+ # else
71
+ # flash[:error] = 'You can not perform this operation!'
72
+ # nil
73
+ # end
74
+ # end
75
+ #
76
+ # If filter method returns false user will be presented with flash error.
77
+ ########################################################################
25
78
  class CmseditController < DcApplicationController
26
- #before_filter :check_authorization, :except => [:login]
27
79
  before_action :check_authorization, :except => [:show, :login]
28
80
 
29
81
  ########################################################################
30
- # check_sort_options
82
+ # Will check and set sorting options for current result set. Subroutine of index method.
31
83
  ########################################################################
32
- def check_sort_options()
84
+ def check_sort_options() #:nodoc:
33
85
  table_name = @tables.first[1]
34
86
  old_sort = session[table_name][:sort].to_s
35
87
  sort, direction = old_sort.split(' ')
@@ -49,9 +101,9 @@ def check_sort_options()
49
101
  end
50
102
 
51
103
  ########################################################################
52
- # check_filter_options. As simple as possible
104
+ # Will check and set current filter options for result set. Subroutine of index method.
53
105
  ########################################################################
54
- def check_filter_options()
106
+ def check_filter_options() #:nodoc:
55
107
  table_name = @tables.first[1]
56
108
  session[table_name] ||= {}
57
109
  # process page
@@ -100,11 +152,18 @@ end
100
152
  ########################################################################
101
153
  def index
102
154
  # 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
- #
155
+ if @form['result_set'].nil?
156
+ return process_return_to(params[:return_to] || 'reload')
157
+ end
158
+ # result set is defined by filter method in control object
105
159
  if @form['result_set']['filter']
106
160
  if respond_to?(@form['result_set']['filter'])
107
161
  @records = send @form['result_set']['filter']
162
+ # something iz wrong. flash[] should have explanation.
163
+ return render(action: :index) if @records.class == FalseClass
164
+ # pagination
165
+ per_page = (@form['result_set']['per_page'] || 30).to_i
166
+ @records = @records.page(params[:page]).per(per_page) if per_page > 0
108
167
  else
109
168
  p "Error: result_set:filter: #{@form['result_set']['filter']} not found in controls!"
110
169
  end
@@ -115,6 +174,7 @@ def index
115
174
  else
116
175
  rec = @tables.first[0].find(@ids.first) # top most document.id
117
176
  1.upto(@tables.size - 2) { |i| rec = rec.send(@tables[i][1].pluralize).find(@ids[i]) } # find embedded childrens by ids
177
+ # p rec,@tables, @tables.last[1].pluralize
118
178
  @records = rec.send(@tables.last[1].pluralize) # current embedded set
119
179
  # sort by order if order field is present in model
120
180
  if @tables.last[1].classify.constantize.respond_to?(:order)
@@ -130,39 +190,35 @@ def index
130
190
  end
131
191
 
132
192
  ########################################################################
133
- # Filter
193
+ # Filter action.
134
194
  ########################################################################
135
195
  def filter
136
196
  index
137
197
  end
138
198
 
139
199
  ########################################################################
140
- # Show is (ab)used to do some usefull things
200
+ # Show is (ab)used for direct login and logout into cmsedit controller. Login
201
+ # and logout actions can be directly performed by calling http://site.com/cmsedit/login
141
202
  ########################################################################
142
203
  def show
143
204
  case
144
205
  when params[:id].in?(%w(login logout)) then # show login menu
145
206
  session[:edit_mode] = 0
146
- # dc_collect_menu_forms
147
207
  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
208
  end
153
209
  end
154
210
 
155
211
  ########################################################################
156
212
  # Show is used to display menu
157
213
  ########################################################################
158
- def login
214
+ def login #:nodoc:
159
215
  # session[:edit_mode] = 0 if params[:id].in? %w(login logout) # show login menu
160
216
  # dc_collect_menu_forms
161
217
  render action: 'show', layout: 'cms'
162
218
  end
163
219
 
164
220
  ########################################################################
165
- # New action
221
+ # New action.
166
222
  ########################################################################
167
223
  def new
168
224
  if (m = callback_method('before_new') )
@@ -197,35 +253,55 @@ def new
197
253
  end
198
254
 
199
255
  ########################################################################
200
- # duplicate_record. For now not needed
256
+ # Duplicate embedded document. Since embedded documents are returned differently
257
+ # then top level document. Subroutine of duplicate_socument.
201
258
  ########################################################################
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
259
+ def duplicate_embedded(source) #:nodoc:
260
+ # TODO Works for two embedded levels. Dies with third and more levels.
261
+ dest = {}
262
+ source.each do |attr_name, value|
263
+ next if attr_name == '_id' # don't duplicate _id
264
+ if value.class == Array
265
+ dest[attr_name] = []
266
+ value.each do |ar|
267
+ dest[attr_name] << duplicate_embedded(ar)
268
+ end
269
+ else
270
+ # if duplicate string must be added. Useful for unique attributes
218
271
  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
272
+ dest[attr_name] = value
273
+ dest[attr_name] << ' dup' if add_duplicate
221
274
  end
222
275
  end
223
- dest.save!
276
+ dest
224
277
  end
225
- =end
226
278
 
227
279
  ########################################################################
228
- # Create or duplicate action
280
+ # Will create duplicate document of source document. This method is used for
281
+ # duplicating document and is called from create action.
282
+ ########################################################################
283
+ def duplicate_document(source)
284
+ dest = {}
285
+ source.attribute_names.each do |attr_name|
286
+ next if attr_name == '_id' # don't duplicate _id
287
+ # if duplicate string must be added. Useful for unique attributes
288
+ add_duplicate = params['dup_fields'].to_s.match(attr_name + ',')
289
+ dest[attr_name] = source[attr_name]
290
+ dest[attr_name] << ' dup' if add_duplicate
291
+ end
292
+ #
293
+ source.embedded_relations.keys.each do |embedded_name|
294
+ next if source[embedded_name].nil? # it happens
295
+ dest[embedded_name] = []
296
+ source[embedded_name].each do |ar|
297
+ dest[embedded_name] << duplicate_embedded(ar)
298
+ end
299
+ end
300
+ dest
301
+ end
302
+
303
+ ########################################################################
304
+ # Create (or duplicate) action. Action is also used for turning filter on.
229
305
  ########################################################################
230
306
  def create
231
307
  # abusing create for turning filter on
@@ -250,16 +326,12 @@ def create
250
326
  end
251
327
  else # duplicate record
252
328
  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
329
+ params['dup_fields'] += ',' if params['dup_fields'] # for easier field matching
330
+ new_doc = duplicate_document(@record)
331
+ create_new_empty_record(new_doc)
332
+ update_standards()
333
+ @record.save!
257
334
 
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
335
  index
264
336
  end
265
337
  end
@@ -277,22 +349,19 @@ def edit
277
349
  @parms['action'] = 'update'
278
350
  end
279
351
 
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
352
  ########################################################################
292
353
  # Update action.
293
354
  ########################################################################
294
355
  def update
295
356
  find_record
357
+ # check if record was not updated in mean time
358
+ if @record.respond_to?(:updated_at)
359
+ if params[:last_updated_at].to_i != @record.updated_at.to_i
360
+ flash[:error] = t('drgcms.updated_by_other')
361
+ return render(action: :edit)
362
+ end
363
+ end
364
+ #
296
365
  if dc_user_can(DcPermission::CAN_EDIT_ALL) or
297
366
  ( @record.respond_to?('created_by') and
298
367
  @record.created_by == session[:user_id] and
@@ -311,7 +380,7 @@ def update
311
380
  end
312
381
 
313
382
  ########################################################################
314
- # Destroy document
383
+ # Destroy action. Used also for enabling and disabling record.
315
384
  ########################################################################
316
385
  def destroy
317
386
  find_record
@@ -381,6 +450,7 @@ end
381
450
 
382
451
  protected
383
452
 
453
+ =begin
384
454
  ########################################################################
385
455
  # Processes on_save_ok form directive. Data is saved to session for
386
456
  # safety reasons.
@@ -390,11 +460,13 @@ def process_on_save_ok
390
460
  session[:on_save_ok_commit] = params[:commit]
391
461
  eval(params[:on_save_ok])
392
462
  end
463
+ =end
393
464
 
394
465
  ########################################################################
395
- # Merges two forms. With a little help of https://www.ruby-forum.com/topic/142809
466
+ # Merges two forms when current form extends other form. Subroutine of read_yaml.
467
+ # With a little help of https://www.ruby-forum.com/topic/142809
396
468
  ########################################################################
397
- def forms_merge(hash1, hash2)
469
+ def forms_merge(hash1, hash2)
398
470
  target = hash1.dup
399
471
  hash2.keys.each do |key|
400
472
  if hash2[key].is_a? Hash and hash1[key].is_a? Hash
@@ -408,7 +480,7 @@ def forms_merge(hash1, hash2)
408
480
  end
409
481
 
410
482
  ########################################################################
411
- # Read yaml form file
483
+ # Read drgcms form into yaml object. Subroutine of check_authorization.
412
484
  ########################################################################
413
485
  def read_yaml
414
486
  table_name = decamelize_type(params[:table].strip)
@@ -424,8 +496,8 @@ def read_yaml
424
496
  form = YAML.load_file( dc_find_form_file(@form['extend']) )
425
497
  @form = forms_merge(form, @form)
426
498
  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)
499
+ # add readonly key to form if readonly parameter is passed in url
500
+ @form['readonly'] = 1 if params['readonly'] and %w(1 yes true).include?(params['readonly'].to_s.downcase.strip)
429
501
  # p '2',@form
430
502
  # !!!!!! Always use strings for key names since @parms['table'] != @parms[:table]
431
503
  @parms = { 'table' => table_name, 'ids' => ids, 'formname' => formname,
@@ -433,10 +505,11 @@ def read_yaml
433
505
  end
434
506
 
435
507
  ############################################################################
436
- # Check if user is authorized for the action.
437
- # If everything is OK it also loads form definition.
508
+ # Check if user is authorized for the action. If authorization is in order it will also
509
+ # load DRG form.
438
510
  ############################################################################
439
511
  def check_authorization
512
+ params[:table] ||= params[:formname]
440
513
  # Extend class with methods defined in drgcms_controls module. May include embedded forms therefor ; => _
441
514
  controls_string = params[:table].gsub(';','_') + '_control'
442
515
  controls = ("DrgcmsControls::#{controls_string.classify}".constantize rescue nil)
@@ -459,9 +532,9 @@ def check_authorization
459
532
  end
460
533
 
461
534
  ########################################################################
462
- # Find record for edit, update or delete.
535
+ # Find current record (document) for edit, update or delete.
463
536
  ########################################################################
464
- def find_record
537
+ def find_record #:nodoc:
465
538
  if @tables.size == 1
466
539
  @record = @tables.first[0].find(params[:id])
467
540
  else
@@ -474,33 +547,18 @@ end
474
547
  ########################################################################
475
548
  # Creates new empty record for new and create action.
476
549
  ########################################################################
477
- def create_new_empty_record
550
+ def create_new_empty_record(initial_data=nil) #:nodoc:
478
551
  if @tables.size == 1
479
- @record = @tables.first[0].new
552
+ @record = @tables.first[0].new(initial_data)
480
553
  else
481
554
  rec = @tables.first[0].find(@ids.first) # top most record
482
555
  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
556
+ @record = rec.send(@tables.last[1].pluralize).new(initial_data) # new record
484
557
  end
485
558
  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
559
+
502
560
  ########################################################################
503
- # update_standard fields like updated_by, created_by
561
+ # Update standard fields like updated_by, created_by, site_id
504
562
  ########################################################################
505
563
  def update_standards(record = @record)
506
564
  record.updated_by = session[:user_id] if record.respond_to?('updated_by')
@@ -514,9 +572,9 @@ end
514
572
 
515
573
  ########################################################################
516
574
  # 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.
575
+ # to get all edit fields on form. This method does it. Subroutine of save_data.
518
576
  ########################################################################
519
- def fields_on_form()
577
+ def fields_on_form() #:nodoc:
520
578
  fields = []
521
579
  if @form['form']['fields']
522
580
  # second element of array is hash. Get only hash element
@@ -530,14 +588,11 @@ def fields_on_form()
530
588
  end
531
589
 
532
590
  ########################################################################
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
591
+ # Save document changes to journal table. Saves all parameters to retrieve record if needed.
592
+ #
593
+ # [Parameters:]
594
+ # [operation] 'delete' or 'update'.
595
+ # [changes] Current document changed fields.
541
596
  ########################################################################
542
597
  def save_journal(operation, changes = {})
543
598
  # return unless session[:save_journal]
@@ -564,10 +619,10 @@ def save_journal(operation, changes = {})
564
619
  end
565
620
 
566
621
  ########################################################################
567
- # Determines if callback method is defined in parameters or in model.
622
+ # Determines if callback method is defined in parameters or in control module.
568
623
  # Returns callback method name or nil if not defined.
569
624
  ########################################################################
570
- def callback_method(key)
625
+ def callback_method(key) #:nodoc:
571
626
  data_key = key.gsub('_','-') # data fields translate _ to -
572
627
  cb = case
573
628
  when params['data'] && params['data'][data_key] then params['data'][data_key]
@@ -576,7 +631,6 @@ def callback_method(key)
576
631
  when params[key] then params[key]
577
632
  else nil
578
633
  end
579
- # p [ '***********************',key, cb, params['data'],params['key']]
580
634
  #
581
635
  ret = case
582
636
  when cb.nil? then cb # otherwise there will be errors in next lines
@@ -592,19 +646,22 @@ end
592
646
  ########################################################################
593
647
  # Calls callback method.
594
648
  ########################################################################
595
- def call_callback_method(m)
649
+ def call_callback_method(m) #:nodoc:
596
650
  send(m) if respond_to?(m)
597
651
  end
598
652
 
599
653
  ########################################################################
600
- # Same as javascript_tag helper
654
+ # Same as javascript_tag helper. Ajax form actions may results in javascript code to be returned.
655
+ # This will add javascript tag to code.
601
656
  ########################################################################
602
- def js_tag(script)
657
+ def js_tag(script) #:nodoc:
603
658
  "<script type=\"text/javascript\">#{script}</script>"
604
659
  end
605
660
 
606
661
  ########################################################################
607
- # Process return_to parameter when set on a form or set by callbacks.
662
+ # Process return_to parameter when defined on form or set by controls methods.
663
+ # params['return_to'] may contain 'index', 'reload' or 'parent.reload' or any valid url to
664
+ # return to, after successful controls method call.
608
665
  ########################################################################
609
666
  def process_return_to(return_to)
610
667
  script = case
@@ -617,37 +674,34 @@ def process_return_to(return_to)
617
674
  end
618
675
 
619
676
  ########################################################################
620
- # Save_data. Save only fields on form.
677
+ # Save edited data. Take care that only fields defined on form are affected.
678
+ # It also saves journal data and calls before_save and after_save callbacks.
621
679
  ########################################################################
622
680
  def save_data
623
681
  fields = fields_on_form()
624
- p fields
625
682
  return true unless fields.size > 0
626
683
  #
627
684
  fields.each do |v|
628
685
  next if v['type'].match('embedded') # don't wipe embedded fields
629
686
  next if params[:edit_only] and params[:edit_only] != v['name'] # otherwise other fields would be wiped
630
687
  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
688
  # return value from form field definition
635
689
  value = DrgcmsFormField.const_get(v['type'].camelize).get_data(params, v['name'])
636
690
  @record.send("#{v['name']}=", value)
637
691
  end
638
- #
639
- update_standards()
692
+ #
640
693
  operation = @record.new_record? ? :new : :update
641
- # callback methods
694
+ # controls callback method
642
695
  if (m = callback_method('before_save') )
643
696
  ret = call_callback_method(m)
644
697
  # dont's save if callback method returns false
645
698
  return false if ret.class == FalseClass
646
699
  end
647
- # check if model has dc_before_save method
700
+ # maybe model has dc_before_save method defined. Call it.
648
701
  @record.dc_before_save(self) if @record.respond_to?('dc_before_save')
649
702
  #
650
703
  changes = @record.changes
704
+ update_standards() if changes.size > 0 # update only if there has been some changes
651
705
  if (saved = @record.save)
652
706
  save_journal(operation, changes)
653
707
  # callback methods
@@ -658,6 +712,7 @@ def save_data
658
712
  saved
659
713
  end
660
714
 
715
+ =begin
661
716
  ########################################################################
662
717
  # Returns true if model has field defined. This might be defined by mongoid,
663
718
  # but I didn't found method.
@@ -669,5 +724,6 @@ def model_has_field?(model, field_name)
669
724
  model.fields.each {|f| return true if f.first == field_name.to_s}
670
725
  false
671
726
  end
727
+ =end
672
728
 
673
729
  end