118 行
3.9 KiB
Ruby
118 行
3.9 KiB
Ruby
class PostVersionsController < ApplicationController
|
|
def index
|
|
post_id = params[:post].presence
|
|
tag_id = params[:tag].presence
|
|
page = (params[:page].presence || 1).to_i
|
|
limit = (params[:limit].presence || 20).to_i
|
|
|
|
page = 1 if page < 1
|
|
limit = 1 if limit < 1
|
|
|
|
offset = (page - 1) * limit
|
|
|
|
tag_name =
|
|
if tag_id
|
|
TagName.joins(:tag).find_by(tag: { id: tag_id })
|
|
end
|
|
return render json: { versions: [], count: 0 } if tag_id && tag_name.blank?
|
|
|
|
q = PostVersion.joins(<<~SQL.squish)
|
|
LEFT JOIN
|
|
post_versions prev
|
|
ON
|
|
prev.post_id = post_versions.post_id
|
|
AND prev.version_no = post_versions.version_no - 1
|
|
SQL
|
|
.select('post_versions.*',
|
|
'prev.title AS prev_title',
|
|
'prev.url AS prev_url',
|
|
'prev.thumbnail_base AS prev_thumbnail_base',
|
|
'prev.tags_json AS prev_tags_json',
|
|
'prev.video_ms AS prev_video_ms',
|
|
'prev.original_created_from AS prev_original_created_from',
|
|
'prev.original_created_before AS prev_original_created_before')
|
|
q = q.where('post_versions.post_id = ?', post_id) if post_id
|
|
if tag_name
|
|
escaped = ActiveRecord::Base.sanitize_sql_like(tag_name.name)
|
|
q = q.where(("JSON_CONTAINTS(post_version.tags_json, JSON_OBJECT('id', :tag_id)) " +
|
|
"OR JSON_CONTAINS(prev.tags_json, JSON_OBJECT('id', :tag_id))"), tag_id:)
|
|
end
|
|
|
|
count = q.except(:select, :order, :limit, :offset).count
|
|
|
|
versions = q.order(Arel.sql('post_versions.created_at DESC, post_versions.id DESC'))
|
|
.limit(limit)
|
|
.offset(offset)
|
|
|
|
render json: { versions: serialise_versions(versions), count: }
|
|
end
|
|
|
|
private
|
|
|
|
def tag_literal tag
|
|
sections = tag.fetch('sections', []).map do |sec|
|
|
begin_ms = sec.fetch('begin_ms')
|
|
end_ms = sec['end_ms']
|
|
|
|
"[#{ Post.ms_to_time(begin_ms) }-#{ end_ms ? Post.ms_to_time(end_ms) : '' }]"
|
|
end
|
|
|
|
"#{ tag.fetch('name') }#{ sections.join }"
|
|
end
|
|
|
|
def serialise_versions rows
|
|
user_ids = rows.map(&:created_by_user_id).compact.uniq
|
|
users_by_id = User.where(id: user_ids).pluck(:id, :name).to_h
|
|
|
|
rows.map do |row|
|
|
cur_tags = split_tags(row.tags_json.map { tag_literal(_1) })
|
|
prev_tags = split_tags(row.attributes['prev_tags_json'].map { tag_literal(_1) })
|
|
|
|
{ post_id: row.post_id,
|
|
version_no: row.version_no,
|
|
event_type: row.event_type,
|
|
title: { current: row.title, prev: row.attributes['prev_title'] },
|
|
url: { current: row.url, prev: row.attributes['prev_url'] },
|
|
thumbnail: { current: nil, prev: nil },
|
|
thumbnail_base: { current: row.thumbnail_base,
|
|
prev: row.attributes['prev_thumbnail_base'] },
|
|
video_ms: { current: row.video_ms, prev: row.attributes['prev_video_ms'] },
|
|
tags: build_version_tags(cur_tags, prev_tags),
|
|
original_created_from: {
|
|
current: row.original_created_from&.iso8601,
|
|
prev: row.attributes['prev_original_created_from']&.iso8601 },
|
|
original_created_before: {
|
|
current: row.original_created_before&.iso8601,
|
|
prev: row.attributes['prev_original_created_before']&.iso8601 },
|
|
created_at: row.created_at.iso8601,
|
|
created_by_user:
|
|
if row.created_by_user_id
|
|
{ id: row.created_by_user_id,
|
|
name: users_by_id[row.created_by_user_id] }
|
|
end }
|
|
end
|
|
end
|
|
|
|
def build_version_tags(cur_tags, prev_tags)
|
|
(cur_tags | prev_tags).map do |name|
|
|
type =
|
|
if cur_tags.include?(name) && prev_tags.include?(name)
|
|
'context'
|
|
elsif cur_tags.include?(name)
|
|
'added'
|
|
else
|
|
'removed'
|
|
end
|
|
|
|
{
|
|
name:,
|
|
type:
|
|
}
|
|
end
|
|
end
|
|
|
|
def split_tags(tags)
|
|
tags.to_s.split(/\s+/).reject(&:blank?)
|
|
end
|
|
end
|