mirror of
https://github.com/indentlabs/notebook.git
synced 2025-10-26 11:19:22 +00:00
Add site-wide ArtFight2025 tag browsing page
- Created new /browse/tag/ArtFight2025 endpoint - Added browse controller for site-wide content display - Fixed tag slug case-sensitivity for reliable content retrieval - Implemented a design that highlights the ArtFight2025 tag - Show all content tags on each card for context - Prioritize character display at the top of search results 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
78b86cfaae
commit
574cfcd6ff
150
app/controllers/browse_controller.rb
Normal file
150
app/controllers/browse_controller.rb
Normal file
@ -0,0 +1,150 @@
|
||||
class BrowseController < ApplicationController
|
||||
# This controller handles browsing global content across the site
|
||||
|
||||
def tag
|
||||
@tag_slug = params[:tag_slug]
|
||||
# Debug logging
|
||||
Rails.logger.info "BrowseController#tag - Looking for content with tag slug: #{@tag_slug}"
|
||||
|
||||
# For now, only allow ArtFight2025 tag to be browsed (case insensitive)
|
||||
unless @tag_slug.downcase == 'artfight2025'
|
||||
redirect_to root_path, notice: 'This tag is not available for browsing.'
|
||||
return
|
||||
end
|
||||
|
||||
@tag = 'ArtFight2025'
|
||||
@tag_slug = 'artfight2025' # Use the correctly slugified version
|
||||
@tagged_content = []
|
||||
|
||||
# Directly check database for any pages with this tag
|
||||
tag_exists = PageTag.exists?(slug: @tag_slug)
|
||||
Rails.logger.info "Tag exists in PageTag table? #{tag_exists}"
|
||||
|
||||
if tag_exists
|
||||
sample_tag = PageTag.find_by(slug: @tag_slug)
|
||||
Rails.logger.info "Sample tag: #{sample_tag.inspect}"
|
||||
end
|
||||
|
||||
# Go through each content type and find public items with this tag
|
||||
Rails.application.config.content_types[:all].each do |content_type|
|
||||
# Try a different query approach - first find page IDs with this tag
|
||||
tag_page_ids = PageTag.where(page_type: content_type.name, slug: @tag_slug).pluck(:page_id)
|
||||
|
||||
if tag_page_ids.any?
|
||||
Rails.logger.info "Found #{tag_page_ids.count} #{content_type.name} page IDs with tag: #{tag_page_ids}"
|
||||
content_pages = content_type.where(id: tag_page_ids).where(privacy: 'public').order(:name)
|
||||
else
|
||||
Rails.logger.info "No #{content_type.name} pages found with tag"
|
||||
content_pages = content_type.none
|
||||
end
|
||||
|
||||
@tagged_content << {
|
||||
type: content_type.name,
|
||||
icon: content_type.icon,
|
||||
color: content_type.color,
|
||||
content: content_pages
|
||||
} if content_pages.any?
|
||||
end
|
||||
|
||||
# Add documents separately since they don't use the common content type structure
|
||||
document_tag_page_ids = PageTag.where(page_type: 'Document', slug: @tag_slug).pluck(:page_id)
|
||||
if document_tag_page_ids.any?
|
||||
Rails.logger.info "Found #{document_tag_page_ids.count} Document page IDs with tag: #{document_tag_page_ids}"
|
||||
documents = Document.where(id: document_tag_page_ids).where(privacy: 'public').order(:title)
|
||||
else
|
||||
Rails.logger.info "No Document pages found with tag"
|
||||
documents = Document.none
|
||||
end # Documents use 'title' instead of 'name'
|
||||
|
||||
@tagged_content << {
|
||||
type: 'Document',
|
||||
icon: 'description',
|
||||
color: 'blue',
|
||||
content: documents
|
||||
} if documents.any?
|
||||
|
||||
# Add timelines separately since they don't use the common content type structure
|
||||
timeline_tag_page_ids = PageTag.where(page_type: 'Timeline', slug: @tag_slug).pluck(:page_id)
|
||||
if timeline_tag_page_ids.any?
|
||||
Rails.logger.info "Found #{timeline_tag_page_ids.count} Timeline page IDs with tag: #{timeline_tag_page_ids}"
|
||||
timelines = Timeline.where(id: timeline_tag_page_ids).where(privacy: 'public').order(:name)
|
||||
else
|
||||
Rails.logger.info "No Timeline pages found with tag"
|
||||
timelines = Timeline.none
|
||||
end
|
||||
|
||||
@tagged_content << {
|
||||
type: 'Timeline',
|
||||
icon: 'timeline',
|
||||
color: 'blue',
|
||||
content: timelines
|
||||
} if timelines.any?
|
||||
|
||||
# Get images for content cards from all users
|
||||
content_ids_by_type = {}
|
||||
user_ids = []
|
||||
|
||||
@tagged_content.each do |content_group|
|
||||
content_group[:content].each do |content|
|
||||
content_type = content.class.name
|
||||
content_ids_by_type[content_type] ||= []
|
||||
content_ids_by_type[content_type] << content.id
|
||||
user_ids << content.user_id
|
||||
end
|
||||
end
|
||||
|
||||
# Get unique user IDs
|
||||
user_ids.uniq!
|
||||
|
||||
# Get all relevant images
|
||||
@random_image_pool_cache = {}
|
||||
if content_ids_by_type.any?
|
||||
content_ids_by_type.each do |content_type, ids|
|
||||
images = ImageUpload.where(content_type: content_type, content_id: ids)
|
||||
|
||||
images.each do |image|
|
||||
key = [image.content_type, image.content_id]
|
||||
@random_image_pool_cache[key] ||= []
|
||||
@random_image_pool_cache[key] << image
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Initialize basil commissions if there are any content items
|
||||
if content_ids_by_type.any?
|
||||
entity_types = []
|
||||
entity_ids = []
|
||||
|
||||
content_ids_by_type.each do |content_type, ids|
|
||||
entity_type = content_type.downcase.pluralize
|
||||
entity_types.concat([entity_type] * ids.length)
|
||||
entity_ids.concat(ids)
|
||||
end
|
||||
|
||||
@saved_basil_commissions = BasilCommission.where(
|
||||
entity_type: entity_types,
|
||||
entity_id: entity_ids
|
||||
).where.not(saved_at: nil)
|
||||
.group_by { |commission| [commission.entity_type, commission.entity_id] }
|
||||
end
|
||||
|
||||
# Set a default accent color for the page
|
||||
@accent_color = 'purple'
|
||||
|
||||
# Get usernames for display with content
|
||||
@users_cache = User.where(id: user_ids).index_by(&:id)
|
||||
|
||||
# Sort content types so Characters always appear first
|
||||
@tagged_content = @tagged_content.sort_by do |content_group|
|
||||
if content_group[:type] == 'Character'
|
||||
# Characters first
|
||||
"0_#{content_group[:type]}"
|
||||
else
|
||||
# Everything else alphabetically
|
||||
"1_#{content_group[:type]}"
|
||||
end
|
||||
end
|
||||
|
||||
@sidenav_expansion = 'community'
|
||||
end
|
||||
end
|
||||
@ -6,55 +6,80 @@ class PageTagService < Service
|
||||
def self.suggested_tags_for(class_name)
|
||||
case class_name
|
||||
when Building.name
|
||||
["School", "Business"]
|
||||
["School", "Business", "Residential", "Religious", "Government", "Military", "Historical", "Abandoned", "Underground", "Magical", "Headquarters", "Landmark", "WIP", "Complete", "Stub",
|
||||
"Ancient", "Modern", "Futuristic", "Secret", "Well-known", "Mysterious", "Imposing", "Central to plot", "Background detail", "Needs expansion"]
|
||||
when Character.name
|
||||
["Main character", "Side character", "Background character"]
|
||||
["Main character", "Side character", "Background character", "Villain", "Hero", "Mentor", "Love interest", "Ally", "Rival", "Family member", "Historical figure", "Child", "Elder", "WIP", "Complete", "Stub",
|
||||
"Protagonist", "Antagonist", "Supporting", "Main plot", "Subplot", "Origin story", "High priority", "Needs development", "Tragic", "Comedic"]
|
||||
when Condition.name
|
||||
["Disease", "Blessing", "Curse"]
|
||||
["Disease", "Blessing", "Curse", "Magical affliction", "Mental condition", "Physical disability", "Temporary", "Permanent", "Contagious", "Hereditary", "Supernatural", "Rare", "Common", "WIP", "Complete", "Stub",
|
||||
"Unknown", "Legendary", "Tragic", "Beneficial", "Plot device", "Background detail", "Mysterious", "Needs research", "Science based", "Mythology inspired"]
|
||||
when Country.name
|
||||
["Kingdom", "Country", "Region"]
|
||||
["Kingdom", "Country", "Region", "Empire", "Republic", "City-state", "Colony", "Island nation", "Confederation", "Disputed territory", "Fallen kingdom", "Hidden realm", "Tribal lands", "WIP", "Complete", "Stub",
|
||||
"Ancient", "Modern", "Developing", "Major power", "Minor nation", "Well-known", "Isolated", "Political entity", "Cultural focus", "Based on history"]
|
||||
when Creature.name
|
||||
["Domesticated", "Wild", "Humanoid"]
|
||||
["Domesticated", "Wild", "Humanoid", "Mythical", "Magical", "Predator", "Aquatic", "Flying", "Subterranean", "Extinct", "Intelligent", "Hybrid", "Shapeshifter", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Legendary", "Keystone species", "Background fauna", "Terrifying", "Majestic", "Cute", "Mythology inspired", "Needs illustration"]
|
||||
when Deity.name
|
||||
["Good", "Evil", "Neutral"]
|
||||
["Good", "Evil", "Neutral", "Creator", "Destroyer", "Nature deity", "War deity", "Love deity", "Death deity", "Trickster", "Ancient", "Forgotten", "Patron", "WIP", "Complete", "Stub",
|
||||
"Worshipped", "Obscure", "Legendary", "Major deity", "Minor deity", "Metaphysical", "Mythology inspired", "Central to plot", "Cultural element", "Needs expansion"]
|
||||
when Flora.name
|
||||
["Floral", "Weed", "Tree", "Bush"]
|
||||
["Floral", "Weed", "Tree", "Bush", "Magical", "Medicinal", "Poisonous", "Edible", "Rare", "Cultivated", "Aquatic", "Carnivorous", "Luminescent", "Extinct", "WIP", "Complete", "Stub",
|
||||
"Common", "Legendary", "Plot device", "Background detail", "Physical world", "Needs illustration", "Science based", "Mysterious", "Prehistoric", "Modern"]
|
||||
when Government.name
|
||||
["Republic", "Democracy", "Monarchy", "Dictatorship"]
|
||||
["Republic", "Democracy", "Monarchy", "Dictatorship", "Oligarchy", "Theocracy", "Feudal", "Tribal", "Anarchy", "Colonial", "Magocracy", "Puppet state", "Technocracy", "Confederation", "WIP", "Complete", "Stub",
|
||||
"Stable", "Unstable", "Corrupt", "Benevolent", "Social structure", "Political entity", "Based on history", "Central to plot", "Background detail", "Needs expansion"]
|
||||
when Group.name
|
||||
["Good", "Evil", "Secret"]
|
||||
["Good", "Evil", "Secret", "Military", "Religious", "Political", "Criminal", "Mercenary", "Merchant", "Nomadic", "Resistance", "Magical", "Ancient", "WIP", "Complete", "Stub",
|
||||
"Well-known", "Obscure", "Powerful", "Minor", "Main plot", "Subplot", "Social structure", "Cultural element", "Needs development", "Based on history"]
|
||||
when Item.name
|
||||
["Weapon", "Armor", "Artifact", "Relic"]
|
||||
["Weapon", "Armor", "Artifact", "Relic", "Magical", "Cursed", "Legendary", "Tool", "Jewelry", "Clothing", "Consumable", "Book", "Technology", "Ritual object", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Unique", "Plot device", "MacGuffin", "Ancient", "Modern", "Futuristic", "Needs illustration", "Mythology inspired"]
|
||||
when Job.name
|
||||
["Military", "Government", "Private sector"]
|
||||
["Military", "Government", "Private sector", "Artisan", "Merchant", "Criminal", "Religious", "Magical", "Academic", "Entertainment", "Nomadic", "Seasonal", "Hereditary", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Prestigious", "Lowly", "Social structure", "Economic system", "Cultural element", "Based on history", "Background detail", "Needs expansion"]
|
||||
when Landmark.name
|
||||
["Cave", "Mountain", "Temple", "Ruins"]
|
||||
["Cave", "Mountain", "Temple", "Ruins", "Waterfall", "Forest", "Monument", "Battlefield", "Sacred site", "Natural wonder", "Magical location", "Bridge", "Graveyard", "Portal", "WIP", "Complete", "Stub",
|
||||
"Famous", "Hidden", "Ancient", "Modern", "Physical world", "Plot location", "Mysterious", "Majestic", "Needs illustration", "Based on geography"]
|
||||
when Language.name
|
||||
["Modern", "Ancient"]
|
||||
["Modern", "Ancient", "Dead", "Sacred", "Trade", "Secret", "Regional", "Magical", "Written only", "Spoken only", "Pidgin", "Artificial", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Scholarly", "Cultural element", "Based on linguistics", "Needs development", "Conlang", "Background detail", "Low priority", "Needs examples"]
|
||||
when Location.name
|
||||
["Town", "City", "River", "Mountains", "Desert"]
|
||||
["Town", "City", "River", "Mountains", "Desert", "Forest", "Ocean", "Lake", "Island", "Swamp", "Tundra", "Valley", "Plateau", "Jungle", "Wasteland", "WIP", "Complete", "Stub",
|
||||
"Inhabited", "Uninhabited", "Explored", "Unexplored", "Dangerous", "Safe", "Physical world", "Plot location", "Needs map", "Based on geography"]
|
||||
when Magic.name
|
||||
["Spell", "Ability", "Superpower"]
|
||||
["Spell", "Ability", "Superpower", "Ritual", "Enchantment", "Elemental", "Necromancy", "Divination", "Illusion", "Healing", "Summoning", "Forbidden", "Innate", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Legendary", "Powerful", "Weak", "Metaphysical", "System-defining", "Plot device", "High priority", "Needs rules"]
|
||||
when Planet.name
|
||||
["Habitable", "Inhabitable"]
|
||||
["Habitable", "Inhabitable", "Earth-like", "Gas giant", "Desert world", "Ocean world", "Ice world", "Jungle world", "Artificial", "Moon", "Dying", "Ancient", "WIP", "Complete", "Stub",
|
||||
"Explored", "Unexplored", "Homeworld", "Colony", "Physical world", "Science based", "Needs map", "Central setting", "Background detail", "Needs development"]
|
||||
when Race.name
|
||||
["Race", "Species", "Humanoid"]
|
||||
["Race", "Species", "Humanoid", "Ancient", "Magical", "Hybrid", "Extinct", "Subterranean", "Aquatic", "Aerial", "Nomadic", "Tribal", "Technological", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Dominant", "Minority", "Cultural focus", "Social structure", "Needs illustration", "Main characters", "Background people", "High priority"]
|
||||
when Religion.name
|
||||
["Modern", "Ancient", "Monotheistic", "Polytheistic"]
|
||||
["Modern", "Ancient", "Monotheistic", "Polytheistic", "State religion", "Cult", "Animistic", "Shamanic", "Ancestor worship", "Nature worship", "Mystical", "Heretical", "Secretive", "Widespread", "WIP", "Complete", "Stub",
|
||||
"Dominant", "Minority", "Cultural element", "Metaphysical", "Based on history", "Mythology inspired", "Plot relevant", "Background detail", "Needs expansion"]
|
||||
when Scene.name
|
||||
["Atmospheric", "Exposition", "Transition"]
|
||||
["Atmospheric", "Exposition", "Transition", "Action", "Dialogue", "Flashback", "Dream sequence", "Climactic", "Introduction", "Resolution", "Worldbuilding", "Character development", "Plot twist", "WIP", "Complete", "Stub",
|
||||
"Main plot", "Subplot", "High tension", "Low tension", "Mysterious", "Romantic", "Tragic", "Comedic", "High priority", "Needs revision"]
|
||||
when Technology.name
|
||||
["Military", "Consumer", "Theoretical"]
|
||||
["Military", "Consumer", "Theoretical", "Ancient", "Futuristic", "Magical", "Medical", "Transportation", "Communication", "Energy", "Forbidden", "Experimental", "Everyday", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Revolutionary", "Obsolete", "Science based", "Plot device", "Physical world", "Needs illustration", "Background detail", "High priority"]
|
||||
when Town.name
|
||||
["Village", "Town", "City", "Metropolis"]
|
||||
["Village", "Town", "City", "Metropolis", "Hamlet", "Outpost", "Port", "Mining settlement", "Trading hub", "Fortress", "Religious center", "Abandoned", "Hidden", "Capital", "WIP", "Complete", "Stub",
|
||||
"Prosperous", "Poor", "Ancient", "Modern", "Plot location", "Character hometown", "Cultural focus", "Needs map", "Based on history", "Background detail"]
|
||||
when Tradition.name
|
||||
["Holiday", "Practice"]
|
||||
["Holiday", "Practice", "Festival", "Ceremony", "Ritual", "Coming of age", "Seasonal", "Religious", "Cultural", "Family", "Military", "Ancient", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Widespread", "Regional", "Cultural element", "Social structure", "Based on history", "Mythology inspired", "Background detail", "Needs expansion"]
|
||||
when Universe.name
|
||||
["Favorite"]
|
||||
["Favorite", "Science fiction", "Fantasy", "Historical", "Post-apocalyptic", "Dystopian", "Utopian", "Alternate history", "Urban fantasy", "Steampunk", "Magical realism", "WIP", "Complete", "Stub",
|
||||
"Main project", "Side project", "Collaborative", "Personal", "High priority", "Low priority", "Needs worldbuilding", "Core concept", "Experimental", "Based on literature"]
|
||||
when Vehicle.name
|
||||
["Automobile", "Train", "Plane", "Spaceship"]
|
||||
["Automobile", "Train", "Plane", "Spaceship", "Ship", "Submarine", "Magical", "Animal-drawn", "Military", "Civilian", "Ancient", "Futuristic", "Unique", "Experimental", "WIP", "Complete", "Stub",
|
||||
"Common", "Rare", "Legendary", "Personal", "Public", "Plot device", "Needs illustration", "Science based", "Background detail", "Technology focus"]
|
||||
when Document.name
|
||||
['Idea', 'Draft', 'In Progress', 'Done']
|
||||
['Idea', 'Draft', 'In Progress', 'Done', 'Historical', 'Religious', 'Legal', 'Personal', 'Scientific', 'Map', 'Journal', 'Letter', 'Prophecy', 'Secret', 'WIP', 'Complete', 'Stub',
|
||||
'Plot relevant', 'Background lore', 'Ancient', 'Modern', 'Cultural element', 'Needs revision', 'High priority', 'Open for collaboration', 'Based on literature', 'Worldbuilding']
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
200
app/views/browse/tag.html.erb
Normal file
200
app/views/browse/tag.html.erb
Normal file
@ -0,0 +1,200 @@
|
||||
<div class="row" style="margin-bottom: 0;">
|
||||
<div class="col s12">
|
||||
<%
|
||||
# Generate a consistent pattern for the background based on tag name
|
||||
pattern_seed = 5 # Fixed for ArtFight tag
|
||||
pattern_url = asset_path("card-headers/patterns/pattern#{pattern_seed}.png")
|
||||
|
||||
# Calculate total items for the stats display
|
||||
total_items = @tagged_content.sum { |group| group[:content].count }
|
||||
content_types_count = @tagged_content.size
|
||||
creators_count = @tagged_content.flat_map { |group| group[:content].map(&:user_id) }.uniq.count
|
||||
%>
|
||||
|
||||
<div class="card z-depth-1" style="border-radius: 4px; overflow: hidden;">
|
||||
<!-- Header with hero image background -->
|
||||
<div class="<%= @accent_color %>" style="position: relative; background: url('<%= pattern_url %>') center center; background-size: cover; height: 180px;">
|
||||
<!-- Dark overlay for better text contrast -->
|
||||
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0,0,0,0.3);"></div>
|
||||
|
||||
<!-- Tag floating badge -->
|
||||
<div style="position: absolute; bottom: -24px; left: 24px; z-index: 2;">
|
||||
<div style="display: inline-block; background-color: white; padding: 14px 22px; border-radius: 4px; box-shadow: 0 2px 10px 0 rgba(0,0,0,0.2);">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<i class="material-icons <%= @accent_color %>-text" style="font-size: 28px; margin-right: 12px;"><%= PageTag.icon %></i>
|
||||
<span style="font-size: 28px; font-weight: 500;" class="<%= @accent_color %>-text"><%= @tag %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Art Fight 2025 header info -->
|
||||
<div style="position: absolute; top: 20px; left: 24px; z-index: 1;">
|
||||
<div>
|
||||
<span style="font-size: 24px; font-weight: 500; text-shadow: 0 1px 3px rgba(0,0,0,0.3); line-height: 1.2; display: block; color: white;">
|
||||
Art Fight 2025
|
||||
</span>
|
||||
<span style="font-size: 16px; text-shadow: 0 1px 2px rgba(0,0,0,0.3); display: block; color: white; margin-top: 4px;">
|
||||
Discover all public content tagged with ArtFight2025 across Notebook.ai
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats bar - clean and elegant -->
|
||||
<div class="<%= @accent_color %> lighten-5" style="padding: 30px 24px 16px 24px;">
|
||||
<div style="display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;">
|
||||
<!-- Left section (for title) -->
|
||||
<div style="margin-bottom: 10px;">
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Right section (for stats) -->
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 10px;">
|
||||
<div class="chip z-depth-0 <%= @accent_color %> lighten-3" style="border: none; margin: 0;">
|
||||
<i class="material-icons left"><%= PageTag.icon %></i>
|
||||
<%= pluralize(total_items, 'item') %>
|
||||
</div>
|
||||
|
||||
<div class="chip z-depth-0 <%= @accent_color %> lighten-3" style="border: none; margin: 0;">
|
||||
<i class="material-icons left">category</i>
|
||||
<%= pluralize(content_types_count, 'category') %>
|
||||
</div>
|
||||
|
||||
<div class="chip z-depth-0 <%= @accent_color %> lighten-3" style="border: none; margin: 0;">
|
||||
<i class="material-icons left">people</i>
|
||||
<%= pluralize(creators_count, 'creator') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12">
|
||||
<% if @tagged_content.empty? %>
|
||||
<div class="center-align" style="margin-top: 80px">
|
||||
<h5 class="grey-text">No public content with this tag</h5>
|
||||
<p class="grey-text">
|
||||
No one has created any public content with the "<%= @tag %>" tag yet.
|
||||
</p>
|
||||
</div>
|
||||
<% else %>
|
||||
<% @tagged_content.each do |content_group| %>
|
||||
<div class="section">
|
||||
<h5 class="<%= content_group[:color] %>-text">
|
||||
<i class="material-icons left"><%= content_group[:icon] %></i>
|
||||
<%= content_group[:type].pluralize %> (<%= content_group[:content].count %>)
|
||||
</h5>
|
||||
|
||||
<div class="row js-content-cards-list">
|
||||
<% content_group[:content].each do |content| %>
|
||||
<div class="col s12 m6 l4 js-content-card-container">
|
||||
<div class="hoverable card sticky-action" style="margin-bottom: 2px">
|
||||
<div class="card-image waves-effect waves-block waves-light">
|
||||
<%
|
||||
# Find image for this content
|
||||
content_image = @random_image_pool_cache.fetch([content.class.name, content.id], [])
|
||||
.sample
|
||||
.try(:src, :medium)
|
||||
|
||||
if @saved_basil_commissions
|
||||
content_image ||= @saved_basil_commissions.fetch([content.class.name, content.id], [])
|
||||
.sample
|
||||
.try(:image)
|
||||
.try(:url)
|
||||
end
|
||||
|
||||
content_image ||= asset_path("card-headers/#{content.class.name.downcase.pluralize}.jpg")
|
||||
%>
|
||||
<div class="activator" style="height: 265px; background: url('<%= content_image %>'); background-size: cover;"></div>
|
||||
|
||||
<span class="card-title js-content-name activator">
|
||||
<div class="bordered-text">
|
||||
<% content_name = content.respond_to?(:name) ? content.name : content.title %>
|
||||
<%= ContentFormatterService.show(text: content_name.presence || 'Untitled', viewing_user: current_user) %>
|
||||
</div>
|
||||
|
||||
<% if content.respond_to?(:page_tags) && content.page_tags.any? %>
|
||||
<p class="tags-container">
|
||||
<% content.page_tags.each do |tag| %>
|
||||
<% if tag.tag == @tag %>
|
||||
<span class="new badge <%= content_group[:color] %> left" data-badge-caption="<%= tag.tag %>"></span>
|
||||
<% else %>
|
||||
<span class="new badge grey left" data-badge-caption="<%= tag.tag %>"></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="card-action">
|
||||
<% if content.is_a?(Document) %>
|
||||
<%= link_to 'View', content, class: 'blue-text text-lighten-1', target: '_blank' %>
|
||||
<% else %>
|
||||
<%= link_to 'View', content, class: 'blue-text text-lighten-1' %>
|
||||
<% end %>
|
||||
|
||||
<% user = @users_cache[content.user_id] %>
|
||||
<% if user %>
|
||||
<%= link_to profile_by_username_path(username: user.username), class: 'right grey-text' do %>
|
||||
<% if user.image_url %>
|
||||
<img src="<%= user.image_url.html_safe %>" alt="<%= user.display_name %>" style="width: 20px; height: 20px; border-radius: 50%; vertical-align: middle; margin-right: 5px;">
|
||||
<% else %>
|
||||
<i class="material-icons tiny" style="vertical-align: middle;">person</i>
|
||||
<% end %>
|
||||
<span style="vertical-align: middle; font-size: 0.9rem;"><%= user.display_name %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="card-reveal">
|
||||
<span class="card-title">
|
||||
<%= content_name.presence || 'Untitled' %>
|
||||
<i class="material-icons right">close</i>
|
||||
</span>
|
||||
<% content_description = content.try(:description) || content.try(:synopsis) %>
|
||||
<% if content_description.present? %>
|
||||
<p>
|
||||
<%= sanitize ContentFormatterService.show(text: truncate(content_description, length: 420, escape: false), viewing_user: current_user) %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if content.respond_to?(:page_tags) && content.page_tags.any? %>
|
||||
<p class="tags-container">
|
||||
<% content.page_tags.each do |tag| %>
|
||||
<% if tag.tag == @tag %>
|
||||
<span class="new badge <%= content_group[:color] %> left" data-badge-caption="<%= tag.tag %>"></span>
|
||||
<% else %>
|
||||
<span class="new badge grey left" data-badge-caption="<%= tag.tag %>"></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</p>
|
||||
<div class="clearfix"></div>
|
||||
<% end %>
|
||||
|
||||
<% user = @users_cache[content.user_id] %>
|
||||
<% if user %>
|
||||
<p>
|
||||
<strong>Creator:</strong>
|
||||
<%= link_to profile_by_username_path(username: user.username) do %>
|
||||
<%= user.display_name %>
|
||||
<% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p class="grey-text clearfix">
|
||||
<%= content.created_at == content.updated_at ? 'created' : 'last updated' %>
|
||||
<%= time_ago_in_words content.updated_at %>
|
||||
ago
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@ -4,6 +4,7 @@
|
||||
%>
|
||||
|
||||
<% if show_notice?(id: 24) && show_artfight_promo %>
|
||||
<div class="clearfix"></div>
|
||||
<div class="card-panel purple lighten-4 black-text show-when-focused" style="margin-top: 30px; border-left: 4px solid #9c27b0; position: relative; box-shadow: 0 2px 5px rgba(0,0,0,0.1); border-radius: 4px;">
|
||||
<div style="display: flex; align-items: flex-start;">
|
||||
<i class="material-icons purple-text" style="margin-right: 10px;">brush</i>
|
||||
|
||||
@ -327,6 +327,11 @@ Rails.application.routes.draw do
|
||||
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
|
||||
end
|
||||
|
||||
# Browse global content routes
|
||||
scope '/browse' do
|
||||
get '/tag/:tag_slug', to: 'browse#tag', as: :browse_tag
|
||||
end
|
||||
|
||||
# Fancy shmancy informative pages
|
||||
scope '/worldbuilding' do
|
||||
Rails.application.config.content_types[:all].each do |content_type|
|
||||
|
||||
Loading…
Reference in New Issue
Block a user