decidim-assemblies 0.26.10 → 0.27.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +12 -74
- data/config/locales/bg.yml +1 -4
- data/config/locales/ca.yml +9 -13
- data/config/locales/cs.yml +26 -30
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +20 -24
- data/config/locales/el.yml +13 -32
- data/config/locales/en.yml +6 -11
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +10 -14
- data/config/locales/es-PY.yml +10 -14
- data/config/locales/es.yml +10 -14
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +187 -206
- data/config/locales/fi-plain.yml +11 -15
- data/config/locales/fi.yml +15 -19
- data/config/locales/fr-CA.yml +14 -18
- data/config/locales/fr.yml +22 -26
- data/config/locales/ga-IE.yml +2 -0
- data/config/locales/gl.yml +13 -9
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +14 -56
- data/config/locales/id-ID.yml +12 -4
- data/config/locales/is-IS.yml +15 -9
- data/config/locales/it.yml +15 -11
- data/config/locales/ja.yml +10 -14
- data/config/locales/ko.yml +1 -0
- data/config/locales/lb.yml +12 -11
- data/config/locales/lt.yml +1 -470
- data/config/locales/lv.yml +10 -1
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +30 -31
- data/config/locales/no.yml +13 -9
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +11 -22
- data/config/locales/pt-BR.yml +14 -29
- data/config/locales/pt.yml +11 -7
- data/config/locales/ro-RO.yml +12 -22
- data/config/locales/ru.yml +13 -6
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sk.yml +1 -20
- 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 +18 -20
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +15 -24
- data/config/locales/uk.yml +13 -6
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +11 -7
- data/config/locales/zh-TW.yml +1 -455
- 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 -50
- data/app/services/decidim/assemblies/assembly_search.rb +0 -18
- data/config/environment.rb +0 -3
- 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
- data/config/locales/sq-AL.yml +0 -1
- data/config/locales/th-TH.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>
|