agile_rails 0.0.0.1

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 (259) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +285 -0
  5. data/Rakefile +39 -0
  6. data/agile_rails.gemspec +36 -0
  7. data/app/assets/fonts/ibm-plex-sans-300.woff2 +0 -0
  8. data/app/assets/fonts/ibm-plex-sans-400.woff2 +0 -0
  9. data/app/assets/fonts/ibm-plex-sans-500.woff2 +0 -0
  10. data/app/assets/fonts/ibm-plex-sans-600.woff2 +0 -0
  11. data/app/assets/fonts/ibm-plex-sans-700.woff2 +0 -0
  12. data/app/assets/fonts/ibm-plex-sans-italic.woff2 +0 -0
  13. data/app/assets/images/32px.png +0 -0
  14. data/app/assets/images/throbber.gif +0 -0
  15. data/app/assets/javascripts/agile/agile.js +1489 -0
  16. data/app/assets/javascripts/agile/jquery-migrate.js +702 -0
  17. data/app/assets/javascripts/agile/jquery.bpopup.js +372 -0
  18. data/app/assets/javascripts/agile/jquery.datetimepicker.js +1353 -0
  19. data/app/assets/javascripts/agile/jstree.min.js +6 -0
  20. data/app/assets/javascripts/agile/select-multiple.js +459 -0
  21. data/app/assets/javascripts/agile/some_scripts.js +33 -0
  22. data/app/assets/javascripts/agile.js +22 -0
  23. data/app/assets/javascripts/agile_application.js +22 -0
  24. data/app/assets/javascripts/agile_editor.js +22 -0
  25. data/app/assets/stylesheets/agile/agile.css +1882 -0
  26. data/app/assets/stylesheets/agile/agile_apps.css +149 -0
  27. data/app/assets/stylesheets/agile/jquery.datetimepicker.css +304 -0
  28. data/app/assets/stylesheets/agile/jstree.css +1107 -0
  29. data/app/assets/stylesheets/agile/select-multiple.css +110 -0
  30. data/app/assets/stylesheets/agile/th-bg.png +0 -0
  31. data/app/assets/stylesheets/agile/theme.css +49 -0
  32. data/app/assets/stylesheets/agile.css +21 -0
  33. data/app/assets/stylesheets/agile_application.css +20 -0
  34. data/app/assets/stylesheets/agile_editor.css +19 -0
  35. data/app/controllers/agile_application_controller.rb +735 -0
  36. data/app/controllers/agile_common_controller.rb +345 -0
  37. data/app/controllers/agile_controller.rb +977 -0
  38. data/app/controllers/agile_main_controller.rb +36 -0
  39. data/app/controls/agile_control.rb +120 -0
  40. data/app/controls/agile_report.rb +364 -0
  41. data/app/controls/ar_category_control.rb +39 -0
  42. data/app/controls/ar_help_control.rb +139 -0
  43. data/app/controls/ar_image_control.rb +180 -0
  44. data/app/controls/ar_journal_control.rb +47 -0
  45. data/app/controls/ar_menu_item_control.rb +55 -0
  46. data/app/controls/ar_page_control.rb +64 -0
  47. data/app/controls/ar_poll_result_control.rb +84 -0
  48. data/app/controls/ar_setup_control.rb +62 -0
  49. data/app/controls/belongs_to_control.rb +61 -0
  50. data/app/controls/browse_models_control.rb +98 -0
  51. data/app/controls/settings_form_control.rb +137 -0
  52. data/app/forms/agile_help.yml +112 -0
  53. data/app/forms/agile_menu.yml +140 -0
  54. data/app/forms/agile_report_defaults.yml +39 -0
  55. data/app/forms/all_options.yml +810 -0
  56. data/app/forms/ar_ad.yml +121 -0
  57. data/app/forms/ar_big_table.yml +60 -0
  58. data/app/forms/ar_big_table_value.yml +52 -0
  59. data/app/forms/ar_browse_fields.yml +35 -0
  60. data/app/forms/ar_browse_models.yml +48 -0
  61. data/app/forms/ar_category.yml +73 -0
  62. data/app/forms/ar_category_as_tree.yml +31 -0
  63. data/app/forms/ar_design.yml +75 -0
  64. data/app/forms/ar_filter.yml +52 -0
  65. data/app/forms/ar_folder_permission.yml +56 -0
  66. data/app/forms/ar_folder_rule.yml +48 -0
  67. data/app/forms/ar_gallery.yml +55 -0
  68. data/app/forms/ar_image.yml +126 -0
  69. data/app/forms/ar_image_search.yml +83 -0
  70. data/app/forms/ar_journal.yml +76 -0
  71. data/app/forms/ar_json_ld.yml +56 -0
  72. data/app/forms/ar_key_value.yml +33 -0
  73. data/app/forms/ar_key_value_store.yml +33 -0
  74. data/app/forms/ar_link.yml +60 -0
  75. data/app/forms/ar_menu.yml +67 -0
  76. data/app/forms/ar_menu_item.yml +141 -0
  77. data/app/forms/ar_page.yml +187 -0
  78. data/app/forms/ar_part.yml +91 -0
  79. data/app/forms/ar_permission.yml +52 -0
  80. data/app/forms/ar_permission_rule.yml +40 -0
  81. data/app/forms/ar_piece.yml +106 -0
  82. data/app/forms/ar_policy.yml +64 -0
  83. data/app/forms/ar_policy_rule.yml +42 -0
  84. data/app/forms/ar_policy_rule_nocms.yml +40 -0
  85. data/app/forms/ar_poll.yml +118 -0
  86. data/app/forms/ar_poll_item.yml +78 -0
  87. data/app/forms/ar_poll_result.yml +88 -0
  88. data/app/forms/ar_poll_result_export.yml +35 -0
  89. data/app/forms/ar_removed_url.yml +41 -0
  90. data/app/forms/ar_role.yml +43 -0
  91. data/app/forms/ar_seo.yml +32 -0
  92. data/app/forms/ar_setup.yml +45 -0
  93. data/app/forms/ar_site.yml +149 -0
  94. data/app/forms/ar_steps_template.yml +51 -0
  95. data/app/forms/ar_user.yml +140 -0
  96. data/app/forms/ar_user_role.yml +57 -0
  97. data/app/forms/help/dc_category_as_tree.en +4 -0
  98. data/app/forms/help/dc_category_as_tree.sl +5 -0
  99. data/app/forms/json_ld_schema.yml +168 -0
  100. data/app/helpers/agile_application_helper.rb +1162 -0
  101. data/app/helpers/agile_category_helper.rb +128 -0
  102. data/app/helpers/agile_common_helper.rb +308 -0
  103. data/app/helpers/agile_edit_helper.rb +645 -0
  104. data/app/helpers/agile_helper.rb +509 -0
  105. data/app/helpers/agile_index_helper.rb +677 -0
  106. data/app/helpers/ar_image_helper.rb +128 -0
  107. data/app/models/agile_form_fields/action.rb +61 -0
  108. data/app/models/agile_form_fields/agile_form_field.rb +322 -0
  109. data/app/models/agile_form_fields/belongs_to.rb +112 -0
  110. data/app/models/agile_form_fields/check_box.rb +73 -0
  111. data/app/models/agile_form_fields/comment.rb +62 -0
  112. data/app/models/agile_form_fields/date_picker.rb +104 -0
  113. data/app/models/agile_form_fields/date_select.rb +68 -0
  114. data/app/models/agile_form_fields/datetime_picker.rb +88 -0
  115. data/app/models/agile_form_fields/datetime_select.rb +73 -0
  116. data/app/models/agile_form_fields/file_field.rb +52 -0
  117. data/app/models/agile_form_fields/file_select.rb +69 -0
  118. data/app/models/agile_form_fields/hidden_field.rb +51 -0
  119. data/app/models/agile_form_fields/html_field.rb +69 -0
  120. data/app/models/agile_form_fields/journal_diff.rb +62 -0
  121. data/app/models/agile_form_fields/link_to.rb +69 -0
  122. data/app/models/agile_form_fields/method.rb +66 -0
  123. data/app/models/agile_form_fields/multitext_autocomplete.rb +215 -0
  124. data/app/models/agile_form_fields/number_field.rb +92 -0
  125. data/app/models/agile_form_fields/password_field.rb +63 -0
  126. data/app/models/agile_form_fields/radio_button.rb +95 -0
  127. data/app/models/agile_form_fields/readonly.rb +77 -0
  128. data/app/models/agile_form_fields/select.rb +281 -0
  129. data/app/models/agile_form_fields/submit_tag.rb +58 -0
  130. data/app/models/agile_form_fields/text_area.rb +61 -0
  131. data/app/models/agile_form_fields/text_autocomplete.rb +171 -0
  132. data/app/models/agile_form_fields/text_field.rb +55 -0
  133. data/app/models/agile_form_fields/text_with_select.rb +94 -0
  134. data/app/models/agile_form_fields/tree_select.rb +170 -0
  135. data/app/models/ar_big_table.rb +82 -0
  136. data/app/models/ar_big_table_value.rb +53 -0
  137. data/app/models/ar_category.rb +109 -0
  138. data/app/models/ar_design.rb +116 -0
  139. data/app/models/ar_filter.rb +200 -0
  140. data/app/models/ar_folder_permission.rb +50 -0
  141. data/app/models/ar_folder_rule.rb +47 -0
  142. data/app/models/ar_gallery.rb +53 -0
  143. data/app/models/ar_image.rb +198 -0
  144. data/app/models/ar_internals.rb +60 -0
  145. data/app/models/ar_journal.rb +46 -0
  146. data/app/models/ar_json_ld.rb +131 -0
  147. data/app/models/ar_key_value_store.rb +128 -0
  148. data/app/models/ar_link.rb +48 -0
  149. data/app/models/ar_memory.rb +172 -0
  150. data/app/models/ar_menu.rb +144 -0
  151. data/app/models/ar_menu_item.rb +106 -0
  152. data/app/models/ar_page.rb +74 -0
  153. data/app/models/ar_part.rb +66 -0
  154. data/app/models/ar_permission.rb +180 -0
  155. data/app/models/ar_permission_rule.rb +65 -0
  156. data/app/models/ar_policy.rb +78 -0
  157. data/app/models/ar_policy_rule.rb +65 -0
  158. data/app/models/ar_poll.rb +74 -0
  159. data/app/models/ar_poll_item.rb +47 -0
  160. data/app/models/ar_poll_result.rb +38 -0
  161. data/app/models/ar_removed_url.rb +42 -0
  162. data/app/models/ar_role.rb +84 -0
  163. data/app/models/ar_setup.rb +115 -0
  164. data/app/models/ar_site.rb +68 -0
  165. data/app/models/ar_temp.rb +150 -0
  166. data/app/models/ar_user.rb +72 -0
  167. data/app/models/ar_user_group.rb +38 -0
  168. data/app/models/ar_user_role.rb +54 -0
  169. data/app/models/ar_visit.rb +41 -0
  170. data/app/models/concerns/ar_page_concern.rb +128 -0
  171. data/app/models/concerns/ar_part_concern.rb +48 -0
  172. data/app/models/concerns/ar_piece_concern.rb +48 -0
  173. data/app/models/concerns/ar_policy_rule_concern.rb +87 -0
  174. data/app/models/concerns/ar_seo_concern.rb +66 -0
  175. data/app/models/concerns/ar_site_concern.rb +103 -0
  176. data/app/models/concerns/ar_user_concern.rb +195 -0
  177. data/app/renderers/agile_common_renderer.rb +93 -0
  178. data/app/renderers/agile_renderer.rb +59 -0
  179. data/app/renderers/ar_ad_renderer.rb +219 -0
  180. data/app/renderers/ar_captcha_renderer.rb +113 -0
  181. data/app/renderers/ar_common_renderer.rb +90 -0
  182. data/app/renderers/ar_gallery_renderer.rb +107 -0
  183. data/app/renderers/ar_menu_renderer.rb +195 -0
  184. data/app/renderers/ar_page_renderer.rb +147 -0
  185. data/app/renderers/ar_part_renderer.rb +235 -0
  186. data/app/renderers/ar_piece_renderer.rb +119 -0
  187. data/app/renderers/ar_poll_renderer.rb +272 -0
  188. data/app/views/agile/_edit_stuff.html.erb +57 -0
  189. data/app/views/agile/_form.html.erb +24 -0
  190. data/app/views/agile/_result.html.erb +28 -0
  191. data/app/views/agile/edit.html.erb +13 -0
  192. data/app/views/agile/error.html.erb +2 -0
  193. data/app/views/agile/index.html.erb +14 -0
  194. data/app/views/agile/login.html.erb +19 -0
  195. data/app/views/agile/new.html.erb +12 -0
  196. data/app/views/agile_common/_help.html.erb +18 -0
  197. data/app/views/agile_common/_iframe_edit.html.erb +2 -0
  198. data/app/views/agile_common/paste_clipboard.html.erb +17 -0
  199. data/app/views/layouts/agile.html.erb +17 -0
  200. data/app/views/layouts/content.html.erb +20 -0
  201. data/app/views/models/dump_models.html.erb +47 -0
  202. data/config/initializers/kaminari_patch.rb +56 -0
  203. data/config/locales/agile_de.yml +138 -0
  204. data/config/locales/agile_en.yml +162 -0
  205. data/config/locales/agile_sl.yml +163 -0
  206. data/config/locales/datetimepicker.yml +19 -0
  207. data/config/locales/de.yml +231 -0
  208. data/config/locales/en.yml +13 -0
  209. data/config/locales/kaminari.yml +26 -0
  210. data/config/locales/models_en.yml +1032 -0
  211. data/config/locales/models_sl.yml +1065 -0
  212. data/config/locales/sl.yml +211 -0
  213. data/db/migrate/20240120160001_add_sessions_table.rb +12 -0
  214. data/db/migrate/20240120160002_ar_big_table.rb +17 -0
  215. data/db/migrate/20240120160003_ar_big_table_value.rb +18 -0
  216. data/db/migrate/20240120160004_ar_category.rb +22 -0
  217. data/db/migrate/20240120160005_ar_design.rb +20 -0
  218. data/db/migrate/20240120160006_ar_filter.rb +17 -0
  219. data/db/migrate/20240120160007_ar_gallery.rb +21 -0
  220. data/db/migrate/20240120160008_ar_journal.rb +19 -0
  221. data/db/migrate/20240120160009_ar_key_value_store.rb +11 -0
  222. data/db/migrate/20240120160010_ar_link.rb +19 -0
  223. data/db/migrate/20240120160011_ar_memory.rb +8 -0
  224. data/db/migrate/20240120160012_ar_menu.rb +21 -0
  225. data/db/migrate/20240120160013_ar_menu_item.rb +28 -0
  226. data/db/migrate/20240120160014_ar_page.rb +50 -0
  227. data/db/migrate/20240120160015_ar_part.rb +33 -0
  228. data/db/migrate/20240120160016_ar_permission.rb +16 -0
  229. data/db/migrate/20240120160017_ar_permission_rule.rb +17 -0
  230. data/db/migrate/20240120160018_ar_piece.rb +28 -0
  231. data/db/migrate/20240120160019_ar_policy.rb +21 -0
  232. data/db/migrate/20240120160020_ar_policy_rule.rb +18 -0
  233. data/db/migrate/20240120160021_ar_poll.rb +27 -0
  234. data/db/migrate/20240120160022_ar_poll_item.rb +23 -0
  235. data/db/migrate/20240120160023_ar_poll_result.rb +14 -0
  236. data/db/migrate/20240120160024_ar_removed_url.rb +16 -0
  237. data/db/migrate/20240120160025_ar_role.rb +17 -0
  238. data/db/migrate/20240120160026_ar_site.rb +37 -0
  239. data/db/migrate/20240120160027_ar_temp.rb +11 -0
  240. data/db/migrate/20240120160028_ar_user.rb +42 -0
  241. data/db/migrate/20240120160029_ar_user_group.rb +12 -0
  242. data/db/migrate/20240120160030_ar_user_role.rb +18 -0
  243. data/db/migrate/20240120160031_ar_visit.rb +15 -0
  244. data/db/migrate/20240703016001_ar_setup.rb +16 -0
  245. data/db/migrate/20240703016002_ar_folder_permission.rb +15 -0
  246. data/db/migrate/20240703016003_ar_folder_rule.rb +14 -0
  247. data/db/migrate/20250115000001_ar_image.rb +25 -0
  248. data/lib/agile/configuration.rb +43 -0
  249. data/lib/agile/engine.rb +29 -0
  250. data/lib/agile/version.rb +27 -0
  251. data/lib/agile.rb +282 -0
  252. data/lib/agile_rails.rb +1 -0
  253. data/lib/generators/agile/USAGE +11 -0
  254. data/lib/generators/agile/new_form_generator.rb +369 -0
  255. data/lib/generators/convert_to_ar/convert_to_ar_generator.rb +158 -0
  256. data/lib/tasks/agile_db_clone.rake +132 -0
  257. data/lib/tasks/agile_db_export_to_yaml.rake +37 -0
  258. data/lib/tasks/agile_db_migrate.rake +35 -0
  259. metadata +414 -0
@@ -0,0 +1,345 @@
1
+ #--
2
+ # Copyright (c) 2024+ Damjan Rems
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #+
23
+
24
+ ########################################################################
25
+ # AgileCommonController holds some common actions used by AgileRails.
26
+ ########################################################################
27
+ class AgileCommonController < AgileApplicationController
28
+ layout false
29
+
30
+ ########################################################################
31
+ # This action is called on ajax autocomplete call. It checks if user has rights to
32
+ # view data.
33
+ #
34
+ # URL parameters:
35
+ # [table] Table (table) model name in lower case indicating table which will be searched.
36
+ # [id] Name of id key field that will be returned. Default is '_id'
37
+ # [input] Search data entered in input field.
38
+ # [search] when passed without dot it defines field name on which search
39
+ # will be performed. When passed with dot class_method.method_name is assumed. Method name will
40
+ # be parsed and any class with class method name can be evaluated. Class method must accept
41
+ # input parameter and return array [ [_id, value],.. ] which will be used in autocomplete field.
42
+ #
43
+ # Return:
44
+ # JSON array [label, value, id] of first 20 documents that confirm to query.
45
+ ########################################################################
46
+ def autocomplete
47
+ # table parameter must be defined. If not, get it from search parameter
48
+ if params['table'].nil? && params['search'].match(/\./)
49
+ name = params['search'].split('.').first
50
+ params['table'] = name.underscore
51
+ end
52
+ if params['table'].match('_control')
53
+ # depends on ar_memory permissions. Should probably be logged on.
54
+ return render json: { label: t('agile.not_authorized') } unless agile_user_can(ArPermission::CAN_VIEW, 'ar_memory')
55
+ else
56
+ return render json: { label: t('agile.not_authorized') } unless agile_user_can(ArPermission::CAN_VIEW)
57
+ end
58
+
59
+ table = params['table'].classify.constantize
60
+ input = params['input'].gsub(/\(|\)|\[|\]|\{|\|\.|\,|\}|\%|\*|\:|\;/, '') # remove special characters
61
+ # call method in class. if search parameter contains . search is defined in a method
62
+ result = if params['search'].match(/\./)
63
+ name, method = params['search'].split('.')
64
+ table.send(method, input).map do |e|
65
+ { label: e[0], value: e[0], id: (e[1] || e[0]).to_s }
66
+ end
67
+ # standard search in table by field_name
68
+ else
69
+ table.where("lower(#{params['search']}) like ?", "%#{input.downcase}%").
70
+ limit(20).map do |e|
71
+ { label: e[params['search']], value: e[params['search']], id: e.id }
72
+ end
73
+ end
74
+ render json: result
75
+ end
76
+
77
+ ##########################################################################
78
+ # Toggle CMS edit mode.This action is called when user clicks CMS icon on
79
+ # top left corner of the browser.
80
+ ##########################################################################
81
+ def toggle_edit_mode
82
+ session[:edit_mode] ||= 0
83
+ return agile_render_404 if session[:edit_mode] < 1 # called without logged in
84
+
85
+ session[:edit_mode] = (session[:edit_mode] == 1) ? 2 : 1
86
+ redirect_to (params[:return_to] || '/')
87
+ end
88
+
89
+ ####################################################################
90
+ # Default user login action.
91
+ ####################################################################
92
+ def process_login
93
+ # Somebody is probably playing
94
+ return agile_render_404 unless ( params[:record] && params[:record][:username] && params[:record][:password] )
95
+
96
+ if params[:record][:password].present? # must not be empty
97
+ user = ArUser.find_by(username: params[:record][:username], active: true)
98
+ if user&.authenticate(params[:record][:password])
99
+ set_login_data(user, params[:record][:remember_me].to_i == 1)
100
+ return redirect_to(params[:return_to] || '/', allow_other_host: true)
101
+ else
102
+ clear_login_data # on the safe side
103
+ end
104
+ end
105
+ flash[:error] = t('agile.invalid_username')
106
+ redirect_to(params[:return_to] || '/', allow_other_host: true)
107
+ end
108
+
109
+ ####################################################################
110
+ # Default user logout action.
111
+ ####################################################################
112
+ def logout
113
+ clear_login_data
114
+ redirect_to(params[:return_to] || '/', allow_other_host: true)
115
+ end
116
+
117
+ ####################################################################
118
+ # Action for restoring document data from journal document.
119
+ ####################################################################
120
+ def restore_from_journal
121
+ # Only administrators can perform this operation
122
+ unless agile_user_has_role?('admin')
123
+ return render plain: { 'msg_info' => (t ('agile.not_authorized')) }.to_json
124
+ end
125
+ # selected fields to hash
126
+ restore = {}
127
+ params[:select].each { |k, v| restore[k] = v if v == '1' }
128
+ result = if restore.size == 0
129
+ { 'msg_error' => (t ('agile.ar_journal.zero_selected')) }
130
+ else
131
+ journal_rec = ArJournal.find(params[:id])
132
+ # update hash with data to be restored
133
+ JSON.parse(journal_rec.diff).each { |k, v| restore[k] = v.first if restore[k] }
134
+ # table model and document id
135
+ table = journal_rec.tables.classify.constantize
136
+ id = journal_rec.ids
137
+ record = table.find(id)
138
+ # restore and save values
139
+ restore.each { |field, value| record.send("#{field}=",value) }
140
+ record.save
141
+ # TODO Error checking
142
+ { 'msg_info' => (t ('agile.ar_journal.restored')) }
143
+ end
144
+ render plain: result.to_json
145
+ end
146
+
147
+ ########################################################################
148
+ # Copy current record to clipboard as json text. It will actually ouput an
149
+ # window with data formatted as json.
150
+ ########################################################################
151
+ def copy_clipboard
152
+ # Only administrators can perform this operation
153
+ return render(plain: t('agile.not_authorized') ) unless agile_user_has_role?('admin')
154
+
155
+ respond_to do |format|
156
+ # just open new window to same url and come back with html request
157
+ format.json { agile_render_ajax(operation: 'window', url: request.url ) }
158
+
159
+ format.html do
160
+ table = AgileHelper.table_param(params).split(';').last
161
+ record = agile_document_find(table, params[:id])
162
+ text = %(<style>body {font-family: monospace;}</style><pre>
163
+ JSON:<br>[#{table},#{params[:id]},#{params[:ids]}]<br>#{record.to_json}<br><br>
164
+ YAML:<br>#{record.attributes.to_yaml.gsub("\n", '<br>')}</pre>)
165
+ render plain: text
166
+
167
+ end
168
+ end
169
+ end
170
+
171
+ ########################################################################
172
+ # Paste data from clipboard into text_area and update documents in destination database.
173
+ # This action is called twice. First time for displaying text_area field and second time
174
+ # ajax call for processing data.
175
+ ########################################################################
176
+ def paste_clipboard
177
+ # Only administrators can perform this operation
178
+ return render(plain: t('agile.not_authorized') ) unless agile_user_has_role?('admin')
179
+
180
+ result = ''
181
+ respond_to do |format|
182
+ # just open new window to same url and come back with html request
183
+ format.html { return render('paste_clipboard', layout: ' agile') }
184
+ format.json {
185
+ table, id, ids = nil
186
+ params[:data].split("\n").each do |line|
187
+ line.chomp!
188
+ next if line.size < 5 # empty line. Skip
189
+
190
+ begin
191
+ if line[0] == '[' # id(s)
192
+ result += "<br>#{line}"
193
+ line = line[/\[(.*?)\]/, 1] # just what is between []
194
+ table, id, ids = line.split(',')
195
+ elsif line[0] == '{' # document data
196
+ result += paste_document_process(line, table, id, ids)
197
+ end
198
+ rescue Exception => e
199
+ result += " Runtime error. #{e.message}\n"
200
+ break
201
+ end
202
+ end
203
+ }
204
+ end
205
+ agile_render_ajax(div: 'result', value: result )
206
+ end
207
+
208
+ ########################################################################
209
+ # Will add new json_ld element with blank structure into ar_json_ld field on a
210
+ # document.
211
+ ########################################################################
212
+ def add_json_ld_schema
213
+ edited_document = ArJsonLd.find_document_by_ids(AgileHelper.table_param(params), params[:ids])
214
+ yaml = YAML.load_file( AgileHelper.form_file_find('json_ld_schema') )
215
+ schema_data = yaml[params[:schema]]
216
+ # Existing document
217
+ if edited_document.ar_json_lds.find_by(type: "@#{params[:schema]}")
218
+ return render json: {'msg_error' => t('helpers.help.ar_json_ld.add_error', schema: params[:schema] ) }
219
+ else
220
+ add_empty_json_ld_schema(edited_document, schema_data, params[:schema], params[:schema], yaml)
221
+ end
222
+ render json: {'reload_' => 1}
223
+ end
224
+
225
+ ########################################################################
226
+ # Will provide help data
227
+ ########################################################################
228
+ def help
229
+ agile_form_read
230
+ form_name = AgileHelper.form_param(params) || AgileHelper.table_param(params)
231
+ help_file_name = @form['help'] || @form['extend'] || form_name
232
+ help_file_name = AgileApplicationController.find_help_file(help_file_name)
233
+ @help = YAML.load_file(help_file_name) if help_file_name
234
+ # no auto generated help on index action
235
+ return render json: {} if params[:type] == 'index' && @help.nil?
236
+
237
+ render json: { popup_help: render_to_string(partial: 'help') }
238
+ end
239
+
240
+ ##########################################################################
241
+ # Save poll results to ar_poll_results table
242
+ ##########################################################################
243
+ def poll_submit
244
+ record = params[:record]
245
+ poll = ArPoll.find(params[:poll_id]) || ArPoll.find_by(name: params[:poll_id])
246
+ result = poll.save_results(record)
247
+ # call additional service
248
+ run = params[:record][:run] || params[:run]
249
+ redirect_to(params[:return_to] || '/') and return if run.blank?
250
+
251
+ service_response = send(run, result)
252
+ respond_to do |format|
253
+ format.html do # submit
254
+ # return on poll-top
255
+ params[:return_to] += '#poll-top' unless params[:return_to].match('#poll-top')
256
+ # response should be in same format as ajax response. Extract error and info
257
+ service_response = {} unless service_response.class == Hash
258
+ flash[:error] = service_response['msg_error']
259
+ flash[:info] = service_response['msg_info']
260
+ redirect_to params[:return_to]
261
+ end
262
+
263
+ format.js do # ajax submit
264
+ render json: service_response || { ok: 1 }
265
+ end
266
+ end
267
+
268
+ end
269
+ protected
270
+
271
+ ########################################################################
272
+ # Subroutine of add_json_ld_schema for adding one element
273
+ ########################################################################
274
+ def add_empty_json_ld_schema(edited_document, schema, schema_name, schema_type, yaml) #:nodoc
275
+ data = {}
276
+ doc = ArJsonLd.new
277
+ doc.name = schema_name
278
+ doc.type = schema_type
279
+
280
+ edited_document.ar_json_lds << doc
281
+ schema.each do |element_name, element|
282
+ next if element_name == 'level' # skip level element
283
+
284
+ if yaml[element['type']]
285
+ if element['n'].to_s == '1'
286
+ # single element
287
+ doc_1 = yaml[element['type'] ]
288
+ data[element_name] = doc_1
289
+ else
290
+ # array
291
+ add_empty_json_ld_schema(doc, yaml[element['type']], element_name, element['type'], yaml)
292
+ end
293
+ else
294
+ data[element_name] = element['text']
295
+ end
296
+ end
297
+ doc.data = data.to_yaml
298
+ doc.save
299
+ end
300
+
301
+ ########################################################################
302
+ # Update some anomalies in json data on paste_clipboard action.
303
+ ########################################################################
304
+ def update_json(json, is_update=false) #:nodoc:
305
+ result = {}
306
+ json.each do |k,v|
307
+ if v.class == Hash
308
+ result[k] = v['$oid'] unless is_update
309
+ # TODO Double check if unless works as expected
310
+ elsif v.class == Array
311
+ result[k] = []
312
+ v.each { |e| result[k] << update_json(e, is_update)}
313
+ else
314
+ result[k] = v
315
+ end
316
+ end
317
+ result
318
+ end
319
+
320
+ ########################################################################
321
+ # Processes one document. Subroutine of paste_clipboard.
322
+ ########################################################################
323
+ def paste_document_process(line, table, id, ids)
324
+ if params[:do_update] == '1'
325
+ doc = agile_document_find(table, id)
326
+ # document found. Update it and return
327
+ if doc
328
+ doc.update( update_json(ActiveSupport::JSON.decode(line), true) )
329
+ msg = agilecheck_model(doc)
330
+ return (msg ? " ERROR! #{msg}" : " UPDATE. OK.")
331
+ end
332
+ end
333
+ # document will be added to collection
334
+ if ids.to_s.size > 5
335
+ #TODO Add embedded document
336
+ " NOT SUPPORTED YET!"
337
+ else
338
+ doc = table.classify.constantize.new( update_json(ActiveSupport::JSON.decode(line)) )
339
+ doc.save
340
+ end
341
+ msg = Agile.model_check(doc)
342
+ msg ? " ERROR! #{msg}" : " NEW. OK."
343
+ end
344
+
345
+ end