Balance is restored, and we have an external json editor

This commit is contained in:
Shoofle 2024-11-01 13:10:37 -04:00
parent eb75c859f2
commit 0b82c15afe
5 changed files with 77 additions and 48 deletions

View File

@ -3,7 +3,7 @@ import { LogInStatusUpdateEscapeTool } from './AuthProvider.jsx';
// This is wrapper functtions to do requests to the api, from the frontend. // This is wrapper functtions to do requests to the api, from the frontend.
const secure = false const secure = false;
export const apiUrl = `http${secure?'s':''}://${window.location.host}/api`; export const apiUrl = `http${secure?'s':''}://${window.location.host}/api`;
@ -56,9 +56,16 @@ export async function fetchPageAtEdit(number, id) {
export async function postPage({number, title, description, type}) { export async function postPage({number, title, description, type}) {
return shoofetch(`${apiUrl}/page/${number}`, { return shoofetch(`${apiUrl}/page/${number}`, {
method: 'POST', method: 'POST',
body: JSON.stringify({number: number, title: title, description: description, type: type}), body: JSON.stringify({number: number, title: title, description: description, type: type}),
}) })
}
export async function postAttributes({number, attributes}) {
return shoofetch(`${apiUrl}/page/${number}/attributes`, {
method: 'POST',
body: JSON.stringify(attributes),
})
} }
export async function deletePage(id) { export async function deletePage(id) {

View File

@ -1,20 +1,19 @@
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useParams, useNavigate } from 'react-router-dom'; import { useParams, useNavigate } from 'react-router-dom';
import { apiUrl, wsUrl, fetchPage, fetchPageAttributes, fetchPageAtEdit, postPage, fetchCurrentVerbs } from '../apiTools.jsx'; import { apiUrl, wsUrl, fetchPage, fetchPageAttributes, postPage, fetchCurrentVerbs } from '../apiTools.jsx';
import { useFixLinks } from '../clientStuff.jsx';
import { useLoggedIn } from '../AuthProvider.jsx';
import useWebSocket, { ReadyState } from 'react-use-websocket'; import useWebSocket, { ReadyState } from 'react-use-websocket';
import Page from '../page/Page.jsx'; import Page from '../page/Page.jsx';
import ExtendedAttributes from '../page/ExtendedAttributes.jsx'; import ExtendedAttributes from '../page/ExtendedAttributes.jsx';
import { JsonEditor } from 'json-edit-react';
import MessageFeed from './MessageFeed.jsx'; import MessageFeed from './MessageFeed.jsx';
import WordSidebar from './WordSidebar.jsx'; import WordSidebar from './WordSidebar.jsx';
import CommandEntry from './CommandEntry.jsx'; import CommandEntry from './CommandEntry.jsx';
function Live({...props}) { function Live({...props}) {
const navigate = useNavigate(); const navigate = useNavigate();
const loggedIn = useLoggedIn();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [ command, setCommand ] = useState(''); const [ command, setCommand ] = useState('');
@ -57,11 +56,6 @@ function Live({...props}) {
setTitle(fetchPageQuery.data?.title); setTitle(fetchPageQuery.data?.title);
}, [fetchPageQuery.data?.title]); }, [fetchPageQuery.data?.title]);
const [text, setText] = useState(null);
useEffect(() => {
setText(fetchPageQuery.data?.description);
}, [fetchPageQuery.data?.description]);
const [type, setType] = useState(false); const [type, setType] = useState(false);
useEffect(() => { useEffect(() => {
setType(fetchPageQuery.data?.type == 1); setType(fetchPageQuery.data?.type == 1);
@ -73,6 +67,11 @@ function Live({...props}) {
queryFn: () => fetchPageAttributes(currentNumber) queryFn: () => fetchPageAttributes(currentNumber)
}); });
const [attributes, setAttributes] = useState(null);
useEffect(() => {
setAttributes(fetchAttributesQuery.data);
}, [fetchAttributesQuery.data]);
// verbs available to us // verbs available to us
const fetchVerbsQuery = useQuery({ const fetchVerbsQuery = useQuery({
queryKey: ['my verbs'], queryKey: ['my verbs'],
@ -91,12 +90,14 @@ function Live({...props}) {
}); });
function saveChanges() { function saveChanges() {
postMutation.mutate({ if (editorRef.current) {
number: currentNumber, postMutation.mutate({
title: title, number: currentNumber,
description: text, title: title,
type: type ? 1 : 0, description: editorRef.current.getMarkdown(),
}); type: type ? 1 : 0,
});
}
} }
function handleSubmitCommand() { function handleSubmitCommand() {
@ -105,6 +106,10 @@ function Live({...props}) {
else if (c == "save changes") { else if (c == "save changes") {
saveChanges(); saveChanges();
setEditing(false); setEditing(false);
} else if ( c == "discard changes") {
queryClient.invalidateQueries(['page', currentNumber, null]);
queryClient.invalidateQueries(['attributes', currentNumber]);
setEditing(false);
} }
else sendMessage(c); else sendMessage(c);
@ -143,16 +148,24 @@ function Live({...props}) {
<> <>
<div className="main-column"> <div className="main-column">
<Page <Page
page={{...fetchPageQuery.data, description: text, title: title, type: type }} page={{...fetchPageQuery.data, title: title, type: type }}
editing={editing} editing={editing}
linkClick={commandLinkClick} linkClick={commandLinkClick}
onChangeTitle={(e) => setTitle(e.target.value)} onChangeTitle={(e) => setTitle(e.target.value)}
onChangeText={setText}
onChangeType={() => setType(!type)} onChangeType={() => setType(!type)}
ref={editorRef} ref={editorRef}
{...props} /> {...props} />
<ExtendedAttributes {editing ?
attributes={fetchAttributesQuery.data} /> <section className="page-contents">
<JsonEditor
theme="githubDark"
data={attributes}
setData={setAttributes} />
</section>
:
<ExtendedAttributes
attributes={attributes} />
}
</div> </div>
<MessageFeed messages={messageHistory}> <MessageFeed messages={messageHistory}>
<button disabled={connecting} onClick={() => setConnecting(true)}> <button disabled={connecting} onClick={() => setConnecting(true)}>

View File

@ -2,26 +2,21 @@ import AttrList from './components/AttrList.jsx';
import JsonDisplay from './components/JsonDisplay.jsx'; import JsonDisplay from './components/JsonDisplay.jsx';
function ExtendedAttributes({attributes, ...props}) { function ExtendedAttributes({attributes, ...props}) {
console.log(attributes); //console.log(attributes);
if (!attributes) if (!attributes)
return <section className="page-contents">This object has no attributes.</section>; return <section className="page-contents">This object has no attributes.</section>;
const {parent, location, contents, verbs, prepositions} = attributes; const {parent, location, contents, verbs, prepositions} = attributes;
let newAttributes = {} const newAttributes = {...attributes,
for (const prop in attributes) { parent: undefined,
if (Object.hasOwn(attributes, prop)) { location: undefined,
newAttributes[prop] = attributes[prop] contents: undefined,
} verbs: undefined,
prepositions: undefined
} }
delete newAttributes["parent"];
delete newAttributes["location"];
delete newAttributes["contents"];
delete newAttributes["verbs"];
delete newAttributes["prepositions"];
return <> return <>
<section className="page-contents"> <section className="page-contents">
{parent ? {parent ?

View File

@ -17,7 +17,7 @@ function ExtendedAttributesEdit({attributes, setAttributes, ...props}) {
}); });
} }
let newAttributes = {...attributes, const newAttributes = {...attributes,
parent: undefined, parent: undefined,
location: undefined, location: undefined,
contents: undefined, contents: undefined,

View File

@ -1,13 +1,10 @@
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useParams, useNavigate } from 'react-router-dom'; import { useParams, useNavigate } from 'react-router-dom';
import { apiUrl, fetchPage, fetchPageAttributes, postPage } from '../apiTools.jsx'; import { apiUrl, fetchPage, fetchPageAttributes, postPage, postAttributes } from '../apiTools.jsx';
import { useLoggedIn } from '../AuthProvider.jsx';
import Page from './Page.jsx'; import Page from './Page.jsx';
import ExtendedAttributes from './ExtendedAttributes.jsx'; import ExtendedAttributes from './ExtendedAttributes.jsx';
//import ExtendedAttributesEdit from './ExtendedAttributesEdit.jsx';
import { JsonEditor } from 'json-edit-react'; import { JsonEditor } from 'json-edit-react';
import './Pages.css'; import './Pages.css';
@ -15,7 +12,6 @@ import './Pages.css';
function GhostPage({editing, ...props}) { function GhostPage({editing, ...props}) {
const { pagenumber, editid } = useParams(); const { pagenumber, editid } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const loggedIn = useLoggedIn();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const fetchPageQuery = useQuery({ const fetchPageQuery = useQuery({
@ -39,7 +35,7 @@ function GhostPage({editing, ...props}) {
const [attributes, setAttributes] = useState(null); const [attributes, setAttributes] = useState(null);
useEffect(() => setAttributes(fetchAttributesQuery.data), [fetchAttributesQuery.data]); useEffect(() => setAttributes(fetchAttributesQuery.data), [fetchAttributesQuery.data]);
const postMutation = useMutation({ // for changing the value when we're done with it const pageMutation = useMutation({ // for changing the main object when we're done with it
mutationFn: postPage, mutationFn: postPage,
onSettled: async (data, error, variables) => { onSettled: async (data, error, variables) => {
// Invalidate and refetch // Invalidate and refetch
@ -48,14 +44,29 @@ function GhostPage({editing, ...props}) {
}, },
}); });
const attributesMutation = useMutation({ // for changing the attributes
mutationFn: postAttributes,
onSettled: (data, error, variables) => {
queryClient.invalidateQueries(['attributes', variables.number]);
}
})
function submitChanges(e) { function submitChanges(e) {
if (editorRef.current) { if (editorRef.current) {
postMutation.mutate({ attributesMutation.mutate({
number: pagenumber,
attributes: attributes,
});
pageMutation.mutate({
number: pagenumber, number: pagenumber,
title: title, title: title,
description: editorRef.current.getMarkdown(), description: editorRef.current.getMarkdown(),
type: type ? 1 : 0, type: type ? 1 : 0,
}); });
} else {
console.log("Tried to submit changes without a valid editor ref; not sure what's going on.");
} }
} }
@ -82,9 +93,12 @@ function GhostPage({editing, ...props}) {
<ExtendedAttributes <ExtendedAttributes
attributes={attributes} /> attributes={attributes} />
: :
<ExtendedAttributesEdit <section className="page-contents">
attributes={attributes} <JsonEditor
setAttributes={setAttributes} /> theme="githubDark"
data={attributes}
setData={setAttributes} />
</section>
} }
<button <button
onClick={() => navigate(`/${pagenumber}/history`)}> onClick={() => navigate(`/${pagenumber}/history`)}>
@ -92,9 +106,9 @@ function GhostPage({editing, ...props}) {
</button> </button>
{editing && ( {editing && (
<button <button
disabled={postMutation.isPending} disabled={pageMutation.isPending || attributesMutation.isPending}
onClick={submitChanges}> onClick={submitChanges}>
{postMutation.isPending ? "Updating..." : "Update"} {(pageMutation.isPending || attributesMutation.isPending) ? "Updating..." : "Update"}
</button>)} </button>)}
{editing && ( {editing && (
<button <button