Fix #4986: Add ability to filter images in /media_assets and /uploads depending on if they have become posts

This commit is contained in:
evazion
2022-02-18 00:14:47 -06:00
parent f54fac74c8
commit 093a808a36
16 changed files with 121 additions and 72 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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; }

View File

@@ -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

View File

@@ -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

View File

@@ -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?

View File

@@ -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 %>

View File

@@ -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 %>

View File

@@ -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 %>

View File

@@ -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" %>

View File

@@ -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 %>

View File

@@ -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 %>

View File

@@ -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" %>

View File

@@ -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 %>