decidim-posts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,116 @@
|
|
|
1
|
+
module Decidim
|
|
2
|
+
module Posts
|
|
3
|
+
class Post < Feeds::ApplicationRecord
|
|
4
|
+
include Decidim::Resourceable
|
|
5
|
+
include Decidim::Authorable
|
|
6
|
+
include Decidim::Reportable
|
|
7
|
+
include Decidim::HasAttachments
|
|
8
|
+
include Decidim::Comments::Commentable
|
|
9
|
+
include Decidim::Searchable
|
|
10
|
+
include Decidim::Endorsable
|
|
11
|
+
include Decidim::TranslatableResource
|
|
12
|
+
include Decidim::TranslatableAttributes
|
|
13
|
+
include Decidim::Fingerprintable
|
|
14
|
+
include Decidim::HasComponent
|
|
15
|
+
include Decidim::FilterableResource
|
|
16
|
+
include Decidim::Posts::Reactionable
|
|
17
|
+
# include Decidim::Loggable
|
|
18
|
+
# include Decidim::DownloadYourData
|
|
19
|
+
# include Decidim::Randomable
|
|
20
|
+
# include Decidim::ScopableResource
|
|
21
|
+
# include Decidim::HasReference
|
|
22
|
+
# include Decidim::HasCategory
|
|
23
|
+
# include Decidim::Followable
|
|
24
|
+
# include Decidim::Traceable
|
|
25
|
+
# include Decidim::NewsletterParticipant
|
|
26
|
+
|
|
27
|
+
# belongs_to :organization, class_name: "Decidim::Organization"
|
|
28
|
+
|
|
29
|
+
has_many :questions, class_name: "Decidim::Posts::Question", dependent: :destroy, foreign_key: "decidim_posts_post_id"
|
|
30
|
+
# accepts_nested_attributes_for :questions, reject_if: ->(attributes){ attributes['name'].blank? }, allow_destroy: true
|
|
31
|
+
|
|
32
|
+
component_manifest_name "posts"
|
|
33
|
+
|
|
34
|
+
translatable_fields :body
|
|
35
|
+
|
|
36
|
+
fingerprint fields: [:body]
|
|
37
|
+
|
|
38
|
+
validates :body, presence: true
|
|
39
|
+
|
|
40
|
+
searchable_fields(
|
|
41
|
+
{
|
|
42
|
+
participatory_space: { component: :participatory_space },
|
|
43
|
+
A: :body,
|
|
44
|
+
datetime: :created_at
|
|
45
|
+
},
|
|
46
|
+
index_on_create: true,
|
|
47
|
+
index_on_update: true
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
scope :filter_category, ->(category) { where(category: category) if category.present? }
|
|
51
|
+
|
|
52
|
+
# Posts don't have a title, but Commentable requires it, so let's extract the first words of each translation of the body
|
|
53
|
+
def title
|
|
54
|
+
truncated_body = {}
|
|
55
|
+
body.each do |locale, translations|
|
|
56
|
+
if locale == "machine_translations"
|
|
57
|
+
truncated_body[locale] = {}
|
|
58
|
+
translations.each do |key, value|
|
|
59
|
+
next if value.class != String
|
|
60
|
+
truncated_body[locale][key] = value.truncate_words(4)
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
next if translations.class != String
|
|
64
|
+
truncated_body[locale] = translations.truncate_words(4)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
truncated_body
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def editable_by?(user)
|
|
71
|
+
user == author
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def deleteable_by?(user)
|
|
75
|
+
user == author || user.admin?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Public: Overrides the `reported_content_url` Reportable concern method.
|
|
79
|
+
def reported_content_url
|
|
80
|
+
ResourceLocatorPresenter.new(self).url
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Public: Overrides the `reported_attributes` Reportable concern method.
|
|
84
|
+
def reported_attributes
|
|
85
|
+
[:body]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Public: Overrides the `reported_searchable_content_extras` Reportable concern method.
|
|
89
|
+
def reported_searchable_content_extras
|
|
90
|
+
[author.name]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def survey_responses_count
|
|
94
|
+
# questions.includes(answers: :user_answers).map(&:answers).flatten.map(&:user_answers).flatten.pluck(:decidim_user_id).uniq.count
|
|
95
|
+
answer_ids = questions.includes(:answers).map(&:answers).flatten.pluck(:id)
|
|
96
|
+
@survey_responses_count ||= UserAnswer.where(decidim_posts_answer_id: answer_ids).distinct.count(:decidim_user_id)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Public: Overrides the `comments_have_alignment?` Commentable concern method.
|
|
100
|
+
# Whether the object's comments can have alignment or not. It enables the
|
|
101
|
+
# alignment selector in the add new comment form.
|
|
102
|
+
def comments_have_alignment?
|
|
103
|
+
false
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Public: Overrides the `comments_have_votes?` Commentable concern method.
|
|
107
|
+
def comments_have_votes?
|
|
108
|
+
true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def users_to_notify_on_comment_created
|
|
112
|
+
[author]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Decidim
|
|
2
|
+
module Posts
|
|
3
|
+
class Question < Feeds::ApplicationRecord
|
|
4
|
+
include Decidim::TranslatableResource
|
|
5
|
+
include Decidim::TranslatableAttributes
|
|
6
|
+
|
|
7
|
+
belongs_to :post, class_name: "Decidim::Posts::Post", foreign_key: "decidim_posts_post_id"
|
|
8
|
+
has_many :answers, class_name: "Decidim::Posts::Answer", dependent: :destroy, foreign_key: "decidim_posts_question_id"
|
|
9
|
+
# accepts_nested_attributes_for :answers, allow_destroy: true
|
|
10
|
+
|
|
11
|
+
enum question_type: { single_choice: 0, multiple_choice: 1 }
|
|
12
|
+
|
|
13
|
+
translatable_fields :title
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Posts
|
|
5
|
+
class Reaction < ApplicationRecord
|
|
6
|
+
include Decidim::Authorable
|
|
7
|
+
|
|
8
|
+
belongs_to :resource, polymorphic: true, counter_cache: true#, touch: true
|
|
9
|
+
belongs_to :reaction_type, class_name: "Decidim::Posts::ReactionType"
|
|
10
|
+
|
|
11
|
+
validates :reaction_type, presence: true
|
|
12
|
+
|
|
13
|
+
def self.reaction_types
|
|
14
|
+
Decidim::Posts::ReactionType.all
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def organization
|
|
18
|
+
resource&.component&.organization
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Posts
|
|
5
|
+
# A reaction type for posts.
|
|
6
|
+
class ReactionType < Decidim::ApplicationRecord
|
|
7
|
+
has_many :reactions, dependent: :destroy
|
|
8
|
+
|
|
9
|
+
validates :name, presence: true, uniqueness: true
|
|
10
|
+
validates :icon_name, presence: true
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Decidim
|
|
2
|
+
module Posts
|
|
3
|
+
class UserAnswer < Feeds::ApplicationRecord
|
|
4
|
+
belongs_to :decidim_posts_answer, class_name: 'Decidim::Posts::Answer', foreign_key: "decidim_posts_answer_id"
|
|
5
|
+
belongs_to :decidim_user, class_name: 'Decidim::User', foreign_key: "decidim_user_id"
|
|
6
|
+
|
|
7
|
+
# validate combination of user and answer
|
|
8
|
+
validates :decidim_user_id, uniqueness: { scope: :decidim_posts_answer_id }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import 'stylesheets/decidim/posts/posts';
|
|
@@ -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,112 @@
|
|
|
1
|
+
const carousel = (() => {
|
|
2
|
+
let startX;
|
|
3
|
+
|
|
4
|
+
const setActiveItem = (galleryId, index, direction = null) => {
|
|
5
|
+
const galleryItems = document.querySelectorAll(`#${galleryId} li`);
|
|
6
|
+
const navDots = document.querySelectorAll(
|
|
7
|
+
`.posts__post_gallery_nav_dot[data-target="${galleryId}"]`
|
|
8
|
+
);
|
|
9
|
+
let activeIndex = index;
|
|
10
|
+
|
|
11
|
+
if (direction) {
|
|
12
|
+
const currentIndex = Array.from(galleryItems).findIndex((item) =>
|
|
13
|
+
item.classList.contains('active')
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
if (direction === 'left' && currentIndex < galleryItems.length - 1) {
|
|
17
|
+
activeIndex = currentIndex + 1;
|
|
18
|
+
} else if (direction === 'right' && currentIndex > 0) {
|
|
19
|
+
activeIndex = currentIndex - 1;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
galleryItems.forEach((item, idx) => {
|
|
24
|
+
if (idx === activeIndex) {
|
|
25
|
+
item.classList.add('active');
|
|
26
|
+
} else {
|
|
27
|
+
item.classList.remove('active');
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
navDots.forEach((dot, idx) => {
|
|
32
|
+
const innerSpan = dot.querySelector('span');
|
|
33
|
+
if (innerSpan) {
|
|
34
|
+
if (idx === activeIndex) {
|
|
35
|
+
innerSpan.classList.add('bg-feeds-notification');
|
|
36
|
+
} else {
|
|
37
|
+
innerSpan.classList.remove('bg-feeds-notification');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Show only the first 8 dots and update the visible range as the user navigates
|
|
43
|
+
const visibleRange = 8;
|
|
44
|
+
let start = 0;
|
|
45
|
+
let end = visibleRange;
|
|
46
|
+
|
|
47
|
+
if (activeIndex >= end - 1) {
|
|
48
|
+
start = activeIndex - visibleRange + 2;
|
|
49
|
+
end = activeIndex + 2;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
start = Math.max(0, start);
|
|
53
|
+
end = Math.min(navDots.length, end);
|
|
54
|
+
|
|
55
|
+
navDots.forEach((dot, idx) => {
|
|
56
|
+
if (idx >= start && idx < end) {
|
|
57
|
+
dot.style.display = 'flex';
|
|
58
|
+
} else {
|
|
59
|
+
dot.style.display = 'none';
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const attachSwipeListeners = (galleryId) => {
|
|
65
|
+
const gallery = document.getElementById(galleryId);
|
|
66
|
+
|
|
67
|
+
gallery.addEventListener('touchstart', (e) => {
|
|
68
|
+
startX = e.touches[0].clientX;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
gallery.addEventListener('touchend', (e) => {
|
|
72
|
+
const endX = e.changedTouches[0].clientX;
|
|
73
|
+
const galleryItems = document.querySelectorAll(`#${galleryId} li`);
|
|
74
|
+
const currentIndex = Array.from(galleryItems).findIndex((item) =>
|
|
75
|
+
item.classList.contains('active')
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (startX - endX > 50 && currentIndex < galleryItems.length - 1) {
|
|
79
|
+
setActiveItem(galleryId, null, 'left');
|
|
80
|
+
} else if (startX - endX < -50 && currentIndex > 0) {
|
|
81
|
+
setActiveItem(galleryId, null, 'right');
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const attachEventListenersToDots = () => {
|
|
87
|
+
document.querySelectorAll('.posts__post_gallery_nav_dot').forEach((dot) => {
|
|
88
|
+
dot.addEventListener('click', function () {
|
|
89
|
+
const targetGalleryId = this.getAttribute('data-target');
|
|
90
|
+
const targetIndex = parseInt(this.getAttribute('data-index'), 10);
|
|
91
|
+
setActiveItem(targetGalleryId, targetIndex);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const init = () => {
|
|
97
|
+
attachEventListenersToDots();
|
|
98
|
+
// Initialize swipe listeners for each gallery
|
|
99
|
+
document.querySelectorAll('.posts__post_gallery').forEach((gallery) => {
|
|
100
|
+
attachSwipeListeners(gallery.id);
|
|
101
|
+
});
|
|
102
|
+
// Initialize the visible dots for each gallery
|
|
103
|
+
document.querySelectorAll('.posts__post_gallery_nav_dot').forEach((dot) => {
|
|
104
|
+
const targetGalleryId = dot.getAttribute('data-target');
|
|
105
|
+
setActiveItem(targetGalleryId, 0);
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
return { init };
|
|
110
|
+
})();
|
|
111
|
+
|
|
112
|
+
export default carousel;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export function host_status() {
|
|
2
|
+
const changeStatusButtons = document.querySelectorAll('.changeStatusButton');
|
|
3
|
+
|
|
4
|
+
changeStatusButtons.forEach(function (button) {
|
|
5
|
+
button.addEventListener('click', handleStatusChange);
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const cancelButton = document.getElementById(
|
|
9
|
+
'confirmationModal__cancelButton'
|
|
10
|
+
);
|
|
11
|
+
cancelButton.addEventListener('click', function () {
|
|
12
|
+
const confirmationModal = document.getElementById('confirmationModal');
|
|
13
|
+
confirmationModal.close();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function handleStatusChange(event) {
|
|
17
|
+
const button = event.currentTarget;
|
|
18
|
+
const postId = button.dataset.postId;
|
|
19
|
+
const newStatus = button.dataset.postStatus;
|
|
20
|
+
const confirmationModalMsg = button.dataset.dialogmsg;
|
|
21
|
+
|
|
22
|
+
const confirmationModal = document.getElementById('confirmationModal');
|
|
23
|
+
const confirmButton = document.getElementById(
|
|
24
|
+
'confirmationModal__confirmButton'
|
|
25
|
+
);
|
|
26
|
+
const confirmButtons = confirmationModal.querySelector(
|
|
27
|
+
'.confirmationModal__buttons'
|
|
28
|
+
);
|
|
29
|
+
const confirmationModalResponse = confirmationModal.querySelector(
|
|
30
|
+
'.confirmationModal__response'
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
confirmationModalResponse.innerHTML = confirmationModalMsg;
|
|
34
|
+
confirmationModal.showModal();
|
|
35
|
+
|
|
36
|
+
const confirmClickHandler = function () {
|
|
37
|
+
confirmButtons.style.display = 'none';
|
|
38
|
+
confirmationModalResponse.innerHTML =
|
|
39
|
+
window.translations.dialog.dialogBodyResponse;
|
|
40
|
+
const params = new URLSearchParams({
|
|
41
|
+
id: postId,
|
|
42
|
+
status: newStatus,
|
|
43
|
+
});
|
|
44
|
+
Rails.ajax({
|
|
45
|
+
url: 'change_status/?' + params.toString(),
|
|
46
|
+
type: 'GET',
|
|
47
|
+
success: function (response) {
|
|
48
|
+
confirmationModal.close();
|
|
49
|
+
confirmButtons.style.display = 'flex';
|
|
50
|
+
confirmationModalResponse.innerText =
|
|
51
|
+
window.translations.dialog.dialogBodyMsg;
|
|
52
|
+
|
|
53
|
+
const postElement = document.getElementById(`feeds_post-${postId}`);
|
|
54
|
+
postElement.innerHTML = 'updating status...';
|
|
55
|
+
postElement.innerHTML = response.new_content;
|
|
56
|
+
|
|
57
|
+
const updatedButtons = postElement.querySelectorAll(
|
|
58
|
+
'.changeStatusButton'
|
|
59
|
+
);
|
|
60
|
+
updatedButtons.forEach(function (updatedButton) {
|
|
61
|
+
updatedButton.addEventListener('click', handleStatusChange);
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
error: function (error) {
|
|
65
|
+
console.error('Error changing status:', error);
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
confirmButton.removeEventListener('click', confirmClickHandler);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
confirmButton.removeEventListener('click', confirmClickHandler);
|
|
73
|
+
confirmButton.addEventListener('click', confirmClickHandler);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const newFeed = document.getElementById('posts__post_newElement');
|
|
2
|
+
const newFeedOpener = document.querySelectorAll(
|
|
3
|
+
'.posts__post_newElement-opener'
|
|
4
|
+
);
|
|
5
|
+
const newFeedCloser = newFeed.querySelector('.posts__post_newElement-closer');
|
|
6
|
+
let lastFocusedButton = null;
|
|
7
|
+
|
|
8
|
+
newFeedOpener.forEach(function (opener) {
|
|
9
|
+
opener.addEventListener('click', function () {
|
|
10
|
+
let isExpanded = opener.getAttribute('aria-expanded') === 'true';
|
|
11
|
+
opener.setAttribute('aria-expanded', !isExpanded);
|
|
12
|
+
const activeFilter = newFeed.getAttribute('data-active-filter');
|
|
13
|
+
const buttonToActivate = activeFilter
|
|
14
|
+
? Array.from(categoryButtons).find(
|
|
15
|
+
(button) => button.getAttribute('data-category') === activeFilter
|
|
16
|
+
)
|
|
17
|
+
: categoryButtons[0];
|
|
18
|
+
activateCategory(buttonToActivate || categoryButtons[0]);
|
|
19
|
+
newFeed.classList.toggle('open');
|
|
20
|
+
lastFocusedButton = this;
|
|
21
|
+
document.getElementById('post_body').focus();
|
|
22
|
+
document.body.style.overflow = 'hidden';
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
newFeed.addEventListener('click', function (event) {
|
|
27
|
+
if (event.target === newFeed) {
|
|
28
|
+
closeDialog();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
newFeedCloser.addEventListener('click', closeDialog);
|
|
33
|
+
|
|
34
|
+
document.addEventListener('keydown', function (event) {
|
|
35
|
+
if (event.key === 'Escape') {
|
|
36
|
+
closeDialog();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const categoryButtons = document.querySelectorAll('.category-selection button');
|
|
41
|
+
const meetingForm = document.querySelector('.meetings_form');
|
|
42
|
+
const postForm = document.querySelector('.posts_form');
|
|
43
|
+
const surveyDiv = document.getElementById('extraFieldsForSurvey');
|
|
44
|
+
const newFeedLiveRegion = document.getElementById(
|
|
45
|
+
'posts__post_newElement_Form-LiveRegion'
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
categoryButtons.forEach((button) => {
|
|
49
|
+
button.addEventListener('click', function () {
|
|
50
|
+
activateCategory(this);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function hideAllForms() {
|
|
55
|
+
meetingForm.classList.remove('open');
|
|
56
|
+
postForm.classList.remove('open');
|
|
57
|
+
surveyDiv.classList.remove('open');
|
|
58
|
+
newFeedLiveRegion.innerHTML = '';
|
|
59
|
+
categoryButtons.forEach(function (button) {
|
|
60
|
+
button.classList.remove('active');
|
|
61
|
+
button.setAttribute('aria-pressed', 'false');
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function closeDialog() {
|
|
66
|
+
newFeedOpener.forEach(function (opener) {
|
|
67
|
+
opener.setAttribute('aria-expanded', 'false');
|
|
68
|
+
newFeed.classList.remove('open');
|
|
69
|
+
lastFocusedButton.focus();
|
|
70
|
+
document.body.style.overflow = 'auto';
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function activateCategory(button) {
|
|
75
|
+
hideAllForms();
|
|
76
|
+
button.classList.add('active');
|
|
77
|
+
button.setAttribute('aria-pressed', 'true');
|
|
78
|
+
const category = button.getAttribute('data-category');
|
|
79
|
+
newFeedLiveRegion.innerHTML = window.translations.newFeedLiveRegion[category];
|
|
80
|
+
|
|
81
|
+
const postBody = document.getElementById('post_body');
|
|
82
|
+
const meetingTitle = document.getElementById('meeting_title');
|
|
83
|
+
if (category === 'calendar') {
|
|
84
|
+
meetingForm.classList.add('open');
|
|
85
|
+
meetingForm.querySelector('.form-error').classList.remove('is-visible');
|
|
86
|
+
meetingTitle.classList.remove('is-invalid-input');
|
|
87
|
+
document.getElementById('meeting_title').focus();
|
|
88
|
+
} else {
|
|
89
|
+
postForm.classList.add('open');
|
|
90
|
+
postForm.querySelector('.form-error').classList.remove('is-visible');
|
|
91
|
+
postBody.classList.remove('is-invalid-input');
|
|
92
|
+
postBody.focus();
|
|
93
|
+
document.getElementById('post_category').value = category;
|
|
94
|
+
if (category === 'survey') surveyDiv.classList.add('open');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { closeDialog, activateCategory, hideAllForms };
|