#19 ひとまづ表示のみ
This commit is contained in:
@@ -1,16 +1,24 @@
|
|||||||
class WikiPagesController < ApplicationController
|
class WikiPagesController < ApplicationController
|
||||||
def index
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
end
|
p params
|
||||||
|
wiki_page = WikiPage.find_by(title: params[:title])
|
||||||
def create
|
if wiki_page
|
||||||
|
render plain: wiki_page.markdown
|
||||||
|
else
|
||||||
|
head :not_found
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
end
|
return head :unauthorized unless current_user
|
||||||
|
|
||||||
def destroy
|
title = params[:title]
|
||||||
|
wiki_page = WikiPage.find_by(title: title)
|
||||||
|
unless wiki_page
|
||||||
|
wiki_page = WikiPage.new(title: title, created_user: current_user, updated_user: current_user)
|
||||||
|
end
|
||||||
|
wiki_page.markdown = params[:markdown]
|
||||||
|
wiki_page.save!
|
||||||
|
head :ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
require 'net/http'
|
|
||||||
require 'uri'
|
|
||||||
|
|
||||||
|
|
||||||
class WikiProxyController < ApplicationController
|
|
||||||
def edit
|
|
||||||
tag = params[:tag]
|
|
||||||
uri = "http://localhost:4567/gollum/edit/#{ URI.encode_www_form_component(tag) }"
|
|
||||||
begin
|
|
||||||
res = fetch_with_redirect(uri)
|
|
||||||
render html: res.body.html_safe, content_type: res.content_type
|
|
||||||
rescue => e
|
|
||||||
render plain: "Wiki システムとの通信に失敗しました:#{ e.message }", status: 502
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def fetch_with_redirect uri_str, limit = 5
|
|
||||||
raise 'Too many redirects' if limit == 0
|
|
||||||
|
|
||||||
uri = URI.parse(uri_str)
|
|
||||||
res = Net::HTTP.get_response(uri)
|
|
||||||
if res.is_a? Net::HTTPRedirection
|
|
||||||
location = res['location']
|
|
||||||
fetch_with_redirect(location, limit - 1)
|
|
||||||
else
|
|
||||||
res
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,11 +1,34 @@
|
|||||||
|
require 'gollum-lib'
|
||||||
|
|
||||||
|
|
||||||
class WikiPage < ApplicationRecord
|
class WikiPage < ApplicationRecord
|
||||||
|
WIKI_PATH = Rails.root.join('wiki').to_s
|
||||||
|
|
||||||
belongs_to :tag, optional: true
|
belongs_to :tag, optional: true
|
||||||
belongs_to :created_user, class_name: 'User', foreign_key: 'created_user_id'
|
belongs_to :created_user, class_name: 'User', foreign_key: 'created_user_id'
|
||||||
belongs_to :updated_user, class_name: 'User', foreign_key: 'updated_user_id'
|
belongs_to :updated_user, class_name: 'User', foreign_key: 'updated_user_id'
|
||||||
|
|
||||||
validates :title, presence: true, length: { maximum: 255 }, uniqueness: true
|
validates :title, presence: true, length: { maximum: 255 }, uniqueness: true
|
||||||
|
|
||||||
def gollum_path
|
def markdown
|
||||||
"wiki/#{ title.parameterize }.md"
|
wiki = Gollum::Wiki.new(WIKI_PATH)
|
||||||
|
page = wiki.page(title)
|
||||||
|
page&.raw_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def markdown= content
|
||||||
|
wiki = Gollum::Wiki.new(WIKI_PATH)
|
||||||
|
|
||||||
|
page = wiki.page(title)
|
||||||
|
|
||||||
|
commit_info = { message: "Update #{ title }",
|
||||||
|
name: current_user.id,
|
||||||
|
email: 'dummy@example.com' }
|
||||||
|
|
||||||
|
if page
|
||||||
|
page.update(content, commit: commit_info)
|
||||||
|
else
|
||||||
|
wiki.write_page(title, :markdown, content, commit_info)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,62 +1,4 @@
|
|||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
get "wiki_pages/index"
|
|
||||||
get "wiki_pages/show"
|
|
||||||
get "wiki_pages/create"
|
|
||||||
get "wiki_pages/update"
|
|
||||||
get "wiki_pages/destroy"
|
|
||||||
get "users/index"
|
|
||||||
get "users/show"
|
|
||||||
get "users/create"
|
|
||||||
get "users/update"
|
|
||||||
get "users/destroy"
|
|
||||||
get "user_post_views/index"
|
|
||||||
get "user_post_views/show"
|
|
||||||
get "user_post_views/create"
|
|
||||||
get "user_post_views/update"
|
|
||||||
get "user_post_views/destroy"
|
|
||||||
get "user_ips/index"
|
|
||||||
get "user_ips/show"
|
|
||||||
get "user_ips/create"
|
|
||||||
get "user_ips/update"
|
|
||||||
get "user_ips/destroy"
|
|
||||||
get "tags/index"
|
|
||||||
get "tags/show"
|
|
||||||
get "tags/create"
|
|
||||||
get "tags/update"
|
|
||||||
get "tags/destroy"
|
|
||||||
get 'tags/autocomplete', to: 'tags#autocomplete'
|
|
||||||
get "tag_aliases/index"
|
|
||||||
get "tag_aliases/show"
|
|
||||||
get "tag_aliases/create"
|
|
||||||
get "tag_aliases/update"
|
|
||||||
get "tag_aliases/destroy"
|
|
||||||
get "settings/index"
|
|
||||||
get "settings/show"
|
|
||||||
get "settings/create"
|
|
||||||
get "settings/update"
|
|
||||||
get "settings/destroy"
|
|
||||||
get "post_tags/index"
|
|
||||||
get "post_tags/show"
|
|
||||||
get "post_tags/create"
|
|
||||||
get "post_tags/update"
|
|
||||||
get "post_tags/destroy"
|
|
||||||
post 'posts/:id/viewed', to: 'posts#viewed'
|
|
||||||
delete 'posts/:id/viewed', to: 'posts#unviewed'
|
|
||||||
get "nico_tag_relation/index"
|
|
||||||
get "nico_tag_relation/show"
|
|
||||||
get "nico_tag_relation/create"
|
|
||||||
get "nico_tag_relation/update"
|
|
||||||
get "nico_tag_relation/destroy"
|
|
||||||
get "ip_addresses/index"
|
|
||||||
get "ip_addresses/show"
|
|
||||||
get "ip_addresses/create"
|
|
||||||
get "ip_addresses/update"
|
|
||||||
get "ip_addresses/destroy"
|
|
||||||
get 'preview/title', to: 'preview#title'
|
|
||||||
get 'preview/thumbnail', to: 'preview#thumbnail'
|
|
||||||
get '/wiki/edit/:tag', to: 'wiki_proxy#edit'
|
|
||||||
root 'home#index'
|
|
||||||
|
|
||||||
resources :posts
|
resources :posts
|
||||||
resources :ip_addresses
|
resources :ip_addresses
|
||||||
resources :nico_tag_relations
|
resources :nico_tag_relations
|
||||||
@@ -72,7 +14,14 @@ Rails.application.routes.draw do
|
|||||||
get :me
|
get :me
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :wiki_pages
|
|
||||||
|
get 'tags/autocomplete', to: 'tags#autocomplete'
|
||||||
|
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', to: 'wiki_pages#show', format: false
|
||||||
|
post 'wiki/*title', to: 'wiki_pages#save', format: false
|
||||||
|
|
||||||
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
|
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
|
||||||
|
|
||||||
|
|||||||
Generated
+1175
-3
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@
|
|||||||
"marked": "^15.0.12",
|
"marked": "^15.0.12",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
|
"react-markdown": "^10.1.0",
|
||||||
"react-markdown-editor-lite": "^1.3.4",
|
"react-markdown-editor-lite": "^1.3.4",
|
||||||
"react-router-dom": "^6.30.0",
|
"react-router-dom": "^6.30.0",
|
||||||
"tailwind-merge": "^3.3.0"
|
"tailwind-merge": "^3.3.0"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import TagSidebar from './components/TagSidebar'
|
|||||||
import PostPage from './pages/PostPage'
|
import PostPage from './pages/PostPage'
|
||||||
import PostNewPage from './pages/PostNewPage'
|
import PostNewPage from './pages/PostNewPage'
|
||||||
import PostDetailPage from './pages/PostDetailPage'
|
import PostDetailPage from './pages/PostDetailPage'
|
||||||
import WikiEditPage from './pages/WikiEditPage'
|
import WikiShowPage from './pages/WikiShowPage'
|
||||||
import { API_BASE_URL } from './config'
|
import { API_BASE_URL } from './config'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Toaster } from '@/components/ui/toaster'
|
import { Toaster } from '@/components/ui/toaster'
|
||||||
@@ -81,7 +81,7 @@ const App = () => {
|
|||||||
<Route path="/posts/new" element={<PostNewPage />} />
|
<Route path="/posts/new" element={<PostNewPage />} />
|
||||||
<Route path="/posts/:id" element={<PostDetailPage posts={posts} setPosts={setPosts} />} />
|
<Route path="/posts/:id" element={<PostDetailPage posts={posts} setPosts={setPosts} />} />
|
||||||
<Route path="/tags/:tag" element={<TagPage />} />
|
<Route path="/tags/:tag" element={<TagPage />} />
|
||||||
<Route path="/wiki/:name" element={<WikiEditPage />} />
|
<Route path="/wiki/:name" element={<WikiShowPage />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import MdEditor from 'react-markdown-editor-lite'
|
||||||
|
import 'react-markdown-editor-lite/lib/index.css'
|
||||||
|
import { marked } from 'marked'
|
||||||
|
|
||||||
|
type Props = { value: string
|
||||||
|
onChange: (text: string) => void
|
||||||
|
onSave: () => void }
|
||||||
|
|
||||||
|
|
||||||
|
const WikiEditor = ({ value, onChange, onSave }) => (
|
||||||
|
<div className="wiki-editor">
|
||||||
|
<MdEditor value={value}
|
||||||
|
style={{ height: '500px' }}
|
||||||
|
renderHTML={text => marked (text)} />
|
||||||
|
<button onClick={onSave}>保存</button>
|
||||||
|
</div>)
|
||||||
|
|
||||||
|
|
||||||
|
export default WikiEditor
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import { useParams } from 'react-router-dom'
|
|
||||||
import { useEffect, useState } from 'react'
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
|
|
||||||
const WikiEditPage = () => {
|
|
||||||
const { name } = useParams<{ name: string }> ()
|
|
||||||
|
|
||||||
const [html, setHtml] = useState('')
|
|
||||||
const [loading, setLoading] = useState(true)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const link = document.createElement('link')
|
|
||||||
link.rel = 'stylesheet'
|
|
||||||
link.href = '/wiki/custom.css' // Gollum の静的 CSS にアクセスできるようにしとく
|
|
||||||
document.head.appendChild(link)
|
|
||||||
return () => {
|
|
||||||
document.head.removeChild(link)
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setLoading(true)
|
|
||||||
axios
|
|
||||||
.get(`/api/wiki/edit/${encodeURIComponent(name)}`, {
|
|
||||||
headers: { 'X-Transfer-Code': localStorage.getItem('user_code') || '' }
|
|
||||||
})
|
|
||||||
.then((res) => setHtml(res.data))
|
|
||||||
.finally(() => setLoading(false))
|
|
||||||
}, [name])
|
|
||||||
|
|
||||||
return loading ? (
|
|
||||||
<p>読み込み中...</p>
|
|
||||||
) : (
|
|
||||||
<div dangerouslySetInnerHTML={{ __html: html }} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default WikiEditPage
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import WikiEditor from '@/components/WikiEditor'
|
||||||
|
import { API_BASE_URL } from '../config'
|
||||||
|
|
||||||
|
|
||||||
|
const WikiPage = () => {
|
||||||
|
const [text, setText] = useState ('')
|
||||||
|
|
||||||
|
useEffect (() => {
|
||||||
|
void (axios.get (`${ API_BASE_URL }/wiki/load`, { params: { page: 'xxx' } })
|
||||||
|
.then (res => setText (res.data.markdown)))
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
void (axios.post ('/api/wiki/save', { page: 'xxx',
|
||||||
|
markdown: text })
|
||||||
|
.catch (err => console.error ('保存失敗', err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return <WikiEditor value={text} onChange={setText} onSave={save} />
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { useParams } from 'react-router-dom'
|
||||||
|
import ReactMarkdown from 'react-markdown'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import axios from 'axios'
|
||||||
|
import { API_BASE_URL } from '@/config'
|
||||||
|
|
||||||
|
|
||||||
|
const WikiShowPage = () => {
|
||||||
|
const { name } = useParams ()
|
||||||
|
|
||||||
|
const [markdown, setMarkdown] = useState ('')
|
||||||
|
|
||||||
|
useEffect (() => {
|
||||||
|
void (axios.get (`${ API_BASE_URL }/wiki/${ encodeURIComponent (name) }`)
|
||||||
|
.then (res => setMarkdown (res.data))
|
||||||
|
.catch (() => setMarkdown ('# ページが存在しません')))
|
||||||
|
}, [name])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="prose mx-auto p-4">
|
||||||
|
<ReactMarkdown>{markdown}</ReactMarkdown>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default WikiShowPage
|
||||||
Reference in New Issue
Block a user