This commit is contained in:
@@ -44,7 +44,7 @@ export default () => {
|
||||
if (data.valid)
|
||||
setUser (toCamel (data.user, { deep: true }))
|
||||
else
|
||||
createUser ()
|
||||
await createUser ()
|
||||
}) ()
|
||||
}
|
||||
else
|
||||
|
||||
+117
-109
@@ -10,14 +10,14 @@ import { cn } from '@/lib/utils'
|
||||
|
||||
import type { Tag, User, WikiPage } from '@/types'
|
||||
|
||||
type Props = { user: User
|
||||
setUser: (user: User) => void }
|
||||
type Props = { user: User
|
||||
setUser: (user: User) => void }
|
||||
|
||||
const enum Menu { None,
|
||||
Post,
|
||||
User,
|
||||
Tag,
|
||||
Wiki }
|
||||
Post,
|
||||
User,
|
||||
Tag,
|
||||
Wiki }
|
||||
|
||||
|
||||
const TopNav: React.FC = ({ user, setUser }: Props) => {
|
||||
@@ -35,14 +35,14 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
|
||||
const [postCount, setPostCount] = useState<number | null> (null)
|
||||
|
||||
const MyLink = ({ to, title, menu, base }: { to: string
|
||||
title: string
|
||||
menu?: Menu
|
||||
base?: string }) => (
|
||||
title: string
|
||||
menu?: Menu
|
||||
base?: string }) => (
|
||||
<Link to={to} className={cn ('hover:text-orange-500 h-full flex items-center',
|
||||
(location.pathname.startsWith (base ?? to)
|
||||
? 'bg-gray-700 px-4 font-bold'
|
||||
: 'px-2'))}>
|
||||
{title}
|
||||
(location.pathname.startsWith (base ?? to)
|
||||
? 'bg-gray-700 px-4 font-bold'
|
||||
: 'px-2'))}>
|
||||
{title}
|
||||
</Link>)
|
||||
|
||||
const whenTagSearchChanged = ev => {
|
||||
@@ -53,8 +53,8 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
|
||||
const q: string = ev.target.value.split (' ').at (-1)
|
||||
if (!(q))
|
||||
{
|
||||
setSuggestions ([])
|
||||
return
|
||||
setSuggestions ([])
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +66,8 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
|
||||
const q: string = ev.target.value.split (' ').at (-1)
|
||||
if (!(q))
|
||||
{
|
||||
setSuggestions ([])
|
||||
return
|
||||
setSuggestions ([])
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,16 +79,16 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
|
||||
const q: string = ev.target.value.split (' ').at (-1)
|
||||
if (!(q))
|
||||
{
|
||||
setSuggestions ([])
|
||||
return
|
||||
setSuggestions ([])
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter' && wikiSearch.length && (!(suggestionsVsbl) || activeIndex < 0))
|
||||
{
|
||||
navigate (`/wiki/${ encodeURIComponent (wikiSearch) }`)
|
||||
setSuggestionsVsbl (false)
|
||||
navigate (`/wiki/${ encodeURIComponent (wikiSearch) }`)
|
||||
setSuggestionsVsbl (false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,105 +120,113 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
|
||||
void ((async () => {
|
||||
try
|
||||
{
|
||||
const { data: pageData } = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`)
|
||||
const wikiPage: WikiPage = toCamel (pageData, { deep: true })
|
||||
const { data: pageData } = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`)
|
||||
const wikiPage: WikiPage = toCamel (pageData, { deep: true })
|
||||
|
||||
const { data: tagData } = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`)
|
||||
const tag: Tag = toCamel (tagData, { deep: true })
|
||||
const { data: tagData } = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`)
|
||||
const tag: Tag = toCamel (tagData, { deep: true })
|
||||
|
||||
setPostCount (tag.postCount)
|
||||
setPostCount (tag.postCount)
|
||||
}
|
||||
catch
|
||||
{
|
||||
setPostCount (0)
|
||||
setPostCount (0)
|
||||
}
|
||||
}) ())
|
||||
}, [wikiId])
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className="bg-gray-800 text-white px-3 flex justify-between items-center w-full min-h-[48px]">
|
||||
<div className="flex items-center gap-2 h-full">
|
||||
<Link to="/posts" className="mx-4 text-xl font-bold text-orange-500">ぼざクリ タグ広場</Link>
|
||||
<MyLink to="/posts" title="広場" />
|
||||
<MyLink to="/tags" title="タグ" />
|
||||
<MyLink to="/wiki/ヘルプ:ホーム" base="/wiki" title="Wiki" />
|
||||
<MyLink to="/users" title="ニジラー" />
|
||||
</div>
|
||||
<div className="ml-auto pr-4">
|
||||
<Button onClick={() => navigate ('/users/settings')}>{user?.name || '名もなきニジラー'}</Button>
|
||||
</div>
|
||||
</nav>
|
||||
{(() => {
|
||||
const className = 'bg-gray-700 text-white px-3 flex items-center w-full min-h-[40px]'
|
||||
const subClass = 'hover:text-orange-500 h-full flex items-center px-3'
|
||||
const inputBox = 'flex items-center px-3 mx-2'
|
||||
const Separator = () => <span className="flex items-center px-2">|</span>
|
||||
switch (selectedMenu)
|
||||
{
|
||||
case Menu.Post:
|
||||
return (
|
||||
<div className={className}>
|
||||
<Link to="/posts" className={subClass}>一覧</Link>
|
||||
<Link to="/posts/new" className={subClass}>投稿追加</Link>
|
||||
<Link to="/wiki/ヘルプ:広場" className={subClass}>ヘルプ</Link>
|
||||
</div>)
|
||||
case Menu.Tag:
|
||||
return (
|
||||
<div className={className}>
|
||||
<input type="text"
|
||||
className={inputBox}
|
||||
placeholder="タグ検索"
|
||||
value={tagSearch}
|
||||
onChange={whenTagSearchChanged}
|
||||
onFocus={() => setSuggestionsVsbl (true)}
|
||||
onBlur={() => setSuggestionsVsbl (false)}
|
||||
onKeyDown={handleKeyDown} />
|
||||
<Link to="/tags" className={subClass}>タグ</Link>
|
||||
<Link to="/tags/aliases" className={subClass}>別名タグ</Link>
|
||||
<Link to="/tags/implications" className={subClass}>上位タグ</Link>
|
||||
<Link to="/wiki/ヘルプ:タグのつけ方" className={subClass}>タグのつけ方</Link>
|
||||
<Link to="/wiki/ヘルプ:タグ" className={subClass}>ヘルプ</Link>
|
||||
</div>)
|
||||
case Menu.Wiki:
|
||||
return (
|
||||
<div className={className}>
|
||||
<input type="text"
|
||||
className={inputBox}
|
||||
placeholder="Wiki 検索"
|
||||
value={wikiSearch}
|
||||
onChange={whenWikiSearchChanged}
|
||||
onFocus={() => setSuggestionsVsbl (true)}
|
||||
onBlur={() => setSuggestionsVsbl (false)}
|
||||
onKeyDown={handleKeyDown} />
|
||||
<Link to="/wiki" className={subClass}>検索</Link>
|
||||
<Link to="/wiki/new" className={subClass}>新規</Link>
|
||||
<Link to="/wiki/changes" className={subClass}>全体履歴</Link>
|
||||
<Link to="/wiki/ヘルプ:Wiki" className={subClass}>ヘルプ</Link>
|
||||
{(/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) &&
|
||||
<>
|
||||
<Separator />
|
||||
<Link to={`/posts?tags=${ location.pathname.split ('/')[2] }`} className={subClass}>広場 ({postCount || 0})</Link>
|
||||
<Link to={`/wiki/changes?id=${ wikiId }`} className={subClass}>履歴</Link>
|
||||
<Link to={`/wiki/${ wikiId || location.pathname.split ('/')[2] }/edit`} className={subClass}>編輯</Link>
|
||||
</>}
|
||||
</div>)
|
||||
case Menu.User:
|
||||
return (
|
||||
<div className={className}>
|
||||
<input type="text"
|
||||
className={inputBox}
|
||||
placeholder="ニジラー検索"
|
||||
value={userSearch}
|
||||
onChange={whenUserSearchChanged}
|
||||
onFocus={() => setSuggestionsVsbl (true)}
|
||||
onBlur={() => setSuggestionsVsbl (false)}
|
||||
onKeyDown={handleKeyDown} />
|
||||
<Link to="/users" className={subClass}>一覧</Link>
|
||||
{user && <Link to={`/users/${ user.id }`} className={subClass}>お前</Link>}
|
||||
</div>)
|
||||
}
|
||||
}) ()}
|
||||
<nav className="bg-gray-800 text-white px-3 flex justify-between items-center w-full min-h-[48px]">
|
||||
<div className="flex items-center gap-2 h-full">
|
||||
<Link to="/posts" className="mx-4 text-xl font-bold text-orange-500">ぼざクリ タグ広場</Link>
|
||||
<MyLink to="/posts" title="広場" />
|
||||
<MyLink to="/tags" title="タグ" />
|
||||
<MyLink to="/wiki/ヘルプ:ホーム" base="/wiki" title="Wiki" />
|
||||
<MyLink to="/users/settings" base="/users" title="ニジラー" />
|
||||
</div>
|
||||
<div className="ml-auto pr-4">
|
||||
{user && (
|
||||
<Button onClick={() => navigate ('/users/settings')}
|
||||
className="bg-gray-600">
|
||||
{user.name || '名もなきニジラー'}
|
||||
</Button>)}
|
||||
</div>
|
||||
</nav>
|
||||
{(() => {
|
||||
const className = 'bg-gray-700 text-white px-3 flex items-center w-full min-h-[40px]'
|
||||
const subClass = 'hover:text-orange-500 h-full flex items-center px-3'
|
||||
const inputBox = 'flex items-center px-3 mx-2'
|
||||
const Separator = () => <span className="flex items-center px-2">|</span>
|
||||
switch (selectedMenu)
|
||||
{
|
||||
case Menu.Post:
|
||||
return (
|
||||
<div className={className}>
|
||||
<Link to="/posts" className={subClass}>一覧</Link>
|
||||
<Link to="/posts/new" className={subClass}>投稿追加</Link>
|
||||
<Link to="/wiki/ヘルプ:広場" className={subClass}>ヘルプ</Link>
|
||||
</div>)
|
||||
case Menu.Tag:
|
||||
return (
|
||||
<div className={className}>
|
||||
{/* TODO: リリース後にやる */}
|
||||
{/* <input type="text"
|
||||
className={inputBox}
|
||||
placeholder="タグ検索"
|
||||
value={tagSearch}
|
||||
onChange={whenTagSearchChanged}
|
||||
onFocus={() => setSuggestionsVsbl (true)}
|
||||
onBlur={() => setSuggestionsVsbl (false)}
|
||||
onKeyDown={handleKeyDown} /> */}
|
||||
<Link to="/tags" className={subClass}>タグ</Link>
|
||||
<Link to="/tags/aliases" className={subClass}>別名タグ</Link>
|
||||
<Link to="/tags/implications" className={subClass}>上位タグ</Link>
|
||||
<Link to="/wiki/ヘルプ:タグのつけ方" className={subClass}>タグのつけ方</Link>
|
||||
<Link to="/wiki/ヘルプ:タグ" className={subClass}>ヘルプ</Link>
|
||||
</div>)
|
||||
case Menu.Wiki:
|
||||
return (
|
||||
<div className={className}>
|
||||
{/* TODO: リリース後にやる */}
|
||||
{/* <input type="text"
|
||||
className={inputBox}
|
||||
placeholder="Wiki 検索"
|
||||
value={wikiSearch}
|
||||
onChange={whenWikiSearchChanged}
|
||||
onFocus={() => setSuggestionsVsbl (true)}
|
||||
onBlur={() => setSuggestionsVsbl (false)}
|
||||
onKeyDown={handleKeyDown} /> */}
|
||||
<Link to="/wiki" className={subClass}>検索</Link>
|
||||
<Link to="/wiki/new" className={subClass}>新規</Link>
|
||||
<Link to="/wiki/changes" className={subClass}>全体履歴</Link>
|
||||
<Link to="/wiki/ヘルプ:Wiki" className={subClass}>ヘルプ</Link>
|
||||
{(/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) &&
|
||||
<>
|
||||
<Separator />
|
||||
<Link to={`/posts?tags=${ location.pathname.split ('/')[2] }`} className={subClass}>広場 ({postCount || 0})</Link>
|
||||
<Link to={`/wiki/changes?id=${ wikiId }`} className={subClass}>履歴</Link>
|
||||
<Link to={`/wiki/${ wikiId || location.pathname.split ('/')[2] }/edit`} className={subClass}>編輯</Link>
|
||||
</>}
|
||||
</div>)
|
||||
case Menu.User:
|
||||
return (
|
||||
<div className={className}>
|
||||
{/* TODO: リリース後にやる */}
|
||||
{/* <input type="text"
|
||||
className={inputBox}
|
||||
placeholder="ニジラー検索"
|
||||
value={userSearch}
|
||||
onChange={whenUserSearchChanged}
|
||||
onFocus={() => setSuggestionsVsbl (true)}
|
||||
onBlur={() => setSuggestionsVsbl (false)}
|
||||
onKeyDown={handleKeyDown} /> */}
|
||||
{/* <Link to="/users" className={subClass}>一覧</Link>
|
||||
{user && <Link to={`/users/${ user.id }`} className={subClass}>お前</Link>} */}
|
||||
{user && <Link to="/users/settings" className={subClass}>設定</Link>}
|
||||
</div>)
|
||||
}
|
||||
}) ()}
|
||||
</>)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ type Props = { visible: boolean
|
||||
|
||||
export default ({ visible, onVisibleChange, user, setUser }: Props) => {
|
||||
const handleChange = async () => {
|
||||
if (!(confirm ('引継ぎコードを再発行しますか?')))
|
||||
if (!(confirm ('引継ぎコードを再発行しますか?\n再発行するとほかのブラウザからはログアウトされます.')))
|
||||
return
|
||||
|
||||
const { data } = await axios.post (`${ API_BASE_URL }/users/code/renew`, { }, { headers: {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import toCamel from 'camelcase-keys'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet-async'
|
||||
|
||||
@@ -7,8 +9,9 @@ import PageTitle from '@/components/common/PageTitle'
|
||||
import MainArea from '@/components/layout/MainArea'
|
||||
import InheritDialogue from '@/components/users/InheritDialogue'
|
||||
import UserCodeDialogue from '@/components/users/UserCodeDialogue'
|
||||
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { toast } from '@/components/ui/use-toast'
|
||||
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
||||
|
||||
import type { User } from '@/types'
|
||||
|
||||
@@ -22,14 +25,18 @@ export default ({ user, setUser }: Props) => {
|
||||
const [inheritVsbl, setInheritVsbl] = useState (false)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const formData = new FormData ()
|
||||
if (!(user))
|
||||
return
|
||||
|
||||
const formData = new FormData
|
||||
formData.append ('name', name)
|
||||
|
||||
try
|
||||
{
|
||||
await axios.post (`${ API_BASE_URL }/users`, formData, { headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'X-Transfer-Code': localStorage.getItem ('user_code') || '' } })
|
||||
const { data } = await axios.put (`${ API_BASE_URL }/users/${ user.id }`, formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data',
|
||||
'X-Transfer-Code': localStorage.getItem ('user_code') || '' } })
|
||||
setUser (user => ({ ...user, ...data }))
|
||||
toast ({ title: '設定を更新しました.' })
|
||||
}
|
||||
catch
|
||||
|
||||
Reference in New Issue
Block a user