decidim-budgets 0.30.3 → 0.31.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.
- checksums.yaml +4 -4
 - data/app/cells/decidim/budgets/budget_list_item/show.erb +19 -9
 - data/app/cells/decidim/budgets/budget_list_item/vote_action.erb +2 -2
 - data/app/cells/decidim/budgets/budget_list_item_cell.rb +44 -10
 - data/app/cells/decidim/budgets/budgets_list/card_list.erb +0 -2
 - data/app/cells/decidim/budgets/budgets_list/main_list.erb +2 -2
 - data/app/cells/decidim/budgets/budgets_list/show.erb +3 -3
 - data/app/cells/decidim/budgets/budgets_list/voted.erb +12 -10
 - data/app/cells/decidim/budgets/budgets_list_cell.rb +22 -0
 - data/app/cells/decidim/budgets/project_budget_amount_cell.rb +14 -0
 - data/app/cells/decidim/budgets/project_l/extra_data.erb +8 -2
 - data/app/cells/decidim/budgets/project_l/metadata.erb +1 -1
 - data/app/cells/decidim/budgets/project_l_cell.rb +2 -4
 - data/app/cells/decidim/budgets/project_metadata_cell.rb +15 -19
 - data/app/cells/decidim/budgets/project_selected_status_cell.rb +1 -11
 - data/app/cells/decidim/budgets/project_vote_button/show.erb +5 -5
 - data/app/cells/decidim/budgets/project_vote_button_cell.rb +14 -9
 - data/app/cells/decidim/budgets/project_votes_count_cell.rb +8 -14
 - data/app/commands/decidim/budgets/cancel_order.rb +5 -0
 - data/app/controllers/decidim/budgets/admin/budgets_controller.rb +2 -2
 - data/app/controllers/decidim/budgets/admin/projects_controller.rb +2 -2
 - data/app/controllers/decidim/budgets/admin/proposals_imports_controller.rb +1 -1
 - data/app/controllers/decidim/budgets/application_controller.rb +13 -1
 - data/app/controllers/decidim/budgets/budgets_controller.rb +1 -3
 - data/app/controllers/decidim/budgets/line_items_controller.rb +19 -0
 - data/app/controllers/decidim/budgets/orders_controller.rb +20 -0
 - data/app/controllers/decidim/budgets/projects_controller.rb +3 -1
 - data/app/forms/decidim/budgets/admin/component_form.rb +4 -30
 - data/app/helpers/decidim/budgets/application_helper.rb +1 -0
 - data/app/helpers/decidim/budgets/projects_helper.rb +11 -7
 - data/app/models/decidim/budgets/order.rb +2 -2
 - data/app/packs/entrypoints/decidim_budgets.js +1 -0
 - data/app/packs/src/decidim/budgets/admin/projects.js +2 -2
 - data/app/packs/src/decidim/budgets/budgetSummaryBackdrop.js +41 -0
 - data/app/packs/src/decidim/budgets/exit_handler.js +7 -2
 - data/app/packs/src/decidim/budgets/progressFixed.js +1 -1
 - data/app/packs/src/decidim/budgets/projects.js +1 -1
 - data/app/packs/stylesheets/budgets.scss +57 -37
 - data/app/permissions/decidim/budgets/permissions.rb +17 -13
 - data/app/presenters/decidim/budgets/project_presenter.rb +2 -4
 - data/app/views/decidim/budgets/admin/budgets/_actions.html.erb +65 -18
 - data/app/views/decidim/budgets/admin/budgets/_budget-tr.html.erb +4 -4
 - data/app/views/decidim/budgets/admin/budgets/_form.html.erb +1 -1
 - data/app/views/decidim/budgets/admin/budgets/index.html.erb +14 -11
 - data/app/views/decidim/budgets/admin/budgets/manage_trash.html.erb +2 -1
 - data/app/views/decidim/budgets/admin/projects/_actions.html.erb +66 -22
 - data/app/views/decidim/budgets/admin/projects/_bulk-actions.html.erb +15 -17
 - data/app/views/decidim/budgets/admin/projects/_form.html.erb +1 -1
 - data/app/views/decidim/budgets/admin/projects/_project-tr.html.erb +7 -7
 - data/app/views/decidim/budgets/admin/projects/bulk_actions/_dropdown.html.erb +23 -30
 - data/app/views/decidim/budgets/admin/projects/index.html.erb +2 -2
 - data/app/views/decidim/budgets/admin/projects/manage_trash.html.erb +2 -1
 - data/app/views/decidim/budgets/line_items/update_budget.js.erb +6 -5
 - data/app/views/decidim/budgets/orders/status.html.erb +30 -30
 - data/app/views/decidim/budgets/projects/_addition_selector.html.erb +1 -1
 - data/app/views/decidim/budgets/projects/_budget_summary.html.erb +5 -1
 - data/app/views/decidim/budgets/projects/_exit_modal.html.erb +1 -1
 - data/app/views/decidim/budgets/projects/_project.html.erb +5 -1
 - data/app/views/decidim/budgets/projects/_project_budget_button.html.erb +1 -9
 - data/app/views/decidim/budgets/projects/_projects.html.erb +3 -1
 - data/app/views/decidim/budgets/projects/index.html.erb +28 -6
 - data/app/views/decidim/budgets/projects/order_progress_summary/_content.html.erb +30 -0
 - data/app/views/decidim/budgets/projects/order_progress_summary/_content_responsive.html.erb +56 -0
 - data/app/views/decidim/budgets/projects/order_progress_summary/_progress_box.html.erb +43 -0
 - data/app/views/decidim/budgets/projects/order_progress_summary/_progress_box_buttons.html.erb +12 -0
 - data/app/views/decidim/budgets/projects/order_progress_summary/_progress_box_sticky.html.erb +25 -0
 - data/app/views/decidim/budgets/projects/show.html.erb +30 -17
 - data/config/assets.rb +2 -2
 - data/config/locales/ar.yml +0 -8
 - data/config/locales/bg.yml +2 -18
 - data/config/locales/ca-IT.yml +26 -14
 - data/config/locales/ca.yml +26 -14
 - data/config/locales/cs.yml +21 -18
 - data/config/locales/de.yml +26 -14
 - data/config/locales/el.yml +0 -7
 - data/config/locales/en.yml +26 -14
 - data/config/locales/es-MX.yml +26 -14
 - data/config/locales/es-PY.yml +26 -14
 - data/config/locales/es.yml +25 -13
 - data/config/locales/eu.yml +26 -14
 - data/config/locales/fi-plain.yml +26 -14
 - data/config/locales/fi.yml +26 -14
 - data/config/locales/fr-CA.yml +26 -14
 - data/config/locales/fr.yml +26 -14
 - data/config/locales/ga-IE.yml +0 -5
 - data/config/locales/gl.yml +0 -7
 - data/config/locales/hu.yml +2 -18
 - data/config/locales/id-ID.yml +0 -7
 - data/config/locales/is-IS.yml +0 -6
 - data/config/locales/it.yml +0 -7
 - data/config/locales/ja.yml +26 -14
 - data/config/locales/kaa.yml +0 -1
 - data/config/locales/ko.yml +0 -5
 - data/config/locales/lb.yml +0 -7
 - data/config/locales/lt.yml +2 -18
 - data/config/locales/lv.yml +0 -7
 - data/config/locales/nl.yml +0 -7
 - data/config/locales/no.yml +0 -7
 - data/config/locales/pl.yml +2 -18
 - data/config/locales/pt-BR.yml +2 -18
 - data/config/locales/pt.yml +0 -7
 - data/config/locales/ro-RO.yml +7 -7
 - data/config/locales/ru.yml +0 -7
 - data/config/locales/sk.yml +0 -7
 - data/config/locales/sq-AL.yml +0 -3
 - data/config/locales/sv.yml +25 -13
 - data/config/locales/tr-TR.yml +0 -8
 - data/config/locales/uk.yml +0 -7
 - data/config/locales/zh-CN.yml +0 -8
 - data/config/locales/zh-TW.yml +0 -7
 - data/db/migrate/20250912110212_move_voting_rules_to_radio_buttons.rb +22 -0
 - data/lib/decidim/api/budget_type.rb +7 -0
 - data/lib/decidim/api/project_type.rb +29 -1
 - data/lib/decidim/budgets/budget_order_pdf.rb +73 -0
 - data/lib/decidim/budgets/component.rb +26 -13
 - data/lib/decidim/budgets/engine.rb +3 -11
 - data/lib/decidim/budgets/seeds.rb +16 -5
 - data/lib/decidim/budgets/test/factories.rb +3 -18
 - data/lib/decidim/budgets/version.rb +1 -1
 - data/lib/decidim/budgets/workflows/base.rb +0 -14
 - data/lib/decidim/budgets.rb +1 -5
 - metadata +21 -15
 - data/app/queries/decidim/budgets/metrics/budget_followers_metric_measure.rb +0 -32
 - data/app/queries/decidim/budgets/metrics/budget_participants_metric_measure.rb +0 -27
 - data/app/views/decidim/budgets/projects/_order_progress_summary_content.html.erb +0 -122
 - /data/app/views/decidim/budgets/projects/{_order_progress_progressbar_marks_right.html.erb → order_progress_summary/_progressbar_marks_right.html.erb} +0 -0
 
| 
         @@ -8,7 +8,7 @@ module Decidim 
     | 
|
| 
       8 
8 
     | 
    
         
             
                # Note that it inherits from `Decidim::Components::BaseController`, which
         
     | 
| 
       9 
9 
     | 
    
         
             
                # override its layout and provide all kinds of useful methods.
         
     | 
| 
       10 
10 
     | 
    
         
             
                class ApplicationController < Decidim::Components::BaseController
         
     | 
| 
       11 
     | 
    
         
            -
                  helper_method :current_workflow, :voting_finished?, :voting_open?
         
     | 
| 
      
 11 
     | 
    
         
            +
                  helper_method :current_workflow, :voting_finished?, :voting_open?, :show_votes_count?
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                  def current_workflow
         
     | 
| 
       14 
14 
     | 
    
         
             
                    @current_workflow ||= Decidim::Budgets.workflows[workflow_name].new(current_component, current_user)
         
     | 
| 
         @@ -22,11 +22,23 @@ module Decidim 
     | 
|
| 
       22 
22 
     | 
    
         
             
                    current_settings.votes == "finished"
         
     | 
| 
       23 
23 
     | 
    
         
             
                  end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
      
 25 
     | 
    
         
            +
                  def show_votes_count?
         
     | 
| 
      
 26 
     | 
    
         
            +
                    current_settings.show_votes?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def resource_added?(project)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    current_order && current_order.projects.include?(project)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
       25 
33 
     | 
    
         
             
                  private
         
     | 
| 
       26 
34 
     | 
    
         | 
| 
       27 
35 
     | 
    
         
             
                  def workflow_name
         
     | 
| 
       28 
36 
     | 
    
         
             
                    @workflow_name ||= current_component.settings.workflow.to_sym
         
     | 
| 
       29 
37 
     | 
    
         
             
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def set_focus_mode_if_voting_open
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @focus_mode = true if voting_open?
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
       30 
42 
     | 
    
         
             
                end
         
     | 
| 
       31 
43 
     | 
    
         
             
              end
         
     | 
| 
       32 
44 
     | 
    
         
             
            end
         
     | 
| 
         @@ -9,9 +9,7 @@ module Decidim 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  include Decidim::Budgets::Orderable
         
     | 
| 
       10 
10 
     | 
    
         
             
                  include Decidim::TranslatableAttributes
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                  def index
         
     | 
| 
       13 
     | 
    
         
            -
                    redirect_to budget_projects_path(current_workflow.single) if current_workflow.single?
         
     | 
| 
       14 
     | 
    
         
            -
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def index; end
         
     | 
| 
       15 
13 
     | 
    
         | 
| 
       16 
14 
     | 
    
         
             
                  def show
         
     | 
| 
       17 
15 
     | 
    
         
             
                    raise ActionController::RoutingError, "Not Found" unless budget
         
     | 
| 
         @@ -8,6 +8,8 @@ module Decidim 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                  helper_method :budget, :project
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
                  before_action :set_focus_mode, :set_request_origin
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       11 
13 
     | 
    
         
             
                  def create
         
     | 
| 
       12 
14 
     | 
    
         
             
                    enforce_permission_to :vote, :project, project:, budget:, workflow: current_workflow
         
     | 
| 
       13 
15 
     | 
    
         | 
| 
         @@ -49,6 +51,23 @@ module Decidim 
     | 
|
| 
       49 
51 
     | 
    
         | 
| 
       50 
52 
     | 
    
         
             
                  private
         
     | 
| 
       51 
53 
     | 
    
         | 
| 
      
 54 
     | 
    
         
            +
                  def set_request_origin
         
     | 
| 
      
 55 
     | 
    
         
            +
                    return unless request.referer
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    path = URI(request.referer).path
         
     | 
| 
      
 58 
     | 
    
         
            +
                    @focus_mode_origin = if path.match?(%r{/budgets/\d+/projects/\d+$})
         
     | 
| 
      
 59 
     | 
    
         
            +
                                           "show"
         
     | 
| 
      
 60 
     | 
    
         
            +
                                         elsif path.match?(%r{/budgets/\d+/projects$})
         
     | 
| 
      
 61 
     | 
    
         
            +
                                           "index"
         
     | 
| 
      
 62 
     | 
    
         
            +
                                         else
         
     | 
| 
      
 63 
     | 
    
         
            +
                                           "unknown"
         
     | 
| 
      
 64 
     | 
    
         
            +
                                         end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  def set_focus_mode
         
     | 
| 
      
 68 
     | 
    
         
            +
                    @focus_mode = true
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
       52 
71 
     | 
    
         
             
                  def project
         
     | 
| 
       53 
72 
     | 
    
         
             
                    @project ||= budget&.projects&.find_by(id: params[:project_id])
         
     | 
| 
       54 
73 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -8,6 +8,8 @@ module Decidim 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                  helper_method :pending_to_vote_budgets
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
                  before_action :set_focus_mode_if_voting_open
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       11 
13 
     | 
    
         
             
                  def checkout
         
     | 
| 
       12 
14 
     | 
    
         
             
                    enforce_permission_to :vote, :project, order: current_order, budget:, workflow: current_workflow
         
     | 
| 
       13 
15 
     | 
    
         | 
| 
         @@ -41,12 +43,30 @@ module Decidim 
     | 
|
| 
       41 
43 
     | 
    
         
             
                    redirect_to redirect_path unless current_order.persisted?
         
     | 
| 
       42 
44 
     | 
    
         
             
                  end
         
     | 
| 
       43 
45 
     | 
    
         | 
| 
      
 46 
     | 
    
         
            +
                  def export_pdf
         
     | 
| 
      
 47 
     | 
    
         
            +
                    enforce_permission_to :export_pdf, :order, order: current_order
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    pdf_export = Decidim::Budgets::OrderPDF.new(current_order).render
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    output = if pdf_signature_service
         
     | 
| 
      
 52 
     | 
    
         
            +
                               pdf_signature_service.new(pdf: pdf_export.read).signed_pdf
         
     | 
| 
      
 53 
     | 
    
         
            +
                             else
         
     | 
| 
      
 54 
     | 
    
         
            +
                               pdf_export.read
         
     | 
| 
      
 55 
     | 
    
         
            +
                             end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    send_data output, filename: "order_#{current_order.id}.pdf", type: "application/pdf"
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
       44 
60 
     | 
    
         
             
                  private
         
     | 
| 
       45 
61 
     | 
    
         | 
| 
       46 
62 
     | 
    
         
             
                  def budget
         
     | 
| 
       47 
63 
     | 
    
         
             
                    @budget ||= Budget.find_by(id: params[:budget_id], component: current_component)
         
     | 
| 
       48 
64 
     | 
    
         
             
                  end
         
     | 
| 
       49 
65 
     | 
    
         | 
| 
      
 66 
     | 
    
         
            +
                  def pdf_signature_service
         
     | 
| 
      
 67 
     | 
    
         
            +
                    @pdf_signature_service ||= Decidim.pdf_signature_service.to_s.safe_constantize
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       50 
70 
     | 
    
         
             
                  def redirect_path
         
     | 
| 
       51 
71 
     | 
    
         
             
                    if params[:return_to] == "budget"
         
     | 
| 
       52 
72 
     | 
    
         
             
                      budget_path(budget)
         
     | 
| 
         @@ -9,7 +9,9 @@ module Decidim 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  include Decidim::Budgets::Orderable
         
     | 
| 
       10 
10 
     | 
    
         
             
                  include Decidim::IconHelper
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                  helper_method :projects, :project, :budget, :all_geocoded_projects, :tabs, :panels
         
     | 
| 
      
 12 
     | 
    
         
            +
                  helper_method :projects, :project, :budget, :all_geocoded_projects, :tabs, :panels, :resource_added?
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  before_action :set_focus_mode_if_voting_open
         
     | 
| 
       13 
15 
     | 
    
         | 
| 
       14 
16 
     | 
    
         
             
                  def index
         
     | 
| 
       15 
17 
     | 
    
         
             
                    raise ActionController::RoutingError, "Not Found" unless budget
         
     | 
| 
         @@ -7,42 +7,16 @@ module Decidim 
     | 
|
| 
       7 
7 
     | 
    
         
             
                  # to a participatory process from the admin panel.
         
     | 
| 
       8 
8 
     | 
    
         
             
                  #
         
     | 
| 
       9 
9 
     | 
    
         
             
                  class ComponentForm < Decidim::Admin::ComponentForm
         
     | 
| 
       10 
     | 
    
         
            -
                    validate : 
     | 
| 
       11 
     | 
    
         
            -
                             :budget_voting_rule_threshold_value_setting,
         
     | 
| 
      
 10 
     | 
    
         
            +
                    validate :budget_voting_rule_threshold_value_setting,
         
     | 
| 
       12 
11 
     | 
    
         
             
                             :budget_voting_rule_minimum_value_setting,
         
     | 
| 
       13 
12 
     | 
    
         
             
                             :budget_voting_rule_projects_value_setting
         
     | 
| 
       14 
13 
     | 
    
         | 
| 
       15 
14 
     | 
    
         
             
                    private
         
     | 
| 
       16 
15 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                    # Validations on budget settings:
         
     | 
| 
       18 
     | 
    
         
            -
                    # - a voting rule must be enabled.
         
     | 
| 
       19 
     | 
    
         
            -
                    def budget_voting_rule_enabled_setting
         
     | 
| 
       20 
     | 
    
         
            -
                      return unless manifest&.name == :budgets
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                      rule_settings = [
         
     | 
| 
       23 
     | 
    
         
            -
                        :vote_rule_threshold_percent_enabled,
         
     | 
| 
       24 
     | 
    
         
            -
                        :vote_rule_minimum_budget_projects_enabled,
         
     | 
| 
       25 
     | 
    
         
            -
                        :vote_rule_selected_projects_enabled
         
     | 
| 
       26 
     | 
    
         
            -
                      ]
         
     | 
| 
       27 
     | 
    
         
            -
                      active_rules = rule_settings.select { |key| settings.public_send(key) == true }
         
     | 
| 
       28 
     | 
    
         
            -
                      i18n_error_scope = "decidim.components.budgets.settings.global.form.errors"
         
     | 
| 
       29 
     | 
    
         
            -
                      if active_rules.blank?
         
     | 
| 
       30 
     | 
    
         
            -
                        rule_settings.each do |key|
         
     | 
| 
       31 
     | 
    
         
            -
                          settings.errors.add(key, I18n.t(:budget_voting_rule_required, scope: i18n_error_scope))
         
     | 
| 
       32 
     | 
    
         
            -
                        end
         
     | 
| 
       33 
     | 
    
         
            -
                      end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                      if active_rules.length > 1
         
     | 
| 
       36 
     | 
    
         
            -
                        rule_settings.each do |key|
         
     | 
| 
       37 
     | 
    
         
            -
                          settings.errors.add(key, I18n.t(:budget_voting_rule_only_one, scope: i18n_error_scope))
         
     | 
| 
       38 
     | 
    
         
            -
                        end
         
     | 
| 
       39 
     | 
    
         
            -
                      end
         
     | 
| 
       40 
     | 
    
         
            -
                    end
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
16 
     | 
    
         
             
                    # - the value must be a valid number
         
     | 
| 
       43 
17 
     | 
    
         
             
                    def budget_voting_rule_threshold_value_setting
         
     | 
| 
       44 
18 
     | 
    
         
             
                      return unless manifest&.name == :budgets
         
     | 
| 
       45 
     | 
    
         
            -
                      return unless settings. 
     | 
| 
      
 19 
     | 
    
         
            +
                      return unless settings.voting_rule == "threshold_percent"
         
     | 
| 
       46 
20 
     | 
    
         | 
| 
       47 
21 
     | 
    
         
             
                      invalid_percent_number = settings.vote_threshold_percent.blank? || settings.vote_threshold_percent.to_i.negative?
         
     | 
| 
       48 
22 
     | 
    
         
             
                      settings.errors.add(:vote_threshold_percent) if invalid_percent_number
         
     | 
| 
         @@ -50,7 +24,7 @@ module Decidim 
     | 
|
| 
       50 
24 
     | 
    
         | 
| 
       51 
25 
     | 
    
         
             
                    def budget_voting_rule_minimum_value_setting
         
     | 
| 
       52 
26 
     | 
    
         
             
                      return unless manifest&.name == :budgets
         
     | 
| 
       53 
     | 
    
         
            -
                      return unless settings. 
     | 
| 
      
 27 
     | 
    
         
            +
                      return unless settings.voting_rule == "minimum_projects"
         
     | 
| 
       54 
28 
     | 
    
         | 
| 
       55 
29 
     | 
    
         
             
                      invalid_minimum_number = settings.vote_minimum_budget_projects_number.blank? || (settings.vote_minimum_budget_projects_number.to_i < 1)
         
     | 
| 
       56 
30 
     | 
    
         
             
                      settings.errors.add(:vote_minimum_budget_projects_number) if invalid_minimum_number
         
     | 
| 
         @@ -58,7 +32,7 @@ module Decidim 
     | 
|
| 
       58 
32 
     | 
    
         | 
| 
       59 
33 
     | 
    
         
             
                    def budget_voting_rule_projects_value_setting
         
     | 
| 
       60 
34 
     | 
    
         
             
                      return unless manifest&.name == :budgets
         
     | 
| 
       61 
     | 
    
         
            -
                      return unless settings. 
     | 
| 
      
 35 
     | 
    
         
            +
                      return unless settings.voting_rule == "selected_projects"
         
     | 
| 
       62 
36 
     | 
    
         | 
| 
       63 
37 
     | 
    
         
             
                      budget_voting_projects_value_setting_min
         
     | 
| 
       64 
38 
     | 
    
         
             
                      budget_voting_projects_value_setting_max
         
     | 
| 
         @@ -14,6 +14,13 @@ module Decidim 
     | 
|
| 
       14 
14 
     | 
    
         
             
                    number_to_currency budget, unit: Decidim.currency_unit, precision: 0
         
     | 
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
      
 17 
     | 
    
         
            +
                  # Render a budget as a currency with the HTML format
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # budget - A integer to represent a budget
         
     | 
| 
      
 20 
     | 
    
         
            +
                  def budget_to_currency_with_html(budget)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    number_to_currency(budget, unit: Decidim.currency_unit, precision: 0, format: t("number.currency.format.format_html"))
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
       17 
24 
     | 
    
         
             
                  # Return a percentage of the current order budget from the total budget
         
     | 
| 
       18 
25 
     | 
    
         
             
                  def current_order_budget_percent
         
     | 
| 
       19 
26 
     | 
    
         
             
                    current_order&.budget_percent.to_f.floor
         
     | 
| 
         @@ -56,13 +63,7 @@ module Decidim 
     | 
|
| 
       56 
63 
     | 
    
         
             
                  def current_rule_call_for_action_text
         
     | 
| 
       57 
64 
     | 
    
         
             
                    return "" unless current_order
         
     | 
| 
       58 
65 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
                    if current_order_minimum_reached?
         
     | 
| 
       60 
     | 
    
         
            -
                      t("minimum_reached", scope: "decidim.budgets.projects.order_progress.dynamic_help")
         
     | 
| 
       61 
     | 
    
         
            -
                    elsif current_order.projects.empty?
         
     | 
| 
       62 
     | 
    
         
            -
                      t("start_adding_projects", scope: "decidim.budgets.projects.order_progress.dynamic_help")
         
     | 
| 
       63 
     | 
    
         
            -
                    else
         
     | 
| 
       64 
     | 
    
         
            -
                      t("keep_adding_projects", scope: "decidim.budgets.projects.order_progress.dynamic_help")
         
     | 
| 
       65 
     | 
    
         
            -
                    end
         
     | 
| 
      
 66 
     | 
    
         
            +
                    t("minimum_reached", scope: "decidim.budgets.projects.order_progress.dynamic_help") if current_order_minimum_reached?
         
     | 
| 
       66 
67 
     | 
    
         
             
                  end
         
     | 
| 
       67 
68 
     | 
    
         | 
| 
       68 
69 
     | 
    
         
             
                  def current_rule_description
         
     | 
| 
         @@ -98,6 +99,9 @@ module Decidim 
     | 
|
| 
       98 
99 
     | 
    
         
             
                                    minimum_budget: budget_to_currency(current_order.minimum_budget)
         
     | 
| 
       99 
100 
     | 
    
         
             
                                  )
         
     | 
| 
       100 
101 
     | 
    
         
             
                                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    return rule_text.html_safe if current_rule_call_for_action_text.nil?
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
       101 
105 
     | 
    
         
             
                    %(<strong>#{current_rule_call_for_action_text}</strong>. #{rule_text}).html_safe
         
     | 
| 
       102 
106 
     | 
    
         
             
                  end
         
     | 
| 
       103 
107 
     | 
    
         | 
| 
         @@ -132,14 +132,14 @@ module Decidim 
     | 
|
| 
       132 
132 
     | 
    
         
             
                  def minimum_projects_rule?
         
     | 
| 
       133 
133 
     | 
    
         
             
                    return unless budget
         
     | 
| 
       134 
134 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
                    budget.settings. 
     | 
| 
      
 135 
     | 
    
         
            +
                    budget.settings.voting_rule == "minimum_projects"
         
     | 
| 
       136 
136 
     | 
    
         
             
                  end
         
     | 
| 
       137 
137 
     | 
    
         | 
| 
       138 
138 
     | 
    
         
             
                  # Public: Returns true if the project voting rule is enabled
         
     | 
| 
       139 
139 
     | 
    
         
             
                  def projects_rule?
         
     | 
| 
       140 
140 
     | 
    
         
             
                    return unless budget
         
     | 
| 
       141 
141 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
                    budget.settings. 
     | 
| 
      
 142 
     | 
    
         
            +
                    budget.settings.voting_rule == "selected_projects"
         
     | 
| 
       143 
143 
     | 
    
         
             
                  end
         
     | 
| 
       144 
144 
     | 
    
         | 
| 
       145 
145 
     | 
    
         
             
                  # Public: Returns the required minimum projects to checkout
         
     | 
| 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            /* eslint-disable no-invalid-this */
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
      
 2 
     | 
    
         
            +
            document.addEventListener("turbo:load", () => {
         
     | 
| 
       3 
3 
     | 
    
         
             
              const selectedResourcesCount = () => {
         
     | 
| 
       4 
4 
     | 
    
         
             
                return $(".table-list .js-check-all-resources:checked").length
         
     | 
| 
       5 
5 
     | 
    
         
             
              }
         
     | 
| 
         @@ -72,7 +72,7 @@ $(() => { 
     | 
|
| 
       72 
72 
     | 
    
         
             
                hideBulkActionForms();
         
     | 
| 
       73 
73 
     | 
    
         
             
                $("#js-bulk-actions-button").addClass("hide");
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
                $("#js-bulk-actions-dropdown  
     | 
| 
      
 75 
     | 
    
         
            +
                $("#js-bulk-actions-dropdown li button").on("click", (event) => {
         
     | 
| 
       76 
76 
     | 
    
         
             
                  event.preventDefault();
         
     | 
| 
       77 
77 
     | 
    
         
             
                  let action = $(event.target).data("action");
         
     | 
| 
       78 
78 
     | 
    
         | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            document.addEventListener("turbo:load", () => {
         
     | 
| 
      
 2 
     | 
    
         
            +
              const toggleBackdrop = () => {
         
     | 
| 
      
 3 
     | 
    
         
            +
                const progressSummaryButton = document.getElementById("progress-summary-button");
         
     | 
| 
      
 4 
     | 
    
         
            +
                const backdrop = document.getElementById("progress-summary-backdrop");
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                if (!progressSummaryButton || !backdrop) {
         
     | 
| 
      
 7 
     | 
    
         
            +
                  return;
         
     | 
| 
      
 8 
     | 
    
         
            +
                }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                const isOpen = progressSummaryButton.getAttribute("aria-expanded") === "true";
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                backdrop.classList.toggle("hidden", !isOpen);
         
     | 
| 
      
 13 
     | 
    
         
            +
              }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              const setupBackdrop = () => {
         
     | 
| 
      
 16 
     | 
    
         
            +
                const progressSummaryButton = document.getElementById("progress-summary-button");
         
     | 
| 
      
 17 
     | 
    
         
            +
                const backdrop = document.getElementById("progress-summary-backdrop");
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                if (!progressSummaryButton || !backdrop) {
         
     | 
| 
      
 20 
     | 
    
         
            +
                  return;
         
     | 
| 
      
 21 
     | 
    
         
            +
                }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                progressSummaryButton.addEventListener("click", toggleBackdrop);
         
     | 
| 
      
 24 
     | 
    
         
            +
                backdrop.addEventListener("click", () => {
         
     | 
| 
      
 25 
     | 
    
         
            +
                  backdrop.classList.add("hidden");
         
     | 
| 
      
 26 
     | 
    
         
            +
                });
         
     | 
| 
      
 27 
     | 
    
         
            +
              }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              const removeStartVotingParam = () => {
         
     | 
| 
      
 30 
     | 
    
         
            +
                const url = new URL(window.location.href);
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                url.searchParams.delete("start_voting");
         
     | 
| 
      
 33 
     | 
    
         
            +
                window.history.replaceState({}, "", url);
         
     | 
| 
      
 34 
     | 
    
         
            +
              }
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              toggleBackdrop();
         
     | 
| 
      
 37 
     | 
    
         
            +
              setupBackdrop();
         
     | 
| 
      
 38 
     | 
    
         
            +
              removeStartVotingParam();
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              window.DecidimBudgets.toggleBackdrop = toggleBackdrop;
         
     | 
| 
      
 41 
     | 
    
         
            +
            });
         
     | 
| 
         @@ -47,7 +47,7 @@ const allowExitFrom = ($el) => { 
     | 
|
| 
       47 
47 
     | 
    
         
             
              return false;
         
     | 
| 
       48 
48 
     | 
    
         
             
            }
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
      
 50 
     | 
    
         
            +
            document.addEventListener("turbo:load", () => {
         
     | 
| 
       51 
51 
     | 
    
         
             
              const $exitNotification = $("#exit-notification");
         
     | 
| 
       52 
52 
     | 
    
         
             
              const $exitLink = $("#exit-notification-link");
         
     | 
| 
       53 
53 
     | 
    
         
             
              const defaultExitUrl = $exitLink.attr("href");
         
     | 
| 
         @@ -90,7 +90,12 @@ $(() => { 
     | 
|
| 
       90 
90 
     | 
    
         
             
                event.stopPropagation();
         
     | 
| 
       91 
91 
     | 
    
         | 
| 
       92 
92 
     | 
    
         
             
                const $link = $(event.currentTarget);
         
     | 
| 
       93 
     | 
    
         
            -
                 
     | 
| 
      
 93 
     | 
    
         
            +
                const linkText = $link.text();
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                if (linkText.length > 0) {
         
     | 
| 
      
 96 
     | 
    
         
            +
                  exitLinkText = linkText;
         
     | 
| 
      
 97 
     | 
    
         
            +
                }
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       94 
99 
     | 
    
         
             
                openExitNotification($link.attr("href"), $link.data("method"));
         
     | 
| 
       95 
100 
     | 
    
         
             
              });
         
     | 
| 
       96 
101 
     | 
    
         
             
              // Custom handling for the exit link which needs to change the exit link
         
     | 
| 
         @@ -1,11 +1,11 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            .budget {
         
     | 
| 
       2 
2 
     | 
    
         
             
              &-list__map {
         
     | 
| 
       3 
     | 
    
         
            -
                @apply  
     | 
| 
      
 3 
     | 
    
         
            +
                @apply lg:-ml-16 -mt-6 lg:-mt-12 mb-6 aspect-square lg:aspect-[21/9] [&>*]:h-full [&+*]:mt-6 lg:[&+*]:mt-12;
         
     | 
| 
       4 
4 
     | 
    
         
             
              }
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
              &-summary {
         
     | 
| 
       7 
7 
     | 
    
         
             
                &__content {
         
     | 
| 
       8 
     | 
    
         
            -
                  @apply bg-tertiary p-4  
     | 
| 
      
 8 
     | 
    
         
            +
                  @apply bg-tertiary p-4 lg:h-full lg:p-0;
         
     | 
| 
       9 
9 
     | 
    
         
             
                }
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                &__container {
         
     | 
| 
         @@ -33,7 +33,7 @@ 
     | 
|
| 
       33 
33 
     | 
    
         
             
                }
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
                &__progressbar {
         
     | 
| 
       36 
     | 
    
         
            -
                  @apply my-0  
     | 
| 
      
 36 
     | 
    
         
            +
                  @apply my-0 xl:my-4 relative;
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
       38 
38 
     | 
    
         
             
                  .budget-progress {
         
     | 
| 
       39 
39 
     | 
    
         
             
                    @apply bg-white rounded h-2;
         
     | 
| 
         @@ -57,48 +57,60 @@ 
     | 
|
| 
       57 
57 
     | 
    
         
             
                }
         
     | 
| 
       58 
58 
     | 
    
         | 
| 
       59 
59 
     | 
    
         
             
                &__progressbar-marks_right {
         
     | 
| 
       60 
     | 
    
         
            -
                  @apply justify-self-end text-left  
     | 
| 
      
 60 
     | 
    
         
            +
                  @apply justify-self-end text-left lg:text-right;
         
     | 
| 
       61 
61 
     | 
    
         
             
                }
         
     | 
| 
       62 
62 
     | 
    
         | 
| 
       63 
63 
     | 
    
         
             
                &__progressbar-legend {
         
     | 
| 
       64 
     | 
    
         
            -
                  @apply text-xs  
     | 
| 
      
 64 
     | 
    
         
            +
                  @apply text-xs lg:text-sm block;
         
     | 
| 
       65 
65 
     | 
    
         
             
                }
         
     | 
| 
       66 
66 
     | 
    
         | 
| 
       67 
67 
     | 
    
         
             
                &__progressbar-legend-strong {
         
     | 
| 
       68 
     | 
    
         
            -
                  @apply font-semibold block text-[10px]  
     | 
| 
      
 68 
     | 
    
         
            +
                  @apply font-semibold block text-[10px] lg:text-sm text-nowrap;
         
     | 
| 
       69 
69 
     | 
    
         
             
                }
         
     | 
| 
       70 
70 
     | 
    
         
             
              }
         
     | 
| 
       71 
71 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
              & 
     | 
| 
       73 
     | 
    
         
            -
                @apply - 
     | 
| 
      
 72 
     | 
    
         
            +
              &__card__list-budget--highlighted {
         
     | 
| 
      
 73 
     | 
    
         
            +
                @apply ring-warning;
         
     | 
| 
      
 74 
     | 
    
         
            +
              }
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              &__card__list-budget--progress {
         
     | 
| 
      
 77 
     | 
    
         
            +
                @apply ring-warning;
         
     | 
| 
      
 78 
     | 
    
         
            +
              }
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              &__card__list-budget--voted {
         
     | 
| 
      
 81 
     | 
    
         
            +
                @apply ring-success;
         
     | 
| 
       74 
82 
     | 
    
         
             
              }
         
     | 
| 
       75 
83 
     | 
    
         | 
| 
       76 
84 
     | 
    
         
             
              &__card__list-project {
         
     | 
| 
       77 
     | 
    
         
            -
                @apply ml-auto rounded py-3 px-4 bg-background w- 
     | 
| 
      
 85 
     | 
    
         
            +
                @apply ml-auto rounded py-3 px-4 bg-background w-64 md:w-96 flex flex-col justify-center items-center xl:flex-row xl:justify-between xl:place-items-center;
         
     | 
| 
       78 
86 
     | 
    
         
             
              }
         
     | 
| 
       79 
87 
     | 
    
         | 
| 
       80 
88 
     | 
    
         
             
              &__card__list-project__amount {
         
     | 
| 
       81 
     | 
    
         
            -
                @apply font-semibold text-gray-2 text-xl inline-block  
     | 
| 
      
 89 
     | 
    
         
            +
                @apply font-semibold text-gray-2 text-xl inline-block m-auto;
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                span {
         
     | 
| 
      
 92 
     | 
    
         
            +
                  @apply text-md;
         
     | 
| 
      
 93 
     | 
    
         
            +
                }
         
     | 
| 
       82 
94 
     | 
    
         
             
              }
         
     | 
| 
       83 
95 
     | 
    
         | 
| 
       84 
96 
     | 
    
         
             
              &__card__highlight-vote {
         
     | 
| 
       85 
     | 
    
         
            -
                @apply justify-center flex  
     | 
| 
      
 97 
     | 
    
         
            +
                @apply justify-center flex w-full xl:w-2/5 items-center bg-background p-4 bg-background font-bold text-gray-2 ml-auto;
         
     | 
| 
       86 
98 
     | 
    
         
             
              }
         
     | 
| 
       87 
99 
     | 
    
         | 
| 
       88 
100 
     | 
    
         
             
              &__card__highlight-vote__header {
         
     | 
| 
       89 
     | 
    
         
            -
                @apply place-items-start  
     | 
| 
       90 
     | 
    
         
            -
              }
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
              &__card__highlight-vote__text {
         
     | 
| 
       93 
     | 
    
         
            -
                @apply block text-sm text-gray-2 font-normal;
         
     | 
| 
      
 101 
     | 
    
         
            +
                @apply place-items-start w-1/3;
         
     | 
| 
       94 
102 
     | 
    
         
             
              }
         
     | 
| 
       95 
103 
     | 
    
         | 
| 
       96 
104 
     | 
    
         
             
              &__card__highlight-vote__number {
         
     | 
| 
       97 
105 
     | 
    
         
             
                @apply text-xl font-semibold;
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                span {
         
     | 
| 
      
 108 
     | 
    
         
            +
                  @apply text-sm;
         
     | 
| 
      
 109 
     | 
    
         
            +
                }
         
     | 
| 
       98 
110 
     | 
    
         
             
              }
         
     | 
| 
       99 
111 
     | 
    
         | 
| 
       100 
112 
     | 
    
         
             
              &__card__highlight-vote__button {
         
     | 
| 
       101 
     | 
    
         
            -
                @apply mt-auto text-left 
     | 
| 
      
 113 
     | 
    
         
            +
                @apply mt-auto text-left;
         
     | 
| 
       102 
114 
     | 
    
         | 
| 
       103 
115 
     | 
    
         
             
                &.button__secondary:hover {
         
     | 
| 
       104 
116 
     | 
    
         
             
                  @apply text-white #{!important};
         
     | 
| 
         @@ -118,11 +130,15 @@ 
     | 
|
| 
       118 
130 
     | 
    
         
             
              }
         
     | 
| 
       119 
131 
     | 
    
         | 
| 
       120 
132 
     | 
    
         
             
              &__definition-data__title {
         
     | 
| 
       121 
     | 
    
         
            -
                @apply text-sm text-gray-2  
     | 
| 
      
 133 
     | 
    
         
            +
                @apply text-sm text-gray-2 mb-2 block;
         
     | 
| 
       122 
134 
     | 
    
         
             
              }
         
     | 
| 
       123 
135 
     | 
    
         | 
| 
       124 
136 
     | 
    
         
             
              &__definition-data__number {
         
     | 
| 
       125 
137 
     | 
    
         
             
                @apply text-gray-2 font-bold text-3xl bg-background text-center p-2 rounded;
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                span {
         
     | 
| 
      
 140 
     | 
    
         
            +
                  @apply text-2xl;
         
     | 
| 
      
 141 
     | 
    
         
            +
                }
         
     | 
| 
       126 
142 
     | 
    
         
             
              }
         
     | 
| 
       127 
143 
     | 
    
         | 
| 
       128 
144 
     | 
    
         
             
              &__filter-title {
         
     | 
| 
         @@ -134,7 +150,7 @@ 
     | 
|
| 
       134 
150 
     | 
    
         
             
              }
         
     | 
| 
       135 
151 
     | 
    
         | 
| 
       136 
152 
     | 
    
         
             
              &__list--header {
         
     | 
| 
       137 
     | 
    
         
            -
                @apply flex items-center justify-between 
     | 
| 
      
 153 
     | 
    
         
            +
                @apply flex items-center justify-between;
         
     | 
| 
       138 
154 
     | 
    
         
             
              }
         
     | 
| 
       139 
155 
     | 
    
         | 
| 
       140 
156 
     | 
    
         
             
              &-list {
         
     | 
| 
         @@ -159,6 +175,10 @@ 
     | 
|
| 
       159 
175 
     | 
    
         | 
| 
       160 
176 
     | 
    
         
             
                  .card__list {
         
     | 
| 
       161 
177 
     | 
    
         
             
                    @apply inline-block w-[65%];
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                    &-metadata span {
         
     | 
| 
      
 180 
     | 
    
         
            +
                      @apply text-xs;
         
     | 
| 
      
 181 
     | 
    
         
            +
                    }
         
     | 
| 
       162 
182 
     | 
    
         
             
                  }
         
     | 
| 
       163 
183 
     | 
    
         | 
| 
       164 
184 
     | 
    
         
             
                  + .project-item {
         
     | 
| 
         @@ -170,7 +190,7 @@ 
     | 
|
| 
       170 
190 
     | 
    
         | 
| 
       171 
191 
     | 
    
         
             
            #budgets-to-vote {
         
     | 
| 
       172 
192 
     | 
    
         
             
              .card__highlight-text {
         
     | 
| 
       173 
     | 
    
         
            -
                @apply w-full  
     | 
| 
      
 193 
     | 
    
         
            +
                @apply w-full lg:w-[70%] p-0;
         
     | 
| 
       174 
194 
     | 
    
         
             
              }
         
     | 
| 
       175 
195 
     | 
    
         | 
| 
       176 
196 
     | 
    
         
             
              .order-by {
         
     | 
| 
         @@ -179,7 +199,7 @@ 
     | 
|
| 
       179 
199 
     | 
    
         
             
            }
         
     | 
| 
       180 
200 
     | 
    
         | 
| 
       181 
201 
     | 
    
         
             
            .verification-modal .card__list .budget__card__list-project {
         
     | 
| 
       182 
     | 
    
         
            -
              @apply inline-block w- 
     | 
| 
      
 202 
     | 
    
         
            +
              @apply inline-block w-80 sm:w-48 text-center;
         
     | 
| 
       183 
203 
     | 
    
         
             
            }
         
     | 
| 
       184 
204 
     | 
    
         | 
| 
       185 
205 
     | 
    
         
             
            #budgets.card__highlight-container {
         
     | 
| 
         @@ -187,7 +207,7 @@ 
     | 
|
| 
       187 
207 
     | 
    
         
             
            }
         
     | 
| 
       188 
208 
     | 
    
         | 
| 
       189 
209 
     | 
    
         
             
            .progressbox-fixed-wrapper {
         
     | 
| 
       190 
     | 
    
         
            -
              @apply bg-tertiary fixed hidden inset-x-0 inset-y-0 h-max z- 
     | 
| 
      
 210 
     | 
    
         
            +
              @apply bg-tertiary fixed hidden inset-x-0 inset-y-0 h-max z-40;
         
     | 
| 
       191 
211 
     | 
    
         | 
| 
       192 
212 
     | 
    
         
             
              box-shadow: 0 4px 6px 0 rgba(211, 211, 211, 0.25);
         
     | 
| 
       193 
213 
     | 
    
         
             
            }
         
     | 
| 
         @@ -209,27 +229,27 @@ 
     | 
|
| 
       209 
229 
     | 
    
         
             
            }
         
     | 
| 
       210 
230 
     | 
    
         | 
| 
       211 
231 
     | 
    
         
             
            .budget-summary__progressbox--checked_out {
         
     | 
| 
       212 
     | 
    
         
            -
              @apply hidden  
     | 
| 
      
 232 
     | 
    
         
            +
              @apply hidden lg:block;
         
     | 
| 
       213 
233 
     | 
    
         
             
            }
         
     | 
| 
       214 
234 
     | 
    
         | 
| 
       215 
235 
     | 
    
         
             
            .budget-summary__content {
         
     | 
| 
       216 
     | 
    
         
            -
              @apply  
     | 
| 
      
 236 
     | 
    
         
            +
              @apply lg:grid lg:grid-cols-12 lg:items-center lg:px-16 pt-4 px-4;
         
     | 
| 
       217 
237 
     | 
    
         
             
            }
         
     | 
| 
       218 
238 
     | 
    
         | 
| 
       219 
239 
     | 
    
         
             
            .budget-summary__progressbox {
         
     | 
| 
       220 
     | 
    
         
            -
              @apply  
     | 
| 
      
 240 
     | 
    
         
            +
              @apply lg:col-span-8;
         
     | 
| 
       221 
241 
     | 
    
         
             
            }
         
     | 
| 
       222 
242 
     | 
    
         | 
| 
       223 
243 
     | 
    
         
             
            .budget-summary__progressbox-buttons {
         
     | 
| 
       224 
     | 
    
         
            -
              @apply  
     | 
| 
      
 244 
     | 
    
         
            +
              @apply lg:col-span-3 lg:col-start-10;
         
     | 
| 
       225 
245 
     | 
    
         
             
            }
         
     | 
| 
       226 
246 
     | 
    
         | 
| 
       227 
247 
     | 
    
         
             
            .budget-summary__button-modal {
         
     | 
| 
       228 
     | 
    
         
            -
              @apply hidden  
     | 
| 
      
 248 
     | 
    
         
            +
              @apply hidden xl:text-secondary xl:block xl:col-span-12 xl:mb-4 xl:pb-4;
         
     | 
| 
       229 
249 
     | 
    
         
             
            }
         
     | 
| 
       230 
250 
     | 
    
         | 
| 
       231 
251 
     | 
    
         
             
            .budget-summary__button-dropdown {
         
     | 
| 
       232 
     | 
    
         
            -
              @apply col-span-12 text-secondary  
     | 
| 
      
 252 
     | 
    
         
            +
              @apply col-span-12 text-secondary xl:hidden;
         
     | 
| 
       233 
253 
     | 
    
         | 
| 
       234 
254 
     | 
    
         
             
              &_text {
         
     | 
| 
       235 
255 
     | 
    
         
             
                @apply flex gap-4 justify-start;
         
     | 
| 
         @@ -246,42 +266,42 @@ 
     | 
|
| 
       246 
266 
     | 
    
         | 
| 
       247 
267 
     | 
    
         
             
            .progressbox-fixed-wrapper {
         
     | 
| 
       248 
268 
     | 
    
         
             
              .budget-summary__progressbar {
         
     | 
| 
       249 
     | 
    
         
            -
                @apply  
     | 
| 
      
 269 
     | 
    
         
            +
                @apply lg:pl-32 lg:pr-8;
         
     | 
| 
       250 
270 
     | 
    
         
             
              }
         
     | 
| 
       251 
271 
     | 
    
         | 
| 
       252 
272 
     | 
    
         
             
              .budget-summary__progressbox {
         
     | 
| 
       253 
     | 
    
         
            -
                @apply  
     | 
| 
      
 273 
     | 
    
         
            +
                @apply lg:col-span-5 lg:col-start-4;
         
     | 
| 
       254 
274 
     | 
    
         
             
              }
         
     | 
| 
       255 
275 
     | 
    
         | 
| 
       256 
276 
     | 
    
         
             
              .budget-summary__progressbox-buttons {
         
     | 
| 
       257 
     | 
    
         
            -
                @apply  
     | 
| 
      
 277 
     | 
    
         
            +
                @apply lg:col-start-10 lg:col-span-2;
         
     | 
| 
       258 
278 
     | 
    
         
             
              }
         
     | 
| 
       259 
279 
     | 
    
         
             
            }
         
     | 
| 
       260 
280 
     | 
    
         | 
| 
       261 
281 
     | 
    
         
             
            #project-item {
         
     | 
| 
       262 
282 
     | 
    
         
             
              .budget-summary__content {
         
     | 
| 
       263 
     | 
    
         
            -
                @apply py-4  
     | 
| 
      
 283 
     | 
    
         
            +
                @apply py-4 lg:py-4 lg:container lg:grid grid-cols-1 lg:grid-cols-12 lg:items-center;
         
     | 
| 
       264 
284 
     | 
    
         
             
              }
         
     | 
| 
       265 
285 
     | 
    
         | 
| 
       266 
286 
     | 
    
         
             
              .budget-summary__progressbox {
         
     | 
| 
       267 
     | 
    
         
            -
                @apply  
     | 
| 
      
 287 
     | 
    
         
            +
                @apply lg:col-start-2 lg:col-span-7 relative;
         
     | 
| 
       268 
288 
     | 
    
         
             
              }
         
     | 
| 
       269 
289 
     | 
    
         | 
| 
       270 
290 
     | 
    
         
             
              .budget-summary__progressbox-buttons {
         
     | 
| 
       271 
     | 
    
         
            -
                @apply  
     | 
| 
      
 291 
     | 
    
         
            +
                @apply lg:col-start-10 lg:col-span-2;
         
     | 
| 
       272 
292 
     | 
    
         
             
              }
         
     | 
| 
       273 
293 
     | 
    
         | 
| 
       274 
294 
     | 
    
         
             
              .budget-summary__button-modal {
         
     | 
| 
       275 
     | 
    
         
            -
                @apply hidden  
     | 
| 
      
 295 
     | 
    
         
            +
                @apply hidden xl:text-secondary xl:block xl:col-span-10 xl:col-start-2 xl:justify-start;
         
     | 
| 
       276 
296 
     | 
    
         
             
              }
         
     | 
| 
       277 
297 
     | 
    
         | 
| 
       278 
298 
     | 
    
         
             
              .budget-summary__button-dropdown {
         
     | 
| 
       279 
     | 
    
         
            -
                @apply block text-secondary col-span-10 col-start-2 justify-start  
     | 
| 
      
 299 
     | 
    
         
            +
                @apply block text-secondary col-span-10 col-start-2 justify-start xl:hidden;
         
     | 
| 
       280 
300 
     | 
    
         
             
              }
         
     | 
| 
       281 
301 
     | 
    
         | 
| 
       282 
302 
     | 
    
         
             
              .progressbox-fixed-wrapper {
         
     | 
| 
       283 
303 
     | 
    
         
             
                .budget-summary__progressbar {
         
     | 
| 
       284 
     | 
    
         
            -
                  @apply  
     | 
| 
      
 304 
     | 
    
         
            +
                  @apply lg:col-start-1 lg:col-span-7;
         
     | 
| 
       285 
305 
     | 
    
         
             
                }
         
     | 
| 
       286 
306 
     | 
    
         
             
              }
         
     | 
| 
       287 
307 
     | 
    
         
             
            }
         
     | 
| 
         @@ -10,21 +10,19 @@ module Decidim 
     | 
|
| 
       10 
10 
     | 
    
         
             
                    return Decidim::Budgets::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
         
     | 
| 
       11 
11 
     | 
    
         
             
                    return permission_action if permission_action.scope != :public
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                     
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                       
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                       
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                       
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                       
     | 
| 
      
 13 
     | 
    
         
            +
                    case [permission_action.action, permission_action.subject]
         
     | 
| 
      
 14 
     | 
    
         
            +
                    when [:vote, :project]
         
     | 
| 
      
 15 
     | 
    
         
            +
                      can_vote?(false) if can_vote_project?(project || order&.projects&.first)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    when [:report, :project]
         
     | 
| 
      
 17 
     | 
    
         
            +
                      permission_action.allow!
         
     | 
| 
      
 18 
     | 
    
         
            +
                    when [:read, :project]
         
     | 
| 
      
 19 
     | 
    
         
            +
                      toggle_allow(project.visible?)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    when [:create, :order]
         
     | 
| 
      
 21 
     | 
    
         
            +
                      can_vote?(true)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    when [:export_pdf, :order]
         
     | 
| 
      
 23 
     | 
    
         
            +
                      can_export_pdf?
         
     | 
| 
       24 
24 
     | 
    
         
             
                    end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                    can_vote?(true) if permission_action.action == :create && permission_action.subject == :order
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
26 
     | 
    
         
             
                    permission_action
         
     | 
| 
       29 
27 
     | 
    
         
             
                  end
         
     | 
| 
       30 
28 
     | 
    
         | 
| 
         @@ -61,6 +59,12 @@ module Decidim 
     | 
|
| 
       61 
59 
     | 
    
         | 
| 
       62 
60 
     | 
    
         
             
                    toggle_allow(is_allowed)
         
     | 
| 
       63 
61 
     | 
    
         
             
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  def can_export_pdf?
         
     | 
| 
      
 64 
     | 
    
         
            +
                    is_allowed = order.user == user
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    toggle_allow(is_allowed)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
       64 
68 
     | 
    
         
             
                end
         
     | 
| 
       65 
69 
     | 
    
         
             
              end
         
     | 
| 
       66 
70 
     | 
    
         
             
            end
         
     | 
| 
         @@ -5,15 +5,13 @@ module Decidim 
     | 
|
| 
       5 
5 
     | 
    
         
             
                class ProjectPresenter < Decidim::ResourcePresenter
         
     | 
| 
       6 
6 
     | 
    
         
             
                  # Renders the title of the project
         
     | 
| 
       7 
7 
     | 
    
         
             
                  #
         
     | 
| 
       8 
     | 
    
         
            -
                  # @param links [Boolean] Should hashtags in the title be rendered as links? Default is +false+.
         
     | 
| 
       9 
     | 
    
         
            -
                  # @param extras [Boolean] Should extra hashtags be included? Default is +true+.
         
     | 
| 
       10 
8 
     | 
    
         
             
                  # @param html_escape [Boolean] Should HTML entities within the title be escaped? Default is +false+.
         
     | 
| 
       11 
9 
     | 
    
         
             
                  # @param all_locales [Boolean] Should the title be returned for all locales? Default is +false+.
         
     | 
| 
       12 
10 
     | 
    
         
             
                  # @return [String] The title of the project.
         
     | 
| 
       13 
     | 
    
         
            -
                  def title( 
     | 
| 
      
 11 
     | 
    
         
            +
                  def title(html_escape: false, all_locales: false)
         
     | 
| 
       14 
12 
     | 
    
         
             
                    return unless project
         
     | 
| 
       15 
13 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                    super(project.title,  
     | 
| 
      
 14 
     | 
    
         
            +
                    super(project.title, html_escape, all_locales)
         
     | 
| 
       17 
15 
     | 
    
         
             
                  end
         
     | 
| 
       18 
16 
     | 
    
         | 
| 
       19 
17 
     | 
    
         
             
                  delegate_missing_to :project
         
     |