decidim-assemblies 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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