decidim-core 0.2.0 → 0.3.0

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.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim.js.es6 +2 -0
  3. data/app/assets/javascripts/decidim/account_form.js.es6 +27 -0
  4. data/app/assets/javascripts/decidim/editor.js.es6 +9 -2
  5. data/app/assets/javascripts/decidim/form_filter.component.js.es6 +1 -1
  6. data/app/assets/javascripts/decidim/form_filter.component.test.js +2 -2
  7. data/app/assets/javascripts/decidim/history.js.es6 +7 -4
  8. data/app/commands/decidim/create_registration.rb +2 -1
  9. data/app/commands/decidim/destroy_account.rb +47 -0
  10. data/app/constraints/decidim/current_feature.rb +4 -5
  11. data/app/controllers/concerns/decidim/needs_participatory_process.rb +6 -1
  12. data/app/controllers/decidim/account_controller.rb +25 -2
  13. data/app/controllers/decidim/authorizations_controller.rb +2 -2
  14. data/app/controllers/decidim/pages_controller.rb +4 -2
  15. data/app/forms/decidim/delete_account_form.rb +8 -0
  16. data/app/forms/decidim/registration_form.rb +13 -0
  17. data/app/helpers/decidim/action_authorization_helper.rb +10 -4
  18. data/app/helpers/decidim/decidim_form_helper.rb +96 -0
  19. data/app/helpers/decidim/omniauth_helper.rb +1 -1
  20. data/app/helpers/decidim/resource_helper.rb +3 -36
  21. data/app/mailers/decidim/reported_mailer.rb +5 -3
  22. data/app/models/decidim/attachment.rb +1 -1
  23. data/app/models/decidim/authorization.rb +1 -1
  24. data/app/models/decidim/categorization.rb +8 -0
  25. data/app/models/decidim/category.rb +7 -2
  26. data/app/models/decidim/feature.rb +3 -5
  27. data/app/models/decidim/identity.rb +0 -1
  28. data/app/models/decidim/moderation.rb +0 -2
  29. data/app/models/decidim/participatory_process.rb +4 -2
  30. data/app/models/decidim/report.rb +1 -1
  31. data/app/models/decidim/resource_link.rb +1 -2
  32. data/app/models/decidim/static_page.rb +1 -2
  33. data/app/models/decidim/user.rb +16 -3
  34. data/app/models/decidim/user_group.rb +5 -3
  35. data/app/presenters/decidim/resource_locator_presenter.rb +48 -0
  36. data/app/services/decidim/authorization_handler.rb +4 -7
  37. data/app/services/decidim/resource_search.rb +3 -1
  38. data/app/uploaders/decidim/avatar_uploader.rb +2 -2
  39. data/app/uploaders/decidim/image_uploader.rb +1 -1
  40. data/app/uploaders/decidim/official_image_footer_uploader.rb +1 -5
  41. data/app/uploaders/decidim/official_image_header_uploader.rb +1 -5
  42. data/app/uploaders/decidim/organization_logo_uploader.rb +1 -1
  43. data/app/views/decidim/account/delete.html.erb +30 -0
  44. data/app/views/decidim/devise/shared/_omniauth_buttons.html.erb +2 -2
  45. data/app/views/decidim/reported_mailer/hide.html.erb +5 -1
  46. data/app/views/decidim/reported_mailer/report.html.erb +5 -1
  47. data/app/views/layouts/decidim/user_profile.html.erb +2 -1
  48. data/config/initializers/devise.rb +9 -9
  49. data/config/locales/ca.yml +20 -3
  50. data/config/locales/en.yml +20 -3
  51. data/config/locales/es.yml +20 -3
  52. data/config/locales/eu.yml +0 -3
  53. data/config/locales/fi.yml +0 -2
  54. data/config/locales/fr.yml +0 -3
  55. data/config/locales/it.yml +350 -0
  56. data/config/locales/nl.yml +0 -2
  57. data/config/routes.rb +5 -1
  58. data/db/migrate/20160817115213_devise_create_decidim_users.rb +1 -0
  59. data/db/migrate/20160919104837_create_decidim_organizations.rb +2 -0
  60. data/db/migrate/20160920140207_devise_invitable_add_to_decidim_users.rb +2 -0
  61. data/db/migrate/20160920141039_user_belongs_to_organization.rb +2 -0
  62. data/db/migrate/20160920141151_user_has_roles.rb +2 -0
  63. data/db/migrate/20161005130108_add_participatory_processes.rb +4 -2
  64. data/db/migrate/20161005153007_add_description_to_organizations.rb +2 -0
  65. data/db/migrate/20161006085629_add_confirmable_to_devise.rb +2 -0
  66. data/db/migrate/20161010085443_add_name_to_users.rb +2 -0
  67. data/db/migrate/20161010102356_translate_processes.rb +2 -0
  68. data/db/migrate/20161010131544_add_locale_to_users.rb +2 -0
  69. data/db/migrate/20161011125616_add_hero_image_to_processes.rb +2 -0
  70. data/db/migrate/20161011141033_add_banner_image_to_processes.rb +2 -0
  71. data/db/migrate/20161013134732_add_promoted_flag_to_processes.rb +2 -0
  72. data/db/migrate/20161017085822_add_participatory_process_steps.rb +4 -2
  73. data/db/migrate/20161018091013_create_decidim_authorizations.rb +2 -0
  74. data/db/migrate/20161019072016_add_active_flag_to_step.rb +7 -1
  75. data/db/migrate/20161020080756_add_position_to_steps.rb +2 -0
  76. data/db/migrate/20161025125300_add_published_at_to_processes.rb +2 -0
  77. data/db/migrate/20161107152228_remove_not_null_on_step_position.rb +2 -0
  78. data/db/migrate/20161108093802_create_decidim_static_pages.rb +2 -0
  79. data/db/migrate/20161110092735_add_index_for_process_slug_organization.rb +5 -3
  80. data/db/migrate/20161110105712_create_decidim_features.rb +2 -0
  81. data/db/migrate/20161116115156_create_attachments.rb +4 -2
  82. data/db/migrate/20161123085134_add_categories.rb +2 -0
  83. data/db/migrate/20161130105257_create_decidim_scopes.rb +2 -0
  84. data/db/migrate/20161209134715_make_organization_description_optional.rb +2 -0
  85. data/db/migrate/20161213094244_add_avatar_to_users.rb +2 -0
  86. data/db/migrate/20161214152811_add_logo_to_organizations.rb +2 -0
  87. data/db/migrate/20170110133113_add_configuration_to_features.rb +2 -0
  88. data/db/migrate/20170110153807_add_handler_to_organization.rb +2 -0
  89. data/db/migrate/20170113150627_create_resource_links.rb +2 -0
  90. data/db/migrate/20170116110851_create_identities.rb +2 -0
  91. data/db/migrate/20170116135237_loosen_step_requirements.rb +2 -0
  92. data/db/migrate/20170117142904_add_uniqueness_field_to_authorizations.rb +2 -0
  93. data/db/migrate/20170119145359_create_user_groups.rb +2 -0
  94. data/db/migrate/20170119150255_create_user_group_memberships.rb +2 -0
  95. data/db/migrate/20170119150649_add_show_statistics_to_organization.rb +3 -1
  96. data/db/migrate/20170120120733_add_user_groups_verified.rb +2 -0
  97. data/db/migrate/20170123134023_make_attachments_polymorphic.rb +2 -0
  98. data/db/migrate/20170123140857_add_avatar_to_user_groups.rb +2 -0
  99. data/db/migrate/20170125135937_rename_attachable_to_attached_to.rb +3 -1
  100. data/db/migrate/20170125152026_add_weight_to_features.rb +2 -0
  101. data/db/migrate/20170126151123_add_extra_info_to_processes.rb +6 -4
  102. data/db/migrate/20170128140553_add_timestamps_to_identities.rb +2 -0
  103. data/db/migrate/20170130132833_add_favicon_to_decidim_organizations.rb +2 -0
  104. data/db/migrate/20170131134349_add_action_permissions_to_decidim_features.rb +2 -0
  105. data/db/migrate/20170202084913_add_comments_and_replies_notifications_to_users.rb +2 -0
  106. data/db/migrate/20170203150545_add_newsletter_notifications_to_users.rb +2 -0
  107. data/db/migrate/20170206083118_rename_extra_info_on_processes.rb +2 -0
  108. data/db/migrate/20170206142116_add_published_at_to_decidim_features.rb +2 -0
  109. data/db/migrate/20170207091021_add_social_media_handlers_to_organization.rb +2 -0
  110. data/db/migrate/20170207093048_add_organization_logo_and_url.rb +3 -1
  111. data/db/migrate/20170213081133_create_decidim_newsletters.rb +2 -0
  112. data/db/migrate/20170215115407_add_organization_custom_reference.rb +2 -0
  113. data/db/migrate/20170220110740_remove_steps_short_description.rb +2 -0
  114. data/db/migrate/20170221094835_add_scopes_to_processes.rb +2 -0
  115. data/db/migrate/20170228142440_add_participatory_process_groups.rb +2 -0
  116. data/db/migrate/20170306144354_add_secondary_hosts_to_organizations.rb +2 -0
  117. data/db/migrate/20170307084957_create_reports.rb +2 -0
  118. data/db/migrate/20170308091316_create_moderations.rb +2 -0
  119. data/db/migrate/20170313095436_add_available_authorizations_to_organization.rb +2 -0
  120. data/db/migrate/20170404132616_change_steps_end_and_start_date_to_date.rb +2 -0
  121. data/db/migrate/20170405091801_change_decidim_user_email_index_uniqueness.rb +2 -0
  122. data/db/migrate/20170405094028_add_organization_to_identities.rb +2 -0
  123. data/db/migrate/20170405094258_change_decidim_identities_provider_uid_index_uniqueness.rb +3 -1
  124. data/db/migrate/20170529150743_add_rejected_at_to_user_groups.rb +2 -0
  125. data/db/migrate/20170605140421_add_deleted_fields_to_users.rb +8 -0
  126. data/db/migrate/20170606102659_set_email_unique_in_organization_conditional.rb +8 -0
  127. data/db/migrate/20170608142521_add_organization_to_user_groups.rb +14 -0
  128. data/db/migrate/20170612070905_add_uniqueness_to_name_and_document_number_to_user_groups.rb +8 -0
  129. data/db/migrate/20170612100253_create_decidim_categorizations.rb +12 -0
  130. data/db/seeds.rb +10 -8
  131. data/lib/decidim/authorable.rb +2 -2
  132. data/lib/decidim/core.rb +1 -1
  133. data/lib/decidim/core/api/author_interface.rb +6 -0
  134. data/lib/decidim/core/api/user_group_type.rb +14 -0
  135. data/lib/decidim/core/api/user_type.rb +10 -0
  136. data/lib/decidim/core/engine.rb +1 -1
  137. data/lib/decidim/core/test/factories.rb +12 -0
  138. data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +3 -3
  139. data/lib/decidim/core/version.rb +2 -2
  140. data/lib/decidim/feature_manifest.rb +2 -3
  141. data/lib/decidim/form_builder.rb +3 -2
  142. data/lib/decidim/has_category.rb +3 -1
  143. data/lib/decidim/has_scope.rb +5 -2
  144. data/lib/decidim/query_extensions.rb +2 -2
  145. data/lib/decidim/reportable.rb +3 -3
  146. data/lib/decidim/stats_registry.rb +2 -2
  147. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.fr.js +14 -0
  148. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.it.js +14 -0
  149. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.nl.js +14 -0
  150. metadata +45 -17
  151. data/app/models/decidim/component.rb +0 -52
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b0dd8d6b3f087054a2af0d5d971d81c6a52adae
4
- data.tar.gz: 5395196374ab3e8f0f7a65abba480e914505938d
3
+ metadata.gz: d96ba296398fd826bdcf4c32066893664f91f190
4
+ data.tar.gz: e378de5bd40d0cbd7f95e811e921cbbce3fd3f15
5
5
  SHA512:
6
- metadata.gz: fae7b86d0ca687eb0f3519d3cd7886c626224e023d95a6db84a7cdeef3d979193475117596993846231df7a4510bcab8f22b5f912283e1ea075b1d68b4018e77
7
- data.tar.gz: 6e0d57a494c3a2d7bcbc1ecac618c47447defd88422c1761006b65e7f9e3a1ecb1889db554d150451728e8fd5c11591d1a18cadbbec176630ffb2c34ea392ee3
6
+ metadata.gz: c5ad0b5762d5c1c9d2ec61392c7a22587ecc4d769f35dbe938be51513f0446df6104c75fb36e34cf5260ba104a71ab5bb591527a3706e5f1e8e1a22155515ba2
7
+ data.tar.gz: 5d32c6d26f18146787b85c53c019bb549d0a3569b90dcae89588a4a7249f6f472e2addad8b08b911276472b487809462b45639277f58fe346aaa95aaa2417c73
@@ -1,3 +1,4 @@
1
+ // = require jquery
1
2
  // = require decidim/foundation
2
3
  // = require modernizr
3
4
  // = require svg4everybody.min
@@ -8,6 +9,7 @@
8
9
  // = require decidim/history
9
10
  // = require decidim/append_elements
10
11
  // = require decidim/user_registrations
12
+ // = require decidim/account_form
11
13
 
12
14
  /* globals svg4everybody */
13
15
 
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Since the delete account has a modal to confirm it we need to copy the content of the
3
+ * reason field to the hidden field in the form inside the modal.
4
+ */
5
+ $(() => {
6
+ const $deleteAccountForm = $('.delete-account');
7
+ const $deleteAccountModalForm = $('.delete-account-modal');
8
+
9
+ if ($deleteAccountForm.length > 0) {
10
+ const $openModalButton = $('.open-modal-button');
11
+ const $modal = $('#deleteConfirm');
12
+
13
+ $openModalButton.on('click', (event) => {
14
+ try {
15
+ const reasonValue = $deleteAccountForm.find('textarea#delete_account_delete_reason').val();
16
+ $deleteAccountModalForm.find('input#delete_account_delete_reason').val(reasonValue);
17
+ $modal.foundation('open');
18
+ } catch (error) {
19
+ console.error(error); // eslint-disable-line no-console
20
+ }
21
+
22
+ event.preventDefault();
23
+ event.stopPropagation();
24
+ return false;
25
+ });
26
+ }
27
+ });
@@ -5,7 +5,7 @@ $(() => {
5
5
  const $container = $('.editor-container');
6
6
  const quillFormats = ['bold', 'italic', 'link', 'underline', 'header', 'list', 'video'];
7
7
 
8
- $container.each((idx, container) => {
8
+ const createQuillEditor = (container) => {
9
9
  const toolbar = $(container).data('toolbar');
10
10
 
11
11
  let quillToolbar = [
@@ -39,6 +39,13 @@ $(() => {
39
39
  }
40
40
  });
41
41
 
42
- quill.root.innerHTML = $input.val();
42
+ quill.root.innerHTML = $input.val() || '';
43
+ };
44
+
45
+ $container.each((idx, container) => {
46
+ createQuillEditor(container);
43
47
  });
48
+
49
+ window.Decidim = window.Decidim || {};
50
+ window.Decidim.createQuillEditor = createQuillEditor;
44
51
  });
@@ -54,7 +54,7 @@
54
54
  }
55
55
 
56
56
  /**
57
- * Finds the values of the location prams that match the given regexp.
57
+ * Finds the values of the location params that match the given regexp.
58
58
  * @private
59
59
  * @param {Regexp} regex - a Regexp to match the params.
60
60
  * @returns {String[]} - An array of values of the params that match the regexp.
@@ -70,14 +70,14 @@ describe('FormFilterComponent', () => {
70
70
  it('clears the form data', () => {
71
71
  spyOn(subject, '_clearForm');
72
72
 
73
- window.onpopstate();
73
+ window.onpopstate({ isTrusted: true });
74
74
 
75
75
  expect(subject._clearForm).toHaveBeenCalled();
76
76
  });
77
77
 
78
78
  it('sets the correct form fields based on the current location', () => {
79
79
  spyOn(subject, '_getLocation').and.returnValue('/filters?filter[scope_id][]=1&scope_id[]=2&filter[category_id]=2');
80
- window.onpopstate();
80
+ window.onpopstate({ isTrusted: true });
81
81
 
82
82
  expect($(selector).find('select').val()).toEqual('2');
83
83
  expect($(selector).find('input[name="filter[scope_id][]"][value="1"]')[0].checked).toBeTruthy();
@@ -4,10 +4,13 @@
4
4
  ((exports) => {
5
5
  let callbacks = {};
6
6
 
7
- exports.onpopstate = () => {
8
- for (let callbackId in callbacks) {
9
- if (callbacks.hasOwnProperty(callbackId)) {
10
- callbacks[callbackId]();
7
+ exports.onpopstate = (event) => {
8
+ // Ensure the event is caused by user action
9
+ if (event.isTrusted) {
10
+ for (let callbackId in callbacks) {
11
+ if (callbacks.hasOwnProperty(callbackId)) {
12
+ callbacks[callbackId]();
13
+ }
11
14
  }
12
15
  }
13
16
  };
@@ -48,7 +48,8 @@ module Decidim
48
48
  UserGroupMembership.create!(user: @user,
49
49
  user_group: UserGroup.new(name: form.user_group_name,
50
50
  document_number: form.user_group_document_number,
51
- phone: form.user_group_phone))
51
+ phone: form.user_group_phone,
52
+ decidim_organization_id: form.current_organization.id))
52
53
  end
53
54
  end
54
55
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This command destroys the user's account.
5
+ class DestroyAccount < Rectify::Command
6
+ # Destroy a user's account.
7
+ #
8
+ # user - The user to be updated.
9
+ # form - The form with the data.
10
+ def initialize(user, form)
11
+ @user = user
12
+ @form = form
13
+ end
14
+
15
+ def call
16
+ return broadcast(:invalid) unless @form.valid?
17
+
18
+ Decidim::User.transaction do
19
+ destroy_user_account!
20
+ destroy_user_identities
21
+ destroy_user_group_memberships
22
+ end
23
+
24
+ broadcast(:ok)
25
+ end
26
+
27
+ private
28
+
29
+ def destroy_user_account!
30
+ @user.name = ""
31
+ @user.email = ""
32
+ @user.delete_reason = @form.delete_reason
33
+ @user.deleted_at = Time.current
34
+ @user.skip_reconfirmation!
35
+ @user.remove_avatar!
36
+ @user.save!
37
+ end
38
+
39
+ def destroy_user_identities
40
+ @user.identities.destroy_all
41
+ end
42
+
43
+ def destroy_user_group_memberships
44
+ Decidim::UserGroupMembership.where(user: @user).destroy_all
45
+ end
46
+ end
47
+ end
@@ -28,7 +28,7 @@ module Decidim
28
28
 
29
29
  env["decidim.current_participatory_process"] ||= @participatory_process
30
30
 
31
- feature = detect_current_feature(request)
31
+ feature = detect_current_feature(params)
32
32
 
33
33
  return false unless feature
34
34
 
@@ -38,12 +38,11 @@ module Decidim
38
38
 
39
39
  private
40
40
 
41
- def detect_current_feature(request)
42
- params = request.params
41
+ def detect_current_feature(params)
43
42
  return nil unless params["feature_id"]
44
43
 
45
- @participatory_process.features.to_a.find do |feature|
46
- params["feature_id"].to_s == feature.id.to_s && feature.manifest_name == @manifest.name.to_s
44
+ @participatory_process.features.find do |feature|
45
+ params["feature_id"] == feature.id.to_s && feature.manifest_name == @manifest.name.to_s
47
46
  end
48
47
  end
49
48
  end
@@ -19,7 +19,7 @@ module Decidim
19
19
  #
20
20
  # Returns the current ParticipatoryProcess.
21
21
  def current_participatory_process
22
- @current_participatory_process ||= current_organization.participatory_processes.find_by(id: params[:participatory_process_id] || params[:id])
22
+ @current_participatory_process ||= detect_participatory_process
23
23
  end
24
24
 
25
25
  private
@@ -27,6 +27,11 @@ module Decidim
27
27
  def verify_participatory_process
28
28
  raise ActionController::RoutingError, "Participatory process not found." unless current_participatory_process
29
29
  end
30
+
31
+ def detect_participatory_process
32
+ request.env["current_participatory_process"] ||
33
+ current_organization.participatory_processes.find_by(id: params[:participatory_process_id] || params[:id])
34
+ end
30
35
  end
31
36
  end
32
37
  end
@@ -18,8 +18,8 @@ module Decidim
18
18
  @account = form(AccountForm).from_params(params)
19
19
 
20
20
  UpdateAccount.call(current_user, @account) do
21
- on(:ok) do |_account, unconfirmed_email|
22
- flash.now[:notice] = if unconfirmed_email
21
+ on(:ok) do |email_is_unconfirmed|
22
+ flash.now[:notice] = if email_is_unconfirmed
23
23
  t("account.update.success_with_email_confirmation", scope: "decidim")
24
24
  else
25
25
  t("account.update.success", scope: "decidim")
@@ -36,6 +36,29 @@ module Decidim
36
36
  render action: :show
37
37
  end
38
38
 
39
+ def delete
40
+ authorize! :delete, current_user
41
+ @form = form(DeleteAccountForm).from_model(current_user)
42
+ end
43
+
44
+ def destroy
45
+ authorize! :delete, current_user
46
+ @form = form(DeleteAccountForm).from_params(params)
47
+
48
+ DestroyAccount.call(current_user, @form) do
49
+ on(:ok) do
50
+ sign_out(current_user)
51
+ flash[:notice] = t("account.destroy.success", scope: "decidim")
52
+ end
53
+
54
+ on(:invalid) do
55
+ flash[:alert] = t("account.destroy.error", scope: "decidim")
56
+ end
57
+ end
58
+
59
+ redirect_to decidim.root_path
60
+ end
61
+
39
62
  private
40
63
 
41
64
  def authorizations
@@ -63,7 +63,7 @@ module Decidim
63
63
  end
64
64
 
65
65
  def handler_name
66
- params[:handler] || params[:authorization_handler][:handler_name]
66
+ params[:handler] || params.dig(:authorization_handler, :handler_name)
67
67
  end
68
68
 
69
69
  def valid_handler
@@ -72,7 +72,7 @@ module Decidim
72
72
  logger.warn "Invalid authorization handler given: #{handler_name} doesn't"\
73
73
  "exist or you haven't added it to `Decidim.authorization_handlers`"
74
74
 
75
- redirect_to(account_path) && (return false)
75
+ redirect_to(authorizations_path) && (return false)
76
76
  end
77
77
 
78
78
  def only_one_handler?
@@ -25,11 +25,13 @@ module Decidim
25
25
  end
26
26
 
27
27
  def promoted_participatory_processes
28
- @promoted_processes ||= OrganizationPrioritizedParticipatoryProcesses.new(current_organization) | PromotedParticipatoryProcesses.new
28
+ @promoted_participatory_processes ||=
29
+ OrganizationPrioritizedParticipatoryProcesses.new(current_organization) | PromotedParticipatoryProcesses.new
29
30
  end
30
31
 
31
32
  def highlighted_participatory_processes
32
- @promoted_processes ||= OrganizationParticipatoryProcesses.new(current_organization) | HighlightedParticipatoryProcesses.new
33
+ @highlighted_participatory_processes ||=
34
+ OrganizationParticipatoryProcesses.new(current_organization) | HighlightedParticipatoryProcesses.new
33
35
  end
34
36
 
35
37
  private
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # The form object that handles the data behind deleting users account.
5
+ class DeleteAccountForm < Form
6
+ attribute :delete_reason, String
7
+ end
8
+ end
@@ -28,6 +28,8 @@ module Decidim
28
28
  validates :user_group_phone, presence: true, if: :user_group?
29
29
 
30
30
  validate :email_unique_in_organization
31
+ validate :user_group_name_unique_in_organization
32
+ validate :user_group_document_number_unique_in_organization
31
33
 
32
34
  def user_group?
33
35
  sign_up_as == "user_group"
@@ -38,5 +40,16 @@ module Decidim
38
40
  def email_unique_in_organization
39
41
  errors.add :email, :taken if User.where(email: email, organization: current_organization).first.present?
40
42
  end
43
+
44
+ def user_group_name_unique_in_organization
45
+ errors.add :user_group_name, :taken if UserGroup.where(name: user_group_name, decidim_organization_id: current_organization.id).first.present?
46
+ end
47
+
48
+ def user_group_document_number_unique_in_organization
49
+ errors.add :user_group_document_number, :taken if UserGroup.where(
50
+ document_number: user_group_document_number,
51
+ decidim_organization_id: current_organization.id
52
+ ).first.present?
53
+ end
41
54
  end
42
55
  end
@@ -33,10 +33,10 @@ module Decidim
33
33
  html_options = arguments[2]
34
34
  end
35
35
 
36
- unless action_authorization(action).ok?
36
+ unless current_user_authorized?(action)
37
37
  html_options ||= {}
38
38
  html_options["onclick"] = "event.preventDefault();"
39
- html_options["data-toggle"] = "#{action.to_s.underscore}AuthorizationModal"
39
+ html_options["data-toggle"] = current_user ? "#{action.to_s.underscore}AuthorizationModal" : "loginModal"
40
40
  url = ""
41
41
  end
42
42
 
@@ -66,9 +66,9 @@ module Decidim
66
66
  html_options = arguments[2] || {}
67
67
  end
68
68
 
69
- unless action_authorization(action).ok?
69
+ unless current_user_authorized?(action)
70
70
  html_options["onclick"] = "event.preventDefault();"
71
- html_options["data-toggle"] = "#{action.to_s.underscore}AuthorizationModal"
71
+ html_options["data-toggle"] = current_user ? "#{action.to_s.underscore}AuthorizationModal" : "loginModal"
72
72
  url = ""
73
73
  end
74
74
 
@@ -78,5 +78,11 @@ module Decidim
78
78
  button_to(body, url, html_options)
79
79
  end
80
80
  end
81
+
82
+ private
83
+
84
+ def current_user_authorized?(action)
85
+ current_user && action_authorization(action).ok?
86
+ end
81
87
  end
82
88
  end
@@ -15,5 +15,101 @@ module Decidim
15
15
  options[:data].update(abide: true, "live-validate" => true, "validate-on-blur" => true)
16
16
  form_for(record, options, &block)
17
17
  end
18
+
19
+ # A custom helper to include an editor field without requiring a form object
20
+ #
21
+ # name - The input name
22
+ # value - The input value
23
+ # options - The set of options to send to the field
24
+ # :label - The Boolean value to create or not the input label (optional) (default: true)
25
+ # :toolbar - The String value to configure WYSIWYG toolbar. It should be 'basic' or
26
+ # or 'full' (optional) (default: 'basic')
27
+ # :lines - The Integer to indicate how many lines should editor have (optional)
28
+ #
29
+ # Returns a rich editor to be included in a html template.
30
+ def editor_field_tag(name, value, options = {})
31
+ options[:toolbar] ||= "basic"
32
+ options[:lines] ||= 10
33
+
34
+ content_tag(:div, class: "editor") do
35
+ template = ""
36
+ template += label_tag(name, options[:label]) if options[:label] != false
37
+ template += hidden_field_tag(name, value, options)
38
+ template += content_tag(:div, nil, class: "editor-container", data: {
39
+ toolbar: options[:toolbar]
40
+ }, style: "height: #{options[:lines]}rem")
41
+ template.html_safe
42
+ end
43
+ end
44
+
45
+ # A custom helper to include a translated field without requiring a form object.
46
+ #
47
+ # type - The type of the translated input field.
48
+ # object_name - The object name used to identify the Foundation tabs.
49
+ # name - The name of the input which will be suffixed with the corresponding locales.
50
+ # value - A hash containing the value for each locale.
51
+ # options - An optional hash of options.
52
+ # * enable_tabs: Adds the data-tabs attribute so Foundation picks up automatically.
53
+ # * tabs_id: The id to identify the Foundation tabs element.
54
+ # * label: The label used for the field.
55
+ #
56
+ # Returns a Foundation tabs element with the translated input field.
57
+ def translated_field_tag(type, object_name, name, value = {}, options = {})
58
+ locales = available_locales
59
+
60
+ tabs_id = options[:tabs_id] || "#{object_name}-#{name}-tabs"
61
+ enabled_tabs = options[:enable_tabs].nil? ? true : options[:enable_tabs]
62
+ tabs_panels_data = enabled_tabs ? { tabs: true } : {}
63
+
64
+ if locales.count == 1
65
+ return send(
66
+ type,
67
+ "#{name}_#{locales.first.to_s.gsub("-", "__")}",
68
+ options.merge(label: options[:label])
69
+ )
70
+ end
71
+
72
+ label_tabs = content_tag(:div, class: "label--tabs") do
73
+ field_label = label_tag(name, options[:label])
74
+
75
+ tabs_panels = "".html_safe
76
+ if options[:label] != false
77
+ tabs_panels = content_tag(:ul, class: "tabs tabs--lang", id: tabs_id, data: tabs_panels_data) do
78
+ locales.each_with_index.inject("".html_safe) do |string, (locale, index)|
79
+ string + content_tag(:li, class: tab_element_class_for("title", index)) do
80
+ title = I18n.with_locale(locale) { I18n.t("name", scope: "locale") }
81
+ tab_content_id = "#{tabs_id}-#{name}-panel-#{index}"
82
+ content_tag(:a, title, href: "##{tab_content_id}")
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ safe_join [field_label, tabs_panels]
89
+ end
90
+
91
+ tabs_content = content_tag(:div, class: "tabs-content", data: { tabs_content: tabs_id }) do
92
+ locales.each_with_index.inject("".html_safe) do |string, (locale, index)|
93
+ tab_content_id = "#{tabs_id}-#{name}-panel-#{index}"
94
+ string + content_tag(:div, class: tab_element_class_for("panel", index), id: tab_content_id) do
95
+ send(type, "#{object_name}[#{name_with_locale(name, locale)}]", value[locale.to_s], options.merge(id: "#{tabs_id}_#{name}_#{locale}", label: false))
96
+ end
97
+ end
98
+ end
99
+
100
+ safe_join [label_tabs, tabs_content]
101
+ end
102
+
103
+ # Helper method used by `translated_field_tag`
104
+ def tab_element_class_for(type, index)
105
+ element_class = "tabs-#{type}"
106
+ element_class += " is-active" if index.zero?
107
+ element_class
108
+ end
109
+
110
+ # Helper method used by `translated_field_tag`
111
+ def name_with_locale(name, locale)
112
+ "#{name}_#{locale.to_s.gsub("-", "__")}"
113
+ end
18
114
  end
19
115
  end