Skip to content
Snippets Groups Projects
block.rb 5.63 KiB
Newer Older
Arnaud Levy's avatar
Arnaud Levy committed
# == Schema Information
#
# Table name: communication_blocks
#
Arnaud Levy's avatar
Arnaud Levy committed
#  id                       :uuid             not null, primary key
#  about_type               :string           indexed => [about_id]
#  data                     :jsonb
#  position                 :integer          default(0), not null
#  published                :boolean          default(TRUE)
#  template_kind            :integer          default(NULL), not null
#  title                    :string
#  created_at               :datetime         not null
#  updated_at               :datetime         not null
#  about_id                 :uuid             indexed => [about_type]
#  communication_website_id :uuid             indexed
#  heading_id               :uuid             indexed
#  university_id            :uuid             not null, indexed
Arnaud Levy's avatar
Arnaud Levy committed
#
# Indexes
#
Arnaud Levy's avatar
Arnaud Levy committed
#  index_communication_blocks_on_communication_website_id  (communication_website_id)
#  index_communication_blocks_on_heading_id                (heading_id)
#  index_communication_blocks_on_university_id             (university_id)
#  index_communication_website_blocks_on_about             (about_type,about_id)
Arnaud Levy's avatar
Arnaud Levy committed
#
# Foreign Keys
#
#  fk_rails_18291ef65f  (university_id => universities.id)
Arnaud Levy's avatar
Arnaud Levy committed
#  fk_rails_80e5625874  (communication_website_id => communication_websites.id)
Arnaud Levy's avatar
Arnaud Levy committed
#  fk_rails_90ac986fab  (heading_id => communication_block_headings.id)
Arnaud Levy's avatar
Arnaud Levy committed
#
class Communication::Block < ApplicationRecord
Arnaud Levy's avatar
Arnaud Levy committed
  include AsIndirectObject
Arnaud Levy's avatar
Arnaud Levy committed
  include WithAccessibility
Arnaud Levy's avatar
Arnaud Levy committed
  include WithPosition
Arnaud Levy's avatar
Arnaud Levy committed
  include WithUniversity
  include Sanitizable
Arnaud Levy's avatar
Arnaud Levy committed

Arnaud Levy's avatar
Arnaud Levy committed
  IMAGE_MAX_SIZE = 5.megabytes
Arnaud Levy's avatar
Arnaud Levy committed
  FILE_MAX_SIZE = 100.megabytes
Arnaud Levy's avatar
Arnaud Levy committed

Arnaud Levy's avatar
Arnaud Levy committed
  belongs_to :about, polymorphic: true
Arnaud Levy's avatar
Arnaud Levy committed
  belongs_to :heading, optional: true
Arnaud Levy's avatar
Arnaud Levy committed
  belongs_to  :communication_website,
              class_name: "Communication::Website",
              optional: true
  alias       :website :communication_website
Arnaud Levy's avatar
Arnaud Levy committed

Sébastien Gaya's avatar
Sébastien Gaya committed
  # We do not use the :touch option of the belongs_to association
  # because we do not want to touch the about when destroying the block.
  after_save :touch_about
Arnaud Levy's avatar
Arnaud Levy committed

Sébastien Gaya's avatar
Sébastien Gaya committed
  # Used to purge images when unattaching them
Arnaud Levy's avatar
Arnaud Levy committed
  # template_blobs would be a better name, because there are files
  has_many_attached :template_images

Arnaud Levy's avatar
Arnaud Levy committed
  # Les numéros sont un peu en vrac
  # Dans l'idée, pour le futur
  # 1000 basic
  # 2000 storytelling
  # 3000 references
  # 4000 utilities
Arnaud Levy's avatar
Arnaud Levy committed
  enum template_kind: {
Arnaud Levy's avatar
Arnaud Levy committed
    chapter: 50,
Arnaud Levy's avatar
Arnaud Levy committed
    image: 51,
Arnaud Levy's avatar
Arnaud Levy committed
    gallery: 300,
Arnaud Levy's avatar
Arnaud Levy committed
    video: 52,
Arnaud Levy's avatar
Arnaud Levy committed
    sound: 1005,
Arnaud Levy's avatar
Arnaud Levy committed
    key_figures: 56,
Arnaud Levy's avatar
Arnaud Levy committed
    features: 2010,
Arnaud Levy's avatar
Arnaud Levy committed
    datatable: 54,
    files: 55,
    embed: 53,
    call_to_action: 900,
alexisben's avatar
alexisben committed
    testimonials: 400,
alexisben's avatar
alexisben committed
    timeline: 700,
alexisben's avatar
alexisben committed
    definitions: 800,
Arnaud Levy's avatar
Arnaud Levy committed
    organization_chart: 100,
    partners: 200,
    posts: 500,
    pages: 600,
alexisben's avatar
alexisben committed
    contact: 57,
    programs: 58
Arnaud Levy's avatar
Arnaud Levy committed
  }

  CATEGORIES = {
Arnaud Levy's avatar
Arnaud Levy committed
    basic: [:chapter, :image, :video, :sound, :datatable],
Arnaud Levy's avatar
Arnaud Levy committed
    storytelling: [:key_figures, :features, :gallery, :call_to_action, :testimonials, :timeline],
alexisben's avatar
alexisben committed
    references: [:pages, :posts, :organization_chart, :partners, :programs],
alexisben's avatar
alexisben committed
    utilities: [:files, :definitions, :embed, :contact]
  scope :published, -> { where(published: true) }
  scope :without_heading, -> { where(heading: nil) }
Arnaud Levy's avatar
Arnaud Levy committed

  before_validation :set_heading_from_about, on: :create
Arnaud Levy's avatar
Arnaud Levy committed
  before_save :attach_template_blobs
Arnaud Levy's avatar
Arnaud Levy committed
  before_validation :set_university_and_website_from_about, on: :create
Arnaud Levy's avatar
Arnaud Levy committed
  # When we set data from json, we pass it to the template.
  # The json we save is first sanitized and prepared by the template.
Arnaud Levy's avatar
Arnaud Levy committed
  def data=(value)
Arnaud Levy's avatar
Arnaud Levy committed
    template.data = value
Arnaud Levy's avatar
Arnaud Levy committed
    super template.data
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  # Template data is clean and sanitized, and initialized with json
Arnaud Levy's avatar
Arnaud Levy committed
  def data
Arnaud Levy's avatar
Arnaud Levy committed
    template.data
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def dependencies
    template.dependencies
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def references
    [about]
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def template
Arnaud Levy's avatar
Arnaud Levy committed
    @template ||= template_class.new self, self.attributes['data']
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def template_reset!
    @template = nil
  end

  def language
    return @language if defined?(@language)
    @language ||= about.respond_to?(:language) ? about.language : about.university.default_language
Arnaud Levy's avatar
Arnaud Levy committed
  def duplicate
    block = self.dup
    block.save
    block
  end

  def translate!(about_translation, heading_id = nil)
    translation = self.dup
    translation.about = about_translation
    translation.template.translate!
    translation.data = translation.template.data
    translation.save
pabois's avatar
pabois committed
    translation.heading_id = heading_id
Arnaud Levy's avatar
Arnaud Levy committed
  def to_s
Arnaud Levy's avatar
Arnaud Levy committed
    title.blank?  ? "#{Communication::Block.model_name.human} #{position}"
                  : "#{title}"
Arnaud Levy's avatar
Arnaud Levy committed
  end
Sébastien Gaya's avatar
Sébastien Gaya committed
  def last_ordered_element
    about.blocks.ordered.last
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def set_university_and_website_from_about
    # about always have an university_id but can have no communication_website_id
Arnaud Levy's avatar
Arnaud Levy committed
    self.university_id = about.university_id
Arnaud Levy's avatar
Arnaud Levy committed
    self.communication_website_id = about.try(:communication_website_id)
Arnaud Levy's avatar
Arnaud Levy committed
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def check_accessibility
    accessibility_merge template
  end

Arnaud Levy's avatar
Arnaud Levy committed
  def template_class
    "Communication::Block::Template::#{template_kind.classify}".constantize
  end

  def set_heading_from_about
Arnaud Levy's avatar
Arnaud Levy committed
    # IMPROVEMENT: Ne gère que le 1er niveau actuellement
pabois's avatar
pabois committed
    self.heading ||= about.headings.root.ordered.last
Arnaud Levy's avatar
Arnaud Levy committed
  # FIXME @sebou
  # Could not find or build blob: expected attachable, got #<ActiveStorage::Blob id: "f4c78657-5062-416b-806f-0b80fb66f9cd", key: "gri33wtop0igur8w3a646llel3sd", filename: "logo.svg", content_type: "image/svg+xml", metadata: {"identified"=>true, "width"=>709, "height"=>137, "analyzed"=>true}, service_name: "scaleway", byte_size: 4137, checksum: "aZqqTYabP5+72ZeddcZ/2Q==", created_at: "2022-05-05 12:17:33.941505000 +0200", university_id: "ebf2d273-ffc9-4d9f-a4ee-a2146913d617">
Arnaud Levy's avatar
Arnaud Levy committed
  def attach_template_blobs
Arnaud Levy's avatar
Arnaud Levy committed
    # self.template_images = template.active_storage_blobs
Sébastien Gaya's avatar
Sébastien Gaya committed

  def touch_about
    about.touch
  end
Arnaud Levy's avatar
Arnaud Levy committed
end