Fix #4986: Add ability to filter images in /media_assets and /uploads depending on if they have become posts
This commit is contained in:
@@ -4,7 +4,14 @@ class UploadMediaAssetsController < ApplicationController
|
||||
respond_to :html, :xml, :json, :js
|
||||
|
||||
def index
|
||||
@upload_media_assets = authorize UploadMediaAsset.visible(CurrentUser.user).includes(media_asset: :post, upload: :uploader).where(upload: { uploader: CurrentUser.user }).paginated_search(params, count_pages: true)
|
||||
@defaults = { upload_id: params[:upload_id] }
|
||||
@defaults[:order] = "id_asc" if params[:upload_id].present?
|
||||
@limit = params.fetch(:limit, 200).to_i.clamp(0, PostSets::Post::MAX_PER_PAGE)
|
||||
@preview_size = params[:size].presence || cookies[:post_preview_size].presence || MediaAssetGalleryComponent::DEFAULT_SIZE
|
||||
|
||||
@upload = Upload.find(params[:upload_id]) if params[:upload_id].present?
|
||||
@upload_media_assets = authorize UploadMediaAsset.visible(CurrentUser.user).includes(:post, :media_asset, upload: :uploader).paginated_search(params, limit: @limit, count_pages: true, defaults: @defaults)
|
||||
|
||||
respond_with(@upload_media_assets)
|
||||
end
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class UploadsController < ApplicationController
|
||||
@preview_size = params[:size].presence || cookies[:post_preview_size].presence || MediaAssetGalleryComponent::DEFAULT_SIZE
|
||||
|
||||
@uploads = authorize Upload.visible(CurrentUser.user).paginated_search(params, limit: @limit, count_pages: true, defaults: @defaults)
|
||||
@uploads = @uploads.includes(:uploader, media_assets: :post, upload_media_assets: { media_asset: :post }) if request.format.html?
|
||||
@uploads = @uploads.includes(:uploader, :posts, upload_media_assets: :media_asset) if request.format.html?
|
||||
|
||||
respond_with(@uploads, include: { upload_media_assets: { include: :media_asset }})
|
||||
end
|
||||
@@ -50,6 +50,8 @@ class UploadsController < ApplicationController
|
||||
if request.format.html? && @upload.media_asset_count == 1 && @upload.media_assets.first&.post.present?
|
||||
flash[:notice] = "Duplicate of post ##{@upload.media_assets.first.post.id}"
|
||||
redirect_to @upload.media_assets.first.post
|
||||
elsif request.format.html? && @upload.media_asset_count > 1
|
||||
redirect_to [@upload, UploadMediaAsset]
|
||||
else
|
||||
respond_with(@upload, include: { upload_media_assets: { include: :media_asset }})
|
||||
end
|
||||
|
||||
@@ -12,6 +12,9 @@ html, body {
|
||||
|
||||
*, ::before, ::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: var(--default-border-color);
|
||||
}
|
||||
|
||||
body, h1, h2, h3, h4, h5, h6, p, ul, ol, li, blockquote, dl, dd, menu, input {
|
||||
|
||||
@@ -114,6 +114,8 @@ html {
|
||||
--link-color: var(--blue-5);
|
||||
--link-hover-color: var(--blue-3);
|
||||
|
||||
--default-border-color: var(--grey-1);
|
||||
|
||||
--error-background-color: var(--red-1);
|
||||
--success-background-color: var(--green-0);
|
||||
--target-background: var(--yellow-0);
|
||||
@@ -330,6 +332,8 @@ body[data-current-user-theme="dark"] {
|
||||
--link-color: var(--azure-4);
|
||||
--link-hover-color: var(--azure-3);
|
||||
|
||||
--default-border-color: var(--grey-7);
|
||||
|
||||
--error-background-color: var(--red-9);
|
||||
--success-background-color: var(--green-9);
|
||||
--target-background: var(--azure-8);
|
||||
|
||||
@@ -61,6 +61,11 @@ $spacer: 0.25rem; /* 4px */
|
||||
|
||||
.border, %border { border-width: 1px; }
|
||||
|
||||
.border-b { border-bottom-width: 1px; }
|
||||
.border-b-2 { border-bottom-width: 0.5 * $spacer; }
|
||||
|
||||
.border-current { border-color: currentColor; }
|
||||
|
||||
.rounded-sm, %rounded-sm { border-radius: 0.5 * $spacer; }
|
||||
.rounded, %rounded { border-radius: 1 * $spacer; }
|
||||
.rounded-lg, %rounded-lg { border-radius: 2 * $spacer; }
|
||||
@@ -91,6 +96,8 @@ $spacer: 0.25rem; /* 4px */
|
||||
.mb-4 { margin-bottom: 4 * $spacer; }
|
||||
.mb-8 { margin-bottom: 8 * $spacer; }
|
||||
|
||||
.-mb-px { margin-bottom: -1px; }
|
||||
|
||||
.ml-4 { margin-left: 4 * $spacer; }
|
||||
|
||||
.p-0 { padding: 0; }
|
||||
@@ -112,6 +119,8 @@ $spacer: 0.25rem; /* 4px */
|
||||
.pt-4 { padding-top: 4 * $spacer; }
|
||||
.pt-8 { padding-top: 8 * $spacer; }
|
||||
|
||||
.pb-2 { padding-bottom: 2 * $spacer; }
|
||||
|
||||
.pr-2 { padding-right: 2 * $spacer; }
|
||||
.pr-4 { padding-right: 4 * $spacer; }
|
||||
|
||||
@@ -171,6 +180,7 @@ $spacer: 0.25rem; /* 4px */
|
||||
.flex-initial { flex: 0 1 auto; }
|
||||
.flex-grow-1 { flex-grow: 1; }
|
||||
.flex-col { flex-direction: column; }
|
||||
.flex-wrap { flex-wrap: wrap; }
|
||||
|
||||
.items-start { align-items: flex-start; }
|
||||
.items-center { align-items: center; }
|
||||
|
||||
@@ -188,6 +188,12 @@ class MediaAsset < ApplicationRecord
|
||||
q = q.joins(:media_metadata).merge(MediaMetadata.search(metadata: params[:metadata]))
|
||||
end
|
||||
|
||||
if params[:is_posted].to_s.truthy?
|
||||
q = q.where.associated(:post)
|
||||
elsif params[:is_posted].to_s.falsy?
|
||||
q = q.where.missing(:post)
|
||||
end
|
||||
|
||||
q.apply_default_order(params)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Upload < ApplicationRecord
|
||||
extend Memoist
|
||||
class Error < StandardError; end
|
||||
|
||||
attr_accessor :file
|
||||
@@ -8,6 +9,7 @@ class Upload < ApplicationRecord
|
||||
belongs_to :uploader, class_name: "User"
|
||||
has_many :upload_media_assets, dependent: :destroy
|
||||
has_many :media_assets, through: :upload_media_assets
|
||||
has_many :posts, through: :media_assets
|
||||
|
||||
normalize :source, :normalize_source
|
||||
|
||||
@@ -72,7 +74,14 @@ class Upload < ApplicationRecord
|
||||
end
|
||||
|
||||
def self.search(params)
|
||||
q = search_attributes(params, :id, :created_at, :updated_at, :source, :referer_url, :status, :media_asset_count, :uploader, :upload_media_assets, :media_assets)
|
||||
q = search_attributes(params, :id, :created_at, :updated_at, :source, :referer_url, :status, :media_asset_count, :uploader, :upload_media_assets, :media_assets, :posts)
|
||||
|
||||
if params[:is_posted].to_s.truthy?
|
||||
q = q.where.not(id: Upload.where.missing(:posts))
|
||||
elsif params[:is_posted].to_s.falsy?
|
||||
q = q.where(id: Upload.where.missing(:posts))
|
||||
end
|
||||
|
||||
q.apply_default_order(params)
|
||||
end
|
||||
|
||||
@@ -96,9 +105,8 @@ class Upload < ApplicationRecord
|
||||
|
||||
update!(upload_media_assets: [upload_media_asset], status: "completed", media_asset_count: 1)
|
||||
elsif source.present?
|
||||
strategy = Sources::Strategies.find(source, referer_url)
|
||||
page_url = strategy.page_url
|
||||
image_urls = strategy.image_urls
|
||||
page_url = source_strategy.page_url
|
||||
image_urls = source_strategy.image_urls
|
||||
|
||||
if image_urls.empty?
|
||||
raise Error, "#{source} doesn't contain any images"
|
||||
@@ -116,7 +124,14 @@ class Upload < ApplicationRecord
|
||||
update!(status: "error", error: e.message)
|
||||
end
|
||||
|
||||
def self.available_includes
|
||||
[:uploader, :upload_media_assets, :media_assets]
|
||||
def source_strategy
|
||||
return nil if source.blank?
|
||||
Sources::Strategies.find(source, referer_url)
|
||||
end
|
||||
|
||||
def self.available_includes
|
||||
[:uploader, :upload_media_assets, :media_assets, :posts]
|
||||
end
|
||||
|
||||
memoize :source_strategy
|
||||
end
|
||||
|
||||
@@ -5,6 +5,7 @@ class UploadMediaAsset < ApplicationRecord
|
||||
|
||||
belongs_to :upload
|
||||
belongs_to :media_asset, optional: true
|
||||
has_one :post, through: :media_asset
|
||||
|
||||
after_create :async_process_upload!
|
||||
after_save :update_upload_status, if: :saved_change_to_status?
|
||||
@@ -25,8 +26,22 @@ class UploadMediaAsset < ApplicationRecord
|
||||
end
|
||||
|
||||
def self.search(params)
|
||||
q = search_attributes(params, :id, :created_at, :updated_at, :status, :source_url, :page_url, :error, :upload, :media_asset)
|
||||
q.apply_default_order(params)
|
||||
q = search_attributes(params, :id, :created_at, :updated_at, :status, :source_url, :page_url, :error, :upload, :media_asset, :post)
|
||||
|
||||
if params[:is_posted].to_s.truthy?
|
||||
q = q.where.associated(:post)
|
||||
elsif params[:is_posted].to_s.falsy?
|
||||
q = q.where.missing(:post)
|
||||
end
|
||||
|
||||
case params[:order]
|
||||
when "id_desc"
|
||||
q = q.order(id: :desc)
|
||||
when "id_asc"
|
||||
q = q.order(id: :asc)
|
||||
else
|
||||
q.apply_default_order(params)
|
||||
end
|
||||
end
|
||||
|
||||
def loading?
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<div id="c-media-assets">
|
||||
<div id="a-index">
|
||||
<div class="flex mb-4">
|
||||
<h1 class="flex-grow-1">All Uploads</h1>
|
||||
<%= render PreviewSizeMenuComponent.new(current_size: @preview_size) %>
|
||||
</div>
|
||||
<h1 class="mb-2">All Uploads</h1>
|
||||
|
||||
<% if params[:search].present? %>
|
||||
<% if search_params[:metadata].present? %>
|
||||
<%= search_form_for(media_assets_path) do |f| %>
|
||||
<%= f.simple_fields_for :metadata do |meta| %>
|
||||
<% params.dig(:search, :metadata).to_h.each do |key, value| %>
|
||||
@@ -17,6 +14,14 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<div class="border-b mb-4 flex flex-wrap gap-4">
|
||||
<%= link_to "All", current_page_path(search: search_params.to_h.without("is_posted")), class: ["inline-block p-1 pb-2", (search_params[:is_posted].nil? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<%= link_to "Posted", current_page_path(search: { is_posted: true }), class: ["inline-block p-1 pb-2", (search_params[:is_posted].to_s.truthy? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<%= link_to "Unposted", current_page_path(search: { is_posted: false }), class: ["inline-block p-1 pb-2", (search_params[:is_posted].to_s.falsy? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<span class="flex-grow-1"></span>
|
||||
<%= render PreviewSizeMenuComponent.new(current_size: @preview_size) %>
|
||||
</div>
|
||||
|
||||
<% if params[:mode] == "table" %>
|
||||
<%= render "media_assets/table" %>
|
||||
<% else %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%= render(MediaAssetGalleryComponent.new(classes: ["upload-media-asset-gallery"])) do |gallery| %>
|
||||
<%= render(MediaAssetGalleryComponent.new(classes: ["upload-media-asset-gallery"], size: size)) do |gallery| %>
|
||||
<% upload_media_assets.each do |upload_media_asset| %>
|
||||
<% gallery.media_asset do %>
|
||||
<%= render "upload_media_assets/preview", upload_media_asset: upload_media_asset, size: gallery.size %>
|
||||
|
||||
@@ -10,18 +10,12 @@
|
||||
<% end %>
|
||||
|
||||
<% preview.footer do %>
|
||||
<div class="text-center text-muted text-xs h-12">
|
||||
<% if media_asset&.post.present? %>
|
||||
<div class="text-center text-xs h-8">
|
||||
<% if upload_media_asset.post.present? %>
|
||||
<div class="leading-none">
|
||||
<%= link_to "post ##{media_asset.post.id}", media_asset.post, class: "leading-none" %>
|
||||
<%= link_to "post ##{upload_media_asset.post.id}", upload_media_asset.post, class: "leading-none" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if upload_media_asset.source_url.present? %>
|
||||
<%= external_link_to upload_media_asset.source_url, Addressable::URI.parse(upload_media_asset.source_url).domain %>
|
||||
<% else %>
|
||||
<em>No source</em>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
<div id="c-upload-media-assets">
|
||||
<div id="a-index">
|
||||
<div class="flex items-center mb-2">
|
||||
<h1 class="flex-1">My Uploads</h1>
|
||||
<h1>Upload</h1>
|
||||
|
||||
<span>
|
||||
<strong>Gallery</strong> |
|
||||
<%= link_to "Table", user_uploads_path(CurrentUser.user.id.to_i, mode: "table") %>
|
||||
</span>
|
||||
<% if policy(@upload).show? && @upload.source_strategy.present? %>
|
||||
<%= render_source_data(@upload.source_strategy) %>
|
||||
<% end %>
|
||||
|
||||
<div class="border-b mb-4 flex flex-wrap gap-4">
|
||||
<%= link_to "All", current_page_path(search: search_params.to_h.without("is_posted")), class: ["inline-block p-1 pb-2", (search_params[:is_posted].nil? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<%= link_to "Posted", current_page_path(search: { is_posted: true }), class: ["inline-block p-1 pb-2", (search_params[:is_posted].to_s.truthy? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<%= link_to "Unposted", current_page_path(search: { is_posted: false }), class: ["inline-block p-1 pb-2", (search_params[:is_posted].to_s.falsy? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<span class="flex-1"></span>
|
||||
<%= render PreviewSizeMenuComponent.new(current_size: @preview_size) %>
|
||||
</div>
|
||||
|
||||
<%= render "upload_media_assets/gallery", upload_media_assets: @upload_media_assets %>
|
||||
<%= render "upload_media_assets/gallery", upload_media_assets: @upload_media_assets, size: @preview_size %>
|
||||
|
||||
<%= numbered_paginator(@upload_media_assets) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "uploads/secondary_links" %>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<%= render(MediaAssetGalleryComponent.new(size: size, classes: ["upload-media-asset-gallery"])) do |gallery| %>
|
||||
<% upload.upload_media_assets.order(id: :asc).each do |upload_media_asset| %>
|
||||
<% gallery.media_asset do %>
|
||||
<%= render "upload_media_assets/preview", upload_media_asset: upload_media_asset, size: gallery.size %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -1,7 +1,8 @@
|
||||
<% upload_media_asset = upload.upload_media_assets.sort_by(&:id).first %>
|
||||
<% media_asset = upload_media_asset&.media_asset %>
|
||||
<% link_target = upload.media_asset_count > 1 ? [upload, UploadMediaAsset] : upload %>
|
||||
|
||||
<%= render(MediaAssetPreviewComponent.new(media_asset: media_asset, size: size, link_target: upload, save_data: CurrentUser.save_data)) do |preview| %>
|
||||
<%= render(MediaAssetPreviewComponent.new(media_asset: media_asset, size: size, link_target: link_target, save_data: CurrentUser.save_data)) do |preview| %>
|
||||
<% preview.missing_image do %>
|
||||
<% if upload.is_errored? || upload_media_asset&.failed? %>
|
||||
Upload failed
|
||||
@@ -20,20 +21,14 @@
|
||||
<% end %>
|
||||
|
||||
<% preview.footer do %>
|
||||
<div class="text-center text-muted text-xs">
|
||||
<div class="text-center text-muted text-xs h-4">
|
||||
<div class="leading-none">
|
||||
<% if upload.media_asset_count == 1 && media_asset&.post.present? %>
|
||||
<%= link_to "post ##{media_asset.post.id}", media_asset.post, class: "leading-none" %>
|
||||
<% else %>
|
||||
<%= link_to "upload ##{upload.id}", upload, class: "leading-none" %>
|
||||
<% if upload.media_asset_count == 1 && upload.posts.first&.present? %>
|
||||
<%= link_to "post ##{upload.posts.first.id}", upload.posts.first, class: "leading-none" %>
|
||||
<% elsif upload.media_asset_count > 1 && upload.posts.length > 0 %>
|
||||
<%= link_to "#{upload.posts.length}/#{upload.media_asset_count} posted", posts_path(tags: "id:#{upload.posts.map(&:id).join(",")}"), class: "leading-none" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if upload.source.present? %>
|
||||
<%= external_link_to upload.source, Addressable::URI.parse(upload.source).domain %>
|
||||
<% else %>
|
||||
<em>No source</em>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
<div id="c-uploads">
|
||||
<div id="a-index">
|
||||
<div class="flex items-center mb-4">
|
||||
<h1 class="flex-1">My Uploads</h1>
|
||||
<h1 class="mb-2">My Uploads</h1>
|
||||
|
||||
<span>
|
||||
<%= render PreviewSizeMenuComponent.new(current_size: @preview_size) %>
|
||||
<div class="border-b mb-4 flex flex-wrap gap-4">
|
||||
<%= link_to "All", current_page_path(search: search_params.to_h.without("is_posted")), class: ["inline-block p-1 pb-2", (search_params[:is_posted].nil? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<%= link_to "Posted", current_page_path(search: { is_posted: true }), class: ["inline-block p-1 pb-2", (search_params[:is_posted].to_s.truthy? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
<%= link_to "Unposted", current_page_path(search: { is_posted: false }), class: ["inline-block p-1 pb-2", (search_params[:is_posted].to_s.falsy? ? "border-current border-b-2 -mb-px" : "inactive-link")] %>
|
||||
|
||||
<% if @mode == "table" %>
|
||||
<%= link_to grid_icon, current_page_path(mode: nil), title: "Gallery", class: "inactive-link" %>
|
||||
<% else %>
|
||||
<%= link_to list_icon, current_page_path(mode: "table"), title: "Table", class: "inactive-link" %>
|
||||
<% end %>
|
||||
</span>
|
||||
<span class="flex-1"></span>
|
||||
|
||||
<%= render PreviewSizeMenuComponent.new(current_size: @preview_size) %>
|
||||
<% if @mode == "table" %>
|
||||
<%= link_to grid_icon, current_page_path(mode: nil), title: "Gallery", class: "inline-block p-1 pb-2 rounded inactive-link" %>
|
||||
<% else %>
|
||||
<%= link_to list_icon, current_page_path(mode: "table"), title: "Table", class: "inline-block p-1 pb-2 rounded inactive-link" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @mode == "gallery" %>
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<div id="c-uploads">
|
||||
<div id="a-show">
|
||||
<div class="flex mb-4">
|
||||
<h1 class="flex-grow-1">Upload</h1>
|
||||
|
||||
<% if @upload.media_asset_count > 1 %>
|
||||
<%= render PreviewSizeMenuComponent.new(current_size: @preview_size) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<h1 class="mb-4">Upload</h1>
|
||||
|
||||
<% if @upload.is_errored? %>
|
||||
<p>Error: <%= @upload.error %>.</p>
|
||||
@@ -16,10 +10,6 @@
|
||||
<% content_for(:html_header) do %>
|
||||
<meta http-equiv="refresh" content="1">
|
||||
<% end %>
|
||||
<% elsif @upload.media_asset_count > 1 %>
|
||||
<div id="p-multiple-asset-upload">
|
||||
<%= render "multiple_asset_upload", upload: @upload, size: @preview_size %>
|
||||
</div>
|
||||
<% elsif @upload.media_asset_count == 1 %>
|
||||
<div id="p-single-asset-upload">
|
||||
<%= render "single_asset_upload", upload_media_asset: @upload.upload_media_assets.first %>
|
||||
|
||||
Reference in New Issue
Block a user