implemented backend part of progressive form

feature/modern-browsers
Inga 🏳‍🌈 2 weeks ago
parent 3c982e845f
commit 98fc37530d
  1. 2
      package-lock.json
  2. 2
      package.json
  3. 5
      src/backend/app.ts
  4. 31
      src/backend/main.tsx
  5. 11
      src/backend/progressive-form.ts
  6. 23
      src/backend/utils.ts
  7. 2
      src/frontend/static/style.css

2
package-lock.json generated

@ -9,6 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "CNPLv7", "license": "CNPLv7",
"dependencies": { "dependencies": {
"body-parser": "^1.20.3",
"express": "^4.21.1", "express": "^4.21.1",
"preact": "^10.24.3", "preact": "^10.24.3",
"preact-render-to-string": "^6.5.11" "preact-render-to-string": "^6.5.11"
@ -16,6 +17,7 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.15.0", "@eslint/js": "^9.15.0",
"@tsconfig/strictest": "^2.0.5", "@tsconfig/strictest": "^2.0.5",
"@types/body-parser": "^1.19.5",
"@types/eslint__js": "^8.42.3", "@types/eslint__js": "^8.42.3",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",

@ -19,6 +19,7 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.15.0", "@eslint/js": "^9.15.0",
"@tsconfig/strictest": "^2.0.5", "@tsconfig/strictest": "^2.0.5",
"@types/body-parser": "^1.19.5",
"@types/eslint__js": "^8.42.3", "@types/eslint__js": "^8.42.3",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
@ -32,6 +33,7 @@
"typescript-eslint": "^8.14.0" "typescript-eslint": "^8.14.0"
}, },
"dependencies": { "dependencies": {
"body-parser": "^1.20.3",
"express": "^4.21.1", "express": "^4.21.1",
"preact": "^10.24.3", "preact": "^10.24.3",
"preact-render-to-string": "^6.5.11" "preact-render-to-string": "^6.5.11"

@ -1,11 +1,14 @@
import path from "node:path"; import path from "node:path";
import bodyParser from "body-parser";
import express from "express"; import express from "express";
import { mainPageHandler } from "./main.tsx"; import { mainPageHandler } from "./main.tsx";
import { createProgressiveForm } from "./progressive-form.ts";
export const createApp = () => { export const createApp = () => {
const app = express(); const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", mainPageHandler); app.use("/", createProgressiveForm(mainPageHandler));
app.use("/frontend", express.static(path.join(import.meta.dirname, "..", "frontend"))); app.use("/frontend", express.static(path.join(import.meta.dirname, "..", "frontend")));
app.use("/shared", express.static(path.join(import.meta.dirname, "..", "shared"))); app.use("/shared", express.static(path.join(import.meta.dirname, "..", "shared")));

@ -2,7 +2,8 @@ import type { RequestHandler } from "express";
import { safeGetQueryValue, sendHtml } from "./utils.ts"; import { safeGetQueryValue, sendHtml } from "./utils.ts";
export const mainPageHandler: RequestHandler = (req, res) => { export const mainPageHandler: RequestHandler = (req, res) => {
const pageNumber = parseInt(safeGetQueryValue(req, "page") ?? "0", 10); const a = parseInt(safeGetQueryValue(req, "a") ?? "0", 10);
const b = parseInt(safeGetQueryValue(req, "b") ?? "0", 10);
sendHtml( sendHtml(
res, res,
<html> <html>
@ -18,12 +19,28 @@ export const mainPageHandler: RequestHandler = (req, res) => {
</head> </head>
<body> <body>
<p>Hello world!</p> <p>Hello world!</p>
<p> <ul>
Page number <span class="pageNumber">{pageNumber}</span> <li>
</p> Value of "a": <span class="counter">{a}</span>
<p> </li>
<a href={`?page=${pageNumber + 1}`}>Go to the next page</a> <li>
</p> Value of "b": <span class="counter">{b}</span>
</li>
</ul>
<form method="post">
<p>
<button type="submit" name={`a`} value={`${a + 1}`}>
Increase "a"
</button>
</p>
</form>
<form method="post">
<p>
<button type="submit" name={`b`} value={`${b + 1}`}>
Increase "b"
</button>
</p>
</form>
</body> </body>
</html>, </html>,
); );

@ -0,0 +1,11 @@
import express, { RequestHandler } from "express";
import { rewriteQueryParams } from "./utils.ts";
export const createProgressiveForm = (mainHandler: RequestHandler) => {
const router = express.Router();
router.get("/", mainHandler);
router.post("/", rewriteQueryParams);
return router;
};

@ -1,4 +1,4 @@
import type { Request, Response } from "express"; import type { Request, RequestHandler, Response } from "express";
import type { VNode } from "preact"; import type { VNode } from "preact";
import { render } from "preact-render-to-string"; import { render } from "preact-render-to-string";
@ -17,3 +17,24 @@ export const safeGetQueryValue = (req: Request, name: string) => {
return result || null; return result || null;
}; };
export const rewriteQueryParams: RequestHandler = (req, res) => {
const newQuery = new URLSearchParams();
for (const [param, value] of Object.entries(req.query)) {
if (typeof value === "string") {
newQuery.set(param, value);
}
}
if (req.body) {
const body = req.body as Record<string, unknown>;
for (const [param, value] of Object.entries(body)) {
if (typeof value === "string") {
newQuery.set(param, value);
}
}
}
res.redirect(`?${newQuery.toString()}`);
};

@ -1,4 +1,4 @@
.pageNumber { .counter {
font-weight: bold; font-weight: bold;
color: red; color: red;
} }

Loading…
Cancel
Save