decidim-feeds 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +39 -0
  4. data/Rakefile +9 -0
  5. data/app/cells/decidim/feeds/content_blocks/feeds_settings_form/show.erb +3 -0
  6. data/app/cells/decidim/feeds/content_blocks/feeds_settings_form_cell.rb +23 -0
  7. data/app/cells/decidim/feeds/feed_cell.rb +24 -0
  8. data/app/cells/decidim/feeds/feed_dropdown_metadata_cell.rb +19 -0
  9. data/app/cells/decidim/feeds/feed_g_cell.rb +33 -0
  10. data/app/cells/decidim/feeds/feed_metadata_g_cell.rb +25 -0
  11. data/app/cells/decidim/feeds/feed_s_cell.rb +13 -0
  12. data/app/commands/decidim/feeds/admin/create_feed.rb +90 -0
  13. data/app/commands/decidim/feeds/admin/update_feed.rb +85 -0
  14. data/app/commands/decidim/feeds/create_feed.rb +90 -0
  15. data/app/commands/decidim/feeds/update_feed.rb +73 -0
  16. data/app/constraints/decidim/feeds/current_component.rb +28 -0
  17. data/app/constraints/decidim/feeds/current_feed.rb +43 -0
  18. data/app/controllers/concerns/decidim/feeds/feed_breadcrumb.rb +36 -0
  19. data/app/controllers/decidim/feeds/admin/application_controller.rb +26 -0
  20. data/app/controllers/decidim/feeds/admin/components_controller.rb +14 -0
  21. data/app/controllers/decidim/feeds/admin/concerns/feed_admin.rb +51 -0
  22. data/app/controllers/decidim/feeds/admin/feeds_controller.rb +92 -0
  23. data/app/controllers/decidim/feeds/application_controller.rb +37 -0
  24. data/app/controllers/decidim/feeds/feeds_controller.rb +137 -0
  25. data/app/forms/decidim/feeds/admin/feed_form.rb +102 -0
  26. data/app/forms/decidim/feeds/feed_form.rb +70 -0
  27. data/app/helpers/decidim/feeds/admin/feeds_admin_menu_helper.rb +10 -0
  28. data/app/helpers/decidim/feeds/application_helper.rb +16 -0
  29. data/app/helpers/decidim/feeds/feeds_helper.rb +38 -0
  30. data/app/models/decidim/feeds/application_record.rb +10 -0
  31. data/app/models/decidim/feeds/feed.rb +113 -0
  32. data/app/packs/entrypoints/decidim_feeds.js +5 -0
  33. data/app/packs/entrypoints/decidim_feeds.scss +1 -0
  34. data/app/packs/images/decidim/feeds/decidim_feeds.svg +1 -0
  35. data/app/packs/images/decidim/feeds/icon.svg +1 -0
  36. data/app/packs/src/decidim/feeds/feeds.js +0 -0
  37. data/app/packs/stylesheets/decidim/feeds/_variables.scss +10 -0
  38. data/app/packs/stylesheets/decidim/feeds/feeds.scss +3 -0
  39. data/app/permissions/decidim/feeds/permissions.rb +53 -0
  40. data/app/presenters/decidim/feeds/admin_log/feed_presenter.rb +46 -0
  41. data/app/queries/decidim/feeds/admin/admin_users.rb +60 -0
  42. data/app/queries/decidim/feeds/organization_feeds.rb +16 -0
  43. data/app/views/decidim/feeds/admin/feeds/_form.html.erb +66 -0
  44. data/app/views/decidim/feeds/admin/feeds/edit.html.erb +20 -0
  45. data/app/views/decidim/feeds/admin/feeds/index.html.erb +65 -0
  46. data/app/views/decidim/feeds/admin/feeds/new.html.erb +20 -0
  47. data/app/views/decidim/feeds/feeds/_form.html.erb +18 -0
  48. data/app/views/decidim/feeds/feeds/edit.html.erb +10 -0
  49. data/app/views/decidim/feeds/feeds/index.html.erb +5 -0
  50. data/app/views/decidim/feeds/feeds/new.html.erb +20 -0
  51. data/app/views/decidim/feeds/feeds/show.html.erb +33 -0
  52. data/app/views/layouts/decidim/admin/_manage_feeds.html.erb +11 -0
  53. data/app/views/layouts/decidim/admin/feed.html.erb +17 -0
  54. data/app/views/layouts/decidim/admin/feeds.html.erb +17 -0
  55. data/app/views/layouts/decidim/feed.html.erb +18 -0
  56. data/config/assets.rb +9 -0
  57. data/config/i18n-tasks.yml +10 -0
  58. data/config/locales/bs.yml +75 -0
  59. data/config/locales/de.yml +77 -0
  60. data/config/locales/en.yml +75 -0
  61. data/config/locales/hr.yml +75 -0
  62. data/config/locales/it.yml +75 -0
  63. data/config/locales/sr.yml +75 -0
  64. data/config/locales/tr.yml +75 -0
  65. data/lib/decidim/api/feed_type.rb +30 -0
  66. data/lib/decidim/feeds/admin.rb +10 -0
  67. data/lib/decidim/feeds/admin_engine.rb +81 -0
  68. data/lib/decidim/feeds/api.rb +9 -0
  69. data/lib/decidim/feeds/content_blocks/content_blocks_homepage.rb +19 -0
  70. data/lib/decidim/feeds/engine.rb +83 -0
  71. data/lib/decidim/feeds/menu.rb +106 -0
  72. data/lib/decidim/feeds/participatory_space.rb +52 -0
  73. data/lib/decidim/feeds/seeds.rb +47 -0
  74. data/lib/decidim/feeds/test/factories.rb +17 -0
  75. data/lib/decidim/feeds/version.rb +9 -0
  76. data/lib/decidim/feeds.rb +13 -0
  77. metadata +142 -0
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module Feeds
7
+ module Admin
8
+ module Concerns
9
+ # This concern is meant to be included in all controllers that are scoped
10
+ # into a feed's admin panel. It will override the layout so it shows
11
+ # the sidebar, preload the feed, etc.
12
+ module FeedAdmin
13
+ extend ActiveSupport::Concern
14
+
15
+ RegistersPermissions
16
+ .register_permissions(::Decidim::Feeds::Admin::Concerns::FeedAdmin,
17
+ Decidim::Feeds::Permissions,
18
+ Decidim::Admin::Permissions)
19
+
20
+ included do
21
+ include Decidim::Admin::ParticipatorySpaceAdminContext
22
+ helper_method :current_feed
23
+ add_breadcrumb_item_from_menu :admin_feed_menu
24
+
25
+ participatory_space_admin_layout
26
+
27
+ def current_feed
28
+ @current_feed ||= organization_feeds.find_by!(
29
+ slug: params[:feed_slug] || params[:slug]
30
+ )
31
+ end
32
+
33
+ alias_method :current_participatory_space, :current_feed
34
+
35
+ def organization_feeds
36
+ @organization_feeds ||= OrganizationFeeds.new(current_organization).query
37
+ end
38
+
39
+ def permissions_context
40
+ super.merge(current_participatory_space:)
41
+ end
42
+
43
+ def permission_class_chain
44
+ PermissionsRegistry.chain_for(FeedAdmin)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ module Admin
6
+ # Controller that allows managing feeds.
7
+ #
8
+ class FeedsController < Decidim::Feeds::Admin::ApplicationController
9
+ include Decidim::Admin::ParticipatorySpaceAdminBreadcrumb
10
+ helper_method :current_feed, :current_participatory_space
11
+ layout "decidim/admin/feeds"
12
+
13
+ def index
14
+ enforce_permission_to :read, :feed_list
15
+ @feeds = collection
16
+ end
17
+
18
+ def new
19
+ enforce_permission_to :create, :feed
20
+ @form = form(FeedForm).instance
21
+ end
22
+
23
+ def create
24
+ enforce_permission_to :create, :feed
25
+
26
+ params[:created_by] = current_user
27
+ @form = form(FeedForm).from_params(params)
28
+
29
+ CreateFeed.call(@form) do
30
+ on(:ok) do |feed|
31
+ flash[:notice] = I18n.t("feeds.create.success", scope: "decidim.admin")
32
+ redirect_to feeds_path
33
+ end
34
+
35
+ on(:invalid) do
36
+ flash.now[:alert] = I18n.t("feeds.create.error", scope: "decidim.admin")
37
+ render :new
38
+ end
39
+ end
40
+ end
41
+
42
+ def edit
43
+ enforce_permission_to :update, :feed, feed: current_feed
44
+ @form = form(FeedForm).from_model(current_feed)
45
+ render layout: "decidim/admin/feed"
46
+ end
47
+
48
+ def update
49
+ enforce_permission_to :update, :feed, feed: current_feed
50
+ @form = form(FeedForm).from_params(
51
+ feed_params,
52
+ feed_id: current_feed.id
53
+ )
54
+
55
+ UpdateFeed.call(current_feed, @form) do
56
+ on(:ok) do |feed|
57
+ flash[:notice] = I18n.t("feeds.update.success", scope: "decidim.admin")
58
+ redirect_to edit_feed_path(feed)
59
+ end
60
+
61
+ on(:invalid) do
62
+ flash.now[:alert] = I18n.t("feeds.update.error", scope: "decidim.admin")
63
+ render :edit, layout: "decidim/admin/feed"
64
+ end
65
+ end
66
+ end
67
+
68
+ def copy
69
+ enforce_permission_to :create, :feed
70
+ end
71
+
72
+ private
73
+
74
+ def collection
75
+ @collection ||= OrganizationFeeds.new(current_user.organization).query
76
+ end
77
+
78
+ def current_feed
79
+ @current_feed ||= collection.where(slug: params[:slug]).or(
80
+ collection.where(id: params[:slug])
81
+ ).first
82
+ end
83
+
84
+ alias current_participatory_space current_feed
85
+
86
+ def feed_params
87
+ { id: params[:slug] }.merge(params[:feed].to_unsafe_h)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ # The main admin application controller for feeds
6
+ class ApplicationController < Decidim::ApplicationController
7
+ helper Decidim::ApplicationHelper
8
+ helper Decidim::Feeds::FeedsHelper
9
+ include NeedsPermission
10
+
11
+ register_permissions(Decidim::Feeds::ApplicationController,
12
+ ::Decidim::Feeds::Permissions,
13
+ ::Decidim::Admin::Permissions,
14
+ ::Decidim::Permissions)
15
+
16
+ private
17
+
18
+ def user_has_no_permission_path
19
+ decidim.new_user_session_path
20
+ end
21
+
22
+ def permissions_context
23
+ super.merge(
24
+ current_participatory_space: try(:current_participatory_space)
25
+ )
26
+ end
27
+
28
+ def permission_class_chain
29
+ ::Decidim.permissions_registry.chain_for(::Decidim::Feeds::ApplicationController)
30
+ end
31
+
32
+ def permission_scope
33
+ :public
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ # A controller that holds the logic to show Feeds in a public layout.
6
+ class FeedsController < Decidim::Feeds::ApplicationController
7
+ include ParticipatorySpaceContext
8
+ include FeedBreadcrumb
9
+ include FormFactory
10
+
11
+ participatory_space_layout only: :show
12
+
13
+ include FilterResource
14
+ include Paginable
15
+ include HasParticipatorySpaceContentBlocks
16
+
17
+ # helper_method :collection, :stats
18
+
19
+ def index
20
+ enforce_permission_to :list, :feed
21
+
22
+ @feeds = published_feeds.query
23
+ end
24
+
25
+ def show
26
+ enforce_permission_to :read, :feed, feed: current_participatory_space
27
+
28
+ @posts_component = current_feed.components.find_by(manifest_name: "posts")
29
+
30
+ if @posts_component.nil?
31
+ flash[:alert] = I18n.t("feeds.show.posts_component_not_found", scope: "decidim.feeds")
32
+ redirect_to feeds_path
33
+ end
34
+
35
+ # redirect_to decidim_feed_posts_path(current_participatory_space, posts_component) if posts_component
36
+ end
37
+
38
+ def new
39
+ enforce_permission_to :create, :feed
40
+
41
+ @form = form(FeedForm).instance
42
+ end
43
+
44
+ def create
45
+ enforce_permission_to :create, :feed
46
+
47
+ @form = form(FeedForm).from_params(params)
48
+
49
+ CreateFeed.call(@form) do
50
+ on(:ok) do |feed|
51
+ flash[:notice] = I18n.t("feeds.create.success", scope: "decidim.feeds")
52
+ redirect_to feeds_path
53
+ end
54
+
55
+ on(:invalid) do
56
+ flash.now[:alert] = I18n.t("feeds.create.error", scope: "decidim.feeds")
57
+ render :new
58
+ end
59
+ end
60
+ end
61
+
62
+ def edit
63
+ enforce_permission_to :update, :feed, feed: current_feed
64
+
65
+ @form = form(FeedForm).from_model(current_feed)
66
+ end
67
+
68
+ def update
69
+ enforce_permission_to :update, :feed, feed: current_feed
70
+
71
+ @form = form(FeedForm).from_params(
72
+ feed_params,
73
+ feed_id: current_feed.id
74
+ )
75
+
76
+ UpdateFeed.call(current_feed, @form) do
77
+ on(:ok) do |feed|
78
+ flash[:notice] = I18n.t("feeds.update.success", scope: "decidim.feeds")
79
+ redirect_to feed
80
+ end
81
+
82
+ on(:invalid) do
83
+ flash.now[:alert] = I18n.t("feeds.update.error", scope: "decidim.feeds")
84
+ render :edit
85
+ end
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def collection
92
+ @collection ||= OrganizationFeeds.new(current_user.organization).query
93
+ end
94
+
95
+ def current_feed
96
+ @current_feed ||= collection.where(slug: params[:slug]).or(
97
+ collection.where(id: params[:slug])
98
+ ).first
99
+ end
100
+
101
+ def search_collection
102
+ Feed.where(organization: current_organization)
103
+ end
104
+
105
+ def default_filter_params
106
+ {
107
+ with_any_scope: nil,
108
+ with_any_area: nil,
109
+ with_any_type: nil
110
+ }
111
+ end
112
+
113
+ def current_participatory_space
114
+ return unless params[:slug]
115
+
116
+ @current_participatory_space ||= OrganizationFeeds.new(current_organization).query.where(slug: params[:slug]).or(
117
+ OrganizationFeeds.new(current_organization).query.where(id: params[:slug])
118
+ ).first!
119
+ end
120
+
121
+ def published_feeds
122
+ @published_feeds ||= OrganizationFeeds.new(current_organization)
123
+ end
124
+
125
+ # def collection
126
+ # @collection ||= paginate(Kaminari.paginate_array(parent_feeds))
127
+ # end
128
+
129
+ def feed_params
130
+ # only allow title to be updated
131
+ title_params = current_organization.available_locales.map { |locale| "title_#{locale}" }
132
+ permitted_params = params.require(:feed).permit(title_params)
133
+ { id: params[:slug] }.merge(permitted_params)
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ module Admin
6
+ # A form object used to create feeds from the admin
7
+ # dashboard.
8
+ #
9
+ class FeedForm < Form
10
+ include TranslatableAttributes
11
+ include AttachmentAttributes
12
+
13
+ mimic :feed
14
+
15
+ translatable_attribute :title, String
16
+
17
+ attribute :created_by, String
18
+ attribute :slug, String
19
+ attribute :attachment, AttachmentForm
20
+ # attribute :participatory_processes_ids, Array[Integer]
21
+ # attribute :included_at, Decidim::Attributes::LocalizedDate
22
+
23
+ # attribute :banner_image
24
+ # attribute :hero_image
25
+ # attribute :remove_banner_image, Boolean, default: false
26
+ # attribute :remove_hero_image, Boolean, default: false
27
+
28
+ attachments_attribute :documents
29
+
30
+ validates :slug, presence: true, format: { with: Decidim::Feeds::Feed.slug_format }
31
+
32
+ validate :slug_uniqueness
33
+ # validate :same_type_organization, if: ->(form) { form.decidim_feeds_type_id }
34
+
35
+ validates :title, translatable_presence: true
36
+
37
+ # validates :banner_image, passthru: { to: Decidim::Feed }
38
+ # validates :hero_image, passthru: { to: Decidim::Feed }
39
+
40
+ # validates :weight, presence: true
41
+
42
+ alias organization current_organization
43
+
44
+ def map_model(model)
45
+ self.title = model.title # translated_attribute(model.title)
46
+ self.slug = model.slug
47
+ self.documents = model.attachments
48
+ end
49
+
50
+ # def created_by_for_select
51
+ # CREATED_BY.map do |creator|
52
+ # [
53
+ # I18n.t("created_by.#{creator}", scope: "decidim.feeds"),
54
+ # creator
55
+ # ]
56
+ # end
57
+ # end
58
+
59
+ # def processes_for_select
60
+ # @processes_for_select ||= organization_participatory_processes
61
+ # &.map { |pp| [translated_attribute(pp.title), pp.id] }
62
+ # &.sort_by { |arr| arr[0] }
63
+ # end
64
+
65
+ def has_attachments?
66
+ feed.has_attachments? && errors[:documents].empty? && documents.present?
67
+ end
68
+
69
+ def has_error_in_attachments?
70
+ errors[:documents].present?
71
+ end
72
+
73
+ private
74
+
75
+ # def organization_participatory_processes
76
+ # Decidim.find_participatory_space_manifest(:participatory_processes)
77
+ # .participatory_spaces.call(current_organization)
78
+ # end
79
+
80
+ def organization_feeds
81
+ OrganizationFeeds.new(current_organization).query
82
+ end
83
+
84
+ def slug_uniqueness
85
+ return unless organization_feeds
86
+ .where(slug:)
87
+ .where.not(id: context[:feed_id])
88
+ .any?
89
+
90
+ errors.add(:slug, :taken)
91
+ end
92
+
93
+ # def same_type_organization
94
+ # return unless feed_type
95
+ # return if feed_type.organization == current_organization
96
+
97
+ # errors.add(:feed_type, :invalid)
98
+ # end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ # A form object used to create feeds from the admin
6
+ # dashboard.
7
+ #
8
+ class FeedForm < Form
9
+ include TranslatableAttributes
10
+
11
+ mimic :feed
12
+
13
+ translatable_attribute :title, String
14
+
15
+ attribute :created_by, String
16
+
17
+ # attribute :participatory_processes_ids, Array[Integer]
18
+ # attribute :included_at, Decidim::Attributes::LocalizedDate
19
+
20
+ # attribute :banner_image
21
+ # attribute :hero_image
22
+ # attribute :remove_banner_image, Boolean, default: false
23
+ # attribute :remove_hero_image, Boolean, default: false
24
+
25
+ # validate :same_type_organization, if: ->(form) { form.decidim_feeds_type_id }
26
+
27
+ validates :title, translatable_presence: true
28
+
29
+ # validates :banner_image, passthru: { to: Decidim::Feed }
30
+ # validates :hero_image, passthru: { to: Decidim::Feed }
31
+
32
+ # validates :weight, presence: true
33
+
34
+ alias organization current_organization
35
+
36
+ # def created_by_for_select
37
+ # CREATED_BY.map do |creator|
38
+ # [
39
+ # I18n.t("created_by.#{creator}", scope: "decidim.feeds"),
40
+ # creator
41
+ # ]
42
+ # end
43
+ # end
44
+
45
+ # def processes_for_select
46
+ # @processes_for_select ||= organization_participatory_processes
47
+ # &.map { |pp| [translated_attribute(pp.title), pp.id] }
48
+ # &.sort_by { |arr| arr[0] }
49
+ # end
50
+
51
+ private
52
+
53
+ # def organization_participatory_processes
54
+ # Decidim.find_participatory_space_manifest(:participatory_processes)
55
+ # .participatory_spaces.call(current_organization)
56
+ # end
57
+
58
+ def organization_feeds
59
+ OrganizationFeeds.new(current_organization).query
60
+ end
61
+
62
+ # def same_type_organization
63
+ # return unless feed_type
64
+ # return if feed_type.organization == current_organization
65
+
66
+ # errors.add(:feed_type, :invalid)
67
+ # end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ module Admin
6
+ module FeedsAdminMenuHelper
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ # Custom helpers, scoped to the feeds engine.
6
+ #
7
+ module ApplicationHelper
8
+ include PaginateHelper
9
+ include SanitizeHelper
10
+ # include Decidim::Feeds::PostsHelper
11
+ include ::Decidim::EndorsableHelper
12
+ include ::Decidim::FollowableHelper
13
+ include Decidim::Comments::CommentsHelper
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ # Helpers related to the Feeds layout.
6
+ module FeedsHelper
7
+ include Decidim::ResourceHelper
8
+ # include Decidim::AttachmentsHelper
9
+ include Decidim::IconHelper
10
+ include Decidim::SanitizeHelper
11
+ include Decidim::ResourceReferenceHelper
12
+ # include Decidim::FiltersHelper
13
+ # include FilterFeedsHelper
14
+
15
+ # Items to display in the navigation of an feed
16
+ def feed_nav_items(participatory_space)
17
+ components = participatory_space.components.published.or(Decidim::Component.where(id: try(:current_component)))
18
+
19
+ [
20
+ *(if participatory_space.members.not_ceased.any?
21
+ [{
22
+ name: t("feed_member_menu_item", scope: "layouts.decidim.feed_navigation"),
23
+ url: decidim_feeds.feed_feed_members_path(participatory_space),
24
+ active: is_active_link?(decidim_feeds.feed_feed_members_path(participatory_space), :inclusive)
25
+ }]
26
+ end
27
+ )
28
+ ] + components.map do |component|
29
+ {
30
+ name: decidim_escape_translated(component.name),
31
+ url: main_component_path(component),
32
+ active: is_active_link?(main_component_path(component), :inclusive)
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ # Abstract class from which all models in this engine inherit.
6
+ class ApplicationRecord < ActiveRecord::Base
7
+ self.abstract_class = true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Feeds
5
+ class Feed < ApplicationRecord
6
+ include Decidim::Participable
7
+ include Decidim::ParticipatorySpaceResourceable
8
+ include Decidim::TranslatableResource
9
+ include Decidim::Loggable
10
+ include Decidim::Traceable
11
+ include Decidim::Searchable
12
+ include Decidim::HasAttachments
13
+ # include Decidim::HasAttachmentCollections
14
+ # include Decidim::Publicable
15
+ # include Decidim::ScopableParticipatorySpace
16
+ # include Decidim::Followable
17
+ # include Decidim::HasReference
18
+ # include Decidim::HasPrivateUsers
19
+ # include Decidim::HasUploadValidations
20
+ # include Decidim::FilterableResource
21
+
22
+ translatable_fields :title
23
+
24
+ belongs_to :organization,
25
+ foreign_key: "decidim_organization_id",
26
+ class_name: "Decidim::Organization"
27
+
28
+ has_many :components, as: :participatory_space, dependent: :destroy
29
+ has_many :categories,
30
+ foreign_key: "decidim_participatory_space_id",
31
+ foreign_type: "decidim_participatory_space_type",
32
+ dependent: :destroy,
33
+ as: :participatory_space
34
+
35
+ # has_one_attached :hero_image
36
+ # validates_upload :hero_image, uploader: Decidim::HeroImageUploader
37
+
38
+ # has_one_attached :banner_image
39
+ # validates_upload :banner_image, uploader: Decidim::BannerImageUploader
40
+
41
+ validates :slug, uniqueness: { scope: :organization }
42
+ validates :slug, presence: true, format: { with: Decidim::Feeds::Feed.slug_format }
43
+
44
+ searchable_fields({
45
+ # scope_id: :decidim_scope_id,
46
+ participatory_space: :itself,
47
+ A: :title,
48
+ # B: :subtitle,
49
+ # C: :short_description,
50
+ # D: :description,
51
+ datetime: :created_at
52
+ },
53
+ index_on_create: true,
54
+ index_on_update: true
55
+ )
56
+
57
+ # Overwriting existing method Decidim::HasPrivateUsers.public_spaces
58
+ # def self.public_spaces
59
+ # where(private_space: false).or(where(private_space: true).where(is_transparent: true)).published
60
+ # end
61
+
62
+ def self.log_presenter_class_for(_log)
63
+ Decidim::Feeds::AdminLog::FeedPresenter
64
+ end
65
+
66
+ # This is required by participable, but Feed is not publicable
67
+ def self.published
68
+ all
69
+ end
70
+
71
+ # def hashtag
72
+ # attributes["hashtag"].to_s.delete("#")
73
+ # end
74
+
75
+ def to_param
76
+ slug
77
+ end
78
+
79
+ def translated_title
80
+ Decidim::FeedPresenter.new(self).translated_title
81
+ end
82
+
83
+ def scopes_enabled?
84
+ false
85
+ end
86
+
87
+ def scope
88
+ nil
89
+ end
90
+
91
+ def followers
92
+ Decidim::User.none
93
+ end
94
+
95
+ def private_space?
96
+ false
97
+ end
98
+
99
+ def has_subscopes?
100
+ false
101
+ end
102
+
103
+ def published?
104
+ true
105
+ end
106
+
107
+ # private
108
+
109
+ # Allow ransacker to search for a key in a hstore column (`title`.`en`)
110
+ # ransacker_i18n :title # requires filterable
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,5 @@
1
+ import 'src/decidim/feeds/feeds.js';
2
+
3
+ require.context('../images', true);
4
+
5
+ import 'entrypoints/decidim_feeds.scss';
@@ -0,0 +1 @@
1
+ @import 'stylesheets/decidim/feeds/feeds';
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm9.5 13.7H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zm0 3.68H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zM22.26 23H8a1 1 0 0 1 0-1.94h14.26a1 1 0 0 1 0 1.94z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm9.5 13.7H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zm0 3.68H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zM22.26 23H8a1 1 0 0 1 0-1.94h14.26a1 1 0 0 1 0 1.94z"/></svg>