This commit is contained in:
@@ -18,7 +18,7 @@ class MaterialsController < ApplicationController
|
|||||||
count = q.count
|
count = q.count
|
||||||
materials = q.order(created_at: :desc, id: :desc).limit(limit).offset(offset)
|
materials = q.order(created_at: :desc, id: :desc).limit(limit).offset(offset)
|
||||||
|
|
||||||
render json: { materials: MaterialRepr.many(materials), count: count }
|
render json: { materials: MaterialRepr.many(materials, host: request.base_url), count: count }
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@@ -29,7 +29,9 @@ class MaterialsController < ApplicationController
|
|||||||
.find_by(id: params[:id])
|
.find_by(id: params[:id])
|
||||||
return head :not_found unless material
|
return head :not_found unless material
|
||||||
|
|
||||||
render json: MaterialRepr.base(material)
|
wiki_page_body = material.tag.tag_name.wiki_page&.current_revision&.body
|
||||||
|
|
||||||
|
render json: MaterialRepr.base(material, host: request.base_url).merge(wiki_page_body:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@@ -50,7 +52,7 @@ class MaterialsController < ApplicationController
|
|||||||
material.file.attach(file)
|
material.file.attach(file)
|
||||||
|
|
||||||
if material.save
|
if material.save
|
||||||
render json: MaterialRepr.base(material), status: :created
|
render json: MaterialRepr.base(material, host: request.base_url), status: :created
|
||||||
else
|
else
|
||||||
render json: { errors: material.errors.full_messages }, status: :unprocessable_entity
|
render json: { errors: material.errors.full_messages }, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
@@ -80,7 +82,7 @@ class MaterialsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
if material.save
|
if material.save
|
||||||
render json: MaterialRepr.base(material)
|
render json: MaterialRepr.base(material, host: request.base_url)
|
||||||
else
|
else
|
||||||
render json: { errors: material.errors.full_messages }, status: :unprocessable_entity
|
render json: { errors: material.errors.full_messages }, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class TagsController < ApplicationController
|
|||||||
else
|
else
|
||||||
Tag.joins(:tag_name)
|
Tag.joins(:tag_name)
|
||||||
end
|
end
|
||||||
.includes(:tag_name, tag_name: :wiki_page)
|
.includes(:tag_name, tag_name: :wiki_page, :materials)
|
||||||
q = q.where(posts: { id: post_id }) if post_id.present?
|
q = q.where(posts: { id: post_id }) if post_id.present?
|
||||||
|
|
||||||
q = q.where('tag_names.name LIKE ?', "%#{ name }%") if name
|
q = q.where('tag_names.name LIKE ?', "%#{ name }%") if name
|
||||||
@@ -83,7 +83,7 @@ class TagsController < ApplicationController
|
|||||||
tags =
|
tags =
|
||||||
Tag
|
Tag
|
||||||
.joins(:tag_name)
|
.joins(:tag_name)
|
||||||
.includes(:tag_name, tag_name: :wiki_page)
|
.includes(:tag_name, tag_name: :wiki_page, :materials)
|
||||||
.where(category: [:meme, :character, :material])
|
.where(category: [:meme, :character, :material])
|
||||||
.where(id: tag_ids)
|
.where(id: tag_ids)
|
||||||
.order('tag_names.name')
|
.order('tag_names.name')
|
||||||
@@ -128,7 +128,7 @@ class TagsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
base = Tag.joins(:tag_name)
|
base = Tag.joins(:tag_name)
|
||||||
.includes(:tag_name, tag_name: :wiki_page)
|
.includes(:tag_name, tag_name: :wiki_page, :materials)
|
||||||
base = base.where('tags.post_count > 0') if present_only
|
base = base.where('tags.post_count > 0') if present_only
|
||||||
|
|
||||||
canonical_hit =
|
canonical_hit =
|
||||||
@@ -153,7 +153,7 @@ class TagsController < ApplicationController
|
|||||||
|
|
||||||
def show
|
def show
|
||||||
tag = Tag.joins(:tag_name)
|
tag = Tag.joins(:tag_name)
|
||||||
.includes(:tag_name, tag_name: :wiki_page)
|
.includes(:tag_name, tag_name: :wiki_page, :materials)
|
||||||
.find_by(id: params[:id])
|
.find_by(id: params[:id])
|
||||||
if tag
|
if tag
|
||||||
render json: TagRepr.base(tag)
|
render json: TagRepr.base(tag)
|
||||||
@@ -167,7 +167,7 @@ class TagsController < ApplicationController
|
|||||||
return head :bad_request if name.blank?
|
return head :bad_request if name.blank?
|
||||||
|
|
||||||
tag = Tag.joins(:tag_name)
|
tag = Tag.joins(:tag_name)
|
||||||
.includes(:tag_name, tag_name: :wiki_page)
|
.includes(:tag_name, tag_name: :wiki_page, :materials)
|
||||||
.find_by(tag_names: { name: })
|
.find_by(tag_names: { name: })
|
||||||
if tag
|
if tag
|
||||||
render json: TagRepr.base(tag)
|
render json: TagRepr.base(tag)
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ class Tag < ApplicationRecord
|
|||||||
|
|
||||||
def has_wiki = wiki_page.present?
|
def has_wiki = wiki_page.present?
|
||||||
|
|
||||||
|
def material_id = materials.first&.id
|
||||||
|
|
||||||
def self.tagme
|
def self.tagme
|
||||||
@tagme ||= find_or_create_by_tag_name!('タグ希望', category: :meta)
|
@tagme ||= find_or_create_by_tag_name!('タグ希望', category: :meta)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,22 +2,23 @@
|
|||||||
|
|
||||||
|
|
||||||
module MaterialRepr
|
module MaterialRepr
|
||||||
BASE = { methods: [:content_type],
|
BASE = { only: [:id, :url, :created_at, :updated_at],
|
||||||
include: { created_by_user: UserRepr::BASE,
|
methods: [:content_type],
|
||||||
|
include: { tag: TagRepr::BASE,
|
||||||
|
created_by_user: UserRepr::BASE,
|
||||||
updated_by_user: UserRepr::BASE } }.freeze
|
updated_by_user: UserRepr::BASE } }.freeze
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def base(material)
|
def base material, host:
|
||||||
material.as_json(BASE).merge(
|
material.as_json(BASE).merge(
|
||||||
file: if material.file.attached?
|
file: if material.file.attached?
|
||||||
Rails.application.routes.url_helpers.rails_storage_proxy_url(
|
Rails.application.routes.url_helpers.rails_storage_proxy_url(
|
||||||
material.file, only_path: false)
|
material.file, host:)
|
||||||
end,
|
end)
|
||||||
tag: TagRepr.base(material.tag))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def many(materials)
|
def many materials, host:
|
||||||
materials.map { |m| base(m) }
|
materials.map { |m| base(m, host) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
module TagRepr
|
module TagRepr
|
||||||
BASE = { only: [:id, :category, :post_count, :created_at, :updated_at],
|
BASE = { only: [:id, :category, :post_count, :created_at, :updated_at],
|
||||||
methods: [:name, :has_wiki] }.freeze
|
methods: [:name, :has_wiki, :material_id] }.freeze
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export default (() => {
|
|||||||
<>
|
<>
|
||||||
<RouteBlockerOverlay/>
|
<RouteBlockerOverlay/>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<div className="flex flex-col h-screen w-screen">
|
<div className="flex flex-col h-dvh w-screen">
|
||||||
<TopNav user={user}/>
|
<TopNav user={user}/>
|
||||||
<RouteTransitionWrapper user={user} setUser={setUser}/>
|
<RouteTransitionWrapper user={user} setUser={setUser}/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import { useEffect, useState } from 'react'
|
|
||||||
|
|
||||||
import PrefetchLink from '@/components/PrefetchLink'
|
import PrefetchLink from '@/components/PrefetchLink'
|
||||||
import { LIGHT_COLOUR_SHADE, DARK_COLOUR_SHADE, TAG_COLOUR } from '@/consts'
|
import { LIGHT_COLOUR_SHADE, DARK_COLOUR_SHADE, TAG_COLOUR } from '@/consts'
|
||||||
import { apiGet } from '@/lib/api'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
import type { ComponentProps, FC, HTMLAttributes } from 'react'
|
import type { ComponentProps, FC, HTMLAttributes } from 'react'
|
||||||
@@ -36,35 +33,6 @@ export default (({ tag,
|
|||||||
withWiki = true,
|
withWiki = true,
|
||||||
withCount = true,
|
withCount = true,
|
||||||
...props }: Props) => {
|
...props }: Props) => {
|
||||||
const [havingWiki, setHavingWiki] = useState (true)
|
|
||||||
|
|
||||||
const wikiExists = async (tag: Tag) => {
|
|
||||||
if ('hasWiki' in tag)
|
|
||||||
{
|
|
||||||
setHavingWiki (tag.hasWiki)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const tagName = (tag as Tag).name
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await apiGet (`/wiki/title/${ encodeURIComponent (tagName) }/exists`)
|
|
||||||
setHavingWiki (true)
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
setHavingWiki (false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect (() => {
|
|
||||||
if (!(linkFlg) || !(withWiki))
|
|
||||||
return
|
|
||||||
|
|
||||||
wikiExists (tag)
|
|
||||||
}, [tag.name, linkFlg, withWiki])
|
|
||||||
|
|
||||||
const spanClass = cn (
|
const spanClass = cn (
|
||||||
`text-${ TAG_COLOUR[tag.category] }-${ LIGHT_COLOUR_SHADE }`,
|
`text-${ TAG_COLOUR[tag.category] }-${ LIGHT_COLOUR_SHADE }`,
|
||||||
`dark:text-${ TAG_COLOUR[tag.category] }-${ DARK_COLOUR_SHADE }`)
|
`dark:text-${ TAG_COLOUR[tag.category] }-${ DARK_COLOUR_SHADE }`)
|
||||||
@@ -77,17 +45,27 @@ export default (({ tag,
|
|||||||
<>
|
<>
|
||||||
{(linkFlg && withWiki) && (
|
{(linkFlg && withWiki) && (
|
||||||
<span className="mr-1">
|
<span className="mr-1">
|
||||||
{havingWiki
|
{(tag.materialId != null || tag.hasWiki)
|
||||||
? (
|
? (
|
||||||
<PrefetchLink to={`/wiki/${ encodeURIComponent (tag.name) }`}
|
tag.materialId == null
|
||||||
className={linkClass}>
|
? (
|
||||||
?
|
<PrefetchLink
|
||||||
</PrefetchLink>)
|
to={`/wiki/${ encodeURIComponent (tag.name) }`}
|
||||||
|
className={linkClass}>
|
||||||
|
?
|
||||||
|
</PrefetchLink>)
|
||||||
|
: (
|
||||||
|
<PrefetchLink
|
||||||
|
to={`/materials/${ tag.materialId }`}
|
||||||
|
className={linkClass}>
|
||||||
|
?
|
||||||
|
</PrefetchLink>))
|
||||||
: (
|
: (
|
||||||
<PrefetchLink to={`/wiki/${ encodeURIComponent (tag.name) }`}
|
<PrefetchLink
|
||||||
className="animate-[wiki-blink_.25s_steps(2,end)_infinite]
|
to={`/wiki/${ encodeURIComponent (tag.name) }`}
|
||||||
dark:animate-[wiki-blink-dark_.25s_steps(2,end)_infinite]"
|
className="animate-[wiki-blink_.25s_steps(2,end)_infinite]
|
||||||
title={`${ tag.name } Wiki が存在しません.`}>
|
dark:animate-[wiki-blink-dark_.25s_steps(2,end)_infinite]"
|
||||||
|
title={`${ tag.name } Wiki が存在しません.`}>
|
||||||
!
|
!
|
||||||
</PrefetchLink>)}
|
</PrefetchLink>)}
|
||||||
</span>)}
|
</span>)}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { FC } from 'react'
|
|||||||
|
|
||||||
|
|
||||||
export default (() => (
|
export default (() => (
|
||||||
<div className="md:flex md:flex-1">
|
<div className="md:flex md:flex-1 md:h-[calc(100dvh-88px)]">
|
||||||
<MaterialSidebar/>
|
<MaterialSidebar/>
|
||||||
<Outlet/>
|
<Outlet/>
|
||||||
</div>)) satisfies FC
|
</div>)) satisfies FC
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Helmet } from 'react-helmet-async'
|
|||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
|
|
||||||
import TagLink from '@/components/TagLink'
|
import TagLink from '@/components/TagLink'
|
||||||
|
import WikiBody from '@/components/WikiBody'
|
||||||
import Label from '@/components/common/Label'
|
import Label from '@/components/common/Label'
|
||||||
import PageTitle from '@/components/common/PageTitle'
|
import PageTitle from '@/components/common/PageTitle'
|
||||||
import TabGroup, { Tab } from '@/components/common/TabGroup'
|
import TabGroup, { Tab } from '@/components/common/TabGroup'
|
||||||
@@ -109,6 +110,12 @@ export default (() => {
|
|||||||
<audio src={material.file} controls/>)))}
|
<audio src={material.file} controls/>)))}
|
||||||
|
|
||||||
<TabGroup>
|
<TabGroup>
|
||||||
|
<Tab name="Wiki">
|
||||||
|
<WikiBody
|
||||||
|
title={material.tag.name}
|
||||||
|
body={material.wikiPageBody ?? undefined}/>
|
||||||
|
</Tab>
|
||||||
|
|
||||||
<Tab name="編輯">
|
<Tab name="編輯">
|
||||||
<div className="max-w-wl pt-2 space-y-4">
|
<div className="max-w-wl pt-2 space-y-4">
|
||||||
{/* タグ */}
|
{/* タグ */}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export default (({ user }: Props) => {
|
|||||||
: 'bg-gray-500 hover:bg-gray-600')
|
: 'bg-gray-500 hover:bg-gray-600')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="md:flex md:flex-1">
|
<div className="md:flex md:flex-1 md:h-[calc(100dvh-88px)]">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
{(post?.thumbnail || post?.thumbnailBase) && (
|
{(post?.thumbnail || post?.thumbnailBase) && (
|
||||||
<meta name="thumbnail" content={post.thumbnail || post.thumbnailBase}/>)}
|
<meta name="thumbnail" content={post.thumbnail || post.thumbnailBase}/>)}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default (() => {
|
|||||||
}, [location.search])
|
}, [location.search])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="md:flex md:flex-1" ref={containerRef}>
|
<div className="md:flex md:flex-1 md:h-[calc(100dvh-88px)]" ref={containerRef}>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>
|
<title>
|
||||||
{tags.length
|
{tags.length
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export type Material = {
|
|||||||
tag: Tag
|
tag: Tag
|
||||||
file: string | null
|
file: string | null
|
||||||
url: string | null
|
url: string | null
|
||||||
|
wikiPageBody?: string | null
|
||||||
contentType: string | null
|
contentType: string | null
|
||||||
createdAt: string
|
createdAt: string
|
||||||
createdByUser: { id: number; name: string }
|
createdByUser: { id: number; name: string }
|
||||||
@@ -140,6 +141,7 @@ export type Tag = {
|
|||||||
createdAt: string
|
createdAt: string
|
||||||
updatedAt: string
|
updatedAt: string
|
||||||
hasWiki: boolean
|
hasWiki: boolean
|
||||||
|
materialId: number
|
||||||
children?: Tag[]
|
children?: Tag[]
|
||||||
matchedAlias?: string | null }
|
matchedAlias?: string | null }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user