class Node < ApplicationRecord
|
|
|
|
MENUS = %i""
|
|
COOKIE_POLICY = :cookie_policy
|
|
SETTINGS = MENUS << COOKIE_POLICY
|
|
|
|
include AncestryWithSortedUrl
|
|
include HasAttachments
|
|
include HasTags
|
|
|
|
|
|
extend Mobility
|
|
translates :slug,
|
|
:tags,
|
|
locale_accessors: I18n.available_locales,
|
|
fallbacks: {zh: :en, hr: :en, cs: :en, da: :en, nl: :en, fi: :en, fr: :en, de: :en, hu: :en, it: :en, ja: :en, ko: :en, nb: :en, pl: :en, pt: :en, ro: :en, sr: :en, sk: :en, sl: :en, es: :en, sv: :en, uk: :en}
|
|
|
|
translates :title,
|
|
:url,
|
|
:href,
|
|
:page_title,
|
|
:page_description,
|
|
locale_accessors: I18n.available_locales,
|
|
fallbacks: {zh: :en, hr: :en, cs: :en, da: :en, nl: :en, fi: :en, fr: :en, de: :en, hu: :en, it: :en, ja: :en, ko: :en, nb: :en, pl: :en, pt: :en, ro: :en, sr: :en, sk: :en, sl: :en, es: :en, sv: :en, uk: :en}
|
|
|
|
|
|
NODE_TEMPLATES = %w"tmpl_article tmpl_index tmpl_list"
|
|
|
|
enum status: { status_published: 0, status_draft: 1, status_archived: 2 }
|
|
|
|
enum template: { tmpl_index: 0,
|
|
tmpl_article: 1,
|
|
tmpl_list: 2
|
|
}
|
|
|
|
include PgSearch::Model
|
|
pg_search_scope :pg_search,
|
|
against: {title: 'A', url: 'B', page_title: 'A', page_description: 'B', href: 'B', slug: 'B' },
|
|
associated_against: {
|
|
attachments: [:body, :url]
|
|
}
|
|
|
|
before_validation :remove_empty_tags
|
|
|
|
validates_presence_of :title
|
|
|
|
validates :expires_at,
|
|
date: { after: :published_at },
|
|
allow_nil: true
|
|
|
|
scope :ordered, -> { order(position: :asc) }
|
|
scope :by_title, ->(rev) { order(Arel.sql(rev ? "title->>'#{I18n.locale.to_s}' DESC, id DESC": "title ->>'#{I18n.locale.to_s}' ASC, id ASC")) }
|
|
scope :by_status, ->(rev) { order(status: rev ? :desc : :asc, id: rev ? :desc : :asc) }
|
|
scope :by_slug, ->(rev) { order(ancestry: rev ? :desc : :asc, position: rev ? :desc : :asc, id: rev ? :desc : :asc) }
|
|
scope :by_last_modified, ->(rev) { order(updated_at: rev ? :asc : :desc, id: rev ? :desc : :asc) }
|
|
|
|
# scope :not_excluded, -> { where "NOT(? = ANY (excluded_locales))", I18n.locale.to_s }
|
|
|
|
scope :for_current_locale, -> { where("(cardinality(excluded_locales) = 0 AND is_allowlist = false) OR
|
|
(is_allowlist = true AND ? = ANY(excluded_locales)) OR
|
|
(is_allowlist = false AND NOT(? = ANY(excluded_locales)))",
|
|
I18n.locale.to_s, I18n.locale.to_s ) }
|
|
|
|
scope :viewable, -> { status_published.for_current_locale.where('published_at <= ? AND (expires_at IS NULL OR expires_at > ?)', Time.current, Time.current) }
|
|
scope :of_template, ->(tmpl) { where(template: Node.templates[tmpl.to_s]) }
|
|
|
|
scope :with_setting, ->(setting) { setting.kind_of?(Array) ? where("settings && ?", "{#{setting.join(',')}}") : where("settings @> ?", "{#{setting}}") }
|
|
|
|
scope :simple_search, ->(q) { pg_search(q) unless q.blank? }
|
|
|
|
scope :tiles, -> { where("ancestry LIKE '/?/%'", Node.where(position: 2, ancestry_depth: 0).first) }
|
|
|
|
def self.tags
|
|
result = {}
|
|
I18n.available_locales.each do |locale|
|
|
result[locale] = pluck(Arel.sql("tags->'#{locale}'")).flatten.compact.uniq.sort.reject{|v| v.blank?}
|
|
end
|
|
result
|
|
end
|
|
|
|
|
|
def self.categories
|
|
['document']
|
|
end
|
|
|
|
|
|
def category
|
|
self.children.any? ? 'folder' : 'document'
|
|
end
|
|
|
|
|
|
def document?
|
|
self.category == 'document'
|
|
end
|
|
|
|
|
|
def href_or_url
|
|
href.present?? href : url
|
|
end
|
|
|
|
|
|
def viewable?
|
|
Node.viewable.where(id: self.path_ids).count == self.path_ids.length
|
|
end
|
|
|
|
|
|
def index?
|
|
self.attachments.blank?
|
|
end
|
|
|
|
|
|
def site?
|
|
(self.root || self).position == 1
|
|
end
|
|
|
|
|
|
def tile?
|
|
(self.root || self).position == 2
|
|
end
|
|
|
|
|
|
def node_type
|
|
return "site" if self.site?
|
|
'tile'
|
|
end
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
def remove_empty_tags
|
|
%w"settings excluded_locales tags_en tags_zh tags_hr tags_cs tags_da tags_nl tags_fi tags_fr tags_de tags_hu tags_it tags_ja tags_ko tags_nb tags_pl tags_pt tags_ro tags_sr tags_sk tags_sl tags_es tags_sv tags_uk ".map do |k|
|
|
self.send "#{k}=", self.send(k).reject { |v| v.blank? } unless self.send(k).blank?
|
|
end
|
|
end
|
|
|
|
end
|