tag table

This commit is contained in:
byte[] 2019-11-29 13:26:44 -05:00
parent 964efa871c
commit bbad33a70c
10 changed files with 816 additions and 230 deletions

View file

@ -271,229 +271,643 @@
"pinkie pie" "pinkie pie"
] ]
}, },
"Season 9": { "Season 9": [
"1-2": "the beginning of the end", {
"3": "uprooted", "1-2": "the beginning of the end"
"4": "twilight's seven", },
"5": "the point of no return", {
"6": "common ground", "3": "uprooted"
"7": "she's all yak", },
"8": "frenemies (episode)", {
"9": "sweet and smoky", "4": "twilight's seven"
"10": "going to seed", },
"11": "student counsel", {
"12": "the last crusade (episode)", "5": "the point of no return"
"13": "between dark and dawn", },
"14": "that's a laugh", {
"15": "2 4 6 greaaat", "6": "common ground"
"16": "a trivial pursuit", },
"17": "the summer sun setback", {
"18": "she talks to angel", "7": "she's all yak"
"19": "dragon dropped", },
"20": "a horse shoe-in", {
"21": "daring doubt", "8": "frenemies (episode)"
"22": "growing up is hard to do", },
"23": "the big mac question", {
"24-25": "the ending of the end", "9": "sweet and smoky"
"26": "the last problem" },
}, {
"8": { "10": "going to seed"
"1-2": "school daze", },
"3": "the maud couple", {
"4": "fake it 'til you make it", "11": "student counsel"
"5": "grannies gone wild", },
"6": "surf and/or turf", {
"7": "horse play", "12": "the last crusade (episode)"
"8": "the parent map", },
"9": "non-compete clause", {
"10": "the break up breakdown", "13": "between dark and dawn"
"11": "molt down", },
"12": "marks for effort", {
"13": "the mean 6", "14": "that's a laugh"
"14": "a matter of principals", },
"15": "the hearth's warming club", {
"16": "friendship university", "15": "2 4 6 greaaat"
"17": "the end in friend", },
"18": "yakity-sax", {
"19": "on the road to friendship", "16": "a trivial pursuit"
"20": "the washouts (episode)", },
"21": "a rockhoof and a hard place", {
"22": "what lies beneath", "17": "the summer sun setback"
"23": "sounds of silence", },
"24": "father knows beast", {
"25-26": "school raze", "18": "she talks to angel"
"Special": "best gift ever" },
}, {
"7": { "19": "dragon dropped"
"1": "celestial advice", },
"2": "all bottled up", {
"3": "a flurry of emotions", "20": "a horse shoe-in"
"4": "rock solid friendship", },
"5": "fluttershy leans in", {
"6": "forever filly", "21": "daring doubt"
"7": "parental glideance", },
"8": "hard to say anything", {
"9": "honest apple", "22": "growing up is hard to do"
"10": "a royal problem", },
"11": "not asking for trouble", {
"12": "discordant harmony", "23": "the big mac question"
"13": "the perfect pear", },
"14": "fame and misfortune", {
"15": "triple threat", "24-25": "the ending of the end"
"16": "campfire tales", },
"17": "to change a changeling", {
"18": "daring done?", "26": "the last problem"
"19": "it isn't the mane thing about you", }
"20": "a health of information", ],
"21": "marks and recreation", "8": [
"22": "once upon a zeppelin", {
"23": "secrets and pies", "1-2": "school daze"
"24": "uncommon bond", },
"25-26": "shadow play" {
}, "3": "the maud couple"
"6": { },
"1-2": "the crystalling", {
"3": "the gift of the maud pie", "4": "fake it 'til you make it"
"4": "on your marks", },
"5": "gauntlet of fire", {
"6": "no second prances", "5": "grannies gone wild"
"7": "newbie dash", },
"8": "a hearth's warming tail", {
"9": "the saddle row review", "6": "surf and/or turf"
"10": "applejack's \"day\" off", },
"11": "flutter brutter", {
"12": "spice up your life", "7": "horse play"
"13": "stranger than fan fiction", },
"14": "the cart before the ponies", {
"15": "28 pranks later", "8": "the parent map"
"16": "the times they are a changeling", },
"17": "dungeons and discords", {
"18": "buckball season", "9": "non-compete clause"
"19": "the fault in our cutie marks", },
"20": "viva las pegasus", {
"21": "every little thing she does", "10": "the break up breakdown"
"22": "ppov", },
"23": "where the apple lies", {
"24": "top bolt", "11": "molt down"
"25-26": "to where and back again" },
}, {
"5": { "12": "marks for effort"
"1-2": "the cutie map", },
"3": "castle sweet castle", {
"4": "bloom and gloom", "13": "the mean 6"
"5": "tanks for the memories", },
"6": "appleoosa's most wanted", {
"7": "make new friends but keep discord", "14": "a matter of principals"
"8": "the lost treasure of griffonstone", },
"9": "slice of life (episode)", {
"10": "princess spike", "15": "the hearth's warming club"
"11": "party pooped", },
"12": "amending fences", {
"13": "do princesses dream of magic sheep", "16": "friendship university"
"14": "canterlot boutique", },
"15": "rarity investigates", {
"16": "made in manehattan", "17": "the end in friend"
"17": "brotherhooves social", },
"18": "crusaders of the lost mark", {
"19": "the one where pinkie pie knows", "18": "yakity-sax"
"20": "hearthbreakers", },
"21": "scare master", {
"22": "what about discord?", "19": "on the road to friendship"
"23": "the hooffields and mccolts", },
"24": "the mane attraction", {
"25-26": "the cutie remark" "20": "the washouts (episode)"
}, },
"4": { {
"1-2": "princess twilight sparkle (episode)", "21": "a rockhoof and a hard place"
"3": "castle mane-ia", },
"4": "daring don't", {
"5": "flight to the finish", "22": "what lies beneath"
"6": "power ponies", },
"7": "bats!", {
"8": "rarity takes manehattan", "23": "sounds of silence"
"9": "pinkie apple pie", },
"10": "rainbow falls", {
"11": "three's a crowd", "24": "father knows beast"
"12": "pinkie pride", },
"13": "simple ways", {
"14": "filli vanilli", "25-26": "school raze"
"15": "twilight time", },
"16": "it ain't easy being breezies", {
"17": "somepony to watch over me", "Special": "best gift ever"
"18": "maud pie (episode)", }
"19": "for whom the sweetie belle toils", ],
"20": "leap of faith", "7": [
"21": "testing testing 1-2-3", {
"22": "trade ya", "1": "celestial advice"
"23": "inspiration manifestation", },
"24": "equestria games", {
"25-26": "twilight's kingdom" "2": "all bottled up"
}, },
"3": { {
"1-2": "the crystal empire", "3": "a flurry of emotions"
"3": "too many pinkie pies", },
"4": "one bad apple", {
"5": "magic duel", "4": "rock solid friendship"
"6": "sleepless in ponyville", },
"7": "wonderbolts academy", {
"8": "just for sidekicks", "5": "fluttershy leans in"
"9": "apple family reunion", },
"10": "spike at your service", {
"11": "keep calm and flutter on", "6": "forever filly"
"12": "games ponies play", },
"13": "magical mystery cure" {
}, "7": "parental glideance"
"2": { },
"1-2": "the return of harmony", {
"3": "lesson zero", "8": "hard to say anything"
"4": "luna eclipsed", },
"5": "sisterhooves social", {
"6": "the cutie pox", "9": "honest apple"
"7": "may the best pet win", },
"8": "the mysterious mare do well", {
"9": "sweet and elite", "10": "a royal problem"
"10": "secret of my excess", },
"11": "family appreciation day", {
"12": "baby cakes", "11": "not asking for trouble"
"13": "hearth's warming eve (episode)", },
"14": "the last roundup", {
"15": "the super speedy cider squeezy 6000", "12": "discordant harmony"
"16": "read it and weep", },
"17": "hearts and hooves day (episode)", {
"18": "a friend in deed", "13": "the perfect pear"
"19": "putting your hoof down", },
"20": "it's about time", {
"21": "dragon quest", "14": "fame and misfortune"
"22": "hurricane fluttershy", },
"23": "ponyville confidential", {
"24": "mmmystery on the friendship express", "15": "triple threat"
"25-26": "a canterlot wedding" },
}, {
"1": { "16": "campfire tales"
"1-2": "friendship is magic", },
"3": "the ticket master", {
"4": "applebuck season", "17": "to change a changeling"
"5": "griffon the brush off", },
"6": "boast busters", {
"7": "dragonshy", "18": "daring done?"
"8": "look before you sleep", },
"9": "bridle gossip", {
"10": "swarm of the century", "19": "it isn't the mane thing about you"
"11": "winter wrap up", },
"12": "call of the cutie", {
"13": "fall weather friends", "20": "a health of information"
"14": "suited for success", },
"15": "feeling pinkie keen", {
"16": "sonic rainboom (episode)", "21": "marks and recreation"
"17": "stare master", },
"18": "the show stoppers", {
"19": "a dog and pony show", "22": "once upon a zeppelin"
"20": "green isn't your color", },
"21": "over a barrel", {
"22": "a bird in the hoof", "23": "secrets and pies"
"23": "the cutie mark chronicles", },
"24": "owl's well that ends well", {
"25": "party of one", "24": "uncommon bond"
"26": "the best night ever" },
} {
} "25-26": "shadow play"
}
],
"6": [
{
"1-2": "the crystalling"
},
{
"3": "the gift of the maud pie"
},
{
"4": "on your marks"
},
{
"5": "gauntlet of fire"
},
{
"6": "no second prances"
},
{
"7": "newbie dash"
},
{
"8": "a hearth's warming tail"
},
{
"9": "the saddle row review"
},
{
"10": "applejack's \"day\" off"
},
{
"11": "flutter brutter"
},
{
"12": "spice up your life"
},
{
"13": "stranger than fan fiction"
},
{
"14": "the cart before the ponies"
},
{
"15": "28 pranks later"
},
{
"16": "the times they are a changeling"
},
{
"17": "dungeons and discords"
},
{
"18": "buckball season"
},
{
"19": "the fault in our cutie marks"
},
{
"20": "viva las pegasus"
},
{
"21": "every little thing she does"
},
{
"22": "ppov"
},
{
"23": "where the apple lies"
},
{
"24": "top bolt"
},
{
"25-26": "to where and back again"
}
],
"5": [
{
"1-2": "the cutie map"
},
{
"3": "castle sweet castle"
},
{
"4": "bloom and gloom"
},
{
"5": "tanks for the memories"
},
{
"6": "appleoosa's most wanted"
},
{
"7": "make new friends but keep discord"
},
{
"8": "the lost treasure of griffonstone"
},
{
"9": "slice of life (episode)"
},
{
"10": "princess spike"
},
{
"11": "party pooped"
},
{
"12": "amending fences"
},
{
"13": "do princesses dream of magic sheep"
},
{
"14": "canterlot boutique"
},
{
"15": "rarity investigates"
},
{
"16": "made in manehattan"
},
{
"17": "brotherhooves social"
},
{
"18": "crusaders of the lost mark"
},
{
"19": "the one where pinkie pie knows"
},
{
"20": "hearthbreakers"
},
{
"21": "scare master"
},
{
"22": "what about discord?"
},
{
"23": "the hooffields and mccolts"
},
{
"24": "the mane attraction"
},
{
"25-26": "the cutie remark"
}
],
"4": [
{
"1-2": "princess twilight sparkle (episode)"
},
{
"3": "castle mane-ia"
},
{
"4": "daring don't"
},
{
"5": "flight to the finish"
},
{
"6": "power ponies"
},
{
"7": "bats!"
},
{
"8": "rarity takes manehattan"
},
{
"9": "pinkie apple pie"
},
{
"10": "rainbow falls"
},
{
"11": "three's a crowd"
},
{
"12": "pinkie pride"
},
{
"13": "simple ways"
},
{
"14": "filli vanilli"
},
{
"15": "twilight time"
},
{
"16": "it ain't easy being breezies"
},
{
"17": "somepony to watch over me"
},
{
"18": "maud pie (episode)"
},
{
"19": "for whom the sweetie belle toils"
},
{
"20": "leap of faith"
},
{
"21": "testing testing 1-2-3"
},
{
"22": "trade ya"
},
{
"23": "inspiration manifestation"
},
{
"24": "equestria games"
},
{
"25-26": "twilight's kingdom"
}
],
"3": [
{
"1-2": "the crystal empire"
},
{
"3": "too many pinkie pies"
},
{
"4": "one bad apple"
},
{
"5": "magic duel"
},
{
"6": "sleepless in ponyville"
},
{
"7": "wonderbolts academy"
},
{
"8": "just for sidekicks"
},
{
"9": "apple family reunion"
},
{
"10": "spike at your service"
},
{
"11": "keep calm and flutter on"
},
{
"12": "games ponies play"
},
{
"13": "magical mystery cure"
}
],
"2": [
{
"1-2": "the return of harmony"
},
{
"3": "lesson zero"
},
{
"4": "luna eclipsed"
},
{
"5": "sisterhooves social"
},
{
"6": "the cutie pox"
},
{
"7": "may the best pet win"
},
{
"8": "the mysterious mare do well"
},
{
"9": "sweet and elite"
},
{
"10": "secret of my excess"
},
{
"11": "family appreciation day"
},
{
"12": "baby cakes"
},
{
"13": "hearth's warming eve (episode)"
},
{
"14": "the last roundup"
},
{
"15": "the super speedy cider squeezy 6000"
},
{
"16": "read it and weep"
},
{
"17": "hearts and hooves day (episode)"
},
{
"18": "a friend in deed"
},
{
"19": "putting your hoof down"
},
{
"20": "it's about time"
},
{
"21": "dragon quest"
},
{
"22": "hurricane fluttershy"
},
{
"23": "ponyville confidential"
},
{
"24": "mmmystery on the friendship express"
},
{
"25-26": "a canterlot wedding"
}
],
"1": [
{
"1-2": "friendship is magic"
},
{
"3": "the ticket master"
},
{
"4": "applebuck season"
},
{
"5": "griffon the brush off"
},
{
"6": "boast busters"
},
{
"7": "dragonshy"
},
{
"8": "look before you sleep"
},
{
"9": "bridle gossip"
},
{
"10": "swarm of the century"
},
{
"11": "winter wrap up"
},
{
"12": "call of the cutie"
},
{
"13": "fall weather friends"
},
{
"14": "suited for success"
},
{
"15": "feeling pinkie keen"
},
{
"16": "sonic rainboom (episode)"
},
{
"17": "stare master"
},
{
"18": "the show stoppers"
},
{
"19": "a dog and pony show"
},
{
"20": "green isn't your color"
},
{
"21": "over a barrel"
},
{
"22": "a bird in the hoof"
},
{
"23": "the cutie mark chronicles"
},
{
"24": "owl's well that ends well"
},
{
"25": "party of one"
},
{
"26": "the best night ever"
}
]
}

View file

@ -42,6 +42,9 @@
button.button.js-tag-sauce-toggle data-click-toggle=".tagsauce, .js-imageform" data-click-focus=".js-taginput-plain:not(.hidden), .js-taginput-input" button.button.js-tag-sauce-toggle data-click-toggle=".tagsauce, .js-imageform" data-click-focus=".js-taginput-plain:not(.hidden), .js-taginput-input"
' Cancel ' Cancel
.block.js-tagtable data-target='[name="image[tag_input]"]'
= PhilomenaWeb.TagView.quick_tags(@conn)
- else - else
p p
' You can't edit the tags on this image. ' You can't edit the tags on this image.

View file

@ -61,6 +61,11 @@
button.button.button--state-warning.button--separate-left.button--bold id="tagsinput-load" type="button" title="This button loads any saved tags from your browser" Load button.button.button--state-warning.button--separate-left.button--bold id="tagsinput-load" type="button" title="This button loads any saved tags from your browser" Load
button.button.button--state-danger.button--separate-left.button--bold id="tagsinput-clear" type="button" title="This button will clear the list of tags above" Clear button.button.button--state-danger.button--separate-left.button--bold id="tagsinput-clear" type="button" title="This button will clear the list of tags above" Clear
p You can mouse over tags below to view a description, and click to add. Short tag names can be used and will expand to full.
.block.js-tagtable data-target='[name="image[tag_input]"]'
= PhilomenaWeb.TagView.quick_tags(@conn)
br br
.field .field

View file

@ -35,9 +35,9 @@ h1 Search
a data-search-add="my:upvotes" data-search-show-help=" " My upvotes a data-search-add="my:upvotes" data-search-show-help=" " My upvotes
a data-search-add="my:uploads" data-search-show-help=" " My uploads a data-search-add="my:uploads" data-search-show-help=" " My uploads
a data-search-add="my:watched" data-search-show-help=" " My watched tags a data-search-add="my:watched" data-search-show-help=" " My watched tags
/.flex__right .flex__right
a href="#" data-click-toggle="#js-search-tags" Quick tags a href="#" data-click-toggle="#js-search-tags" Quick tags
a href=search_syntax_path Help a href="/search/syntax" Help
.block__content .block__content
.hidden.walloftext data-search-help="numeric" .hidden.walloftext data-search-help="numeric"
@ -93,8 +93,9 @@ h1 Search
code<> source_url:*deviantart.com* code<> source_url:*deviantart.com*
| . | .
/#js-search-tags.hidden #js-search-tags.hidden
/= render partial: 'tags/quick_tag_table', locals: { target: '.js-search-field' } .block.js-tagtable data-target=".js-search-field"
= PhilomenaWeb.TagView.quick_tags(@conn)
.field.field--inline.flex-wrap .field.field--inline.flex-wrap
= submit "Search", class: "button button--state-primary" = submit "Search", class: "button button--state-primary"

View file

@ -0,0 +1,14 @@
elixir:
tabs = Enum.with_index(@data["tabs"])
tab_modes = @data["tab_modes"]
.block__header--sub.block__header--js--tabbed
= for {name, i} <- tabs do
= link name, to: "#", class: tab_class(i), data: [click_tab: name]
= for {name, i} <- tabs do
- tab_data = @data[name]
- tab_mode = tab_modes[name]
.block__tab.quick-tag-table__tab class=tab_body_class(i) data-tab=name
= render PhilomenaWeb.TagView, "_quick_tag_table_#{tab_mode}.html", tab: name, data: tab_data, shipping: @shipping, tags: @tags, conn: @conn

View file

@ -0,0 +1,8 @@
= for {heading, tag_names} <- @data do
div
strong = heading
br
= for tag_name <- tag_names do
= tag_link @tags[tag_name], tag_name
br

View file

@ -0,0 +1,9 @@
= for slice <- Enum.chunk_every(@data, 10) do
div
= for map <- slice do
- [{header, tag_name}] = Enum.to_list(map)
= header
' .
= tag_link @tags[tag_name], tag_name
br

View file

@ -0,0 +1,5 @@
= for slice <- Enum.chunk_every(@shipping[@tab], 10) do
div
= for tag_name <- slice do
= tag_link @tags[tag_name], tag_name
br

View file

@ -0,0 +1,10 @@
= for {heading, maps} <- @data do
div
strong = heading
br
= for {name, alias_name} <- maps do
=> name
' -
= tag_link @tags[alias_name], alias_name
br

View file

@ -1,3 +1,120 @@
defmodule PhilomenaWeb.TagView do defmodule PhilomenaWeb.TagView do
use PhilomenaWeb, :view use PhilomenaWeb, :view
# this is bad practice, don't copy this.
alias Philomena.Tags.Implication
alias Philomena.Tags.Tag
alias Philomena.Repo
import Ecto.Query
def quick_tags(conn) do
case Application.get_env(:philomena, :quick_tags) do
nil ->
quick_tags =
Application.get_env(:philomena, :quick_tags_json)
|> Jason.decode!()
|> lookup_quick_tags()
|> render_quick_tags(conn)
Application.put_env(:philomena, :quick_tags, quick_tags)
quick_tags
quick_tags ->
quick_tags
end
end
def tab_class(0), do: "selected"
def tab_class(_), do: nil
def tab_body_class(0), do: nil
def tab_body_class(_), do: "hidden"
def tag_link(nil, tag_name), do: tag_name
def tag_link(tag, tag_name) do
title = title(implications(tag) ++ short_description(tag))
link tag_name, to: "#", title: title, data: [tag_name: tag_name, click_addtag: tag_name]
end
defp implications(%{implied_tags: []}), do: []
defp implications(%{implied_tags: it}) do
names =
it
|> Enum.map(& &1.name)
|> Enum.sort()
|> Enum.join(", ")
["Implies: #{names}"]
end
defp short_description(%{short_description: s}) when s in ["", nil], do: []
defp short_description(%{short_description: s}), do: [s]
defp title([]), do: nil
defp title(descriptions), do: Enum.join(descriptions, "\n")
defp lookup_quick_tags(%{"tabs" => tabs, "tab_modes" => tab_modes} = data) do
tags =
tabs
|> Enum.flat_map(&names_in_tab(tab_modes[&1], data[&1]))
|> tags_indexed_by_name()
shipping =
tabs
|> Enum.filter(&tab_modes[&1] == "shipping")
|> Map.new(fn tab ->
sd = data[tab]
{tab, implied_by_multitag(sd["implying"], sd["not_implying"])}
end)
{tags, shipping, data}
end
defp render_quick_tags({tags, shipping, data}, conn) do
render PhilomenaWeb.TagView, "_quick_tag_table.html", tags: tags, shipping: shipping, data: data, conn: conn
end
defp names_in_tab("default", data) do
Map.values(data)
|> List.flatten()
end
defp names_in_tab("season", data) do
data
|> Enum.flat_map(&Map.values/1)
end
defp names_in_tab("shorthand", data) do
data
|> Map.values()
|> Enum.flat_map(&Map.values/1)
end
defp names_in_tab(_mode, _data), do: []
defp tags_indexed_by_name(names) do
Tag
|> where([t], t.name in ^names)
|> preload(:implied_tags)
|> Repo.all()
|> Map.new(&{&1.name, &1})
end
defp implied_by_multitag(tag_names, ignore_tag_names) do
query =
from t in Tag,
left_join: i in Implication,
on: t.id == i.tag_id,
left_join: it in Tag,
on: it.id == i.implied_tag_id,
where: it.name in ^tag_names and it.name not in ^ignore_tag_names,
order_by: [desc: t.images_count],
preload: :implied_tags,
limit: 40
Repo.all(query)
end
end end