ai tags: add buttons for quickly adding and removing tags on the /ai_tags page.
Add "Add" and "Remove" buttons beneath thumbnails on the /ai_tags page. These let you add the tag to the post if it's correct, or remove it if it's wrong.
This commit is contained in:
@@ -12,4 +12,26 @@ class AITagsController < ApplicationController
|
||||
|
||||
respond_with(@ai_tags)
|
||||
end
|
||||
|
||||
# Add the tag to the post, or remove the tag from the post.
|
||||
def tag
|
||||
@ai_tag = authorize AITag.find_by!(media_asset_id: params[:media_asset_id], tag_id: params[:tag_id])
|
||||
@post = @ai_tag.post
|
||||
|
||||
if params[:mode] == "remove"
|
||||
@post.remove_tag(@ai_tag.tag.name)
|
||||
flash.now[:notice] = DText.format_text("Post ##{@post.id}: Removed [[#{@ai_tag.tag.pretty_name}]].", inline: true).html_safe
|
||||
else
|
||||
@post.add_tag(@ai_tag.tag.name)
|
||||
flash.now[:notice] = DText.format_text("Post ##{@post.id}: Added [[#{@ai_tag.tag.pretty_name}]].", inline: true).html_safe
|
||||
end
|
||||
|
||||
@post.save
|
||||
if @post.invalid?
|
||||
flash.now[:notice] = DText.format_text("Couldn't update post ##{@post.id}: #{@post.errors.full_messages.join("; ")}", inline: true).html_safe
|
||||
end
|
||||
|
||||
@preview_size = params[:size].presence || cookies[:post_preview_size].presence || PostGalleryComponent::DEFAULT_SIZE
|
||||
respond_with(@ai_tag)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -142,7 +142,9 @@ html, body[data-current-user-theme="light"] {
|
||||
--button-primary-background-color: var(--link-color);
|
||||
--button-primary-hover-background-color: var(--link-hover-color);
|
||||
--button-primary-disabled-color: var(--grey-5);
|
||||
|
||||
--button-outline-primary-color: var(--link-color);
|
||||
--button-outline-danger-color: var(--red-5);
|
||||
|
||||
--quick-search-form-background: var(--body-background-color);
|
||||
|
||||
@@ -360,7 +362,9 @@ html, body[data-current-user-theme="light"] {
|
||||
--button-primary-background-color: var(--link-color);
|
||||
--button-primary-hover-background-color: var(--link-hover-color);
|
||||
--button-primary-disabled-color: var(--grey-4);
|
||||
|
||||
--button-outline-primary-color: var(--azure-4);
|
||||
--button-outline-danger-color: var(--red-4);
|
||||
|
||||
--quick-search-form-background: var(--grey-9);
|
||||
|
||||
|
||||
@@ -84,6 +84,27 @@ a, button, input[type="submit"] {
|
||||
}
|
||||
}
|
||||
|
||||
/* An outlined red button. */
|
||||
&.button-outline-danger {
|
||||
@extend %button;
|
||||
|
||||
color: var(--button-outline-danger-color);
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--button-outline-danger-color);
|
||||
|
||||
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
|
||||
&:hover:not([disabled]) {
|
||||
color: var(--inverse-text-color);
|
||||
background-color: var(--button-outline-danger-color);
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: var(--button-primary-disabled-color);
|
||||
border: 1px solid var(--button-primary-disabled-color);
|
||||
}
|
||||
}
|
||||
|
||||
/* A small button. */
|
||||
&.button-sm {
|
||||
padding: 0.25em 1em;
|
||||
|
||||
@@ -152,6 +152,8 @@ $spacer: 0.25rem; /* 4px */
|
||||
.h-8 { height: 8 * $spacer; }
|
||||
.h-10 { height: 10 * $spacer; }
|
||||
.h-12 { height: 12 * $spacer; }
|
||||
.h-16 { height: 16 * $spacer; }
|
||||
.h-full { height: 100%; }
|
||||
.h-150px { height: 150px; }
|
||||
.h-180px { height: 180px; }
|
||||
.h-225px { height: 225px; }
|
||||
@@ -194,6 +196,10 @@ $spacer: 0.25rem; /* 4px */
|
||||
|
||||
.justify-items-center { justify-items: center; }
|
||||
.justify-center { justify-content: center; }
|
||||
.justify-between { justify-content: space-between; }
|
||||
.justify-end { justify-content: flex-end; }
|
||||
|
||||
.self-start { align-self: flex-start; }
|
||||
|
||||
.float-right { float: right; }
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ class AITag < ApplicationRecord
|
||||
order(media_asset_id: :desc, tag_id: :asc)
|
||||
end
|
||||
|
||||
def correct?
|
||||
# True if the AI tag is present on the post; false if the AI tag is not on the post, or the asset isn't a post yet.
|
||||
def post_tagged?
|
||||
if post.nil?
|
||||
false
|
||||
elsif tag.name =~ /\Arating:(.)\z/
|
||||
|
||||
@@ -4,4 +4,8 @@ class AITagPolicy < ApplicationPolicy
|
||||
def index?
|
||||
true
|
||||
end
|
||||
|
||||
def tag?
|
||||
unbanned? && record.post.present? && policy(record.post).update?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
<%= render(MediaAssetPreviewComponent.new(media_asset: media_asset, size: size, link_target: media_asset.post || media_asset, html: { **data_attributes_for(media_asset) })) do |preview| %>
|
||||
<%= render(MediaAssetPreviewComponent.new(media_asset: media_asset, size: size, link_target: media_asset.post || media_asset, classes: "flex flex-col items-center w-full h-full border rounded pb-2", html: { "data-tag-id": ai_tag.tag_id, **data_attributes_for(media_asset) })) do |preview| %>
|
||||
<% preview.footer do %>
|
||||
<div class="text-center text-xs h-8">
|
||||
<% if media_asset.post.present? %>
|
||||
<%= link_to "post ##{media_asset.post.id}", media_asset.post %>
|
||||
<% end %>
|
||||
<div class="text-center text-xs flex flex-col px-2 h-full justify-end">
|
||||
<div class="mb-2">
|
||||
<% if media_asset.post.present? %>
|
||||
<div>
|
||||
<%= link_to "post ##{media_asset.post.id}", media_asset.post %>
|
||||
<%= link_to "»", ai_tags_path(search: search_params.merge(media_asset_id: ai_tag.media_asset_id)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div>
|
||||
<%= link_to ai_tag.tag.pretty_name, ai_tags_path(search: { tag_name: ai_tag.tag.name, **params[:search].except(:tag_name) }), class: "tag-type-#{ai_tag.tag.category}", "data-tag-name": ai_tag.tag.name %>
|
||||
<%= link_to "#{ai_tag.score}%", ai_tags_path(search: { tag_name: ai_tag.tag.name, score: ">=#{ai_tag.score}", **params[:search].except(:tag_name, :score) }), class: "tag-type-#{ai_tag.tag.category}", "data-tag-name": ai_tag.tag.name %>
|
||||
<div class="leading-none">
|
||||
<%= link_to ai_tag.tag.pretty_name, ai_tags_path(search: search_params.merge(tag_name: ai_tag.tag.name)), class: "tag-type-#{ai_tag.tag.category}", "data-tag-name": ai_tag.tag.name %>
|
||||
<%= link_to "#{ai_tag.score}%", ai_tags_path(search: search_params.merge(tag_name: ai_tag.tag.name, score: ">=#{ai_tag.score}")), class: "tag-type-#{ai_tag.tag.category}", "data-tag-name": ai_tag.tag.name %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if ai_tag.post.nil? %>
|
||||
<%= button_to "Add", nil, class: "button-primary button-sm", disabled: true %>
|
||||
<% elsif ai_tag.post_tagged? %>
|
||||
<%= button_to "Remove", tag_ai_tag_path(media_asset_id: ai_tag.media_asset, tag_id: ai_tag.tag), remote: true, method: :put, params: { mode: "remove" }, class: "button-outline-danger button-sm" %>
|
||||
<% else %>
|
||||
<%= button_to "Add", tag_ai_tag_path(media_asset_id: ai_tag.media_asset, tag_id: ai_tag.tag), remote: true, method: :put, params: { mode: "add" }, class: "button-primary button-sm" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<%= ai_tag.score %>%
|
||||
<% end %>
|
||||
|
||||
<% t.column "Present?" do |ai_tag| %>
|
||||
<%= "Yes" if ai_tag.correct? %>
|
||||
<% t.column "Tagged?" do |ai_tag| %>
|
||||
<%= "Yes" if ai_tag.post_tagged? %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
7
app/views/ai_tags/tag.js.erb
Normal file
7
app/views/ai_tags/tag.js.erb
Normal file
@@ -0,0 +1,7 @@
|
||||
$(function() {
|
||||
let $el = $(".media-asset-preview[data-id=<%= @ai_tag.media_asset_id %>][data-tag-id=<%= @ai_tag.tag_id %>]").get(0);
|
||||
let html = "<%= j render("ai_tags/preview", ai_tag: @ai_tag, media_asset: @ai_tag.media_asset, size: @preview_size) %>";
|
||||
morphdom($el, html);
|
||||
|
||||
Danbooru.Utility.notice("<%= j flash[:notice] %>");
|
||||
});
|
||||
@@ -158,7 +158,10 @@ Rails.application.routes.draw do
|
||||
end
|
||||
resources :media_assets, only: [:index, :show]
|
||||
resources :media_metadata, only: [:index]
|
||||
|
||||
resources :ai_tags, only: [:index]
|
||||
put "/ai_tags/:media_asset_id/:tag_id/tag", to: "ai_tags#tag", as: "tag_ai_tag"
|
||||
|
||||
resources :mod_actions
|
||||
resources :moderation_reports, only: [:new, :create, :index, :show, :update]
|
||||
resources :modqueue, only: [:index]
|
||||
|
||||
Reference in New Issue
Block a user