decidim-core 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/decidim/extras/_add_comments.scss +9 -0
  3. data/app/assets/stylesheets/decidim/extras/_label-required.scss +3 -0
  4. data/app/assets/stylesheets/decidim/extras/_reference.scss +3 -0
  5. data/app/assets/stylesheets/decidim/extras/_social_icons_mini.scss +10 -0
  6. data/app/commands/decidim/invite_user.rb +1 -1
  7. data/app/commands/decidim/update_account.rb +2 -6
  8. data/app/constraints/decidim/current_feature.rb +11 -18
  9. data/app/constraints/decidim/current_participatory_process.rb +35 -0
  10. data/app/controllers/concerns/decidim/devise_controllers.rb +1 -0
  11. data/app/controllers/concerns/decidim/locale_switcher.rb +2 -2
  12. data/app/controllers/concerns/decidim/needs_authorization.rb +1 -2
  13. data/app/controllers/concerns/decidim/needs_organization.rb +1 -2
  14. data/app/controllers/concerns/decidim/needs_participatory_process.rb +19 -10
  15. data/app/controllers/decidim/account_controller.rb +13 -9
  16. data/app/controllers/decidim/application_controller.rb +3 -8
  17. data/app/controllers/decidim/devise/registrations_controller.rb +0 -1
  18. data/app/controllers/decidim/devise/sessions_controller.rb +0 -1
  19. data/app/controllers/decidim/errors_controller.rb +15 -0
  20. data/app/controllers/decidim/features/base_controller.rb +1 -0
  21. data/app/controllers/decidim/participatory_process_groups_controller.rb +6 -2
  22. data/app/controllers/decidim/participatory_process_steps_controller.rb +1 -0
  23. data/app/controllers/decidim/participatory_processes_controller.rb +3 -3
  24. data/app/helpers/decidim/application_helper.rb +3 -0
  25. data/app/helpers/decidim/feature_path_helper.rb +35 -0
  26. data/app/helpers/decidim/feature_reference_helper.rb +4 -2
  27. data/app/helpers/decidim/icon_helper.rb +20 -0
  28. data/app/helpers/decidim/menu_helper.rb +1 -1
  29. data/app/helpers/decidim/participatory_process_helper.rb +0 -14
  30. data/app/models/decidim/feature.rb +9 -1
  31. data/app/models/decidim/static_page.rb +1 -0
  32. data/app/models/decidim/user.rb +2 -0
  33. data/app/queries/decidim/highlighted_participatory_processes.rb +1 -1
  34. data/app/views/decidim/account/show.html.erb +1 -3
  35. data/app/views/decidim/devise/shared/_omniauth_buttons.html.erb +1 -1
  36. data/app/views/decidim/devise/shared/_omniauth_buttons_mini.html.erb +20 -0
  37. data/app/views/{pages/500.html.erb → decidim/errors/internal_server_error.html.erb} +0 -0
  38. data/app/views/{pages/404.html.erb → decidim/errors/not_found.html.erb} +1 -1
  39. data/app/views/decidim/shared/_login_modal.html.erb +4 -0
  40. data/app/views/decidim/shared/_share_modal.html.erb +1 -1
  41. data/app/views/layouts/decidim/_process_header.html.erb +2 -2
  42. data/config/i18n-tasks.yml +2 -0
  43. data/config/initializers/invisible_captcha.rb +2 -2
  44. data/config/locales/ca.yml +14 -8
  45. data/config/locales/en.yml +13 -7
  46. data/config/locales/es.yml +13 -7
  47. data/config/locales/eu.yml +0 -7
  48. data/config/locales/fi.yml +0 -7
  49. data/config/locales/fr.yml +4 -11
  50. data/config/locales/it.yml +0 -7
  51. data/config/locales/nl.yml +0 -7
  52. data/config/routes.rb +2 -8
  53. data/db/migrate/20160817115213_devise_create_decidim_users.rb +6 -6
  54. data/db/migrate/20160920140207_devise_invitable_add_to_decidim_users.rb +9 -9
  55. data/db/seeds.rb +2 -2
  56. data/lib/decidim/core.rb +25 -1
  57. data/lib/decidim/core/engine.rb +0 -1
  58. data/lib/decidim/core/test.rb +1 -0
  59. data/lib/decidim/core/test/factories.rb +11 -6
  60. data/lib/decidim/core/test/shared_examples/comments_examples.rb +69 -66
  61. data/lib/decidim/core/test/shared_examples/errors.rb +21 -0
  62. data/lib/decidim/core/test/shared_examples/has_reference.rb +18 -2
  63. data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +2 -2
  64. data/lib/decidim/core/version.rb +1 -1
  65. data/lib/decidim/devise_failure_app.rb +1 -1
  66. data/lib/decidim/form_builder.rb +89 -5
  67. data/lib/decidim/has_reference.rb +3 -15
  68. data/lib/decidim/notifiable.rb +22 -0
  69. data/lib/devise/models/decidim_validatable.rb +4 -4
  70. metadata +41 -16
@@ -3,6 +3,8 @@
3
3
  module Decidim
4
4
  # Main module to add application-wide helpers.
5
5
  module ApplicationHelper
6
+ include Decidim::OmniauthHelper
7
+
6
8
  # Truncates a given text respecting its HTML tags.
7
9
  #
8
10
  # text - The String text to be truncated.
@@ -17,6 +19,7 @@ module Decidim
17
19
  options[:tail] = options.delete(:separator) || options[:tail] || "..."
18
20
  options[:count_tags] ||= false
19
21
  options[:count_tail] ||= false
22
+ options[:tail_before_final_tag] ||= true
20
23
 
21
24
  Truncato.truncate(text, options)
22
25
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # A helper to get the root path for a feature.
5
+ module FeaturePathHelper
6
+ # Returns the defined root path for a given feature.
7
+ #
8
+ # feature - the Feature we want to find the root path for.
9
+ #
10
+ # Returns a url.
11
+ def feature_path(feature)
12
+ feature_root_path_for(feature.manifest.engine, feature)
13
+ end
14
+
15
+ # Returns the defined admin root path for a given feature.
16
+ #
17
+ # feature - the Feature we want to find the root path for.
18
+ #
19
+ # Returns a url.
20
+ def manage_feature_path(feature)
21
+ feature_root_path_for(feature.manifest.admin_engine, feature)
22
+ end
23
+
24
+ private
25
+
26
+ def feature_root_path_for(engine, feature)
27
+ url_params = {
28
+ feature_id: feature.id,
29
+ participatory_process_id: feature.participatory_process.id
30
+ }
31
+
32
+ engine.routes.url_helpers.root_path(url_params)
33
+ end
34
+ end
35
+ end
@@ -6,12 +6,14 @@ module Decidim
6
6
  # Displays the localized reference for the given feature.
7
7
  #
8
8
  # feature - the Feature that has the reference to display.
9
+ # options - An optional hash of options
10
+ # * class: A string of extra css classes
9
11
  #
10
12
  # Returns a String.
11
- def feature_reference(feature)
13
+ def feature_reference(feature, options = {})
12
14
  return unless feature.reference
13
15
  @reference = feature.reference
14
- "<div class='reference'>#{localized_reference}</div>".html_safe
16
+ "<div class='reference #{options[:class]}'>#{localized_reference}</div>".html_safe
15
17
  end
16
18
 
17
19
  private
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Helpers related to icons
5
+ module IconHelper
6
+ # Public: Returns an icon given an instance of a Feature. It defaults to
7
+ # a question mark when no icon is found.
8
+ #
9
+ # feature - The feature to generate the icon for.
10
+ #
11
+ # Returns an HTML tag with the icon.
12
+ def feature_icon(feature)
13
+ if feature.manifest.icon
14
+ external_icon feature.manifest.icon
15
+ else
16
+ icon "question-mark"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -5,7 +5,7 @@ module Decidim
5
5
  module MenuHelper
6
6
  # Public: Returns the main menu presenter object
7
7
  def main_menu
8
- @main_menu ||= MenuPresenter.new(
8
+ @main_menu ||= ::Decidim::MenuPresenter.new(
9
9
  :menu,
10
10
  self,
11
11
  element_class: "main-nav__link",
@@ -13,19 +13,5 @@ module Decidim
13
13
  dates = [participatory_process_step.start_date, participatory_process_step.end_date]
14
14
  dates.map { |date| date ? localize(date.to_date, format: :default) : "?" }.join(" - ")
15
15
  end
16
-
17
- # Public: Returns an icon given an instance of a Feature. It defaults to
18
- # a question mark when no icon is found.
19
- #
20
- # feature - The feature to generate the icon for.
21
- #
22
- # Returns an HTML tag with the icon.
23
- def feature_icon(feature)
24
- if feature.manifest.icon
25
- external_icon feature.manifest.icon
26
- else
27
- icon "question-mark"
28
- end
29
- end
30
16
  end
31
17
  end
@@ -61,6 +61,14 @@ module Decidim
61
61
  self[:settings]["global"] = serialize_settings(settings_schema(:global), data)
62
62
  end
63
63
 
64
+ def default_step_settings
65
+ settings_schema(:step).new(self[:settings]["default_step"])
66
+ end
67
+
68
+ def default_step_settings=(data)
69
+ self[:settings]["default_step"] = serialize_settings(settings_schema(:step), data)
70
+ end
71
+
64
72
  def step_settings
65
73
  participatory_process.steps.each_with_object({}) do |step, result|
66
74
  result[step.id.to_s] = settings_schema(:step).new(self[:settings].dig("steps", step.id.to_s))
@@ -75,7 +83,7 @@ module Decidim
75
83
 
76
84
  def active_step_settings
77
85
  active_step = participatory_process.active_step
78
- return nil unless active_step
86
+ return default_step_settings unless active_step
79
87
 
80
88
  step_settings.fetch(active_step.id.to_s)
81
89
  end
@@ -11,6 +11,7 @@ module Decidim
11
11
  belongs_to :organization, foreign_key: "decidim_organization_id", class_name: "Decidim::Organization", inverse_of: :static_pages
12
12
 
13
13
  validates :slug, presence: true, uniqueness: { scope: :organization }
14
+ validates :slug, format: { with: /\A[a-z0-9-]+/ }
14
15
 
15
16
  # These pages will be created by default when registering an organization
16
17
  # and cannot be deleted.
@@ -28,6 +28,8 @@ module Decidim
28
28
  validate :all_roles_are_valid
29
29
  mount_uploader :avatar, Decidim::AvatarUploader
30
30
 
31
+ scope :not_deleted, -> { where(deleted_at: nil) }
32
+
31
33
  # Public: Allows customizing the invitation instruction email content when
32
34
  # inviting a user.
33
35
  #
@@ -5,7 +5,7 @@ module Decidim
5
5
  # public view.
6
6
  class HighlightedParticipatoryProcesses < Rectify::Query
7
7
  def query
8
- Decidim::ParticipatoryProcess.order("promoted DESC").includes(:active_step).order("decidim_participatory_process_steps.end_date ASC").limit(8)
8
+ PrioritizedParticipatoryProcesses.new.query.limit(8)
9
9
  end
10
10
  end
11
11
  end
@@ -1,9 +1,7 @@
1
1
  <div class="row">
2
2
  <%= decidim_form_for(@account, url: account_path, method: :put, class: "user-form") do |f| %>
3
3
  <div class="columns large-4">
4
- <%= image_tag current_user.avatar.big.url, width: "100%" %>
5
- <%= f.file_field :avatar, label: false %>
6
- <%= f.check_box :remove_avatar %>
4
+ <%= f.upload :avatar %>
7
5
  </div>
8
6
 
9
7
  <div class="columns large-8 end">
@@ -12,7 +12,7 @@
12
12
  <%= icon normalize_provider_name(provider) %>
13
13
  </span>
14
14
  <%= t("devise.shared.links.sign_in_with_provider", provider: normalize_provider_name(provider).titleize) %>
15
- <% end %>
15
+ <% end %>
16
16
  </div>
17
17
  <% end %>
18
18
  <% end %>
@@ -0,0 +1,20 @@
1
+ <% if Devise.mappings[:user].omniauthable? && any_social_provider_enabled? %>
2
+ <div class="row">
3
+ <div class="columns medium-8 medium-centered">
4
+ <span class="register__separator">
5
+ <span class="register__separator__text"><%= t('or', scope: "decidim.devise.shared.omniauth_buttons") %></span>
6
+ </span>
7
+ <div class="text-center">
8
+ <%- Decidim::User.omniauth_providers.each do |provider| %>
9
+ <% if social_provider_enabled? provider %>
10
+ <%= link_to decidim.send("user_#{provider}_omniauth_authorize_path"), class: "button button--social button--#{normalize_provider_name(provider)} button--social--mini" do %>
11
+ <span class="button--social__icon">
12
+ <%= icon normalize_provider_name(provider) %>
13
+ </span>
14
+ <% end %>
15
+ <% end %>
16
+ <% end %>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ <% end %>
@@ -8,6 +8,6 @@
8
8
  <%= link_to t(".back_home"), root_path, class: "button" %>
9
9
  </div>
10
10
  </div>
11
+ </div>
11
12
  </div>
12
- </div>
13
13
  </main>
@@ -24,6 +24,10 @@
24
24
  <p class="text-center">
25
25
  <%= link_to t('.sign_up'), decidim.new_user_registration_path, class: "sign-up-link" %>
26
26
  </p>
27
+ <p class="text-center">
28
+ <%= link_to t("devise.shared.links.forgot_your_password"), new_password_path(:user) %>
29
+ </p>
27
30
  </div>
31
+ <%= render "decidim/devise/shared/omniauth_buttons_mini" %>
28
32
  </div>
29
33
  </div>
@@ -29,5 +29,5 @@
29
29
  <span aria-hidden="true">&times;</span>
30
30
  </button>
31
31
  </div>
32
- <h4 class="heading4"><%= "#{content_for(:meta_url)}" %></h4>
32
+ <h4 class="heading4"><%= "#{decidim_meta_url}" %></h4>
33
33
  </div>
@@ -48,8 +48,8 @@
48
48
 
49
49
  <% current_participatory_process.features.each do |feature| %>
50
50
  <% if feature.published? || feature == self.try(:current_feature) %>
51
- <li class="<%= "is-active" if is_active_link?(decidim.feature_path(current_participatory_process, feature), :inclusive) %>">
52
- <%= active_link_to decidim.feature_path(current_participatory_process, feature), class: "process-nav__link", active: :inclusive, class_active: "is-active" do %>
51
+ <li class="<%= "is-active" if is_active_link?(feature_path(feature), :inclusive) %>">
52
+ <%= active_link_to feature_path(feature), class: "process-nav__link", active: :inclusive, class_active: "is-active" do %>
53
53
  <%= feature_icon(feature) %>
54
54
 
55
55
  <%= translated_attribute(feature.name) %>
@@ -105,6 +105,8 @@ ignore_unused:
105
105
  - decidim.participatory_processes.scopes.global
106
106
  - decidim.participatory_processes.participatory_process_groups.none
107
107
  - pages.home.statistics.*
108
+ - forms.*
109
+
108
110
  # - 'activerecord.attributes.*'
109
111
  # - '{devise,kaminari,will_paginate}.*'
110
112
  # - 'simple_form.{yes,no}'
@@ -2,9 +2,9 @@
2
2
 
3
3
  InvisibleCaptcha.setup do |config|
4
4
  config.honeypots << "another_fake_attribute"
5
- config.visual_honeypots = false
5
+ config.visual_honeypots = false
6
6
  config.timestamp_threshold = 4
7
- config.timestamp_enabled = false
7
+ config.timestamp_enabled = false
8
8
  # Leave these unset if you want to use I18n (see below)
9
9
  # config.sentence_for_humans = 'If you are a human, ignore this field'
10
10
  # config.timestamp_error_message = 'Sorry, that was too quick! Please resubmit.'
@@ -118,6 +118,14 @@ ca:
118
118
  shared:
119
119
  omniauth_buttons:
120
120
  or: O
121
+ errors:
122
+ internal_server_error:
123
+ title: Hi ha hagut un problema amb el nostre servidor
124
+ try_later: Si us plau, torna-ho a intentar més tard.
125
+ not_found:
126
+ back_home: Tornar a l'inici
127
+ content_doesnt_exist: Aquesta adreça és incorrecta o ha estat eliminada.
128
+ title: No s'ha trobat la pàgina que busques
121
129
  export_mailer:
122
130
  export:
123
131
  ready: S'adjunta una versió comprimida de l'exportació.
@@ -145,6 +153,9 @@ ca:
145
153
  proposal: propostes
146
154
  result: Resultats
147
155
  forms:
156
+ current_file: Fitxer actual
157
+ current_image: Imatge actual
158
+ default_image: Imatge predeterminada
148
159
  errors:
149
160
  error: Hi ha un error en aquest camp.
150
161
  menu:
@@ -284,6 +295,8 @@ ca:
284
295
  too_many_marks: Està utilitzant massa símbols d'exclamació o interrogació
285
296
  too_much_caps: Està utilitzant massa majúscules
286
297
  too_short: És massa curt
298
+ forms:
299
+ required: Obligatori
287
300
  invisible_captcha:
288
301
  sentence_for_humans: Si ets un humà, pots ignorar aquest camp
289
302
  timestamp_error_message: Ho sentim, has estat massa ràpid! Torna a enviar-ho.
@@ -345,13 +358,6 @@ ca:
345
358
  locale:
346
359
  name: Català
347
360
  pages:
348
- '404':
349
- back_home: Tornar a l'inici
350
- content_doesnt_exist: Aquesta adreça és incorrecta o ha estat eliminada.
351
- title: No s'ha trobat la pàgina que busques!
352
- '500':
353
- title: Hi ha hagut un problema amb el nostre servidor
354
- try_later: Si us plau, torna-ho a intentar més tard.
355
361
  home:
356
362
  extended:
357
363
  debates: Debats
@@ -364,7 +370,7 @@ ca:
364
370
  proposals_explanation: Espai obert de propostes dels ciutadans sobre quin tipus de ciutat volem viure.
365
371
  footer_sub_hero:
366
372
  footer_sub_hero_body: Construïm una societat més oberta, transparent i col·laborativa.<br />Uneix-te, participa i decideix.
367
- footer_sub_hero_headline: Benvingut a la plataforma participativa %{organization}.
373
+ footer_sub_hero_headline: Bienvenida y bienvenido a la plataforma participativa %{organization}.
368
374
  register: Registra't
369
375
  hero:
370
376
  participate: Participa
@@ -119,6 +119,14 @@ en:
119
119
  shared:
120
120
  omniauth_buttons:
121
121
  or: Or
122
+ errors:
123
+ internal_server_error:
124
+ title: There was a problem with our server
125
+ try_later: Please try again later.
126
+ not_found:
127
+ back_home: Back home
128
+ content_doesnt_exist: This address is incorrect or has been removed.
129
+ title: The page you're looking for can't be found
122
130
  export_mailer:
123
131
  export:
124
132
  ready: Please find attached a zipped version of your export.
@@ -146,6 +154,9 @@ en:
146
154
  proposal: Proposals
147
155
  result: Results
148
156
  forms:
157
+ current_file: Current file
158
+ current_image: Current image
159
+ default_image: Default image
149
160
  errors:
150
161
  error: There's an error in this field.
151
162
  menu:
@@ -285,6 +296,8 @@ en:
285
296
  too_many_marks: Is using too many marks
286
297
  too_much_caps: Is using too much caps
287
298
  too_short: Is too short
299
+ forms:
300
+ required: Required
288
301
  invisible_captcha:
289
302
  sentence_for_humans: If you are human, ignore this field
290
303
  timestamp_error_message: Sorry, that was too quick! Please resubmit.
@@ -346,13 +359,6 @@ en:
346
359
  locale:
347
360
  name: English
348
361
  pages:
349
- '404':
350
- back_home: Back home
351
- content_doesnt_exist: This address is incorrect or has been removed.
352
- title: The page you're looking for can't be found
353
- '500':
354
- title: There was a problem with our server
355
- try_later: Please try again later.
356
362
  home:
357
363
  extended:
358
364
  debates: Debates
@@ -118,6 +118,14 @@ es:
118
118
  shared:
119
119
  omniauth_buttons:
120
120
  or: O
121
+ errors:
122
+ internal_server_error:
123
+ title: Ha habido un problema con nuestro servidor
124
+ try_later: Por favor, vuelve a intentarlo más tarde.
125
+ not_found:
126
+ back_home: Volver al inicio
127
+ content_doesnt_exist: Esta dirección es incorrecta o ha sido eliminada.
128
+ title: No se ha encontrado la página que buscas
121
129
  export_mailer:
122
130
  export:
123
131
  ready: Adjunto encontrará una versión comprimida de su exportación.
@@ -145,6 +153,9 @@ es:
145
153
  proposal: Propuestas
146
154
  result: Resultados
147
155
  forms:
156
+ current_file: Archivo actual
157
+ current_image: Imagen actual
158
+ default_image: Imagen predeterminada
148
159
  errors:
149
160
  error: Hay un error en este campo.
150
161
  menu:
@@ -284,6 +295,8 @@ es:
284
295
  too_many_marks: Está utilizando demasiados símbolos de interrogación o exclamación
285
296
  too_much_caps: Está usando demasiadas mayúsculas
286
297
  too_short: Es demasiado corto
298
+ forms:
299
+ required: Obligatorio
287
300
  invisible_captcha:
288
301
  sentence_for_humans: Si eres humano, ignora este campo
289
302
  timestamp_error_message: Lo siento, has sido demasiado rápido! Por favor, vuelva a enviar.
@@ -345,13 +358,6 @@ es:
345
358
  locale:
346
359
  name: Castellano
347
360
  pages:
348
- '404':
349
- back_home: Volver al inicio
350
- content_doesnt_exist: Esta dirección es incorrecta o ha sido eliminada.
351
- title: '¡No se ha encontrado la página que buscas!'
352
- '500':
353
- title: Ha habido un problema con nuestro servidor
354
- try_later: Por favor, vuelve a intentarlo más tarde.
355
361
  home:
356
362
  extended:
357
363
  debates: Debates
@@ -323,13 +323,6 @@ eu:
323
323
  locale:
324
324
  name: Euskera
325
325
  pages:
326
- '404':
327
- back_home: Itzuli hasierara
328
- content_doesnt_exist: Helbide okerra da edo ezabatu da.
329
- title: Ez dugu aurkitu bilatzen duzun orria!
330
- '500':
331
- title: Arazo bat izan da gure zerbitzariarekin
332
- try_later: Mesedez, berriz saiatu geroago.
333
326
  home:
334
327
  extended:
335
328
  debates: Eztabaidak