Add create file table, insert first user, fully port to tailwind

This commit is contained in:
2024-11-19 21:45:10 +01:00
parent 63de1a3b02
commit 5f0b8a69d3
10 changed files with 114 additions and 147 deletions

View File

@@ -1,7 +1,7 @@
import { AttachmentId, PieceId, RequestId, SessionId, Sha256, UserId } from "common";
import { ColumnType, CompiledQuery, CreateTableBuilder, Insertable, Kysely, Selectable, sql, Updateable } from "kysely";
import { BunSqliteDialect } from "kysely-bun-sqlite";
import { Database as BunSqliteDatabase } from "bun:sqlite";
import { AttachmentId, PieceId, RequestId, SessionId, Sha256, UserId } from "common";
import { ColumnType, CompiledQuery, CreateTableBuilder, Kysely } from "kysely";
import { BunSqliteDialect } from "kysely-bun-sqlite";
export function generateSessionId(byteLength: number = 32): SessionId {
const array = new Uint8Array(byteLength);
@@ -112,6 +112,13 @@ export async function initDatabase(filename: string = "db.sqlite3"): Promise<Kys
.column("timestamp")
.execute();
await db.schema
.createTable("File")
.ifNotExists()
.addColumn("sha256", "blob", (c) => c.notNull().primaryKey())
.addColumn("data", "blob", (c) => c.notNull())
.execute();
await db.schema
.createTable("User")
.ifNotExists()
@@ -152,11 +159,28 @@ export async function initDatabase(filename: string = "db.sqlite3"): Promise<Kys
.ifNotExists()
.addColumn("attachmentId", "text", (c) => c.notNull().primaryKey())
.addColumn("pieceId", "text", (c) => c.notNull().references("Piece.pieceId").onDelete("cascade").onUpdate("cascade"))
.addColumn("sha256", "blob", (c) => c.notNull())
.addColumn("sha256", "blob", (c) => c.notNull().references("File.sha256").onDelete("restrict").onUpdate("restrict"))
.addColumn("filename", "text", (c) => c.notNull())
.addColumn("mediaType", "text", (c) => c.notNull())
.$call(systemInformation)
.execute();
const { count } = await db
.selectFrom("User")
.select((eb) => eb.fn.countAll().as("count"))
.executeTakeFirstOrThrow();
if (BigInt(count) === 0n) {
const userId = UserId(Bun.randomUUIDv7());
const username = "admin";
const password = await Bun.password.hash("admin");
const admin = 1;
await db
.insertInto("User")
.values({ userId, username, password, admin })
.execute();
}
return db;
}

View File

@@ -1,9 +1,9 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { Home } from "./routes/Home";
import { Login } from "./routes/Login";
import { createRoot } from "react-dom/client";
import { StrictMode } from "react";
import "./style.css";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
const router = createBrowserRouter([
{

View File

@@ -1,4 +1,4 @@
import { treaty } from "@elysiajs/eden";
import type { App } from "backend/app";
export const client = treaty<App>("localhost:3000");
export const client = treaty<App>("localhost:3000", { fetch: { credentials: "include" } });

View File

@@ -1,59 +0,0 @@
export const logout = {
padding: 8,
backgroundColor: "#C0C0C0",
borderWidth: 2,
borderStyle: "solid",
borderTopColor: "#E0E0E0",
borderLeftColor: "#E0E0E0",
borderRightColor: "#404040",
borderBottomColor: "#404040",
borderRadius: 4,
cursor: "pointer",
"selectors": {
"&:focus": {
outlineWidth: 2,
outlineStyle: "solid",
outlineColor: "#8080FF",
"@media": {
"(prefers-color-scheme: dark)": {
outlineColor: "#C0C0FF",
},
},
},
"&:active": {
borderTopColor: "#404040",
borderLeftColor: "#404040",
borderRightColor: "#E0E0E0",
borderBottomColor: "#E0E0E0",
"@media": {
"(prefers-color-scheme: dark)": {
outlineColor: "#C0C0FF",
borderTopColor: "#202020",
borderLeftColor: "#202020",
borderRightColor: "#606060",
borderBottomColor: "#606060",
},
},
},
},
"@media": {
"(prefers-color-scheme: dark)": {
backgroundColor: "#404040",
borderTopColor: "#606060",
borderLeftColor: "#606060",
borderRightColor: "#202020",
borderBottomColor: "#202020",
},
},
};

View File

@@ -2,8 +2,9 @@ import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { client } from "../client";
import { useStore } from "../store";
import { Button } from "../styled/Button";
export const Home = () => {
export function Home() {
const navigate = useNavigate();
@@ -28,7 +29,7 @@ export const Home = () => {
}, []);
const onLogoutClick = async () => {
const { data, error } = await client.logout.post();
const { error } = await client.logout.post();
if (error !== null) {
console.error("Response was not ok");
@@ -53,15 +54,11 @@ export const Home = () => {
Użytkownik: {user.username}
</div>
<div>
<button
className="p-2 bg-stone-300 border-2 border-t-stone-200 border-l-stone-200 border-r-stone-600 border-b-stone-600 rounded"
type="button"
onClick={onLogoutClick}
>
<Button type="button" onClick={onLogoutClick}>
Wyloguj się
</button>
</Button>
</div>
</div>
</div>
);
};
}

View File

@@ -1,59 +0,0 @@
export const submit = {
padding: 8,
backgroundColor: "#C0C0C0",
borderWidth: 2,
borderStyle: "solid",
borderTopColor: "#E0E0E0",
borderLeftColor: "#E0E0E0",
borderRightColor: "#404040",
borderBottomColor: "#404040",
borderRadius: 4,
cursor: "pointer",
"selectors": {
"&:focus": {
outlineWidth: 2,
outlineStyle: "solid",
outlineColor: "#8080FF",
"@media": {
"(prefers-color-scheme: dark)": {
outlineColor: "#C0C0FF",
},
},
},
"&:active": {
borderTopColor: "#404040",
borderLeftColor: "#404040",
borderRightColor: "#E0E0E0",
borderBottomColor: "#E0E0E0",
"@media": {
"(prefers-color-scheme: dark)": {
outlineColor: "#C0C0FF",
borderTopColor: "#202020",
borderLeftColor: "#202020",
borderRightColor: "#606060",
borderBottomColor: "#606060",
},
},
},
},
"@media": {
"(prefers-color-scheme: dark)": {
backgroundColor: "#404040",
borderTopColor: "#606060",
borderLeftColor: "#606060",
borderRightColor: "#202020",
borderBottomColor: "#202020",
},
},
});

View File

@@ -2,8 +2,10 @@ import { FormEventHandler, useId } from "react";
import { useNavigate } from "react-router-dom";
import { client } from "../client";
import { useStore } from "../store";
import { Button } from "../styled/Button";
import { Input } from "../styled/Input";
export const Login = () => {
export function Login() {
const navigate = useNavigate();
@@ -43,9 +45,8 @@ export const Login = () => {
<form className="p-2 flex flex-col gap-2 border border-black rounded dark:border-white" onSubmit={onSubmit}>
<header className="pb-2 border-b border-black text-center font-bold dark:border-white">Repozytorium muzyczne</header>
<label htmlFor={usernameId}>Nazwa użytkownika</label>
<input
<Input
id={usernameId}
className="w-[32ch] p-2 bg-transparent border border-black rounded focus:outline focus:outline-2 focus:outline-sky-500 focus:dark:outline-sky-200 dark:border-white"
type="text"
value={loginUsername}
autoFocus
@@ -53,21 +54,17 @@ export const Login = () => {
onInput={(e) => setLoginUsername(e.currentTarget.value)}
/>
<label htmlFor={passwordId}>Hasło</label>
<input
<Input
id={passwordId}
className="w-[32ch] p-2 bg-transparent border border-black rounded focus:outline focus:outline-2 focus:outline-sky-500 focus:dark:outline-sky-200 dark:border-white"
type="password"
value={loginPassword}
required
onInput={(e) => setLoginPassword(e.currentTarget.value)}
/>
<button
className="p-2 bg-stone-300 border-2 border-t-stone-200 border-l-stone-200 border-r-stone-600 border-b-stone-600 rounded dark:bg-stone-700 dark:border-t-stone-600 dark:border-l-stone-600 dark:border-r-stone-900 dark:border-b-stone-900"
type="submit"
>
<Button type="submit">
Zaloguj się
</button>
</Button>
</form>
</div>
);
};
}

View File

@@ -0,0 +1,41 @@
import { ButtonHTMLAttributes, DetailedHTMLProps } from "react";
export namespace Button {
export type Props = Omit<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "className">;
}
export function Button({ children, ...props }: Button.Props) {
return (
<button
{...props}
className="
p-2
bg-stone-300
border-2
border-t-stone-200
border-l-stone-200
border-r-stone-600
border-b-stone-600
active:border-t-stone-600
active:border-l-stone-600
active:border-r-stone-200
active:border-b-stone-200
rounded
focus:outline
focus:outline-2
focus:outline-red-500
dark:bg-stone-700
dark:border-t-stone-600
dark:border-l-stone-600
dark:border-r-stone-900
dark:border-b-stone-900
dark:active:border-t-stone-900
dark:active:border-l-stone-900
dark:active:border-r-stone-600
dark:active:border-b-stone-600
"
>
{children}
</button>
);
}

View File

@@ -0,0 +1,27 @@
import { DetailedHTMLProps, InputHTMLAttributes } from "react";
export namespace Input {
export type Props = Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "className">;
}
export function Input({ children, ...props }: Input.Props) {
return (
<input
{...props}
className="
w-[32ch]
p-2
bg-transparent
border
border-black
rounded
focus:outline
focus:outline-2
focus:outline-red-500
dark:border-white
"
>
{children}
</input>
);
}

View File

@@ -5,6 +5,5 @@
{ "path": "packages/backend" },
{ "path": "packages/common" },
{ "path": "packages/frontend" },
{ "path": "packages/make-api" },
],
}