decidim-lausanne-budgets 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +141 -0
  3. data/Rakefile +93 -0
  4. data/app/cells/decidim/lausanne/budgets/base_cell.rb +24 -0
  5. data/app/cells/decidim/lausanne/budgets/budget_cell.rb +23 -0
  6. data/app/cells/decidim/lausanne/budgets/budget_information_modal/show.erb +21 -0
  7. data/app/cells/decidim/lausanne/budgets/budget_information_modal_cell.rb +24 -0
  8. data/app/cells/decidim/lausanne/budgets/budget_list_item/show.erb +21 -0
  9. data/app/cells/decidim/lausanne/budgets/budget_list_item_cell.rb +43 -0
  10. data/app/cells/decidim/lausanne/budgets/budget_m/data.erb +12 -0
  11. data/app/cells/decidim/lausanne/budgets/budget_m/footer.erb +5 -0
  12. data/app/cells/decidim/lausanne/budgets/budget_m_cell.rb +18 -0
  13. data/app/cells/decidim/lausanne/budgets/budgets_header/show.erb +7 -0
  14. data/app/cells/decidim/lausanne/budgets/budgets_header_cell.rb +16 -0
  15. data/app/cells/decidim/lausanne/budgets/budgets_list/card_list.erb +7 -0
  16. data/app/cells/decidim/lausanne/budgets/budgets_list/highlighted.erb +11 -0
  17. data/app/cells/decidim/lausanne/budgets/budgets_list/show.erb +20 -0
  18. data/app/cells/decidim/lausanne/budgets/budgets_list/voted.erb +43 -0
  19. data/app/cells/decidim/lausanne/budgets/budgets_list_cell.rb +40 -0
  20. data/app/cells/decidim/lausanne/budgets/limit_announcement_cell.rb +47 -0
  21. data/app/cells/decidim/lausanne/budgets/project_cell.rb +23 -0
  22. data/app/cells/decidim/lausanne/budgets/project_list_item/project_data.erb +19 -0
  23. data/app/cells/decidim/lausanne/budgets/project_list_item/project_data_vote_button.erb +22 -0
  24. data/app/cells/decidim/lausanne/budgets/project_list_item/project_image.erb +5 -0
  25. data/app/cells/decidim/lausanne/budgets/project_list_item/project_text.erb +23 -0
  26. data/app/cells/decidim/lausanne/budgets/project_list_item/show.erb +5 -0
  27. data/app/cells/decidim/lausanne/budgets/project_list_item_cell.rb +75 -0
  28. data/app/cells/decidim/lausanne/budgets/project_m/data.erb +12 -0
  29. data/app/cells/decidim/lausanne/budgets/project_m/footer.erb +5 -0
  30. data/app/cells/decidim/lausanne/budgets/project_m_cell.rb +24 -0
  31. data/app/cells/decidim/lausanne/budgets/project_selected_status_cell.rb +30 -0
  32. data/app/cells/decidim/lausanne/budgets/project_tags/show.erb +4 -0
  33. data/app/cells/decidim/lausanne/budgets/project_tags_cell.rb +20 -0
  34. data/app/cells/decidim/lausanne/budgets/project_voted_hint_cell.rb +35 -0
  35. data/app/cells/decidim/lausanne/budgets/project_votes_count_cell.rb +46 -0
  36. data/app/commands/decidim/lausanne/budgets/add_line_item.rb +54 -0
  37. data/app/commands/decidim/lausanne/budgets/admin/create_budget.rb +50 -0
  38. data/app/commands/decidim/lausanne/budgets/admin/create_project.rb +71 -0
  39. data/app/commands/decidim/lausanne/budgets/admin/destroy_budget.rb +44 -0
  40. data/app/commands/decidim/lausanne/budgets/admin/destroy_project.rb +44 -0
  41. data/app/commands/decidim/lausanne/budgets/admin/import_proposals_to_budgets.rb +87 -0
  42. data/app/commands/decidim/lausanne/budgets/admin/update_budget.rb +50 -0
  43. data/app/commands/decidim/lausanne/budgets/admin/update_project.rb +79 -0
  44. data/app/commands/decidim/lausanne/budgets/cancel_order.rb +46 -0
  45. data/app/commands/decidim/lausanne/budgets/checkout.rb +43 -0
  46. data/app/commands/decidim/lausanne/budgets/command.rb +16 -0
  47. data/app/commands/decidim/lausanne/budgets/create_user_record.rb +39 -0
  48. data/app/commands/decidim/lausanne/budgets/remove_line_item.rb +40 -0
  49. data/app/commands/decidim/lausanne/budgets/update_user_record.rb +40 -0
  50. data/app/controllers/concerns/decidim/lausanne/budgets/needs_current_order.rb +52 -0
  51. data/app/controllers/concerns/decidim/lausanne/budgets/orderable.rb +54 -0
  52. data/app/controllers/decidim/lausanne/budgets/admin/application_controller.rb +34 -0
  53. data/app/controllers/decidim/lausanne/budgets/admin/attachment_collections_controller.rb +27 -0
  54. data/app/controllers/decidim/lausanne/budgets/admin/attachments_controller.rb +28 -0
  55. data/app/controllers/decidim/lausanne/budgets/admin/lausanne_budgets_controller.rb +105 -0
  56. data/app/controllers/decidim/lausanne/budgets/admin/projects_controller.rb +98 -0
  57. data/app/controllers/decidim/lausanne/budgets/admin/proposals_imports_controller.rb +43 -0
  58. data/app/controllers/decidim/lausanne/budgets/application_controller.rb +77 -0
  59. data/app/controllers/decidim/lausanne/budgets/lausanne_budgets_controller.rb +29 -0
  60. data/app/controllers/decidim/lausanne/budgets/line_items_controller.rb +63 -0
  61. data/app/controllers/decidim/lausanne/budgets/orders_controller.rb +59 -0
  62. data/app/controllers/decidim/lausanne/budgets/projects_controller.rb +103 -0
  63. data/app/controllers/decidim/lausanne/budgets/user_records_controller.rb +121 -0
  64. data/app/forms/decidim/lausanne/budgets/admin/component_form.rb +93 -0
  65. data/app/forms/decidim/lausanne/budgets/admin/lausanne_budget_form.rb +41 -0
  66. data/app/forms/decidim/lausanne/budgets/admin/project_form.rb +96 -0
  67. data/app/forms/decidim/lausanne/budgets/admin/project_import_proposals_form.rb +52 -0
  68. data/app/forms/decidim/lausanne/budgets/user_record_form.rb +61 -0
  69. data/app/helpers/decidim/lausanne/budgets/admin/application_helper.rb +15 -0
  70. data/app/helpers/decidim/lausanne/budgets/application_helper.rb +26 -0
  71. data/app/helpers/decidim/lausanne/budgets/projects_helper.rb +103 -0
  72. data/app/jobs/decidim/lausanne/budgets/send_order_summary_job.rb +17 -0
  73. data/app/mailers/decidim/lausanne/budgets/order_summary_mailer.rb +38 -0
  74. data/app/models/decidim/lausanne/budgets/application_record.rb +12 -0
  75. data/app/models/decidim/lausanne/budgets/lausanne_budget.rb +37 -0
  76. data/app/models/decidim/lausanne/budgets/line_item.rb +23 -0
  77. data/app/models/decidim/lausanne/budgets/order.rb +204 -0
  78. data/app/models/decidim/lausanne/budgets/project.rb +129 -0
  79. data/app/models/decidim/lausanne/budgets/user_record.rb +28 -0
  80. data/app/packs/entrypoints/decidim_lausanne_budgets.js +2 -0
  81. data/app/packs/images/decidim/lausanne/budgets/icon.svg +1 -0
  82. data/app/packs/images/decidim/lausanne/budgets/lausanneparticipe.gif +0 -0
  83. data/app/packs/src/decidim/lausanne/budgets/index.js +1 -0
  84. data/app/packs/src/decidim/lausanne/budgets/progressFixed.js.es6 +23 -0
  85. data/app/packs/src/decidim/lausanne/budgets/projects.js.es6 +66 -0
  86. data/app/packs/stylesheets/decidim/lausanne/budgets/_budgets.scss +13 -0
  87. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_budget-list.scss +195 -0
  88. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_budget-meter.scss +85 -0
  89. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_print.scss +73 -0
  90. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_progress.scss +25 -0
  91. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_proposal_link.scss +38 -0
  92. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_share_buttons.scss +15 -0
  93. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_user_record_form.scss +8 -0
  94. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_votation-progress.scss +100 -0
  95. data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_voting-rules.scss +20 -0
  96. data/app/permissions/decidim/lausanne/budgets/admin/permissions.rb +49 -0
  97. data/app/permissions/decidim/lausanne/budgets/permissions.rb +63 -0
  98. data/app/presenters/decidim/lausanne/budgets/admin_log/budget_presenter.rb +44 -0
  99. data/app/presenters/decidim/lausanne/budgets/admin_log/project_presenter.rb +44 -0
  100. data/app/queries/decidim/lausanne/budgets/filtered_projects.rb +47 -0
  101. data/app/queries/decidim/lausanne/budgets/metrics/budget_followers_metric_measure.rb +34 -0
  102. data/app/queries/decidim/lausanne/budgets/metrics/budget_participants_metric_measure.rb +29 -0
  103. data/app/queries/decidim/lausanne/budgets/query.rb +16 -0
  104. data/app/serializers/decidim/lausanne/budgets/data_portability_budgets_order_serializer.rb +46 -0
  105. data/app/services/decidim/lausanne/budgets/project_search.rb +65 -0
  106. data/app/services/decidim/lausanne/budgets/project_search_rs.rb +13 -0
  107. data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/_form.html.erb +23 -0
  108. data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/edit.html.erb +7 -0
  109. data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/index.html.erb +75 -0
  110. data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/new.html.erb +7 -0
  111. data/app/views/decidim/lausanne/budgets/admin/projects/_form.html.erb +47 -0
  112. data/app/views/decidim/lausanne/budgets/admin/projects/edit.html.erb +7 -0
  113. data/app/views/decidim/lausanne/budgets/admin/projects/index.html.erb +82 -0
  114. data/app/views/decidim/lausanne/budgets/admin/projects/new.html.erb +7 -0
  115. data/app/views/decidim/lausanne/budgets/admin/projects/proposals_picker.html.erb +1 -0
  116. data/app/views/decidim/lausanne/budgets/admin/proposals_imports/new.html.erb +32 -0
  117. data/app/views/decidim/lausanne/budgets/lausanne_budgets/index.html.erb +5 -0
  118. data/app/views/decidim/lausanne/budgets/line_items/update_budget.js.erb +41 -0
  119. data/app/views/decidim/lausanne/budgets/order_summary_mailer/order_summary.html.erb +22 -0
  120. data/app/views/decidim/lausanne/budgets/orders/show.html.erb +71 -0
  121. data/app/views/decidim/lausanne/budgets/projects/_budget_confirm.html.erb +37 -0
  122. data/app/views/decidim/lausanne/budgets/projects/_budget_excess.html.erb +14 -0
  123. data/app/views/decidim/lausanne/budgets/projects/_budget_summary.html.erb +95 -0
  124. data/app/views/decidim/lausanne/budgets/projects/_count.html.erb +1 -0
  125. data/app/views/decidim/lausanne/budgets/projects/_filters.html.erb +34 -0
  126. data/app/views/decidim/lausanne/budgets/projects/_filters_small_view.html.erb +18 -0
  127. data/app/views/decidim/lausanne/budgets/projects/_linked_projects.html.erb +12 -0
  128. data/app/views/decidim/lausanne/budgets/projects/_order_progress.html.erb +32 -0
  129. data/app/views/decidim/lausanne/budgets/projects/_order_selected_projects.html.erb +27 -0
  130. data/app/views/decidim/lausanne/budgets/projects/_order_total_budget.html.erb +7 -0
  131. data/app/views/decidim/lausanne/budgets/projects/_project.html.erb +1 -0
  132. data/app/views/decidim/lausanne/budgets/projects/_project_budget_button.html.erb +46 -0
  133. data/app/views/decidim/lausanne/budgets/projects/_projects.html.erb +13 -0
  134. data/app/views/decidim/lausanne/budgets/projects/_user_record_form.html.erb +40 -0
  135. data/app/views/decidim/lausanne/budgets/projects/_votation_banner.html.erb +71 -0
  136. data/app/views/decidim/lausanne/budgets/projects/index.html.erb +36 -0
  137. data/app/views/decidim/lausanne/budgets/projects/index.js.erb +10 -0
  138. data/app/views/decidim/lausanne/budgets/projects/show.html.erb +81 -0
  139. data/app/views/decidim/lausanne/budgets/user_records/edit.html.erb +6 -0
  140. data/app/views/decidim/proposals/proposals/show.html.erb +172 -0
  141. data/app/views/layouts/lausanne_budgets/print.erb +12 -0
  142. data/config/assets.rb +11 -0
  143. data/config/initializers/social_share.rb +3 -0
  144. data/config/locales/fr.yml +381 -0
  145. data/config/routes.rb +7 -0
  146. data/db/migrate/20170127114122_create_lausanne_projects.rb +15 -0
  147. data/db/migrate/20170127114123_create_lausanne_user_records.rb +14 -0
  148. data/db/migrate/20170130095615_create_lausanne_orders.rb +16 -0
  149. data/db/migrate/20170130101825_create_lausanne_line_items.rb +12 -0
  150. data/db/migrate/20170215132708_add_lausanne_reference_to_projects.rb +13 -0
  151. data/db/migrate/20200617105120_create_decidim_lausanne_budgets.rb +15 -0
  152. data/db/migrate/20200629134013_add_lausanne_budget_reference_to_project.rb +7 -0
  153. data/db/migrate/20200706142609_add_lausanne_budget_reference_to_order.rb +7 -0
  154. data/db/migrate/20200714103519_move_lausanne_budgets_to_own_model.rb +109 -0
  155. data/db/migrate/20200717140012_add_lausanne_scope_to_budgets.rb +7 -0
  156. data/db/migrate/20200728075039_add_lausanne_selected_at_to_project.rb +7 -0
  157. data/db/migrate/20200804175222_lausanne_votes_enabled_to_votes_choices.rb +35 -0
  158. data/db/migrate/20200827154129_add_lausanne_commentable_counter_cache_to_projects.rb +9 -0
  159. data/db/migrate/20210310120613_add_lausanne_followable_counter_cache_to_budgets.rb +16 -0
  160. data/db/migrate/20210508180613_add_checkboxes_to_user_record.rb +9 -0
  161. data/db/migrate/20221001151237_add_excerpt_to_decidim_lausanne_budgets_project.rb +7 -0
  162. data/lib/decidim/lausanne/budgets/admin.rb +12 -0
  163. data/lib/decidim/lausanne/budgets/admin_engine.rb +40 -0
  164. data/lib/decidim/lausanne/budgets/component.rb +107 -0
  165. data/lib/decidim/lausanne/budgets/current_user_record_middleware.rb +17 -0
  166. data/lib/decidim/lausanne/budgets/engine.rb +57 -0
  167. data/lib/decidim/lausanne/budgets/project_serializer.rb +83 -0
  168. data/lib/decidim/lausanne/budgets/seeds/Exampledocument.pdf +0 -0
  169. data/lib/decidim/lausanne/budgets/seeds/city.jpeg +0 -0
  170. data/lib/decidim/lausanne/budgets/test/factories.rb +169 -0
  171. data/lib/decidim/lausanne/budgets/version.rb +15 -0
  172. data/lib/decidim/lausanne/budgets/workflows/all.rb +22 -0
  173. data/lib/decidim/lausanne/budgets/workflows/base.rb +140 -0
  174. data/lib/decidim/lausanne/budgets/workflows/one.rb +35 -0
  175. data/lib/decidim/lausanne/budgets/workflows.rb +19 -0
  176. data/lib/decidim/lausanne/budgets.rb +17 -0
  177. metadata +372 -0
@@ -0,0 +1,19 @@
1
+ <div class="budget-list__data <%= data_class %>">
2
+ <% if voting_finished? %>
3
+ <div class="budget-list__data__votes">
4
+ <%= cell("decidim/lausanne/budgets/project_votes_count", model) %>
5
+
6
+ <%= cell("decidim/lausanne/budgets/project_voted_hint", model, class: "display-block margin-top-1") %>
7
+ </div>
8
+ <% else %>
9
+ <span class="budget-list__data__number budget-list__number show-for-medium">
10
+ <%= budget_to_currency(model.budget_amount) %>
11
+
12
+ <%= cell("decidim/lausanne/budgets/project_votes_count", model, layout: :one_line, class: "display-inline-block") %>
13
+
14
+ <%= cell("decidim/lausanne/budgets/project_voted_hint", model, class: "display-block margin-top-1") if current_order_checked_out? && resource_added? %>
15
+ </span>
16
+
17
+ <%= render :project_data_vote_button if !current_order_checked_out? && voting_open? %>
18
+ <% end %>
19
+ </div>
@@ -0,0 +1,22 @@
1
+ <% if user_record_submitted? %>
2
+ <%= button_to(
3
+ lausanne_budget_order_line_item_path(model.budget, project_id: model),
4
+ method: vote_button_method,
5
+ remote: true,
6
+ data: {
7
+ disable: true,
8
+ budget: model.budget_amount,
9
+ allocation: resource_allocation,
10
+ "redirect-url": lausanne_budget_project_path(model.budget, model)
11
+ },
12
+ disabled: current_order_checked_out?,
13
+ title: vote_button_label,
14
+ class: "button tiny budget-list__action #{vote_button_class}",
15
+ ) do %>
16
+ <%= icon(resource_added? ? "x" : "check", class: "icon--small", aria_label: vote_button_label, role: "img") %>
17
+ <% end %>
18
+ <% else %>
19
+ <button class="button tiny budget-list__action <%= vote_button_class %>" data-toggle="userRecord">
20
+ <%= icon(resource_added? ? "x" : "check", class: "icon--small", aria_label: vote_button_label, role: "img") %>
21
+ </button>
22
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% if model.photos.first %>
2
+ <div class="budget-list__image">
3
+ <%= image_tag model.photos.first.thumbnail_url, alt: resource_title %>
4
+ </div>
5
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <div class="budget-list__text card__text">
2
+ <div>
3
+ <%= link_to resource_path, class: "card__link" do %>
4
+ <h5 class="card__title budget-list__title">
5
+ <%= cell("decidim/lausanne/budgets/project_selected_status", model) %>
6
+ <strong><%= resource_title %></strong>
7
+ </h5>
8
+ <span class="budget-list__excerpt"><%= resource_excerpt %></span>
9
+ <% end %>
10
+
11
+ <div class="show-for-medium">
12
+ <%= cell "decidim/lausanne/budgets/project_tags", model, context: { extra_classes: ["tags--project"] } %>
13
+ </div>
14
+
15
+ <div class="budget-list__data__number budget-list__number hide-for-medium">
16
+ <%= cell("decidim/lausanne/budgets/project_votes_count",
17
+ model,
18
+ layout: :one_line) %>
19
+
20
+ <%= cell("decidim/lausanne/budgets/project_voted_hint", model, class: "margin-left-1") if current_order_checked_out? && resource_added? %>
21
+ </div>
22
+ </div>
23
+ </div>
@@ -0,0 +1,5 @@
1
+ <div id="project-<%= model.id %>-item" class="budget-list__item">
2
+ <%= render :project_image %>
3
+ <%= render :project_text %>
4
+ <%= render :project_data %>
5
+ </div>
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ # This cell renders a horizontal project card
7
+ # for an given instance of a Project in a budget list
8
+ class ProjectListItemCell < Decidim::ViewModel
9
+ include ActiveSupport::NumberHelper
10
+ include Decidim::LayoutHelper
11
+ include Decidim::ActionAuthorizationHelper
12
+ include Decidim::Lausanne::Budgets::ProjectsHelper
13
+ include Decidim::Lausanne::Budgets::Engine.routes.url_helpers
14
+
15
+ delegate :current_user, :current_settings, :current_order, :current_user_record, :current_component,
16
+ :current_participatory_space, :can_have_order?, :voting_open?, :voting_finished?,
17
+ :user_record_for_budget?, :voted_for?, :user_record_submitted?, to: :parent_controller
18
+
19
+ private
20
+
21
+ def resource_path
22
+ resource_locator([model.budget, model]).path
23
+ end
24
+
25
+ def resource_title
26
+ translated_attribute model.title
27
+ end
28
+ def resource_excerpt
29
+ translated_attribute model.excerpt
30
+ end
31
+
32
+ def resource_added?
33
+ current_order && current_order.projects.include?(model)
34
+ end
35
+
36
+ def resource_allocation
37
+ current_order.allocation_for(model)
38
+ end
39
+
40
+ def data_class
41
+ [].tap do |list|
42
+ list << "budget-list__data--added" if can_have_order? && resource_added?
43
+ list << "show-for-medium" if voting_finished? || (current_order_checked_out? && !resource_added?)
44
+ end.join(" ")
45
+ end
46
+
47
+ def vote_button_disabled?
48
+ !can_have_order?
49
+ end
50
+
51
+ def vote_button_class
52
+ return "disabled" unless user_record_submitted?
53
+ return "success" if resource_added?
54
+ "hollow"
55
+ end
56
+
57
+ def vote_button_method
58
+ return :delete if resource_added?
59
+ :post
60
+ end
61
+
62
+ def vote_button_label
63
+ if resource_added?
64
+ return t(
65
+ "decidim.lausanne.budgets.projects.project.remove",
66
+ resource_name: resource_title
67
+ )
68
+ end
69
+
70
+ t("decidim.lausanne.budgets.projects.project.add", resource_name: resource_title)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,12 @@
1
+ <div class="card__icondata">
2
+ <ul class="card-data">
3
+ <li class="card-data__item">
4
+ <%= icon "euro-outline", class: "icon--big", role: "img", "aria-hidden": true %>
5
+ </li>
6
+ <li class="card-data__item">
7
+ <div class="text-left">
8
+ <strong class="heading4"><%= budget_to_currency model.budget_amount %></strong>
9
+ </div>
10
+ </li>
11
+ </ul>
12
+ </div>
@@ -0,0 +1,5 @@
1
+ <div class="card__footer">
2
+ <div class="card__support">
3
+ <%= link_to t("view", scope: "decidim.lausanne_budgets.projects.project"), resource_path, class: "card__button button button--sc small" %>
4
+ </div>
5
+ </div>
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ # This cell renders the Medium (:m) project card
7
+ # for an given instance of a Project
8
+ class ProjectMCell < Decidim::CardMCell
9
+ include ActiveSupport::NumberHelper
10
+ include Decidim::Lausanne::Budgets::ProjectsHelper
11
+
12
+ private
13
+
14
+ def resource_icon
15
+ icon "projects", class: "icon--big"
16
+ end
17
+
18
+ def resource_path
19
+ resource_locator([model.budget, model]).path
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ # This cell renders the selected status if the project has been selected
7
+ class ProjectSelectedStatusCell < Decidim::ViewModel
8
+ delegate :voting_finished?, to: :controller
9
+
10
+ def show
11
+ if voting_finished? && model.selected?
12
+ content_tag :span, class: css_class do
13
+ t("decidim.lausanne_budgets.projects.project.selected")
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def css_class
21
+ if options[:as_label] == true
22
+ "success label project-status"
23
+ else
24
+ "success card__text--status"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,4 @@
1
+ <%= content_tag :ul, class: tags_classes do %>
2
+ <%= content_tag :li, link_to_category if category? %>
3
+ <%= content_tag :li, link_to_scope if scope? %>
4
+ <% end %>
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ # This cell overrides *_path methods from Decidim::TagsCell for project tags
7
+ class ProjectTagsCell < Decidim::TagsCell
8
+ private
9
+
10
+ def category_path
11
+ resource_locator([model.budget, model]).index(filter: { category_id: [model.category.id.to_s] })
12
+ end
13
+
14
+ def scope_path
15
+ resource_locator([model.budget, model]).index(filter: { scope_id: [model.scope.id] })
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ # This cell renders a checkmark with a text.
7
+ class ProjectVotedHintCell < BaseCell
8
+ include Decidim::IconHelper
9
+
10
+ delegate :voted_for?, :current_order, to: :controller
11
+
12
+ def show
13
+ return unless voted_for?(model)
14
+
15
+ content_tag :span, safe_join(hint), class: css_class
16
+ end
17
+
18
+ private
19
+
20
+ def hint
21
+ contents = []
22
+ contents << icon("check", role: "img")
23
+ contents << " "
24
+ contents << t("decidim.budgets.projects.project.you_voted")
25
+ end
26
+
27
+ def css_class
28
+ css = ["text-sm", "text-success"]
29
+ css << options[:class] if options[:class]
30
+ css.join(" ")
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ # This cell renders the vote count.
7
+ # Two possible layouts: One or two lines
8
+ class ProjectVotesCountCell < Decidim::ViewModel
9
+ include Decidim::IconHelper
10
+ delegate :show_votes_count?, to: :controller
11
+
12
+ def show
13
+ return unless show_votes_count?
14
+
15
+ content_tag :span, content, class: css_class
16
+ end
17
+
18
+ private
19
+
20
+ def content
21
+ if options[:layout] == :one_line
22
+ safe_join([model.confirmed_orders_count, " ", label: t("decidim.lausanne_budgets.projects.project.votes",
23
+ count: model.confirmed_orders_count)])
24
+ else
25
+ safe_join([number, label: t("decidim.lausanne_budgets.projects.project.votes",
26
+ count: model.confirmed_orders_count)])
27
+ end
28
+ end
29
+
30
+ def number
31
+ content_tag :div, model.confirmed_orders_count, class: "text-large"
32
+ end
33
+
34
+ def label(i18n_string)
35
+ content_tag :span, i18n_string, class: "text-uppercase text-small"
36
+ end
37
+
38
+ def css_class
39
+ css = ["project-votes"]
40
+ css << options[:class] if options[:class]
41
+ css.join(" ")
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ # A command with all the business to add new line items to orders
7
+ class AddLineItem < Decidim::Lausanne::Budgets::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # order - The current order for the user or nil if it is not created yet.
11
+ # project - The the project to include in the order
12
+ # current_user - The current user logged in
13
+ def initialize(current_order, project, current_user)
14
+ @order = current_order
15
+ @project = project
16
+ @current_user = current_user
17
+ end
18
+
19
+ # Executes the command. Broadcasts these events:
20
+ #
21
+ # - :ok when everything is valid.
22
+ # - :invalid if the there is an error.
23
+ #
24
+ # Returns nothing.
25
+ def call
26
+ transaction do
27
+ return broadcast(:invalid) if voting_not_enabled? || order.checked_out?
28
+
29
+ add_line_item
30
+ broadcast(:ok, order)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :current_user, :project
37
+
38
+ def order
39
+ @order ||= Order.create!(user: current_user, budget: project.budget)
40
+ end
41
+
42
+ def add_line_item
43
+ order.with_lock do
44
+ order.projects << project
45
+ end
46
+ end
47
+
48
+ def voting_not_enabled?
49
+ project.component.current_settings.votes != "enabled"
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ module Admin
7
+ # This command is executed when the user creates an Budget
8
+ # from the admin panel.
9
+ class CreateBudget < Decidim::Lausanne::Budgets::Command
10
+ def initialize(form)
11
+ @form = form
12
+ end
13
+
14
+ # Creates the budget if valid.
15
+ #
16
+ # Broadcasts :ok if successful, :invalid otherwise.
17
+ def call
18
+ return broadcast(:invalid) if form.invalid?
19
+
20
+ create_budget!
21
+
22
+ broadcast(:ok, budget)
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :form, :budget
28
+
29
+ def create_budget!
30
+ attributes = {
31
+ component: form.current_component,
32
+ scope: form.scope,
33
+ title: form.title,
34
+ weight: form.weight,
35
+ description: form.description,
36
+ total_budget: form.total_budget
37
+ }
38
+
39
+ @budget = Decidim.traceability.create!(
40
+ LausanneBudget,
41
+ form.current_user,
42
+ attributes,
43
+ visibility: "all"
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ module Admin
7
+ # This command is executed when the user creates a Project from the admin
8
+ # panel.
9
+ class CreateProject < Decidim::Lausanne::Budgets::Command
10
+ include ::Decidim::AttachmentMethods
11
+ include ::Decidim::GalleryMethods
12
+
13
+ def initialize(form)
14
+ @form = form
15
+ end
16
+
17
+ # Creates the project if valid.
18
+ #
19
+ # Broadcasts :ok if successful, :invalid otherwise.
20
+ def call
21
+ return broadcast(:invalid) if @form.invalid?
22
+
23
+ if process_gallery?
24
+ build_gallery
25
+ return broadcast(:invalid) if gallery_invalid?
26
+ end
27
+
28
+ transaction do
29
+ create_project!
30
+ link_proposals
31
+ create_gallery if process_gallery?
32
+ end
33
+
34
+ broadcast(:ok)
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :form, :project, :gallery
40
+
41
+ def create_project!
42
+ attributes = {
43
+ budget: form.budget,
44
+ scope: form.scope,
45
+ category: form.category,
46
+ title: form.title,
47
+ description: form.description,
48
+ budget_amount: form.budget_amount
49
+ }
50
+
51
+ @project = Decidim.traceability.create!(
52
+ Project,
53
+ form.current_user,
54
+ attributes,
55
+ visibility: "all"
56
+ )
57
+ @attached_to = @project
58
+ end
59
+
60
+ def proposals
61
+ @proposals ||= project.sibling_scope(:proposals).where(id: form.proposal_ids)
62
+ end
63
+
64
+ def link_proposals
65
+ project.link_resources(proposals, "included_proposals")
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ module Admin
7
+ # This command is executed when the user destroys a Budget
8
+ # from the admin panel.
9
+ class DestroyBudget < Decidim::Lausanne::Budgets::Command
10
+ def initialize(budget, current_user)
11
+ @budget = budget
12
+ @current_user = current_user
13
+ end
14
+
15
+ # Destroys the budget if valid.
16
+ #
17
+ # Broadcasts :ok if successful, :invalid otherwise.
18
+ def call
19
+ return broadcast(:invalid) if budget.projects.present?
20
+
21
+ destroy_budget!
22
+
23
+ broadcast(:ok, budget)
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :budget, :current_user
29
+
30
+ def destroy_budget!
31
+ Decidim.traceability.perform_action!(
32
+ :delete,
33
+ budget,
34
+ current_user,
35
+ visibility: "all"
36
+ ) do
37
+ budget.destroy!
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Lausanne
5
+ module Budgets
6
+ module Admin
7
+ # This command is executed when the user deletes a Project from the admin
8
+ # panel.
9
+ class DestroyProject < Decidim::Lausanne::Budgets::Command
10
+ # Initializes an UpdateProject Command.
11
+ #
12
+ # project - The current instance of the project to be destroyed.
13
+ # current_user - the user that performs the action
14
+ def initialize(project, current_user)
15
+ @project = project
16
+ @current_user = current_user
17
+ end
18
+
19
+ # Performs the action.
20
+ #
21
+ # Broadcasts :ok if successful, :invalid otherwise.
22
+ def call
23
+ destroy_project
24
+ broadcast(:ok)
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :project, :current_user
30
+
31
+ def destroy_project
32
+ Decidim.traceability.perform_action!(
33
+ :delete,
34
+ project,
35
+ current_user
36
+ ) do
37
+ project.destroy!
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end