#107 Co-authored-by: miteruzo <miteruzo@naver.com> Reviewed-on: https://git.miteruzo.com/miteruzo/btrc-hub/pulls/192feature/157
| @@ -13,6 +13,22 @@ class WikiPagesController < ApplicationController | |||||
| render_wiki_page_or_404 WikiPage.find_by(title: params[:title]) | render_wiki_page_or_404 WikiPage.find_by(title: params[:title]) | ||||
| end | end | ||||
| def exists | |||||
| if WikiPage.exists?(params[:id]) | |||||
| head :no_content | |||||
| else | |||||
| head :not_found | |||||
| end | |||||
| end | |||||
| def exists_by_title | |||||
| if WikiPage.exists?(title: params[:title]) | |||||
| head :no_content | |||||
| else | |||||
| head :not_found | |||||
| end | |||||
| end | |||||
| def diff | def diff | ||||
| id = params[:id] | id = params[:id] | ||||
| from = params[:from] | from = params[:from] | ||||
| @@ -1,46 +1,60 @@ | |||||
| Rails.application.routes.draw do | Rails.application.routes.draw do | ||||
| get 'tags/nico', to: 'nico_tags#index' | |||||
| put 'tags/nico/:id', to: 'nico_tags#update' | |||||
| get 'tags/autocomplete', to: 'tags#autocomplete' | |||||
| get 'tags/name/:name', to: 'tags#show_by_name' | |||||
| get 'posts/random', to: 'posts#random' | |||||
| get 'posts/changes', to: 'posts#changes' | |||||
| post 'posts/:id/viewed', to: 'posts#viewed' | |||||
| delete 'posts/:id/viewed', to: 'posts#unviewed' | |||||
| get 'preview/title', to: 'preview#title' | |||||
| get 'preview/thumbnail', to: 'preview#thumbnail' | |||||
| get 'wiki/title/:title', to: 'wiki_pages#show_by_title' | |||||
| get 'wiki/search', to: 'wiki_pages#search' | |||||
| get 'wiki/changes', to: 'wiki_pages#changes' | |||||
| get 'wiki/:id/diff', to: 'wiki_pages#diff' | |||||
| get 'wiki/:id', to: 'wiki_pages#show' | |||||
| get 'wiki', to: 'wiki_pages#index' | |||||
| post 'wiki', to: 'wiki_pages#create' | |||||
| put 'wiki/:id', to: 'wiki_pages#update' | |||||
| post 'users/code/renew', to: 'users#renew' | |||||
| resources :posts | |||||
| resources :ip_addresses | |||||
| resources :nico_tag_relations | |||||
| resources :post_tags | |||||
| resources :settings | |||||
| resources :tag_aliases | |||||
| resources :tags | |||||
| resources :user_ips | |||||
| resources :user_post_views | |||||
| resources :nico_tags, path: 'tags/nico', only: [:index, :update] | |||||
| resources :tags do | |||||
| collection do | |||||
| get :autocomplete | |||||
| get 'name/:name', action: :show_by_name | |||||
| end | |||||
| end | |||||
| scope :preview, controller: :preview do | |||||
| get :title | |||||
| get :thumbnail | |||||
| end | |||||
| resources :wiki_pages, path: 'wiki', only: [:index, :show, :create, :update] do | |||||
| collection do | |||||
| get :search | |||||
| get :changes | |||||
| scope :title do | |||||
| get ':title/exists', action: :exists_by_title | |||||
| get ':title', action: :show_by_title | |||||
| end | |||||
| end | |||||
| member do | |||||
| get :exists | |||||
| get :diff | |||||
| end | |||||
| end | |||||
| resources :posts do | |||||
| collection do | |||||
| get :random | |||||
| get :changes | |||||
| end | |||||
| member do | |||||
| post :viewed | |||||
| delete :viewed, action: :unviewed | |||||
| end | |||||
| end | |||||
| resources :users, only: [:create, :update] do | resources :users, only: [:create, :update] do | ||||
| collection do | collection do | ||||
| post :verify | post :verify | ||||
| get :me | get :me | ||||
| post 'code/renew', action: :renew | |||||
| end | end | ||||
| end | end | ||||
| # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html | |||||
| # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. | |||||
| # Can be used by load balancers and uptime monitors to verify that the app is live. | |||||
| # get "up" => "rails/health#show", as: :rails_health_check | |||||
| # Defines the root path route ("/") | |||||
| # root "posts#index" | |||||
| resources :ip_addresses | |||||
| resources :nico_tag_relations | |||||
| resources :post_tags | |||||
| resources :settings | |||||
| resources :tag_aliases | |||||
| resources :user_ips | |||||
| resources :user_post_views | |||||
| end | end | ||||
| @@ -1,5 +1,8 @@ | |||||
| import axios from 'axios' | |||||
| import { useEffect, useState } from 'react' | |||||
| import { Link } from 'react-router-dom' | import { Link } from 'react-router-dom' | ||||
| import { API_BASE_URL } from '@/config' | |||||
| import { LIGHT_COLOUR_SHADE, DARK_COLOUR_SHADE, TAG_COLOUR } from '@/consts' | import { LIGHT_COLOUR_SHADE, DARK_COLOUR_SHADE, TAG_COLOUR } from '@/consts' | ||||
| import { cn } from '@/lib/utils' | import { cn } from '@/lib/utils' | ||||
| @@ -27,6 +30,27 @@ export default (({ tag, | |||||
| withWiki = true, | withWiki = true, | ||||
| withCount = true, | withCount = true, | ||||
| ...props }: Props) => { | ...props }: Props) => { | ||||
| const [havingWiki, setHavingWiki] = useState (true) | |||||
| const wikiExists = async (tagName: string) => { | |||||
| try | |||||
| { | |||||
| await axios.get (`${ API_BASE_URL }/wiki/title/${ encodeURIComponent (tagName) }/exists`) | |||||
| setHavingWiki (true) | |||||
| } | |||||
| catch | |||||
| { | |||||
| setHavingWiki (false) | |||||
| } | |||||
| } | |||||
| useEffect (() => { | |||||
| if (!(linkFlg) || !(withWiki)) | |||||
| return | |||||
| wikiExists (tag.name) | |||||
| }, [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 }`) | ||||
| @@ -39,10 +63,19 @@ export default (({ tag, | |||||
| <> | <> | ||||
| {(linkFlg && withWiki) && ( | {(linkFlg && withWiki) && ( | ||||
| <span className="mr-1"> | <span className="mr-1"> | ||||
| <Link to={`/wiki/${ encodeURIComponent (tag.name) }`} | |||||
| className={linkClass}> | |||||
| ? | |||||
| </Link> | |||||
| {havingWiki | |||||
| ? ( | |||||
| <Link to={`/wiki/${ encodeURIComponent (tag.name) }`} | |||||
| className={linkClass}> | |||||
| ? | |||||
| </Link>) | |||||
| : ( | |||||
| <Link to={`/wiki/${ encodeURIComponent (tag.name) }`} | |||||
| className="animate-[wiki-blink_.25s_steps(2,end)_infinite] | |||||
| dark:animate-[wiki-blink-dark_.25s_steps(2,end)_infinite]" | |||||
| title={`${ tag.name } Wiki が存在しません.`}> | |||||
| ! | |||||
| </Link>)} | |||||
| </span>)} | </span>)} | ||||
| {nestLevel > 0 && ( | {nestLevel > 0 && ( | ||||
| <span | <span | ||||
| @@ -96,3 +96,15 @@ button:focus-visible | |||||
| background-color: #f9f9f9; | background-color: #f9f9f9; | ||||
| } | } | ||||
| } | } | ||||
| @keyframes wiki-blink | |||||
| { | |||||
| 0%, 100% { color: #dc2626; } | |||||
| 50% { color: #2563eb; } | |||||
| } | |||||
| @keyframes wiki-blink-dark | |||||
| { | |||||
| 0%, 100% { color: #f87171; } | |||||
| 50% { color: #60a5fa; } | |||||
| } | |||||