decidim-posts 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +40 -0
- data/Rakefile +9 -0
- data/app/cells/decidim/posts/comments/add_comment.erb +15 -0
- data/app/cells/decidim/posts/comments/comments_loading.erb +1 -0
- data/app/cells/decidim/posts/comments/order_control.erb +13 -0
- data/app/cells/decidim/posts/comments/show.erb +31 -0
- data/app/cells/decidim/posts/comments_cell.rb +158 -0
- data/app/cells/decidim/posts/content_blocks/posts/show.erb +3 -0
- data/app/cells/decidim/posts/content_blocks/posts_cell.rb +50 -0
- data/app/cells/decidim/posts/content_blocks/posts_settings_form/show.erb +3 -0
- data/app/cells/decidim/posts/content_blocks/posts_settings_form_cell.rb +23 -0
- data/app/cells/decidim/posts/feed_dropdown_metadata_cell.rb +19 -0
- data/app/cells/decidim/posts/meeting/show.erb +65 -0
- data/app/cells/decidim/posts/meeting_cell.rb +44 -0
- data/app/cells/decidim/posts/post/show.erb +30 -0
- data/app/cells/decidim/posts/post/survey.erb +68 -0
- data/app/cells/decidim/posts/post_attachments/show.erb +40 -0
- data/app/cells/decidim/posts/post_attachments_cell.rb +17 -0
- data/app/cells/decidim/posts/post_cell.rb +44 -0
- data/app/cells/decidim/posts/post_comment/show.erb +17 -0
- data/app/cells/decidim/posts/post_comment_cell.rb +49 -0
- data/app/cells/decidim/posts/post_header/show.erb +53 -0
- data/app/cells/decidim/posts/post_header_cell.rb +79 -0
- data/app/cells/decidim/posts/post_host/show.erb +74 -0
- data/app/cells/decidim/posts/post_host_cell.rb +73 -0
- data/app/cells/decidim/posts/post_metadata/show.erb +9 -0
- data/app/cells/decidim/posts/post_metadata_cell.rb +67 -0
- data/app/cells/decidim/posts/reaction_menu/show.erb +18 -0
- data/app/cells/decidim/posts/reaction_menu/styles.erb +7 -0
- data/app/cells/decidim/posts/reaction_menu_cell.rb +26 -0
- data/app/cells/decidim/posts/reactions/show.erb +8 -0
- data/app/cells/decidim/posts/reactions_cell.rb +22 -0
- data/app/commands/decidim/posts/add_reaction_to_resource.rb +90 -0
- data/app/commands/decidim/posts/create_post.rb +112 -0
- data/app/commands/decidim/posts/destroy_post.rb +20 -0
- data/app/commands/decidim/posts/remove_reaction_from_resource.rb +41 -0
- data/app/commands/decidim/posts/update_post.rb +72 -0
- data/app/controllers/concerns/decidim/posts/admin/filterable.rb +46 -0
- data/app/controllers/concerns/decidim/posts/reactionable.rb +31 -0
- data/app/controllers/decidim/posts/admin/application_controller.rb +26 -0
- data/app/controllers/decidim/posts/admin/posts_controller.rb +93 -0
- data/app/controllers/decidim/posts/application_controller.rb +18 -0
- data/app/controllers/decidim/posts/meetings_controller.rb +176 -0
- data/app/controllers/decidim/posts/posts_controller.rb +202 -0
- data/app/controllers/decidim/posts/reactions_controller.rb +54 -0
- data/app/controllers/decidim/posts/user_answers_controller.rb +36 -0
- data/app/events/decidim/posts/resource_reacted_event.rb +38 -0
- data/app/forms/decidim/posts/answer_form.rb +13 -0
- data/app/forms/decidim/posts/post_form.rb +121 -0
- data/app/forms/decidim/posts/question_form.rb +20 -0
- data/app/helpers/decidim/posts/admin/posts_helper.rb +8 -0
- data/app/helpers/decidim/posts/application_helper.rb +20 -0
- data/app/helpers/decidim/posts/post_cells_helper.rb +35 -0
- data/app/helpers/decidim/posts/posts_helper.rb +34 -0
- data/app/helpers/decidim/posts/reaction_helper.rb +22 -0
- data/app/models/decidim/posts/answer.rb +13 -0
- data/app/models/decidim/posts/application_record.rb +10 -0
- data/app/models/decidim/posts/post.rb +116 -0
- data/app/models/decidim/posts/question.rb +17 -0
- data/app/models/decidim/posts/reaction.rb +22 -0
- data/app/models/decidim/posts/reaction_type.rb +13 -0
- data/app/models/decidim/posts/user_answer.rb +11 -0
- data/app/packs/entrypoints/decidim_posts.js +5 -0
- data/app/packs/entrypoints/decidim_posts.scss +1 -0
- data/app/packs/images/decidim/posts/icon.svg +1 -0
- data/app/packs/src/decidim/posts/carousel.js +112 -0
- data/app/packs/src/decidim/posts/host_status.js +75 -0
- data/app/packs/src/decidim/posts/newFeeds.js +98 -0
- data/app/packs/src/decidim/posts/posts.js +272 -0
- data/app/packs/src/decidim/posts/submenu.js +46 -0
- data/app/packs/src/decidim/posts/survey.js +94 -0
- data/app/packs/stylesheets/decidim/posts/_variables.scss +10 -0
- data/app/packs/stylesheets/decidim/posts/posts.scss +415 -0
- data/app/permissions/decidim/posts/admin/permissions.rb +23 -0
- data/app/permissions/decidim/posts/permissions.rb +101 -0
- data/app/presenters/decidim/posts/post_presenter.rb +45 -0
- data/app/views/decidim/posts/admin/posts/_post-tr.html.erb +45 -0
- data/app/views/decidim/posts/admin/posts/index.html.erb +54 -0
- data/app/views/decidim/posts/meetings/edit.html.erb +24 -0
- data/app/views/decidim/posts/posts/_admin_options.html.erb +30 -0
- data/app/views/decidim/posts/posts/_attachment.html.erb +24 -0
- data/app/views/decidim/posts/posts/_edit_form.html.erb +16 -0
- data/app/views/decidim/posts/posts/_feed.html.erb +8 -0
- data/app/views/decidim/posts/posts/_form.html.erb +104 -0
- data/app/views/decidim/posts/posts/_index.html.erb +49 -0
- data/app/views/decidim/posts/posts/_meeting_form.erb +18 -0
- data/app/views/decidim/posts/posts/_new.html.erb +33 -0
- data/app/views/decidim/posts/posts/_new_survey.html.erb +20 -0
- data/app/views/decidim/posts/posts/_new_survey_answer.html.erb +11 -0
- data/app/views/decidim/posts/posts/_new_survey_question.html.erb +17 -0
- data/app/views/decidim/posts/posts/_post.html.erb +11 -0
- data/app/views/decidim/posts/posts/_post_form.html.erb +5 -0
- data/app/views/decidim/posts/posts/_sidebar.html.erb +36 -0
- data/app/views/decidim/posts/posts/edit.html.erb +34 -0
- data/app/views/decidim/posts/posts/index.html.erb +1 -0
- data/app/views/decidim/posts/posts/show.html.erb +12 -0
- data/app/views/decidim/posts/reactions/_update_buttons_and_counters.html.erb +1 -0
- data/config/assets.rb +9 -0
- data/config/i18n-tasks.yml +10 -0
- data/config/locales/bs.yml +215 -0
- data/config/locales/de.yml +217 -0
- data/config/locales/en.yml +216 -0
- data/config/locales/hr.yml +219 -0
- data/config/locales/it.yml +215 -0
- data/config/locales/sr.yml +220 -0
- data/config/locales/tr.yml +219 -0
- data/lib/decidim/posts/admin.rb +10 -0
- data/lib/decidim/posts/admin_engine.rb +25 -0
- data/lib/decidim/posts/component.rb +59 -0
- data/lib/decidim/posts/content_blocks/content_blocks_homepage.rb +19 -0
- data/lib/decidim/posts/engine.rb +84 -0
- data/lib/decidim/posts/test/factories.rb +14 -0
- data/lib/decidim/posts/version.rb +9 -0
- data/lib/decidim/posts.rb +13 -0
- metadata +183 -0
@@ -0,0 +1,202 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# require_dependency "decidim/posts/application_controller"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Posts
|
7
|
+
class PostsController < Decidim::Posts::ApplicationController
|
8
|
+
include Decidim::ApplicationHelper
|
9
|
+
include FormFactory
|
10
|
+
include Flaggable
|
11
|
+
include Decidim::AttachmentsHelper
|
12
|
+
|
13
|
+
helper_method :post_presenter, :form_presenter
|
14
|
+
|
15
|
+
def index
|
16
|
+
enforce_permission_to :read, :post
|
17
|
+
|
18
|
+
@posts = posts(filter_post_category).where(fixed: [false, nil])
|
19
|
+
@fixed_posts = posts.where(fixed: true).order(created_at: :desc)
|
20
|
+
|
21
|
+
@meetings = meetings(filter_post_category)
|
22
|
+
|
23
|
+
@non_fixed_objects = (@posts + @meetings).sort_by(&:created_at).reverse
|
24
|
+
@non_fixed_objects = Kaminari.paginate_array(@non_fixed_objects).page(params[:page]).per(20)
|
25
|
+
end
|
26
|
+
|
27
|
+
# action to load more posts and meetings on the index page via ajax
|
28
|
+
def load_more
|
29
|
+
enforce_permission_to :read, :post
|
30
|
+
|
31
|
+
@posts = posts(filter_post_category).where(fixed: false)
|
32
|
+
@meetings = meetings(filter_post_category)
|
33
|
+
|
34
|
+
@non_fixed_objects = (@posts + @meetings).sort_by(&:created_at).reverse
|
35
|
+
@non_fixed_objects = Kaminari.paginate_array(@non_fixed_objects).page(params[:page]).per(20)
|
36
|
+
|
37
|
+
render partial: "decidim/posts/posts/feed", locals: { objects: @non_fixed_objects }
|
38
|
+
end
|
39
|
+
|
40
|
+
def show
|
41
|
+
@post = Post.find(params[:id])
|
42
|
+
|
43
|
+
enforce_permission_to :read, :post
|
44
|
+
|
45
|
+
raise ActionController::RoutingError, "Not Found" unless @post
|
46
|
+
end
|
47
|
+
|
48
|
+
def new
|
49
|
+
enforce_permission_to :create, :post
|
50
|
+
@form = form(PostForm).from_params(post_creation_params)
|
51
|
+
end
|
52
|
+
|
53
|
+
def create
|
54
|
+
enforce_permission_to :create, :post
|
55
|
+
|
56
|
+
@form = form(PostForm).from_params(post_creation_params)
|
57
|
+
|
58
|
+
CreatePost.call(@form) do
|
59
|
+
on(:ok) do |post|
|
60
|
+
flash[:notice] = I18n.t("posts.create.success", scope: "decidim.posts")
|
61
|
+
# TODO: implement javascript to create a new post without reloading the page
|
62
|
+
# redirect_to decidim.root_path
|
63
|
+
# redirect_to current_component_path
|
64
|
+
redirect_to posts_path
|
65
|
+
end
|
66
|
+
|
67
|
+
on(:invalid) do
|
68
|
+
flash.now[:alert] = I18n.t("posts.create.invalid", scope: "decidim.posts")
|
69
|
+
redirect_to posts_path
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def edit
|
75
|
+
@post = Post.find(params[:id])
|
76
|
+
enforce_permission_to :edit, :post, post: @post
|
77
|
+
@form = Decidim::Posts::PostForm.from_model(@post).with_context(context)
|
78
|
+
end
|
79
|
+
|
80
|
+
def update
|
81
|
+
@post = Post.find(params[:id])
|
82
|
+
enforce_permission_to :edit, :post, post: @post
|
83
|
+
|
84
|
+
@form = form(PostForm).from_params(params)
|
85
|
+
UpdatePost.call(@form, current_user, @post) do
|
86
|
+
on(:ok) do |post|
|
87
|
+
flash[:notice] = I18n.t("posts.update.success", scope: "decidim.posts")
|
88
|
+
redirect_to posts_path
|
89
|
+
# redirect_to Decidim::ResourceLocatorPresenter.new(@post).path
|
90
|
+
end
|
91
|
+
|
92
|
+
on(:invalid) do
|
93
|
+
flash.now[:alert] = I18n.t("posts.update.invalid", scope: "decidim.posts")
|
94
|
+
render :edit
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def destroy
|
100
|
+
@post = Post.find(params[:id])
|
101
|
+
enforce_permission_to :delete, :post, post: @post
|
102
|
+
|
103
|
+
DestroyPost.call(@post, current_user) do
|
104
|
+
on(:ok) do
|
105
|
+
flash[:notice] = I18n.t("posts.destroy.success", scope: "decidim.posts")
|
106
|
+
redirect_to posts_path
|
107
|
+
end
|
108
|
+
|
109
|
+
on(:invalid) do
|
110
|
+
flash.now[:alert] = I18n.t("posts.destroy.invalid", scope: "decidim.posts")
|
111
|
+
redirect_to posts_path
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def change_status
|
117
|
+
@post = Decidim::Posts::Post.find(params[:id])
|
118
|
+
# enable_comments: params[:status] ? true : false
|
119
|
+
if @post.update(status: params[:status], enable_comments: false)
|
120
|
+
render json: { message: 'Status updated successfully', new_content: cell("decidim/posts/post_host", @post).call(:show) }, status: :ok
|
121
|
+
else
|
122
|
+
render json: { error: 'Failed to update status' }, status: :unprocessable_entity
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def post_categories
|
130
|
+
["post", "host", "calendar", "survey", "sharecare"]
|
131
|
+
end
|
132
|
+
|
133
|
+
def allowed_post_categories
|
134
|
+
["all"] + post_categories
|
135
|
+
end
|
136
|
+
|
137
|
+
def default_filter_post_category
|
138
|
+
return "host" if current_user.admin?
|
139
|
+
|
140
|
+
"all"
|
141
|
+
end
|
142
|
+
|
143
|
+
def filter_post_category
|
144
|
+
allowed_post_categories.include?(params[:filter_post_category]) ? params[:filter_post_category] : default_filter_post_category
|
145
|
+
end
|
146
|
+
|
147
|
+
def posts(filter_category=nil)
|
148
|
+
category = filter_category == "all" ? nil : filter_category
|
149
|
+
|
150
|
+
Decidim::Posts::Post
|
151
|
+
.where(decidim_component_id: current_component.id)
|
152
|
+
.filter_category(category)
|
153
|
+
.order(created_at: :desc)
|
154
|
+
.includes(:attachments)
|
155
|
+
end
|
156
|
+
|
157
|
+
def meetings(filter_category=nil)
|
158
|
+
category = filter_category == "all" ? nil : filter_category
|
159
|
+
|
160
|
+
if category.blank? || category == 'calendar'
|
161
|
+
meetings_component.blank? ? [] : Decidim::Meetings::Meeting.where(component: meetings_component).published.except_withdrawn
|
162
|
+
else
|
163
|
+
[]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def post_presenter
|
168
|
+
@post_presenter ||= present(@post)
|
169
|
+
end
|
170
|
+
|
171
|
+
def form_presenter
|
172
|
+
@form_presenter ||= present(@form, presenter_class: Decidim::Posts::PostPresenter)
|
173
|
+
end
|
174
|
+
|
175
|
+
def post_creation_params
|
176
|
+
params[:post]
|
177
|
+
end
|
178
|
+
|
179
|
+
def participatory_space
|
180
|
+
@participatory_space ||= current_component.participatory_space
|
181
|
+
end
|
182
|
+
|
183
|
+
def meetings_component
|
184
|
+
@meetings_component ||= participatory_space.components.find_by(manifest_name: "meetings")
|
185
|
+
end
|
186
|
+
|
187
|
+
# def meeting_form
|
188
|
+
# form(Decidim::Meetings::MeetingForm).from_params(params)
|
189
|
+
# end
|
190
|
+
|
191
|
+
def context
|
192
|
+
{
|
193
|
+
current_component: current_component,
|
194
|
+
current_organization: current_component.organization,
|
195
|
+
current_user:,
|
196
|
+
current_participatory_space: participatory_space
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Posts
|
5
|
+
class ReactionsController < Decidim::Components::BaseController
|
6
|
+
before_action :authenticate_user!
|
7
|
+
|
8
|
+
def create
|
9
|
+
enforce_permission_to(:create, :reaction, resource:)
|
10
|
+
|
11
|
+
reaction_type_id = params[:reaction_type_id]
|
12
|
+
user_group_id = params[:user_group_id]
|
13
|
+
|
14
|
+
AddReactionToResource.call(resource, current_user, user_group_id, reaction_type_id) do
|
15
|
+
on(:ok) do
|
16
|
+
resource.reload
|
17
|
+
render partial: "update_buttons_and_counters", locals: { resource: resource }
|
18
|
+
#render json: { success: true, reaction_type: @reaction.reaction_type }, status: :ok
|
19
|
+
end
|
20
|
+
|
21
|
+
on(:invalid) do
|
22
|
+
render json: { error: I18n.t("resource_reactions.create.error", scope: "decidim") }, status: :unprocessable_entity
|
23
|
+
#render json: { success: false, errors: @reaction.errors.full_messages }, status: :unprocessable_entity
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def destroy
|
29
|
+
enforce_permission_to(:withdraw, :reaction, resource:)
|
30
|
+
|
31
|
+
user_group_id = params[:user_group_id]
|
32
|
+
user_group = user_groups.find(user_group_id) if user_group_id
|
33
|
+
|
34
|
+
RemoveReactionFromResource.call(resource, current_user, user_group) do
|
35
|
+
on(:ok) do
|
36
|
+
resource.reload
|
37
|
+
render :update_buttons_and_counters
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def resource
|
45
|
+
gid_param = params[:id] || params[:resource_id]
|
46
|
+
@resource ||= GlobalID::Locator.locate(GlobalID.parse(gid_param))
|
47
|
+
end
|
48
|
+
|
49
|
+
def user_groups
|
50
|
+
Decidim::UserGroups::ManageableUserGroups.for(current_user).verified
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# app/controllers/decidim/posts/user_answers_controller.rb
|
2
|
+
module Decidim
|
3
|
+
module Posts
|
4
|
+
class UserAnswersController < ApplicationController
|
5
|
+
|
6
|
+
def create
|
7
|
+
answer_id = params[:answer_id].to_i
|
8
|
+
checked = params[:checked].to_s.downcase == "true" ? true : false
|
9
|
+
|
10
|
+
answer = Answer.find(answer_id)
|
11
|
+
|
12
|
+
if checked
|
13
|
+
if answer.question.single_choice?
|
14
|
+
UserAnswer.where(decidim_user_id: current_user.id, decidim_posts_answer_id: answer.question.answers.pluck(:id)).destroy_all
|
15
|
+
end
|
16
|
+
UserAnswer.find_or_create_by(decidim_user_id: current_user.id, decidim_posts_answer_id: answer_id)
|
17
|
+
else
|
18
|
+
UserAnswer.where(decidim_user_id: current_user.id, decidim_posts_answer_id: answer_id).destroy_all
|
19
|
+
end
|
20
|
+
|
21
|
+
# get count of user_answers for all answers of the question
|
22
|
+
user_answers_counts = {}
|
23
|
+
answer.question.answers.each do |a|
|
24
|
+
user_answers_counts[a.id] = UserAnswer.where(decidim_posts_answer_id: a.id).count
|
25
|
+
end
|
26
|
+
result = {
|
27
|
+
user_answers: user_answers_counts,
|
28
|
+
survey_responses_count: answer.question.post.survey_responses_count
|
29
|
+
}
|
30
|
+
|
31
|
+
render json: result, status: :ok
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Posts
|
5
|
+
class ResourceReactedEvent < Decidim::Events::SimpleEvent
|
6
|
+
i18n_attributes :reactor_nickname, :reactor_name, :reactor_path, :nickname, :resource_type
|
7
|
+
|
8
|
+
delegate :nickname, :name, to: :reactor, prefix: true
|
9
|
+
|
10
|
+
def nickname
|
11
|
+
reactor_nickname
|
12
|
+
end
|
13
|
+
|
14
|
+
def reactor_path
|
15
|
+
reactor.profile_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def resource_text
|
19
|
+
return resource.body if resource.respond_to? :body
|
20
|
+
return resource.description if resource.respond_to? :description
|
21
|
+
end
|
22
|
+
|
23
|
+
def resource_type
|
24
|
+
resource.class.model_name.human
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def reactor
|
30
|
+
@reactor ||= Decidim::UserPresenter.new(reactor_user)
|
31
|
+
end
|
32
|
+
|
33
|
+
def reactor_user
|
34
|
+
@reactor_user ||= Decidim::User.find_by(id: extra[:reactor_id])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Posts
|
5
|
+
class PostForm < Decidim::Form
|
6
|
+
include Decidim::TranslatableAttributes
|
7
|
+
include Decidim::AttachmentAttributes
|
8
|
+
# include Decidim::HasUploadValidations # should be included by AttachmentForm
|
9
|
+
|
10
|
+
mimic :post
|
11
|
+
|
12
|
+
#attribute :body, Decidim::Attributes::CleanString
|
13
|
+
# attribute :body, String
|
14
|
+
attribute :body, Decidim::Attributes::CleanString
|
15
|
+
attribute :category, String
|
16
|
+
attribute :enable_comments, Boolean, default: true
|
17
|
+
#attribute :body_template, String
|
18
|
+
#attribute :user_group_id, Integer
|
19
|
+
#attribute :category_id, Integer
|
20
|
+
#attribute :scope_id, Integer
|
21
|
+
attribute :attachment, AttachmentForm
|
22
|
+
#attribute :suggested_hashtags, Array[String]
|
23
|
+
attribute :questions, Array[QuestionForm]
|
24
|
+
attribute :highlighted, Boolean
|
25
|
+
attribute :fixed, Boolean
|
26
|
+
|
27
|
+
attachments_attribute :documents
|
28
|
+
|
29
|
+
validates :body, presence: true#, etiquette: true
|
30
|
+
# validates :body, length: { in: 15..150 }
|
31
|
+
validates :category, presence: true
|
32
|
+
validate :questions_validator
|
33
|
+
|
34
|
+
# validate :body_is_not_bare_template
|
35
|
+
validate :notify_missing_attachment_if_errored
|
36
|
+
|
37
|
+
alias component current_component
|
38
|
+
# delegate :categories, to: :current_component
|
39
|
+
|
40
|
+
def map_model(model)
|
41
|
+
self.body = translated_attribute(model.body)
|
42
|
+
self.highlighted = model.highlighted
|
43
|
+
self.fixed = model.fixed
|
44
|
+
self.category = model.category
|
45
|
+
self.enable_comments = model.enable_comments
|
46
|
+
|
47
|
+
self.questions = model.questions.map do |question|
|
48
|
+
QuestionForm.from_model(question)
|
49
|
+
end
|
50
|
+
|
51
|
+
# @suggested_hashtags = Decidim::ContentRenderers::HashtagRenderer.new(body).extra_hashtags.map(&:name).map(&:downcase)
|
52
|
+
|
53
|
+
# presenter = PostPresenter.new(model)
|
54
|
+
# self.body = presenter.editor_body(all_locales: body.is_a?(Hash))
|
55
|
+
|
56
|
+
self.documents = model.attachments
|
57
|
+
end
|
58
|
+
|
59
|
+
# Finds the Category from the category_id.
|
60
|
+
#
|
61
|
+
# Returns a Decidim::Category
|
62
|
+
# def category
|
63
|
+
# @category ||= categories.find_by(id: category_id)
|
64
|
+
# end
|
65
|
+
|
66
|
+
# def extra_hashtags
|
67
|
+
# @extra_hashtags ||= (component_automatic_hashtags + suggested_hashtags).uniq
|
68
|
+
# end
|
69
|
+
|
70
|
+
# def suggested_hashtags
|
71
|
+
# downcased_suggested_hashtags = super.to_set(&:downcase)
|
72
|
+
# component_suggested_hashtags.select { |hashtag| downcased_suggested_hashtags.member?(hashtag.downcase) }
|
73
|
+
# end
|
74
|
+
|
75
|
+
# def suggested_hashtag_checked?(hashtag)
|
76
|
+
# suggested_hashtags.member?(hashtag)
|
77
|
+
# end
|
78
|
+
|
79
|
+
# def component_automatic_hashtags
|
80
|
+
# @component_automatic_hashtags ||= ordered_hashtag_list(current_component.current_settings.automatic_hashtags)
|
81
|
+
# end
|
82
|
+
|
83
|
+
# def component_suggested_hashtags
|
84
|
+
# @component_suggested_hashtags ||= ordered_hashtag_list(current_component.current_settings.suggested_hashtags)
|
85
|
+
# end
|
86
|
+
|
87
|
+
def has_attachments?
|
88
|
+
post.has_attachments? && errors[:documents].empty? && documents.present?
|
89
|
+
end
|
90
|
+
|
91
|
+
def has_error_in_attachments?
|
92
|
+
errors[:documents].present?
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
# def body_is_not_bare_template
|
98
|
+
# return if body_template.blank?
|
99
|
+
|
100
|
+
# errors.add(:body, :cant_be_equal_to_template) if body.presence == body_template.presence
|
101
|
+
# end
|
102
|
+
|
103
|
+
# This method will add an error to the "documents" field only if there is any error
|
104
|
+
# in any other field. This is needed because when the form has an error, the attachment
|
105
|
+
# is lost, so we need a way to inform the user of this problem.
|
106
|
+
def notify_missing_attachment_if_errored
|
107
|
+
errors.add(:documents, :needs_to_be_reattached) if errors.any? && documents.present?
|
108
|
+
end
|
109
|
+
|
110
|
+
def questions_validator
|
111
|
+
@questions_validator ||= questions.reject(&:deleted).each do |question|
|
112
|
+
errors.add(:questions, I18n.t("decidim.posts.posts.form.question_too_short")) if question.title.length <= 3
|
113
|
+
end.map(&:title).uniq
|
114
|
+
end
|
115
|
+
|
116
|
+
# def ordered_hashtag_list(string)
|
117
|
+
# string.to_s.split.compact_blank.uniq.sort_by(&:parameterize)
|
118
|
+
# end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Posts
|
3
|
+
class QuestionForm < Decidim::Form
|
4
|
+
include Decidim::TranslatableAttributes
|
5
|
+
|
6
|
+
mimic :question
|
7
|
+
|
8
|
+
attribute :title, Decidim::Attributes::CleanString
|
9
|
+
attribute :answers, Array[AnswerForm]
|
10
|
+
attribute :deleted, Boolean, default: false
|
11
|
+
attribute :question_type, String
|
12
|
+
|
13
|
+
validates :title, presence: true
|
14
|
+
|
15
|
+
def map_model(model)
|
16
|
+
self.title = translated_attribute(model.title)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Posts
|
5
|
+
# Custom helpers, scoped to the feeds engine.
|
6
|
+
#
|
7
|
+
module ApplicationHelper
|
8
|
+
include PaginateHelper
|
9
|
+
include SanitizeHelper
|
10
|
+
# include Decidim::Posts::PostsHelper
|
11
|
+
include ::Decidim::EndorsableHelper
|
12
|
+
include ::Decidim::FollowableHelper
|
13
|
+
include Decidim::Comments::CommentsHelper
|
14
|
+
|
15
|
+
def posts_component_for_meeting(meeting)
|
16
|
+
meeting.component.participatory_space.components.find_by(manifest_name: "posts")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Posts
|
5
|
+
module PostCellsHelper
|
6
|
+
include Decidim::Posts::ApplicationHelper
|
7
|
+
include Decidim::Posts::Engine.routes.url_helpers
|
8
|
+
include Decidim::LayoutHelper
|
9
|
+
include Decidim::ApplicationHelper
|
10
|
+
include Decidim::TranslationsHelper
|
11
|
+
include Decidim::ResourceReferenceHelper
|
12
|
+
include Decidim::TranslatableAttributes
|
13
|
+
include Decidim::CardHelper
|
14
|
+
|
15
|
+
delegate :body, :category, to: :model
|
16
|
+
|
17
|
+
def current_settings
|
18
|
+
model.component.current_settings
|
19
|
+
end
|
20
|
+
|
21
|
+
def component_settings
|
22
|
+
model.component.settings
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_component
|
26
|
+
model.component
|
27
|
+
end
|
28
|
+
|
29
|
+
def participatory_space
|
30
|
+
@participatory_space ||= current_component.participatory_space
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Posts
|
5
|
+
# Custom helpers used in posts views
|
6
|
+
module PostsHelper
|
7
|
+
include Decidim::ApplicationHelper
|
8
|
+
include Decidim::TranslationsHelper
|
9
|
+
include Decidim::ResourceHelper
|
10
|
+
include Decidim::Meetings::ApplicationHelper
|
11
|
+
|
12
|
+
def calendar_months
|
13
|
+
[Date.current, Date.current.next_month]
|
14
|
+
end
|
15
|
+
|
16
|
+
def collection
|
17
|
+
@collection ||= meetings.limit(limit)
|
18
|
+
end
|
19
|
+
|
20
|
+
def meetings
|
21
|
+
@meetings ||= show_upcoming_meetings? ? upcoming_meetings : past_meetings
|
22
|
+
end
|
23
|
+
|
24
|
+
def limit
|
25
|
+
3
|
26
|
+
end
|
27
|
+
|
28
|
+
def participatory_space
|
29
|
+
@participatory_space ||= current_component.participatory_space
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Posts
|
5
|
+
module ReactionHelper
|
6
|
+
def reaction_icon(icon_name)
|
7
|
+
emojis = {
|
8
|
+
"heart": "❤️",
|
9
|
+
"laugh": "😂",
|
10
|
+
"surprise": "😮",
|
11
|
+
"sad": "😢",
|
12
|
+
"angry": "😡",
|
13
|
+
"like": "👍"
|
14
|
+
}
|
15
|
+
|
16
|
+
return "?" unless emojis.key?(icon_name.to_sym)
|
17
|
+
|
18
|
+
emojis[icon_name.to_sym]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Posts
|
3
|
+
class Answer < Feeds::ApplicationRecord
|
4
|
+
include Decidim::TranslatableResource
|
5
|
+
include Decidim::TranslatableAttributes
|
6
|
+
|
7
|
+
belongs_to :question, class_name: "Decidim::Posts::Question", foreign_key: "decidim_posts_question_id"
|
8
|
+
has_many :user_answers, class_name: "Decidim::Posts::UserAnswer", dependent: :destroy, foreign_key: "decidim_posts_answer_id"
|
9
|
+
|
10
|
+
translatable_fields :title
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|