decidim-core 0.31.2 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -13
- data/app/cells/decidim/amendable/amend_button_card/show.erb +2 -2
- data/app/cells/decidim/amendable/amend_button_card_cell.rb +1 -1
- data/app/cells/decidim/author_cell.rb +0 -4
- data/app/cells/decidim/card_metadata_cell.rb +1 -1
- data/app/cells/decidim/comments_button_cell.rb +9 -1
- data/app/cells/decidim/content_blocks/announcement_settings_form/show.erb +5 -0
- data/app/cells/decidim/content_blocks/announcement_settings_form_cell.rb +17 -0
- data/app/cells/decidim/content_blocks/cta_settings_form/show.erb +1 -1
- data/app/cells/decidim/content_blocks/hero_settings_form/show.erb +1 -1
- data/app/cells/decidim/content_blocks/highlighted_content_banner_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/highlighted_content_banner_settings_form/show.erb +1 -1
- data/app/cells/decidim/content_blocks/highlighted_elements_with_cell_for_list_cell.rb +5 -1
- data/app/cells/decidim/content_blocks/highlighted_participatory_spaces_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/how_to_participate/show.erb +1 -1
- data/app/cells/decidim/content_blocks/html_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/participatory_space_announcement_cell.rb +1 -3
- data/app/cells/decidim/content_blocks/participatory_space_hero_cell.rb +1 -5
- data/app/cells/decidim/content_blocks/participatory_space_hero_settings_form/show.erb +1 -1
- data/app/cells/decidim/content_blocks/static_page/section_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/static_page/section_settings_form/show.erb +3 -1
- data/app/cells/decidim/content_blocks/static_page/summary_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/static_page/summary_settings_form/show.erb +3 -1
- data/app/cells/decidim/content_blocks/static_page/two_pane_section_cell.rb +2 -2
- data/app/cells/decidim/content_blocks/static_page/two_pane_section_settings_form/show.erb +4 -2
- data/app/cells/decidim/data_consent/category.erb +25 -38
- data/app/cells/decidim/footer_topics/show.erb +5 -8
- data/app/cells/decidim/{participatory_space_private_user → member}/show.erb +6 -6
- data/app/cells/decidim/{participatory_space_private_user_cell.rb → member_cell.rb} +1 -5
- data/app/cells/decidim/nav_links/show.erb +3 -3
- data/app/cells/decidim/onboarding_action_message_cell.rb +1 -0
- data/app/cells/decidim/profile/details.erb +1 -1
- data/app/cells/decidim/profile_cell.rb +1 -0
- data/app/cells/decidim/profile_member_of/show.erb +13 -0
- data/app/cells/decidim/profile_member_of_cell.rb +35 -0
- data/app/cells/decidim/report_button/already_reported_modal.erb +1 -1
- data/app/cells/decidim/report_button/flag_modal.erb +1 -1
- data/app/cells/decidim/report_user_button/already_reported_modal.erb +1 -1
- data/app/cells/decidim/report_user_button/flag_modal.erb +1 -1
- data/app/cells/decidim/resource_types_filter/show.erb +2 -2
- data/app/cells/decidim/share_text_widget/modal.erb +1 -1
- data/app/cells/decidim/share_widget/qr_code_modal.erb +1 -1
- data/app/cells/decidim/tags_cell.rb +1 -1
- data/app/cells/decidim/upload_modal/files.erb +5 -1
- data/app/cells/decidim/upload_modal_cell.rb +15 -1
- data/app/cells/decidim/versions_list/show.erb +25 -0
- data/app/commands/decidim/create_follow.rb +3 -5
- data/app/commands/decidim/create_user_report.rb +1 -1
- data/app/commands/decidim/destroy_account.rb +15 -4
- data/app/commands/decidim/multiple_attachments_methods.rb +42 -24
- data/app/commands/decidim/search.rb +5 -5
- data/app/controllers/concerns/decidim/ajax_permission_handler.rb +1 -1
- data/app/controllers/concerns/decidim/devise_controllers.rb +9 -0
- data/app/controllers/concerns/decidim/direct_upload.rb +3 -2
- data/app/controllers/concerns/decidim/ephemeral_session_checker.rb +1 -1
- data/app/controllers/concerns/decidim/force_authentication.rb +10 -1
- data/app/controllers/concerns/decidim/impersonate_users.rb +4 -0
- data/app/controllers/concerns/decidim/locale_switcher.rb +52 -2
- data/app/controllers/concerns/decidim/needs_tos_accepted.rb +1 -1
- data/app/controllers/concerns/decidim/participatory_space/has_members_page.rb +27 -0
- data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -5
- data/app/controllers/decidim/account_controller.rb +1 -1
- data/app/controllers/decidim/amendments_controller.rb +5 -4
- data/app/controllers/decidim/components/base_controller.rb +20 -3
- data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +1 -1
- data/app/controllers/decidim/devise/passwords_controller.rb +1 -1
- data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
- data/app/controllers/decidim/devise/sessions_controller.rb +1 -1
- data/app/controllers/decidim/download_your_data_controller.rb +2 -2
- data/app/controllers/decidim/editor_images_controller.rb +1 -1
- data/app/controllers/decidim/follows_controller.rb +4 -3
- data/app/controllers/decidim/geolocation_controller.rb +1 -1
- data/app/controllers/decidim/likes_controller.rb +2 -1
- data/app/controllers/decidim/locales_controller.rb +3 -11
- data/app/controllers/decidim/messaging/conversations_controller.rb +3 -3
- data/app/controllers/decidim/newsletters_controller.rb +1 -1
- data/app/controllers/decidim/notifications_settings_controller.rb +1 -1
- data/app/controllers/decidim/notifications_subscriptions_controller.rb +8 -0
- data/app/controllers/decidim/open_data_controller.rb +1 -1
- data/app/controllers/decidim/private_downloads_controller.rb +29 -0
- data/app/controllers/decidim/report_users_controller.rb +2 -2
- data/app/controllers/decidim/reports_controller.rb +1 -1
- data/app/controllers/decidim/user_activities_controller.rb +1 -2
- data/app/events/decidim/amendable/amendment_base_event.rb +7 -1
- data/app/events/decidim/welcome_notification_event.rb +1 -1
- data/app/forms/decidim/upload_validation_form.rb +1 -1
- data/app/helpers/concerns/decidim/flash_helper_extensions.rb +1 -0
- data/app/helpers/decidim/active_link_to_helper.rb +136 -0
- data/app/helpers/decidim/amendments_helper.rb +3 -3
- data/app/helpers/decidim/check_boxes_tree_helper.rb +2 -2
- data/app/helpers/decidim/component_path_helper.rb +9 -4
- data/app/helpers/decidim/filters_helper.rb +0 -2
- data/app/helpers/decidim/mailer_helper.rb +36 -0
- data/app/helpers/decidim/menu_helper.rb +4 -5
- data/app/helpers/decidim/meta_tags_helper.rb +0 -2
- data/app/helpers/decidim/newsletters_helper.rb +4 -22
- data/app/helpers/decidim/paginate_helper.rb +14 -1
- data/app/helpers/decidim/sanitize_helper.rb +1 -0
- data/app/helpers/decidim/short_link_helper.rb +5 -5
- data/app/helpers/decidim/translations_helper.rb +4 -4
- data/app/jobs/decidim/delete_inactive_participants_job.rb +2 -2
- data/app/jobs/decidim/find_and_update_descendants_job.rb +8 -2
- data/app/jobs/decidim/process_inactive_participant_job.rb +0 -7
- data/app/jobs/decidim/update_search_indexes_job.rb +2 -2
- data/app/mailers/decidim/application_mailer.rb +11 -2
- data/app/mailers/decidim/decidim_devise_mailer.rb +1 -0
- data/app/mailers/decidim/delete_user_mailer.rb +14 -0
- data/app/mailers/decidim/participants_account_mailer.rb +0 -16
- data/app/mailers/decidim/reported_mailer.rb +4 -1
- data/app/models/decidim/action_log.rb +1 -1
- data/app/models/decidim/attachment.rb +20 -2
- data/app/models/decidim/authorization.rb +7 -0
- data/app/models/decidim/authorization_transfer.rb +1 -1
- data/app/models/decidim/component.rb +6 -9
- data/app/models/decidim/content_block.rb +3 -3
- data/app/models/decidim/moderation.rb +1 -1
- data/app/models/decidim/newsletter.rb +2 -2
- data/app/models/decidim/participatory_space/member.rb +55 -0
- data/app/models/decidim/private_download.rb +61 -0
- data/app/models/decidim/private_export.rb +6 -0
- data/app/models/decidim/resource_link.rb +1 -1
- data/app/models/decidim/short_link.rb +1 -1
- data/app/models/decidim/user.rb +2 -2
- data/app/models/decidim/user_base_entity.rb +17 -2
- data/app/models/decidim/user_moderation.rb +1 -1
- data/app/packs/src/decidim/a11y.js +29 -0
- data/app/packs/src/decidim/a11y.test.js +81 -0
- data/app/packs/src/decidim/confirm.js +8 -1
- data/app/packs/src/decidim/confirm.test.js +225 -0
- data/app/packs/src/decidim/controllers/accordion/accordion.test.js +272 -0
- data/app/packs/src/decidim/controllers/accordion/controller.js +117 -17
- data/app/packs/src/decidim/controllers/assign_role/assign_role.test.js +80 -0
- data/app/packs/src/decidim/controllers/assign_role/controller.js +27 -0
- data/app/packs/src/decidim/controllers/breadcrumb_truncate/breadcrumb_truncate.test.js +230 -0
- data/app/packs/src/decidim/controllers/breadcrumb_truncate/controller.js +172 -0
- data/app/packs/src/decidim/controllers/dropdown/controller.js +32 -0
- data/app/packs/src/decidim/controllers/dropdown/dropdown.test.js +215 -0
- data/app/packs/src/decidim/controllers/form_validator/form_validator.js +9 -8
- data/app/packs/src/decidim/controllers/form_validator/form_validator.test.js +28 -1
- data/app/packs/src/decidim/controllers/language_change/controller.js +1 -0
- data/app/packs/src/decidim/controllers/language_change/language_change.test.js +13 -0
- data/app/packs/src/decidim/controllers/main_menu/controller.js +152 -0
- data/app/packs/src/decidim/controllers/main_menu/main_menu.test.js +285 -0
- data/app/packs/src/decidim/controllers/mention/controller.js +296 -140
- data/app/packs/src/decidim/controllers/mention/input_mentions.test.js +120 -457
- data/app/packs/src/decidim/controllers/multiple_mentions/controller.js +68 -32
- data/app/packs/src/decidim/controllers/multiple_mentions/input_multiple_mentions.test.js +30 -23
- data/app/packs/src/decidim/controllers/password_toggler/controller.js +22 -1
- data/app/packs/src/decidim/controllers/password_toggler/password_toggler.test.js +11 -20
- data/app/packs/src/decidim/datepicker/datepicker_functions.js +26 -0
- data/app/packs/src/decidim/datepicker/generate_datepicker.js +3 -14
- data/app/packs/src/decidim/datepicker/generate_timepicker.js +3 -2
- data/app/packs/src/decidim/datepicker/test/datepicker_functions_adjust_picker_position.test.js +234 -0
- data/app/packs/src/decidim/direct_uploads/upload_field.js +4 -4
- data/app/packs/src/decidim/direct_uploads/upload_modal.js +12 -7
- data/app/packs/src/decidim/editor/common/suggestion.js +4 -2
- data/app/packs/src/decidim/editor/extensions/decidim_kit/index.js +4 -1
- data/app/packs/src/decidim/editor/extensions/image/index.js +57 -16
- data/app/packs/src/decidim/editor/extensions/image/node_view.js +9 -1
- data/app/packs/src/decidim/editor/extensions/indent/index.js +9 -0
- data/app/packs/src/decidim/editor/extensions/link/bubble_menu.js +34 -6
- data/app/packs/src/decidim/editor/extensions/link/index.js +53 -12
- data/app/packs/src/decidim/editor/extensions/mention/index.js +18 -5
- data/app/packs/src/decidim/editor/extensions/mention_resource/index.js +16 -7
- data/app/packs/src/decidim/editor/test/extensions/decidim_kit.test.js +13 -4
- data/app/packs/src/decidim/editor/test/extensions/heading.test.js +1 -1
- data/app/packs/src/decidim/editor/test/extensions/image.test.js +26 -28
- data/app/packs/src/decidim/editor/test/extensions/image_links.test.js +161 -0
- data/app/packs/src/decidim/editor/test/extensions/mention.test.js +6 -2
- data/app/packs/src/decidim/editor/test/extensions/video_embed.test.js +27 -15
- data/app/packs/src/decidim/editor/test/helpers.js +8 -10
- data/app/packs/src/decidim/editor/test/toolbar/full.test.js +15 -4
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_block.js +8 -4
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_formatting.js +5 -1
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_indent.js +9 -5
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_link.js +5 -1
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_list.js +8 -4
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_styling.js +13 -9
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_content_styling.js +6 -2
- data/app/packs/src/decidim/geocoding/reverse_geocoding.js +15 -5
- data/app/packs/src/decidim/geocoding/reverse_geocoding.test.js +197 -0
- data/app/packs/src/decidim/index.js +4 -4
- data/app/packs/src/decidim/map/controller.js +10 -1
- data/app/packs/src/decidim/refactor/moved/focus_guard.js +16 -16
- data/app/packs/src/decidim/refactor/moved/focus_guard.test.js +136 -0
- data/app/packs/src/decidim/sw/push-permissions.js +48 -13
- data/app/packs/src/decidim/sw/sw.js +1 -1
- data/app/packs/src/decidim/utilities/text.js +6 -6
- data/app/packs/stylesheets/decidim/_cards.scss +15 -6
- data/app/packs/stylesheets/decidim/_conversations.scss +14 -0
- data/app/packs/stylesheets/decidim/_cookies.scss +13 -5
- data/app/packs/stylesheets/decidim/_datepicker.scss +0 -8
- data/app/packs/stylesheets/decidim/_documents.scss +1 -1
- data/app/packs/stylesheets/decidim/_dropdown.scss +22 -32
- data/app/packs/stylesheets/decidim/_editor_suggestions.scss +49 -0
- data/app/packs/stylesheets/decidim/_flash.scss +1 -1
- data/app/packs/stylesheets/decidim/_floating_help.scss +1 -1
- data/app/packs/stylesheets/decidim/_footer.scss +27 -31
- data/app/packs/stylesheets/decidim/_forms.scss +5 -1
- data/app/packs/stylesheets/decidim/_header.scss +183 -48
- data/app/packs/stylesheets/decidim/_language_chooser.scss +79 -0
- data/app/packs/stylesheets/decidim/_participatory_spaces.scss +1 -1
- data/app/packs/stylesheets/decidim/_rich_text.scss +17 -0
- data/app/packs/stylesheets/decidim/_tom_select.scss +23 -0
- data/app/packs/stylesheets/decidim/application.scss +3 -0
- data/app/packs/stylesheets/decidim/editor.scss +12 -33
- data/app/packs/stylesheets/decidim/geocoding_addons.scss +10 -2
- data/app/presenters/decidim/admin_log/participatory_space/member_presenter.rb +40 -0
- data/app/presenters/decidim/admin_log/static_page_resource_presenter.rb +1 -1
- data/app/presenters/decidim/authorization_transfer_presenter.rb +1 -1
- data/app/presenters/decidim/breadcrumb_root_menu_item_presenter.rb +3 -3
- data/app/presenters/decidim/footer_menu_presenter.rb +2 -4
- data/app/presenters/decidim/log/user_presenter.rb +1 -0
- data/app/presenters/decidim/log/value_types/access_mode_presenter.rb +45 -0
- data/app/presenters/decidim/menu_item_presenter.rb +15 -3
- data/app/presenters/decidim/participatory_space/member_presenter.rb +48 -0
- data/app/presenters/decidim/resource_locator_presenter.rb +22 -3
- data/app/presenters/decidim/stats_presenter.rb +1 -1
- data/app/queries/decidim/last_activity.rb +1 -1
- data/app/resolvers/decidim/meta_image_url_resolver.rb +7 -0
- data/app/serializers/decidim/exporters/participatory_space_serializer.rb +15 -1
- data/app/services/decidim/email_notification_generator.rb +2 -0
- data/app/services/decidim/notification_generator.rb +4 -0
- data/app/services/decidim/notifications_subscriptions_persistor.rb +6 -0
- data/app/services/decidim/push_subscription_endpoint_validator.rb +34 -0
- data/app/services/decidim/send_push_notification.rb +5 -1
- data/app/uploaders/decidim/image_uploader.rb +1 -1
- data/app/uploaders/decidim/organization_favicon_uploader.rb +4 -9
- data/app/validators/uploader_image_dimensions_validator.rb +13 -11
- data/app/views/decidim/delete_user_mailer/delete.html.erb +6 -0
- data/app/views/decidim/devise/invitations/edit.html.erb +3 -3
- data/app/views/decidim/devise/registrations/new.html.erb +1 -0
- data/app/views/decidim/devise/shared/_tos_fields.html.erb +3 -3
- data/app/views/decidim/gamification/badges/index.html.erb +1 -1
- data/app/views/decidim/homepage/show.html.erb +2 -2
- data/app/views/decidim/last_activities/index.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/_error_modal.html.erb +11 -19
- data/app/views/decidim/messaging/conversations/_new_conversation_button.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/error.js.erb +12 -7
- data/app/views/decidim/messaging/conversations/new.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/show.html.erb +2 -2
- data/app/views/decidim/newsletters/unsubscribe.html.erb +1 -1
- data/app/views/decidim/notification_mailer/event_received.html.erb +3 -3
- data/app/views/decidim/notifications_settings/show.html.erb +5 -5
- data/app/views/decidim/offline/show.html.erb +1 -1
- data/app/views/decidim/pages/_tabbed.html.erb +3 -3
- data/app/views/decidim/pages/index.html.erb +1 -1
- data/app/views/decidim/participatory_space/members/_member.html.erb +1 -0
- data/app/views/decidim/profiles/show.html.erb +1 -1
- data/app/views/decidim/searches/_filters.html.erb +1 -1
- data/app/views/decidim/shared/_filters.html.erb +5 -5
- data/app/views/decidim/shared/_resource_actions.html.erb +4 -4
- data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
- data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +2 -2
- data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
- data/app/views/decidim/shared/filters/_dropdown_label.html.erb +4 -3
- data/app/views/decidim/user_activities/index.html.erb +1 -1
- data/app/views/devise/mailer/{invite_private_user.html.erb → invite_member.html.erb} +2 -2
- data/app/views/devise/mailer/{invite_private_user.text.erb → invite_member.text.erb} +2 -2
- data/app/views/layouts/decidim/_head.html.erb +2 -2
- data/app/views/layouts/decidim/_wrapper.html.erb +3 -3
- data/app/views/layouts/decidim/footer/_focus_mode_main.html.erb +0 -1
- data/app/views/layouts/decidim/footer/_main.html.erb +1 -2
- data/app/views/layouts/decidim/footer/_main_links.html.erb +56 -28
- data/app/views/layouts/decidim/header/_focus_mode_back_button.html.erb +4 -1
- data/app/views/layouts/decidim/header/_main.html.erb +17 -8
- data/app/views/layouts/decidim/header/_main_language_chooser.html.erb +24 -0
- data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +56 -56
- data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +2 -2
- data/app/views/layouts/decidim/header/_main_links_mobile_item_account.html.erb +3 -1
- data/app/views/layouts/decidim/header/_main_menu_mobile.html.erb +18 -5
- data/app/views/layouts/decidim/header/_main_search.html.erb +3 -3
- data/app/views/layouts/decidim/header/_menu.html.erb +5 -5
- data/app/views/layouts/decidim/header/_menu_breadcrumb_desktop.html.erb +40 -12
- data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile.html.erb +33 -0
- data/app/views/layouts/decidim/shared/_layout_center.html.erb +1 -1
- data/app/views/layouts/decidim/shared/_layout_item.html.erb +1 -1
- data/app/views/layouts/decidim/shared/_layout_two_col.html.erb +1 -1
- data/config/initializers/decidim_locale_aware_named_route_helper.rb +16 -0
- data/config/initializers/devise.rb +6 -0
- data/config/initializers/invisible_captcha.rb +1 -0
- data/config/locales/ar.yml +6 -38
- data/config/locales/bg.yml +3 -39
- data/config/locales/ca-IT.yml +91 -58
- data/config/locales/ca.yml +91 -58
- data/config/locales/cs.yml +54 -58
- data/config/locales/de.yml +45 -68
- data/config/locales/el.yml +3 -31
- data/config/locales/en.yml +88 -55
- data/config/locales/es-MX.yml +93 -60
- data/config/locales/es-PY.yml +93 -60
- data/config/locales/es.yml +95 -62
- data/config/locales/eu.yml +124 -92
- data/config/locales/fi-plain.yml +93 -55
- data/config/locales/fi.yml +96 -58
- data/config/locales/fr-CA.yml +70 -52
- data/config/locales/fr.yml +71 -54
- data/config/locales/ga-IE.yml +3 -1
- data/config/locales/gl.yml +3 -31
- data/config/locales/hu.yml +7 -40
- data/config/locales/id-ID.yml +3 -30
- data/config/locales/is-IS.yml +0 -6
- data/config/locales/it.yml +15 -33
- data/config/locales/ja.yml +105 -71
- data/config/locales/lb.yml +3 -33
- data/config/locales/lt.yml +4 -37
- data/config/locales/lv.yml +3 -30
- data/config/locales/nl.yml +3 -33
- data/config/locales/no.yml +3 -33
- data/config/locales/pl.yml +7 -41
- data/config/locales/pt-BR.yml +24 -65
- data/config/locales/pt.yml +3 -33
- data/config/locales/ro-RO.yml +12 -55
- data/config/locales/ru.yml +0 -16
- data/config/locales/sk.yml +1417 -32
- data/config/locales/sv.yml +44 -62
- data/config/locales/tr-TR.yml +20 -37
- data/config/locales/uk.yml +0 -9
- data/config/locales/zh-CN.yml +3 -30
- data/config/locales/zh-TW.yml +4 -35
- data/config/routes.rb +140 -76
- data/db/data/20251213075429_rename_members_in_action_log.rb +22 -0
- data/db/data/20260319145808_rename_send_to_members_in_newsletter.rb +27 -0
- data/db/migrate/20200730142511_add_file_upload_settings_to_decidim_organizations.rb +13 -15
- data/db/migrate/20250217192438_convert_user_groups_into_users.rb +3 -2
- data/db/migrate/20250523104311_move_cta_to_hero_content_block.rb +1 -1
- data/db/migrate/20250527122040_move_highlighted_content_banner_settings_to_content_block.rb +1 -1
- data/db/migrate/20250819110800_convert_private_exports_id_to_uuid.rb +2 -2
- data/db/migrate/20251112132305_remove_legacy_images_from_core_module.rb +27 -0
- data/db/migrate/20251205122428_rename_participatory_space_private_users_to_members.rb +9 -0
- data/db/migrate/20251216185133_rename_privatable_to_to_participatory_space_in_members.rb +10 -0
- data/db/migrate/20260208201405_remove_user_group_core.rb +21 -0
- data/db/migrate/20260208201406_remove_user_group_memberships.rb +30 -0
- data/db/migrate/20260208201407_remove_user_group_organizations.rb +11 -0
- data/db/migrate/20260217152425_remove_enable_participatory_space_filters_from_decidim_organizations.rb +7 -0
- data/db/migrate/20260314081619_add_index_on_decidim_members.rb +25 -0
- data/decidim-core.gemspec +28 -28
- data/lib/decidim/acts_as_tree.rb +12 -12
- data/lib/decidim/admin_filters_registry.rb +1 -1
- data/lib/decidim/amendable.rb +5 -1
- data/lib/decidim/api/functions/category_list.rb +1 -0
- data/lib/decidim/api/functions/component_finder_base.rb +1 -1
- data/lib/decidim/api/functions/component_list.rb +3 -1
- data/lib/decidim/api/functions/component_list_base.rb +1 -0
- data/lib/decidim/api/functions/participatory_space_finder_base.rb +1 -1
- data/lib/decidim/api/functions/participatory_space_list_base.rb +1 -0
- data/lib/decidim/api/functions/user_entity_list.rb +2 -1
- data/lib/decidim/api/interfaces/amendable_entity_interface.rb +1 -0
- data/lib/decidim/api/interfaces/amendable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/attachable_collection_interface.rb +1 -0
- data/lib/decidim/api/interfaces/attachable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/author_interface.rb +2 -1
- data/lib/decidim/api/interfaces/authorable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/categories_container_interface.rb +1 -0
- data/lib/decidim/api/interfaces/categorizable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/coauthorable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/component_interface.rb +9 -8
- data/lib/decidim/api/interfaces/fingerprint_interface.rb +1 -0
- data/lib/decidim/api/interfaces/followable_interface.rb +2 -0
- data/lib/decidim/api/interfaces/likeable_interface.rb +2 -2
- data/lib/decidim/api/interfaces/localizable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/participatory_space_interface.rb +1 -0
- data/lib/decidim/api/interfaces/referable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/scopable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/taxonomizable_interface.rb +1 -0
- data/lib/decidim/api/interfaces/timestamps_interface.rb +1 -0
- data/lib/decidim/api/interfaces/traceable_interface.rb +1 -0
- data/lib/decidim/api/types/attachment_collection_type.rb +5 -3
- data/lib/decidim/api/types/attachment_type.rb +11 -4
- data/lib/decidim/api/types/badge_score_type.rb +28 -0
- data/lib/decidim/api/types/moderation_type.rb +25 -0
- data/lib/decidim/api/types/participant_details_type.rb +17 -0
- data/lib/decidim/api/types/reportable_type.rb +18 -0
- data/lib/decidim/api/types/reportable_user_type.rb +17 -0
- data/lib/decidim/api/types/static_page_topic_type.rb +16 -0
- data/lib/decidim/api/types/static_page_type.rb +22 -0
- data/lib/decidim/api/types/taxonomy_type.rb +2 -0
- data/lib/decidim/api/types/user_moderation_type.rb +36 -0
- data/lib/decidim/api/types/user_type.rb +13 -0
- data/lib/decidim/asset_router/pipeline.rb +1 -1
- data/lib/decidim/asset_router/storage.rb +9 -9
- data/lib/decidim/assets/tailwind/tailwind.config.js.erb +4 -1
- data/lib/decidim/attachment_attributes.rb +58 -9
- data/lib/decidim/attribute_encryptor.rb +51 -10
- data/lib/decidim/attribute_object/model.rb +0 -5
- data/lib/decidim/block_registry.rb +1 -1
- data/lib/decidim/coauthorable.rb +2 -1
- data/lib/decidim/command.rb +2 -1
- data/lib/decidim/content_parsers/blob_parser.rb +3 -3
- data/lib/decidim/content_processor.rb +1 -1
- data/lib/decidim/content_renderers/base_renderer.rb +112 -0
- data/lib/decidim/content_renderers/blob_renderer.rb +6 -9
- data/lib/decidim/content_renderers/mention_resource_renderer.rb +10 -6
- data/lib/decidim/content_renderers/resource_renderer.rb +16 -7
- data/lib/decidim/content_renderers/user_renderer.rb +11 -9
- data/lib/decidim/core/api.rb +8 -0
- data/lib/decidim/core/content_blocks/registry_manager.rb +4 -10
- data/lib/decidim/core/engine.rb +10 -34
- data/lib/decidim/core/menu.rb +0 -26
- data/lib/decidim/core/test/factories.rb +32 -18
- data/lib/decidim/core/test/shared_examples/access_mode_restricted_participatory_spaces.rb +175 -0
- data/lib/decidim/core/test/shared_examples/access_mode_transparent_participatory_spaces.rb +244 -0
- data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +10 -10
- data/lib/decidim/core/test/shared_examples/amendable/amendment_event_examples.rb +2 -2
- data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +3 -3
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +147 -117
- data/lib/decidim/core/test/shared_examples/fingerprint_examples.rb +2 -0
- data/lib/decidim/core/test/shared_examples/has_members.rb +63 -0
- data/lib/decidim/core/test/shared_examples/has_space_in_mcell_examples.rb +2 -1
- data/lib/decidim/core/test/shared_examples/manage_share_tokens_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/map_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/participant_details_examples.rb +16 -0
- data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +10 -10
- data/lib/decidim/core/test/shared_examples/participatory_space_members_shared_examples.rb +121 -0
- data/lib/decidim/core/test/shared_examples/resource_liked_event_examples.rb +3 -3
- data/lib/decidim/core/test/shared_examples/resource_locator_presenter_examples.rb +7 -7
- data/lib/decidim/core/test/shared_examples/searchable_participatory_space_examples.rb +3 -3
- data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +2 -2
- data/lib/decidim/core/test/shared_examples/simple_event.rb +1 -0
- data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +2 -2
- data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +1 -1
- data/lib/decidim/core/test.rb +2 -1
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +222 -335
- data/lib/decidim/download_your_data_serializers/{download_your_data_participatory_space_private_user_serializer.rb → download_your_data_member_serializer.rb} +6 -6
- data/lib/decidim/download_your_data_serializers.rb +2 -2
- data/lib/decidim/engine_router.rb +31 -6
- data/lib/decidim/exporters/csv.rb +1 -1
- data/lib/decidim/filter_form_builder.rb +1 -1
- data/lib/decidim/form_builder.rb +58 -36
- data/{app/controllers/concerns → lib}/decidim/form_factory.rb +11 -1
- data/lib/decidim/has_settings.rb +2 -2
- data/lib/decidim/legacy_form_builder.rb +1 -0
- data/lib/decidim/locale_router_detector.rb +41 -0
- data/lib/decidim/maintenance/import_models/scope.rb +1 -1
- data/lib/decidim/maintenance/import_models.rb +0 -2
- data/lib/decidim/maintenance/taxonomy_importer.rb +1 -1
- data/lib/decidim/map/autocomplete.rb +4 -3
- data/lib/decidim/map/dynamic_map.rb +3 -1
- data/lib/decidim/map/frontend.rb +1 -1
- data/lib/decidim/map/geocoding.rb +2 -2
- data/lib/decidim/map/static_map.rb +10 -22
- data/lib/decidim/map/utility.rb +3 -6
- data/lib/decidim/map.rb +2 -2
- data/lib/decidim/menu.rb +1 -1
- data/lib/decidim/menu_item.rb +1 -0
- data/lib/decidim/menu_registry.rb +1 -1
- data/lib/decidim/moderation_tools.rb +1 -1
- data/lib/decidim/newsletter_encryptor.rb +5 -8
- data/lib/decidim/organization_settings.rb +2 -2
- data/lib/decidim/participable.rb +1 -0
- data/lib/decidim/participatory_space/has_members.rb +61 -0
- data/lib/decidim/participatory_space_manifest.rb +0 -4
- data/lib/decidim/participatory_space_resourceable.rb +10 -1
- data/lib/decidim/participatory_space_user.rb +1 -1
- data/lib/decidim/routes/locale_redirects.rb +47 -0
- data/lib/decidim/routes.rb +7 -0
- data/lib/decidim/search_resource_fields_mapper.rb +3 -4
- data/lib/decidim/searchable.rb +9 -4
- data/lib/decidim/seeds.rb +17 -0
- data/lib/decidim/shakapacker/runner.rb +4 -4
- data/lib/decidim/shakapacker/shakapacker.yml +28 -3
- data/lib/decidim/taxonomizable.rb +1 -1
- data/lib/decidim/translatable_attributes.rb +9 -3
- data/lib/decidim/view_model.rb +5 -1
- data/lib/devise/models/decidim_newsletterable.rb +1 -1
- data/lib/tasks/decidim_mailers_tasks.rake +31 -9
- data/lib/tasks/decidim_procfile.rake +1 -1
- data/lib/tasks/decidim_tasks.rake +0 -1
- data/lib/tasks/decidim_taxonomies.rake +1 -1
- data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +0 -1
- data/lib/tasks/upgrade/decidim_encryption.rake +12 -0
- data/lib/tasks/upgrade/decidim_migrate_wysiwyg_content.rake +0 -1
- data/lib/tasks/upgrade/decidim_remove_deleted_users_left_data_tasks.rake +1 -1
- data/lib/tasks/upgrade/{fix_deleted_private_follows.rake → fix_deleted_members_follows.rake} +5 -5
- data/lib/tasks/upgrade/migrations.rake +0 -1
- data/lib/tasks/upgrade/user_groups_migration.rake +0 -1
- metadata +244 -132
- data/app/cells/decidim/content_blocks/global_menu/show.erb +0 -11
- data/app/cells/decidim/content_blocks/global_menu_cell.rb +0 -35
- data/app/cells/decidim/content_blocks/menu_breadcrumb_last_activity/show.erb +0 -10
- data/app/cells/decidim/content_blocks/menu_breadcrumb_last_activity_cell.rb +0 -49
- data/app/cells/decidim/participatory_space_dropdown_metadata/links.erb +0 -9
- data/app/cells/decidim/participatory_space_dropdown_metadata/metadata.erb +0 -1
- data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +0 -11
- data/app/cells/decidim/participatory_space_dropdown_metadata_cell.rb +0 -26
- data/app/commands/decidim/gallery_methods.rb +0 -107
- data/app/controllers/concerns/decidim/has_members_page.rb +0 -25
- data/app/jobs/decidim/newsletters_opt_in_job.rb +0 -11
- data/app/jobs/decidim/user_report_job.rb +0 -11
- data/app/models/decidim/participatory_space_private_user.rb +0 -51
- data/app/packs/src/decidim/controllers/sticky_header/controller.js +0 -116
- data/app/packs/src/decidim/controllers/sticky_header/sticky_header.test.js +0 -320
- data/app/packs/src/decidim/dropdown_menu.js +0 -18
- data/app/packs/src/decidim/identity_selector_dialog.js +0 -33
- data/app/packs/src/decidim/vendor/tribute.js +0 -1890
- data/app/packs/stylesheets/decidim/_tribute.scss +0 -36
- data/app/presenters/decidim/admin_log/participatory_space_private_user_presenter.rb +0 -38
- data/app/presenters/decidim/participatory_space_private_user_presenter.rb +0 -46
- data/app/views/decidim/participants_account_mailer/removal_notification.html.erb +0 -11
- data/app/views/decidim/participatory_space_private_users/_participatory_space_private_user.html.erb +0 -1
- data/app/views/layouts/decidim/footer/_main_language_chooser.html.erb +0 -26
- data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +0 -34
- data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_desktop.html.erb +0 -10
- data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_mobile.html.erb +0 -17
- data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_top_left.html.erb +0 -2
- data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +0 -33
- data/app/views/layouts/decidim/header/_mobile_language_choose.html.erb +0 -25
- data/lib/decidim/core/test/shared_examples/has_private_users.rb +0 -63
- data/lib/decidim/core/test/shared_examples/participatory_space_dropdown_metadata_cell_examples.rb +0 -81
- data/lib/decidim/has_private_users.rb +0 -57
- data/lib/decidim/maintenance/import_models/assembly_type.rb +0 -49
- data/lib/decidim/maintenance/import_models/participatory_process_type.rb +0 -21
- data/lib/decidim/query_extensions.rb +0 -64
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@use "stylesheets/decidim/editor_suggestions";
|
|
2
|
+
|
|
1
3
|
.editor-props {
|
|
2
4
|
--editor-active-color: #487bda;
|
|
3
5
|
--editor-disabled-color: #eee;
|
|
@@ -5,12 +7,6 @@
|
|
|
5
7
|
--editor-bubble-shadow-color: #333;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
.editor-suggestions-props {
|
|
9
|
-
--editor-suggestions-border-color: #000;
|
|
10
|
-
--editor-suggestions-background-color: #eee;
|
|
11
|
-
--editor-suggestions-selected-highlight-color: #ccc;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
10
|
.editor-active {
|
|
15
11
|
@apply outline outline-4 outline-[var(--editor-active-color)];
|
|
16
12
|
}
|
|
@@ -130,6 +126,16 @@
|
|
|
130
126
|
[data-image-resizer-wrapper] {
|
|
131
127
|
@apply relative inline-block;
|
|
132
128
|
|
|
129
|
+
[data-image-resizer-control],
|
|
130
|
+
[data-image-resizer-dimensions] {
|
|
131
|
+
z-index: 1;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
> a {
|
|
135
|
+
position: relative;
|
|
136
|
+
z-index: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
133
139
|
[data-image-resizer-control] {
|
|
134
140
|
@apply absolute hidden w-2.5 h-2.5 rounded-none border border-solid border-[#000] bg-[#fff] opacity-80;
|
|
135
141
|
}
|
|
@@ -176,30 +182,3 @@
|
|
|
176
182
|
}
|
|
177
183
|
}
|
|
178
184
|
}
|
|
179
|
-
|
|
180
|
-
.editor-suggestions {
|
|
181
|
-
@apply editor-suggestions-props border-0 bg-[var(--editor-suggestions-background-color)] max-w-sm drop-shadow-md rounded-md;
|
|
182
|
-
|
|
183
|
-
&:hover {
|
|
184
|
-
.editor-suggestions-item[data-selected]:not(:hover) {
|
|
185
|
-
@apply bg-transparent;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.editor-suggestions-item {
|
|
190
|
-
@apply block w-full text-left py-[0.375rem] px-1.5 border-0 rounded-none truncate text-sm;
|
|
191
|
-
|
|
192
|
-
&:first-child {
|
|
193
|
-
@apply rounded-t-md;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
&:last-child {
|
|
197
|
-
@apply rounded-b-md;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
&:hover,
|
|
201
|
-
&[data-selected] {
|
|
202
|
-
@apply bg-[var(--editor-suggestions-selected-highlight-color)];
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
.geocoding
|
|
2
|
-
.
|
|
1
|
+
.geocoding {
|
|
2
|
+
&__locate .geocoding__button {
|
|
3
3
|
@apply mt-4;
|
|
4
|
+
|
|
5
|
+
&--locating {
|
|
6
|
+
@apply opacity-70 cursor-wait;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.geocoding__spinner {
|
|
10
|
+
@apply inline-block w-4 h-4 rounded-full animate-spin border-2 border-l-transparent border-y-transparent border-r-secondary align-middle;
|
|
11
|
+
}
|
|
4
12
|
}
|
|
5
13
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module AdminLog
|
|
5
|
+
module ParticipatorySpace
|
|
6
|
+
# This class holds the logic to present a `Decidim::ParticipatorySpace::MemberPresenter`
|
|
7
|
+
# for the `AdminLog` log.
|
|
8
|
+
#
|
|
9
|
+
# Usage should be automatic and you should not need to call this class
|
|
10
|
+
# directly, but here is an example:
|
|
11
|
+
#
|
|
12
|
+
# action_log = Decidim::ActionLog.last
|
|
13
|
+
# view_helpers # => this comes from the views
|
|
14
|
+
# MemberPresenter.new(action_log, view_helpers).present
|
|
15
|
+
class MemberPresenter < Decidim::Log::BasePresenter
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def diff_fields_mapping
|
|
19
|
+
{
|
|
20
|
+
name: :string,
|
|
21
|
+
email: :string
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def action_string
|
|
26
|
+
case action
|
|
27
|
+
when "create", "create_via_csv", "delete"
|
|
28
|
+
"decidim.admin_log.member.#{action}"
|
|
29
|
+
else
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def i18n_labels_scope
|
|
35
|
+
"activemodel.attributes.member"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -20,7 +20,7 @@ module Decidim
|
|
|
20
20
|
# "Decidim::Bar" => "Bars: 456"
|
|
21
21
|
# }
|
|
22
22
|
#
|
|
23
|
-
# @return [Hash
|
|
23
|
+
# @return [Hash{String => String}] The translated resource counts with the
|
|
24
24
|
# resource type as its keys and the translated text with the record count
|
|
25
25
|
# as its values.
|
|
26
26
|
def translated_record_counts
|
|
@@ -9,16 +9,16 @@ module Decidim
|
|
|
9
9
|
|
|
10
10
|
def render
|
|
11
11
|
content_tag :li, class: link_wrapper_classes do
|
|
12
|
-
output = [
|
|
12
|
+
output = [root_link(label, url, link_options)]
|
|
13
13
|
output.push(@view.send(:simple_menu, **@menu_item.submenu).render) if @menu_item.submenu
|
|
14
14
|
|
|
15
15
|
safe_join(output)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def root_link(text, url, args = {})
|
|
20
20
|
link_to url, class: args.with_indifferent_access[:class] do
|
|
21
|
-
"<span>#{text}</span>
|
|
21
|
+
"<span>#{text}</span>".html_safe
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
module Decidim
|
|
4
4
|
# A presenter to render footer menu
|
|
5
5
|
class FooterMenuPresenter < MenuPresenter
|
|
6
|
-
def
|
|
7
|
-
|
|
8
|
-
safe_join([content_tag(:h2, @options[:label], class: "h5 mb-4"), render_menu])
|
|
9
|
-
end
|
|
6
|
+
def render_menu_items
|
|
7
|
+
render_menu
|
|
10
8
|
end
|
|
11
9
|
end
|
|
12
10
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Log
|
|
5
|
+
module ValueTypes
|
|
6
|
+
# This class presents the given value as an access mode. Check
|
|
7
|
+
# the `DefaultPresenter` for more info on how value
|
|
8
|
+
# presenters work.
|
|
9
|
+
class AccessModePresenter < DefaultPresenter
|
|
10
|
+
# Public: Presents the value as an access mode. If the access mode can
|
|
11
|
+
# be found, it shows its translated label. Otherwise it shows a fallback message.
|
|
12
|
+
#
|
|
13
|
+
# Returns an HTML-safe String.
|
|
14
|
+
def present
|
|
15
|
+
return unless value
|
|
16
|
+
return translated_access_mode if valid_access_mode?
|
|
17
|
+
|
|
18
|
+
I18n.t("not_found", id: value, scope: "decidim.log.value_types.access_mode_presenter")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def valid_access_mode?
|
|
24
|
+
access_modes.has_value?(value.to_i)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def translated_access_mode
|
|
28
|
+
I18n.t(access_mode_key, scope: "decidim.log.value_types.access_mode_presenter.access_modes")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def access_mode_key
|
|
32
|
+
access_modes.key(value.to_i)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def access_modes
|
|
36
|
+
# Access modes are consistent across participatory spaces (assemblies, processes, etc.)
|
|
37
|
+
# open: 0 - fully visible and accessible
|
|
38
|
+
# transparent: 1 - visible but content restricted
|
|
39
|
+
# restricted: 2 - not visible, requires permission
|
|
40
|
+
{ open: 0, transparent: 1, restricted: 2 }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -29,9 +29,9 @@ module Decidim
|
|
|
29
29
|
delegate :content_tag, :safe_join, :link_to, :active_link_to_class, :is_active_link?, :icon, to: :@view
|
|
30
30
|
|
|
31
31
|
def render
|
|
32
|
-
content_tag :li, role:
|
|
32
|
+
content_tag :li, role: wrapper_role, class: link_wrapper_classes do
|
|
33
33
|
output = if url == "#"
|
|
34
|
-
[content_tag(:span, composed_label, class: "sidebar-menu__item-disabled")]
|
|
34
|
+
[content_tag(:span, composed_label, class: "sidebar-menu__item-disabled", role: menuitem_role)]
|
|
35
35
|
else
|
|
36
36
|
[link_to(composed_label, url, link_options)]
|
|
37
37
|
end
|
|
@@ -52,7 +52,7 @@ module Decidim
|
|
|
52
52
|
{ aria: { current: "page" } }
|
|
53
53
|
else
|
|
54
54
|
{}
|
|
55
|
-
end.merge({ class: link_classes })
|
|
55
|
+
end.merge({ class: link_classes, role: menuitem_role })
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def composed_label
|
|
@@ -69,6 +69,18 @@ module Decidim
|
|
|
69
69
|
[@options.element_wrapper_class, active_class].compact.join(" ")
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
def menuitem_role
|
|
73
|
+
return if @options.role == false
|
|
74
|
+
|
|
75
|
+
@options.role || :menuitem
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def wrapper_role
|
|
79
|
+
return if menuitem_role.blank?
|
|
80
|
+
|
|
81
|
+
:presentation
|
|
82
|
+
end
|
|
83
|
+
|
|
72
84
|
def active_class
|
|
73
85
|
active_link_to_class(
|
|
74
86
|
url,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module ParticipatorySpace
|
|
5
|
+
#
|
|
6
|
+
# Decorator for participatory space members
|
|
7
|
+
#
|
|
8
|
+
class MemberPresenter < SimpleDelegator
|
|
9
|
+
delegate :profile_url, to: :user, allow_nil: true
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
user ? user.name : full_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def nickname
|
|
16
|
+
user.nickname if user
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def avatar_url(variant = nil)
|
|
20
|
+
return user.avatar_url(variant) if user.present?
|
|
21
|
+
|
|
22
|
+
non_user_avatar_path(variant)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def non_user_avatar_path(variant = nil)
|
|
26
|
+
return non_user_avatar.default_url(variant) unless non_user_avatar.attached?
|
|
27
|
+
|
|
28
|
+
non_user_avatar.path(variant:)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def non_user_avatar
|
|
32
|
+
attached_uploader(:non_user_avatar)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def deleted?
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def user
|
|
42
|
+
@user ||= if (user = __getobj__.user.presence)
|
|
43
|
+
Decidim::UserPresenter.new(user)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -55,8 +55,9 @@ module Decidim
|
|
|
55
55
|
# Returns a String.
|
|
56
56
|
def show(options = {})
|
|
57
57
|
options.merge!(options_for_polymorphic)
|
|
58
|
+
locale = options.delete(:locale) || I18n.locale
|
|
58
59
|
|
|
59
|
-
admin_route_proxy.send("#{member_route_name}_path", target, options)
|
|
60
|
+
normalize_locale_route(admin_route_proxy.send("#{member_route_name}_path", target, options), locale)
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
# Builds the admin edit path to the resource.
|
|
@@ -66,8 +67,9 @@ module Decidim
|
|
|
66
67
|
# Returns a String.
|
|
67
68
|
def edit(options = {})
|
|
68
69
|
options.merge!(options_for_polymorphic)
|
|
70
|
+
locale = options.delete(:locale) || I18n.locale
|
|
69
71
|
|
|
70
|
-
admin_route_proxy.send("edit_#{member_route_name}_path", target, options)
|
|
72
|
+
normalize_locale_route(admin_route_proxy.send("edit_#{member_route_name}_path", target, options), locale)
|
|
71
73
|
end
|
|
72
74
|
|
|
73
75
|
private
|
|
@@ -112,8 +114,9 @@ module Decidim
|
|
|
112
114
|
|
|
113
115
|
def admin_collection_route(route_type, options)
|
|
114
116
|
options.merge!(options_for_polymorphic)
|
|
117
|
+
locale = options.delete(:locale) || I18n.locale
|
|
115
118
|
|
|
116
|
-
admin_route_proxy.send("#{collection_route_name}_#{route_type}", options)
|
|
119
|
+
normalize_locale_route(admin_route_proxy.send("#{collection_route_name}_#{route_type}", options), locale)
|
|
117
120
|
end
|
|
118
121
|
|
|
119
122
|
def manifest_for(record)
|
|
@@ -172,5 +175,21 @@ module Decidim
|
|
|
172
175
|
def admin_route_proxy
|
|
173
176
|
@admin_route_proxy ||= EngineRouter.admin_proxy(component || target)
|
|
174
177
|
end
|
|
178
|
+
|
|
179
|
+
def normalize_locale_route(path, locale)
|
|
180
|
+
path = path.sub(/([?&])locale=[^&]*(?=&|\z)/, "\\1")
|
|
181
|
+
path = path.delete_suffix("?")
|
|
182
|
+
path = path.delete_suffix("&")
|
|
183
|
+
path = path.sub("?&", "?")
|
|
184
|
+
|
|
185
|
+
path = "/#{path}" unless path.start_with?("/")
|
|
186
|
+
|
|
187
|
+
locale_candidates = Regexp.union(I18n.available_locales.map(&:to_s).sort_by(&:length).reverse)
|
|
188
|
+
path = path.sub(%r{\A/#{locale_candidates}(?=/|\z)}, "")
|
|
189
|
+
|
|
190
|
+
path = "/" if path.empty?
|
|
191
|
+
|
|
192
|
+
"/#{locale}#{path}"
|
|
193
|
+
end
|
|
175
194
|
end
|
|
176
195
|
end
|
|
@@ -79,7 +79,7 @@ module Decidim
|
|
|
79
79
|
Decidim.participatory_space_manifests.map do |manifest|
|
|
80
80
|
klass = manifest.model_class_name.constantize
|
|
81
81
|
|
|
82
|
-
condition = if klass.include?(Decidim::
|
|
82
|
+
condition = if klass.include?(Decidim::ParticipatorySpace::HasMembers)
|
|
83
83
|
Arel.sql(
|
|
84
84
|
<<~SQL.squish
|
|
85
85
|
(
|
|
@@ -79,6 +79,9 @@ module Decidim
|
|
|
79
79
|
image_url = image_element["src"]
|
|
80
80
|
next if image_url.blank?
|
|
81
81
|
|
|
82
|
+
blob = find_blob_by_id(image_url.split("/").last)
|
|
83
|
+
return blob if blob.present?
|
|
84
|
+
|
|
82
85
|
blob = find_blob_by_key(image_url.split("/").second_to_last)
|
|
83
86
|
return blob if blob.present?
|
|
84
87
|
end
|
|
@@ -120,6 +123,10 @@ module Decidim
|
|
|
120
123
|
ActiveStorage::Blob.find_signed(blob_key) if blob_key.present?
|
|
121
124
|
end
|
|
122
125
|
|
|
126
|
+
def find_blob_by_id(blob_id)
|
|
127
|
+
ActiveStorage::Blob.find_by(id: blob_id) if blob_id.present?
|
|
128
|
+
end
|
|
129
|
+
|
|
123
130
|
def blob_from_attached_file(file)
|
|
124
131
|
return unless file.respond_to?(:attached?) && file.attached?
|
|
125
132
|
|
|
@@ -27,7 +27,8 @@ module Decidim
|
|
|
27
27
|
follows_count: resource.follows_count,
|
|
28
28
|
short_description: resource.short_description,
|
|
29
29
|
description: resource.description,
|
|
30
|
-
promoted: resource.promoted
|
|
30
|
+
promoted: resource.promoted,
|
|
31
|
+
component_settings:
|
|
31
32
|
}
|
|
32
33
|
end
|
|
33
34
|
|
|
@@ -98,6 +99,19 @@ module Decidim
|
|
|
98
99
|
serializer = Decidim::Exporters::ParticipatorySpaceComponentsSerializer.new(resource)
|
|
99
100
|
serializer.run
|
|
100
101
|
end
|
|
102
|
+
|
|
103
|
+
def component_settings
|
|
104
|
+
return unless resource.respond_to?(:components)
|
|
105
|
+
|
|
106
|
+
resource.components.map do |component|
|
|
107
|
+
{
|
|
108
|
+
id: component.id,
|
|
109
|
+
name: component.name,
|
|
110
|
+
manifest_name: component.manifest_name,
|
|
111
|
+
settings: component.settings.respond_to?(:as_json) ? component.settings.as_json : component.settings
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
end
|
|
101
115
|
end
|
|
102
116
|
end
|
|
103
117
|
end
|
|
@@ -44,6 +44,7 @@ module Decidim
|
|
|
44
44
|
|
|
45
45
|
def send_to_affected_users
|
|
46
46
|
affected_users.each do |recipient|
|
|
47
|
+
next unless recipient.is_a?(Decidim::User)
|
|
47
48
|
next unless ["all", "own-only"].include?(recipient.notification_types)
|
|
48
49
|
next if recipient.deleted? || recipient.blocked?
|
|
49
50
|
|
|
@@ -53,6 +54,7 @@ module Decidim
|
|
|
53
54
|
|
|
54
55
|
def send_to_followers
|
|
55
56
|
followers.each do |recipient|
|
|
57
|
+
next unless recipient.is_a?(Decidim::User)
|
|
56
58
|
next unless ["all", "followed-only"].include?(recipient.notification_types)
|
|
57
59
|
next if recipient.deleted? || recipient.blocked?
|
|
58
60
|
|
|
@@ -37,10 +37,14 @@ module Decidim
|
|
|
37
37
|
return unless event_class.types.include?(:notification)
|
|
38
38
|
|
|
39
39
|
followers.each do |recipient|
|
|
40
|
+
next unless recipient.is_a?(Decidim::User)
|
|
41
|
+
|
|
40
42
|
generate_notification_for(recipient, user_role: :follower) if ["all", "followed-only"].include?(recipient.notification_types)
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
affected_users.each do |recipient|
|
|
46
|
+
next unless recipient.is_a?(Decidim::User)
|
|
47
|
+
|
|
44
48
|
generate_notification_for(recipient, user_role: :affected_user) if ["all", "own-only"].include?(recipient.notification_types)
|
|
45
49
|
end
|
|
46
50
|
end
|
|
@@ -4,6 +4,10 @@ module Decidim
|
|
|
4
4
|
# This class manages the creation and deletion of user notifications
|
|
5
5
|
|
|
6
6
|
class NotificationsSubscriptionsPersistor
|
|
7
|
+
include PushSubscriptionEndpointValidator
|
|
8
|
+
|
|
9
|
+
class UnsupportedPushSubscriptionEndpointError < StandardError; end
|
|
10
|
+
|
|
7
11
|
attr_reader :user
|
|
8
12
|
|
|
9
13
|
def initialize(user)
|
|
@@ -11,6 +15,8 @@ module Decidim
|
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
def add_subscription(params)
|
|
18
|
+
raise UnsupportedPushSubscriptionEndpointError unless supported_push_subscription_endpoint?(params[:endpoint])
|
|
19
|
+
|
|
14
20
|
subscriptions = user.notification_settings["subscriptions"] || {}
|
|
15
21
|
filtered_params = filter_params(params)
|
|
16
22
|
new_subscription = { filtered_params[:auth] => filtered_params }
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
# Shared validation for browser push subscription endpoints.
|
|
5
|
+
module PushSubscriptionEndpointValidator
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def supported_push_subscription_endpoint?(endpoint)
|
|
9
|
+
return false if endpoint.blank?
|
|
10
|
+
|
|
11
|
+
uri = URI.parse(endpoint)
|
|
12
|
+
return false unless uri.is_a?(URI::HTTPS)
|
|
13
|
+
|
|
14
|
+
host = uri.host&.downcase
|
|
15
|
+
return false if host.blank?
|
|
16
|
+
|
|
17
|
+
allowed_push_subscription_endpoint_patterns.any? { |pattern| pattern.match?(host) }
|
|
18
|
+
rescue URI::InvalidURIError
|
|
19
|
+
false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Override this method to customize the browser push endpoint allowlist.
|
|
23
|
+
def allowed_push_subscription_endpoint_patterns
|
|
24
|
+
[
|
|
25
|
+
/\A(?:.*\.)?push\.services\.mozilla\.com\z/,
|
|
26
|
+
/\A(?:.*\.)?fcm\.googleapis\.com\z/,
|
|
27
|
+
/\A(?:.*\.)?android\.googleapis\.com\z/,
|
|
28
|
+
/\A(?:.*\.)?push\.apple\.com\z/,
|
|
29
|
+
/\A(?:.*\.)?opera\.com\z/,
|
|
30
|
+
/\A(?:.*\.)?notify\.windows\.com\z/
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -10,6 +10,7 @@ module Decidim
|
|
|
10
10
|
|
|
11
11
|
class SendPushNotification
|
|
12
12
|
include ActionView::Helpers::UrlHelper
|
|
13
|
+
include PushSubscriptionEndpointValidator
|
|
13
14
|
|
|
14
15
|
# Send the push notification. Returns `nil` if the user did not allowed push notifications
|
|
15
16
|
# or if the subscription to push notifications does not exist
|
|
@@ -24,9 +25,12 @@ module Decidim
|
|
|
24
25
|
raise ArgumentError, "Need to provide a title if the notification is a PushNotificationMessage" if notification.is_a?(Decidim::PushNotificationMessage) && title.nil?
|
|
25
26
|
|
|
26
27
|
user = notification.user
|
|
28
|
+
subscriptions = user.notifications_subscriptions.values.select do |subscription|
|
|
29
|
+
supported_push_subscription_endpoint?(subscription["endpoint"])
|
|
30
|
+
end
|
|
27
31
|
|
|
28
32
|
I18n.with_locale(user.locale || user.organization.default_locale) do
|
|
29
|
-
|
|
33
|
+
subscriptions.map do |subscription|
|
|
30
34
|
payload = build_payload(message_params(notification, title), subscription)
|
|
31
35
|
# Capture webpush exceptions in order to avoid this call to be repeated by the background job runner
|
|
32
36
|
# Webpush::Error class is the parent class of all defined errors
|
|
@@ -8,7 +8,7 @@ module Decidim
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def content_type_allowlist
|
|
11
|
-
extension_allowlist.
|
|
11
|
+
extension_allowlist.filter_map { |ext| MiniMime.lookup_by_extension(ext)&.content_type }.uniq
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# Fetches info about different variants, their processors and dimensions
|
|
@@ -7,7 +7,8 @@ module Decidim
|
|
|
7
7
|
huge: 512,
|
|
8
8
|
big: 192,
|
|
9
9
|
medium: 180,
|
|
10
|
-
small: 32
|
|
10
|
+
small: 32,
|
|
11
|
+
favicon: 256
|
|
11
12
|
}.freeze
|
|
12
13
|
|
|
13
14
|
set_variants do
|
|
@@ -16,17 +17,11 @@ module Decidim
|
|
|
16
17
|
resize_and_pad: [value, value],
|
|
17
18
|
format: :png
|
|
18
19
|
}
|
|
19
|
-
end
|
|
20
|
-
favicon: {
|
|
21
|
-
resize_and_pad: [256, 256],
|
|
22
|
-
define: "icon:auto-resize=16,24,32,48,64,72,96,128,256",
|
|
23
|
-
format: :ico
|
|
24
|
-
}
|
|
25
|
-
)
|
|
20
|
+
end
|
|
26
21
|
end
|
|
27
22
|
|
|
28
23
|
def extension_allowlist
|
|
29
|
-
%w(png jpg jpeg webp
|
|
24
|
+
%w(png jpg jpeg webp)
|
|
30
25
|
end
|
|
31
26
|
end
|
|
32
27
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# This validator checks when the files to be uploaded are images and the attached uploader's
|
|
4
4
|
# has enabled dimensions validation that the image dimensions are below the
|
|
5
5
|
# limit defined by the uploader
|
|
6
|
-
require "
|
|
6
|
+
require "vips"
|
|
7
7
|
|
|
8
8
|
class UploaderImageDimensionsValidator < ActiveModel::Validations::FileContentTypeValidator
|
|
9
9
|
def validate_each(record, attribute, value)
|
|
@@ -28,14 +28,16 @@ class UploaderImageDimensionsValidator < ActiveModel::Validations::FileContentTy
|
|
|
28
28
|
return unless uploader.validable_dimensions
|
|
29
29
|
return if (image = extract_image(file)).blank?
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# The error may happen because of many reasons but most commonly the image
|
|
34
|
-
# exceeds the default maximum dimensions set for ImageMagick when the
|
|
35
|
-
# `identify` command fails to identify the image.
|
|
31
|
+
# A simple check to avoid DoS with maliciously crafted images, or just to
|
|
32
|
+
# avoid reckless users that upload images with too many pixels.
|
|
36
33
|
#
|
|
37
|
-
#
|
|
38
|
-
|
|
34
|
+
# See https://hackerone.com/reports/390
|
|
35
|
+
max_dimension = [image.width, image.height].max
|
|
36
|
+
record.errors.add attribute, I18n.t("decidim.errors.files.file_resolution_too_large") if max_dimension > uploader.max_image_height_or_width
|
|
37
|
+
rescue Vips::Error
|
|
38
|
+
# The error may happen because of many reasons but most commonly the image
|
|
39
|
+
# exceeds the default maximum dimensions set for libvips when the image
|
|
40
|
+
# fails to load.
|
|
39
41
|
#
|
|
40
42
|
# Note that the error can also happen because of other reasons than only
|
|
41
43
|
# the image dimensions being too large. But as we do not really know the
|
|
@@ -47,11 +49,11 @@ class UploaderImageDimensionsValidator < ActiveModel::Validations::FileContentTy
|
|
|
47
49
|
return unless file.try(:content_type).to_s.start_with?("image")
|
|
48
50
|
|
|
49
51
|
if uploaded_file?(file)
|
|
50
|
-
|
|
52
|
+
Vips::Image.new_from_file(file.path)
|
|
51
53
|
elsif file.is_a?(ActiveStorage::Attached) && file.blob.persisted?
|
|
52
|
-
|
|
54
|
+
Vips::Image.new_from_buffer(file.blob.download, "")
|
|
53
55
|
end
|
|
54
|
-
rescue ActiveStorage::FileNotFoundError,
|
|
56
|
+
rescue ActiveStorage::FileNotFoundError, Vips::Error
|
|
55
57
|
# Although the blob is persisted, the file is not available to download and analyze
|
|
56
58
|
# after committing the record
|
|
57
59
|
nil
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<p class="email-greeting"><%= t(".hello", username: @user_name) %></p>
|
|
2
|
+
|
|
3
|
+
<p class="email-instructions"><%= t ".body_1" %></p>
|
|
4
|
+
<p class="email-instructions"><%= t ".body_2" %></p>
|
|
5
|
+
|
|
6
|
+
<p class="email-closing"><%= t(".greetings_html", organization_name: organization_name(@organization), organization_url: decidim.root_url(host: @organization.host)) %></p>
|