decidim-enhanced_textwork 1.0.0

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 (441) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +64 -0
  3. data/Rakefile +3 -0
  4. data/app/cells/decidim/enhanced_textwork/amendment/show.erb +14 -0
  5. data/app/cells/decidim/enhanced_textwork/amendment_cell.rb +39 -0
  6. data/app/cells/decidim/enhanced_textwork/collaborative_draft_cell.rb +49 -0
  7. data/app/cells/decidim/enhanced_textwork/collaborative_draft_link_to_paragraph/show.erb +13 -0
  8. data/app/cells/decidim/enhanced_textwork/collaborative_draft_link_to_paragraph_cell.rb +57 -0
  9. data/app/cells/decidim/enhanced_textwork/collaborative_draft_m/footer.erb +6 -0
  10. data/app/cells/decidim/enhanced_textwork/collaborative_draft_m/tags.erb +1 -0
  11. data/app/cells/decidim/enhanced_textwork/collaborative_draft_m_cell.rb +44 -0
  12. data/app/cells/decidim/enhanced_textwork/collaborative_drafts/reported_content/show.erb +3 -0
  13. data/app/cells/decidim/enhanced_textwork/collaborative_drafts/reported_content_cell.rb +15 -0
  14. data/app/cells/decidim/enhanced_textwork/comments/show.erb +33 -0
  15. data/app/cells/decidim/enhanced_textwork/comments_cell.rb +8 -0
  16. data/app/cells/decidim/enhanced_textwork/content_blocks/highlighted_paragraphs/elements.erb +5 -0
  17. data/app/cells/decidim/enhanced_textwork/content_blocks/highlighted_paragraphs/heading.erb +1 -0
  18. data/app/cells/decidim/enhanced_textwork/content_blocks/highlighted_paragraphs_cell.rb +19 -0
  19. data/app/cells/decidim/enhanced_textwork/cost_report/show.erb +35 -0
  20. data/app/cells/decidim/enhanced_textwork/cost_report_cell.rb +42 -0
  21. data/app/cells/decidim/enhanced_textwork/highlighted_paragraphs/show.erb +3 -0
  22. data/app/cells/decidim/enhanced_textwork/highlighted_paragraphs_cell.rb +25 -0
  23. data/app/cells/decidim/enhanced_textwork/highlighted_paragraphs_for_component/show.erb +19 -0
  24. data/app/cells/decidim/enhanced_textwork/highlighted_paragraphs_for_component_cell.rb +41 -0
  25. data/app/cells/decidim/enhanced_textwork/irreversible_action_modal/show.erb +27 -0
  26. data/app/cells/decidim/enhanced_textwork/irreversible_action_modal_cell.rb +80 -0
  27. data/app/cells/decidim/enhanced_textwork/paragraph_activity_cell.rb +35 -0
  28. data/app/cells/decidim/enhanced_textwork/paragraph_cell.rb +53 -0
  29. data/app/cells/decidim/enhanced_textwork/paragraph_link_to_collaborative_draft_cell.rb +26 -0
  30. data/app/cells/decidim/enhanced_textwork/paragraph_link_to_rejected_emendation/show.erb +9 -0
  31. data/app/cells/decidim/enhanced_textwork/paragraph_link_to_rejected_emendation_cell.rb +34 -0
  32. data/app/cells/decidim/enhanced_textwork/paragraph_linked_resources/show.erb +9 -0
  33. data/app/cells/decidim/enhanced_textwork/paragraph_linked_resources_cell.rb +14 -0
  34. data/app/cells/decidim/enhanced_textwork/paragraph_m/footer.erb +26 -0
  35. data/app/cells/decidim/enhanced_textwork/paragraph_m/tags.erb +1 -0
  36. data/app/cells/decidim/enhanced_textwork/paragraph_m_cell.rb +152 -0
  37. data/app/cells/decidim/enhanced_textwork/paragraph_tags/show.erb +33 -0
  38. data/app/cells/decidim/enhanced_textwork/paragraph_tags_cell.rb +35 -0
  39. data/app/cells/decidim/enhanced_textwork/paragraphs_picker/paragraphs.erb +12 -0
  40. data/app/cells/decidim/enhanced_textwork/paragraphs_picker/show.erb +14 -0
  41. data/app/cells/decidim/enhanced_textwork/paragraphs_picker_cell.rb +72 -0
  42. data/app/cells/decidim/enhanced_textwork/participatory_text_paragraph/buttons.erb +33 -0
  43. data/app/cells/decidim/enhanced_textwork/participatory_text_paragraph/show.erb +38 -0
  44. data/app/cells/decidim/enhanced_textwork/participatory_text_paragraph_cell.rb +104 -0
  45. data/app/cells/decidim/enhanced_textwork/reported_content/show.erb +4 -0
  46. data/app/cells/decidim/enhanced_textwork/reported_content_cell.rb +13 -0
  47. data/app/commands/decidim/enhanced_textwork/accept_access_to_collaborative_draft.rb +70 -0
  48. data/app/commands/decidim/enhanced_textwork/admin/answer_paragraph.rb +74 -0
  49. data/app/commands/decidim/enhanced_textwork/admin/assign_paragraphs_to_valuator.rb +61 -0
  50. data/app/commands/decidim/enhanced_textwork/admin/create_paragraph.rb +97 -0
  51. data/app/commands/decidim/enhanced_textwork/admin/create_paragraph_note.rb +67 -0
  52. data/app/commands/decidim/enhanced_textwork/admin/destroy_paragraph.rb +32 -0
  53. data/app/commands/decidim/enhanced_textwork/admin/discard_participatory_text.rb +40 -0
  54. data/app/commands/decidim/enhanced_textwork/admin/import_from_editor_participatory_text.rb +53 -0
  55. data/app/commands/decidim/enhanced_textwork/admin/import_paragraphs.rb +101 -0
  56. data/app/commands/decidim/enhanced_textwork/admin/import_participatory_text.rb +55 -0
  57. data/app/commands/decidim/enhanced_textwork/admin/merge_paragraphs.rb +69 -0
  58. data/app/commands/decidim/enhanced_textwork/admin/notify_paragraph_answer.rb +85 -0
  59. data/app/commands/decidim/enhanced_textwork/admin/publish_answers.rb +67 -0
  60. data/app/commands/decidim/enhanced_textwork/admin/publish_participatory_text.rb +81 -0
  61. data/app/commands/decidim/enhanced_textwork/admin/split_paragraphs.rb +67 -0
  62. data/app/commands/decidim/enhanced_textwork/admin/unassign_paragraphs_from_valuator.rb +62 -0
  63. data/app/commands/decidim/enhanced_textwork/admin/update_paragraph.rb +86 -0
  64. data/app/commands/decidim/enhanced_textwork/admin/update_paragraph_category.rb +68 -0
  65. data/app/commands/decidim/enhanced_textwork/admin/update_paragraph_scope.rb +75 -0
  66. data/app/commands/decidim/enhanced_textwork/admin/update_participatory_text.rb +68 -0
  67. data/app/commands/decidim/enhanced_textwork/create_collaborative_draft.rb +81 -0
  68. data/app/commands/decidim/enhanced_textwork/create_paragraph.rb +106 -0
  69. data/app/commands/decidim/enhanced_textwork/destroy_paragraph.rb +33 -0
  70. data/app/commands/decidim/enhanced_textwork/gallery_methods.rb +18 -0
  71. data/app/commands/decidim/enhanced_textwork/hashtags_methods.rb +36 -0
  72. data/app/commands/decidim/enhanced_textwork/publish_collaborative_draft.rb +93 -0
  73. data/app/commands/decidim/enhanced_textwork/publish_paragraph.rb +105 -0
  74. data/app/commands/decidim/enhanced_textwork/reject_access_to_collaborative_draft.rb +62 -0
  75. data/app/commands/decidim/enhanced_textwork/request_access_to_collaborative_draft.rb +49 -0
  76. data/app/commands/decidim/enhanced_textwork/unvote_paragraph.rb +65 -0
  77. data/app/commands/decidim/enhanced_textwork/update_collaborative_draft.rb +63 -0
  78. data/app/commands/decidim/enhanced_textwork/update_paragraph.rb +135 -0
  79. data/app/commands/decidim/enhanced_textwork/vote_paragraph.rb +77 -0
  80. data/app/commands/decidim/enhanced_textwork/withdraw_collaborative_draft.rb +65 -0
  81. data/app/commands/decidim/enhanced_textwork/withdraw_paragraph.rb +50 -0
  82. data/app/controllers/concerns/decidim/enhanced_textwork/admin/filterable.rb +82 -0
  83. data/app/controllers/concerns/decidim/enhanced_textwork/admin/picker.rb +21 -0
  84. data/app/controllers/concerns/decidim/enhanced_textwork/collaborative_orderable.rb +42 -0
  85. data/app/controllers/concerns/decidim/enhanced_textwork/orderable.rb +78 -0
  86. data/app/controllers/decidim/enhanced_textwork/admin/application_controller.rb +16 -0
  87. data/app/controllers/decidim/enhanced_textwork/admin/paragraph_answers_controller.rb +50 -0
  88. data/app/controllers/decidim/enhanced_textwork/admin/paragraph_notes_controller.rb +39 -0
  89. data/app/controllers/decidim/enhanced_textwork/admin/paragraphs_controller.rb +237 -0
  90. data/app/controllers/decidim/enhanced_textwork/admin/paragraphs_imports_controller.rb +33 -0
  91. data/app/controllers/decidim/enhanced_textwork/admin/paragraphs_merges_controller.rb +30 -0
  92. data/app/controllers/decidim/enhanced_textwork/admin/paragraphs_splits_controller.rb +30 -0
  93. data/app/controllers/decidim/enhanced_textwork/admin/participatory_texts_controller.rb +128 -0
  94. data/app/controllers/decidim/enhanced_textwork/admin/valuation_assignments_controller.rb +58 -0
  95. data/app/controllers/decidim/enhanced_textwork/application_controller.rb +31 -0
  96. data/app/controllers/decidim/enhanced_textwork/collaborative_draft_collaborator_requests_controller.rb +53 -0
  97. data/app/controllers/decidim/enhanced_textwork/collaborative_drafts_controller.rb +161 -0
  98. data/app/controllers/decidim/enhanced_textwork/paragraph_votes_controller.rb +65 -0
  99. data/app/controllers/decidim/enhanced_textwork/paragraphs_controller.rb +316 -0
  100. data/app/controllers/decidim/enhanced_textwork/versions_controller.rb +21 -0
  101. data/app/controllers/decidim/enhanced_textwork/widgets_controller.rb +19 -0
  102. data/app/events/decidim/enhanced_textwork/accepted_paragraph_event.rb +17 -0
  103. data/app/events/decidim/enhanced_textwork/admin/paragraph_note_created_event.rb +27 -0
  104. data/app/events/decidim/enhanced_textwork/admin/update_paragraph_category_event.rb +11 -0
  105. data/app/events/decidim/enhanced_textwork/admin/update_paragraph_scope_event.rb +11 -0
  106. data/app/events/decidim/enhanced_textwork/collaborative_draft_access_accepted_event.rb +8 -0
  107. data/app/events/decidim/enhanced_textwork/collaborative_draft_access_rejected_event.rb +8 -0
  108. data/app/events/decidim/enhanced_textwork/collaborative_draft_access_request_event.rb +27 -0
  109. data/app/events/decidim/enhanced_textwork/collaborative_draft_access_requested_event.rb +8 -0
  110. data/app/events/decidim/enhanced_textwork/collaborative_draft_access_requester_accepted_event.rb +8 -0
  111. data/app/events/decidim/enhanced_textwork/collaborative_draft_access_requester_rejected_event.rb +8 -0
  112. data/app/events/decidim/enhanced_textwork/collaborative_draft_withdrawn_event.rb +29 -0
  113. data/app/events/decidim/enhanced_textwork/creation_enabled_event.rb +8 -0
  114. data/app/events/decidim/enhanced_textwork/endorsing_enabled_event.rb +8 -0
  115. data/app/events/decidim/enhanced_textwork/evaluating_paragraph_event.rb +11 -0
  116. data/app/events/decidim/enhanced_textwork/paragraph_endorsed_event.rb +33 -0
  117. data/app/events/decidim/enhanced_textwork/paragraph_mentioned_event.rb +21 -0
  118. data/app/events/decidim/enhanced_textwork/publish_paragraph_event.rb +25 -0
  119. data/app/events/decidim/enhanced_textwork/rejected_paragraph_event.rb +17 -0
  120. data/app/events/decidim/enhanced_textwork/voting_enabled_event.rb +8 -0
  121. data/app/forms/decidim/enhanced_textwork/accept_access_to_collaborative_draft_form.rb +10 -0
  122. data/app/forms/decidim/enhanced_textwork/access_to_collaborative_draft_form.rb +33 -0
  123. data/app/forms/decidim/enhanced_textwork/admin/import_editor_participatory_text_form.rb +35 -0
  124. data/app/forms/decidim/enhanced_textwork/admin/import_participatory_text_form.rb +68 -0
  125. data/app/forms/decidim/enhanced_textwork/admin/paragraph_answer_form.rb +44 -0
  126. data/app/forms/decidim/enhanced_textwork/admin/paragraph_base_form.rb +137 -0
  127. data/app/forms/decidim/enhanced_textwork/admin/paragraph_form.rb +32 -0
  128. data/app/forms/decidim/enhanced_textwork/admin/paragraph_note_form.rb +16 -0
  129. data/app/forms/decidim/enhanced_textwork/admin/paragraphs_fork_form.rb +63 -0
  130. data/app/forms/decidim/enhanced_textwork/admin/paragraphs_import_form.rb +67 -0
  131. data/app/forms/decidim/enhanced_textwork/admin/paragraphs_merge_form.rb +13 -0
  132. data/app/forms/decidim/enhanced_textwork/admin/paragraphs_split_form.rb +12 -0
  133. data/app/forms/decidim/enhanced_textwork/admin/participatory_text_paragraph_form.rb +20 -0
  134. data/app/forms/decidim/enhanced_textwork/admin/preview_participatory_text_form.rb +21 -0
  135. data/app/forms/decidim/enhanced_textwork/admin/valuation_assignment_form.rb +37 -0
  136. data/app/forms/decidim/enhanced_textwork/collaborative_draft_form.rb +20 -0
  137. data/app/forms/decidim/enhanced_textwork/paragraph_form.rb +126 -0
  138. data/app/forms/decidim/enhanced_textwork/paragraph_wizard_create_step_form.rb +41 -0
  139. data/app/forms/decidim/enhanced_textwork/reject_access_to_collaborative_draft_form.rb +9 -0
  140. data/app/forms/decidim/enhanced_textwork/request_access_to_collaborative_draft_form.rb +20 -0
  141. data/app/helpers/decidim/enhanced_textwork/admin/filterable_helper.rb +17 -0
  142. data/app/helpers/decidim/enhanced_textwork/admin/paragraph_bulk_actions_helper.rb +35 -0
  143. data/app/helpers/decidim/enhanced_textwork/admin/paragraph_rankings_helper.rb +63 -0
  144. data/app/helpers/decidim/enhanced_textwork/admin/paragraphs_helper.rb +144 -0
  145. data/app/helpers/decidim/enhanced_textwork/admin/paragraphs_picker_helper.rb +30 -0
  146. data/app/helpers/decidim/enhanced_textwork/application_helper.rb +191 -0
  147. data/app/helpers/decidim/enhanced_textwork/collaborative_draft_cells_helper.rb +48 -0
  148. data/app/helpers/decidim/enhanced_textwork/collaborative_draft_helper.rb +29 -0
  149. data/app/helpers/decidim/enhanced_textwork/control_version_helper.rb +12 -0
  150. data/app/helpers/decidim/enhanced_textwork/map_helper.rb +48 -0
  151. data/app/helpers/decidim/enhanced_textwork/paragraph_cells_helper.rb +75 -0
  152. data/app/helpers/decidim/enhanced_textwork/paragraph_votes_helper.rb +103 -0
  153. data/app/helpers/decidim/enhanced_textwork/paragraph_wizard_helper.rb +140 -0
  154. data/app/helpers/decidim/enhanced_textwork/paragraphs_helper.rb +63 -0
  155. data/app/helpers/decidim/enhanced_textwork/participatory_texts_helper.rb +49 -0
  156. data/app/jobs/decidim/enhanced_textwork/notify_paragraphs_mentioned_job.rb +27 -0
  157. data/app/jobs/decidim/enhanced_textwork/settings_change_job.rb +50 -0
  158. data/app/models/decidim/enhanced_textwork/application_record.rb +10 -0
  159. data/app/models/decidim/enhanced_textwork/collaborative_draft.rb +73 -0
  160. data/app/models/decidim/enhanced_textwork/collaborative_draft_collaborator_request.rb +13 -0
  161. data/app/models/decidim/enhanced_textwork/paragraph.rb +411 -0
  162. data/app/models/decidim/enhanced_textwork/paragraph_note.rb +20 -0
  163. data/app/models/decidim/enhanced_textwork/paragraph_vote.rb +50 -0
  164. data/app/models/decidim/enhanced_textwork/participatory_text.rb +16 -0
  165. data/app/models/decidim/enhanced_textwork/valuation_assignment.rb +24 -0
  166. data/app/packs/documents/decidim/enhanced_textwork/participatory_texts/participatory_text.md +52 -0
  167. data/app/packs/documents/decidim/enhanced_textwork/participatory_texts/participatory_text.odt +0 -0
  168. data/app/packs/entrypoints/decidim_enhanced_textwork.js +17 -0
  169. data/app/packs/entrypoints/decidim_enhanced_textwork_admin.js +3 -0
  170. data/app/packs/images/decidim/enhanced_textwork/decidim_paragraphs.svg +1 -0
  171. data/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_accepted_paragraphs.svg +1 -0
  172. data/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_paragraph_votes.svg +1 -0
  173. data/app/packs/images/decidim/gamification/badges/decidim_gamification_badges_paragraphs.svg +1 -0
  174. data/app/packs/src/decidim/enhanced_textwork/add_paragraph.js +49 -0
  175. data/app/packs/src/decidim/enhanced_textwork/admin/paragraphs.js +143 -0
  176. data/app/packs/src/decidim/enhanced_textwork/admin/paragraphs_form.js +29 -0
  177. data/app/packs/src/decidim/enhanced_textwork/admin/paragraphs_picker.js +35 -0
  178. data/app/packs/src/decidim/enhanced_textwork/toggle_element.js +21 -0
  179. data/app/packs/src/decidim/enhanced_textwork/utils.js +11 -0
  180. data/app/packs/stylesheets/decidim/enhanced_textwork/_paragraphs.scss +208 -0
  181. data/app/packs/stylesheets/decidim/enhanced_textwork/paragraphs/_preview.scss +3 -0
  182. data/app/permissions/decidim/enhanced_textwork/admin/permissions.rb +147 -0
  183. data/app/permissions/decidim/enhanced_textwork/permissions.rb +163 -0
  184. data/app/presenters/decidim/enhanced_textwork/admin_log/paragraph_note_presenter.rb +39 -0
  185. data/app/presenters/decidim/enhanced_textwork/admin_log/paragraph_presenter.rb +51 -0
  186. data/app/presenters/decidim/enhanced_textwork/admin_log/valuation_assignment_presenter.rb +51 -0
  187. data/app/presenters/decidim/enhanced_textwork/admin_log/value_types/paragraph_state_presenter.rb +17 -0
  188. data/app/presenters/decidim/enhanced_textwork/admin_log/value_types/paragraph_title_body_presenter.rb +23 -0
  189. data/app/presenters/decidim/enhanced_textwork/admin_log/value_types/valuator_role_user_presenter.rb +19 -0
  190. data/app/presenters/decidim/enhanced_textwork/collaborative_draft_presenter.rb +25 -0
  191. data/app/presenters/decidim/enhanced_textwork/log/resource_presenter.rb +22 -0
  192. data/app/presenters/decidim/enhanced_textwork/log/valuation_assignment_presenter.rb +22 -0
  193. data/app/presenters/decidim/enhanced_textwork/official_author_presenter.rb +14 -0
  194. data/app/presenters/decidim/enhanced_textwork/paragraph_presenter.rb +146 -0
  195. data/app/queries/decidim/enhanced_textwork/filtered_paragraphs.rb +37 -0
  196. data/app/queries/decidim/enhanced_textwork/metrics/accepted_paragraphs_metric_manage.rb +32 -0
  197. data/app/queries/decidim/enhanced_textwork/metrics/endorsements_metric_manage.rb +58 -0
  198. data/app/queries/decidim/enhanced_textwork/metrics/paragraph_followers_metric_measure.rb +58 -0
  199. data/app/queries/decidim/enhanced_textwork/metrics/paragraph_participants_metric_measure.rb +74 -0
  200. data/app/queries/decidim/enhanced_textwork/metrics/paragraphs_metric_manage.rb +48 -0
  201. data/app/queries/decidim/enhanced_textwork/metrics/votes_metric_manage.rb +52 -0
  202. data/app/queries/decidim/enhanced_textwork/similar_paragraphs.rb +67 -0
  203. data/app/services/decidim/enhanced_textwork/collaborative_draft_search.rb +59 -0
  204. data/app/services/decidim/enhanced_textwork/diff_renderer.rb +74 -0
  205. data/app/services/decidim/enhanced_textwork/paragraph_builder.rb +132 -0
  206. data/app/services/decidim/enhanced_textwork/paragraph_search.rb +85 -0
  207. data/app/validators/paragraph_length_validator.rb +40 -0
  208. data/app/views/decidim/enhanced_textwork/admin/paragraph_answers/_form.html.erb +35 -0
  209. data/app/views/decidim/enhanced_textwork/admin/paragraph_notes/_form.html.erb +8 -0
  210. data/app/views/decidim/enhanced_textwork/admin/paragraph_notes/_paragraph_notes.html.erb +45 -0
  211. data/app/views/decidim/enhanced_textwork/admin/paragraphs/_bulk-actions.html.erb +33 -0
  212. data/app/views/decidim/enhanced_textwork/admin/paragraphs/_form.html.erb +101 -0
  213. data/app/views/decidim/enhanced_textwork/admin/paragraphs/_js-callout.html.erb +6 -0
  214. data/app/views/decidim/enhanced_textwork/admin/paragraphs/_paragraph-tr.html.erb +76 -0
  215. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_assign_to_valuator.html.erb +15 -0
  216. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_dropdown.html.erb +56 -0
  217. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_merge.html.erb +15 -0
  218. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_publish_answers.html.erb +14 -0
  219. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_recategorize.html.erb +15 -0
  220. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_scope-change.html.erb +25 -0
  221. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_split.html.erb +15 -0
  222. data/app/views/decidim/enhanced_textwork/admin/paragraphs/bulk_actions/_unassign_from_valuator.html.erb +15 -0
  223. data/app/views/decidim/enhanced_textwork/admin/paragraphs/edit.html.erb +7 -0
  224. data/app/views/decidim/enhanced_textwork/admin/paragraphs/index.html.erb +84 -0
  225. data/app/views/decidim/enhanced_textwork/admin/paragraphs/new.html.erb +7 -0
  226. data/app/views/decidim/enhanced_textwork/admin/paragraphs/publish_answers.js.erb +12 -0
  227. data/app/views/decidim/enhanced_textwork/admin/paragraphs/show.html.erb +186 -0
  228. data/app/views/decidim/enhanced_textwork/admin/paragraphs/update_category.js.erb +26 -0
  229. data/app/views/decidim/enhanced_textwork/admin/paragraphs/update_scope.js.erb +27 -0
  230. data/app/views/decidim/enhanced_textwork/admin/paragraphs_imports/new.html.erb +37 -0
  231. data/app/views/decidim/enhanced_textwork/admin/participatory_texts/_article-preview.html.erb +16 -0
  232. data/app/views/decidim/enhanced_textwork/admin/participatory_texts/_bulk-actions.html.erb +3 -0
  233. data/app/views/decidim/enhanced_textwork/admin/participatory_texts/index.html.erb +55 -0
  234. data/app/views/decidim/enhanced_textwork/admin/participatory_texts/new_editor.html.erb +39 -0
  235. data/app/views/decidim/enhanced_textwork/admin/participatory_texts/new_import.html.erb +39 -0
  236. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_accept_request_access_form.html.erb +8 -0
  237. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_collaborative_drafts.html.erb +16 -0
  238. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_collaborator_requests.html.erb +20 -0
  239. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_count.html.erb +1 -0
  240. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_edit_form_fields.html.erb +83 -0
  241. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_filters.html.erb +32 -0
  242. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_filters_small_view.html.erb +18 -0
  243. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_new_collaborative_draft_button.html.erb +11 -0
  244. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_reject_request_access_form.html.erb +10 -0
  245. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_request_access_form.html.erb +7 -0
  246. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_wizard_aside.html.erb +13 -0
  247. data/app/views/decidim/enhanced_textwork/collaborative_drafts/_wizard_header.html.erb +14 -0
  248. data/app/views/decidim/enhanced_textwork/collaborative_drafts/edit.html.erb +31 -0
  249. data/app/views/decidim/enhanced_textwork/collaborative_drafts/index.html.erb +23 -0
  250. data/app/views/decidim/enhanced_textwork/collaborative_drafts/index.js.erb +10 -0
  251. data/app/views/decidim/enhanced_textwork/collaborative_drafts/new.html.erb +24 -0
  252. data/app/views/decidim/enhanced_textwork/collaborative_drafts/show.html.erb +128 -0
  253. data/app/views/decidim/enhanced_textwork/paragraph_votes/update_buttons_and_counters.js.erb +41 -0
  254. data/app/views/decidim/enhanced_textwork/paragraphs/_count.html.erb +1 -0
  255. data/app/views/decidim/enhanced_textwork/paragraphs/_dynamic_map_instructions.html.erb +4 -0
  256. data/app/views/decidim/enhanced_textwork/paragraphs/_edit_form_fields.html.erb +115 -0
  257. data/app/views/decidim/enhanced_textwork/paragraphs/_endorsements_card_row.html.erb +0 -0
  258. data/app/views/decidim/enhanced_textwork/paragraphs/_filters.html.erb +48 -0
  259. data/app/views/decidim/enhanced_textwork/paragraphs/_filters_small_view.html.erb +18 -0
  260. data/app/views/decidim/enhanced_textwork/paragraphs/_linked_paragraphs.html.erb +34 -0
  261. data/app/views/decidim/enhanced_textwork/paragraphs/_paragraph.html.erb +1 -0
  262. data/app/views/decidim/enhanced_textwork/paragraphs/_paragraph_badge.html.erb +3 -0
  263. data/app/views/decidim/enhanced_textwork/paragraphs/_paragraph_similar.html.erb +22 -0
  264. data/app/views/decidim/enhanced_textwork/paragraphs/_paragraphs.html.erb +46 -0
  265. data/app/views/decidim/enhanced_textwork/paragraphs/_remaining_votes_count.html.erb +3 -0
  266. data/app/views/decidim/enhanced_textwork/paragraphs/_vote_button.html.erb +61 -0
  267. data/app/views/decidim/enhanced_textwork/paragraphs/_votes_count.html.erb +18 -0
  268. data/app/views/decidim/enhanced_textwork/paragraphs/_voting_rules.html.erb +50 -0
  269. data/app/views/decidim/enhanced_textwork/paragraphs/_wizard_aside.html.erb +20 -0
  270. data/app/views/decidim/enhanced_textwork/paragraphs/_wizard_header.html.erb +42 -0
  271. data/app/views/decidim/enhanced_textwork/paragraphs/compare.html.erb +23 -0
  272. data/app/views/decidim/enhanced_textwork/paragraphs/complete.html.erb +24 -0
  273. data/app/views/decidim/enhanced_textwork/paragraphs/edit.html.erb +31 -0
  274. data/app/views/decidim/enhanced_textwork/paragraphs/edit_draft.html.erb +26 -0
  275. data/app/views/decidim/enhanced_textwork/paragraphs/index.html.erb +56 -0
  276. data/app/views/decidim/enhanced_textwork/paragraphs/index.js.erb +10 -0
  277. data/app/views/decidim/enhanced_textwork/paragraphs/new.html.erb +38 -0
  278. data/app/views/decidim/enhanced_textwork/paragraphs/participatory_texts/_index.html.erb +20 -0
  279. data/app/views/decidim/enhanced_textwork/paragraphs/participatory_texts/_overview.html.erb +35 -0
  280. data/app/views/decidim/enhanced_textwork/paragraphs/participatory_texts/_paragraph_vote_button.html.erb +53 -0
  281. data/app/views/decidim/enhanced_textwork/paragraphs/participatory_texts/_paragraph_vote_button_chevron.html.erb +72 -0
  282. data/app/views/decidim/enhanced_textwork/paragraphs/participatory_texts/_paragraph_votes_count.html.erb +41 -0
  283. data/app/views/decidim/enhanced_textwork/paragraphs/participatory_texts/_view_index.html.erb +10 -0
  284. data/app/views/decidim/enhanced_textwork/paragraphs/participatory_texts/participatory_text.html.erb +29 -0
  285. data/app/views/decidim/enhanced_textwork/paragraphs/preview.html.erb +41 -0
  286. data/app/views/decidim/enhanced_textwork/paragraphs/show.html.erb +143 -0
  287. data/app/views/decidim/enhanced_textwork/versions/index.html.erb +16 -0
  288. data/app/views/decidim/enhanced_textwork/versions/show.html.erb +18 -0
  289. data/config/assets.rb +10 -0
  290. data/config/locales/de.yml +927 -0
  291. data/config/locales/en.yml +967 -0
  292. data/config/locales/todo/am-ET.yml +1 -0
  293. data/config/locales/todo/ar-SA.yml +801 -0
  294. data/config/locales/todo/ar.yml +791 -0
  295. data/config/locales/todo/bg-BG.yml +237 -0
  296. data/config/locales/todo/bg.yml +238 -0
  297. data/config/locales/todo/ca.yml +908 -0
  298. data/config/locales/todo/cs-CZ.yml +787 -0
  299. data/config/locales/todo/cs.yml +969 -0
  300. data/config/locales/todo/da-DK.yml +1 -0
  301. data/config/locales/todo/da.yml +1 -0
  302. data/config/locales/todo/el-GR.yml +1 -0
  303. data/config/locales/todo/el.yml +848 -0
  304. data/config/locales/todo/eo-UY.yml +1 -0
  305. data/config/locales/todo/eo.yml +1 -0
  306. data/config/locales/todo/es-MX.yml +908 -0
  307. data/config/locales/todo/es-PY.yml +908 -0
  308. data/config/locales/todo/es.yml +908 -0
  309. data/config/locales/todo/et-EE.yml +1 -0
  310. data/config/locales/todo/et.yml +1 -0
  311. data/config/locales/todo/eu.yml +717 -0
  312. data/config/locales/todo/fi-pl.yml +763 -0
  313. data/config/locales/todo/fi-plain.yml +920 -0
  314. data/config/locales/todo/fi.yml +920 -0
  315. data/config/locales/todo/fr-CA.yml +936 -0
  316. data/config/locales/todo/fr-LU.yml +903 -0
  317. data/config/locales/todo/fr.yml +936 -0
  318. data/config/locales/todo/ga-IE.yml +275 -0
  319. data/config/locales/todo/gl.yml +808 -0
  320. data/config/locales/todo/hr-HR.yml +1 -0
  321. data/config/locales/todo/hr.yml +1 -0
  322. data/config/locales/todo/hu.yml +847 -0
  323. data/config/locales/todo/id-ID.yml +704 -0
  324. data/config/locales/todo/is-IS.yml +269 -0
  325. data/config/locales/todo/is.yml +274 -0
  326. data/config/locales/todo/it.yml +908 -0
  327. data/config/locales/todo/ja.yml +922 -0
  328. data/config/locales/todo/ko-KR.yml +1 -0
  329. data/config/locales/todo/ko.yml +1 -0
  330. data/config/locales/todo/lb-LU.yml +1 -0
  331. data/config/locales/todo/lb.yml +40 -0
  332. data/config/locales/todo/lt-LT.yml +1 -0
  333. data/config/locales/todo/lt.yml +1 -0
  334. data/config/locales/todo/lv.yml +838 -0
  335. data/config/locales/todo/mt-MT.yml +1 -0
  336. data/config/locales/todo/mt.yml +1 -0
  337. data/config/locales/todo/nl.yml +882 -0
  338. data/config/locales/todo/no.yml +770 -0
  339. data/config/locales/todo/om-ET.yml +1 -0
  340. data/config/locales/todo/pl.yml +927 -0
  341. data/config/locales/todo/pt-BR.yml +908 -0
  342. data/config/locales/todo/pt.yml +945 -0
  343. data/config/locales/todo/ro-RO.yml +886 -0
  344. data/config/locales/todo/ru.yml +379 -0
  345. data/config/locales/todo/si-LK.yml +1 -0
  346. data/config/locales/todo/sk-SK.yml +896 -0
  347. data/config/locales/todo/sk.yml +851 -0
  348. data/config/locales/todo/sl.yml +26 -0
  349. data/config/locales/todo/so-SO.yml +1 -0
  350. data/config/locales/todo/sr-CS.yml +125 -0
  351. data/config/locales/todo/sv.yml +908 -0
  352. data/config/locales/todo/sw-KE.yml +1 -0
  353. data/config/locales/todo/ti-ER.yml +1 -0
  354. data/config/locales/todo/tr-TR.yml +890 -0
  355. data/config/locales/todo/uk.yml +379 -0
  356. data/config/locales/todo/vi-VN.yml +1 -0
  357. data/config/locales/todo/vi.yml +1 -0
  358. data/config/locales/todo/zh-CN.yml +857 -0
  359. data/config/locales/todo/zh-TW.yml +1 -0
  360. data/db/migrate/20161212110850_create_decidim_paragraphs.rb +16 -0
  361. data/db/migrate/20170112115253_create_paragraph_votes.rb +14 -0
  362. data/db/migrate/20170113114245_add_enhanced_textwork_text_search_indexes.rb +8 -0
  363. data/db/migrate/20170118120151_add_counter_cache_votes_to_paragraphs.rb +7 -0
  364. data/db/migrate/20170120151202_add_user_group_id_to_paragraphs.rb +7 -0
  365. data/db/migrate/20170131092413_add_answers_to_paragraphs.rb +9 -0
  366. data/db/migrate/20170205082832_add_index_to_decidim_enhanced_textwork_paragraphs_paragraph_votes_count.rb +9 -0
  367. data/db/migrate/20170215113152_create_paragraph_reports.rb +16 -0
  368. data/db/migrate/20170215131720_add_report_count_to_paragraphs.rb +7 -0
  369. data/db/migrate/20170215132030_add_reference_to_paragraphs.rb +13 -0
  370. data/db/migrate/20170220152416_add_hidden_at_to_paragraphs.rb +7 -0
  371. data/db/migrate/20170228105156_add_geolocalization_fields_to_paragraphs.rb +9 -0
  372. data/db/migrate/20170307085300_migrate_paragraph_reports_data_to_reports.rb +24 -0
  373. data/db/migrate/20170410073742_remove_not_null_reference_paragraphs.rb +7 -0
  374. data/db/migrate/20170612101809_migrate_paragraphs_category.rb +15 -0
  375. data/db/migrate/20171201115434_create_paragraph_endorsements.rb +16 -0
  376. data/db/migrate/20171201122623_add_counter_cache_endorsements_to_paragraphs.rb +8 -0
  377. data/db/migrate/20171212102250_enable_pg_trgm_extension_for_paragraphs.rb +18 -0
  378. data/db/migrate/20171220084719_add_published_at_to_paragraphs.rb +14 -0
  379. data/db/migrate/20180111110204_create_decidim_paragraph_notes.rb +15 -0
  380. data/db/migrate/20180115155220_add_index_created_at_paragraph_notes.rb +7 -0
  381. data/db/migrate/20180305133811_rename_features_to_components_at_paragraphs.rb +11 -0
  382. data/db/migrate/20180326091532_create_decidim_enhanced_textwork_collaborative_drafts.rb +29 -0
  383. data/db/migrate/20180413135249_fix_nil_threshold_per_paragraph.rb +18 -0
  384. data/db/migrate/20180529101323_add_counter_cache_coauthorships_to_paragraphs.rb +8 -0
  385. data/db/migrate/20180529110230_move_enhanced_textwork_authorships_to_coauthorships.rb +28 -0
  386. data/db/migrate/20180529110830_remove_authorships_from_paragraphs.rb +8 -0
  387. data/db/migrate/20180613151121_create_enhanced_textwork_collaborative_draft_collaborator_requests.rb +12 -0
  388. data/db/migrate/20180711074134_add_enhanced_textwork_counter_cache_coauthorships_to_collaborative_drafts.rb +7 -0
  389. data/db/migrate/20180711075004_remove_index_counter_cache_coauthorships_to_paragraphs.rb +7 -0
  390. data/db/migrate/20180927111721_create_enhanced_textwork_participatory_texts.rb +13 -0
  391. data/db/migrate/20180930125321_add_participatory_text_level_to_paragraphs.rb +7 -0
  392. data/db/migrate/20180930125321_add_position_to_paragraphs.rb +7 -0
  393. data/db/migrate/20181003074440_fix_user_groups_ids_in_paragraphs_endorsements.rb +20 -0
  394. data/db/migrate/20181010114622_add_enhanced_textwork_temporary_votes.rb +9 -0
  395. data/db/migrate/20181016132225_add_enhanced_textwork_organization_as_author.rb +13 -0
  396. data/db/migrate/20181017084221_make_author_polymorhpic_for_paragraph_endorsements.rb +31 -0
  397. data/db/migrate/20181026073215_add_enhanced_textwork_created_in_meeting.rb +7 -0
  398. data/db/migrate/20190215113158_use_enhanced_textwork_md5_indexes.rb +17 -0
  399. data/db/migrate/20191206154128_add_endorsements_counter_cache_to_paragraphs.rb +7 -0
  400. data/db/migrate/20200120215928_move_paragraph_endorsements_to_core_endorsements.rb +54 -0
  401. data/db/migrate/20200120230130_drop_paragraph_endorsements.rb +8 -0
  402. data/db/migrate/20200203111239_add_paragraph_valuation_assignments.rb +12 -0
  403. data/db/migrate/20200210135152_add_costs_to_paragraphs.rb +9 -0
  404. data/db/migrate/20200212120110_sync_paragraphs_state_with_amendments_state.rb +28 -0
  405. data/db/migrate/20200227175922_add_state_published_at_to_paragraphs.rb +7 -0
  406. data/db/migrate/20200306123652_publish_existing_paragraphs_state.rb +15 -0
  407. data/db/migrate/20200708091228_move_paragraphs_fields_to_i18n.rb +86 -0
  408. data/db/migrate/20200730131631_move_paragraph_endorsed_event_notifications_to_resource_endorsed_event.rb +20 -0
  409. data/db/migrate/20200827154156_add_commentable_counter_cache_to_paragraphs.rb +12 -0
  410. data/db/migrate/20201002085508_fix_paragraphs_data.rb +36 -0
  411. data/db/migrate/20210127115628_fix_answered_paragraphs_after_copy.rb +14 -0
  412. data/db/migrate/20210310102839_add_followable_counter_cache_to_paragraphs.rb +16 -0
  413. data/db/migrate/20210310120812_add_enhanced_textwork_followable_counter_cache_to_collaborative_drafts.rb +16 -0
  414. data/db/migrate/20210318082934_fix_counters_for_copied_paragraphs.rb +19 -0
  415. data/lib/decidim/api/paragraph_input_filter.rb +29 -0
  416. data/lib/decidim/api/paragraph_input_sort.rb +20 -0
  417. data/lib/decidim/api/paragraph_type.rb +56 -0
  418. data/lib/decidim/api/paragraphs_type.rb +43 -0
  419. data/lib/decidim/content_parsers/paragraph_parser.rb +101 -0
  420. data/lib/decidim/content_renderers/paragraph_renderer.rb +33 -0
  421. data/lib/decidim/enhanced_textwork/admin.rb +10 -0
  422. data/lib/decidim/enhanced_textwork/admin_engine.rb +52 -0
  423. data/lib/decidim/enhanced_textwork/api.rb +10 -0
  424. data/lib/decidim/enhanced_textwork/commentable_collaborative_draft.rb +38 -0
  425. data/lib/decidim/enhanced_textwork/commentable_paragraph.rb +36 -0
  426. data/lib/decidim/enhanced_textwork/component.rb +448 -0
  427. data/lib/decidim/enhanced_textwork/doc_to_markdown.rb +50 -0
  428. data/lib/decidim/enhanced_textwork/engine.rb +204 -0
  429. data/lib/decidim/enhanced_textwork/html_to_markdown.rb +22 -0
  430. data/lib/decidim/enhanced_textwork/markdown_to_paragraphs.rb +153 -0
  431. data/lib/decidim/enhanced_textwork/odt_to_markdown.rb +46 -0
  432. data/lib/decidim/enhanced_textwork/paragraph_creator.rb +98 -0
  433. data/lib/decidim/enhanced_textwork/paragraph_serializer.rb +95 -0
  434. data/lib/decidim/enhanced_textwork/participatory_text_section.rb +21 -0
  435. data/lib/decidim/enhanced_textwork/test/capybara_paragraphs_picker.rb +59 -0
  436. data/lib/decidim/enhanced_textwork/test/factories.rb +492 -0
  437. data/lib/decidim/enhanced_textwork/valuatable.rb +21 -0
  438. data/lib/decidim/enhanced_textwork/version.rb +14 -0
  439. data/lib/decidim/enhanced_textwork.rb +58 -0
  440. data/lib/decidim/exporters/word.rb +309 -0
  441. metadata +704 -0
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users want to create a paragraph.
7
+ class ParagraphBaseForm < Decidim::Form
8
+ include Decidim::TranslatableAttributes
9
+ include Decidim::AttachmentAttributes
10
+ include Decidim::ApplicationHelper
11
+
12
+ mimic :paragraph
13
+
14
+ attribute :address, String
15
+ attribute :latitude, Float
16
+ attribute :longitude, Float
17
+ attribute :category_id, Integer
18
+ attribute :scope_id, Integer
19
+ attribute :attachment, AttachmentForm
20
+ attribute :position, Integer
21
+ attribute :created_in_meeting, Boolean
22
+ attribute :meeting_id, Integer
23
+ attribute :suggested_hashtags, Array[String]
24
+
25
+ attachments_attribute :photos
26
+
27
+ validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? }
28
+ validates :category, presence: true, if: ->(form) { form.category_id.present? }
29
+ validates :scope, presence: true, if: ->(form) { form.scope_id.present? }
30
+ validates :scope_id, scope_belongs_to_component: true, if: ->(form) { form.scope_id.present? }
31
+ validates :meeting_as_author, presence: true, if: ->(form) { form.created_in_meeting? }
32
+
33
+ validate :notify_missing_attachment_if_errored
34
+
35
+ delegate :categories, to: :current_component
36
+
37
+ def map_model(model)
38
+ body = translated_attribute(model.body)
39
+ @suggested_hashtags = Decidim::ContentRenderers::HashtagRenderer.new(body).extra_hashtags.map(&:name).map(&:downcase)
40
+
41
+ return unless model.categorization
42
+
43
+ self.category_id = model.categorization.decidim_category_id
44
+ self.scope_id = model.decidim_scope_id
45
+ end
46
+
47
+ alias component current_component
48
+
49
+ # Finds the Category from the category_id.
50
+ #
51
+ # Returns a Decidim::Category
52
+ def category
53
+ @category ||= categories.find_by(id: category_id)
54
+ end
55
+
56
+ # Finds the Scope from the given decidim_scope_id, uses participatory space scope if missing.
57
+ #
58
+ # Returns a Decidim::Scope
59
+ def scope
60
+ @scope ||= @scope_id ? current_component.scopes.find_by(id: @scope_id) : current_component.scope
61
+ end
62
+
63
+ # Scope identifier
64
+ #
65
+ # Returns the scope identifier related to the paragraph
66
+ def scope_id
67
+ @scope_id || scope&.id
68
+ end
69
+
70
+ def geocoding_enabled?
71
+ Decidim::Map.available?(:geocoding) && current_component.settings.geocoding_enabled?
72
+ end
73
+
74
+ def has_address?
75
+ geocoding_enabled? && address.present?
76
+ end
77
+
78
+ def geocoded?
79
+ latitude.present? && longitude.present?
80
+ end
81
+
82
+ # Finds the Meetings of the current participatory space
83
+ def meetings
84
+ @meetings ||= Decidim.find_resource_manifest(:meetings).try(:resource_scope, current_component)
85
+ &.order(title: :asc)
86
+ end
87
+
88
+ # Return the meeting as author
89
+ def meeting_as_author
90
+ @meeting_as_author ||= meetings.find_by(id: meeting_id)
91
+ end
92
+
93
+ def author
94
+ return current_organization unless created_in_meeting?
95
+
96
+ meeting_as_author
97
+ end
98
+
99
+ def extra_hashtags
100
+ @extra_hashtags ||= (component_automatic_hashtags + suggested_hashtags).uniq
101
+ end
102
+
103
+ def suggested_hashtags
104
+ downcased_suggested_hashtags = Array(@suggested_hashtags&.map(&:downcase)).to_set
105
+ component_suggested_hashtags.select { |hashtag| downcased_suggested_hashtags.member?(hashtag.downcase) }
106
+ end
107
+
108
+ def suggested_hashtag_checked?(hashtag)
109
+ suggested_hashtags.member?(hashtag)
110
+ end
111
+
112
+ def component_automatic_hashtags
113
+ @component_automatic_hashtags ||= ordered_hashtag_list(current_component.current_settings.automatic_hashtags)
114
+ end
115
+
116
+ def component_suggested_hashtags
117
+ @component_suggested_hashtags ||= ordered_hashtag_list(current_component.current_settings.suggested_hashtags)
118
+ end
119
+
120
+ private
121
+
122
+ # This method will add an error to the `attachment` field only if there's
123
+ # any error in any other field. This is needed because when the form has
124
+ # an error, the attachment is lost, so we need a way to inform the user of
125
+ # this problem.
126
+ def notify_missing_attachment_if_errored
127
+ errors.add(:attachment, :needs_to_be_reattached) if errors.any? && attachment.present?
128
+ errors.add(:add_photos, :needs_to_be_reattached) if errors.any? && add_photos.present?
129
+ end
130
+
131
+ def ordered_hashtag_list(string)
132
+ string.to_s.split.reject(&:blank?).uniq.sort_by(&:parameterize)
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users want to create a paragraph.
7
+ class ParagraphForm < Decidim::EnhancedTextwork::Admin::ParagraphBaseForm
8
+ translatable_attribute :title, String do |field, _locale|
9
+ validates field, length: { in: 15..150 }, if: proc { |resource| resource.send(field).present? }
10
+ end
11
+ translatable_attribute :body, String
12
+
13
+ validates :title, :body, translatable_presence: true
14
+
15
+ validate :notify_missing_attachment_if_errored
16
+
17
+ def map_model(model)
18
+ super(model)
19
+ presenter = ParagraphPresenter.new(model)
20
+
21
+ self.title = presenter.title(all_locales: title.is_a?(Hash))
22
+ self.body = presenter.body(all_locales: body.is_a?(Hash))
23
+ self.attachment = if model.documents.first.present?
24
+ { file: model.documents.first.file, title: translated_attribute(model.documents.first.title) }
25
+ else
26
+ {}
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users want to create a paragraph.
7
+ class ParagraphNoteForm < Decidim::Form
8
+ mimic :paragraph_note
9
+
10
+ attribute :body, String
11
+
12
+ validates :body, presence: true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A common abstract to be used by the Merge and Split paragraphs forms.
7
+ class ParagraphsForkForm < Decidim::Form
8
+ mimic :paragraphs_import
9
+
10
+ attribute :target_component_id, Integer
11
+ attribute :paragraph_ids, Array
12
+
13
+ validates :target_component, :paragraphs, :current_component, presence: true
14
+ validate :same_participatory_space
15
+ validate :mergeable_to_same_component
16
+
17
+ def paragraphs
18
+ @paragraphs ||= Decidim::EnhancedTextwork::Paragraph.where(component: current_component, id: paragraph_ids).uniq
19
+ end
20
+
21
+ def target_component
22
+ return current_component if clean_target_component_id == current_component.id
23
+
24
+ @target_component ||= current_component.siblings.find_by(id: target_component_id)
25
+ end
26
+
27
+ def same_component?
28
+ target_component == current_component
29
+ end
30
+
31
+ private
32
+
33
+ def errors_set
34
+ @errors_set ||= Set[]
35
+ end
36
+
37
+ def mergeable_to_same_component
38
+ return true unless same_component?
39
+
40
+ paragraphs.each do |paragraph|
41
+ errors_set << :not_official unless paragraph.official?
42
+ errors_set << :supported if paragraph.votes.any? || paragraph.endorsements.any?
43
+ end
44
+
45
+ errors_set.each { |error| errors.add(:base, error) } if errors_set.any?
46
+ end
47
+
48
+ def same_participatory_space
49
+ return if !target_component || !current_component
50
+
51
+ errors.add(:target_component, :invalid) if current_component.participatory_space != target_component.participatory_space
52
+ end
53
+
54
+ # Private: Returns the id of the target component.
55
+ #
56
+ # We receive this as ["id"] since it's from a select in a form.
57
+ def clean_target_component_id
58
+ target_component_id.first.to_i
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users want to import a collection of paragraphs
7
+ # from another component.
8
+ class ParagraphsImportForm < Decidim::Form
9
+ mimic :paragraphs_import
10
+
11
+ attribute :origin_component_id, Integer
12
+ attribute :import_paragraphs, Boolean
13
+ attribute :keep_answers, Boolean
14
+ attribute :keep_authors, Boolean
15
+ attribute :states, Array
16
+ attribute :scope_ids, Array
17
+
18
+ validates :origin_component_id, :origin_component, :states, :current_component, presence: true
19
+ validates :import_paragraphs, allow_nil: false, acceptance: true
20
+ validate :valid_states
21
+
22
+ VALID_STATES = %w(accepted not_answered evaluating rejected withdrawn).freeze
23
+
24
+ def states_collection
25
+ VALID_STATES.map do |state|
26
+ OpenStruct.new(
27
+ name: I18n.t(state, scope: "decidim.enhanced_textwork.answers"),
28
+ value: state
29
+ )
30
+ end
31
+ end
32
+
33
+ def states
34
+ super.reject(&:blank?)
35
+ end
36
+
37
+ def scopes
38
+ Decidim::Scope.where(organization: current_organization, id: scope_ids)
39
+ end
40
+
41
+ def origin_component
42
+ @origin_component ||= origin_components.find_by(id: origin_component_id)
43
+ end
44
+
45
+ def origin_components
46
+ @origin_components ||= current_participatory_space.components.where.not(id: current_component.id).where(manifest_name: :paragraphs)
47
+ end
48
+
49
+ def origin_components_collection
50
+ origin_components.map do |component|
51
+ [component.name[I18n.locale.to_s], component.id]
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def valid_states
58
+ return if states.all? do |state|
59
+ VALID_STATES.include?(state)
60
+ end
61
+
62
+ errors.add(:states, :invalid)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users wants to merge two or more
7
+ # paragraphs into a new one to another paragraph component in the same space.
8
+ class ParagraphsMergeForm < ParagraphsForkForm
9
+ validates :paragraphs, length: { minimum: 2 }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users wants to split two or more
7
+ # paragraphs into a new one to another paragraph component in the same space.
8
+ class ParagraphsSplitForm < ParagraphsForkForm
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users want to create a paragraph
7
+ # through the participatory texts.
8
+ class ParticipatoryTextParagraphForm < Admin::ParagraphBaseForm
9
+ attribute :title, String
10
+ attribute :body, String
11
+ validates :title, length: { maximum: 150 }, presence: true
12
+
13
+ def map_model(model)
14
+ self.title = translated_attribute(model.title)
15
+ self.body = translated_attribute(model.body)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ # A form object to be used when admin users want to review a collection of paragraphs
7
+ # from a participatory text.
8
+ class PreviewParticipatoryTextForm < Decidim::Form
9
+ attribute :paragraphs, Array[Decidim::EnhancedTextwork::Admin::ParticipatoryTextParagraphForm]
10
+
11
+ def from_models(paragraphs)
12
+ self.paragraphs = paragraphs.collect do |paragraph|
13
+ Admin::ParticipatoryTextParagraphForm.from_model(paragraph)
14
+ end
15
+ end
16
+
17
+ def paragraphs_attributes=(attributes); end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ class ValuationAssignmentForm < Decidim::Form
7
+ mimic :valuator_role
8
+
9
+ attribute :id, Integer
10
+ attribute :paragraph_ids, Array
11
+
12
+ validates :valuator_role, :paragraphs, :current_component, presence: true
13
+ validate :same_participatory_space
14
+
15
+ def paragraphs
16
+ @paragraphs ||= Decidim::EnhancedTextwork::Paragraph.where(component: current_component, id: paragraph_ids).uniq
17
+ end
18
+
19
+ def valuator_role
20
+ @valuator_role ||= current_component.participatory_space.user_roles(:valuator).find_by(id: id)
21
+ end
22
+
23
+ def valuator_user
24
+ return unless valuator_role
25
+
26
+ @valuator_user ||= valuator_role.user
27
+ end
28
+
29
+ def same_participatory_space
30
+ return if !valuator_role || !current_component
31
+
32
+ errors.add(:id, :invalid) if current_component.participatory_space != valuator_role.participatory_space
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ # A form object to be used when public users want to create a Collaborative Draft.
6
+ class CollaborativeDraftForm < Decidim::EnhancedTextwork::ParagraphForm
7
+ def map_model(model)
8
+ super
9
+
10
+ return unless model.categorization
11
+
12
+ self.category_id = model.categorization.decidim_category_id
13
+ end
14
+
15
+ def user_group
16
+ @user_group ||= Decidim::UserGroup.find user_group_id if user_group_id.present?
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ # A form object to be used when public users want to create a paragraph.
6
+ class ParagraphForm < Decidim::EnhancedTextwork::ParagraphWizardCreateStepForm
7
+ include Decidim::TranslatableAttributes
8
+ include Decidim::AttachmentAttributes
9
+
10
+ mimic :paragraph
11
+
12
+ attribute :address, String
13
+ attribute :latitude, Float
14
+ attribute :longitude, Float
15
+ attribute :category_id, Integer
16
+ attribute :scope_id, Integer
17
+ attribute :has_address, Boolean
18
+ attribute :attachment, AttachmentForm
19
+ attribute :suggested_hashtags, Array[String]
20
+
21
+ attachments_attribute :photos
22
+ attachments_attribute :documents
23
+
24
+ validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? }
25
+ validates :address, presence: true, if: ->(form) { form.has_address? }
26
+ validates :category, presence: true, if: ->(form) { form.category_id.present? }
27
+ validates :scope, presence: true, if: ->(form) { form.scope_id.present? }
28
+ validates :scope_id, scope_belongs_to_component: true, if: ->(form) { form.scope_id.present? }
29
+ validate :notify_missing_attachment_if_errored
30
+
31
+ delegate :categories, to: :current_component
32
+
33
+ def map_model(model)
34
+ super
35
+
36
+ body = translated_attribute(model.body)
37
+ @suggested_hashtags = Decidim::ContentRenderers::HashtagRenderer.new(body).extra_hashtags.map(&:name).map(&:downcase)
38
+
39
+ # The scope attribute is with different key (decidim_scope_id), so it
40
+ # has to be manually mapped.
41
+ self.scope_id = model.scope.id if model.scope
42
+
43
+ self.has_address = true if model.address.present?
44
+ end
45
+
46
+ # Finds the Category from the category_id.
47
+ #
48
+ # Returns a Decidim::Category
49
+ def category
50
+ @category ||= categories.find_by(id: category_id)
51
+ end
52
+
53
+ # Finds the Scope from the given scope_id, uses participatory space scope if missing.
54
+ #
55
+ # Returns a Decidim::Scope
56
+ def scope
57
+ @scope ||= @scope_id ? current_component.scopes.find_by(id: @scope_id) : current_component.scope
58
+ end
59
+
60
+ # Scope identifier
61
+ #
62
+ # Returns the scope identifier related to the paragraph
63
+ def scope_id
64
+ @scope_id || scope&.id
65
+ end
66
+
67
+ def geocoding_enabled?
68
+ Decidim::Map.available?(:geocoding) && current_component.settings.geocoding_enabled?
69
+ end
70
+
71
+ def address
72
+ return unless has_address
73
+
74
+ super
75
+ end
76
+
77
+ def has_address?
78
+ return unless has_address
79
+
80
+ geocoding_enabled? && address.present?
81
+ end
82
+
83
+ def geocoded?
84
+ latitude.present? && longitude.present?
85
+ end
86
+
87
+ def extra_hashtags
88
+ @extra_hashtags ||= (component_automatic_hashtags + suggested_hashtags).uniq
89
+ end
90
+
91
+ def suggested_hashtags
92
+ downcased_suggested_hashtags = Array(@suggested_hashtags&.map(&:downcase)).to_set
93
+ component_suggested_hashtags.select { |hashtag| downcased_suggested_hashtags.member?(hashtag.downcase) }
94
+ end
95
+
96
+ def suggested_hashtag_checked?(hashtag)
97
+ suggested_hashtags.member?(hashtag)
98
+ end
99
+
100
+ def component_automatic_hashtags
101
+ @component_automatic_hashtags ||= ordered_hashtag_list(current_component.current_settings.automatic_hashtags)
102
+ end
103
+
104
+ def component_suggested_hashtags
105
+ @component_suggested_hashtags ||= ordered_hashtag_list(current_component.current_settings.suggested_hashtags)
106
+ end
107
+
108
+ private
109
+
110
+ # This method will add an error to the `add_photos` and/or "add_documents" fields
111
+ # only if there's any error in any other field. This is needed because when the
112
+ # form has an error, the attachment is lost, so we need a way to inform the user of
113
+ # this problem.
114
+ def notify_missing_attachment_if_errored
115
+ if errors.any?
116
+ errors.add(:add_photos, :needs_to_be_reattached) if add_photos.present?
117
+ errors.add(:add_documents, :needs_to_be_reattached) if add_documents.present?
118
+ end
119
+ end
120
+
121
+ def ordered_hashtag_list(string)
122
+ string.to_s.split.reject(&:blank?).uniq.sort_by(&:parameterize)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ # A form object to be used when public users want to create a paragraph.
6
+ class ParagraphWizardCreateStepForm < Decidim::Form
7
+ mimic :paragraph
8
+
9
+ attribute :title, String
10
+ attribute :body, Decidim::Attributes::CleanString
11
+ attribute :body_template, String
12
+ attribute :user_group_id, Integer
13
+
14
+ validates :title, :body, presence: true, etiquette: true
15
+ validates :title, length: { in: 15..150 }
16
+ validates :body, paragraph_length: {
17
+ minimum: 15,
18
+ maximum: ->(record) { record.component.settings.paragraph_length }
19
+ }
20
+
21
+ validate :body_is_not_bare_template
22
+
23
+ alias component current_component
24
+
25
+ def map_model(model)
26
+ self.user_group_id = model.user_groups.first&.id
27
+ return unless model.categorization
28
+
29
+ self.category_id = model.categorization.decidim_category_id
30
+ end
31
+
32
+ private
33
+
34
+ def body_is_not_bare_template
35
+ return if body_template.blank?
36
+
37
+ errors.add(:body, :cant_be_equal_to_template) if body.presence == body_template.presence
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ # A form object to be used when Collaborative Draft editors rejects a request to acces it.
6
+ class RejectAccessToCollaborativeDraftForm < AccessToCollaborativeDraftForm
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ # A form object to be used when public users want to request acces to a Collaborative Draft.
6
+ class RequestAccessToCollaborativeDraftForm < Decidim::Form
7
+ mimic :collaborative_draft
8
+
9
+ attribute :id, String
10
+ attribute :state, String
11
+
12
+ validates :id, presence: true
13
+ validates :state, presence: true, inclusion: { in: %w(open) }
14
+
15
+ def collaborative_draft
16
+ @collaborative_draft ||= Decidim::EnhancedTextwork::CollaborativeDraft.find id
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module EnhancedTextwork
5
+ module Admin
6
+ module FilterableHelper
7
+ def extra_dropdown_submenu_options_items(filter, i18n_scope)
8
+ options = case filter
9
+ when :state_eq
10
+ tag.li(filter_link_value(:state_null, true, i18n_scope))
11
+ end
12
+ [options].compact
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end