decidim-budgets 0.25.2 → 0.26.0.rc1
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/assets/stylesheets/decidim/budgets/budget/_budget-vote-button.scss +22 -0
- data/app/cells/decidim/budgets/budget_information_modal/show.erb +3 -3
- data/app/cells/decidim/budgets/budget_list_item/show.erb +31 -15
- data/app/cells/decidim/budgets/budget_list_item_cell.rb +30 -1
- data/app/cells/decidim/budgets/budgets_header/show.erb +1 -1
- data/app/cells/decidim/budgets/budgets_list/card_list.erb +17 -6
- data/app/cells/decidim/budgets/budgets_list/show.erb +2 -3
- data/app/cells/decidim/budgets/budgets_list/voted.erb +6 -0
- data/app/cells/decidim/budgets/project_list_item/project_data.erb +1 -1
- data/app/cells/decidim/budgets/{project_list_item/project_data_vote_button.erb → project_vote_button/show.erb} +1 -0
- data/app/cells/decidim/budgets/project_vote_button_cell.rb +10 -0
- data/app/commands/decidim/budgets/add_line_item.rb +5 -1
- data/app/controllers/concerns/decidim/budgets/admin/filterable.rb +51 -0
- data/app/controllers/decidim/budgets/admin/projects_controller.rb +6 -1
- data/app/controllers/decidim/budgets/line_items_controller.rb +2 -2
- data/app/helpers/decidim/budgets/admin/filterable_helper.rb +10 -0
- data/app/models/decidim/budgets/project.rb +28 -1
- data/app/packs/entrypoints/decidim_budgets.js +1 -0
- data/app/packs/src/decidim/budgets/exit_handler.js +131 -0
- data/app/packs/src/decidim/budgets/projects.js +9 -39
- data/app/packs/stylesheets/decidim/budgets/budget/_budget-list.scss +35 -1
- data/app/views/decidim/budgets/admin/projects/index.html.erb +16 -5
- data/app/views/decidim/budgets/projects/_exit_modal.html.erb +22 -0
- data/app/views/decidim/budgets/projects/_filters_small_view.html.erb +3 -3
- data/app/views/decidim/budgets/projects/_project_budget_button.html.erb +17 -38
- data/app/views/decidim/budgets/projects/index.html.erb +25 -22
- data/app/views/decidim/budgets/projects/show.html.erb +41 -38
- data/config/locales/ca.yml +3 -0
- data/config/locales/cs.yml +23 -0
- data/config/locales/de.yml +9 -0
- data/config/locales/en.yml +23 -0
- data/config/locales/es.yml +23 -0
- data/config/locales/eu.yml +3 -0
- data/config/locales/fi-plain.yml +23 -0
- data/config/locales/fi.yml +23 -0
- data/config/locales/fr-CA.yml +11 -0
- data/config/locales/fr.yml +13 -2
- data/config/locales/gl.yml +9 -0
- data/config/locales/it.yml +9 -0
- data/config/locales/ja.yml +28 -5
- data/config/locales/lb-LU.yml +294 -0
- data/config/locales/nl.yml +18 -0
- data/config/locales/pl.yml +2 -0
- data/config/locales/pt-BR.yml +1 -1
- data/config/locales/pt.yml +3 -0
- data/config/locales/ro-RO.yml +15 -0
- data/config/locales/sv.yml +3 -0
- data/config/locales/val-ES.yml +1 -0
- data/lib/decidim/budgets/version.rb +1 -1
- metadata +23 -17
- data/app/cells/decidim/budgets/budgets_list/highlighted.erb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5faa45ba2c53c8c620e02d864b28790d7a776a82aa4650fdf6e5bfa36353adb3
|
|
4
|
+
data.tar.gz: d4698f56fef1acacb46f2f37f0eea903c543814d063b6473e7ebfa5677113fac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a19091bcad973926f835062473591c953166beda0fce9f7529cc1902569c40aa0fb9526fa4f25d8810ca62a9e1d2fb9d93a3e32845f3e9f5f8cc2f0966e432e5
|
|
7
|
+
data.tar.gz: 9f10d173bdf303db02468bd2bf3fcb78d9f18a052d148e955d934d7bdb1df78150bd90136442d63eb7627e9cc03af1c584ddcbd417aba49188712ab07eb349c8
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.budget-vote-button.expanded{
|
|
2
|
+
display: flex;
|
|
3
|
+
text-align: left;
|
|
4
|
+
justify-content: space-between;
|
|
5
|
+
align-items: center;
|
|
6
|
+
|
|
7
|
+
span{
|
|
8
|
+
font-size: 1rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&.added{
|
|
12
|
+
background-color: tint($success, 80%);
|
|
13
|
+
color: $body-font-color;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&:not(.added){
|
|
17
|
+
.budget-list__action{
|
|
18
|
+
border-color: white;
|
|
19
|
+
color: white;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
<button class="link" data-open="budget-modal-info" aria-controls="budget-modal-info" aria-haspopup="
|
|
1
|
+
<button class="link" data-open="budget-modal-info" aria-controls="budget-modal-info" aria-haspopup="dialog" tabindex="0">
|
|
2
2
|
<%= t(:more_information, scope: i18n_scope) %>
|
|
3
3
|
</button>
|
|
4
4
|
|
|
5
|
-
<div class="reveal" data-reveal id="budget-modal-info">
|
|
5
|
+
<div class="reveal" data-reveal id="budget-modal-info" aria-modal="true" aria-labelledby="budget-modal-info-label">
|
|
6
6
|
<div class="reveal__header">
|
|
7
|
-
<h3 class="reveal__title"><%= decidim_sanitize(component_name) %></h3>
|
|
7
|
+
<h3 id="budget-modal-info-label" class="reveal__title"><%= decidim_sanitize(component_name) %></h3>
|
|
8
8
|
<button class="close-button" data-close aria-label="<%= t(:close_modal, scope: i18n_scope) %>" type="button">
|
|
9
9
|
<span aria-hidden="true">×</span>
|
|
10
10
|
</button>
|
|
@@ -1,22 +1,38 @@
|
|
|
1
|
-
<div class="<%= card_class %>">
|
|
2
|
-
<div class="
|
|
1
|
+
<div class="<%= card_class %> budget-list__item budget-list__item-cell">
|
|
2
|
+
<div class="budget-list__text flex-horizontal">
|
|
3
3
|
<%= link_to budget_path(budget), class: link_class do %>
|
|
4
|
-
|
|
5
|
-
<strong>
|
|
6
|
-
<%= translated_attribute(title) %>
|
|
7
|
-
</strong>
|
|
8
|
-
<span class="button tiny success card--list__check card--list__check--disabled">
|
|
9
|
-
<%= icon "check", class: "icon--small", role: "img", aria_label: t("decidim.budgets.budget_list_item.voting_finished") %>
|
|
10
|
-
</span>
|
|
11
|
-
<% else %>
|
|
4
|
+
<h5 class="card--list__heading">
|
|
12
5
|
<%= translated_attribute(title) %>
|
|
6
|
+
</h5>
|
|
7
|
+
<% end %>
|
|
8
|
+
|
|
9
|
+
<h5>
|
|
10
|
+
<strong>
|
|
11
|
+
<%= budget_to_currency(total_budget) %>
|
|
12
|
+
</strong>
|
|
13
|
+
</h5>
|
|
14
|
+
|
|
15
|
+
<%= decidim_sanitize html_truncate(translated_attribute(description), length: 140) %>
|
|
16
|
+
</div>
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
<% if !voting_finished? %>
|
|
19
|
+
<div class="budget-list__icon mr-s">
|
|
20
|
+
<% if voted? %>
|
|
21
|
+
<span class="button tiny success card--list__check card--list__check--disabled card--list__check--inline">
|
|
22
|
+
<%= icon "check", class: "icon--small", role: "img", aria_label: t("decidim.budgets.budget_list_item.voting_finished") %>
|
|
23
|
+
</span>
|
|
24
|
+
<% elsif progress? %>
|
|
25
|
+
<span class="button tiny warning card--list__check card--list__check--disabled card--list__check--inline">
|
|
26
|
+
<%= icon "bookmark", class: "icon--small", role: "img", aria_label: t("decidim.budgets.budget_list_item.voting_started") %>
|
|
27
|
+
</span>
|
|
19
28
|
<% end %>
|
|
29
|
+
</div>
|
|
30
|
+
<% end %>
|
|
31
|
+
|
|
32
|
+
<div class="budget-list__data">
|
|
33
|
+
<%= link_to budget_path(budget), class: "button button--sc expanded #{button_class} mb-none" do %>
|
|
34
|
+
<span><%= button_text %></span>
|
|
35
|
+
<%= icon "chevron-right", class: "icon--small", role: "img" %>
|
|
20
36
|
<% end %>
|
|
21
37
|
</div>
|
|
22
38
|
</div>
|
|
@@ -4,9 +4,15 @@ module Decidim
|
|
|
4
4
|
module Budgets
|
|
5
5
|
# This cell renders the budget item list in the budgets list
|
|
6
6
|
class BudgetListItemCell < BaseCell
|
|
7
|
+
include Decidim::SanitizeHelper
|
|
8
|
+
include Decidim::ApplicationHelper
|
|
9
|
+
include ActiveSupport::NumberHelper
|
|
10
|
+
include Decidim::Budgets::ProjectsHelper
|
|
11
|
+
|
|
7
12
|
delegate :voting_finished?, to: :controller
|
|
13
|
+
delegate :highlighted, to: :current_workflow
|
|
8
14
|
|
|
9
|
-
property :title
|
|
15
|
+
property :title, :description, :total_budget
|
|
10
16
|
alias budget model
|
|
11
17
|
|
|
12
18
|
private
|
|
@@ -17,6 +23,7 @@ module Decidim
|
|
|
17
23
|
list << "card--list__data-added" if voted?
|
|
18
24
|
list << "card--list__data-progress" if progress?
|
|
19
25
|
end
|
|
26
|
+
list << "budget--highlighted" if highlighted?
|
|
20
27
|
end.join(" ")
|
|
21
28
|
end
|
|
22
29
|
|
|
@@ -32,9 +39,31 @@ module Decidim
|
|
|
32
39
|
current_user && status == :progress
|
|
33
40
|
end
|
|
34
41
|
|
|
42
|
+
def highlighted?
|
|
43
|
+
highlighted.include?(budget)
|
|
44
|
+
end
|
|
45
|
+
|
|
35
46
|
def status
|
|
36
47
|
@status ||= current_workflow.status(budget)
|
|
37
48
|
end
|
|
49
|
+
|
|
50
|
+
def button_class
|
|
51
|
+
"hollow" if voted? || !highlighted?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def button_text
|
|
55
|
+
key = if current_workflow.vote_allowed?(budget) && !voted?
|
|
56
|
+
progress? ? :progress : :vote
|
|
57
|
+
else
|
|
58
|
+
:show
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
t(key, scope: i18n_scope)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def i18n_scope
|
|
65
|
+
"decidim.budgets.budgets_list"
|
|
66
|
+
end
|
|
38
67
|
end
|
|
39
68
|
end
|
|
40
69
|
end
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
<%# show highlighted budgets first %>
|
|
2
|
+
<% if highlighted.any? %>
|
|
3
|
+
<div id="highlighted-budgets" class="card card--list budget-list">
|
|
4
|
+
<% highlighted.each do |budget| %>
|
|
5
|
+
<%= cell("decidim/budgets/budget_list_item", budget) %>
|
|
6
|
+
<% end %>
|
|
7
|
+
</div>
|
|
8
|
+
<% end %>
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
<% non_highlighted = (budgets - highlighted - voted) %>
|
|
11
|
+
|
|
12
|
+
<% if non_highlighted.any? %>
|
|
13
|
+
<div id="budgets" class="card card--list budget-list">
|
|
14
|
+
<% non_highlighted.each do |budget| %>
|
|
15
|
+
<%= cell("decidim/budgets/budget_list_item", budget) %>
|
|
16
|
+
<% end %>
|
|
17
|
+
</div>
|
|
18
|
+
<% end %>
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
<div class="row">
|
|
2
2
|
<div class="columns medium-7 mediumlarge-8">
|
|
3
|
-
<% if !voting_finished? && (
|
|
3
|
+
<% if !voting_finished? && (voted?) %>
|
|
4
4
|
<div class="section">
|
|
5
5
|
<h3 class="section-heading">
|
|
6
6
|
<%= t(:my_budgets, scope: i18n_scope) %>
|
|
7
7
|
</h3>
|
|
8
8
|
|
|
9
|
-
<%= render :highlighted %>
|
|
10
9
|
<%= render :voted %>
|
|
11
10
|
</div>
|
|
12
11
|
<% end %>
|
|
13
12
|
|
|
14
13
|
<div class="row">
|
|
15
|
-
<div class="columns mediumlarge-
|
|
14
|
+
<div class="columns mediumlarge-12">
|
|
16
15
|
<%= render :card_list %>
|
|
17
16
|
</div>
|
|
18
17
|
</div>
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
<%= t(:voted_on, scope: i18n_scope, links: budgets_link_list(voted)) %>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
+
<div id="voted-budgets" class="card card--list budget-list">
|
|
8
|
+
<% voted.each do |budget| %>
|
|
9
|
+
<%= cell("decidim/budgets/budget_list_item", budget) %>
|
|
10
|
+
<% end %>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
7
13
|
<% if finished? %>
|
|
8
14
|
<p class="lead">
|
|
9
15
|
<%= t(:finished_message, scope: i18n_scope) %>
|
|
@@ -14,6 +14,6 @@
|
|
|
14
14
|
<%= cell("decidim/budgets/project_voted_hint", model, class: "display-block margin-top-1") if current_order_checked_out? && resource_added? %>
|
|
15
15
|
</span>
|
|
16
16
|
|
|
17
|
-
<%=
|
|
17
|
+
<%= cell("decidim/budgets/project_vote_button", model) if !current_order_checked_out? && voting_open? %>
|
|
18
18
|
<% end %>
|
|
19
19
|
</div>
|
|
@@ -23,7 +23,7 @@ module Decidim
|
|
|
23
23
|
# Returns nothing.
|
|
24
24
|
def call
|
|
25
25
|
transaction do
|
|
26
|
-
return broadcast(:invalid) if voting_not_enabled? || order.checked_out?
|
|
26
|
+
return broadcast(:invalid) if voting_not_enabled? || order.checked_out? || exceeds_budget?
|
|
27
27
|
|
|
28
28
|
add_line_item
|
|
29
29
|
broadcast(:ok, order)
|
|
@@ -44,6 +44,10 @@ module Decidim
|
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
def exceeds_budget?
|
|
48
|
+
order.allocation_for(project) + order.total > order.available_allocation
|
|
49
|
+
end
|
|
50
|
+
|
|
47
51
|
def voting_not_enabled?
|
|
48
52
|
project.component.current_settings.votes != "enabled"
|
|
49
53
|
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
|
|
5
|
+
module Decidim
|
|
6
|
+
module Budgets
|
|
7
|
+
module Admin
|
|
8
|
+
module Filterable
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
included do
|
|
12
|
+
include Decidim::Admin::Filterable
|
|
13
|
+
|
|
14
|
+
helper Decidim::Budgets::Admin::FilterableHelper
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def base_query
|
|
19
|
+
collection
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def search_field_predicate
|
|
23
|
+
:id_string_or_title_cont
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def filters
|
|
27
|
+
[
|
|
28
|
+
:scope_id_eq,
|
|
29
|
+
:category_id_eq,
|
|
30
|
+
:selected_at_null
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def filters_with_values
|
|
35
|
+
{
|
|
36
|
+
scope_id_eq: scope_ids_hash(scopes.top_level),
|
|
37
|
+
category_id_eq: category_ids_hash(categories.first_class),
|
|
38
|
+
selected_at_null: [true, false]
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Can't user `super` here, because it does not belong to a superclass
|
|
43
|
+
# but to a concern.
|
|
44
|
+
def dynamically_translated_filters
|
|
45
|
+
[:scope_id_eq, :category_id_eq]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -7,9 +7,14 @@ module Decidim
|
|
|
7
7
|
class ProjectsController < Admin::ApplicationController
|
|
8
8
|
include Decidim::ApplicationHelper
|
|
9
9
|
include Decidim::Proposals::Admin::Picker if Decidim::Budgets.enable_proposal_linking
|
|
10
|
+
include Decidim::Budgets::Admin::Filterable
|
|
10
11
|
|
|
11
12
|
helper_method :projects, :finished_orders, :pending_orders, :present
|
|
12
13
|
|
|
14
|
+
def collection
|
|
15
|
+
@collection ||= budget.projects.page(params[:page]).per(15)
|
|
16
|
+
end
|
|
17
|
+
|
|
13
18
|
def new
|
|
14
19
|
enforce_permission_to :create, :project
|
|
15
20
|
@form = form(ProjectForm).from_params(
|
|
@@ -72,7 +77,7 @@ module Decidim
|
|
|
72
77
|
private
|
|
73
78
|
|
|
74
79
|
def projects
|
|
75
|
-
@projects ||=
|
|
80
|
+
@projects ||= filtered_collection
|
|
76
81
|
end
|
|
77
82
|
|
|
78
83
|
def orders
|
|
@@ -20,7 +20,7 @@ module Decidim
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
on(:invalid) do
|
|
23
|
-
render
|
|
23
|
+
format.js { render "update_budget", status: :unprocessable_entity }
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -35,7 +35,7 @@ module Decidim
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
on(:invalid) do
|
|
38
|
-
render
|
|
38
|
+
format.js { render "update_budget", status: :unprocessable_entity }
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
end
|
|
@@ -46,7 +46,8 @@ module Decidim
|
|
|
46
46
|
# delimiter. Otherwise e.g. ID 2 would match ID "26" in the original
|
|
47
47
|
# array. This is why we search for match ",2," instead to get the actual
|
|
48
48
|
# position for ID 2.
|
|
49
|
-
|
|
49
|
+
concat_ids = connection.quote(",#{ids.join(",")},")
|
|
50
|
+
order(Arel.sql("position(concat(',', id::text, ',') in #{concat_ids})"))
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
def self.log_presenter_class_for(_log)
|
|
@@ -92,6 +93,32 @@ module Decidim
|
|
|
92
93
|
def attachment_context
|
|
93
94
|
:admin
|
|
94
95
|
end
|
|
96
|
+
|
|
97
|
+
ransacker :id_string do
|
|
98
|
+
Arel.sql(%{cast("decidim_budgets_projects"."id" as text)})
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Allow ransacker to search for a key in a hstore column (`title`.`en`)
|
|
102
|
+
ransacker :title do |parent|
|
|
103
|
+
Arel::Nodes::InfixOperation.new("->>", parent.table[:title], Arel::Nodes.build_quoted(I18n.locale.to_s))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
ransacker :selected do
|
|
107
|
+
Arel.sql(%{("decidim_budgets_projects"."selected_at")::text})
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
ransacker :confirmed_orders_count do
|
|
111
|
+
query = <<-SQL.squish
|
|
112
|
+
(
|
|
113
|
+
SELECT COUNT(decidim_budgets_line_items.decidim_order_id)
|
|
114
|
+
FROM decidim_budgets_line_items
|
|
115
|
+
LEFT JOIN decidim_budgets_orders ON decidim_budgets_orders.id = decidim_budgets_line_items.decidim_order_id
|
|
116
|
+
WHERE decidim_budgets_orders.checked_out_at IS NOT NULL
|
|
117
|
+
AND decidim_budgets_projects.id = decidim_budgets_line_items.decidim_project_id
|
|
118
|
+
)
|
|
119
|
+
SQL
|
|
120
|
+
Arel.sql(query)
|
|
121
|
+
end
|
|
95
122
|
end
|
|
96
123
|
end
|
|
97
124
|
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const currentAllocationZero = () => {
|
|
2
|
+
const $budgetSummary = $(".budget-summary__progressbox");
|
|
3
|
+
return parseInt($budgetSummary.attr("data-current-allocation"), 10) === 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const isSafeUrl = (exitUrl) => {
|
|
7
|
+
if (!exitUrl) {
|
|
8
|
+
return false
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const safeUrls = [
|
|
12
|
+
$(".budget-summary").attr("data-safe-url").split("?")[0],
|
|
13
|
+
`${location.pathname}#`,
|
|
14
|
+
`${location.href}#`,
|
|
15
|
+
"#"
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
let safe = false;
|
|
19
|
+
safeUrls.forEach((url) => {
|
|
20
|
+
if (exitUrl.startsWith(url)) {
|
|
21
|
+
safe = true
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return safe;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const allowExitFrom = ($el) => {
|
|
29
|
+
if (currentAllocationZero()) {
|
|
30
|
+
return true
|
|
31
|
+
} else if ($el.attr("target") === "_blank") {
|
|
32
|
+
return true;
|
|
33
|
+
} else if ($el.parents("#loginModal").length > 0) {
|
|
34
|
+
return true;
|
|
35
|
+
} else if ($el.parents("#authorizationModal").length > 0) {
|
|
36
|
+
return true;
|
|
37
|
+
} else if ($el.attr("id") === "exit-notification-link") {
|
|
38
|
+
return true;
|
|
39
|
+
} else if ($el.parents(".voting-wrapper").length > 0) {
|
|
40
|
+
return true;
|
|
41
|
+
} else if (isSafeUrl($el.attr("href"))) {
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Don't show browser's default confirmation panel when visit current_path is called in tests.
|
|
49
|
+
const testReload = (initialLocation) => {
|
|
50
|
+
if (navigator && navigator.webdriver && initialLocation === location.href) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
$(() => {
|
|
58
|
+
const $exitNotification = $("#exit-notification");
|
|
59
|
+
const $exitLink = $("#exit-notification-link");
|
|
60
|
+
const defaultExitUrl = $exitLink.attr("href");
|
|
61
|
+
const defaultExitLinkText = $exitLink.text();
|
|
62
|
+
let exitLinkText = defaultExitLinkText;
|
|
63
|
+
const initialLocation = location.href;
|
|
64
|
+
|
|
65
|
+
if ($exitNotification.length < 1) {
|
|
66
|
+
// Do not apply when not inside the voting pipeline
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const openExitNotification = (url, method = null) => {
|
|
71
|
+
if (method && method !== "get") {
|
|
72
|
+
$exitLink.attr("data-method", method);
|
|
73
|
+
} else {
|
|
74
|
+
$exitLink.removeAttr("data-method");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
$exitLink.attr("href", url);
|
|
78
|
+
$exitLink.html(exitLinkText);
|
|
79
|
+
$exitNotification.foundation("open");
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Handle "beforeunload"
|
|
83
|
+
window.allowExit = false;
|
|
84
|
+
$(document).on("click", "a", (event) => {
|
|
85
|
+
exitLinkText = defaultExitLinkText;
|
|
86
|
+
window.allowExit = false;
|
|
87
|
+
|
|
88
|
+
const $link = $(event.currentTarget);
|
|
89
|
+
if (allowExitFrom($link)) {
|
|
90
|
+
window.allowExit = true;
|
|
91
|
+
} else {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
openExitNotification($link.attr("href"), $link.data("method"));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
// Custom handling for the header sign out so that it won't trigger the
|
|
97
|
+
// logout form submit and so that it changes the exit link text. This does
|
|
98
|
+
// not trigger the document link click listener because it has the
|
|
99
|
+
// data-method attribute to trigger a form submit event.
|
|
100
|
+
$(".header a.sign-out-link").on("click", (event) => {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
event.stopPropagation();
|
|
103
|
+
|
|
104
|
+
const $link = $(event.currentTarget);
|
|
105
|
+
exitLinkText = $link.text();
|
|
106
|
+
openExitNotification($link.attr("href"), $link.data("method"));
|
|
107
|
+
});
|
|
108
|
+
// Custom handling for the exit link which needs to change the exit link
|
|
109
|
+
// text to the default text as this is not handled by the document click
|
|
110
|
+
// listener.
|
|
111
|
+
$("a[data-open='exit-notification']").on("click", () => {
|
|
112
|
+
exitLinkText = defaultExitLinkText;
|
|
113
|
+
openExitNotification(defaultExitUrl);
|
|
114
|
+
});
|
|
115
|
+
// Allow all form submits on the page, including language change and sign
|
|
116
|
+
// out form (when triggered by the exit link click).
|
|
117
|
+
$(document).on("submit", "form", () => {
|
|
118
|
+
window.allowExit = true;
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
window.addEventListener("beforeunload", (event) => {
|
|
122
|
+
const allowExit = window.allowExit;
|
|
123
|
+
window.allowExit = false;
|
|
124
|
+
|
|
125
|
+
if (allowExit || testReload(initialLocation)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
event.returnValue = true;
|
|
130
|
+
});
|
|
131
|
+
});
|
|
@@ -3,28 +3,28 @@ $(() => {
|
|
|
3
3
|
const $budgetSummaryTotal = $(".budget-summary__total");
|
|
4
4
|
const $budgetExceedModal = $("#budget-excess");
|
|
5
5
|
const $budgetSummary = $(".budget-summary__progressbox");
|
|
6
|
+
const $voteButton = $(".budget-vote-button");
|
|
6
7
|
const totalAllocation = parseInt($budgetSummaryTotal.attr("data-total-allocation"), 10);
|
|
7
8
|
|
|
8
9
|
const cancelEvent = (event) => {
|
|
10
|
+
$(event.currentTarget).removeClass("loading-spinner");
|
|
9
11
|
event.stopPropagation();
|
|
10
12
|
event.preventDefault();
|
|
11
13
|
};
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} else if ($el.parents("#authorizationModal").length > 0) {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
15
|
+
$voteButton.on("click", "span", () => {
|
|
16
|
+
$(".budget-list__action").click();
|
|
17
|
+
});
|
|
22
18
|
|
|
23
19
|
$projects.on("click", ".budget-list__action", (event) => {
|
|
24
20
|
const currentAllocation = parseInt($budgetSummary.attr("data-current-allocation"), 10);
|
|
25
21
|
const $currentTarget = $(event.currentTarget);
|
|
26
22
|
const projectAllocation = parseInt($currentTarget.attr("data-allocation"), 10);
|
|
27
23
|
|
|
24
|
+
if (!$currentTarget.attr("data-open")) {
|
|
25
|
+
$currentTarget.addClass("loading-spinner");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
28
|
if ($currentTarget.attr("disabled")) {
|
|
29
29
|
cancelEvent(event);
|
|
30
30
|
} else if (($currentTarget.attr("data-add") === "true") && ((currentAllocation + projectAllocation) > totalAllocation)) {
|
|
@@ -32,34 +32,4 @@ $(() => {
|
|
|
32
32
|
cancelEvent(event);
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
|
-
|
|
36
|
-
if ($("#order-progress [data-toggle=budget-confirm]").length > 0) {
|
|
37
|
-
const safeUrl = $(".budget-summary").attr("data-safe-url").split("?")[0];
|
|
38
|
-
$(document).on("click", "a", (event) => {
|
|
39
|
-
if (allowExitFrom($(event.currentTarget))) {
|
|
40
|
-
window.exitUrl = null;
|
|
41
|
-
} else {
|
|
42
|
-
window.exitUrl = event.currentTarget.href;
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
$(document).on("submit", "form", (event) => {
|
|
46
|
-
if (allowExitFrom($(event.currentTarget))) {
|
|
47
|
-
window.exitUrl = null;
|
|
48
|
-
} else {
|
|
49
|
-
window.exitUrl = event.currentTarget.action;
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
window.addEventListener("beforeunload", (event) => {
|
|
54
|
-
const currentAllocation = parseInt($budgetSummary.attr("data-current-allocation"), 10);
|
|
55
|
-
const exitUrl = window.exitUrl;
|
|
56
|
-
window.exitUrl = null;
|
|
57
|
-
|
|
58
|
-
if (currentAllocation === 0 || (exitUrl && exitUrl.startsWith(safeUrl))) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
event.returnValue = true;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
35
|
});
|