From 6d66070b65645f5c820c3a76889431d7759351ec Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 11:42:40 +0000
Subject: [PATCH 01/63] [TAN-2538] Remove seeding of initiatives
---
.../multi_tenancy/db/seeds/initiatives.rb | 56 -------------------
.../multi_tenancy/db/seeds/runner.rb | 16 +-----
2 files changed, 3 insertions(+), 69 deletions(-)
delete mode 100644 back/engines/commercial/multi_tenancy/db/seeds/initiatives.rb
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
From 3b450c999901879d2f5f3023ea7d687637cefb40 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 11:56:01 +0000
Subject: [PATCH 02/63] [TAN-2538] Remove web_api/v1 controller + routes - see
what breaks
---
.../web_api/v1/initiatives_controller.rb | 244 ------------------
back/config/routes.rb | 16 --
2 files changed, 260 deletions(-)
delete mode 100644 back/app/controllers/web_api/v1/initiatives_controller.rb
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/config/routes.rb b/back/config/routes.rb
index 6674a5f89cd9..e8d1d8fe4c8a 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
From 7952f5508c981eb94a473584d6cf6bb336eaf16b Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 12:17:57 +0000
Subject: [PATCH 03/63] [TAN-2538] Remove _status_changes_ & _statuses_
controllers & obviosuly related specs
---
.../initiative_status_changes_controller.rb | 83 --
.../v1/initiative_statuses_controller.rb | 22 -
.../spec/acceptance/initiatives_spec.rb | 74 --
.../acceptance/initiative_comments_spec.rb | 359 --------
back/spec/acceptance/initiative_files_spec.rb | 76 --
.../spec/acceptance/initiative_images_spec.rb | 87 --
.../initiative_official_feedbacks_spec.rb | 132 ---
.../acceptance/initiative_reactions_spec.rb | 148 ----
.../acceptance/initiative_spam_report_spec.rb | 84 --
.../initiative_status_changes_spec.rb | 227 -----
.../acceptance/initiative_statuses_spec.rb | 33 -
back/spec/acceptance/initiatives_spec.rb | 796 ------------------
12 files changed, 2121 deletions(-)
delete mode 100644 back/app/controllers/web_api/v1/initiative_status_changes_controller.rb
delete mode 100644 back/app/controllers/web_api/v1/initiative_statuses_controller.rb
delete mode 100644 back/engines/commercial/flag_inappropriate_content/spec/acceptance/initiatives_spec.rb
delete mode 100644 back/spec/acceptance/initiative_comments_spec.rb
delete mode 100644 back/spec/acceptance/initiative_files_spec.rb
delete mode 100644 back/spec/acceptance/initiative_images_spec.rb
delete mode 100644 back/spec/acceptance/initiative_official_feedbacks_spec.rb
delete mode 100644 back/spec/acceptance/initiative_reactions_spec.rb
delete mode 100644 back/spec/acceptance/initiative_spam_report_spec.rb
delete mode 100644 back/spec/acceptance/initiative_status_changes_spec.rb
delete mode 100644 back/spec/acceptance/initiative_statuses_spec.rb
delete mode 100644 back/spec/acceptance/initiatives_spec.rb
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/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/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
From 14c692e547c91e8e08ecba0d5befbcbb409f9a82 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 12:32:39 +0000
Subject: [PATCH 04/63] [TAN-2538] Fix test in rack_attack_spec
---
back/spec/requests/rack_attack_spec.rb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
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
From 2c6c10c2754d8ac9fa8426f55a651e74a1adbe8d Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 12:36:24 +0000
Subject: [PATCH 05/63] [TAN-2538] Fix test in followers_spec
---
back/spec/acceptance/followers_spec.rb | 6 ------
1 file changed, 6 deletions(-)
diff --git a/back/spec/acceptance/followers_spec.rb b/back/spec/acceptance/followers_spec.rb
index 23db18c2f4af..ba4da1cb4a85 100644
--- a/back/spec/acceptance/followers_spec.rb
+++ b/back/spec/acceptance/followers_spec.rb
@@ -50,7 +50,6 @@
end
end
- # TODO: cleanup-after-proposals-migration
get 'web_api/v1/followers/:id' do
let(:id) { create(:follower, user: user).id }
@@ -77,11 +76,6 @@
resource: 'ideas',
factory: 'idea'
},
- {
- type: 'initiative',
- resource: 'initiatives',
- factory: 'initiative'
- },
{
type: 'topic',
resource: 'topics',
From f59794f87569c66a02a6ac3f00bf8194771adf87 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 12:38:56 +0000
Subject: [PATCH 06/63] [TAN-2538] Remove tests from internal_comments_spec
---
.../spec/acceptance/internal_comments_spec.rb | 273 ------------------
1 file changed, 273 deletions(-)
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
From 72b13a26d4d7e2b1da5746926d5221f84e094ddf Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 14:44:25 +0000
Subject: [PATCH 07/63] [TAN-2538] Remove serializers & spec
---
.../web_api/v1/initiative_serializer.rb | 98 ----------------
.../v1/initiative_status_change_serializer.rb | 10 --
.../v1/initiative_status_serializer.rb | 9 --
.../web_api/v1/initiative_serializer_spec.rb | 105 ------------------
4 files changed, 222 deletions(-)
delete mode 100644 back/app/serializers/web_api/v1/initiative_serializer.rb
delete mode 100644 back/app/serializers/web_api/v1/initiative_status_change_serializer.rb
delete mode 100644 back/app/serializers/web_api/v1/initiative_status_serializer.rb
delete mode 100644 back/spec/serializers/web_api/v1/initiative_serializer_spec.rb
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/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
From 7b704a2cc3eb323743bfc9d9ac254b0dc190cc82 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 15:06:19 +0000
Subject: [PATCH 08/63] [TAN-2538] Fix tests + remove from machine_translations
controller & routes
---
.../v1/machine_translations_controller.rb | 4 --
.../machine_translations/config/routes.rb | 3 --
.../acceptance/machine_translations_spec.rb | 49 -------------------
back/spec/acceptance/followers_spec.rb | 5 +-
back/spec/acceptance/user_comments_spec.rb | 3 +-
5 files changed, 3 insertions(+), 61 deletions(-)
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/spec/acceptance/followers_spec.rb b/back/spec/acceptance/followers_spec.rb
index ba4da1cb4a85..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
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)
From 512c00b8699554c334b308d9eb90c32823ebfbf9 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 15:16:17 +0000
Subject: [PATCH 09/63] [TAN-2538] Remove 8 initiative related policies & 4
related specs
---
.../app/policies/initiative_comment_policy.rb | 58 ---
back/app/policies/initiative_file_policy.rb | 25 --
back/app/policies/initiative_image_policy.rb | 25 --
.../initiative_official_feedback_policy.rb | 25 --
back/app/policies/initiative_policy.rb | 92 ----
.../policies/initiative_reaction_policy.rb | 45 --
.../initiative_status_change_policy.rb | 22 -
back/app/policies/initiative_status_policy.rb | 43 --
.../initiative_comment_policy_spec.rb | 176 --------
back/spec/policies/initiative_policy_spec.rb | 417 ------------------
.../initiative_reaction_policy_spec.rb | 74 ----
.../policies/initiative_status_policy_spec.rb | 81 ----
12 files changed, 1083 deletions(-)
delete mode 100644 back/app/policies/initiative_comment_policy.rb
delete mode 100644 back/app/policies/initiative_file_policy.rb
delete mode 100644 back/app/policies/initiative_image_policy.rb
delete mode 100644 back/app/policies/initiative_official_feedback_policy.rb
delete mode 100644 back/app/policies/initiative_policy.rb
delete mode 100644 back/app/policies/initiative_reaction_policy.rb
delete mode 100644 back/app/policies/initiative_status_change_policy.rb
delete mode 100644 back/app/policies/initiative_status_policy.rb
delete mode 100644 back/spec/policies/initiative_comment_policy_spec.rb
delete mode 100644 back/spec/policies/initiative_policy_spec.rb
delete mode 100644 back/spec/policies/initiative_reaction_policy_spec.rb
delete mode 100644 back/spec/policies/initiative_status_policy_spec.rb
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/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
From 0c2edf7245d465b45d915c14288428442c2a2d89 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 15:32:29 +0000
Subject: [PATCH 10/63] [TAN-2538] Remove from CONSTANTIZER in imges & files
controllers
---
back/app/controllers/web_api/v1/files_controller.rb | 7 -------
back/app/controllers/web_api/v1/images_controller.rb | 7 -------
2 files changed, 14 deletions(-)
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,
From fb6058c4c428eaca9a1efefd30f7c7879512902f Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 15:43:27 +0000
Subject: [PATCH 11/63] [TAN-2538] Remove from Folower FOLLOWABLE_TYPES +
folllower_policy_spec tests
---
back/app/models/follower.rb | 2 +-
back/spec/policies/follower_policy_spec.rb | 40 ----------------------
2 files changed, 1 insertion(+), 41 deletions(-)
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/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) }
From a0f51a42e5705d84c2186b5720f4a1c76911fd63 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 15:48:05 +0000
Subject: [PATCH 12/63] [TAN-2538] Remove from UserCommentsController
---
.../app/controllers/web_api/v1/user_comments_controller.rb | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
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)
From 4b8420e32084cc5b46cd041a61be2beb487dc75c Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 15:55:46 +0000
Subject: [PATCH 13/63] [TAN-2538] Comment out
back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
---
.../spec/graphql/initiatives_spec.rb | 125 +++++++++---------
1 file changed, 65 insertions(+), 60 deletions(-)
diff --git a/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb b/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
index 1451fb27ae6f..9a8f9c0b703f 100644
--- a/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
+++ b/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
@@ -3,65 +3,70 @@
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
+#
+# Commented out for now, just so I can use CI to see other failures clearly, and because I'm not sure what
+# we want to do about the admin_api for Initiatives. Maybe we remove it all, or maybe we keep it and return useful
+# errors, like 'initiatives are no longer supported as a separate model, use ideas instead' or something.
+#
+# 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
+# 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
+# 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
From 0910e982abe89516e99264320478406170f7da38 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 16:02:45 +0000
Subject: [PATCH 14/63] [TAN-2538] Remove stats_initiatives routes, controller
& spec
---
.../v1/stats_initiatives_controller.rb | 16 ---
back/config/routes.rb | 3 -
.../spec/acceptance/stats_initiatives_spec.rb | 98 -------------------
3 files changed, 117 deletions(-)
delete mode 100644 back/app/controllers/web_api/v1/stats_initiatives_controller.rb
delete mode 100644 back/spec/acceptance/stats_initiatives_spec.rb
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/config/routes.rb b/back/config/routes.rb
index e8d1d8fe4c8a..9c2cb889a981 100644
--- a/back/config/routes.rb
+++ b/back/config/routes.rb
@@ -100,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: /.*/ }
@@ -263,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/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
From 6660cd77897b6017302a95cce025328a198d1614 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 16:13:26 +0000
Subject: [PATCH 15/63] [TAN-2538] Remove test from avatars_spec
---
back/spec/acceptance/avatars_spec.rb | 20 --------------------
1 file changed, 20 deletions(-)
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 }
From 24c653fad554e4bf2a2f0c5667070373df7e08da Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 16:13:51 +0000
Subject: [PATCH 16/63] [TAN-2538] Remove SideFxInitiativesService + spec
---
.../services/side_fx_initiative_service.rb | 158 --------------
.../patches/side_fx_initiative_service.rb | 34 ---
.../side_fx_initiative_service_spec.rb | 204 ------------------
3 files changed, 396 deletions(-)
delete mode 100644 back/app/services/side_fx_initiative_service.rb
delete mode 100644 back/engines/commercial/flag_inappropriate_content/app/services/flag_inappropriate_content/patches/side_fx_initiative_service.rb
delete mode 100644 back/spec/services/side_fx_initiative_service_spec.rb
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/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/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
From ebbbdba5ff19da52f378ebda74aa31c9a5d4c95c Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 16:51:54 +0000
Subject: [PATCH 17/63] [TAN-2538] Comment out problematic test in
SideFxCommentService + add explanatory comments
---
.../services/side_fx_comment_service_spec.rb | 27 ++++++++++++-------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/back/spec/services/side_fx_comment_service_spec.rb b/back/spec/services/side_fx_comment_service_spec.rb
index b0d696856d99..0a789612c208 100644
--- a/back/spec/services/side_fx_comment_service_spec.rb
+++ b/back/spec/services/side_fx_comment_service_spec.rb
@@ -47,15 +47,24 @@
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)
-
- expect do
- service.after_create comment, user
- end.not_to change(Follower, :count)
- end
+ # TODO: Part of initiatives cleanup
+ # I have commented this out, for now, as it fails if I change initiative to idea
+ # This seems to be because the related `after_create` method in fact creates a folllower for the related project,
+ # and intitiatives never had a related project.
+ # Furthermore, it appears that the `after_create` method will go on to also create another follower for the
+ # project's folder, it there is one.
+ # Thus, this test was not as general (to Post) as it might have seemed + I think we need to check that the cascading
+ # follower creations (idea -> project -> folder as followable) is intended & necessary.
+ #
+ # 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)
+
+ # expect do
+ # service.after_create comment, user
+ # end.not_to change(Follower, :count)
+ # end
end
describe 'after_update' do
From 6d9bcb4776e287cb0c60bab11bc8c6a5f2331212 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 16:57:08 +0000
Subject: [PATCH 18/63] [TAN-2538] Remove InitiativesFinder + spec
---
back/app/finders/initiatives_finder.rb | 62 ------
back/spec/finders/initiatives_finder_spec.rb | 195 -------------------
2 files changed, 257 deletions(-)
delete mode 100644 back/app/finders/initiatives_finder.rb
delete mode 100644 back/spec/finders/initiatives_finder_spec.rb
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/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
From af95d9786f6ed212b9efb81a0ac9660fc8d30402 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 17:18:45 +0000
Subject: [PATCH 19/63] [TAN-1084] Remove initiatives from
UserController#comments_count + clean up users_spec
---
.../web_api/v1/users_controller.rb | 8 ++---
back/spec/acceptance/users_spec.rb | 33 ++-----------------
2 files changed, 5 insertions(+), 36 deletions(-)
diff --git a/back/app/controllers/web_api/v1/users_controller.rb b/back/app/controllers/web_api/v1/users_controller.rb
index 8f2e579fd60b..b36f70e5ecda 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
+ # This test won't make sense once 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/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
From df14123e37e0116db396e19f98f9041dfa28602c Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 17:19:46 +0000
Subject: [PATCH 20/63] [TAN-1084] Remove comment_on_initiative_you_follow
notification + spec
---
.../comment_on_initiative_you_follow.rb | 96 -------------------
.../comment_on_initiative_you_follow_spec.rb | 33 -------
2 files changed, 129 deletions(-)
delete mode 100644 back/app/models/notifications/comment_on_initiative_you_follow.rb
delete mode 100644 back/spec/models/notifications/comment_on_initiative_you_follow_spec.rb
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 210a153d1da7..000000000000
--- a/back/app/models/notifications/comment_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
-#
-# 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_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_... (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/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
From fa6efd6e6c887804c333b12f05820ccd704963dd Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 17:26:35 +0000
Subject: [PATCH 21/63] [TAN-1084] Remove
notifications/status_change_on_initiative_you_follow + spec
---
.../status_change_on_initiative_you_follow.rb | 93 -------------------
.../analytics/populate_dimensions_service.rb | 6 +-
.../populate_dimensions_service_spec.rb | 4 +-
...us_change_on_initiative_you_follow_spec.rb | 39 --------
4 files changed, 3 insertions(+), 139 deletions(-)
delete mode 100644 back/app/models/notifications/status_change_on_initiative_you_follow.rb
delete mode 100644 back/spec/models/notifications/status_change_on_initiative_you_follow_spec.rb
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 78182563c275..000000000000
--- a/back/app/models/notifications/status_change_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,93 +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
-#
-# 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_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_... (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/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/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/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
From c921772f822ae0802fe9d46bfbe289e3f7dec141 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 17:28:05 +0000
Subject: [PATCH 22/63] [TAN-1084] Remove
side_fx_initiative_status_change_service + spec
---
...ide_fx_initiative_status_change_service.rb | 21 ---------
...x_initiative_status_change_service_spec.rb | 45 -------------------
2 files changed, 66 deletions(-)
delete mode 100644 back/app/services/side_fx_initiative_status_change_service.rb
delete mode 100644 back/spec/services/side_fx_initiative_status_change_service_spec.rb
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/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
From 910021628680c9d02f6930d608dc3e2cca11ce43 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Tue, 17 Dec 2024 17:29:29 +0000
Subject: [PATCH 23/63] [TAN-1084] Remove
notifications/official_feedback_on_initiative_you_follow + spec
---
...icial_feedback_on_initiative_you_follow.rb | 98 -------------------
..._feedback_on_initiative_you_follow_spec.rb | 62 ------------
2 files changed, 160 deletions(-)
delete mode 100644 back/app/models/notifications/official_feedback_on_initiative_you_follow.rb
delete mode 100644 back/spec/models/notifications/official_feedback_on_initiative_you_follow_spec.rb
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 4a738eff9ec5..000000000000
--- a/back/app/models/notifications/official_feedback_on_initiative_you_follow.rb
+++ /dev/null
@@ -1,98 +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
-#
-# 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_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_... (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/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
From cf688c94a4ffd40449a176b3ddd94d301dc75e58 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 09:19:31 +0000
Subject: [PATCH 24/63] [TAN-2538] Remove 3 deleted notification classes from
NotificationService NOTIFICATION_CLASSES
---
back/app/services/notification_service.rb | 3 ---
1 file changed, 3 deletions(-)
diff --git a/back/app/services/notification_service.rb b/back/app/services/notification_service.rb
index b836c6ce1334..1e72f4b1b590 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -6,7 +6,6 @@ class NotificationService
Notifications::CommentDeletedByAdmin,
Notifications::CommentMarkedAsSpam,
Notifications::CommentOnIdeaYouFollow,
- Notifications::CommentOnInitiativeYouFollow,
Notifications::CommentOnYourComment,
Notifications::CosponsorOfYourIdea,
Notifications::CosponsorOfYourInitiative,
@@ -30,7 +29,6 @@ class NotificationService
Notifications::MentionInOfficialFeedback,
Notifications::NativeSurveyNotSubmitted,
Notifications::OfficialFeedbackOnIdeaYouFollow,
- Notifications::OfficialFeedbackOnInitiativeYouFollow,
Notifications::ProjectFolderModerationRightsReceived,
Notifications::ProjectModerationRightsReceived,
Notifications::ProjectPhaseStarted,
@@ -39,7 +37,6 @@ class NotificationService
Notifications::ProjectReviewRequest,
Notifications::ProjectReviewStateChange,
Notifications::StatusChangeOnIdeaYouFollow,
- Notifications::StatusChangeOnInitiativeYouFollow,
Notifications::ThresholdReachedForAdmin,
Notifications::VotingBasketNotSubmitted,
Notifications::VotingBasketSubmitted,
From a9014e4a9c2c52206b3c4c9ec118e433828fcd47 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 09:41:30 +0000
Subject: [PATCH 25/63] [TAN-2538] Remove test from notification service
---
back/spec/serializers/web_api/v1/notifications_spec.rb | 7 -------
1 file changed, 7 deletions(-)
diff --git a/back/spec/serializers/web_api/v1/notifications_spec.rb b/back/spec/serializers/web_api/v1/notifications_spec.rb
index b5a12b4d3c9e..4ccf9d0f2e4e 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,
From 9df49f0d0fda2780ef5ce73d9818589ed8f12fcb Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 09:48:46 +0000
Subject: [PATCH 26/63] [TAN-2538] Remove
status_change_on_initiative_you_follow mail code & specs
---
...nge_on_initiative_you_follow_serializer.rb | 15 ---
..._change_on_initiative_you_follow_mailer.rb | 29 ------
.../status_change_on_initiative_you_follow.rb | 95 -------------------
.../spec/factories/campaigns.rb | 4 -
...on_initiative_you_follow_mailer_preview.rb | 18 ----
...ge_on_initiative_you_follow_mailer_spec.rb | 45 ---------
...us_change_on_initiative_you_follow_spec.rb | 38 --------
back/spec/factories/notifications.rb | 8 --
8 files changed, 252 deletions(-)
delete mode 100644 back/app/serializers/web_api/v1/notifications/status_change_on_initiative_you_follow_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/status_change_on_initiative_you_follow_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/status_change_on_initiative_you_follow.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/status_change_on_initiative_you_follow_mailer_preview.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/status_change_on_initiative_you_follow_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/status_change_on_initiative_you_follow_spec.rb
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/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/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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 2f45ee7afadf..83d15041ddb9 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -190,10 +190,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/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/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/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/factories/notifications.rb b/back/spec/factories/notifications.rb
index 8ed70d4f7e65..56c2bad6d803 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -236,14 +236,6 @@
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_status, factory: :proposals_status
From c05e9fd6ccfcae5f1e8bdf838b32417327cd42b4 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 09:56:06 +0000
Subject: [PATCH 27/63] [TAN-2538] Remove MJML for
StatusChangeOnInitiativeYouFollow
---
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 17 -----------------
2 files changed, 18 deletions(-)
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/status_change_on_initiative_you_follow_mailer/campaign_mail.mjml
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..f1d727ca38e3 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
@@ -51,7 +51,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/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 %>
From 5586579828b0a5d4c3975a34894a063eed3849d6 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 10:04:06 +0000
Subject: [PATCH 28/63] [TAN-2538] Fix footer spec
---
.../free/email_campaigns/spec/mailers/footer_spec.rb | 8 ++++----
back/spec/jobs/log_activity_job_spec.rb | 3 ---
2 files changed, 4 insertions(+), 7 deletions(-)
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/spec/jobs/log_activity_job_spec.rb b/back/spec/jobs/log_activity_job_spec.rb
index 476920f7b05f..71c84ea8b6ee 100644
--- a/back/spec/jobs/log_activity_job_spec.rb
+++ b/back/spec/jobs/log_activity_job_spec.rb
@@ -178,7 +178,6 @@
Notifications::CommentMarkedAsSpam,
Notifications::CommentOnYourComment,
Notifications::CommentOnIdeaYouFollow,
- Notifications::CommentOnInitiativeYouFollow,
Notifications::IdeaMarkedAsSpam,
Notifications::InitiativeAssignedToYou,
Notifications::InitiativeMarkedAsSpam,
@@ -187,14 +186,12 @@
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,
From cea1e4c402deeb3972143baff5970d32533cda4f Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 10:06:24 +0000
Subject: [PATCH 29/63] [TAN-2538] Remove OfficialFeedbackOnInitiativeYouFollow
mail files & spec
---
...eedback_on_initiative_you_follow_mailer.rb | 36 --------------
.../campaign_mail.mjml | 7 ---
...ck_on_initiative_you_follow_mailer_spec.rb | 48 -------------------
...on_initiative_you_follow_mailer_preview.rb | 25 ----------
4 files changed, 116 deletions(-)
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/official_feedback_on_initiative_you_follow_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/official_feedback_on_initiative_you_follow_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/official_feedback_on_initiative_you_follow_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/official_feedback_on_initiative_you_follow_mailer_preview.rb
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/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/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/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
From 5a4e47062c7dfcc6c050fa94f28bd789a66ae442 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 10:08:39 +0000
Subject: [PATCH 30/63] [TAN-2538] Remove test from notification_spec
---
back/spec/models/notification_spec.rb | 8 --------
1 file changed, 8 deletions(-)
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)
From d56f56e8c450a8066dfd4dff04075ef5eecebf72 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 10:13:16 +0000
Subject: [PATCH 31/63] [TAN-2538] Remove test from fact_participation_spec
---
.../spec/models/analytics/fact_participation_spec.rb | 10 ----------
1 file changed, 10 deletions(-)
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) }
From 68c5c935238c1b1d8abc60b29a186173ff91944f Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 10:18:55 +0000
Subject: [PATCH 32/63] [TAN-2538] Remove comment_on_initiative_you_follow mail
files & specs
---
...ent_on_initiative_you_follow_serializer.rb | 24 -----
...comment_on_initiative_you_follow_mailer.rb | 30 -------
.../comment_on_initiative_you_follow.rb | 89 -------------------
.../campaign_mail.mjml | 23 -----
...nt_on_initiative_you_follow_mailer_spec.rb | 53 -----------
...on_initiative_you_follow_mailer_preview.rb | 25 ------
.../comment_on_initiative_you_follow_spec.rb | 53 -----------
7 files changed, 297 deletions(-)
delete mode 100644 back/app/serializers/web_api/v1/notifications/comment_on_initiative_you_follow_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/comment_on_initiative_you_follow_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/comment_on_initiative_you_follow.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/comment_on_initiative_you_follow_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/comment_on_initiative_you_follow_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/comment_on_initiative_you_follow_mailer_preview.rb
delete mode 100644 back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/comment_on_initiative_you_follow_spec.rb
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/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/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/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/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/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/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
From 647aee6cf6ca8f6ede87a8b4879fa5312543df04 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 11:01:28 +0000
Subject: [PATCH 33/63] [TAN-2538] Remove constant value & factory of removed
campaign
---
.../app/services/email_campaigns/delivery_service.rb | 1 -
back/engines/free/email_campaigns/spec/factories/campaigns.rb | 4 ----
2 files changed, 5 deletions(-)
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 f1d727ca38e3..fe1909a6c761 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,7 +9,6 @@ class DeliveryService
Campaigns::CommentDeletedByAdmin,
Campaigns::CommentMarkedAsSpam,
Campaigns::CommentOnIdeaYouFollow,
- Campaigns::CommentOnInitiativeYouFollow,
Campaigns::CommentOnYourComment,
Campaigns::CosponsorOfYourInitiative,
Campaigns::CosponsorOfYourIdea,
diff --git a/back/engines/free/email_campaigns/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 83d15041ddb9..264c1e7e72f0 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -42,10 +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
From f16dbacfab773f90f91bfe67dfe32887d5ae87b3 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 11:17:16 +0000
Subject: [PATCH 34/63] [TAN-2538] Remove OfficialFeedbackOnInitiativeYouFollow
campaign files & spec
---
...ack_on_initiative_you_follow_serializer.rb | 15 ----
...icial_feedback_on_initiative_you_follow.rb | 87 -------------------
..._feedback_on_initiative_you_follow_spec.rb | 35 --------
3 files changed, 137 deletions(-)
delete mode 100644 back/app/serializers/web_api/v1/notifications/official_feedback_on_initiative_you_follow_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow.rb
delete mode 100644 back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/official_feedback_on_initiative_you_follow_spec.rb
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/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/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
From 4bd4c164c3d1460773492683c1438ac85ff7c9b6 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 11:38:05 +0000
Subject: [PATCH 35/63] [TAN-2538] Remove OfficialFeedbackOnInitiativeYouFollow
factory
---
back/engines/free/email_campaigns/spec/factories/campaigns.rb | 4 ----
1 file changed, 4 deletions(-)
diff --git a/back/engines/free/email_campaigns/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 264c1e7e72f0..0cce94c7671d 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -150,10 +150,6 @@
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
From 5b85c7820d3aea106c7d5eeeb2db889d622c48c0 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 11:40:26 +0000
Subject: [PATCH 36/63] [TAN-2538] Remove OfficialFeedbackOnInitiativeYouFollow
notification factory
---
.../app/services/email_campaigns/delivery_service.rb | 1 -
back/spec/factories/notifications.rb | 6 ------
2 files changed, 7 deletions(-)
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 fe1909a6c761..00371aca317c 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
@@ -41,7 +41,6 @@ class DeliveryService
Campaigns::NewIdeaForAdmin,
Campaigns::NewInitiativeForAdmin,
Campaigns::OfficialFeedbackOnIdeaYouFollow,
- Campaigns::OfficialFeedbackOnInitiativeYouFollow,
Campaigns::ProjectFolderModerationRightsReceived,
Campaigns::ProjectModerationRightsReceived,
Campaigns::ProjectPhaseStarted,
diff --git a/back/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index 56c2bad6d803..cdda0e6bb41e 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -185,12 +185,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
From f2f7f65747f5a0eeb240b94c1a77583a8617a06f Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 11:57:37 +0000
Subject: [PATCH 37/63] [TAN-2538] Fix campaigns_spec
---
.../free/email_campaigns/spec/acceptance/campaigns_spec.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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
From bfd31f31a9bc056086b7809c58a7585854a6347b Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 12:11:29 +0000
Subject: [PATCH 38/63] [TAN-2538] Fix notifications_spec
---
back/spec/serializers/web_api/v1/notifications_spec.rb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/back/spec/serializers/web_api/v1/notifications_spec.rb b/back/spec/serializers/web_api/v1/notifications_spec.rb
index 4ccf9d0f2e4e..7e889d37d62d 100644
--- a/back/spec/serializers/web_api/v1/notifications_spec.rb
+++ b/back/spec/serializers/web_api/v1/notifications_spec.rb
@@ -50,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
From 2514774d6a08d6e53b21f4ae1d7e629015938b07 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 12:27:04 +0000
Subject: [PATCH 39/63] [TAN-2538] Improve tests in
side_fx-comment_service_spec
---
.../services/side_fx_comment_service_spec.rb | 38 +++++++++----------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/back/spec/services/side_fx_comment_service_spec.rb b/back/spec/services/side_fx_comment_service_spec.rb
index 0a789612c208..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,24 +47,24 @@
expect(user.follows.pluck(:followable_id)).to contain_exactly idea.id, project.id, folder.id
end
- # TODO: Part of initiatives cleanup
- # I have commented this out, for now, as it fails if I change initiative to idea
- # This seems to be because the related `after_create` method in fact creates a folllower for the related project,
- # and intitiatives never had a related project.
- # Furthermore, it appears that the `after_create` method will go on to also create another follower for the
- # project's folder, it there is one.
- # Thus, this test was not as general (to Post) as it might have seemed + I think we need to check that the cascading
- # follower creations (idea -> project -> folder as followable) is intended & necessary.
- #
- # 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)
-
- # expect do
- # service.after_create comment, user
- # end.not_to change(Follower, :count)
- # end
+ 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)
+
+ 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
describe 'after_update' do
From 0eaad86af08e00d8dc9f0ed6b5f9d34b89d0b747 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 12:38:14 +0000
Subject: [PATCH 40/63] [TAN-2538] Remove InitiativeAssignedToYou notification
& campaign files & specs
---
.../initiative_assigned_to_you.rb | 99 -------------------
.../initiative_assigned_to_you_serializer.rb | 24 -----
back/app/services/notification_service.rb | 1 -
.../initiative_assigned_to_you_mailer.rb | 25 -----
.../campaigns/initiative_assigned_to_you.rb | 91 -----------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 20 ----
.../spec/factories/campaigns.rb | 4 -
.../initiative_assigned_to_you_mailer_spec.rb | 53 ----------
...itiative_assigned_to_you_mailer_preview.rb | 28 ------
back/spec/factories/notifications.rb | 5 -
back/spec/jobs/log_activity_job_spec.rb | 1 -
12 files changed, 352 deletions(-)
delete mode 100644 back/app/models/notifications/initiative_assigned_to_you.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/initiative_assigned_to_you_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_assigned_to_you_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_assigned_to_you.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/initiative_assigned_to_you_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/initiative_assigned_to_you_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_assigned_to_you_mailer_preview.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index 1e72f4b1b590..4355e829dd11 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -10,7 +10,6 @@ class NotificationService
Notifications::CosponsorOfYourIdea,
Notifications::CosponsorOfYourInitiative,
Notifications::IdeaMarkedAsSpam,
- Notifications::InitiativeAssignedToYou,
Notifications::InitiativeMarkedAsSpam,
Notifications::InitiativeResubmittedForReview,
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index 00371aca317c..a8cdf04d2f9d 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
@@ -15,7 +15,6 @@ class DeliveryService
Campaigns::EventRegistrationConfirmation,
Campaigns::IdeaMarkedAsSpam,
Campaigns::IdeaPublished,
- Campaigns::InitiativeAssignedToYou,
Campaigns::InitiativeMarkedAsSpam,
Campaigns::InitiativePublished,
Campaigns::InitiativeResubmittedForReview,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 0cce94c7671d..4467107b1d47 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -70,10 +70,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
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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index cdda0e6bb41e..95f8f7629a0a 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -114,11 +114,6 @@
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
diff --git a/back/spec/jobs/log_activity_job_spec.rb b/back/spec/jobs/log_activity_job_spec.rb
index 71c84ea8b6ee..c138677d8d1f 100644
--- a/back/spec/jobs/log_activity_job_spec.rb
+++ b/back/spec/jobs/log_activity_job_spec.rb
@@ -179,7 +179,6 @@
Notifications::CommentOnYourComment,
Notifications::CommentOnIdeaYouFollow,
Notifications::IdeaMarkedAsSpam,
- Notifications::InitiativeAssignedToYou,
Notifications::InitiativeMarkedAsSpam,
Notifications::InviteAccepted,
Notifications::MarkedAsSpam,
From 83a5c8661f174a6e6e97beb35fb0859863f9daa0 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 12:51:25 +0000
Subject: [PATCH 41/63] [TAN-2538] Remove InitiativeMarkedAsSpam notification &
campaign files & specs
---
.../initiative_marked_as_spam.rb | 96 -------------------
.../initiative_marked_as_spam_serializer.rb | 24 -----
back/app/services/notification_service.rb | 1 -
.../initiative_marked_as_spam_mailer.rb | 25 -----
.../campaigns/initiative_marked_as_spam.rb | 93 ------------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 42 --------
.../spec/factories/campaigns.rb | 4 -
.../initiative_marked_as_spam_mailer_spec.rb | 58 -----------
...nitiative_marked_as_spam_mailer_preview.rb | 31 ------
back/spec/factories/notifications.rb | 6 --
back/spec/jobs/log_activity_job_spec.rb | 1 -
12 files changed, 382 deletions(-)
delete mode 100644 back/app/models/notifications/initiative_marked_as_spam.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/initiative_marked_as_spam_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_marked_as_spam_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_marked_as_spam.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/initiative_marked_as_spam_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/initiative_marked_as_spam_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_marked_as_spam_mailer_preview.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index 4355e829dd11..1e3f79b97f46 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -10,7 +10,6 @@ class NotificationService
Notifications::CosponsorOfYourIdea,
Notifications::CosponsorOfYourInitiative,
Notifications::IdeaMarkedAsSpam,
- Notifications::InitiativeMarkedAsSpam,
Notifications::InitiativeResubmittedForReview,
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
Notifications::InternalComments::InternalCommentOnIdeaYouCommentedInternallyOn,
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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index a8cdf04d2f9d..03ba809dac66 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
@@ -15,7 +15,6 @@ class DeliveryService
Campaigns::EventRegistrationConfirmation,
Campaigns::IdeaMarkedAsSpam,
Campaigns::IdeaPublished,
- Campaigns::InitiativeMarkedAsSpam,
Campaigns::InitiativePublished,
Campaigns::InitiativeResubmittedForReview,
Campaigns::InternalCommentOnIdeaAssignedToYou,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 4467107b1d47..92813ee09da0 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -70,10 +70,6 @@
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
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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index 95f8f7629a0a..c1f1a82b51fa 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -114,12 +114,6 @@
initiating_user
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
diff --git a/back/spec/jobs/log_activity_job_spec.rb b/back/spec/jobs/log_activity_job_spec.rb
index c138677d8d1f..ada3362cf134 100644
--- a/back/spec/jobs/log_activity_job_spec.rb
+++ b/back/spec/jobs/log_activity_job_spec.rb
@@ -179,7 +179,6 @@
Notifications::CommentOnYourComment,
Notifications::CommentOnIdeaYouFollow,
Notifications::IdeaMarkedAsSpam,
- Notifications::InitiativeMarkedAsSpam,
Notifications::InviteAccepted,
Notifications::MarkedAsSpam,
Notifications::MentionInComment,
From 776db9129462a2e3174e1c0c6114907f3dfd229d Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 12:52:58 +0000
Subject: [PATCH 42/63] [TAN-2538] Remove InitiativePublished campaign files &
specs
---
.../initiative_published_mailer.rb | 25 ----
.../campaigns/initiative_published.rb | 94 ---------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 111 ------------------
.../initiative_published_mailer_spec.rb | 58 ---------
.../initiative_published_mailer_preview.rb | 35 ------
6 files changed, 324 deletions(-)
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_published_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_published.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/initiative_published_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/initiative_published_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_published_mailer_preview.rb
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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index 03ba809dac66..76823d0b9b8a 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
@@ -15,7 +15,6 @@ class DeliveryService
Campaigns::EventRegistrationConfirmation,
Campaigns::IdeaMarkedAsSpam,
Campaigns::IdeaPublished,
- Campaigns::InitiativePublished,
Campaigns::InitiativeResubmittedForReview,
Campaigns::InternalCommentOnIdeaAssignedToYou,
Campaigns::InternalCommentOnIdeaYouCommentedInternallyOn,
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/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/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
From 6e4eb312b50361a41221267631711764887c783b Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 12:55:47 +0000
Subject: [PATCH 43/63] [TAN-2538] Remove InitiativeResubmittedForReview
notification & campaign files & specs
---
.../initiative_resubmitted_for_review.rb | 104 ------------------
...ative_resubmitted_for_review_serializer.rb | 11 --
back/app/services/notification_service.rb | 1 -
...nitiative_resubmitted_for_review_mailer.rb | 25 -----
.../initiative_resubmitted_for_review.rb | 84 --------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 20 ----
.../spec/factories/campaigns.rb | 8 --
...tive_resubmitted_for_review_mailer_spec.rb | 45 --------
...e_resubmitted_for_review_mailer_preview.rb | 19 ----
back/spec/factories/notifications.rb | 5 -
.../initiative_resubmitted_for_review_spec.rb | 21 ----
12 files changed, 344 deletions(-)
delete mode 100644 back/app/models/notifications/initiative_resubmitted_for_review.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/initiative_resubmitted_for_review_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/initiative_resubmitted_for_review_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/initiative_resubmitted_for_review.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/initiative_resubmitted_for_review_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/initiative_resubmitted_for_review_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/initiative_resubmitted_for_review_mailer_preview.rb
delete mode 100644 back/spec/models/notifications/initiative_resubmitted_for_review_spec.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index 1e3f79b97f46..702d933276b4 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -10,7 +10,6 @@ class NotificationService
Notifications::CosponsorOfYourIdea,
Notifications::CosponsorOfYourInitiative,
Notifications::IdeaMarkedAsSpam,
- Notifications::InitiativeResubmittedForReview,
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
Notifications::InternalComments::InternalCommentOnIdeaYouCommentedInternallyOn,
Notifications::InternalComments::InternalCommentOnIdeaYouModerate,
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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index 76823d0b9b8a..2edb826dbe56 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
@@ -15,7 +15,6 @@ class DeliveryService
Campaigns::EventRegistrationConfirmation,
Campaigns::IdeaMarkedAsSpam,
Campaigns::IdeaPublished,
- Campaigns::InitiativeResubmittedForReview,
Campaigns::InternalCommentOnIdeaAssignedToYou,
Campaigns::InternalCommentOnIdeaYouCommentedInternallyOn,
Campaigns::InternalCommentOnIdeaYouModerate,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 92813ee09da0..e879db1eea5c 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -70,14 +70,6 @@
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
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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index c1f1a82b51fa..bb92ef46bac9 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -131,11 +131,6 @@
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
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
From 533091f3cfe66fcd6c6affd37c71899c02007256 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 12:59:56 +0000
Subject: [PATCH 44/63] [TAN-2538] Remove CosponsorOfYourInitiative
notification & campaign files & specs
---
.../cosponsor_of_your_initiative.rb | 96 -------------------
...cosponsor_of_your_initiative_serializer.rb | 24 -----
back/app/services/notification_service.rb | 1 -
.../cosponsor_of_your_initiative_mailer.rb | 25 -----
.../campaigns/cosponsor_of_your_initiative.rb | 95 ------------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 2 -
.../spec/factories/campaigns.rb | 4 -
...osponsor_of_your_initiative_mailer_spec.rb | 46 ---------
...onsor_of_your_initiative_mailer_preview.rb | 19 ----
back/spec/factories/notifications.rb | 12 ---
.../cosponsor_of_your_initiative_spec.rb | 25 -----
12 files changed, 350 deletions(-)
delete mode 100644 back/app/models/notifications/cosponsor_of_your_initiative.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/cosponsor_of_your_initiative_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/cosponsor_of_your_initiative_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/cosponsor_of_your_initiative.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/cosponsor_of_your_initiative_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/cosponsor_of_your_initiative_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/cosponsor_of_your_initiative_mailer_preview.rb
delete mode 100644 back/spec/models/notifications/cosponsor_of_your_initiative_spec.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index 702d933276b4..e3584bc80a65 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -8,7 +8,6 @@ class NotificationService
Notifications::CommentOnIdeaYouFollow,
Notifications::CommentOnYourComment,
Notifications::CosponsorOfYourIdea,
- Notifications::CosponsorOfYourInitiative,
Notifications::IdeaMarkedAsSpam,
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
Notifications::InternalComments::InternalCommentOnIdeaYouCommentedInternallyOn,
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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index 2edb826dbe56..c9fbdb92062c 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
@@ -10,7 +10,6 @@ class DeliveryService
Campaigns::CommentMarkedAsSpam,
Campaigns::CommentOnIdeaYouFollow,
Campaigns::CommentOnYourComment,
- Campaigns::CosponsorOfYourInitiative,
Campaigns::CosponsorOfYourIdea,
Campaigns::EventRegistrationConfirmation,
Campaigns::IdeaMarkedAsSpam,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index e879db1eea5c..e64f2e697466 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -42,10 +42,6 @@
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
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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index bb92ef46bac9..1df75c05c39d 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
@@ -138,12 +132,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
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
From d5b4e9513b44fcb74d1ad7e03c95bc7da7d9deef Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 13:47:24 +0000
Subject: [PATCH 45/63] [TAN-2538] Remove
InternalCommentOnInitiativeAssignedToYou notification & campaign files &
specs
---
...l_comment_on_initiative_assigned_to_you.rb | 82 -------------------
...n_initiative_assigned_to_you_serializer.rb | 4 -
back/app/services/notification_service.rb | 1 -
...t_on_initiative_assigned_to_you_builder.rb | 26 ------
...nt_on_initiative_assigned_to_you_mailer.rb | 6 --
...l_comment_on_initiative_assigned_to_you.rb | 79 ------------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 1 -
.../spec/factories/campaigns.rb | 4 -
..._initiative_assigned_to_you_mailer_spec.rb | 36 --------
...itiative_assigned_to_you_mailer_preview.rb | 31 -------
...ment_on_initiative_assigned_to_you_spec.rb | 19 -----
back/spec/factories/notifications.rb | 8 --
...ment_on_initiative_assigned_to_you_spec.rb | 74 -----------------
...iative_you_commented_internally_on_spec.rb | 8 --
15 files changed, 380 deletions(-)
delete mode 100644 back/app/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_assigned_to_you_serializer.rb
delete mode 100644 back/app/services/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_builder.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_assigned_to_you_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_assigned_to_you_mailer_preview.rb
delete mode 100644 back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_assigned_to_you_spec.rb
delete mode 100644 back/spec/models/notifications/internal_comments/internal_comment_on_initiative_assigned_to_you_spec.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index e3584bc80a65..5833a50d0267 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -12,7 +12,6 @@ class NotificationService
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
Notifications::InternalComments::InternalCommentOnIdeaYouCommentedInternallyOn,
Notifications::InternalComments::InternalCommentOnIdeaYouModerate,
- Notifications::InternalComments::InternalCommentOnInitiativeAssignedToYou,
Notifications::InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn,
Notifications::InternalComments::InternalCommentOnUnassignedInitiative,
Notifications::InternalComments::InternalCommentOnUnassignedUnmoderatedIdea,
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/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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index c9fbdb92062c..f0e0b86ff154 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
@@ -17,7 +17,6 @@ class DeliveryService
Campaigns::InternalCommentOnIdeaAssignedToYou,
Campaigns::InternalCommentOnIdeaYouCommentedInternallyOn,
Campaigns::InternalCommentOnIdeaYouModerate,
- Campaigns::InternalCommentOnInitiativeAssignedToYou,
Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn,
Campaigns::InternalCommentOnUnassignedInitiative,
Campaigns::InternalCommentOnUnassignedUnmoderatedIdea,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index e64f2e697466..33ebb1388368 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -78,10 +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
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/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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index 1df75c05c39d..d8f2a7dea065 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -61,14 +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
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
index 7019c7dfd4ea..b0fd5026fe0f 100644
--- 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
@@ -84,13 +84,5 @@
# 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
From acc9891e62d6bf3d1e495913a5d5a6737cdd577a Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 13:53:01 +0000
Subject: [PATCH 46/63] [TAN-2538] Remove
InternalCommentOnInitiativeYouCommentedInternallyOn notification & campaign
files & specs
---
..._initiative_you_commented_internally_on.rb | 82 -----------------
..._you_commented_internally_on_serializer.rb | 4 -
back/app/services/notification_service.rb | 1 -
...ive_you_commented_internally_on_builder.rb | 27 ------
...tive_you_commented_internally_on_mailer.rb | 6 --
..._initiative_you_commented_internally_on.rb | 79 -----------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 1 -
.../spec/factories/campaigns.rb | 4 -
...you_commented_internally_on_mailer_spec.rb | 36 --------
..._commented_internally_on_mailer_preview.rb | 31 -------
...iative_you_commented_internally_on_spec.rb | 19 ----
back/spec/factories/notifications.rb | 8 --
...iative_you_commented_internally_on_spec.rb | 88 -------------------
...l_comment_on_unassigned_initiative_spec.rb | 79 -----------------
...ent_on_unassigned_unmoderated_idea_spec.rb | 2 +-
16 files changed, 1 insertion(+), 467 deletions(-)
delete mode 100644 back/app/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/internal_comment_on_initiative_you_commented_internally_on_serializer.rb
delete mode 100644 back/app/services/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_builder.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/internal_comment_on_initiative_you_commented_internally_on_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_initiative_you_commented_internally_on_mailer_preview.rb
delete mode 100644 back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_initiative_you_commented_internally_on_spec.rb
delete mode 100644 back/spec/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_spec.rb
delete mode 100644 back/spec/models/notifications/internal_comments/internal_comment_on_unassigned_initiative_spec.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index 5833a50d0267..75fc28945252 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -12,7 +12,6 @@ class NotificationService
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
Notifications::InternalComments::InternalCommentOnIdeaYouCommentedInternallyOn,
Notifications::InternalComments::InternalCommentOnIdeaYouModerate,
- Notifications::InternalComments::InternalCommentOnInitiativeYouCommentedInternallyOn,
Notifications::InternalComments::InternalCommentOnUnassignedInitiative,
Notifications::InternalComments::InternalCommentOnUnassignedUnmoderatedIdea,
Notifications::InternalComments::InternalCommentOnYourInternalComment,
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/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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index f0e0b86ff154..91122d0d2b58 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
@@ -17,7 +17,6 @@ class DeliveryService
Campaigns::InternalCommentOnIdeaAssignedToYou,
Campaigns::InternalCommentOnIdeaYouCommentedInternallyOn,
Campaigns::InternalCommentOnIdeaYouModerate,
- Campaigns::InternalCommentOnInitiativeYouCommentedInternallyOn,
Campaigns::InternalCommentOnUnassignedInitiative,
Campaigns::InternalCommentOnUnassignedUnmoderatedIdea,
Campaigns::InternalCommentOnYourInternalComment,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 33ebb1388368..6b71c467c45d 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -78,10 +78,6 @@
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
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/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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index d8f2a7dea065..6bbac7cb3571 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -61,14 +61,6 @@
association :post, factory: :idea
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
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 b0fd5026fe0f..000000000000
--- a/back/spec/models/notifications/internal_comments/internal_comment_on_initiative_you_commented_internally_on_spec.rb
+++ /dev/null
@@ -1,88 +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
- 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
From 3346e5e347c656067fc76a8147a86e144b4d35d0 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 13:55:24 +0000
Subject: [PATCH 47/63] [TAN-2538] Remove InternalCommentOnUnassignedInitiative
notification & campaign files & specs
---
...ternal_comment_on_unassigned_initiative.rb | 82 -------------------
...ent_on_unassigned_initiative_serializer.rb | 4 -
back/app/services/notification_service.rb | 1 -
...omment_on_unassigned_initiative_builder.rb | 29 -------
...comment_on_unassigned_initiative_mailer.rb | 6 --
...ternal_comment_on_unassigned_initiative.rb | 79 ------------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 1 -
.../spec/factories/campaigns.rb | 4 -
...nt_on_unassigned_initiative_mailer_spec.rb | 36 --------
...on_unassigned_initiative_mailer_preview.rb | 31 -------
...l_comment_on_unassigned_initiative_spec.rb | 19 -----
back/spec/factories/notifications.rb | 8 --
13 files changed, 301 deletions(-)
delete mode 100644 back/app/models/notifications/internal_comments/internal_comment_on_unassigned_initiative.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/internal_comment_on_unassigned_initiative_serializer.rb
delete mode 100644 back/app/services/notifications/internal_comments/internal_comment_on_unassigned_initiative_builder.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/internal_comment_on_unassigned_initiative_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/internal_comment_on_unassigned_initiative_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/internal_comment_on_unassigned_initiative_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/internal_comment_on_unassigned_initiative_mailer_preview.rb
delete mode 100644 back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/internal_comment_on_unassigned_initiative_spec.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index 75fc28945252..e18b380e84ad 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -12,7 +12,6 @@ class NotificationService
Notifications::InternalComments::InternalCommentOnIdeaAssignedToYou,
Notifications::InternalComments::InternalCommentOnIdeaYouCommentedInternallyOn,
Notifications::InternalComments::InternalCommentOnIdeaYouModerate,
- Notifications::InternalComments::InternalCommentOnUnassignedInitiative,
Notifications::InternalComments::InternalCommentOnUnassignedUnmoderatedIdea,
Notifications::InternalComments::InternalCommentOnYourInternalComment,
Notifications::InternalComments::MentionInInternalComment,
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/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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index 91122d0d2b58..99fa26d1cfc1 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
@@ -17,7 +17,6 @@ class DeliveryService
Campaigns::InternalCommentOnIdeaAssignedToYou,
Campaigns::InternalCommentOnIdeaYouCommentedInternallyOn,
Campaigns::InternalCommentOnIdeaYouModerate,
- Campaigns::InternalCommentOnUnassignedInitiative,
Campaigns::InternalCommentOnUnassignedUnmoderatedIdea,
Campaigns::InternalCommentOnYourInternalComment,
Campaigns::InvitationToCosponsorIdea,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 6b71c467c45d..71f0449a8076 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -78,10 +78,6 @@
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
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/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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index 6bbac7cb3571..ba8350bc542f 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -61,14 +61,6 @@
association :post, factory: :idea
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
From 7548317acbccc76a852cecb6fccb8516318c858e Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 13:57:27 +0000
Subject: [PATCH 48/63] [TAN-2538] Remove InvitationToCosponsorInitiative
notification & campaign files & specs
---
.../invitation_to_cosponsor_initiative.rb | 96 -------------------
...tion_to_cosponsor_initiative_serializer.rb | 24 -----
back/app/services/notification_service.rb | 1 -
...vitation_to_cosponsor_initiative_mailer.rb | 25 -----
.../invitation_to_cosponsor_initiative.rb | 93 ------------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 26 -----
.../spec/factories/campaigns.rb | 4 -
...ion_to_cosponsor_initiative_mailer_spec.rb | 45 ---------
..._to_cosponsor_initiative_mailer_preview.rb | 19 ----
back/spec/factories/notifications.rb | 6 --
...invitation_to_cosponsor_initiative_spec.rb | 20 ----
12 files changed, 360 deletions(-)
delete mode 100644 back/app/models/notifications/invitation_to_cosponsor_initiative.rb
delete mode 100644 back/app/serializers/web_api/v1/notifications/invitation_to_cosponsor_initiative_serializer.rb
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/invitation_to_cosponsor_initiative_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/invitation_to_cosponsor_initiative.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/invitation_to_cosponsor_initiative_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/invitation_to_cosponsor_initiative_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/invitation_to_cosponsor_initiative_mailer_preview.rb
delete mode 100644 back/spec/models/notifications/invitation_to_cosponsor_initiative_spec.rb
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/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/services/notification_service.rb b/back/app/services/notification_service.rb
index e18b380e84ad..3300a002d4d8 100644
--- a/back/app/services/notification_service.rb
+++ b/back/app/services/notification_service.rb
@@ -16,7 +16,6 @@ class NotificationService
Notifications::InternalComments::InternalCommentOnYourInternalComment,
Notifications::InternalComments::MentionInInternalComment,
Notifications::InvitationToCosponsorIdea,
- Notifications::InvitationToCosponsorInitiative,
Notifications::InviteAccepted,
Notifications::MentionInComment,
Notifications::MentionInOfficialFeedback,
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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index 99fa26d1cfc1..4324f9af19a8 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
@@ -20,7 +20,6 @@ class DeliveryService
Campaigns::InternalCommentOnUnassignedUnmoderatedIdea,
Campaigns::InternalCommentOnYourInternalComment,
Campaigns::InvitationToCosponsorIdea,
- Campaigns::InvitationToCosponsorInitiative,
Campaigns::InviteReceived,
Campaigns::InviteReminder,
Campaigns::Manual,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 71f0449a8076..371a33bacdc2 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -90,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
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/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/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index ba8350bc542f..078f402330f0 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -89,12 +89,6 @@
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
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
From b1b2848e2684ee0a7fd03440d5d61f6214826310 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 13:59:08 +0000
Subject: [PATCH 49/63] [TAN-2538] Remove NewInitiativeForAdmin notification &
campaign files & specs
---
.../new_initiative_for_admin_mailer.rb | 25 -----
.../campaigns/new_initiative_for_admin.rb | 106 ------------------
.../email_campaigns/delivery_service.rb | 1 -
.../campaign_mail.mjml | 19 ----
.../spec/factories/campaigns.rb | 4 -
.../new_initiative_for_admin_mailer_spec.rb | 49 --------
...new_initiative_for_admin_mailer_preview.rb | 26 -----
.../new_initiative_for_admin_spec.rb | 35 ------
8 files changed, 265 deletions(-)
delete mode 100644 back/engines/free/email_campaigns/app/mailers/email_campaigns/new_initiative_for_admin_mailer.rb
delete mode 100644 back/engines/free/email_campaigns/app/models/email_campaigns/campaigns/new_initiative_for_admin.rb
delete mode 100644 back/engines/free/email_campaigns/app/views/email_campaigns/new_initiative_for_admin_mailer/campaign_mail.mjml
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/new_initiative_for_admin_mailer_spec.rb
delete mode 100644 back/engines/free/email_campaigns/spec/mailers/previews/email_campaigns/new_initiative_for_admin_mailer_preview.rb
delete mode 100644 back/engines/free/email_campaigns/spec/models/email_campaigns/campaigns/new_initiative_for_admin_spec.rb
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/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/services/email_campaigns/delivery_service.rb b/back/engines/free/email_campaigns/app/services/email_campaigns/delivery_service.rb
index 4324f9af19a8..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
@@ -30,7 +30,6 @@ class DeliveryService
Campaigns::NativeSurveyNotSubmitted,
Campaigns::NewCommentForAdmin,
Campaigns::NewIdeaForAdmin,
- Campaigns::NewInitiativeForAdmin,
Campaigns::OfficialFeedbackOnIdeaYouFollow,
Campaigns::ProjectFolderModerationRightsReceived,
Campaigns::ProjectModerationRightsReceived,
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/spec/factories/campaigns.rb b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
index 371a33bacdc2..9758bfd3e8e7 100644
--- a/back/engines/free/email_campaigns/spec/factories/campaigns.rb
+++ b/back/engines/free/email_campaigns/spec/factories/campaigns.rb
@@ -106,10 +106,6 @@
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
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/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/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
From 20d39152fcf97eda48ae85e8fe1c82dc82a04db6 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 14:06:38 +0000
Subject: [PATCH 50/63] [TAN-2538] Use idea factory in
threshold_reached_for_admin factory
---
back/spec/factories/notifications.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/back/spec/factories/notifications.rb b/back/spec/factories/notifications.rb
index 078f402330f0..214142f814c3 100644
--- a/back/spec/factories/notifications.rb
+++ b/back/spec/factories/notifications.rb
@@ -173,7 +173,7 @@
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
From 5c5a65c456109fe87af4315e9c9631cb3b7796d6 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 14:16:25 +0000
Subject: [PATCH 51/63] [TAN-2538] Comment out failing intitiative_spec test
---
back/spec/models/initiative_spec.rb | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
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)
From 8b13bb6f1af0ec6f8df107f954be596d8514e2a3 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 14:22:28 +0000
Subject: [PATCH 52/63] [TAN-2538] Remove admin_api controller & spec
---
.../admin_api/types/initiative_type.rb | 54 --------------
.../spec/graphql/initiatives_spec.rb | 72 -------------------
2 files changed, 126 deletions(-)
delete mode 100644 back/engines/commercial/admin_api/app/graphql/admin_api/types/initiative_type.rb
delete mode 100644 back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
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/spec/graphql/initiatives_spec.rb b/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
deleted file mode 100644
index 9a8f9c0b703f..000000000000
--- a/back/engines/commercial/admin_api/spec/graphql/initiatives_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-# TODO: cleanup-after-proposals-migration
-#
-# Commented out for now, just so I can use CI to see other failures clearly, and because I'm not sure what
-# we want to do about the admin_api for Initiatives. Maybe we remove it all, or maybe we keep it and return useful
-# errors, like 'initiatives are no longer supported as a separate model, use ideas instead' or something.
-#
-# 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
From 92308a20b2f7525cc30654d04b6b40cf477cfcae Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 14:35:02 +0000
Subject: [PATCH 53/63] [TAN-2538] Remove initiatives from admin_api graphql
query_type.rb
---
.../web_api/v1/users_controller.rb | 2 +-
.../app/graphql/admin_api/types/query_type.rb | 24 -------------------
2 files changed, 1 insertion(+), 25 deletions(-)
diff --git a/back/app/controllers/web_api/v1/users_controller.rb b/back/app/controllers/web_api/v1/users_controller.rb
index b36f70e5ecda..d49677b0d44b 100644
--- a/back/app/controllers/web_api/v1/users_controller.rb
+++ b/back/app/controllers/web_api/v1/users_controller.rb
@@ -204,7 +204,7 @@ def comments_count
count = 0
published_comments = @user.comments.published
# TODO: cleanup-after-proposals-migration
- # This test won't make sense once Comment.post_type is removed
+ # Simplify when Comment.post_type is removed
if !params[:post_type] || params[:post_type] == 'Idea'
count += policy_scope(
published_comments.where(post_type: 'Idea'),
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
From 25d46e3526e6a563c3fd8ab2702404708e28f846 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 15:08:27 +0000
Subject: [PATCH 54/63] [TAN-2538] Remove permissions + spec
---
back/app/models/permission.rb | 2 +-
.../permissions/base_permissions_service.rb | 3 --
.../initiative_permissions_service.rb | 22 -----------
.../acceptance/action_descriptors_spec.rb | 33 ----------------
back/spec/acceptance/permissions_spec.rb | 6 +--
.../initiatives_permissions_service_spec.rb | 38 -------------------
6 files changed, 3 insertions(+), 101 deletions(-)
delete mode 100644 back/app/services/permissions/initiative_permissions_service.rb
delete mode 100644 back/spec/services/permissions/initiatives_permissions_service_spec.rb
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/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/spec/acceptance/action_descriptors_spec.rb b/back/spec/acceptance/action_descriptors_spec.rb
index 8648cb7994ce..0f9fc693a41c 100644
--- a/back/spec/acceptance/action_descriptors_spec.rb
+++ b/back/spec/acceptance/action_descriptors_spec.rb
@@ -28,39 +28,6 @@
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/permissions_spec.rb b/back/spec/acceptance/permissions_spec.rb
index c3689c4e190e..bd1625fda14d 100644
--- a/back/spec/acceptance/permissions_spec.rb
+++ b/back/spec/acceptance/permissions_spec.rb
@@ -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/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
From f872d6f5a1042efc084012501e9ceec44219a619 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 15:30:53 +0000
Subject: [PATCH 55/63] [TAN-2538] Remove action_descriptors_controller & spec
---
.../v1/action_descriptors_controller.rb | 11 -------
.../acceptance/action_descriptors_spec.rb | 33 -------------------
2 files changed, 44 deletions(-)
delete mode 100644 back/app/controllers/web_api/v1/action_descriptors_controller.rb
delete mode 100644 back/spec/acceptance/action_descriptors_spec.rb
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/spec/acceptance/action_descriptors_spec.rb b/back/spec/acceptance/action_descriptors_spec.rb
deleted file mode 100644
index 0f9fc693a41c..000000000000
--- a/back/spec/acceptance/action_descriptors_spec.rb
+++ /dev/null
@@ -1,33 +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
- end
- end
-end
From 86472855ed3a371df697aab31107fbaf5816c73c Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 15:33:41 +0000
Subject: [PATCH 56/63] [TAN-2538] Fix 2 permissions related tests
---
back/spec/acceptance/comment_reactions_spec.rb | 4 ++--
back/spec/acceptance/permissions_spec.rb | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
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/permissions_spec.rb b/back/spec/acceptance/permissions_spec.rb
index bd1625fda14d..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
From 2e90958ef05025a07a560d32b3ca8abce0ade8df Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Wed, 18 Dec 2024 16:01:31 +0000
Subject: [PATCH 57/63] [TAN-2538] Delete a bunch of initiatives related
campaigns translations
---
.../email_campaigns/config/locales/en.yml | 113 ------------------
.../spec/fixtures/locales/mailers.en.yml | 108 -----------------
2 files changed, 221 deletions(-)
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/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:"
From 7fa17038e76200581b50650c6ea93282eeb27a71 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Thu, 19 Dec 2024 11:15:44 +0000
Subject: [PATCH 58/63] [TAN-2538] Remove public_api controller, route + spec
---
.../public_api/v2/initiatives_controller.rb | 25 ------
.../commercial/public_api/config/routes.rb | 1 -
.../spec/acceptance/v2/initiatives_spec.rb | 89 -------------------
3 files changed, 115 deletions(-)
delete mode 100644 back/engines/commercial/public_api/app/controllers/public_api/v2/initiatives_controller.rb
delete mode 100644 back/engines/commercial/public_api/spec/acceptance/v2/initiatives_spec.rb
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
From 2441e03f44a5e176110b1b84a52ac5ca3f92f98f Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Fri, 20 Dec 2024 11:12:52 +0000
Subject: [PATCH 59/63] [TAN-2538] Update views & migrate
---
...tiatives_from_analytics_views.analytics.rb | 14 ++
back/db/structure.sql | 190 +++++++-----------
.../views/analytics_build_feedbacks_v02.sql | 28 +++
.../analytics_dimension_statuses_v03.sql | 1 +
.../analytics_fact_participations_v08.sql | 127 ++++++++++++
back/db/views/analytics_fact_posts_v09.sql | 25 +++
...remove_initiatives_from_analytics_views.rb | 13 ++
.../views/analytics_build_feedbacks_v02.sql | 28 +++
.../analytics_dimension_statuses_v03.sql | 1 +
.../analytics_fact_participations_v08.sql | 127 ++++++++++++
.../db/views/analytics_fact_posts_v09.sql | 25 +++
11 files changed, 463 insertions(+), 116 deletions(-)
create mode 100644 back/db/migrate/20241220103433_remove_initiatives_from_analytics_views.analytics.rb
create mode 100644 back/db/views/analytics_build_feedbacks_v02.sql
create mode 100644 back/db/views/analytics_dimension_statuses_v03.sql
create mode 100644 back/db/views/analytics_fact_participations_v08.sql
create mode 100644 back/db/views/analytics_fact_posts_v09.sql
create mode 100644 back/engines/commercial/analytics/db/migrate/20241220103251_remove_initiatives_from_analytics_views.rb
create mode 100644 back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql
create mode 100644 back/engines/commercial/analytics/db/views/analytics_dimension_statuses_v03.sql
create mode 100644 back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql
create mode 100644 back/engines/commercial/analytics/db/views/analytics_fact_posts_v09.sql
diff --git a/back/db/migrate/20241220103433_remove_initiatives_from_analytics_views.analytics.rb b/back/db/migrate/20241220103433_remove_initiatives_from_analytics_views.analytics.rb
new file mode 100644
index 000000000000..ac920508698b
--- /dev/null
+++ b/back/db/migrate/20241220103433_remove_initiatives_from_analytics_views.analytics.rb
@@ -0,0 +1,14 @@
+# This migration comes from analytics (originally 20241220103251)
+class RemoveInitiativesFromAnalyticsViews < ActiveRecord::Migration[7.0]
+ def change
+ # We need to drop analytics_fact_posts, before updating analytics_build_feedbacks
+ # because analytics_fact_posts depends on analytics_build_feedbacks.
+ drop_view :analytics_fact_posts, revert_to_version: 8
+ update_view :analytics_build_feedbacks, version: 2, revert_to_version: 1
+ # We recreate analytics_fact_posts, after updating analytics_build_feedbacks
+ create_view :analytics_fact_posts, version: 8
+ update_view :analytics_dimension_statuses, version: 3, revert_to_version: 2
+ update_view :analytics_fact_participations, version: 8, revert_to_version: 7
+ update_view :analytics_fact_posts, version: 9, revert_to_version: 8
+ end
+end
diff --git a/back/db/structure.sql b/back/db/structure.sql
index 224b08c361c1..fca50116bfbb 100644
--- a/back/db/structure.sql
+++ b/back/db/structure.sql
@@ -571,6 +571,9 @@ DROP TABLE IF EXISTS public.machine_translations_machine_translations;
DROP TABLE IF EXISTS public.internal_comments;
DROP TABLE IF EXISTS public.initiatives_topics;
DROP VIEW IF EXISTS public.initiative_initiative_statuses;
+DROP TABLE IF EXISTS public.initiatives;
+DROP TABLE IF EXISTS public.initiative_statuses;
+DROP TABLE IF EXISTS public.initiative_status_changes;
DROP TABLE IF EXISTS public.initiative_images;
DROP TABLE IF EXISTS public.initiative_files;
DROP TABLE IF EXISTS public.impact_tracking_salts;
@@ -622,14 +625,12 @@ DROP VIEW IF EXISTS public.analytics_fact_registrations;
DROP TABLE IF EXISTS public.invites;
DROP VIEW IF EXISTS public.analytics_fact_project_statuses;
DROP VIEW IF EXISTS public.analytics_fact_posts;
-DROP TABLE IF EXISTS public.initiative_status_changes;
DROP VIEW IF EXISTS public.analytics_fact_participations;
DROP TABLE IF EXISTS public.volunteering_volunteers;
DROP TABLE IF EXISTS public.volunteering_causes;
DROP TABLE IF EXISTS public.reactions;
DROP TABLE IF EXISTS public.polls_responses;
DROP TABLE IF EXISTS public.phases;
-DROP TABLE IF EXISTS public.initiatives;
DROP TABLE IF EXISTS public.ideas;
DROP TABLE IF EXISTS public.events_attendances;
DROP TABLE IF EXISTS public.comments;
@@ -644,7 +645,6 @@ DROP TABLE IF EXISTS public.users;
DROP TABLE IF EXISTS public.analytics_fact_visits;
DROP TABLE IF EXISTS public.analytics_dimension_types;
DROP VIEW IF EXISTS public.analytics_dimension_statuses;
-DROP TABLE IF EXISTS public.initiative_statuses;
DROP TABLE IF EXISTS public.idea_statuses;
DROP TABLE IF EXISTS public.analytics_dimension_referrer_types;
DROP TABLE IF EXISTS public.analytics_dimension_projects_fact_visits;
@@ -1161,7 +1161,7 @@ CREATE VIEW public.analytics_build_feedbacks AS
0 AS feedback_official,
1 AS feedback_status_change
FROM public.activities
- WHERE (((activities.action)::text = 'changed_status'::text) AND ((activities.item_type)::text = ANY (ARRAY[('Idea'::character varying)::text, ('Initiative'::character varying)::text])))
+ WHERE (((activities.action)::text = 'changed_status'::text) AND ((activities.item_type)::text = 'Idea'::text))
GROUP BY activities.item_id
UNION ALL
SELECT official_feedbacks.post_id,
@@ -1281,38 +1281,16 @@ CREATE TABLE public.idea_statuses (
);
---
--- Name: initiative_statuses; Type: TABLE; Schema: public; Owner: -
---
-
-CREATE TABLE public.initiative_statuses (
- id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL,
- title_multiloc jsonb DEFAULT '{}'::jsonb,
- description_multiloc jsonb DEFAULT '{}'::jsonb,
- ordering integer,
- code character varying,
- color character varying,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL
-);
-
-
--
-- Name: analytics_dimension_statuses; Type: VIEW; Schema: public; Owner: -
--
CREATE VIEW public.analytics_dimension_statuses AS
- SELECT idea_statuses.id,
- idea_statuses.title_multiloc,
- idea_statuses.code,
- idea_statuses.color
- FROM public.idea_statuses
-UNION ALL
- SELECT initiative_statuses.id,
- initiative_statuses.title_multiloc,
- initiative_statuses.code,
- initiative_statuses.color
- FROM public.initiative_statuses;
+ SELECT id,
+ title_multiloc,
+ code,
+ color
+ FROM public.idea_statuses;
--
@@ -1582,37 +1560,6 @@ CREATE TABLE public.ideas (
);
---
--- Name: initiatives; Type: TABLE; Schema: public; Owner: -
---
-
-CREATE TABLE public.initiatives (
- id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL,
- title_multiloc jsonb DEFAULT '{}'::jsonb,
- body_multiloc jsonb DEFAULT '{}'::jsonb,
- publication_status character varying,
- published_at timestamp without time zone,
- author_id uuid,
- likes_count integer DEFAULT 0 NOT NULL,
- dislikes_count integer DEFAULT 0 NOT NULL,
- location_point shared_extensions.geography(Point,4326),
- location_description character varying,
- slug character varying,
- comments_count integer DEFAULT 0 NOT NULL,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL,
- header_bg character varying,
- assignee_id uuid,
- official_feedbacks_count integer DEFAULT 0 NOT NULL,
- assigned_at timestamp without time zone,
- author_hash character varying,
- anonymous boolean DEFAULT false NOT NULL,
- internal_comments_count integer DEFAULT 0 NOT NULL,
- followers_count integer DEFAULT 0 NOT NULL,
- editing_locked boolean DEFAULT false NOT NULL
-);
-
-
--
-- Name: phases; Type: TABLE; Schema: public; Owner: -
--
@@ -1747,18 +1694,6 @@ CREATE VIEW public.analytics_fact_participations AS
JOIN public.analytics_dimension_types idea ON (((idea.name)::text = 'idea'::text)))
LEFT JOIN public.analytics_dimension_types survey ON (((survey.name)::text = 'survey'::text)))
WHERE ((i.publication_status)::text = 'published'::text)
-UNION ALL
- SELECT i.id,
- i.author_id AS dimension_user_id,
- COALESCE((i.author_id)::text, (i.author_hash)::text, (i.id)::text) AS participant_id,
- NULL::uuid AS dimension_project_id,
- adt.id AS dimension_type_id,
- (i.created_at)::date AS dimension_date_created_id,
- (i.likes_count + i.dislikes_count) AS reactions_count,
- i.likes_count,
- i.dislikes_count
- FROM (public.initiatives i
- JOIN public.analytics_dimension_types adt ON (((adt.name)::text = 'initiative'::text)))
UNION ALL
SELECT c.id,
c.author_id AS dimension_user_id,
@@ -1848,21 +1783,6 @@ UNION ALL
JOIN public.analytics_dimension_types adt ON (((adt.name)::text = 'event_attendance'::text)));
---
--- Name: initiative_status_changes; Type: TABLE; Schema: public; Owner: -
---
-
-CREATE TABLE public.initiative_status_changes (
- id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL,
- user_id uuid,
- initiative_id uuid,
- initiative_status_id uuid,
- official_feedback_id uuid,
- created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL
-);
-
-
--
-- Name: analytics_fact_posts; Type: VIEW; Schema: public; Owner: -
--
@@ -1895,32 +1815,7 @@ CREATE VIEW public.analytics_fact_posts AS
WHEN ((creation_phase.participation_method)::text = 'proposals'::text) THEN 'proposal'::text
ELSE NULL::text
END)))
- WHERE ((creation_phase.* IS NULL) OR ((creation_phase.participation_method)::text = 'proposals'::text))
-UNION ALL
- SELECT i.id,
- i.author_id AS user_id,
- NULL::uuid AS dimension_project_id,
- adt.id AS dimension_type_id,
- (i.created_at)::date AS dimension_date_created_id,
- (abf.feedback_first_date)::date AS dimension_date_first_feedback_id,
- isc.initiative_status_id AS dimension_status_id,
- (abf.feedback_first_date - i.created_at) AS feedback_time_taken,
- COALESCE(abf.feedback_official, 0) AS feedback_official,
- COALESCE(abf.feedback_status_change, 0) AS feedback_status_change,
- CASE
- WHEN (abf.feedback_first_date IS NULL) THEN 1
- ELSE 0
- END AS feedback_none,
- (i.likes_count + i.dislikes_count) AS reactions_count,
- i.likes_count,
- i.dislikes_count,
- i.publication_status
- FROM (((public.initiatives i
- JOIN public.analytics_dimension_types adt ON (((adt.name)::text = 'initiative'::text)))
- LEFT JOIN public.analytics_build_feedbacks abf ON ((abf.post_id = i.id)))
- LEFT JOIN public.initiative_status_changes isc ON (((isc.initiative_id = i.id) AND (isc.updated_at = ( SELECT max(isc_.updated_at) AS max
- FROM public.initiative_status_changes isc_
- WHERE (isc_.initiative_id = i.id))))));
+ WHERE ((creation_phase.* IS NULL) OR ((creation_phase.participation_method)::text = 'proposals'::text));
--
@@ -2683,6 +2578,68 @@ CREATE TABLE public.initiative_images (
);
+--
+-- Name: initiative_status_changes; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.initiative_status_changes (
+ id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL,
+ user_id uuid,
+ initiative_id uuid,
+ initiative_status_id uuid,
+ official_feedback_id uuid,
+ created_at timestamp without time zone NOT NULL,
+ updated_at timestamp without time zone NOT NULL
+);
+
+
+--
+-- Name: initiative_statuses; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.initiative_statuses (
+ id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL,
+ title_multiloc jsonb DEFAULT '{}'::jsonb,
+ description_multiloc jsonb DEFAULT '{}'::jsonb,
+ ordering integer,
+ code character varying,
+ color character varying,
+ created_at timestamp without time zone NOT NULL,
+ updated_at timestamp without time zone NOT NULL
+);
+
+
+--
+-- Name: initiatives; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.initiatives (
+ id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL,
+ title_multiloc jsonb DEFAULT '{}'::jsonb,
+ body_multiloc jsonb DEFAULT '{}'::jsonb,
+ publication_status character varying,
+ published_at timestamp without time zone,
+ author_id uuid,
+ likes_count integer DEFAULT 0 NOT NULL,
+ dislikes_count integer DEFAULT 0 NOT NULL,
+ location_point shared_extensions.geography(Point,4326),
+ location_description character varying,
+ slug character varying,
+ comments_count integer DEFAULT 0 NOT NULL,
+ created_at timestamp without time zone NOT NULL,
+ updated_at timestamp without time zone NOT NULL,
+ header_bg character varying,
+ assignee_id uuid,
+ official_feedbacks_count integer DEFAULT 0 NOT NULL,
+ assigned_at timestamp without time zone,
+ author_hash character varying,
+ anonymous boolean DEFAULT false NOT NULL,
+ internal_comments_count integer DEFAULT 0 NOT NULL,
+ followers_count integer DEFAULT 0 NOT NULL,
+ editing_locked boolean DEFAULT false NOT NULL
+);
+
+
--
-- Name: initiative_initiative_statuses; Type: VIEW; Schema: public; Owner: -
--
@@ -7805,6 +7762,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20241127093339'),
('20241203151945'),
('20241204133717'),
-('20241204144321');
+('20241204144321'),
+('20241220103433');
diff --git a/back/db/views/analytics_build_feedbacks_v02.sql b/back/db/views/analytics_build_feedbacks_v02.sql
new file mode 100644
index 000000000000..84d81d6ab248
--- /dev/null
+++ b/back/db/views/analytics_build_feedbacks_v02.sql
@@ -0,0 +1,28 @@
+SELECT
+ post_id,
+ MIN(feedback_first_date) AS feedback_first_date,
+ MAX(feedback_official) AS feedback_official,
+ MAX(feedback_status_change) AS feedback_status_change
+FROM (
+ SELECT
+ item_id AS post_id,
+ MIN(created_at) AS feedback_first_date,
+ 0 AS feedback_official,
+ 1 AS feedback_status_change
+ FROM activities
+ WHERE
+ action = 'changed_status' AND
+ item_type = 'Idea'
+ GROUP BY item_id
+
+ UNION ALL
+
+ SELECT
+ post_id,
+ MIN(created_at) AS feedback_first_date,
+ 1 AS feedback_official,
+ 0 AS feedback_status_change
+ FROM official_feedbacks
+ GROUP BY post_id
+ ) AS a
+GROUP BY post_id;
\ No newline at end of file
diff --git a/back/db/views/analytics_dimension_statuses_v03.sql b/back/db/views/analytics_dimension_statuses_v03.sql
new file mode 100644
index 000000000000..b23507512883
--- /dev/null
+++ b/back/db/views/analytics_dimension_statuses_v03.sql
@@ -0,0 +1 @@
+SELECT id, title_multiloc, code, color FROM idea_statuses
diff --git a/back/db/views/analytics_fact_participations_v08.sql b/back/db/views/analytics_fact_participations_v08.sql
new file mode 100644
index 000000000000..73dca99913a6
--- /dev/null
+++ b/back/db/views/analytics_fact_participations_v08.sql
@@ -0,0 +1,127 @@
+-- Analytics view for all types of participation
+
+-- Ideas & Native surveys
+SELECT
+ i.id,
+ i.author_id AS dimension_user_id,
+ COALESCE(i.author_id::TEXT, i.author_hash, i.id::TEXT) as participant_id,
+ i.project_id AS dimension_project_id,
+ CASE
+ WHEN ph.participation_method = 'native_survey' THEN survey.id
+ ELSE idea.id
+ END AS dimension_type_id,
+ i.created_at::DATE AS dimension_date_created_id,
+ likes_count + dislikes_count AS reactions_count,
+ likes_count,
+ dislikes_count
+FROM ideas i
+LEFT JOIN projects pr ON pr.id = i.project_id
+LEFT JOIN phases ph ON ph.id = i.creation_phase_id
+INNER JOIN analytics_dimension_types idea ON idea.name = 'idea'
+LEFT JOIN analytics_dimension_types survey ON survey.name = 'survey'
+WHERE i.publication_status = 'published'
+
+UNION ALL
+
+-- Comments
+SELECT
+ c.id,
+ c.author_id AS dimension_user_id,
+ COALESCE(c.author_id::TEXT, c.author_hash, c.id::TEXT) as participant_id,
+ i.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ c.created_at::DATE AS dimension_date_created_id,
+ c.likes_count + c.dislikes_count AS reactions_count,
+ c.likes_count,
+ c.dislikes_count
+FROM comments c
+INNER JOIN analytics_dimension_types adt ON adt.name = 'comment' AND adt.parent = LOWER(c.post_type)
+LEFT JOIN ideas i ON c.post_id = i.id
+
+UNION ALL
+
+-- Reactions
+SELECT
+ r.id,
+ r.user_id AS dimension_user_id,
+ COALESCE(r.user_id::TEXT, r.id::TEXT) as participant_id,
+ COALESCE(i.project_id, ic.project_id) AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ r.created_at::DATE AS dimension_date_created_id,
+ 1 AS reactions_count,
+ CASE WHEN r.mode = 'up' THEN 1 ELSE 0 END AS likes_count,
+ CASE WHEN r.mode = 'down' THEN 1 ELSE 0 END AS dislikes_count
+FROM reactions r
+INNER JOIN analytics_dimension_types adt ON adt.name = 'reaction' AND adt.parent = LOWER(r.reactable_type)
+LEFT JOIN ideas i ON i.id = r.reactable_id
+LEFT JOIN comments c ON c.id = r.reactable_id
+LEFT JOIN ideas ic ON ic.id = c.post_id
+
+UNION ALL
+
+-- Poll Response
+SELECT
+ pr.id,
+ pr.user_id AS dimension_user_id,
+ COALESCE(pr.user_id::TEXT, pr.id::TEXT) as participant_id,
+ p.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ pr.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM polls_responses pr
+LEFT JOIN phases p ON p.id = pr.phase_id
+INNER JOIN analytics_dimension_types adt ON adt.name = 'poll'
+
+UNION ALL
+
+-- Volunteering
+SELECT
+ vv.id,
+ vv.user_id AS dimension_user_id,
+ COALESCE(vv.user_id::TEXT, vv.id::TEXT) as participant_id,
+ p.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ vv.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM volunteering_volunteers vv
+LEFT JOIN volunteering_causes vc ON vc.id = vv.cause_id
+LEFT JOIN phases p ON p.id = vc.phase_id
+INNER JOIN analytics_dimension_types adt ON adt.name = 'volunteer'
+
+UNION ALL
+
+--Baskets
+SELECT
+ b.id,
+ b.user_id AS dimension_user_id,
+ COALESCE(b.user_id::TEXT, b.id::TEXT) as participant_id,
+ p.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ b.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM baskets b
+LEFT JOIN phases p ON p.id = b.phase_id
+INNER JOIN analytics_dimension_types adt ON adt.name = 'basket'
+
+UNION ALL
+
+--Event attendance
+SELECT
+ ea.id,
+ ea.attendee_id AS dimension_user_id,
+ ea.attendee_id::TEXT as participant_id,
+ e.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ ea.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM events_attendances ea
+LEFT JOIN events e ON e.id = ea.event_id
+INNER JOIN analytics_dimension_types adt on adt.name = 'event_attendance';
\ No newline at end of file
diff --git a/back/db/views/analytics_fact_posts_v09.sql b/back/db/views/analytics_fact_posts_v09.sql
new file mode 100644
index 000000000000..5ba6a9bd3f34
--- /dev/null
+++ b/back/db/views/analytics_fact_posts_v09.sql
@@ -0,0 +1,25 @@
+-- Analytics view for posts
+SELECT
+ i.id,
+ i.author_id AS user_id,
+ i.project_id AS dimension_project_id,
+ adt.id as dimension_type_id,
+ i.created_at::DATE AS dimension_date_created_id,
+ abf.feedback_first_date::DATE as dimension_date_first_feedback_id,
+ idea_status_id as dimension_status_id,
+ (abf.feedback_first_date - i.created_at) as feedback_time_taken,
+ COALESCE(abf.feedback_official,0) AS feedback_official,
+ COALESCE(abf.feedback_status_change,0) AS feedback_status_change,
+ CASE WHEN abf.feedback_first_date IS NULL THEN 1 ELSE 0 END AS feedback_none,
+ likes_count + dislikes_count as reactions_count,
+ likes_count,
+ dislikes_count,
+ i.publication_status
+from ideas i
+LEFT JOIN analytics_build_feedbacks AS abf ON abf.post_id = i.id
+LEFT JOIN phases AS creation_phase on i.creation_phase_id = creation_phase.id
+INNER JOIN analytics_dimension_types adt ON adt.name = CASE
+ WHEN creation_phase IS NULL THEN 'idea'
+ WHEN creation_phase.participation_method = 'proposals' THEN 'proposal'
+ END
+WHERE creation_phase IS NULL OR creation_phase.participation_method = 'proposals'
diff --git a/back/engines/commercial/analytics/db/migrate/20241220103251_remove_initiatives_from_analytics_views.rb b/back/engines/commercial/analytics/db/migrate/20241220103251_remove_initiatives_from_analytics_views.rb
new file mode 100644
index 000000000000..56372a99e9e7
--- /dev/null
+++ b/back/engines/commercial/analytics/db/migrate/20241220103251_remove_initiatives_from_analytics_views.rb
@@ -0,0 +1,13 @@
+class RemoveInitiativesFromAnalyticsViews < ActiveRecord::Migration[7.0]
+ def change
+ # We need to drop analytics_fact_posts, before updating analytics_build_feedbacks
+ # because analytics_fact_posts depends on analytics_build_feedbacks.
+ drop_view :analytics_fact_posts, revert_to_version: 8
+ update_view :analytics_build_feedbacks, version: 2, revert_to_version: 1
+ # We recreate analytics_fact_posts, after updating analytics_build_feedbacks
+ create_view :analytics_fact_posts, version: 8
+ update_view :analytics_dimension_statuses, version: 3, revert_to_version: 2
+ update_view :analytics_fact_participations, version: 8, revert_to_version: 7
+ update_view :analytics_fact_posts, version: 9, revert_to_version: 8
+ end
+end
diff --git a/back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql b/back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql
new file mode 100644
index 000000000000..84d81d6ab248
--- /dev/null
+++ b/back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql
@@ -0,0 +1,28 @@
+SELECT
+ post_id,
+ MIN(feedback_first_date) AS feedback_first_date,
+ MAX(feedback_official) AS feedback_official,
+ MAX(feedback_status_change) AS feedback_status_change
+FROM (
+ SELECT
+ item_id AS post_id,
+ MIN(created_at) AS feedback_first_date,
+ 0 AS feedback_official,
+ 1 AS feedback_status_change
+ FROM activities
+ WHERE
+ action = 'changed_status' AND
+ item_type = 'Idea'
+ GROUP BY item_id
+
+ UNION ALL
+
+ SELECT
+ post_id,
+ MIN(created_at) AS feedback_first_date,
+ 1 AS feedback_official,
+ 0 AS feedback_status_change
+ FROM official_feedbacks
+ GROUP BY post_id
+ ) AS a
+GROUP BY post_id;
\ No newline at end of file
diff --git a/back/engines/commercial/analytics/db/views/analytics_dimension_statuses_v03.sql b/back/engines/commercial/analytics/db/views/analytics_dimension_statuses_v03.sql
new file mode 100644
index 000000000000..b23507512883
--- /dev/null
+++ b/back/engines/commercial/analytics/db/views/analytics_dimension_statuses_v03.sql
@@ -0,0 +1 @@
+SELECT id, title_multiloc, code, color FROM idea_statuses
diff --git a/back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql b/back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql
new file mode 100644
index 000000000000..73dca99913a6
--- /dev/null
+++ b/back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql
@@ -0,0 +1,127 @@
+-- Analytics view for all types of participation
+
+-- Ideas & Native surveys
+SELECT
+ i.id,
+ i.author_id AS dimension_user_id,
+ COALESCE(i.author_id::TEXT, i.author_hash, i.id::TEXT) as participant_id,
+ i.project_id AS dimension_project_id,
+ CASE
+ WHEN ph.participation_method = 'native_survey' THEN survey.id
+ ELSE idea.id
+ END AS dimension_type_id,
+ i.created_at::DATE AS dimension_date_created_id,
+ likes_count + dislikes_count AS reactions_count,
+ likes_count,
+ dislikes_count
+FROM ideas i
+LEFT JOIN projects pr ON pr.id = i.project_id
+LEFT JOIN phases ph ON ph.id = i.creation_phase_id
+INNER JOIN analytics_dimension_types idea ON idea.name = 'idea'
+LEFT JOIN analytics_dimension_types survey ON survey.name = 'survey'
+WHERE i.publication_status = 'published'
+
+UNION ALL
+
+-- Comments
+SELECT
+ c.id,
+ c.author_id AS dimension_user_id,
+ COALESCE(c.author_id::TEXT, c.author_hash, c.id::TEXT) as participant_id,
+ i.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ c.created_at::DATE AS dimension_date_created_id,
+ c.likes_count + c.dislikes_count AS reactions_count,
+ c.likes_count,
+ c.dislikes_count
+FROM comments c
+INNER JOIN analytics_dimension_types adt ON adt.name = 'comment' AND adt.parent = LOWER(c.post_type)
+LEFT JOIN ideas i ON c.post_id = i.id
+
+UNION ALL
+
+-- Reactions
+SELECT
+ r.id,
+ r.user_id AS dimension_user_id,
+ COALESCE(r.user_id::TEXT, r.id::TEXT) as participant_id,
+ COALESCE(i.project_id, ic.project_id) AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ r.created_at::DATE AS dimension_date_created_id,
+ 1 AS reactions_count,
+ CASE WHEN r.mode = 'up' THEN 1 ELSE 0 END AS likes_count,
+ CASE WHEN r.mode = 'down' THEN 1 ELSE 0 END AS dislikes_count
+FROM reactions r
+INNER JOIN analytics_dimension_types adt ON adt.name = 'reaction' AND adt.parent = LOWER(r.reactable_type)
+LEFT JOIN ideas i ON i.id = r.reactable_id
+LEFT JOIN comments c ON c.id = r.reactable_id
+LEFT JOIN ideas ic ON ic.id = c.post_id
+
+UNION ALL
+
+-- Poll Response
+SELECT
+ pr.id,
+ pr.user_id AS dimension_user_id,
+ COALESCE(pr.user_id::TEXT, pr.id::TEXT) as participant_id,
+ p.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ pr.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM polls_responses pr
+LEFT JOIN phases p ON p.id = pr.phase_id
+INNER JOIN analytics_dimension_types adt ON adt.name = 'poll'
+
+UNION ALL
+
+-- Volunteering
+SELECT
+ vv.id,
+ vv.user_id AS dimension_user_id,
+ COALESCE(vv.user_id::TEXT, vv.id::TEXT) as participant_id,
+ p.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ vv.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM volunteering_volunteers vv
+LEFT JOIN volunteering_causes vc ON vc.id = vv.cause_id
+LEFT JOIN phases p ON p.id = vc.phase_id
+INNER JOIN analytics_dimension_types adt ON adt.name = 'volunteer'
+
+UNION ALL
+
+--Baskets
+SELECT
+ b.id,
+ b.user_id AS dimension_user_id,
+ COALESCE(b.user_id::TEXT, b.id::TEXT) as participant_id,
+ p.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ b.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM baskets b
+LEFT JOIN phases p ON p.id = b.phase_id
+INNER JOIN analytics_dimension_types adt ON adt.name = 'basket'
+
+UNION ALL
+
+--Event attendance
+SELECT
+ ea.id,
+ ea.attendee_id AS dimension_user_id,
+ ea.attendee_id::TEXT as participant_id,
+ e.project_id AS dimension_project_id,
+ adt.id AS dimension_type_id,
+ ea.created_at::DATE AS dimension_date_created_id,
+ 0 AS reactions_count,
+ 0 AS likes_count,
+ 0 AS dislikes_count
+FROM events_attendances ea
+LEFT JOIN events e ON e.id = ea.event_id
+INNER JOIN analytics_dimension_types adt on adt.name = 'event_attendance';
\ No newline at end of file
diff --git a/back/engines/commercial/analytics/db/views/analytics_fact_posts_v09.sql b/back/engines/commercial/analytics/db/views/analytics_fact_posts_v09.sql
new file mode 100644
index 000000000000..5ba6a9bd3f34
--- /dev/null
+++ b/back/engines/commercial/analytics/db/views/analytics_fact_posts_v09.sql
@@ -0,0 +1,25 @@
+-- Analytics view for posts
+SELECT
+ i.id,
+ i.author_id AS user_id,
+ i.project_id AS dimension_project_id,
+ adt.id as dimension_type_id,
+ i.created_at::DATE AS dimension_date_created_id,
+ abf.feedback_first_date::DATE as dimension_date_first_feedback_id,
+ idea_status_id as dimension_status_id,
+ (abf.feedback_first_date - i.created_at) as feedback_time_taken,
+ COALESCE(abf.feedback_official,0) AS feedback_official,
+ COALESCE(abf.feedback_status_change,0) AS feedback_status_change,
+ CASE WHEN abf.feedback_first_date IS NULL THEN 1 ELSE 0 END AS feedback_none,
+ likes_count + dislikes_count as reactions_count,
+ likes_count,
+ dislikes_count,
+ i.publication_status
+from ideas i
+LEFT JOIN analytics_build_feedbacks AS abf ON abf.post_id = i.id
+LEFT JOIN phases AS creation_phase on i.creation_phase_id = creation_phase.id
+INNER JOIN analytics_dimension_types adt ON adt.name = CASE
+ WHEN creation_phase IS NULL THEN 'idea'
+ WHEN creation_phase.participation_method = 'proposals' THEN 'proposal'
+ END
+WHERE creation_phase IS NULL OR creation_phase.participation_method = 'proposals'
From d34f9960740cc6df9611287f2fdef847005588cb Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Fri, 20 Dec 2024 11:20:17 +0000
Subject: [PATCH 60/63] [TAN-2538] Add EOF newlines
---
back/db/views/analytics_build_feedbacks_v02.sql | 2 +-
back/db/views/analytics_fact_participations_v08.sql | 2 +-
.../analytics/db/views/analytics_build_feedbacks_v02.sql | 2 +-
.../analytics/db/views/analytics_fact_participations_v08.sql | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/back/db/views/analytics_build_feedbacks_v02.sql b/back/db/views/analytics_build_feedbacks_v02.sql
index 84d81d6ab248..568d37a2bcff 100644
--- a/back/db/views/analytics_build_feedbacks_v02.sql
+++ b/back/db/views/analytics_build_feedbacks_v02.sql
@@ -25,4 +25,4 @@ FROM (
FROM official_feedbacks
GROUP BY post_id
) AS a
-GROUP BY post_id;
\ No newline at end of file
+GROUP BY post_id;
diff --git a/back/db/views/analytics_fact_participations_v08.sql b/back/db/views/analytics_fact_participations_v08.sql
index 73dca99913a6..16c9c30f36d5 100644
--- a/back/db/views/analytics_fact_participations_v08.sql
+++ b/back/db/views/analytics_fact_participations_v08.sql
@@ -124,4 +124,4 @@ SELECT
0 AS dislikes_count
FROM events_attendances ea
LEFT JOIN events e ON e.id = ea.event_id
-INNER JOIN analytics_dimension_types adt on adt.name = 'event_attendance';
\ No newline at end of file
+INNER JOIN analytics_dimension_types adt on adt.name = 'event_attendance';
diff --git a/back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql b/back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql
index 84d81d6ab248..568d37a2bcff 100644
--- a/back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql
+++ b/back/engines/commercial/analytics/db/views/analytics_build_feedbacks_v02.sql
@@ -25,4 +25,4 @@ FROM (
FROM official_feedbacks
GROUP BY post_id
) AS a
-GROUP BY post_id;
\ No newline at end of file
+GROUP BY post_id;
diff --git a/back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql b/back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql
index 73dca99913a6..16c9c30f36d5 100644
--- a/back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql
+++ b/back/engines/commercial/analytics/db/views/analytics_fact_participations_v08.sql
@@ -124,4 +124,4 @@ SELECT
0 AS dislikes_count
FROM events_attendances ea
LEFT JOIN events e ON e.id = ea.event_id
-INNER JOIN analytics_dimension_types adt on adt.name = 'event_attendance';
\ No newline at end of file
+INNER JOIN analytics_dimension_types adt on adt.name = 'event_attendance';
From 5a8e3792049eab74d39645838c51e7b1fcd2c4eb Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Fri, 20 Dec 2024 11:29:17 +0000
Subject: [PATCH 61/63] [TAN-2538] Fix specs
---
.../spec/acceptance/analytics_participations_spec.rb | 4 +---
.../spec/models/analytics/dimension_status_spec.rb | 9 ---------
.../analytics/spec/models/analytics/fact_post_spec.rb | 10 ----------
.../services/analytics/query_runner_service_spec.rb | 10 ++--------
4 files changed, 3 insertions(+), 30 deletions(-)
diff --git a/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb b/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb
index b0737e2e01f7..f0d61be3d969 100644
--- a/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb
+++ b/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb
@@ -22,7 +22,6 @@
# Type dimensions
[
{ name: 'idea', parent: 'post' },
- { name: 'initiative', parent: 'post' },
{ name: 'comment', parent: 'idea' },
{ name: 'reaction', parent: 'idea' }
].each do |type|
@@ -37,7 +36,6 @@
idea = create(:idea, created_at: dates[0], author: male)
create(:comment, created_at: dates[2], post: idea, author: female)
create(:reaction, created_at: dates[3], user: create(:admin, gender: 'female'), reactable: idea)
- create(:initiative, created_at: dates[1], author: unspecified)
end
example 'group participations by month' do
@@ -52,7 +50,7 @@
})
assert_status 200
expect(response_data[:attributes]).to match_array([
- { 'dimension_date_created.month': '2022-09', count: 2 },
+ { 'dimension_date_created.month': '2022-09', count: 1 },
{ 'dimension_date_created.month': '2022-10', count: 2 }
])
end
diff --git a/back/engines/commercial/analytics/spec/models/analytics/dimension_status_spec.rb b/back/engines/commercial/analytics/spec/models/analytics/dimension_status_spec.rb
index 515a1c3ffc74..a5eb29dbad1f 100644
--- a/back/engines/commercial/analytics/spec/models/analytics/dimension_status_spec.rb
+++ b/back/engines/commercial/analytics/spec/models/analytics/dimension_status_spec.rb
@@ -10,13 +10,4 @@
expect { described_class.find(idea_status.id) }.not_to raise_error
end
end
-
- # TODO: cleanup-after-proposals-migration
- context 'when an initiative status is created' do
- let!(:initiative_status) { create(:initiative_status) }
-
- it 'is also available as a status dimension' do
- expect { described_class.find(initiative_status.id) }.not_to raise_error
- end
- end
end
diff --git a/back/engines/commercial/analytics/spec/models/analytics/fact_post_spec.rb b/back/engines/commercial/analytics/spec/models/analytics/fact_post_spec.rb
index be5bd5ccf3f5..c2f39722dd68 100644
--- a/back/engines/commercial/analytics/spec/models/analytics/fact_post_spec.rb
+++ b/back/engines/commercial/analytics/spec/models/analytics/fact_post_spec.rb
@@ -11,14 +11,4 @@
expect { described_class.find(idea.id) }.not_to raise_error
end
end
-
- # TODO: cleanup-after-proposals-migration
- context 'when an initiative is created and there is an initiative type' do
- let!(:type_initiative) { create(:dimension_type, name: 'initiative') }
- let!(:initiative) { create(:initiative) }
-
- it 'is also available as a post fact' do
- expect { described_class.find(initiative.id) }.not_to raise_error
- end
- end
end
diff --git a/back/engines/commercial/analytics/spec/services/analytics/query_runner_service_spec.rb b/back/engines/commercial/analytics/spec/services/analytics/query_runner_service_spec.rb
index d968fcaaeb4f..131fd644704d 100644
--- a/back/engines/commercial/analytics/spec/services/analytics/query_runner_service_spec.rb
+++ b/back/engines/commercial/analytics/spec/services/analytics/query_runner_service_spec.rb
@@ -23,9 +23,7 @@
it 'return groups with aggregations' do
idea = create(:idea)
- initiative = create(:initiative)
create_list(:reaction, 2, reactable: idea)
- create_list(:reaction, 1, reactable: initiative)
query_param = {
fact: 'post',
@@ -39,10 +37,7 @@
runner = described_class.new
results, * = runner.run(query)
- expected_result = [
- { 'dimension_type.name' => 'initiative', 'sum_reactions_count' => 1 },
- { 'dimension_type.name' => 'idea', 'sum_reactions_count' => 2 }
- ]
+ expected_result = [{ 'dimension_type.name' => 'idea', 'sum_reactions_count' => 2 }]
expect(results).to match_array expected_result
end
@@ -68,7 +63,6 @@
it 'return first two sorted posts' do
ideas = create_list(:idea, 5)
- initiatives = create_list(:initiative, 5)
query_param = {
fact: 'post',
@@ -79,7 +73,7 @@
runner = described_class.new
results, * = runner.run(query)
- posts = (ideas + initiatives)
+ posts = ideas
.sort_by { |p| p[:id] }
.map { |p| { 'id' => p.id } }
expect(results).to eq(posts)
From 4783d9435fc167c01394864fb1dc0e0a2cffd9b8 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Fri, 20 Dec 2024 11:54:47 +0000
Subject: [PATCH 62/63] [TAN-2538] Linting
---
.../analytics/spec/acceptance/analytics_participations_spec.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb b/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb
index f0d61be3d969..ae60c686fca8 100644
--- a/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb
+++ b/back/engines/commercial/analytics/spec/acceptance/analytics_participations_spec.rb
@@ -30,7 +30,7 @@
male = create(:user, gender: 'male')
female = create(:user, gender: 'female')
- unspecified = create(:user, gender: 'unspecified')
+ _unspecified = create(:user, gender: 'unspecified')
# Create participations (3 by citizens, 1 by admin)
idea = create(:idea, created_at: dates[0], author: male)
From a40997fb115959b5cd86f6234774d804105664e5 Mon Sep 17 00:00:00 2001
From: Simon Tharby
Date: Fri, 20 Dec 2024 14:10:37 +0000
Subject: [PATCH 63/63] [TAN-2538] Fix ThresholdReachedForAdminMailerPreview
---
.../threshold_reached_for_admin_mailer_preview.rb | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
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'
}