decidim-collaborative_texts 0.31.0.rc1
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.
- checksums.yaml +7 -0
- data/README.md +24 -0
- data/Rakefile +3 -0
- data/app/cells/decidim/collaborative_texts/document_cell.rb +23 -0
- data/app/cells/decidim/collaborative_texts/document_l_cell.rb +15 -0
- data/app/commands/decidim/collaborative_texts/admin/create_document.rb +25 -0
- data/app/commands/decidim/collaborative_texts/admin/publish_document.rb +52 -0
- data/app/commands/decidim/collaborative_texts/admin/unpublish_document.rb +44 -0
- data/app/commands/decidim/collaborative_texts/admin/update_document.rb +101 -0
- data/app/commands/decidim/collaborative_texts/admin/update_document_settings.rb +13 -0
- data/app/commands/decidim/collaborative_texts/create_suggestion.rb +28 -0
- data/app/commands/decidim/collaborative_texts/rollout.rb +50 -0
- data/app/controllers/concerns/decidim/collaborative_texts/admin/filterable.rb +23 -0
- data/app/controllers/decidim/collaborative_texts/admin/application_controller.rb +15 -0
- data/app/controllers/decidim/collaborative_texts/admin/documents_controller.rb +142 -0
- data/app/controllers/decidim/collaborative_texts/application_controller.rb +14 -0
- data/app/controllers/decidim/collaborative_texts/documents_controller.rb +57 -0
- data/app/controllers/decidim/collaborative_texts/suggestions_controller.rb +55 -0
- data/app/events/decidim/collaborative_texts/suggestion_accepted_event.rb +6 -0
- data/app/forms/decidim/collaborative_texts/admin/document_form.rb +29 -0
- data/app/forms/decidim/collaborative_texts/rollout_form.rb +26 -0
- data/app/forms/decidim/collaborative_texts/suggestion_form.rb +42 -0
- data/app/helpers/decidim/collaborative_texts/application_helper.rb +20 -0
- data/app/models/decidim/collaborative_texts/application_record.rb +10 -0
- data/app/models/decidim/collaborative_texts/document.rb +78 -0
- data/app/models/decidim/collaborative_texts/suggestion.rb +36 -0
- data/app/models/decidim/collaborative_texts/version.rb +35 -0
- data/app/packs/entrypoints/decidim_collaborative_texts.js +7 -0
- data/app/packs/images/decidim/collaborative_texts/decidim_collaborative_texts.svg +1 -0
- data/app/packs/src/decidim/collaborative_texts/document.js +168 -0
- data/app/packs/src/decidim/collaborative_texts/editor.js +80 -0
- data/app/packs/src/decidim/collaborative_texts/init_documents.js +27 -0
- data/app/packs/src/decidim/collaborative_texts/manager.js +106 -0
- data/app/packs/src/decidim/collaborative_texts/selection.js +106 -0
- data/app/packs/src/decidim/collaborative_texts/suggestion.js +243 -0
- data/app/packs/src/decidim/collaborative_texts/suggestions_list.js +103 -0
- data/app/packs/src/decidim/collaborative_texts/test/document.test.js +83 -0
- data/app/packs/src/decidim/collaborative_texts/test/manager.test.js +149 -0
- data/app/packs/src/decidim/collaborative_texts/test/selection.test.js +125 -0
- data/app/packs/src/decidim/collaborative_texts/test/suggestions.test.js +233 -0
- data/app/packs/src/decidim/collaborative_texts/test/toc.test.js +70 -0
- data/app/packs/src/decidim/collaborative_texts/toc.js +48 -0
- data/app/packs/stylesheets/decidim/collaborative_texts/collaborative_texts.scss +287 -0
- data/app/permissions/decidim/collaborative_texts/admin/permissions.rb +28 -0
- data/app/permissions/decidim/collaborative_texts/permissions.rb +36 -0
- data/app/presenters/decidim/collaborative_texts/admin_log/document_presenter.rb +54 -0
- data/app/presenters/decidim/collaborative_texts/admin_log/suggestion_presenter.rb +62 -0
- data/app/presenters/decidim/collaborative_texts/admin_log/suggestion_resource_presenter.rb +20 -0
- data/app/presenters/decidim/collaborative_texts/admin_log/version_presenter.rb +53 -0
- data/app/presenters/decidim/collaborative_texts/official_author_presenter.rb +11 -0
- data/app/presenters/decidim/collaborative_texts/suggestion_presenter.rb +57 -0
- data/app/views/decidim/collaborative_texts/admin/documents/_actions.html.erb +82 -0
- data/app/views/decidim/collaborative_texts/admin/documents/_document-tr.html.erb +15 -0
- data/app/views/decidim/collaborative_texts/admin/documents/_documents-thead.html.erb +7 -0
- data/app/views/decidim/collaborative_texts/admin/documents/_draft_options.html.erb +6 -0
- data/app/views/decidim/collaborative_texts/admin/documents/_form.html.erb +16 -0
- data/app/views/decidim/collaborative_texts/admin/documents/_non_draft_options.html.erb +9 -0
- data/app/views/decidim/collaborative_texts/admin/documents/_versions.html.erb +18 -0
- data/app/views/decidim/collaborative_texts/admin/documents/edit.html.erb +33 -0
- data/app/views/decidim/collaborative_texts/admin/documents/edit_settings.html.erb +18 -0
- data/app/views/decidim/collaborative_texts/admin/documents/index.html.erb +32 -0
- data/app/views/decidim/collaborative_texts/admin/documents/manage_trash.html.erb +19 -0
- data/app/views/decidim/collaborative_texts/admin/documents/new.html.erb +18 -0
- data/app/views/decidim/collaborative_texts/admin/settings/_form.html.erb +9 -0
- data/app/views/decidim/collaborative_texts/documents/_editor_template.html.erb +15 -0
- data/app/views/decidim/collaborative_texts/documents/_manager.html.erb +9 -0
- data/app/views/decidim/collaborative_texts/documents/_suggestions_box_item_template.html.erb +33 -0
- data/app/views/decidim/collaborative_texts/documents/_suggestions_box_template.html.erb +20 -0
- data/app/views/decidim/collaborative_texts/documents/index.html.erb +29 -0
- data/app/views/decidim/collaborative_texts/documents/show.html.erb +70 -0
- data/config/assets.rb +8 -0
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/ar.yml +1 -0
- data/config/locales/bg.yml +1 -0
- data/config/locales/bn-BD.yml +1 -0
- data/config/locales/bs-BA.yml +1 -0
- data/config/locales/ca-IT.yml +154 -0
- data/config/locales/ca.yml +154 -0
- data/config/locales/cs.yml +122 -0
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +154 -0
- data/config/locales/el.yml +1 -0
- data/config/locales/en.yml +154 -0
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +154 -0
- data/config/locales/es-PY.yml +154 -0
- data/config/locales/es.yml +154 -0
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +154 -0
- data/config/locales/fa-IR.yml +1 -0
- data/config/locales/fi-plain.yml +154 -0
- data/config/locales/fi.yml +154 -0
- data/config/locales/fr-CA.yml +125 -0
- data/config/locales/fr.yml +125 -0
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/gl.yml +1 -0
- data/config/locales/gn-PY.yml +1 -0
- data/config/locales/he-IL.yml +1 -0
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +1 -0
- data/config/locales/id-ID.yml +1 -0
- data/config/locales/is-IS.yml +1 -0
- data/config/locales/it.yml +1 -0
- data/config/locales/ja.yml +153 -0
- data/config/locales/ka-GE.yml +1 -0
- data/config/locales/kaa.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lb.yml +1 -0
- data/config/locales/lo-LA.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/lv.yml +1 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +1 -0
- data/config/locales/no.yml +6 -0
- data/config/locales/oc-FR.yml +1 -0
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +1 -0
- data/config/locales/pt-BR.yml +1 -0
- data/config/locales/pt.yml +1 -0
- data/config/locales/ro-RO.yml +89 -0
- data/config/locales/ru.yml +1 -0
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sk.yml +1 -0
- data/config/locales/sl.yml +1 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sq-AL.yml +1 -0
- data/config/locales/sr-CS.yml +1 -0
- data/config/locales/sv.yml +117 -0
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/th-TH.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +69 -0
- data/config/locales/uk.yml +1 -0
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +1 -0
- data/config/locales/zh-TW.yml +1 -0
- data/db/migrate/20250205215038_create_decidim_collaborative_texts_documents.rb +16 -0
- data/db/migrate/20250213113536_create_collaborative_texts_versions.rb +13 -0
- data/db/migrate/20250227204839_create_collaborative_texts_suggestions.rb +13 -0
- data/db/migrate/20250312140133_add_counter_caches_to_collaborative_texts_documents.rb +13 -0
- data/db/migrate/20250408205231_add_counter_caches_to_collaborative_text_versions.rb +8 -0
- data/decidim-collaborative_texts.gemspec +36 -0
- data/lib/decidim/api/document_input_filter.rb +29 -0
- data/lib/decidim/api/document_input_sort.rb +14 -0
- data/lib/decidim/api/document_type.rb +31 -0
- data/lib/decidim/api/documents_type.rb +39 -0
- data/lib/decidim/api/suggestion_type.rb +18 -0
- data/lib/decidim/api/version_type.rb +21 -0
- data/lib/decidim/collaborative_texts/admin.rb +10 -0
- data/lib/decidim/collaborative_texts/admin_engine.rb +34 -0
- data/lib/decidim/collaborative_texts/api.rb +12 -0
- data/lib/decidim/collaborative_texts/component.rb +54 -0
- data/lib/decidim/collaborative_texts/engine.rb +28 -0
- data/lib/decidim/collaborative_texts/seeds.rb +117 -0
- data/lib/decidim/collaborative_texts/test/factories.rb +80 -0
- data/lib/decidim/collaborative_texts/version.rb +9 -0
- data/lib/decidim/collaborative_texts.rb +13 -0
- metadata +233 -0
@@ -0,0 +1,287 @@
|
|
1
|
+
.collaborative-texts {
|
2
|
+
&-toc {
|
3
|
+
@apply w-full py-8 lg:sticky top-0;
|
4
|
+
|
5
|
+
.spinner-container::after {
|
6
|
+
@apply bg-transparent;
|
7
|
+
}
|
8
|
+
|
9
|
+
ul {
|
10
|
+
@apply list-none;
|
11
|
+
|
12
|
+
li {
|
13
|
+
@apply flex items-center gap-2 text-secondary text-lg leading-8 cursor-pointer;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
&-container {
|
19
|
+
@apply relative mb-8 md:mr-[18rem] pr-4;
|
20
|
+
|
21
|
+
h2 {
|
22
|
+
@apply mt-8;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
&-hidden:not(&-highlight-shown),
|
27
|
+
&-highlight-hidden {
|
28
|
+
@apply hidden;
|
29
|
+
}
|
30
|
+
|
31
|
+
&-manager {
|
32
|
+
@apply sticky top-4 drop-shadow z-10 p-4 bg-background rounded border border-black;
|
33
|
+
|
34
|
+
> div {
|
35
|
+
@apply flex justify-between gap-2 mb-4;
|
36
|
+
}
|
37
|
+
|
38
|
+
&.hidden {
|
39
|
+
display: none;
|
40
|
+
}
|
41
|
+
|
42
|
+
&-applied,
|
43
|
+
&-pending {
|
44
|
+
@apply font-bold;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
&-alert {
|
49
|
+
@apply fixed top-8 border-alert z-[40] bg-white rounded;
|
50
|
+
|
51
|
+
> div {
|
52
|
+
@apply flex items-center gap-2 p-4 bg-alert/20 rounded;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
&-selection {
|
57
|
+
@apply hidden;
|
58
|
+
}
|
59
|
+
|
60
|
+
&-highlight {
|
61
|
+
@apply relative outline-dashed outline-1 outline-offset-2 outline-gray;
|
62
|
+
|
63
|
+
&:not(.applied) .collaborative-texts-hidden {
|
64
|
+
@apply block;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
&-editor {
|
69
|
+
@apply bg-gray-5 mb-4 p-2 pt-1 rounded;
|
70
|
+
|
71
|
+
&-header {
|
72
|
+
@apply flex gap-2 border-b border-gray-6 justify-between items-baseline;
|
73
|
+
|
74
|
+
> svg {
|
75
|
+
@apply fill-secondary text-md;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
&-profile {
|
80
|
+
@apply mt-4;
|
81
|
+
|
82
|
+
a {
|
83
|
+
@apply text-black;
|
84
|
+
}
|
85
|
+
|
86
|
+
img {
|
87
|
+
@apply my-0;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
&-container {
|
92
|
+
@apply px-2 pt-2 pb-4 my-4 bg-white rounded border border-gray-2 text-md;
|
93
|
+
|
94
|
+
&:focus-visible {
|
95
|
+
@apply outline-none;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
&-menu {
|
100
|
+
@apply flex justify-end;
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
&-menu {
|
105
|
+
@apply absolute top-0 right-0 z-[9] flex gap-2;
|
106
|
+
}
|
107
|
+
|
108
|
+
&-suggestions-box {
|
109
|
+
@apply bg-gray-5 shadow outline outline-gray-3 outline-1 text-xs rounded px-2 pb-2 pt-1 md:pt-0 md:absolute md:top-0 md:right-[-18rem] md:w-[18rem] md:transition-all ease-in-out duration-300;
|
110
|
+
|
111
|
+
.icon {
|
112
|
+
@apply inline-block text-md mr-2;
|
113
|
+
|
114
|
+
&-hover,
|
115
|
+
&-applied {
|
116
|
+
@apply hidden;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
&:has([aria-hidden="false"]) {
|
121
|
+
@apply z-[9] shadow-lg;
|
122
|
+
|
123
|
+
&:has(.collaborative-texts-suggestions-box-item:hover) {
|
124
|
+
.icon-pending {
|
125
|
+
@apply hidden;
|
126
|
+
}
|
127
|
+
|
128
|
+
.icon-applied {
|
129
|
+
@apply hidden;
|
130
|
+
}
|
131
|
+
|
132
|
+
.icon-hover {
|
133
|
+
@apply inline-block;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
&:has(.applied.collaborative-texts-suggestions-box-item:hover) {
|
138
|
+
.icon-hover {
|
139
|
+
@apply hidden;
|
140
|
+
}
|
141
|
+
|
142
|
+
.icon-applied {
|
143
|
+
@apply inline-block;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
&:has(.applied) {
|
149
|
+
.icon-applied {
|
150
|
+
@apply inline-block;
|
151
|
+
}
|
152
|
+
|
153
|
+
.icon-pending {
|
154
|
+
@apply hidden;
|
155
|
+
}
|
156
|
+
|
157
|
+
.icon-hover {
|
158
|
+
@apply hidden;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
&:hover {
|
163
|
+
@apply z-10;
|
164
|
+
}
|
165
|
+
|
166
|
+
&-header {
|
167
|
+
@apply flex items-center justify-between text-secondary mb-4 fill-secondary;
|
168
|
+
}
|
169
|
+
|
170
|
+
&-item {
|
171
|
+
@apply p-2 pr-0 mb-4 rounded w-full;
|
172
|
+
|
173
|
+
&:hover {
|
174
|
+
@apply bg-white drop-shadow relative z-[1];
|
175
|
+
}
|
176
|
+
|
177
|
+
.button-restore {
|
178
|
+
@apply hidden;
|
179
|
+
}
|
180
|
+
|
181
|
+
&.applied {
|
182
|
+
@apply bg-white drop-shadow;
|
183
|
+
|
184
|
+
.button-restore {
|
185
|
+
@apply flex;
|
186
|
+
}
|
187
|
+
|
188
|
+
.button-apply {
|
189
|
+
@apply hidden;
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
img {
|
194
|
+
@apply m-0;
|
195
|
+
}
|
196
|
+
|
197
|
+
.text {
|
198
|
+
@apply font-semibold;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
&-item-header {
|
203
|
+
@apply flex items-center justify-between;
|
204
|
+
}
|
205
|
+
|
206
|
+
[data-controller="accordion"] {
|
207
|
+
@apply relative bg-gray-5;
|
208
|
+
|
209
|
+
> button {
|
210
|
+
@apply flex outline-none w-full justify-between;
|
211
|
+
|
212
|
+
svg {
|
213
|
+
@apply fill-secondary;
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
[id*="panel"][aria-hidden="false"] {
|
218
|
+
@apply z-10 relative;
|
219
|
+
}
|
220
|
+
|
221
|
+
[aria-expanded="false"] > svg:last-of-type,
|
222
|
+
[aria-expanded="false"] > span:last-of-type,
|
223
|
+
[aria-expanded="true"] > span:first-of-type,
|
224
|
+
[aria-expanded="true"] > svg:first-of-type {
|
225
|
+
@apply hidden;
|
226
|
+
}
|
227
|
+
|
228
|
+
[aria-expanded="true"] > svg:last-of-type,
|
229
|
+
[aria-expanded="true"] > span:last-of-type,
|
230
|
+
[aria-expanded="false"] > span:first-of-type,
|
231
|
+
[aria-expanded="false"] > svg:first-of-type {
|
232
|
+
@apply block;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
/* overwrite default dropdown styles */
|
237
|
+
[id*="dropdown-trigger"] {
|
238
|
+
@apply flex pr-1;
|
239
|
+
|
240
|
+
> svg {
|
241
|
+
@apply h-3 w-3;
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
[id*="dropdown-menu"] {
|
246
|
+
@apply cursor-auto w-auto;
|
247
|
+
|
248
|
+
&[aria-hidden="true"] {
|
249
|
+
@apply hidden;
|
250
|
+
}
|
251
|
+
|
252
|
+
ul {
|
253
|
+
@apply list-none;
|
254
|
+
}
|
255
|
+
|
256
|
+
&[aria-hidden="false"] {
|
257
|
+
animation-name: fadeIn;
|
258
|
+
animation-duration: 300ms;
|
259
|
+
animation-fill-mode: forwards;
|
260
|
+
}
|
261
|
+
|
262
|
+
@keyframes fadeIn {
|
263
|
+
from {
|
264
|
+
opacity: 0;
|
265
|
+
visibility: hidden;
|
266
|
+
}
|
267
|
+
|
268
|
+
to {
|
269
|
+
opacity: 1;
|
270
|
+
visibility: visible;
|
271
|
+
}
|
272
|
+
}
|
273
|
+
|
274
|
+
@keyframes fadeOut {
|
275
|
+
from {
|
276
|
+
opacity: 1;
|
277
|
+
visibility: visible;
|
278
|
+
}
|
279
|
+
|
280
|
+
to {
|
281
|
+
opacity: 0;
|
282
|
+
visibility: hidden;
|
283
|
+
}
|
284
|
+
}
|
285
|
+
}
|
286
|
+
}
|
287
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CollaborativeTexts
|
5
|
+
module Admin
|
6
|
+
class Permissions < Decidim::DefaultPermissions
|
7
|
+
def permissions
|
8
|
+
return permission_action if permission_action.scope != :admin
|
9
|
+
|
10
|
+
return permission_action if permission_action.subject != :collaborative_text
|
11
|
+
|
12
|
+
case permission_action.action
|
13
|
+
when :update, :read, :create, :destroy
|
14
|
+
allow!
|
15
|
+
end
|
16
|
+
|
17
|
+
permission_action
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def document
|
23
|
+
@document ||= context.fetch(:document, nil)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CollaborativeTexts
|
5
|
+
class Permissions < Decidim::DefaultPermissions
|
6
|
+
def permissions
|
7
|
+
# Delegate the admin permission checks to the admin permissions class
|
8
|
+
return Decidim::CollaborativeTexts::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
|
9
|
+
return permission_action if permission_action.scope != :public
|
10
|
+
|
11
|
+
return permission_action if permission_action.subject != :collaborative_text
|
12
|
+
|
13
|
+
case permission_action.action
|
14
|
+
when :suggest
|
15
|
+
allow! if user
|
16
|
+
when :rollout
|
17
|
+
allow! if user && (user.admin? || space_allows_admin_access?)
|
18
|
+
end
|
19
|
+
|
20
|
+
permission_action
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def document
|
26
|
+
@document ||= context.fetch(:document, nil) || context.fetch(:resource, nil)
|
27
|
+
end
|
28
|
+
|
29
|
+
def space_allows_admin_access?
|
30
|
+
return false unless document.participatory_space.respond_to?(:admins)
|
31
|
+
|
32
|
+
document.participatory_space.admins.exists?(id: user.id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CollaborativeTexts
|
5
|
+
module AdminLog
|
6
|
+
# This class holds the logic to present a `Decidim::CollaborativeTexts::Document`
|
7
|
+
# for the `AdminLog` log.
|
8
|
+
class DocumentPresenter < Decidim::Log::BasePresenter
|
9
|
+
private
|
10
|
+
|
11
|
+
def action_string
|
12
|
+
case action
|
13
|
+
when "create", "delete", "update", "soft_delete", "restore", "publish", "unpublish"
|
14
|
+
"decidim.collaborative_texts.admin_log.document.#{action}"
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def diff_fields_mapping
|
21
|
+
{
|
22
|
+
title: :string,
|
23
|
+
body: :string,
|
24
|
+
version_number: :integer
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def i18n_labels_scope
|
29
|
+
"activemodel.attributes.collaborative_texts.document"
|
30
|
+
end
|
31
|
+
|
32
|
+
# adds the body from the version to the changeset
|
33
|
+
def changeset
|
34
|
+
Decidim::Log::DiffChangesetCalculator.new(
|
35
|
+
full_changeset,
|
36
|
+
diff_fields_mapping,
|
37
|
+
i18n_labels_scope
|
38
|
+
).changeset
|
39
|
+
end
|
40
|
+
|
41
|
+
def full_changeset
|
42
|
+
action_log.version.changeset.tap do |changeset|
|
43
|
+
if action == "create"
|
44
|
+
changeset[:body] = [nil, action_log&.extra&.dig("extra", "body")]
|
45
|
+
changeset[:version_number] = [nil, "1"]
|
46
|
+
elsif (version_number = action_log&.extra&.dig("extra", "version_number"))
|
47
|
+
changeset[:version_number] = [nil, version_number]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CollaborativeTexts
|
5
|
+
module AdminLog
|
6
|
+
# This class holds the logic to present a `Decidim::CollaborativeTexts::Suggestion`
|
7
|
+
# for the `AdminLog` log.
|
8
|
+
# Note that this is only used in updates, creation is handled by the document creation.
|
9
|
+
#
|
10
|
+
class SuggestionPresenter < Decidim::Log::BasePresenter
|
11
|
+
private
|
12
|
+
|
13
|
+
def action_string
|
14
|
+
case action
|
15
|
+
when "create"
|
16
|
+
"decidim.collaborative_texts.admin_log.suggestion.#{action}"
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def i18n_labels_scope
|
23
|
+
"activemodel.attributes.collaborative_texts.suggestion"
|
24
|
+
end
|
25
|
+
|
26
|
+
def diff_fields_mapping
|
27
|
+
{
|
28
|
+
original: :array,
|
29
|
+
replace: :array,
|
30
|
+
nodes: :array
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Private: Caches the object that will be responsible of presenting the newsletter.
|
35
|
+
# Overwrites the method so that we can use a custom presenter to show the correct
|
36
|
+
# path for the newsletter.
|
37
|
+
#
|
38
|
+
# Returns an object that responds to `present`.
|
39
|
+
def resource_presenter
|
40
|
+
@resource_presenter ||= Decidim::CollaborativeTexts::AdminLog::SuggestionResourcePresenter.new(action_log.resource, h, action_log.extra["resource"])
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Currently, only the action "create" exists. Update this if other
|
45
|
+
# actions are added in the future.
|
46
|
+
def changeset
|
47
|
+
changeset = action_log.version.changeset
|
48
|
+
current = changeset.delete("changeset")[1]
|
49
|
+
changeset["original"] = [nil, current["original"]]
|
50
|
+
changeset["replace"] = [nil, current["replace"]]
|
51
|
+
changeset["nodes"] = [nil, (current["firstNode"]..current["lastNode"]).to_a]
|
52
|
+
|
53
|
+
Decidim::Log::DiffChangesetCalculator.new(
|
54
|
+
changeset,
|
55
|
+
diff_fields_mapping,
|
56
|
+
i18n_labels_scope
|
57
|
+
).changeset
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CollaborativeTexts
|
5
|
+
module AdminLog
|
6
|
+
# This class extends the default resource presenter for logs, so that
|
7
|
+
# it can properly link to the newsletter.
|
8
|
+
class SuggestionResourcePresenter < Decidim::Log::ResourcePresenter
|
9
|
+
private
|
10
|
+
|
11
|
+
# Private: Finds the admin link for the newsletter.
|
12
|
+
#
|
13
|
+
# Returns an HTML-safe String.
|
14
|
+
def resource_path
|
15
|
+
@resource_path ||= Decidim::ResourceLocatorPresenter.new(resource.document).path(anchor: "ct-node-#{resource.changeset["firstNode"]}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CollaborativeTexts
|
5
|
+
module AdminLog
|
6
|
+
# This class holds the logic to present a `Decidim::CollaborativeTexts::Version`
|
7
|
+
# for the `AdminLog` log.
|
8
|
+
# Note that this is only used in updates, creation is handled by the document creation.
|
9
|
+
#
|
10
|
+
class VersionPresenter < Decidim::Log::BasePresenter
|
11
|
+
private
|
12
|
+
|
13
|
+
def action_string
|
14
|
+
case action
|
15
|
+
when "delete", "update"
|
16
|
+
"decidim.collaborative_texts.admin_log.version.#{action}"
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def i18n_labels_scope
|
23
|
+
"activemodel.attributes.collaborative_texts.version"
|
24
|
+
end
|
25
|
+
|
26
|
+
def diff_fields_mapping
|
27
|
+
{
|
28
|
+
body: :string,
|
29
|
+
draft: :boolean,
|
30
|
+
version_number: :integer
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def changeset
|
35
|
+
Decidim::Log::DiffChangesetCalculator.new(
|
36
|
+
full_changeset,
|
37
|
+
diff_fields_mapping,
|
38
|
+
i18n_labels_scope
|
39
|
+
).changeset
|
40
|
+
end
|
41
|
+
|
42
|
+
def full_changeset
|
43
|
+
action_log.version.changeset.tap do |changeset|
|
44
|
+
changeset[:version_number] = [
|
45
|
+
nil,
|
46
|
+
action_log.extra.dig("extra", "version_number")
|
47
|
+
]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module CollaborativeTexts
|
5
|
+
#
|
6
|
+
# Decorator for collaborative texts suggestions.
|
7
|
+
#
|
8
|
+
class SuggestionPresenter < Decidim::ResourcePresenter
|
9
|
+
include Decidim::ApplicationHelper
|
10
|
+
|
11
|
+
delegate :changeset, :status, :created_at, :author, to: :suggestion
|
12
|
+
# A summary to print in the UI
|
13
|
+
def summary
|
14
|
+
txt = type == :remove ? original : text
|
15
|
+
@summary ||= I18n.t("decidim.collaborative_texts.suggestion.#{type}_html", text: txt.truncate(150))
|
16
|
+
end
|
17
|
+
|
18
|
+
# A text representation of the changeset. Without HTML.
|
19
|
+
def text
|
20
|
+
@text ||= ActionView::Base.full_sanitizer.sanitize(changeset["replace"]&.join(" ")&.strip).to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def original
|
24
|
+
@original ||= ActionView::Base.full_sanitizer.sanitize(changeset["original"]&.join(" ")&.strip).to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def suggestion
|
28
|
+
__getobj__
|
29
|
+
end
|
30
|
+
|
31
|
+
# Render the suggestion title
|
32
|
+
#
|
33
|
+
# Returns a String.
|
34
|
+
def title(html_escape: false, all_locales: false)
|
35
|
+
super(suggestion.document.title, html_escape, all_locales)
|
36
|
+
end
|
37
|
+
|
38
|
+
def type
|
39
|
+
return :remove if text.blank?
|
40
|
+
return :add if text.include?(original.to_s)
|
41
|
+
|
42
|
+
:replace
|
43
|
+
end
|
44
|
+
|
45
|
+
def safe_json
|
46
|
+
{
|
47
|
+
id:,
|
48
|
+
changeset:,
|
49
|
+
summary:,
|
50
|
+
status:,
|
51
|
+
type:,
|
52
|
+
createdAt: created_at
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
<button type="button" data-controller="dropdown" data-target="actions-post-<%= document.id %>" aria-label="<%= t("decidim.admin.actions.actions_label", resource: document.title) %>">
|
2
|
+
<%= icon "more-fill", class: "text-secondary" %>
|
3
|
+
</button>
|
4
|
+
|
5
|
+
<div class="inline-block relative">
|
6
|
+
<ul id="actions-post-<%= document.id %>" class="dropdown dropdown__action" aria-hidden="true">
|
7
|
+
<% if view == :deleted %>
|
8
|
+
<% if allowed_to? :restore, :collaborative_text, trashable_deleted_resource: document %>
|
9
|
+
<li class="dropdown__item">
|
10
|
+
<%= link_to restore_document_path(document), method: :patch, class: "dropdown__button" do %>
|
11
|
+
<%= icon "refresh-line" %>
|
12
|
+
<%= t("actions.restore", scope: "decidim.admin") %>
|
13
|
+
<% end %>
|
14
|
+
</li>
|
15
|
+
<% end %>
|
16
|
+
<% else %>
|
17
|
+
<% if allowed_to? :update, :collaborative_text, document: document %>
|
18
|
+
<li class="dropdown__item">
|
19
|
+
<%= link_to edit_document_path(document), class: "dropdown__button" do %>
|
20
|
+
<%= icon "pencil-line" %>
|
21
|
+
<%= t("actions.edit", scope: "decidim.collaborative_texts") %>
|
22
|
+
<% end %>
|
23
|
+
</li>
|
24
|
+
<li class="dropdown__item">
|
25
|
+
<%= link_to edit_settings_document_path(document), class: "dropdown__button" do %>
|
26
|
+
<%= icon "settings-4-line" %>
|
27
|
+
<%= t("actions.manage", scope: "decidim.collaborative_texts") %>
|
28
|
+
<% end %>
|
29
|
+
</li>
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<% if allowed_to?(:update, :collaborative_text, document: document) %>
|
33
|
+
<hr>
|
34
|
+
|
35
|
+
<% if document.published? %>
|
36
|
+
<li class="dropdown__item">
|
37
|
+
<%= link_to unpublish_document_path(document), method: :put, class: "dropdown__button" do %>
|
38
|
+
<%= icon "close-circle-line" %>
|
39
|
+
<%= t("actions.unpublish", scope: "decidim.admin") %>
|
40
|
+
<% end %>
|
41
|
+
</li>
|
42
|
+
<% else %>
|
43
|
+
<li class="dropdown__item">
|
44
|
+
<%= link_to publish_document_path(document), method: :put, class: "dropdown__button" do %>
|
45
|
+
<%= icon "check-line" %>
|
46
|
+
<%= t("actions.publish", scope: "decidim.admin") %>
|
47
|
+
<% end %>
|
48
|
+
</li>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
<hr>
|
53
|
+
|
54
|
+
<li class="dropdown__item">
|
55
|
+
<%= link_to resource_locator(document).path, target: :blank, data: { "external-link": false }, class: "dropdown__button" do %>
|
56
|
+
<%= icon "eye-line" %>
|
57
|
+
<%= t("actions.preview", scope: "decidim.admin") %>
|
58
|
+
<% end %>
|
59
|
+
</li>
|
60
|
+
|
61
|
+
<hr>
|
62
|
+
|
63
|
+
<li class="dropdown__item">
|
64
|
+
<% if allowed_to? :soft_delete, :collaborative_text, trashable_deleted_resource: document %>
|
65
|
+
<%= link_to soft_delete_document_path(document), method: :patch, data: { confirm: t("actions.confirm_delete_document", scope: "decidim.collaborative_texts") }, class: "dropdown__button" do %>
|
66
|
+
<%= icon "delete-bin-line" %>
|
67
|
+
<%= t("actions.soft_delete", scope: "decidim.admin") %>
|
68
|
+
<% end %>
|
69
|
+
<% else %>
|
70
|
+
<div class="dropdown__button-disabled">
|
71
|
+
<%= with_tooltip t("tooltips.deleted_collaborative_texts_info", scope: "decidim.admin") do %>
|
72
|
+
<%= icon "delete-bin-line", class: "text-gray" %>
|
73
|
+
<span>
|
74
|
+
<%= t("actions.soft_delete", scope: "decidim.admin") %>
|
75
|
+
</span>
|
76
|
+
<% end %>
|
77
|
+
</div>
|
78
|
+
<% end %>
|
79
|
+
</li>
|
80
|
+
<% end %>
|
81
|
+
</ul>
|
82
|
+
</div>
|