decidim-admin 0.13.1 → 0.14.1

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.

Potentially problematic release.


This version of decidim-admin might be problematic. Click here for more details.

Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/admin/application.js.es6 +3 -0
  3. data/app/assets/javascripts/decidim/admin/bundle.js +5 -5
  4. data/app/assets/javascripts/decidim/admin/bundle.js.map +1 -1
  5. data/app/assets/javascripts/decidim/admin/draggable-list.js.es6 +30 -0
  6. data/app/assets/stylesheets/decidim/admin/components/_autocomplete_select.component.scss +6 -0
  7. data/app/assets/stylesheets/decidim/admin/extra/_action-icon.scss +5 -0
  8. data/app/assets/stylesheets/decidim/admin/extra/_title_bar.scss +4 -0
  9. data/app/assets/stylesheets/decidim/admin/modules/_card-grid.scss +25 -0
  10. data/app/assets/stylesheets/decidim/admin/modules/_draggable-list.scss +27 -0
  11. data/app/assets/stylesheets/decidim/admin/modules/_forms.scss +8 -1
  12. data/app/assets/stylesheets/decidim/admin/modules/_modules.scss +8 -0
  13. data/app/assets/stylesheets/decidim/admin/utils/_mixins.scss +2 -0
  14. data/app/cells/decidim/admin/content_block/show.erb +13 -0
  15. data/app/cells/decidim/admin/content_block_cell.rb +19 -0
  16. data/app/commands/decidim/admin/reorder_content_blocks.rb +97 -0
  17. data/app/commands/decidim/admin/update_component_permissions.rb +31 -11
  18. data/app/commands/decidim/admin/update_content_block.rb +55 -0
  19. data/app/commands/decidim/admin/update_organization_appearance.rb +0 -3
  20. data/app/controllers/decidim/admin/component_permissions_controller.rb +32 -5
  21. data/app/controllers/decidim/admin/components/base_controller.rb +2 -1
  22. data/app/controllers/decidim/admin/concerns/has_attachment_collections.rb +0 -8
  23. data/app/controllers/decidim/admin/concerns/has_private_users.rb +6 -10
  24. data/app/controllers/decidim/admin/impersonations_controller.rb +1 -0
  25. data/app/controllers/decidim/admin/officializations_controller.rb +1 -0
  26. data/app/controllers/decidim/admin/organization_homepage_content_blocks_controller.rb +64 -0
  27. data/app/controllers/decidim/admin/organization_homepage_controller.rb +52 -0
  28. data/app/forms/decidim/admin/content_block_form.rb +24 -0
  29. data/app/forms/decidim/admin/organization_appearance_form.rb +0 -4
  30. data/app/helpers/decidim/admin/resource_permissions_helper.rb +24 -0
  31. data/app/views/decidim/admin/component_permissions/edit.html.erb +8 -3
  32. data/app/views/decidim/admin/components/edit.html.erb +1 -1
  33. data/app/views/decidim/admin/components/new.html.erb +1 -1
  34. data/app/views/decidim/admin/officializations/index.html.erb +3 -2
  35. data/app/views/decidim/admin/organization_appearance/_form.html.erb +0 -10
  36. data/app/views/decidim/admin/organization_homepage/edit.html.erb +43 -0
  37. data/app/views/decidim/admin/organization_homepage_content_blocks/edit.html.erb +13 -0
  38. data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +3 -2
  39. data/app/views/layouts/decidim/admin/newsletters.erb +1 -1
  40. data/app/views/layouts/decidim/admin/settings.html.erb +3 -0
  41. data/config/locales/ca.yml +8 -30
  42. data/config/locales/en.yml +8 -30
  43. data/config/locales/es-PY.yml +8 -30
  44. data/config/locales/es.yml +8 -30
  45. data/config/locales/eu.yml +8 -30
  46. data/config/locales/fi.yml +128 -150
  47. data/config/locales/fr.yml +8 -30
  48. data/config/locales/gl.yml +8 -30
  49. data/config/locales/hu.yml +660 -0
  50. data/config/locales/it.yml +8 -30
  51. data/config/locales/nl.yml +8 -30
  52. data/config/locales/pl.yml +8 -30
  53. data/config/locales/pt-BR.yml +41 -63
  54. data/config/locales/pt.yml +8 -30
  55. data/config/locales/ru.yml +18 -43
  56. data/config/locales/sv.yml +38 -60
  57. data/config/locales/uk.yml +19 -44
  58. data/config/routes.rb +3 -0
  59. data/lib/decidim/admin/engine.rb +8 -0
  60. data/lib/decidim/admin/form_builder.rb +2 -1
  61. data/lib/decidim/admin/test/manage_attachment_collections_examples.rb +1 -1
  62. data/lib/decidim/admin/test/manage_attachments_examples.rb +4 -4
  63. data/lib/decidim/admin/test/manage_component_permissions_examples.rb +192 -0
  64. data/lib/decidim/admin/version.rb +1 -1
  65. metadata +31 -11
@@ -0,0 +1,30 @@
1
+ ((exports) => {
2
+ const { createSortList } = exports.DecidimAdmin;
3
+
4
+ const createSortableList = (lists) => {
5
+ createSortList(lists, {
6
+ handle: "li",
7
+ forcePlaceholderSize: true,
8
+ connectWith: ".js-connect"
9
+ })
10
+ };
11
+
12
+ // Once in DOM
13
+ $(() => {
14
+ const $draggables = $(".draggable-list")
15
+ let draggablesClassNames = []
16
+ $draggables.each((index, elem) => {
17
+ draggablesClassNames = [...draggablesClassNames, `.${elem.className.split(" ").filter((name) => (/js-list.*/).test(name))[0]}`]
18
+ })
19
+
20
+ document.addEventListener("drag", function (event) {
21
+ $draggables.not(event.target.parentElement).addClass("dragging")
22
+ })
23
+
24
+ document.addEventListener("dragend", function() {
25
+ $draggables.removeClass("dragging")
26
+ })
27
+
28
+ createSortableList(draggablesClassNames.join(", "))
29
+ })
30
+ })(window)
@@ -11,3 +11,9 @@
11
11
  }
12
12
  }
13
13
  }
14
+
15
+ .autocomplete-field--results-inline{
16
+ .Select-menu-outer{
17
+ position: relative;
18
+ }
19
+ }
@@ -4,5 +4,10 @@
4
4
  color: rgba($muted, .3);
5
5
  vertical-align: bottom;
6
6
  }
7
+
8
+ &.action-icon--highlighted{
9
+ color: $warning-color;
10
+ vertical-align: bottom;
11
+ }
7
12
  }
8
13
  }
@@ -18,6 +18,10 @@
18
18
  position: initial;
19
19
  }
20
20
 
21
+ .is-dropdown-submenu{
22
+ z-index: 2;
23
+ }
24
+
21
25
  .user-login{
22
26
  vertical-align: middle;
23
27
  position: initial;
@@ -0,0 +1,25 @@
1
+ $card-grid-margin-bottom: map-get($grid-column-gutter, medium);
2
+
3
+ .card-grid{
4
+ display: flex;
5
+ flex-wrap: wrap;
6
+
7
+ &::before{
8
+ width: 0; //fixes a flexbox bug in Safari with the clearfix element
9
+ }
10
+
11
+ .column{
12
+ margin-bottom: $card-grid-margin-bottom;
13
+ }
14
+
15
+ .card{
16
+ margin-bottom: 0;
17
+ display: flex;
18
+ flex-direction: column;
19
+ height: 100%;
20
+ }
21
+
22
+ .card__content{
23
+ flex-grow: 1;
24
+ }
25
+ }
@@ -0,0 +1,27 @@
1
+ .draggable-list{
2
+ margin: 0;
3
+ padding: 0;
4
+ list-style-type: none;
5
+ min-height: ($global-padding * 2) + $global-lineheight;
6
+
7
+ &.dragging{
8
+ border-top: 2px dashed $medium-gray;
9
+ border-bottom: 2px dashed $medium-gray;
10
+ background-color: $body-background;
11
+ }
12
+
13
+ li{
14
+ cursor: move;
15
+ padding: $global-padding / 2 0;
16
+ }
17
+
18
+ .draggable-content{
19
+ @include flex;
20
+ @include flex-align(justify, middle);
21
+
22
+ font-weight: $global-weight-bold;
23
+ border: $border;
24
+ background-color: $light-gray;
25
+ padding: $global-padding / 2 $global-padding;
26
+ }
27
+ }
@@ -63,13 +63,20 @@ textarea{
63
63
  justify-content: center;
64
64
  }
65
65
 
66
- .check-radio{
66
+ .check-radio,
67
+ .check-radio-collection{
67
68
  label{
68
69
  font-weight: normal;
69
70
  display: inline-flex;
70
71
  align-items: center;
71
72
  }
72
73
 
74
+ legend{
75
+ font-weight: 600;
76
+ }
77
+ }
78
+
79
+ .check-radio{
73
80
  input{
74
81
  margin-bottom: 0;
75
82
  }
@@ -18,6 +18,7 @@
18
18
  //Contents
19
19
  @import "callouts";
20
20
  @import "cards";
21
+ @import "card-grid";
21
22
  @import "table-list";
22
23
  @import "action-icon";
23
24
  @import "char-counter";
@@ -26,3 +27,10 @@
26
27
  @import "filters";
27
28
  @import "dropdown";
28
29
  @import "agenda";
30
+ @import "draggable-list";
31
+
32
+ // mentions__container
33
+ @import "decidim/modules/tags";
34
+ @import "decidim/modules/input-tags";
35
+ @import "decidim/modules/input-mentions";
36
+ @import "decidim/modules/input-hashtags";
@@ -36,6 +36,7 @@ $palette: $foundation-palette;
36
36
  }
37
37
 
38
38
  // helpers
39
+ $margin-xs: .5rem;
39
40
  $margin-s: 1rem;
40
41
  $margin-sm: 2rem;
41
42
  $margin-m: 3rem;
@@ -43,6 +44,7 @@ $margin-l: 5rem;
43
44
 
44
45
  $size:(
45
46
  none: 0,
47
+ xs: $margin-xs,
46
48
  s: $margin-s,
47
49
  sm: $margin-sm,
48
50
  m: $margin-m,
@@ -0,0 +1,13 @@
1
+ <li draggable="true" data-content-block-manifest-name="<%= manifest_name %>">
2
+ <div class="draggable-content">
3
+ <%= t(public_name_key) %>
4
+ <div>
5
+ <% if has_settings? %>
6
+ <%= link_to decidim_admin.edit_organization_homepage_content_block_path(manifest_name), class: "mr-s text-muted" do %>
7
+ <%= icon "pencil" %>
8
+ <% end %>
9
+ <% end %>
10
+ <%= icon "menu" %>
11
+ </div>
12
+ </div>
13
+ </li>
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ class ContentBlockCell < Decidim::ViewModel
6
+ include Decidim::IconHelper
7
+
8
+ delegate :public_name_key, :has_settings?, to: :model
9
+
10
+ def manifest_name
11
+ model.try(:manifest_name) || model.name
12
+ end
13
+
14
+ def decidim_admin
15
+ Decidim::Admin::Engine.routes.url_helpers
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A command that reorders a collection of content blocks. It also creates
6
+ # the ones that might be missing.
7
+ class ReorderContentBlocks < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # organization - the Organization where the content blocks reside
11
+ # scope - the scope applied to the content blocks
12
+ # order - an Array holding the order of IDs of published content blocks.
13
+ def initialize(organization, scope, order)
14
+ @organization = organization
15
+ @scope = scope
16
+ @order = order
17
+ end
18
+
19
+ # Executes the command. Broadcasts these events:
20
+ #
21
+ # - :ok when everything is valid.
22
+ # - :invalid if the data wasn't valid and we couldn't proceed.
23
+ #
24
+ # Returns nothing.
25
+ def call
26
+ return broadcast(:invalid) if order.blank?
27
+
28
+ reorder_steps
29
+ broadcast(:ok)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :organization, :scope
35
+
36
+ def reorder_steps
37
+ transaction do
38
+ reset_weights
39
+ collection.reload
40
+ set_new_weights
41
+ unpublish_removed_content_blocks
42
+ publish_appearing_content_blocks
43
+ end
44
+ end
45
+
46
+ def reset_weights
47
+ # rubocop:disable Rails/SkipsModelValidations
48
+ collection.where.not(weight: nil).update_all(weight: nil)
49
+ # rubocop:enable Rails/SkipsModelValidations
50
+ end
51
+
52
+ def set_new_weights
53
+ data = order.each_with_index.inject({}) do |hash, (manifest_name, index)|
54
+ hash.update(manifest_name => index + 1)
55
+ end
56
+
57
+ data.each do |manifest_name, weight|
58
+ content_block = collection.find { |block| block.manifest_name == manifest_name }
59
+ if content_block.present?
60
+ content_block.update!(weight: weight)
61
+ else
62
+ create_content_block(manifest_name, weight)
63
+ end
64
+ end
65
+ end
66
+
67
+ # rubocop:disable Rails/SkipsModelValidations
68
+ def unpublish_removed_content_blocks
69
+ collection.where(weight: nil).update_all(published_at: nil)
70
+ end
71
+
72
+ def publish_appearing_content_blocks
73
+ collection.where(published_at: nil).where.not(weight: nil).update_all(published_at: Time.current)
74
+ end
75
+ # rubocop:enable Rails/SkipsModelValidations
76
+
77
+ def create_content_block(manifest_name, weight)
78
+ Decidim::ContentBlock.create!(
79
+ organization: organization,
80
+ scope: scope,
81
+ weight: weight,
82
+ manifest_name: manifest_name
83
+ )
84
+ end
85
+
86
+ def order
87
+ return nil unless @order.is_a?(Array) && @order.present?
88
+
89
+ @order
90
+ end
91
+
92
+ def collection
93
+ @collection ||= Decidim::ContentBlock.for_scope(scope, organization: organization)
94
+ end
95
+ end
96
+ end
97
+ end
@@ -5,22 +5,22 @@ module Decidim
5
5
  # This command gets called when permissions for a component are updated
6
6
  # in the admin panel.
7
7
  class UpdateComponentPermissions < Rectify::Command
8
- attr_reader :form, :component
9
-
10
8
  # Public: Initializes the command.
11
9
  #
12
10
  # form - The form from which the data in this component comes from.
13
11
  # component - The component to update.
14
- def initialize(form, component)
12
+ # resource - The resource to update.
13
+ def initialize(form, component, resource)
15
14
  @form = form
16
15
  @component = component
16
+ @resource = resource
17
17
  end
18
18
 
19
19
  # Public: Sets the permissions for a component.
20
20
  #
21
21
  # Broadcasts :ok if created, :invalid otherwise.
22
22
  def call
23
- return broadcast(:invalid) unless @form.valid?
23
+ return broadcast(:invalid) unless form.valid?
24
24
 
25
25
  transaction do
26
26
  update_permissions
@@ -32,9 +32,11 @@ module Decidim
32
32
 
33
33
  private
34
34
 
35
+ attr_reader :form, :component, :resource
36
+
35
37
  def configured_permissions
36
- @form.permissions.select do |_action, permission|
37
- permission.authorization_handler_name.present?
38
+ form.permissions.select do |action, permission|
39
+ permission.authorization_handler_name.present? || overriding_component_permissions?(action)
38
40
  end
39
41
  end
40
42
 
@@ -45,16 +47,34 @@ module Decidim
45
47
  "options" => value.options
46
48
  }
47
49
 
48
- result.update(key => serialized)
50
+ result.update(key => value.authorization_handler_name.present? ? serialized : {})
49
51
  end
50
52
 
51
- @component.update!(
52
- permissions: permissions
53
- )
53
+ if resource
54
+ resource_permissions.update!(permissions: different_from_component_permissions(permissions))
55
+ else
56
+ component.update!(permissions: permissions)
57
+ end
54
58
  end
55
59
 
56
60
  def run_hooks
57
- @component.manifest.run_hooks(:permission_update, @component)
61
+ component.manifest.run_hooks(:permission_update, component: component, resource: resource)
62
+ end
63
+
64
+ def resource_permissions
65
+ @resource_permissions ||= resource.resource_permission || resource.build_resource_permission
66
+ end
67
+
68
+ def different_from_component_permissions(permissions)
69
+ return permissions unless component.permissions
70
+
71
+ permissions.deep_stringify_keys.reject do |action, config|
72
+ HashDiff.diff(config, component.permissions[action]).empty?
73
+ end
74
+ end
75
+
76
+ def overriding_component_permissions?(action)
77
+ resource && component&.permissions&.fetch(action, nil)
58
78
  end
59
79
  end
60
80
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # This command gets called when a content block is updated from the admin
6
+ # panel.
7
+ class UpdateContentBlock < Rectify::Command
8
+ attr_reader :form, :content_block, :scope
9
+
10
+ # Public: Initializes the command.
11
+ #
12
+ # form - The form from which the data in this component comes from.
13
+ # component - The component to update.
14
+ # scope - the scope where the content block belongs to.
15
+ def initialize(form, content_block, scope)
16
+ @form = form
17
+ @content_block = content_block
18
+ @scope = scope
19
+ end
20
+
21
+ # Public: Updates the content block settings and its attachments.
22
+ #
23
+ # Broadcasts :ok if created, :invalid otherwise.
24
+ def call
25
+ return broadcast(:invalid) if form.invalid?
26
+
27
+ transaction do
28
+ update_content_block_settings
29
+ update_content_block_images
30
+ content_block.save!
31
+ end
32
+
33
+ broadcast(:ok)
34
+ end
35
+
36
+ private
37
+
38
+ def update_content_block_settings
39
+ content_block.settings = form.settings
40
+ end
41
+
42
+ def update_content_block_images
43
+ content_block.manifest.images.each do |image_config|
44
+ image_name = image_config[:name]
45
+
46
+ if form.images["remove_#{image_name}".to_sym]
47
+ content_block.images_container.send("remove_#{image_name}=", true)
48
+ elsif form.images[image_name]
49
+ content_block.images_container.send("#{image_name}=", form.images[image_name])
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -59,9 +59,6 @@ module Decidim
59
59
  cta_button_path: form.cta_button_path,
60
60
  cta_button_text: form.cta_button_text,
61
61
  description: form.description,
62
- welcome_text: form.welcome_text,
63
- homepage_image: form.homepage_image,
64
- remove_homepage_image: form.remove_homepage_image,
65
62
  logo: form.logo,
66
63
  remove_logo: form.remove_logo,
67
64
  favicon: form.favicon,
@@ -5,7 +5,11 @@ module Decidim
5
5
  # Controller that allows managing component permissions.
6
6
  #
7
7
  class ComponentPermissionsController < Decidim::Admin::ApplicationController
8
- helper_method :authorizations, :other_authorizations_for, :component
8
+ include Decidim::ComponentPathHelper
9
+
10
+ helper Decidim::ResourceHelper
11
+
12
+ helper_method :authorizations, :other_authorizations_for, :component, :resource_params, :resource
9
13
 
10
14
  def edit
11
15
  enforce_permission_to :update, :component, component: component
@@ -18,10 +22,10 @@ module Decidim
18
22
  enforce_permission_to :update, :component, component: component
19
23
  @permissions_form = PermissionsForm.from_params(params)
20
24
 
21
- UpdateComponentPermissions.call(@permissions_form, component) do
25
+ UpdateComponentPermissions.call(@permissions_form, component, resource) do
22
26
  on(:ok) do
23
27
  flash[:notice] = t("component_permissions.update.success", scope: "decidim.admin")
24
- redirect_to components_path(current_participatory_space)
28
+ redirect_to return_path
25
29
  end
26
30
 
27
31
  on(:invalid) do
@@ -32,8 +36,20 @@ module Decidim
32
36
 
33
37
  private
34
38
 
39
+ def return_path
40
+ if resource
41
+ manage_component_path(component)
42
+ else
43
+ components_path(current_participatory_space)
44
+ end
45
+ end
46
+
47
+ def resource_params
48
+ params.permit(:resource_id, :resource_name).to_h.symbolize_keys
49
+ end
50
+
35
51
  def permission_forms
36
- component.manifest.actions.inject({}) do |result, action|
52
+ actions.inject({}) do |result, action|
37
53
  form = PermissionForm.new(
38
54
  authorization_handler_name: authorization_for(action),
39
55
  options: permissions.dig(action, "options")
@@ -43,6 +59,10 @@ module Decidim
43
59
  end
44
60
  end
45
61
 
62
+ def actions
63
+ @actions ||= (resource&.resource_manifest || component.manifest).actions
64
+ end
65
+
46
66
  def authorizations
47
67
  Verifications::Adapter.from_collection(
48
68
  current_organization.available_authorizations
@@ -55,12 +75,19 @@ module Decidim
55
75
  )
56
76
  end
57
77
 
78
+ def resource
79
+ @resource ||= if params[:resource_id] && params[:resource_name]
80
+ res = Decidim.find_resource_manifest(params[:resource_name])&.resource_scope(component)&.find_by(id: params[:resource_id])
81
+ res if res&.allow_resource_permissions?
82
+ end
83
+ end
84
+
58
85
  def component
59
86
  @component ||= current_participatory_space.components.find(params[:component_id])
60
87
  end
61
88
 
62
89
  def permissions
63
- @permissions ||= component.permissions || {}
90
+ @permissions ||= (component.permissions || {}).merge(resource&.permissions || {})
64
91
  end
65
92
 
66
93
  def authorization_for(action)
@@ -15,6 +15,7 @@ module Decidim
15
15
  helper Decidim::ResourceHelper
16
16
  helper Decidim::Admin::ExportsHelper
17
17
  helper Decidim::Admin::BulkActionsHelper
18
+ helper Decidim::Admin::ResourcePermissionsHelper
18
19
 
19
20
  helper_method :current_component,
20
21
  :current_participatory_space,
@@ -53,7 +54,7 @@ module Decidim
53
54
  end
54
55
 
55
56
  def parent_path
56
- @parent_path ||= EngineRouter.admin_proxy(current_participatory_space).components_path
57
+ @parent_path ||= ::Decidim::EngineRouter.admin_proxy(current_participatory_space).components_path
57
58
  end
58
59
  end
59
60
  end
@@ -100,14 +100,6 @@ module Decidim
100
100
  raise NotImplementedError
101
101
  end
102
102
 
103
- # Public: The Class or Object to be used with the authorization layer to
104
- # verify the user can manage the attachment collection
105
- #
106
- # By default is the same as the collection_for.
107
- def authorization_object
108
- collection_for
109
- end
110
-
111
103
  def collection
112
104
  @collection ||= collection_for.attachment_collections
113
105
  end
@@ -13,7 +13,8 @@ module Decidim
13
13
  extend ActiveSupport::Concern
14
14
 
15
15
  included do
16
- helper_method :privatable_to, :authorization_object, :collection
16
+ helper PaginateHelper
17
+ helper_method :privatable_to, :collection
17
18
 
18
19
  def index
19
20
  enforce_permission_to :read, :space_private_user
@@ -84,16 +85,11 @@ module Decidim
84
85
  raise NotImplementedError
85
86
  end
86
87
 
87
- # Public: The Class or Object to be used with the authorization layer to
88
- # verify the user can manage the private users
89
- #
90
- # By default is the same as the privatable_to.
91
- def authorization_object
92
- privatable_to
93
- end
94
-
95
88
  def collection
96
- @collection ||= privatable_to.participatory_space_private_users
89
+ @collection ||= privatable_to
90
+ .participatory_space_private_users
91
+ .page(params[:page])
92
+ .per(20)
97
93
  end
98
94
  end
99
95
  end
@@ -80,6 +80,7 @@ module Decidim
80
80
  managed: true,
81
81
  name: params.dig(:impersonate_user, :name)
82
82
  ) do |u|
83
+ u.nickname = User.nicknamize(u.name, organization: current_organization)
83
84
  u.admin = false
84
85
  u.tos_agreement = true
85
86
  end
@@ -8,6 +8,7 @@ module Decidim
8
8
  layout "decidim/admin/users"
9
9
 
10
10
  helper_method :user
11
+ helper Decidim::Messaging::ConversationHelper
11
12
 
12
13
  def index
13
14
  enforce_permission_to :read, :officialization
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # Controller that allows managing the organization homepage content blocks
6
+ class OrganizationHomepageContentBlocksController < Decidim::Admin::ApplicationController
7
+ layout "decidim/admin/settings"
8
+
9
+ helper_method :content_block
10
+
11
+ def edit
12
+ enforce_permission_to :update, :organization, organization: current_organization
13
+ @form = form(ContentBlockForm).from_model(content_block)
14
+ end
15
+
16
+ def update
17
+ enforce_permission_to :update, :organization, organization: current_organization
18
+ @form = form(ContentBlockForm).from_params(params)
19
+
20
+ UpdateContentBlock.call(@form, content_block, :homepage) do
21
+ on(:ok) do
22
+ redirect_to edit_organization_homepage_path
23
+ end
24
+ on(:invalid) do
25
+ render :edit
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def content_block
33
+ @content_block ||= content_blocks.find_by(manifest_name: params[:id]) ||
34
+ content_block_from_manifest
35
+ end
36
+
37
+ def content_block_manifest
38
+ @content_block_manifest = unused_content_block_manifests.find { |manifest| manifest.name.to_s == params[:id] }
39
+ end
40
+
41
+ def content_blocks
42
+ @content_blocks ||= Decidim::ContentBlock.for_scope(:homepage, organization: current_organization)
43
+ end
44
+
45
+ def used_content_block_manifests
46
+ @used_content_block_manifests ||= content_blocks.map(&:manifest_name)
47
+ end
48
+
49
+ def unused_content_block_manifests
50
+ @unused_content_block_manifests ||= Decidim.content_blocks.for(:homepage).reject do |manifest|
51
+ used_content_block_manifests.include?(manifest.name.to_s)
52
+ end
53
+ end
54
+
55
+ def content_block_from_manifest
56
+ Decidim::ContentBlock.create!(
57
+ organization: current_organization,
58
+ scope: :homepage,
59
+ manifest_name: params[:id]
60
+ )
61
+ end
62
+ end
63
+ end
64
+ end