workin like a worker bee but not keeping track of what i do

This commit is contained in:
Shoofle 2024-09-20 12:09:16 -04:00
parent 6ce4def6e5
commit 1e0eb1e831
12 changed files with 145 additions and 154 deletions

View File

@ -1,5 +1,8 @@
.App { .App {
text-align: center; text-align: center;
padding-left: 60vmin;
padding-right: 60vmin;
background-color: #282c34;
} }
.App-logo { .App-logo {
@ -14,7 +17,6 @@
} }
.App-header { .App-header {
background-color: #282c34;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -41,6 +43,8 @@
text-align: left; text-align: left;
padding: 1em; padding: 1em;
border: 1px solid black; border: 1px solid black;
width: 100%;
}
.Page-contents pre {
width: 100%;
} }

View File

@ -4,7 +4,7 @@ import './App.css';
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 { useState } from 'react'; import { useState } from 'react';
import { apiUrl, fetchPage, postPage, deletePage } from './clientStuff.jsx'; import { apiUrl, fetchPage, postPage, deletePage } from './apiTools.jsx';
function PageView() { function PageView() {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@ -56,10 +56,9 @@ function PageView() {
navigate(`/`); navigate(`/`);
} }
return ( return (
<div className="App"> <div className="App">
<header className="App-header"> <section className="App-header">
<a href="/"><img src={logo} className="App-logo" alt="logo" /></a> <a href="/"><img src={logo} className="App-logo" alt="logo" /></a>
<div className="Page-title"> <div className="Page-title">
<h3> <h3>
@ -92,7 +91,7 @@ function PageView() {
{ fetchQuery.isPending ? "Loading..." : JSON.stringify(fetchQuery.error) } { fetchQuery.isPending ? "Loading..." : JSON.stringify(fetchQuery.error) }
</div> </div>
} }
</header> </section>
</div> </div>
); );
} }

View File

@ -1,14 +1,16 @@
import logo from './logo.svg'; import logo from './logo.svg';
import './App.css'; import './App.css';
import { useNavigate } from 'react-router-dom' import { useNavigate, Link } from 'react-router-dom'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiUrl, fetchPageList, postNewPage } from './clientStuff.jsx'; import { apiUrl, fetchPageList, postNewPage } from './apiTools.jsx';
import { useFixLinks } from './clientStuff.jsx';
function Landing() { function Landing() {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const navigate = useNavigate(); const navigate = useNavigate();
const noLoad = useFixLinks();
const { isPending, error, data } = useQuery({ // fetch the currrent values const { isPending, error, data } = useQuery({ // fetch the currrent values
queryKey: ['pages'], queryKey: ['pages'],
queryFn: fetchPageList queryFn: fetchPageList
@ -38,8 +40,8 @@ function Landing() {
<ul> <ul>
{ {
data.map((row) => data.map((row) =>
<li> <li key={row}>
<a key={row} href={`/${row}`}>page {row}</a> <a href={`/${row}`} {...noLoad}>page {row}</a>
</li> </li>
) )
} }

View File

@ -4,11 +4,14 @@ import './App.css';
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 { useState } from 'react'; import { useState } from 'react';
import { apiUrl, fetchPage, postPage } from './clientStuff.jsx'; import { apiUrl, fetchPage, postPage } from './apiTools.jsx';
import { useFixLinks } from './clientStuff.jsx';
function PageView() { function PageView() {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const navigate = useNavigate(); const navigate = useNavigate();
const noLoad = useFixLinks();
const { pagenumber } = useParams(); const { pagenumber } = useParams();
const { isPending, error, data } = useQuery({ // fetch the currrent values const { isPending, error, data } = useQuery({ // fetch the currrent values
@ -24,7 +27,7 @@ function PageView() {
return ( return (
<div className="App"> <div className="App">
<header className="App-header"> <header className="App-header">
<a href="/"><img src={logo} className="App-logo" alt="logo" /></a> <a href="/" {...noLoad}><img src={logo} className="App-logo" alt="logo" /></a>
<div className="Page-title"> <div className="Page-title">
<h3>{pagenumber}. {ready ? (page_title || " ") : "..."}</h3> <h3>{pagenumber}. {ready ? (page_title || " ") : "..."}</h3>
</div> </div>
@ -32,6 +35,7 @@ function PageView() {
<div <div
className="Page-contents" className="Page-contents"
dangerouslySetInnerHTML={{ __html: (page_html || " ") }} dangerouslySetInnerHTML={{ __html: (page_html || " ") }}
{...noLoad}
/> />
: :
<div className="Page-contents"> <div className="Page-contents">

45
client/src/apiTools.jsx Normal file
View File

@ -0,0 +1,45 @@
// This is wrapper functtions to do requests to the api, from the frontend.
export const apiUrl = "http://127.0.0.1:3001"
const defaults = {
headers: {'Content-Type': 'application/json'}
};
export async function postNewPage() {
return fetch(`${apiUrl}/page/new`, {
method: 'POST',
...defaults
}).then((res) => res.json())
.then((data) => data.id)
}
export async function fetchPageList() {
return fetch(`${apiUrl}/pages`, {
method: 'GET',
...defaults
}).then((res) => res.json())
}
export async function fetchPage(id) {
return fetch(`${apiUrl}/page/${id}`, {
method: 'GET',
...defaults
}).then((res) => res.json())
}
export async function postPage({id, title, description}) {
return fetch(`${apiUrl}/page/${id}`, {
method: 'POST',
body: JSON.stringify({id: id, title: title, description: description}),
...defaults
})
}
export async function deletePage(id) {
return fetch(`${apiUrl}/page/${id}`, {
method: 'DELETE',
headers: {'Content-Type': 'application/json'},
...defaults
})
}

View File

@ -1,43 +1,14 @@
export const apiUrl = "http://127.0.0.1:3001" // New hook to make links use the react-router `navigate` method instead of default browser behavior.
const defaults = { import { useNavigate } from 'react-router-dom'
headers: {'Content-Type': 'application/json'}
};
export async function postNewPage() { export function useFixLinks() {
return fetch(`${apiUrl}/page/new`, { // spread this return value on <a/> elements in order to make them navigate
method: 'POST', const navigate = useNavigate();
...defaults return { onClick: (e) => {
}).then((res) => res.json()) if (e.target.tagName != "A") { return; }
.then((data) => data.id) if (!e.target.href.includes(window.location.origin)) { return; }
} e.preventDefault();
navigate(e.target.href.replace(window.location.origin, ""));
export async function fetchPageList() { }};
return fetch(`${apiUrl}/pages`, {
method: 'GET',
...defaults
}).then((res) => res.json())
}
export async function fetchPage(id) {
return fetch(`${apiUrl}/page/${id}`, {
method: 'GET',
...defaults
}).then((res) => res.json())
}
export async function postPage({id, title, description}) {
return fetch(`${apiUrl}/page/${id}`, {
method: 'POST',
body: JSON.stringify({id: id, title: title, description: description}),
...defaults
})
}
export async function deletePage(id) {
return fetch(`${apiUrl}/page/${id}`, {
method: 'DELETE',
headers: {'Content-Type': 'application/json'},
...defaults
})
} }

View File

@ -1 +0,0 @@
'{"statements": [{"q": ["replace into pages (id, title, description) values (?, ?, ?)", "params": [2,"main2","dummyvalue"] }], }'

View File

@ -1 +1 @@
{"id":"7de13931-444c-4dd2-a19a-5cd1e70b7f36","rows_written":109,"rows_read":1706,"storage_bytes_used":12288,"write_requests_delegated":0,"current_frame_no":108,"top_query_threshold":3,"top_queries":[{"rows_written":2,"rows_read":1,"query":"\ncreate table if not exists renders (\n id integer primary key,\n title varchar(255),\n description text\n)\n"},{"rows_written":0,"rows_read":4,"query":"select id from pages"},{"rows_written":0,"rows_read":5,"query":"select id from pages"},{"rows_written":1,"rows_read":4,"query":"\nalter table pages \nadd column html text\n"},{"rows_written":0,"rows_read":6,"query":"\nselect p.id from pages p where not exists (select r.id from renders r where p.id = r.id)\n"},{"rows_written":0,"rows_read":10,"query":"select id from pages"},{"rows_written":0,"rows_read":11,"query":"select id from pages"},{"rows_written":0,"rows_read":12,"query":"select id from pages"},{"rows_written":0,"rows_read":13,"query":"select id from pages"},{"rows_written":0,"rows_read":14,"query":"select id from pages"}],"slowest_query_threshold":0,"slowest_queries":[{"elapsed_ms":0,"query":"select id, title, description from pages where id=@val","rows_written":0,"rows_read":1},{"elapsed_ms":0,"query":"select title from pages","rows_written":0,"rows_read":1},{"elapsed_ms":0,"query":"select title from pages","rows_written":0,"rows_read":2},{"elapsed_ms":1,"query":"\nalter table pages \nadd column html text\n","rows_written":1,"rows_read":4},{"elapsed_ms":1,"query":"\ncreate table if not exists renders (\n id integer primary key,\n title varchar(255),\n description text\n)\n","rows_written":2,"rows_read":1},{"elapsed_ms":1,"query":"insert into pages (title, description) values (?, ?) returning id","rows_written":1,"rows_read":1},{"elapsed_ms":1,"query":"replace into pages (id, title, description) values (?, ?, ?)","rows_written":1,"rows_read":1},{"elapsed_ms":1,"query":"select * from pages where id=@val","rows_written":0,"rows_read":1},{"elapsed_ms":1,"query":"select count(*) as num_pages from pages","rows_written":0,"rows_read":1},{"elapsed_ms":7,"query":"replace into pages (id, title, description) values (?, ?, ?)","rows_written":1,"rows_read":1}],"embedded_replica_frames_replicated":0,"query_count":877,"query_latency":90259} {"id":"7de13931-444c-4dd2-a19a-5cd1e70b7f36","rows_written":112,"rows_read":2745,"storage_bytes_used":12288,"write_requests_delegated":0,"current_frame_no":111,"top_query_threshold":3,"top_queries":[{"rows_written":2,"rows_read":1,"query":"\ncreate table if not exists renders (\n id integer primary key,\n title varchar(255),\n description text\n)\n"},{"rows_written":0,"rows_read":4,"query":"select id from pages"},{"rows_written":0,"rows_read":5,"query":"select id from pages"},{"rows_written":1,"rows_read":4,"query":"\nalter table pages \nadd column html text\n"},{"rows_written":0,"rows_read":6,"query":"\nselect p.id from pages p where not exists (select r.id from renders r where p.id = r.id)\n"},{"rows_written":0,"rows_read":10,"query":"select id from pages"},{"rows_written":0,"rows_read":11,"query":"select id from pages"},{"rows_written":0,"rows_read":12,"query":"select id from pages"},{"rows_written":0,"rows_read":13,"query":"select id from pages"},{"rows_written":0,"rows_read":14,"query":"select id from pages"}],"slowest_query_threshold":0,"slowest_queries":[{"elapsed_ms":0,"query":"select title from pages","rows_written":0,"rows_read":1},{"elapsed_ms":0,"query":"select title from pages","rows_written":0,"rows_read":2},{"elapsed_ms":1,"query":"\nalter table pages \nadd column html text\n","rows_written":1,"rows_read":4},{"elapsed_ms":1,"query":"\ncreate table if not exists renders (\n id integer primary key,\n title varchar(255),\n description text\n)\n","rows_written":2,"rows_read":1},{"elapsed_ms":1,"query":"insert into pages (title, description) values (?, ?) returning id","rows_written":1,"rows_read":1},{"elapsed_ms":1,"query":"replace into pages (id, title, description) values (?, ?, ?)","rows_written":1,"rows_read":1},{"elapsed_ms":1,"query":"replace into pages (id, title, description, html) values (?, ?, ?, ?)","rows_written":1,"rows_read":1},{"elapsed_ms":1,"query":"select * from pages where id=@val","rows_written":0,"rows_read":1},{"elapsed_ms":1,"query":"select count(*) as num_pages from pages","rows_written":0,"rows_read":1},{"elapsed_ms":7,"query":"replace into pages (id, title, description) values (?, ?, ?)","rows_written":1,"rows_read":1}],"embedded_replica_frames_replicated":0,"query_count":1006,"query_latency":98084}

Binary file not shown.

19
server/dbHelper.js Normal file
View File

@ -0,0 +1,19 @@
// helper function(s?) to make a query to the database
const db_url = 'http://localhost:8000'
async function query(q, params) {
return fetch(db_url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
statements: [{
q: q,
params: params
}]
})
}).then((res) => res.json())
.then((data) => data[0].results);
}
module.exports = { query: query };

View File

@ -1,7 +1,7 @@
const express = require('express'); const express = require('express');
const showdown = require('showdown'); const showdown = require('showdown');
const { query } = require('./dbHelper.js');
const db_url = 'http://localhost:8000'
const port = process.env.PORT || 3001; // Use the port provided by the host or default to 3000 const port = process.env.PORT || 3001; // Use the port provided by the host or default to 3000
const app = express(); const app = express();
@ -19,93 +19,41 @@ app.listen(port, () => {
console.log(`Server listening on port ${port}`); console.log(`Server listening on port ${port}`);
}); });
// Define a route to handle incoming requests
app.post('/', (req, res) => {
res.send('Hello, Express!');
});
app.get('/pages', (req, res) => { app.get('/pages', (req, res) => {
fetch(db_url, { query('select id from pages', [])
method: 'POST', .then((r) => r.rows)
headers: {'Content-Type': 'application/json'}, .then((row) => row.map(([id]) => id))
body: JSON.stringify({ .then((ids) => res.status(200).json(ids))
statements: ['select id from pages']
})
}).then((rsp) => rsp.json())
.then((data) => data[0].results.rows)
.then((rows) => rows.map(([id]) => id))
.then((ids) => res.json(ids))
.catch((error) => res.status(500).json({"error": error})); .catch((error) => res.status(500).json({"error": error}));
}); });
app.post('/page/new', (req, res) => { app.post('/page/new', (req, res) => {
fetch(db_url, { query('insert into pages (title, description) values (?, ?) returning id',
method: 'POST', ["new page", "this page is new!"])
headers: {'Content-Type': 'application/json'}, .then((r) => r.rows[0][0])
body: JSON.stringify({
statements: [{
q: 'insert into pages (title, description) values (?, ?) returning id',
params: ["new page", "this page is new!"]
}]
})
}).then((rsp) => rsp.json())
.then((data) => data[0].results.rows[0][0])
.then((row) => res.status(200).json({id: row})) .then((row) => res.status(200).json({id: row}))
.catch((error) => res.status(500).json({"error": error})) .catch((error) => res.status(500).json({"error": error}))
}); });
app.get('/page/:id', (req, res) => { app.get('/page/:id', (req, res) => {
fetch(db_url, { query('select * from pages where id=?', [req.params.id])
method: 'POST', .then((r) => {
headers: {'Content-Type': 'application/json'}, if (r.rows.length == 0) return res.status(404).json({"error": "page not found in db"});
body: JSON.stringify({ return r.rows[0];
statements: [{
q: 'select * from pages where id=?',
params: [req.params.id]
}]
})
}).then((rsp) => rsp.json())
.then((data) => {
if (data[0].results.rows.length == 0) return res.status(404).json({"error": "page not found in db"});
return data[0].results.rows[0];
}).then((row) => res.status(200).json(row)) }).then((row) => res.status(200).json(row))
.catch((error) => res.status(500).json({"error": error})); .catch((error) => res.status(500).json({"error": error}));
}); });
app.post('/page/:id', (req, res) => { app.post('/page/:id', (req, res) => {
console.log(`got a post for /page/${req.params.id}`, req.body);
console.log(`rendering new input ${req.params.id}`);
const html = converter.makeHtml(req.body.description); const html = converter.makeHtml(req.body.description);
console.log(`the output was ${html}`) query('replace into pages (id, title, description, html) values (?, ?, ?, ?)',
[req.params.id, req.body.title, req.body.description, html])
console.log("done rendering"); .then(() => res.status(200).json({}))
fetch(db_url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
statements: [{
q: 'replace into pages (id, title, description, html) values (?, ?, ?, ?)',
params: [Number(req.params.id), req.body.title, req.body.description, html],
}]
})
}).then(() => res.status(200).json({}))
.catch((error) => res.status(500).json({"error": error})); .catch((error) => res.status(500).json({"error": error}));
}); });
app.delete('/page/:id', (req, res) => { app.delete('/page/:id', (req, res) => {
console.log(`deleting page #${req.params.id}`); query('delete from pages where id = ?', [req.params.id])
.then(() => res.status(200).json({id: req.params.id}))
fetch(db_url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
statements: [{
q: 'delete from pages where id = ?',
params: [Number(req.params.id)]
}]
})
}).then(() => res.status(200).json({id: req.params.id}))
.catch((error) => res.status(500).json({"error": error})) .catch((error) => res.status(500).json({"error": error}))
}) })