diff --git a/back/app/controllers/web_api/v1/action_descriptors_controller.rb b/back/app/controllers/web_api/v1/action_descriptors_controller.rb
deleted file mode 100644
index 18b724bcb092..000000000000
--- a/back/app/controllers/web_api/v1/action_descriptors_controller.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::ActionDescriptorsController < ApplicationController
- skip_before_action :authenticate_user
- skip_after_action :verify_authorized, only: [:initiatives]
-
- def initiatives
- descriptors = Permissions::InitiativePermissionsService.new(current_user).action_descriptors
- render(json: raw_json(descriptors))
- end
-end
diff --git a/back/app/controllers/web_api/v1/files_controller.rb b/back/app/controllers/web_api/v1/files_controller.rb
index 0d96eea89f0f..8b374627ee0c 100644
--- a/back/app/controllers/web_api/v1/files_controller.rb
+++ b/back/app/controllers/web_api/v1/files_controller.rb
@@ -13,13 +13,6 @@ class WebApi::V1::FilesController < ApplicationController
file_relationship: :idea_files,
container_id: :idea_id
},
- 'Initiative' => {
- container_class: Initiative,
- file_class: InitiativeFile,
- policy_scope_class: InitiativeFilePolicy::Scope,
- file_relationship: :initiative_files,
- container_id: :initiative_id
- },
'Project' => {
container_class: Project,
file_class: ProjectFile,
diff --git a/back/app/controllers/web_api/v1/images_controller.rb b/back/app/controllers/web_api/v1/images_controller.rb
index 925f64124fb1..339f4598a8e6 100644
--- a/back/app/controllers/web_api/v1/images_controller.rb
+++ b/back/app/controllers/web_api/v1/images_controller.rb
@@ -18,13 +18,6 @@ class WebApi::V1::ImagesController < ApplicationController
image_relationship: :event_images,
container_id: :event_id
},
- 'Initiative' => {
- container_class: Initiative,
- image_class: InitiativeImage,
- policy_scope_class: InitiativeImagePolicy::Scope,
- image_relationship: :initiative_images,
- container_id: :initiative_id
- },
'Project' => {
container_class: Project,
image_class: ProjectImage,
diff --git a/back/app/controllers/web_api/v1/initiative_status_changes_controller.rb b/back/app/controllers/web_api/v1/initiative_status_changes_controller.rb
deleted file mode 100644
index f67d986c2141..000000000000
--- a/back/app/controllers/web_api/v1/initiative_status_changes_controller.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::InitiativeStatusChangesController < ApplicationController
- before_action :set_initiative, only: %i[index create]
- before_action :set_change, only: %i[show]
- skip_before_action :authenticate_user
-
- def index
- @changes = policy_scope(InitiativeStatusChange)
- .where(initiative: @initiative)
- .order(created_at: :desc)
- @changes = paginate @changes
-
- render json: linked_json(@changes, WebApi::V1::InitiativeStatusChangeSerializer, params: jsonapi_serializer_params)
- end
-
- def show
- render json: WebApi::V1::InitiativeStatusChangeSerializer.new(
- @change,
- params: jsonapi_serializer_params
- ).serializable_hash
- end
-
- def create
- attributes = status_change_params.to_h
- if attributes[:initiative_status_id] == @initiative.initiative_status_id
- skip_authorization
- render json: { errors: { base: [{ error: 'initiative_status_transition_without_change' }] } }, status: :unprocessable_entity
- return
- end
- if attributes[:official_feedback_attributes].present? # If not nil nor empty hash
- attributes[:official_feedback_attributes].merge! post_id: @initiative.id, post_type: 'Initiative'
- else
- attributes.except! :official_feedback_attributes
- end
- @change = InitiativeStatusChange.new attributes
- @change.initiative = @initiative
- @change.user ||= current_user
- authorize @change
- SideFxInitiativeStatusChangeService.new.before_create @change, current_user
- if InitiativeStatusService.new.transition_allowed?(
- @initiative,
- @initiative.initiative_status,
- @change.initiative_status,
- with_feedback: attributes[:official_feedback_attributes].present? || attributes[:official_feedback_id]
- )
- if @change.save
- SideFxInitiativeStatusChangeService.new.after_create @change, current_user
- render json: WebApi::V1::InitiativeStatusChangeSerializer.new(
- @change,
- params: jsonapi_serializer_params
- ).serializable_hash, status: :created
- else
- render json: { errors: @change.errors.details }, status: :unprocessable_entity
- end
- else
- render json: { errors: { base: [{ error: 'initiative_status_transition_not_allowed' }] } }, status: :unprocessable_entity
- end
- end
-
- private
-
- def set_change
- @change = InitiativeStatusChange.find params[:id]
- authorize @change
- end
-
- def set_initiative
- @initiative = Initiative.find params[:initiative_id]
- end
-
- def status_change_params
- params.require(:initiative_status_change).permit(
- :initiative_status_id,
- :user_id,
- :official_feedback_id,
- official_feedback_attributes: [
- body_multiloc: CL2_SUPPORTED_LOCALES,
- author_multiloc: CL2_SUPPORTED_LOCALES
- ]
- )
- end
-end
diff --git a/back/app/controllers/web_api/v1/initiative_statuses_controller.rb b/back/app/controllers/web_api/v1/initiative_statuses_controller.rb
deleted file mode 100644
index 76398d7154c6..000000000000
--- a/back/app/controllers/web_api/v1/initiative_statuses_controller.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::InitiativeStatusesController < ApplicationController
- before_action :set_initiative_status, only: :show
- skip_before_action :authenticate_user
-
- def index
- @initiative_statuses = policy_scope(InitiativeStatus).order(:ordering)
- render json: WebApi::V1::InitiativeStatusSerializer.new(@initiative_statuses, params: jsonapi_serializer_params).serializable_hash
- end
-
- def show
- render json: WebApi::V1::InitiativeStatusSerializer.new(@initiative_status, params: jsonapi_serializer_params).serializable_hash
- end
-
- private
-
- def set_initiative_status
- @initiative_status = InitiativeStatus.find(params[:id])
- authorize @initiative_status
- end
-end
diff --git a/back/app/controllers/web_api/v1/initiatives_controller.rb b/back/app/controllers/web_api/v1/initiatives_controller.rb
deleted file mode 100644
index 9049aea14cb8..000000000000
--- a/back/app/controllers/web_api/v1/initiatives_controller.rb
+++ /dev/null
@@ -1,244 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::InitiativesController < ApplicationController
- include BlockingProfanity
-
- before_action :set_initiative, only: %i[show update destroy allowed_transitions accept_cosponsorship_invite]
- skip_before_action :authenticate_user
- skip_after_action :verify_authorized, only: %i[index_xlsx index_initiative_markers filter_counts]
-
- rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
-
- def index
- initiatives = InitiativesFinder.new(
- params,
- current_user: current_user,
- scope: policy_scope(Initiative),
- includes: %i[author assignee topics areas]
- ).find_records
- initiatives = paginate SortByParamsService.new.sort_initiatives(initiatives, params, current_user)
- render json: linked_json(initiatives, WebApi::V1::InitiativeSerializer, serialization_options_for(initiatives))
- end
-
- def index_initiative_markers
- initiatives = InitiativesFinder.new(
- params,
- current_user: current_user,
- scope: policy_scope(Initiative)
- ).find_records
- initiatives = paginate SortByParamsService.new.sort_initiatives(initiatives, params, current_user)
- render json: linked_json(initiatives, WebApi::V1::PostMarkerSerializer, params: jsonapi_serializer_params)
- end
-
- def index_xlsx
- authorize :initiative, :index_xlsx?
- initiatives = InitiativesFinder.new(
- params,
- current_user: current_user,
- scope: policy_scope(Initiative).where(publication_status: 'published'),
- includes: %i[author cosponsors initiative_status topics areas]
- ).find_records
- initiatives = SortByParamsService.new.sort_initiatives(initiatives, params, current_user)
-
- I18n.with_locale(current_user&.locale) do
- xlsx = XlsxService.new.generate_initiatives_xlsx(
- initiatives,
- view_private_attributes: policy(User).view_private_attributes?
- )
-
- xlsx_content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
- send_data(xlsx, type: xlsx_content_type, filename: 'initiatives.xlsx')
- end
- end
-
- def filter_counts
- initiatives = policy_scope(Initiative)
- search_last_names = !UserDisplayNameService.new(AppConfiguration.instance, current_user).restricted?
- initiatives = PostsFilteringService.new.apply_common_initiative_index_filters(
- initiatives, params,
- search_last_names
- )
- counts = {
- 'initiative_status_id' => {},
- 'area_id' => {},
- 'topic_id' => {}
- }
- attributes = %w[initiative_status_id area_id topic_id]
- initiatives
- .joins('FULL OUTER JOIN initiatives_topics ON initiatives_topics.initiative_id = initiatives.id')
- .joins('FULL OUTER JOIN areas_initiatives ON areas_initiatives.initiative_id = initiatives.id')
- .joins('FULL OUTER JOIN initiative_initiative_statuses ON initiative_initiative_statuses.initiative_id = initiatives.id')
- .select('initiative_initiative_statuses.initiative_status_id, areas_initiatives.area_id, initiatives_topics.topic_id, COUNT(DISTINCT(initiatives.id)) as count')
- .reorder(nil) # Avoids SQL error on GROUP BY when a search string is used
- .group('GROUPING SETS (initiative_initiative_statuses.initiative_status_id, areas_initiatives.area_id, initiatives_topics.topic_id)')
- .each do |record|
- attributes.each do |attribute|
- id = record.send attribute
- counts[attribute][id] = record.count if id
- end
- end
- counts['total'] = initiatives.reorder(nil).distinct.count # reorder(nil) avoids SQL error on SELECT DISTINCT when a search string is used
- render json: raw_json(counts)
- end
-
- def show
- render json: WebApi::V1::InitiativeSerializer.new(
- @initiative,
- params: jsonapi_serializer_params,
- include: %i[author cosponsors topics areas user_reaction initiative_images]
- ).serializable_hash
- end
-
- def by_slug
- @initiative = Initiative.find_by!(slug: params[:slug])
- authorize @initiative
- show
- end
-
- def create
- service = SideFxInitiativeService.new
-
- @initiative = Initiative.new(permitted_attributes(Initiative))
- @initiative.author ||= current_user
-
- service.before_create(@initiative, current_user)
-
- authorize @initiative
- if anonymous_not_allowed?
- render json: { errors: { base: [{ error: :anonymous_participation_not_allowed }] } }, status: :unprocessable_entity
- return
- end
- verify_profanity @initiative
-
- save_options = {}
- save_options[:context] = :publication if params.dig(:initiative, :publication_status) == 'published'
- ActiveRecord::Base.transaction do
- if @initiative.save(**save_options)
- service.after_create(@initiative, current_user)
- render json: WebApi::V1::InitiativeSerializer.new(
- @initiative.reload,
- params: jsonapi_serializer_params,
- include: %i[author cosponsors topics areas user_reaction initiative_images]
- ).serializable_hash, status: :created
- else
- render json: { errors: @initiative.errors.details }, status: :unprocessable_entity
- end
- end
- end
-
- def update
- service = SideFxInitiativeService.new
-
- cosponsor_ids = @initiative.cosponsors.map(&:id)
- initiative_params = permitted_attributes(@initiative)
- @initiative.assign_attributes(initiative_params)
- remove_image_if_requested!(@initiative, initiative_params, :header_bg)
-
- authorize @initiative
- if anonymous_not_allowed?
- render json: { errors: { base: [{ error: :anonymous_participation_not_allowed }] } }, status: :unprocessable_entity
- return
- end
- verify_profanity @initiative
-
- service.before_update(@initiative, current_user)
-
- save_options = {}
- save_options[:context] = :publication if params.dig(:initiative, :publication_status) == 'published'
- saved = nil
- ActiveRecord::Base.transaction do
- saved = @initiative.save(**save_options)
- if saved
- service.after_update(@initiative, current_user, cosponsor_ids)
- end
- end
-
- # Keeping `render` outside of the transaction is better anyway.
- # Additionally, if we wouldn't do it here, we're running into an issue
- # where carrierwave is not storing the actual header_bg file on the
- # filesystem. The root cause it not exactly clear.
- if saved
- render json: WebApi::V1::InitiativeSerializer.new(
- @initiative.reload,
- params: jsonapi_serializer_params,
- include: %i[author cosponsors topics areas user_reaction initiative_images]
- ).serializable_hash, status: :ok
- else
- render json: { errors: @initiative.errors.details }, status: :unprocessable_entity
- end
- end
-
- def destroy
- service = SideFxInitiativeService.new
-
- initiative = @initiative.destroy
- if initiative.destroyed?
- service.after_destroy(initiative, current_user)
- head :ok
- else
- head :internal_server_error
- end
- end
-
- def accept_cosponsorship_invite
- @cosponsors_initiative = @initiative.cosponsors_initiatives.find_by(user_id: current_user.id)
-
- if @cosponsors_initiative.update(status: 'accepted')
- SideFxInitiativeService.new.after_accept_cosponsorship_invite(@cosponsors_initiative, current_user)
-
- render json: WebApi::V1::InitiativeSerializer.new(
- @initiative.reload,
- params: jsonapi_serializer_params,
- include: %i[author cosponsors topics areas user_reaction initiative_images]
- ).serializable_hash, status: :ok
- else
- render json: { errors: @initiative.errors.details }, status: :unprocessable_entity
- end
- end
-
- def allowed_transitions
- authorize @initiative
- render json: raw_json(InitiativeStatusService.new.allowed_transitions(@initiative))
- end
-
- private
-
- # renders errors in the new HookForm format
- def render_profanity_blocked(exception)
- errors = exception.violating_attributes.index_with { [{ error: :includes_banned_words }] }
- render json: { errors: errors }, status: :unprocessable_entity
- end
-
- def set_initiative
- @initiative = Initiative.find params[:id]
- authorize @initiative
- end
-
- def serialization_options_for(initiatives)
- default_params = jsonapi_serializer_params
-
- if current_user
- reactions = current_user.reactions.where(
- reactable_id: initiatives.pluck(:id),
- reactable_type: 'Initiative'
- ).index_by(&:reactable_id)
- user_followers = current_user.follows
- .where(followable_type: 'Initiative')
- .group_by do |follower|
- [follower.followable_id, follower.followable_type]
- end
- user_followers ||= {}
- { params: default_params.merge(vbii: reactions, user_followers: user_followers), include: %i[author cosponsors user_reaction initiative_images assignee] }
- else
- { params: default_params, include: %i[author cosponsors initiative_images] }
- end
- end
-
- def display_names_restricted?
- UserDisplayNameService.new(Tenant.current, current_user).restricted?
- end
-
- def anonymous_not_allowed?
- params.dig('initiative', 'anonymous') && !AppConfiguration.instance.settings.dig('initiatives', 'allow_anonymous_participation')
- end
-end
diff --git a/back/app/controllers/web_api/v1/stats_initiatives_controller.rb b/back/app/controllers/web_api/v1/stats_initiatives_controller.rb
deleted file mode 100644
index 95fbff5ae713..000000000000
--- a/back/app/controllers/web_api/v1/stats_initiatives_controller.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::StatsInitiativesController < WebApi::V1::StatsController
- def initiatives_count
- initiatives = policy_scope(Initiative.published).where(published_at: @start_at..@end_at)
- initiatives = PostsFilteringService.new.apply_common_initiative_index_filters initiatives, params
-
- render json: raw_json({ count: initiatives.count })
- end
-
- private
-
- def do_authorize
- authorize :stat_initiative
- end
-end
diff --git a/back/app/controllers/web_api/v1/user_comments_controller.rb b/back/app/controllers/web_api/v1/user_comments_controller.rb
index b3e0800a4ec8..d7413325348b 100644
--- a/back/app/controllers/web_api/v1/user_comments_controller.rb
+++ b/back/app/controllers/web_api/v1/user_comments_controller.rb
@@ -9,22 +9,17 @@ def index
comment_allowed_ideas = policy_scope(Comment, policy_scope_class: IdeaCommentPolicy::Scope)
.published
.where(author_id: params[:user_id])
- comment_allowed_initiatives = policy_scope(Comment, policy_scope_class: InitiativeCommentPolicy::Scope)
- .published
- .where(author_id: params[:user_id])
# Apply pagination to the posts, using the union_posts
# view and ordering by publication date.
joined_posts = UnionPost.joins('INNER JOIN comments ON comments.post_id = union_posts.id')
paged_posts = joined_posts.where(comments: { id: comment_allowed_ideas })
- .or(joined_posts.where(comments: { id: comment_allowed_initiatives }))
.order(published_at: :desc)
.group('union_posts.id, union_posts.published_at') # Remove union_post duplicates
.select('union_posts.id')
paged_posts = paginate paged_posts
- # Get the comments, grouped by the corresponding posts
- # page.
+ # Get the comments, grouped by the corresponding posts page.
comments = Comment.where(post_id: paged_posts)
.where(author_id: params[:user_id])
.includes(:post)
diff --git a/back/app/controllers/web_api/v1/users_controller.rb b/back/app/controllers/web_api/v1/users_controller.rb
index 8f2e579fd60b..d49677b0d44b 100644
--- a/back/app/controllers/web_api/v1/users_controller.rb
+++ b/back/app/controllers/web_api/v1/users_controller.rb
@@ -203,18 +203,14 @@ def initiatives_count
def comments_count
count = 0
published_comments = @user.comments.published
+ # TODO: cleanup-after-proposals-migration
+ # Simplify when Comment.post_type is removed
if !params[:post_type] || params[:post_type] == 'Idea'
count += policy_scope(
published_comments.where(post_type: 'Idea'),
policy_scope_class: IdeaCommentPolicy::Scope
).count
end
- if !params[:post_type] || params[:post_type] == 'Initiative'
- count += policy_scope(
- published_comments.where(post_type: 'Initiative'),
- policy_scope_class: InitiativeCommentPolicy::Scope
- ).count
- end
render json: raw_json({ count: count }), status: :ok
end
diff --git a/back/app/finders/initiatives_finder.rb b/back/app/finders/initiatives_finder.rb
deleted file mode 100644
index 25b9f02d7eb9..000000000000
--- a/back/app/finders/initiatives_finder.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativesFinder < ApplicationFinder
- def find_records
- initiatives = super
- # We use Initiative.where to avoid duplicates caused by `left_outer_joins(:cosponsors_initiatives)`.
- # #distinct fails with `ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list ... md5(`
- Initiative.where(id: initiatives).includes(@includes)
- end
-
- private
-
- def topics_condition(topics)
- scope(:with_some_topics, topics)
- end
-
- def areas_condition(areas)
- scope(:with_some_areas, areas)
- end
-
- def initiative_status_condition(status_id)
- records.left_outer_joins(:initiative_initiative_status)
- .where(initiative_initiative_statuses: { initiative_status_id: status_id })
- end
-
- def assignee_condition(assignee_id)
- assignee_id = nil if assignee_id == 'unassigned'
- where(assignee_id: assignee_id)
- end
-
- def feedback_needed_condition(feedback_needed)
- feedback_needed ? scope(:feedback_needed) : scope(:no_feedback_needed)
- end
-
- def author_condition(author_id)
- records.includes(:author).where(author_id: author_id)
- end
-
- def search_condition(search_term)
- if _search_restricted?
- scope(:restricted_search, search_term)
- else
- scope(:search_by_all, search_term)
- end
- end
-
- def publication_status_condition(status)
- where(publication_status: status)
- end
-
- def bounding_box_condition(bounding_box)
- scope(:with_bounding_box, bounding_box)
- end
-
- def initiatives_condition(initiative_ids)
- where(id: initiative_ids)
- end
-
- def _search_restricted?
- UserDisplayNameService.new(AppConfiguration.instance, current_user).restricted?
- end
-end
diff --git a/back/app/models/follower.rb b/back/app/models/follower.rb
index 71c7efc4361b..cd316243db8f 100644
--- a/back/app/models/follower.rb
+++ b/back/app/models/follower.rb
@@ -23,7 +23,7 @@
# fk_rails_... (user_id => users.id)
#
class Follower < ApplicationRecord
- FOLLOWABLE_TYPES = %w[Project ProjectFolders::Folder Idea Initiative Topic Area]
+ FOLLOWABLE_TYPES = %w[Project ProjectFolders::Folder Idea Topic Area]
belongs_to :user
belongs_to :followable, polymorphic: true
diff --git a/back/app/models/notifications/comment_on_initiative_you_follow.rb b/back/app/models/notifications/comment_on_initiative_you_follow.rb
deleted file mode 100644
index 31e98d3135db..000000000000
--- a/back/app/models/notifications/comment_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class CommentOnInitiativeYouFollow < Notification
- validates :comment, :initiating_user, :post, presence: true
- validates :post_type, inclusion: { in: ['Initiative'] }
-
- ACTIVITY_TRIGGERS = { 'Comment' => { 'created' => true } }
- EVENT_NAME = 'Comment on initiative you follow'
-
- def self.make_notifications_on(activity)
- return [] unless AppConfiguration.instance.feature_activated? 'follow'
-
- comment = activity.item
- initiator_id = comment&.author_id
-
- if comment.post_type == 'Initiative' && initiator_id
- User.from_follows(comment.post.followers).where.not(id: initiator_id).map do |recipient|
- new(
- recipient_id: recipient.id,
- initiating_user_id: initiator_id,
- post: comment.post,
- comment: comment
- )
- end
- else
- []
- end
- end
- end
-end
diff --git a/back/app/models/notifications/cosponsor_of_your_initiative.rb b/back/app/models/notifications/cosponsor_of_your_initiative.rb
deleted file mode 100644
index 731528cf6028..000000000000
--- a/back/app/models/notifications/cosponsor_of_your_initiative.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class CosponsorOfYourInitiative < Notification
- validates :initiating_user, :cosponsors_initiative, presence: true
-
- ACTIVITY_TRIGGERS = { 'CosponsorsInitiative' => { 'cosponsorship_accepted' => true } }
- EVENT_NAME = 'Cosponsor has accepted your invitation to cosponsor your initiative'
-
- def self.make_notifications_on(activity)
- cosponsors_initiative = activity&.item
- initiating_user = activity&.user
- initiative = cosponsors_initiative&.initiative
- recipient_id = initiative&.author_id
-
- if recipient_id && initiating_user && initiative
- [new(
- recipient_id: recipient_id,
- initiating_user: initiating_user,
- cosponsors_initiative: cosponsors_initiative,
- post: initiative
- )]
- else
- []
- end
- end
- end
-end
diff --git a/back/app/models/notifications/initiative_assigned_to_you.rb b/back/app/models/notifications/initiative_assigned_to_you.rb
deleted file mode 100644
index 23c2303b4bd1..000000000000
--- a/back/app/models/notifications/initiative_assigned_to_you.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class InitiativeAssignedToYou < Notification
- validates :initiating_user, :post, presence: true
- validates :post_type, inclusion: { in: ['Initiative'] }
-
- ACTIVITY_TRIGGERS = { 'Initiative' => { 'changed_assignee' => true } }
- EVENT_NAME = 'Initiative assigned to you'
-
- def self.make_notifications_on(activity)
- initiative = activity.item
- recipient_id = initiative.assignee_id
- initiator_id = activity.user_id
-
- # We only notify manual assignments, meaning there needs to be an
- # initiator
- if recipient_id && initiator_id && recipient_id != initiator_id
- [
- new(
- recipient_id: recipient_id,
- post: initiative,
- initiating_user_id: initiator_id
- )
- ]
- else
- []
- end
- end
- end
-end
diff --git a/back/app/models/notifications/initiative_marked_as_spam.rb b/back/app/models/notifications/initiative_marked_as_spam.rb
deleted file mode 100644
index 811ca53d2944..000000000000
--- a/back/app/models/notifications/initiative_marked_as_spam.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class InitiativeMarkedAsSpam < MarkedAsSpam
- validates :post, presence: true
- validates :post_type, inclusion: { in: ['Initiative'] }
-
- ACTIVITY_TRIGGERS = { 'SpamReport' => { 'created' => true } }
- EVENT_NAME = 'Initiative marked as spam'
-
- def self.make_notifications_on(activity)
- spam_report = activity.item
- if spam_report.spam_reportable_type == 'Initiative'
- initiator_id = spam_report.user_id
- recipient_ids(initiator_id).map do |recipient_id|
- new(
- recipient_id: recipient_id,
- initiating_user_id: initiator_id,
- spam_report: spam_report,
- post: spam_report.spam_reportable
- )
- end
- else
- []
- end
- end
- end
-end
diff --git a/back/app/models/notifications/initiative_resubmitted_for_review.rb b/back/app/models/notifications/initiative_resubmitted_for_review.rb
deleted file mode 100644
index c0eaf89d7afe..000000000000
--- a/back/app/models/notifications/initiative_resubmitted_for_review.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class InitiativeResubmittedForReview < Notification
- validates :post_status, :post, presence: true
- validates :post_type, inclusion: { in: ['Initiative'] }
-
- ACTIVITY_TRIGGERS = { 'Initiative' => { 'changed_status' => true } }
- EVENT_NAME = 'Initiative resubmitted for review'
-
- class << self
- def make_notifications_on(activity)
- initiative = activity.item
- recipient_id = initiative&.assignee_id
-
- if initiative && recipient_id && transitioned_from_rejected_to_pending?(initiative)
- [new(
- recipient_id: recipient_id,
- initiating_user_id: activity.user_id,
- post: initiative,
- post_status: initiative.initiative_status
- )]
- else
- []
- end
- end
-
- private
-
- def transitioned_from_rejected_to_pending?(initiative)
- previous_change = initiative.initiative_status_changes.order(created_at: :asc)[-2]
- previous_change && previous_change.initiative_status.code == 'changes_requested' && initiative.initiative_status.code == 'review_pending'
- end
- end
- end
-end
diff --git a/back/app/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you.rb b/back/app/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you.rb
deleted file mode 100644
index 9f2c328a172b..000000000000
--- a/back/app/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class InternalComments::InternalCommentOnInitiativeAssignedToYou < Notification
- validates :initiating_user, :internal_comment, :post, presence: true
-
- ACTIVITY_TRIGGERS = { 'InternalComment' => { 'created' => true } }
- EVENT_NAME = 'Internal comment on initiative assigned to you'
-
- def self.make_notifications_on(activity)
- InternalComments::InternalCommentOnInitiativeAssignedToYouBuilder.new(activity).build_notifications
- end
- end
-end
diff --git a/back/app/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on.rb b/back/app/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on.rb
deleted file mode 100644
index 21647cfe14b8..000000000000
--- a/back/app/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn < Notification
- validates :initiating_user, :internal_comment, :post, presence: true
-
- ACTIVITY_TRIGGERS = { 'InternalComment' => { 'created' => true } }
- EVENT_NAME = 'Internal comment on initiative you commented internally on'
-
- def self.make_notifications_on(activity)
- InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOnBuilder.new(activity).build_notifications
- end
- end
-end
diff --git a/back/app/models/notifications/internal_comments/internal_comment_on_unassigned_initiative.rb b/back/app/models/notifications/internal_comments/internal_comment_on_unassigned_initiative.rb
deleted file mode 100644
index dec2b97b3c8b..000000000000
--- a/back/app/models/notifications/internal_comments/internal_comment_on_unassigned_initiative.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class InternalComments::InternalCommentOnUnassignedInitiative < Notification
- validates :initiating_user, :internal_comment, :post, presence: true
-
- ACTIVITY_TRIGGERS = { 'InternalComment' => { 'created' => true } }
- EVENT_NAME = 'Internal comment on unassigned initiative'
-
- def self.make_notifications_on(activity)
- InternalComments::InternalCommentOnUnassignedInitiativeBuilder.new(activity).build_notifications
- end
- end
-end
diff --git a/back/app/models/notifications/invitation_to_cosponsor_initiative.rb b/back/app/models/notifications/invitation_to_cosponsor_initiative.rb
deleted file mode 100644
index e3e1be3e092f..000000000000
--- a/back/app/models/notifications/invitation_to_cosponsor_initiative.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class InvitationToCosponsorInitiative < Notification
- validates :initiating_user, :cosponsors_initiative, presence: true
-
- ACTIVITY_TRIGGERS = { 'CosponsorsInitiative' => { 'created' => true } }
- EVENT_NAME = 'Invitation to cosponsor an initiative'
-
- def self.make_notifications_on(activity)
- cosponsors_initiative = activity&.item
- initiating_user = activity&.user
- recipient_id = cosponsors_initiative&.user_id
- initiative = cosponsors_initiative&.initiative
-
- if recipient_id && initiating_user && initiative
- [new(
- recipient_id: recipient_id,
- initiating_user: initiating_user,
- cosponsors_initiative: cosponsors_initiative,
- post: initiative
- )]
- else
- []
- end
- end
- end
-end
diff --git a/back/app/models/notifications/official_feedback_on_initiative_you_follow.rb b/back/app/models/notifications/official_feedback_on_initiative_you_follow.rb
deleted file mode 100644
index 5b8fd8e96f45..000000000000
--- a/back/app/models/notifications/official_feedback_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class OfficialFeedbackOnInitiativeYouFollow < Notification
- validates :initiating_user, :post, :official_feedback, presence: true
- validates :post_type, inclusion: { in: ['Initiative'] }
-
- ACTIVITY_TRIGGERS = { 'OfficialFeedback' => { 'created' => true } }
- EVENT_NAME = 'Official feedback on initiative you follow'
-
- def self.make_notifications_on(activity)
- return [] unless AppConfiguration.instance.feature_activated? 'follow'
-
- official_feedback = activity.item
- initiator_id = official_feedback.user_id
-
- if official_feedback.post_type == 'Initiative' && initiator_id
- User.from_follows(official_feedback.post.followers).where.not(id: initiator_id).filter_map do |recipient|
- next if InitiativeStatusChange.exists?(official_feedback: official_feedback)
-
- new(
- recipient_id: recipient.id,
- initiating_user_id: initiator_id,
- post: official_feedback.post,
- official_feedback: official_feedback
- )
- end
- else
- []
- end
- end
- end
-end
diff --git a/back/app/models/notifications/status_change_on_initiative_you_follow.rb b/back/app/models/notifications/status_change_on_initiative_you_follow.rb
deleted file mode 100644
index 7e397946c37a..000000000000
--- a/back/app/models/notifications/status_change_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: notifications
-#
-# id :uuid not null, primary key
-# type :string
-# read_at :datetime
-# recipient_id :uuid
-# post_id :uuid
-# comment_id :uuid
-# project_id :uuid
-# created_at :datetime not null
-# updated_at :datetime not null
-# initiating_user_id :uuid
-# spam_report_id :uuid
-# invite_id :uuid
-# reason_code :string
-# other_reason :string
-# post_status_id :uuid
-# official_feedback_id :uuid
-# phase_id :uuid
-# post_type :string
-# post_status_type :string
-# project_folder_id :uuid
-# inappropriate_content_flag_id :uuid
-# internal_comment_id :uuid
-# basket_id :uuid
-# cosponsors_initiative_id :uuid
-# cosponsorship_id :uuid
-# project_review_id :uuid
-#
-# Indexes
-#
-# index_notifications_on_basket_id (basket_id)
-# index_notifications_on_cosponsors_initiative_id (cosponsors_initiative_id)
-# index_notifications_on_cosponsorship_id (cosponsorship_id)
-# index_notifications_on_created_at (created_at)
-# index_notifications_on_inappropriate_content_flag_id (inappropriate_content_flag_id)
-# index_notifications_on_initiating_user_id (initiating_user_id)
-# index_notifications_on_internal_comment_id (internal_comment_id)
-# index_notifications_on_invite_id (invite_id)
-# index_notifications_on_official_feedback_id (official_feedback_id)
-# index_notifications_on_phase_id (phase_id)
-# index_notifications_on_post_id_and_post_type (post_id,post_type)
-# index_notifications_on_post_status_id (post_status_id)
-# index_notifications_on_post_status_id_and_post_status_type (post_status_id,post_status_type)
-# index_notifications_on_project_review_id (project_review_id)
-# index_notifications_on_recipient_id (recipient_id)
-# index_notifications_on_recipient_id_and_read_at (recipient_id,read_at)
-# index_notifications_on_spam_report_id (spam_report_id)
-#
-# Foreign Keys
-#
-# fk_rails_... (basket_id => baskets.id)
-# fk_rails_... (comment_id => comments.id)
-# fk_rails_... (cosponsors_initiative_id => cosponsors_initiatives.id)
-# fk_rails_... (cosponsorship_id => cosponsorships.id)
-# fk_rails_... (inappropriate_content_flag_id => flag_inappropriate_content_inappropriate_content_flags.id)
-# fk_rails_... (initiating_user_id => users.id)
-# fk_rails_... (internal_comment_id => internal_comments.id)
-# fk_rails_... (invite_id => invites.id)
-# fk_rails_... (official_feedback_id => official_feedbacks.id)
-# fk_rails_... (phase_id => phases.id)
-# fk_rails_... (project_id => projects.id)
-# fk_rails_... (project_review_id => project_reviews.id)
-# fk_rails_... (recipient_id => users.id)
-# fk_rails_... (spam_report_id => spam_reports.id)
-#
-module Notifications
- class StatusChangeOnInitiativeYouFollow < Notification
- validates :post_status, :post, presence: true
- validates :post_type, inclusion: { in: ['Initiative'] }
-
- ACTIVITY_TRIGGERS = { 'Initiative' => { 'changed_status' => true } }
- EVENT_NAME = 'Status change on initiative you follow'
-
- def self.make_notifications_on(activity)
- return [] unless AppConfiguration.instance.feature_activated? 'follow'
-
- initiator_id = activity.user_id
- initiative = activity.item
- return [] if !initiative
-
- User.from_follows(initiative.followers).where.not(id: initiator_id).map do |recipient|
- new(
- recipient_id: recipient.id,
- initiating_user_id: initiator_id,
- post: initiative,
- post_status: initiative.initiative_status
- )
- end
- end
- end
-end
diff --git a/back/app/models/permission.rb b/back/app/models/permission.rb
index ef63779294bf..56b96a29a69e 100644
--- a/back/app/models/permission.rb
+++ b/back/app/models/permission.rb
@@ -24,7 +24,7 @@ class Permission < ApplicationRecord
PERMITTED_BIES = %w[everyone everyone_confirmed_email users admins_moderators verified].freeze
ACTIONS = {
# NOTE: Order of actions in each array is used when using :order_by_action
- nil => %w[visiting following posting_initiative commenting_initiative reacting_initiative attending_event],
+ nil => %w[visiting following attending_event],
'information' => %w[attending_event],
'ideation' => %w[posting_idea commenting_idea reacting_idea attending_event],
'proposals' => %w[posting_idea commenting_idea reacting_idea attending_event],
diff --git a/back/app/policies/initiative_comment_policy.rb b/back/app/policies/initiative_comment_policy.rb
deleted file mode 100644
index 5b2a4bec46f2..000000000000
--- a/back/app/policies/initiative_comment_policy.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativeCommentPolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- scope.where(post: scope_for(Initiative))
- end
- end
-
- def index_xlsx?
- user&.admin?
- end
-
- def create?
- return unless active?
- return true if admin?
-
- owner? && commenting_allowed?(user)
- end
-
- def children?
- show?
- end
-
- def show?
- policy_for(record.post).show?
- end
-
- def update?
- create?
- end
-
- def mark_as_deleted?
- update?
- end
-
- def destroy?
- false
- end
-
- def permitted_attributes_for_update
- attrs = %i[parent_id author_id]
- if record.author_id == user&.id
- attrs += [body_multiloc: CL2_SUPPORTED_LOCALES]
- end
- attrs
- end
-
- private
-
- def commenting_allowed?(user)
- !Permissions::InitiativePermissionsService.new(user).denied_reason_for_action 'commenting_initiative'
- end
-
- def owner?
- user && (record.author_id == user.id)
- end
-end
diff --git a/back/app/policies/initiative_file_policy.rb b/back/app/policies/initiative_file_policy.rb
deleted file mode 100644
index 910b88e275fc..000000000000
--- a/back/app/policies/initiative_file_policy.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativeFilePolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- scope.where(initiative: scope_for(Initiative))
- end
- end
-
- def create?
- policy_for(record.initiative).update?
- end
-
- def show?
- policy_for(record.initiative).show?
- end
-
- def update?
- policy_for(record.initiative).update?
- end
-
- def destroy?
- policy_for(record.initiative).update?
- end
-end
diff --git a/back/app/policies/initiative_image_policy.rb b/back/app/policies/initiative_image_policy.rb
deleted file mode 100644
index 8cd7e7a670b0..000000000000
--- a/back/app/policies/initiative_image_policy.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativeImagePolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- scope.where(initiative: scope_for(Initiative))
- end
- end
-
- def create?
- policy_for(record.initiative).update?
- end
-
- def show?
- policy_for(record.initiative).show?
- end
-
- def update?
- policy_for(record.initiative).update?
- end
-
- def destroy?
- policy_for(record.initiative).update?
- end
-end
diff --git a/back/app/policies/initiative_official_feedback_policy.rb b/back/app/policies/initiative_official_feedback_policy.rb
deleted file mode 100644
index 48e888bd605d..000000000000
--- a/back/app/policies/initiative_official_feedback_policy.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativeOfficialFeedbackPolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- scope.where(post: scope_for(Initiative))
- end
- end
-
- def create?
- user&.admin?
- end
-
- def show?
- policy_for(record.post).show?
- end
-
- def update?
- create?
- end
-
- def destroy?
- create?
- end
-end
diff --git a/back/app/policies/initiative_policy.rb b/back/app/policies/initiative_policy.rb
deleted file mode 100644
index faf4e8add487..000000000000
--- a/back/app/policies/initiative_policy.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativePolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- published = scope.where(publication_status: 'published')
-
- if UserRoleService.new.can_moderate_initiatives?(user)
- published
- elsif user&.active?
- published.left_outer_joins(:cosponsors_initiatives).with_status_code(InitiativeStatus::NOT_REVIEW_CODES)
- .or(published.where(author: user))
- .or(published.where(cosponsors_initiatives: { user: user }))
- else
- published.with_status_code(InitiativeStatus::NOT_REVIEW_CODES)
- end
- end
- end
-
- def index_xlsx?
- active? && UserRoleService.new.can_moderate_initiatives?(user)
- end
-
- def create?
- return true if active? && can_moderate?
-
- reason = posting_denied_reason user
- raise_not_authorized reason if reason
-
- active? && owner?
- end
-
- def show?
- return true if active? && (owner? || cosponsor? || can_moderate?)
- return false if record.review_status?
-
- true
- end
-
- def by_slug?
- show?
- end
-
- def update?
- return true if active? && can_moderate?
-
- create? && !record.editing_locked
- end
-
- def destroy?
- create?
- end
-
- def accept_cosponsorship_invite?
- cosponsor?
- end
-
- def allowed_transitions?
- can_moderate?
- end
-
- def permitted_attributes
- shared = [
- :publication_status,
- :location_description,
- :header_bg,
- :anonymous,
- { cosponsor_ids: [] },
- { location_point_geojson: [:type, { coordinates: [] }],
- title_multiloc: CL2_SUPPORTED_LOCALES,
- body_multiloc: CL2_SUPPORTED_LOCALES,
- topic_ids: [],
- area_ids: [] }
- ]
-
- can_moderate? ? [:author_id, :assignee_id, *shared] : shared
- end
-
- private
-
- def posting_denied_reason(user)
- Permissions::InitiativePermissionsService.new(user).denied_reason_for_action 'posting_initiative'
- end
-
- def owner?
- user && record.author_id == user.id
- end
-
- def cosponsor?
- user && record&.cosponsors&.include?(user)
- end
-end
diff --git a/back/app/policies/initiative_reaction_policy.rb b/back/app/policies/initiative_reaction_policy.rb
deleted file mode 100644
index cc61ba356128..000000000000
--- a/back/app/policies/initiative_reaction_policy.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativeReactionPolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- if user&.admin?
- scope.all
- elsif user
- scope.where(user: user)
- else
- scope.none
- end
- end
- end
-
- def create?
- return if !user&.active? || !owner?
-
- reason = reacting_denied_reason user
- reason ? raise_not_authorized(reason) : true
- end
-
- def destroy?
- create?
- end
-
- def up?
- create?
- end
-
- def down?
- # TODO: JS - should this reason be in a permissions service
- raise_not_authorized('dislikes_not_supported')
- end
-
- def show?
- active? && (owner? || admin?)
- end
-
- private
-
- def reacting_denied_reason(user)
- Permissions::InitiativePermissionsService.new(user).denied_reason_for_action 'reacting_initiative'
- end
-end
diff --git a/back/app/policies/initiative_status_change_policy.rb b/back/app/policies/initiative_status_change_policy.rb
deleted file mode 100644
index 137857fefdcc..000000000000
--- a/back/app/policies/initiative_status_change_policy.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativeStatusChangePolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- # Disabled
- if user&.active? && user&.admin?
- scope.all
- else
- scope.none
- end
- end
- end
-
- def create?
- user&.active? && user&.admin?
- end
-
- def show?
- user&.active? && user&.admin?
- end
-end
diff --git a/back/app/policies/initiative_status_policy.rb b/back/app/policies/initiative_status_policy.rb
deleted file mode 100644
index 0a34855457fc..000000000000
--- a/back/app/policies/initiative_status_policy.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class InitiativeStatusPolicy < ApplicationPolicy
- class Scope < ApplicationPolicy::Scope
- def resolve
- filter_out_review_statuses
- end
-
- private
-
- # This method handles the case when review was turned on,
- # some initiatives were created, and then review was turned off.
- # We still want to show statuses of all used initiatives after that.
- def filter_out_review_statuses
- if UserRoleService.new.can_moderate_initiatives?(user)
- if Initiative.review_required?
- scope.all
- else
- review_initiatives = initiatives.with_status_code(InitiativeStatus::REVIEW_CODES)
-
- if review_initiatives.any?
- scope.all # make it possible to change the status of initiatives that were created when review was on
- else
- scope.where(code: InitiativeStatus::NOT_REVIEW_CODES)
- end
- end
- else
- public_codes = InitiativeStatus::NOT_REVIEW_CODES
- # We want to show only statuses of initiatives available to the current user.
- user_codes = initiatives.joins(:initiative_status).distinct.pluck('initiative_status.code')
- scope.where(code: (public_codes + user_codes).uniq)
- end
- end
-
- def initiatives
- scope_for(Initiative)
- end
- end
-
- def show?
- true
- end
-end
diff --git a/back/app/serializers/web_api/v1/initiative_serializer.rb b/back/app/serializers/web_api/v1/initiative_serializer.rb
deleted file mode 100644
index e3acfcd4cffb..000000000000
--- a/back/app/serializers/web_api/v1/initiative_serializer.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::InitiativeSerializer < WebApi::V1::BaseSerializer
- attributes :title_multiloc,
- :slug,
- :publication_status,
- :likes_count,
- :comments_count,
- :internal_comments_count,
- :official_feedbacks_count,
- :followers_count,
- :location_point_geojson,
- :location_description,
- :created_at,
- :updated_at,
- :published_at,
- :expires_at,
- :reactions_needed,
- :anonymous,
- :author_hash,
- :editing_locked,
- :public,
- :proposed_at
-
- attribute :author_name do |object, params|
- name_service = UserDisplayNameService.new(AppConfiguration.instance, current_user(params))
- name_service.display_name!(object.author)
- end
-
- attribute :body_multiloc do |object|
- TextImageService.new.render_data_images_multiloc object.body_multiloc, field: :body_multiloc, imageable: object
- end
-
- attribute :header_bg do |object|
- object.header_bg && object.header_bg.versions.to_h { |k, v| [k.to_s, v.url] }
- end
-
- attribute :internal_comments_count, if: proc { |object, params|
- can_moderate?(object, params)
- }
-
- attribute :cosponsorships do |object, params|
- name_service = UserDisplayNameService.new(AppConfiguration.instance, current_user(params))
-
- object.cosponsors_initiatives.includes(:user).map do |ci|
- { user_id: ci.user_id, name: name_service.display_name!(ci.user), status: ci.status }
- end
- end
-
- attribute :public do |object|
- object.initiative_status ? object.initiative_status.public? : false
- end
-
- has_many :initiative_images, serializer: WebApi::V1::ImageSerializer
- has_many :topics
- has_many :areas
- has_many :cosponsors, record_type: :user, serializer: WebApi::V1::UserSerializer
-
- belongs_to :author, record_type: :user, serializer: WebApi::V1::UserSerializer
- belongs_to :initiative_status
- belongs_to :assignee, if: proc { |object, params|
- can_moderate? object, params
- }, record_type: :user, serializer: WebApi::V1::UserSerializer
-
- has_one :user_reaction, if: proc { |object, params|
- signed_in? object, params
- }, record_type: :reaction, serializer: WebApi::V1::ReactionSerializer do |object, params|
- cached_user_reaction object, params
- end
-
- has_one :user_follower, record_type: :follower, if: proc { |object, params|
- signed_in? object, params
- } do |object, params|
- user_follower object, params
- end
-
- def self.can_moderate?(_object, params)
- current_user(params) && UserRoleService.new.can_moderate_initiatives?(current_user(params))
- end
-
- def self.cached_user_reaction(object, params)
- if params[:vbii]
- params.dig(:vbii, object.id)
- else
- object.reactions.where(user_id: current_user(params)&.id).first
- end
- end
-
- def self.user_follower(object, params)
- if params[:user_followers]
- params.dig(:user_followers, [object.id, 'Initiative'])&.first
- else
- current_user(params)&.follows&.find do |follow|
- follow.followable_id == object.id && follow.followable_type == 'Initiative'
- end
- end
- end
-end
diff --git a/back/app/serializers/web_api/v1/initiative_status_change_serializer.rb b/back/app/serializers/web_api/v1/initiative_status_change_serializer.rb
deleted file mode 100644
index 950140ce95ab..000000000000
--- a/back/app/serializers/web_api/v1/initiative_status_change_serializer.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::InitiativeStatusChangeSerializer < WebApi::V1::BaseSerializer
- attribute :created_at, :updated_at
-
- belongs_to :initiative_status
- belongs_to :initiative
- belongs_to :user
- belongs_to :official_feedback
-end
diff --git a/back/app/serializers/web_api/v1/initiative_status_serializer.rb b/back/app/serializers/web_api/v1/initiative_status_serializer.rb
deleted file mode 100644
index 7f32a528a01d..000000000000
--- a/back/app/serializers/web_api/v1/initiative_status_serializer.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::InitiativeStatusSerializer < WebApi::V1::BaseSerializer
- attributes :title_multiloc, :description_multiloc, :ordering, :code, :color
-
- attribute :transition_type do |object|
- InitiativeStatusService.new.transition_type object
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/comment_on_initiative_you_follow_serializer.rb b/back/app/serializers/web_api/v1/notifications/comment_on_initiative_you_follow_serializer.rb
deleted file mode 100644
index 7222480ac0f7..000000000000
--- a/back/app/serializers/web_api/v1/notifications/comment_on_initiative_you_follow_serializer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::CommentOnInitiativeYouFollowSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :initiating_user_first_name do |object|
- object.initiating_user&.first_name
- end
-
- attribute :initiating_user_last_name do |object, params|
- name_service = UserDisplayNameService.new(AppConfiguration.instance, current_user(params))
- name_service.last_name!(object.initiating_user)
- end
-
- attribute :initiating_user_slug do |object|
- object.initiating_user&.slug
- end
-
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/cosponsor_of_your_initiative_serializer.rb b/back/app/serializers/web_api/v1/notifications/cosponsor_of_your_initiative_serializer.rb
deleted file mode 100644
index 3704d93821ce..000000000000
--- a/back/app/serializers/web_api/v1/notifications/cosponsor_of_your_initiative_serializer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::CosponsorOfYourInitiativeSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :initiating_user_first_name do |object|
- object.initiating_user&.first_name
- end
-
- attribute :initiating_user_last_name do |object, params|
- name_service = UserDisplayNameService.new(AppConfiguration.instance, current_user(params))
- name_service.last_name!(object.initiating_user)
- end
-
- attribute :initiating_user_slug do |object|
- object.initiating_user&.slug
- end
-
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/initiative_assigned_to_you_serializer.rb b/back/app/serializers/web_api/v1/notifications/initiative_assigned_to_you_serializer.rb
deleted file mode 100644
index f1e9b5b509d6..000000000000
--- a/back/app/serializers/web_api/v1/notifications/initiative_assigned_to_you_serializer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::InitiativeAssignedToYouSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :initiating_user_first_name do |object|
- object.initiating_user&.first_name
- end
-
- attribute :initiating_user_last_name do |object, params|
- name_service = UserDisplayNameService.new(AppConfiguration.instance, current_user(params))
- name_service.last_name!(object.initiating_user)
- end
-
- attribute :initiating_user_slug do |object|
- object.initiating_user&.slug
- end
-
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/initiative_marked_as_spam_serializer.rb b/back/app/serializers/web_api/v1/notifications/initiative_marked_as_spam_serializer.rb
deleted file mode 100644
index 0758c665535a..000000000000
--- a/back/app/serializers/web_api/v1/notifications/initiative_marked_as_spam_serializer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::InitiativeMarkedAsSpamSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :initiating_user_first_name do |object|
- object.initiating_user&.first_name
- end
-
- attribute :initiating_user_last_name do |object, params|
- name_service = UserDisplayNameService.new(AppConfiguration.instance, current_user(params))
- name_service.last_name!(object.initiating_user)
- end
-
- attribute :initiating_user_slug do |object|
- object.initiating_user&.slug
- end
-
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/initiative_resubmitted_for_review_serializer.rb b/back/app/serializers/web_api/v1/notifications/initiative_resubmitted_for_review_serializer.rb
deleted file mode 100644
index e9f4bd27f94e..000000000000
--- a/back/app/serializers/web_api/v1/notifications/initiative_resubmitted_for_review_serializer.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::InitiativeResubmittedForReviewSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_assigned_to_you_serializer.rb b/back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_assigned_to_you_serializer.rb
deleted file mode 100644
index 14d31cd81403..000000000000
--- a/back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_assigned_to_you_serializer.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::InternalCommentOnInitiativeAssignedToYouSerializer < WebApi::V1::Notifications::InternalCommentNotificationSerializer
-end
diff --git a/back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_you_commented_internally_on_serializer.rb b/back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_you_commented_internally_on_serializer.rb
deleted file mode 100644
index 870840dc0666..000000000000
--- a/back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_you_commented_internally_on_serializer.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::InternalCommentOnInitiativeYouCommentedInternallyOnSerializer < WebApi::V1::Notifications::InternalCommentNotificationSerializer
-end
diff --git a/back/app/serializers/web_api/v1/notifications/internal_comment_on_unassigned_initiative_serializer.rb b/back/app/serializers/web_api/v1/notifications/internal_comment_on_unassigned_initiative_serializer.rb
deleted file mode 100644
index 76470100b128..000000000000
--- a/back/app/serializers/web_api/v1/notifications/internal_comment_on_unassigned_initiative_serializer.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::InternalCommentOnUnassignedInitiativeSerializer < WebApi::V1::Notifications::InternalCommentNotificationSerializer
-end
diff --git a/back/app/serializers/web_api/v1/notifications/invitation_to_cosponsor_initiative_serializer.rb b/back/app/serializers/web_api/v1/notifications/invitation_to_cosponsor_initiative_serializer.rb
deleted file mode 100644
index 7eb8c49e16a7..000000000000
--- a/back/app/serializers/web_api/v1/notifications/invitation_to_cosponsor_initiative_serializer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::InvitationToCosponsorInitiativeSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :initiating_user_first_name do |object|
- object.initiating_user&.first_name
- end
-
- attribute :initiating_user_last_name do |object, params|
- name_service = UserDisplayNameService.new(AppConfiguration.instance, current_user(params))
- name_service.last_name!(object.initiating_user)
- end
-
- attribute :initiating_user_slug do |object|
- object.initiating_user&.slug
- end
-
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/official_feedback_on_initiative_you_follow_serializer.rb b/back/app/serializers/web_api/v1/notifications/official_feedback_on_initiative_you_follow_serializer.rb
deleted file mode 100644
index 869016f45276..000000000000
--- a/back/app/serializers/web_api/v1/notifications/official_feedback_on_initiative_you_follow_serializer.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::OfficialFeedbackOnInitiativeYouFollowSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :official_feedback_author do |object|
- object.official_feedback&.author_multiloc
- end
-
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-end
diff --git a/back/app/serializers/web_api/v1/notifications/status_change_on_initiative_you_follow_serializer.rb b/back/app/serializers/web_api/v1/notifications/status_change_on_initiative_you_follow_serializer.rb
deleted file mode 100644
index a4aa6571309b..000000000000
--- a/back/app/serializers/web_api/v1/notifications/status_change_on_initiative_you_follow_serializer.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class WebApi::V1::Notifications::StatusChangeOnInitiativeYouFollowSerializer < WebApi::V1::Notifications::NotificationSerializer
- attribute :post_title_multiloc do |object|
- object.post&.title_multiloc
- end
-
- attribute :post_slug do |object|
- object.post&.slug
- end
-
- attribute :initiative_status_title_multiloc do |object|
- object.post_status&.title_multiloc
- end
-end
diff --git a/back/app/services/notification_service.rb b/back/app/services/notification_service.rb
index b836c6ce1334..3300a002d4d8 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -6,31 +6,21 @@ class NotificationService
Notifications::CommentDeletedByAdmin,
Notifications::CommentMarkedAsSpam,
Notifications::CommentOnIdeaYouFollow,
- Notifications::CommentOnInitiativeYouFollow,
Notifications::CommentOnYourComment,
Notifications::CosponsorOfYourIdea,
- Notifications::CosponsorOfYourInitiative,
Notifications::IdeaMarkedAsSpam,
- Notifications::InitiativeAssignedToYou,
- Notifications::InitiativeMarkedAsSpam,
- Notifications::InitiativeResubmittedForReview,
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
Notifications::InternalComments::InternalCommentOnIdeaYouCommentedInternallyOn,
Notifications::InternalComments::InternalCommentOnIdeaYouModerate,
- Notifications::InternalComments::InternalCommentOnInitiativeAssignedToYou,
- Notifications::InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn,
- Notifications::InternalComments::InternalCommentOnUnassignedInitiative,
Notifications::InternalComments::InternalCommentOnUnassignedUnmoderatedIdea,
Notifications::InternalComments::InternalCommentOnYourInternalComment,
Notifications::InternalComments::MentionInInternalComment,
Notifications::InvitationToCosponsorIdea,
- Notifications::InvitationToCosponsorInitiative,
Notifications::InviteAccepted,
Notifications::MentionInComment,
Notifications::MentionInOfficialFeedback,
Notifications::NativeSurveyNotSubmitted,
Notifications::OfficialFeedbackOnIdeaYouFollow,
- Notifications::OfficialFeedbackOnInitiativeYouFollow,
Notifications::ProjectFolderModerationRightsReceived,
Notifications::ProjectModerationRightsReceived,
Notifications::ProjectPhaseStarted,
@@ -39,7 +29,6 @@ class NotificationService
Notifications::ProjectReviewRequest,
Notifications::ProjectReviewStateChange,
Notifications::StatusChangeOnIdeaYouFollow,
- Notifications::StatusChangeOnInitiativeYouFollow,
Notifications::ThresholdReachedForAdmin,
Notifications::VotingBasketNotSubmitted,
Notifications::VotingBasketSubmitted,
diff --git a/back/app/services/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_builder.rb b/back/app/services/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_builder.rb
deleted file mode 100644
index c02106ad6009..000000000000
--- a/back/app/services/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_builder.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Notifications
- class InternalComments::InternalCommentOnInitiativeAssignedToYouBuilder < InternalComments::BaseNotificationBuilder
- protected
-
- def skip_recipient?(recipient)
- initiator_id.nil? ||
- initiator_id == recipient.id ||
- recipient.id == parent_author_id ||
- MentionService.new.user_mentioned?(internal_comment.body, recipient)
- end
-
- def recipients
- [User.find_by(id: internal_comment&.post&.assignee_id)].compact
- end
-
- def preconditions_met?
- post_type == 'Initiative'
- end
-
- def notification_class
- Notifications::InternalComments::InternalCommentOnInitiativeAssignedToYou
- end
- end
-end
diff --git a/back/app/services/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_builder.rb b/back/app/services/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_builder.rb
deleted file mode 100644
index 3c71e349d370..000000000000
--- a/back/app/services/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_builder.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Notifications
- class InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOnBuilder < InternalComments::BaseNotificationBuilder
- protected
-
- def skip_recipient?(recipient)
- initiator_id.nil? ||
- initiator_id == recipient.id ||
- recipient.id == parent_author_id ||
- recipient.id == assignee_id ||
- MentionService.new.user_mentioned?(internal_comment.body, recipient)
- end
-
- def recipients
- InternalComment.where(post_id: internal_comment.post_id).map(&:author).uniq
- end
-
- def preconditions_met?
- post_type == 'Initiative'
- end
-
- def notification_class
- Notifications::InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn
- end
- end
-end
diff --git a/back/app/services/notifications/internal_comments/internal_comment_on_unassigned_initiative_builder.rb b/back/app/services/notifications/internal_comments/internal_comment_on_unassigned_initiative_builder.rb
deleted file mode 100644
index 3a4f84233efb..000000000000
--- a/back/app/services/notifications/internal_comments/internal_comment_on_unassigned_initiative_builder.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Notifications
- class InternalComments::InternalCommentOnUnassignedInitiativeBuilder < InternalComments::BaseNotificationBuilder
- protected
-
- def skip_recipient?(recipient)
- initiator_id.nil? ||
- initiator_id == recipient.id ||
- recipient.id == parent_author_id ||
- recipient.id == assignee_id ||
- MentionService.new.user_mentioned?(internal_comment.body, recipient)
- end
-
- def recipients
- commenters = InternalComment.where(post_id: internal_comment.post_id).map(&:author).uniq
-
- User.admin - commenters
- end
-
- def preconditions_met?
- post_type == 'Initiative' && assignee_id.nil?
- end
-
- def notification_class
- Notifications::InternalComments::InternalCommentOnUnassignedInitiative
- end
- end
-end
diff --git a/back/app/services/permissions/base_permissions_service.rb b/back/app/services/permissions/base_permissions_service.rb
index d1e44d3a8a0e..cee6d2b7b782 100644
--- a/back/app/services/permissions/base_permissions_service.rb
+++ b/back/app/services/permissions/base_permissions_service.rb
@@ -3,9 +3,6 @@ class BasePermissionsService
SUPPORTED_ACTIONS = %w[
following
visiting
- posting_initiative
- commenting_initiative
- reacting_initiative
posting_idea
commenting_idea
reacting_idea
diff --git a/back/app/services/permissions/initiative_permissions_service.rb b/back/app/services/permissions/initiative_permissions_service.rb
deleted file mode 100644
index 13ac58a152c9..000000000000
--- a/back/app/services/permissions/initiative_permissions_service.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Permissions
- class InitiativePermissionsService < BasePermissionsService
- def action_descriptors
- posting_disabled_reason = denied_reason_for_action 'posting_initiative'
- commenting_disabled_reason = denied_reason_for_action 'commenting_initiative'
- reacting_disabled_reason = denied_reason_for_action 'reacting_initiative'
-
- descriptors = {
- posting_initiative: { disabled_reason: posting_disabled_reason },
- commenting_initiative: { disabled_reason: commenting_disabled_reason },
- reacting_initiative: { disabled_reason: reacting_disabled_reason }
- }
-
- descriptors.each_value { |desc| desc[:enabled] = !desc[:disabled_reason] }
- descriptors[:comment_reacting_initiative] = descriptors[:commenting_initiative]
- descriptors[:cancelling_initiative_reactions] = descriptors[:reacting_initiative]
- descriptors
- end
- end
-end
diff --git a/back/app/services/side_fx_initiative_service.rb b/back/app/services/side_fx_initiative_service.rb
deleted file mode 100644
index ce9199d5c45f..000000000000
--- a/back/app/services/side_fx_initiative_service.rb
+++ /dev/null
@@ -1,158 +0,0 @@
-# frozen_string_literal: true
-
-class SideFxInitiativeService
- include SideFxHelper
-
- def initialize
- @automatic_assignment = false
- end
-
- def before_create(initiative, user)
- before_publish initiative, user if initiative.published?
- end
-
- def after_create(initiative, user)
- initiative.update!(body_multiloc: TextImageService.new.swap_data_images_multiloc(initiative.body_multiloc, field: :body_multiloc, imageable: initiative))
- return unless initiative.published?
-
- after_publish initiative, user
-
- log_activities_if_cosponsors_added(initiative, user, _old_cosponsor_ids = [])
- end
-
- def before_update(initiative, user)
- initiative.body_multiloc = TextImageService.new.swap_data_images_multiloc(initiative.body_multiloc, field: :body_multiloc, imageable: initiative)
- return unless initiative.publication_status_change == %w[draft published]
-
- before_publish initiative, user
- end
-
- def after_update(initiative, user, old_cosponsor_ids)
- transition_to_review_pending_if_required(initiative, user)
- remove_user_from_past_activities_with_item(initiative, user) if initiative.anonymous_previously_changed?(to: true)
-
- LogActivityJob.perform_later(initiative, 'changed', user_for_activity_on_anonymizable_item(initiative, user), initiative.updated_at.to_i)
-
- if initiative.assignee_id_previously_changed?
- initiating_user = @automatic_assignment ? nil : user
- LogActivityJob.perform_later(initiative, 'changed_assignee', user_for_activity_on_anonymizable_item(initiative, initiating_user), initiative.updated_at.to_i, payload: { change: initiative.assignee_id_previous_change })
- end
-
- if initiative.title_multiloc_previously_changed?
- LogActivityJob.perform_later(initiative, 'changed_title', user_for_activity_on_anonymizable_item(initiative, user), initiative.updated_at.to_i, payload: { change: initiative.title_multiloc_previous_change })
- end
-
- if initiative.body_multiloc_previously_changed?
- LogActivityJob.perform_later(initiative, 'changed_body', user_for_activity_on_anonymizable_item(initiative, user), initiative.updated_at.to_i, payload: { change: initiative.body_multiloc_previous_change })
- end
-
- log_activities_if_cosponsors_added(initiative, user, old_cosponsor_ids)
- end
-
- def after_accept_cosponsorship_invite(cosponsors_initiative, user)
- LogActivityJob.perform_later(
- cosponsors_initiative,
- 'cosponsorship_accepted',
- user, # We don't want anonymized users being cosponsors
- cosponsors_initiative.updated_at.to_i,
- payload: { change: cosponsors_initiative.status_previous_change }
- )
- create_followers cosponsors_initiative.initiative, cosponsors_initiative.user
- end
-
- def before_destroy(initiative, user); end
-
- def after_destroy(frozen_initiative, user)
- serialized_initiative = clean_time_attributes(frozen_initiative.attributes)
- serialized_initiative['location_point'] = serialized_initiative['location_point'].to_s
- LogActivityJob.perform_later(encode_frozen_resource(frozen_initiative), 'deleted', user, Time.now.to_i, payload: { initiative: serialized_initiative })
- end
-
- def log_initiative_proposed_activity(initiative, user)
- LogActivityJob.perform_later(
- initiative,
- 'proposed',
- user_for_activity_on_anonymizable_item(initiative, user),
- initiative.updated_at.to_i
- )
- end
-
- private
-
- def log_activities_if_cosponsors_added(initiative, user, old_cosponsor_ids)
- added_ids = initiative.reload.cosponsors.map(&:id) - old_cosponsor_ids
-
- if added_ids.present?
- new_cosponsors_initiatives = initiative.cosponsors_initiatives.where(user_id: added_ids)
-
- new_cosponsors_initiatives.each do |cosponsors_initiative|
- LogActivityJob.perform_later(
- cosponsors_initiative,
- 'created',
- user, # We don't want anonymized authors when cosponsors feature in use
- cosponsors_initiative.created_at.to_i
- )
- end
- end
- end
-
- def transition_to_review_pending_if_required(initiative, user)
- if initiative.initiative_status&.code == 'changes_requested' && user == initiative.author
- status_id_to = InitiativeStatus.find_by(code: 'review_pending')&.id
- InitiativeStatusService.new.transition!([initiative.id], status_id_to)
- end
- end
-
- def before_publish(initiative, _user)
- set_assignee initiative
- end
-
- def after_publish(initiative, user)
- add_autoreaction(initiative, user)
- log_activity_jobs_after_published(initiative, user)
- create_followers(initiative, user) unless initiative.anonymous?
- end
-
- def set_assignee(initiative)
- default_assignee = User.active.admin.order(:created_at).reject(&:super_admin?).first
- return unless !initiative.assignee && default_assignee
-
- initiative.assignee = default_assignee
- @automatic_assignment = true
- end
-
- def add_autoreaction(initiative, user)
- reaction = Reaction.new(reactable: initiative, user: user, mode: 'up')
-
- begin
- Pundit.authorize(
- user,
- reaction,
- :create?,
- policy_class: InitiativeReactionPolicy
- )
- rescue Pundit::NotAuthorizedErrorWithReason
- # Do not create the auto-reaction.
- else
- initiative.reactions.create!(mode: 'up', user: initiative.author)
- initiative.reload
- end
- end
-
- def log_activity_jobs_after_published(initiative, user)
- LogActivityJob.set(wait: 20.seconds).perform_later(
- initiative,
- 'published',
- user_for_activity_on_anonymizable_item(initiative, user),
- initiative.published_at.to_i
- )
-
- log_initiative_proposed_activity(initiative, user) if initiative.initiative_status.code == 'proposed'
- end
-
- def create_followers(initiative, user)
- Follower.find_or_create_by(followable: initiative, user: user)
- end
-end
-
-SideFxInitiativeService.prepend(FlagInappropriateContent::Patches::SideFxInitiativeService)
diff --git a/back/app/services/side_fx_initiative_status_change_service.rb b/back/app/services/side_fx_initiative_status_change_service.rb
deleted file mode 100644
index 8a53c4ae56cc..000000000000
--- a/back/app/services/side_fx_initiative_status_change_service.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-class SideFxInitiativeStatusChangeService
- include SideFxHelper
-
- def before_create(change, user); end
-
- def after_create(change, user)
- InitiativeStatusService.new.log_status_change change, user: user
-
- # Behaviour we want when proposal review feature is on and initiative_status_change is to 'proposed':
- # * Create an Initiative 'proposed' activity type, to trigger the InitiativePublished campaign.
- # * Lock (prevent) editing of the initiative.
- # This works because, if the review feature is off, the associated initiative_status_change with code 'proposed'
- # is created at the model level when the initiative is published, and does not invoke this method.
- if change.initiative_status.code == 'proposed'
- SideFxInitiativeService.new.log_initiative_proposed_activity(change.initiative, user)
- change.initiative.update!(editing_locked: true)
- end
- end
-end
diff --git a/back/config/routes.rb b/back/config/routes.rb
index 6674a5f89cd9..9c2cb889a981 100644
--- a/back/config/routes.rb
+++ b/back/config/routes.rb
@@ -73,22 +73,6 @@
get :similarities, on: :member
end
- resources :initiatives,
- concerns: %i[reactable spam_reportable post followable],
- defaults: { reactable: 'Initiative', spam_reportable: 'Initiative', post: 'Initiative', followable: 'Initiative' } do
- resources :images, defaults: { container_type: 'Initiative' }
- resources :files, defaults: { container_type: 'Initiative' }
-
- resources :initiative_status_changes, shallow: true, except: %i[update destroy]
-
- get :as_xlsx, on: :collection, action: 'index_xlsx'
- get 'by_slug/:slug', on: :collection, to: 'initiatives#by_slug'
- get :as_markers, on: :collection, action: 'index_initiative_markers'
- get :filter_counts, on: :collection
- get :allowed_transitions, on: :member
- patch :accept_cosponsorship_invite, on: :member
- end
-
resources :background_jobs, only: %i[index]
resources :idea_statuses do
@@ -116,7 +100,6 @@
get 'by_slug/:slug', on: :collection, to: 'users#by_slug'
get 'by_invite/:token', on: :collection, to: 'users#by_invite'
get 'ideas_count', on: :member
- get 'initiatives_count', on: :member
get 'comments_count', on: :member
get 'blocked_count', on: :collection
get 'check/:email', on: :collection, to: 'users#check', constraints: { email: /.*/ }
@@ -279,8 +262,6 @@
get 'ideas_by_project_as_xlsx'
end
- get 'initiatives_count', controller: 'stats_initiatives'
-
with_options controller: 'stats_comments' do
get 'comments_count'
get 'comments_by_topic'
diff --git a/back/engines/commercial/admin_api/app/graphql/admin_api/types/initiative_type.rb b/back/engines/commercial/admin_api/app/graphql/admin_api/types/initiative_type.rb
deleted file mode 100644
index 65bf2ec62b8c..000000000000
--- a/back/engines/commercial/admin_api/app/graphql/admin_api/types/initiative_type.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-module AdminApi
- class Types::InitiativeType < GraphQL::Schema::Object
- description 'Single unit of citizen input'
-
- class InitiativePublicationStatus < GraphQL::Schema::Enum
- Initiative::PUBLICATION_STATUSES.each do |ps|
- value ps
- end
- end
-
- class InitiativeImage < GraphQL::Schema::Object
- description 'An image associates with an initiative'
-
- field :id, ID, null: false
- field :ordering, Integer, null: true
- field :small_url, String, null: false
- def small_url
- object.image.versions[:small].url
- end
- field :medium_url, String, null: false
- def medium_url
- object.image.versions[:medium].url
- end
- field :large_url, String, null: false
- def large_url
- object.image.versions[:large].url
- end
- field :updated_at, String, null: false
- field :created_at, String, null: false
- end
-
- field :id, ID, null: false
- field :title_multiloc, Types::MultilocType, null: false
- field :slug, String, null: false
- field :publication_status, InitiativePublicationStatus, null: false
- field :updated_at, String, null: false
- field :created_at, String, null: false
- field :published_at, String, null: false
- field :href, String, null: true
- field :likes_count, Integer, null: false
- field :comments_count, Integer, null: false
- field :internal_comments_count, Integer, null: false
- field :images, InitiativeImage.connection_type, null: true
- def images
- object.initiative_images
- end
-
- def href
- Frontend::UrlService.new.model_to_url(object)
- end
- end
-end
diff --git a/back/engines/commercial/admin_api/app/graphql/admin_api/types/query_type.rb b/back/engines/commercial/admin_api/app/graphql/admin_api/types/query_type.rb
index cc8c3de750b9..623fdc355136 100644
--- a/back/engines/commercial/admin_api/app/graphql/admin_api/types/query_type.rb
+++ b/back/engines/commercial/admin_api/app/graphql/admin_api/types/query_type.rb
@@ -72,21 +72,6 @@ def public_ideas(args = {})
ideas
end
- field :initiatives, Types::InitiativeType.connection_type, null: false
-
- def initiatives
- Initiative.all
- end
-
- field :public_initiatives, Types::InitiativeType.connection_type, null: false
-
- def public_initiatives(_args = {})
- ::InitiativePolicy::Scope.new(nil, Initiative)
- .resolve
- .includes(:initiative_images)
- .published
- end
-
field :user, Types::UserType, null: false do
argument :id, ID, required: true
end
@@ -132,15 +117,6 @@ def idea(args)
Idea.find(args[:id])
end
- field :initiative, Types::InitiativeType, null: false do
- argument :id, ID, required: true
- description 'Find an initiative by ID'
- end
-
- def initiative(args)
- Initiative.find(args[:id])
- end
-
field :public_pages, Types::PageType.connection_type, null: false
def public_pages
::StaticPagePolicy::Scope.new(nil, StaticPage).resolve
diff --git a/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb b/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
deleted file mode 100644
index 1451fb27ae6f..000000000000
--- a/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-RSpec.describe AdminApi::Schema do
- let(:context) { {} }
- let(:variables) { {} }
- let(:result) do
- res = described_class.execute(
- query_string,
- context: context,
- variables: variables
- )
- if res['errors']
- pp res
- end
- res
- end
-
- describe 'publicInitiatives' do
- let(:query_string) do
- %|
- query {
- publicInitiatives(first: 5) {
- edges {
- node {
- id
- href
- titleMultiloc {
- en
- nlBe
- frBe
- frFr
- }
- images(first: 1) {
- edges {
- node {
- smallUrl
- }
- }
- }
- likesCount
- commentsCount
- internalCommentsCount
- }
- }
- }
- }
- |
- end
-
- it 'returns all public initiatives with fields' do
- create_list(:initiative, 5)
- create(:initiative, publication_status: 'draft')
- response = result
- edges = response.dig('data', 'publicInitiatives', 'edges')
- expect(edges&.size).to eq 5
- expect(edges&.first&.dig('node', 'id')).to be_present
- expect(edges&.first&.dig('node', 'href')).to be_present
- expect(edges&.first&.dig('node', 'titleMultiloc')&.values&.compact&.size).to be >= 1
- expect(edges&.first&.dig('node', 'likesCount')).to be_present
- expect(edges&.first&.dig('node', 'commentsCount')).to be_present
- expect(edges&.first&.dig('node', 'internalCommentsCount')).to be_present
- end
- end
-end
diff --git a/back/engines/commercial/analytics/app/services/analytics/populate_dimensions_service.rb b/back/engines/commercial/analytics/app/services/analytics/populate_dimensions_service.rb
index 236c1d82c391..7fd955a9571c 100644
--- a/back/engines/commercial/analytics/app/services/analytics/populate_dimensions_service.rb
+++ b/back/engines/commercial/analytics/app/services/analytics/populate_dimensions_service.rb
@@ -13,12 +13,9 @@ def run
def populate_types
types = [
{ name: 'idea', parent: 'post' },
- { name: 'initiative', parent: 'post' },
{ name: 'proposal', parent: 'post' },
- { name: 'comment', parent: 'initiative' },
{ name: 'comment', parent: 'idea' },
{ name: 'comment', parent: 'proposal' },
- { name: 'reaction', parent: 'initiative' },
{ name: 'reaction', parent: 'idea' },
{ name: 'reaction', parent: 'comment' },
{ name: 'poll', parent: nil },
@@ -43,8 +40,7 @@ def populate_dates
tenant_creation = AppConfiguration.instance.created_at
first_idea = Idea.order(:created_at).limit(1).pluck(:created_at)[0]
- first_initiative = Initiative.order(:created_at).limit(1).pluck(:created_at)[0]
- first_activity_date = [tenant_creation, first_idea, first_initiative].compact.min.to_date
+ first_activity_date = [tenant_creation, first_idea].compact.min.to_date
if Analytics::DimensionDate.none?
from = first_activity_date
diff --git a/back/engines/commercial/analytics/spec/models/analytics/fact_participation_spec.rb b/back/engines/commercial/analytics/spec/models/analytics/fact_participation_spec.rb
index 5dafc9046703..493ab1fea6bd 100644
--- a/back/engines/commercial/analytics/spec/models/analytics/fact_participation_spec.rb
+++ b/back/engines/commercial/analytics/spec/models/analytics/fact_participation_spec.rb
@@ -34,16 +34,6 @@
end
end
- # TODO: cleanup-after-proposals-migration
- context 'when an initiative is created' do
- let!(:initiative) { create(:initiative) }
-
- it 'is also available as a participation fact' do
- participation = described_class.find(initiative.id)
- expect(participation.dimension_type.name).to eq('initiative')
- end
- end
-
context 'when a comment is added' do
let!(:comment) { create(:comment) }
diff --git a/back/engines/commercial/analytics/spec/services/analytics/populate_dimensions_service_spec.rb b/back/engines/commercial/analytics/spec/services/analytics/populate_dimensions_service_spec.rb
index 0a6544482012..044a7ba01b65 100644
--- a/back/engines/commercial/analytics/spec/services/analytics/populate_dimensions_service_spec.rb
+++ b/back/engines/commercial/analytics/spec/services/analytics/populate_dimensions_service_spec.rb
@@ -3,7 +3,7 @@
require 'rails_helper'
describe Analytics::PopulateDimensionsService do
- describe 'run with no ideas or initiatives' do
+ describe 'run with no ideas' do
before_all do
described_class.run
end
@@ -21,7 +21,7 @@
end
it 'has 20 dimension types' do
- expect(Analytics::DimensionType.count).to eq(20)
+ expect(Analytics::DimensionType.count).to eq(16)
end
it 'has 5 referrer types' do
diff --git a/back/engines/commercial/flag_inappropriate_content/app/services/flag_inappropriate_content/patches/side_fx_initiative_service.rb b/back/engines/commercial/flag_inappropriate_content/app/services/flag_inappropriate_content/patches/side_fx_initiative_service.rb
deleted file mode 100644
index 97c0aa60c78e..000000000000
--- a/back/engines/commercial/flag_inappropriate_content/app/services/flag_inappropriate_content/patches/side_fx_initiative_service.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module FlagInappropriateContent
- module Patches
- module SideFxInitiativeService
- SUPPORTED_ATTRS = %i[title_multiloc body_multiloc location_description].freeze
-
- def after_create(initiative, user)
- super
- ToxicityDetectionJob.perform_later initiative, attributes: SUPPORTED_ATTRS
- end
-
- def after_update(initiative, user, _old_cosponsor_ids)
- # before super to reliably detect attribute changes
- atrs = updated_supported_attrs initiative
- if atrs.present?
- # retry all attributes to consider removing flag
- atrs = SUPPORTED_ATTRS if initiative.inappropriate_content_flag
- ToxicityDetectionJob.perform_later initiative, attributes: atrs
- end
-
- super
- end
-
- private
-
- def updated_supported_attrs(initiative)
- SUPPORTED_ATTRS.select do |atr|
- initiative.saved_change_to_attribute? atr
- end
- end
- end
- end
-end
diff --git a/back/engines/commercial/flag_inappropriate_content/spec/acceptance/initiatives_spec.rb b/back/engines/commercial/flag_inappropriate_content/spec/acceptance/initiatives_spec.rb
deleted file mode 100644
index 428e736a6999..000000000000
--- a/back/engines/commercial/flag_inappropriate_content/spec/acceptance/initiatives_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'Initiatives' do
- before do
- header 'Content-Type', 'application/json'
- @user = create(:user)
- header_token_for @user
-
- create(:initiative_status, code: 'proposed')
- end
-
- post 'web_api/v1/initiatives' do
- with_options scope: :initiative do
- parameter :publication_status
- parameter :title_multiloc
- parameter :body_multiloc
- parameter :location_description
- end
-
- let(:initiative) { build(:initiative) }
- let(:publication_status) { 'published' }
- let(:title_multiloc) { initiative.title_multiloc }
- let(:body_multiloc) { initiative.body_multiloc }
-
- example 'Toxicity detection job is enqueued when creating an initiative', document: false do
- SettingsService.new.activate_feature! 'moderation'
- SettingsService.new.activate_feature! 'flag_inappropriate_content'
- expect do
- do_request
- end.to have_enqueued_job(ToxicityDetectionJob)
- end
- end
-
- patch 'web_api/v1/initiatives/:id' do
- before do
- SettingsService.new.activate_feature! 'moderation'
- SettingsService.new.activate_feature! 'flag_inappropriate_content'
- @initiative = create(:initiative, author: @user)
- end
-
- with_options scope: :initiative do
- parameter :title_multiloc
- parameter :body_multiloc
- parameter :location_description
- parameter :topic_ids
- end
-
- let(:id) { @initiative.id }
-
- describe do
- let(:location_description) { 'Watkins Road 8' }
-
- example 'Toxicity detection job is enqueued when updating an initiative\'s title', document: false do
- expect do
- do_request
- end.to have_enqueued_job(ToxicityDetectionJob).with(@initiative, attributes: [:location_description])
- end
- end
-
- describe do
- let(:topic_ids) { [create(:topic).id] }
-
- example 'No toxicity detection job is enqueued when updating initiative attributes without text', document: false do
- expect do
- do_request
- end.not_to have_enqueued_job(ToxicityDetectionJob)
- end
- end
- end
-end
diff --git a/back/engines/commercial/machine_translations/app/controllers/machine_translations/web_api/v1/machine_translations_controller.rb b/back/engines/commercial/machine_translations/app/controllers/machine_translations/web_api/v1/machine_translations_controller.rb
index c39099e30117..b724b51e4035 100644
--- a/back/engines/commercial/machine_translations/app/controllers/machine_translations/web_api/v1/machine_translations_controller.rb
+++ b/back/engines/commercial/machine_translations/app/controllers/machine_translations/web_api/v1/machine_translations_controller.rb
@@ -11,10 +11,6 @@ class MachineTranslationsController < ApplicationController
translatable_class: Idea,
translatable_id: :idea_id
},
- 'Initiative' => {
- translatable_class: Initiative,
- translatable_id: :initiative_id
- },
'Comment' => {
translatable_class: Comment,
translatable_id: :comment_id
diff --git a/back/engines/commercial/machine_translations/config/routes.rb b/back/engines/commercial/machine_translations/config/routes.rb
index e0f7df62a830..e5aa47c5db0f 100644
--- a/back/engines/commercial/machine_translations/config/routes.rb
+++ b/back/engines/commercial/machine_translations/config/routes.rb
@@ -6,9 +6,6 @@
defaults translatable_type: 'Idea' do
get 'ideas/:idea_id/machine_translation', action: :show, controller: 'machine_translations'
end
- defaults translatable_type: 'Initiative' do
- get 'initiatives/:initiative_id/machine_translation', action: :show, controller: 'machine_translations'
- end
defaults translatable_type: 'Comment' do
get 'comments/:comment_id/machine_translation', action: :show, controller: 'machine_translations'
end
diff --git a/back/engines/commercial/machine_translations/spec/acceptance/machine_translations_spec.rb b/back/engines/commercial/machine_translations/spec/acceptance/machine_translations_spec.rb
index 409347b9a1ae..406eb1bf6e19 100644
--- a/back/engines/commercial/machine_translations/spec/acceptance/machine_translations_spec.rb
+++ b/back/engines/commercial/machine_translations/spec/acceptance/machine_translations_spec.rb
@@ -80,55 +80,6 @@
end
end
- # TODO: cleanup-after-proposals-migration
- get '/web_api/v1/initiatives/:initiative_id/machine_translation' do
- with_options scope: :machine_translation do
- parameter :attribute_name, 'The name of the attribute to translate (e.g. title_multiloc)'
- parameter :locale_to, 'The locale to translate to'
- end
-
- describe 'Get one machine translation:' do
- let(:translation) { create(:machine_translation, translatable: create(:initiative, title_multiloc: { 'nl-BE' => 'Fietssnelweg doorheen het stadcentrum' })) }
- let(:initiative_id) { translation.translatable_id }
- let(:attribute_name) { translation.attribute_name }
- let(:locale_to) { translation.locale_to }
-
- example_request 'Return an up to date translation if it has already been created' do
- expect(status).to eq 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :attributes, :translation)).to eq translation.translation
- end
-
- example 'Update the translation if it has already been created but the original text might have changed' do
- prev_updated_at = translation.updated_at
- translation.translatable.update! title_multiloc: { 'nl-BE' => 'Fietssnelweg doorheen elke deelgemeente' }
- do_request
- expect(status).to eq 200
- expect(translation.reload.updated_at).to be > prev_updated_at
- end
-
- example '[error] Create a translation for an unknown resource' do
- translation.translatable.destroy!
- do_request
- expect(status).to eq 404
- end
- end
-
- describe do
- let(:translation) { nil }
- let(:initiative_id) { create(:initiative).id }
- let(:attribute_name) { 'title_multiloc' }
- let(:locale_to) { 'en' }
-
- example_request 'A new machine translation is created when the translation was never done before' do
- expect(status).to eq 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :attributes, :attribute_name)).to eq attribute_name
- expect(json_response.dig(:data, :relationships, :translatable, :data, :id)).to eq initiative_id
- end
- end
- end
-
get '/web_api/v1/comments/:comment_id/machine_translation' do
with_options scope: :machine_translation do
parameter :attribute_name, 'The name of the attribute to translate (e.g. title_multiloc)'
diff --git a/back/engines/commercial/multi_tenancy/db/seeds/initiatives.rb b/back/engines/commercial/multi_tenancy/db/seeds/initiatives.rb
deleted file mode 100644
index 5cbd84219395..000000000000
--- a/back/engines/commercial/multi_tenancy/db/seeds/initiatives.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'base'
-
-module MultiTenancy
- module Seeds
- class Initiatives < Base
- def run
- runner.num_initiatives.times do
- created_at = Faker::Date.between(from: Tenant.current.created_at, to: Time.zone.now)
- initiative = Initiative.create!(
- title_multiloc: runner.create_for_some_locales { Faker::Lorem.sentence[0...80] },
- body_multiloc: runner.rand_description_multiloc,
- author: User.offset(rand(User.count)).first,
- publication_status: 'published',
- published_at: Faker::Date.between(from: created_at, to: Time.zone.now),
- created_at: created_at,
- location_point: rand(3) == 0 ? nil : "POINT(#{runner.map_center[1] + (((rand * 2) - 1) * runner.map_offset)} #{runner.map_center[0] + (((rand * 2) - 1) * runner.map_offset)})",
- location_description: rand(2) == 0 ? nil : Faker::Address.street_address,
- header_bg: rand(25) == 0 ? nil : Rails.root.join("spec/fixtures/image#{rand(20)}.png").open,
- topics: Array.new(rand(3)) { rand(Topic.count) }.uniq.map { |offset| Topic.offset(offset).first },
- areas: Array.new(rand(3)) { rand(Area.count) }.uniq.map { |offset| Area.offset(offset).first },
- assignee: rand(5) == 0 ? User.admin.sample : nil
- )
-
- [1, 1, 2, 2, 3][rand(5)].times do |_i|
- initiative.initiative_images.create!(image: Rails.root.join("spec/fixtures/image#{rand(20)}.png").open)
- end
- if rand(5) == 0
- rand(1..3).times do
- initiative.initiative_files.create!(runner.generate_file_attributes)
- end
- end
-
- User.all.each do |u|
- r = rand(5)
- if r < 2
- Reaction.create!(reactable: initiative, user: u, mode: 'up',
- created_at: Faker::Date.between(from: initiative.published_at, to: Time.zone.now))
- end
- end
-
- rand(5).times do
- initiative.official_feedbacks.create!(
- body_multiloc: runner.rand_description_multiloc,
- author_multiloc: runner.create_for_some_locales { Faker::FunnyName.name },
- user: User.admin.sample
- )
- end
-
- runner.create_comment_tree(initiative, nil)
- end
- end
- end
- end
-end
diff --git a/back/engines/commercial/multi_tenancy/db/seeds/runner.rb b/back/engines/commercial/multi_tenancy/db/seeds/runner.rb
index 4ff5ab51c17d..17cc1b61d41a 100644
--- a/back/engines/commercial/multi_tenancy/db/seeds/runner.rb
+++ b/back/engines/commercial/multi_tenancy/db/seeds/runner.rb
@@ -16,7 +16,6 @@
require_relative 'followers'
require_relative 'groups'
require_relative 'ideas'
-require_relative 'initiatives'
require_relative 'internal_comments'
require_relative 'invites'
require_relative 'permissions'
@@ -44,20 +43,17 @@ class Runner
small: {
num_users: 5,
num_projects: 1,
- num_ideas: 4,
- num_initiatives: 3
+ num_ideas: 4
},
medium: {
num_users: 10,
num_projects: 5,
- num_ideas: 15,
- num_initiatives: 10
+ num_ideas: 15
},
large: {
num_users: 50,
num_projects: 20,
- num_ideas: 100,
- num_initiatives: 60
+ num_ideas: 100
}
}.freeze
@@ -111,7 +107,6 @@ def seed_localhost_tenant
MultiTenancy::Seeds::ProjectFolders.new(runner: self).run
MultiTenancy::Seeds::Projects.new(runner: self).run
MultiTenancy::Seeds::Ideas.new(runner: self).run
- MultiTenancy::Seeds::Initiatives.new(runner: self).run
MultiTenancy::Seeds::InternalComments.new(runner: self).run
InitiativeStatusService.new.automated_transitions!
@@ -150,11 +145,6 @@ def num_ideas
SEED_SIZES.dig(seed_size, :num_ideas)
end
- # @return [Integer] Number of iniatives to be seeded
- def num_initiatives
- SEED_SIZES.dig(seed_size, :num_initiatives)
- end
-
# @return [Float] default map center
def map_center
MAP_CENTER
diff --git a/back/engines/commercial/public_api/app/controllers/public_api/v2/initiatives_controller.rb b/back/engines/commercial/public_api/app/controllers/public_api/v2/initiatives_controller.rb
deleted file mode 100644
index 79be12f1a4cf..000000000000
--- a/back/engines/commercial/public_api/app/controllers/public_api/v2/initiatives_controller.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module PublicApi
- class V2::InitiativesController < PublicApiController
- include DeletedItemsAction
-
- def index
- initiatives = Initiative
- .order(created_at: :desc)
- .page(params[:page_number])
- .per(num_per_page)
-
- initiatives = common_date_filters(initiatives)
-
- render json: initiatives,
- each_serializer: V2::InitiativeSerializer,
- adapter: :json,
- meta: meta_properties(initiatives)
- end
-
- def show
- show_item Initiative.find(params[:id]), V2::InitiativeSerializer
- end
- end
-end
diff --git a/back/engines/commercial/public_api/config/routes.rb b/back/engines/commercial/public_api/config/routes.rb
index 6c6593eedf26..c7e359e4b6af 100644
--- a/back/engines/commercial/public_api/config/routes.rb
+++ b/back/engines/commercial/public_api/config/routes.rb
@@ -26,7 +26,6 @@
route_mapper.resources :events
route_mapper.resources :event_attendances
route_mapper.resources :ideas
- route_mapper.resources :initiatives
route_mapper.resources :phases
route_mapper.resources :project_folders
route_mapper.resources :reactions, only: %i[index]
diff --git a/back/engines/commercial/public_api/spec/acceptance/v2/initiatives_spec.rb b/back/engines/commercial/public_api/spec/acceptance/v2/initiatives_spec.rb
deleted file mode 100644
index e97199abb191..000000000000
--- a/back/engines/commercial/public_api/spec/acceptance/v2/initiatives_spec.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-require './engines/commercial/public_api/spec/acceptance/v2/support/shared'
-
-# TODO: cleanup-after-proposals-migration
-resource 'Posts' do
- # NOTE: Same name as in ideas_spec to combine the documentation into the same section
- explanation <<~DESC.squish
- Posts are written inputs created by citizens. These can be ideas, initiatives
- (proposals), or survey responses.
- DESC
-
- include_context 'common_auth'
-
- let!(:initiatives) { create_list(:initiative, 5, created_at: '2020-01-01') }
-
- get '/api/v2/initiatives/' do
- route_summary 'List initiatives - known as proposals in the platform'
- route_description <<~DESC.squish
- Retrieve a paginated list of all the initiatives in the platform, with the most
- recent ones appearing first.
- DESC
-
- include_context 'common_list_params'
-
- context 'when the page size is smaller than the total number of initiatives' do
- let(:page_size) { 2 }
-
- example_request 'List only the first initiatives' do
- assert_status 200
- expect(json_response_body[:initiatives].size).to eq(page_size)
-
- total_pages = (initiatives.size.to_f / page_size).ceil
- expect(json_response_body[:meta]).to eq({ total_pages: total_pages, current_page: 1 })
- end
- end
-
- include_examples 'filtering_by_date', :initiative, :created_at
- include_examples 'filtering_by_date', :initiative, :updated_at
- end
-
- get '/api/v2/initiatives/:id' do
- route_summary 'Get an initiative (proposal)'
- route_description 'Retrieve a single initiative (proposal) by its ID.'
-
- include_context 'common_item_params'
-
- let(:initiative) { initiatives.first }
- let(:id) { initiative.id }
-
- before do
- # NOTE: Temp fix until locales of factories and tenants are consistent
- # Currently, the tenant locales are ["en", "fr-FR", "nl-NL"], while the factory
- # locales are ["en", "nl-BE"]. The following code aligns the two by replacing
- # the "nl-BE" locale with "nl-NL" in the initiative.
- title = initiative[:title_multiloc]
- title['nl-NL'] = title.delete 'nl-BE'
- initiative.update!(title_multiloc: title)
- end
-
- example_request 'Return the initiative in the default locale' do
- assert_status 200
- expect(json_response_body[:initiative]).to include({ id: id })
- expect(json_response_body.dig(:initiative, :threshold_reached_at)).to be_nil
- end
-
- context 'when requesting the initiative in a specific locale' do
- let(:locale) { 'nl-NL' }
-
- example_request 'Return the initiative in the requested locale', document: false do
- assert_status 200
- expect(json_response_body.dig(:initiative, :title)).to eq initiative.title_multiloc['nl-NL']
- end
- end
-
- context 'when initiative is successful' do
- let(:initiative) { create(:initiative, initiative_status: create(:initiative_status_threshold_reached)) }
-
- example_request 'Return the initiative with successful date', document: false do
- assert_status 200
- expect(json_response_body.dig(:initiative, :threshold_reached_at)).not_to be_nil
- end
- end
- end
-
- include_examples '/api/v2/.../deleted', :initiatives
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/comment_on_initiative_you_follow_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/comment_on_initiative_you_follow_mailer.rb
deleted file mode 100644
index 3888e0ef4fa4..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/comment_on_initiative_you_follow_mailer.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class CommentOnInitiativeYouFollowMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject', values: { organizationName: organization_name, authorName: event.comment_author_name })
- end
-
- def header_title
- format_message('main_header', values: { commentAuthor: event.comment_author_name })
- end
-
- def header_message
- format_message(
- 'event_description',
- values: {
- authorNameFull: event.comment_author_name,
- authorName: event.initiating_user_first_name,
- initiativeTitle: localize_for_recipient(event.post_title_multiloc)
- }
- )
- end
-
- def preheader
- format_message('preheader', values: { organizationName: organization_name, authorName: event.comment_author_name })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/cosponsor_of_your_initiative_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/cosponsor_of_your_initiative_mailer.rb
deleted file mode 100644
index fc73e3166a6c..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/cosponsor_of_your_initiative_mailer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class CosponsorOfYourInitiativeMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject', values: { cosponsorName: event.post_cosponsor_name })
- end
-
- def header_title
- format_message('main_header', values: { cosponsorName: event.post_cosponsor_name })
- end
-
- private
-
- def header_message
- format_message('event_description_initiative', values: { cosponsorName: event.post_cosponsor_name })
- end
-
- def preheader
- format_message('preheader_initiative', values: { cosponsorName: event.post_cosponsor_name })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_assigned_to_you_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_assigned_to_you_mailer.rb
deleted file mode 100644
index 85b45b1d7e1f..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_assigned_to_you_mailer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativeAssignedToYouMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject', values: { organizationName: organization_name })
- end
-
- private
-
- def header_title
- format_message('main_header', values: { firstName: recipient_first_name })
- end
-
- def header_message
- format_message('event_description_initiative')
- end
-
- def preheader
- format_message('preheader_initiative', values: { organizationName: organization_name, authorName: event.post_author_name })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_marked_as_spam_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_marked_as_spam_mailer.rb
deleted file mode 100644
index f5184b8460eb..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_marked_as_spam_mailer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativeMarkedAsSpamMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject', values: { organizationName: organization_name })
- end
-
- private
-
- def header_title
- format_message('title_spam_report', values: { firstName: event.initiating_user_first_name, lastName: event.initiating_user_last_name })
- end
-
- def header_message
- false
- end
-
- def preheader
- format_message('preheader')
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_published_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_published_mailer.rb
deleted file mode 100644
index 88a29be4f472..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_published_mailer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativePublishedMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject', values: { organizationName: organization_name })
- end
-
- private
-
- def header_title
- format_message('main_header')
- end
-
- def header_message
- format_message('message_next_steps', values: { userFirstName: recipient_first_name, organizationName: organization_name })
- end
-
- def preheader
- format_message('preheader', values: { initiativeTitle: localize_for_recipient(event.post_title_multiloc), organizationName: organization_name })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_resubmitted_for_review_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_resubmitted_for_review_mailer.rb
deleted file mode 100644
index b82ac46ce727..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_resubmitted_for_review_mailer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativeResubmittedForReviewMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject', values: { organizationName: organization_name })
- end
-
- private
-
- def header_title
- format_message('main_header', values: { firstName: recipient_first_name })
- end
-
- def header_message
- format_message('event_description_initiative')
- end
-
- def preheader
- format_message('preheader_initiative', values: { organizationName: organization_name, authorName: event.post_author_name })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer.rb
deleted file mode 100644
index 7ee697d6d952..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InternalCommentOnInitiativeAssignedToYouMailer < BaseInternalCommentMailer
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer.rb
deleted file mode 100644
index 433d8d883d52..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InternalCommentOnInitiativeYouCommentedInternallyOnMailer < BaseInternalCommentMailer
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_unassigned_initiative_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_unassigned_initiative_mailer.rb
deleted file mode 100644
index 6e193e272dac..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_unassigned_initiative_mailer.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InternalCommentOnUnassignedInitiativeMailer < BaseInternalCommentMailer
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/invitation_to_cosponsor_initiative_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/invitation_to_cosponsor_initiative_mailer.rb
deleted file mode 100644
index ec1ccb891097..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/invitation_to_cosponsor_initiative_mailer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InvitationToCosponsorInitiativeMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject')
- end
-
- def header_title
- format_message('main_header')
- end
-
- private
-
- def header_message
- format_message('event_description_initiative', values: { authorName: event.post_author_name })
- end
-
- def preheader
- format_message('preheader_initiative', values: { authorName: event.post_author_name })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/new_initiative_for_admin_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/new_initiative_for_admin_mailer.rb
deleted file mode 100644
index f84102d7eea8..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/new_initiative_for_admin_mailer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class NewInitiativeForAdminMailer < ApplicationMailer
- protected
-
- def subject
- format_message('subject', values: { organizationName: organization_name })
- end
-
- private
-
- def header_title
- format_message('main_header', values: { firstName: recipient_first_name })
- end
-
- def header_message
- format_message('event_description', values: { authorName: event.post_author_name, organizationName: organization_name })
- end
-
- def preheader
- format_message('preheader', values: { authorName: event.post_author_name, organizationName: organization_name })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/official_feedback_on_initiative_you_follow_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/official_feedback_on_initiative_you_follow_mailer.rb
deleted file mode 100644
index 058398f9070b..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/official_feedback_on_initiative_you_follow_mailer.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class OfficialFeedbackOnInitiativeYouFollowMailer < ApplicationMailer
- private
-
- helper_method :author_name
-
- def author_name
- localize_for_recipient(event.official_feedback_author_multiloc)
- end
-
- def preheader
- format_message('preheader')
- end
-
- def subject
- format_message('subject', values: { organizationName: organization_name })
- end
-
- def header_title
- format_message('header_title', values: { officialName: organization_name })
- end
-
- def header_message
- format_message(
- 'header_message',
- values: {
- initiativeTitle: localize_for_recipient(event.post_title_multiloc),
- officialName: localize_for_recipient(event.official_feedback_author_multiloc),
- organizationName: organization_name
- }
- )
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/mailers/email_campaigns/status_change_on_initiative_you_follow_mailer.rb b/back/engines/free/email_campaigns/app/mailers/email_campaigns/status_change_on_initiative_you_follow_mailer.rb
deleted file mode 100644
index ff92361291e7..000000000000
--- a/back/engines/free/email_campaigns/app/mailers/email_campaigns/status_change_on_initiative_you_follow_mailer.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class StatusChangeOnInitiativeYouFollowMailer < ApplicationMailer
- private
-
- def preheader
- format_message('preheader')
- end
-
- def subject
- format_message('subject')
- end
-
- def header_title
- format_message('header_title', values: { organizationName: organization_name })
- end
-
- def header_message
- format_message(
- 'header_message',
- values: {
- initiativeTitle: localize_for_recipient(event.post_title_multiloc),
- organizationName: organization_name
- }
- )
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/comment_on_initiative_you_follow.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/comment_on_initiative_you_follow.rb
deleted file mode 100644
index c10b7a3d45c3..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/comment_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::CommentOnInitiativeYouFollow < Campaign
- include Consentable
- include Disableable
- include ActivityTriggerable
- include RecipientConfigurable
- include LifecycleStageRestrictable
- include Trackable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def mailer_class
- CommentOnInitiativeYouFollowMailer
- end
-
- def activity_triggers
- { 'Notifications::CommentOnInitiativeYouFollow' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.registered_users'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.users_who_follow_the_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.user_comments_on_proposal'
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- notification = activity.item
- name_service = UserDisplayNameService.new(AppConfiguration.instance, recipient)
- [{
- event_payload: {
- initiating_user_first_name: notification.initiating_user&.first_name,
- initiating_user_last_name: name_service.last_name!(notification.initiating_user),
- comment_author_name: name_service.display_name!(notification.comment.author),
- comment_body_multiloc: notification.comment.body_multiloc,
- comment_url: Frontend::UrlService.new.model_to_url(notification.comment, locale: Locale.new(recipient.locale)),
- post_published_at: notification.post.published_at.iso8601,
- post_title_multiloc: notification.post.title_multiloc,
- post_author_name: name_service.display_name!(notification.post.author),
- unfollow_url: Frontend::UrlService.new.unfollow_url(Follower.new(followable: notification.post, user: recipient))
- }
- }]
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/cosponsor_of_your_initiative.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/cosponsor_of_your_initiative.rb
deleted file mode 100644
index e70a52021bc0..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/cosponsor_of_your_initiative.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::CosponsorOfYourInitiative < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include Trackable
- include LifecycleStageRestrictable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def mailer_class
- CosponsorOfYourInitiativeMailer
- end
-
- def activity_triggers
- { 'Notifications::CosponsorOfYourInitiative' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.registered_users'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.user_who_published_the_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.user_accepts_invitation_to_cosponsor_a_proposal'
- end
-
- def generate_commands(recipient:, activity:)
- initiative = activity.item.post
- cosponsor = activity.item.initiating_user
- name_service = UserDisplayNameService.new(AppConfiguration.instance, recipient)
-
- [{
- event_payload: {
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_author_name: name_service.display_name!(initiative.author),
- post_cosponsor_name: name_service.display_name!(cosponsor),
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- post_image_medium_url: post_image_medium_url(initiative)
- }
- }]
- end
-
- private
-
- def post_image_medium_url(initiative)
- image = initiative&.initiative_images&.first
- image.image.versions[:medium].url if image&.image&.versions
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_assigned_to_you.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_assigned_to_you.rb
deleted file mode 100644
index 507bb010407e..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_assigned_to_you.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InitiativeAssignedToYou < Campaign
- include Consentable
- include ActivityTriggerable
- include Disableable
- include Trackable
- include LifecycleStageRestrictable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def self.consentable_roles
- ['admin']
- end
-
- def mailer_class
- InitiativeAssignedToYouMailer
- end
-
- def activity_triggers
- { 'Notifications::InitiativeAssignedToYou' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.admins_and_managers'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.admins_assigned_to_a_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.proposal_is_assigned_to_admin'
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- notification = activity.item
- name_service = UserDisplayNameService.new(AppConfiguration.instance, recipient)
- [{
- event_payload: {
- post_title_multiloc: notification.post.title_multiloc,
- post_body_multiloc: notification.post.body_multiloc,
- post_author_name: name_service.display_name!(notification.post.author),
- post_published_at: notification.post.published_at.iso8601,
- post_url: Frontend::UrlService.new.model_to_url(notification.post, locale: Locale.new(recipient.locale)),
- post_assigned_at: notification.post.assigned_at&.iso8601,
- initiative_reactions_needed: notification.post.reactions_needed,
- initiative_expires_at: notification.post.expires_at.iso8601
- }
- }]
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_marked_as_spam.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_marked_as_spam.rb
deleted file mode 100644
index 9029de537cfd..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_marked_as_spam.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InitiativeMarkedAsSpam < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include LifecycleStageRestrictable
- include Trackable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def self.consentable_roles
- ['admin']
- end
-
- def mailer_class
- InitiativeMarkedAsSpamMailer
- end
-
- def activity_triggers
- { 'Notifications::InitiativeMarkedAsSpam' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.admins_and_managers'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.admins'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.proposal_gets_reported_as_spam'
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- notification = activity.item
- [{
- event_payload: {
- initiating_user_first_name: notification.initiating_user&.first_name,
- initiating_user_last_name: notification.initiating_user&.last_name,
- post_created_at: notification.post.created_at.iso8601,
- post_title_multiloc: notification.post.title_multiloc,
- post_author_name: notification.post.author_name,
- post_url: Frontend::UrlService.new.model_to_url(notification.post, locale: Locale.new(recipient.locale)),
- initiative_reactions_needed: notification.post.reactions_needed,
- initiative_expires_at: notification.post.expires_at.iso8601,
- spam_report_reason_code: notification.spam_report.reason_code,
- spam_report_other_reason: notification.spam_report.other_reason
- }
- }]
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_published.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_published.rb
deleted file mode 100644
index b2640b2897e5..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_published.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InitiativePublished < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include Trackable
- include LifecycleStageRestrictable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_recipient
-
- def mailer_class
- InitiativePublishedMailer
- end
-
- def activity_triggers
- { 'Initiative' => { 'proposed' => true } }
- end
-
- def filter_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.author_id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.registered_users'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.user_who_published_the_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.proposal_is_published'
- end
-
- def generate_commands(recipient:, activity:)
- initiative = activity.item
- [{
- event_payload: {
- post_id: initiative.id,
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- post_images: initiative.initiative_images.map do |image|
- {
- ordering: image.ordering,
- versions: image.image.versions.to_h { |k, v| [k.to_s, v.url] }
- }
- end,
- initiative_header_bg: {
- versions: initiative.header_bg.versions.to_h { |k, v| [k.to_s, v.url] }
- },
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }]
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_resubmitted_for_review.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_resubmitted_for_review.rb
deleted file mode 100644
index eb3831d95d36..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_resubmitted_for_review.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InitiativeResubmittedForReview < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include Trackable
- include LifecycleStageRestrictable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def mailer_class
- InitiativeResubmittedForReviewMailer
- end
-
- def activity_triggers
- { 'Notifications::InitiativeResubmittedForReview' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.admins_and_managers'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.admins_assigned_to_a_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.initiative_resubmitted_for_review'
- end
-
- def generate_commands(recipient:, activity:)
- initiative = activity.item.post
- name_service = UserDisplayNameService.new(AppConfiguration.instance, recipient)
-
- [{
- event_payload: {
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_author_name: name_service.display_name!(initiative.author)
- }
- }]
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you.rb
deleted file mode 100644
index ba84d3b3fc62..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InternalCommentOnInitiativeAssignedToYou < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include LifecycleStageRestrictable
- include Trackable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def activity_triggers
- { 'Notifications::InternalComments::InternalCommentOnInitiativeAssignedToYou' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.consentable_roles
- %w[admin]
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.admins'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.admins'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.internal_comments'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.internal_comment_is_posted_on_initiative_assigned_to_user'
- end
-
- def mailer_class
- InternalCommentOnInitiativeAssignedToYouMailer
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- InternalCommentCampaignCommandsBuilder.new.build_commands(recipient, activity)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on.rb
deleted file mode 100644
index 311c18a46a17..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include LifecycleStageRestrictable
- include Trackable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def activity_triggers
- { 'Notifications::InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.consentable_roles
- %w[admin]
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.admins'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.admins'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.internal_comments'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.internal_comment_is_posted_on_initiative_user_has_commented_internally_on'
- end
-
- def mailer_class
- InternalCommentOnInitiativeYouCommentedInternallyOnMailer
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- InternalCommentCampaignCommandsBuilder.new.build_commands(recipient, activity)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative.rb
deleted file mode 100644
index c52df10f5ffb..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InternalCommentOnUnassignedInitiative < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include LifecycleStageRestrictable
- include Trackable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def activity_triggers
- { 'Notifications::InternalComments::InternalCommentOnUnassignedInitiative' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.consentable_roles
- %w[admin]
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.admins'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.admins'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.internal_comments'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.internal_comment_is_posted_on_unassigned_initiative'
- end
-
- def mailer_class
- InternalCommentOnUnassignedInitiativeMailer
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- InternalCommentCampaignCommandsBuilder.new.build_commands(recipient, activity)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/invitation_to_cosponsor_initiative.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/invitation_to_cosponsor_initiative.rb
deleted file mode 100644
index c3a94bbb91d7..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/invitation_to_cosponsor_initiative.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::InvitationToCosponsorInitiative < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include Trackable
- include LifecycleStageRestrictable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def mailer_class
- InvitationToCosponsorInitiativeMailer
- end
-
- def activity_triggers
- { 'Notifications::InvitationToCosponsorInitiative' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.registered_users'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.user_who_is_invited_to_cosponsor_a_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.user_is_invited_to_cosponsor_a_proposal'
- end
-
- def generate_commands(recipient:, activity:)
- initiative = activity.item.post
- name_service = UserDisplayNameService.new(AppConfiguration.instance, recipient)
-
- [{
- event_payload: {
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_author_name: name_service.display_name!(initiative.author),
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- post_image_medium_url: post_image_medium_url(initiative)
- }
- }]
- end
-
- private
-
- def post_image_medium_url(initiative)
- image = initiative&.initiative_images&.first
- image.image.versions[:medium].url if image&.image&.versions
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/new_initiative_for_admin.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/new_initiative_for_admin.rb
deleted file mode 100644
index 9b539b06d32e..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/new_initiative_for_admin.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::NewInitiativeForAdmin < Campaign
- include Consentable
- include ActivityTriggerable
- include RecipientConfigurable
- include Disableable
- include LifecycleStageRestrictable
- include Trackable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_recipient
-
- def self.consentable_roles
- ['admin']
- end
-
- def mailer_class
- NewInitiativeForAdminMailer
- end
-
- def activity_triggers
- { 'Initiative' => { 'published' => true } }
- end
-
- def filter_recipient(users_scope, activity:, time: nil)
- initiative = activity.item
- initiator = initiative.author
-
- recipient_ids = if initiator && !initiator.admin?
- User.admin.ids.reject do |recipient_id|
- recipient_id == initiative&.assignee_id
- end
- else
- []
- end
-
- users_scope.where(id: recipient_ids)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.admins_and_managers'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.admins'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.new_proposal_is_posted'
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- initiative = activity.item
- [{
- event_payload: {
- post_published_at: initiative.published_at.iso8601,
- post_title_multiloc: initiative.title_multiloc,
- post_author_name: initiative.author_name,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }]
- end
-
- protected
-
- def set_enabled
- self.enabled = false if enabled.nil?
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow.rb
deleted file mode 100644
index eeb2878f80ea..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::OfficialFeedbackOnInitiativeYouFollow < Campaign
- include Consentable
- include Disableable
- include ActivityTriggerable
- include RecipientConfigurable
- include Trackable
- include LifecycleStageRestrictable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def mailer_class
- OfficialFeedbackOnInitiativeYouFollowMailer
- end
-
- def activity_triggers
- { 'Notifications::OfficialFeedbackOnInitiativeYouFollow' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient.id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.registered_users'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.users_who_follow_the_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.proposal_is_updated'
- end
-
- def generate_commands(recipient:, activity:, time: nil)
- notification = activity.item
- name_service = UserDisplayNameService.new(AppConfiguration.instance, recipient)
- [{
- event_payload: {
- official_feedback_author_multiloc: notification.official_feedback.author_multiloc,
- official_feedback_body_multiloc: notification.official_feedback.body_multiloc,
- official_feedback_url: Frontend::UrlService.new.model_to_url(notification.official_feedback, locale: Locale.new(recipient.locale)),
- post_published_at: notification.post.published_at.iso8601,
- post_title_multiloc: notification.post.title_multiloc,
- post_author_name: name_service.display_name!(notification.post.author),
- unfollow_url: Frontend::UrlService.new.unfollow_url(Follower.new(followable: notification.post, user: recipient))
- }
- }]
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/status_change_on_initiative_you_follow.rb b/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/status_change_on_initiative_you_follow.rb
deleted file mode 100644
index 514573af0cad..000000000000
--- a/back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/status_change_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: email_campaigns_campaigns
-#
-# id :uuid not null, primary key
-# type :string not null
-# author_id :uuid
-# enabled :boolean
-# sender :string
-# reply_to :string
-# schedule :jsonb
-# subject_multiloc :jsonb
-# body_multiloc :jsonb
-# created_at :datetime not null
-# updated_at :datetime not null
-# deliveries_count :integer default(0), not null
-# context_id :uuid
-#
-# Indexes
-#
-# index_email_campaigns_campaigns_on_author_id (author_id)
-# index_email_campaigns_campaigns_on_context_id (context_id)
-# index_email_campaigns_campaigns_on_type (type)
-#
-# Foreign Keys
-#
-# fk_rails_... (author_id => users.id)
-#
-module EmailCampaigns
- class Campaigns::StatusChangeOnInitiativeYouFollow < Campaign
- include Consentable
- include Disableable
- include ActivityTriggerable
- include RecipientConfigurable
- include Trackable
- include LifecycleStageRestrictable
- allow_lifecycle_stages only: %w[trial active]
-
- recipient_filter :filter_notification_recipient
-
- def mailer_class
- StatusChangeOnInitiativeYouFollowMailer
- end
-
- def activity_triggers
- { 'Notifications::StatusChangeOnInitiativeYouFollow' => { 'created' => true } }
- end
-
- def filter_notification_recipient(users_scope, activity:, time: nil)
- users_scope.where(id: activity.item.recipient_id)
- end
-
- def self.recipient_role_multiloc_key
- 'email_campaigns.admin_labels.recipient_role.registered_users'
- end
-
- def self.recipient_segment_multiloc_key
- 'email_campaigns.admin_labels.recipient_segment.users_who_follow_the_proposal'
- end
-
- def self.content_type_multiloc_key
- 'email_campaigns.admin_labels.content_type.proposals'
- end
-
- def self.trigger_multiloc_key
- 'email_campaigns.admin_labels.trigger.proposal_status_changes'
- end
-
- def generate_commands(recipient:, activity:)
- initiative = activity.item.post
- status = initiative.initiative_status
- [{
- event_payload: {
- post_id: initiative.id,
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- post_images: initiative.initiative_images.map do |image|
- {
- ordering: image.ordering,
- versions: image.image.versions.to_h { |k, v| [k.to_s, v.url] }
- }
- end,
- initiative_status_id: status.id,
- initiative_status_title_multiloc: status.title_multiloc,
- initiative_status_code: status.code,
- initiative_status_color: status.color,
- unfollow_url: Frontend::UrlService.new.unfollow_url(Follower.new(followable: initiative, user: recipient))
- }
- }]
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index f1c056601489..17c44abd2342 100644
--- a/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
+++ b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
@@ -9,27 +9,17 @@ class DeliveryService
Campaigns::CommentDeletedByAdmin,
Campaigns::CommentMarkedAsSpam,
Campaigns::CommentOnIdeaYouFollow,
- Campaigns::CommentOnInitiativeYouFollow,
Campaigns::CommentOnYourComment,
- Campaigns::CosponsorOfYourInitiative,
Campaigns::CosponsorOfYourIdea,
Campaigns::EventRegistrationConfirmation,
Campaigns::IdeaMarkedAsSpam,
Campaigns::IdeaPublished,
- Campaigns::InitiativeAssignedToYou,
- Campaigns::InitiativeMarkedAsSpam,
- Campaigns::InitiativePublished,
- Campaigns::InitiativeResubmittedForReview,
Campaigns::InternalCommentOnIdeaAssignedToYou,
Campaigns::InternalCommentOnIdeaYouCommentedInternallyOn,
Campaigns::InternalCommentOnIdeaYouModerate,
- Campaigns::InternalCommentOnInitiativeAssignedToYou,
- Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn,
- Campaigns::InternalCommentOnUnassignedInitiative,
Campaigns::InternalCommentOnUnassignedUnmoderatedIdea,
Campaigns::InternalCommentOnYourInternalComment,
Campaigns::InvitationToCosponsorIdea,
- Campaigns::InvitationToCosponsorInitiative,
Campaigns::InviteReceived,
Campaigns::InviteReminder,
Campaigns::Manual,
@@ -40,9 +30,7 @@ class DeliveryService
Campaigns::NativeSurveyNotSubmitted,
Campaigns::NewCommentForAdmin,
Campaigns::NewIdeaForAdmin,
- Campaigns::NewInitiativeForAdmin,
Campaigns::OfficialFeedbackOnIdeaYouFollow,
- Campaigns::OfficialFeedbackOnInitiativeYouFollow,
Campaigns::ProjectFolderModerationRightsReceived,
Campaigns::ProjectModerationRightsReceived,
Campaigns::ProjectPhaseStarted,
@@ -51,7 +39,6 @@ class DeliveryService
Campaigns::ProjectReviewRequest,
Campaigns::ProjectReviewStateChange,
Campaigns::StatusChangeOnIdeaYouFollow,
- Campaigns::StatusChangeOnInitiativeYouFollow,
Campaigns::ThresholdReachedForAdmin,
Campaigns::UserDigest,
Campaigns::VotingBasketNotSubmitted,
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/comment_on_initiative_you_follow_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/comment_on_initiative_you_follow_mailer/campaign_mail.mjml
deleted file mode 100644
index ee1b0af013e5..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/comment_on_initiative_you_follow_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- <%= format_message('author_wrote', component: 'general', values: {
- authorName: "
- #{event.initiating_user_first_name&.upcase}
- "
- }).html_safe %>
-
- <%= localize_for_recipient_and_truncate(event.comment_body_multiloc, 140) %>
-
-
-
-
-
-
-<%= render partial: 'application/cta_button', locals: { href: event.comment_url, message: format_message('cta_reply_to', values: {commentAuthor: event.initiating_user_first_name&.capitalize}) } %>
-
-<% if AppConfiguration.instance.feature_activated?('follow') %>
- <%= render 'email_campaigns/follow/card' %>
-<% end %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/cosponsor_of_your_initiative_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/cosponsor_of_your_initiative_mailer/campaign_mail.mjml
deleted file mode 100644
index 297e57cace57..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/cosponsor_of_your_initiative_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,2 +0,0 @@
-<%= render 'email_campaigns/posts/post_with_image', post_image_url: event&.post_image_medium_url, post_title_multiloc: event.post_title_multiloc, post_body_multiloc: event.post_body_multiloc %>
-<%= render partial: 'application/cta_button', locals: { href: event.post_url, message: format_message('cta_reply_to', values: { authorName: event.post_author_name }) } %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_assigned_to_you_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_assigned_to_you_mailer/campaign_mail.mjml
deleted file mode 100644
index b7eadf7f4740..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_assigned_to_you_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
- <%= localize_for_recipient(event.post_title_multiloc) %>
-
- <%= format_message('by_author', component: 'general', values: { authorName: event.post_author_name }) %>
-
-
- <%= localize_for_recipient(event.post_body_multiloc).html_safe %>
-
-
-
-
-
-<%= render partial: 'application/cta_button', locals: { href: url_service.admin_initiatives_url, message: format_message('cta_reply_to', values: { authorName: event.post_author_name }) } %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_marked_as_spam_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_marked_as_spam_mailer/campaign_mail.mjml
deleted file mode 100644
index c0b7d5b69873..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_marked_as_spam_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
- <%= localize_for_recipient(event.post_title_multiloc) %>
-
-
- <%= format_message('by_author', component: 'general', values: { authorName: event.post_author_name }) %>
-
-
-
-
-
-
-
-
-
- <%= format_message('reported_this_because', values: {
- reporterFirstName: "#{event.initiating_user_first_name}"
- }, escape_html: false) %>
-
-
-
- <% case event.spam_report_reason_code %>
- <% when 'other' %>
- <%= event.spam_report_other_reason %>
- <% when 'inappropriate' %>
- <%= format_message('report_inappropriate_offensive_content') %>
- <% when 'wrong_content' %>
- <%= format_message('report_not_an_initiative') %>
- <% end %>
-
-
-
-
-
-
-<%= render partial: 'application/cta_button', locals: { href: event.post_url, message: format_message('cta_review_initiative') } %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_published_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_published_mailer/campaign_mail.mjml
deleted file mode 100644
index b64cecf1ffb9..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_published_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-
- <%= format_message("message_get_votes") %>
-
-
-
-
-
-
-
- |
-
-
- <%= format_message('action_published_initiative') %>
-
- |
-
-
-
-
-
-
- |
-
- <%= format_message('action_share_fb', values: {
- fbLink: "Facebook"
- }, escape_html: false)
- %>
- |
-
-
- |
-
-
-
-
-
- |
-
- <%= format_message('action_share_twitter', values: {
- twitterLink: "Twitter"
- }, escape_html: false)
- %>
- |
-
-
- |
-
-
-
-
-
-
- |
-
- <%= format_message('action_send_email', values: {
- sendEmailLink: "#{format_message('send_email')}"
- }, escape_html: false)
- %>
- |
-
-
- |
-
-
-
-
-
-
- |
-
- <%= format_message('action_share_link', values: {
- link: "#{format_message('link')}"
- }, escape_html: false)
- %>
- |
-
-
- |
-
-
-
-
-
-
-
- <%= render partial: 'application/cta_button', locals: { href: event.post_url, message: format_message('cta_goto_proposal', component: 'general') } %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_resubmitted_for_review_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_resubmitted_for_review_mailer/campaign_mail.mjml
deleted file mode 100644
index 5eb306cae8c8..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/initiative_resubmitted_for_review_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
- <%= localize_for_recipient(event.post_title_multiloc) %>
-
- <%= format_message('by_author', values: { authorName: event.post_author_name }) %>
-
-
- <%= localize_for_recipient(event.post_body_multiloc).html_safe %>
-
-
-
-
-
-<%= render partial: 'application/cta_button', locals: { href: url_service.admin_initiatives_url, message: format_message('cta_reply_to', values: { authorName: event.post_author_name }) } %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer/campaign_mail.mjml
deleted file mode 100644
index 328c41c16b0a..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1 +0,0 @@
-<%= render 'email_campaigns/internal_comments/internal_comment_mail', event: event %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer/campaign_mail.mjml
deleted file mode 100644
index 328c41c16b0a..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1 +0,0 @@
-<%= render 'email_campaigns/internal_comments/internal_comment_mail', event: event %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_unassigned_initiative_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_unassigned_initiative_mailer/campaign_mail.mjml
deleted file mode 100644
index 328c41c16b0a..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_unassigned_initiative_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1 +0,0 @@
-<%= render 'email_campaigns/internal_comments/internal_comment_mail', event: event %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/invitation_to_cosponsor_initiative_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/invitation_to_cosponsor_initiative_mailer/campaign_mail.mjml
deleted file mode 100644
index f53f543d4270..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/invitation_to_cosponsor_initiative_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- <%= format_message('event_description_cosponsoring', escape_html: false) %>
-
-
-
-
-
-
-
- <%= format_message('event_description_before_action', escape_html: false) %>
-
-
-
-
-
-
-
- <%= format_message('event_description_action') %>
-
-
-
-
-<%= render 'email_campaigns/posts/post_with_image', post_image_url: event&.post_image_medium_url, post_title_multiloc: event.post_title_multiloc, post_body_multiloc: event.post_body_multiloc %>
-<%= render partial: 'application/cta_button', locals: { href: event.post_url, message: format_message('cta_reply_to', values: { authorName: event.post_author_name }) } %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/new_initiative_for_admin_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/new_initiative_for_admin_mailer/campaign_mail.mjml
deleted file mode 100644
index f228934cc515..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/new_initiative_for_admin_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
- <%= localize_for_recipient(event.post_title_multiloc) %>
-
-
- <%= format_message('by_author', component: 'general', values: { authorName: event.post_author_name }) %>
-
-
-
-
-
-
-<%= render partial: 'application/cta_button', locals: { href: event.post_url, message: format_message('cta_reply_to', values: { authorName: event.post_author_name }) } %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/official_feedback_on_initiative_you_follow_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/official_feedback_on_initiative_you_follow_mailer/campaign_mail.mjml
deleted file mode 100644
index 27b52c41206d..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/official_feedback_on_initiative_you_follow_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,7 +0,0 @@
-<%= render 'email_campaigns/official_feedbacks/card' %>
-
-<%= render partial: 'application/cta_button', locals: { href: event.official_feedback_url , message: format_message('cta_goto_proposal', component: 'general') } %>
-
-<% if AppConfiguration.instance.feature_activated?('follow') %>
- <%= render 'email_campaigns/follow/card' %>
-<% end %>
diff --git a/back/engines/free/email_campaigns/app/views/email_campaigns/status_change_on_initiative_you_follow_mailer/campaign_mail.mjml b/back/engines/free/email_campaigns/app/views/email_campaigns/status_change_on_initiative_you_follow_mailer/campaign_mail.mjml
deleted file mode 100644
index c7ef267bd366..000000000000
--- a/back/engines/free/email_campaigns/app/views/email_campaigns/status_change_on_initiative_you_follow_mailer/campaign_mail.mjml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- <%= format_message('status_change', values: {
- initiativeStatus: localize_for_recipient(event.initiative_status_title_multiloc)
- }) %>
-
-
-
-
-<%= render partial: 'application/cta_button', locals: { href: event.post_url , message: format_message('cta_goto_proposal', component: 'general') } %>
-
-<% if AppConfiguration.instance.feature_activated?('follow') %>
- <%= render 'email_campaigns/follow/card' %>
-<% end %>
diff --git a/back/engines/free/email_campaigns/config/locales/en.yml b/back/engines/free/email_campaigns/config/locales/en.yml
index 34594a924179..a39d0da8b62b 100644
--- a/back/engines/free/email_campaigns/config/locales/en.yml
+++ b/back/engines/free/email_campaigns/config/locales/en.yml
@@ -8,35 +8,23 @@ en:
"comment_marked_as_spam": Comment spam report
"comment_on_your_comment": A reply on my comment
"comment_on_idea_you_follow": A comment on an idea that you follow
- "comment_on_initiative_you_follow": A comment on a proposal that you follow
- "cosponsor_of_your_initiative": A user accepts my invitation to co-sponsor my proposal
"cosponsor_of_your_idea": A user accepts my invitation to co-sponsor my proposal
"event_registration_confirmation": Event registration confirmation
"idea_marked_as_spam": Idea spam report
"idea_published": Publication of my input
- "initiative_assigned_to_you": Assignment of a proposal to me
- "initiative_marked_as_spam": Proposal spam report
- "initiative_published": Publication of my proposal
- "invitation_to_cosponsor_initiative": Invitation to co-sponsor a proposal
"invitation_to_cosponsor_idea": Invitation to co-sponsor a proposal
- "initiative_resubmitted_for_review": Proposal resubmitted for review
"invite_received": Invitation
"invite_reminder": Invitation reminder
"internal_comment_on_idea_assigned_to_you": Internal comment on input assigned to me
"internal_comment_on_idea_you_commented_internally_on": Internal comment on input I commented internally on
"internal_comment_on_idea_you_moderate": Internal comment on input in project or folder I manage
- "internal_comment_on_initiative_assigned_to_you": Internal comment on proposal assigned to me
- "internal_comment_on_initiative_you_commented_internally_on": Internal comment on proposal I commented internally on
- "internal_comment_on_unassigned_initiative": Internal comment on unassigned proposal
"internal_comment_on_unassigned_unmoderated_idea": Internal comment on unassigned input in unmanaged project
"internal_comment_on_your_internal_comment": Internal comment on my internal comment
"mention_in_official_feedback": Mention in an update
"mention_in_internal_comment": Mention in an internal comment
"new_comment_for_admin": New comment in a project I moderate
"new_idea_for_admin": New input in a project I moderate
- "new_initiative_for_admin": New proposal
"official_feedback_on_idea_you_follow": Update on an input that you follow
- "official_feedback_on_initiative_you_follow": Update on a proposal that you follow
"password_reset": Password reset
"project_moderation_rights_received": Project moderation rights received
"project_folder_moderation_rights_received": Folder manager rights received
@@ -46,7 +34,6 @@ en:
"project_review_request": Project review request
"project_review_state_change": Project approved
"status_change_on_idea_you_follow": Status change of an input that you follow
- "status_change_on_initiative_you_follow": Status change of a proposal that you follow
"threshold_reached_for_admin": Proposal reached the voting threshold
"welcome": After registration
"admin_digest": Weekly overview for admins
@@ -73,7 +60,6 @@ en:
issue: 'Go to this issue'
option: 'Go to this option'
proposal: 'Go to this proposal'
- initiative: 'Go to this initiative'
petition: 'Go to this petition'
cta_goto_your:
idea: 'Go to your idea'
@@ -83,7 +69,6 @@ en:
issue: 'Go to your issue'
option: 'Go to your option'
proposal: 'Go to your proposal'
- initiative: 'Go to your initiative'
petition: 'Go to your petition'
cta_goto_proposal: 'Go to this proposal'
cta_goto_project: 'Go to this project'
@@ -130,7 +115,6 @@ en:
new_comments: 'New comments'
title_activity_past_week: 'Activity of the past week'
title_no_activity_past_week: 'There was no activity in the past week'
- title_initiatives_past_week: 'New proposals of the past week'
reached_threshold: 'Reached the threshold'
yesterday_by_author: 'Yesterday by %{author}'
today_by_author: 'Today by %{author}'
@@ -168,12 +152,6 @@ en:
main_header: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
subject: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
preheader: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
- cosponsor_of_your_initiative:
- cta_reply_to: 'View your proposal'
- event_description_initiative: 'Congratulations! %{cosponsorName} has accepted your invitation to co-sponsor your proposal.'
- main_header: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
- subject: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
- preheader_initiative: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
assignee_digest:
subject: 'Inputs requiring your feedback: %{numberIdeas}'
preheader: 'Assignee digest of %{organizationName}'
@@ -194,20 +172,6 @@ en:
preheader: 'Act upon this spam report'
reported_this_because: '%{reporterFirstName} reported this because:'
title_spam_report: '%{firstName} %{lastName} reported spam'
- initiative_marked_as_spam:
- cta_review_initiative: 'Review proposal'
- report_inappropriate_offensive_content: 'I find this content inappropriate or offensive.'
- report_not_an_initiative: 'This content is not a proposal and does not belong here.'
- subject: 'You have a spam report on the platform of %{organizationName}'
- preheader: 'Act upon this spam report'
- reported_this_because: '%{reporterFirstName} reported this because:'
- title_spam_report: '%{firstName} %{lastName} reported spam'
- initiative_assigned_to_you:
- cta_reply_to: 'Give feedback to %{authorName}'
- event_description_initiative: 'A proposal has been assigned to you. Give feedback by writing an official update or by changing its status.'
- main_header: '%{firstName}, you have a new assignment'
- subject: 'You have an assignment on the platform of %{organizationName}'
- preheader_initiative: 'The proposal of %{authorName} has been assigned to you'
invitation_to_cosponsor_idea:
cta_reply_to: 'Co-sponsor this proposal'
event_description: '%{authorName} has created a new proposal and would like you to co-sponsor it.'
@@ -217,22 +181,6 @@ en:
main_header: 'You have been invited to co-sponsor a proposal'
subject: 'You have been invited to co-sponsor a proposal'
preheader: 'You have been invited to co-sponsor the proposal of %{authorName}'
- invitation_to_cosponsor_initiative:
- cta_reply_to: 'Co-sponsor this proposal'
- event_description_initiative: '%{authorName} has created a new proposal and would like you to co-sponsor it.'
- event_description_cosponsoring: 'Co-sponsoring a proposal means that your name will be displayed with the names of other co-sponsors of the proposal.'
- event_description_before_action: 'To see the proposal and accept the invitation, you must be logged in to your account.'
- event_description_action: 'Click below to read the proposal.'
- main_header: 'You have been invited to co-sponsor a proposal'
- subject: 'You have been invited to co-sponsor a proposal'
- preheader_initiative: 'You have been invited to co-sponsor the proposal of %{authorName}'
- initiative_resubmitted_for_review:
- by_author: 'by %{authorName}'
- cta_reply_to: 'Give feedback to %{authorName}'
- event_description_initiative: 'A proposal has been resubmitted for review. Give feedback by writing an official update or by changing its status.'
- main_header: '%{firstName}, you have a proposal to review'
- subject: 'You have a proposal to review on the platform of %{organizationName}'
- preheader_initiative: 'The proposal of %{authorName} has been resubmitted for review'
invite_reminder:
cta_accept_invitation: 'Accept your invitation'
invitation_header: 'Your invitation is pending'
@@ -247,20 +195,6 @@ en:
invitation_expiry_message: 'This invitation expires in %{expiryDays} days.'
preheader: '%{organizationName} sent you an invite to join their participation platform.'
subject: 'You are invited to join the platform of %{organizationName}'
- initiative_published:
- action_add_image: '%{addImageLink} to increase visibility'
- action_published_initiative: 'Published proposal'
- action_send_email: 'Send your contacts an %{sendEmailLink}'
- action_share_fb: 'Let your friends know on %{fbLink}'
- action_share_link: 'Share it via any channel by copying the %{link}'
- action_share_twitter: 'Inform your followers on %{twitterLink}'
- link: link
- main_header: 'You posted a proposal! Let''s gather support for it.'
- message_next_steps: '%{userFirstName}, your proposal has successfully been published on the participation platform of %{organizationName}. You will be notified when people interact with your proposal. Find out what next steps you can take below.'
- message_get_votes: 'Reach the voting threshold:'
- preheader: 'Thank you for sharing your proposal %{initiativeTitle} for %{organizationName}. The next step is to get support for your proposal by sharing it across your network.'
- send_email: email
- subject: 'Your proposal was published on the platform of %{organizationName}'
mention_in_comment:
cta_reply_to: 'Reply to %{commentAuthor}'
event_description: '%{commentAuthorFull} has mentioned you in his comment on the idea ''%{post}‘. Click the link below to enter the conversation with %{commentAuthor}'
@@ -309,22 +243,9 @@ en:
issue: '%{authorName} commented on an issue you follow'
option: '%{authorName} commented on an option you follow'
proposal: '%{authorName} commented on a proposal you follow'
- initiative: '%{authorName} commented on an initiative you follow'
petition: '%{authorName} commented on a petition you follow'
subject: 'There''s a new comment on "%{input_title}"'
preheader: '%{authorName} left a comment on an idea for %{organizationName}'
- comment_on_initiative_you_follow:
- cta_reply_to: 'Reply to %{commentAuthor}'
- event_description: '%{authorNameFull} placed a reaction on the proposal ''%{initiativeTitle}''. Click the button below to continue the conversation with %{authorName}.'
- main_header: '%{commentAuthor} commented on an proposal you follow'
- subject: 'There''s a new comment on the proposal you follow'
- preheader: '%{authorName} left a comment on an proposal for %{organizationName}'
- new_initiative_for_admin:
- cta_reply_to: 'Give feedback to %{authorName}'
- event_description: '%{authorName} has published a new proposal on your platform. Discover it now, give some feedback or change its status!'
- main_header: '%{firstName}, a new proposal has been published on your platform'
- subject: 'Someone published a new proposal on the platform of %{organizationName}'
- preheader: '%{authorName} published a new proposal on your platform'
new_idea_for_admin:
main_header_publication: 'A new input has been published on your platform'
event_description_publication: '%{authorName} has submitted a new input on your platform. Discover it now, give some feedback or change its status!'
@@ -368,24 +289,6 @@ en:
subject: 'New internal comment on ''%{post}'''
main_header: 'New internal comment on ''%{post}'''
preheader: 'New internal comment on ''%{post}'''
- internal_comment_on_initiative_assigned_to_you:
- cta_reply_to: 'View comment by %{firstName}'
- event_description: '%{authorNameFull} commented internally on a proposal assigned to you.'
- subject: 'New internal comment on ''%{post}'''
- main_header: 'New internal comment on ''%{post}'''
- preheader: 'New internal comment on ''%{post}'''
- internal_comment_on_initiative_you_commented_internally_on:
- cta_reply_to: 'View comment by %{firstName}'
- event_description: '%{authorNameFull} commented internally on a proposal you commented internally on.'
- subject: 'New internal comment on ''%{post}'''
- main_header: 'New internal comment on ''%{post}'''
- preheader: 'New internal comment on ''%{post}'''
- internal_comment_on_unassigned_initiative:
- cta_reply_to: 'View comment by %{firstName}'
- event_description: '%{authorNameFull} commented internally on an unassigned proposal.'
- subject: 'New internal comment on ''%{post}'''
- main_header: 'New internal comment on ''%{post}'''
- preheader: 'New internal comment on ''%{post}'''
internal_comment_on_unassigned_unmoderated_idea:
cta_reply_to: 'View comment by %{firstName}'
event_description: '%{authorNameFull} commented internally on an unassigned input in an unmanaged project.'
@@ -397,11 +300,6 @@ en:
header_title: 'There''s an update on "%{input_title}"'
subject: 'Official feedback was posted on "%{input_title}"'
preheader: 'There''s an update on an input you follow'
- official_feedback_on_initiative_you_follow:
- header_message: '%{officialName} gave an update on the proposal ''%{initiativeTitle}''. Click the button below to enter the conversation with %{organizationName}.'
- header_title: 'There''s an update on a proposal you follow'
- subject: 'A proposal you follow has received an official update on the platform of %{organizationName}'
- preheader: 'There''s an update on a proposal you follow'
mention_in_official_feedback:
cta_reply_to: 'Reply to %{organizationName}'
event_description: '%{organizationName} mentioned you in their feedback on the idea ''%{post}‘. Click the link below to enter the conversation with %{organizationName}'
@@ -475,12 +373,6 @@ en:
header_title: 'An input you follow has a new status'
subject: 'The status of "%{input_title}" has changed'
preheader: 'An input you follow has a new status'
- status_change_on_initiative_you_follow:
- status_change: 'The new status of this proposal is ''%{initiativeStatus}'''
- header_message: 'The status of the proposal ''%{initiativeTitle}'' has been updated on the digital participation platform of %{organizationName}.'
- header_title: 'A proposal you follow has a new status'
- subject: 'The status of a proposal you follow has changed'
- preheader: 'A proposal you follow has a new status'
user_digest:
subject: "This week on the participation platform of %{organizationName}"
commented: "%{authorFirstName} commented:"
@@ -521,7 +413,6 @@ en:
issue: 'Your issue has been published'
option: 'Your option has been published'
proposal: 'Your proposal has been published'
- initiative: 'Your initiative has been published'
petition: 'Your petition has been published'
main_header: 'You posted "%{input_title}"'
header_message: 'Let''s make sure it gets read.'
@@ -545,7 +436,6 @@ en:
issue: 'Your issue is in "%{prescreening_status_title}"'
option: 'Your option is in "%{prescreening_status_title}"'
proposal: 'Your proposal is in "%{prescreening_status_title}"'
- initiative: 'Your initiative is in "%{prescreening_status_title}"'
petition: 'Your petition is in "%{prescreening_status_title}"'
message: '"%{input_title}" will become visible to others once it has been reviewed and approved.'
subject: '"%{input_title}" is almost published'
@@ -674,9 +564,6 @@ en:
internal_comment_is_posted_on_idea_in_project_or_folder_user_manages: 'Internal comment is posted on input in project or folder user manages'
internal_comment_is_posted_on_idea_user_has_commented_internally_on: 'Internal comment is posted on input user commented internally on'
internal_comment_is_posted_on_idea_user_moderates: 'Internal comment is posted on input user moderates'
- internal_comment_is_posted_on_initiative_assigned_to_user: 'Internal comment is posted on proposal assigned to user'
- internal_comment_is_posted_on_initiative_user_has_commented_internally_on: 'Internal comment is posted on proposal user commented internally on'
- internal_comment_is_posted_on_unassigned_initiative: 'Internal comment is posted on unassigned proposal'
internal_comment_is_posted_on_unassigned_unmoderated_idea: 'Internal comment is posted on unassigned input in unmanaged project'
project_review_request: 'Moderator requested a project review'
project_review_state_change: 'Reviewer approved the project'
diff --git a/back/engines/free/email_campaigns/spec/acceptance/campaigns_spec.rb b/back/engines/free/email_campaigns/spec/acceptance/campaigns_spec.rb
index 47de9df0ca43..77b3fd4f90e8 100644
--- a/back/engines/free/email_campaigns/spec/acceptance/campaigns_spec.rb
+++ b/back/engines/free/email_campaigns/spec/acceptance/campaigns_spec.rb
@@ -9,7 +9,7 @@
before do
@manual_campaigns = create_list(:manual_campaign, 4)
@manual_project_participants_campaign = create(:manual_project_participants_campaign)
- @automated_campaigns = create_list(:official_feedback_on_initiative_you_follow_campaign, 2)
+ @automated_campaigns = create_list(:official_feedback_on_idea_you_follow_campaign, 2)
end
context 'as an admin' do
diff --git a/back/engines/free/email_campaigns/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 2f45ee7afadf..9758bfd3e8e7 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -42,14 +42,6 @@
enabled { true }
end
- factory :comment_on_initiative_you_follow_campaign, class: EmailCampaigns::Campaigns::CommentOnInitiativeYouFollow do
- enabled { true }
- end
-
- factory :cosponsor_of_your_initiative_campaign, class: EmailCampaigns::Campaigns::CosponsorOfYourInitiative do
- enabled { true }
- end
-
factory :cosponsor_of_your_idea_campaign, class: EmailCampaigns::Campaigns::CosponsorOfYourIdea do
enabled { true }
end
@@ -74,22 +66,6 @@
enabled { true }
end
- factory :initiative_assigned_to_you_campaign, class: EmailCampaigns::Campaigns::InitiativeAssignedToYou do
- enabled { true }
- end
-
- factory :initiative_marked_as_spam_campaign, class: EmailCampaigns::Campaigns::InitiativeMarkedAsSpam do
- enabled { true }
- end
-
- factory :initiative_published_campaign, class: EmailCampaigns::Campaigns::InitiativePublished do
- enabled { true }
- end
-
- factory :initiative_resubmitted_for_review_campaign, class: EmailCampaigns::Campaigns::InitiativeResubmittedForReview do
- enabled { true }
- end
-
factory :internal_comment_on_idea_assigned_to_you_campaign, class: EmailCampaigns::Campaigns::InternalCommentOnIdeaAssignedToYou do
enabled { true }
end
@@ -102,18 +78,6 @@
enabled { true }
end
- factory :internal_comment_on_initiative_assigned_to_you_campaign, class: EmailCampaigns::Campaigns::InternalCommentOnInitiativeAssignedToYou do
- enabled { true }
- end
-
- factory :internal_comment_on_initiative_you_commented_internally_on_campaign, class: EmailCampaigns::Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn do
- enabled { true }
- end
-
- factory :internal_comment_on_unassigned_initiative_campaign, class: EmailCampaigns::Campaigns::InternalCommentOnUnassignedInitiative do
- enabled { true }
- end
-
factory :internal_comment_on_unassigned_unmoderated_idea_campaign, class: EmailCampaigns::Campaigns::InternalCommentOnUnassignedUnmoderatedIdea do
enabled { true }
end
@@ -126,10 +90,6 @@
enabled { true }
end
- factory :invitation_to_cosponsor_initiative_campaign, class: EmailCampaigns::Campaigns::InvitationToCosponsorInitiative do
- enabled { true }
- end
-
factory :mention_in_internal_comment_campaign, class: EmailCampaigns::Campaigns::MentionInInternalComment do
enabled { true }
end
@@ -146,18 +106,10 @@
enabled { true }
end
- factory :new_initiative_for_admin_campaign, class: EmailCampaigns::Campaigns::NewInitiativeForAdmin do
- enabled { true }
- end
-
factory :official_feedback_on_idea_you_follow_campaign, class: EmailCampaigns::Campaigns::OfficialFeedbackOnIdeaYouFollow do
enabled { true }
end
- factory :official_feedback_on_initiative_you_follow_campaign, class: EmailCampaigns::Campaigns::OfficialFeedbackOnInitiativeYouFollow do
- enabled { true }
- end
-
factory :project_folder_moderation_rights_received_campaign, class: EmailCampaigns::Campaigns::ProjectFolderModerationRightsReceived do
enabled { true }
end
@@ -190,10 +142,6 @@
enabled { true }
end
- factory :status_change_on_initiative_you_follow_campaign, class: EmailCampaigns::Campaigns::StatusChangeOnInitiativeYouFollow do
- enabled { true }
- end
-
factory :threshold_reached_for_admin_campaign, class: EmailCampaigns::Campaigns::ThresholdReachedForAdmin do
enabled { true }
end
diff --git a/back/engines/free/email_campaigns/spec/fixtures/locales/mailers.en.yml b/back/engines/free/email_campaigns/spec/fixtures/locales/mailers.en.yml
index 43f6ac448615..1bdc6797a535 100644
--- a/back/engines/free/email_campaigns/spec/fixtures/locales/mailers.en.yml
+++ b/back/engines/free/email_campaigns/spec/fixtures/locales/mailers.en.yml
@@ -8,31 +8,20 @@ en:
"comment_marked_as_spam": Comment spam report
"comment_on_your_comment": A reply on my comment
"comment_on_idea_you_follow": A comment on an idea that you follow
- "comment_on_initiative_you_follow": A comment on a proposal that you follow
- "cosponsor_of_your_initiative": A user accepts my invitation to co-sponor my proposal
"idea_marked_as_spam": Idea spam report
"idea_published": Publication of my input
- "initiative_assigned_to_you": Assignment of a proposal to me
- "initiative_marked_as_spam": Proposal spam report
- "initiative_published": Publication of my proposal
"internal_comment_on_idea_assigned_to_you": Internal comment on input assigned to me
"internal_comment_on_idea_you_commented_internally_on": Internal comment on input I commented internally on
"internal_comment_on_idea_you_moderate": Internal comment on input in project or folder I manage
- "internal_comment_on_initiative_assigned_to_you": Internal comment on proposal assigned to me
- "internal_comment_on_initiative_you_commented_internally_on": Internal comment on proposal I commented internally on
- "internal_comment_on_unassigned_initiative": Internal comment on unassigned proposal
"internal_comment_on_unassigned_unmoderated_idea": Internal comment on unassigned input in unmanaged project
"internal_comment_on_your_internal_comment": Internal comment on my internal comment
"invite_received": Invitation
"invite_reminder": Invitation reminder
- "invitation_to_cosponsor_initiative": Invitation to co-sponsor a proposal
"mention_in_internal_comment": Mention in an internal comment
"mention_in_official_feedback": Mention in an update
"new_comment_for_admin": New comment in a project I moderate
"new_idea_for_admin": New input in a project I moderate
- "new_initiative_for_admin": New proposal
"official_feedback_on_idea_you_follow": Update on an input that you follow
- "official_feedback_on_initiative_you_follow": Update on a proposal that you follow
"password_reset": Password reset
"project_moderation_rights_received": Project moderation rights received
"project_folder_moderation_rights_received": Project folder moderation rights received
@@ -40,7 +29,6 @@ en:
"project_phase_upcoming": Upcoming new project phase
"project_published": Project published
"status_change_on_idea_you_follow": Status change of an input that you follow
- "status_change_on_initiative_you_follow": Status change of a proposal that you follow
"threshold_reached_for_admin": Proposal reached the voting threshold
"welcome": After registration
"admin_digest": Weekly overview for admins
@@ -99,8 +87,6 @@ en:
new_comments: 'New comments'
title_activity_past_week: 'Activity of the past week'
title_no_activity_past_week: 'There was no activity in the past week'
- title_initiatives_past_week: 'New proposals of the past week'
- title_successful_initiatives_past_week: 'Proposals that reached the threshold in the past week'
yesterday_by_author: 'Yesterday by %{author}'
today_by_author: 'Today by %{author}'
x_days_ago_by_author: '%{x} days ago by %{author}'
@@ -131,12 +117,6 @@ en:
today: Today
wrong_content: 'The comment is not relevant.'
yesterday: Yesterday
- cosponsor_of_your_initiative:
- cta_reply_to: 'View your proposal'
- event_description_initiative: 'Congratulations! %{cosponsorName} has accepted your invitation to co-sponsor your proposal.'
- main_header: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
- subject: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
- preheader_initiative: '%{cosponsorName} has accepted your invitation to co-sponsor your proposal'
assignee_digest:
subject: 'Ideas requiring your feedback: %{numberIdeas}'
preheader: 'Assignee digest of %{organizationName}'
@@ -149,9 +129,6 @@ en:
today_by_author: 'Today by %{author}'
x_days_ago_by_author: '%{x} days ago by %{author}'
idea_section: Ideas
- initiative_section: Proposals
- title_initiatives_past_week: 'New proposals assigned to you'
- title_successful_initiatives_past_week: 'Proposals assigned to you that reached the threshold'
idea_marked_as_spam:
cta_review_idea: 'Review idea'
report_inappropriate_offensive_content: 'I find this content inappropriate or offensive.'
@@ -160,20 +137,6 @@ en:
preheader: 'Act upon this spam report'
reported_this_because: '%{reporterFirstName} reported this because:'
title_spam_report: '%{firstName} %{lastName} reported spam'
- initiative_marked_as_spam:
- cta_review_initiative: 'Review proposal'
- report_inappropriate_offensive_content: 'I find this content inappropriate or offensive.'
- report_not_an_initiative: 'This content is not a proposal and does not belong here.'
- subject: 'You have a spam report on the platform of %{organizationName}'
- preheader: 'Act upon this spam report'
- reported_this_because: '%{reporterFirstName} reported this because:'
- title_spam_report: '%{firstName} %{lastName} reported spam'
- initiative_assigned_to_you:
- cta_reply_to: 'Give feedback to %{authorName}'
- event_description_initiative: 'An proposal has been assigned to you. Give feedback by writing an official update or by changing its status.'
- main_header: '%{firstName}, you have a new assignment'
- subject: 'You have an assignment on the platform of %{organizationName}'
- preheader_initiative: 'The proposal of %{authorName} has been assigned to you'
invite_reminder:
cta_accept_invitation: 'Accept your invitation'
invitation_header: 'Your invitation is pending'
@@ -197,29 +160,6 @@ en:
main_header: 'You have been invited to co-sponsor a proposal'
subject: 'You have been invited to co-sponsor a proposal'
preheader: 'You have been invited to co-sponsor the proposal of %{authorName}'
- invitation_to_cosponsor_initative:
- cta_reply_to: 'Co-sponsor this proposal'
- event_description_initiative: '%{authorName} has created a new proposal and would like you to co-sponsor it.'
- event_description_cosponsoring: 'Co-sponsoring a proposal means that your name will be displayed with the names of other co-sponsors of the proposal'
- event_description_before_action: 'To see the proposal and accept the invitation, you must be logged in to your account.'
- event_description_action: 'Click below to read the proposal'
- main_header: 'You have been invited to co-sponsor a proposal'
- subject: 'You have been invited to co-sponsor a proposal'
- preheader_initiative: 'You have been invited to co-sponsor the proposal of %{authorName}'
- initiative_published:
- action_add_image: '%{addImageLink} to increase visibility'
- action_published_initiative: 'Published proposal'
- action_send_email: 'Send your contacts an %{sendEmailLink}'
- action_share_fb: 'Let your friends know on %{fbLink}'
- action_share_link: 'Share it via any channel by copying the %{link}'
- action_share_twitter: 'Inform your followers on %{twitterLink}'
- link: link
- main_header: 'You posted a proposal! Let''s gather support for it.'
- message_next_steps: '%{userFirstName}, your proposal has successfully been published on the participation platform of %{organizationName}. You will be notified when people interact with your proposal. Find out what next steps you can take below.'
- message_get_votes: 'Reach the voting threshold:'
- preheader: 'Thank you for sharing your proposal %{initiativeTitle} for %{organizationName}. The next step is to get support for your proposal by sharing it across your network.'
- send_email: email
- subject: 'Your proposal was published on the platform of %{organizationName}'
new_comment_on_commented_idea:
cta_reply_to: 'Reply to %{commentAuthor}'
event_description: '%{commentAuthorFull} also wrote a comment on the idea ''%{ideaTitle}'' on the participation platform of %{organizationName}. Click the button below to start the conversation with %{commentAuthor}.'
@@ -252,13 +192,6 @@ en:
yesterday_by_author: 'Yesterday by %{author}'
today_by_author: 'Today by %{author}'
x_days_ago_by_author: '%{x} days ago by %{author}'
- new_comment_on_commented_initiative:
- commented: '%{commentAuthor} wrote:'
- cta_reply_to: 'Reply to %{commentAuthor}'
- event_description: '%{commentAuthorFull} also wrote a comment on the proposal ''%{initiativeTitle}'' on the participation platform of %{organizationName}. Click the button below to start the conversation with %{commentAuthor}.'
- main_header: '%{commentAuthor} wrote a comment on the same proposal'
- subject: 'There''s another comment on the proposal you commented on'
- preheader: '%{commentAuthor} also left a comment on an proposal for %{organizationName}'
new_comment_for_admin:
commented: '%{authorFirstName} commented:'
cta_reply_to: 'View %{commentAuthor}''s comment'
@@ -275,18 +208,6 @@ en:
main_header: '%{authorName} commented on an idea you follow'
subject: 'There''s a new comment on an idea you follow'
preheader: '%{authorName} left a comment on an idea for %{organizationName}'
- comment_on_initiative_you_follow:
- cta_reply_to: 'Reply to %{commentAuthor}'
- event_description: '%{authorNameFull} placed a reaction on the initiative ''%{initiativeTitle}''. Click the button below to continue the conversation with %{authorName}.'
- main_header: '%{commentAuthor} commented on an initiative you follow'
- subject: 'There''s a new comment on the proposal you follow'
- preheader: '%{authorName} left a comment on an initiative for %{organizationName}'
- new_initiative_for_admin:
- cta_reply_to: 'Give feedback to %{authorName}'
- event_description: '%{authorName} has published a new proposal on your platform. Discover it now, give some feedback or change its status!'
- main_header: '%{firstName}, a new proposal has been published on your platform'
- subject: 'Someone published a new proposal on the platform of %{organizationName}'
- preheader: '%{authorName} published a new proposal on your platform'
new_idea_for_admin:
new_idea_for_admin:
main_header_publication: '%{firstName}, a new input has been published on your platform'
@@ -331,24 +252,6 @@ en:
subject: '''%{post}'' has a new internal comment'
main_header: '''%{post}'' has a new internal comment'
preheader: '''%{post}'' has a new internal comment'
- internal_comment_on_initiative_assigned_to_you:
- cta_reply_to: 'View comment by %{firstName}'
- event_description: '%{authorNameFull} commented internally on a proposal assigned to you.'
- subject: '''%{post}'' has a new internal comment'
- main_header: '''%{post}'' has a new internal comment'
- preheader: '''%{post}'' has a new internal comment'
- internal_comment_on_initiative_you_commented_internally_on:
- cta_reply_to: 'View comment by %{firstName}'
- event_description: '%{authorNameFull} commented internally on a proposal you commented internally on.'
- subject: '''%{post}'' has a new internal comment'
- main_header: '''%{post}'' has a new internal comment'
- preheader: '''%{post}'' has a new internal comment'
- internal_comment_on_unassigned_initiative:
- cta_reply_to: 'View comment by %{firstName}'
- event_description: '%{authorNameFull} commented internally on an unassigned proposal.'
- subject: '''%{post}'' has a new internal comment'
- main_header: '''%{post}'' has a new internal comment'
- preheader: '''%{post}'' has a new internal comment'
internal_comment_on_unassigned_unmoderated_idea:
cta_reply_to: 'View comment by %{firstName}'
event_description: '%{authorNameFull} commented internally on an unassigned input in an unmanaged project.'
@@ -360,11 +263,6 @@ en:
header_title: 'There''s an update on an input you follow'
subject: 'An input you follow has received an official update on the platform of %{organizationName}'
preheader: 'There''s an update on an input you follow'
- official_feedback_on_initiative_you_follow:
- header_message: '%{officialName} gave an update on the proposal ''%{initiativeTitle}''. Click the button below to enter the conversation with %{organizationName}.'
- header_title: 'There''s an update on a proposal you follow'
- subject: 'A proposal you follow has received an official update on the platform of %{organizationName}'
- preheader: 'There''s an update on a proposal you follow'
mention_in_official_feedback:
cta_reply_to: 'Reply to %{organizationName}'
event_description: '%{organizationName} mentioned you in their feedback on the idea ''%{post}‘. Click the link below to enter the conversation with %{organizationName}'
@@ -428,12 +326,6 @@ en:
header_title: 'An input you follow has a new status'
subject: 'The status of "%{input_title}" has changed'
preheader: 'An input you follow has a new status'
- status_change_on_initiative_you_follow:
- status_change: 'The new status of this proposal is ''%{initiativeStatus}'''
- header_message: 'The status of the proposal ''%{initiativeTitle}'' has been updated on the digital participation platform of %{organizationName}.'
- header_title: 'A proposal you follow has a new status'
- subject: 'The status of a proposal you follow has changed'
- preheader: 'A proposal you follow has a new status'
user_digest:
subject: "Your activity on the participation platform of %{organizationName}"
commented: "%{authorFirstName} commented:"
diff --git a/back/engines/free/email_campaigns/spec/mailers/comment_on_initiative_you_follow_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/comment_on_initiative_you_follow_mailer_spec.rb
deleted file mode 100644
index 2042e403a333..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/comment_on_initiative_you_follow_mailer_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::CommentOnInitiativeYouFollowMailer do
- describe 'CommentOnInitiativeYouFollow' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::CommentOnInitiativeYouFollow.create! }
- let_it_be(:initiative) { create(:initiative) }
- let_it_be(:initiator) { create(:user, first_name: 'Dries') }
- let_it_be(:comment) { create(:comment, post: initiative, body_multiloc: { 'en' => 'I agree' }, author: initiator) }
- let_it_be(:notification) { create(:comment_on_initiative_you_follow, recipient: recipient, post: initiative, comment: comment) }
- let_it_be(:command) do
- activity = create(:activity, item: notification, action: 'created')
- create(:comment_on_initiative_you_follow_campaign).generate_commands(
- activity: activity,
- recipient: recipient
- ).first.merge({ recipient: recipient })
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to be_present
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns organisation name' do
- expect(mail.body.encoded).to match(AppConfiguration.instance.settings('core', 'organization_name')['en'])
- end
-
- it 'includes the comment author name' do
- expect(mail.body.encoded).to include('Dries')
- end
-
- it 'includes the comment body' do
- expect(mail.body.encoded).to include('I agree')
- end
-
- it 'includes the unfollow url' do
- expect(mail.body.encoded).to match(Frontend::UrlService.new.unfollow_url(Follower.new(followable: initiative, user: recipient)))
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/cosponsor_of_your_initiative_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/cosponsor_of_your_initiative_mailer_spec.rb
deleted file mode 100644
index 1ec16b426a74..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/cosponsor_of_your_initiative_mailer_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: move-old-proposals-test
-RSpec.describe EmailCampaigns::CosponsorOfYourInitiativeMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:author) { create(:user) }
- let_it_be(:cosponsor) { create(:user) }
- let_it_be(:initiative) { create(:initiative, author: author) }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::CosponsorOfYourInitiative.create! }
- let_it_be(:cosponsor_name) { UserDisplayNameService.new(AppConfiguration.instance, cosponsor).display_name!(cosponsor) }
- let_it_be(:command) do
- item = Notifications::CosponsorOfYourInitiative.new(post: initiative, initiating_user: cosponsor)
- activity = Activity.new(item: item, user: author)
- commands = EmailCampaigns::Campaigns::CosponsorOfYourInitiative.new.generate_commands(recipient: recipient, activity: activity)
- commands[0].merge({ recipient: recipient })
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to match('has accepted your invitation to co-sponsor your proposal')
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns initiative cosponsor name' do
- expect(mail.body.encoded).to match(cosponsor_name)
- end
-
- it 'assigns cta url' do
- post_url = Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale))
- expect(mail.body.encoded).to match(post_url)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/footer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/footer_spec.rb
index febaf59c6904..888ca058e9b7 100644
--- a/back/engines/free/email_campaigns/spec/mailers/footer_spec.rb
+++ b/back/engines/free/email_campaigns/spec/mailers/footer_spec.rb
@@ -10,15 +10,15 @@
let(:locale) { 'en' }
let(:recipient) { create(:user, locale: locale) }
- let(:campaign) { EmailCampaigns::Campaigns::CommentOnInitiativeYouFollow.create! }
+ let(:campaign) { EmailCampaigns::Campaigns::CommentOnIdeaYouFollow.create! }
let(:command) do
- create(:comment_on_initiative_you_follow_campaign).generate_commands(
- activity: create(:activity, item: create(:comment_on_initiative_you_follow), action: 'created'),
+ create(:comment_on_idea_you_follow_campaign).generate_commands(
+ activity: create(:activity, item: create(:comment_on_idea_you_follow), action: 'created'),
recipient: recipient
).first.merge({ recipient: recipient })
end
- let(:mail) { EmailCampaigns::CommentOnInitiativeYouFollowMailer.with(command: command, campaign: campaign).campaign_mail.deliver_now }
+ let(:mail) { EmailCampaigns::CommentOnIdeaYouFollowMailer.with(command: command, campaign: campaign).campaign_mail.deliver_now }
it 'includes Go Vocal logo' do
expect(mail.body.encoded).to have_tag('a', with: { href: 'https://govocal.com/' }) do
diff --git a/back/engines/free/email_campaigns/spec/mailers/initiative_assigned_to_you_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/initiative_assigned_to_you_mailer_spec.rb
deleted file mode 100644
index cc93cf523fed..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/initiative_assigned_to_you_mailer_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::InitiativeAssignedToYouMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InitiativeAssignedToYou.create! }
- let_it_be(:assigned_at) { Time.zone.now }
- let_it_be(:initiative) { create(:initiative, author: recipient, assignee: create(:admin), assigned_at: assigned_at) }
- let_it_be(:author_name) { UserDisplayNameService.new(AppConfiguration.instance, recipient).display_name!(initiative.author) }
- let_it_be(:command) do
- {
- recipient: recipient,
- event_payload: {
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_author_name: author_name,
- post_published_at: initiative.published_at&.iso8601,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- post_assigned_at: initiative.assigned_at&.iso8601 || Time.now.iso8601,
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('You have an assignment on the platform of')
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns initiative author name' do
- expect(mail.body.encoded).to match(author_name)
- end
-
- it 'assigns go to initiative CTA' do
- admin_initiatives_url = Frontend::UrlService.new.admin_initiatives_url
- expect(mail.body.encoded).to match(admin_initiatives_url)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/initiative_marked_as_spam_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/initiative_marked_as_spam_mailer_spec.rb
deleted file mode 100644
index 7106b6e2d348..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/initiative_marked_as_spam_mailer_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::InitiativeMarkedAsSpamMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InitiativeMarkedAsSpam.create! }
- let_it_be(:initiating_user) { create(:user) }
- let_it_be(:initiative) { create(:initiative, author: recipient) }
- let_it_be(:command) do
- {
- recipient: recipient,
- event_payload: {
- initiating_user_first_name: initiating_user&.first_name,
- initiating_user_last_name: initiating_user&.last_name,
- post_created_at: initiative.created_at.iso8601,
- post_title_multiloc: initiative.title_multiloc,
- post_author_name: initiative.author_name,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601,
- spam_report_reason_code: 'other',
- spam_report_other_reason: 'This post is an intrusion to my privacy'
- }
- }
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('You have a spam report on the platform of')
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns reporter\'s name' do
- expect(mail.body.encoded).to match(initiating_user.first_name)
- end
-
- it 'assigns the reason' do
- expect(mail.body.encoded).to match('This post is an intrusion to my privacy')
- end
-
- it 'assigns go to initiative CTA' do
- initiative_url = Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale))
- expect(mail.body.encoded).to match(initiative_url)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/initiative_published_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/initiative_published_mailer_spec.rb
deleted file mode 100644
index 13b017a19bbd..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/initiative_published_mailer_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::InitiativePublishedMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InitiativePublished.create! }
- let_it_be(:initiative) { create(:initiative, author: recipient) }
- let_it_be(:command) do
- {
- recipient: recipient,
- event_payload: {
- post_id: initiative.id,
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- post_images: initiative.initiative_images.map do |image|
- {
- ordering: image.ordering,
- versions: image.image.versions.to_h { |k, v| [k.to_s, v.url] }
- }
- end,
- initiative_header_bg: {
- versions: initiative.header_bg.versions.to_h { |k, v| [k.to_s, v.url] }
- },
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('Your proposal was published on the platform of')
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns organisation name' do
- expect(mail.body.encoded).to match(AppConfiguration.instance.settings('core', 'organization_name', 'en'))
- end
-
- it 'assigns go to initiative CTA' do
- initiative_url = Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale))
- expect(mail.body.encoded).to match(initiative_url)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/initiative_resubmitted_for_review_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/initiative_resubmitted_for_review_mailer_spec.rb
deleted file mode 100644
index c6f4f7f78a5e..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/initiative_resubmitted_for_review_mailer_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: move-old-proposals-test
-RSpec.describe EmailCampaigns::InitiativeResubmittedForReviewMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:author) { create(:user) }
- let_it_be(:initiative) { create(:initiative, author: author) }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InitiativeResubmittedForReview.create! }
- let_it_be(:author_name) { UserDisplayNameService.new(AppConfiguration.instance, author).display_name!(initiative.author) }
- let_it_be(:command) do
- item = Notifications::InitiativeResubmittedForReview.new(post: initiative)
- activity = Activity.new(item: item)
- commands = EmailCampaigns::Campaigns::InitiativeResubmittedForReview.new.generate_commands(recipient: recipient, activity: activity)
- commands[0].merge({ recipient: recipient })
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('You have a proposal to review on the platform of')
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns initiative author name' do
- expect(mail.body.encoded).to match(author_name)
- end
-
- it 'assigns cta url' do
- admin_initiatives_url = Frontend::UrlService.new.admin_initiatives_url
- expect(mail.body.encoded).to match(admin_initiatives_url)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_assigned_to_you_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_assigned_to_you_mailer_spec.rb
deleted file mode 100644
index c1e9e20328bc..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_assigned_to_you_mailer_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::InternalCommentOnInitiativeAssignedToYouMailer do
- describe 'InternalCommentOnInitiativeAssignedToYouMailer' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:post_image) { create(:idea_image) }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InternalCommentOnInitiativeAssignedToYou.create! }
- let_it_be(:token) { ResetPasswordService.new.generate_reset_password_token recipient }
- let_it_be(:command) do
- {
- recipient: recipient,
- event_payload: {
- initiating_user_first_name: 'Matthias',
- initiating_user_last_name: 'Geeke',
- internal_comment_author_name: 'Matthias Geeke',
- internal_comment_body: 'I agree. I really think this proposal is amazing! Wowzers!',
- internal_comment_url: 'http://localhost:3000/en/internal_comments/fake-url-comment-does-not-exist',
- post_title_multiloc: { en: 'Permit paving of front gardens' },
- post_body_multiloc: {
- en: 'There are many advantages to paving your front garden. Less cars on the road and more space for pedestrians.'
- },
- post_type: 'Initiative',
- post_image_medium_url: post_image.image.versions[:medium].url
- }
- }
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- include_examples 'internal_comment_campaign_mailer_examples'
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_you_commented_internally_on_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_you_commented_internally_on_mailer_spec.rb
deleted file mode 100644
index 019256ecf14a..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_you_commented_internally_on_mailer_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::InternalCommentOnInitiativeYouCommentedInternallyOnMailer do
- describe 'InternalCommentOnInitiativeYouCommentedInternallyOnMailer' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:post_image) { create(:idea_image) }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn.create! }
- let_it_be(:token) { ResetPasswordService.new.generate_reset_password_token recipient }
- let_it_be(:command) do
- {
- recipient: recipient,
- event_payload: {
- initiating_user_first_name: 'Matthias',
- initiating_user_last_name: 'Geeke',
- internal_comment_author_name: 'Matthias Geeke',
- internal_comment_body: 'I also think this proposal is amazing! Wowzers!',
- internal_comment_url: 'http://localhost:3000/en/internal_comments/fake-url-comment-does-not-exist',
- post_title_multiloc: { en: 'Permit paving of front gardens' },
- post_body_multiloc: {
- en: 'There are many advantages to paving your front garden. Less cars on the road and more space for pedestrians.'
- },
- post_type: 'Initiative',
- post_image_medium_url: post_image.image.versions[:medium].url
- }
- }
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- include_examples 'internal_comment_campaign_mailer_examples'
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_unassigned_initiative_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_unassigned_initiative_mailer_spec.rb
deleted file mode 100644
index 06f9c022491d..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/internal_comment_on_unassigned_initiative_mailer_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::InternalCommentOnUnassignedInitiativeMailer do
- describe 'InternalCommentOnUnassignedInitiativeMailer' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:post_image) { create(:idea_image) }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InternalCommentOnUnassignedInitiative.create! }
- let_it_be(:token) { ResetPasswordService.new.generate_reset_password_token recipient }
- let_it_be(:command) do
- {
- recipient: recipient,
- event_payload: {
- initiating_user_first_name: 'Matthias',
- initiating_user_last_name: 'Geeke',
- internal_comment_author_name: 'Matthias Geeke',
- internal_comment_body: 'I think this proposal is amazing! Wowzers!',
- internal_comment_url: 'http://localhost:3000/en/internal_comments/fake-url-comment-does-not-exist',
- post_title_multiloc: { en: 'Permit paving of front gardens' },
- post_body_multiloc: {
- en: 'There are many advantages to paving your front garden. Less cars on the road and more space for pedestrians.'
- },
- post_type: 'Initiative',
- post_image_medium_url: post_image.image.versions[:medium].url
- }
- }
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- include_examples 'internal_comment_campaign_mailer_examples'
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/invitation_to_cosponsor_initiative_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/invitation_to_cosponsor_initiative_mailer_spec.rb
deleted file mode 100644
index c34322c99cf6..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/invitation_to_cosponsor_initiative_mailer_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: move-old-proposals-test
-RSpec.describe EmailCampaigns::InvitationToCosponsorInitiativeMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:author) { create(:user) }
- let_it_be(:initiative) { create(:initiative, author: author) }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::InvitationToCosponsorInitiative.create! }
- let_it_be(:author_name) { UserDisplayNameService.new(AppConfiguration.instance, author).display_name!(initiative.author) }
- let_it_be(:command) do
- item = Notifications::InvitationToCosponsorInitiative.new(post: initiative)
- activity = Activity.new(item: item)
- commands = EmailCampaigns::Campaigns::InvitationToCosponsorInitiative.new.generate_commands(recipient: recipient, activity: activity)
- commands[0].merge({ recipient: recipient })
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('You have been invited to co-sponsor a proposal')
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns initiative author name' do
- expect(mail.body.encoded).to match(author_name)
- end
-
- it 'assigns cta url' do
- post_url = Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale))
- expect(mail.body.encoded).to match(post_url)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/new_initiative_for_admin_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/new_initiative_for_admin_mailer_spec.rb
deleted file mode 100644
index 97c38455c4d6..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/new_initiative_for_admin_mailer_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::NewInitiativeForAdminMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::NewInitiativeForAdmin.create! }
- let_it_be(:initiative) { create(:initiative, author: recipient) }
- let_it_be(:command) do
- {
- recipient: recipient,
- event_payload: {
- post_published_at: initiative.published_at.iso8601,
- post_title_multiloc: initiative.title_multiloc,
- post_author_name: initiative.author_name,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale)),
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before_all { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('Someone published a new proposal on the platform of')
- end
-
- it 'renders the receiver email' do
- expect(mail.to).to eq([recipient.email])
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns author name' do
- expect(mail.body.encoded).to match(initiative.author_name)
- end
-
- it 'assigns go to initiative CTA' do
- initiative_url = Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient.locale))
- expect(mail.body.encoded).to match(initiative_url)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/official_feedback_on_initiative_you_follow_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/official_feedback_on_initiative_you_follow_mailer_spec.rb
deleted file mode 100644
index bd1ace30947c..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/official_feedback_on_initiative_you_follow_mailer_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::OfficialFeedbackOnInitiativeYouFollowMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:initiative) { create(:initiative, title_multiloc: { 'en' => 'Initiative title' }) }
- let_it_be(:feedback) { create(:official_feedback, body_multiloc: { 'en' => 'We appreciate your participation' }, post: initiative) }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::OfficialFeedbackOnInitiativeYouFollow.create! }
- let_it_be(:notification) { create(:official_feedback_on_initiative_you_follow, recipient: recipient, post: initiative, official_feedback: feedback) }
- let_it_be(:command) do
- activity = create(:activity, item: notification, action: 'created')
- create(:official_feedback_on_initiative_you_follow_campaign).generate_commands(
- activity: activity,
- recipient: recipient
- ).first.merge({ recipient: recipient })
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('A proposal you follow has received an official update')
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns organisation name' do
- expect(mail.body.encoded).to match(AppConfiguration.instance.settings('core', 'organization_name', 'en'))
- end
-
- it 'assigns cta url' do
- expect(mail.body.encoded).to match(command.dig(:event_payload, :official_feedback_url))
- end
-
- it 'includes the initiative title' do
- expect(mail.body.encoded).to match('Initiative title')
- end
-
- it 'includes the unfollow url' do
- expect(mail.body.encoded).to match(Frontend::UrlService.new.unfollow_url(Follower.new(followable: notification.post, user: recipient)))
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/comment_on_initiative_you_follow_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/comment_on_initiative_you_follow_mailer_preview.rb
deleted file mode 100644
index 96cc5395ce50..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/comment_on_initiative_you_follow_mailer_preview.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class CommentOnInitiativeYouFollowMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- comment = Comment.where(post_type: 'Initiative').first || Comment.create(post: Initiative.first, author: User.first, body_multiloc: { 'en' => 'I agree' })
- notification = Notifications::CommentOnInitiativeYouFollow.create!(
- recipient_id: recipient_user.id,
- initiating_user: comment.author,
- post: comment.post,
- comment: comment
- )
- activity = Activity.new(item: notification, action: 'created')
-
- campaign = EmailCampaigns::Campaigns::CommentOnInitiativeYouFollow.first
- command = campaign.generate_commands(
- activity: activity,
- recipient: recipient_user
- ).first.merge({ recipient: recipient_user })
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/cosponsor_of_your_initiative_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/cosponsor_of_your_initiative_mailer_preview.rb
deleted file mode 100644
index 27dfe1df492f..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/cosponsor_of_your_initiative_mailer_preview.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class CosponsorOfYourInitiativeMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- campaign = EmailCampaigns::Campaigns::CosponsorOfYourInitiative.first
- initiative = Initiative.order(created_at: :asc).first
- user = User.order(created_at: :asc).first
- item = Notifications::CosponsorOfYourInitiative.new(post: initiative)
- activity = Activity.new(item: item, user: user)
- commands = EmailCampaigns::Campaigns::CosponsorOfYourInitiative.new.generate_commands(recipient: user, activity: activity)
- command = commands[0].merge({ recipient: user })
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_assigned_to_you_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_assigned_to_you_mailer_preview.rb
deleted file mode 100644
index 51e22cd563e7..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_assigned_to_you_mailer_preview.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativeAssignedToYouMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- initiative = Initiative.order(created_at: :asc).first
- # TODO: generate commands with campaign#generate_commands method
- command = {
- recipient: recipient_user,
- event_payload: {
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_author_name: UserDisplayNameService.new(AppConfiguration.instance, recipient_user).display_name!(initiative.author),
- post_published_at: initiative.published_at&.iso8601,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient_user.locale)),
- post_assigned_at: initiative.assigned_at&.iso8601 || Time.now.iso8601,
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }
- campaign = EmailCampaigns::Campaigns::InitiativeAssignedToYou.first
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_marked_as_spam_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_marked_as_spam_mailer_preview.rb
deleted file mode 100644
index cdeeb07a0016..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_marked_as_spam_mailer_preview.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativeMarkedAsSpamMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- initiative = Initiative.first
- initiating_user = User.last
- # TODO: generate commands with campaign#generate_commands method
- command = {
- recipient: recipient_user,
- event_payload: {
- initiating_user_first_name: initiating_user&.first_name,
- initiating_user_last_name: initiating_user&.last_name,
- post_created_at: initiative.created_at.iso8601,
- post_title_multiloc: initiative.title_multiloc,
- post_author_name: initiative.author_name,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient_user.locale)),
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601,
- spam_report_reason_code: 'other',
- spam_report_other_reason: 'This post is an intrusion to my privacy'
- }
- }
- campaign = EmailCampaigns::Campaigns::InitiativeMarkedAsSpam.first
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_published_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_published_mailer_preview.rb
deleted file mode 100644
index 6b9109be956d..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_published_mailer_preview.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativePublishedMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- initiative = Initiative.first
- # TODO: generate commands with campaign#generate_commands method
- command = {
- recipient: recipient_user,
- event_payload: {
- post_id: initiative.id,
- post_title_multiloc: initiative.title_multiloc,
- post_body_multiloc: initiative.body_multiloc,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient_user.locale)),
- post_images: initiative.initiative_images.map do |image|
- {
- ordering: image.ordering,
- versions: image.image.versions.to_h { |k, v| [k.to_s, v.url] }
- }
- end,
- initiative_header_bg: {
- versions: initiative.header_bg.versions.to_h { |k, v| [k.to_s, v.url] }
- },
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }
- campaign = EmailCampaigns::Campaigns::InitiativePublished.first
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_resubmitted_for_review_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_resubmitted_for_review_mailer_preview.rb
deleted file mode 100644
index 31388f5b3df3..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_resubmitted_for_review_mailer_preview.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InitiativeResubmittedForReviewMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- campaign = EmailCampaigns::Campaigns::InitiativeResubmittedForReview.first
- initiative = Initiative.order(created_at: :asc).first
- user = User.order(created_at: :asc).first
- item = Notifications::InitiativeResubmittedForReview.new(post: initiative)
- activity = Activity.new(item: item)
- commands = EmailCampaigns::Campaigns::InitiativeResubmittedForReview.new.generate_commands(recipient: user, activity: activity)
- command = commands[0].merge({ recipient: user })
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer_preview.rb
deleted file mode 100644
index 3667b9257f29..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer_preview.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InternalCommentOnInitiativeAssignedToYouMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- # TODO: generate commands with campaign#generate_commands method
- command = {
- recipient: recipient_user,
- event_payload: {
- initiating_user_first_name: 'Matthias',
- initiating_user_last_name: 'Geeke',
- internal_comment_author_name: 'Matthias Geeke',
- internal_comment_body: 'I agree. I really think this proposal is amazing!',
- internal_comment_url: 'http://localhost:3000/en/internal_comments/fake-url-comment-does-not-exist',
- post_title_multiloc: { en: 'Permit paving of front gardens' },
- post_body_multiloc: {
- en: 'There are many advantages to paving your front garden. Less cars on the road and more space for pedestrians.'
- },
- post_type: 'Initiative',
- post_image_medium_url: InitiativeImage.first.image.versions[:medium].url
- }
- }
-
- campaign = EmailCampaigns::Campaigns::InternalCommentOnInitiativeAssignedToYou.first
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer_preview.rb
deleted file mode 100644
index e74f00c7d510..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer_preview.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InternalCommentOnInitiativeYouCommentedInternallyOnMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- # TODO: generate commands with campaign#generate_commands method
- command = {
- recipient: recipient_user,
- event_payload: {
- initiating_user_first_name: 'Matthias',
- initiating_user_last_name: 'Geeke',
- internal_comment_author_name: 'Matthias Geeke',
- internal_comment_body: 'I also think this proposal is amazing!',
- internal_comment_url: 'http://localhost:3000/en/internal_comments/fake-url-comment-does-not-exist',
- post_title_multiloc: { en: 'Permit paving of front gardens' },
- post_body_multiloc: {
- en: 'There are many advantages to paving your front garden. Less cars on the road and more space for pedestrians.'
- },
- post_type: 'Initiative',
- post_image_medium_url: InitiativeImage.first.image.versions[:medium].url
- }
- }
-
- campaign = EmailCampaigns::Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn.first
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_unassigned_initiative_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_unassigned_initiative_mailer_preview.rb
deleted file mode 100644
index f0ec38d39870..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_unassigned_initiative_mailer_preview.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InternalCommentOnUnassignedInitiativeMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- # TODO: generate commands with campaign#generate_commands method
- command = {
- recipient: recipient_user,
- event_payload: {
- initiating_user_first_name: 'Matthias',
- initiating_user_last_name: 'Geeke',
- internal_comment_author_name: 'Matthias Geeke',
- internal_comment_body: 'I think this proposal is amazing!',
- internal_comment_url: 'http://localhost:3000/en/internal_comments/fake-url-comment-does-not-exist',
- post_title_multiloc: { en: 'Permit paving of front gardens' },
- post_body_multiloc: {
- en: 'There are many advantages to paving your front garden. Less cars on the road and more space for pedestrians.'
- },
- post_type: 'Initiative',
- post_image_medium_url: InitiativeImage.first.image.versions[:medium].url
- }
- }
-
- campaign = EmailCampaigns::Campaigns::InternalCommentOnUnassignedInitiative.first
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/invitation_to_cosponsor_initiative_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/invitation_to_cosponsor_initiative_mailer_preview.rb
deleted file mode 100644
index 835a4ea94466..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/invitation_to_cosponsor_initiative_mailer_preview.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class InvitationToCosponsorInitiativeMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- campaign = EmailCampaigns::Campaigns::InvitationToCosponsorInitiative.first
- initiative = Initiative.order(created_at: :asc).first
- user = User.order(created_at: :asc).first
- item = Notifications::InvitationToCosponsorInitiative.new(post: initiative)
- activity = Activity.new(item: item)
- commands = EmailCampaigns::Campaigns::InvitationToCosponsorInitiative.new.generate_commands(recipient: user, activity: activity)
- command = commands[0].merge({ recipient: user })
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/new_initiative_for_admin_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/new_initiative_for_admin_mailer_preview.rb
deleted file mode 100644
index 944fc3893a1a..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/new_initiative_for_admin_mailer_preview.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class NewInitiativeForAdminMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- initiative = Initiative.first
- # TODO: generate commands with campaign#generate_commands method
- command = {
- recipient: recipient_user,
- event_payload: {
- post_published_at: initiative.published_at.iso8601,
- post_title_multiloc: initiative.title_multiloc,
- post_author_name: initiative.author_name,
- post_url: Frontend::UrlService.new.model_to_url(initiative, locale: Locale.new(recipient_user.locale)),
- initiative_reactions_needed: initiative.reactions_needed,
- initiative_expires_at: initiative.expires_at.iso8601
- }
- }
- campaign = EmailCampaigns::Campaigns::NewInitiativeForAdmin.first
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/official_feedback_on_initiative_you_follow_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/official_feedback_on_initiative_you_follow_mailer_preview.rb
deleted file mode 100644
index 3b92ef49b676..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/official_feedback_on_initiative_you_follow_mailer_preview.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class OfficialFeedbackOnInitiativeYouFollowMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- campaign = EmailCampaigns::Campaigns::OfficialFeedbackOnInitiativeYouFollow.first
-
- command = {
- recipient: recipient_user,
- event_payload: {
- official_feedback_author_multiloc: { 'en' => 'City of Plattsburgh Official' },
- official_feedback_body_multiloc: { 'en' => 'Thank you for taking the time to comment on our parks. We value your feedback and will be looking at improving the dog park in the same way the one at the city beach has been improved.' },
- official_feedback_url: 'https://demo.stg.govocal.com',
- post_published_at: Time.zone.today.prev_week.iso8601,
- post_title_multiloc: { 'en' => 'Fence around the park' },
- post_author_name: 'Julia Langer'
- }
- }
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/status_change_on_initiative_you_follow_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/status_change_on_initiative_you_follow_mailer_preview.rb
deleted file mode 100644
index d864c049650c..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/status_change_on_initiative_you_follow_mailer_preview.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module EmailCampaigns
- class StatusChangeOnInitiativeYouFollowMailerPreview < ActionMailer::Preview
- include EmailCampaigns::MailerPreviewRecipient
-
- def campaign_mail
- campaign = EmailCampaigns::Campaigns::StatusChangeOnInitiativeYouFollow.first
-
- command = campaign.generate_commands(
- recipient: recipient_user,
- activity: Activity.new(item: Notification.new(post: Initiative.first))
- ).first.merge({ recipient: recipient_user })
-
- campaign.mailer_class.with(campaign: campaign, command: command).campaign_mail
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/threshold_reached_for_admin_mailer_preview.rb b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/threshold_reached_for_admin_mailer_preview.rb
index 5d5dd4ab80af..ab35caf3be16 100644
--- a/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/threshold_reached_for_admin_mailer_preview.rb
+++ b/back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/threshold_reached_for_admin_mailer_preview.rb
@@ -6,7 +6,7 @@ class ThresholdReachedForAdminMailerPreview < ActionMailer::Preview
def campaign_mail
campaign = EmailCampaigns::Campaigns::ThresholdReachedForAdmin.first
- post = Initiative.first
+ post = Idea.first
# TODO: generate commands with campaign#generate_commands method
command = {
@@ -19,15 +19,12 @@ def campaign_mail
post_url: 'demo.stg.govocal.com',
post_likes_count: 3,
post_comments_count: 4,
- post_images: post.initiative_images.map do |image|
+ post_images: post.idea_images.map do |image|
{
ordering: image.ordering,
versions: image.image.versions.to_h { |k, v| [k.to_s, v.url] }
}
end,
- initiative_header_bg: {
- versions: post.header_bg.versions.to_h { |k, v| [k.to_s, v.url] }
- },
assignee_first_name: 'Lady',
assignee_last_name: 'Gaga'
}
diff --git a/back/engines/free/email_campaigns/spec/mailers/status_change_on_initiative_you_follow_mailer_spec.rb b/back/engines/free/email_campaigns/spec/mailers/status_change_on_initiative_you_follow_mailer_spec.rb
deleted file mode 100644
index 1624a76761c4..000000000000
--- a/back/engines/free/email_campaigns/spec/mailers/status_change_on_initiative_you_follow_mailer_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::StatusChangeOnInitiativeYouFollowMailer do
- describe 'campaign_mail' do
- let_it_be(:recipient) { create(:user, locale: 'en') }
- let_it_be(:campaign) { EmailCampaigns::Campaigns::StatusChangeOnInitiativeYouFollow.create! }
- let_it_be(:initiative) { create(:initiative) }
- let_it_be(:command) do
- campaign.generate_commands(
- recipient: recipient,
- activity: Activity.new(item: Notification.new(post: initiative))
- ).first.merge({ recipient: recipient })
- end
-
- let_it_be(:mail) { described_class.with(command: command, campaign: campaign).campaign_mail.deliver_now }
-
- before { EmailCampaigns::UnsubscriptionToken.create!(user_id: recipient.id) }
-
- it 'renders the subject' do
- expect(mail.subject).to start_with('The status of a proposal you follow has changed')
- end
-
- it 'renders the sender email' do
- expect(mail.from).to all(end_with('@citizenlab.co'))
- end
-
- it 'assigns organisation name' do
- expect(mail.body.encoded).to match(AppConfiguration.instance.settings('core', 'organization_name', 'en'))
- end
-
- it 'assigns cta url' do
- expect(mail.body.encoded).to match(command.dig(:event_payload, :post_url))
- end
-
- it 'includes the initiative title' do
- expect(mail.body.encoded).to match(initiative.title_multiloc['en'])
- end
-
- it 'includes the unfollow url' do
- expect(mail.body.encoded).to match(Frontend::UrlService.new.unfollow_url(Follower.new(followable: initiative, user: recipient)))
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/comment_on_initiative_you_follow_spec.rb b/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/comment_on_initiative_you_follow_spec.rb
deleted file mode 100644
index 0965d35bcbc8..000000000000
--- a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/comment_on_initiative_you_follow_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::Campaigns::CommentOnInitiativeYouFollow do
- describe 'CommentOnYourInitiative Campaign default factory' do
- it 'is valid' do
- expect(build(:comment_on_initiative_you_follow_campaign)).to be_valid
- end
- end
-
- describe '#generate_commands' do
- let(:campaign) { create(:comment_on_initiative_you_follow_campaign) }
- let(:notification) { create(:comment_on_initiative_you_follow) }
- let(:notification_activity) { create(:activity, item: notification, action: 'created') }
- let(:command) do
- campaign.generate_commands(recipient: notification_activity.item.recipient, activity: notification_activity).first
- end
-
- it 'generates a command with the desired payload and tracked content' do
- expect(command).to match({
- event_payload: hash_including(
- initiating_user_first_name: notification.initiating_user.first_name,
- initiating_user_last_name: notification.initiating_user.last_name,
- comment_author_name: notification.comment.author.full_name,
- comment_body_multiloc: notification.comment.body_multiloc,
- comment_url: an_instance_of(String),
- post_published_at: an_instance_of(String),
- post_title_multiloc: notification.post.title_multiloc,
- post_author_name: notification.post.author.full_name,
- unfollow_url: an_instance_of(String)
- )
- })
-
- expect(
- command.dig(:event_payload, :initiating_user_first_name)
- ).to eq(notification.initiating_user.first_name)
- expect(
- command.dig(:event_payload, :comment_body_multiloc)
- ).to eq(notification.comment.body_multiloc)
- end
-
- it 'generates a command with an abbreviated name' do
- SettingsService.new.activate_feature! 'abbreviated_user_names'
-
- expect(notification.recipient.admin?).to be false
- expect(notification.initiating_user.admin?).to be false
-
- initial = "#{notification.initiating_user.last_name[0]}."
- expect(command.dig(:event_payload, :initiating_user_last_name)).to eq(initial)
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you_spec.rb b/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you_spec.rb
deleted file mode 100644
index 83ad0da92d81..000000000000
--- a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::Campaigns::InternalCommentOnInitiativeAssignedToYou do
- describe 'InternalCommentOnInitiativeAssignedToYou Campaign default factory' do
- it 'is valid' do
- expect(build(:internal_comment_on_initiative_assigned_to_you_campaign)).to be_valid
- end
- end
-
- describe '#generate_commands' do
- let(:campaign) { create(:internal_comment_on_initiative_assigned_to_you_campaign) }
- let(:notification) { create(:internal_comment_on_initiative_assigned_to_you) }
- let!(:post_image) { create(:initiative_image, initiative: notification.post) }
-
- include_examples 'internal_comment_campaign_generate_commands'
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on_spec.rb b/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on_spec.rb
deleted file mode 100644
index 2db0cb4c3bd2..000000000000
--- a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn do
- describe 'InternalCommentOnInitiativeYouCommentedInternallyOn Campaign default factory' do
- it 'is valid' do
- expect(build(:internal_comment_on_initiative_you_commented_internally_on_campaign)).to be_valid
- end
- end
-
- describe '#generate_commands' do
- let(:campaign) { create(:internal_comment_on_initiative_you_commented_internally_on_campaign) }
- let(:notification) { create(:internal_comment_on_initiative_you_commented_internally_on) }
- let!(:post_image) { create(:initiative_image, initiative: notification.post) }
-
- include_examples 'internal_comment_campaign_generate_commands'
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative_spec.rb b/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative_spec.rb
deleted file mode 100644
index 78d58f0f4aa8..000000000000
--- a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::Campaigns::InternalCommentOnUnassignedInitiative do
- describe 'InternalCommentOnUnassignedInitiative Campaign default factory' do
- it 'is valid' do
- expect(build(:internal_comment_on_unassigned_initiative_campaign)).to be_valid
- end
- end
-
- describe '#generate_commands' do
- let(:campaign) { create(:internal_comment_on_unassigned_initiative_campaign) }
- let(:notification) { create(:internal_comment_on_unassigned_initiative) }
- let!(:post_image) { create(:initiative_image, initiative: notification.post) }
-
- include_examples 'internal_comment_campaign_generate_commands'
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/new_initiative_for_admin_spec.rb b/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/new_initiative_for_admin_spec.rb
deleted file mode 100644
index 26622ec42e84..000000000000
--- a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/new_initiative_for_admin_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::Campaigns::NewInitiativeForAdmin do
- describe 'NewInitiativeForAdmin Campaign default factory' do
- it 'is valid' do
- expect(build(:new_initiative_for_admin_campaign)).to be_valid
- end
- end
-
- describe 'apply_recipient_filters' do
- let(:campaign) { build(:new_initiative_for_admin_campaign) }
-
- it 'filters out normal users' do
- initiative = create(:initiative)
- create(:user)
- admin = create(:admin)
-
- expect(campaign.apply_recipient_filters(activity: create(:activity, item: initiative, action: 'published')).ids).to match_array([admin.id])
- end
- end
-
- describe 'apply_recipient_filters' do
- let(:campaign) { build(:new_initiative_for_admin_campaign) }
-
- it 'filters out everyone if the author is admin' do
- author = create(:admin)
- initiative = create(:initiative, author: author)
- create(:admin)
-
- expect(campaign.apply_recipient_filters(activity: create(:activity, item: initiative, action: 'published')).count).to eq 0
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow_spec.rb b/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow_spec.rb
deleted file mode 100644
index 2520317e1a6e..000000000000
--- a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::Campaigns::OfficialFeedbackOnInitiativeYouFollow do
- describe 'OfficialFeedbackOnInitiativeYouFollow campaign default factory' do
- it 'is valid' do
- expect(build(:official_feedback_on_initiative_you_follow_campaign)).to be_valid
- end
- end
-
- describe '#generate_commands' do
- let(:campaign) { create(:official_feedback_on_initiative_you_follow_campaign) }
- let(:notification) { create(:official_feedback_on_initiative_you_follow) }
- let(:notification_activity) { create(:activity, item: notification, action: 'created') }
-
- it 'generates a command with the desired payload and tracked content' do
- command = campaign.generate_commands(
- recipient: notification_activity.item.recipient,
- activity: notification_activity
- ).first
-
- expect(command).to match({
- event_payload: hash_including(
- official_feedback_author_multiloc: notification.official_feedback.author_multiloc,
- official_feedback_body_multiloc: notification.official_feedback.body_multiloc,
- official_feedback_url: an_instance_of(String),
- post_published_at: an_instance_of(String),
- post_title_multiloc: notification.post.title_multiloc,
- post_author_name: notification.post.author_name
- )
- })
- end
- end
-end
diff --git a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/status_change_on_initiative_you_follow_spec.rb b/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/status_change_on_initiative_you_follow_spec.rb
deleted file mode 100644
index ba1d6ce6345b..000000000000
--- a/back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/status_change_on_initiative_you_follow_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe EmailCampaigns::Campaigns::StatusChangeOnInitiativeYouFollow do
- describe 'StatusChangeOnInitiativeYouFollow campaign default factory' do
- it 'is valid' do
- expect(build(:status_change_on_initiative_you_follow_campaign)).to be_valid
- end
- end
-
- describe '#generate_commands' do
- let(:campaign) { create(:status_change_on_initiative_you_follow_campaign) }
- let(:notification) { create(:status_change_on_initiative_you_follow) }
- let(:notification_activity) { create(:activity, item: notification, action: 'created') }
-
- it 'generates a command with the desired payload and tracked content' do
- command = campaign.generate_commands(
- recipient: notification_activity.item.recipient,
- activity: notification_activity
- ).first
-
- expect(command).to match({
- event_payload: hash_including(
- post_id: notification.post.id,
- post_title_multiloc: notification.post.title_multiloc,
- post_body_multiloc: notification.post.body_multiloc,
- post_url: an_instance_of(String),
- post_images: an_instance_of(Array),
- initiative_status_id: notification.post_status.id,
- initiative_status_title_multiloc: notification.post_status.title_multiloc,
- initiative_status_code: notification.post_status.code,
- initiative_status_color: notification.post_status.color
- )
- })
- end
- end
-end
diff --git a/back/spec/acceptance/action_descriptors_spec.rb b/back/spec/acceptance/action_descriptors_spec.rb
deleted file mode 100644
index 8648cb7994ce..000000000000
--- a/back/spec/acceptance/action_descriptors_spec.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-resource 'ActionDescriptors' do
- explanation 'Describe which actions the current user is allowed to take.'
-
- let(:json_response) { json_parse(response_body) }
-
- before do
- resident_header_token
- header 'Content-Type', 'application/json'
- end
-
- get 'web_api/v1/action_descriptors/initiatives' do
- example_request 'Get the global action descriptors for initiatives' do
- assert_status 200
- expect(json_response.dig(:data, :type)).to eq 'initiatives'
- json_attributes = json_response.dig(:data, :attributes)
- expect(json_attributes.values.pluck(:enabled).all?).to be true
- expect(json_attributes.values.pluck(:disabled_reason).none?).to be true
- end
-
- context 'with permissions on a phase enabled', document: false do
- before do
- Permissions::PermissionsUpdateService.new.update_all_permissions
- Permission.find_by(permission_scope: nil, action: 'commenting_initiative')
- .update!(permitted_by: 'users', groups: create_list(:group, 2))
- end
-
- # TODO: cleanup-after-proposals-migration
- example_request 'Get the global action descriptors for initiatives' do
- expect(json_response).to eq(
- {
- data: {
- type: 'initiatives',
- attributes: {
- posting_initiative: {
- enabled: true,
- disabled_reason: nil
- },
- commenting_initiative: {
- enabled: false,
- disabled_reason: 'user_not_in_group'
- },
- reacting_initiative: {
- enabled: true,
- disabled_reason: nil
- },
- cancelling_initiative_reactions: {
- enabled: true,
- disabled_reason: nil
- },
- comment_reacting_initiative: {
- enabled: false,
- disabled_reason: 'user_not_in_group'
- }
- }
- }
- }
- )
- end
- end
- end
-end
diff --git a/back/spec/acceptance/avatars_spec.rb b/back/spec/acceptance/avatars_spec.rb
index 9c8446bddfb8..a7f8d7d1767e 100644
--- a/back/spec/acceptance/avatars_spec.rb
+++ b/back/spec/acceptance/avatars_spec.rb
@@ -91,26 +91,6 @@
end
end
- # TODO: cleanup-after-proposals-migration
- describe do
- let(:initiative) { create(:initiative) }
- let(:context_type) { 'initiative' }
- let(:context_id) { initiative.id }
- let(:author_id) { initiative.author.id }
- let!(:commenter_ids) { Array.new(2) { create(:comment, post: initiative).author.id } }
- let(:limit) { 2 }
-
- example_request 'List random user avatars on an initiative (author and commenters)' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- expect(json_response[:data].map { |d| d.dig(:attributes, :avatar).keys }).to all(eq %i[small medium large])
- expect(json_response[:data].flat_map { |d| d.dig(:attributes, :avatar).values }).to all(be_present)
- expect(json_response[:data].pluck(:id)).to all(satisfy { |id| (commenter_ids + [author_id]).include?(id) })
- expect(json_response.dig(:meta, :total)).to eq 3
- end
- end
-
context 'as an admin' do
before { admin_header_token }
diff --git a/back/spec/acceptance/comment_reactions_spec.rb b/back/spec/acceptance/comment_reactions_spec.rb
index c327431875c0..b229c7dbce85 100644
--- a/back/spec/acceptance/comment_reactions_spec.rb
+++ b/back/spec/acceptance/comment_reactions_spec.rb
@@ -70,9 +70,9 @@
end
describe do
- before { @comment.update!(post: create(:initiative)) }
+ before { @comment.update!(post: create(:idea)) }
- example 'Create a reaction on a comment of an initiative', document: false do
+ example 'Create a reaction on a comment of an idea', document: false do
do_request
assert_status 201
end
diff --git a/back/spec/acceptance/followers_spec.rb b/back/spec/acceptance/followers_spec.rb
index 23db18c2f4af..fead47c9d9e6 100644
--- a/back/spec/acceptance/followers_spec.rb
+++ b/back/spec/acceptance/followers_spec.rb
@@ -25,15 +25,14 @@
let!(:other_follow) { create(:follower, user: create(:user)) }
let!(:folder_follows) { create_list(:project_folder, 2).map { |project| create(:follower, user: user, followable: project) } }
let!(:idea_follows) { [create(:follower, user: user, followable: create(:idea))] }
- let!(:initiative_follows) { [create(:follower, user: user, followable: create(:initiative))] }
let!(:topic_follows) { [create(:follower, user: user, followable: create(:topic))] }
let!(:area_follows) { [create(:follower, user: user, followable: create(:area))] }
example_request 'List all followers' do
assert_status 200
json_response = json_parse response_body
- expect(json_response[:data].size).to eq 8
- expect(json_response[:data].pluck(:id)).to match_array (project_follows + folder_follows + idea_follows + initiative_follows + topic_follows + area_follows).map(&:id)
+ expect(json_response[:data].size).to eq 7
+ expect(json_response[:data].pluck(:id)).to match_array (project_follows + folder_follows + idea_follows + topic_follows + area_follows).map(&:id)
end
describe do
@@ -50,7 +49,6 @@
end
end
- # TODO: cleanup-after-proposals-migration
get 'web_api/v1/followers/:id' do
let(:id) { create(:follower, user: user).id }
@@ -77,11 +75,6 @@
resource: 'ideas',
factory: 'idea'
},
- {
- type: 'initiative',
- resource: 'initiatives',
- factory: 'initiative'
- },
{
type: 'topic',
resource: 'topics',
diff --git a/back/spec/acceptance/initiative_comments_spec.rb b/back/spec/acceptance/initiative_comments_spec.rb
deleted file mode 100644
index e883065f17f5..000000000000
--- a/back/spec/acceptance/initiative_comments_spec.rb
+++ /dev/null
@@ -1,359 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'Comments' do
- explanation 'Comments permit users to have discussions about content (i.e. ideas).'
-
- before do
- header 'Content-Type', 'application/json'
- @initiative = create(:initiative)
- end
-
- get 'web_api/v1/initiatives/:initiative_id/comments' do
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of top-level comments per page. The response will include 2 to 5 child comments per top-level comment, so expect to receive more'
- end
- parameter :sort, 'Either new, -new, likes_count or -likes_count. Defaults to -new. Only applies to the top-level comments, children are always returned chronologically.'
-
- describe do
- before do
- @c1 = create(:comment, post: @initiative)
- @c2 = create(:comment, post: @initiative)
- @c1sub1 = create(:comment, parent: @c2, post: @initiative)
- @c1sub2 = create(:comment, parent: @c2, post: @initiative)
- @c1sub3 = create(:comment, parent: @c2, post: @initiative)
- @c1sub4 = create(:comment, parent: @c2, post: @initiative)
- @c1sub5 = create(:comment, parent: @c2, post: @initiative)
- @c3 = create(:comment, post: @initiative)
- @c3sub1 = create(:comment, parent: @c3, post: @initiative)
- @c3sub2 = create(:comment, parent: @c3, post: @initiative)
- @c3sub3 = create(:comment, parent: @c3, post: @initiative)
- @c3sub4 = create(:comment, parent: @c3, post: @initiative)
- @c3sub5 = create(:comment, parent: @c3, post: @initiative)
- @c3sub6 = create(:comment, parent: @c3, post: @initiative)
- @c4 = create(:comment, post: @initiative)
- @c4sub1 = create(:comment, parent: @c4, post: @initiative)
- end
-
- let(:initiative_id) { @initiative.id }
- let(:size) { 3 }
-
- example_request 'List the top-level comments of an initiative' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 10
- expect(json_response[:data].pluck(:id)).to eq([
- @c1,
- @c2,
- @c1sub1,
- @c1sub2,
- @c1sub3,
- @c1sub4,
- @c1sub5,
- @c3,
- @c3sub5,
- @c3sub6
- ].map(&:id))
- end
- end
-
- describe do
- let(:initiative_id) { @initiative.id }
- let(:sort) { '-likes_count' }
-
- before do
- @c1, @c2, @c3 = create_list(:comment, 3, post: @initiative)
- create_list(:reaction, 2, reactable: @c3)
- create_list(:reaction, 3, reactable: @c2)
- @c3sub1, @c3sub2 = create_list(:comment, 2, parent: @c3, post: @initiative)
- create(:reaction, reactable: @c3sub2)
- end
-
- example_request 'List the top-level comments of an initiative sorted by descending likes_count' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 5
- expect(json_response[:data].pluck(:id)).to eq([
- @c2,
- @c3,
- @c3sub1,
- @c3sub2,
- @c1
- ].map(&:id))
- end
- end
- end
-
- get 'web_api/v1/comments/:comment_id/children' do
- explanation 'Children are always returned chronologically'
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of comments per page'
- end
-
- before do
- @c = create(:comment, post: @initiative)
- @csub1 = create(:comment, parent: @c, post: @initiative)
- @csub2 = create(:comment, parent: @c, post: @initiative)
- @csub3 = create(:comment, parent: @c, post: @initiative)
- @csub4 = create(:comment, parent: @c, post: @initiative)
- @csub5 = create(:comment, parent: @c, post: @initiative)
- @csub6 = create(:comment, parent: @c, post: @initiative)
- @c2 = create(:comment, post: @initiative)
- end
-
- let(:comment_id) { @c.id }
-
- example_request 'List the direct child comments of a comment on an initiative' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 6
- expect(json_response[:data].pluck(:id)).to eq([
- @csub1,
- @csub2,
- @csub3,
- @csub4,
- @csub5,
- @csub6
- ].map(&:id))
- end
- end
-
- get 'web_api/v1/initiatives/comments/as_xlsx' do
- parameter :initiatives, 'Filter by a given list of initiative ids', required: false
- before do
- @user = create(:admin)
- header_token_for @user
- end
-
- describe do
- before do
- @comments = Array.new(3) do |_i|
- create(:comment, post: create(:initiative))
- end
- end
-
- example_request 'XLSX export of comments on initiatives' do
- expect(status).to eq 200
- worksheet = RubyXL::Parser.parse_buffer(response_body).worksheets[0]
- expect(worksheet.count).to eq(@comments.size + 1)
- end
- end
-
- describe do
- before do
- @comments = create_list(:comment, 4, post: create(:initiative))
- end
-
- let(:initiatives) { @comments.map(&:post_id) }
-
- example 'XLSX export by initiative ids', document: false do
- do_request
- expect(status).to eq 200
- worksheet = RubyXL::Parser.parse_buffer(response_body).worksheets[0]
- expect(worksheet.count).to eq(initiatives.size + 1)
- end
- end
-
- describe 'when resident' do
- before { resident_header_token }
-
- example '[error] XLSX export', document: false do
- do_request
- expect(status).to eq 401
- end
- end
- end
-
- get 'web_api/v1/comments/:id' do
- let(:comment) { create(:comment, post: create(:initiative)) }
- let(:id) { comment.id }
-
- example_request 'Get one comment by id' do
- expect(status).to eq 200
- expect(response_data[:id]).to eq id
- expect(response_data[:attributes]).to include(
- dislikes_count: 0,
- publication_status: 'published',
- is_admin_comment: false,
- anonymous: false,
- author_hash: comment.author_hash
- )
- end
- end
-
- context 'when authenticated' do
- before do
- @user = create(:user)
- header_token_for @user
- end
-
- get 'web_api/v1/initiatives/:initiative_id/comments' do
- let(:initiative_id) { @initiative.id }
-
- example 'List all comments of an initiative includes the user_reaction when authenticated' do
- comment = create(:comment, post: @initiative)
- reaction = create(:reaction, user: @user, reactable: comment)
- do_request
- json_response = json_parse(response_body)
- expect(json_response[:data].filter_map { |d| d[:relationships][:user_reaction][:data] }.first[:id]).to eq reaction.id
- expect(json_response[:included].pluck(:id)).to include reaction.id
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/comments' do
- with_options scope: :comment do
- parameter :author_id, 'The user id of the user owning the comment. Signed in user by default', required: false
- parameter :body_multiloc, 'Multi-locale field with the comment body', required: true
- parameter :parent_id, 'The id of the comment this comment is a response to', required: false
- parameter :anonymous, 'Post this comment anonymously - true/false', required: false
- end
- ValidationErrorHelper.new.error_fields(self, Comment)
- response_field :base, "Array containing objects with signature { error: #{Permissions::InitiativePermissionsService::USER_DENIED_REASONS.values.join(' | ')} }", scope: :errors
-
- let(:initiative_id) { @initiative.id }
- let(:comment) { build(:comment) }
- let(:body_multiloc) { comment.body_multiloc }
-
- example_request 'Create a comment on an initiative' do
- expect(response_status).to eq 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :author, :data, :id)).to eq @user.id
- expect(json_response.dig(:data, :attributes, :body_multiloc).stringify_keys).to match body_multiloc
- expect(json_response.dig(:data, :relationships, :parent, :data)).to be_nil
- expect(json_response.dig(:data, :relationships, :post, :data, :id)).to eq initiative_id
- expect(@initiative.reload.comments_count).to eq 1
- end
-
- describe 'anomymous commenting' do
- let(:allow_anonymous_participation) { true }
- let(:anonymous) { true }
-
- before do
- config = AppConfiguration.instance
- config.settings['initiatives']['allow_anonymous_participation'] = allow_anonymous_participation
- config.save!
- end
-
- example_request 'Create an anonymous comment on an initiative' do
- assert_status 201
- expect(response_data.dig(:relationships, :author, :data, :id)).to be_nil
- expect(response_data.dig(:attributes, :anonymous)).to be true
- expect(response_data.dig(:attributes, :author_name)).to be_nil
- end
-
- example 'Does not add the author as a follower', document: false do
- expect { do_request }.not_to change(Follower, :count)
- end
-
- example 'Does not log activities for the author', document: false do
- expect { do_request }.not_to have_enqueued_job(LogActivityJob).with(anything, anything, @user, anything)
- end
-
- describe 'when anonymous posting is not allowed' do
- let(:allow_anonymous_participation) { false }
-
- example_request 'Rejects the anonymous parameter' do
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:base, 'anonymous_participation_not_allowed')
- end
- end
- end
- end
-
- post 'web_api/v1/comments/:id/mark_as_deleted' do
- with_options scope: :comment do
- parameter :reason_code, "one of #{Notifications::CommentDeletedByAdmin::REASON_CODES}; only required for admins", required: false
- parameter :other_reason, "the reason for deleting the comment, if none of the reason codes is applicable, in which case 'other' must be chosen", required: false
- end
-
- let(:comment) { create(:comment, author: @user, post: @initiative) }
- let(:id) { comment.id }
-
- example_request 'Mark a comment on an initiative as deleted' do
- expect(response_status).to eq 202
- expect(comment.reload.publication_status).to eq('deleted')
- end
- end
-
- patch 'web_api/v1/comments/:id' do
- with_options scope: :comment do
- parameter :author_id, 'The user id of the user owning the comment. Signed in user by default'
- parameter :body_multiloc, 'Multi-locale field with the comment body'
- parameter :parent_id, 'The id of the comment this comment is a response to'
- parameter :anonymous, 'Change this comment to anonymous - true/false'
- end
- ValidationErrorHelper.new.error_fields(self, Comment)
- response_field :base, "Array containing objects with signature { error: #{Permissions::InitiativePermissionsService::USER_DENIED_REASONS.values.join(' | ')} }", scope: :errors
-
- let(:comment) { create(:comment, author: @user, post: @initiative) }
- let(:id) { comment.id }
- let(:body_multiloc) { { 'en' => "His hair is not blond, it's orange. Get your facts straight!" } }
-
- example_request 'Update a comment on an initiative' do
- expect(response_status).to eq 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :body_multiloc).stringify_keys).to match body_multiloc
- expect(@initiative.reload.comments_count).to eq 1
- end
-
- example 'Admins cannot modify a comment on an initiative', document: false do
- admin_header_token
- do_request
- expect(comment.reload.body_multiloc).not_to eq body_multiloc
- end
-
- describe 'anomymous commenting' do
- let(:allow_anonymous_participation) { true }
- let(:anonymous) { true }
-
- before do
- config = AppConfiguration.instance
- config.settings['initiatives']['allow_anonymous_participation'] = allow_anonymous_participation
- config.save!
- end
-
- example_request 'Change an comment on an initiative to anonymous' do
- assert_status 200
- expect(response_data.dig(:relationships, :author, :data, :id)).to be_nil
- expect(response_data.dig(:attributes, :anonymous)).to be true
- expect(response_data.dig(:attributes, :author_name)).to be_nil
- end
-
- example '[Error] Cannot update an anonymous comment' do
- comment.update!(anonymous: true)
- do_request
- assert_status 401
- expect(json_response_body.dig(:errors, :base, 0, :error)).to eq 'Unauthorized!'
- end
-
- example 'Does not log activities for the author and clears the author from past activities', document: false do
- clear_activity = create(:activity, item: comment, user: @user)
- other_item_activity = create(:activity, item: comment, user: create(:user))
- other_user_activity = create(:activity, user: @user)
-
- expect { do_request }.not_to have_enqueued_job(LogActivityJob).with(anything, anything, @user, anything)
- expect(clear_activity.reload.user_id).to be_nil
- expect(other_item_activity.reload.user_id).to be_present
- expect(other_user_activity.reload.user_id).to eq @user.id
- end
-
- describe 'when anonymous posting is not allowed' do
- let(:allow_anonymous_participation) { false }
-
- example 'Rejects the anonymous parameter' do
- do_request comment: { anonymous: true }
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:base, 'anonymous_participation_not_allowed')
- end
- end
- end
- end
- end
-end
diff --git a/back/spec/acceptance/initiative_files_spec.rb b/back/spec/acceptance/initiative_files_spec.rb
deleted file mode 100644
index cae6b6ead8bb..000000000000
--- a/back/spec/acceptance/initiative_files_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'InitiativeFile' do
- explanation 'File attachments.'
-
- before do
- header 'Content-Type', 'application/json'
- @user = create(:user)
- header_token_for @user
- @initiative = create(:initiative, author: @user)
- create_list(:initiative_file, 2, initiative: @initiative)
- end
-
- get 'web_api/v1/initiatives/:initiative_id/files' do
- let(:initiative_id) { @initiative.id }
-
- example_request 'List all file attachments of an initiative' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- end
- end
-
- get 'web_api/v1/initiatives/:initiative_id/files/:file_id' do
- let(:initiative_id) { @initiative.id }
- let(:file_id) { InitiativeFile.first.id }
-
- example_request 'Get one file attachment of an initiative by id' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :file)).to be_present
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/files' do
- with_options scope: :file do
- parameter :file, 'The base64 encoded file', required: true
- parameter :name, 'The name of the file, including the file extension', required: true
- parameter :ordering, 'An integer that is used to order the files within an initiative', required: false
- end
- ValidationErrorHelper.new.error_fields(self, InitiativeFile)
-
- let(:initiative_id) { @initiative.id }
- let(:file) { encode_file_as_base64('afvalkalender.pdf') }
- let(:ordering) { 1 }
- let(:name) { 'afvalkalender.pdf' }
-
- example_request 'Add a file attachment to an initiative' do
- expect(response_status).to eq 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :file)).to be_present
- expect(json_response.dig(:data, :attributes, :ordering)).to eq(1)
- expect(json_response.dig(:data, :attributes, :name)).to eq(name)
- end
- end
-
- delete 'web_api/v1/initiatives/:initiative_id/files/:file_id' do
- let(:initiative_id) { @initiative.id }
- let(:file_id) { InitiativeFile.first.id }
-
- example_request 'Delete a file attachment from an initiative' do
- expect(response_status).to eq 200
- expect { InitiativeFile.find(file_id) }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- private
-
- def encode_file_as_base64(filename)
- "data:application/pdf;base64,#{Base64.encode64(Rails.root.join('spec', 'fixtures', filename).read)}"
- end
-end
diff --git a/back/spec/acceptance/initiative_images_spec.rb b/back/spec/acceptance/initiative_images_spec.rb
deleted file mode 100644
index 82db8a7c4103..000000000000
--- a/back/spec/acceptance/initiative_images_spec.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'InitiativeImage' do
- explanation 'Initiatives can have mutliple images.'
-
- before do
- header 'Content-Type', 'application/json'
- @user = create(:user)
- header_token_for @user
- @initiative = create(:initiative, author: @user)
- create_list(:initiative_image, 2, initiative: @initiative)
- end
-
- get 'web_api/v1/initiatives/:initiative_id/images' do
- let(:initiative_id) { @initiative.id }
-
- example_request 'List all images of an initiative' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- end
- end
-
- get 'web_api/v1/initiatives/:initiative_id/images/:image_id' do
- let(:initiative_id) { @initiative.id }
- let(:image_id) { InitiativeImage.first.id }
-
- example_request 'Get one image of an initiative by id' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :versions).keys).to match %i[small medium large fb]
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/images' do
- with_options scope: :image do
- parameter :image, 'The base64 encoded image', required: true
- parameter :ordering, 'An integer that is used to order the images within an initiative', required: false
- end
- ValidationErrorHelper.new.error_fields(self, InitiativeImage)
-
- let(:initiative_id) { @initiative.id }
- let(:image) { png_image_as_base64 'image13.png' }
- let(:ordering) { 1 }
-
- example_request 'Add an image to an initiative' do
- expect(response_status).to eq 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :versions).keys).to match %i[small medium large fb]
- expect(json_response.dig(:data, :attributes, :ordering)).to eq(1)
- end
- end
-
- patch 'web_api/v1/initiatives/:initiative_id/images/:image_id' do
- with_options scope: :image do
- parameter :image, 'The base64 encoded image'
- parameter :ordering, 'An integer that is used to order the images within an initiative'
- end
- ValidationErrorHelper.new.error_fields(self, InitiativeImage)
-
- let(:initiative_id) { @initiative.id }
- let(:image_id) { InitiativeImage.first.id }
- let(:image) { png_image_as_base64 'image14.png' }
- let(:ordering) { 2 }
-
- example_request 'Update an image for an initiative' do
- expect(response_status).to eq 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :versions).keys).to match %i[small medium large fb]
- expect(json_response.dig(:data, :attributes, :ordering)).to eq(2)
- end
- end
-
- delete 'web_api/v1/initiatives/:initiative_id/images/:image_id' do
- let(:initiative_id) { @initiative.id }
- let(:image_id) { InitiativeImage.first.id }
-
- example_request 'Delete an image from an initiative' do
- expect(response_status).to eq 200
- expect { InitiativeImage.find(image_id) }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-end
diff --git a/back/spec/acceptance/initiative_official_feedbacks_spec.rb b/back/spec/acceptance/initiative_official_feedbacks_spec.rb
deleted file mode 100644
index 2d405bbbd53e..000000000000
--- a/back/spec/acceptance/initiative_official_feedbacks_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'OfficialFeedback' do
- explanation 'Official feedback is input from moderators on content (i.e. ideas), separated from comments.'
-
- before do
- header 'Content-Type', 'application/json'
- @initiative = create(:initiative)
- @feedbacks = create_list(:official_feedback, 2, post: @initiative)
- end
-
- get 'web_api/v1/initiatives/:initiative_id/official_feedback' do
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of official feedback per page'
- end
-
- let(:initiative_id) { @initiative.id }
-
- example_request 'List all official feedback of an initiative' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- expect(json_response.dig(:data, 0, :attributes, :body_multiloc)).to be_present
- expect(json_response.dig(:data, 0, :attributes, :author_multiloc)).to be_present
- end
- end
-
- get 'web_api/v1/official_feedback/:id' do
- let(:id) { @feedbacks.first.id }
-
- example_request 'Get one official feedback on an initiative by id' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :id)).to eq @feedbacks.first.id
- end
- end
-
- context 'when authenticated' do
- before do
- @user = create(:admin)
- header_token_for @user
- end
-
- post 'web_api/v1/initiatives/:initiative_id/official_feedback' do
- with_options scope: :official_feedback do
- parameter :body_multiloc, 'Multi-locale field with the feedback body', required: true
- parameter :author_multiloc, 'Multi-locale field with describing the author', required: true
- end
- ValidationErrorHelper.new.error_fields(self, OfficialFeedback)
-
- let(:initiative_id) { @initiative.id }
- let(:feedback) { build(:official_feedback) }
- let(:body_multiloc) { feedback.body_multiloc }
- let(:author_multiloc) { feedback.author_multiloc }
-
- example_request 'Create an official feedback on an initiative' do
- assert_status 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :user, :data, :id)).to eq @user.id
- expect(json_response.dig(:data, :attributes, :body_multiloc).stringify_keys).to match body_multiloc
- expect(json_response.dig(:data, :attributes, :author_multiloc).stringify_keys).to match author_multiloc
- expect(json_response.dig(:data, :relationships, :post, :data, :id)).to eq initiative_id
- expect(@initiative.reload.official_feedbacks_count).to eq 3
- end
-
- describe do
- let(:body_multiloc) { { 'en' => '' } }
-
- example_request '[error] Create an invalid official feedback on an initiative' do
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:body_multiloc, 'blank')
- end
- end
- end
-
- patch 'web_api/v1/official_feedback/:id' do
- with_options scope: :official_feedback do
- parameter :body_multiloc, 'Multi-locale field with the feedback body', required: true
- parameter :author_multiloc, 'Multi-locale field with describing the author', required: true
- end
- ValidationErrorHelper.new.error_fields(self, OfficialFeedback)
-
- let(:official_feedback) { create(:official_feedback, user: @user, post: @initiative) }
- let(:id) { official_feedback.id }
- let(:body_multiloc) { { 'en' => "His hair is not blond, it's orange. Get your facts straight!" } }
-
- example_request 'Update an official feedback for an initiative' do
- expect(response_status).to eq 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :body_multiloc).stringify_keys).to match body_multiloc
- expect(@initiative.reload.official_feedbacks_count).to eq 3
- end
- end
-
- delete 'web_api/v1/official_feedback/:id' do
- let(:official_feedback) { create(:official_feedback, user: @user, post: @initiative) }
- let(:id) { official_feedback.id }
- example_request 'Delete an official feedback from an initiative' do
- expect(response_status).to eq 200
- expect { OfficialFeedback.find(id) }.to raise_error(ActiveRecord::RecordNotFound)
- expect(@initiative.reload.official_feedbacks_count).to eq 2
- end
- end
- end
-
- context 'when resident' do
- before { resident_header_token }
-
- post 'web_api/v1/initiatives/:initiative_id/official_feedback' do
- with_options scope: :official_feedback do
- parameter :body_multiloc, 'Multi-locale field with the feedback body', required: true
- parameter :author_multiloc, 'Multi-locale field with describing the author', required: true
- end
- ValidationErrorHelper.new.error_fields(self, OfficialFeedback)
-
- let(:initiative_id) { @initiative.id }
- let(:feedback) { build(:official_feedback) }
- let(:body_multiloc) { feedback.body_multiloc }
- let(:author_multiloc) { feedback.author_multiloc }
-
- example_request '[error] Create an official feedback on an initiative' do
- expect(response_status).to eq 401
- end
- end
- end
-end
diff --git a/back/spec/acceptance/initiative_reactions_spec.rb b/back/spec/acceptance/initiative_reactions_spec.rb
deleted file mode 100644
index c16109130871..000000000000
--- a/back/spec/acceptance/initiative_reactions_spec.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'Reactions' do
- explanation 'Reactions are used to express agreement on content (i.e. ideas). Ideally, the city would accept the most reactiond initiatives.'
-
- before do
- @user = create(:admin)
- header_token_for @user
- header 'Content-Type', 'application/json'
-
- @status_proposed = create(:initiative_status_proposed)
- @status_expired = create(:initiative_status_expired)
- @status_threshold_reached = create(:initiative_status_threshold_reached)
- @status_answered = create(:initiative_status_answered)
- @status_ineligible = create(:initiative_status_ineligible)
-
- @initiative = create(:initiative)
-
- @initiative.initiative_status_changes.create!(
- initiative_status: @status_proposed
- )
- @reactions = create_list(:reaction, 2, reactable: @initiative, mode: 'up')
- end
-
- get 'web_api/v1/initiatives/:initiative_id/reactions' do
- let(:initiative_id) { @initiative.id }
-
- example_request 'List all reactions of an initiative' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- end
- end
-
- get 'web_api/v1/reactions/:id' do
- let(:id) { @reactions.first.id }
-
- example_request 'Get one reaction on an initiative by id' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :id)).to eq @reactions.first.id
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/reactions' do
- with_options scope: :reaction do
- parameter :user_id, 'The user id of the user owning the reaction. Signed in user by default', required: false
- parameter :mode, 'one of [up, down]', required: true
- end
- ValidationErrorHelper.new.error_fields(self, Reaction)
-
- disabled_reasons = Permissions::InitiativePermissionsService::USER_DENIED_REASONS.values
- response_field :base, "Array containing objects with signature { error: #{disabled_reasons.join(' | ')} }", scope: :errors
-
- let(:initiative_id) { @initiative.id }
- let(:mode) { 'up' }
-
- example_request 'Create a reaction to an initiative' do
- assert_status 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :user, :data, :id)).to be_nil
- expect(json_response.dig(:data, :attributes, :mode)).to eq 'up'
- expect(@initiative.reload.likes_count).to eq 3
- end
-
- # TODO: cleanup-after-proposals-migration
- example 'Reaching the voting threshold immediately triggers status change', document: false do
- settings = AppConfiguration.instance.settings
- settings['initiatives']['reacting_threshold'] = 3
- AppConfiguration.instance.update! settings: settings
-
- do_request
- assert_status 201
- expect(@initiative.reload.initiative_status).to eq @status_threshold_reached
- end
-
- example 'The first non-author reaction create action will set editing_locked to true', document: false do
- expect(@initiative.reload.editing_locked).to be false
- do_request
- assert_status 201
- expect(@initiative.reload.editing_locked).to be true
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/reactions/up' do
- ValidationErrorHelper.new.error_fields(self, Reaction)
-
- disabled_reasons = Permissions::InitiativePermissionsService::USER_DENIED_REASONS.values
- response_field :base, "Array containing objects with signature { error: #{disabled_reasons.join(' | ')} }", scope: :errors
-
- let(:initiative_id) { @initiative.id }
-
- example_request "Like an initiative that doesn't have your reaction yet" do
- assert_status 201
- expect(@initiative.reload.likes_count).to eq 3
- expect(@initiative.reload.dislikes_count).to eq 0
- end
-
- example 'Like an initiative that you disliked before' do
- @initiative.reactions.create(user: @user, mode: 'down')
- do_request
- assert_status 201
- expect(@initiative.reload.likes_count).to eq 3
- expect(@initiative.reload.dislikes_count).to eq 0
- end
-
- example '[error] Like an initiative that you liked before' do
- @initiative.reactions.create(user: @user, mode: 'up')
- do_request
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:base, 'already_liked')
- expect(@initiative.reload.likes_count).to eq 3
- expect(@initiative.reload.dislikes_count).to eq 0
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/reactions/down' do
- ValidationErrorHelper.new.error_fields(self, Reaction)
-
- disabled_reasons = Permissions::InitiativePermissionsService::USER_DENIED_REASONS.values
- response_field :base, "Array containing objects with signature { error: #{disabled_reasons.join(' | ')} }", scope: :errors
-
- let(:initiative_id) { @initiative.id }
-
- example_request "[error] Dislike an initiative that doesn't have your reaction yet" do
- assert_status 401
- json_response = json_parse(response_body)
- expect(json_response.dig(:errors, :base)).to include({ error: 'dislikes_not_supported' })
- expect(@initiative.reload.likes_count).to eq 2
- expect(@initiative.reload.dislikes_count).to eq 0
- end
- end
-
- delete 'web_api/v1/reactions/:id' do
- let(:reaction) { create(:reaction, user: @user, reactable: @initiative) }
- let(:id) { reaction.id }
-
- example_request 'Delete a reaction from an initiative' do
- assert_status 200
- expect { Reaction.find(id) }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-end
diff --git a/back/spec/acceptance/initiative_spam_report_spec.rb b/back/spec/acceptance/initiative_spam_report_spec.rb
deleted file mode 100644
index d19fee268f84..000000000000
--- a/back/spec/acceptance/initiative_spam_report_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'Spam Reports' do
- explanation 'Reporting undesired content (i.e. an initiative).'
-
- before do
- @user = create(:admin)
- header_token_for @user
- header 'Content-Type', 'application/json'
- @initiative = create(:initiative)
- @spam_reports = create_list(:spam_report, 2, spam_reportable: @initiative)
- end
-
- get 'web_api/v1/initiatives/:initiative_id/spam_reports' do
- let(:initiative_id) { @initiative.id }
-
- example_request 'List all spam reports of an initiative' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- end
- end
-
- get 'web_api/v1/spam_reports/:id' do
- let(:id) { @spam_reports.first.id }
-
- example_request 'Get one spam report of an initiative by id' do
- expect(status).to eq 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :id)).to eq @spam_reports.first.id
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/spam_reports' do
- with_options scope: :spam_report do
- parameter :user_id, 'the user id of the user owning the spam report. Signed in user by default', required: false
- parameter :reason_code, 'one of [wrong_content, inappropriate, other]', required: true
- parameter :other_reason, "the reason for the spam report, if none of the reason codes is applicable, in which case 'other' must be chosen", required: false
- end
- ValidationErrorHelper.new.error_fields(self, SpamReport)
-
- let(:initiative_id) { @initiative.id }
- let(:reason_code) { 'inappropriate' }
-
- example_request 'Create a spam report for an initiative' do
- expect(response_status).to eq 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :user, :data, :id)).to eq @user.id
- expect(json_response.dig(:data, :attributes, :reason_code)).to eq 'inappropriate'
- end
- end
-
- patch 'web_api/v1/spam_reports/:id' do
- with_options scope: :spam_report do
- parameter :reason_code, 'one of [wrong_content, inappropriate, other]', required: true
- parameter :other_reason, "the reason for the spam report, if none of the reason codes is applicable, in which case 'other' must be chosen", required: false
- end
- ValidationErrorHelper.new.error_fields(self, SpamReport)
-
- let(:spam_report) { create(:spam_report, user: @user, spam_reportable: @initiative, reason_code: 'other', other_reason: 'pagiarism') }
- let(:id) { spam_report.id }
- let(:reason_code) { 'inappropriate' }
-
- example_request 'Update a spam report for an initiative' do
- expect(status).to be 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :reason_code)).to eq 'inappropriate'
- end
- end
-
- delete 'web_api/v1/spam_reports/:id' do
- let(:spam_report) { create(:spam_report, user: @user, spam_reportable: @initiative) }
- let(:id) { spam_report.id }
-
- example_request 'Delete a spam report from an initiative' do
- expect(response_status).to eq 200
- expect { SpamReport.find(id) }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-end
diff --git a/back/spec/acceptance/initiative_status_changes_spec.rb b/back/spec/acceptance/initiative_status_changes_spec.rb
deleted file mode 100644
index 94d9819d8764..000000000000
--- a/back/spec/acceptance/initiative_status_changes_spec.rb
+++ /dev/null
@@ -1,227 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'InitiativeStatusChange' do
- explanation 'Initiative status changes allow admins to apply manual status changes on initiatives.'
-
- before do
- header 'Content-Type', 'application/json'
- @initiative = create(:initiative)
- @changes = create_list(:initiative_status_change, 2, initiative: @initiative)
- end
-
- get 'web_api/v1/initiatives/:initiative_id/initiative_status_changes' do
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of status changes per page'
- end
-
- before { admin_header_token }
-
- let(:initiative_id) { @initiative.id }
-
- example_request 'List all status changes of an initiative' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 3
- expect(json_response.dig(:data, 0, :attributes, :created_at)).to be_present
- end
- end
-
- get 'web_api/v1/initiative_status_changes/:id' do
- before { admin_header_token }
-
- let(:id) { @changes.first.id }
-
- example_request 'Get one status changes on an initiative by id' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :id)).to eq @changes.first.id
- end
- end
-
- context 'when authenticated' do
- before do
- @user = create(:admin)
- header_token_for @user
-
- @status_review_pending = create(:initiative_status_review_pending)
- @status_changes_requested = create(:initiative_status_changes_requested)
- @status_proposed = create(:initiative_status_proposed)
- @status_expired = create(:initiative_status_expired)
- @status_threshold_reached = create(:initiative_status_threshold_reached)
- @status_answered = create(:initiative_status_answered)
- @status_ineligible = create(:initiative_status_ineligible)
-
- create(
- :initiative_status_change,
- initiative: @initiative, initiative_status: @status_threshold_reached
- )
- end
-
- post 'web_api/v1/initiatives/:initiative_id/initiative_status_changes' do
- with_options scope: :initiative_status_change do
- parameter :initiative_status_id, 'The new initiative status', required: true
- parameter :user_id, 'The user who made the status change', required: false
- parameter :official_feedback_id, 'An existing official feedback can be used', required: false
- end
- with_options scope: %i[initiative_status_change official_feedback_attributes] do
- parameter :body_multiloc, 'Multi-locale field with the feedback body', required: false
- parameter :author_multiloc, 'Multi-locale field with describing the author', required: false
- end
- ValidationErrorHelper.new.error_fields(self, InitiativeStatusChange)
-
- let(:initiative_id) { @initiative.id }
- let(:initiative_status_id) { @status_answered.id }
- let(:feedback) { build(:official_feedback) }
- let(:body_multiloc) { feedback.body_multiloc }
- let(:author_multiloc) { feedback.author_multiloc }
-
- example_request 'Create a status change on an initiative with new feedback' do
- assert_status 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :user, :data, :id)).to eq @user.id
- expect(@initiative.reload.official_feedbacks_count).to eq 1
- end
-
- describe do
- let(:official_feedback_id) { create(:official_feedback, post: @initiative).id }
- let(:body_multiloc) { nil }
- let(:author_multiloc) { nil }
-
- example_request 'Create a status change on an initiative using an existing feedback' do
- assert_status 201
- expect(@initiative.reload.official_feedbacks_count).to eq 1
- end
- end
-
- describe do
- let(:body_multiloc) { nil }
- let(:author_multiloc) { nil }
-
- example_request '[error] Create a status change on an initiative without feedback' do
- assert_status 422
- end
- end
-
- describe do
- let(:initiative_status_id) { @status_expired.id }
-
- example_request '[error] Create a status change through an invalid transition' do
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:base, 'initiative_status_transition_not_allowed')
- end
- end
-
- describe do
- let(:initiative_status_id) { @status_threshold_reached.id }
-
- example_request '[error] Create a status change to the same status' do
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:base, 'initiative_status_transition_without_change')
- end
- end
-
- # If the review feature is off, the initiative_status_change with code 'proposed'
- # is created at the model level when the initiative is published.
- # Thus, this POST request can only happen when the review feature is on.
- context 'when the the status change is to the proposed status' do
- let(:new_initiative) { create(:initiative) }
- let!(:_initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: new_initiative,
- initiative_status: @status_review_pending
- )
- end
-
- let(:initiative_id) { new_initiative.id }
- let(:initiative_status_id) { @status_proposed.id }
-
- example 'creation of status change record' do
- expect(Initiative.find(initiative_id).editing_locked).to be false
-
- # results in the logging of an Initiative 'proposed' activity
- expect { do_request }
- .to have_enqueued_job(LogActivityJob)
- .with(instance_of(Initiative), 'proposed', @user, instance_of(Integer))
- .exactly(1).times
- assert_status 201
- # results in the setting of editing_locked: true
- expect(Initiative.find(initiative_id).editing_locked).to be true
- end
- end
-
- context 'when the the status change is to the changes_requested status' do
- let(:new_initiative) { create(:initiative) }
- let!(:_initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: new_initiative,
- initiative_status: @status_changes_requested
- )
- end
-
- let(:initiative_id) { new_initiative.id }
- let(:initiative_status_id) { @status_review_pending.id }
-
- example 'creation of status change record' do
- expect(Initiative.find(initiative_id).editing_locked).to be false
-
- # does not result in the logging of an Initiative 'proposed' activity
- expect { do_request }
- .not_to have_enqueued_job(LogActivityJob)
- .with(instance_of(Initiative), 'proposed', anything, anything)
- assert_status 201
- # does not result in locked editing
- expect(Initiative.find(initiative_id).editing_locked).to be false
- end
- end
- end
- end
-
- context 'when resident' do
- before do
- resident_header_token
-
- @status_proposed = create(:initiative_status_proposed)
- @status_expired = create(:initiative_status_expired)
- @status_threshold_reached = create(:initiative_status_threshold_reached)
- @status_answered = create(:initiative_status_answered)
- @status_ineligible = create(:initiative_status_ineligible)
-
- create(
- :initiative_status_change,
- initiative: @initiative, initiative_status: @status_threshold_reached
- )
- end
-
- post 'web_api/v1/initiatives/:initiative_id/initiative_status_changes' do
- with_options scope: :initiative_status_change do
- parameter :initiative_status_id, 'The new initiative status', required: true
- parameter :user_id, 'The user who made the status change', required: false
- parameter :official_feedback_id, 'An existing official feedback can be used', required: false
- end
- with_options scope: %i[initiative_status_change official_feedback_attributes] do
- parameter :body_multiloc, 'Multi-locale field with the feedback body', required: false
- parameter :author_multiloc, 'Multi-locale field with describing the author', required: false
- end
- ValidationErrorHelper.new.error_fields(self, InitiativeStatusChange)
-
- let(:initiative_id) { @initiative.id }
- let(:initiative_status_id) { @status_answered.id }
- let(:feedback) { build(:official_feedback) }
- let(:body_multiloc) { feedback.body_multiloc }
- let(:author_multiloc) { feedback.author_multiloc }
-
- example_request '[error] Create an official feedback on an initiative' do
- expect(response_status).to eq 401
- end
- end
- end
-end
diff --git a/back/spec/acceptance/initiative_statuses_spec.rb b/back/spec/acceptance/initiative_statuses_spec.rb
deleted file mode 100644
index 1c873c524a4a..000000000000
--- a/back/spec/acceptance/initiative_statuses_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-# TODO: cleanup-after-proposals-migration
-resource 'InitiativeStatuses' do
- explanation 'Initivative statuses reflect the cities attitude towards an initiative.'
-
- before do
- header 'Content-Type', 'application/json'
- @statuses = create_list(:initiative_status, 3)
- end
-
- get 'web_api/v1/initiative_statuses' do
- example_request 'List all initiative statuses' do
- expect(status).to eq(200)
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 3
- expect(json_response[:data].pluck(:id)).to match_array @statuses.map(&:id)
- end
- end
-
- get 'web_api/v1/initiative_statuses/:id' do
- let(:id) { @statuses.first.id }
-
- example_request 'Get one initiative status by id' do
- expect(status).to eq 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :id)).to eq @statuses.first.id
- end
- end
-end
diff --git a/back/spec/acceptance/initiatives_spec.rb b/back/spec/acceptance/initiatives_spec.rb
deleted file mode 100644
index 509399a1c964..000000000000
--- a/back/spec/acceptance/initiatives_spec.rb
+++ /dev/null
@@ -1,796 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-resource 'Initiatives' do
- explanation 'Proposals from citizens (but more spontaneous than ideas) to the city.'
-
- before do
- header 'Content-Type', 'application/json'
- @first_admin = create(:admin)
- @initiatives = %w[published published draft published published published].map { |ps| create(:initiative, publication_status: ps, assignee: create(:admin)) }
- @user = create(:user)
- header_token_for @user
- end
-
- # TODO: cleanup-after-proposals-migration
- get 'web_api/v1/initiatives' do
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of initiatives per page'
- end
- parameter :author, 'Filter by author (user id)', required: false
- parameter :publication_status, 'Filter by publication status; returns all publlished initiatives by default', required: false
- parameter :topics, 'Filter by topics (OR)', required: false
- parameter :areas, 'Filter by areas (OR)', required: false
- parameter :initiative_status, 'Filter by status (initiative status id)', required: false
- parameter :assignee, 'Filter by assignee (user id)', required: false
- parameter :search, 'Filter by searching in title and body', required: false
- parameter :feedback_needed, 'Filter out initiatives that need feedback', required: false
- parameter :sort, "Either 'trending' (default), 'new', '-new', 'author_name', '-author_name', 'likes_count', '-likes_count', 'status', '-status', 'random'", required: false
-
- example_request 'List all published initiatives (default behaviour)' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 5
- expect(json_response[:data].map { |d| d.dig(:attributes, :publication_status) }).to all(eq 'published')
- end
-
- example "Don't list drafts (default behaviour)", document: false do
- do_request publication_status: 'draft'
-
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 0
- end
-
- example 'List all initiatives which match one of the given topics', document: false do
- t1 = create(:topic)
- t2 = create(:topic)
-
- i1 = @initiatives[0]
- i1.topics = [t1]
- i1.save
- i2 = @initiatives[1]
- i2.topics = [t2]
- i2.save
-
- do_request topics: [t1.id, t2.id]
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- expect(json_response[:data].pluck(:id)).to match_array [i1.id, i2.id]
- end
-
- example 'List all initiatives which match one of the given areas', document: false do
- a1 = create(:area)
- a2 = create(:area)
-
- i1 = @initiatives.first
- i1.areas = [a1]
- i1.save
- i2 = @initiatives.second
- i2.areas = [a2]
- i2.save
-
- do_request areas: [a1.id, a2.id]
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 2
- expect(json_response[:data].pluck(:id)).to match_array [i1.id, i2.id]
- end
-
- example 'List all initiatives for a user' do
- u = create(:user)
- i = create(:initiative, author: u)
-
- do_request author: u.id
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 1
- expect(json_response[:data][0][:id]).to eq i.id
- end
-
- example 'List all initiatives for an initiative status', document: false do
- status = create(:initiative_status)
- i = create(:initiative, initiative_status: status)
-
- do_request initiative_status: status.id
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 1
- expect(json_response[:data][0][:id]).to eq i.id
- end
-
- example 'List all initiatives for an assignee', document: false do
- a = create(:admin)
- i = create(:initiative, assignee: a)
-
- do_request assignee: a.id
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 1
- expect(json_response[:data][0][:id]).to eq i.id
- end
-
- example 'List all unassigned initiatives' do
- create(:initiative, assignee: create(:admin))
- initiatives = create_list(:initiative, 2, assignee: nil)
-
- do_request assignee: 'unassigned'
-
- assert_status 200
- json_response = json_parse response_body
- expect(json_response[:data].size).to eq 2
- expect(json_response[:data].pluck(:id)).to match_array initiatives.map(&:id)
- end
-
- example 'List all initiatives that need feedback', document: false do
- threshold_reached = create(:initiative_status_threshold_reached)
- i = create(:initiative, initiative_status: threshold_reached)
-
- do_request feedback_needed: true
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 1
- expect(json_response[:data][0][:id]).to eq i.id
- end
-
- example 'Search for initiatives', document: false do
- create(:user)
- initiatives = [
- create(:initiative, title_multiloc: { en: 'This initiative is uniqque' }),
- create(:initiative, title_multiloc: { en: 'This one origiinal' })
- ]
-
- do_request search: 'uniqque'
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 1
- expect(json_response[:data][0][:id]).to eq initiatives[0].id
- end
-
- example 'List all initiatives sorted by new', document: false do
- create(:user)
- i1 = create(:initiative)
-
- do_request sort: 'new'
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 6
- expect(json_response[:data][0][:id]).to eq i1.id
- end
-
- example 'List all initiatives by random ordering', document: false do
- create(:user)
- create(:initiative)
-
- do_request sort: 'random'
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 6
- end
-
- example 'List all initiatives includes the user_reaction and user_follower', document: false do
- initiative = create(:initiative)
- reaction = create(:reaction, reactable: initiative, user: @user)
- follower = create(:follower, followable: create(:initiative), user: @user)
-
- do_request
- json_response = json_parse(response_body)
- expect(json_response[:data].filter_map { |d| d.dig(:relationships, :user_reaction, :data, :id) }.first).to eq reaction.id
- expect(json_response[:data].filter_map { |d| d.dig(:relationships, :user_follower, :data, :id) }.first).to eq follower.id
- expect(json_response[:included].pluck(:id)).to include reaction.id
- end
- end
-
- # TODO: cleanup-after-proposals-migration
- get 'web_api/v1/initiatives/as_markers' do
- before do
- locations = [[51.044039, 3.716964], [50.845552, 4.357355], [50.640255, 5.571848], [50.950772, 4.308304], [51.215929, 4.422602], [50.453848, 3.952217], [-27.148983, -109.424659]]
- placenames = ['Ghent', 'Brussels', 'Liège', 'Meise', 'Antwerp', 'Mons', 'Hanga Roa']
- @initiatives.each do |i|
- i.location_point_geojson = { 'type' => 'Point', 'coordinates' => locations.pop }
- i.title_multiloc['en'] = placenames.pop
- i.publication_status = 'published'
- i.save!
- end
- end
-
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of initiatives per page'
- end
- parameter :author, 'Filter by author (user id)', required: false
- parameter :publication_status, 'Return only initiatives with the specified publication status; returns all pusblished initiatives by default', required: false
- parameter :bounding_box, 'Given an [x1,y1,x2,y2] array of doubles (x being latitude and y being longitude), the markers are filtered to only retain those within the (x1,y1)-(x2,y2) box.', required: false
- parameter :topics, 'Filter by topics (OR)', required: false
- parameter :areas, 'Filter by areas (OR)', required: false
- parameter :assignee, 'Filter by assignee (user id)', required: false
- parameter :search, 'Filter by searching in title and body', required: false
-
- example 'List all markers within a bounding box' do
- do_request(bounding_box: '[51.208758,3.224363,50.000667,5.715281]') # Bruges-Bastogne
-
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 4
- expect(json_response[:data].map { |d| d.dig(:attributes, :title_multiloc, :en) }.sort).to match %w[Brussels Liège Meise Mons].sort
- end
- end
-
- # TODO: move-old-proposals-test
- get 'web_api/v1/initiatives/as_xlsx' do
- before { admin_header_token }
-
- parameter :initiatives, 'Filter by a given list of initiative ids', required: false
-
- example_request 'XLSX export' do
- assert_status 200
- end
-
- describe do
- before do
- @selected_initiatives = @initiatives.select(&:published?).shuffle.take 2
- end
-
- let(:initiatives) { @selected_initiatives.map(&:id) }
-
- example_request 'XLSX export by initiative ids', document: false do
- assert_status 200
- worksheet = RubyXL::Parser.parse_buffer(response_body).worksheets[0]
- expect(worksheet.count).to eq(@selected_initiatives.size + 1)
- end
- end
-
- describe 'when resident' do
- before { resident_header_token }
-
- example '[error] XLSX export', document: false do
- do_request
- assert_status 401
- end
- end
- end
-
- # TODO: cleanup-after-proposals-migration
- get 'web_api/v1/initiatives/filter_counts' do
- before do
- Initiative.all.each(&:destroy!)
- @t1 = create(:topic)
- @t2 = create(:topic)
- @a1 = create(:area)
- @a2 = create(:area)
- @s1 = create(:initiative_status)
- @s2 = create(:initiative_status)
- @i1 = create(:initiative, topics: [@t1, @t2], areas: [@a1], initiative_status: @s1)
- @i2 = create(:initiative, topics: [@t1], areas: [@a1, @a2], initiative_status: @s2)
- @i3 = create(:initiative, topics: [@t2], areas: [], initiative_status: @s2)
- @i4 = create(:initiative, topics: [], areas: [@a1], initiative_status: @s2)
-
- # a1 -> 3
- # a2 -> 1
- # t1 -> 2
- # t2 -> 2
- # s1 -> 1
- # s2 -> 3
- end
-
- parameter :topics, 'Filter by topics (OR)', required: false
- parameter :areas, 'Filter by areas (OR)', required: false
- parameter :author, 'Filter by author (user id)', required: false
- parameter :assignee, 'Filter by assignee (user id)', required: false
- parameter :initiative_status, 'Filter by status (initiative status id)', required: false
- parameter :search, 'Filter by searching in title and body', required: false
- parameter :publication_status, 'Return only initiatives with the specified publication status; returns all pusblished initiatives by default', required: false
-
- example_request 'List initiative counts per filter option' do
- assert_status 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :type)).to eq 'filter_counts'
-
- expect(json_response.dig(:data, :attributes, :initiative_status_id)[@s1.id.to_sym]).to eq 1
- expect(json_response.dig(:data, :attributes, :initiative_status_id)[@s2.id.to_sym]).to eq 3
- expect(json_response.dig(:data, :attributes, :area_id)[@a1.id.to_sym]).to eq 3
- expect(json_response.dig(:data, :attributes, :area_id)[@a2.id.to_sym]).to eq 1
- expect(json_response.dig(:data, :attributes, :topic_id)[@t1.id.to_sym]).to eq 2
- expect(json_response.dig(:data, :attributes, :topic_id)[@t2.id.to_sym]).to eq 2
- expect(json_response.dig(:data, :attributes, :total)).to eq 4
- end
-
- example 'List initiative counts per filter option on topic', document: false do
- do_request topics: [@t1.id]
- assert_status 200
- end
-
- example 'List initiative counts per filter option on area', document: false do
- do_request areas: [@a1.id]
- assert_status 200
- end
-
- example 'List initiative counts when also using search filtering AND sort', document: false do
- do_request(search: 'uniqque', sort: 'new')
- assert_status 200
- end
- end
-
- get 'web_api/v1/initiatives/:id' do
- let(:initiative) { @initiatives.first }
- let(:id) { initiative.id }
-
- example_request 'Get one initiative by id' do
- assert_status 200
- expect(response_data[:id]).to eq initiative.id
- expect(response_data[:attributes]).to include(
- anonymous: false,
- author_hash: initiative.author_hash
- )
- end
- end
-
- get 'web_api/v1/initiatives/by_slug/:slug' do
- let(:slug) { @initiatives.first.slug }
-
- example_request 'Get one initiative by slug' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :id)).to eq @initiatives.first.id
- end
-
- describe do
- let(:slug) { 'unexisting-initiative' }
-
- example '[error] Get an unexisting initiative', document: false do
- do_request
- assert_status 404
- end
- end
- end
-
- # TODO: cleanup-after-proposals-migration
- post 'web_api/v1/initiatives' do
- before do
- create(:initiative_status, code: 'proposed')
- end
-
- with_options scope: :initiative do
- parameter :author_id, 'The user id of the user owning the initiative. This can only be specified by moderators and is inferred from the JWT token for residents.'
- parameter :publication_status, 'Publication status', required: true, extra: "One of #{Post::PUBLICATION_STATUSES.join(',')}"
- parameter :title_multiloc, 'Multi-locale field with the initiative title', required: true, extra: 'Maximum 100 characters'
- parameter :body_multiloc, 'Multi-locale field with the initiative body', extra: 'Required if not draft'
- parameter :location_point_geojson, 'A GeoJSON point that situates the location the initiative applies to'
- parameter :location_description, 'A human readable description of the location the initiative applies to'
- parameter :header_bg, 'Base64 encoded header image'
- parameter :topic_ids, 'Array of ids of the associated topics'
- parameter :area_ids, 'Array of ids of the associated areas'
- parameter :assignee_id, 'The user id of the admin that takes ownership. Set automatically if not provided. Only allowed for admins.'
- parameter :anonymous, 'Post this initiative anonymously - true/false'
- parameter :cosponsor_ids, 'Array of user ids of the desired cosponsors'
- end
- ValidationErrorHelper.new.error_fields(self, Initiative)
-
- let(:initiative) { build(:initiative) }
- let(:publication_status) { 'published' }
- let(:title_multiloc) { initiative.title_multiloc }
- let(:body_multiloc) { initiative.body_multiloc }
- let(:location_point_geojson) { { type: 'Point', coordinates: [51.11520776293035, 3.921154106874878] } }
- let(:location_description) { 'Stanley Road 4' }
- let(:header_bg) { file_as_base64 'header.jpg', 'image/jpeg' }
- let(:topic_ids) { create_list(:topic, 2).map(&:id) }
- let(:area_ids) { create_list(:area, 2).map(&:id) }
- let(:assignee_id) { create(:admin).id }
-
- describe do
- before do
- @user.add_role 'admin'
- @user.save!
- end
-
- example_request 'Create an initiative' do
- assert_status 201
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :location_point_geojson)).to eq location_point_geojson
- expect(json_response.dig(:data, :attributes, :location_description)).to eq location_description
- expect(json_response.dig(:data, :relationships, :topics, :data).pluck(:id)).to match_array topic_ids
- expect(json_response.dig(:data, :relationships, :areas, :data).pluck(:id)).to match_array area_ids
- expect(json_response.dig(:data, :relationships, :assignee, :data, :id)).to eq assignee_id
- end
-
- example 'Check for the automatic creation of a like by the author when an initiative is created', document: false do
- do_request
- json_response = json_parse(response_body)
- new_initiative = Initiative.find(json_response.dig(:data, :id))
- expect(new_initiative.reactions.size).to eq 1
- expect(new_initiative.reactions[0].mode).to eq 'up'
- expect(new_initiative.reactions[0].user.id).to eq @user.id
- expect(json_response[:data][:attributes][:likes_count]).to eq 1
- end
-
- example 'Check for the automatic assignement of the default assignee', document: false do
- do_request(initiative: { assignee_id: nil })
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :assignee, :data, :id)).to eq @first_admin.id
- end
- end
-
- example_group 'with permissions on phase' do
- let(:group) { create(:group) }
-
- before do
- Permissions::PermissionsUpdateService.new.update_global_permissions
- Permission.find_by(permission_scope: nil, action: 'posting_initiative')
- .update!(permitted_by: 'users', groups: [group])
- end
-
- example '[error] Not authorized to create an initiative', document: false do
- do_request
- assert_status 401
- end
-
- example 'Create an initiative (group permission)' do
- group.add_member(@user).save!
- do_request
- assert_status 201
- end
- end
-
- describe do
- before { SettingsService.new.activate_feature! 'blocking_profanity' }
-
- let(:title_multiloc) { { 'nl-BE' => 'Fuck' } }
- let(:body_multiloc) { { 'fr-FR' => 'Fuck' } }
-
- example_request '[error] Create an initiative with blocked words' do
- assert_status 422
- json_response = json_parse(response_body)
- title_multiloc_error = json_response
- .dig(:errors, :title_multiloc)&.select { |err| err[:error] == 'includes_banned_words' }
- body_multiloc_error = json_response
- .dig(:errors, :body_multiloc)&.select { |err| err[:error] == 'includes_banned_words' }
- expect(title_multiloc_error).to be_present
- expect(body_multiloc_error).to be_present
- end
- end
-
- describe 'anomymous posting of inititatives' do
- let(:allow_anonymous_participation) { true }
- let(:anonymous) { true }
-
- before do
- config = AppConfiguration.instance
- config.settings['initiatives']['allow_anonymous_participation'] = allow_anonymous_participation
- config.save!
- end
-
- example_request 'Create an anonymous initiative' do
- assert_status 201
- expect(response_data.dig(:relationships, :author, :data, :id)).to be_nil
- expect(response_data.dig(:attributes, :anonymous)).to be true
- expect(response_data.dig(:attributes, :author_name)).to be_nil
- end
-
- example 'Does not log activities for the author', document: false do
- expect { do_request }.not_to have_enqueued_job(LogActivityJob).with(anything, anything, @user, anything)
- end
-
- example 'Does not add the author as a follower of the initiative', document: false do
- expect { do_request }.not_to change(Follower, :count)
- initiative_id = response_data[:id]
- expect(Follower.where(followable_id: initiative_id, user: @user)).not_to exist
- end
-
- describe 'when anonymous posting is not allowed' do
- let(:allow_anonymous_participation) { false }
-
- example_request 'Rejects the anonymous parameter' do
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:base, 'anonymous_participation_not_allowed')
- end
- end
- end
-
- describe 'cosponsor_ids' do
- let(:cosponsor) { create(:user) }
- let(:cosponsor_ids) { [cosponsor.id] }
-
- example 'Update the cosponsors of an initiative' do
- expect { do_request }
- .to have_enqueued_job(LogActivityJob)
- .with(instance_of(CosponsorsInitiative), 'created', @user, instance_of(Integer))
- .exactly(1).times
-
- assert_status 201
- json_response = json_parse(response_body)
-
- expect(json_response.dig(:data, :relationships, :cosponsors, :data).pluck(:id)).to match_array cosponsor_ids
- end
- end
- end
-
- # TODO: cleanup-after-proposals-migration
- patch 'web_api/v1/initiatives/:id' do
- before do
- create(:initiative_status, code: 'proposed')
- @initiative = create(:initiative, author: @user)
- end
-
- with_options scope: :initiative do
- parameter :author_id, 'The user id of the user owning the initiative. This can only be specified by moderators and is inferred from the JWT token for residents.'
- parameter :publication_status, "Either #{Post::PUBLICATION_STATUSES.join(', ')}"
- parameter :title_multiloc, 'Multi-locale field with the initiative title', extra: 'Maximum 100 characters'
- parameter :body_multiloc, 'Multi-locale field with the initiative body', extra: 'Required if not draft'
- parameter :location_point_geojson, 'A GeoJSON point that situates the location the initiative applies to'
- parameter :location_description, 'A human readable description of the location the initiative applies to'
- parameter :header_bg, 'Base64 encoded header image'
- parameter :topic_ids, 'Array of ids of the associated topics'
- parameter :area_ids, 'Array of ids of the associated areas'
- parameter :assignee_id, 'The user id of the admin that takes ownership. Only allowed for admins.'
- parameter :anonymous, 'Post this initiative anonymously - true/false'
- parameter :cosponsor_ids, 'Array of user ids of the desired cosponsors'
- end
- ValidationErrorHelper.new.error_fields(self, Initiative)
-
- describe 'published initiatives' do
- let(:id) { @initiative.id }
- let(:location_point_geojson) { { type: 'Point', coordinates: [51.4365635, 3.825930459] } }
- let(:location_description) { 'Watkins Road 8' }
- let(:header_bg) { file_as_base64 'header.jpg', 'image/jpeg' }
- let(:topic_ids) { create_list(:topic, 2).map(&:id) }
- let(:area_ids) { create_list(:area, 2).map(&:id) }
-
- describe do
- let(:title_multiloc) { { 'en' => 'Changed title' } }
-
- example_request 'Update an initiative' do
- expect(status).to be 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :title_multiloc, :en)).to eq 'Changed title'
- expect(json_response.dig(:data, :attributes, :location_point_geojson)).to eq location_point_geojson
- expect(json_response.dig(:data, :attributes, :location_description)).to eq location_description
- expect(json_response.dig(:data, :relationships, :topics, :data).pluck(:id)).to match_array topic_ids
- expect(json_response.dig(:data, :relationships, :areas, :data).pluck(:id)).to match_array area_ids
- end
- end
-
- describe do
- let(:id) { @initiative.id }
- let(:header_bg) { file_as_base64 'header.jpg', 'image/jpeg' }
-
- example 'The header image can be updated and the file is present', document: false do
- do_request
- expect(@initiative.reload.header_bg_url).to be_present
- expect(@initiative.reload.header_bg.file).to be_present
- end
- end
-
- describe do
- let(:id) { @initiative.id }
-
- example 'The header image can be removed' do
- @initiative.update!(header_bg: Rails.root.join('spec/fixtures/header.jpg').open)
- expect(@initiative.reload.header_bg_url).to be_present
- do_request initiative: { header_bg: nil }
- expect(@initiative.reload.header_bg_url).to be_nil
- end
- end
-
- describe do
- let(:topic_ids) { [] }
- let(:area_ids) { [] }
-
- example 'Remove the topics/areas', document: false do
- @initiative.topics = create_list(:topic, 2)
- @initiative.areas = create_list(:area, 2)
- do_request
- expect(status).to be 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :topics, :data).pluck(:id)).to match_array topic_ids
- expect(json_response.dig(:data, :relationships, :areas, :data).pluck(:id)).to match_array area_ids
- end
- end
-
- describe do
- let(:assignee_id) { create(:admin).id }
-
- example 'Changing the assignee as a non-admin does not work', document: false do
- do_request
- expect(status).to be 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :relationships, :assignee)).to be_nil
- end
- end
-
- describe 'changing the author of my own initiative' do
- let(:author_id) { create(:admin).id }
-
- example '[Error] Cannot change the author from your own id as a non-admin', document: false do
- do_request
- expect(@initiative.reload.author_id).not_to eq author_id
- end
- end
-
- describe 'changing the author of another authors initiative' do
- let(:author_id) { @user.id }
-
- example '[Error] Cannot update another authors record to your own id as a non-admin', document: false do
- @initiative.update!(author: create(:user))
- do_request
- assert_status 401
- expect(json_response_body.dig(:errors, :base, 0, :error)).to eq 'Unauthorized!'
- end
- end
-
- describe 'updating anomymous initiatives' do
- let(:allow_anonymous_participation) { true }
- let(:anonymous) { true }
-
- before do
- config = AppConfiguration.instance
- config.settings['initiatives']['allow_anonymous_participation'] = allow_anonymous_participation
- config.save!
- end
-
- example_request 'Change a published initiative to anonymous' do
- assert_status 200
- expect(response_data.dig(:relationships, :author, :data, :id)).to be_nil
- expect(response_data.dig(:attributes, :anonymous)).to be true
- expect(response_data.dig(:attributes, :author_name)).to be_nil
- end
-
- example '[Error] Cannot update an anonymous initiative as a non-admin' do
- @initiative.update!(anonymous: true)
- do_request
- assert_status 401
- expect(json_response_body.dig(:errors, :base, 0, :error)).to eq 'Unauthorized!'
- end
-
- example 'Does not log activities for the author and clears the author from past activities', document: false do
- clear_activity = create(:activity, item: @initiative, user: @user)
- other_item_activity = create(:activity, item: @initiative, user: create(:user))
- other_user_activity = create(:activity, user: @user)
-
- expect { do_request }.not_to have_enqueued_job(LogActivityJob).with(anything, anything, @user, anything)
- expect(clear_activity.reload.user_id).to be_nil
- expect(other_item_activity.reload.user_id).to be_present
- expect(other_user_activity.reload.user_id).to eq @user.id
- end
-
- describe 'when anonymous posting is not allowed' do
- let(:allow_anonymous_participation) { false }
-
- example_request 'Rejects the anonymous parameter' do
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:base, 'anonymous_participation_not_allowed')
- end
- end
- end
- end
-
- describe 'draft initiatives' do
- before do
- @initiative = create(:initiative, author: @user, publication_status: 'draft')
- end
-
- parameter :publication_status, "Either #{Post::PUBLICATION_STATUSES.join(', ')}", required: true, scope: :initiative
-
- let(:id) { @initiative.id }
-
- describe 'updating anomymous initiatives' do
- let(:anonymous) { true }
-
- before do
- config = AppConfiguration.instance
- config.settings['initiatives']['allow_anonymous_participation'] = true
- config.save!
- end
-
- example_request 'Change a draft initiative to anonymous' do
- assert_status 200
- expect(response_data.dig(:relationships, :author, :data, :id)).to be_nil
- expect(response_data.dig(:attributes, :anonymous)).to be true
- expect(response_data.dig(:attributes, :author_name)).to be_nil
- end
- end
-
- describe 'publishing an initiative' do
- let(:publication_status) { 'published' }
-
- example_request 'Change the publication status' do
- assert_status 200
- expect(response_data.dig(:attributes, :publication_status)).to eq 'published'
- end
- end
-
- describe 'changing a draft initiative of another user' do
- let(:title_multiloc) { { 'en' => 'Changed title' } }
-
- example '[Error] Cannot update an anonymous initiative as a non-admin' do
- @initiative.update!(author: create(:user))
- do_request
- assert_status 401
- expect(json_response_body.dig(:errors, :base, 0, :error)).to eq 'Unauthorized!'
- end
- end
-
- describe 'cosponsor_ids' do
- let(:id) { @initiative.id }
- let(:cosponsor) { create(:user) }
- let(:cosponsor_ids) { [cosponsor.id] }
-
- example 'Update the cosponsors of an initiative' do
- expect { do_request }
- .to have_enqueued_job(LogActivityJob)
- .with(instance_of(CosponsorsInitiative), 'created', @user, instance_of(Integer))
- .exactly(1).times
-
- assert_status 200
- json_response = json_parse(response_body)
-
- expect(json_response.dig(:data, :relationships, :cosponsors, :data).pluck(:id)).to match_array cosponsor_ids
- end
- end
- end
- end
-
- # TODO: move-old-proposals-test
- patch 'web_api/v1/initiatives/:id/accept_cosponsorship_invite' do
- before do
- @initiative = create(:initiative)
- @cosponsors_initiative = create(:cosponsors_initiative, initiative: @initiative, user: @user)
- end
-
- describe 'for initiative with associated cosponsor' do
- let(:id) { @initiative.id }
-
- example 'cosponsor accepts invitation' do
- expect { do_request }.to change { @cosponsors_initiative.reload.status }.from('pending').to('accepted')
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :slug)).to eq @initiative.slug
- end
- end
- end
-
- # TODO: cleanup-after-proposals-migration
- delete 'web_api/v1/initiatives/:id' do
- before do
- @initiative = create(:initiative_with_topics, author: @user, publication_status: 'published')
- end
-
- let(:id) { @initiative.id }
-
- example_request 'Delete an initiative' do
- assert_status 200
- expect { Initiative.find(id) }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- # TODO: cleanup-after-proposals-migration
- get 'web_api/v1/initiatives/:id/allowed_transitions' do
- before do
- admin_header_token
-
- @initiative = create(:initiative)
- threshold_reached = create(:initiative_status_threshold_reached)
- create(
- :initiative_status_change,
- initiative: @initiative, initiative_status: threshold_reached
- )
- end
-
- let(:id) { @initiative.id }
-
- example_request 'Allowed transitions' do
- assert_status 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :type)).to eq 'allowed_transitions'
- expect(json_response).to eq({
- data: {
- type: 'allowed_transitions',
- attributes: {
- **InitiativeStatus.where(code: 'answered').ids.to_h do |id|
- [id.to_sym, { feedback_required: true }]
- end,
- **InitiativeStatus.where(code: 'ineligible').ids.to_h do |id|
- [id.to_sym, { feedback_required: true }]
- end
- }
- }
- })
- end
- end
-end
diff --git a/back/spec/acceptance/internal_comments_spec.rb b/back/spec/acceptance/internal_comments_spec.rb
index 38db842df0d6..5387810b3ec4 100644
--- a/back/spec/acceptance/internal_comments_spec.rb
+++ b/back/spec/acceptance/internal_comments_spec.rb
@@ -294,277 +294,4 @@
end
end
end
-
- # TODO: cleanup-after-proposals-migration
- context 'when internal comments are on an initiative' do
- before { @initiative = create(:initiative) }
-
- context 'when an authenticated regular user' do
- before do
- @user = create(:user)
- header_token_for @user
- end
-
- post 'web_api/v1/initiatives/:initiative_id/internal_comments' do
- with_options scope: :internal_comment do
- parameter :body, 'Text field with the comment body', required: true
- parameter :parent_id, 'The id of the comment this comment is a response to', required: false
- end
-
- let(:initiative_id) { @initiative.id }
- let(:internal_comment) { build(:internal_comment) }
- let(:body) { internal_comment.body }
-
- example_request '[Unauthorized] Create an internal comment on an initiative' do
- assert_status 401
- json_response = json_parse(response_body)
-
- expect(json_response.dig(:errors, :base)[0][:error]).to eq 'Unauthorized!'
- expect(@initiative.reload.internal_comments_count).to eq 0
- end
- end
- end
-
- context 'when an authenticated admin' do
- before do
- @user = create(:admin)
- header_token_for @user
- end
-
- get 'web_api/v1/internal_comments/:id' do
- let(:initiative) { create(:initiative) }
- let(:parent) { create(:internal_comment, post: initiative) }
- let(:internal_comment) { create(:internal_comment, parent: parent, post: initiative) }
- let(:id) { internal_comment.id }
-
- example_request 'Get one internal comment by id' do
- assert_status 200
- json_response = json_parse(response_body)
-
- expect(json_response.dig(:data, :id)).to eq id
- expect(json_response.dig(:data, :type)).to eq 'internal_comment'
- expect(json_response.dig(:data, :attributes)).to include(publication_status: 'published')
- expect(json_response.dig(:data, :relationships)).to include(
- post: {
- data: { id: internal_comment.post_id, type: 'initiative' }
- },
- author: {
- data: { id: internal_comment.author_id, type: 'user' }
- },
- parent: {
- data: { id: parent.id, type: 'internal_comment' }
- }
- )
- expect(json_response.dig(:included, 0, :attributes)).to include(
- first_name: internal_comment.author.first_name,
- locale: internal_comment.author.locale
- )
- end
- end
-
- get 'web_api/v1/initiatives/:initiative_id/internal_comments' do
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of top-level comments per page. The response will include 2 to 5 child comments per top-level comment, so expect to receive more'
- end
- parameter :sort, 'Either new or -new. Defaults to -new. Only applies to the top-level comments, children are always returned chronologically.'
-
- describe do
- before do
- @c1 = create(:internal_comment, post: @initiative)
- @c2 = create(:internal_comment, post: @initiative)
- @c1sub1 = create(:internal_comment, parent: @c2, post: @initiative)
- @c1sub2 = create(:internal_comment, parent: @c2, post: @initiative)
- @c1sub3 = create(:internal_comment, parent: @c2, post: @initiative)
- @c1sub4 = create(:internal_comment, parent: @c2, post: @initiative)
- @c1sub5 = create(:internal_comment, parent: @c2, post: @initiative)
- @c3 = create(:internal_comment, post: @initiative)
- @c3sub1 = create(:internal_comment, parent: @c3, post: @initiative)
- @c3sub2 = create(:internal_comment, parent: @c3, post: @initiative)
- @c3sub3 = create(:internal_comment, parent: @c3, post: @initiative)
- @c3sub4 = create(:internal_comment, parent: @c3, post: @initiative)
- @c3sub5 = create(:internal_comment, parent: @c3, post: @initiative)
- @c3sub6 = create(:internal_comment, parent: @c3, post: @initiative)
- @c4 = create(:internal_comment, post: @initiative)
- @c4sub1 = create(:internal_comment, parent: @c4, post: @initiative)
- end
-
- let(:initiative_id) { @initiative.id }
- let(:size) { 3 }
-
- example_request 'List the top-level internal comments of an initiative' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 10
- expect(json_response[:data].pluck(:id)).to eq([
- @c1,
- @c2,
- @c1sub1,
- @c1sub2,
- @c1sub3,
- @c1sub4,
- @c1sub5,
- @c3,
- @c3sub5,
- @c3sub6
- ].map(&:id))
- expect(json_response[:links][:next]).to be_present
- end
- end
-
- describe do
- let(:initiative_id) { @initiative.id }
- let(:sort) { '-new' }
-
- before do
- @c1 = create(:internal_comment, post: @initiative, created_at: 1.day.ago)
- @c2 = create(:internal_comment, post: @initiative, created_at: 2.days.ago)
- @c3 = create(:internal_comment, post: @initiative, created_at: 3.days.ago)
- @c2sub1, @c2sub2 = create_list(:internal_comment, 2, parent: @c2, post: @initiative)
- end
-
- example_request 'List the top-level internal comments of an initiative sorted by age, with oldest first' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 5
- expect(json_response[:data].pluck(:id)).to eq([
- @c3,
- @c2,
- @c2sub1,
- @c2sub2,
- @c1
- ].map(&:id))
- end
- end
- end
-
- get 'web_api/v1/internal_comments/:internal_comment_id/children' do
- explanation 'Children are always returned chronologically'
- with_options scope: :page do
- parameter :number, 'Page number'
- parameter :size, 'Number of internal comments per page'
- end
-
- describe do
- before do
- @c = create(:internal_comment, post: @initiative)
- @csub1 = create(:internal_comment, parent: @c, post: @initiative)
- @csub2 = create(:internal_comment, parent: @c, post: @initiative)
- @csub3 = create(:internal_comment, parent: @c, post: @initiative)
- @csub4 = create(:internal_comment, parent: @c, post: @initiative)
- @csub5 = create(:internal_comment, parent: @c, post: @initiative)
- @csub6 = create(:internal_comment, parent: @c, post: @initiative)
- @c2 = create(:internal_comment, post: @initiative)
- end
-
- let(:internal_comment_id) { @c.id }
-
- example_request 'List the direct child internal comments of an internal comment on an initiative' do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response[:data].size).to eq 6
- expect(json_response[:data].pluck(:id)).to eq([
- @csub1,
- @csub2,
- @csub3,
- @csub4,
- @csub5,
- @csub6
- ].map(&:id))
- end
- end
- end
-
- post 'web_api/v1/initiatives/:initiative_id/internal_comments' do
- with_options scope: :internal_comment do
- parameter :body, 'Text field with the comment body', required: true
- parameter :parent_id, 'The id of the comment this comment is a response to', required: false
- end
-
- let(:initiative_id) { @initiative.id }
- let(:internal_comment) { build(:internal_comment) }
- let(:body) { internal_comment.body }
-
- example_request 'Create an internal comment on an initiative' do
- assert_status 201
- json_response = json_parse(response_body)
-
- expect(json_response.dig(:data, :relationships, :author, :data, :id)).to eq @user.id
- expect(json_response.dig(:data, :attributes, :body)).to match body
- expect(json_response.dig(:data, :relationships, :parent, :data)).to be_nil
- expect(json_response.dig(:data, :relationships, :post, :data, :id)).to eq initiative_id
- expect(@initiative.reload.internal_comments_count).to eq 1
- end
-
- describe do
- let(:parent_id) { create(:internal_comment, post: @initiative).id }
-
- example_request 'Create an internal comment on an internal comment' do
- assert_status 201
- json_response = json_parse(response_body)
-
- expect(json_response.dig(:data, :relationships, :author, :data, :id)).to eq @user.id
- expect(json_response.dig(:data, :attributes, :body)).to match body
- expect(json_response.dig(:data, :relationships, :parent, :data, :id)).to eq parent_id
- expect(json_response.dig(:data, :relationships, :post, :data, :id)).to eq initiative_id
- expect(@initiative.reload.internal_comments_count).to eq 2
- end
- end
-
- describe do
- let(:body) { '' }
-
- example_request '[error] Create an invalid internal comment' do
- assert_status 422
- json_response = json_parse response_body
- expect(json_response).to include_response_error(:body, 'blank')
- end
- end
- end
-
- patch 'web_api/v1/internal_comments/:id' do
- with_options scope: :internal_comment do
- parameter :body, 'Text field with the comment body'
- parameter :parent_id, 'The id of the internal comment this internal comment is a response to'
- end
-
- let(:internal_comment) { create(:internal_comment, author: @user, post: @initiative) }
- let(:id) { internal_comment.id }
- let(:body) { "His hair is not blond, it's orange. Get your facts straight!" }
-
- example_request "Update author's own internal comment on an initiative" do
- assert_status 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :body)).to match body
- expect(@initiative.reload.internal_comments_count).to eq 1
- end
-
- example "[Unauthorized] Update other admin's internal comment on an initiative" do
- internal_comment.update!(author: create(:admin))
-
- do_request
- assert_status 401
- expect(@initiative.reload.internal_comments_count).to eq 1
- end
- end
-
- patch 'web_api/v1/internal_comments/:id/mark_as_deleted' do
- let(:internal_comment) { create(:internal_comment, author: @user, post: @initiative) }
- let(:id) { internal_comment.id }
-
- example_request "Author marks their own internal comment as 'deleted'" do
- assert_status 204
- expect(internal_comment.reload.publication_status).to eq('deleted')
- end
-
- example "[Unauthorized] Admin (not author) marks an internal comment on an initiative as 'deleted'" do
- internal_comment.update!(author: create(:admin))
-
- do_request
- assert_status 401
- expect(internal_comment.reload.publication_status).to eq('published')
- end
- end
- end
- end
end
diff --git a/back/spec/acceptance/permissions_spec.rb b/back/spec/acceptance/permissions_spec.rb
index c3689c4e190e..102d6392885d 100644
--- a/back/spec/acceptance/permissions_spec.rb
+++ b/back/spec/acceptance/permissions_spec.rb
@@ -91,7 +91,7 @@
example_request 'List all global permissions' do
assert_status 200
- expect(response_data.size).to eq 6
+ expect(response_data.size).to eq 3
expect(response_data.map { |d| d.dig(:attributes, :action) }).to match_array Permission.available_actions(nil)
end
end
@@ -123,9 +123,8 @@
end
end
- # TODO: posting_initiative
get 'web_api/v1/permissions/:action' do
- let(:action) { 'posting_initiative' }
+ let(:action) { 'attending_event' }
example_request 'Get one global permission by action' do
assert_status 200
@@ -198,7 +197,6 @@
end
end
- # TODO: posting_initiative
patch 'web_api/v1/permissions/:action' do
with_options scope: :permission do
parameter :permitted_by, "Defines who is granted permission, either #{Permission::PERMITTED_BIES.join(',')}.", required: false
@@ -207,7 +205,7 @@
end
ValidationErrorHelper.new.error_fields(self, Permission)
- let(:action) { 'reacting_initiative' }
+ let(:action) { 'attending_event' }
let(:permitted_by) { 'users' }
let(:group_ids) { create_list(:group, 3).map(&:id) }
diff --git a/back/spec/acceptance/stats_initiatives_spec.rb b/back/spec/acceptance/stats_initiatives_spec.rb
deleted file mode 100644
index 46dff56278da..000000000000
--- a/back/spec/acceptance/stats_initiatives_spec.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'rspec_api_documentation/dsl'
-
-def time_boundary_parameters(s)
- s.parameter :start_at, 'Date defining from where results should start', required: false
- s.parameter :end_at, 'Date defining till when results should go', required: false
-end
-
-def time_series_parameters(s)
- time_boundary_parameters s
- s.parameter :interval, 'Either day, week, month, year', required: true
-end
-
-def group_filter_parameter(s)
- s.parameter :group, 'Group ID. Only count initiatives posted by users in the given group', required: false
-end
-
-def topic_filter_parameter(s)
- s.parameter :topic, 'Topic ID. Only count initiatives that have the given topic assigned', required: false
-end
-
-def feedback_needed_filter_parameter(s)
- s.parameter :feedback_needed, 'Only count initiatives that need feedback', required: false
-end
-
-# TODO: cleanup-after-proposals-migration
-resource 'Stats - Initiatives' do
- explanation 'The various stats endpoints can be used to show certain properties of initiatives.'
- header 'Content-Type', 'application/json'
-
- let_it_be(:now) { AppConfiguration.timezone.now }
-
- before { admin_header_token }
-
- before_all do
- AppConfiguration.instance.update!(created_at: now - 3.years)
-
- @threshold_reached = create(:initiative_status, code: 'threshold_reached')
- @initiatives_with_topics = []
- @initiatives_with_areas = []
-
- begin_of_last_year = AppConfiguration.timezone.now.beginning_of_year - 1.year
-
- travel_to(begin_of_last_year - 1.month) do
- i = create(:initiative, initiative_status: @threshold_reached)
- create(:official_feedback, post: i)
- end
-
- travel_to(begin_of_last_year + 2.months) do
- @initiatives_with_topics += create_list(:initiative_with_topics, 2, initiative_status: @threshold_reached)
- @initiatives_with_areas += create_list(:initiative_with_areas, 3, initiative_status: @threshold_reached)
- end
-
- travel_to(begin_of_last_year + 5.months) do
- @initiatives_with_topics += create_list(:initiative_with_topics, 3, initiative_status: @threshold_reached)
- @initiatives_with_areas += create_list(:initiative_with_areas, 2, initiative_status: @threshold_reached)
- create(:initiative, initiative_status: @threshold_reached)
- end
- end
-
- get 'web_api/v1/stats/initiatives_count' do
- time_boundary_parameters self
- group_filter_parameter self
- topic_filter_parameter self
- feedback_needed_filter_parameter self
-
- example_request 'Count all initiatives' do
- assert_status 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :type)).to eq 'initiatives_count'
- expect(json_response.dig(:data, :attributes, :count)).to eq Initiative.published.count
- end
-
- describe 'with feedback_needed filter' do
- let(:feedback_needed) { true }
-
- example_request 'Count all initiatives that need feedback' do
- assert_status 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :type)).to eq 'initiatives_count'
- expect(json_response.dig(:data, :attributes, :count)).to eq Initiative.published.count
- end
-
- example 'Count all initiatives that need feedback for a specific assignee' do
- assignee = create(:admin)
- create(:initiative, initiative_status: @threshold_reached, assignee: assignee)
- do_request assignee: assignee.id
-
- assert_status 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :type)).to eq 'initiatives_count'
- expect(json_response.dig(:data, :attributes, :count)).to eq 1
- end
- end
- end
-end
diff --git a/back/spec/acceptance/user_comments_spec.rb b/back/spec/acceptance/user_comments_spec.rb
index 58072113a124..cf099a8e693a 100644
--- a/back/spec/acceptance/user_comments_spec.rb
+++ b/back/spec/acceptance/user_comments_spec.rb
@@ -21,7 +21,7 @@
describe do
before do
@i1 = create(:idea, published_at: Time.zone.now)
- @i2 = create(:initiative, published_at: 1.day.ago)
+ @i2 = create(:idea, published_at: 1.day.ago)
@i3 = create(:idea, published_at: 3.days.ago)
@user = create(:user)
@c1 = create(:comment, post: @i2, author: @user, created_at: 1.hour.ago)
@@ -35,7 +35,6 @@
let(:user_id) { @user.id }
let(:size) { 2 }
- # TODO: posting_initiative
example_request 'List the comments of a user' do
expect(status).to eq(200)
json_response = json_parse(response_body)
diff --git a/back/spec/acceptance/users_spec.rb b/back/spec/acceptance/users_spec.rb
index e1a08f72435a..16592f2e9819 100644
--- a/back/spec/acceptance/users_spec.rb
+++ b/back/spec/acceptance/users_spec.rb
@@ -1439,31 +1439,15 @@
end
end
- # TODO: cleanup-after-proposals-migration
- get 'web_api/v1/users/:id/initiatives_count' do
- let(:id) { @user.id }
-
- example 'Get the number of initiatives published by one user' do
- create(:initiative, author: @user)
- create(:initiative)
- create(:initiative, author: @user, publication_status: 'draft')
- do_request
- assert_status 200
- json_response = json_parse response_body
- expect(json_response.dig(:data, :type)).to eq 'initiatives_count'
- expect(json_response.dig(:data, :attributes, :count)).to eq 1
- end
- end
-
get 'web_api/v1/users/:id/comments_count' do
parameter :post_type, "Count only comments of one post type. Either 'Idea' or 'Initiative'.", required: false
let(:id) { @user.id }
example 'Get the number of comments posted by one user' do
- create(:comment, author: @user, post: create(:initiative))
create(:comment)
create(:comment, author: @user, post: create(:idea))
+ create(:comment, author: @user, post: create(:idea))
create(:comment, author: @user, publication_status: 'deleted')
do_request
expect(status).to eq 200
@@ -1471,6 +1455,8 @@
expect(json_response.dig(:data, :attributes, :count)).to eq 2
end
+ # TODO: cleanup-after-proposals-migration
+ # This test won't make sense once Comment.post_type is removed
example 'Get the number of comments on ideas posted by one user' do
create(:comment, author: @user, post: create(:initiative))
create(:comment, post: create(:initiative))
@@ -1482,19 +1468,6 @@
json_response = json_parse(response_body)
expect(json_response.dig(:data, :attributes, :count)).to eq 2
end
-
- # TODO: cleanup-after-proposals-migration
- example 'Get the number of comments on initiatives posted by one user' do
- create(:comment, author: @user, post: create(:initiative))
- create(:comment, author: @user, post: create(:initiative))
- create(:comment, post: create(:idea))
- create(:comment, author: @user, post: create(:idea))
- create(:comment, author: @user, publication_status: 'deleted', post: create(:initiative))
- do_request post_type: 'Initiative'
- expect(status).to eq 200
- json_response = json_parse(response_body)
- expect(json_response.dig(:data, :attributes, :count)).to eq 2
- end
end
end
end
diff --git a/back/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index 8ed70d4f7e65..214142f814c3 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -31,12 +31,6 @@
association :post, factory: :idea
end
- factory :cosponsor_of_your_initiative, parent: :notification, class: 'Notifications::CosponsorOfYourInitiative' do
- association :post, factory: :initiative
- cosponsors_initiative
- initiating_user
- end
-
factory :cosponsor_of_your_idea, parent: :notification, class: 'Notifications::CosponsorOfYourIdea' do
association :post, factory: :idea
cosponsorship
@@ -67,30 +61,6 @@
association :post, factory: :idea
end
- factory :internal_comment_on_initiative_assigned_to_you,
- parent: :notification,
- class: 'Notifications::InternalComments::InternalCommentOnInitiativeAssignedToYou' do
- initiating_user
- internal_comment
- association :post, factory: :initiative
- end
-
- factory :internal_comment_on_initiative_you_commented_internally_on,
- parent: :notification,
- class: 'Notifications::InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn' do
- initiating_user
- internal_comment
- association :post, factory: :initiative
- end
-
- factory :internal_comment_on_unassigned_initiative,
- parent: :notification,
- class: 'Notifications::InternalComments::InternalCommentOnUnassignedInitiative' do
- initiating_user
- internal_comment
- association :post, factory: :initiative
- end
-
factory :internal_comment_on_unassigned_unmoderated_idea,
parent: :notification,
class: 'Notifications::InternalComments::InternalCommentOnUnassignedUnmoderatedIdea' do
@@ -114,39 +84,17 @@
initiating_user
end
- factory :initiative_assigned_to_you, parent: :notification, class: 'Notifications::InitiativeAssignedToYou' do
- initiating_user
- association :post, factory: :initiative
- end
-
- factory :initiative_marked_as_spam, parent: :notification, class: 'Notifications::InitiativeMarkedAsSpam' do
- association :post, factory: :initiative
- spam_report
- initiating_user
- end
-
factory :invite_accepted, parent: :notification, class: 'Notifications::InviteAccepted' do
initiating_user
invite
end
- factory :invitation_to_cosponsor_initiative, parent: :notification, class: 'Notifications::InvitationToCosponsorInitiative' do
- association :post, factory: :initiative
- cosponsors_initiative
- initiating_user
- end
-
factory :invitation_to_cosponsor_idea, parent: :notification, class: 'Notifications::InvitationToCosponsorIdea' do
association :post, factory: :idea
cosponsorship
initiating_user
end
- factory :initiative_resubmitted_for_review, parent: :notification, class: 'Notifications::InitiativeResubmittedForReview' do
- association :post, factory: :initiative
- association :post_status, factory: :initiative_status, code: 'review_pending'
- end
-
factory :comment_on_idea_you_follow, parent: :notification, class: 'Notifications::CommentOnIdeaYouFollow' do
initiating_user
comment
@@ -154,12 +102,6 @@
project
end
- factory :comment_on_initiative_you_follow, parent: :notification, class: 'Notifications::CommentOnInitiativeYouFollow' do
- initiating_user
- comment
- association :post, factory: :initiative
- end
-
factory :mention_in_comment, parent: :notification, class: 'Notifications::MentionInComment' do
initiating_user
comment
@@ -185,12 +127,6 @@
project
end
- factory :official_feedback_on_initiative_you_follow, parent: :notification, class: 'Notifications::OfficialFeedbackOnInitiativeYouFollow' do
- initiating_user
- official_feedback
- association :post, factory: :initiative
- end
-
factory :project_folder_moderation_rights_received, parent: :notification, class: 'Notifications::ProjectFolderModerationRightsReceived' do
initiating_user
project_folder
@@ -236,16 +172,8 @@
end
end
- factory :status_change_on_initiative_you_follow, parent: :notification, class: 'Notifications::StatusChangeOnInitiativeYouFollow' do
- association :post, factory: :initiative
- association :post_status, factory: :initiative_status
- before(:create) do |notification|
- notification.post.initiative_status_changes.create!(initiative_status: notification.post_status)
- end
- end
-
factory :threshold_reached_for_admin, parent: :notification, class: 'Notifications::ThresholdReachedForAdmin' do
- association :post, factory: :initiative
+ association :post, factory: :idea
association :post_status, factory: :proposals_status
end
diff --git a/back/spec/finders/initiatives_finder_spec.rb b/back/spec/finders/initiatives_finder_spec.rb
deleted file mode 100644
index aa4990b2041e..000000000000
--- a/back/spec/finders/initiatives_finder_spec.rb
+++ /dev/null
@@ -1,195 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-describe InitiativesFinder do
- subject(:finder) { described_class.new(params, **options) }
-
- let(:record_ids) { finder.find_records.pluck(:id) }
- let(:options) { {} }
- let(:params) { {} }
-
- before { create_list(:initiative, 3, assignee: create(:admin)) }
-
- context 'without passing params' do
- it 'returns all initiatives' do
- expect(finder.find_records.count).to eq Initiative.count
- end
- end
-
- describe '#find_records' do
- let(:normal_user) { create(:user) }
-
- let(:options) do
- {
- scope: InitiativePolicy::Scope.new(normal_user, Initiative).resolve
- }
- end
-
- before do
- users = User.all
- Initiative.first.cosponsors << users[0]
- Initiative.first.cosponsors << users[1]
- end
-
- it 'does not return duplicate records' do
- expect(record_ids).to match_array Initiative.all.pluck(:id).uniq
- end
- end
-
- describe '#topics_condition' do
- let(:topic_ids) { Topic.limit(3).pluck(:id) }
-
- before do
- params[:topics] = topic_ids
- end
-
- it 'filters by topics' do
- expect(record_ids).to match_array Initiative.with_some_topics(topic_ids)
- end
- end
-
- describe '#areas_condition' do
- let(:area_ids) { Area.limit(3).pluck(:id) }
-
- before do
- params[:areas] = area_ids
- end
-
- it 'filters by areas' do
- expect(record_ids).to match_array Initiative.with_some_areas(area_ids)
- end
- end
-
- describe '#initiative_status_condition' do
- let(:initiative_status_id) { InitiativeStatus.first.id }
-
- before do
- params[:initiative_status] = initiative_status_id
- end
-
- it 'filters by initiative_status' do
- filtered_ids = Initiative
- .left_outer_joins(:initiative_initiative_status)
- .where(initiative_initiative_statuses: { initiative_status_id: initiative_status_id })
- .pluck(:id)
- expect(record_ids).to match_array filtered_ids
- end
- end
-
- describe '#assignee_condition' do
- let(:assignee) { create(:admin) }
- let!(:unassigned_initiatives) { create_list(:initiative, 2, assignee: nil) }
- let!(:assigned_initiatives) { create_list(:initiative, 3, assignee: assignee) }
-
- describe 'filtering on an assignee ID' do
- let(:params) { { assignee: assignee.id } }
-
- it 'returns the correct records' do
- expect(record_ids).to match_array assigned_initiatives.map(&:id)
- end
- end
-
- describe 'filtering on unassigned' do
- let(:params) { { assignee: 'unassigned' } }
-
- it 'returns the correct records' do
- expect(record_ids).to match_array unassigned_initiatives.map(&:id)
- end
- end
- end
-
- describe '#feedback_needed_condition' do
- let(:initiative_status) { create(:initiative_status) }
- let(:feedback_needed_initiative_status) { create(:initiative_status, code: 'threshold_reached') }
-
- context 'when true' do
- before do
- create(:initiative, initiative_status: initiative_status)
- create(:initiative, initiative_status: feedback_needed_initiative_status)
- params[:feedback_needed] = true
- end
-
- it 'filters by feedback needed' do
- expect(record_ids).to match_array Initiative.feedback_needed.pluck(:id)
- end
- end
-
- context 'when false' do
- before do
- create(:initiative, initiative_status: initiative_status)
- create(:initiative, initiative_status: feedback_needed_initiative_status)
- params[:feedback_needed] = false
- end
-
- it 'filters by feedback not needed' do
- expect(record_ids).to match_array Initiative.no_feedback_needed.pluck(:id)
- end
- end
- end
-
- describe '#author_condition' do
- let(:author) { create(:user) }
-
- before do
- create(:initiative, author_id: author.id)
- params[:author] = author.id
- end
-
- it 'filters by author' do
- expect(record_ids).to match_array Initiative.where(author_id: author.id).pluck(:id)
- end
- end
-
- describe '#search_condition' do
- let(:slug) { 'slug-1' }
- let(:expected_record_ids) { Initiative.search_by_all(slug).pluck(:id) }
-
- before do
- params[:search] = slug
- end
-
- it 'returns the correct records' do
- create(:initiative, slug: slug)
- expect(record_ids).to match_array expected_record_ids
- end
- end
-
- describe '#publication_status_condition' do
- let(:publication_status) { :published }
-
- before do
- create(:initiative, publication_status: publication_status)
- params[:publication_status] = publication_status
- end
-
- it 'filters by publication_status' do
- expect(record_ids).to match_array Initiative.where(publication_status: publication_status).pluck(:id)
- end
- end
-
- describe '#bounding_box_condition' do
- let(:bounding_box) { '[51.208758, 3.224363, 50.000667, 5.715281]' }
-
- before do
- params[:bounding_box] = bounding_box
- end
-
- it 'filters by bounding_box' do
- expect(record_ids).to match_array Initiative.with_bounding_box(bounding_box).pluck(:id)
- end
- end
-
- describe '#initiatives_condition' do
- let(:ids) { Initiative.limit(2).pluck(:id) }
-
- before do
- params[:initiatives] = ids
- end
-
- it 'filters by initiatives' do
- expect(record_ids).to match_array Initiative.where(id: ids).pluck(:id)
- end
- end
-end
diff --git a/back/spec/jobs/log_activity_job_spec.rb b/back/spec/jobs/log_activity_job_spec.rb
index 476920f7b05f..ada3362cf134 100644
--- a/back/spec/jobs/log_activity_job_spec.rb
+++ b/back/spec/jobs/log_activity_job_spec.rb
@@ -178,23 +178,18 @@
Notifications::CommentMarkedAsSpam,
Notifications::CommentOnYourComment,
Notifications::CommentOnIdeaYouFollow,
- Notifications::CommentOnInitiativeYouFollow,
Notifications::IdeaMarkedAsSpam,
- Notifications::InitiativeAssignedToYou,
- Notifications::InitiativeMarkedAsSpam,
Notifications::InviteAccepted,
Notifications::MarkedAsSpam,
Notifications::MentionInComment,
Notifications::MentionInOfficialFeedback,
Notifications::OfficialFeedbackOnIdeaYouFollow,
- Notifications::OfficialFeedbackOnInitiativeYouFollow,
Notifications::ProjectFolderModerationRightsReceived,
Notifications::ProjectModerationRightsReceived,
Notifications::ProjectPhaseStarted,
Notifications::ProjectPhaseUpcoming,
Notifications::ProjectPublished,
Notifications::StatusChangeOnIdeaYouFollow,
- Notifications::StatusChangeOnInitiativeYouFollow,
Notifications::ThresholdReachedForAdmin,
OfficialFeedback,
Phase,
diff --git a/back/spec/models/initiative_spec.rb b/back/spec/models/initiative_spec.rb
index 246532cc8fd1..09bd170b0a04 100644
--- a/back/spec/models/initiative_spec.rb
+++ b/back/spec/models/initiative_spec.rb
@@ -266,13 +266,13 @@
expect(User.find(cosponsor1.id)).to be_present
end
- it 'removes cosponsors_initiative even when an associated notifcation exists' do
- cosponsor2 = create(:user)
- create(:invitation_to_cosponsor_initiative, cosponsors_initiative: cosponsors_initiative)
- initiative.update!(cosponsor_ids: [cosponsor2.id])
+ # it 'removes cosponsors_initiative even when an associated notifcation exists' do
+ # cosponsor2 = create(:user)
+ # create(:invitation_to_cosponsor_initiative, cosponsors_initiative: cosponsors_initiative)
+ # initiative.update!(cosponsor_ids: [cosponsor2.id])
- expect(initiative.reload.cosponsors).to match_array [cosponsor2]
- end
+ # expect(initiative.reload.cosponsors).to match_array [cosponsor2]
+ # end
it 'can add and remove cosponsors_initiatives at the same time' do
cosponsor2 = create(:user)
diff --git a/back/spec/models/notification_spec.rb b/back/spec/models/notification_spec.rb
index 362fe4225a52..3c94a8a4ba06 100644
--- a/back/spec/models/notification_spec.rb
+++ b/back/spec/models/notification_spec.rb
@@ -132,14 +132,6 @@
expect(described_class.count).to eq(count - 1)
end
- it 'deleting an initiative status also deletes notifications requiring that initiative status' do
- initiative_status = create(:initiative_status)
- create(:status_change_on_initiative_you_follow, post_status: initiative_status)
- count = described_class.count
- initiative_status.destroy!
- expect(described_class.count).to eq(count - 1)
- end
-
it 'deleting an invite also deletes notifications requiring that invite' do
invite = create(:invite)
create(:invite_accepted, invite: invite)
diff --git a/back/spec/models/notifications/comment_on_initiative_you_follow_spec.rb b/back/spec/models/notifications/comment_on_initiative_you_follow_spec.rb
deleted file mode 100644
index 41152605f43c..000000000000
--- a/back/spec/models/notifications/comment_on_initiative_you_follow_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::CommentOnInitiativeYouFollow do
- describe 'make_notifications_on' do
- it 'makes a notification on created comment activity' do
- initiative = create(:initiative)
- follower = create(:follower, followable: initiative)
- comment = create(:comment, post: initiative)
- activity = create(:activity, item: comment, action: 'created')
-
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: follower.user_id,
- initiating_user_id: comment.author_id,
- post_id: initiative.id,
- comment_id: comment.id
- )
- end
-
- it 'does not make a notification when follow feature is turned off' do
- initiative = create(:initiative)
- create(:follower, followable: initiative)
- comment = create(:comment, post: initiative)
- activity = create(:activity, item: comment, action: 'created')
-
- SettingsService.new.deactivate_feature! 'follow'
- notifications = described_class.make_notifications_on activity
- expect(notifications).to be_empty
- end
- end
-end
diff --git a/back/spec/models/notifications/cosponsor_of_your_initiative_spec.rb b/back/spec/models/notifications/cosponsor_of_your_initiative_spec.rb
deleted file mode 100644
index 2eedc91b14dc..000000000000
--- a/back/spec/models/notifications/cosponsor_of_your_initiative_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::CosponsorOfYourInitiative do
- describe 'cosponsor_of_your_initiative' do
- it 'makes a notification on cosponsorship_accepted cosponsors_initiative activity' do
- initiative = create(:initiative, author: create(:user))
- cosponsors_initiative = create(:cosponsors_initiative, initiative: initiative, status: 'accepted')
- activity = create(
- :activity,
- item: cosponsors_initiative,
- user_id: cosponsors_initiative.user_id,
- action: 'cosponsorship_accepted'
- )
-
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: initiative.author_id,
- initiating_user: cosponsors_initiative.user,
- post: initiative
- )
- end
- end
-end
diff --git a/back/spec/models/notifications/initiative_resubmitted_for_review_spec.rb b/back/spec/models/notifications/initiative_resubmitted_for_review_spec.rb
deleted file mode 100644
index dd930fb9da21..000000000000
--- a/back/spec/models/notifications/initiative_resubmitted_for_review_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::InitiativeResubmittedForReview do
- describe '.make_notifications_on' do
- it 'makes a notification on changed_status activity, when status changes from changes_requested to review_pending' do
- assignee = create(:admin)
- initiative = create(:initiative, assignee: assignee)
- create(:initiative_status_change, initiative: initiative, initiative_status: create(:initiative_status, code: 'changes_requested'))
- create(:initiative_status_change, initiative: initiative, initiative_status: create(:initiative_status, code: 'review_pending'))
- activity = create(:activity, item: initiative, action: 'changed_status')
-
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: assignee.id,
- post_id: initiative.id
- )
- end
- end
-end
diff --git a/back/spec/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_spec.rb b/back/spec/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_spec.rb
deleted file mode 100644
index 265a2994e526..000000000000
--- a/back/spec/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::InternalComments::InternalCommentOnInitiativeAssignedToYou do
- describe 'make_notifications_on' do
- let(:assignee) { create(:admin) }
- let(:initiative) { create(:initiative, assignee: assignee) }
- let(:internal_comment) { create(:internal_comment, post: initiative) }
-
- context 'when an assignee should receive this notification' do
- let(:activity) { create(:activity, item: internal_comment, action: 'created') }
-
- it 'makes a notification on created internal comment activity' do
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: assignee.id,
- initiating_user_id: internal_comment.author_id,
- post_id: initiative.id,
- internal_comment_id: internal_comment.id
- )
- end
- end
-
- shared_examples 'no notification created' do
- it 'does not make a notification on created internal comment activity' do
- notifications_count = described_class.count
- activity = create(:activity, item: internal_comment, action: 'created')
- notifications = described_class.make_notifications_on activity
-
- expect(notifications.count).to eq notifications_count
- end
- end
-
- context 'when the recipient is the internal comment author' do
- let(:internal_comment) { create(:internal_comment, author: assignee, post: initiative) }
-
- it_behaves_like 'no notification created'
- end
-
- context "when the internal comment is a comment on the assignee's internal comment" do
- let(:parent_internal_comment) { create(:internal_comment, post: initiative, author: assignee) }
- let(:internal_comment) { create(:internal_comment, parent: parent_internal_comment, post: initiative) }
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a InternalCommentOnYourInternalComment notification to the recipient.
- it_behaves_like 'no notification created'
- end
-
- context 'when the internal comment contains a mention of the assignee' do
- let(:internal_comment) do
- create(
- :internal_comment,
- :with_mentions,
- mentioned_users: [assignee],
- post: initiative
- )
- end
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a MentionInInternalComment notification to the recipient.
- it_behaves_like 'no notification created'
- end
-
- context 'when the internal comment is on an idea the assignee is assigned to' do
- let(:idea) { create(:idea, assignee: assignee) }
- let(:internal_comment) { create(:internal_comment, post: idea) }
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a InternalCommentOnIdeaAssignedToYou notification to the recipient.
- it_behaves_like 'no notification created'
- end
- end
-end
diff --git a/back/spec/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_spec.rb b/back/spec/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_spec.rb
deleted file mode 100644
index 7019c7dfd4ea..000000000000
--- a/back/spec/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_spec.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn do
- describe 'make_notifications_on' do
- let(:initiative) { create(:initiative) }
- let!(:commenter) { create(:admin) }
- let!(:_internal_comment2) { create(:internal_comment, post: initiative, author: commenter) }
- let(:internal_comment) { create(:internal_comment, post: initiative) }
-
- context 'when admin has internally commented on initiative and should receive this notification' do
- let(:activity) { create(:activity, item: internal_comment, action: 'created') }
-
- it 'makes a notification on created internal comment activity' do
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: commenter.id,
- initiating_user_id: internal_comment.author_id,
- internal_comment_id: internal_comment.id,
- post_id: initiative.id,
- post_type: 'Initiative',
- project_id: nil
- )
- end
- end
-
- context 'when recipient is moderator and should receive this notification' do
- let(:initiative2) { create(:initiative) }
- let!(:project_moderator) { create(:project_moderator) }
- let(:internal_comment) { create(:internal_comment, post: initiative2) }
- let!(:_internal_comment2) { create(:internal_comment, post: initiative2, author: project_moderator) }
- let(:activity) { create(:activity, item: internal_comment, action: 'created') }
-
- it 'makes a notification on created internal comment activity' do
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: project_moderator.id,
- initiating_user_id: internal_comment.author_id,
- internal_comment_id: internal_comment.id,
- post_id: initiative2.id,
- post_type: 'Initiative',
- project_id: nil
- )
- end
- end
-
- shared_examples 'no notification created' do
- it 'does not make a notification on created internal comment activity' do
- notifications_count = described_class.count
- activity = create(:activity, item: internal_comment, action: 'created')
- notifications = described_class.make_notifications_on activity
-
- expect(notifications.count).to eq notifications_count
- end
- end
-
- context 'when the recipient is the internal comment author' do
- let(:internal_comment) { create(:internal_comment, author: commenter, post: initiative) }
-
- it_behaves_like 'no notification created'
- end
-
- context "when the internal comment is a comment on the recipient's internal comment" do
- let(:parent_internal_comment) { create(:internal_comment, post: initiative, author: commenter) }
- let(:internal_comment) { create(:internal_comment, parent: parent_internal_comment, post: initiative) }
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a InternalCommentOnYourInternalComment notification to the recipient.
- it_behaves_like 'no notification created'
- end
-
- context 'when the internal comment contains a mention of the recipient' do
- let(:internal_comment) do
- create(
- :internal_comment,
- :with_mentions,
- mentioned_users: [commenter],
- post: initiative
- )
- end
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a MentionInInternalComment notification to the recipient.
- it_behaves_like 'no notification created'
- end
-
- context 'when the internal comment is on an initiative the recipient is assigned to' do
- let(:initiative) { create(:initiative, assignee: commenter) }
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a InternalCommentOnInitiativeAssignedToYou notification to the recipient.
- it_behaves_like 'no notification created'
- end
- end
-end
diff --git a/back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_initiative_spec.rb b/back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_initiative_spec.rb
deleted file mode 100644
index fd327838a428..000000000000
--- a/back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_initiative_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::InternalComments::InternalCommentOnUnassignedInitiative do
- describe 'make_notifications_on' do
- let(:initiative) { create(:initiative) }
- let!(:admin) { create(:admin) }
- let(:internal_comment) { create(:internal_comment, post: initiative) }
-
- context 'when an admin should receive this notification' do
- let(:activity) { create(:activity, item: internal_comment, action: 'created') }
-
- it 'makes a notification on created internal comment activity' do
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: admin.id,
- initiating_user_id: internal_comment.author_id,
- post_id: initiative.id,
- internal_comment_id: internal_comment.id
- )
- end
- end
-
- shared_examples 'no notification created' do
- it 'does not make a notification on created internal comment activity' do
- notifications_count = described_class.count
- activity = create(:activity, item: internal_comment, action: 'created')
- notifications = described_class.make_notifications_on activity
-
- expect(notifications.count).to eq notifications_count
- end
- end
-
- context 'when the recipient is the internal comment author' do
- let(:internal_comment) { create(:internal_comment, author: admin, post: initiative) }
-
- it_behaves_like 'no notification created'
- end
-
- context 'when someone is assigned to the initiative' do
- let(:initiative) { create(:initiative, assignee: create(:admin)) }
-
- it_behaves_like 'no notification created'
- end
-
- context "when the internal comment is a comment on the recipient's internal comment" do
- let(:parent_internal_comment) { create(:internal_comment, post: initiative, author: admin) }
- let(:internal_comment) { create(:internal_comment, parent: parent_internal_comment, post: initiative) }
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a InternalCommentOnYourInternalComment notification to the recipient.
- it_behaves_like 'no notification created'
- end
-
- context 'when the internal comment contains a mention of the recipient' do
- let(:internal_comment) do
- create(
- :internal_comment,
- :with_mentions,
- mentioned_users: [admin],
- post: initiative
- )
- end
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a MentionInInternalComment notification to the recipient.
- it_behaves_like 'no notification created'
- end
-
- context 'when the recipient has already commented internally on the initiative' do
- let!(:_other_internal_comment) { create(:internal_comment, post: initiative, author: admin) }
-
- # Don't create this notification if the Activity (internal comment created)
- # should lead to a InternalCommentOnInitiativeYouCommentedInternallyOn notification to the recipient.
- it_behaves_like 'no notification created'
- end
- end
-end
diff --git a/back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_unmoderated_idea_spec.rb b/back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_unmoderated_idea_spec.rb
index 97ba9401f488..b9507ebb54fc 100644
--- a/back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_unmoderated_idea_spec.rb
+++ b/back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_unmoderated_idea_spec.rb
@@ -87,7 +87,7 @@
let!(:_other_internal_comment) { create(:internal_comment, post: idea, author: admin) }
# Don't create this notification if the Activity (internal comment created)
- # should lead to a InternalCommentOnInitiativeYouCommentedInternallyOn notification to the recipient.
+ # should lead to a InternalCommentOnIdeaYouCommentedInternallyOn notification to the recipient.
it_behaves_like 'no notification created'
end
end
diff --git a/back/spec/models/notifications/invitation_to_cosponsor_initiative_spec.rb b/back/spec/models/notifications/invitation_to_cosponsor_initiative_spec.rb
deleted file mode 100644
index 7b930878aeae..000000000000
--- a/back/spec/models/notifications/invitation_to_cosponsor_initiative_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::InvitationToCosponsorInitiative do
- describe 'invitation_to_cosponsor_initiative' do
- it 'makes a notification on created cosponsors_initiative activity' do
- initiative = create(:initiative, author: create(:user))
- cosponsors_initiative = create(:cosponsors_initiative, initiative: initiative)
- activity = create(:activity, item: cosponsors_initiative, user_id: initiative.author.id, action: 'created')
-
- notifications = described_class.make_notifications_on activity
- expect(notifications.first).to have_attributes(
- recipient_id: cosponsors_initiative.user_id,
- initiating_user: cosponsors_initiative.initiative.author,
- post: initiative
- )
- end
- end
-end
diff --git a/back/spec/models/notifications/official_feedback_on_initiative_you_follow_spec.rb b/back/spec/models/notifications/official_feedback_on_initiative_you_follow_spec.rb
deleted file mode 100644
index ec9a89ab10d1..000000000000
--- a/back/spec/models/notifications/official_feedback_on_initiative_you_follow_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::OfficialFeedbackOnInitiativeYouFollow do
- describe 'make_notifications_on' do
- it 'generates exactly one notification for each follower of the initiative' do
- initiative = create(:initiative)
- follower1 = create(:follower, followable: initiative)
- create(:follower)
- follower3 = create(:follower, followable: initiative)
-
- official_feedback = create(:official_feedback, post: initiative)
- activity = create(:activity, item: official_feedback, action: :created)
-
- notifications = described_class.make_notifications_on(activity)
- expect(notifications.map(&:recipient_id)).to contain_exactly follower1.user_id, follower3.user_id
- end
-
- it "doesn't generate notifications for the initiating user" do
- initiative = create(:initiative)
- follower = create(:follower, followable: initiative)
-
- official_feedback = create(:official_feedback, post: initiative, user: follower.user)
- activity = create(:activity, item: official_feedback, action: :created)
-
- notifications = described_class.make_notifications_on(activity)
- expect(notifications).to eq []
- end
-
- it "doesn't generate notifications when there was a status change for the same official feedback" do
- initiative = create(:initiative)
- create(:follower, followable: initiative)
- official_feedback = create(:official_feedback, post: initiative)
- create(:initiative_status_change, initiative: initiative, official_feedback: official_feedback)
- activity = create(:activity, item: official_feedback, action: :created)
-
- notifications = described_class.make_notifications_on(activity)
- expect(notifications).to eq []
- end
-
- it "doesn't generate notifications when the post is an idea" do
- idea = create(:idea)
- official_feedback = create(:official_feedback, post: idea)
- activity = create(:activity, item: official_feedback, action: :created)
-
- notifications = described_class.make_notifications_on(activity)
- expect(notifications).to eq []
- end
-
- it 'does not make a notification when follow feature is turned off' do
- initiative = create(:initiative)
- create(:follower, followable: initiative)
- official_feedback = create(:official_feedback, post: initiative)
- activity = create(:activity, item: official_feedback, action: :created)
-
- SettingsService.new.deactivate_feature! 'follow'
- notifications = described_class.make_notifications_on activity
- expect(notifications).to be_empty
- end
- end
-end
diff --git a/back/spec/models/notifications/status_change_on_initiative_you_follow_spec.rb b/back/spec/models/notifications/status_change_on_initiative_you_follow_spec.rb
deleted file mode 100644
index 5ff07d281cb0..000000000000
--- a/back/spec/models/notifications/status_change_on_initiative_you_follow_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Notifications::StatusChangeOnInitiativeYouFollow do
- describe 'make_notifications_on' do
- it 'generates exactly one notification for each follower of the initiative' do
- initiative = create(:initiative)
- follower1 = create(:follower, followable: initiative)
- create(:follower)
- follower3 = create(:follower, followable: initiative)
-
- activity = create(:activity, item: initiative, action: 'changed_status')
-
- notifications = described_class.make_notifications_on activity
- expect(notifications.map(&:recipient_id)).to contain_exactly follower1.user_id, follower3.user_id
- end
-
- it "doesn't generate notifications for the initiating user" do
- initiative = create(:initiative)
- follower = create(:follower, followable: initiative)
-
- activity = create(:activity, item: initiative, action: 'changed_status', user: follower.user)
-
- notifications = described_class.make_notifications_on(activity)
- expect(notifications).to eq []
- end
-
- it 'does not make a notification when follow feature is turned off' do
- initiative = create(:initiative)
- create(:follower, followable: initiative)
- activity = create(:activity, item: initiative, action: 'changed_status')
-
- SettingsService.new.deactivate_feature! 'follow'
- notifications = described_class.make_notifications_on activity
- expect(notifications).to be_empty
- end
- end
-end
diff --git a/back/spec/policies/follower_policy_spec.rb b/back/spec/policies/follower_policy_spec.rb
index e02fc71ade7e..91b1d13c9e7a 100644
--- a/back/spec/policies/follower_policy_spec.rb
+++ b/back/spec/policies/follower_policy_spec.rb
@@ -196,46 +196,6 @@
end
end
- context 'for an initiative' do
- let(:followable) { create(:initiative) }
-
- context 'for a resident' do
- let(:user) { create(:user) }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'does not index the follower' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- context 'for the following user' do
- let(:user) { following_user }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:destroy) }
-
- it 'indexes the follower' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'does not index the follower' do
- expect(scope.resolve.size).to eq 0
- end
- end
- end
-
context 'for a topic' do
let(:followable) { create(:topic) }
diff --git a/back/spec/policies/initiative_comment_policy_spec.rb b/back/spec/policies/initiative_comment_policy_spec.rb
deleted file mode 100644
index 1181e481d36d..000000000000
--- a/back/spec/policies/initiative_comment_policy_spec.rb
+++ /dev/null
@@ -1,176 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe InitiativeCommentPolicy do
- subject { described_class.new(user, comment) }
-
- let(:scope) { InitiativeCommentPolicy::Scope.new(user, initiative.comments) }
-
- context 'on comment on initiative with proposed status' do
- let(:initiative) { create(:initiative) }
-
- let!(:_initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: initiative,
- initiative_status: create(:initiative_status_proposed)
- )
- end
-
- let!(:comment) { create(:comment, post: initiative) }
-
- context 'for a visitor' do
- let(:user) { nil }
-
- it { is_expected.to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'indexes the comment' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is not the author of the comment' do
- let(:user) { create(:user) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'indexes the comment' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is the author of the comment' do
- let(:user) { comment.author }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'indexes the comment' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for blocked comment author' do
- let(:user) { create(:user, block_end_at: 5.days.from_now) }
- let(:comment) { create(:comment, author: user, post: initiative) }
-
- it_behaves_like 'policy for blocked user'
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'indexes the comment' do
- expect(scope.resolve.size).to eq 1
- end
- end
- end
-
- context 'on comment on initiative with review_pending status' do
- let(:initiative) { create(:initiative) }
-
- let!(:_initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: initiative,
- initiative_status: create(:initiative_status_review_pending)
- )
- end
-
- let!(:comment) { create(:comment, post: initiative, author: initiative.author) }
-
- context 'for a visitor' do
- let(:user) { nil }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'does not index the comment' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- context 'for a user who is not the author of the initiative or the comment' do
- let(:user) { create(:user) }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'does not index the comment' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- context 'for a user who is the author of the initiative and the comment' do
- let(:user) { initiative.author }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'indexes the comment' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for blocked comment author' do
- let(:user) { create(:user, block_end_at: 5.days.from_now) }
- let(:comment) { create(:comment, author: user, post: initiative) }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'does not index the comment' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'indexes the comment' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is cosponsor of the initiative' do
- let(:user) { create(:user) }
- let!(:cosponsors_initiative) { create(:cosponsors_initiative, user: user, initiative: initiative) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
- end
-end
diff --git a/back/spec/policies/initiative_policy_spec.rb b/back/spec/policies/initiative_policy_spec.rb
deleted file mode 100644
index 19c8f38c8814..000000000000
--- a/back/spec/policies/initiative_policy_spec.rb
+++ /dev/null
@@ -1,417 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-describe InitiativePolicy do
- subject(:policy) { described_class.new(user, initiative) }
-
- let(:scope) { InitiativePolicy::Scope.new(user, Initiative) }
- let(:author) { create(:user) }
-
- # We need to consider 4 main scenarios:
- # 1. When review feature is NOT active, and
- # 2. When review feature is active
- # a). When initiative has review_pending or review_rejected status
- # b). when initiative has status other than review_pending or review_rejected
- # 1a + 1b + 2a + 2b = 4 scenarios
- #
- # We avoid testing initiatives with 'custom' status, as it is not used and not adequately considered in the codebase.
-
- # ------------------- 1. Review feature is NOT active -------------------
-
- context 'when review feature is NOT fully active' do
- it 'is not active' do
- expect(Initiative.review_required?).to be false
- end
-
- # For statuses with REVIEW_CODES, we only show/index initiatives with review statuses to the author and admins.
- context 'for an initiative with status review_pending' do
- let!(:initiative) do
- create(:initiative, author: author, initiative_status: create(:initiative_status_review_pending))
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is not author of the initiative' do
- let(:user) { create(:user) }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'does not index the initiative' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- context 'for a user who is author of the initiative' do
- let(:user) { author }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is cosponsor of the initiative' do
- let(:user) { create(:user) }
- let!(:cosponsors_initiative) { create(:cosponsors_initiative, user: user, initiative: initiative) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a visitor' do
- let(:user) { nil }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:by_slug) }
- it { expect { policy.create? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.update? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.destroy? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'does not index the initiative' do
- expect(scope.resolve.size).to eq 0
- end
- end
- end
-
- context 'for an initiative with proposed status' do
- let!(:initiative) do
- create(:initiative, author: author, initiative_status: create(:initiative_status_proposed))
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is not author of the initiative' do
- let(:user) { create(:user) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is author of the initiative' do
- let(:user) { author }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is cosponsor of the initiative' do
- let(:user) { create(:user) }
- let!(:cosponsors_initiative) { create(:cosponsors_initiative, user: user, initiative: initiative) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a visitor' do
- let(:user) { nil }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { expect { policy.create? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.update? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.destroy? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
- end
- end
-
- # ------------------- 2. Review feature IS active ----------------------
-
- context 'when review feature IS fully active' do
- before do
- SettingsService.new.activate_feature! 'initiative_review'
-
- configuration = AppConfiguration.instance
- configuration.settings['initiatives']['require_review'] = true
- configuration.save!
- end
-
- it 'is active' do
- expect(Initiative.review_required?).to be true
- end
-
- # For statuses with REVIEW_CODES, we only show initiatives with review statuses to the author and admins.
- context 'for an initiative with review_pending status' do
- let!(:initiative) do
- create(:initiative, author: author, initiative_status: create(:initiative_status_review_pending))
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is not author of the initiative' do
- let(:user) { create(:user) }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'does not index the initiative' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- # Author can still see their own initiative if review feature is active,
- # even when status in InitiativeStatus::REVIEW_CODES.
- context 'for a user who is author of the initiative' do
- let(:user) { author }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- # Cosponsor can still see an initiative thaye are a cosponsor of if review feature is active,
- # even when status in InitiativeStatus::REVIEW_CODES.
- context 'for a user who is cosponsor of the initiative' do
- let(:user) { create(:user) }
- let!(:cosponsors_initiative) { create(:cosponsors_initiative, user: user, initiative: initiative) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a visitor' do
- let(:user) { nil }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:by_slug) }
- it { expect { policy.create? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.update? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.destroy? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'does not index the initiative' do
- expect(scope.resolve.size).to eq 0
- end
- end
- end
-
- context 'for an initiative with proposed status' do
- let!(:initiative) do
- create(:initiative, author: author, initiative_status: create(:initiative_status_proposed))
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is not author of the initiative' do
- let(:user) { create(:user) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'does not index the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- # Author can see initiative, but not edit, if review feature is active,
- # and when status in InitiativeStatus::NOT_REVIEW_CODES
- context 'for a user who is author of the initiative' do
- let(:user) { author }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) } # TODO: This is confusing, as editing_locked should be true when status proposed!
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is cosponsor of the initiative' do
- let(:user) { create(:user) }
- let!(:cosponsors_initiative) { create(:cosponsors_initiative, user: user, initiative: initiative) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.not_to permit(:destroy) }
- it { is_expected.to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a visitor' do
- let(:user) { nil }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { expect { policy.create? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.update? }.to raise_error(Pundit::NotAuthorizedError) }
- it { expect { policy.destroy? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'does not index the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
- end
- end
-
- # Nobody can edit initiative if editing is locked, including admins and authors
- context 'when editing is locked for the initiative' do
- let!(:initiative) do
- create(:initiative, author: author, editing_locked: true, initiative_status: create(:initiative_status_proposed))
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for a user who is author of the initiative' do
- let(:user) { author }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:by_slug) }
- it { is_expected.to permit(:create) }
- it { is_expected.not_to permit(:update) }
- it { is_expected.to permit(:destroy) }
- it { is_expected.not_to permit(:accept_cosponsorship_invite) }
-
- it 'indexes the initiative' do
- expect(scope.resolve.size).to eq 1
- end
- end
- end
-end
diff --git a/back/spec/policies/initiative_reaction_policy_spec.rb b/back/spec/policies/initiative_reaction_policy_spec.rb
deleted file mode 100644
index c6cc7bb1844c..000000000000
--- a/back/spec/policies/initiative_reaction_policy_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe InitiativeReactionPolicy do
- subject(:policy) { described_class.new(user, reaction) }
-
- let(:scope) { InitiativeReactionPolicy::Scope.new(user, Reaction) }
- let(:reactable) { create(:initiative) }
- let!(:reaction) { create(:reaction, reactable: reactable) }
-
- context 'for a visitor' do
- let(:user) { nil }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:up) }
- it { expect { policy.down? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'should not index the reaction' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- context 'for a mortal user on a reaction of another user' do
- let(:user) { create(:user) }
-
- it { is_expected.not_to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:up) }
- it { expect { policy.down? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'should not index the reaction' do
- expect(scope.resolve.size).to eq 0
- end
- end
-
- context 'for a mortal user who owns the reaction' do
- let(:user) { reaction.user }
-
- it { is_expected.to permit(:show) }
- it { is_expected.to permit(:create) }
- it { is_expected.to permit(:up) }
- it { expect { policy.down? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.to permit(:destroy) }
-
- it 'should index the reaction' do
- expect(scope.resolve.size).to eq 1
- end
- end
-
- context 'for blocked reaction owner' do
- let(:user) { create(:user, block_end_at: 5.days.from_now) }
- let(:reaction) { create(:reaction, user: user, reactable: reactable) }
-
- it_behaves_like 'policy for blocked user reaction', down_authorized: false
- end
-
- context 'for an admin' do
- let(:user) { create(:admin) }
-
- it { is_expected.to permit(:show) }
- it { is_expected.not_to permit(:create) }
- it { is_expected.not_to permit(:up) }
- it { expect { policy.down? }.to raise_error(Pundit::NotAuthorizedError) }
- it { is_expected.not_to permit(:destroy) }
-
- it 'should index the reaction' do
- expect(scope.resolve.size).to eq 1
- end
- end
-end
diff --git a/back/spec/policies/initiative_status_policy_spec.rb b/back/spec/policies/initiative_status_policy_spec.rb
deleted file mode 100644
index dd63b5b6d68e..000000000000
--- a/back/spec/policies/initiative_status_policy_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-describe InitiativeStatusPolicy do
- describe InitiativeStatusPolicy::Scope do
- subject(:scope) { described_class.new(user, InitiativeStatus).resolve }
-
- def create_initiative_status_change(status, initiative: build(:initiative))
- create(:initiative_status_change, initiative: initiative, initiative_status: status)
- end
-
- context 'with default statuses' do
- let!(:status_review_pending) { create(:initiative_status_review_pending) }
- let!(:status_changes_requested) { create(:initiative_status_changes_requested) }
- let!(:status_proposed) { create(:initiative_status_proposed) }
- let!(:status_expired) { create(:initiative_status_expired) }
- let!(:status_threshold_reached) { create(:initiative_status_threshold_reached) }
- let!(:status_answered) { create(:initiative_status_answered) }
- let!(:status_ineligible) { create(:initiative_status_ineligible) }
-
- let!(:default_codes) { InitiativeStatus::CODES - ['custom'] }
- let!(:not_review_codes) { InitiativeStatus::NOT_REVIEW_CODES - ['custom'] }
-
- context 'when admin' do
- let(:user) { create(:admin) }
-
- context 'when review feature is not fully activated' do
- it 'does not return review statuses if no review initiative exists' do
- expect(scope.pluck(:code)).to match_array not_review_codes
- end
-
- it 'returns all statuses if at least one review_pending initiative exists' do
- create_initiative_status_change(status_review_pending)
- expect(scope.pluck(:code)).to match_array default_codes
- end
-
- it 'returns all statuses if at least one changes_requested initiative exists' do
- create_initiative_status_change(status_changes_requested)
- expect(scope.pluck(:code)).to match_array default_codes
- end
- end
-
- context 'when review feature is fully activated' do
- before do
- SettingsService.new.activate_feature! 'initiative_review'
-
- configuration = AppConfiguration.instance
- configuration.settings['initiatives']['require_review'] = true
- configuration.save!
- end
-
- it 'returns all initiative statuses' do
- expect(scope.pluck(:code)).to match_array default_codes
- end
- end
- end
-
- context 'when normal user' do
- let(:user) { create(:user) }
-
- it 'does not return review statuses if user authored no review initiatives' do
- create_initiative_status_change(status_review_pending)
- create_initiative_status_change(status_changes_requested)
- expect(scope.pluck(:code)).to match_array not_review_codes
- end
-
- it 'returns review_pending status if user authored an review_pending initiative' do
- create_initiative_status_change(status_review_pending, initiative: build(:initiative, author: user))
- expect(scope.pluck(:code)).to match_array not_review_codes + ['review_pending']
- end
-
- it 'returns changes_requested status if user authored an changes_requested initiative' do
- create_initiative_status_change(status_changes_requested, initiative: build(:initiative, author: user))
- expect(scope.pluck(:code)).to match_array not_review_codes + ['changes_requested']
- end
- end
- end
- end
-end
diff --git a/back/spec/requests/rack_attack_spec.rb b/back/spec/requests/rack_attack_spec.rb
index c46ac9a86fc1..d99535eb6693 100644
--- a/back/spec/requests/rack_attack_spec.rb
+++ b/back/spec/requests/rack_attack_spec.rb
@@ -248,16 +248,16 @@
it 'limits search requests from same IP to 15 in 20 seconds' do
freeze_time do
15.times do
- get '/web_api/v1/initiatives?search=some-random-search-term'
+ get '/web_api/v1/ideas?search=some-random-search-term'
end
expect(status).to eq(200) # OK
- get '/web_api/v1/initiatives?search=some-random-search-term'
+ get '/web_api/v1/ideas?search=some-random-search-term'
expect(status).to eq(429) # Too many requests
end
travel_to(20.seconds.from_now) do
- get '/web_api/v1/initiatives?search=some-random-search-term'
+ get '/web_api/v1/ideas?search=some-random-search-term'
expect(status).to eq(200) # OK
end
end
diff --git a/back/spec/serializers/web_api/v1/initiative_serializer_spec.rb b/back/spec/serializers/web_api/v1/initiative_serializer_spec.rb
deleted file mode 100644
index 62f5ef698f69..000000000000
--- a/back/spec/serializers/web_api/v1/initiative_serializer_spec.rb
+++ /dev/null
@@ -1,105 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe WebApi::V1::InitiativeSerializer do
- context "with 'abbreviated user names' enabled" do
- before { SettingsService.new.activate_feature! 'abbreviated_user_names' }
-
- let(:jane) { create(:user, first_name: 'Jane', last_name: 'Doe') }
- let(:john) { create(:user, first_name: 'John', last_name: 'Smith') }
- let(:admin) { create(:admin, first_name: 'Thomas', last_name: 'Anderson') }
-
- it 'should abbreviate the author name' do
- jane_initiative = create(:initiative, author: jane)
- last_name = described_class
- .new(jane_initiative, params: { current_user: john })
- .serializable_hash
- .dig(:data, :attributes, :author_name)
- expect(last_name).to eq 'Jane D.'
- end
-
- it 'should not abbreviate user names for admins' do
- jane_initiative = create(:initiative, author: jane)
- last_name = described_class
- .new(jane_initiative, params: { current_user: admin })
- .serializable_hash
- .dig(:data, :attributes, :author_name)
- expect(last_name).to eq 'Jane Doe'
-
- admin_initiative = create(:initiative, author: admin)
- last_name = described_class
- .new(admin_initiative, params: { current_user: john })
- .serializable_hash
- .dig(:data, :attributes, :author_name)
- expect(last_name).to eq 'Thomas Anderson'
- end
- end
-
- context 'when serializing internal comments count of initiative' do
- let(:initiative) { create(:initiative) }
-
- before do
- create_list(:internal_comment, 2, post: initiative)
- initiative.reload
- end
-
- context 'when current user is nil (visitor)' do
- it 'should not include internal comments count' do
- expect(internal_comments_count_for_current_user(initiative, nil)).to be_nil
- end
- end
-
- context 'when current user is regular user' do
- it 'should not include internal comments count' do
- expect(internal_comments_count_for_current_user(initiative, create(:user))).to be_nil
- end
- end
-
- context 'when current user is admin' do
- it 'should include internal comments count' do
- expect(internal_comments_count_for_current_user(initiative, create(:admin))).to eq 2
- end
- end
- end
-
- context 'when cosponsors of initiative exist' do
- let(:initiative) { create(:initiative) }
- let(:current_user) { create(:user) }
- let(:cosponsor) { create(:user) }
- let(:name_service) { UserDisplayNameService.new(AppConfiguration.instance, current_user) }
- let(:cosponsor_display_name) { name_service.display_name!(cosponsor) }
- let!(:_cosponsorship) { create(:cosponsors_initiative, initiative: initiative, user: cosponsor) }
-
- it 'should include cosponsorships' do
- expect(cosponsorships(initiative, current_user).first[:user_id]).to eq cosponsor.id
- expect(cosponsorships(initiative, current_user).first[:name]).to eq cosponsor_display_name
- end
-
- it 'should include cosponsors' do
- expect(cosponsors(initiative, current_user).size).to eq 1
- expect(cosponsors(initiative, current_user).first[:id]).to eq cosponsor.id
- end
- end
-
- def internal_comments_count_for_current_user(initiative, current_user)
- described_class
- .new(initiative, params: { current_user: current_user })
- .serializable_hash
- .dig(:data, :attributes, :internal_comments_count)
- end
-
- def cosponsors(initiative, current_user)
- described_class
- .new(initiative, params: { current_user: current_user })
- .serializable_hash
- .dig(:data, :relationships, :cosponsors, :data)
- end
-
- def cosponsorships(initiative, current_user)
- described_class
- .new(initiative, params: { current_user: current_user })
- .serializable_hash
- .dig(:data, :attributes, :cosponsorships)
- end
-end
diff --git a/back/spec/serializers/web_api/v1/notifications_spec.rb b/back/spec/serializers/web_api/v1/notifications_spec.rb
index b5a12b4d3c9e..7e889d37d62d 100644
--- a/back/spec/serializers/web_api/v1/notifications_spec.rb
+++ b/back/spec/serializers/web_api/v1/notifications_spec.rb
@@ -43,13 +43,6 @@ def expect_serializer_to_hide_name(user1, user2, admin, notification_factory_nam
)
end
- it 'serializes CommentOnInitiativeYouFollow correctly' do
- expect_serializer_to_hide_name(
- john, jane, admin, :comment_on_initiative_you_follow,
- WebApi::V1::Notifications::CommentOnInitiativeYouFollowSerializer
- )
- end
-
it 'serializes CommentOnIdeaYouFollow correctly' do
expect_serializer_to_hide_name(
john, jane, admin, :comment_on_idea_you_follow,
@@ -57,10 +50,10 @@ def expect_serializer_to_hide_name(user1, user2, admin, notification_factory_nam
)
end
- it 'serializes InitiativeAssignedToYouSerializer correctly' do
+ it 'serializes InternalCommentOnIdeaAssignedToYouSerializer correctly' do
expect_serializer_to_hide_name(
- john, jane, admin, :initiative_assigned_to_you,
- WebApi::V1::Notifications::InitiativeAssignedToYouSerializer
+ john, jane, admin, :internal_comment_on_idea_assigned_to_you,
+ WebApi::V1::Notifications::InternalCommentOnIdeaAssignedToYouSerializer
)
end
diff --git a/back/spec/services/permissions/initiatives_permissions_service_spec.rb b/back/spec/services/permissions/initiatives_permissions_service_spec.rb
deleted file mode 100644
index 0ff55870247f..000000000000
--- a/back/spec/services/permissions/initiatives_permissions_service_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-describe Permissions::InitiativePermissionsService do
- let(:service) { described_class.new(user) }
-
- before { SettingsService.new.activate_feature! 'user_confirmation' }
-
- # NOTE: Most of the logic here is tested in the parent class tests - BasePermissionsService
- describe '"posting_initiative" denied_reason_for_action' do
- let(:action) { 'posting_initiative' }
- let(:permission) { Permission.find_by(permission_scope: nil, action: action) }
- let(:user) { create(:user) }
-
- before { Permissions::PermissionsUpdateService.new.update_global_permissions }
-
- it 'returns nil when action is allowed' do
- groups = create_list(:group, 2)
- groups.first.add_member(user).save!
- permission.update!(permitted_by: 'users', group_ids: groups.map(&:id))
- expect(service.denied_reason_for_action(action)).to be_nil
- end
-
- context 'when the user is not signed in' do
- let(:user) { nil }
-
- it 'returns `user_not_signed_in` when user needs to be signed in' do
- permission.update!(permitted_by: 'users')
- expect(service.denied_reason_for_action(action)).to eq 'user_not_signed_in'
- end
- end
-
- it 'returns `user_not_in_group` when user is not in authorized groups' do
- permission.update!(permitted_by: 'users', group_ids: create_list(:group, 2).map(&:id))
- expect(service.denied_reason_for_action(action)).to eq 'user_not_in_group'
- end
- end
-end
diff --git a/back/spec/services/side_fx_comment_service_spec.rb b/back/spec/services/side_fx_comment_service_spec.rb
index b0d696856d99..6f6a50d83d0b 100644
--- a/back/spec/services/side_fx_comment_service_spec.rb
+++ b/back/spec/services/side_fx_comment_service_spec.rb
@@ -34,7 +34,7 @@
expectation.to enqueue_job(LogActivityJob).with(comment, 'mentioned', user, created_at, payload: { mentioned_user: u2.id }, project_id: project_id)
end
- it 'creates a follower' do
+ it 'creates the expected follower records' do
project = create(:project)
folder = create(:project_folder, projects: [project])
idea = create(:idea, project: project)
@@ -47,14 +47,23 @@
expect(user.follows.pluck(:followable_id)).to contain_exactly idea.id, project.id, folder.id
end
- it 'does not create a follower if the user already follows the post' do
- initiative = create(:initiative)
- comment = create(:comment, post: initiative)
- create(:follower, followable: initiative, user: user)
+ it 'does not create new follower records for followable items user already follows' do
+ project = create(:project)
+ folder = create(:project_folder, projects: [project])
+ idea = create(:idea, project: project)
+ comment = create(:comment, post: idea)
- expect do
- service.after_create comment, user
- end.not_to change(Follower, :count)
+ create(:follower, followable: idea, user: user)
+ create(:follower, followable: project, user: user)
+ create(:follower, followable: folder, user: user)
+ n_idea_followers = idea.followers.count
+ n_project_followers = project.followers.count
+ n_folder_followers = folder.followers.count
+
+ service.after_create comment, user
+ expect(idea.reload.followers.count).to eq n_idea_followers
+ expect(project.reload.followers.count).to eq n_project_followers
+ expect(folder.reload.followers.count).to eq n_folder_followers
end
end
diff --git a/back/spec/services/side_fx_initiative_service_spec.rb b/back/spec/services/side_fx_initiative_service_spec.rb
deleted file mode 100644
index 8efc2568ce1e..000000000000
--- a/back/spec/services/side_fx_initiative_service_spec.rb
+++ /dev/null
@@ -1,204 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-describe SideFxInitiativeService do
- let(:service) { described_class.new }
- let(:user) { create(:user) }
-
- describe '#after_update' do
- it "logs a 'changed' action job when the initiative has changed" do
- initiative = create(:initiative)
- initiative.update!(title_multiloc: { en: 'something else' })
- expect { service.after_update(initiative, user, _cosponsor_ids = []) }
- .to enqueue_job(LogActivityJob).with(initiative, 'changed', any_args).exactly(1).times
- end
-
- it "logs a 'changed_title' action job when the title has changed" do
- initiative = create(:initiative)
- old_initiative_title = initiative.title_multiloc
- initiative.update!(title_multiloc: { en: 'changed' })
-
- expect { service.after_update(initiative, user, _cosponsor_ids = []) }
- .to enqueue_job(LogActivityJob).with(
- initiative,
- 'changed_title',
- any_args,
- payload: { change: [old_initiative_title, initiative.title_multiloc] }
- ).exactly(1).times
- end
-
- it "logs a 'changed_body' action job when the body has changed" do
- initiative = create(:initiative)
- old_initiative_body = initiative.body_multiloc
- initiative.update!(body_multiloc: { en: 'changed' })
-
- expect { service.after_update(initiative, user, _cosponsor_ids = []) }
- .to enqueue_job(LogActivityJob).with(
- initiative,
- 'changed_body',
- any_args,
- payload: { change: [old_initiative_body, initiative.body_multiloc] }
- )
- end
-
- context 'when initiative status is changes_requested' do
- let(:initiative) do
- create(:initiative_status_review_pending)
- changes_requested = create(:initiative_status_changes_requested)
- create(:initiative, initiative_status: changes_requested, author: user)
- end
-
- it 'changes initiative status to review_pending' do
- service.after_update(initiative, user, _cosponsor_ids = [])
- expect(initiative.reload.initiative_status.code).to eq 'review_pending'
- end
- end
-
- context 'when update results in new cosponsors' do
- let(:initiative) { create(:initiative, author: user) }
- let(:cosponsor1) { create(:user) }
- let(:cosponsor2) { create(:user) }
-
- it "logs CosponsorsInitiative 'created' activity jobs" do
- initiative.update!(cosponsor_ids: [cosponsor1.id, cosponsor2.id])
- cosponsors_initiatives =
- CosponsorsInitiative.where(initiative: initiative).where(user_id: [cosponsor1.id, cosponsor2.id])
-
- expect { service.after_update(initiative, user, _old_cosponsor_ids = []) }
- .to enqueue_job(LogActivityJob)
- .with(cosponsors_initiatives[0], 'created', user, cosponsors_initiatives[0].created_at.to_i)
- .exactly(1).times
- .and enqueue_job(LogActivityJob)
- .with(cosponsors_initiatives[1], 'created', user, cosponsors_initiatives[1].created_at.to_i)
- .exactly(1).times
- end
- end
- end
-
- describe '#after_accept_cosponsorship_invite' do
- let(:initiative) { create(:initiative) }
- let(:cosponsors_initiative) { create(:cosponsors_initiative, status: 'accepted', user: user, initiative: initiative) }
-
- it 'logs a cosponsorship_accepted activity job' do
- expect { service.after_accept_cosponsorship_invite(cosponsors_initiative, user) }
- .to enqueue_job(LogActivityJob)
- .with(
- cosponsors_initiative,
- 'cosponsorship_accepted',
- user,
- cosponsors_initiative.updated_at.to_i,
- payload: { change: %w[pending accepted] }
- )
- .exactly(1).times
- end
-
- it 'creates a follower' do
- expect do
- service.after_accept_cosponsorship_invite cosponsors_initiative, user
- end.to change(Follower, :count).from(0).to(1)
-
- expect(user.follows.pluck(:followable_id)).to contain_exactly initiative.id
- end
- end
-
- describe 'after_create' do
- it "logs a 'published' action job when publication_state is published" do
- initiative = create(:initiative, publication_status: 'published', author: user)
-
- expect { service.after_create(initiative, user) }
- .to enqueue_job(LogActivityJob)
- .with(initiative, 'published', user, initiative.created_at.to_i)
- .exactly(1).times
- end
-
- it "doesn't log a 'published' action job when publication_state is draft" do
- initiative = create(:initiative, publication_status: 'draft')
- expect { service.after_create(initiative, user) }
- .not_to enqueue_job(LogActivityJob)
- end
-
- it 'creates a follower' do
- initiative = create(:initiative)
-
- expect do
- service.after_create initiative, user
- end.to change(Follower, :count).from(0).to(1)
-
- expect(user.follows.pluck(:followable_id)).to contain_exactly initiative.id
- end
-
- it 'creates a reaction (vote) for an author who can react (vote)' do
- initiative = create(:initiative)
-
- expect do
- service.after_create initiative, user
- end.to change(Reaction, :count).from(0).to(1)
-
- expect(initiative.reactions.pluck(:user_id)).to contain_exactly initiative.author.id
- end
-
- it 'does not create a reaction (vote) for an author who cannot react (vote)' do
- initiative = create(:initiative)
-
- create(
- :permission,
- permission_scope: nil,
- action: 'reacting_initiative',
- permitted_by: 'users',
- groups: [create(:group)]
- )
-
- expect do
- service.after_create initiative, user
- end.not_to change(Reaction, :count)
- end
-
- context "when initiative has status 'proposed'" do
- let(:initiative) { create(:initiative) }
- let!(:initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: initiative,
- initiative_status: create(:initiative_status_proposed)
- )
- end
-
- it 'logs a proposed activity job' do
- expect { service.after_create(initiative, user) }
- .to enqueue_job(LogActivityJob)
- .with(initiative, 'proposed', user, initiative.updated_at.to_i)
- .exactly(1).times
- end
- end
-
- context "when initiative has status 'review_pending'" do
- let(:initiative) { create(:initiative) }
- let!(:initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: initiative,
- initiative_status: create(:initiative_status_review_pending)
- )
- end
-
- it "doesn't log a proposed activity job" do
- expect { service.after_update(initiative, user, _cosponsor_ids = []) }
- .not_to enqueue_job(LogActivityJob)
- .with(instance_of(Initiative), 'proposed', anything, anything)
- end
- end
- end
-
- describe 'after_destroy' do
- it "logs a 'deleted' action job when the initiative is destroyed" do
- initiative = create(:initiative)
- freeze_time do
- frozen_initiative = initiative.destroy
- expect { service.after_destroy(frozen_initiative, user) }
- .to enqueue_job(LogActivityJob).exactly(1).times
- end
- end
- end
-end
diff --git a/back/spec/services/side_fx_initiative_status_change_service_spec.rb b/back/spec/services/side_fx_initiative_status_change_service_spec.rb
deleted file mode 100644
index 31509bbf8de0..000000000000
--- a/back/spec/services/side_fx_initiative_status_change_service_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-describe SideFxInitiativeStatusChangeService do
- let(:service) { described_class.new }
- let(:user) { create(:user) }
- let(:initiative) { create(:initiative, author: user) }
-
- describe '#after_create' do
- context "when status change is to 'proposed'" do
- let!(:initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: initiative,
- initiative_status: create(:initiative_status_proposed)
- )
- end
-
- it 'logs a proposed activity job' do
- expect { service.after_create(initiative_status_change, user) }
- .to enqueue_job(LogActivityJob)
- .with(initiative_status_change.initiative, 'proposed', user, instance_of(Integer))
- .exactly(1).times
- end
- end
-
- context "when status change is to 'review_pending'" do
- let!(:initiative_status_change) do
- create(
- :initiative_status_change,
- initiative: initiative,
- initiative_status: create(:initiative_status_review_pending)
- )
- end
-
- it "doesn't log a proposed activity job" do
- expect { service.after_create(initiative_status_change, user) }
- .not_to enqueue_job(LogActivityJob)
- .with(instance_of(Initiative), 'proposed', anything, anything)
- end
- end
- end
-end