decidim-admin 0.29.2 → 0.30.0.rc2

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 (236) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/admin/multi_select_picker/show.erb +10 -0
  3. data/app/cells/decidim/admin/multi_select_picker_cell.rb +38 -0
  4. data/app/commands/decidim/admin/bulk_action.rb +92 -0
  5. data/app/commands/decidim/admin/bulk_block_users.rb +75 -0
  6. data/app/commands/decidim/admin/bulk_unblock_users.rb +66 -0
  7. data/app/commands/decidim/admin/bulk_unreport_users.rb +69 -0
  8. data/app/commands/decidim/admin/content_blocks/update_content_block.rb +1 -1
  9. data/app/commands/decidim/admin/create_participatory_space_private_user.rb +3 -1
  10. data/app/commands/decidim/admin/create_share_token.rb +39 -0
  11. data/app/commands/decidim/admin/create_taxonomy.rb +23 -0
  12. data/app/commands/decidim/admin/create_taxonomy_filter.rb +24 -0
  13. data/app/commands/decidim/admin/destroy_share_token.rb +22 -0
  14. data/app/commands/decidim/admin/destroy_taxonomy.rb +18 -0
  15. data/app/commands/decidim/admin/destroy_taxonomy_filter.rb +20 -0
  16. data/app/commands/decidim/admin/hide_menu_component.rb +37 -0
  17. data/app/commands/decidim/admin/hide_resource.rb +4 -3
  18. data/app/commands/decidim/admin/publish_all_participatory_space_private_users.rb +50 -0
  19. data/app/commands/decidim/admin/publish_component.rb +3 -0
  20. data/app/commands/decidim/admin/reorder_components.rb +47 -0
  21. data/app/commands/decidim/admin/reorder_taxonomies.rb +76 -0
  22. data/app/commands/decidim/admin/unhide_resource.rb +11 -3
  23. data/app/commands/decidim/admin/unpublish_all_participatory_space_private_users.rb +50 -0
  24. data/app/commands/decidim/admin/unreport_resource.rb +11 -3
  25. data/app/commands/decidim/admin/update_component_permissions.rb +53 -13
  26. data/app/commands/decidim/admin/update_participatory_space_private_user.rb +11 -0
  27. data/app/commands/decidim/admin/update_share_token.rb +24 -0
  28. data/app/commands/decidim/admin/update_taxonomy.rb +20 -0
  29. data/app/commands/decidim/admin/update_taxonomy_filter.rb +28 -0
  30. data/app/controllers/concerns/decidim/admin/component_taxonomies_helper.rb +19 -0
  31. data/app/controllers/concerns/decidim/admin/filterable.rb +15 -18
  32. data/app/controllers/concerns/decidim/admin/has_trashable_resources.rb +170 -0
  33. data/app/controllers/concerns/decidim/admin/needs_admin_tos_accepted.rb +2 -29
  34. data/app/controllers/concerns/decidim/admin/participatory_space_admin_context.rb +12 -2
  35. data/app/controllers/concerns/decidim/admin/taxonomies/filterable.rb +27 -0
  36. data/app/controllers/decidim/admin/application_controller.rb +1 -2
  37. data/app/controllers/decidim/admin/areas_controller.rb +1 -0
  38. data/app/controllers/decidim/admin/block_user_controller.rb +42 -0
  39. data/app/controllers/decidim/admin/component_permissions_controller.rb +2 -4
  40. data/app/controllers/decidim/admin/components_controller.rb +50 -9
  41. data/app/controllers/decidim/admin/concerns/has_private_users.rb +59 -2
  42. data/app/controllers/decidim/admin/global_moderations_controller.rb +4 -0
  43. data/app/controllers/decidim/admin/moderated_users_controller.rb +26 -0
  44. data/app/controllers/decidim/admin/moderations_controller.rb +18 -0
  45. data/app/controllers/decidim/admin/newsletters_controller.rb +50 -7
  46. data/app/controllers/decidim/admin/resource_permissions_controller.rb +1 -1
  47. data/app/controllers/decidim/admin/scopes_controller.rb +1 -0
  48. data/app/controllers/decidim/admin/share_tokens_controller.rb +109 -7
  49. data/app/controllers/decidim/admin/taxonomies_controller.rb +129 -0
  50. data/app/controllers/decidim/admin/taxonomy_filters_controller.rb +112 -0
  51. data/app/controllers/decidim/admin/taxonomy_filters_selector_controller.rb +81 -0
  52. data/app/controllers/decidim/admin/taxonomy_items_controller.rb +91 -0
  53. data/app/forms/concerns/decidim/has_taxonomy_form_attributes.rb +57 -0
  54. data/app/forms/decidim/admin/block_users_form.rb +21 -0
  55. data/app/forms/decidim/admin/import_example_form.rb +1 -1
  56. data/app/forms/decidim/admin/newsletter_form.rb +1 -1
  57. data/app/forms/decidim/admin/participatory_space_private_user_form.rb +5 -0
  58. data/app/forms/decidim/admin/selective_newsletter_form.rb +46 -11
  59. data/app/forms/decidim/admin/share_token_form.rb +55 -0
  60. data/app/forms/decidim/admin/taxonomy_filter_form.rb +85 -0
  61. data/app/forms/decidim/admin/taxonomy_form.rb +20 -0
  62. data/app/forms/decidim/admin/taxonomy_item_form.rb +54 -0
  63. data/app/helpers/decidim/admin/application_helper.rb +0 -1
  64. data/app/helpers/decidim/admin/bulk_actions_helper.rb +0 -31
  65. data/app/helpers/decidim/admin/moderations/reports_helper.rb +1 -1
  66. data/app/helpers/decidim/admin/moderations_helper.rb +1 -1
  67. data/app/helpers/decidim/admin/newsletters_helper.rb +57 -27
  68. data/app/helpers/decidim/admin/scopes_helper.rb +0 -6
  69. data/app/helpers/decidim/admin/search_form_helper.rb +1 -1
  70. data/app/helpers/decidim/admin/settings_helper.rb +85 -11
  71. data/app/jobs/decidim/admin/newsletter_job.rb +3 -1
  72. data/app/packs/entrypoints/decidim_admin.js +4 -0
  73. data/app/packs/src/decidim/admin/application.js +2 -0
  74. data/app/packs/src/decidim/admin/draggable-table.js +33 -0
  75. data/app/packs/src/decidim/admin/form.js +0 -1
  76. data/app/packs/src/decidim/admin/global_moderations.js +186 -0
  77. data/app/packs/src/decidim/admin/managed_moderated_users.js +186 -0
  78. data/app/packs/src/decidim/admin/newsletters.js +164 -82
  79. data/app/packs/src/decidim/admin/proposal_infinite_edit.js +3 -6
  80. data/app/packs/src/decidim/admin/sortable.js +28 -16
  81. data/app/packs/src/decidim/admin/taxonomy_filters.js +93 -0
  82. data/app/packs/stylesheets/decidim/admin/_component-show.scss +66 -5
  83. data/app/packs/stylesheets/decidim/admin/_legacy_foundation.scss +13 -0
  84. data/app/packs/stylesheets/decidim/admin/_select_picker.scss +20 -0
  85. data/app/packs/stylesheets/decidim/admin/_table-list.scss +22 -0
  86. data/app/packs/stylesheets/decidim/admin/_taxonomies.scss +74 -0
  87. data/app/packs/stylesheets/decidim/admin/application.scss +3 -0
  88. data/app/permissions/decidim/admin/permissions.rb +32 -1
  89. data/app/queries/decidim/admin/newsletter_recipients.rb +50 -14
  90. data/app/views/decidim/admin/areas/index.html.erb +3 -0
  91. data/app/views/decidim/admin/block_user/bulk_new.html.erb +45 -0
  92. data/app/views/decidim/admin/components/_actions.html.erb +50 -33
  93. data/app/views/decidim/admin/components/{_component.html.erb → _component_row.html.erb} +10 -5
  94. data/app/views/decidim/admin/components/_components_table.html.erb +18 -0
  95. data/app/views/decidim/admin/components/_form.html.erb +0 -12
  96. data/app/views/decidim/admin/components/_taxonomy_filters_drawer.html.erb +2 -0
  97. data/app/views/decidim/admin/components/_visibility_label.html.erb +9 -0
  98. data/app/views/decidim/admin/components/index.html.erb +12 -14
  99. data/app/views/decidim/admin/components/manage_trash.html.erb +11 -0
  100. data/app/views/decidim/admin/moderated_users/_bulk-actions.html.erb +6 -0
  101. data/app/views/decidim/admin/moderated_users/bulk_actions/_block.html.erb +20 -0
  102. data/app/views/decidim/admin/moderated_users/bulk_actions/_dropdown.html.erb +40 -0
  103. data/app/views/decidim/admin/moderated_users/bulk_actions/_unblock.html.erb +20 -0
  104. data/app/views/decidim/admin/moderated_users/bulk_actions/_unreport.html.erb +20 -0
  105. data/app/views/decidim/admin/moderated_users/index.html.erb +14 -6
  106. data/app/views/decidim/admin/moderations/_bulk-actions.html.erb +7 -0
  107. data/app/views/decidim/admin/moderations/_moderation-tr.html.erb +50 -0
  108. data/app/views/decidim/admin/moderations/_moderations-thead.html.erb +18 -0
  109. data/app/views/decidim/admin/moderations/bulk_actions/_dropdown.html.erb +43 -0
  110. data/app/views/decidim/admin/moderations/bulk_actions/_hide.html.erb +20 -0
  111. data/app/views/decidim/admin/moderations/bulk_actions/_unhide.html.erb +20 -0
  112. data/app/views/decidim/admin/moderations/bulk_actions/_unreport.html.erb +20 -0
  113. data/app/views/decidim/admin/moderations/index.html.erb +13 -81
  114. data/app/views/decidim/admin/newsletters/confirm_recipients.html.erb +64 -0
  115. data/app/views/decidim/admin/newsletters/select_recipients_to_deliver.html.erb +44 -20
  116. data/app/views/decidim/admin/participatory_space_private_users/_form.html.erb +6 -0
  117. data/app/views/decidim/admin/participatory_space_private_users/edit.html.erb +19 -0
  118. data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +15 -1
  119. data/app/views/decidim/admin/resource_permissions/_options_form.html.erb +5 -0
  120. data/app/views/decidim/admin/resource_permissions/edit.html.erb +2 -2
  121. data/app/views/decidim/admin/scope_types/index.html.erb +3 -0
  122. data/app/views/decidim/admin/scopes/index.html.erb +3 -0
  123. data/app/views/decidim/admin/share_tokens/_form.html.erb +52 -0
  124. data/app/views/decidim/admin/share_tokens/edit.html.erb +33 -0
  125. data/app/views/decidim/admin/share_tokens/index.html.erb +47 -0
  126. data/app/views/decidim/admin/share_tokens/new.html.erb +69 -0
  127. data/app/views/decidim/admin/taxonomies/_filters.html.erb +19 -0
  128. data/app/views/decidim/admin/taxonomies/_form.html.erb +5 -0
  129. data/app/views/decidim/admin/taxonomies/_row.html.erb +40 -0
  130. data/app/views/decidim/admin/taxonomies/_row_children.html.erb +8 -0
  131. data/app/views/decidim/admin/taxonomies/_table.html.erb +86 -0
  132. data/app/views/decidim/admin/taxonomies/_taxonomy_actions.html.erb +15 -0
  133. data/app/views/decidim/admin/taxonomies/edit.html.erb +87 -0
  134. data/app/views/decidim/admin/taxonomies/index.html.erb +28 -0
  135. data/app/views/decidim/admin/taxonomies/new.html.erb +16 -0
  136. data/app/views/decidim/admin/taxonomy_filters/_check_boxes.html.erb +10 -0
  137. data/app/views/decidim/admin/taxonomy_filters/_form.html.erb +96 -0
  138. data/app/views/decidim/admin/taxonomy_filters/_table.html.erb +33 -0
  139. data/app/views/decidim/admin/taxonomy_filters/edit.html.erb +22 -0
  140. data/app/views/decidim/admin/taxonomy_filters/index.html.erb +26 -0
  141. data/app/views/decidim/admin/taxonomy_filters/new.html.erb +32 -0
  142. data/app/views/decidim/admin/taxonomy_filters_selector/_check_boxes.html.erb +7 -0
  143. data/app/views/decidim/admin/taxonomy_filters_selector/_component_table.html.erb +25 -0
  144. data/app/views/decidim/admin/taxonomy_filters_selector/_taxonomies_select.html.erb +16 -0
  145. data/app/views/decidim/admin/taxonomy_filters_selector/index.html.erb +1 -0
  146. data/app/views/decidim/admin/taxonomy_filters_selector/new.html.erb +27 -0
  147. data/app/views/decidim/admin/taxonomy_filters_selector/show.html.erb +18 -0
  148. data/app/views/decidim/admin/taxonomy_items/_form.html.erb +8 -0
  149. data/app/views/decidim/admin/taxonomy_items/edit.html.erb +12 -0
  150. data/app/views/decidim/admin/taxonomy_items/new.html.erb +12 -0
  151. data/app/views/layouts/decidim/admin/taxonomy_filters.html.erb +17 -0
  152. data/app/views/layouts/decidim/admin/taxonomy_filters_selector.html.erb +10 -0
  153. data/config/locales/ar.yml +45 -37
  154. data/config/locales/bg.yml +48 -51
  155. data/config/locales/bs-BA.yml +1 -27
  156. data/config/locales/ca.yml +301 -50
  157. data/config/locales/cs.yml +299 -46
  158. data/config/locales/de.yml +301 -50
  159. data/config/locales/el.yml +1 -50
  160. data/config/locales/en.yml +301 -50
  161. data/config/locales/es-MX.yml +298 -47
  162. data/config/locales/es-PY.yml +298 -47
  163. data/config/locales/es.yml +298 -47
  164. data/config/locales/eu.yml +302 -51
  165. data/config/locales/fi-plain.yml +298 -47
  166. data/config/locales/fi.yml +298 -47
  167. data/config/locales/fr-CA.yml +184 -47
  168. data/config/locales/fr.yml +184 -47
  169. data/config/locales/ga-IE.yml +0 -23
  170. data/config/locales/gl.yml +1 -46
  171. data/config/locales/hu.yml +1 -51
  172. data/config/locales/id-ID.yml +0 -24
  173. data/config/locales/is-IS.yml +0 -30
  174. data/config/locales/it.yml +2 -46
  175. data/config/locales/ja.yml +299 -50
  176. data/config/locales/kaa.yml +0 -7
  177. data/config/locales/ko.yml +0 -50
  178. data/config/locales/lb.yml +1 -46
  179. data/config/locales/lt.yml +1 -50
  180. data/config/locales/lv.yml +1 -28
  181. data/config/locales/nl.yml +1 -46
  182. data/config/locales/no.yml +1 -46
  183. data/config/locales/pl.yml +3 -51
  184. data/config/locales/pt-BR.yml +38 -50
  185. data/config/locales/pt.yml +29 -49
  186. data/config/locales/ro-RO.yml +38 -52
  187. data/config/locales/ru.yml +1 -24
  188. data/config/locales/sk.yml +1 -28
  189. data/config/locales/sl.yml +0 -5
  190. data/config/locales/sq-AL.yml +0 -22
  191. data/config/locales/sr-CS.yml +1 -27
  192. data/config/locales/sv.yml +296 -46
  193. data/config/locales/th-TH.yml +0 -10
  194. data/config/locales/tr-TR.yml +1 -44
  195. data/config/locales/uk.yml +0 -23
  196. data/config/locales/zh-CN.yml +0 -38
  197. data/config/locales/zh-TW.yml +1 -50
  198. data/config/routes.rb +13 -12
  199. data/decidim-admin.gemspec +1 -1
  200. data/lib/decidim/admin/engine.rb +2 -1
  201. data/lib/decidim/admin/import/creator.rb +2 -6
  202. data/lib/decidim/admin/import/readers/json.rb +1 -1
  203. data/lib/decidim/admin/menu.rb +9 -1
  204. data/lib/decidim/admin/search_form_builder.rb +1 -1
  205. data/lib/decidim/admin/test/destroy_admin_examples.rb +2 -2
  206. data/lib/decidim/admin/test/filterable_examples.rb +100 -9
  207. data/lib/decidim/admin/test/forms/attachment_collection_form_examples.rb +1 -1
  208. data/lib/decidim/admin/test/forms/attachment_form_examples.rb +1 -1
  209. data/lib/decidim/admin/test/invite_participatory_space_admins_shared_examples.rb +2 -4
  210. data/lib/decidim/admin/test/manage_component_permissions_examples.rb +5 -5
  211. data/lib/decidim/admin/test/manage_hide_content_examples.rb +0 -1
  212. data/lib/decidim/admin/test/manage_moderations_examples.rb +3 -3
  213. data/lib/decidim/admin/test/manage_resource_soft_deletion_examples.rb +113 -0
  214. data/lib/decidim/admin/test/manage_taxonomy_filters_examples.rb +127 -0
  215. data/lib/decidim/admin/test/taxonomy_filters_examples.rb +32 -0
  216. data/lib/decidim/admin/test.rb +3 -1
  217. data/lib/decidim/admin/version.rb +1 -1
  218. metadata +103 -29
  219. data/app/commands/decidim/admin/create_category.rb +0 -15
  220. data/app/commands/decidim/admin/destroy_category.rb +0 -15
  221. data/app/commands/decidim/admin/destroy_component.rb +0 -19
  222. data/app/commands/decidim/admin/update_category.rb +0 -11
  223. data/app/controllers/decidim/admin/categories_controller.rb +0 -98
  224. data/app/forms/decidim/admin/category_form.rb +0 -32
  225. data/app/helpers/decidim/admin/resource_scope_helper.rb +0 -52
  226. data/app/packs/src/decidim/admin/scope_picker_enabler.component.js +0 -12
  227. data/app/views/decidim/admin/categories/_form.html.erb +0 -18
  228. data/app/views/decidim/admin/categories/edit.html.erb +0 -19
  229. data/app/views/decidim/admin/categories/index.html.erb +0 -65
  230. data/app/views/decidim/admin/categories/new.html.erb +0 -19
  231. data/app/views/decidim/admin/share_tokens/_share_tokens.html.erb +0 -45
  232. data/lib/decidim/admin/test/commands/create_category_examples.rb +0 -74
  233. data/lib/decidim/admin/test/commands/destroy_category_examples.rb +0 -83
  234. data/lib/decidim/admin/test/commands/update_category_examples.rb +0 -76
  235. data/lib/decidim/admin/test/forms/category_form_examples.rb +0 -70
  236. data/lib/decidim/admin/test/manage_categories_examples.rb +0 -128
@@ -1,91 +1,173 @@
1
- $(() => {
2
- const $form = $(".form.newsletter_deliver");
3
-
4
- if ($form.length > 0) {
5
- const $sendNewsletterToAllUsers = $form.find("#send_newsletter_to_all_users");
6
- const $sendNewsletterToFollowers = $form.find("#send_newsletter_to_followers");
7
- const $sendNewsletterToParticipants = $form.find("#send_newsletter_to_participants");
8
- const $participatorySpacesForSelect = $form.find("#participatory_spaces_for_select");
9
-
10
- const checkSelectiveNewsletterFollowers = $sendNewsletterToFollowers.find("input[type='checkbox']").prop("checked");
11
- const checkSelectiveNewsletterParticipants = $sendNewsletterToParticipants.find("input[type='checkbox']").prop("checked");
12
-
13
- $sendNewsletterToAllUsers.on("change", (event) => {
14
- const checked = event.target.checked;
15
- if (checked) {
16
- $sendNewsletterToFollowers.find("input[type='checkbox']").prop("checked", !checked);
17
- $sendNewsletterToParticipants.find("input[type='checkbox']").prop("checked", !checked);
18
- $participatorySpacesForSelect.hide();
1
+ import TomSelect from "tom-select/dist/cjs/tom-select.popular";
2
+
3
+ document.addEventListener("DOMContentLoaded", () => {
4
+ const isOnSelectRecipientsPage = window.location.pathname.includes("/select_recipients_to_deliver");
5
+
6
+ const selectors = {
7
+ form: document.querySelector(".form.newsletter_deliver"),
8
+ sendToAllUsers: document.querySelector("#newsletter_send_to_all_users"),
9
+ sendToVerifiedUsers: document.querySelector("#newsletter_send_to_verified_users"),
10
+ sendToParticipants: document.querySelector("#newsletter_send_to_participants"),
11
+ sendToFollowers: document.querySelector("#newsletter_send_to_followers"),
12
+ sendToPrivateMembers: document.querySelector("#newsletter_send_to_private_members"),
13
+ verificationTypesSelect: document.querySelector("#verification_types_for_select"),
14
+ participatorySpacesForSelect: document.querySelector("#participatory_spaces_for_select"),
15
+ deliverButton: document.querySelector("#deliver-button"),
16
+ confirmRecipientsLink: document.querySelector("#confirm-recipients-link"),
17
+ recipientsCount: document.querySelector("#recipients_count"),
18
+ recipientsCountSpinner: document.querySelector("#recipients_count_spinner"),
19
+ csrfToken: document.querySelector('meta[name="csrf-token"]')
20
+ };
21
+
22
+ const inputs = {
23
+ radioButtons: [selectors.sendToAllUsers, selectors.sendToVerifiedUsers].filter(Boolean),
24
+ checkboxes: [
25
+ selectors.sendToParticipants,
26
+ selectors.sendToFollowers,
27
+ selectors.sendToPrivateMembers
28
+ ].filter(Boolean)
29
+ };
30
+
31
+ const toggleVisibility = (element, condition) => element?.classList.toggle("hidden", !condition);
32
+
33
+ const updateDeliverButtonVisibility = () => {
34
+ const sendToAllUsersChecked = selectors.form?.elements["newsletter[send_to_all_users]"]?.value === "1";
35
+
36
+ toggleVisibility(selectors.deliverButton, sendToAllUsersChecked);
37
+ toggleVisibility(selectors.confirmRecipientsLink, !sendToAllUsersChecked);
38
+ };
39
+
40
+ const updateHiddenField = (input) => {
41
+ const hiddenInput = selectors.form?.elements[input.name];
42
+ if (hiddenInput) {
43
+ hiddenInput.value = input.checked
44
+ ? "1"
45
+ : "0";}
46
+ };
47
+
48
+ const ensureAtLeastOneOptionSelected = () => {
49
+ if (![...inputs.radioButtons, ...inputs.checkboxes].some((input) => input?.checked)) {
50
+ selectors.sendToAllUsers.checked = true;
51
+ updateHiddenField(selectors.sendToAllUsers);
52
+ }
53
+ };
54
+
55
+ const updateConfirmRecipientsLink = () => {
56
+ if (!selectors.confirmRecipientsLink) {
57
+ return;
58
+ }
59
+ const params = new URLSearchParams(new FormData(selectors.form));
60
+ selectors.confirmRecipientsLink.setAttribute(
61
+ "href",
62
+ `${selectors.confirmRecipientsLink.dataset.baseUrl}?${params.toString()}`
63
+ );
64
+ };
65
+
66
+ const updateRecipientsCount = async () => {
67
+ const url = selectors.form?.dataset?.recipientsCountNewsletterPath;
68
+ if (!url) {
69
+ return;
70
+ }
71
+
72
+ selectors.recipientsCountSpinner?.classList.remove("hide");
73
+ try {
74
+ const response = await fetch(url, {
75
+ method: "POST",
76
+ headers: { "X-CSRF-Token": selectors.csrfToken?.content },
77
+ body: new FormData(selectors.form)
78
+ });
79
+ selectors.recipientsCount.textContent = await response.text();
80
+ } catch (error) {
81
+ console.error("Error fetching recipients count:", error);
82
+ } finally {
83
+ selectors.recipientsCountSpinner?.classList.add("hide");
84
+ }
85
+ };
86
+
87
+ const resetIdsForParticipatorySpaces = () => {
88
+ document.querySelectorAll('.form.newsletter_deliver select[name$="[ids][]"]').forEach((select) => {
89
+ if (select.tomselect) {
90
+ select.tomselect.clear();
19
91
  } else {
20
- $sendNewsletterToFollowers.find("input[type='checkbox']").prop("checked", !checked);
21
- $sendNewsletterToParticipants.find("input[type='checkbox']").prop("checked", !checked);
22
- $participatorySpacesForSelect.show();
23
- }
24
- })
25
-
26
- $sendNewsletterToFollowers.on("change", (event) => {
27
- const checked = event.target.checked;
28
- const selectiveNewsletterParticipants = $sendNewsletterToParticipants.find("input[type='checkbox']").prop("checked");
29
-
30
- if (checked) {
31
- $sendNewsletterToAllUsers.find("input[type='checkbox']").prop("checked", !checked);
32
- $participatorySpacesForSelect.show();
33
- } else if (!selectiveNewsletterParticipants) {
34
- $sendNewsletterToAllUsers.find("input[type='checkbox']").prop("checked", true);
35
- $participatorySpacesForSelect.hide();
92
+ select.value = [];
36
93
  }
37
- })
38
-
39
- $sendNewsletterToParticipants.on("change", (event) => {
40
- const checked = event.target.checked;
41
- const selectiveNewsletterFollowers = $sendNewsletterToFollowers.find("input[type='checkbox']").prop("checked");
42
- if (checked) {
43
- $sendNewsletterToAllUsers.find("input[type='checkbox']").prop("checked", !checked);
44
- $participatorySpacesForSelect.show();
45
- } else if (!selectiveNewsletterFollowers) {
46
- $sendNewsletterToAllUsers.find("input[type='checkbox']").prop("checked", true);
47
- $participatorySpacesForSelect.hide();
48
- }
49
- })
94
+ });
95
+ };
50
96
 
51
- if (checkSelectiveNewsletterFollowers || checkSelectiveNewsletterParticipants) {
52
- $participatorySpacesForSelect.show();
53
- } else {
54
- $participatorySpacesForSelect.hide();
97
+ const resetVerificationTypes = () => {
98
+ const select = document.querySelector("#verification-types-select");
99
+ select?.tomselect?.clear();
100
+ const hiddenInput = selectors.form?.elements["newsletter[verification_types]"];
101
+ if (hiddenInput) {
102
+ hiddenInput.value = "";
55
103
  }
104
+ };
56
105
 
57
- $(".form .spaces-block-tag").each(function (_i, blockTag) {
58
- const selectTag = $(blockTag).find(".chosen-select")
59
- selectTag.change(function () {
60
- let optionSelected = selectTag.find("option:selected").val()
61
- if (optionSelected === "all") {
62
- selectTag.find("option").not(":first").prop("selected", true);
63
- selectTag.find("option[value='all']").prop("selected", false);
64
- } else if (optionSelected === "") {
65
- selectTag.find("option").not(":first").prop("selected", false);
66
- }
106
+ const updateFormState = () => {
107
+ [...inputs.radioButtons, ...inputs.checkboxes].forEach(updateHiddenField);
108
+ const isAllUsersChecked = selectors.sendToAllUsers?.checked;
109
+ const isAnyChecked = [...inputs.radioButtons, ...inputs.checkboxes].some((input) => input?.checked);
110
+
111
+ toggleVisibility(selectors.deliverButton, isAllUsersChecked);
112
+ toggleVisibility(selectors.confirmRecipientsLink, !isAllUsersChecked && isAnyChecked);
113
+ toggleVisibility(
114
+ selectors.participatorySpacesForSelect,
115
+ inputs.checkboxes.some((input) => input.checked) && !selectors.sendToVerifiedUsers?.checked
116
+ );
117
+ toggleVisibility(selectors.verificationTypesSelect, selectors.sendToVerifiedUsers?.checked);
118
+ ensureAtLeastOneOptionSelected();
119
+ updateConfirmRecipientsLink();
120
+ updateRecipientsCount();
121
+ };
122
+
123
+ const handleRadioChange = (radio) => {
124
+ inputs.radioButtons.forEach((rb) => (rb.checked = rb === radio));
125
+ inputs.checkboxes.forEach((checkbox) => (checkbox.checked = false));
126
+ resetVerificationTypes();
127
+ resetIdsForParticipatorySpaces();
128
+ updateFormState();
129
+ };
130
+
131
+ const handleCheckboxChange = () => {
132
+ inputs.radioButtons.forEach((radio) => (radio.checked = false));
133
+ resetVerificationTypes();
134
+ resetIdsForParticipatorySpaces();
135
+ updateFormState();
136
+ };
137
+
138
+ const attachEventListeners = () => {
139
+ inputs.radioButtons.forEach((radio) =>
140
+ radio.addEventListener("change", () => handleRadioChange(radio))
141
+ );
142
+
143
+ inputs.checkboxes.forEach((checkbox) =>
144
+ checkbox.addEventListener("change", handleCheckboxChange)
145
+ );
146
+
147
+ selectors.form?.addEventListener("change", updateFormState);
148
+ };
149
+
150
+ const initializeTomSelect = () => {
151
+ document.querySelectorAll("[data-multiselect='true']").forEach((select) => {
152
+ const tomSelect = new TomSelect(select, {
153
+ plugins: ["remove_button", "dropdown_input"],
154
+ allowEmptyOption: true
67
155
  });
68
- })
69
-
70
- $form.on("change", function(event) {
71
- let formData = new FormData(event.target.closest("form"));
72
- let url = $form.data("recipients-count-newsletter-path");
73
- const $modal = $("#recipients_count_spinner");
74
- $modal.removeClass("hide");
75
-
76
- const xhr = new XMLHttpRequest();
77
- xhr.open("POST", url, true);
78
- xhr.onload = function() {
79
- if (xhr.status === 200) {
80
- $("#recipients_count").text(xhr.responseText);
156
+
157
+ tomSelect.on("change", () => {
158
+ const selectedOptions = tomSelect.getValue();
159
+
160
+ if (selectedOptions.includes("all") && selectedOptions.length > 1) {
161
+ tomSelect.setValue(["all"]);
81
162
  }
82
- $modal.addClass("hide");
83
- };
84
- xhr.onerror = function() {
85
- $modal.addClass("hide");
86
- };
87
- // Send the form data
88
- xhr.send(formData);
89
- })
163
+ });
164
+ });
165
+ };
166
+
167
+ if (isOnSelectRecipientsPage) {
168
+ attachEventListeners();
169
+ initializeTomSelect();
170
+ updateFormState();
171
+ updateDeliverButtonVisibility();
90
172
  }
91
173
  });
@@ -1,10 +1,7 @@
1
1
  $(() => {
2
- const $limitedTimeLabel = $("label[for='component_settings_proposal_edit_time_limited']")
3
- const $limitedTimeRadioButton = $("#component_settings_proposal_edit_time_limited")
4
- const $infiniteTimeRadioButton = $("#component_settings_proposal_edit_time_infinite")
5
- const $editTimeContainer = $(".proposal_edit_before_minutes_container")
6
-
7
- $editTimeContainer.detach().appendTo($limitedTimeLabel)
2
+ const $limitedTimeRadioButton = $("#component_settings_proposal_edit_time_limited");
3
+ const $infiniteTimeRadioButton = $("#component_settings_proposal_edit_time_infinite");
4
+ const $editTimeContainer = $(".edit_time_container");
8
5
 
9
6
  if ($infiniteTimeRadioButton.is(":checked")) {
10
7
  $editTimeContainer.hide();
@@ -1,19 +1,31 @@
1
- import createSortList from "src/decidim/admin/sort_list.component"
1
+ import sortable from "html5sortable/dist/html5sortable.es";
2
2
 
3
- // Once in DOM
4
- $(() => {
5
- const selector = ".js-sortable"
6
- const $sortable = $(selector)
3
+ /*
4
+ Initializes any element with the class js-sortable as a sortable list
5
+ User html5Sortable, with options available as data-draggable-options (see https://github.com/lukasoppermann/html5sortable)
7
6
 
8
- $sortable.each((index, elem) => {
9
- const item = (elem.id)
10
- ? `#${elem.id}`
11
- : selector
7
+ Event are dispatched on the element with the class js-sortable, so you can simply do:
12
8
 
13
- createSortList(item, {
14
- handle: "li",
15
- forcePlaceholderSize: true,
16
- placeholderClass: "sort-placeholder"
17
- })
18
- })
19
- })
9
+ document.querySelector('.js-sortable').addEventListener('sortupdate', (event) => {
10
+ console.log('The new order is:', event.target.children);
11
+ });
12
+ */
13
+ window.addEventListener("DOMContentLoaded", () => {
14
+ const draggables = document.querySelectorAll(".js-sortable");
15
+
16
+ if (draggables) {
17
+ draggables.forEach((draggable) => {
18
+ let options = {
19
+ "forcePlaceholderSize": true
20
+ };
21
+ ["items", "acceptFrom", "handle", "placeholderClass", "placeholder", "hoverClass"].forEach((option) => {
22
+ let dataOption = `draggable${option.charAt(0).toUpperCase() + option.slice(1)}`;
23
+ if (draggable.dataset[dataOption]) {
24
+ options[option] = draggable.dataset[dataOption];
25
+ }
26
+ });
27
+ // console.log("initialize sortable with options", options);
28
+ sortable(draggable, options);
29
+ });
30
+ }
31
+ });
@@ -0,0 +1,93 @@
1
+ /* eslint-disable no-use-before-define */
2
+ document.addEventListener("decidim:loaded", () => {
3
+ document.querySelectorAll(".js-taxonomy-filters-container").forEach((settingsContainer) => {
4
+ const drawer = window.Decidim.currentDialogs[settingsContainer.dataset.drawer];
5
+ const container = drawer.dialog.querySelector(".js-taxonomy-filters-drawer-container");
6
+ const addButton = settingsContainer.querySelector(".js-add-taxonomy-filter");
7
+
8
+ // Handles the click on edit button for each taxonomy filter in the component settings table
9
+ const activateSettingsActions = () => {
10
+ const edits = settingsContainer.querySelectorAll(".js-edit-taxonomy-filter");
11
+ edits.forEach((edit) => {
12
+ edit.addEventListener("click", (event) => {
13
+ event.preventDefault();
14
+ drawer.open();
15
+ fetchUrl(edit.href);
16
+ });
17
+ });
18
+ };
19
+
20
+ // Handles the change on the taxonomy and filter selects in the drawer
21
+ const activateDrawerActions = () => {
22
+ const taxonomySelector = container.querySelector(".js-drawer-taxonomy-select select");
23
+ const filterSelector = container.querySelector(".js-drawer-filter-select select");
24
+ const selectForm = drawer.dialog.querySelector("#select-taxonomy-filter-form");
25
+ const saveForm = drawer.dialog.querySelector("#save-taxonomy-filter-form");
26
+ const save = drawer.dialog.querySelector("#save-taxonomy-filter");
27
+ const remove = drawer.dialog.querySelector("#remove-taxonomy-filter");
28
+ const currentFilters = settingsContainer.querySelector(".js-current-filters");
29
+
30
+ if (selectForm) {
31
+ selectForm.addEventListener("ajax:success", (event) => {
32
+ container.innerHTML = event.detail[2].responseText;
33
+ activateDrawerActions();
34
+ });
35
+ }
36
+
37
+ if (remove) {
38
+ remove.addEventListener("ajax:success", (event) => {
39
+ currentFilters.innerHTML = event.detail[2].responseText;
40
+ activateSettingsActions();
41
+ drawer.close();
42
+ });
43
+ }
44
+
45
+ if (taxonomySelector) {
46
+ taxonomySelector.addEventListener("change", () => {
47
+ Rails.fire(selectForm, "submit");
48
+ });
49
+ }
50
+
51
+ if (filterSelector) {
52
+ filterSelector.addEventListener("change", () => {
53
+ Rails.fire(selectForm, "submit");
54
+ });
55
+ }
56
+
57
+ if (saveForm) {
58
+ saveForm.addEventListener("ajax:success", (event) => {
59
+ currentFilters.innerHTML = event.detail[2].responseText;
60
+ activateSettingsActions();
61
+ drawer.close();
62
+ });
63
+
64
+ if (save) {
65
+ save.addEventListener("click", (event) => {
66
+ event.preventDefault();
67
+ Rails.fire(saveForm, "submit");
68
+ });
69
+ }
70
+ }
71
+ };
72
+
73
+ const fetchUrl = (url) => {
74
+ container.classList.add("spinner-container");
75
+ fetch(url).then((response) => response.text()).then((html) => {
76
+ container.innerHTML = html;
77
+ container.classList.remove("spinner-container");
78
+ activateDrawerActions();
79
+ });
80
+ };
81
+
82
+ // Activate the rendered edit buttons
83
+ activateSettingsActions();
84
+
85
+ // Opens the drawer with the form to add a new taxonomy filter
86
+ addButton.addEventListener("click", (event) => {
87
+ event.preventDefault();
88
+ const url = addButton.dataset.url;
89
+ fetchUrl(url);
90
+ drawer.open();
91
+ });
92
+ });
93
+ });
@@ -62,13 +62,74 @@
62
62
  }
63
63
 
64
64
  &_notes {
65
- &-grid {
66
- @apply grid grid-cols-2 gap-4 my-4;
65
+ .comment,
66
+ .comment-reply {
67
+ @apply mt-4 p-4 rounded w-full border border-gray-3 space-y-2;
67
68
 
68
- .comment {
69
- @apply p-4 rounded;
69
+ background-color: rgba(255, 252, 238, 1);
70
+ }
71
+
72
+ .comment-reply {
73
+ @apply bg-white;
74
+ }
75
+
76
+ .comment__content {
77
+ @apply space-y-4;
78
+
79
+ a {
80
+ @apply text-secondary;
81
+ }
82
+ }
83
+
84
+ .comment-actions {
85
+ @apply flex items-center gap-4;
86
+
87
+ .button[aria-expanded="false"] {
88
+ svg:first-of-type {
89
+ @apply block;
90
+ }
91
+
92
+ svg:last-of-type {
93
+ @apply hidden;
94
+ }
95
+
96
+ span:first-of-type {
97
+ @apply block;
98
+ }
99
+
100
+ span:last-of-type {
101
+ @apply hidden;
102
+ }
103
+ }
104
+
105
+ .button[aria-expanded="true"] {
106
+ svg:first-of-type {
107
+ @apply hidden;
108
+ }
109
+
110
+ svg:last-of-type {
111
+ @apply block;
112
+ }
113
+
114
+ span:first-of-type {
115
+ @apply hidden;
116
+ }
117
+
118
+ span:last-of-type {
119
+ @apply block;
120
+ }
121
+ }
122
+ }
123
+
124
+ .form__wrapper {
125
+ @apply pb-4;
126
+
127
+ label {
128
+ @apply text-gray-2 text-sm;
129
+ }
70
130
 
71
- background-color: rgba(255, 252, 238, 1);
131
+ textarea {
132
+ @apply mt-2;
72
133
  }
73
134
  }
74
135
  }
@@ -388,6 +388,19 @@ li.opens-left > .is-dropdown-submenu {
388
388
  color: var(--secondary);
389
389
  }
390
390
 
391
+ .dropdown-pane.dropdown-pane--buttons {
392
+ li {
393
+ padding: 0;
394
+ }
395
+
396
+ li button {
397
+ width: 100%;
398
+ height: 100%;
399
+ text-align: left;
400
+ padding: 1rem;
401
+ }
402
+ }
403
+
391
404
  .dropdown-pane li:hover {
392
405
  color: #fff;
393
406
  background-color: var(--secondary);
@@ -0,0 +1,20 @@
1
+ @import "tom-select/dist/scss/tom-select";
2
+
3
+ /* overwrite tom-select defaults */
4
+ .ts {
5
+ &-control {
6
+ @apply border-gray text-md min-h-[40px];
7
+
8
+ input {
9
+ @apply font-normal text-black text-md;
10
+ }
11
+ }
12
+
13
+ &-dropdown {
14
+ @apply text-md text-gray-2 font-normal;
15
+
16
+ .active {
17
+ @apply text-white bg-secondary;
18
+ }
19
+ }
20
+ }
@@ -1,6 +1,10 @@
1
1
  .table-scroll {
2
2
  @apply overflow-x-auto;
3
3
 
4
+ &.half-vh {
5
+ @apply max-h-[50vh];
6
+ }
7
+
4
8
  table {
5
9
  border-collapse: unset;
6
10
 
@@ -108,6 +112,20 @@
108
112
  .icon-active {
109
113
  @apply bg-[#5dc560] inline-block w-3 h-3 align-middle mr-2 rounded-[50%];
110
114
  }
115
+
116
+ .draggable-table {
117
+ &.dragging {
118
+ @apply border-dashed border-y-2 border-gray;
119
+ }
120
+
121
+ .dragging-handle {
122
+ @apply cursor-ns-resize align-top p-3;
123
+
124
+ .dragger {
125
+ @apply text-2xl;
126
+ }
127
+ }
128
+ }
111
129
  }
112
130
 
113
131
  .table-list__actions {
@@ -153,3 +171,7 @@
153
171
  @apply inline-block;
154
172
  }
155
173
  }
174
+
175
+ .table-list__title-ellipsis {
176
+ @apply whitespace-nowrap overflow-hidden text-ellipsis max-w-[200px] sm:max-w-sm md:max-w-md lg:max-w-lg xl:max-w-2xl inline-block align-middle;
177
+ }
@@ -0,0 +1,74 @@
1
+ .spinner-container {
2
+ &::before {
3
+ @apply absolute -mt-2 -ml-4 top-1/2 left-1/2;
4
+ }
5
+ }
6
+
7
+ .draggable-taxonomy {
8
+ &.change-page {
9
+ @apply bg-gray-3 italic;
10
+ }
11
+
12
+ .dragger {
13
+ @apply text-2xl;
14
+ }
15
+
16
+ td {
17
+ @apply align-top cursor-ns-resize;
18
+
19
+ &.js-drag-handle .dragger {
20
+ @apply mt-1;
21
+ }
22
+ }
23
+ }
24
+
25
+ ul.taxonomy {
26
+ @apply flex;
27
+
28
+ li {
29
+ @apply flex-none text-center w-20 mt-2 mb-2;
30
+
31
+ &:first-child {
32
+ @apply flex-initial text-left flex-grow;
33
+ }
34
+
35
+ &:nth-child(2),
36
+ &:last-child {
37
+ @apply w-36;
38
+ }
39
+ }
40
+
41
+ .taxonomy-list__actions {
42
+ span {
43
+ @apply ml-1;
44
+ }
45
+
46
+ svg {
47
+ @apply inline-block fill-secondary w-5 h-5;
48
+ }
49
+
50
+ .action-space {
51
+ @apply w-5 h-5;
52
+ }
53
+ }
54
+ }
55
+
56
+ [data-dialog]#item-form {
57
+ @apply bottom-0 sm:top-[5.5rem] top-[8.55rem];
58
+
59
+ [data-dialog-container] > :last-child {
60
+ grid-column: span 1 / span 1;
61
+ }
62
+ }
63
+
64
+ #item-form-content {
65
+ @apply p-6 rounded-r-none py-0;
66
+
67
+ h1 {
68
+ @apply mt-6 mx-0;
69
+ }
70
+
71
+ .row {
72
+ @apply px-0;
73
+ }
74
+ }
@@ -24,12 +24,14 @@
24
24
  @import "stylesheets/decidim/admin/_logs.scss";
25
25
  @import "stylesheets/decidim/admin/_filters.scss";
26
26
  @import "stylesheets/decidim/admin/_table-list.scss";
27
+ @import "stylesheets/decidim/admin/_taxonomies.scss";
27
28
  @import "stylesheets/decidim/admin/_dropdown.scss";
28
29
  @import "stylesheets/decidim/admin/_item_show.scss";
29
30
  @import "stylesheets/decidim/admin/_item_edit.scss";
30
31
  @import "stylesheets/decidim/admin/_tabs.scss";
31
32
  @import "stylesheets/decidim/admin/_component-show.scss";
32
33
  @import "stylesheets/decidim/admin/_moderations.scss";
34
+ @import "stylesheets/decidim/admin/_select_picker.scss";
33
35
  @import "stylesheets/decidim/admin/_show_email.scss";
34
36
  @import "stylesheets/decidim/admin/_bulk_actions.scss";
35
37
  @import "stylesheets/decidim/admin/_data_picker.scss";
@@ -38,3 +40,4 @@
38
40
  @import "stylesheets/decidim/admin/_datepicker.scss";
39
41
  @import "stylesheets/decidim/admin/_minimap.scss";
40
42
  @import "stylesheets/decidim/admin/_proposal_status.scss";
43
+ @import "stylesheets/decidim/_tribute.scss";