decidim-assemblies 0.6.0

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 (86) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +34 -0
  3. data/Rakefile +3 -0
  4. data/app/assets/config/admin/decidim_assemblies_manifest.js +1 -0
  5. data/app/assets/config/decidim_assemblies_manifest.js +1 -0
  6. data/app/assets/images/decidim/assemblies/assembly.svg +6 -0
  7. data/app/assets/javascripts/decidim/assemblies/admin/assemblies.js.es6 +12 -0
  8. data/app/commands/decidim/assemblies/admin/copy_assembly.rb +88 -0
  9. data/app/commands/decidim/assemblies/admin/create_assembly.rb +68 -0
  10. data/app/commands/decidim/assemblies/admin/publish_assembly.rb +34 -0
  11. data/app/commands/decidim/assemblies/admin/unpublish_assembly.rb +34 -0
  12. data/app/commands/decidim/assemblies/admin/update_assembly.rb +73 -0
  13. data/app/constraints/decidim/assemblies/current_assembly.rb +37 -0
  14. data/app/constraints/decidim/assemblies/current_feature.rb +28 -0
  15. data/app/controllers/concerns/decidim/assemblies/admin/assembly_context.rb +21 -0
  16. data/app/controllers/concerns/decidim/assemblies/assembly_context.rb +25 -0
  17. data/app/controllers/concerns/decidim/assemblies/needs_assembly.rb +50 -0
  18. data/app/controllers/decidim/assemblies/admin/application_controller.rb +11 -0
  19. data/app/controllers/decidim/assemblies/admin/assemblies_controller.rb +100 -0
  20. data/app/controllers/decidim/assemblies/admin/assembly_attachments_controller.rb +27 -0
  21. data/app/controllers/decidim/assemblies/admin/assembly_copies_controller.rb +35 -0
  22. data/app/controllers/decidim/assemblies/admin/assembly_publications_controller.rb +45 -0
  23. data/app/controllers/decidim/assemblies/admin/categories_controller.rb +13 -0
  24. data/app/controllers/decidim/assemblies/admin/concerns/assembly_admin.rb +26 -0
  25. data/app/controllers/decidim/assemblies/admin/exports_controller.rb +14 -0
  26. data/app/controllers/decidim/assemblies/admin/feature_permissions_controller.rb +14 -0
  27. data/app/controllers/decidim/assemblies/admin/features_controller.rb +14 -0
  28. data/app/controllers/decidim/assemblies/admin/moderations_controller.rb +12 -0
  29. data/app/controllers/decidim/assemblies/assemblies_controller.rb +43 -0
  30. data/app/controllers/decidim/assemblies/assembly_widgets_controller.rb +21 -0
  31. data/app/controllers/decidim/assemblies/categories_controller.rb +13 -0
  32. data/app/forms/decidim/assemblies/admin/assembly_copy_form.rb +34 -0
  33. data/app/forms/decidim/assemblies/admin/assembly_form.rb +63 -0
  34. data/app/models/decidim/assemblies/abilities/admin/admin_ability.rb +18 -0
  35. data/app/models/decidim/assemblies/abilities/admin_ability.rb +16 -0
  36. data/app/models/decidim/assemblies/abilities/everyone_ability.rb +17 -0
  37. data/app/models/decidim/assembly.rb +45 -0
  38. data/app/presenters/decidim/assemblies/assembly_stats_presenter.rb +52 -0
  39. data/app/queries/decidim/assemblies/admin/admin_users.rb +39 -0
  40. data/app/queries/decidim/assemblies/organization_assemblies.rb +16 -0
  41. data/app/queries/decidim/assemblies/organization_prioritized_assemblies.rb +20 -0
  42. data/app/queries/decidim/assemblies/organization_published_assemblies.rb +19 -0
  43. data/app/queries/decidim/assemblies/prioritized_assemblies.rb +13 -0
  44. data/app/queries/decidim/assemblies/promoted_assemblies.rb +12 -0
  45. data/app/queries/decidim/assemblies/published_assemblies.rb +12 -0
  46. data/app/views/decidim/assemblies/_assembly.html.erb +22 -0
  47. data/app/views/decidim/assemblies/_order_by_assemblies.html.erb +3 -0
  48. data/app/views/decidim/assemblies/admin/assemblies/_form.html.erb +89 -0
  49. data/app/views/decidim/assemblies/admin/assemblies/edit.html.erb +19 -0
  50. data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +66 -0
  51. data/app/views/decidim/assemblies/admin/assemblies/new.html.erb +11 -0
  52. data/app/views/decidim/assemblies/admin/assembly_copies/_form.html.erb +34 -0
  53. data/app/views/decidim/assemblies/admin/assembly_copies/new.html.erb +7 -0
  54. data/app/views/decidim/assemblies/assemblies/_no_assemblies_yet.html.erb +3 -0
  55. data/app/views/decidim/assemblies/assemblies/_promoted_assembly.html.erb +27 -0
  56. data/app/views/decidim/assemblies/assemblies/_statistics.html.erb +10 -0
  57. data/app/views/decidim/assemblies/assemblies/index.html.erb +17 -0
  58. data/app/views/decidim/assemblies/assemblies/show.html.erb +74 -0
  59. data/app/views/decidim/assemblies/assembly_widgets/show.html.erb +11 -0
  60. data/app/views/layouts/decidim/_assembly_header.html.erb +64 -0
  61. data/app/views/layouts/decidim/admin/assemblies.html.erb +14 -0
  62. data/app/views/layouts/decidim/admin/assembly.html.erb +54 -0
  63. data/app/views/layouts/decidim/assembly.html.erb +30 -0
  64. data/config/locales/ca.yml +128 -0
  65. data/config/locales/en.yml +128 -0
  66. data/config/locales/es.yml +128 -0
  67. data/config/locales/eu.yml +127 -0
  68. data/config/locales/fi.yml +127 -0
  69. data/config/locales/fr.yml +127 -0
  70. data/config/locales/it.yml +127 -0
  71. data/config/locales/nl.yml +127 -0
  72. data/config/locales/pl.yml +128 -0
  73. data/config/locales/uk.yml +129 -0
  74. data/db/migrate/20170727190859_add_assemblies.rb +37 -0
  75. data/db/migrate/20170822153055_add_scopes_enabled_to_assemblies.rb +7 -0
  76. data/db/seeds/Exampledocument.pdf +0 -0
  77. data/db/seeds/city.jpeg +0 -0
  78. data/db/seeds/city2.jpeg +0 -0
  79. data/db/seeds/homepage_image.jpg +0 -0
  80. data/lib/decidim/assemblies.rb +12 -0
  81. data/lib/decidim/assemblies/admin.rb +10 -0
  82. data/lib/decidim/assemblies/admin_engine.rb +79 -0
  83. data/lib/decidim/assemblies/engine.rb +53 -0
  84. data/lib/decidim/assemblies/participatory_space.rb +69 -0
  85. data/lib/decidim/assemblies/test/factories.rb +41 -0
  86. metadata +188 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 591047129445508418be028edb2f2504ed403d6a
4
+ data.tar.gz: 75821f7bde3542f291179dd1faaa37e617bb6822
5
+ SHA512:
6
+ metadata.gz: a1ba81ca9013d9c3fee4c2d344a655a9747f26fad14f65d1a220360d57c73f889e0edd76da7b1fd32038aa8ff1e908de23bcb5827f4be0f46d97ec019eb1ea71
7
+ data.tar.gz: 6eca23d69ffc25424fc679a1942c2dc4f26f000792c10e59e3b7abc0926f89c21e4e7048946582f40d51bb03dde8a7a405ca2fdb2ded2660d089301b0a02f0be
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Decidim::Assemblies
2
+
3
+ Assemblies are the permanent Decidim's participatory space. They are always
4
+ "active" so unlike participatory processes, they have no steps or phases.
5
+
6
+ A assembly can get different features (such as meetings or proposals) attached.
7
+ It can also have attachments, be associated to custom categories or scopes, and
8
+ can be fully managed via an administration UI.
9
+
10
+ ## Usage
11
+
12
+ This plugin provides:
13
+
14
+ * A CRUD engine to manage assemblies.
15
+
16
+ * Public views for assembly via a high level section in the main menu.
17
+
18
+ ## Installation
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem 'decidim-assemblies'
23
+ ```
24
+
25
+ And then execute:
26
+ ```bash
27
+ $ bundle
28
+ ```
29
+
30
+ ## Contributing
31
+ See [Decidim](https://github.com/decidim/decidim).
32
+
33
+ ## License
34
+ See [Decidim](https://github.com/decidim/decidim).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
@@ -0,0 +1 @@
1
+ //= link decidim/assemblies/admin/assemblies.js
@@ -0,0 +1 @@
1
+ //= link_directory ../images/decidim/assemblies
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36.02 36.02">
2
+ <path d="M883.8,543.84a18,18,0,1,1,18-18A18,18,0,0,1,883.8,543.84Zm0-34a16,16,0,1,0,16,16A16,16,0,0,0,883.8,509.83Z" transform="translate(-865.8 -507.83)" />
3
+ <ellipse ry="5.504777" rx="5.5598245" cy="17.971844" cx="18" />
4
+ <path d="M883.8,543.84a18,18,0,1,1,18-18A18,18,0,0,1,883.8,543.84Zm0-34a16,16,0,1,0,16,16A16,16,0,0,0,883.8,509.83Z" transform="translate(-865.8 -507.83)" />
5
+ <path d="m 6.3078227,-25.154474 a 9.3338938,9.0435648 0 0 1 -8.7369752,9.025052 9.3338938,9.0435648 0 0 1 -9.8544645,-7.870717 9.3338938,9.0435648 0 0 1 7.4765554,-10.031744" transform="matrix(-0.78352169,0.62136443,-0.62136443,-0.78352169,0,0)" class="stroked-shape" />
6
+ </svg>
@@ -0,0 +1,12 @@
1
+ $(() => {
2
+ const $assemblyScopeEnabled = $('#assembly_scopes_enabled');
3
+ const $assemblyScopeId = $("#assembly_scope_id");
4
+
5
+ if ($('.edit_assembly, .new_assembly').length > 0) {
6
+ $assemblyScopeEnabled.on('change', (event) => {
7
+ const checked = event.target.checked;
8
+ $assemblyScopeId.attr("disabled", !checked);
9
+ })
10
+ $assemblyScopeId.attr("disabled", !$assemblyScopeEnabled.prop('checked'));
11
+ }
12
+ });
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command with all the business logic when copying a new participatory
7
+ # assembly in the system.
8
+ class CopyAssembly < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # form - A form object with the params.
12
+ # assembly - An assembly we want to duplicate
13
+ def initialize(form, assembly)
14
+ @form = form
15
+ @assembly = assembly
16
+ end
17
+
18
+ # Executes the command. Broadcasts these events:
19
+ #
20
+ # - :ok when everything is valid.
21
+ # - :invalid if the form wasn't valid and we couldn't proceed.
22
+ #
23
+ # Returns nothing.
24
+ def call
25
+ return broadcast(:invalid) if form.invalid?
26
+
27
+ Assembly.transaction do
28
+ copy_assembly
29
+ copy_assembly_categories if @form.copy_categories?
30
+ copy_assembly_features if @form.copy_features?
31
+ end
32
+
33
+ broadcast(:ok, @copied_assembly)
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :form
39
+
40
+ def copy_assembly
41
+ @copied_assembly = Assembly.create!(
42
+ organization: @assembly.organization,
43
+ title: form.title,
44
+ subtitle: @assembly.subtitle,
45
+ slug: form.slug,
46
+ hashtag: @assembly.hashtag,
47
+ description: @assembly.description,
48
+ short_description: @assembly.short_description,
49
+ hero_image: @assembly.hero_image,
50
+ banner_image: @assembly.banner_image,
51
+ promoted: @assembly.promoted,
52
+ scope: @assembly.scope,
53
+ developer_group: @assembly.developer_group,
54
+ local_area: @assembly.local_area,
55
+ target: @assembly.target,
56
+ participatory_scope: @assembly.participatory_scope,
57
+ participatory_structure: @assembly.participatory_structure,
58
+ meta_scope: @assembly.meta_scope
59
+ )
60
+ end
61
+
62
+ def copy_assembly_categories
63
+ @assembly.categories.each do |category|
64
+ Category.create!(
65
+ name: category.name,
66
+ description: category.description,
67
+ parent_id: category.parent_id,
68
+ participatory_space: @copied_assembly
69
+ )
70
+ end
71
+ end
72
+
73
+ def copy_assembly_features
74
+ @assembly.features.each do |feature|
75
+ new_feature = Feature.create!(
76
+ manifest_name: feature.manifest_name,
77
+ name: feature.name,
78
+ participatory_space: @copied_assembly,
79
+ settings: feature.settings,
80
+ step_settings: feature.step_settings
81
+ )
82
+ feature.manifest.run_hooks(:copy, new_feature: new_feature, old_feature: feature)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command with all the business logic when creating a new participatory
7
+ # assembly in the system.
8
+ class CreateAssembly < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # form - A form object with the params.
12
+ def initialize(form)
13
+ @form = form
14
+ end
15
+
16
+ # Executes the command. Broadcasts these events:
17
+ #
18
+ # - :ok when everything is valid.
19
+ # - :invalid if the form wasn't valid and we couldn't proceed.
20
+ #
21
+ # Returns nothing.
22
+ def call
23
+ return broadcast(:invalid) if form.invalid?
24
+ assembly = create_assembly
25
+
26
+ if assembly.persisted?
27
+ broadcast(:ok, assembly)
28
+ else
29
+ form.errors.add(:hero_image, assembly.errors[:hero_image]) if assembly.errors.include? :hero_image
30
+ form.errors.add(:banner_image, assembly.errors[:banner_image]) if assembly.errors.include? :banner_image
31
+ broadcast(:invalid)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :form
38
+
39
+ def create_assembly
40
+ assembly = Assembly.new(
41
+ organization: form.current_organization,
42
+ title: form.title,
43
+ subtitle: form.subtitle,
44
+ slug: form.slug,
45
+ hashtag: form.hashtag,
46
+ description: form.description,
47
+ short_description: form.short_description,
48
+ hero_image: form.hero_image,
49
+ banner_image: form.banner_image,
50
+ promoted: form.promoted,
51
+ scopes_enabled: form.scopes_enabled,
52
+ scope: form.scope,
53
+ developer_group: form.developer_group,
54
+ local_area: form.local_area,
55
+ target: form.target,
56
+ participatory_scope: form.participatory_scope,
57
+ participatory_structure: form.participatory_structure,
58
+ meta_scope: form.meta_scope
59
+ )
60
+
61
+ return assembly unless assembly.valid?
62
+ assembly.save!
63
+ assembly
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command that sets an assembly as published.
7
+ class PublishAssembly < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # assembly - A Assembly that will be published
11
+ def initialize(assembly)
12
+ @assembly = assembly
13
+ end
14
+
15
+ # Executes the command. Broadcasts these events:
16
+ #
17
+ # - :ok when everything is valid.
18
+ # - :invalid if the data wasn't valid and we couldn't proceed.
19
+ #
20
+ # Returns nothing.
21
+ def call
22
+ return broadcast(:invalid) if assembly.nil? || assembly.published?
23
+
24
+ assembly.publish!
25
+ broadcast(:ok)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :assembly
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command that sets an assembly as unpublished.
7
+ class UnpublishAssembly < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # assembly - A Assembly that will be unpublished
11
+ def initialize(assembly)
12
+ @assembly = assembly
13
+ end
14
+
15
+ # Executes the command. Broadcasts these events:
16
+ #
17
+ # - :ok when everything is valid.
18
+ # - :invalid if the data wasn't valid and we couldn't proceed.
19
+ #
20
+ # Returns nothing.
21
+ def call
22
+ return broadcast(:invalid) if assembly.nil? || !assembly.published?
23
+
24
+ assembly.unpublish!
25
+ broadcast(:ok)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :assembly
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command with all the business logic when creating a new participatory
7
+ # assembly in the system.
8
+ class UpdateAssembly < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # assembly - the Assembly to update
12
+ # form - A form object with the params.
13
+ def initialize(assembly, form)
14
+ @assembly = assembly
15
+ @form = form
16
+ end
17
+
18
+ # Executes the command. Broadcasts these events:
19
+ #
20
+ # - :ok when everything is valid.
21
+ # - :invalid if the form wasn't valid and we couldn't proceed.
22
+ #
23
+ # Returns nothing.
24
+ def call
25
+ return broadcast(:invalid) if form.invalid?
26
+ update_assembly
27
+
28
+ if @assembly.valid?
29
+ broadcast(:ok, @assembly)
30
+ else
31
+ form.errors.add(:hero_image, @assembly.errors[:hero_image]) if @assembly.errors.include? :hero_image
32
+ form.errors.add(:banner_image, @assembly.errors[:banner_image]) if @assembly.errors.include? :banner_image
33
+ broadcast(:invalid)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :form, :assembly
40
+
41
+ def update_assembly
42
+ @assembly.assign_attributes(attributes)
43
+ @assembly.save! if @assembly.valid?
44
+ end
45
+
46
+ def attributes
47
+ {
48
+ title: form.title,
49
+ subtitle: form.subtitle,
50
+ slug: form.slug,
51
+ hashtag: form.hashtag,
52
+ hero_image: form.hero_image,
53
+ remove_hero_image: form.remove_hero_image,
54
+ banner_image: form.banner_image,
55
+ remove_banner_image: form.remove_banner_image,
56
+ promoted: form.promoted,
57
+ description: form.description,
58
+ short_description: form.short_description,
59
+ scopes_enabled: form.scopes_enabled,
60
+ scope: form.scope,
61
+ developer_group: form.developer_group,
62
+ local_area: form.local_area,
63
+ target: form.target,
64
+ participatory_scope: form.participatory_scope,
65
+ participatory_structure: form.participatory_structure,
66
+ meta_scope: form.meta_scope,
67
+ show_statistics: form.show_statistics
68
+ }
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ # This class infers the current assembly we're scoped to by
6
+ # looking at the request parameters and the organization in the request
7
+ # environment, and injects it into the environment.
8
+ class CurrentAssembly
9
+ # Public: Matches the request against an assembly and injects it
10
+ # into the environment.
11
+ #
12
+ # request - The request that holds the assembly relevant
13
+ # information.
14
+ #
15
+ # Returns a true if the request matched, false otherwise
16
+ def matches?(request)
17
+ env = request.env
18
+
19
+ @organization = env["decidim.current_organization"]
20
+ return false unless @organization
21
+
22
+ current_assembly(env, request.params) ? true : false
23
+ end
24
+
25
+ private
26
+
27
+ def current_assembly(env, params)
28
+ env["decidim.current_participatory_space"] ||=
29
+ detect_current_assembly(params)
30
+ end
31
+
32
+ def detect_current_assembly(params)
33
+ OrganizationAssemblies.new(@organization).query.find_by_id(params["assembly_id"])
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ # This class infers the current feature on an assembly context
6
+ # request parameters and injects it into the environment.
7
+ class CurrentFeature
8
+ # Public: Initializes the class.
9
+ #
10
+ # manifest - The manifest of the feature to check against.
11
+ def initialize(manifest)
12
+ @manifest = manifest
13
+ end
14
+
15
+ # Public: Matches the request against a feature and injects it into the
16
+ # environment.
17
+ #
18
+ # request - The request that holds the current feature relevant information.
19
+ #
20
+ # Returns a true if the request matches an assembly and a
21
+ # feature belonging to that assembly, false otherwise
22
+ def matches?(request)
23
+ CurrentAssembly.new.matches?(request) &&
24
+ Decidim::CurrentFeature.new(@manifest).matches?(request)
25
+ end
26
+ end
27
+ end
28
+ end