decidim-assemblies 0.26.9 → 0.27.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) 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 +12 -74
  63. data/config/locales/bg.yml +1 -4
  64. data/config/locales/ca.yml +9 -13
  65. data/config/locales/cs.yml +26 -30
  66. data/config/locales/da.yml +1 -0
  67. data/config/locales/de.yml +20 -24
  68. data/config/locales/el.yml +13 -32
  69. data/config/locales/en.yml +6 -11
  70. data/config/locales/eo.yml +1 -0
  71. data/config/locales/es-MX.yml +10 -14
  72. data/config/locales/es-PY.yml +10 -14
  73. data/config/locales/es.yml +10 -14
  74. data/config/locales/et.yml +1 -0
  75. data/config/locales/eu.yml +187 -206
  76. data/config/locales/fi-plain.yml +11 -15
  77. data/config/locales/fi.yml +15 -19
  78. data/config/locales/fr-CA.yml +14 -18
  79. data/config/locales/fr.yml +22 -26
  80. data/config/locales/ga-IE.yml +2 -0
  81. data/config/locales/gl.yml +13 -9
  82. data/config/locales/hr.yml +1 -0
  83. data/config/locales/hu.yml +14 -56
  84. data/config/locales/id-ID.yml +12 -4
  85. data/config/locales/is-IS.yml +15 -9
  86. data/config/locales/it.yml +15 -11
  87. data/config/locales/ja.yml +10 -14
  88. data/config/locales/ko.yml +1 -0
  89. data/config/locales/lb.yml +12 -11
  90. data/config/locales/lt.yml +1 -470
  91. data/config/locales/lv.yml +10 -1
  92. data/config/locales/mt.yml +1 -0
  93. data/config/locales/nl.yml +30 -31
  94. data/config/locales/no.yml +13 -9
  95. data/config/locales/om-ET.yml +1 -0
  96. data/config/locales/pl.yml +11 -22
  97. data/config/locales/pt-BR.yml +14 -29
  98. data/config/locales/pt.yml +11 -7
  99. data/config/locales/ro-RO.yml +12 -22
  100. data/config/locales/ru.yml +13 -6
  101. data/config/locales/si-LK.yml +1 -0
  102. data/config/locales/sk.yml +1 -20
  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 +18 -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 +15 -24
  110. data/config/locales/uk.yml +13 -6
  111. data/config/locales/val-ES.yml +1 -0
  112. data/config/locales/vi.yml +1 -0
  113. data/config/locales/zh-CN.yml +11 -7
  114. data/config/locales/zh-TW.yml +1 -455
  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 -50
  120. data/app/services/decidim/assemblies/assembly_search.rb +0 -18
  121. data/config/environment.rb +0 -3
  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
  128. data/config/locales/sq-AL.yml +0 -1
  129. 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 * 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>