parent
13fb4db1d1
commit
090ded9e85
@ -0,0 +1,49 @@ |
||||
import { useQuery } from '@tanstack/react-query'; |
||||
import { useParams, useNavigate } from 'react-router-dom'; |
||||
import { fetchPageHistory } from '../apiTools.jsx'; |
||||
import { useFixLinks } from '../clientStuff.jsx'; |
||||
|
||||
import './Pages.css'; |
||||
|
||||
function HistoryView() { |
||||
const noLoad = useFixLinks(); |
||||
const { pagenumber, editid } = useParams(); |
||||
const navigate = useNavigate(); |
||||
|
||||
const { isPending, error, data } = useQuery({ // fetch the currrent values |
||||
queryKey: ['page history', pagenumber], |
||||
queryFn: () => fetchPageHistory(pagenumber) |
||||
}) |
||||
const edits = data; |
||||
|
||||
const ready = !(error || isPending); |
||||
|
||||
const pageTitle = edits ? edits[0]?.title : "[no title]"; |
||||
|
||||
return ( |
||||
<div className="main-column"> |
||||
<div> |
||||
<header> |
||||
<h1><a href="/" {...noLoad}>🌳</a>{pagenumber}. {ready ? pageTitle : "..."}</h1> |
||||
<hr/> |
||||
</header> |
||||
<section className="page-contents"> |
||||
{ ready ? |
||||
<ol> |
||||
{ edits.map(({id, number, title, time, author}) => |
||||
<li key={id}> |
||||
<a href={`/${number}/${id}`} {...noLoad}>{id} : "{title}", {time} by user #{author}</a> |
||||
</li> |
||||
) } |
||||
</ol> |
||||
: |
||||
(isPending ? "Loading..." : JSON.stringify(error)) |
||||
} |
||||
</section> |
||||
<button onClick={() => navigate(`/${pagenumber}`)}>Return to page</button> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default HistoryView; |
@ -0,0 +1,116 @@ |
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; |
||||
import { useParams, useNavigate } from 'react-router-dom'; |
||||
import { apiUrl, fetchPage, fetchPageAtEdit, postPage, deletePage } from '../apiTools.jsx'; |
||||
import { useFixLinks } from '../clientStuff.jsx'; |
||||
import { useLoggedIn } from '../AuthProvider.jsx'; |
||||
|
||||
import './Pages.css'; |
||||
|
||||
function Page({ editing }) { |
||||
const queryClient = useQueryClient(); |
||||
const navigate = useNavigate(); |
||||
const { pagenumber, editid } = useParams(); |
||||
const loggedIn = useLoggedIn(); |
||||
const noLoad = useFixLinks(); |
||||
|
||||
const fetchQuery = useQuery({ // fetch the currrent values |
||||
queryKey: ['page', pagenumber, editid], |
||||
queryFn: () => editid ? fetchPageAtEdit(pagenumber, editid) : fetchPage(pagenumber) |
||||
}) |
||||
|
||||
const postMutation = useMutation({ // for changing the value when we're done with it |
||||
mutationFn: ({id, title, description}) => postPage({id, title, description}), |
||||
onSettled: async (data, error, variables) => { |
||||
// Invalidate and refetch |
||||
await queryClient.invalidateQueries({ queryKey: ['page', variables.id, undefined] }) |
||||
}, |
||||
}); |
||||
|
||||
const deleteMutation = useMutation({ // for changing the value when we're done with it |
||||
mutationFn: (id) => deletePage(id), |
||||
onSettled: async (data, error, variables) => { |
||||
// Invalidate and refetch |
||||
await queryClient.invalidateQueries({ queryKey: ['pages'] }) |
||||
}, |
||||
}); |
||||
|
||||
const readyToShow = !(fetchQuery.error || fetchQuery.isPending); |
||||
|
||||
let {id, title, description, html, time, author} = fetchQuery.data || {}; |
||||
if (!title) title = "[no title]"; |
||||
if (!html) html = "[body missing]"; |
||||
if (!description) description = "[body missing]"; |
||||
|
||||
function submitChanges(e) { |
||||
const newTitle = document.querySelector('span').innerHTML; |
||||
const newText = document.querySelector('pre').innerHTML; |
||||
postMutation.mutate({ |
||||
id: pagenumber, |
||||
title: newTitle, |
||||
description: newText |
||||
}); |
||||
navigate(`/${pagenumber}`, {replace: true}) |
||||
} |
||||
|
||||
function submitDelete(e) { |
||||
e.preventDefault(); |
||||
deleteMutation.mutate(pagenumber); |
||||
navigate(`/`); |
||||
} |
||||
|
||||
return ( |
||||
<div className="main-column"> |
||||
<header> |
||||
<h1> |
||||
<a href="/" {...noLoad}>🌳</a> |
||||
{pagenumber}. |
||||
<span |
||||
contentEditable={editing} |
||||
dangerouslySetInnerHTML={{__html: readyToShow ? title : "..." }} /> |
||||
</h1> |
||||
{readyToShow && editid && `saved at ${time} by user #${author}`} |
||||
<hr/> |
||||
</header> |
||||
<section className="page-contents"> |
||||
{ readyToShow ? |
||||
( |
||||
editing ? |
||||
<pre |
||||
contentEditable="true" |
||||
dangerouslySetInnerHTML={{__html: description}} /> |
||||
: |
||||
<div |
||||
dangerouslySetInnerHTML={{__html: html}} |
||||
{...noLoad} /> |
||||
) |
||||
: |
||||
"..." |
||||
} |
||||
</section> |
||||
<button |
||||
onClick={() => navigate(`/${pagenumber}/history`)}> |
||||
History |
||||
</button> |
||||
{editing && ( |
||||
<button |
||||
disabled={postMutation.isPending} |
||||
onClick={submitChanges}> |
||||
{postMutation.isPending ? "Updating..." : "Update"} |
||||
</button>)} |
||||
{!editing && !editid && ( |
||||
<button |
||||
disabled={!loggedIn} |
||||
onClick={() => navigate(`/${pagenumber}/edit`)}> |
||||
Edit Page |
||||
</button>)} |
||||
{loggedIn && ( |
||||
<button |
||||
disabled={deleteMutation.isPending} |
||||
onClick={submitDelete}> |
||||
{deleteMutation.isPending ? "Deleting..." : "Delete this page and entire edit history (no backsies)"} |
||||
</button>)} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default Page; |
@ -1,97 +0,0 @@ |
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; |
||||
import { useParams, useNavigate } from 'react-router-dom'; |
||||
import { apiUrl, fetchPage, postPage, deletePage } from '../apiTools.jsx'; |
||||
|
||||
import './Pages.css'; |
||||
|
||||
function PageEdit() { |
||||
const queryClient = useQueryClient(); |
||||
const navigate = useNavigate(); |
||||
const { pagenumber } = useParams(); |
||||
|
||||
const fetchQuery = useQuery({ // fetch the currrent values |
||||
queryKey: ['page', pagenumber], |
||||
queryFn: () => fetchPage(pagenumber) |
||||
}) |
||||
|
||||
const postMutation = useMutation({ // for changing the value when we're done with it |
||||
mutationFn: ({id, title, description}) => postPage({id, title, description}), |
||||
onSettled: async (data, error, variables) => { |
||||
// Invalidate and refetch |
||||
await queryClient.invalidateQueries({ queryKey: ['page', variables.id] }) |
||||
}, |
||||
}); |
||||
|
||||
const deleteMutation = useMutation({ // for changing the value when we're done with it |
||||
mutationFn: (id) => deletePage(id), |
||||
onSettled: async (data, error, variables) => { |
||||
// Invalidate and refetch |
||||
await queryClient.invalidateQueries({ queryKey: ['pages'] }) |
||||
}, |
||||
}); |
||||
|
||||
const ready = !(fetchQuery.error || fetchQuery.isPending); |
||||
|
||||
let {id, title, description, html} = fetchQuery.data || {}; |
||||
if (!title) title = " "; |
||||
if (!description) description = " "; |
||||
|
||||
function submitChanges(e) { |
||||
const newTitle = document.querySelector('span').innerHTML; |
||||
const newText = document.querySelector('pre').innerHTML; |
||||
postMutation.mutate({ |
||||
id: pagenumber, |
||||
title: newTitle, |
||||
description: newText, |
||||
}); |
||||
navigate(`/${pagenumber}`, {replace: true}) |
||||
} |
||||
|
||||
function submitDelete(e) { |
||||
e.preventDefault(); |
||||
deleteMutation.mutate(pagenumber); |
||||
navigate(`/`); |
||||
} |
||||
|
||||
return ( |
||||
<div className="main-column"> |
||||
<header> |
||||
<h1> |
||||
<a href="/">🌳</a> |
||||
{pagenumber}. |
||||
<span |
||||
contentEditable="true" |
||||
dangerouslySetInnerHTML={{__html: ready ? title : "..." }} /> |
||||
</h1> |
||||
<hr/> |
||||
</header> |
||||
<section> |
||||
{ ready ? |
||||
<> |
||||
<div className="page-contents"> |
||||
<pre |
||||
contentEditable="true" |
||||
dangerouslySetInnerHTML={{__html: description}} /> |
||||
</div> |
||||
<button |
||||
disabled={postMutation.isPending} |
||||
onClick={submitChanges}> |
||||
{postMutation.isPending ? "Updating..." : "Update"} |
||||
</button> |
||||
<button |
||||
disabled={deleteMutation.isPending} |
||||
onClick={submitDelete}> |
||||
{deleteMutation.isPending ? "Deleting..." : "Delete this page (no backsies)"} |
||||
</button> |
||||
</> |
||||
: |
||||
<div className="page-contents"> |
||||
{ fetchQuery.isPending ? "Loading..." : JSON.stringify(fetchQuery.error) } |
||||
</div> |
||||
} |
||||
</section> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default PageEdit; |
@ -1,48 +0,0 @@ |
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; |
||||
import { useParams, useNavigate } from 'react-router-dom'; |
||||
import { apiUrl, fetchPage, postPage } from '../apiTools.jsx'; |
||||
import { useFixLinks } from '../clientStuff.jsx'; |
||||
|
||||
import './Pages.css'; |
||||
|
||||
function PageView() { |
||||
const queryClient = useQueryClient(); |
||||
const navigate = useNavigate(); |
||||
const noLoad = useFixLinks(); |
||||
const { pagenumber } = useParams(); |
||||
|
||||
const { isPending, error, data } = useQuery({ // fetch the currrent values |
||||
queryKey: ['page', pagenumber], |
||||
queryFn: () => fetchPage(pagenumber) |
||||
}) |
||||
|
||||
const ready = !(error || isPending); |
||||
|
||||
let {id, title, description, html} = data || {}; |
||||
|
||||
return ( |
||||
<div className="main-column"> |
||||
<div> |
||||
<header> |
||||
<h1> |
||||
<a href="/" {...noLoad}>🌳</a>{pagenumber}. {ready ? (title || " ") : "..."}</h1> |
||||
<hr/> |
||||
</header> |
||||
<section> |
||||
{ ready ? |
||||
<div |
||||
className="page-contents" |
||||
dangerouslySetInnerHTML={{ __html: (html || " ") }} |
||||
{...noLoad} |
||||
/> |
||||
: |
||||
(isPending ? "Loading..." : JSON.stringify(error)) |
||||
} |
||||
<button onClick={(e) => { e.preventDefault(); navigate(`/${pagenumber}/edit`, {replace: true})}}>Edit this page!</button> |
||||
</section> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default PageView; |
Loading…
Reference in new issue