Balance is restored, and we have an external json editor
This commit is contained in:
parent
eb75c859f2
commit
0b82c15afe
@ -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`;
|
||||||
|
|
||||||
@ -61,6 +61,13 @@ export async function postPage({number, title, description, 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) {
|
||||||
return shoofetch(`${apiUrl}/page/${id}`, {method: 'DELETE'});
|
return shoofetch(`${apiUrl}/page/${id}`, {method: 'DELETE'});
|
||||||
}
|
}
|
||||||
|
@ -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,13 +90,15 @@ function Live({...props}) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function saveChanges() {
|
function saveChanges() {
|
||||||
|
if (editorRef.current) {
|
||||||
postMutation.mutate({
|
postMutation.mutate({
|
||||||
number: currentNumber,
|
number: currentNumber,
|
||||||
title: title,
|
title: title,
|
||||||
description: text,
|
description: editorRef.current.getMarkdown(),
|
||||||
type: type ? 1 : 0,
|
type: type ? 1 : 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleSubmitCommand() {
|
function handleSubmitCommand() {
|
||||||
const c = command.trim();
|
const c = command.trim();
|
||||||
@ -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} />
|
||||||
|
{editing ?
|
||||||
|
<section className="page-contents">
|
||||||
|
<JsonEditor
|
||||||
|
theme="githubDark"
|
||||||
|
data={attributes}
|
||||||
|
setData={setAttributes} />
|
||||||
|
</section>
|
||||||
|
:
|
||||||
<ExtendedAttributes
|
<ExtendedAttributes
|
||||||
attributes={fetchAttributesQuery.data} />
|
attributes={attributes} />
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<MessageFeed messages={messageHistory}>
|
<MessageFeed messages={messageHistory}>
|
||||||
<button disabled={connecting} onClick={() => setConnecting(true)}>
|
<button disabled={connecting} onClick={() => setConnecting(true)}>
|
||||||
|
@ -2,25 +2,20 @@ 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">
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user