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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb +2 -2
  3. data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb +5 -5
  4. data/app/commands/decidim/assemblies/admin/copy_assembly.rb +10 -7
  5. data/app/commands/decidim/assemblies/admin/create_assemblies_type.rb +1 -1
  6. data/app/commands/decidim/assemblies/admin/create_assembly.rb +1 -1
  7. data/app/commands/decidim/assemblies/admin/create_assembly_member.rb +12 -12
  8. data/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb +1 -1
  9. data/app/commands/decidim/assemblies/admin/destroy_assembly_admin.rb +1 -6
  10. data/app/commands/decidim/assemblies/admin/destroy_assembly_member.rb +1 -1
  11. data/app/commands/decidim/assemblies/admin/import_assembly.rb +11 -7
  12. data/app/commands/decidim/assemblies/admin/notify_role_assigned_to_assembly.rb +1 -1
  13. data/app/commands/decidim/assemblies/admin/publish_assembly.rb +1 -1
  14. data/app/commands/decidim/assemblies/admin/unpublish_assembly.rb +1 -1
  15. data/app/commands/decidim/assemblies/admin/update_assemblies_setting.rb +1 -1
  16. data/app/commands/decidim/assemblies/admin/update_assemblies_type.rb +1 -1
  17. data/app/commands/decidim/assemblies/admin/update_assembly.rb +1 -1
  18. data/app/commands/decidim/assemblies/admin/update_assembly_member.rb +11 -11
  19. data/app/controllers/decidim/assemblies/admin/assemblies_types_controller.rb +1 -1
  20. data/app/controllers/decidim/assemblies/admin/assembly_copies_controller.rb +1 -1
  21. data/app/controllers/decidim/assemblies/admin/assembly_imports_controller.rb +1 -1
  22. data/app/controllers/decidim/assemblies/admin/assembly_members_controller.rb +1 -1
  23. data/app/controllers/decidim/assemblies/admin/reminders_controller.rb +14 -0
  24. data/app/controllers/decidim/assemblies/assemblies_controller.rb +6 -6
  25. data/app/events/decidim/role_assigned_to_assembly_event.rb +1 -1
  26. data/app/forms/decidim/assemblies/admin/assembly_import_form.rb +5 -6
  27. data/app/helpers/decidim/assemblies/filter_assemblies_helper.rb +10 -6
  28. data/app/models/decidim/assembly.rb +10 -4
  29. data/app/packs/src/decidim/assemblies/orgchart.js +52 -46
  30. data/app/permissions/decidim/assemblies/permissions.rb +45 -11
  31. data/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb +1 -1
  32. data/app/presenters/decidim/assemblies/assembly_stats_presenter.rb +4 -1
  33. data/app/presenters/decidim/assembly_member_presenter.rb +3 -5
  34. data/app/queries/decidim/assemblies/admin/admin_users.rb +1 -1
  35. data/app/queries/decidim/assemblies/admin/assembly_members.rb +1 -1
  36. data/app/queries/decidim/assemblies/assemblies_with_user_role.rb +1 -1
  37. data/app/queries/decidim/assemblies/filtered_assemblies.rb +1 -1
  38. data/app/queries/decidim/assemblies/organization_assemblies.rb +1 -1
  39. data/app/queries/decidim/assemblies/organization_prioritized_assemblies.rb +2 -2
  40. data/app/queries/decidim/assemblies/organization_published_assemblies.rb +2 -2
  41. data/app/queries/decidim/assemblies/parent_assemblies.rb +1 -1
  42. data/app/queries/decidim/assemblies/parent_assemblies_for_select.rb +1 -1
  43. data/app/queries/decidim/assemblies/prioritized_assemblies.rb +1 -1
  44. data/app/queries/decidim/assemblies/promoted_assemblies.rb +1 -1
  45. data/app/queries/decidim/assemblies/published_assemblies.rb +1 -1
  46. data/app/queries/decidim/assemblies/visible_assemblies.rb +1 -1
  47. data/app/serializers/decidim/assemblies/assembly_importer.rb +3 -4
  48. data/app/views/decidim/assemblies/_filter_by_type.html.erb +1 -1
  49. data/app/views/decidim/assemblies/admin/assemblies/_form.html.erb +2 -2
  50. data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +2 -3
  51. data/app/views/decidim/assemblies/admin/assemblies/new.html.erb +0 -2
  52. data/app/views/decidim/assemblies/admin/assemblies_settings/edit.html.erb +0 -1
  53. data/app/views/decidim/assemblies/admin/assemblies_types/edit.html.erb +0 -1
  54. data/app/views/decidim/assemblies/admin/assemblies_types/index.html.erb +0 -2
  55. data/app/views/decidim/assemblies/admin/assemblies_types/new.html.erb +0 -1
  56. data/app/views/decidim/assemblies/assemblies/_promoted_assembly.html.erb +1 -1
  57. data/app/views/decidim/assemblies/assemblies/index.html.erb +3 -1
  58. data/app/views/decidim/assemblies/assemblies/show.html.erb +8 -6
  59. data/app/views/layouts/decidim/_assembly_header.html.erb +1 -1
  60. data/app/views/layouts/decidim/admin/assembly.html.erb +0 -1
  61. data/config/locales/am-ET.yml +1 -0
  62. data/config/locales/ar.yml +7 -76
  63. data/config/locales/bg.yml +1 -4
  64. data/config/locales/ca.yml +8 -12
  65. data/config/locales/cs.yml +20 -24
  66. data/config/locales/da.yml +1 -0
  67. data/config/locales/de.yml +9 -13
  68. data/config/locales/el.yml +6 -32
  69. data/config/locales/en.yml +6 -11
  70. data/config/locales/eo.yml +1 -0
  71. data/config/locales/es-MX.yml +8 -12
  72. data/config/locales/es-PY.yml +8 -12
  73. data/config/locales/es.yml +10 -14
  74. data/config/locales/et.yml +1 -0
  75. data/config/locales/eu.yml +27 -33
  76. data/config/locales/fi-plain.yml +9 -13
  77. data/config/locales/fi.yml +11 -15
  78. data/config/locales/fr-CA.yml +9 -13
  79. data/config/locales/fr.yml +14 -18
  80. data/config/locales/ga-IE.yml +1 -0
  81. data/config/locales/gl.yml +6 -8
  82. data/config/locales/hr.yml +1 -0
  83. data/config/locales/hu.yml +8 -57
  84. data/config/locales/id-ID.yml +6 -1
  85. data/config/locales/is-IS.yml +9 -6
  86. data/config/locales/it.yml +8 -11
  87. data/config/locales/ja.yml +6 -10
  88. data/config/locales/ko.yml +1 -0
  89. data/config/locales/lb.yml +6 -8
  90. data/config/locales/lt.yml +1 -466
  91. data/config/locales/lv.yml +4 -1
  92. data/config/locales/mt.yml +1 -0
  93. data/config/locales/nl.yml +23 -31
  94. data/config/locales/no.yml +6 -9
  95. data/config/locales/om-ET.yml +1 -0
  96. data/config/locales/pl.yml +6 -4
  97. data/config/locales/pt-BR.yml +7 -29
  98. data/config/locales/pt.yml +4 -7
  99. data/config/locales/ro-RO.yml +5 -22
  100. data/config/locales/ru.yml +7 -3
  101. data/config/locales/si-LK.yml +1 -0
  102. data/config/locales/sk.yml +1 -17
  103. data/config/locales/sl.yml +5 -15
  104. data/config/locales/so-SO.yml +1 -0
  105. data/config/locales/sr-CS.yml +1 -0
  106. data/config/locales/sv.yml +12 -20
  107. data/config/locales/sw-KE.yml +1 -0
  108. data/config/locales/ti-ER.yml +1 -0
  109. data/config/locales/tr-TR.yml +8 -24
  110. data/config/locales/uk.yml +7 -3
  111. data/config/locales/val-ES.yml +1 -0
  112. data/config/locales/vi.yml +1 -0
  113. data/config/locales/zh-CN.yml +4 -7
  114. data/config/locales/zh-TW.yml +1 -462
  115. data/lib/decidim/assemblies/admin_engine.rb +5 -4
  116. data/lib/decidim/assemblies/participatory_space.rb +9 -9
  117. data/lib/decidim/assemblies/test/factories.rb +0 -4
  118. data/lib/decidim/assemblies/version.rb +1 -1
  119. metadata +13 -48
  120. data/app/services/decidim/assemblies/assembly_search.rb +0 -18
  121. data/config/environment.rb +0 -0
  122. data/config/locales/fa-IR.yml +0 -1
  123. data/config/locales/gn-PY.yml +0 -1
  124. data/config/locales/ka-GE.yml +0 -1
  125. data/config/locales/kaa.yml +0 -60
  126. data/config/locales/lo-LA.yml +0 -1
  127. 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 * as d3 from "d3"
8
- import renderChart from "src/decidim/vizzs/renders"
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 hierarchy = {}
60
+ let _hierarchy = {}
58
61
 
59
62
  // main chart object
60
- let main = function (selection) {
61
- selection.each(function scope() {
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
- hierarchy.root = d3.hierarchy(attrs.data.root)
74
+ _hierarchy.root = hierarchy(attrs.data.root)
72
75
 
73
76
  // ########################### BEHAVIORS #########################
74
77
  let behaviors = {}
75
- // behaviors.zoom = d3.zoom().scaleExtent([0.75, 100, 8]).on("zoom", zoomed)
76
- behaviors.drag = d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended)
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 = d3.forceLink().id((d) => d.id)
87
- force.charge = d3.forceManyBody().strength(-240)
88
- force.center = d3.forceCenter(calc.chartWidth / 2, calc.chartHeight / 2)
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 = d3.forceCollide().radius((d) => {
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 d3.max([attrs.nodeDistance * 3, fakeRadius])
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 = d3.forceX()
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 d3.cluster)
119
- force.y = d3.forceY()
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 = d3.forceSimulation()
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(hierarchy.root)
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 = d3.select(this)
169
+ let container = select(this)
167
170
 
168
171
  // add svg
169
- let svg = container.patternify({ tag: "svg", selector: "svg-chart-container" })
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 = svg.patternify({ tag: "g", selector: "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 = chart.patternify({ tag: "g", selector: "links-wrapper" })
184
+ let linksWrapper = patternify(chart, { tag: "g", selector: "links-wrapper" })
182
185
 
183
186
  // node wrapper
184
- let nodesWrapper = chart.patternify({ tag: "g", selector: "nodes-wrapper" })
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(hierarchy.root)
200
+ layouts.radial(_hierarchy.root)
198
201
 
199
202
  // nodes and links array
200
- let nodesArr = flatten(hierarchy.root, true)
203
+ let nodesArr = flatten(_hierarchy.root, true)
201
204
  .orderBy((d) => d.depth)
202
205
  .filter((d) => !d.hidden)
203
206
 
204
- let linksArr = hierarchy.root.links()
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) => d3.max([(d.children || {}).length, (d._children || {}).length]))
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 = d3.event.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 = d3.event.x
334
- d.fy = d3.event.y
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 = hierarchy.root.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
- d3.selectAll(".node").each((n) => {
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
- d3.selection.prototype.patternify = function (_params) {
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 selection = this.selectAll(`.${selector}`).data(_data)
517
- selection.exit().remove()
518
- selection = selection.enter().append(elementTag).merge(selection)
519
- selection.attr("class", selector)
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 selection
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, max) {
531
- node.proportion = (max + min) / 2
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 = (max - min) / node.children.length
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
- d3.selectAll(attrs.container)
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
- hierarchy.root.children.forEach((e) => collapse(e, true))
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
- d3.json($container.data("url")).then((data) => {
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
- renderChart(renderOrgCharts);
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
- Decidim::Assemblies::AssembliesWithUserRole.for(user, role)
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
- assemblies = AssembliesWithUserRole.for(user)
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: assemblies + parent_assemblies)
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
- # create a assembly or perform actions on assembly groups or other
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
@@ -63,7 +63,7 @@ module Decidim
63
63
 
64
64
  def action_string
65
65
  case action
66
- when "create", "publish", "unpublish", "update"
66
+ when "create", "publish", "unpublish", "update", "duplicate", "export", "import"
67
67
  "decidim.admin_log.assembly.#{action}"
68
68
  else
69
69
  super
@@ -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 ||= begin
50
- if (user = __getobj__.user.presence)
51
- Decidim::UserPresenter.new(user)
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 < Rectify::Query
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 < Rectify::Query
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 < Rectify::Query
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
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module Assemblies
5
5
  # This query filters assemblies by type.
6
- class FilteredAssemblies < Rectify::Query
6
+ class FilteredAssemblies < Decidim::Query
7
7
  def initialize(filter)
8
8
  @filter = filter
9
9
  end
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module Assemblies
5
5
  # This query class filters all assemblies given an organization.
6
- class OrganizationAssemblies < Rectify::Query
6
+ class OrganizationAssemblies < Decidim::Query
7
7
  def initialize(organization)
8
8
  @organization = organization
9
9
  end
@@ -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 < Rectify::Query
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
- Rectify::Query.merge(
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 < Rectify::Query
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
- Rectify::Query.merge(
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 so only parent assemblies are returned.
6
- class ParentAssemblies < Rectify::Query
6
+ class ParentAssemblies < Decidim::Query
7
7
  def query
8
8
  Decidim::Assembly.where(parent: nil)
9
9
  end
@@ -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 < Rectify::Query
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 < Rectify::Query
7
+ class PrioritizedAssemblies < Decidim::Query
8
8
  def query
9
9
  Decidim::Assembly.order(promoted: :desc)
10
10
  end
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module Assemblies
5
5
  # This query filters assemblies so only promoted ones are returned.
6
- class PromotedAssemblies < Rectify::Query
6
+ class PromotedAssemblies < Decidim::Query
7
7
  def query
8
8
  Decidim::Assembly.promoted
9
9
  end
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module Assemblies
5
5
  # This query filters published assemblies only.
6
- class PublishedAssemblies < Rectify::Query
6
+ class PublishedAssemblies < Decidim::Query
7
7
  def query
8
8
  Decidim::Assembly.published
9
9
  end
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module Assemblies
5
5
  # This query class filters assemblies given a current_user.
6
- class VisibleAssemblies < Rectify::Query
6
+ class VisibleAssemblies < Decidim::Query
7
7
  def initialize(user)
8
8
  @user = user
9
9
  end
@@ -61,9 +61,8 @@ module Decidim
61
61
  meta_scope: attributes["meta_scope"],
62
62
  announcement: attributes["announcement"]
63
63
  )
64
- @imported_assembly.attached_uploader(:hero_image).remote_url = attributes["remote_hero_image_url"] if attributes["remote_hero_image_url"].present?
65
- @imported_assembly.attached_uploader(:banner_image).remote_url = attributes["remote_banner_image_url"] if attributes["remote_banner_image_url"].present?
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.open(file["remote_file_url"])
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.any? %>
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, toolbar: :content %>
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? :create, :assembly, assembly: assembly %>
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? :create, :assembly, assembly: assembly %>
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>