diff --git a/decidim-budgets/app/cells/decidim/budgets/budget_information_modal/show.erb b/decidim-budgets/app/cells/decidim/budgets/budget_information_modal/show.erb index 26a8e819745d4..b96ec1457a990 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budget_information_modal/show.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budget_information_modal/show.erb @@ -1,28 +1,10 @@ - - -
-
-

<%= decidim_sanitize(component_name) %>

- -
- - <%= content_tag(:p, more_information) if more_information %> - - <% unless current_workflow.single? %> -

- <%= link_to t(:back_to, scope: i18n_scope, component_name: component_name), budgets_path %> -

- <% end %> - -
-
- -
+<% if more_information %> + + +
+ <%= content_tag(:p, more_information) %>
-
+<% end %> diff --git a/decidim-budgets/app/cells/decidim/budgets/budget_information_modal_cell.rb b/decidim-budgets/app/cells/decidim/budgets/budget_information_modal_cell.rb index 2e44153bc4072..66342a7b0280a 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budget_information_modal_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/budget_information_modal_cell.rb @@ -7,7 +7,7 @@ class BudgetInformationModalCell < BaseCell alias budget model def more_information - translated_attribute(current_settings.more_information_modal).presence || translated_attribute(settings.more_information_modal) + translated_attribute(current_settings.more_information_modal).presence || translated_attribute(settings.more_information_modal).presence end def component_name diff --git a/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb b/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb index 280ff42439b69..3ca9551171f8c 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb @@ -1,22 +1,38 @@ -
-
+
+
<%= link_to budget_path(budget), class: link_class do %> - <% if voted? && !voting_finished? %> - - <%= translated_attribute(title) %> - - - <%= icon "check", class: "icon--small", role: "img", aria_label: t("decidim.budgets.budget_list_item.voting_finished") %> - - <% else %> +
<%= translated_attribute(title) %> +
+ <% end %> + +
+ + <%= budget_to_currency(total_budget) %> + +
+ + <%= decidim_sanitize html_truncate(translated_attribute(description), length: 140) %> +
- <% if progress? && !voting_finished? %> - - <%= icon "bookmark", class: "icon--small", role: "img", aria_label: t("decidim.budgets.budget_list_item.voting_started") %> - - <% end %> + <% if !voting_finished? %> +
+ <% if voted? %> + + <%= icon "check", class: "icon--small", role: "img", aria_label: t("decidim.budgets.budget_list_item.voting_finished") %> + + <% elsif progress? %> + + <%= icon "bookmark", class: "icon--small", role: "img", aria_label: t("decidim.budgets.budget_list_item.voting_started") %> + <% end %> +
+ <% end %> + +
+ <%= link_to budget_path(budget), class: "button button--sc expanded #{button_class} mb-none" do %> + <%= button_text %> + <%= icon "chevron-right", class: "icon--small", role: "img" %> <% end %>
diff --git a/decidim-budgets/app/cells/decidim/budgets/budget_list_item_cell.rb b/decidim-budgets/app/cells/decidim/budgets/budget_list_item_cell.rb index 2716b347e418c..35e299f904d29 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budget_list_item_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/budget_list_item_cell.rb @@ -4,9 +4,14 @@ module Decidim module Budgets # This cell renders the budget item list in the budgets list class BudgetListItemCell < BaseCell + include Decidim::SanitizeHelper + include Decidim::ApplicationHelper + include Decidim::Budgets::ProjectsHelper + delegate :voting_finished?, to: :controller + delegate :highlighted, to: :current_workflow - property :title + property :title, :description, :total_budget alias budget model private @@ -17,6 +22,7 @@ def card_class list << "card--list__data-added" if voted? list << "card--list__data-progress" if progress? end + list << "budget--highlighted" if highlighted? end.join(" ") end @@ -32,9 +38,31 @@ def progress? current_user && status == :progress end + def highlighted? + highlighted.include?(budget) + end + def status @status ||= current_workflow.status(budget) end + + def button_class + "hollow" if voted? || !highlighted? + end + + def button_text + key = if current_workflow.vote_allowed?(budget) && !voted? + progress? ? :progress : :vote + else + :show + end + + t(key, scope: i18n_scope) + end + + def i18n_scope + "decidim.budgets.budgets_list" + end end end end diff --git a/decidim-budgets/app/cells/decidim/budgets/budget_m_cell.rb b/decidim-budgets/app/cells/decidim/budgets/budget_m_cell.rb index ab05907a4801f..244e1909c5dfd 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budget_m_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/budget_m_cell.rb @@ -5,7 +5,6 @@ module Budgets # This cell renders the Medium (:m) budget card # for an given instance of a Decidim::Budgets::Budget class BudgetMCell < Decidim::CardMCell - include ActiveSupport::NumberHelper include Decidim::Budgets::ProjectsHelper def statuses diff --git a/decidim-budgets/app/cells/decidim/budgets/budgets_header/show.erb b/decidim-budgets/app/cells/decidim/budgets/budgets_header/show.erb index 12fe6b4a64731..a881b59840962 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budgets_header/show.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budgets_header/show.erb @@ -1,7 +1,3 @@ -
-
-
- <%= decidim_sanitize(landing_page_content) %> -
-
+
+ <%= decidim_sanitize(landing_page_content) %>
diff --git a/decidim-budgets/app/cells/decidim/budgets/budgets_header_cell.rb b/decidim-budgets/app/cells/decidim/budgets/budgets_header_cell.rb index 0cabeaaa6e718..45710a6d0cc93 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budgets_header_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/budgets_header_cell.rb @@ -9,6 +9,10 @@ class BudgetsHeaderCell < BaseCell def landing_page_content translated_attribute(current_settings.landing_page_content).presence || translated_attribute(settings.landing_page_content) end + + def landing_page_instructions + translated_attribute(current_settings.landing_page_instructions).presence || translated_attribute(settings.landing_page_instructions) + end end end end diff --git a/decidim-budgets/app/cells/decidim/budgets/budgets_list/card_list.erb b/decidim-budgets/app/cells/decidim/budgets/budgets_list/card_list.erb index 8cbbe75b3a228..e22c514657368 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budgets_list/card_list.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budgets_list/card_list.erb @@ -1,7 +1,18 @@ -
- <% budgets.each do |budget| %> - <% next if highlighted.include?(budget) && !voting_finished? %> +<%# show highlighted budgets first %> +<% if highlighted.any? %> +
+ <% highlighted.each do |budget| %> + <%= cell("decidim/budgets/budget_list_item", budget) %> + <% end %> +
+<% end %> - <%= cell("decidim/budgets/budget_list_item", budget) %> - <% end %> -
+<% non_highlighted = (budgets - highlighted - voted) %> + +<% if non_highlighted.any? %> +
+ <% non_highlighted.each do |budget| %> + <%= cell("decidim/budgets/budget_list_item", budget) %> + <% end %> +
+<% end %> diff --git a/decidim-budgets/app/cells/decidim/budgets/budgets_list/highlighted.erb b/decidim-budgets/app/cells/decidim/budgets/budgets_list/highlighted.erb deleted file mode 100644 index e680002273126..0000000000000 --- a/decidim-budgets/app/cells/decidim/budgets/budgets_list/highlighted.erb +++ /dev/null @@ -1,11 +0,0 @@ -<% if highlighted? %> -

- <% highlighted.each do |budget| %> - <%= link_to( - t("highlighted_cta", scope: i18n_scope, - name: translated_attribute(budget.title)), - resource_locator(budget).path, - class: :button ) %> - <% end %> -

-<% end %> diff --git a/decidim-budgets/app/cells/decidim/budgets/budgets_list/show.erb b/decidim-budgets/app/cells/decidim/budgets/budgets_list/show.erb index 51d5a1ffa0054..3bfb8ff27de70 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budgets_list/show.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budgets_list/show.erb @@ -1,20 +1,15 @@ -
-
- <% if !voting_finished? && (highlighted? || voted?) %> -
-

- <%= t(:my_budgets, scope: i18n_scope) %> -

+<% if voted? %> +
+

+ <%= t(:my_budgets, scope: i18n_scope) %> +

- <%= render :highlighted %> - <%= render :voted %> -
- <% end %> + <%= render :voted %> +
+<% end %> -
-
- <%= render :card_list %> -
-
+
+
+ <%= render :card_list %>
diff --git a/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb b/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb index 0ca04f4acdef2..70efe6f7b0d9d 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb @@ -4,6 +4,12 @@ <%= t(:voted_on, scope: i18n_scope, links: budgets_link_list(voted)) %>

+
+ <% voted.each do |budget| %> + <%= cell("decidim/budgets/budget_list_item", budget) %> + <% end %> +
+ <% if finished? %>

<%= t(:finished_message, scope: i18n_scope) %> diff --git a/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_data.erb b/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_data.erb index 53abf5cf3d717..e6f3b53350d61 100644 --- a/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_data.erb +++ b/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_data.erb @@ -14,6 +14,6 @@ <%= cell("decidim/budgets/project_voted_hint", model, class: "display-block margin-top-1") if current_order_checked_out? && resource_added? %> - <%= render :project_data_vote_button if !current_order_checked_out? && voting_open? %> + <%= cell("decidim/budgets/project_vote_button", model) if !current_order_checked_out? && voting_open? %> <% end %>

diff --git a/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_text.erb b/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_text.erb index 6e4d5e7e61b93..bfb13f2bb9557 100644 --- a/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_text.erb +++ b/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_text.erb @@ -12,6 +12,12 @@ <%= cell "decidim/budgets/project_tags", model, context: { extra_classes: ["tags--project"] } %>
+ <% unless voting_finished? %> +
+ <%= budget_to_currency(model.budget_amount) %> +
+ <% end %> +
<%= cell("decidim/budgets/project_votes_count", model, diff --git a/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb b/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb index 2de429ae8de9c..222df75e40b7d 100644 --- a/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb @@ -5,7 +5,6 @@ module Budgets # This cell renders a horizontal project card # for an given instance of a Project in a budget list class ProjectListItemCell < Decidim::ViewModel - include ActiveSupport::NumberHelper include Decidim::LayoutHelper include Decidim::ActionAuthorizationHelper include Decidim::Budgets::ProjectsHelper diff --git a/decidim-budgets/app/cells/decidim/budgets/project_m_cell.rb b/decidim-budgets/app/cells/decidim/budgets/project_m_cell.rb index 71e70c6550552..e0a2cede5a1e6 100644 --- a/decidim-budgets/app/cells/decidim/budgets/project_m_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/project_m_cell.rb @@ -5,7 +5,6 @@ module Budgets # This cell renders the Medium (:m) project card # for an given instance of a Project class ProjectMCell < Decidim::CardMCell - include ActiveSupport::NumberHelper include Decidim::Budgets::ProjectsHelper private diff --git a/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_data_vote_button.erb b/decidim-budgets/app/cells/decidim/budgets/project_vote_button/show.erb similarity index 84% rename from decidim-budgets/app/cells/decidim/budgets/project_list_item/project_data_vote_button.erb rename to decidim-budgets/app/cells/decidim/budgets/project_vote_button/show.erb index b2b13e701ebb9..523ac38479849 100644 --- a/decidim-budgets/app/cells/decidim/budgets/project_list_item/project_data_vote_button.erb +++ b/decidim-budgets/app/cells/decidim/budgets/project_vote_button/show.erb @@ -3,12 +3,13 @@ method: vote_button_method, remote: true, class: "button tiny budget-list__action #{vote_button_class}", + id: "project-vote-button-#{model.id}", data: { add: !resource_added?, disable: true, budget: model.budget_amount, allocation: resource_allocation, - "redirect-url": resource_path + "redirect-url": budget_projects_path(model.budget) }, disabled: vote_button_disabled?, title: vote_button_label do %> diff --git a/decidim-budgets/app/cells/decidim/budgets/project_vote_button_cell.rb b/decidim-budgets/app/cells/decidim/budgets/project_vote_button_cell.rb new file mode 100644 index 0000000000000..bd4d9d6d43c76 --- /dev/null +++ b/decidim-budgets/app/cells/decidim/budgets/project_vote_button_cell.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + # This cell renders an authorized_action button + # to vote a given instance of a Project in a budget list + class ProjectVoteButtonCell < ProjectListItemCell + end + end +end diff --git a/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb b/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb index ab2f512ceb520..388fc87a78f8f 100644 --- a/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb +++ b/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb @@ -23,7 +23,7 @@ def initialize(current_order, project, current_user) # Returns nothing. def call transaction do - return broadcast(:invalid) if voting_not_enabled? || order.checked_out? + return broadcast(:invalid) if voting_not_enabled? || order.checked_out? || exceeds_budget? add_line_item broadcast(:ok, order) @@ -44,6 +44,10 @@ def add_line_item end end + def exceeds_budget? + order.allocation_for(project) + order.total > order.available_allocation + end + def voting_not_enabled? project.component.current_settings.votes != "enabled" end diff --git a/decidim-budgets/app/controllers/decidim/budgets/application_controller.rb b/decidim-budgets/app/controllers/decidim/budgets/application_controller.rb index 9b254a38e7a51..964b5c025fe6b 100644 --- a/decidim-budgets/app/controllers/decidim/budgets/application_controller.rb +++ b/decidim-budgets/app/controllers/decidim/budgets/application_controller.rb @@ -8,6 +8,7 @@ module Budgets # Note that it inherits from `Decidim::Components::BaseController`, which # override its layout and provide all kinds of useful methods. class ApplicationController < Decidim::Components::BaseController + helper Decidim::FocusModeHelper helper_method :current_workflow, :voting_finished?, :voting_open? def current_workflow diff --git a/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb b/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb index 227612c0b8a4b..f81b01e2f3ed9 100644 --- a/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb +++ b/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb @@ -20,7 +20,7 @@ def create end on(:invalid) do - render nothing: true, status: :unprocessable_entity + format.js { render "update_budget", status: :unprocessable_entity } end end end @@ -35,7 +35,7 @@ def destroy end on(:invalid) do - render nothing: true, status: :unprocessable_entity + format.js { render "update_budget", status: :unprocessable_entity } end end end diff --git a/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb b/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb index 3aa9b0d04223a..a41affeff9aa9 100644 --- a/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb +++ b/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb @@ -4,6 +4,8 @@ module Decidim module Budgets # A helper to render order and budgets actions module ProjectsHelper + include ActiveSupport::NumberHelper + # Render a budget as a currency # # budget - A integer to represent a budget @@ -13,7 +15,7 @@ def budget_to_currency(budget) # Return a percentage of the current order budget from the total budget def current_order_budget_percent - current_order&.budget_percent.to_f.floor + current_order&.budget_percent.to_f.floor.clamp(0, 100) end # Return the minimum percentage of the current order budget from the total budget diff --git a/decidim-budgets/app/packs/src/decidim/budgets/projects.js b/decidim-budgets/app/packs/src/decidim/budgets/projects.js index 00f4f8a9b45c3..53c785295a275 100644 --- a/decidim-budgets/app/packs/src/decidim/budgets/projects.js +++ b/decidim-budgets/app/packs/src/decidim/budgets/projects.js @@ -4,8 +4,10 @@ $(() => { const $budgetExceedModal = $("#budget-excess"); const $budgetSummary = $(".budget-summary__progressbox"); const totalAllocation = parseInt($budgetSummaryTotal.attr("data-total-allocation"), 10); + const $voteButton = $(".budget-vote-button"); const cancelEvent = (event) => { + $(event.currentTarget).removeClass("loading-spinner"); event.stopPropagation(); event.preventDefault(); }; @@ -20,11 +22,19 @@ $(() => { return false; } + $voteButton.on("click", "span", (event) => { + $(".budget-list__action").click(); + }); + $projects.on("click", ".budget-list__action", (event) => { const currentAllocation = parseInt($budgetSummary.attr("data-current-allocation"), 10); const $currentTarget = $(event.currentTarget); const projectAllocation = parseInt($currentTarget.attr("data-allocation"), 10); + if (!$currentTarget.attr("data-open")) { + $currentTarget.addClass("loading-spinner"); + } + if ($currentTarget.attr("disabled")) { cancelEvent(event); } else if (($currentTarget.attr("data-add") === "true") && ((currentAllocation + projectAllocation) > totalAllocation)) { diff --git a/decidim-budgets/app/packs/stylesheets/decidim/budgets/_budgets.scss b/decidim-budgets/app/packs/stylesheets/decidim/budgets/_budgets.scss index a8f2382528ebc..661abeba3f6d5 100644 --- a/decidim-budgets/app/packs/stylesheets/decidim/budgets/_budgets.scss +++ b/decidim-budgets/app/packs/stylesheets/decidim/budgets/_budgets.scss @@ -1,3 +1,4 @@ @import "stylesheets/decidim/budgets/budget/budget-list"; @import "stylesheets/decidim/budgets/budget/budget-meter"; +@import "stylesheets/decidim/budgets/budget/budget-vote-button"; @import "stylesheets/decidim/budgets/budget/progress"; diff --git a/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-list.scss b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-list.scss index 9e76d1f8f9fa4..89051dc607c1f 100644 --- a/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-list.scss +++ b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-list.scss @@ -19,6 +19,26 @@ border-bottom-right-radius: $card-border-radius; border-bottom: $border; } + + &-cell { + display: grid; + grid-template-columns: 1fr 40px; + + .budget-list__data { + grid-column: span 2; + background: none; + } + + @include breakpoint(medium){ + grid-template-columns: 1fr 40px 15em; + grid-template-rows: 1fr; + + .budget-list__data { + background: $card-secondary-bg; + grid-column: 3; + } + } + } } &__image{ @@ -54,6 +74,11 @@ padding: $card-padding; display: flex; align-items: center; + + &.flex-horizontal { + flex-direction: column; + align-items: flex-start; + } } .card__text--status{ @@ -79,10 +104,18 @@ min-width: 7rem; flex-direction: row; justify-content: flex-end; - flex-basis: 12rem; + flex-basis: 14rem; padding: 1rem $card-padding; } + .loading-spinner { + margin: 0 !important; + position: relative; + &:before { + position: absolute; + } + } + &:last-child{ margin-bottom: 0; } diff --git a/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-meter.scss b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-meter.scss index 3ab5ae966f434..386dc55822eba 100644 --- a/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-meter.scss +++ b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-meter.scss @@ -1,5 +1,22 @@ .budget-summary__total{ margin-bottom: .5rem; + + .mini-title { + display: block; + + &__strong { + line-height: 1rem; + } + } + + @include breakpoint(medium) { + align-content: center; + display: flex; + + .mini-title:nth-of-type(2) { + margin-left: auto; + } + } } .budget-summary__progressbox{ diff --git a/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-vote-button.scss b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-vote-button.scss new file mode 100644 index 0000000000000..23c8fc9065362 --- /dev/null +++ b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_budget-vote-button.scss @@ -0,0 +1,22 @@ +.budget-vote-button.expanded { + display: flex; + text-align: left; + justify-content: space-between; + align-items: center; + + span { + font-size: 1rem; + } + + &.added { + background-color: tint($success, 80%); + color: $body-font-color; + } + + &:not(.added) { + .budget-list__action { + border-color: white; + color: white; + } + } +} diff --git a/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_progress.scss b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_progress.scss index 97c4d9cd73f14..a282f6c60c497 100644 --- a/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_progress.scss +++ b/decidim-budgets/app/packs/stylesheets/decidim/budgets/budget/_progress.scss @@ -4,6 +4,17 @@ position: relative; } +.budget-progress .progress-meter{ + &:not(&--minimum) { + background-color: tint($success, 80%); + } + + .progress-meter-text{ + color: $body-font-color; + font-size: 1rem; + } +} + .progress-meter--minimum{ background: repeating-linear-gradient(-55deg, rgba(white, .2), rgba(white, .2) 8px, rgba(black, .03) 8px, rgba(black, .03) 16px); position: absolute; @@ -16,4 +27,22 @@ text-align: right; padding-left: 1rem; padding-right: .5rem; + + @include breakpoint(smallmedium down) { + text-align: center; + padding: 0; + left: 0; + } } + +.progress-text-wrapper { + height: 100%; + width: 100%; + display: flex; + align-items: center; + padding: 1em; +} + +.progress-text { + font-size: 1em; +} \ No newline at end of file diff --git a/decidim-budgets/app/views/decidim/budgets/budgets/index.html.erb b/decidim-budgets/app/views/decidim/budgets/budgets/index.html.erb index 8f57b162f9d98..7b52505e5be94 100644 --- a/decidim-budgets/app/views/decidim/budgets/budgets/index.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/budgets/index.html.erb @@ -1,5 +1,34 @@ <%= render partial: "decidim/shared/component_announcement" %> +<% start_date, end_date = %w(start_date end_date).map { |attribute| current_component.participatory_space.try(:active_step)&.try(attribute) || current_component.participatory_space.try(attribute) } %> +<% instructions = translated_attribute(current_component.current_settings.landing_page_instructions).presence || translated_attribute(current_component.settings.landing_page_instructions) %> -<%= cell("decidim/budgets/budgets_header", current_workflow) %> +
+
+ <%= cell("decidim/budgets/budgets_header", current_workflow) %> + <%= cell("decidim/budgets/budgets_list", current_workflow) %> +
-<%= cell("decidim/budgets/budgets_list", current_workflow) %> + <% if start_date.present? || instructions.present? %> +
+ <% if start_date %> +
+
+

<%= t(".date") %>

+ <%= cell("decidim/date", { start: start_date, end: end_date, extra_classes: "extra__date-container--horizontal" }) %> +
+
+ <% end %> + + <% if instructions.present? %> +
+
+

<%= t(".instructions") %>

+
+ <%== instructions %> +
+
+
+ <% end %> +
+ <% end %> +
diff --git a/decidim-budgets/app/views/decidim/budgets/line_items/update_budget.js.erb b/decidim-budgets/app/views/decidim/budgets/line_items/update_budget.js.erb index 93c41777c7f0e..f2ed14195849c 100644 --- a/decidim-budgets/app/views/decidim/budgets/line_items/update_budget.js.erb +++ b/decidim-budgets/app/views/decidim/budgets/line_items/update_budget.js.erb @@ -1,4 +1,5 @@ var $orderTotalBudget = $('#order-total-budget'); +var $orderRemainingBudget = $('#order-remaining-budget'); var $orderSelectedProjects = $('#order-selected-projects'); var $orderProgress = $('#order-progress'); var $projectItem = $('#project-<%= project.id %>-item'); @@ -6,6 +7,7 @@ var $projectBudgetButton = $('#project-<%= project.id %>-budget-button'); var $budgetConfirm = $('#budget-confirm'); morphdom($orderTotalBudget[0], '<%= j(render partial: "decidim/budgets/projects/order_total_budget").strip.html_safe %>'); +morphdom($orderRemainingBudget[0], '<%= j(render partial: "decidim/budgets/projects/order_remaining_budget").strip.html_safe %>'); morphdom($orderSelectedProjects[0], '<%= j(render partial: "decidim/budgets/projects/order_selected_projects").strip.html_safe %>'); morphdom($orderProgress[0], '<%= j(render partial: "decidim/budgets/projects/order_progress").strip.html_safe %>'); morphdom($budgetConfirm[0], '<%= j(render partial: "decidim/budgets/projects/budget_confirm").strip.html_safe %>') @@ -20,5 +22,3 @@ if ($projectItem.length > 0) { if ($projectBudgetButton.length > 0) { morphdom($projectBudgetButton[0], '<%= j(render partial: "decidim/budgets/projects/project_budget_button", locals: { project: project }).strip.html_safe %>'); } - -window.DecidimBudgets.checkProgressPosition(); diff --git a/decidim-budgets/app/views/decidim/budgets/projects/_budget_summary.html.erb b/decidim-budgets/app/views/decidim/budgets/projects/_budget_summary.html.erb index 60db9a5412ea8..adb4f20687095 100644 --- a/decidim-budgets/app/views/decidim/budgets/projects/_budget_summary.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/projects/_budget_summary.html.erb @@ -1,20 +1,24 @@ -
-
-
-
-

- <%= t(".rules.title") %> -

-
    - <%= raw current_rule_explanation %> -
-
-
-
-
-
-
- <% if include_heading %> +<%= focus_mode( + title: translated_attribute(current_component.participatory_space.title), + url: Decidim::EngineRouter.main_proxy(current_component).root_path, + opener_button: false +) do %> + + <% unless current_workflow.single? %> + <% project_detail = action_name == "show" %> + <% back_path = project_detail ? budget_path(budget) : Decidim::EngineRouter.main_proxy(current_component).root_path %> + <% back_title = project_detail ? t(".back_to_projects", budget_name: translated_attribute(budget.title)) : t(".back_to_budgets", component_name: translated_attribute(current_component.name)) %> + +

+ <%= link_to back_path, class: "muted-link" do %> + <%= icon "chevron-left", class: "icon--small", role: "img", "aria-hidden": true %> + <%= back_title %> + <% end %> +

+ <% end %> + +
+
<% if current_order_checked_out? %>

<%= t(".checked_out.title") %> @@ -33,44 +37,54 @@ <%= translated_attribute(budget.title) %> <% end %>

-

- <%= raw current_rule_description %> -

<% end %> - <% end %> - <% if current_order.projects_rule? %> -
- <%= t(".total_projects") %> - - <%= current_order.maximum_projects %> - - -
- <% else %> -
- <%= t(".total_budget") %> - - <%= budget_to_currency(budget.total_budget) %> - - +
+
+
+
+ <%= raw current_rule_explanation %> +
+
+
- <% end %> - <%= render partial: "order_progress" %> + <%= cell("decidim/budgets/budget_information_modal", budget) %> + + <% if current_order.projects_rule? %> +
+ <%= t(".total_projects") %> + + <%= current_order.maximum_projects %> + + +
+ <% else %> +
+ <%= t(".total_budget") %> + + <%= budget_to_currency(budget.total_budget) %> + + -
- - <%= t(".assigned") %> - <%= render partial: "order_total_budget" %> - + + <%= t(".assigned") %> + <%= render partial: "order_total_budget" %> + + + + <%= t(".remaining") %> + <%= render partial: "order_remaining_budget" %> + +
+ <% end %> + + <%= render partial: "order_progress" %>
- <%= cell("decidim/budgets/budget_information_modal", budget) %> + <%= render partial: "order_selected_projects" %>
- <%= render partial: "order_selected_projects" %> -
- -<%= render partial: "budget_excess" %> -<%= render partial: "budget_confirm" %> + <%= render partial: "budget_excess" %> + <%= render partial: "budget_confirm" %> +<% end %> diff --git a/decidim-budgets/app/views/decidim/budgets/projects/_order_progress.html.erb b/decidim-budgets/app/views/decidim/budgets/projects/_order_progress.html.erb index 384d8f553c1c1..eff9eb1079934 100644 --- a/decidim-budgets/app/views/decidim/budgets/projects/_order_progress.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/projects/_order_progress.html.erb @@ -1,10 +1,14 @@
+ <% projects_count = current_order.projects.size %> + <% selected = "#{projects_count} #{t("selected_projects", scope: "decidim.budgets.projects.order_selected_projects", count: projects_count)}" %> + <% label = current_order.minimum_projects_rule? ? selected : current_order_budget_percent.to_s + "%" %> +
-
+
- <%= current_order_budget_percent %>% + <%= label %>
<% if !current_order_checked_out? && voting_open? %> @@ -13,20 +17,4 @@ <% end %>
- -
-
-
-
-
- <%= current_order_budget_percent %>% -
-
- <% if !current_order_checked_out? && voting_open? %> - - <% end %> -
-
diff --git a/decidim-budgets/app/views/decidim/budgets/projects/_order_remaining_budget.html.erb b/decidim-budgets/app/views/decidim/budgets/projects/_order_remaining_budget.html.erb new file mode 100644 index 0000000000000..085d7c6de794f --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/projects/_order_remaining_budget.html.erb @@ -0,0 +1,5 @@ + + <% unless current_order.projects_rule? %> + <%= budget_to_currency (current_order&.budget&.total_budget.to_f - current_order&.total_budget.to_f) %> + <% end %> + diff --git a/decidim-budgets/app/views/decidim/budgets/projects/_project_budget_button.html.erb b/decidim-budgets/app/views/decidim/budgets/projects/_project_budget_button.html.erb index 1f75846964739..204692aa33749 100644 --- a/decidim-budgets/app/views/decidim/budgets/projects/_project_budget_button.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/projects/_project_budget_button.html.erb @@ -1,40 +1,15 @@ -
- <% if voted_for?(project) %> - <%= action_authorized_button_to( - "vote", - t(".added"), - budget_order_line_item_path(budget, project_id: project), - method: :delete, - remote: true, - data: { - disable: true, - budget: project.budget_amount, - "redirect-url": budget_project_path(budget, project) - }, - disabled: !can_have_order? || current_order_checked_out?, - class: "button expanded button--sc success", - "aria-label": t(".added_descriptive", resource_name: translated_attribute(project.title)) - ) %> - <% elsif current_user.present? %> - <%= action_authorized_button_to( - "vote", - t(".add"), - budget_order_line_item_path(budget, project_id: project), - method: :post, - remote: true, - data: { - disable: true, - budget: project.budget_amount, - add: true, - "redirect-url": budget_project_path(budget, project) - }, - disabled: !can_have_order? || current_order_checked_out?, - class: "button expanded button--sc", - "aria-label": t(".add_descriptive", resource_name: translated_attribute(project.title)) - ) %> - <% else %> - - <% end %> -
+
+<% else %> +
button expanded primary button--sc budget-vote-button budget-list__data"> + + <%= t(voted_for?(project) ? ".added" : ".add") %> + + + <%= cell("decidim/budgets/project_vote_button", project) %> +
+<% end %> diff --git a/decidim-budgets/app/views/decidim/budgets/projects/index.html.erb b/decidim-budgets/app/views/decidim/budgets/projects/index.html.erb index c9b46651b80ad..4a2278b799c87 100644 --- a/decidim-budgets/app/views/decidim/budgets/projects/index.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/projects/index.html.erb @@ -8,7 +8,7 @@ <%= t("decidim.budgets.projects.projects_for", name: translated_attribute(budget.title)) %> <% else %> - <%= render partial: "budget_summary", locals: { include_heading: true } %> + <%= render partial: "budget_summary" %> <% end %>
diff --git a/decidim-budgets/app/views/decidim/budgets/projects/show.html.erb b/decidim-budgets/app/views/decidim/budgets/projects/show.html.erb index 51c7632115c38..7e6d4a1177a11 100644 --- a/decidim-budgets/app/views/decidim/budgets/projects/show.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/projects/show.html.erb @@ -16,7 +16,7 @@ edit_link(
<% unless voting_finished? %> - <%= render partial: "budget_summary", locals: { include_heading: false } %> + <%= render partial: "budget_summary" %> <% end %>
diff --git a/decidim-budgets/config/locales/ca.yml b/decidim-budgets/config/locales/ca.yml index 519b9f8ea68fd..f640182444fe4 100644 --- a/decidim-budgets/config/locales/ca.yml +++ b/decidim-budgets/config/locales/ca.yml @@ -103,6 +103,10 @@ ca: update: "%{user_name} ha actualitzat el projecte %{resource_name} de l'espai %{space_name}" budget: view: Veure tots els projectes de pressupost + budgets: + index: + date: Dates de votació + instructions: Com participar budget_information_modal: back_to: Tornar a %{component_name} close_modal: Tancar el modal @@ -119,6 +123,9 @@ ca: highlighted_cta: Votar a %{name} if_change_opinion: Si has canviat d'opinió, pots my_budgets: Els meus pressupostos + progress: Finalitza la votació + show: Veure projectes + vote: Vota voted_on: Has votat a %{links} limit_announcement: cant_vote: No pots votar a aquests pressupostos. Prova amb un altre pressupost . @@ -158,27 +165,31 @@ ca: budget_summary: are_you_sure: Segur que vols cancel·lar el teu vot? assigned: 'Assignat:' + back_to_budgets: Tornar a %{component_name} + back_to_projects: Tornar a %{budget_name} cancel_order: eliminar el teu vot i començar de nou checked_out: description: Ja has votat pel pressupost. Si has canviat d'idea, pots %{cancel_link}. title: Vot pels pressupostos completat minimum_projects_rule: - description: A quins projectes creus que hem de destinar el pressupost? Selecciona com a mínim %{minimum_number} projectes i vota segons les teves preferències per a definir el pressupost. - instruction: "
  • Selecciona com a mínim %{minimum_number} projectes i vota segons les teves preferències per a definir el pressupost.
  • " + description: A quins projectes creus que hem de destinar el pressupost? Selecciona com a mínim %{minimum_number} projectes i vota segons les teves preferències per a definir el pressupost. + instruction: "Selecciona com a mínim %{minimum_number} projectes i vota segons les teves preferències per a definir el pressupost." projects_rule: - description: A quins projectes creus que hem de destinar el pressupost? Selecciona entre %{minimum_number} i %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost. - instruction: "
  • Selecciona entre %{minimum_number} i %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost.
  • " + description: A quins projectes creus que hem de destinar el pressupost? Selecciona entre %{minimum_number} i %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost. + instruction: "Selecciona entre %{minimum_number} i %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost." projects_rule_maximum_only: - description: A quins projectes creus que hem de destinar el pressupost? Selecciona fins a %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost. - instruction: "
  • Selecciona fins a %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost.
  • " + description: A quins projectes creus que hem de destinar el pressupost? Selecciona fins a %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost. + instruction: "Selecciona fins a %{maximum_number} projectes i vota segons les teves preferències per a definir el pressupost." + remaining: 'Restant:' rules: title: Regles de votació title: Tu decideixes el pressupost total_budget: Pressupost total total_projects: Vots totals vote_threshold_percent_rule: - description: A quins projectes creus que hem de destinar el pressupost? Assigna com a mínim %{minimum_budget} als projectes que vulguis i vota segons les teves preferències per a definir el pressupost. - instruction: "
  • Assigna com a mínim %{minimum_budget} als projectes que vulguis i vota segons les teves preferències per a definir el pressupost.
  • " + description: A quins projectes creus que hem de destinar el pressupost? Assigna com a mínim %{minimum_budget} als projectes que vulguis i vota segons les teves preferències per a definir el pressupost. + instruction: "Assigna com a mínim %{minimum_budget} als projectes que vulguis i vota segons les teves preferències per a definir el pressupost." + vote: Vota count: projects_count: one: 1 projecte @@ -245,6 +256,7 @@ ca: budget_voting_rule_only_one: Cal activar com a mínim una norma per a la votació budget_voting_rule_required: Es requereix una norma per a la votació landing_page_content: Pàgina d'inici de pressupostos + landing_page_instructions: Instruccions per la pàgina d'inici de pressupostos more_information_modal: Finestra de "Més informació" projects_per_page: Projectes per pàgina resources_permissions_enabled: Es poden establir permisos d'accions per a cada projecte @@ -268,6 +280,7 @@ ca: comments_blocked: Comentaris bloquejats highlighted_heading: Capçalera destacada landing_page_content: Pàgina d'inici de pressupostos + landing_page_instructions: Instruccions per la pàgina d'inici de pressupostos list_heading: Títol de la llista more_information_modal: Finestra de "Més informació" show_votes: Mostra els suports diff --git a/decidim-budgets/config/locales/en.yml b/decidim-budgets/config/locales/en.yml index 9d82cc6f76799..439b5b5b91869 100644 --- a/decidim-budgets/config/locales/en.yml +++ b/decidim-budgets/config/locales/en.yml @@ -112,6 +112,10 @@ en: budget_list_item: voting_finished: You have voted in this budget voting_started: You have started to vote in this budget + budgets: + index: + date: Voting dates + instructions: How to participate budgets_list: cancel_order: more_than_one: delete your vote on %{name} and start over @@ -120,6 +124,9 @@ en: highlighted_cta: Vote on %{name} if_change_opinion: If you've changed your mind, you can my_budgets: My budgets + progress: Finish voting + show: See projects + vote: Vote voted_on: You've voted on %{links} limit_announcement: cant_vote: You can't vote on this budget. Try on another budget. @@ -159,27 +166,30 @@ en: budget_summary: are_you_sure: Are you sure you want to cancel your vote? assigned: 'Assigned:' + back_to_budgets: Back to %{component_name} + back_to_projects: Back to %{budget_name} cancel_order: delete your vote and start over checked_out: description: You've already voted for the budget. If you've changed your mind, you can %{cancel_link}. title: Budget vote completed minimum_projects_rule: - description: What projects do you think we should allocate budget for? Select at least %{minimum_number} projects you want and vote according to your preferences to define the budget. - instruction: "
  • Select at least %{minimum_number} projects you want and vote according to your preferences to define the budget.
  • " + description: What projects do you think we should allocate budget for? Select at least %{minimum_number} projects you want and vote according to your preferences to define the budget. + instruction: "Select at least %{minimum_number} projects you want and vote according to your preferences to define the budget." projects_rule: - description: What projects do you think we should allocate budget for? Select at least %{minimum_number} and up to %{maximum_number} projects you want and vote according to your preferences to define the budget. - instruction: "
  • Select at least %{minimum_number} and up to %{maximum_number} projects you want and vote according to your preferences to define the budget.
  • " + description: What projects do you think we should allocate budget for? Select at least %{minimum_number} and up to %{maximum_number} projects you want and vote according to your preferences to define the budget. + instruction: "Select at least %{minimum_number} and up to %{maximum_number} projects you want and vote according to your preferences to define the budget." projects_rule_maximum_only: - description: What projects do you think we should allocate budget for? Select up to %{maximum_number} projects you want and vote according to your preferences to define the budget. - instruction: "
  • Select up to %{maximum_number} projects you want and vote according to your preferences to define the budget.
  • " + description: What projects do you think we should allocate budget for? Select up to %{maximum_number} projects you want and vote according to your preferences to define the budget. + instruction: "Select up to %{maximum_number} projects you want and vote according to your preferences to define the budget." + remaining: 'Remaining:' rules: title: Budget rules title: You decide the budget total_budget: Total budget total_projects: Total votes vote_threshold_percent_rule: - description: What projects do you think we should allocate budget for? Assign at least %{minimum_budget} to the projects you want and vote according to your preferences to define the budget. - instruction: "
  • Assign at least %{minimum_budget} to the projects you want and vote according to your preferences to define the budget.
  • " + description: What projects do you think we should allocate budget for? Assign at least %{minimum_budget} to the projects you want and vote according to your preferences to define the budget. + instruction: "Assign at least %{minimum_budget} to the projects you want and vote according to your preferences to define the budget." count: projects_count: one: 1 project @@ -247,6 +257,7 @@ en: budget_voting_rule_only_one: Only one voting rule must be enabled budget_voting_rule_required: One voting rule is required landing_page_content: Budgets landing page + landing_page_instructions: Budgets landing page instructions more_information_modal: More information modal projects_per_page: Projects per page resources_permissions_enabled: Actions permissions can be set for each project @@ -270,6 +281,7 @@ en: comments_blocked: Comments blocked highlighted_heading: Highlighted heading landing_page_content: Budgets landing page + landing_page_instructions: Budgets landing page instructions list_heading: List heading more_information_modal: More information modal show_votes: Show votes diff --git a/decidim-budgets/config/locales/es.yml b/decidim-budgets/config/locales/es.yml index bd62ac00ea5f3..426c03d7ca548 100644 --- a/decidim-budgets/config/locales/es.yml +++ b/decidim-budgets/config/locales/es.yml @@ -103,6 +103,10 @@ es: update: "%{user_name} actualizó el proyecto %{resource_name} en el espacio %{space_name}" budget: view: Ver todos los proyectos de presupuesto + budgets: + index: + date: Fechas de votación + instructions: Cómo participar budget_information_modal: back_to: Volver a %{component_name} close_modal: Cierra el modal @@ -119,6 +123,9 @@ es: highlighted_cta: Votar en %{name} if_change_opinion: Si has cambiado de opinión, puedes my_budgets: Mis presupuestos + progress: Finaliza la votación + show: Ver proyectos + vote: Vota voted_on: Has votado en %{links} limit_announcement: cant_vote: No puedes votar en este presupuesto. Prueba con otro presupuesto. @@ -158,27 +165,31 @@ es: budget_summary: are_you_sure: '¿Estás seguro de que deseas cancelar tu voto?' assigned: 'Asignado:' + back_to_budgets: Volver a %{component_name} + back_to_projects: Volver a %{budget_name} cancel_order: eliminar tu voto y empezar de nuevo checked_out: description: Ya has votado para el presupuesto. Si has cambiado de idea, puedes %{cancel_link}. title: Voto para los presupuestos completado minimum_projects_rule: - description: '¿A qué proyectos crees que deberíamos destinar el presupuesto? Selecciona por lo menos %{minimum_number} y vota según tus preferencias para definir el presupuesto.' - instruction: "
  • Selecciona al menos %{minimum_number} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto.
  • " + description: '¿A qué proyectos crees que deberíamos destinar el presupuesto? Selecciona por lo menos %{minimum_number} proyectos y vota según tus preferencias para definir el presupuesto.' + instruction: "Selecciona al menos %{minimum_number} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto." projects_rule: - description: '¿A qué proyectos crees que deberíamos destinar el presupuesto? Selecciona entre %{minimum_number} y %{maximum_number} proyectos, y vota según tus preferencias para definir el presupuesto.' - instruction: "
  • Selecciona al menos %{minimum_number} y hasta %{maximum_number} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto.
  • " + description: '¿A qué proyectos crees que deberíamos destinar el presupuesto? Selecciona entre %{minimum_number} y %{maximum_number} proyectos, y vota según tus preferencias para definir el presupuesto.' + instruction: "Selecciona al menos %{minimum_number} y hasta %{maximum_number} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto." projects_rule_maximum_only: - description: '¿A qué proyectos crees que deberíamos destinar el presupuesto? Selecciona hasta %{maximum_number} y vota según tus preferencias para definir el presupuesto.' - instruction: "
  • Selecciona hasta %{maximum_number} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto.
  • " + description: '¿A qué proyectos crees que deberíamos destinar el presupuesto? Selecciona hasta %{maximum_number} proyectos y vota según tus preferencias para definir el presupuesto.' + instruction: "Selecciona hasta %{maximum_number} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto." + remaining: 'Restante:' rules: title: Reglas de presupuesto title: Tú decides el presupuesto total_budget: Presupuesto total total_projects: Total de votos vote_threshold_percent_rule: - description: '¿A qué proyectos crees que deberíamos asignar el presupuesto? Asigna por lo menos %{minimum_budget} a los proyectos que desees y vota para definir el presupuesto.' - instruction: "
  • Selecciona al menos %{minimum_budget} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto.
  • " + description: '¿A qué proyectos crees que deberíamos asignar el presupuesto? Asigna por lo menos %{minimum_budget} a los proyectos que desees y vota para definir el presupuesto.' + instruction: "Selecciona al menos %{minimum_budget} proyectos que quieras y vota de acuerdo a tus preferencias para definir el presupuesto." + vote: Vota count: projects_count: one: 1 proyecto @@ -245,6 +256,7 @@ es: budget_voting_rule_only_one: Hay que activar por lo menos una norma para la votación budget_voting_rule_required: Se requiere una norma para la votación landing_page_content: Página de inicio de presupuestos + landing_page_instructions: Instrucciones para la página de inicio de presupuestos more_information_modal: Modal de "Más información" projects_per_page: Proyectos por página resources_permissions_enabled: Se pueden establecer permisos de acciones para cada proyecto @@ -268,6 +280,7 @@ es: comments_blocked: Comentarios bloqueados highlighted_heading: Encabezado destacado landing_page_content: Página de inicio de presupuestos + landing_page_instructions: Instrucciones para la página de inicio de presupuestos list_heading: Título de lista more_information_modal: Modal de "Más información" show_votes: Mostrar los votos diff --git a/decidim-budgets/lib/decidim/budgets/component.rb b/decidim-budgets/lib/decidim/budgets/component.rb index f52389af467e1..2dce34ef6435a 100644 --- a/decidim-budgets/lib/decidim/budgets/component.rb +++ b/decidim-budgets/lib/decidim/budgets/component.rb @@ -94,6 +94,7 @@ settings.attribute :announcement, type: :text, translated: true, editor: true settings.attribute :landing_page_content, type: :text, translated: true, editor: true + settings.attribute :landing_page_instructions, type: :text, translated: true, editor: true settings.attribute :more_information_modal, type: :text, translated: true end @@ -104,6 +105,7 @@ settings.attribute :announcement, type: :text, translated: true, editor: true settings.attribute :landing_page_content, type: :text, translated: true, editor: true + settings.attribute :landing_page_instructions, type: :text, translated: true, editor: true settings.attribute :more_information_modal, type: :text, translated: true settings.attribute :announcement, type: :text, translated: true, editor: true end diff --git a/decidim-budgets/lib/decidim/budgets/test/factories.rb b/decidim-budgets/lib/decidim/budgets/test/factories.rb index 251c0066f9c90..419ae4e2d15c2 100644 --- a/decidim-budgets/lib/decidim/budgets/test/factories.rb +++ b/decidim-budgets/lib/decidim/budgets/test/factories.rb @@ -98,6 +98,22 @@ } end end + + trait :with_landing_page_content do + transient do + landing_page_content { Decidim::Faker::Localized.wrapped("

    ", "

    ") } + landing_page_instructions { Decidim::Faker::Localized.wrapped("

    ", "

    ") } + end + + step_settings do + { + participatory_space.active_step.id => { + landing_page_content: landing_page_content, + landing_page_instructions: landing_page_instructions + } + } + end + end end factory :budget, class: "Decidim::Budgets::Budget" do diff --git a/decidim-budgets/spec/system/explore_budgets_spec.rb b/decidim-budgets/spec/system/explore_budgets_spec.rb index b28c02250df48..2c5ba00c074a4 100644 --- a/decidim-budgets/spec/system/explore_budgets_spec.rb +++ b/decidim-budgets/spec/system/explore_budgets_spec.rb @@ -6,6 +6,29 @@ include_context "with a component" let(:manifest_name) { "budgets" } + let!(:component) do + create(:budgets_component, + :with_vote_threshold_percent, + :with_landing_page_content, + manifest: manifest, + participatory_space: participatory_process, + landing_page_content: { en: "

    Big title

    " }, + landing_page_instructions: { en: "

    Follow your instincts

    " }) + end + + let!(:current_step) do + create(:participatory_process_step, + start_date: 1.day.ago, + end_date: 3.days.from_now, + participatory_process: participatory_process + ) + end + + before do + participatory_process.steps.first.update(start_date: 1.month.ago, end_date: 1.day.ago - 1.hour, active: false) + participatory_process.steps.last.update(active: true) + end + context "with only one budget" do let!(:budgets) { create_list(:budget, 1, component: component) } @@ -17,15 +40,86 @@ end context "with many budgets" do - let!(:budgets) { create_list(:budget, 6, component: component) } + let!(:budgets) do + 1.upto(6).to_a.map { |x| create(:budget, component: component, total_budget: x * 10_000_000, description: { en: "This is budget #{x}" }) } + end - it "lists all the budgets" do + before do visit_component + end + it "shows the content" do + expect(page).to have_content("Big title") + end + + it "shows the dates" do + expect(page).to have_content("Voting dates") + + within ".extra__date-container" do + expect(page).to have_content(I18n.l(current_step.start_date, format: "%B")) + expect(page).to have_content(current_step.start_date.day) + expect(page).to have_content(I18n.l(current_step.end_date, format: "%B")) + expect(page).to have_content(current_step.end_date.day) + end + end + + it "shows the instructions" do + expect(page).to have_content("How to participate") + expect(page).to have_content("Follow your instincts") + end + + it "lists all the budgets" do expect(page).to have_selector(".card--list__item", count: 6) budgets.each do |budget| expect(page).to have_content(translated(budget.title)) + expect(page).to have_content("This is budget 1") + expect(page).to have_content("€10,000,000") + end + end + + describe "budget list item" do + let(:budget) { budgets.first } + let(:item) { page.find(".budget-list .card--list__item:first-child", match: :first) } + let!(:projects) { create_list(:project, 3, budget: budget, budget_amount: 10_000_000) } + + before do + login_as user, scope: :user + end + + it "has a clickable title" do + expect(item).to have_link(translated(budget.title), href: budget_path(budget)) + end + + context "when an item is bookmarked" do + let!(:order) { create(:order, user: user, budget: budget) } + let!(:line_item) { create(:line_item, order: order, project: projects.first) } + + it "shows the bookmark icon" do + visit_component + + expect(item).to have_selector(".budget-list__icon .icon--bookmark") + expect(item).to have_link("Finish voting", href: budget_path(budget)) + end + end + + context "when an item is voted" do + let(:item) { page.find("#voted-budgets .card--list__item:first-child") } + + let!(:order) do + order = create(:order, user: user, budget: budget) + order.projects = [projects.first] + order.checked_out_at = Time.current + order.save! + order + end + + it "shows the check icon" do + visit_component + + expect(item).to have_selector(".budget-list__icon .icon--check") + expect(item).to have_link("Show", href: budget_path(budget)) + end end end end @@ -35,4 +129,8 @@ let(:target_path) { Decidim::EngineRouter.main_proxy(component).budget_path(99_999_999) } end end + + def budget_path(budget) + Decidim::EngineRouter.main_proxy(component).budget_path(budget.id) + end end diff --git a/decidim-budgets/spec/system/explore_projects_spec.rb b/decidim-budgets/spec/system/explore_projects_spec.rb index ca97bbbd83b63..60734722f56d6 100644 --- a/decidim-budgets/spec/system/explore_projects_spec.rb +++ b/decidim-budgets/spec/system/explore_projects_spec.rb @@ -14,8 +14,13 @@ let(:categories) { create_list(:category, 3, participatory_space: component.participatory_space) } describe "index" do - it "shows all resources for the given component" do + before do visit_budget + end + + it_behaves_like "has focus mode", "TOTAL BUDGET" + + it "shows all resources for the given component" do within "#projects" do expect(page).to have_selector(".budget-list__item", count: projects_count) end diff --git a/decidim-budgets/spec/system/orders_spec.rb b/decidim-budgets/spec/system/orders_spec.rb index af1362b7f6d73..4c9e27c9157fd 100644 --- a/decidim-budgets/spec/system/orders_spec.rb +++ b/decidim-budgets/spec/system/orders_spec.rb @@ -21,9 +21,13 @@ context "when the user is not logged in" do let!(:projects) { create_list(:project, 1, budget: budget, budget_amount: 25_000_000) } - it "is given the option to sign in" do + before do visit_budget + end + it_behaves_like "has focus mode", "TOTAL BUDGET" + + it "is given the option to sign in" do within "#project-#{project.id}-item" do page.find(".budget-list__action").click end @@ -44,15 +48,12 @@ visit_budget end + it_behaves_like "has focus mode", "You decide the budget" + context "when voting by percentage threshold" do - it "displays description messages" do + it "displays description messages and voting rules" do within ".budget-summary" do - expect(page).to have_content("You decide the budget\nWhat projects do you think we should allocate budget for? Assign at least €70,000,000 to the projects you want and vote according to your preferences to define the budget.") - end - end - - it "displays rules" do - within ".voting-rules" do + expect(page).to have_content("You decide the budget") expect(page).to have_content("Assign at least €70,000,000 to the projects you want and vote according to your preferences to define the budget.") end end @@ -66,15 +67,23 @@ participatory_space: participatory_process) end - it "displays description messages" do + it "displays voting rules" do within ".budget-summary" do - expect(page).to have_content("What projects do you think we should allocate budget for? Select at least 3 projects you want and vote according to your preferences to define the budget.") + expect(page).to have_content("Select at least 3 projects you want and vote according to your preferences to define the budget.") end end - it "displays rules" do - within ".voting-rules" do - expect(page).to have_content("Select at least 3 projects you want and vote according to your preferences to define the budget.") + it "shows the project count in the progress bar" do + within ".progress-meter-text" do + expect(page).to have_content("0 projects selected") + end + + within "#project-#{project.id}-item" do + page.find(".budget-list__action").click + end + + within ".progress-meter-text" do + expect(page).to have_content("1 project selected") end end end @@ -88,14 +97,8 @@ participatory_space: participatory_process) end - it "displays description messages" do + it "displays voting rules" do within ".budget-summary" do - expect(page).to have_content("What projects do you think we should allocate budget for? Select up to 6 projects you want and vote according to your preferences to define the budget.") - end - end - - it "displays rules" do - within ".voting-rules" do expect(page).to have_content("Select up to 6 projects you want and vote according to your preferences to define the budget.") end end @@ -109,14 +112,8 @@ participatory_space: participatory_process) end - it "displays description messages" do + it "displays voting rules" do within ".budget-summary" do - expect(page).to have_content("What projects do you think we should allocate budget for? Select at least 3 and up to 6 projects you want and vote according to your preferences to define the budget.") - end - end - - it "displays rules" do - within ".voting-rules" do expect(page).to have_content("Select at least 3 and up to 6 projects you want and vote according to your preferences to define the budget.") end end @@ -137,6 +134,7 @@ expect(page).to have_selector ".budget-list__data--added", count: 1 expect(page).to have_content "ASSIGNED: €25,000,000" + expect(page).to have_content "REMAINING: €75,000,000" expect(page).to have_content "1 project selected" within ".budget-summary__selected" do @@ -172,6 +170,7 @@ expect(page).to have_selector ".budget-list__data--added", count: 1 expect(page).to have_content "ASSIGNED: €25,000,000" + expect(page).to have_content "REMAINING: €75,000,000" expect(page).to have_content "1 project selected" within ".budget-summary__selected" do @@ -179,7 +178,7 @@ end within "#order-progress .budget-summary__progressbox" do - expect(page).to have_content "25%" + expect(page).to have_content "1 project selected" expect(page).to have_selector("button.small:disabled") end end @@ -295,6 +294,7 @@ visit_budget expect(page).to have_content "ASSIGNED: €25,000,000" + expect(page).to have_content "REMAINING: €75,000,000" within "#project-#{project.id}-item" do page.find(".budget-list__action").click @@ -317,11 +317,13 @@ visit_budget expect(page).to have_content "ASSIGNED: €25,000,000" + expect(page).to have_content "REMAINING: €75,000,000" # Note that this is not a default alert box, this is the default browser # prompt for verifying the page unload. Therefore, `dismiss_prompt` is # used instead of `dismiss_confirm`. dismiss_prompt do + page.find(".focus-mode__close").click page.find(".logo-wrapper a").click end @@ -491,6 +493,7 @@ expect(page).to have_content("Budget vote completed") + page.find(".focus-mode__close").click page.find(".logo-wrapper a").click expect(page).to have_current_path decidim.root_path @@ -562,7 +565,7 @@ visit_budget - expect(page).to have_selector("[id^=project-]", count: 1) + expect(page).to have_selector("[id^=project-][id$=-item]", count: 1) end it "respects the projects_per_page setting when it matches total projects" do @@ -572,7 +575,7 @@ visit_budget - expect(page).to have_selector("[id^=project-]", count: 2) + expect(page).to have_selector("[id^=project-][id$=-item]", count: 2) end it "respects the projects_per_page setting when over total projects" do @@ -582,7 +585,7 @@ visit_budget - expect(page).to have_selector("[id^=project-]", count: 2) + expect(page).to have_selector("[id^=project-][id$=-item]", count: 2) end end diff --git a/decidim-core/app/cells/decidim/date_range/show.erb b/decidim-core/app/cells/decidim/date_range/show.erb index 7f294f07796f4..84d6efdf2377d 100644 --- a/decidim-core/app/cells/decidim/date_range/show.erb +++ b/decidim-core/app/cells/decidim/date_range/show.erb @@ -1,4 +1,4 @@ -
    +
    <% if same_day? %>
    <%= l start_time, format: "%d" %> diff --git a/decidim-core/app/cells/decidim/date_range_cell.rb b/decidim-core/app/cells/decidim/date_range_cell.rb index d0e43d70ac044..11039b7a701ce 100644 --- a/decidim-core/app/cells/decidim/date_range_cell.rb +++ b/decidim-core/app/cells/decidim/date_range_cell.rb @@ -31,6 +31,10 @@ def end_time model[:end] end + def extra_classes + model[:extra_classes] + end + def same_day? start_time.beginning_of_day == end_time.beginning_of_day end diff --git a/decidim-core/app/cells/decidim/focus_mode/show.erb b/decidim-core/app/cells/decidim/focus_mode/show.erb new file mode 100644 index 0000000000000..16e0310fe1449 --- /dev/null +++ b/decidim-core/app/cells/decidim/focus_mode/show.erb @@ -0,0 +1,39 @@ +
    + + +
    +
    +
    + <%= yield %> +
    +
    +
    +
    + +
    +
    + <% if opener_button %> + + <% end %> +
    diff --git a/decidim-core/app/cells/decidim/focus_mode_cell.rb b/decidim-core/app/cells/decidim/focus_mode_cell.rb new file mode 100644 index 0000000000000..1ccbe519047bf --- /dev/null +++ b/decidim-core/app/cells/decidim/focus_mode_cell.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require "decidim/diffy_extension" + +module Decidim + # This cell renders a dismissable overlay to highlight information about the current + # action being performed by the user + class FocusModeCell < Decidim::ViewModel + include Cell::ViewModel::Partial + include LayoutHelper + + def show(&block) + render(&block) + end + + def title + options[:title] + end + + def user + return unless current_user + + link_to current_user.name, decidim.account_path + end + + def opener_button + options[:opener_button] + end + end +end diff --git a/decidim-core/app/helpers/decidim/focus_mode_helper.rb b/decidim-core/app/helpers/decidim/focus_mode_helper.rb new file mode 100644 index 0000000000000..0bd961a4356e6 --- /dev/null +++ b/decidim-core/app/helpers/decidim/focus_mode_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Decidim + # Helpers related to focus mode + module FocusModeHelper + def focus_mode(opts, &body) + cell(FocusModeCell, nil, opts).call do + capture(&body) + end + end + end +end \ No newline at end of file diff --git a/decidim-core/app/packs/src/decidim/focus_mode.js.es6 b/decidim-core/app/packs/src/decidim/focus_mode.js.es6 new file mode 100644 index 0000000000000..400386661c03f --- /dev/null +++ b/decidim-core/app/packs/src/decidim/focus_mode.js.es6 @@ -0,0 +1,124 @@ +$(() => { + const $focusModeOn = $("[data-focus-on]"); + const $focusModeOff = $("[data-focus-off]"); + const $wrapper = $(".focus-mode__body"); + const $focusContent = $("[data-focus-body]"); + const $pageContent = $("#content"); + const $closer = $("[data-focus-close]"); + const $opener = $("[data-focus-open]"); + const $flashMessagesContainer = $(".focus-mode__flash-messages"); + + const $background = $(".title-bar, [data-set='nav-holder'], .process-header"); + + const $overlay = $(".omnipresent-banner, .cookie-warning"); + const $cookieButton = $(".cookie-bar__button"); + + const FADEOUT_TIME = 200; + + const flashMessagesObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.addedNodes !== null) { + var $nodes = $(mutation.addedNodes); + if ($nodes.filter(".flash.callout").length > 0) { + moveFlashMessages(); + } + } + }); + }); + + const watchFlashMessages = () => { + // Pass in the target node, as well as the observer options + flashMessagesObserver.observe($("#content")[0], { attributes: true, childList: true, characterData: true }); + }; + + const unwatchFlashMessages = () => { + flashMessagesObserver.disconnect(); + }; + + const moveFlashMessages = () => { + $(".flash.callout").appendTo($flashMessagesContainer); + }; + + const overlayHeight = () => { + var h = 0; + $overlay.outerHeight((i, v) => { + if ($($overlay[i]).is(":visible")) h += v; + }); + return h; + }; + + const moveToShowOverlay = () => { + const top = $(document).scrollTop(); + const height = overlayHeight(); + + if (top <= height) { + $focusModeOn.css({ top: `${height}px` }) + } else { + $focusModeOn.css({ top: "0px" }) + } + } + + const moveOverlay = () => { + if (!$overlay.length) return; + + if ($cookieButton.length) { + $cookieButton.on("click", moveToShowOverlay); + } + + moveToShowOverlay(); + window.addEventListener("scroll", moveToShowOverlay); + } + + const focusModeOn = function(fadeTime) { + if ($opener.length) $opener.fadeOut(fadeTime); + + $background.hide(fadeTime); + $pageContent.animate({ "margin-top": `${$focusModeOn.outerHeight() + overlayHeight() - 50}px` }, fadeTime); + + moveOverlay(); + moveFlashMessages(); + + $focusContent.fadeOut(fadeTime, () => { + $focusContent.detach().prependTo($wrapper); + $focusModeOn.fadeIn(fadeTime, () => { + $focusContent.fadeIn(fadeTime, () => {}); + }); + }); + + watchFlashMessages(); + } + + const focusModeOff = function(fadeTime) { + $focusContent.fadeOut(fadeTime); + $background.show(fadeTime); + $pageContent.animate({ "margin-top": "0px" }, fadeTime); + + $focusModeOn.fadeOut(fadeTime, () => { + $focusContent.detach().prependTo($focusModeOff); + $focusModeOff.fadeIn(fadeTime, () => { + $focusContent.fadeIn(fadeTime, () => {}); + if ($opener.length) $opener.fadeIn(fadeTime); + }); + }); + + unwatchFlashMessages(); + } + + const initializeFocusMode = () => { + const focusModePresent = !!$focusModeOn.length; + + $closer.on("click", () => { focusModeOff(FADEOUT_TIME) }); + + if ($opener.length) $opener.on("click", () => { focusModeOn(FADEOUT_TIME) }); + + if (focusModePresent > 0 && window.matchMedia('(min-width: 800px)').matches) { + focusModeOn(0); + } else { + focusModeOff(0); + } + } + + initializeFocusMode(); + + $(window).resize(initializeFocusMode); +}); diff --git a/decidim-core/app/packs/stylesheets/decidim/layouts/_focus_mode.scss b/decidim-core/app/packs/stylesheets/decidim/layouts/_focus_mode.scss new file mode 100644 index 0000000000000..660657ad44588 --- /dev/null +++ b/decidim-core/app/packs/stylesheets/decidim/layouts/_focus_mode.scss @@ -0,0 +1,63 @@ +.focus-mode { + position: fixed; + z-index: 1000; + width: 100%; + top: 0; + left: 0; + background: $medium-gray; + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3); + + &__title { + text-align: center; + } + + &__bar { + padding: 0.5em; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + align-items: center; + + &--right { + display: flex; + justify-content: right; + align-items: center; + gap: 1em; + text-align: right; + } + } + + &__close { + position: relative; + margin: 0; + right: 0; + top: 0; + line-height: 0.5em; + } + + &__wrapper { + background: white; + } + + &__body { + max-width: 75rem; + padding: 1em; + font-size: 80%; + margin: auto; + + // Reduce sizes of content as much as possible + .card, + .card__content { + margin: 0; + padding: 0; + border: none; + } + + ul { + margin-bottom: 0; + } + + .budget-summary__selected-list { + margin-top: 0; + } + } +} diff --git a/decidim-core/app/packs/stylesheets/decidim/layouts/_layouts.scss b/decidim-core/app/packs/stylesheets/decidim/layouts/_layouts.scss index 2a83ad4725832..6e2a723678500 100644 --- a/decidim-core/app/packs/stylesheets/decidim/layouts/_layouts.scss +++ b/decidim-core/app/packs/stylesheets/decidim/layouts/_layouts.scss @@ -1,3 +1,4 @@ +@import "stylesheets/decidim/layouts/focus_mode"; @import "stylesheets/decidim/layouts/highlighted_banner"; @import "stylesheets/decidim/layouts/home"; @import "stylesheets/decidim/layouts/logo"; diff --git a/decidim-core/app/packs/stylesheets/decidim/modules/_cards.scss b/decidim-core/app/packs/stylesheets/decidim/modules/_cards.scss index 499ceb6b30fab..e6db782b168c4 100644 --- a/decidim-core/app/packs/stylesheets/decidim/modules/_cards.scss +++ b/decidim-core/app/packs/stylesheets/decidim/modules/_cards.scss @@ -634,6 +634,10 @@ a .card__title{ pointer-events: none; } + &--inline{ + display: inline-block; + } + svg{ flex-basis: auto; } diff --git a/decidim-core/app/packs/stylesheets/decidim/modules/_extra.scss b/decidim-core/app/packs/stylesheets/decidim/modules/_extra.scss index c63ca46ba1ec7..7e5e94ba4df9d 100644 --- a/decidim-core/app/packs/stylesheets/decidim/modules/_extra.scss +++ b/decidim-core/app/packs/stylesheets/decidim/modules/_extra.scss @@ -32,6 +32,14 @@ .extra__date-container{ margin-bottom: 1rem; + + &--horizontal{ + margin-bottom: 1rem; + display: flex; + justify-content: center; + align-items: center; + gap: 2rem; + } } .extra__month{ diff --git a/decidim-core/config/locales/en.yml b/decidim-core/config/locales/en.yml index db348961a22f6..fc688f3656bad 100644 --- a/decidim-core/config/locales/en.yml +++ b/decidim-core/config/locales/en.yml @@ -695,6 +695,8 @@ en: source: Source title: Fingerprint value: Value + focus_mode: + focus_mode: Enter focus mode followers: followers_count: one: "%{count} follower" diff --git a/decidim-core/lib/decidim/core/test.rb b/decidim-core/lib/decidim/core/test.rb index f2121bcd68a2e..f069438305216 100644 --- a/decidim-core/lib/decidim/core/test.rb +++ b/decidim-core/lib/decidim/core/test.rb @@ -10,6 +10,7 @@ require "decidim/core/test/shared_examples/has_attachments" require "decidim/core/test/shared_examples/has_attachment_collections" require "decidim/core/test/shared_examples/has_component" +require "decidim/core/test/shared_examples/has_focus_mode" require "decidim/core/test/shared_examples/has_scope" require "decidim/core/test/shared_examples/has_category" require "decidim/core/test/shared_examples/has_reference" diff --git a/decidim-core/lib/decidim/core/test/shared_examples/has_focus_mode.rb b/decidim-core/lib/decidim/core/test/shared_examples/has_focus_mode.rb new file mode 100644 index 0000000000000..44ccd99f1acf8 --- /dev/null +++ b/decidim-core/lib/decidim/core/test/shared_examples/has_focus_mode.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require "spec_helper" + +shared_examples_for "has focus mode" do |content| + it "has the necessary elements" do + expect(page).to have_selector("#focus-mode") + expect(page).to have_selector("#off-focus-mode") + end + + it "is opened by default" do + within "#focus-mode" do + expect(page).to have_content(content) + end + end + + it "can be closed" do + expect(page).to have_selector(".focus-mode__close") + + page.find(".focus-mode__close").click + + within "#focus-mode" do + expect(page).not_to have_content(content) + end + + within "#off-focus-mode" do + expect(page).to have_content(content) + end + end +end diff --git a/decidim-core/spec/cells/decidim/date_range_cell_spec.rb b/decidim-core/spec/cells/decidim/date_range_cell_spec.rb index 0490c13e7add9..5f870848a93b1 100644 --- a/decidim-core/spec/cells/decidim/date_range_cell_spec.rb +++ b/decidim-core/spec/cells/decidim/date_range_cell_spec.rb @@ -10,7 +10,8 @@ let(:my_cell) { cell("decidim/date_range", model) } let!(:organization) { create(:organization) } let(:user) { create(:user, :confirmed, organization: organization) } - let(:model) { { start: start_time, end: end_time } } + let(:model) { { start: start_time, end: end_time, extra_classes: extra_classes } } + let(:extra_classes) { "extra__class" } let(:base_time) { Time.zone.parse(Time.zone.now.strftime("%Y-%m-%d 12:00:00")) } let(:start_time) { base_time - 1.hour } let(:start_time_past_year) { base_time - 1.year } @@ -25,6 +26,10 @@ it "renders a Date card" do expect(subject).to have_css(".extra__date-container") end + + it "renders a the extra classes" do + expect(subject).to have_css(".extra__class") + end end context "when start and end time are on the same date" do diff --git a/decidim-core/spec/cells/decidim/focus_mode_cell_spec.rb b/decidim-core/spec/cells/decidim/focus_mode_cell_spec.rb new file mode 100644 index 0000000000000..e170685ca7814 --- /dev/null +++ b/decidim-core/spec/cells/decidim/focus_mode_cell_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe Decidim::FocusModeCell, type: :cell do + subject { my_cell.call { "content" } } + + controller Decidim::Budgets::BudgetsController + + let(:my_cell) { cell("decidim/focus_mode", nil, options) } + let!(:organization) { create(:organization) } + let(:user) { create(:user, :confirmed, organization: organization) } + let(:options) { { title: "A title for focus mode", opener_button: opener_button, context: { current_user: user, current_organization: organization } } } + let(:opener_button) { false } + let(:decidim) { Decidim::Core::Engine.routes } + + it "renders the content passed as a block" do + expect(subject).to have_content("content") + end + + it "renders the title passed in the options" do + expect(subject).to have_content("A title for focus mode") + end + + it "renders the organization name linking to the home page" do + expect(subject).to have_link(organization.name, href: "http://#{organization.host}/") + end + + context "when opener_button option is false" do + let(:opener_button) { false } + + it "does not render the opener button" do + expect(subject).not_to have_css("[data-focus-open]") + end + end + + context "when opener_button option is true" do + let(:opener_button) { true } + + it "renders the opener button" do + expect(subject).to have_css("[data-focus-open]") + end + end + + context "when the user is logged in" do + it "renders the user name with a link to the account page" do + expect(subject).to have_css(".focus-mode__user") + expect(subject).to have_link(user.name, href: "/account") + end + end + + context "when the user is not logged in" do + let(:user) { nil } + + it "does not render the user name" do + expect(subject).not_to have_css(".focus-mode__user") + end + end +end