Browse Source

#59 関聯投稿一覧の追加

#59
みてるぞ 1 week ago
parent
commit
efb6b16412
4 changed files with 31 additions and 5 deletions
  1. +4
    -4
      backend/app/controllers/posts_controller.rb
  2. +21
    -0
      backend/app/models/post.rb
  3. +4
    -0
      frontend/src/pages/posts/PostDetailPage.tsx
  4. +2
    -1
      frontend/src/types.ts

+ 4
- 4
backend/app/controllers/posts_controller.rb View File

@@ -5,16 +5,16 @@ require 'nokogiri'
class PostsController < ApplicationController
# GET /posts
def index
limit = (params[:limit] || 20).to_i
limit = params[:limit].presence&.to_i
cursor = params[:cursor].presence

q = filtered_posts.order(created_at: :desc)
q = q.where('posts.created_at < ?', Time.iso8601(cursor)) if cursor

posts = q.limit(limit + 1)
posts = limit ? q.limit(limit + 1) : q

next_cursor = nil
if posts.size > limit
if limit && posts.size > limit
next_cursor = posts.last.created_at.iso8601(6)
posts = posts.first(limit)
end
@@ -51,7 +51,7 @@ class PostsController < ApplicationController

render json: (post
.as_json(include: { tags: { only: [:id, :name, :category, :post_count] } })
.merge(viewed: viewed))
.merge(related: post.related(limit: 20), viewed:))
end

# POST /posts


+ 21
- 0
backend/app/models/post.rb View File

@@ -7,6 +7,12 @@ class Post < ApplicationRecord
has_many :post_tags, dependent: :destroy
has_many :tags, through: :post_tags
has_many :user_post_views, dependent: :destroy
has_many :post_similarities_as_post,
class_name: 'PostSimilarity',
foreign_key: :post_id
has_many :post_similarities_as_target_post,
class_name: 'PostSimilarity',
foreign_key: :target_post_id
has_one_attached :thumbnail

def as_json options = { }
@@ -18,6 +24,21 @@ class Post < ApplicationRecord
super(options).merge(thumbnail: nil)
end

def related(limit: nil)
ids_with_cos =
post_similarities_as_post.select(:target_post_id, :cos)
.map { |ps| [ps.target_post_id, ps.cos] } +
post_similarities_as_target_post.select(:post_id, :cos)
.map { |ps| [ps.post_id, ps.cos] }

sorted = ids_with_cos.sort_by { |_, cos| -cos }

ids = sorted.map(&:first)
ids = ids.first(limit) if limit

Post.where(id: ids)
end

def resized_thumbnail!
return unless thumbnail.attached?



+ 4
- 0
frontend/src/pages/posts/PostDetailPage.tsx View File

@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet-async'
import { useParams } from 'react-router-dom'

import PostList from '@/components/PostList'
import TagDetailSidebar from '@/components/TagDetailSidebar'
import NicoViewer from '@/components/NicoViewer'
import PostEditForm from '@/components/PostEditForm'
@@ -117,6 +118,9 @@ export default ({ user }: Props) => {
{post.viewed ? '閲覧済' : '未閲覧'}
</Button>
<TabGroup>
<Tab name="関聯">
<PostList posts={post.related} />
</Tab>
{(['admin', 'member'].some (r => user?.role === r) && editing) && (
<Tab name="編輯">
<PostEditForm post={post}


+ 2
- 1
frontend/src/types.ts View File

@@ -23,7 +23,8 @@ export type Post = {
thumbnail: string
thumbnailBase: string
tags: Tag[]
viewed: boolean }
viewed: boolean
related: Post[] }

export type SubMenuItem = {
component: React.ReactNode


Loading…
Cancel
Save