decidim-core 0.26.5 → 0.26.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/announcement_cell.rb +1 -1
  3. data/app/cells/decidim/collapsible_list/show.erb +1 -1
  4. data/app/cells/decidim/content_blocks/cta_cell.rb +1 -1
  5. data/app/cells/decidim/content_blocks/hero/show.erb +1 -1
  6. data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
  7. data/app/cells/decidim/content_blocks/sub_hero_cell.rb +1 -1
  8. data/app/controllers/decidim/authorization_modals_controller.rb +1 -1
  9. data/app/controllers/decidim/links_controller.rb +8 -11
  10. data/app/forms/url_validator.rb +1 -1
  11. data/app/helpers/decidim/cells_helper.rb +1 -0
  12. data/app/helpers/decidim/external_domain_helper.rb +14 -3
  13. data/app/helpers/decidim/layout_helper.rb +15 -4
  14. data/app/helpers/decidim/layout_helper.rb.orig +225 -0
  15. data/app/helpers/decidim/sanitize_helper.rb +15 -5
  16. data/app/models/decidim/organization.rb +6 -0
  17. data/app/models/decidim/scope_type.rb +28 -0
  18. data/app/packs/src/decidim/editor/clipboard_override.js +6 -2
  19. data/app/packs/src/decidim/editor.js +63 -33
  20. data/app/packs/src/decidim/map/controller/drag_marker.js +0 -2
  21. data/app/packs/src/decidim/map/controller/markers.js +0 -1
  22. data/app/packs/src/decidim/map/controller/static.js +0 -1
  23. data/app/packs/src/decidim/map/controller.js +0 -2
  24. data/app/packs/src/decidim/map/factory.js +4 -1
  25. data/app/packs/src/decidim/map/icon.js +0 -1
  26. data/app/packs/src/decidim/map/legacy.js +0 -1
  27. data/app/packs/src/decidim/map/provider/default.js +2 -0
  28. data/app/packs/src/decidim/map/provider/here.js +2 -1
  29. data/app/packs/stylesheets/decidim/_editor.scss +129 -0
  30. data/app/packs/stylesheets/decidim/extras/_quill.scss +0 -6
  31. data/app/packs/stylesheets/decidim/modules/_buttons.scss +10 -6
  32. data/app/packs/stylesheets/decidim/modules/_cards.scss +1 -1
  33. data/app/packs/stylesheets/decidim/modules/_comments.scss +24 -0
  34. data/app/packs/stylesheets/decidim/modules/_dropdown_menu.scss +9 -0
  35. data/app/packs/stylesheets/decidim/vizzs/_linechart.scss +2 -2
  36. data/app/packs/stylesheets/decidim/vizzs/_rowchart.scss +2 -2
  37. data/app/presenters/decidim/notification_presenter.rb +1 -1
  38. data/app/presenters/decidim/user_group_presenter.rb +1 -1
  39. data/app/presenters/decidim/user_presenter.rb +1 -1
  40. data/app/queries/decidim/metrics/users_metric_manage.rb +6 -6
  41. data/app/scrubbers/decidim/admin_input_scrubber.rb +27 -0
  42. data/app/scrubbers/decidim/user_input_scrubber.rb +32 -5
  43. data/app/services/decidim/traceability.rb +1 -0
  44. data/app/views/decidim/devise/registrations/new.html.erb.orig +231 -0
  45. data/app/views/decidim/links/_invalid_url_modal.html.erb +17 -0
  46. data/app/views/decidim/links/_modal.html.erb +1 -1
  47. data/app/views/decidim/links/invalid_url.js.erb +24 -0
  48. data/app/views/decidim/links/new.html.erb +1 -1
  49. data/app/views/decidim/messaging/conversations/_conversation.html.erb +1 -5
  50. data/app/views/decidim/pages/_standalone.html.erb +1 -1
  51. data/app/views/decidim/pages/_tabbed.html.erb +1 -1
  52. data/config/environment.rb +0 -0
  53. data/config/locales/ar.yml +423 -8
  54. data/config/locales/bg.yml +1 -4
  55. data/config/locales/ca.yml +26 -23
  56. data/config/locales/cs.yml +40 -32
  57. data/config/locales/da.yml +3 -0
  58. data/config/locales/de.yml +39 -23
  59. data/config/locales/el.yml +100 -2
  60. data/config/locales/en.yml +16 -13
  61. data/config/locales/eo.yml +5 -1
  62. data/config/locales/es-MX.yml +21 -18
  63. data/config/locales/es-PY.yml +23 -20
  64. data/config/locales/es.yml +25 -22
  65. data/config/locales/et.yml +3 -0
  66. data/config/locales/eu.yml +91 -67
  67. data/config/locales/fa-IR.yml +1 -0
  68. data/config/locales/fi-plain.yml +16 -13
  69. data/config/locales/fi.yml +18 -15
  70. data/config/locales/fr-CA.yml +28 -22
  71. data/config/locales/fr.yml +27 -21
  72. data/config/locales/ga-IE.yml +1 -0
  73. data/config/locales/gl.yml +4 -23
  74. data/config/locales/gn-PY.yml +3 -0
  75. data/config/locales/hr.yml +3 -0
  76. data/config/locales/hu.yml +66 -21
  77. data/config/locales/id-ID.yml +6 -4
  78. data/config/locales/is-IS.yml +5 -2
  79. data/config/locales/it.yml +5 -15
  80. data/config/locales/ja.yml +16 -15
  81. data/config/locales/ka-GE.yml +3 -0
  82. data/config/locales/kaa.yml +5 -0
  83. data/config/locales/lb.yml +8 -12
  84. data/config/locales/lt.yml +1 -34
  85. data/config/locales/lv.yml +0 -3
  86. data/config/locales/nl.yml +5 -24
  87. data/config/locales/no.yml +5 -28
  88. data/config/locales/oc-FR.yml +2 -0
  89. data/config/locales/pl.yml +0 -33
  90. data/config/locales/pt-BR.yml +3 -7
  91. data/config/locales/pt.yml +1 -5
  92. data/config/locales/ro-RO.yml +5 -8
  93. data/config/locales/ru.yml +3 -3
  94. data/config/locales/sk.yml +18 -10
  95. data/config/locales/sl.yml +1 -0
  96. data/config/locales/sr-CS.yml +10 -0
  97. data/config/locales/sv.yml +11 -34
  98. data/config/locales/tr-TR.yml +3 -7
  99. data/config/locales/uk.yml +3 -3
  100. data/config/locales/zh-CN.yml +0 -4
  101. data/config/locales/zh-TW.yml +1726 -0
  102. data/db/migrate/20181030090144_destroy_deleted_users_follows.rb +1 -1
  103. data/db/migrate/20181204110723_remove_following_users_count_from_users.rb +11 -2
  104. data/db/migrate/20181214101250_add_notification_types_to_users.rb +6 -1
  105. data/db/migrate/20190412131728_fix_user_names.rb +13 -6
  106. data/db/migrate/20200211173227_add_direct_message_types_to_users.rb +6 -1
  107. data/db/migrate/20210302150803_invalidate_all_sessions_for_deleted_users.rb +10 -3
  108. data/db/migrate/20210310120640_add_followable_counter_cache_to_users.rb +13 -3
  109. data/lib/decidim/core/test/shared_examples/comments_examples.rb +36 -0
  110. data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +10 -0
  111. data/lib/decidim/core/test/shared_examples/map_examples.rb +4 -1
  112. data/lib/decidim/core/test/shared_examples/rich_text_editor_examples.rb +7 -3
  113. data/lib/decidim/core/test.rb +1 -0
  114. data/lib/decidim/core/version.rb +1 -1
  115. data/lib/decidim/core.rb +43 -0
  116. data/lib/decidim/dependency_resolver.rb +272 -0
  117. data/lib/decidim/form_builder.rb +6 -14
  118. data/lib/decidim/publicable.rb +4 -0
  119. data/lib/tasks/upgrade/decidim_user_moderation.rake +14 -0
  120. metadata +18 -6
@@ -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
  }
@@ -1,6 +1,4 @@
1
- import * as L from "leaflet";
2
1
  import MapController from "src/decidim/map/controller"
3
- import "src/decidim/vendor/leaflet-tilelayer-here"
4
2
 
5
3
  export default class MapDragMarkerController extends MapController {
6
4
  start() {
@@ -1,5 +1,4 @@
1
1
  import "src/decidim/vendor/jquery-tmpl"
2
- import * as L from "leaflet";
3
2
  import MapController from "src/decidim/map/controller"
4
3
  import "leaflet.markercluster";
5
4
 
@@ -1,4 +1,3 @@
1
- import * as L from "leaflet";
2
1
  import MapController from "src/decidim/map/controller"
3
2
 
4
3
  const openLink = window.open;
@@ -1,5 +1,3 @@
1
- import * as L from "leaflet";
2
- import "src/decidim/map/icon"
3
1
  import MapControllerRegistry from "src/decidim/map/controller_registry"
4
2
 
5
3
  export default class MapController {
@@ -1,3 +1,5 @@
1
+ import "src/decidim/map/icon"
2
+
1
3
  import MapMarkersController from "src/decidim/map/controller/markers"
2
4
  import MapStaticController from "src/decidim/map/controller/static"
3
5
  import MapDragMarkerController from "src/decidim/map/controller/drag_marker"
@@ -22,7 +24,8 @@ import MapDragMarkerController from "src/decidim/map/controller/drag_marker"
22
24
  * window.Decidim.createMapController = (mapId, config) => {
23
25
  * if (config.type === "custom") {
24
26
  * // Obviously you need to implement CustomMapController for this to
25
- * // work.
27
+ * // work. You can find an example at:
28
+ * // decidim-dev/app/packs/src/decidim/dev/test/custom_map_factory.js
26
29
  * return new window.Decidim.CustomMapController(mapId, config);
27
30
  * }
28
31
  *
@@ -1,4 +1,3 @@
1
- import * as L from "leaflet";
2
1
  import { SVGIcon } from "leaflet-svgicon"
3
2
 
4
3
  L.DivIcon.SVGIcon = SVGIcon;
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable require-jsdoc */
2
2
 
3
- import * as L from "leaflet";
4
3
  import "src/decidim/map/factory"
5
4
 
6
5
  /**
@@ -1,3 +1,5 @@
1
+ import "leaflet"
2
+
1
3
  /**
2
4
  * NOTE:
3
5
  * This has to load before decidim/map in order for it to apply correctly when
@@ -1,4 +1,5 @@
1
- import * as L from "leaflet"
1
+ import "leaflet"
2
+ import "src/decidim/vendor/leaflet-tilelayer-here"
2
3
 
3
4
  /**
4
5
  * NOTE:
@@ -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{
@@ -0,0 +1,9 @@
1
+ .dropdown.menu > li {
2
+ &.is-active > a {
3
+ color: var(--secondary);
4
+ }
5
+
6
+ &.is-dropdown-submenu-parent > a::after {
7
+ border-color: var(--secondary) transparent transparent;
8
+ }
9
+ }
@@ -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
@@ -11,15 +11,15 @@ module Decidim
11
11
  private
12
12
 
13
13
  def query
14
- return @query if @query
15
-
16
- @query = Decidim::User.where(organization: @organization)
17
- @query = @query.where("created_at <= ?", end_time)
18
- @query
14
+ @query ||= Decidim::User.where(organization: @organization)
15
+ .where("deleted_at IS NULL OR deleted_at > ?", end_time)
16
+ .where("blocked_at IS NULL OR blocked_at > ?", end_time)
17
+ .confirmed
18
+ .where("created_at <= ?", end_time)
19
19
  end
20
20
 
21
21
  def quantity
22
- @quantity ||= @query.where("created_at >= ?", start_time).count
22
+ @quantity ||= query.where("created_at >= ?", start_time).count
23
23
  end
24
24
  end
25
25
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Use this class as a scrubber to sanitize admin user input. The default
5
+ # scrubbed provided by Rails does not allow `iframe`s, and we are using
6
+ # them to embed videos, so we need to provide a whole new scrubber.
7
+ #
8
+ # Example:
9
+ #
10
+ # sanitize(@page.body, scrubber: Decidim::AdminInputScrubber.new)
11
+ #
12
+ # Lists of default tags and attributes are extracted from
13
+ # https://stackoverflow.com/a/35073814/2110884.
14
+ class AdminInputScrubber < UserInputScrubber
15
+ private
16
+
17
+ DECIDIM_ALLOWED_TAGS = %w(img video audio source comment iframe).freeze
18
+
19
+ def custom_allowed_attributes
20
+ super + %w(frameborder allowfullscreen) - %w(onerror)
21
+ end
22
+
23
+ def custom_allowed_tags
24
+ super + DECIDIM_ALLOWED_TAGS
25
+ end
26
+ end
27
+ end
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Decidim
4
- # Use this class as a scrubber to sanitize user input. The default
5
- # scrubbed provided by Rails does not allow `iframe`s, and we're using
6
- # them to embed videos, so we need to provide a whole new scrubber.
4
+ # Use this class as a scrubber to sanitize participant user input.
7
5
  #
8
6
  # Example:
9
7
  #
@@ -20,12 +18,41 @@ module Decidim
20
18
 
21
19
  private
22
20
 
21
+ RESTRICTED_TAGS = %w(
22
+ area
23
+ article
24
+ aside
25
+ audio
26
+ button
27
+ canvas
28
+ fieldset
29
+ figcaption
30
+ figure
31
+ font
32
+ footer
33
+ form
34
+ header
35
+ img
36
+ input
37
+ label
38
+ legend
39
+ main
40
+ map
41
+ menu
42
+ optgroup
43
+ option
44
+ output
45
+ select
46
+ textarea
47
+ video
48
+ ).freeze
49
+
23
50
  def custom_allowed_attributes
24
- Loofah::HTML5::SafeList::ALLOWED_ATTRIBUTES + %w(frameborder allowfullscreen) - %w(onerror)
51
+ Loofah::HTML5::SafeList::ALLOWED_ATTRIBUTES
25
52
  end
26
53
 
27
54
  def custom_allowed_tags
28
- Loofah::HTML5::SafeList::ALLOWED_ELEMENTS_WITH_LIBXML2 + %w(iframe)
55
+ Loofah::HTML5::SafeList::ACCEPTABLE_ELEMENTS - RESTRICTED_TAGS
29
56
  end
30
57
  end
31
58
  end
@@ -117,6 +117,7 @@ module Decidim
117
117
  return unless user.is_a?(Decidim::User)
118
118
  # If the record is not valid, it may not yet have an ID causing an
119
119
  # exception when trying to save the log record.
120
+ return if resource.nil?
120
121
  return unless resource.valid?
121
122
 
122
123
  Decidim::ActionLogger.log(