decidim-assemblies 0.26.8 → 0.27.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 +4 -4
- data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb +2 -2
- data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb +5 -5
- data/app/commands/decidim/assemblies/admin/copy_assembly.rb +10 -7
- data/app/commands/decidim/assemblies/admin/create_assemblies_type.rb +1 -1
- data/app/commands/decidim/assemblies/admin/create_assembly.rb +1 -1
- data/app/commands/decidim/assemblies/admin/create_assembly_member.rb +12 -12
- data/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb +1 -1
- data/app/commands/decidim/assemblies/admin/destroy_assembly_admin.rb +1 -6
- data/app/commands/decidim/assemblies/admin/destroy_assembly_member.rb +1 -1
- data/app/commands/decidim/assemblies/admin/import_assembly.rb +11 -7
- data/app/commands/decidim/assemblies/admin/notify_role_assigned_to_assembly.rb +1 -1
- data/app/commands/decidim/assemblies/admin/publish_assembly.rb +1 -1
- data/app/commands/decidim/assemblies/admin/unpublish_assembly.rb +1 -1
- data/app/commands/decidim/assemblies/admin/update_assemblies_setting.rb +1 -1
- data/app/commands/decidim/assemblies/admin/update_assemblies_type.rb +1 -1
- data/app/commands/decidim/assemblies/admin/update_assembly.rb +1 -1
- data/app/commands/decidim/assemblies/admin/update_assembly_member.rb +11 -11
- data/app/controllers/decidim/assemblies/admin/assemblies_types_controller.rb +1 -1
- data/app/controllers/decidim/assemblies/admin/assembly_copies_controller.rb +1 -1
- data/app/controllers/decidim/assemblies/admin/assembly_imports_controller.rb +1 -1
- data/app/controllers/decidim/assemblies/admin/assembly_members_controller.rb +1 -1
- data/app/controllers/decidim/assemblies/admin/reminders_controller.rb +14 -0
- data/app/controllers/decidim/assemblies/assemblies_controller.rb +6 -6
- data/app/events/decidim/role_assigned_to_assembly_event.rb +1 -1
- data/app/forms/decidim/assemblies/admin/assembly_import_form.rb +5 -6
- data/app/helpers/decidim/assemblies/filter_assemblies_helper.rb +10 -6
- data/app/models/decidim/assembly.rb +10 -4
- data/app/packs/src/decidim/assemblies/orgchart.js +52 -46
- data/app/permissions/decidim/assemblies/permissions.rb +45 -11
- data/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb +1 -1
- data/app/presenters/decidim/assemblies/assembly_stats_presenter.rb +4 -1
- data/app/presenters/decidim/assembly_member_presenter.rb +3 -5
- data/app/queries/decidim/assemblies/admin/admin_users.rb +1 -1
- data/app/queries/decidim/assemblies/admin/assembly_members.rb +1 -1
- data/app/queries/decidim/assemblies/assemblies_with_user_role.rb +1 -1
- data/app/queries/decidim/assemblies/filtered_assemblies.rb +1 -1
- data/app/queries/decidim/assemblies/organization_assemblies.rb +1 -1
- data/app/queries/decidim/assemblies/organization_prioritized_assemblies.rb +2 -2
- data/app/queries/decidim/assemblies/organization_published_assemblies.rb +2 -2
- data/app/queries/decidim/assemblies/parent_assemblies.rb +1 -1
- data/app/queries/decidim/assemblies/parent_assemblies_for_select.rb +1 -1
- data/app/queries/decidim/assemblies/prioritized_assemblies.rb +1 -1
- data/app/queries/decidim/assemblies/promoted_assemblies.rb +1 -1
- data/app/queries/decidim/assemblies/published_assemblies.rb +1 -1
- data/app/queries/decidim/assemblies/visible_assemblies.rb +1 -1
- data/app/serializers/decidim/assemblies/assembly_importer.rb +3 -4
- data/app/views/decidim/assemblies/_filter_by_type.html.erb +1 -1
- data/app/views/decidim/assemblies/admin/assemblies/_form.html.erb +2 -2
- data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +2 -3
- data/app/views/decidim/assemblies/admin/assemblies/new.html.erb +0 -2
- data/app/views/decidim/assemblies/admin/assemblies_settings/edit.html.erb +0 -1
- data/app/views/decidim/assemblies/admin/assemblies_types/edit.html.erb +0 -1
- data/app/views/decidim/assemblies/admin/assemblies_types/index.html.erb +0 -2
- data/app/views/decidim/assemblies/admin/assemblies_types/new.html.erb +0 -1
- data/app/views/decidim/assemblies/assemblies/_promoted_assembly.html.erb +1 -1
- data/app/views/decidim/assemblies/assemblies/index.html.erb +3 -1
- data/app/views/decidim/assemblies/assemblies/show.html.erb +8 -6
- data/app/views/layouts/decidim/_assembly_header.html.erb +1 -1
- data/app/views/layouts/decidim/admin/assembly.html.erb +0 -1
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/ar.yml +7 -76
- data/config/locales/bg.yml +1 -4
- data/config/locales/ca.yml +8 -12
- data/config/locales/cs.yml +20 -24
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +9 -13
- data/config/locales/el.yml +6 -32
- data/config/locales/en.yml +6 -11
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +8 -12
- data/config/locales/es-PY.yml +8 -12
- data/config/locales/es.yml +10 -14
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +27 -33
- data/config/locales/fi-plain.yml +9 -13
- data/config/locales/fi.yml +11 -15
- data/config/locales/fr-CA.yml +9 -13
- data/config/locales/fr.yml +14 -18
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/gl.yml +6 -8
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +8 -57
- data/config/locales/id-ID.yml +6 -1
- data/config/locales/is-IS.yml +9 -6
- data/config/locales/it.yml +8 -11
- data/config/locales/ja.yml +6 -10
- data/config/locales/ko.yml +1 -0
- data/config/locales/lb.yml +6 -8
- data/config/locales/lt.yml +1 -466
- data/config/locales/lv.yml +4 -1
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +23 -31
- data/config/locales/no.yml +6 -9
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +6 -4
- data/config/locales/pt-BR.yml +7 -29
- data/config/locales/pt.yml +4 -7
- data/config/locales/ro-RO.yml +5 -22
- data/config/locales/ru.yml +7 -3
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sk.yml +1 -17
- data/config/locales/sl.yml +5 -15
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sr-CS.yml +1 -0
- data/config/locales/sv.yml +12 -20
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +8 -24
- data/config/locales/uk.yml +7 -3
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +4 -7
- data/config/locales/zh-TW.yml +1 -462
- data/lib/decidim/assemblies/admin_engine.rb +5 -4
- data/lib/decidim/assemblies/participatory_space.rb +9 -9
- data/lib/decidim/assemblies/test/factories.rb +0 -4
- data/lib/decidim/assemblies/version.rb +1 -1
- metadata +13 -48
- data/app/services/decidim/assemblies/assembly_search.rb +0 -18
- data/config/environment.rb +0 -0
- data/config/locales/fa-IR.yml +0 -1
- data/config/locales/gn-PY.yml +0 -1
- data/config/locales/ka-GE.yml +0 -1
- data/config/locales/kaa.yml +0 -60
- data/config/locales/lo-LA.yml +0 -1
- data/config/locales/oc-FR.yml +0 -1
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
/* eslint dot-location: ["error", "property"], no-negated-condition: "error" */
|
|
3
3
|
/* eslint no-unused-expressions: ["error", { "allowTernary": true }] */
|
|
4
4
|
/* eslint no-unused-vars: 0 */
|
|
5
|
-
/* global d3 */
|
|
6
5
|
|
|
7
|
-
import
|
|
8
|
-
import
|
|
6
|
+
import { select, selectAll, event } from "d3-selection";
|
|
7
|
+
import { max } from "d3-array";
|
|
8
|
+
import { hierarchy } from "d3-hierarchy";
|
|
9
|
+
import { forceManyBody, forceCollide, forceCenter, forceX, forceY, forceSimulation, forceLink } from "d3-force";
|
|
10
|
+
import { drag } from "d3-drag";
|
|
11
|
+
import { json } from "d3-fetch";
|
|
9
12
|
|
|
10
13
|
// lib
|
|
11
14
|
const renderOrgCharts = () => {
|
|
@@ -54,11 +57,11 @@ const renderOrgCharts = () => {
|
|
|
54
57
|
let updateData
|
|
55
58
|
let collapse, expand
|
|
56
59
|
let filter
|
|
57
|
-
let
|
|
60
|
+
let _hierarchy = {}
|
|
58
61
|
|
|
59
62
|
// main chart object
|
|
60
|
-
let main = function (
|
|
61
|
-
|
|
63
|
+
let main = function (_selection) {
|
|
64
|
+
_selection.each(function scope() {
|
|
62
65
|
|
|
63
66
|
// calculated properties
|
|
64
67
|
let calc = {}
|
|
@@ -68,12 +71,12 @@ const renderOrgCharts = () => {
|
|
|
68
71
|
calc.chartHeight = attrs.svgHeight - attrs.marginBottom - calc.chartTopMargin
|
|
69
72
|
|
|
70
73
|
// ########################## HIERARCHY STUFF #########################
|
|
71
|
-
|
|
74
|
+
_hierarchy.root = hierarchy(attrs.data.root)
|
|
72
75
|
|
|
73
76
|
// ########################### BEHAVIORS #########################
|
|
74
77
|
let behaviors = {}
|
|
75
|
-
// behaviors.zoom =
|
|
76
|
-
behaviors.drag =
|
|
78
|
+
// behaviors.zoom = zoom().scaleExtent([0.75, 100, 8]).on("zoom", zoomed)
|
|
79
|
+
behaviors.drag = drag().on("start", dragstarted).on("drag", dragged).on("end", dragended)
|
|
77
80
|
|
|
78
81
|
// ########################### LAYOUTS #########################
|
|
79
82
|
let layouts = {}
|
|
@@ -83,24 +86,24 @@ const renderOrgCharts = () => {
|
|
|
83
86
|
|
|
84
87
|
// ########################### FORCE STUFF #########################
|
|
85
88
|
let force = {}
|
|
86
|
-
force.link =
|
|
87
|
-
force.charge =
|
|
88
|
-
force.center =
|
|
89
|
+
force.link = forceLink().id((d) => d.id)
|
|
90
|
+
force.charge = forceManyBody().strength(-240)
|
|
91
|
+
force.center = forceCenter(calc.chartWidth / 2, calc.chartHeight / 2)
|
|
89
92
|
|
|
90
93
|
// prevent collide
|
|
91
|
-
force.collide =
|
|
94
|
+
force.collide = forceCollide().radius((d) => {
|
|
92
95
|
// Creates an invented radius based on element measures: diagonal = 2 * radius = sqrt(width^2, height^2)
|
|
93
96
|
let base = (d.bbox || {}).width + (attrs.nodeGutter.x * 2)
|
|
94
97
|
let height = (d.bbox || {}).height + (attrs.nodeGutter.y * 2)
|
|
95
98
|
let diagonal = Math.sqrt(Math.pow(base, 2) + Math.pow(height, 2))
|
|
96
99
|
let fakeRadius = (diagonal / 2)
|
|
97
100
|
|
|
98
|
-
// return
|
|
101
|
+
// return max([attrs.nodeDistance * 3, fakeRadius])
|
|
99
102
|
return fakeRadius * 1.5
|
|
100
103
|
})
|
|
101
104
|
|
|
102
105
|
// manually set x positions (which is calculated using custom radial layout)
|
|
103
|
-
force.x =
|
|
106
|
+
force.x = forceX()
|
|
104
107
|
.strength(0.5)
|
|
105
108
|
.x(function (d) {
|
|
106
109
|
|
|
@@ -115,8 +118,8 @@ const renderOrgCharts = () => {
|
|
|
115
118
|
return projectCircle(d.proportion, (d.depth - 1) * attrs.distance)[0]
|
|
116
119
|
})
|
|
117
120
|
|
|
118
|
-
// manually set y positions (which is calculated using
|
|
119
|
-
force.y =
|
|
121
|
+
// manually set y positions (which is calculated using cluster)
|
|
122
|
+
force.y = forceY()
|
|
120
123
|
.strength(0.5)
|
|
121
124
|
.y(function (d) {
|
|
122
125
|
|
|
@@ -134,7 +137,7 @@ const renderOrgCharts = () => {
|
|
|
134
137
|
// --------------------------------- INITIALISE FORCE SIMULATION ----------------------------
|
|
135
138
|
|
|
136
139
|
// get based on top parameter simulation
|
|
137
|
-
force.simulation =
|
|
140
|
+
force.simulation = forceSimulation()
|
|
138
141
|
.force("link", force.link)
|
|
139
142
|
.force("charge", force.charge)
|
|
140
143
|
.force("center", force.center)
|
|
@@ -145,7 +148,7 @@ const renderOrgCharts = () => {
|
|
|
145
148
|
// ########################### HIERARCHY STUFF #########################
|
|
146
149
|
|
|
147
150
|
// flatten root
|
|
148
|
-
let arr = flatten(
|
|
151
|
+
let arr = flatten(_hierarchy.root)
|
|
149
152
|
|
|
150
153
|
// hide members based on their depth
|
|
151
154
|
arr.forEach((d) => {
|
|
@@ -163,25 +166,25 @@ const renderOrgCharts = () => {
|
|
|
163
166
|
// #################################### DRAWINGS #######################
|
|
164
167
|
|
|
165
168
|
// drawing containers
|
|
166
|
-
let container =
|
|
169
|
+
let container = select(this)
|
|
167
170
|
|
|
168
171
|
// add svg
|
|
169
|
-
let svg =
|
|
172
|
+
let svg = patternify(container, { tag: "svg", selector: "svg-chart-container" })
|
|
170
173
|
.attr("width", attrs.svgWidth)
|
|
171
174
|
.attr("height", attrs.svgHeight)
|
|
172
175
|
// .call(behaviors.zoom)
|
|
173
176
|
|
|
174
177
|
// add container g element
|
|
175
|
-
let chart =
|
|
178
|
+
let chart = patternify(svg, { tag: "g", selector: "chart" })
|
|
176
179
|
.attr("transform", `translate(${calc.chartLeftMargin},${calc.chartTopMargin})`)
|
|
177
180
|
|
|
178
181
|
// ################################ Chart Content Drawing ##################################
|
|
179
182
|
|
|
180
183
|
// link wrapper
|
|
181
|
-
let linksWrapper =
|
|
184
|
+
let linksWrapper = patternify(chart, { tag: "g", selector: "links-wrapper" })
|
|
182
185
|
|
|
183
186
|
// node wrapper
|
|
184
|
-
let nodesWrapper =
|
|
187
|
+
let nodesWrapper = patternify(chart, { tag: "g", selector: "nodes-wrapper" })
|
|
185
188
|
let links, nodes
|
|
186
189
|
|
|
187
190
|
// reusable function which updates visual based on data change
|
|
@@ -194,14 +197,14 @@ const renderOrgCharts = () => {
|
|
|
194
197
|
(clickedNode) ? $btnReset.removeClass("invisible") : $btnReset.addClass("invisible")
|
|
195
198
|
|
|
196
199
|
// set xy and proportion properties with custom radial layout
|
|
197
|
-
layouts.radial(
|
|
200
|
+
layouts.radial(_hierarchy.root)
|
|
198
201
|
|
|
199
202
|
// nodes and links array
|
|
200
|
-
let nodesArr = flatten(
|
|
203
|
+
let nodesArr = flatten(_hierarchy.root, true)
|
|
201
204
|
.orderBy((d) => d.depth)
|
|
202
205
|
.filter((d) => !d.hidden)
|
|
203
206
|
|
|
204
|
-
let linksArr =
|
|
207
|
+
let linksArr = _hierarchy.root.links()
|
|
205
208
|
.filter((d) => !d.source.hidden)
|
|
206
209
|
.filter((d) => !d.target.hidden)
|
|
207
210
|
|
|
@@ -274,7 +277,7 @@ const renderOrgCharts = () => {
|
|
|
274
277
|
.attr("class", "as-text")
|
|
275
278
|
.attr("dx", (d) => d.bbox.x + d.bbox.width + attrs.nodeGutter.x)
|
|
276
279
|
.attr("dy", attrs.childrenIndicatorRadius + 3)
|
|
277
|
-
.text((d) =>
|
|
280
|
+
.text((d) => max([(d.children || {}).length, (d._children || {}).length]))
|
|
278
281
|
|
|
279
282
|
// merge node groups and style it
|
|
280
283
|
nodes = enteredNodes.merge(nodes)
|
|
@@ -291,7 +294,7 @@ const renderOrgCharts = () => {
|
|
|
291
294
|
// zoom handler
|
|
292
295
|
// function zoomed() {
|
|
293
296
|
// // get transform event
|
|
294
|
-
// let transform =
|
|
297
|
+
// let transform = event.transform
|
|
295
298
|
// attrs.lastTransform = transform
|
|
296
299
|
//
|
|
297
300
|
// // apply transform event props to the wrapper
|
|
@@ -330,8 +333,8 @@ const renderOrgCharts = () => {
|
|
|
330
333
|
// handle dragging event
|
|
331
334
|
function dragged(d) {
|
|
332
335
|
// make dragged node fixed
|
|
333
|
-
d.fx =
|
|
334
|
-
d.fy =
|
|
336
|
+
d.fx = event.x
|
|
337
|
+
d.fy = event.y
|
|
335
338
|
}
|
|
336
339
|
|
|
337
340
|
// -------------------- handle drag end event ---------------
|
|
@@ -342,7 +345,7 @@ const renderOrgCharts = () => {
|
|
|
342
345
|
// -------------------------- node mouse hover handler ---------------
|
|
343
346
|
function nodeMouseEnter(d) {
|
|
344
347
|
// get links
|
|
345
|
-
let _links =
|
|
348
|
+
let _links = _hierarchy.root.links()
|
|
346
349
|
|
|
347
350
|
// get hovered node connected links
|
|
348
351
|
let connectedLinks = _links.filter((l) => l.source.id === d.id || l.target.id === d.id)
|
|
@@ -438,7 +441,7 @@ const renderOrgCharts = () => {
|
|
|
438
441
|
// }
|
|
439
442
|
|
|
440
443
|
function freeNodes() {
|
|
441
|
-
|
|
444
|
+
selectAll(".node").each((n) => {
|
|
442
445
|
n.fx = null
|
|
443
446
|
n.fy = null
|
|
444
447
|
})
|
|
@@ -507,18 +510,18 @@ const renderOrgCharts = () => {
|
|
|
507
510
|
}
|
|
508
511
|
|
|
509
512
|
// ----------- PROTOTYEPE FUNCTIONS ----------------------
|
|
510
|
-
|
|
513
|
+
function patternify(node, _params) {
|
|
511
514
|
let selector = _params.selector
|
|
512
515
|
let elementTag = _params.tag
|
|
513
516
|
let _data = _params.data || [selector]
|
|
514
517
|
|
|
515
518
|
// pattern in action
|
|
516
|
-
let
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
519
|
+
let _selection = node.selectAll(`.${selector}`).data(_data)
|
|
520
|
+
_selection.exit().remove()
|
|
521
|
+
_selection = _selection.enter().append(elementTag).merge(_selection)
|
|
522
|
+
_selection.attr("class", selector)
|
|
520
523
|
|
|
521
|
-
return
|
|
524
|
+
return _selection
|
|
522
525
|
}
|
|
523
526
|
|
|
524
527
|
// custom radial layout
|
|
@@ -527,8 +530,8 @@ const renderOrgCharts = () => {
|
|
|
527
530
|
|
|
528
531
|
recurse(root, 0, 1)
|
|
529
532
|
|
|
530
|
-
function recurse(node, min,
|
|
531
|
-
node.proportion = (
|
|
533
|
+
function recurse(node, min, _max) {
|
|
534
|
+
node.proportion = (_max + min) / 2
|
|
532
535
|
if (!node.x) {
|
|
533
536
|
|
|
534
537
|
// if node has parent, match entered node positions to it's parent
|
|
@@ -550,7 +553,7 @@ const renderOrgCharts = () => {
|
|
|
550
553
|
|
|
551
554
|
// recursively do the same for children
|
|
552
555
|
if (node.children) {
|
|
553
|
-
let offset = (
|
|
556
|
+
let offset = (_max - min) / node.children.length
|
|
554
557
|
node.children.forEach(function (child, i) {
|
|
555
558
|
let newMin = min + (offset * i)
|
|
556
559
|
let newMax = newMin + offset
|
|
@@ -624,7 +627,7 @@ const renderOrgCharts = () => {
|
|
|
624
627
|
|
|
625
628
|
// run visual
|
|
626
629
|
main.run = function () {
|
|
627
|
-
|
|
630
|
+
selectAll(attrs.container)
|
|
628
631
|
.call(main)
|
|
629
632
|
return main
|
|
630
633
|
}
|
|
@@ -643,7 +646,7 @@ const renderOrgCharts = () => {
|
|
|
643
646
|
|
|
644
647
|
main.reset = function () {
|
|
645
648
|
|
|
646
|
-
|
|
649
|
+
_hierarchy.root.children.forEach((e) => collapse(e, true))
|
|
647
650
|
main.run()
|
|
648
651
|
|
|
649
652
|
return main
|
|
@@ -659,7 +662,7 @@ const renderOrgCharts = () => {
|
|
|
659
662
|
let width = $container.width()
|
|
660
663
|
let height = width / (16 / 9)
|
|
661
664
|
|
|
662
|
-
|
|
665
|
+
json($container.data("url")).then((data) => {
|
|
663
666
|
// Make a fake previous node if the data entry is not hierarchical
|
|
664
667
|
if (data instanceof Array) {
|
|
665
668
|
fake = true
|
|
@@ -691,5 +694,8 @@ const renderOrgCharts = () => {
|
|
|
691
694
|
}
|
|
692
695
|
|
|
693
696
|
$(() => {
|
|
694
|
-
|
|
697
|
+
renderOrgCharts()
|
|
698
|
+
$(document).on("change.zf.tabs", () => {
|
|
699
|
+
renderOrgCharts()
|
|
700
|
+
});
|
|
695
701
|
})
|
|
@@ -32,6 +32,8 @@ module Decidim
|
|
|
32
32
|
user_can_list_assembly_list?
|
|
33
33
|
user_can_read_current_assembly?
|
|
34
34
|
user_can_create_assembly?
|
|
35
|
+
user_can_export_assembly?
|
|
36
|
+
user_can_copy_assembly?
|
|
35
37
|
user_can_read_assemblies_setting?
|
|
36
38
|
|
|
37
39
|
# org admins and space admins can do everything in the admin section
|
|
@@ -71,6 +73,12 @@ module Decidim
|
|
|
71
73
|
user.admin? || (assembly ? can_manage_assembly?(role: :admin) : has_manageable_assemblies?)
|
|
72
74
|
end
|
|
73
75
|
|
|
76
|
+
# It's an admin assembly when assembly exists and the user is allowed to
|
|
77
|
+
# manage the current assembly.
|
|
78
|
+
def admin_assembly?
|
|
79
|
+
assembly.present? && assembly_admin_allowed_assemblies.include?(assembly)
|
|
80
|
+
end
|
|
81
|
+
|
|
74
82
|
# Checks if it has any manageable assembly, with any possible role.
|
|
75
83
|
def has_manageable_assemblies?(role: :any)
|
|
76
84
|
return unless user
|
|
@@ -88,7 +96,11 @@ module Decidim
|
|
|
88
96
|
# Returns a collection of assemblies where the given user has the
|
|
89
97
|
# specific role privilege.
|
|
90
98
|
def assemblies_with_role_privileges(role)
|
|
91
|
-
|
|
99
|
+
if role == :admin
|
|
100
|
+
assembly_admin_allowed_assemblies
|
|
101
|
+
else
|
|
102
|
+
Decidim::Assemblies::AssembliesWithUserRole.for(user, role)
|
|
103
|
+
end
|
|
92
104
|
end
|
|
93
105
|
|
|
94
106
|
def public_list_assemblies_action?
|
|
@@ -151,12 +163,26 @@ module Decidim
|
|
|
151
163
|
allow! if user.admin? || has_manageable_assemblies?
|
|
152
164
|
end
|
|
153
165
|
|
|
154
|
-
# Only organization admins can create a assembly
|
|
166
|
+
# Only organization admins and assemblies admins can create a assembly
|
|
155
167
|
def user_can_create_assembly?
|
|
156
168
|
return unless permission_action.action == :create &&
|
|
157
169
|
permission_action.subject == :assembly
|
|
158
170
|
|
|
159
|
-
toggle_allow(user.admin?)
|
|
171
|
+
toggle_allow(user.admin? || admin_assembly? || user_role == "admin")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def user_can_export_assembly?
|
|
175
|
+
return unless permission_action.action == :export &&
|
|
176
|
+
permission_action.subject == :assembly
|
|
177
|
+
|
|
178
|
+
toggle_allow(user.admin? || admin_assembly?)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def user_can_copy_assembly?
|
|
182
|
+
return unless permission_action.action == :copy &&
|
|
183
|
+
permission_action.subject == :assembly
|
|
184
|
+
|
|
185
|
+
toggle_allow(user.admin? || admin_assembly?)
|
|
160
186
|
end
|
|
161
187
|
|
|
162
188
|
def user_can_read_assemblies_setting?
|
|
@@ -185,10 +211,9 @@ module Decidim
|
|
|
185
211
|
end
|
|
186
212
|
|
|
187
213
|
def allowed_list_of_assemblies?
|
|
188
|
-
|
|
189
|
-
parent_assemblies = assemblies.flat_map { |assembly| [assembly.id] + assembly.ancestors.pluck(:id) }
|
|
214
|
+
parent_assemblies = assembly_admin_allowed_assemblies.flat_map { |assembly| [assembly.id] + assembly.ancestors.pluck(:id) }
|
|
190
215
|
|
|
191
|
-
allowed_list_of_assemblies = Decidim::Assembly.where(id:
|
|
216
|
+
allowed_list_of_assemblies = Decidim::Assembly.where(id: assembly_admin_allowed_assemblies + parent_assemblies)
|
|
192
217
|
allowed_list_of_assemblies.uniq.member?(assembly)
|
|
193
218
|
end
|
|
194
219
|
|
|
@@ -196,7 +221,7 @@ module Decidim
|
|
|
196
221
|
return unless read_assembly_list_permission_action?
|
|
197
222
|
return if permission_action.subject == :assembly_list
|
|
198
223
|
|
|
199
|
-
toggle_allow(user.admin? || can_manage_assembly?)
|
|
224
|
+
toggle_allow(user.admin? || can_manage_assembly? || admin_assembly?)
|
|
200
225
|
end
|
|
201
226
|
|
|
202
227
|
# A moderator needs to be able to read the assembly they are assigned to,
|
|
@@ -223,13 +248,10 @@ module Decidim
|
|
|
223
248
|
end
|
|
224
249
|
|
|
225
250
|
# Process admins can perform everything *inside* that assembly. They cannot
|
|
226
|
-
#
|
|
227
|
-
# assemblies.
|
|
251
|
+
# perform actions on assembly groups or other assemblies.
|
|
228
252
|
def assembly_admin_action?
|
|
229
253
|
return unless can_manage_assembly?(role: :admin)
|
|
230
254
|
return if user.admin?
|
|
231
|
-
return disallow! if permission_action.action == :create &&
|
|
232
|
-
permission_action.subject == :assembly
|
|
233
255
|
|
|
234
256
|
is_allowed = [
|
|
235
257
|
:attachment,
|
|
@@ -279,6 +301,18 @@ module Decidim
|
|
|
279
301
|
def assembly
|
|
280
302
|
@assembly ||= context.fetch(:current_participatory_space, nil) || context.fetch(:assembly, nil)
|
|
281
303
|
end
|
|
304
|
+
|
|
305
|
+
def user_role
|
|
306
|
+
assembly_user_role = Decidim::AssemblyUserRole.find_by(decidim_user_id: user.id)
|
|
307
|
+
assembly_user_role.present? ? assembly_user_role.role : :any
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def assembly_admin_allowed_assemblies
|
|
311
|
+
assemblies = AssembliesWithUserRole.for(user, :admin)
|
|
312
|
+
child_assemblies = assemblies.flat_map { |assembly| [assembly.id] + assembly.children.pluck(:id) }
|
|
313
|
+
|
|
314
|
+
Decidim::Assembly.where(id: assemblies + child_assemblies)
|
|
315
|
+
end
|
|
282
316
|
end
|
|
283
317
|
end
|
|
284
318
|
end
|
|
@@ -4,9 +4,12 @@ module Decidim
|
|
|
4
4
|
module Assemblies
|
|
5
5
|
# A presenter to render statistics in an Assembly.
|
|
6
6
|
class AssemblyStatsPresenter < Decidim::StatsPresenter
|
|
7
|
-
attribute :assembly, Decidim::Assembly
|
|
8
7
|
include Decidim::IconHelper
|
|
9
8
|
|
|
9
|
+
def assembly
|
|
10
|
+
__getobj__.fetch(:assembly)
|
|
11
|
+
end
|
|
12
|
+
|
|
10
13
|
# Public: returns a collection of stats (Hash) for the Assembly Home.
|
|
11
14
|
def collection
|
|
12
15
|
highlighted_stats = assembly_participants_stats
|
|
@@ -46,11 +46,9 @@ module Decidim
|
|
|
46
46
|
private
|
|
47
47
|
|
|
48
48
|
def user
|
|
49
|
-
@user ||=
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
end
|
|
49
|
+
@user ||= if (user = __getobj__.user.presence)
|
|
50
|
+
Decidim::UserPresenter.new(user)
|
|
51
|
+
end
|
|
54
52
|
end
|
|
55
53
|
end
|
|
56
54
|
end
|
|
@@ -4,7 +4,7 @@ module Decidim
|
|
|
4
4
|
module Assemblies
|
|
5
5
|
module Admin
|
|
6
6
|
# A class used to find the admins for an assembly or an organization assemblies.
|
|
7
|
-
class AdminUsers <
|
|
7
|
+
class AdminUsers < Decidim::Query
|
|
8
8
|
# Syntactic sugar to initialize the class and return the queried objects.
|
|
9
9
|
#
|
|
10
10
|
# assembly - an assembly that needs to find its assembly admins
|
|
@@ -4,7 +4,7 @@ module Decidim
|
|
|
4
4
|
module Assemblies
|
|
5
5
|
module Admin
|
|
6
6
|
# A class used to find the AssemblyMembers's by their status status.
|
|
7
|
-
class AssemblyMembers <
|
|
7
|
+
class AssemblyMembers < Decidim::Query
|
|
8
8
|
# Syntactic sugar to initialize the class and return the queried objects.
|
|
9
9
|
#
|
|
10
10
|
# assembly_members - the initial AssemblyMember relation that needs to be filtered.
|
|
@@ -4,7 +4,7 @@ module Decidim
|
|
|
4
4
|
module Assemblies
|
|
5
5
|
# A class used to find the Assemblies that the given user has
|
|
6
6
|
# the specific role privilege.
|
|
7
|
-
class AssembliesWithUserRole <
|
|
7
|
+
class AssembliesWithUserRole < Decidim::Query
|
|
8
8
|
# Syntactic sugar to initialize the class and return the queried objects.
|
|
9
9
|
#
|
|
10
10
|
# user - a User that needs to find which assemblies can manage
|
|
@@ -4,14 +4,14 @@ module Decidim
|
|
|
4
4
|
module Assemblies
|
|
5
5
|
# This query class filters public assemblies given an organization in a
|
|
6
6
|
# meaningful prioritized order.
|
|
7
|
-
class OrganizationPrioritizedAssemblies <
|
|
7
|
+
class OrganizationPrioritizedAssemblies < Decidim::Query
|
|
8
8
|
def initialize(organization, user = nil)
|
|
9
9
|
@organization = organization
|
|
10
10
|
@user = user
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def query
|
|
14
|
-
|
|
14
|
+
Decidim::Query.merge(
|
|
15
15
|
OrganizationPublishedAssemblies.new(@organization, @user),
|
|
16
16
|
PrioritizedAssemblies.new
|
|
17
17
|
).query
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
module Decidim
|
|
4
4
|
module Assemblies
|
|
5
5
|
# This query class filters published assemblies given an organization.
|
|
6
|
-
class OrganizationPublishedAssemblies <
|
|
6
|
+
class OrganizationPublishedAssemblies < Decidim::Query
|
|
7
7
|
def initialize(organization, user = nil)
|
|
8
8
|
@organization = organization
|
|
9
9
|
@user = user
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def query
|
|
13
|
-
|
|
13
|
+
Decidim::Query.merge(
|
|
14
14
|
OrganizationAssemblies.new(@organization),
|
|
15
15
|
PublishedAssemblies.new,
|
|
16
16
|
VisibleAssemblies.new(@user)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Decidim
|
|
4
4
|
module Assemblies
|
|
5
5
|
# This query filters assemblies that can be assigned as parents for an assembly.
|
|
6
|
-
class ParentAssembliesForSelect <
|
|
6
|
+
class ParentAssembliesForSelect < Decidim::Query
|
|
7
7
|
# Syntactic sugar to initialize the class and return the queried objects.
|
|
8
8
|
def self.for(organization, assembly)
|
|
9
9
|
new(organization, assembly).query
|
|
@@ -4,7 +4,7 @@ module Decidim
|
|
|
4
4
|
module Assemblies
|
|
5
5
|
# This query orders assemblies by importance, prioritizing promoted
|
|
6
6
|
# assemblies.
|
|
7
|
-
class PrioritizedAssemblies <
|
|
7
|
+
class PrioritizedAssemblies < Decidim::Query
|
|
8
8
|
def query
|
|
9
9
|
Decidim::Assembly.order(promoted: :desc)
|
|
10
10
|
end
|
|
@@ -61,9 +61,8 @@ module Decidim
|
|
|
61
61
|
meta_scope: attributes["meta_scope"],
|
|
62
62
|
announcement: attributes["announcement"]
|
|
63
63
|
)
|
|
64
|
-
@imported_assembly.
|
|
65
|
-
@imported_assembly.
|
|
66
|
-
|
|
64
|
+
@imported_assembly.remote_hero_image_url = attributes["remote_hero_image_url"] if remote_file_exists?(attributes["remote_hero_image_url"])
|
|
65
|
+
@imported_assembly.remote_banner_image_url = attributes["remote_banner_image_url"] if remote_file_exists?(attributes["remote_banner_image_url"])
|
|
67
66
|
@imported_assembly.save!
|
|
68
67
|
@imported_assembly
|
|
69
68
|
end
|
|
@@ -108,7 +107,7 @@ module Decidim
|
|
|
108
107
|
attachments["files"].map do |file|
|
|
109
108
|
next unless remote_file_exists?(file["remote_file_url"])
|
|
110
109
|
|
|
111
|
-
file_tmp = URI.
|
|
110
|
+
file_tmp = URI.parse(file["remote_file_url"]).open
|
|
112
111
|
|
|
113
112
|
Decidim.traceability.perform_action!("create", Attachment, @user) do
|
|
114
113
|
attachment = Attachment.new(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div id="assemblies-filter" class="inline-filters">
|
|
2
|
-
<% if available_filters.
|
|
2
|
+
<% if available_filters.present? %>
|
|
3
3
|
<div id="inline-filter-sort" class="dropdown-pane" data-position="bottom" data-alignment="right" data-dropdown data-auto-focus="true">
|
|
4
4
|
<ul class="list-reset">
|
|
5
5
|
<% available_filters.each do |title, id| %>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
</div>
|
|
35
35
|
|
|
36
36
|
<div class="row column">
|
|
37
|
-
<%= form.translated :editor, :description %>
|
|
37
|
+
<%= form.translated :editor, :description, toolbar: :full, lines: 25 %>
|
|
38
38
|
</div>
|
|
39
39
|
|
|
40
40
|
<div class="row column">
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
</div>
|
|
80
80
|
|
|
81
81
|
<div class="row column" id="closing_date_reason_div">
|
|
82
|
-
<%= form.translated :editor, :closing_date_reason
|
|
82
|
+
<%= form.translated :editor, :closing_date_reason %>
|
|
83
83
|
</div>
|
|
84
84
|
</div>
|
|
85
85
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
<% add_decidim_page_title(t("assemblies", scope: "decidim.admin.titles")) %>
|
|
2
1
|
<div class="card with-overflow" id="assemblies">
|
|
3
2
|
<div class="card-divider">
|
|
4
3
|
<h2 class="card-title">
|
|
@@ -83,13 +82,13 @@
|
|
|
83
82
|
<% end %>
|
|
84
83
|
</td>
|
|
85
84
|
<td class="table-list__actions">
|
|
86
|
-
<% if allowed_to? :
|
|
85
|
+
<% if allowed_to? :export, :assembly, assembly: assembly %>
|
|
87
86
|
<%= icon_link_to "data-transfer-download", assembly_export_path(assembly), t("actions.export", scope: "decidim.admin"), method: :post, class: "action-icon--export" %>
|
|
88
87
|
<% else %>
|
|
89
88
|
<span class="action-space icon"></span>
|
|
90
89
|
<% end %>
|
|
91
90
|
|
|
92
|
-
<% if allowed_to? :
|
|
91
|
+
<% if allowed_to? :copy, :assembly, assembly: assembly %>
|
|
93
92
|
<%= icon_link_to "clipboard", new_assembly_copy_path(assembly), t("actions.duplicate", scope: "decidim.admin"), class: "action-icon--copy" %>
|
|
94
93
|
<% else %>
|
|
95
94
|
<span class="action-space icon"></span>
|