decidim-decidim_awesome 0.12.5 → 0.13.1
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 +4 -4
- data/CHANGELOG.md +16 -4
- data/README.md +3 -2
- data/Rakefile +4 -12
- data/app/cells/decidim/decidim_awesome/content_blocks/map/show.erb +1 -1
- data/app/cells/decidim/decidim_awesome/content_blocks/map_cell.rb +2 -10
- data/app/cells/decidim/decidim_awesome/content_blocks/map_form/show.erb +13 -0
- data/app/cells/decidim/decidim_awesome/voting/proposal_metadata_cell.rb +1 -1
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal/show.erb +1 -1
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal_cell.rb +1 -1
- data/app/commands/decidim/decidim_awesome/admin/rename_scope_label.rb +2 -0
- data/app/controllers/concerns/decidim/decidim_awesome/admin_accountability/admin/filterable.rb +2 -0
- data/app/controllers/concerns/decidim/decidim_awesome/needs_hashcash.rb +2 -2
- data/app/controllers/decidim/decidim_awesome/admin/admin_accountability_controller.rb +2 -1
- data/app/controllers/decidim/decidim_awesome/admin/custom_redirects_controller.rb +1 -1
- data/app/controllers/decidim/decidim_awesome/required_authorizations_controller.rb +4 -0
- data/app/forms/decidim/decidim_awesome/admin/config_form.rb +1 -1
- data/app/helpers/concerns/decidim/decidim_awesome/proposals/application_helper_override.rb +4 -4
- data/app/helpers/decidim/decidim_awesome/map_helper.rb +17 -14
- data/app/jobs/decidim/decidim_awesome/destroy_private_data_job.rb +1 -1
- data/app/jobs/decidim/decidim_awesome/export_admin_actions_job.rb +6 -2
- data/app/models/decidim/decidim_awesome/paper_trail_version.rb +21 -8
- data/app/overrides/decidim/devise/sessions/new/add_hashcash.html.erb.deface +1 -1
- data/app/overrides/decidim/proposals/proposals/_proposal_actions/limit_amendments_modal.html.erb.deface +2 -0
- data/app/overrides/decidim/proposals/proposals/_votes_count/replace_counter.html.erb.deface +1 -1
- data/app/overrides/decidim/shared/_login_modal/add_hashcash.html.erb.deface +1 -1
- data/app/packs/src/decidim/decidim_awesome/amendments/show_modal_on_limits.js +13 -10
- data/app/packs/src/decidim/decidim_awesome/awesome_map/api/fetcher.js +6 -5
- data/app/packs/src/decidim/decidim_awesome/awesome_map/api/meetings_fetcher.js +1 -1
- data/app/packs/src/decidim/decidim_awesome/awesome_map/api/proposals_fetcher.js +1 -1
- data/app/packs/src/decidim/decidim_awesome/awesome_map/awesome_map.js +12 -12
- data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/controller.js +11 -8
- data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/meetings_controller.js +1 -1
- data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/proposals_controller.js +6 -6
- data/app/packs/src/decidim/decidim_awesome/awesome_map/controls_ui.js +150 -71
- data/app/packs/src/decidim/decidim_awesome/awesome_map/load_map.js +1 -1
- data/app/packs/stylesheets/decidim/decidim_awesome/admin/admin_accountability.scss +10 -6
- data/app/packs/stylesheets/decidim/decidim_awesome/awesome_map/map.scss +39 -6
- data/app/presenters/decidim/decidim_awesome/role_base_presenter.rb +3 -1
- data/app/presenters/decidim/decidim_awesome/user_entity_presenter.rb +2 -2
- data/app/serializers/concerns/decidim/decidim_awesome/proposals/proposal_serializer_methods.rb +3 -3
- data/app/serializers/decidim/decidim_awesome/proposals/private_proposal_serializer.rb +1 -1
- data/app/validators/concerns/decidim/decidim_awesome/etiquette_validator_override.rb +21 -3
- data/app/views/decidim/decidim_awesome/admin/admin_accountability/index.html.erb +5 -8
- data/app/views/decidim/decidim_awesome/admin/custom_redirects/_form.html.erb +18 -12
- data/app/views/decidim/decidim_awesome/admin/custom_redirects/edit.html.erb +15 -11
- data/app/views/decidim/decidim_awesome/admin/custom_redirects/new.html.erb +16 -11
- data/app/views/decidim/decidim_awesome/admin/shared/_filters_with_date.html.erb +1 -5
- data/app/views/decidim/decidim_awesome/map_component/map/_map_template.html.erb +4 -4
- data/app/views/decidim/decidim_awesome/map_component/map/show.html.erb +3 -1
- data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +2 -2
- data/config/i18n-tasks.yml +1 -0
- data/config/locales/ca.yml +8 -3
- data/config/locales/cs.yml +8 -3
- data/config/locales/de.yml +8 -3
- data/config/locales/en.yml +8 -2
- data/config/locales/es.yml +8 -3
- data/config/locales/eu.yml +8 -3
- data/config/locales/fr.yml +5 -3
- data/config/locales/hu.yml +0 -3
- data/config/locales/it.yml +0 -3
- data/config/locales/ja.yml +8 -3
- data/config/locales/lt.yml +0 -1
- data/config/locales/nl.yml +0 -2
- data/config/locales/pt-BR.yml +0 -3
- data/config/locales/pt-PT.yml +0 -1
- data/config/locales/ro-RO.yml +0 -6
- data/config/locales/sv.yml +0 -2
- data/lib/decidim/decidim_awesome/checksums.yml +29 -3
- data/lib/decidim/decidim_awesome/engine.rb +10 -6
- data/lib/decidim/decidim_awesome/map_component/component.rb +2 -1
- data/lib/decidim/decidim_awesome/map_component/engine.rb +2 -1
- data/lib/decidim/decidim_awesome/test/shared_examples/admin_accountability_contexts.rb +11 -0
- data/lib/decidim/decidim_awesome/version.rb +2 -2
- data/lib/tasks/decidim_awesome_migrate_menu_categories.rake +38 -0
- data/lib/tasks/decidim_awesome_upgrade_tasks.rake +4 -0
- data/package.json +7 -8
- metadata +14 -12
- data/app/overrides/decidim/proposals/proposals/_proposal_aside/limit_amendments_modal.html.erb.deface +0 -5
@@ -50,7 +50,11 @@ export default class Controller {
|
|
50
50
|
// subgroups don't have th addLayers utility
|
51
51
|
collectionEdges.forEach((item) => {
|
52
52
|
this.awesomeMap.layers[this.component.type].group.addLayer(item.node.marker);
|
53
|
-
|
53
|
+
if (item.node.taxonomies && item.node.taxonomies.length > 0) {
|
54
|
+
item.node.taxonomies.forEach((taxonomy) => {
|
55
|
+
this.addMarkerTaxonomy(item.node.marker, taxonomy);
|
56
|
+
});
|
57
|
+
}
|
54
58
|
this.addMarkerHashtags(item.node.marker, item.node.hashtags);
|
55
59
|
});
|
56
60
|
}
|
@@ -103,15 +107,14 @@ export default class Controller {
|
|
103
107
|
this.allNodes.push(node);
|
104
108
|
}
|
105
109
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
if (this.awesomeMap.layers[cat.id]) {
|
110
|
+
addMarkerTaxonomy(marker, taxonomy) {
|
111
|
+
const tax = this.awesomeMap.getTaxonomy(taxonomy);
|
112
|
+
if (this.awesomeMap.layers[tax.id]) {
|
110
113
|
try {
|
111
|
-
this.awesomeMap.layers[
|
112
|
-
this.awesomeMap.controls.
|
114
|
+
this.awesomeMap.layers[tax.id].group.addLayer(marker);
|
115
|
+
this.awesomeMap.controls.showTaxonomy(tax);
|
113
116
|
} catch (evt) {
|
114
|
-
console.error("Failed
|
117
|
+
console.error("Failed taxonomy marker assignation. taxonomy:", taxonomy, "marker:", marker, evt.message);
|
115
118
|
}
|
116
119
|
}
|
117
120
|
}
|
@@ -13,7 +13,7 @@ export default class MeetingsController extends Controller {
|
|
13
13
|
// for each meeting, create a marker with an associated popup
|
14
14
|
this.fetcher.onNode = (meeting) => {
|
15
15
|
let marker = new L.Marker([meeting.coordinates.latitude, meeting.coordinates.longitude], {
|
16
|
-
icon: this.createIcon(this.awesomeMap.
|
16
|
+
icon: this.createIcon(this.awesomeMap.getTaxonomy(meeting.taxonomies && meeting.taxonomies[0]).color),
|
17
17
|
title: meeting.title.translation
|
18
18
|
});
|
19
19
|
// console.log("new meeting", meeting, marker)
|
@@ -28,15 +28,15 @@ export default class ProposalsController extends Controller {
|
|
28
28
|
// for each proposal, create a marker with an associated popup
|
29
29
|
this.fetcher.onNode = (proposal) => {
|
30
30
|
let marker = new L.Marker([proposal.coordinates.latitude, proposal.coordinates.longitude], {
|
31
|
-
icon: this.createIcon(this.awesomeMap.
|
31
|
+
icon: this.createIcon(this.awesomeMap.getTaxonomy(proposal.taxonomies && proposal.taxonomies[0]).color),
|
32
32
|
title: proposal.title.translation
|
33
33
|
});
|
34
34
|
|
35
35
|
// Check if it has amendments, add it to a list
|
36
|
-
// also assign parent's proposal
|
36
|
+
// also assign parent's proposal taxonomies to it
|
37
37
|
// console.log("onNode proposal", proposal, "amendment:", proposal.amendments)
|
38
38
|
if (proposal.amendments && proposal.amendments.length) {
|
39
|
-
proposal.amendments.forEach((amendment) => {
|
39
|
+
proposal.amendments.filter((amendment) => amendment && amendment.emendation).forEach((amendment) => {
|
40
40
|
this.amendments[amendment.emendation.id] = proposal;
|
41
41
|
});
|
42
42
|
}
|
@@ -67,10 +67,10 @@ export default class ProposalsController extends Controller {
|
|
67
67
|
}
|
68
68
|
if (this.awesomeMap.config.menu.amendments) {
|
69
69
|
marker.marker.addTo(this.awesomeMap.layers.amendments.group);
|
70
|
-
// mimic parent
|
71
|
-
if (parent.
|
70
|
+
// mimic parent taxonomy (amendments doesn't have taxonomies)
|
71
|
+
if (parent.taxonomy) {
|
72
72
|
marker.marker.setIcon(this.createIcon("text-secondary"));
|
73
|
-
this.
|
73
|
+
this.addMarkerTaxonomy(marker.marker, parent.taxonomy)
|
74
74
|
}
|
75
75
|
}
|
76
76
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/* eslint-disable no-ternary, multiline-ternary */
|
1
|
+
/* eslint-disable no-ternary, multiline-ternary, no-nested-ternary, max-lines */
|
2
2
|
|
3
3
|
import * as L from "leaflet";
|
4
4
|
|
@@ -21,7 +21,7 @@ export default class ControlsUI {
|
|
21
21
|
this.onHashtag = this._orderHashtags;
|
22
22
|
|
23
23
|
this.awesomeMap.map.on("overlayadd", () => {
|
24
|
-
this.
|
24
|
+
this.removeHiddenTaxonomies();
|
25
25
|
});
|
26
26
|
}
|
27
27
|
|
@@ -30,18 +30,18 @@ export default class ControlsUI {
|
|
30
30
|
this.main.addTo(this.awesomeMap.map);
|
31
31
|
|
32
32
|
this.addSearchControls();
|
33
|
-
if (this.awesomeMap.config.menu.
|
34
|
-
this.
|
33
|
+
if (this.awesomeMap.config.menu.taxonomies) {
|
34
|
+
this.addTaxonomiesControls();
|
35
35
|
}
|
36
36
|
|
37
37
|
// sub-layer hashtag title toggle
|
38
38
|
$("#awesome-map").on("click", ".awesome_map-title-control", (evt) => {
|
39
39
|
evt.preventDefault();
|
40
40
|
evt.stopPropagation();
|
41
|
-
const
|
41
|
+
const taxonomies = document.getElementById("awesome_map-taxonomies-control");
|
42
42
|
const hashtags = document.getElementById("awesome_map-hashtags-control");
|
43
|
-
if (
|
44
|
-
|
43
|
+
if (taxonomies) {
|
44
|
+
taxonomies.classList.toggle("active");
|
45
45
|
}
|
46
46
|
if (hashtags) {
|
47
47
|
hashtags.classList.toggle("active");
|
@@ -82,62 +82,146 @@ export default class ControlsUI {
|
|
82
82
|
addSearchControls() {
|
83
83
|
const section = this.main.getContainer().querySelector(".leaflet-control-layers-list");
|
84
84
|
if (section) {
|
85
|
-
section.insertAdjacentHTML("beforeend", `<div id="awesome_map-
|
85
|
+
section.insertAdjacentHTML("beforeend", `<div id="awesome_map-taxonomies-control" class="active"><b class="awesome_map-title-control">${window.DecidimAwesome.i18n.taxonomies}</b><div class="taxonomies-container"></div></div>
|
86
86
|
<div id="awesome_map-hashtags-control"><b class="awesome_map-title-control">${window.DecidimAwesome.i18n.hashtags}</b><div class="hashtags-container"></div><a href="#" class="awesome_map-toggle_all_tags">${window.DecidimAwesome.i18n.selectDeselectAll}</a></div>`);
|
87
87
|
} else {
|
88
88
|
console.error("Can't find the section to insert the controls");
|
89
89
|
}
|
90
90
|
}
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
categories.insertAdjacentHTML("beforeend", `<label data-layer="${category.id}" class="awesome_map-category-${category.id}${category.parent ? " subcategory" : ""}" data-parent="${category.parent}"><input type="checkbox" class="awesome_map-categories-selector" checked><span>${label}</span></label>`);
|
104
|
-
} else {
|
105
|
-
console.error("Can't find the section to insert the categories");
|
106
|
-
}
|
107
|
-
})
|
92
|
+
addTaxonomiesControls() {
|
93
|
+
// First, organize taxonomies by levels
|
94
|
+
const rootTaxonomies = this.awesomeMap.taxonomies.filter((tax) => !tax.parent);
|
95
|
+
|
96
|
+
// Process each root taxonomy independently
|
97
|
+
rootTaxonomies.forEach((rootTaxonomy) => {
|
98
|
+
// Add the root taxonomy
|
99
|
+
this._addTaxonomyToUI(rootTaxonomy, 0);
|
100
|
+
|
101
|
+
// Find and add direct children of this root taxonomy
|
102
|
+
const children = this.awesomeMap.taxonomies.filter((tax) => tax.parent === rootTaxonomy.id);
|
108
103
|
|
109
|
-
|
110
|
-
|
104
|
+
children.forEach((child) => {
|
105
|
+
this._addTaxonomyToUI(child, 1);
|
106
|
+
|
107
|
+
// Find and add grandchildren of this child
|
108
|
+
const grandchildren = this.awesomeMap.taxonomies.filter((tax) => tax.parent === child.id);
|
109
|
+
|
110
|
+
grandchildren.forEach((grandchild) => {
|
111
|
+
this._addTaxonomyToUI(grandchild, 2);
|
112
|
+
});
|
113
|
+
});
|
114
|
+
});
|
115
|
+
|
116
|
+
// taxonomy events
|
117
|
+
$("#awesome-map").on("change", ".awesome_map-taxonomies-selector", (evt) => {
|
111
118
|
evt.preventDefault();
|
112
119
|
evt.stopPropagation();
|
113
120
|
|
114
121
|
const id = $(evt.target).closest("label").data("layer");
|
115
|
-
const
|
116
|
-
|
117
|
-
if (
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
+
const taxonomy = this.awesomeMap.getTaxonomy(id);
|
123
|
+
|
124
|
+
if (taxonomy) {
|
125
|
+
this._handleTaxonomyToggle(taxonomy, evt.target.checked);
|
126
|
+
}
|
127
|
+
});
|
128
|
+
}
|
129
|
+
|
130
|
+
_addTaxonomyToUI(taxonomy, level) {
|
131
|
+
// Create control layer for this taxonomy
|
132
|
+
const circleIcon = taxonomy.parent ? `<i class="awesome_map-taxonomy_${taxonomy.id}"></i> ` : "";
|
133
|
+
const label = `${circleIcon}${taxonomy.name}`;
|
134
|
+
this.awesomeMap.layers[taxonomy.id] = {
|
135
|
+
label: label,
|
136
|
+
group: new L.FeatureGroup.SubGroup(this.awesomeMap.cluster)
|
137
|
+
};
|
138
|
+
this.awesomeMap.layers[taxonomy.id].group.addTo(this.awesomeMap.map);
|
139
|
+
|
140
|
+
const taxonomiesContainer = document.querySelector("#awesome_map-taxonomies-control .taxonomies-container");
|
141
|
+
if (taxonomiesContainer) {
|
142
|
+
const levelClass = level === 0 ? "root-taxonomy" : level === 1 ? "child-taxonomy" : "grandchild-taxonomy";
|
143
|
+
const indentStyle = `style="padding-left: ${level * 20}px;"`;
|
144
|
+
|
145
|
+
taxonomiesContainer.insertAdjacentHTML("beforeend",
|
146
|
+
`<label data-layer="${taxonomy.id}"
|
147
|
+
class="awesome_map-taxonomy-${taxonomy.id} ${levelClass}"
|
148
|
+
data-parent="${taxonomy.parent || ""}"
|
149
|
+
data-level="${level}"
|
150
|
+
${indentStyle}>
|
151
|
+
<input type="checkbox" class="awesome_map-taxonomies-selector" checked>
|
152
|
+
<span>${label}</span>
|
153
|
+
</label>`
|
154
|
+
);
|
155
|
+
} else {
|
156
|
+
console.error("Can't find the section to insert the taxonomies");
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
_handleTaxonomyToggle(taxonomy, isChecked) {
|
161
|
+
const layer = this.awesomeMap.layers[taxonomy.id];
|
162
|
+
|
163
|
+
if (isChecked) {
|
164
|
+
// Show group of markers
|
165
|
+
this.awesomeMap.map.addLayer(layer.group);
|
166
|
+
} else {
|
167
|
+
// Hide group of markers
|
168
|
+
this.awesomeMap.map.removeLayer(layer.group);
|
169
|
+
// Uncheck all children when parent is unchecked
|
170
|
+
this._uncheckChildrenTaxonomies(taxonomy.id);
|
171
|
+
}
|
172
|
+
|
173
|
+
// Update parent state (indeterminate/checked/unchecked)
|
174
|
+
this._updateParentTaxonomyState(taxonomy);
|
175
|
+
|
176
|
+
// sync hashtags
|
177
|
+
this.updateHashtagLayers();
|
178
|
+
}
|
179
|
+
|
180
|
+
_uncheckChildrenTaxonomies(taxonomyId) {
|
181
|
+
const children = this.awesomeMap.taxonomies.filter((tax) => tax.parent === taxonomyId);
|
182
|
+
children.forEach((child) => {
|
183
|
+
const childInput = document.querySelector(`label[data-layer="${child.id}"] input`);
|
184
|
+
if (childInput && childInput.checked) {
|
185
|
+
childInput.checked = false;
|
186
|
+
this.awesomeMap.map.removeLayer(this.awesomeMap.layers[child.id].group);
|
187
|
+
// Recursively uncheck grandchildren
|
188
|
+
this._uncheckChildrenTaxonomies(child.id);
|
189
|
+
}
|
190
|
+
});
|
191
|
+
}
|
192
|
+
|
193
|
+
_updateParentTaxonomyState(taxonomy) {
|
194
|
+
if (taxonomy.parent) {
|
195
|
+
const parentInput = document.querySelector(`label[data-layer="${taxonomy.parent}"] input`);
|
196
|
+
if (parentInput) {
|
197
|
+
const siblings = this.awesomeMap.taxonomies.filter((tax) => tax.parent === taxonomy.parent);
|
198
|
+
const checkedSiblings = siblings.filter((sibling) => {
|
199
|
+
const siblingInput = document.querySelector(`label[data-layer="${sibling.id}"] input`);
|
200
|
+
return siblingInput && siblingInput.checked;
|
201
|
+
});
|
202
|
+
|
203
|
+
if (checkedSiblings.length === 0) {
|
204
|
+
// No siblings checked - uncheck parent
|
205
|
+
parentInput.checked = true;
|
206
|
+
this.awesomeMap.map.removeLayer(this.awesomeMap.layers[taxonomy].group);
|
207
|
+
} else if (checkedSiblings.length === siblings.length) {
|
208
|
+
// All siblings checked - check parent
|
209
|
+
parentInput.checked = true;
|
210
|
+
this.awesomeMap.map.addLayer(this.awesomeMap.layers[taxonomy.parent].group);
|
122
211
|
} else {
|
123
|
-
//
|
124
|
-
|
125
|
-
|
126
|
-
// let $el = $(`.awesome_map-category-${c.id}`);
|
127
|
-
// if($el.contents("input").prop("checked")) {
|
128
|
-
// $el.click();
|
129
|
-
// }
|
130
|
-
// });
|
212
|
+
// Some siblings checked
|
213
|
+
parentInput.checked = true;
|
214
|
+
this.awesomeMap.map.addLayer(this.awesomeMap.layers[taxonomy.parent].group);
|
131
215
|
}
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
this.
|
216
|
+
|
217
|
+
// Recursively update grandparent
|
218
|
+
const parentTaxonomy = this.awesomeMap.getTaxonomy(taxonomy.parent);
|
219
|
+
this._updateParentTaxonomyState(parentTaxonomy);
|
136
220
|
}
|
137
|
-
}
|
221
|
+
}
|
138
222
|
}
|
139
223
|
|
140
|
-
// Hashtags are collected directly from proposals (this is different than
|
224
|
+
// Hashtags are collected directly from proposals (this is different than taxonomies)
|
141
225
|
addHashtagsControls(hashtags, marker) {
|
142
226
|
// show hashtag layer
|
143
227
|
if (hashtags && hashtags.length) {
|
@@ -163,20 +247,24 @@ export default class ControlsUI {
|
|
163
247
|
}
|
164
248
|
}
|
165
249
|
|
166
|
-
|
167
|
-
document.getElementById("awesome_map-
|
168
|
-
|
169
|
-
|
170
|
-
const
|
171
|
-
if (label) {
|
250
|
+
showTaxonomy(tax) {
|
251
|
+
document.getElementById("awesome_map-taxonomies-control").style.display = "block";
|
252
|
+
|
253
|
+
// Show taxonomy if hidden
|
254
|
+
const label = document.querySelector(`label.awesome_map-taxonomy-${tax.id}`);
|
255
|
+
if (label) {
|
172
256
|
label.style.display = "block";
|
173
257
|
// update number of items
|
174
|
-
|
258
|
+
const currentCount = parseInt(label.title || 0, 10) + 1;
|
259
|
+
label.setAttribute("title", `${currentCount} ${window.DecidimAwesome.i18n.items}`);
|
175
260
|
}
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
261
|
+
|
262
|
+
// Also show all parent taxonomies up the hierarchy
|
263
|
+
if (tax.parent) {
|
264
|
+
const parentTaxonomy = this.awesomeMap.getTaxonomy(tax.parent);
|
265
|
+
if (parentTaxonomy) {
|
266
|
+
this.showTaxonomy(parentTaxonomy);
|
267
|
+
}
|
180
268
|
}
|
181
269
|
}
|
182
270
|
|
@@ -191,8 +279,8 @@ export default class ControlsUI {
|
|
191
279
|
});
|
192
280
|
}
|
193
281
|
|
194
|
-
|
195
|
-
$(".awesome_map-
|
282
|
+
removeHiddenTaxonomies() {
|
283
|
+
$(".awesome_map-taxonomies-selector:not(:checked)").each((_idx, el) => {
|
196
284
|
const layer = this.awesomeMap.layers[$(el).closest("label").data("layer")];
|
197
285
|
if (layer) {
|
198
286
|
this.awesomeMap.map.addLayer(layer.group);
|
@@ -216,9 +304,9 @@ export default class ControlsUI {
|
|
216
304
|
this.awesomeMap.map.addLayer(layer.group);
|
217
305
|
}
|
218
306
|
});
|
219
|
-
// hide non-selected
|
307
|
+
// hide non-selected taxonomies
|
220
308
|
this.removeHiddenComponents();
|
221
|
-
this.
|
309
|
+
this.removeHiddenTaxonomies();
|
222
310
|
}
|
223
311
|
|
224
312
|
updateStats(uid, total) {
|
@@ -227,15 +315,6 @@ export default class ControlsUI {
|
|
227
315
|
$component.attr("title", `${total} ${window.DecidimAwesome.i18n.items}`);
|
228
316
|
}
|
229
317
|
|
230
|
-
_indeterminateParentInput(cat) {
|
231
|
-
if (cat.parent) {
|
232
|
-
let $input = $(`.awesome_map-category-${cat.parent}`).contents("input");
|
233
|
-
let $subcats = $(`[class^="awesome_map-category-"][data-parent="${cat.parent}"]:visible`);
|
234
|
-
let numChecked = $subcats.contents("input:checked").length;
|
235
|
-
$input.prop("indeterminate", numChecked !== $subcats.length && numChecked !== 0);
|
236
|
-
}
|
237
|
-
}
|
238
|
-
|
239
318
|
// order hashtags alphabetically
|
240
319
|
_orderHashtags(_hashtag, $div) {
|
241
320
|
let $last = $div.contents("label:last");
|
@@ -30,7 +30,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
30
30
|
menu: {
|
31
31
|
amendments: parse(dataset.menuAmendments),
|
32
32
|
meetings: parse(dataset.menuMeetings),
|
33
|
-
|
33
|
+
taxonomies: parse(dataset.menuTaxonomies),
|
34
34
|
hashtags: parse(dataset.menuHashtags),
|
35
35
|
mergeComponents: parse(dataset.menuMergeComponents)
|
36
36
|
},
|
@@ -49,10 +49,6 @@
|
|
49
49
|
}
|
50
50
|
}
|
51
51
|
|
52
|
-
.row.column:last-child {
|
53
|
-
@apply flex items-center justify-center;
|
54
|
-
}
|
55
|
-
|
56
52
|
.search-button-container {
|
57
53
|
@apply flex flex-col items-start;
|
58
54
|
|
@@ -61,7 +57,15 @@
|
|
61
57
|
}
|
62
58
|
}
|
63
59
|
|
64
|
-
.row.column
|
65
|
-
@apply
|
60
|
+
.row.column {
|
61
|
+
@apply mb-0;
|
62
|
+
|
63
|
+
&:last-child {
|
64
|
+
@apply flex items-center justify-center;
|
65
|
+
}
|
66
|
+
|
67
|
+
&.search-field {
|
68
|
+
@apply flex-grow;
|
69
|
+
}
|
66
70
|
}
|
67
71
|
}
|
@@ -110,7 +110,7 @@
|
|
110
110
|
}
|
111
111
|
|
112
112
|
#awesome_map- {
|
113
|
-
&
|
113
|
+
&taxonomies-control {
|
114
114
|
display: none;
|
115
115
|
|
116
116
|
label {
|
@@ -123,20 +123,53 @@
|
|
123
123
|
width: 0.8rem;
|
124
124
|
height: 0.8rem;
|
125
125
|
border-radius: 50%;
|
126
|
-
background-color: var(-- primary);
|
127
126
|
}
|
128
127
|
|
129
|
-
|
130
|
-
|
128
|
+
// Hierarchical styling for taxonomies
|
129
|
+
&.root-taxonomy {
|
130
|
+
font-weight: bold;
|
131
|
+
margin-bottom: 0.3em;
|
132
|
+
}
|
133
|
+
|
134
|
+
&.child-taxonomy {
|
135
|
+
font-weight: 500;
|
136
|
+
margin-bottom: 0.2em;
|
137
|
+
}
|
138
|
+
|
139
|
+
&.grandchild-taxonomy {
|
140
|
+
font-weight: normal;
|
141
|
+
margin-bottom: 0.1em;
|
142
|
+
|
143
|
+
i {
|
144
|
+
width: 0.6rem;
|
145
|
+
height: 0.6rem;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
// Indeterminate checkbox styling
|
150
|
+
input[type="checkbox"]:indeterminate {
|
151
|
+
background-color: #6c757d;
|
152
|
+
border-color: #6c757d;
|
153
|
+
|
154
|
+
&::before {
|
155
|
+
content: "−";
|
156
|
+
color: white;
|
157
|
+
font-weight: bold;
|
158
|
+
text-align: center;
|
159
|
+
line-height: 1;
|
160
|
+
display: block;
|
161
|
+
}
|
131
162
|
}
|
132
163
|
}
|
133
164
|
|
134
|
-
.
|
165
|
+
.taxonomies-container {
|
135
166
|
display: none;
|
167
|
+
max-height: 300px;
|
168
|
+
overflow-y: auto;
|
136
169
|
}
|
137
170
|
|
138
171
|
&.active {
|
139
|
-
.
|
172
|
+
.taxonomies-container {
|
140
173
|
display: block;
|
141
174
|
}
|
142
175
|
}
|
@@ -9,9 +9,9 @@ module Decidim
|
|
9
9
|
query = PaperTrail::Version.where(item_type:, event: "update", item_id:)
|
10
10
|
.where("id > ?", entry.id)
|
11
11
|
if roles.include? "admin"
|
12
|
-
query.where("object_changes
|
12
|
+
query.where("object_changes @> ?", { "admin" => [true, false] }.to_json).first
|
13
13
|
else
|
14
|
-
query.where("object_changes
|
14
|
+
query.where("object_changes @> ?", { "roles" => [[], []] }.to_json).first
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/app/serializers/concerns/decidim/decidim_awesome/proposals/proposal_serializer_methods.rb
CHANGED
@@ -30,12 +30,12 @@ module Decidim
|
|
30
30
|
if body.is_a?(Hash)
|
31
31
|
body.each do |translation_locale, value|
|
32
32
|
fields_entries(custom_fields, value) do |field_key, field_value|
|
33
|
-
payload["body/#{field_key}/#{translation_locale}"
|
33
|
+
payload[:"body/#{field_key}/#{translation_locale}"] = field_value if payload[:"body/#{field_key}/#{translation_locale}"].blank?
|
34
34
|
end
|
35
35
|
end
|
36
36
|
else
|
37
37
|
fields_entries(custom_fields, body) do |key, value|
|
38
|
-
payload["body/#{key}/#{locale}"
|
38
|
+
payload[:"body/#{key}/#{locale}"] = value
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -49,7 +49,7 @@ module Decidim
|
|
49
49
|
if private_custom_fields.present?
|
50
50
|
fields_entries(private_custom_fields, proposal.private_body) do |key, value|
|
51
51
|
value = value.first if value.is_a? Array
|
52
|
-
payload["private_body/#{key}"
|
52
|
+
payload[:"private_body/#{key}"] = value
|
53
53
|
end
|
54
54
|
end
|
55
55
|
payload
|
@@ -6,24 +6,36 @@ module Decidim
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
9
|
+
alias_method :original_validate_caps, :validate_caps
|
10
|
+
alias_method :original_validate_marks, :validate_marks
|
11
|
+
alias_method :original_validate_caps_first, :validate_caps_first
|
12
|
+
|
9
13
|
private
|
10
14
|
|
11
15
|
def validate_caps(record, attribute, value)
|
12
|
-
|
16
|
+
awesome_config = awesome_config(record, "validate_#{attribute_without_locale(attribute)}_max_caps_percent")
|
17
|
+
return original_validate_caps(record, attribute, value) if awesome_config.nil?
|
18
|
+
|
19
|
+
percent = awesome_config.to_f
|
13
20
|
return if value.scan(/[[:upper:]]/).length < value.length * percent / 100
|
14
21
|
|
15
22
|
record.errors.add(attribute, options[:message] || I18n.t("too_much_caps", scope: "decidim.decidim_awesome.validators", percent: percent.round))
|
16
23
|
end
|
17
24
|
|
18
25
|
def validate_marks(record, attribute, value)
|
19
|
-
|
26
|
+
awesome_config = awesome_config(record, "validate_#{attribute_without_locale(attribute)}_max_marks_together")
|
27
|
+
return original_validate_marks(record, attribute, value) if awesome_config.nil?
|
28
|
+
|
29
|
+
marks = awesome_config.to_i + 1
|
20
30
|
return if value.scan(/[!?¡¿]{#{marks},}/).empty?
|
21
31
|
|
22
32
|
record.errors.add(attribute, options[:message] || :too_many_marks)
|
23
33
|
end
|
24
34
|
|
25
35
|
def validate_caps_first(record, attribute, value)
|
26
|
-
|
36
|
+
awesome_config = awesome_config(record, "validate_#{attribute_without_locale(attribute)}_start_with_caps")
|
37
|
+
return original_validate_caps_first(record, attribute, value) if awesome_config.nil?
|
38
|
+
return unless awesome_config
|
27
39
|
return if value.scan(/\A[[:lower:]]{1}/).empty?
|
28
40
|
|
29
41
|
record.errors.add(attribute, options[:message] || :must_start_with_caps)
|
@@ -35,6 +47,12 @@ module Decidim
|
|
35
47
|
|
36
48
|
config[var.to_sym]
|
37
49
|
end
|
50
|
+
|
51
|
+
def attribute_without_locale(attribute)
|
52
|
+
return attribute unless Decidim.available_locales.map { |locale| "_#{locale}" }.any? { |str| attribute.ends_with?(str) }
|
53
|
+
|
54
|
+
attribute.to_s[0...-3]
|
55
|
+
end
|
38
56
|
end
|
39
57
|
end
|
40
58
|
end
|
@@ -1,8 +1,7 @@
|
|
1
|
-
<div class="
|
2
|
-
|
3
|
-
<h2 class="card-title flex md:flex-row justify-between sm:flex-wrap">
|
1
|
+
<div class="item_show__header">
|
2
|
+
<h1 class="item_show__header-title">
|
4
3
|
<%= t(".title") %>
|
5
|
-
<div class="
|
4
|
+
<div class="gap-4">
|
6
5
|
<%= link_to t(global? ? ".see_spaces" : ".see_global"), admin_accountability_path(admins: !global?), class: "button button__sm button__transparent-secondary tiny button--title new" %>
|
7
6
|
<span class="exports button button__sm button__secondary tiny button--simple button--title" data-toggle="export-dropdown">
|
8
7
|
<%= t "exports.button", scope: "decidim.decidim_awesome.admin.admin_accountability" %>
|
@@ -21,13 +20,12 @@
|
|
21
20
|
</ul>
|
22
21
|
</div>
|
23
22
|
</div>
|
24
|
-
</
|
23
|
+
</h1>
|
25
24
|
</div>
|
26
25
|
|
27
26
|
<%= render partial: "decidim/decidim_awesome/admin/shared/filters_with_date", locals: { i18n_ctx: "admin_accountability" } %>
|
28
27
|
|
29
|
-
|
30
|
-
<p class="help-text"><%= t(global? ? ".global_description" : ".description") %></p>
|
28
|
+
<p class="help-text mt-3 mb-3"><%= t(global? ? ".global_description" : ".description") %></p>
|
31
29
|
|
32
30
|
<% if global_users_missing_date %>
|
33
31
|
<div class="callout warning"><%= t(".missing_users", date: l(global_users_missing_date, format: :decidim_short)) %></div>
|
@@ -67,5 +65,4 @@
|
|
67
65
|
<%= paginate admin_actions, theme: "decidim" %>
|
68
66
|
</div>
|
69
67
|
</div>
|
70
|
-
</div>
|
71
68
|
<% append_stylesheet_pack_tag "decidim_admin_decidim_awesome_search_form" %>
|