summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/asset.rb12
-rw-r--r--app/models/asset_license.rb15
-rw-r--r--app/models/concerns/file_attachment.rb11
-rw-r--r--app/models/node_action.rb8
-rw-r--r--app/models/page.rb22
-rw-r--r--app/models/related_asset.rb9
6 files changed, 59 insertions, 18 deletions
diff --git a/app/models/asset.rb b/app/models/asset.rb
index aca0ee8..4a295d8 100644
--- a/app/models/asset.rb
+++ b/app/models/asset.rb
@@ -1,12 +1,22 @@
1class Asset < ApplicationRecord 1class Asset < ApplicationRecord
2 IMAGE_CONTENT_TYPES = ["image/gif", "image/jpeg", "image/png", "image/webp"]
2 3
3 include FileAttachment 4 include FileAttachment
4 5
5 has_many :related_assets, :dependent => :destroy 6 has_many :related_assets, :dependent => :destroy
6 has_many :pages, :through => :related_assets 7 has_many :pages, :through => :related_assets
7 8
8 scope :images, -> { where(:upload_content_type => ["image/gif", "image/jpeg", "image/png", "image/webp"]) } 9 scope :images, -> { where(:upload_content_type => IMAGE_CONTENT_TYPES) }
9 scope :documents, -> { where(:upload_content_type => ["application/pdf", "text/plain", "text/rtf"]) } 10 scope :documents, -> { where(:upload_content_type => ["application/pdf", "text/plain", "text/rtf"]) }
10 scope :audio, -> { where(:upload_content_type => ["audio/mpeg", "audio/x-m4a", "audio/wav", "audio/x-wav"]) } 11 scope :audio, -> { where(:upload_content_type => ["audio/mpeg", "audio/x-m4a", "audio/wav", "audio/x-wav"]) }
11 12
13 validates :license_key, inclusion: { in: -> { AssetLicense.keys } }, allow_blank: true
14
15 def image?
16 IMAGE_CONTENT_TYPES.include?(upload_content_type)
17 end
18
19 def has_credit?
20 creator.present? || source_url.present? || license_key.present?
21 end
12end 22end
diff --git a/app/models/asset_license.rb b/app/models/asset_license.rb
new file mode 100644
index 0000000..ca66d40
--- /dev/null
+++ b/app/models/asset_license.rb
@@ -0,0 +1,15 @@
1class AssetLicense
2 Entry = Struct.new(:key, :url, :requires_attribution, :style, keyword_init: true)
3
4 DICTIONARY = YAML.load_file(Rails.root.join("config", "asset_licenses.yml")).freeze
5
6 def self.keys
7 DICTIONARY.keys
8 end
9
10 def self.find(key)
11 entry = DICTIONARY[key.to_s] if key.present?
12 return nil unless entry
13 Entry.new(key: key.to_s, url: entry["url"], requires_attribution: entry["requires_attribution"], style: entry["style"])
14 end
15end
diff --git a/app/models/concerns/file_attachment.rb b/app/models/concerns/file_attachment.rb
index 613a6f0..e7a33c5 100644
--- a/app/models/concerns/file_attachment.rb
+++ b/app/models/concerns/file_attachment.rb
@@ -52,6 +52,14 @@ module FileAttachment
52 build_upload_proxy 52 build_upload_proxy
53 end 53 end
54 54
55 def has_variant?(style)
56 upload_file_name.present? && File.exist?(file_path(style))
57 end
58
59 def previewable?
60 has_variant?(:medium)
61 end
62
55 private 63 private
56 64
57 def build_upload_proxy 65 def build_upload_proxy
@@ -106,7 +114,8 @@ module FileAttachment
106 end 114 end
107 115
108 def sanitize_filename(filename) 116 def sanitize_filename(filename)
109 File.basename(filename).gsub(/[^\w\.\-]/, '_') 117 name = File.basename(filename).unicode_normalize(:nfc)
118 name.gsub(/(?u)[^\w\.\-]/, '_')
110 end 119 end
111 120
112 # Proxy object returned by asset.upload, providing the Paperclip-compatible 121 # Proxy object returned by asset.upload, providing the Paperclip-compatible
diff --git a/app/models/node_action.rb b/app/models/node_action.rb
index 13bd5ba..63a99ae 100644
--- a/app/models/node_action.rb
+++ b/app/models/node_action.rb
@@ -166,4 +166,12 @@ class NodeAction < ApplicationRecord
166 def subject_name 166 def subject_name
167 metadata["human_readable_node_name"] || node&.unique_name || "deleted node" 167 metadata["human_readable_node_name"] || node&.unique_name || "deleted node"
168 end 168 end
169
170 def diff_link_params
171 prev = NodeAction.where(node_id: node_id, action: "publish")
172 .where("id < ?", id)
173 .order(id: :desc).first
174 return nil unless prev&.page && page
175 { start_revision: prev.page.revision, end_revision: page.revision }
176 end
169end 177end
diff --git a/app/models/page.rb b/app/models/page.rb
index f33d88d..c1498fc 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -220,7 +220,12 @@ class Page < ApplicationRecord
220 end 220 end
221 221
222 # Clone asset references 222 # Clone asset references
223 self.assets = page.assets 223 self.related_assets.delete_all
224 page.related_assets.each do |related|
225 self.related_assets.create!(:asset_id => related.asset_id,
226 :position => related.position,
227 :headline => related.headline)
228 end
224 229
225 self.save 230 self.save
226 end 231 end
@@ -314,21 +319,6 @@ class Page < ApplicationRecord
314 end 319 end
315 end 320 end
316 321
317 def update_assets image_ids
318
319 transaction do
320 self.related_assets.delete_all
321
322 if image_ids
323 image_ids.each_with_index do |id, index|
324 asset = Asset.find(id)
325 self.related_assets.create!(:asset_id => asset.id, :position => index+1)
326 end
327 end
328 end
329
330 end
331
332 # Installs (or re-installs) the trigger that keeps page_translations' 322 # Installs (or re-installs) the trigger that keeps page_translations'
333 # search_vector in sync. Idempotent, safe to call on every boot. 323 # search_vector in sync. Idempotent, safe to call on every boot.
334 # search_vector is populated by a raw Postgres trigger, not anything 324 # search_vector is populated by a raw Postgres trigger, not anything
diff --git a/app/models/related_asset.rb b/app/models/related_asset.rb
index 8f16460..62000cc 100644
--- a/app/models/related_asset.rb
+++ b/app/models/related_asset.rb
@@ -5,4 +5,13 @@ class RelatedAsset < ApplicationRecord
5 acts_as_list :scope => :page_id 5 acts_as_list :scope => :page_id
6 6
7 default_scope -> { order("position ASC") } 7 default_scope -> { order("position ASC") }
8
9 validate :headline_only_for_images
10
11 private
12
13 def headline_only_for_images
14 return unless asset
15 errors.add(:headline, "can only be set on image assets") if headline? && !asset.image?
16 end
8end 17end