decidim-core 0.26.5 → 0.26.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/announcement_cell.rb +1 -1
  3. data/app/cells/decidim/content_blocks/cta_cell.rb +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/sub_hero_cell.rb +1 -1
  7. data/app/controllers/decidim/links_controller.rb +8 -11
  8. data/app/helpers/decidim/cells_helper.rb +1 -0
  9. data/app/helpers/decidim/external_domain_helper.rb +14 -3
  10. data/app/helpers/decidim/sanitize_helper.rb +15 -5
  11. data/app/models/decidim/scope_type.rb +28 -0
  12. data/app/packs/src/decidim/editor/clipboard_override.js +6 -2
  13. data/app/packs/src/decidim/editor.js +63 -33
  14. data/app/packs/stylesheets/decidim/_editor.scss +129 -0
  15. data/app/packs/stylesheets/decidim/extras/_quill.scss +0 -6
  16. data/app/packs/stylesheets/decidim/modules/_buttons.scss +10 -6
  17. data/app/packs/stylesheets/decidim/modules/_cards.scss +1 -1
  18. data/app/packs/stylesheets/decidim/modules/_comments.scss +24 -0
  19. data/app/packs/stylesheets/decidim/vizzs/_linechart.scss +2 -2
  20. data/app/packs/stylesheets/decidim/vizzs/_rowchart.scss +2 -2
  21. data/app/presenters/decidim/notification_presenter.rb +1 -1
  22. data/app/presenters/decidim/user_group_presenter.rb +1 -1
  23. data/app/presenters/decidim/user_presenter.rb +1 -1
  24. data/app/scrubbers/decidim/admin_input_scrubber.rb +27 -0
  25. data/app/scrubbers/decidim/user_input_scrubber.rb +32 -5
  26. data/app/services/decidim/traceability.rb +1 -0
  27. data/app/views/decidim/links/_invalid_url_modal.html.erb +17 -0
  28. data/app/views/decidim/links/_modal.html.erb +1 -1
  29. data/app/views/decidim/links/invalid_url.js.erb +24 -0
  30. data/app/views/decidim/links/new.html.erb +1 -1
  31. data/app/views/decidim/messaging/conversations/_conversation.html.erb +1 -5
  32. data/app/views/decidim/pages/_standalone.html.erb +1 -1
  33. data/app/views/decidim/pages/_tabbed.html.erb +1 -1
  34. data/config/locales/ar.yml +422 -7
  35. data/config/locales/bg.yml +1 -4
  36. data/config/locales/ca.yml +20 -18
  37. data/config/locales/cs.yml +21 -29
  38. data/config/locales/da.yml +3 -0
  39. data/config/locales/de.yml +4 -23
  40. data/config/locales/el.yml +2 -4
  41. data/config/locales/en.yml +15 -13
  42. data/config/locales/eo.yml +2 -1
  43. data/config/locales/es-MX.yml +19 -17
  44. data/config/locales/es-PY.yml +19 -17
  45. data/config/locales/es.yml +20 -18
  46. data/config/locales/et.yml +3 -0
  47. data/config/locales/eu.yml +87 -63
  48. data/config/locales/fa-IR.yml +1 -0
  49. data/config/locales/fi-plain.yml +0 -19
  50. data/config/locales/fi.yml +17 -15
  51. data/config/locales/fr-CA.yml +22 -17
  52. data/config/locales/fr.yml +20 -15
  53. data/config/locales/ga-IE.yml +1 -0
  54. data/config/locales/gl.yml +0 -22
  55. data/config/locales/gn-PY.yml +3 -0
  56. data/config/locales/hr.yml +3 -0
  57. data/config/locales/hu.yml +48 -24
  58. data/config/locales/id-ID.yml +2 -4
  59. data/config/locales/is-IS.yml +2 -1
  60. data/config/locales/it.yml +1 -11
  61. data/config/locales/ja.yml +9 -23
  62. data/config/locales/ka-GE.yml +3 -0
  63. data/config/locales/kaa.yml +1 -0
  64. data/config/locales/lb.yml +0 -4
  65. data/config/locales/lt.yml +0 -33
  66. data/config/locales/lv.yml +0 -3
  67. data/config/locales/nl.yml +1 -20
  68. data/config/locales/no.yml +1 -24
  69. data/config/locales/oc-FR.yml +2 -0
  70. data/config/locales/pl.yml +0 -33
  71. data/config/locales/pt-BR.yml +2 -6
  72. data/config/locales/pt.yml +0 -4
  73. data/config/locales/ro-RO.yml +5 -8
  74. data/config/locales/ru.yml +1 -3
  75. data/config/locales/sk.yml +3 -5
  76. data/config/locales/sl.yml +1 -0
  77. data/config/locales/sr-CS.yml +2 -0
  78. data/config/locales/sv.yml +1 -24
  79. data/config/locales/tr-TR.yml +3 -7
  80. data/config/locales/uk.yml +1 -3
  81. data/config/locales/zh-CN.yml +0 -4
  82. data/config/locales/zh-TW.yml +1712 -0
  83. data/lib/decidim/core/test/shared_examples/comments_examples.rb +36 -0
  84. data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +10 -0
  85. data/lib/decidim/core/test/shared_examples/rich_text_editor_examples.rb +7 -3
  86. data/lib/decidim/core/test.rb +1 -0
  87. data/lib/decidim/core/version.rb +1 -1
  88. data/lib/decidim/form_builder.rb +0 -1
  89. data/lib/decidim/publicable.rb +4 -0
  90. metadata +12 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8937550934aed6ed69fa84837edbbc2902c5fd6779654a5180a63abbfe25d700
4
- data.tar.gz: ba86b8da585b54db8845cf1d5e476086db70d03920f99ddf3a32cbe023521992
3
+ metadata.gz: 2d573b856227ec581d40d90cff9a85c1f21502a1ed6278b82aa9768a434f0e9c
4
+ data.tar.gz: 2ca2fff70b6e6b9314450c35ab22965b3ba60af303a2839c7716e502cb566b3a
5
5
  SHA512:
6
- metadata.gz: de40caba191fb9ff0b88bbf9055fbb4592fcc12352c6e35d21d812e87399b1772254d669438ade3ada960ca994247ab87b3eb4743e80df9121cb3bb07c6a9f18
7
- data.tar.gz: c115b3d2e531d0b0d8e43f7b41a863dc51eb2c076bc8c4f2c8731e642fb191115b2fdf6aebe6a3cf28c48fb746c3e9cec85ea9a5be630d382ee695cff238278f
6
+ metadata.gz: 1000d09afe7e9af0586fa14c917c77a150bf9f55adee9d0a243744799a9cf9c84aa364b0f014cdec6eda3855c10b4b15772732c979d9f15e381c8a62e78aad8f
7
+ data.tar.gz: 1a4feafaa713a4fa540aab815e0306f125cc74d45599d5defbec2e9dd2cce8bc6223acd0148424b3973a0f1d6853b96cd3ee9a6fda7ff45cc91073fd2b84ac8a
@@ -62,7 +62,7 @@ module Decidim
62
62
  end
63
63
 
64
64
  def clean(value)
65
- decidim_sanitize(translated_attribute(value))
65
+ decidim_sanitize_admin(translated_attribute(value))
66
66
  end
67
67
  end
68
68
  end
@@ -16,7 +16,7 @@ module Decidim
16
16
  end
17
17
 
18
18
  def translated_description
19
- @translated_description ||= decidim_sanitize_editor(translated_attribute(model.settings.description))
19
+ @translated_description ||= decidim_sanitize_editor_admin(translated_attribute(model.settings.description))
20
20
  end
21
21
 
22
22
  def button_url
@@ -6,7 +6,7 @@
6
6
  <% if translated_welcome_text.blank? %>
7
7
  <%= t("decidim.pages.home.hero.welcome", organization: current_organization.name) %>
8
8
  <% else %>
9
- <%= decidim_sanitize translated_welcome_text %>
9
+ <%= decidim_sanitize_admin translated_welcome_text %>
10
10
  <% end %>
11
11
  </h1>
12
12
  </div>
@@ -7,7 +7,7 @@
7
7
  <%= translated_attribute current_organization.highlighted_content_banner_title %>
8
8
  </h1>
9
9
  <span class="text-highlight">
10
- <%= decidim_sanitize_editor translated_attribute current_organization.highlighted_content_banner_short_description %>
10
+ <%= decidim_sanitize_editor_admin translated_attribute current_organization.highlighted_content_banner_short_description %>
11
11
  </span>
12
12
  </div>
13
13
  <div class="columns large-2">
@@ -15,7 +15,7 @@ module Decidim
15
15
  private
16
16
 
17
17
  def organization_description
18
- desc = decidim_sanitize(translated_attribute(current_organization.description))
18
+ desc = decidim_sanitize_admin(translated_attribute(current_organization.description))
19
19
 
20
20
  # Strip the surrounding paragraph tag because it is not allowed within
21
21
  # a <hN> element.
@@ -21,24 +21,21 @@ module Decidim
21
21
 
22
22
  def invalid_url
23
23
  flash[:alert] = I18n.t("decidim.links.invalid_url")
24
- redirect_to decidim.root_path
24
+ if request.xhr?
25
+ render "invalid_url"
26
+ else
27
+ redirect_to decidim.root_path
28
+ end
25
29
  end
26
30
 
27
31
  def parse_url
32
+ raise Decidim::InvalidUrlError if params[:external_url].blank?
28
33
  raise Decidim::InvalidUrlError unless external_url
29
-
30
- parts = external_url.match %r{\A(([a-z]+):)?//([^/]+)(/.*)?\z}
31
- raise Decidim::InvalidUrlError unless parts
32
-
33
- @url_parts = {
34
- protocol: parts[1],
35
- domain: parts[3],
36
- path: parts[4]
37
- }
34
+ raise Decidim::InvalidUrlError unless %w(http https).include?(external_url.scheme)
38
35
  end
39
36
 
40
37
  def external_url
41
- @external_url ||= URI.parse(params[:external_url]).to_s
38
+ @external_url ||= URI.parse(params[:external_url])
42
39
  end
43
40
  end
44
41
  end
@@ -35,6 +35,7 @@ module Decidim
35
35
  end
36
36
 
37
37
  def user_flaggable?
38
+ return if (try(:profile_holder) || try(:profile_user) || try(:model)).try(:blocked)
38
39
  return unless context[:controller].try(:flaggable_controller?)
39
40
 
40
41
  true
@@ -3,10 +3,21 @@
3
3
  module Decidim
4
4
  module ExternalDomainHelper
5
5
  def highlight_domain
6
+ highlighted_domain = [
7
+ external_url.host,
8
+ (external_url.port && [80, 443].include?(external_url.port) ? "" : ":#{external_url.port}")
9
+ ].join
10
+
11
+ path = [
12
+ external_url.path,
13
+ (external_url.query ? "?#{external_url.query}" : ""),
14
+ (external_url.fragment ? "##{external_url.fragment}" : "")
15
+ ].join
16
+
6
17
  tag.div do
7
- content_tag(:span, "#{@url_parts[:protocol]}//") +
8
- content_tag(:span, @url_parts[:domain], class: "alert") +
9
- content_tag(:span, @url_parts[:path])
18
+ content_tag(:span, "#{external_url.scheme}://") +
19
+ content_tag(:span, highlighted_domain, class: "text-alert") +
20
+ content_tag(:span, path)
10
21
  end
11
22
  end
12
23
  end
@@ -16,13 +16,18 @@ module Decidim
16
16
  #
17
17
  # Returns an HTML-safe String.
18
18
  def decidim_sanitize(html, options = {})
19
+ scrubber = options[:scrubber] || Decidim::UserInputScrubber.new
19
20
  if options[:strip_tags]
20
- strip_tags sanitize(html, scrubber: Decidim::UserInputScrubber.new)
21
+ strip_tags sanitize(html, scrubber: scrubber)
21
22
  else
22
- sanitize(html, scrubber: Decidim::UserInputScrubber.new)
23
+ sanitize(html, scrubber: scrubber)
23
24
  end
24
25
  end
25
26
 
27
+ def decidim_sanitize_admin(html, options = {})
28
+ decidim_sanitize(html, { scrubber: Decidim::AdminInputScrubber.new }.merge(options))
29
+ end
30
+
26
31
  def decidim_sanitize_newsletter(html, options = {})
27
32
  if options[:strip_tags]
28
33
  strip_tags sanitize(html, scrubber: Decidim::NewsletterScrubber.new)
@@ -32,7 +37,11 @@ module Decidim
32
37
  end
33
38
 
34
39
  def decidim_sanitize_editor(html, options = {})
35
- content_tag(:div, decidim_sanitize(html, options), class: %w(ql-editor ql-reset-decidim))
40
+ content_tag(:div, decidim_sanitize(html, options), class: %w(ql-editor-display))
41
+ end
42
+
43
+ def decidim_sanitize_editor_admin(html, options = {})
44
+ decidim_sanitize_editor(html, { scrubber: Decidim::AdminInputScrubber.new }.merge(options))
36
45
  end
37
46
 
38
47
  def decidim_html_escape(text)
@@ -102,9 +111,10 @@ module Decidim
102
111
  #
103
112
  # @return ActiveSupport::SafeBuffer
104
113
  def render_sanitized_content(resource, method)
105
- content = present(resource).send(method, links: true, strip_tags: !safe_content?)
114
+ content = present(resource).send(method, links: true, strip_tags: !try(:safe_content?))
106
115
 
107
- return decidim_sanitize(content, {}) unless safe_content?
116
+ return decidim_sanitize(content, {}) unless try(:safe_content?)
117
+ return decidim_sanitize_editor_admin(content, {}) if try(:safe_content_admin?)
108
118
 
109
119
  decidim_sanitize_editor(content)
110
120
  end
@@ -15,5 +15,33 @@ module Decidim
15
15
  has_many :scopes, class_name: "Decidim::Scope", inverse_of: :scope_type, dependent: :nullify
16
16
 
17
17
  validates :name, presence: true
18
+
19
+ before_destroy :detach_dynamic_associations
20
+
21
+ def self.log_presenter_class_for(_log)
22
+ Decidim::AdminLog::ScopeTypePresenter
23
+ end
24
+
25
+ private
26
+
27
+ # This method detaches all records that may have association with the scope
28
+ # type. This cannot be done directly using the `dependent` option in the
29
+ # `has_many` relation in order to avoid tight coupling between the modules.
30
+ #
31
+ # This logic does not have to be applied to any classes that have been
32
+ # defined as `has_many` associations within this model already as they are
33
+ # already handled by the `dependent` option.
34
+ def detach_dynamic_associations
35
+ ActiveRecord::Base.descendants.each do |cls|
36
+ next if cls.abstract_class? || !cls.name&.match?(/^Decidim::/)
37
+ next if [self.class, Decidim::Scope].include?(cls)
38
+
39
+ cls.reflect_on_all_associations(:belongs_to).each do |ref|
40
+ next unless ref.options[:class_name] == self.class.name
41
+
42
+ cls.where(ref.options[:foreign_key] => id).update_all(ref.options[:foreign_key] => nil) # rubocop:disable Rails/SkipsModelValidations
43
+ end
44
+ end
45
+ end
18
46
  end
19
47
  end
@@ -70,7 +70,9 @@ export default class ClipboardOverride extends Clipboard {
70
70
  const text = ev.clipboardData.getData("text/plain");
71
71
  const files = Array.from(ev.clipboardData.files || []);
72
72
  if (!html && files.length > 0) {
73
- this.quill.uploader.upload(range, files);
73
+ if (typeof this.quill.uploader !== "undefined") {
74
+ this.quill.uploader.upload(range, files);
75
+ }
74
76
  return;
75
77
  }
76
78
  if (html && files.length > 0) {
@@ -79,7 +81,9 @@ export default class ClipboardOverride extends Clipboard {
79
81
  doc.body.childElementCount === 1 &&
80
82
  doc.body.firstElementChild.tagName === "IMG"
81
83
  ) {
82
- this.quill.uploader.upload(range, files);
84
+ if (typeof this.quill.uploader !== "undefined") {
85
+ this.quill.uploader.upload(range, files);
86
+ }
83
87
  return;
84
88
  }
85
89
  }
@@ -1,11 +1,25 @@
1
1
  /* eslint-disable require-jsdoc */
2
2
 
3
- import lineBreakButtonHandler from "src/decidim/editor/linebreak_module"
4
- import "src/decidim/editor/clipboard_override"
5
- import "src/decidim/vendor/image-resize.min"
6
- import "src/decidim/vendor/image-upload.min"
3
+ import lineBreakButtonHandler from "src/decidim/editor/linebreak_module";
4
+ import "src/decidim/editor/clipboard_override";
5
+ import "src/decidim/vendor/image-resize.min";
6
+ import "src/decidim/vendor/image-upload.min";
7
7
 
8
- const quillFormats = ["bold", "italic", "link", "underline", "header", "list", "video", "image", "alt", "break", "width", "style", "code", "blockquote", "indent"];
8
+ const quillFormats = [
9
+ "bold",
10
+ "italic",
11
+ "link",
12
+ "underline",
13
+ "header",
14
+ "list",
15
+ "alt",
16
+ "break",
17
+ "width",
18
+ "style",
19
+ "code",
20
+ "blockquote",
21
+ "indent"
22
+ ];
9
23
 
10
24
  export default function createQuillEditor(container) {
11
25
  const toolbar = $(container).data("toolbar");
@@ -17,26 +31,28 @@ export default function createQuillEditor(container) {
17
31
  [{ list: "ordered" }, { list: "bullet" }],
18
32
  ["link", "clean"],
19
33
  ["code", "blockquote"],
20
- [{ "indent": "-1"}, { "indent": "+1" }]
34
+ [{ indent: "-1" }, { indent: "+1" }]
21
35
  ];
22
36
 
23
- let addImage = $(container).data("editorImages");
37
+ let addImage = false;
38
+ let addVideo = false;
24
39
 
25
- if (toolbar === "full") {
40
+ /**
41
+ * - basic = only basic controls without titles
42
+ * - content = basic + headings
43
+ * - full = basic + headings + image + video
44
+ */
45
+ if (toolbar === "content") {
46
+ quillToolbar = [[{ header: [2, 3, 4, 5, 6, false] }], ...quillToolbar];
47
+ } else if (toolbar === "full") {
48
+ addImage = true;
49
+ addVideo = true;
26
50
  quillToolbar = [
27
51
  [{ header: [2, 3, 4, 5, 6, false] }],
28
52
  ...quillToolbar,
29
- ["video"]
53
+ ["video"],
54
+ ["image"]
30
55
  ];
31
- } else if (toolbar === "basic") {
32
- quillToolbar = [
33
- ...quillToolbar,
34
- ["video"]
35
- ];
36
- }
37
-
38
- if (addImage) {
39
- quillToolbar.push(["image"]);
40
56
  }
41
57
 
42
58
  let modules = {
@@ -44,17 +60,26 @@ export default function createQuillEditor(container) {
44
60
  toolbar: {
45
61
  container: quillToolbar,
46
62
  handlers: {
47
- "linebreak": lineBreakButtonHandler
63
+ linebreak: lineBreakButtonHandler
48
64
  }
49
65
  }
50
66
  };
51
67
  const $input = $(container).siblings('input[type="hidden"]');
52
68
  container.innerHTML = $input.val() || "";
53
69
  const token = $('meta[name="csrf-token"]').attr("content");
70
+
71
+ if (addVideo) {
72
+ quillFormats.push("video");
73
+ }
74
+
54
75
  if (addImage) {
76
+ // Attempt to allow images only if the image support is enabled at editor support.
77
+ // see: https://github.com/quilljs/quill/issues/1108
78
+ quillFormats.push("image");
79
+
55
80
  modules.imageResize = {
56
81
  modules: ["Resize", "DisplaySize"]
57
- }
82
+ };
58
83
  modules.imageUpload = {
59
84
  url: $(container).data("uploadImagesPath"),
60
85
  method: "POST",
@@ -62,18 +87,23 @@ export default function createQuillEditor(container) {
62
87
  withCredentials: false,
63
88
  headers: { "X-CSRF-Token": token },
64
89
  callbackOK: (serverResponse, next) => {
65
- $("div.ql-toolbar").last().removeClass("editor-loading")
90
+ $("div.ql-toolbar").last().removeClass("editor-loading");
66
91
  next(serverResponse.url);
67
92
  },
68
93
  callbackKO: (serverError) => {
69
- $("div.ql-toolbar").last().removeClass("editor-loading")
94
+ $("div.ql-toolbar").last().removeClass("editor-loading");
70
95
  console.log(`Image upload error: ${serverError.message}`);
71
96
  },
72
97
  checkBeforeSend: (file, next) => {
73
- $("div.ql-toolbar").last().addClass("editor-loading")
98
+ $("div.ql-toolbar").last().addClass("editor-loading");
74
99
  next(file);
75
100
  }
76
- }
101
+ };
102
+
103
+ const text = $(container).data("dragAndDropHelpText");
104
+ $(container).after(
105
+ `<p class="help-text" style="margin-top:-1.5rem;">${text}</p>`
106
+ );
77
107
  }
78
108
  const quill = new Quill(container, {
79
109
  modules: modules,
@@ -81,6 +111,11 @@ export default function createQuillEditor(container) {
81
111
  theme: "snow"
82
112
  });
83
113
 
114
+ if (addImage === false) {
115
+ // Firefox natively implements image drop in contenteditable which is why we need to disable that
116
+ quill.root.addEventListener("drop", (ev) => ev.preventDefault());
117
+ }
118
+
84
119
  if (disabled) {
85
120
  quill.disable();
86
121
  }
@@ -95,7 +130,10 @@ export default function createQuillEditor(container) {
95
130
  });
96
131
  container.dispatchEvent(event);
97
132
 
98
- if ((text === "\n" || text === "\n\n") && quill.root.querySelectorAll(allowedEmptyContentSelector).length === 0) {
133
+ if (
134
+ (text === "\n" || text === "\n\n") &&
135
+ quill.root.querySelectorAll(allowedEmptyContentSelector).length === 0
136
+ ) {
99
137
  $input.val("");
100
138
  } else {
101
139
  const emptyParagraph = "<p><br></p>";
@@ -109,13 +147,5 @@ export default function createQuillEditor(container) {
109
147
  // After editor is ready, linebreak_module deletes two extraneous new lines
110
148
  quill.emitter.emit("editor-ready");
111
149
 
112
- if (addImage) {
113
- const text = $(container).data("dragAndDropHelpText");
114
- $(container).after(`<p class="help-text" style="margin-top:-1.5rem;">${text}</p>`);
115
- }
116
-
117
- // After editor is ready, linebreak_module deletes two extraneous new lines
118
- quill.emitter.emit("editor-ready");
119
-
120
150
  return quill;
121
151
  }
@@ -10,4 +10,133 @@
10
10
  margin-bottom: $paragraph-margin-bottom;
11
11
  text-rendering: $paragraph-text-rendering;
12
12
  }
13
+
14
+ ul,
15
+ ol{
16
+ margin-bottom: $paragraph-margin-bottom;
17
+ }
18
+ }
19
+
20
+ .ql-editor-display{
21
+ ul,
22
+ ol{
23
+ li{
24
+ list-style-type: none;
25
+ margin-bottom: .5rem;
26
+
27
+ &::before{
28
+ content: "\2022";
29
+ display: inline-block;
30
+ white-space: nowrap;
31
+ width: 1.2em;
32
+ }
33
+
34
+ &.ql-indent-1{
35
+ padding-left: 3em;
36
+ }
37
+
38
+ &.ql-indent-2{
39
+ padding-left: 6em;
40
+ }
41
+
42
+ &.ql-indent-3{
43
+ padding-left: 9em;
44
+ }
45
+
46
+ &.ql-indent-4{
47
+ padding-left: 12em;
48
+ }
49
+
50
+ &.ql-indent-5{
51
+ padding-left: 15em;
52
+ }
53
+
54
+ &.ql-indent-6{
55
+ padding-left: 18em;
56
+ }
57
+
58
+ &.ql-indent-7{
59
+ padding-left: 21em;
60
+ }
61
+
62
+ &.ql-indent-8{
63
+ padding-left: 24em;
64
+ }
65
+
66
+ &.ql-indent-9{
67
+ padding-left: 27em;
68
+ }
69
+ }
70
+ }
71
+
72
+ ol{
73
+ li{
74
+ counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
75
+ counter-increment: list-0;
76
+
77
+ &::before{ content: counter(list-0, decimal) ". "; }
78
+
79
+ &.ql-indent-1{
80
+ counter-increment: list-1;
81
+ counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
82
+
83
+ &::before{ content: counter(list-1, lower-alpha) ". "; }
84
+ }
85
+
86
+ &.ql-indent-2{
87
+ counter-increment: list-2;
88
+ counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9;
89
+
90
+ &::before{ content: counter(list-2, lower-roman) ". "; }
91
+ }
92
+
93
+ &.ql-indent-3{
94
+ counter-increment: list-3;
95
+ counter-reset: list-4 list-5 list-6 list-7 list-8 list-9;
96
+
97
+ &::before{ content: counter(list-3, decimal) ". "; }
98
+ }
99
+
100
+ &.ql-indent-4{
101
+ counter-increment: list-4;
102
+ counter-reset: list-5 list-6 list-7 list-8 list-9;
103
+
104
+ &::before{ content: counter(list-4, lower-alpha) ". "; }
105
+ }
106
+
107
+ &.ql-indent-5{
108
+ counter-increment: list-5;
109
+ counter-reset: list-6 list-7 list-8 list-9;
110
+
111
+ &::before{ content: counter(list-5, lower-roman) ". "; }
112
+ }
113
+
114
+ &.ql-indent-6{
115
+ counter-increment: list-6;
116
+ counter-reset: list-7 list-8 list-9;
117
+
118
+ &::before{ content: counter(list-6, decimal) ". "; }
119
+ }
120
+
121
+ &.ql-indent-7{
122
+ counter-increment: list-7;
123
+ counter-reset: list-8 list-9;
124
+
125
+ &::before{ content: counter(list-7, lower-alpha) ". "; }
126
+ }
127
+
128
+ &.ql-indent-8{
129
+ counter-increment: list-8;
130
+ counter-reset: list-9;
131
+
132
+ &::before{ content: counter(list-8, lower-roman) ". "; }
133
+ }
134
+
135
+ &.ql-indent-9{
136
+ counter-increment: list-9;
137
+
138
+ &::before{ content: counter(list-9, decimal) ". "; }
139
+ }
140
+ }
141
+ }
13
142
  }
@@ -11,9 +11,3 @@
11
11
  margin-top: 0;
12
12
  margin-bottom: 0;
13
13
  }
14
-
15
- .ql-reset-decidim{
16
- display: inline;
17
- padding: 0;
18
- white-space: inherit;
19
- }
@@ -123,6 +123,10 @@
123
123
  }
124
124
  }
125
125
 
126
+ &.primary{
127
+ @include button-hollow-variant(var(--primary));
128
+ }
129
+
126
130
  &.secondary{
127
131
  @include button-hollow-variant(var(--secondary));
128
132
  }
@@ -257,12 +261,12 @@
257
261
 
258
262
  .button--shadow{
259
263
  $shadows: (
260
- primary: shade($primary, 50),
261
- secondary: shade($secondary, 50),
262
- success: shade($success, 50),
263
- warning: shade($warning, 50),
264
- alert: shade($alert, 50),
265
- muted: shade($muted, 50),
264
+ primary: shade($primary, 50%),
265
+ secondary: shade($secondary, 50%),
266
+ success: shade($success, 50%),
267
+ warning: shade($warning, 50%),
268
+ alert: shade($alert, 50%),
269
+ muted: shade($muted, 50%),
266
270
  );
267
271
 
268
272
  @include modifiers(background-color, $shadows){
@@ -934,7 +934,7 @@ a .card__title{
934
934
  @include modifiers(
935
935
  color,
936
936
  (
937
- muted: tint($muted, 50),
937
+ muted: tint($muted, 50%),
938
938
  )
939
939
  ){
940
940
  margin-top: -$global-margin * .95;
@@ -17,6 +17,30 @@ $comment-form-bg: $light-gray;
17
17
 
18
18
  .comment-thread{
19
19
  @extend .card;
20
+
21
+ .show-comment-replies{
22
+ display: none;
23
+ }
24
+
25
+ .hide-comment-replies{
26
+ display: inline;
27
+ }
28
+
29
+ .comment__hide{
30
+ float: left;
31
+ margin-bottom: 0;
32
+ }
33
+
34
+ .no-comments{
35
+ .show-comment-replies{
36
+ display: inline;
37
+ }
38
+
39
+ .hide-comment-replies,
40
+ .replies{
41
+ display: none;
42
+ }
43
+ }
20
44
  }
21
45
 
22
46
  .comment-thread__title{
@@ -36,8 +36,8 @@
36
36
  @mixin loop-colors-types($color, $max: 12){
37
37
  @for $i from 0 through ($max - 1){
38
38
  $interval: ($i % 4) * 24 + 1;
39
- $tints: tint($color, $interval);
40
- $shades: shade($color, $interval);
39
+ $tints: tint($color, $interval * 1%);
40
+ $shades: shade($color, $interval * 1%);
41
41
  $adjusts: adjust-color($color, $lightness: $interval * 1%, $hue: -$interval);
42
42
 
43
43
  .type-#{$i}:not(.legend){
@@ -27,8 +27,8 @@
27
27
  @mixin loop-colors-types($color, $max: 12){
28
28
  @for $i from 0 through ($max - 1){
29
29
  $interval: ($i % 4) * 24 + 1;
30
- $tints: tint($color, $interval);
31
- $shades: shade($color, $interval);
30
+ $tints: tint($color, $interval * 1%);
31
+ $shades: shade($color, $interval * 1%);
32
32
  $adjusts: adjust-color($color, $lightness: $interval * 1%, $hue: -$interval);
33
33
 
34
34
  .type-#{$i}{
@@ -11,7 +11,7 @@ module Decidim
11
11
 
12
12
  def created_at_in_words
13
13
  if created_at.between?(1.month.ago, Time.current)
14
- time_ago_in_words(created_at)
14
+ I18n.t("decidim.user_conversations.index.time_ago", time: time_ago_in_words(created_at))
15
15
  else
16
16
  format = created_at.year == Time.current.year ? :ddmm : :ddmmyyyy
17
17
  I18n.l(created_at, format: format)
@@ -16,7 +16,7 @@ module Decidim
16
16
  end
17
17
 
18
18
  def can_be_contacted?
19
- true
19
+ true unless blocked?
20
20
  end
21
21
 
22
22
  def officialization_text
@@ -61,7 +61,7 @@ module Decidim
61
61
  end
62
62
 
63
63
  def can_be_contacted?
64
- true
64
+ true unless blocked?
65
65
  end
66
66
 
67
67
  def officialization_text