decidim-core 0.26.1 → 0.26.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim-core might be problematic. Click here for more details.

Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/card_m/show.erb +1 -1
  3. data/app/cells/decidim/content_blocks/cta/show.erb +1 -1
  4. data/app/cells/decidim/content_blocks/hero/show.erb +1 -1
  5. data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
  6. data/app/cells/decidim/content_blocks/stats_cell.rb +1 -0
  7. data/app/cells/decidim/followers_cell.rb +1 -1
  8. data/app/cells/decidim/notification/show.erb +1 -1
  9. data/app/cells/decidim/notification_cell.rb +6 -0
  10. data/app/commands/decidim/update_user_interests.rb +5 -1
  11. data/app/controllers/concerns/decidim/resource_versions_concern.rb +4 -0
  12. data/app/controllers/concerns/decidim/skip_timeoutable.rb +17 -0
  13. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  14. data/app/controllers/decidim/timeouts_controller.rb +2 -6
  15. data/app/events/decidim/resource_endorsed_event.rb +2 -1
  16. data/app/forms/decidim/account_form.rb +5 -4
  17. data/app/forms/decidim/registration_form.rb +8 -2
  18. data/app/forms/decidim/user_interest_scope_form.rb +1 -1
  19. data/app/helpers/decidim/application_helper.rb +4 -0
  20. data/app/helpers/decidim/filters_helper.rb +5 -1
  21. data/app/helpers/decidim/meta_tags_helper.rb +24 -1
  22. data/app/helpers/decidim/sanitize_helper.rb +8 -2
  23. data/app/models/decidim/action_log.rb +9 -8
  24. data/app/models/decidim/user_base_entity.rb +2 -0
  25. data/app/packs/src/decidim/external_link.js +6 -0
  26. data/app/packs/src/decidim/map/controller/static.js +6 -5
  27. data/app/packs/src/decidim/map/factory.js +3 -1
  28. data/app/packs/src/decidim/map/legacy.js +2 -2
  29. data/app/packs/src/decidim/map.js +2 -2
  30. data/app/packs/src/decidim/session_timeouter.js +10 -5
  31. data/app/packs/stylesheets/decidim/modules/_cards.scss +2 -0
  32. data/app/packs/stylesheets/decidim/modules/_comments.scss +2 -0
  33. data/app/packs/stylesheets/decidim/modules/_forms.scss +5 -0
  34. data/app/permissions/decidim/permissions.rb +4 -2
  35. data/app/presenters/decidim/user_presenter.rb +4 -1
  36. data/app/validators/password_validator.rb +12 -3
  37. data/app/views/decidim/data_portability/show.html.erb +1 -1
  38. data/app/views/decidim/devise/invitations/edit.html.erb +2 -2
  39. data/app/views/decidim/notifications_settings/show.html.erb +49 -51
  40. data/app/views/decidim/user_interests/show.html.erb +11 -13
  41. data/app/views/layouts/decidim/_timeout_modal.html.erb +2 -0
  42. data/config/initializers/devise.rb +2 -1
  43. data/config/locales/ar.yml +17 -2
  44. data/config/locales/bg.yml +1 -1
  45. data/config/locales/ca.yml +21 -6
  46. data/config/locales/cs.yml +17 -10
  47. data/config/locales/de.yml +72 -5
  48. data/config/locales/en.yml +7 -0
  49. data/config/locales/es-MX.yml +21 -6
  50. data/config/locales/es-PY.yml +17 -2
  51. data/config/locales/es.yml +19 -4
  52. data/config/locales/eu.yml +4 -4
  53. data/config/locales/fi-plain.yml +8 -0
  54. data/config/locales/fi.yml +8 -1
  55. data/config/locales/fr-CA.yml +10 -3
  56. data/config/locales/fr.yml +45 -38
  57. data/config/locales/ga-IE.yml +1 -1
  58. data/config/locales/gl.yml +0 -2
  59. data/config/locales/hu.yml +174 -1
  60. data/config/locales/id-ID.yml +0 -2
  61. data/config/locales/is-IS.yml +2 -1
  62. data/config/locales/it.yml +11 -3
  63. data/config/locales/ja.yml +10 -3
  64. data/config/locales/lb.yml +2 -2
  65. data/config/locales/lt.yml +1802 -0
  66. data/config/locales/nl.yml +3 -3
  67. data/config/locales/no.yml +1 -1
  68. data/config/locales/oc-FR.yml +1 -0
  69. data/config/locales/pl.yml +51 -2
  70. data/config/locales/pt-BR.yml +3 -3
  71. data/config/locales/pt.yml +4 -4
  72. data/config/locales/ro-RO.yml +1 -1
  73. data/config/locales/ru.yml +2 -3
  74. data/config/locales/sk.yml +1 -4
  75. data/config/locales/sv.yml +5 -2
  76. data/config/locales/tr-TR.yml +2 -2
  77. data/config/locales/uk.yml +1 -2
  78. data/config/locales/zh-CN.yml +2 -2
  79. data/lib/decidim/content_parsers/hashtag_parser.rb +1 -1
  80. data/lib/decidim/content_parsers/resource_parser.rb +97 -0
  81. data/lib/decidim/content_parsers.rb +1 -0
  82. data/lib/decidim/content_processor.rb +2 -1
  83. data/lib/decidim/content_renderers/resource_renderer.rb +30 -0
  84. data/lib/decidim/content_renderers.rb +1 -0
  85. data/lib/decidim/core/engine.rb +1 -1
  86. data/lib/decidim/core/test/factories.rb +2 -1
  87. data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +60 -0
  88. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +40 -0
  89. data/lib/decidim/core/test/shared_examples/with_endorsable_permissions_examples.rb +1 -1
  90. data/lib/decidim/core/test.rb +2 -0
  91. data/lib/decidim/core/version.rb +1 -1
  92. data/lib/decidim/events/simple_event.rb +8 -1
  93. data/lib/decidim/has_resource_permission.rb +0 -2
  94. data/lib/decidim/map/provider/dynamic_map/here.rb +46 -1
  95. data/lib/decidim/nicknamizable.rb +1 -1
  96. data/lib/decidim/translatable_attributes.rb +8 -1
  97. data/lib/devise/models/decidim_validatable.rb +3 -3
  98. metadata +14 -13
  99. data/app/cells/decidim/endorsement_buttons_cell.rb.2 +0 -211
  100. data/app/helpers/decidim/social_share_button_helper.rb +0 -26
  101. data/lib/decidim/social_share/service.rb +0 -33
  102. data/lib/decidim/social_share/service_registry.rb +0 -63
  103. data/lib/decidim/social_share.rb +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53feb2cc6c5c494c20cf8e6ae1d35cc933ddf3a91ee2704b9b2fb6436b267c87
4
- data.tar.gz: 431d81f9df34a6c1f0a88a3786f138e748e4cc9b5a706707493e7735a7cf782a
3
+ metadata.gz: 3cbd72f4c386bc8730dfa1d3958a691c5ed719b3cf43b15f778d2011ae5a7f0d
4
+ data.tar.gz: 32e72e8185fc2f28f0298ef2a9a0350cd8b436e1a39bda136fe82c9da5644433
5
5
  SHA512:
6
- metadata.gz: 69ec72cc2adbd4c88933c2c21aade155b7b98dc9708c85d9f0677b32621ce205c8b247109d96c0b13d3b7e6b96214eea3ac1c03e3aedfdaae2ca0afba7de96cd
7
- data.tar.gz: 92caf28a3f0ea16de36d307a4ff484478d071a5b442a6848a09741c657b1bdf86f1c53c9ccf799920901fabb8aea5284f32e661c07d3d6830e77e8299c482557
6
+ metadata.gz: 3d7a4d41fa9aeb76c68e21e5a486b8a3149d117a956c4d0ec17020db1abad1c8a8ce1316ba014a158bbb2fe254ebc0db4b4923a756d0f97997c06bb128c3e440
7
+ data.tar.gz: e282e746492e32a9e85edb4b72ede7804be3b5b7fd9567e49eac2ba6b9430f6d46da2596f044b87fa520fb4cde0e92259c40695837c87d6fb0943f2c244fa8e2
@@ -9,7 +9,7 @@
9
9
  <div class="card__text">
10
10
  <div class="card__text--paragraph">
11
11
  <%= render :badge if has_badge? %>
12
- <%= description %>
12
+ <%= Decidim::ContentProcessor.render(description, "div") %>
13
13
  </div>
14
14
  </div>
15
15
 
@@ -1,5 +1,5 @@
1
1
  <section class="section">
2
- <div class="expanded hero" style="background-image:url(<%= background_image %>);">
2
+ <div class="expanded hero" style="background-image:url('<%= background_image %>');">
3
3
  <div class="hero__container">
4
4
  <div class="row">
5
5
  <div class="columns small-centered medium-6 text-center">
@@ -1,4 +1,4 @@
1
- <section class="extended hero home-section" style="background-image:url(<%= background_image %>);">
1
+ <section class="extended hero home-section" style="background-image:url('<%= background_image %>');">
2
2
  <div class="hero__container">
3
3
  <div class="row">
4
4
  <div class="columns small-centered large-10">
@@ -1,5 +1,5 @@
1
1
  <section class="extended highligted-content-banner home-section"
2
- style="background-image:url(<%= current_organization.attached_uploader(:highlighted_content_banner_image).path %>);">
2
+ style="background-image:url('<%= current_organization.attached_uploader(:highlighted_content_banner_image).path %>');">
3
3
  <div class="highligted-content-banner__container">
4
4
  <div class="row">
5
5
  <div class="columns large-10">
@@ -16,6 +16,7 @@ module Decidim
16
16
  def cache_hash
17
17
  hash = []
18
18
  hash.push(I18n.locale)
19
+ hash.push(current_organization.cache_key)
19
20
  hash.join(Decidim.cache_key_separator)
20
21
  end
21
22
  end
@@ -12,7 +12,7 @@ module Decidim
12
12
  end
13
13
 
14
14
  def followers
15
- @followers ||= model.followers.page(params[:page]).per(20)
15
+ @followers ||= model.followers.not_blocked.page(params[:page]).per(20)
16
16
  end
17
17
  end
18
18
  end
@@ -13,7 +13,7 @@
13
13
  <span class="text-small"><%= notification.event_class.constantize.model_name.human %></span>
14
14
  <br>
15
15
  <span>
16
- <%= notification.event_class_instance.notification_title %>
16
+ <%= notification_title %>
17
17
  </span>
18
18
  <% if notification.display_resource_text? %>
19
19
  <p>
@@ -11,6 +11,12 @@ module Decidim
11
11
  render :show
12
12
  end
13
13
 
14
+ def notification_title
15
+ notification.event_class_instance.notification_title
16
+ rescue StandardError
17
+ I18n.t("decidim.notifications.show.missing_event")
18
+ end
19
+
14
20
  private
15
21
 
16
22
  def notification
@@ -29,7 +29,11 @@ module Decidim
29
29
  end
30
30
 
31
31
  def selected_scopes_ids
32
- @form.scopes.select(&:checked).map(&:id)
32
+ @form.scopes.map do |scope|
33
+ next unless scope.checked?
34
+
35
+ scope.id.to_i
36
+ end.compact
33
37
  end
34
38
  end
35
39
  end
@@ -10,6 +10,10 @@ module Decidim
10
10
  helper Decidim::TraceabilityHelper
11
11
  helper_method :current_version, :versioned_resource
12
12
 
13
+ def show
14
+ raise ActionController::RoutingError, "Not found" unless current_version
15
+ end
16
+
13
17
  private
14
18
 
15
19
  # Overwrite this method in your controller to define how to find the
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ # We don't want to reset timeout timer on routes where we make requests automatically
7
+ # (e.g. asking time before timeout or fetching comments).
8
+ module SkipTimeoutable
9
+ extend ActiveSupport::Concern
10
+
11
+ private
12
+
13
+ def skip_timeout
14
+ request.env["devise.skip_timeoutable"] = true
15
+ end
16
+ end
17
+ end
@@ -37,7 +37,7 @@ module Decidim
37
37
  end
38
38
 
39
39
  on(:invalid) do
40
- flash.now[:alert] = @form.errors[:base].join(", ") if @form.errors[:base].any?
40
+ flash.now[:alert] = @form.errors.full_messages.join(", ") if @form.errors.full_messages.any?
41
41
  render :new
42
42
  end
43
43
  end
@@ -5,6 +5,8 @@ require "active_support/concern"
5
5
  module Decidim
6
6
  # Tells/Extends time before inactivity warning or automatic logout.
7
7
  class TimeoutsController < Decidim::ApplicationController
8
+ include Decidim::SkipTimeoutable
9
+
8
10
  # Skip these methods because they can call Devise's store_location_for, which can save timeouts path to session.
9
11
  skip_before_action :store_current_location
10
12
 
@@ -23,11 +25,5 @@ module Decidim
23
25
  format.js
24
26
  end
25
27
  end
26
-
27
- private
28
-
29
- def skip_timeout
30
- request.env["devise.skip_timeoutable"] = true
31
- end
32
28
  end
33
29
  end
@@ -15,7 +15,8 @@ module Decidim
15
15
  end
16
16
 
17
17
  def resource_text
18
- resource.body
18
+ return resource.body if resource.respond_to? :body
19
+ return resource.description if resource.respond_to? :description
19
20
  end
20
21
 
21
22
  def resource_type
@@ -50,7 +50,7 @@ module Decidim
50
50
  end
51
51
 
52
52
  def unique_email
53
- return true if Decidim::User.where(
53
+ return true if Decidim::UserBaseEntity.where(
54
54
  organization: context.current_organization,
55
55
  email: email
56
56
  ).where.not(id: context.current_user.id).empty?
@@ -60,9 +60,10 @@ module Decidim
60
60
  end
61
61
 
62
62
  def unique_nickname
63
- return true if Decidim::User.where(
64
- organization: context.current_organization,
65
- nickname: nickname
63
+ return true if Decidim::UserBaseEntity.where(
64
+ "decidim_organization_id = ? AND LOWER(nickname) = ? ",
65
+ context.current_organization.id,
66
+ nickname.downcase
66
67
  ).where.not(id: context.current_user.id).empty?
67
68
 
68
69
  errors.add :nickname, :taken
@@ -35,11 +35,17 @@ module Decidim
35
35
  private
36
36
 
37
37
  def email_unique_in_organization
38
- errors.add :email, :taken if User.no_active_invitation.find_by(email: email, organization: current_organization).present?
38
+ errors.add :email, :taken if valid_users.find_by(email: email, organization: current_organization).present?
39
39
  end
40
40
 
41
41
  def nickname_unique_in_organization
42
- errors.add :nickname, :taken if User.no_active_invitation.find_by(nickname: nickname, organization: current_organization).present?
42
+ return false unless nickname
43
+
44
+ errors.add :nickname, :taken if valid_users.find_by("LOWER(nickname)= ? AND decidim_organization_id = ?", nickname.downcase, current_organization.id).present?
45
+ end
46
+
47
+ def valid_users
48
+ UserBaseEntity.where(invitation_token: nil)
43
49
  end
44
50
 
45
51
  def no_pending_invitations_exist
@@ -6,7 +6,7 @@ module Decidim
6
6
  class UserInterestScopeForm < Form
7
7
  mimic :scope
8
8
 
9
- attribute :name, String
9
+ attribute :name, JsonbAttributes
10
10
  attribute :checked, Boolean
11
11
  attribute :children, Array[UserInterestScopeForm]
12
12
 
@@ -119,5 +119,9 @@ module Decidim
119
119
  [base_url, "/", process.active_step.cta_path].join("")
120
120
  end
121
121
  end
122
+
123
+ def prevent_timeout_seconds
124
+ 0
125
+ end
122
126
  end
123
127
  end
@@ -24,7 +24,11 @@ module Decidim
24
24
  remote: true,
25
25
  html: { id: nil }.merge(html_options)
26
26
  ) do |form|
27
- yield form
27
+ # Cannot use `concat()` here because it's not available in cells
28
+ inner = []
29
+ inner << hidden_field_tag("per_page", params[:per_page], id: nil) if params[:per_page]
30
+ inner << capture { yield form }
31
+ inner.join.html_safe
28
32
  end
29
33
  end
30
34
  end
@@ -16,7 +16,30 @@ module Decidim
16
16
  add_decidim_meta_description(tags[:description])
17
17
  add_decidim_meta_url(tags[:url])
18
18
  add_decidim_meta_twitter_handler(tags[:twitter_handler])
19
- add_decidim_meta_image_url(tags[:image_url])
19
+ add_decidim_meta_image_url(add_base_url_to(tags[:image_url]))
20
+ end
21
+
22
+ # Public: Add base url to path if path doesn't include host.
23
+ # path - A String containing path (e.g. "/proposals/1" )
24
+ # Returns a String of URL including base URL and path, or path if it's blank.
25
+ def add_base_url_to(path)
26
+ return path if path.blank?
27
+ return path if URI.parse(path).host.present?
28
+
29
+ "#{resolve_base_url}#{path}"
30
+ end
31
+
32
+ # Public: Resolve base url (example: https://www.decidim.org) without url params
33
+ # Returns a String of base URL
34
+ def resolve_base_url
35
+ return request.base_url if respond_to?(:request) && request&.base_url.present?
36
+
37
+ uri = URI.parse(decidim.root_url(host: current_organization.host))
38
+ if uri.port.blank? || [80, 443].include?(uri.port)
39
+ "#{uri.scheme}://#{uri.host}"
40
+ else
41
+ "#{uri.scheme}://#{uri.host}:#{uri.port}"
42
+ end
20
43
  end
21
44
 
22
45
  # Public: Accumulates the given `title` so that they can be chained. Since Rails views
@@ -94,11 +94,17 @@ module Decidim
94
94
  end
95
95
  end
96
96
 
97
+ # This method is currently being used only for Proposal and Meeting,
98
+ # It aims to load the presenter class, and perform some basic sanitization on the content
99
+ # This method should be used along side simple_format.
100
+ # @param resource [Object] Resource object
101
+ # @param method [Symbol] Method name
102
+ #
103
+ # @return ActiveSupport::SafeBuffer
97
104
  def render_sanitized_content(resource, method)
98
105
  content = present(resource).send(method, links: true, strip_tags: !safe_content?)
99
- content = simple_format(content, {}, sanitize: false)
100
106
 
101
- return content unless safe_content?
107
+ return decidim_sanitize(content, {}) unless safe_content?
102
108
 
103
109
  decidim_sanitize_editor(content)
104
110
  end
@@ -130,15 +130,16 @@ module Decidim
130
130
  end
131
131
 
132
132
  # Whether this activity or log is visible for a given user (can also be nil)
133
- #
134
- # Returns a True/False.
135
133
  def visible_for?(user)
136
- return false if resource_lazy.blank?
137
- return false if participatory_space_lazy.blank?
138
- return false if resource_lazy.respond_to?(:hidden?) && resource_lazy.hidden?
139
- return false if resource_lazy.respond_to?(:can_participate?) && !resource_lazy.can_participate?(user)
140
-
141
- true
134
+ resource_lazy.present? &&
135
+ participatory_space_lazy.present? &&
136
+ !resource_lazy.try(:deleted?) &&
137
+ !resource_lazy.try(:hidden?) &&
138
+ (!resource_lazy.respond_to?(:can_participate?) || resource_lazy.try(:can_participate?, user))
139
+ rescue NameError => e
140
+ Rails.logger.warn "Failed resource for #{self.class.name}(id=#{id}): #{e.message}"
141
+
142
+ false
142
143
  end
143
144
  end
144
145
  end
@@ -30,6 +30,7 @@ module Decidim
30
30
 
31
31
  scope :blocked, -> { where(blocked: true) }
32
32
  scope :not_blocked, -> { where(blocked: false) }
33
+ scope :available, -> { where(deleted_at: nil, blocked: false, managed: false) }
33
34
 
34
35
  # Public: Returns a collection with all the public entities this user is following.
35
36
  #
@@ -55,6 +56,7 @@ module Decidim
55
56
  scope = scope.public_spaces if klass.try(:participatory_space?)
56
57
  scope = scope.includes(:component) if klass.try(:has_component?)
57
58
  scope = scope.filter(&:visible?) if klass.method_defined?(:visible?)
59
+ scope = scope.reject(&:blocked) if klass == Decidim::UserBaseEntity
58
60
  scope
59
61
  end
60
62
  end
@@ -5,6 +5,9 @@ const EXCLUDE_CLASSES = [
5
5
  "footer-social__icon",
6
6
  "logo-cityhall"
7
7
  ];
8
+ const EXCLUDE_ANCESTOR_CLASSES = [
9
+ "editor-container"
10
+ ]
8
11
  const EXCLUDE_REL = ["license", "decidim"];
9
12
 
10
13
  const DEFAULT_MESSAGES = {
@@ -27,6 +30,9 @@ export default class ExternalLink {
27
30
  if (EXCLUDE_CLASSES.some((cls) => this.$link.hasClass(cls))) {
28
31
  return;
29
32
  }
33
+ if (EXCLUDE_ANCESTOR_CLASSES.some((cls) => this.$link.parents().hasClass(cls))) {
34
+ return;
35
+ }
30
36
  if (
31
37
  EXCLUDE_REL.some((rel) => {
32
38
  const linkRels = `${this.$link.attr("rel")}`.split(" ");
@@ -16,6 +16,12 @@ export default class MapStaticController extends MapController {
16
16
  this.map.tap.disable();
17
17
  }
18
18
 
19
+ if (this.config.zoom) {
20
+ this.map.setZoom(this.config.zoom);
21
+ } else {
22
+ this.map.setZoom(15);
23
+ }
24
+
19
25
  if (this.config.latitude && this.config.longitude) {
20
26
  const coordinates = [this.config.latitude, this.config.longitude];
21
27
 
@@ -27,11 +33,6 @@ export default class MapStaticController extends MapController {
27
33
  }).addTo(this.map);
28
34
  marker._icon.removeAttribute("tabindex");
29
35
  }
30
- if (this.config.zoom) {
31
- this.map.setZoom(this.config.zoom);
32
- } else {
33
- this.map.setZoom(15);
34
- }
35
36
 
36
37
  if (this.config.link) {
37
38
  this.map._container.addEventListener("click", (ev) => {
@@ -33,7 +33,7 @@ import MapDragMarkerController from "src/decidim/map/controller/drag_marker"
33
33
  * @param {Object} config The map configuration object.
34
34
  * @returns {MapController} The controller for the map.
35
35
  */
36
- export default function createMapController(mapId, config) {
36
+ const createMapController = function(mapId, config) {
37
37
  if (config.type === "static") {
38
38
  return new MapStaticController(mapId, config);
39
39
  } else if (config.type === "drag-marker") {
@@ -42,3 +42,5 @@ export default function createMapController(mapId, config) {
42
42
 
43
43
  return new MapMarkersController(mapId, config);
44
44
  }
45
+
46
+ window.Decidim.createMapController = createMapController;
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable require-jsdoc */
2
2
 
3
3
  import * as L from "leaflet";
4
- import createMapController from "src/decidim/map/factory"
4
+ import "src/decidim/map/factory"
5
5
 
6
6
  /**
7
7
  * @deprecated
@@ -60,7 +60,7 @@ const loadMap = (mapId, markersData) => {
60
60
  legacyMapSupport($map);
61
61
 
62
62
  const mapData = $map.data("decidim-map");
63
- const ctrl = createMapController(mapId, mapData);
63
+ const ctrl = window.Decidim.createMapController(mapId, mapData);
64
64
  const map = ctrl.load();
65
65
 
66
66
  L.tileLayer.here(mapData.tileLayer).addTo(map);
@@ -1,4 +1,4 @@
1
- import createMapController from "src/decidim/map/factory"
1
+ import "src/decidim/map/factory"
2
2
 
3
3
  $(() => {
4
4
  // Load the map controller factory method in the document.ready handler to
@@ -20,7 +20,7 @@ $(() => {
20
20
  }
21
21
 
22
22
  const mapConfig = $map.data("decidim-map");
23
- const ctrl = createMapController(mapId, mapConfig);
23
+ const ctrl = window.Decidim.createMapController(mapId, mapConfig);
24
24
  const map = ctrl.load();
25
25
 
26
26
  $map.data("map", map);
@@ -1,5 +1,4 @@
1
1
  import moment from "moment"
2
- import Foundation from "foundation-sites"
3
2
 
4
3
  $(() => {
5
4
  let sessionTimeOutEnabled = true;
@@ -8,17 +7,18 @@ $(() => {
8
7
  const secondsUntilTimeoutPath = $timeoutModal.data("seconds-until-timeout-path");
9
8
  const heartbeatPath = $timeoutModal.data("heartbeat-path");
10
9
  const interval = parseInt($timeoutModal.data("session-timeout-interval"), 10);
10
+ const preventTimeOutSeconds = $timeoutModal.data("prevent-timeout-seconds");
11
11
  let endsAt = moment().add(timeoutInSeconds, "seconds");
12
12
  let lastAction = moment();
13
- const popup = new Foundation.Reveal($timeoutModal);
14
13
  const $continueSessionButton = $("#continueSession");
15
14
  let lastActivityCheck = moment();
16
15
  // 5 * 60 seconds = 5 Minutes
17
16
  const activityCheckInterval = 5 * 60;
17
+ const preventTimeOutUntil = moment().add(preventTimeOutSeconds, "seconds");
18
18
 
19
19
  // Ajax request is made at timeout_modal.html.erb
20
20
  $continueSessionButton.on("click", () => {
21
- $("#timeoutModal").foundation("close");
21
+ $timeoutModal.foundation("close");
22
22
  // In admin panel we have to hide all overlays
23
23
  $(".reveal-overlay").css("display", "none");
24
24
  lastActivityCheck = moment();
@@ -82,7 +82,12 @@ $(() => {
82
82
  }
83
83
 
84
84
  const timeRemaining = Math.round((endsAt - moment()) / 1000);
85
- if (timeRemaining > 150) {
85
+ if (timeRemaining > 170) {
86
+ return;
87
+ }
88
+
89
+ if (moment() < preventTimeOutUntil) {
90
+ heartbeat();
86
91
  return;
87
92
  }
88
93
 
@@ -95,7 +100,7 @@ $(() => {
95
100
  } else if (secondsUntilSessionExpires <= 90) {
96
101
  $timeoutModal.find("#reveal-hidden-sign-out")[0].click();
97
102
  } else if (secondsUntilSessionExpires <= 150) {
98
- popup.open();
103
+ $timeoutModal.foundation("open");
99
104
  }
100
105
  });
101
106
  }, interval);
@@ -30,6 +30,8 @@ $datetime-bg: var(--primary);
30
30
  border-radius: $card-border-radius;
31
31
  // Keep visible for accessibility (active/focused card as a link)
32
32
  overflow: visible;
33
+ overflow-wrap: break-word;
34
+ hyphens: auto;
33
35
 
34
36
  @include modifiers(
35
37
  border-top-color,
@@ -80,6 +80,8 @@ $comment-form-bg: $light-gray;
80
80
 
81
81
  .comment__content{
82
82
  padding: 0 $comment-padding;
83
+ overflow-wrap: break-word;
84
+ hyphens: auto;
83
85
 
84
86
  > :last-child{
85
87
  margin-bottom: 0;
@@ -77,6 +77,11 @@ label > [type="radio"]{
77
77
  margin-right: 1rem;
78
78
  flex-shrink: 0;
79
79
  }
80
+
81
+ &,
82
+ &.tiny{
83
+ height: auto;
84
+ }
80
85
  }
81
86
 
82
87
  .switch{
@@ -116,9 +116,11 @@ module Decidim
116
116
  end
117
117
 
118
118
  def apply_endorsement_permissions
119
- return disallow! if !current_settings.endorsements_enabled || current_settings.endorsements_blocked
119
+ is_allowed = current_settings.endorsements_enabled &&
120
+ !current_settings.endorsements_blocked &&
121
+ authorized?(:endorse, resource: context.fetch(:resource, nil))
120
122
 
121
- allow!
123
+ toggle_allow(is_allowed)
122
124
  end
123
125
 
124
126
  def notification_action?
@@ -13,6 +13,8 @@ module Decidim
13
13
  # nickname presented in a twitter-like style
14
14
  #
15
15
  def nickname
16
+ return "" if __getobj__.blocked?
17
+
16
18
  "@#{__getobj__.nickname}"
17
19
  end
18
20
 
@@ -33,13 +35,14 @@ module Decidim
33
35
  end
34
36
 
35
37
  def avatar_url(variant = nil)
38
+ return default_avatar_url if __getobj__.blocked?
36
39
  return avatar.default_url unless avatar.attached?
37
40
 
38
41
  avatar.path(variant: variant)
39
42
  end
40
43
 
41
44
  def default_avatar_url
42
- attached_uploader.default_url
45
+ attached_uploader(:avatar).default_url
43
46
  end
44
47
 
45
48
  def profile_path
@@ -49,6 +49,15 @@ class PasswordValidator < ActiveModel::EachValidator
49
49
  I18n.t "password_validator.#{reason}"
50
50
  end
51
51
 
52
+ def organization
53
+ @organization ||= organization_from_record
54
+ end
55
+
56
+ def organization_from_record
57
+ return record.current_organization if record.respond_to?(:current_organization)
58
+ return record.organization if record.respond_to?(:organization)
59
+ end
60
+
52
61
  def strong?
53
62
  VALIDATION_METHODS.each do |method|
54
63
  @weak_password_reasons << method.to_s.sub(/\?$/, "").to_sym if send(method.to_s)
@@ -96,10 +105,10 @@ class PasswordValidator < ActiveModel::EachValidator
96
105
  end
97
106
 
98
107
  def domain_included_in_password?
99
- return false unless record&.current_organization&.host
100
- return true if value.include?(record.current_organization.host)
108
+ return false unless organization && organization.host
109
+ return true if value.include?(organization.host)
101
110
 
102
- record.current_organization.host.split(".").each do |part|
111
+ organization.host.split(".").each do |part|
103
112
  next if part.length < IGNORE_SIMILARITY_SHORTER_THAN
104
113
 
105
114
  return true if value.include?(part)
@@ -1,7 +1,7 @@
1
1
  <% add_decidim_page_title(t("my_data", scope: "layouts.decidim.user_profile")) %>
2
2
  <% content_for(:subtitle) { t("my_data", scope: "layouts.decidim.user_profile") } %>
3
3
 
4
- <div class="row data-portability">
4
+ <div class="data-portability">
5
5
  <strong><%= t(".download_data") %></strong>
6
6
  <p><%= t(".download_data_description", user_email: current_user.email).html_safe %></p>
7
7
  <%= button_to t(".request_data"), export_data_portability_path, class: "button", data: { disable: true } %>
@@ -27,11 +27,11 @@
27
27
 
28
28
  <% if f.object.class.require_password_on_accepting %>
29
29
  <div class="field">
30
- <p><%= f.password_field :password, required: "required", minlength: ::Devise.password_length.min, maxlength: ::Devise.password_length.max %></p>
30
+ <p><%= f.password_field :password, required: "required", minlength: ::PasswordValidator::MINIMUM_LENGTH, maxlength: ::PasswordValidator::MAX_LENGTH %></p>
31
31
  </div>
32
32
 
33
33
  <div class="field">
34
- <p><%= f.password_field :password_confirmation, required: "required", minlength: ::Devise.password_length.min, maxlength: ::Devise.password_length.max %></p>
34
+ <p><%= f.password_field :password_confirmation, required: "required", minlength: ::PasswordValidator::MINIMUM_LENGTH, maxlength: ::PasswordValidator::MAX_LENGTH %></p>
35
35
  </div>
36
36
  <% end %>
37
37
  </div>