decidim-participatory_documents 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/lint.yml +2 -2
- data/.github/workflows/test.yml +8 -5
- data/.ruby-version +1 -1
- data/.simplecov +15 -9
- data/Gemfile.lock +186 -184
- data/README.md +32 -28
- data/app/commands/decidim/participatory_documents/create_suggestion.rb +3 -1
- data/app/controllers/concerns/decidim/participatory_documents/needs_pdf_document.rb +8 -1
- data/app/controllers/decidim/participatory_documents/admin/documents_controller.rb +5 -3
- data/app/controllers/decidim/participatory_documents/admin/suggestions_controller.rb +21 -1
- data/app/controllers/decidim/participatory_documents/admin/valuation_assignments_controller.rb +5 -1
- data/app/controllers/decidim/participatory_documents/document_suggestions_controller.rb +14 -0
- data/app/controllers/decidim/participatory_documents/section_suggestions_controller.rb +4 -0
- data/app/forms/decidim/participatory_documents/admin/document_form.rb +2 -1
- data/app/jobs/decidim/participatory_documents/export_my_suggestions_job.rb +16 -0
- data/app/models/decidim/participatory_documents/suggestion.rb +12 -0
- data/app/packs/entrypoints/decidim_participatory_documents.scss +8 -0
- data/app/packs/entrypoints/decidim_participatory_documents_editor.js +1 -3
- data/app/packs/entrypoints/decidim_participatory_documents_viewer_off.js +6 -0
- data/app/packs/images/export_suggestions.svg +1 -0
- data/app/packs/src/decidim/participatory_documents/pdf/pdf_modal_manager.js +4 -1
- data/app/packs/src/decidim/participatory_documents/pdf/suggestion_form.js +1 -1
- data/app/packs/src/decidim/participatory_documents/pdf.js +46 -0
- data/app/packs/src/decidim/participatory_documents/pdf_off.js +39 -0
- data/app/packs/stylesheets/decidim/participatory_documents/pdf/admin_modals.scss +9 -5
- data/app/packs/stylesheets/decidim/participatory_documents/pdf/admin_tweaks.scss +0 -21
- data/app/packs/stylesheets/decidim/participatory_documents/{decidim_admin_classes.scss → pdf/decidim_admin_styles.scss} +0 -3
- data/app/packs/stylesheets/decidim/participatory_documents/pdf/modals.scss +49 -0
- data/app/packs/stylesheets/decidim/participatory_documents/pdf/tweaks.scss +76 -7
- data/app/permissions/decidim/participatory_documents/admin/permissions.rb +30 -15
- data/app/permissions/decidim/participatory_documents/permissions.rb +2 -0
- data/app/serializers/decidim/participatory_documents/my_suggestion_serializer.rb +22 -0
- data/app/serializers/decidim/participatory_documents/suggestion_serializer.rb +1 -1
- data/app/uploaders/decidim/participatory_documents/pdf_document_uploader.rb +4 -0
- data/app/views/decidim/participatory_documents/admin/documents/_editor_modal.html.erb +1 -1
- data/app/views/decidim/participatory_documents/admin/documents/pdf_viewer.html.erb +1 -1
- data/app/views/decidim/participatory_documents/admin/sections/_form.html.erb +0 -3
- data/app/views/decidim/participatory_documents/admin/suggestions/_suggestion.html.erb +1 -1
- data/app/views/decidim/participatory_documents/documents/_export_modal.html.erb +25 -0
- data/app/views/decidim/participatory_documents/documents/_pdfjs_base.html.erb +5 -2
- data/app/views/decidim/participatory_documents/documents/pdf_viewer.html.erb +40 -33
- data/config/assets.rb +1 -0
- data/config/locales/ca.yml +259 -0
- data/config/locales/de.yml +259 -0
- data/config/locales/en.yml +13 -0
- data/config/locales/es.yml +259 -0
- data/lib/decidim/participatory_documents/component.rb +6 -4
- data/lib/decidim/participatory_documents/engine.rb +5 -1
- data/lib/decidim/participatory_documents/version.rb +2 -2
- data/lib/decidim/participatory_documents.rb +5 -3
- metadata +12 -3
@@ -19,6 +19,31 @@
|
|
19
19
|
margin: 12px;
|
20
20
|
}
|
21
21
|
|
22
|
+
#toolbarViewerMiddle {
|
23
|
+
padding-left: 0;
|
24
|
+
padding-right: 0;
|
25
|
+
|
26
|
+
@media(min-width: 940px) {
|
27
|
+
transform: translateX(-75%);
|
28
|
+
}
|
29
|
+
|
30
|
+
@media(max-width: 680px) {
|
31
|
+
padding-left: 1em;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
#toolbarViewerLeft {
|
36
|
+
@media(max-width: 680px) {
|
37
|
+
display: none;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
#toolbarViewerRight {
|
42
|
+
@media(max-width: 380px) {
|
43
|
+
display: none;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
22
47
|
.secondaryToolbar,
|
23
48
|
.findbar {
|
24
49
|
top: 53px;
|
@@ -49,6 +74,18 @@
|
|
49
74
|
margin-top: 8px;
|
50
75
|
}
|
51
76
|
|
77
|
+
.hiddenSmallView {
|
78
|
+
@media(max-width: 800px) {
|
79
|
+
display: none;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
.toolbarButtonSpacer {
|
84
|
+
@media(max-width: 980px) {
|
85
|
+
width: 0;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
52
89
|
.toolbarField {
|
53
90
|
margin-top: 9px;
|
54
91
|
}
|
@@ -64,13 +101,19 @@
|
|
64
101
|
background: #fff;
|
65
102
|
border: 1px solid #000;
|
66
103
|
}
|
104
|
+
|
105
|
+
@media(max-width: 940px) {
|
106
|
+
display: none;
|
107
|
+
}
|
108
|
+
|
109
|
+
@media(min-width: 941px) {
|
110
|
+
display: block;
|
111
|
+
}
|
67
112
|
}
|
68
113
|
|
69
114
|
.decidimButton {
|
70
|
-
|
71
|
-
|
72
|
-
margin: 0 0 1rem;
|
73
|
-
padding: .85em 1em;
|
115
|
+
margin: 0 0 0 1rem;
|
116
|
+
padding: .65em;
|
74
117
|
border-radius: 4px;
|
75
118
|
transition: background-color .25s ease-out, color .25s ease-out;
|
76
119
|
font-family: inherit;
|
@@ -83,16 +126,42 @@
|
|
83
126
|
border: transparent solid 1px;
|
84
127
|
color: var(--box-text-color);
|
85
128
|
text-shadow: 0 0 0 #fff;
|
129
|
+
|
130
|
+
&:first-child {
|
131
|
+
margin-left: 0;
|
132
|
+
}
|
133
|
+
|
134
|
+
&.muted {
|
135
|
+
background: #ddd;
|
136
|
+
color: #333;
|
137
|
+
}
|
138
|
+
|
139
|
+
@media(max-width: 900px) {
|
140
|
+
margin-top: 12px;
|
141
|
+
}
|
86
142
|
}
|
87
143
|
|
88
144
|
#globalSuggestionTrigger {
|
89
|
-
min-width: 160px;
|
90
|
-
|
91
145
|
&::before {
|
92
146
|
display: none;
|
93
147
|
}
|
94
148
|
}
|
95
149
|
|
150
|
+
#exportSuggestionsTrigger {
|
151
|
+
background-image: url(../images/export_suggestions.svg);
|
152
|
+
background-repeat: no-repeat;
|
153
|
+
background-size: 20px 20px;
|
154
|
+
background-position: 8px 9px;
|
155
|
+
padding-left: 34px;
|
156
|
+
|
157
|
+
@media(max-width: 900px) {
|
158
|
+
width: 28px;
|
159
|
+
height: 36px;
|
160
|
+
overflow: hidden;
|
161
|
+
font-size: 0;
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
96
165
|
#fullscreenButton {
|
97
166
|
background-image: url(../images/fullscreen.svg);
|
98
167
|
background-repeat: no-repeat;
|
@@ -115,7 +184,7 @@
|
|
115
184
|
background-image: url(../images/fullscreen_exit.svg);
|
116
185
|
}
|
117
186
|
|
118
|
-
@media(max-width:
|
187
|
+
@media(max-width: 940px) {
|
119
188
|
width: 28px;
|
120
189
|
height: 28px;
|
121
190
|
margin-right: 0;
|
@@ -7,38 +7,53 @@ module Decidim
|
|
7
7
|
def permissions
|
8
8
|
return permission_action if permission_action.scope != :admin
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
handle_valuator_permissions if user_is_valuator?
|
11
|
+
handle_general_permissions unless user_is_valuator?
|
12
|
+
|
13
|
+
permission_action
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def handle_valuator_permissions
|
19
|
+
if valuator_assigned_to_suggestion?
|
20
|
+
can_create_suggestion_note?
|
21
|
+
can_create_suggestion_answer?
|
22
|
+
allow! if action_is_show_on_suggestion?
|
23
|
+
elsif action_is_show_on_suggestion?
|
24
|
+
disallow!
|
19
25
|
end
|
26
|
+
valuator_can_unassign_valuator_from_suggestions?
|
27
|
+
end
|
20
28
|
|
29
|
+
def handle_general_permissions
|
30
|
+
allow! if action_is_show_on_suggestion?
|
21
31
|
if create_permission_action?
|
22
32
|
can_create_suggestion_note?
|
23
33
|
can_create_suggestion_answer?
|
24
34
|
end
|
25
|
-
|
26
35
|
edit_suggestion_note?
|
36
|
+
can_edit_document_or_sections? if action_is_update_on_document?
|
37
|
+
allow_default_admin_actions
|
38
|
+
end
|
27
39
|
|
28
|
-
|
40
|
+
def action_is_show_on_suggestion?
|
41
|
+
permission_action.subject == :suggestion && permission_action.action == :show
|
42
|
+
end
|
43
|
+
|
44
|
+
def action_is_update_on_document?
|
45
|
+
permission_action.subject == :participatory_document && permission_action.action == :update
|
46
|
+
end
|
29
47
|
|
48
|
+
def allow_default_admin_actions
|
30
49
|
allow! if permission_action.subject == :suggestion_note && permission_action.action == :create
|
31
50
|
allow! if permission_action.subject == :suggestion_answer
|
32
51
|
allow! if permission_action.subject == :document_section
|
33
52
|
allow! if permission_action.subject == :document_annotations
|
34
53
|
allow! if permission_action.subject == :participatory_document && permission_action.action == :create
|
35
54
|
allow! if permission_action.subject == :suggestions
|
36
|
-
|
37
|
-
permission_action
|
38
55
|
end
|
39
56
|
|
40
|
-
private
|
41
|
-
|
42
57
|
def suggestion
|
43
58
|
@suggestion ||= context.fetch(:suggestion, nil)
|
44
59
|
end
|
@@ -6,6 +6,8 @@ module Decidim
|
|
6
6
|
def permissions
|
7
7
|
return permission_action unless user
|
8
8
|
|
9
|
+
allow! if permission_action.subject == :suggestion && permission_action.action == :create
|
10
|
+
|
9
11
|
# Delegate the admin permission checks to the admin permissions class
|
10
12
|
return Decidim::ParticipatoryDocuments::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
|
11
13
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ParticipatoryDocuments
|
5
|
+
# This class serializes a Suggestion so can be exported to CSV, JSON or other
|
6
|
+
# formats.
|
7
|
+
class MySuggestionSerializer < SuggestionSerializer
|
8
|
+
# Public: Exports a hash with the serialized data for this suggestion.
|
9
|
+
def serialize
|
10
|
+
{
|
11
|
+
id: suggestion.id,
|
12
|
+
body: suggestion_body(suggestion),
|
13
|
+
author: suggestion.try(:normalized_author).try(:name),
|
14
|
+
state: humanize_suggestion_state(suggestion.state),
|
15
|
+
answer: answer_text(suggestion),
|
16
|
+
section: section(suggestion),
|
17
|
+
submitted_on: submitted_on(suggestion)
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -24,7 +24,7 @@ module Decidim
|
|
24
24
|
state: humanize_suggestion_state(suggestion.state),
|
25
25
|
answer: answer_text(suggestion),
|
26
26
|
section: section(suggestion),
|
27
|
-
valuators: suggestion.valuation_assignments.
|
27
|
+
valuators: suggestion.valuation_assignments.map(&:valuator).map(&:name).join(", "),
|
28
28
|
submitted_on: submitted_on(suggestion)
|
29
29
|
}
|
30
30
|
end
|
@@ -21,7 +21,7 @@
|
|
21
21
|
</head>
|
22
22
|
|
23
23
|
<body tabindex="1">
|
24
|
-
<%= render "decidim/participatory_documents/documents/pdfjs_base",
|
24
|
+
<%= render "decidim/participatory_documents/documents/pdfjs_base", display_save: true %>
|
25
25
|
|
26
26
|
<%= render "decidim/participatory_documents/admin/documents/editor_modal" %>
|
27
27
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
</td>
|
5
5
|
<td><%= suggestion.id %></td>
|
6
6
|
<td>
|
7
|
-
<%= truncate(suggestion_content(suggestion)[:text], length: 50) %>
|
7
|
+
<%= link_to truncate(suggestion_content(suggestion)[:text], length: 50), document_suggestion_path(document, suggestion) %>
|
8
8
|
<% if suggestion_content(suggestion)[:file_link] %>
|
9
9
|
<%= suggestion_content(suggestion)[:file_link] %>
|
10
10
|
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<div id="decidim">
|
2
|
+
<div class="reveal-overlay">
|
3
|
+
<div class="reveal" id="export-modal" data-reveal>
|
4
|
+
<div class="reveal__header">
|
5
|
+
<h2 class="reveal__title"><%= t(".title") %></h2>
|
6
|
+
<button class="close-button" data-close aria-label="close"
|
7
|
+
type="button">
|
8
|
+
<span aria-hidden="true">×</span>
|
9
|
+
</button>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div class="content">
|
13
|
+
<div class="row">
|
14
|
+
<p><%= t(".description_html", email: current_user&.email, count: all_suggestions&.count) %></p>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div class="row">
|
18
|
+
<div class="column flex-center">
|
19
|
+
<button type="button" class="export-button button primary expanded" data-url="<%= export_document_suggestions_path(document) %>"><%= t(".send") %></button>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
@@ -305,15 +305,18 @@ See https://github.com/adobe-type-tools/cmap-resources
|
|
305
305
|
</button>
|
306
306
|
</div>
|
307
307
|
<div id="toolbarViewerMiddle">
|
308
|
-
<% if defined?(
|
308
|
+
<% if defined?(display_save) && display_save == true %>
|
309
309
|
<button id="DecidimPDSaveButton" class="decidimButton" title="<%= t "save_changes", scope: "decidim.participatory_documents.document" %>">
|
310
310
|
<%= t "save_changes", scope: "decidim.participatory_documents.document" %>
|
311
311
|
</button>
|
312
312
|
<% end %>
|
313
|
-
<% if defined?(
|
313
|
+
<% if defined?(display_suggestions) && display_suggestions == true %>
|
314
314
|
<button id="globalSuggestionTrigger" class="decidimButton" title="<%= t "global_suggestions", scope: "decidim.participatory_documents.document" %>">
|
315
315
|
<%= t "global_suggestions", scope: "decidim.participatory_documents.document" %>
|
316
316
|
</button>
|
317
|
+
<button id="exportSuggestionsTrigger" class="decidimButton muted" title="<%= t "export_my_suggestions", scope: "decidim.participatory_documents.document" %>">
|
318
|
+
<%= t "export_my_suggestions", scope: "decidim.participatory_documents.document" %>
|
319
|
+
</button>
|
317
320
|
<% end %>
|
318
321
|
</div>
|
319
322
|
</div>
|
@@ -13,51 +13,58 @@
|
|
13
13
|
<!-- This snippet is used in production (included from viewer.html) -->
|
14
14
|
<link rel="resource" type="application/l10n" href="/pdfjs/web/locale/locale.properties">
|
15
15
|
<script src="/pdfjs/web/viewer.js"></script>
|
16
|
-
<%= javascript_pack_tag "decidim_participatory_documents_viewer" %>
|
17
16
|
<%= stylesheet_pack_tag "decidim_participatory_documents_viewer" %>
|
17
|
+
<%= javascript_pack_tag "decidim_participatory_documents_viewer" if current_user %>
|
18
|
+
<%= javascript_pack_tag "decidim_participatory_documents_viewer_off" unless current_user %>
|
18
19
|
<%= organization_colors %>
|
19
20
|
<%= pdf_custom_style %>
|
20
21
|
<%= csrf_meta_tags %>
|
21
22
|
</head>
|
22
23
|
|
23
24
|
<body tabindex="1">
|
24
|
-
<%= render "decidim/participatory_documents/documents/pdfjs_base",
|
25
|
+
<%= render "decidim/participatory_documents/documents/pdfjs_base", display_suggestions: true %>
|
25
26
|
|
26
27
|
<div id="notifications"></div>
|
27
28
|
|
28
29
|
<div id="participation-modal"></div>
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
31
|
+
<%= render "export_modal" %>
|
32
|
+
|
33
|
+
<script>
|
34
|
+
|
35
|
+
var I18n = <%= I18n.t("decidim.participatory_documents.ui_messages").to_json.html_safe %>;
|
36
|
+
var DocumentPath = '<%= document_path(document).split("?")[0] %>';
|
37
|
+
var CurrentBoxes = <%= document.annotations.collect(&:serialize).to_json.html_safe %>;
|
38
|
+
var pages = {};
|
39
|
+
|
40
|
+
PDFViewerApplication.initializedPromise.then(function() {
|
41
|
+
var options = {
|
42
|
+
i18n: I18n,
|
43
|
+
documentPath: DocumentPath,
|
44
|
+
globalSuggestionsButton: document.getElementById("globalSuggestionTrigger"),
|
45
|
+
participationLayout: document.getElementById("participation-modal"),
|
46
|
+
exportButton: document.getElementById("exportSuggestionsTrigger"),
|
47
|
+
exportModal: document.getElementById("export-modal")
|
48
|
+
};
|
49
|
+
|
50
|
+
window.InitDocumentManagers(options);
|
51
|
+
|
52
|
+
window.showInfo(I18n.startSuggesting, {delay: 5000});
|
53
|
+
|
54
|
+
PDFViewerApplication.eventBus.on('annotationeditorlayerrendered', function (doc) {
|
55
|
+
var page = PDFViewerApplication.pdfViewer._pages[doc.pageNumber - 1];
|
56
|
+
var annotationsLayer = page.annotationEditorLayer && page.annotationEditorLayer.div;
|
57
|
+
var savedPage = pages[doc.pageNumber];
|
58
|
+
// Let's render the object only if not already existing.
|
59
|
+
// Note that the PDF library might redraw the annotation layer, if this happens we need to re-render the areas.
|
60
|
+
if(annotationsLayer && (!savedPage || savedPage.boxEditor.div !== annotationsLayer)) {
|
61
|
+
page.boxEditor = window.InitPolygonViewer(annotationsLayer, CurrentBoxes.filter(box => box.page_number === doc.pageNumber), options);
|
62
|
+
pages[doc.pageNumber] = page;
|
63
|
+
}
|
64
|
+
// make all links with target blank to prevent open them inside the iframe
|
65
|
+
page.div.querySelectorAll("a[href]").forEach(anchor => anchor.target = "_blank")
|
66
|
+
});
|
59
67
|
});
|
60
|
-
|
61
|
-
</script>
|
68
|
+
</script>
|
62
69
|
</body>
|
63
70
|
</html>
|
data/config/assets.rb
CHANGED
@@ -6,6 +6,7 @@ Decidim::Webpacker.register_path("#{base_path}/app/packs")
|
|
6
6
|
Decidim::Webpacker.register_entrypoints(
|
7
7
|
decidim_participatory_documents_admin: "#{base_path}/app/packs/entrypoints/decidim_participatory_documents_admin.js",
|
8
8
|
decidim_participatory_documents_viewer: "#{base_path}/app/packs/entrypoints/decidim_participatory_documents_viewer.js",
|
9
|
+
decidim_participatory_documents_viewer_off: "#{base_path}/app/packs/entrypoints/decidim_participatory_documents_viewer_off.js",
|
9
10
|
decidim_participatory_documents_editor: "#{base_path}/app/packs/entrypoints/decidim_participatory_documents_editor.js",
|
10
11
|
decidim_participatory_documents: "#{base_path}/app/packs/entrypoints/decidim_participatory_documents.js"
|
11
12
|
)
|