Skip to content

Commit

Permalink
Merge branch 'TAN-515-remove-continuous-code-engines' into TAN-515-re…
Browse files Browse the repository at this point in the history
…name-factories

# Conflicts:
#	back/engines/commercial/bulk_import_ideas/spec/services/print_custom_fields_service_spec.rb
  • Loading branch information
jamesspeake committed Nov 20, 2023
2 parents d0732a2 + fdada21 commit 6d5c8c4
Show file tree
Hide file tree
Showing 320 changed files with 4,442 additions and 2,145 deletions.
2 changes: 1 addition & 1 deletion back/.rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Metrics/BlockNesting:
# Offense count: 81
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
Max: 689
Max: 690

# Offense count: 1
# Configuration parameters: LengthThreshold.
Expand Down
2 changes: 1 addition & 1 deletion back/app/controllers/web_api/v1/phases_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class WebApi::V1::PhasesController < ApplicationController

def index
@phases = policy_scope(Phase)
.includes(:permissions)
.includes(:permissions, :report)
.where(project_id: params[:project_id])
.order(:start_at)
@phases = paginate @phases
Expand Down
4 changes: 2 additions & 2 deletions back/app/models/permission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ class Permission < ApplicationRecord
before_validation :set_permitted_by_and_global_custom_fields, on: :create
before_validation :update_global_custom_fields, on: :update

def self.available_actions(phase)
ACTIONS[phase&.participation_method]
def self.available_actions(permission_scope)
ACTIONS[permission_scope&.participation_method]
end

# Remove any actions that are not enabled on the project
Expand Down
2 changes: 2 additions & 0 deletions back/app/models/phase.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class Phase < ApplicationRecord
before_destroy :remove_notifications # Must occur before has_many :notifications (see https://github.com/rails/rails/issues/5205)
has_many :notifications, dependent: :nullify

has_one :report, class_name: 'ReportBuilder::Report', dependent: :destroy

validates :project, presence: true
validates :title_multiloc, presence: true, multiloc: { presence: true }
validates :description_multiloc, multiloc: { presence: false, html: true }
Expand Down
2 changes: 1 addition & 1 deletion back/app/serializers/web_api/v1/custom_field_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class WebApi::V1::CustomFieldSerializer < WebApi::V1::BaseSerializer
:enabled, :code, :created_at, :updated_at, :logic

attribute :description_multiloc do |field|
TextImageService.new.render_data_images field, :description_multiloc
TextImageService.new.render_data_images_multiloc field.description_multiloc, field: :description_multiloc, imageable: field
end

attribute :answer_visible_to, if: proc { |_object, params|
Expand Down
2 changes: 1 addition & 1 deletion back/app/serializers/web_api/v1/event_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class WebApi::V1::EventSerializer < WebApi::V1::BaseSerializer
)

attribute :description_multiloc do |object|
TextImageService.new.render_data_images object, :description_multiloc
TextImageService.new.render_data_images_multiloc object.description_multiloc, field: :description_multiloc, imageable: object
end

has_many :event_images, serializer: WebApi::V1::ImageSerializer
Expand Down
2 changes: 1 addition & 1 deletion back/app/serializers/web_api/v1/folder_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class WebApi::V1::FolderSerializer < WebApi::V1::BaseSerializer
end

attribute :description_multiloc do |object|
TextImageService.new.render_data_images object, :description_multiloc
TextImageService.new.render_data_images_multiloc object.description_multiloc, field: :description_multiloc, imageable: object
end

attribute :header_bg do |object|
Expand Down
14 changes: 10 additions & 4 deletions back/app/serializers/web_api/v1/home_page_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ class WebApi::V1::HomePageSerializer < WebApi::V1::BaseSerializer
:banner_cta_signed_out_text_multiloc,
:banner_cta_signed_out_type,
:banner_cta_signed_out_url,
:pinned_admin_publication_ids,
:craftjs_json
:pinned_admin_publication_ids

attribute :header_bg do |object|
object.header_bg && object.header_bg.versions.to_h { |k, v| [k.to_s, v.url] }
Expand All @@ -30,13 +29,20 @@ class WebApi::V1::HomePageSerializer < WebApi::V1::BaseSerializer
attribute :top_info_section_multiloc, if: proc { |object, _|
object.top_info_section_multiloc.present?
} do |object|
TextImageService.new.render_data_images object, :top_info_section_multiloc
TextImageService.new.render_data_images_multiloc object.top_info_section_multiloc, field: :top_info_section_multiloc, imageable: object
end

attribute :bottom_info_section_multiloc, if: proc { |object, _|
object.bottom_info_section_multiloc.present?
} do |object|
TextImageService.new.render_data_images object, :bottom_info_section_multiloc
TextImageService.new.render_data_images_multiloc object.bottom_info_section_multiloc, field: :bottom_info_section_multiloc, imageable: object
end

attribute :craftjs_json, if: proc {
AppConfiguration.instance.feature_activated? 'homepage_builder'
} do |homepage|
# TODO: move to layout
ContentBuilder::LayoutImageService.new.render_data_images homepage.craftjs_json
end

has_many :pinned_admin_publications, serializer: :admin_publication
Expand Down
2 changes: 1 addition & 1 deletion back/app/serializers/web_api/v1/idea_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class WebApi::V1::IdeaSerializer < WebApi::V1::BaseSerializer
end

attribute :body_multiloc do |object|
TextImageService.new.render_data_images object, :body_multiloc
TextImageService.new.render_data_images_multiloc object.body_multiloc, field: :body_multiloc, imageable: object
end

attribute :internal_comments_count, if: proc { |object, params|
Expand Down
2 changes: 1 addition & 1 deletion back/app/serializers/web_api/v1/initiative_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class WebApi::V1::InitiativeSerializer < WebApi::V1::BaseSerializer
end

attribute :body_multiloc do |object|
TextImageService.new.render_data_images object, :body_multiloc
TextImageService.new.render_data_images_multiloc object.body_multiloc, field: :body_multiloc, imageable: object
end

attribute :header_bg do |object|
Expand Down
4 changes: 3 additions & 1 deletion back/app/serializers/web_api/v1/phase_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class WebApi::V1::PhaseSerializer < WebApi::V1::ParticipationContextSerializer
attributes :title_multiloc, :start_at, :end_at, :created_at, :updated_at, :ideas_count, :campaigns_settings

attribute :description_multiloc do |object|
TextImageService.new.render_data_images object, :description_multiloc
TextImageService.new.render_data_images_multiloc object.description_multiloc, field: :description_multiloc, imageable: object
end

attribute :previous_phase_end_at_updated do |object|
Expand All @@ -23,6 +23,8 @@ class WebApi::V1::PhaseSerializer < WebApi::V1::ParticipationContextSerializer
user_basket object, params
end

has_one :report, serializer: ReportBuilder::WebApi::V1::ReportSerializer

has_many :permissions

def self.user_basket(object, params)
Expand Down
2 changes: 1 addition & 1 deletion back/app/serializers/web_api/v1/project_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class WebApi::V1::ProjectSerializer < WebApi::V1::ParticipationContextSerializer
end

attribute :description_multiloc do |object|
TextImageService.new.render_data_images object, :description_multiloc
TextImageService.new.render_data_images_multiloc object.description_multiloc, field: :description_multiloc, imageable: object
end

attribute :header_bg do |object|
Expand Down
4 changes: 2 additions & 2 deletions back/app/serializers/web_api/v1/static_page_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ class WebApi::V1::StaticPageSerializer < WebApi::V1::BaseSerializer
attribute :top_info_section_multiloc, if: proc { |object, _|
object.top_info_section_multiloc.present?
} do |object|
TextImageService.new.render_data_images object, :top_info_section_multiloc
TextImageService.new.render_data_images_multiloc object.top_info_section_multiloc, field: :top_info_section_multiloc, imageable: object
end

attribute :bottom_info_section_multiloc, if: proc { |object, _|
object.bottom_info_section_multiloc.present?
} do |object|
TextImageService.new.render_data_images object, :bottom_info_section_multiloc
TextImageService.new.render_data_images_multiloc object.bottom_info_section_multiloc, field: :bottom_info_section_multiloc, imageable: object
end

# This is used to keep supporting default titles for
Expand Down
37 changes: 28 additions & 9 deletions back/app/services/activities_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,60 @@ def create_periodic_activities(now: Time.zone.now, since: 1.hour)
def create_phase_started_activities(now, last_time)
return unless now.to_date != last_time.to_date

Phase.published.starting_on(now.to_date).each do |phase|
start_date = now.to_date
starting_phases = Phase.published.starting_on(start_date)

# Phases that already have a started activity for *this starting date* are excluded
# to avoid creating duplicate activities (and, consequently, duplicate
# notifications). We still allow the creation of new activities when the start date
# is different (which can occur if the phase is edited).
excluded_phases = Activity
.where(item_id: starting_phases, action: 'started', acted_at: start_date)
.select(:item_id)

starting_phases.where.not(id: excluded_phases).each do |phase|
if phase.ends_before?(now + 1.day)
raise "Invalid phase started event would have been generated for phase\
#{phase.id} with now=#{now} and last_time=#{last_time}"
end

LogActivityJob.perform_later(phase, 'started', nil, phase.start_at.to_time.to_i)
LogActivityJob.perform_later(phase, 'started', nil, start_date.to_time)
end
end

def create_phase_upcoming_activities(now, last_time)
return unless now.to_date != last_time.to_date
today = now.to_date
return unless today != last_time.to_date

upcoming_phases = Phase.published.starting_on(today..(today + 1.week))
# Exclude phases for which an upcoming activity has already been created to avoid
# duplicate notifications.
excluded_phases = Activity
.where(item_id: upcoming_phases, action: 'upcoming')
.select(:item_id)

Phase.published.starting_on(now.to_date + 1.week).each do |phase|
upcoming_phases.where.not(id: excluded_phases).each do |phase|
if phase.ends_before?(now + 1.day)
raise "Invalid phase upcoming event would have been generated for phase\
#{phase.id} with now=#{now} and last_time=#{last_time}"
end

LogActivityJob.perform_later(phase, 'upcoming', nil, now.to_i)
LogActivityJob.perform_later(phase, 'upcoming', nil, now)
end
end

def create_invite_not_accepted_since_3_days_activities(now, last_time)
Invite.where(accepted_at: nil)
.where(created_at: (last_time - 3.days)..(now - 3.days)).each do |invite|
LogActivityJob.perform_later(invite, 'not_accepted_since_3_days', nil, now.to_i)
LogActivityJob.perform_later(invite, 'not_accepted_since_3_days', nil, now)
end
end

def create_phase_ending_soon_activities(now)
if now.hour >= 8 && now.hour <= 20 # Only log activities during day time so they emails are more likely to be noticed
Phase.published.where(end_at: now..now + 2.days).each do |phase|
if Activity.find_by(item: phase, action: 'ending_soon').nil?
LogActivityJob.perform_later(phase, 'ending_soon', nil, now.to_i)
LogActivityJob.perform_later(phase, 'ending_soon', nil, now)
end
end
end
Expand All @@ -62,15 +81,15 @@ def create_phase_ending_soon_activities(now)
def create_basket_not_submitted_activities(now)
Basket.not_submitted.each do |basket|
if Activity.find_by(item: basket, action: 'not_submitted').nil? && basket.baskets_ideas.present? && basket.baskets_ideas.order(:updated_at).last.updated_at <= now - 1.day
LogActivityJob.perform_later(basket, 'not_submitted', nil, now.to_i)
LogActivityJob.perform_later(basket, 'not_submitted', nil, now)
end
end
end

def create_phase_ended_activities(now)
Phase.published.where(end_at: ..now).each do |phase|
if Activity.find_by(item: phase, action: 'ended').nil?
LogActivityJob.perform_later(phase, 'ended', nil, now.to_i)
LogActivityJob.perform_later(phase, 'ended', nil, now)
end
end
end
Expand Down
97 changes: 57 additions & 40 deletions back/app/services/content_image_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,62 @@ def initialize(options = {})
attr_reader :parse_errors
end

def swap_data_images(imageable, field)
multiloc = imageable.send field
multiloc.each_with_object({}) do |(locale, encoded_content), output|
content = begin
decode_content encoded_content
rescue DecodingError => e
log_decoding_error e
output[locale] = encoded_content
next
end
def swap_data_images_multiloc(multiloc, imageable: nil, field: nil)
multiloc.transform_values do |encoded_content|
swap_data_images encoded_content, imageable: imageable, field: field
end
end

def swap_data_images(encoded_content, imageable: nil, field: nil)
content = begin
decode_content encoded_content
rescue DecodingError => e
log_decoding_error e
end
return encoded_content if !content

image_elements(content).each do |img_elt|
next unless attribute? img_elt, image_attribute_for_element
image_elements(content).each do |img_elt|
next if image_attributes_for_element.none? { |elt_atr| attribute? img_elt, elt_atr }

unless attribute? img_elt, code_attribute_for_element
content_image = content_image_class.create! image_attributes(img_elt, imageable, field)
set_attribute! img_elt, code_attribute_for_element, content_image[code_attribute_for_model]
end
remove_attribute! img_elt, image_attribute_for_element
if !attribute? img_elt, code_attribute_for_element
content_image = content_image_class.create! image_attributes(img_elt, imageable, field)
set_attribute! img_elt, code_attribute_for_element, content_image[code_attribute_for_model]
end
image_attributes_for_element.each do |elt_atr|
remove_attribute! img_elt, elt_atr
end

output[locale] = encode_content content
end

encode_content content
end

def render_data_images(imageable, field)
multiloc = imageable.send field
def render_data_images_multiloc(multiloc, imageable: nil, field: nil)
return multiloc if multiloc.blank?
return multiloc if multiloc.values.none? { |encoded_content| could_include_images?(encoded_content) }

return multiloc if multiloc.nil?
return multiloc unless multiloc.values.any? { |encoded_content| could_include_images?(encoded_content) }
precompute_for_rendering_multiloc multiloc, imageable, field

precompute_for_rendering multiloc, imageable, field
multiloc.transform_values do |encoded_content|
render_data_images encoded_content, imageable: imageable, field: field
end
end

multiloc.each_with_object({}) do |(locale, encoded_content), output|
content = decode_content encoded_content
def render_data_images(encoded_content, imageable: nil, field: nil)
content = decode_content encoded_content
precompute_for_rendering content, imageable, field

image_elements(content).each do |img_elt|
next unless attribute? img_elt, code_attribute_for_element
image_elements(content).each do |img_elt|
next if !attribute? img_elt, code_attribute_for_element

code = get_attribute img_elt, code_attribute_for_element
content_image = fetch_content_image code
if content_image.present?
set_attribute! img_elt, image_attribute_for_element, content_image_url(content_image)
else
log_content_image_not_found code, imageable, field
end
code = get_attribute img_elt, code_attribute_for_element
content_image = fetch_content_image code
if content_image.present?
set_image_attributes! img_elt, content_image
else
log_content_image_not_found code, imageable, field
end
output[locale] = encode_content content
end
encode_content content
end

protected
Expand Down Expand Up @@ -95,6 +102,10 @@ def get_attribute(img_elt, image_attribute)
img_elt[image_attribute]
end

def set_image_attributes!(img_elt, content_image)
set_attribute! img_elt, image_attribute_for_element, content_image_url(content_image)
end

def set_attribute!(img_elt, attribute, value)
# Hash representation by default.
img_elt[attribute] = value
Expand All @@ -113,6 +124,10 @@ def image_attribute_for_element
'src'
end

def image_attributes_for_element
[image_attribute_for_element]
end

def code_attribute_for_model
'code'
end
Expand All @@ -121,7 +136,9 @@ def could_include_images?(_encoded_content)
true
end

def precompute_for_rendering(_multiloc, _imageable, _field); end
def precompute_for_rendering_multiloc(_multiloc, _imageable, _field); end

def precompute_for_rendering(content, imageable, field); end

def fetch_content_image(code)
content_image_class.find_by code_attribute_for_model => code
Expand All @@ -142,9 +159,9 @@ def log_content_image_not_found(code, imageable, field)
Exception.new('No content image found with code'),
extra: {
code: code,
imageable_type: imageable.class,
imageable_id: imageable.id,
imageable_created_at: imageable.created_at,
imageable_type: imageable&.class,
imageable_id: imageable&.id,
imageable_created_at: imageable&.created_at,
imageable_field: field
}
)
Expand Down
Loading

0 comments on commit 6d5c8c4

Please sign in to comment.