who needs allat. maybe i want to live simply
This commit is contained in:
parent
db51f003bb
commit
776fc1b38e
@ -17,12 +17,6 @@ export default defineConfig({
|
||||
adapter: node({
|
||||
mode: "standalone",
|
||||
}),
|
||||
session: {
|
||||
driver: "localstorage",
|
||||
options: {
|
||||
base: "app:",
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
fonts: [
|
||||
{
|
||||
|
14
db/config.ts
14
db/config.ts
@ -12,19 +12,7 @@ const Guestbook = defineTable({
|
||||
},
|
||||
});
|
||||
|
||||
const Comment = defineTable({
|
||||
columns: {
|
||||
id: column.number({ primaryKey: true }),
|
||||
postId: column.text(),
|
||||
replyId: column.number(),
|
||||
username: column.text(),
|
||||
website: column.text({ optional: true }),
|
||||
comment: column.text({ multiline: true }),
|
||||
published: column.date({ default: NOW }),
|
||||
},
|
||||
});
|
||||
|
||||
// https://astro.build/db/config
|
||||
export default defineDb({
|
||||
tables: { Guestbook, Comment },
|
||||
tables: { Guestbook },
|
||||
});
|
||||
|
@ -1,21 +0,0 @@
|
||||
import { defineAction } from "astro:actions";
|
||||
import { z } from "astro:content";
|
||||
import sanitize from "sanitize-html";
|
||||
|
||||
export const comments = {
|
||||
addComment: defineAction({
|
||||
accept: "form",
|
||||
input: z.object({
|
||||
postId: z.string(),
|
||||
replyId: z.number().optional(),
|
||||
name: z.string(),
|
||||
website: z.string().url().optional(),
|
||||
comment: z.string(),
|
||||
}),
|
||||
handler: async (input) => {
|
||||
// sanitize but allow line breaks
|
||||
sanitize(input.comment);
|
||||
// post to comment server
|
||||
},
|
||||
}),
|
||||
};
|
@ -1,7 +1,6 @@
|
||||
import { ActionError, defineAction } from "astro:actions";
|
||||
import { z } from "astro:content";
|
||||
import { db, eq, Guestbook } from "astro:db";
|
||||
import bcrypt from "bcryptjs";
|
||||
import sanitize from "sanitize-html";
|
||||
|
||||
export const guestbook = {
|
||||
@ -14,6 +13,8 @@ export const guestbook = {
|
||||
}),
|
||||
handler: async ({ username, website, message }) => {
|
||||
// figure out how to add line breaks and THEN sanitize message
|
||||
const addLine = message.replaceAll("/n", "<br/>");
|
||||
sanitize(addLine);
|
||||
|
||||
const entry = await db.insert(Guestbook).values({
|
||||
username,
|
||||
@ -31,7 +32,7 @@ export const guestbook = {
|
||||
reply: z.string(),
|
||||
}),
|
||||
handler: async ({ id, reply }, context) => {
|
||||
if (!context.session?.get("pwd")) {
|
||||
if (context.url.hostname !== "127.0.0.1" || "localhost") {
|
||||
throw new ActionError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
|
||||
@ -49,27 +50,4 @@ export const guestbook = {
|
||||
return update[0];
|
||||
},
|
||||
}),
|
||||
login: defineAction({
|
||||
accept: "form",
|
||||
input: z.object({
|
||||
password: z.string(),
|
||||
}),
|
||||
handler: async ({ password }, context) => {
|
||||
// find env var here
|
||||
if (password !== "super secret password") {
|
||||
throw new ActionError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
|
||||
const hash = await bcrypt.hash(password, 10);
|
||||
context.session?.set("pwd", hash);
|
||||
return { code: 200, message: "set the thing" };
|
||||
}
|
||||
}),
|
||||
logout: defineAction({
|
||||
accept: "form",
|
||||
handler: async (_input, context) => {
|
||||
context.session?.destroy();
|
||||
return { code: 200, message: "set the thing" };
|
||||
}
|
||||
}),
|
||||
};
|
@ -1,9 +1,7 @@
|
||||
import { comments } from "./comment";
|
||||
import { contact } from "./contact";
|
||||
import { guestbook } from "./guestbook";
|
||||
|
||||
export const server = {
|
||||
comments,
|
||||
contact,
|
||||
guestbook,
|
||||
};
|
@ -12,34 +12,6 @@
|
||||
--ko-font: GulimChe, DotumChe, Gulim, Dotum, system-ui-ko, system-ui-ja, system-ui-zh-cn, system-ui-zh-tw, system-ui-zh-hk, monospace, sans-serif;
|
||||
--dotum-11-font: var(--dotumche-11), var(--dotum-11), var(--ko-font);
|
||||
--dotum-12-font: var(--dotumche-12), var(--dotum-12), var(--ko-font);
|
||||
|
||||
@media screen and (prefers-color-scheme: light) {
|
||||
--bg-color: #e6f2ef;
|
||||
--fg-color: #151640;
|
||||
--accent-color: #f783b0;
|
||||
--secondary-color: #3f6d9e;
|
||||
}
|
||||
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
--bg-color: #555568;
|
||||
--fg-color: #f3eded;
|
||||
--accent-color: #eeb9c7;
|
||||
--secondary-color: #b9eedc;
|
||||
}
|
||||
}
|
||||
|
||||
.light {
|
||||
--bg-color: #e6f2ef;
|
||||
--fg-color: #151640;
|
||||
--accent-color: #f783b0;
|
||||
--secondary-color: #3f6d9e;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--bg-color: #555568;
|
||||
--fg-color: #f3eded;
|
||||
--accent-color: #eeb9c7;
|
||||
--secondary-color: #b9eedc;
|
||||
}
|
||||
|
||||
body {
|
||||
@ -125,21 +97,3 @@ button, .button {
|
||||
box-shadow: 0 0 0 var(--fg-color);
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
button, .button {
|
||||
background-color: var(--accent-color);
|
||||
color: var(--bg-color);
|
||||
|
||||
&:hover {
|
||||
background-color: hsl(from var(--accent-color) h s calc(l - 10));
|
||||
color: var(--bg-color);
|
||||
}
|
||||
|
||||
&:active, &:focus {
|
||||
color: var(--bg-color);
|
||||
background-color: var(--secondary-color);
|
||||
border-color: var(--bg-color);
|
||||
}
|
||||
}
|
||||
}
|
50
src/assets/styles/themes.css
Normal file
50
src/assets/styles/themes.css
Normal file
@ -0,0 +1,50 @@
|
||||
:root {
|
||||
@media screen and (prefers-color-scheme: light) {
|
||||
--bg-color: #e6f2ef;
|
||||
--fg-color: #151640;
|
||||
--accent-color: #f783b0;
|
||||
--secondary-color: #3f6d9e;
|
||||
}
|
||||
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
--bg-color: #555568;
|
||||
--fg-color: #f3eded;
|
||||
--accent-color: #eeb9c7;
|
||||
--secondary-color: #b9eedc;
|
||||
}
|
||||
}
|
||||
|
||||
.light {
|
||||
--bg-color: #e6f2ef;
|
||||
--fg-color: #151640;
|
||||
--accent-color: #f783b0;
|
||||
--secondary-color: #3f6d9e;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--bg-color: #555568;
|
||||
--fg-color: #f3eded;
|
||||
--accent-color: #eeb9c7;
|
||||
--secondary-color: #b9eedc;
|
||||
}
|
||||
|
||||
/* custom theme styling */
|
||||
|
||||
/* dark-specific styles */
|
||||
.dark {
|
||||
button, .button {
|
||||
background-color: var(--accent-color);
|
||||
color: var(--bg-color);
|
||||
|
||||
&:hover {
|
||||
background-color: hsl(from var(--accent-color) h s calc(l - 10));
|
||||
color: var(--bg-color);
|
||||
}
|
||||
|
||||
&:active, &:focus {
|
||||
color: var(--bg-color);
|
||||
background-color: var(--secondary-color);
|
||||
border-color: var(--bg-color);
|
||||
}
|
||||
}
|
||||
}
|
3
src/env.d.ts
vendored
3
src/env.d.ts
vendored
@ -1,3 +0,0 @@
|
||||
interface Window {
|
||||
Alpine: import("alpinejs").Alpine;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
import "$/styles/base.css";
|
||||
import "$/styles/themes.css";
|
||||
import { Font } from "astro:assets";
|
||||
|
||||
interface Props { title?: string; }
|
||||
@ -11,7 +12,6 @@ const { title = "haetae" }: Props = Astro.props;
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<meta name="pinterest" content="nopin nohover" />
|
||||
<meta name="robots" content="noai, noimageai" />
|
||||
<Font cssVariable="--sq" preload />
|
||||
|
@ -3,19 +3,20 @@ export const prerender = false;
|
||||
|
||||
import { actions } from "astro:actions";
|
||||
import { db, desc, Guestbook } from "astro:db";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import formatDate from "@/utils/formatDate";
|
||||
|
||||
const pwd = await Astro.session?.get("pwd");
|
||||
|
||||
if (!pwd) {
|
||||
const fromUrl = Astro.url.pathname + Astro.url.search;
|
||||
return Astro.redirect(`/guestbook/login?redirect=${fromUrl}`);
|
||||
if (!import.meta.env.DEV) {
|
||||
console.error("you shouldn't be here...");
|
||||
return Astro.redirect("/guestbook");
|
||||
}
|
||||
|
||||
const entries = await db.select().from(Guestbook).orderBy(desc(Guestbook.published));
|
||||
---
|
||||
<h1>entries</h1>
|
||||
<Layout title="guestbook admin">
|
||||
<h1>entries</h1>
|
||||
|
||||
<section>
|
||||
<section>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -33,7 +34,7 @@ const entries = await db.select().from(Guestbook).orderBy(desc(Guestbook.publish
|
||||
<td>{entry.username}</td>
|
||||
<td>{entry.website}</td>
|
||||
<td>{entry.message}</td>
|
||||
<td>{entry.published}</td>
|
||||
<td>{formatDate(entry.published, false, 'MMMM D, YYYY')}</td>
|
||||
<td>{entry.reply}</td>
|
||||
<td><button class="edit">edit</button></td>
|
||||
</tr>
|
||||
@ -43,7 +44,7 @@ const entries = await db.select().from(Guestbook).orderBy(desc(Guestbook.publish
|
||||
|
||||
<dialog id="edit-entry">
|
||||
<form id="edit-entry-form" action={actions.guestbook.reply} method="post">
|
||||
<input type="hidden" name="id" value="" />
|
||||
<input type="hidden" name="id" id="entryId" value="" />
|
||||
<p id="entry-username"></p>
|
||||
<p id="entry-website"></p>
|
||||
<div id="entry-message"></div>
|
||||
@ -54,11 +55,19 @@ const entries = await db.select().from(Guestbook).orderBy(desc(Guestbook.publish
|
||||
<button type="submit">Reply</button>
|
||||
</form>
|
||||
</dialog>
|
||||
</section>
|
||||
</section>
|
||||
</Layout>
|
||||
|
||||
<form action={actions.guestbook.logout} method="post">
|
||||
<button type="submit">logout</button>
|
||||
</form>
|
||||
<style>
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
|
||||
td {
|
||||
max-width: 30ch;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const modal = document.getElementById("edit-entry") as HTMLDialogElement;
|
||||
@ -70,7 +79,7 @@ const entries = await db.select().from(Guestbook).orderBy(desc(Guestbook.publish
|
||||
const data = row.cells;
|
||||
const fields = document.querySelectorAll("[id^='entry-']");
|
||||
|
||||
(document.getElementById("id") as HTMLInputElement).value = id;
|
||||
(document.getElementById("entryId") as HTMLInputElement).value = id;
|
||||
fields.forEach((field, i) => {
|
||||
field.innerHTML = data.item(i)!.innerText;
|
||||
});
|
||||
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
export const prerender = false;
|
||||
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
if (Astro.request.method === "POST") {
|
||||
const form = await Astro.request.formData();
|
||||
const pwd = form.get("password");
|
||||
|
||||
if (pwd) {
|
||||
const hashed = bcrypt.hashSync(pwd.toString(), 10);
|
||||
Astro.session?.set("pwd", hashed);
|
||||
return Astro.redirect("/guestbook/admin");
|
||||
}
|
||||
}
|
||||
---
|
Loading…
x
Reference in New Issue
Block a user