add a bunch of frontend stuff
This commit is contained in:
parent
2586161abd
commit
bc85b7c340
30 changed files with 1459 additions and 136 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"useTabs": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"singleQuote": false
|
||||||
|
}
|
19
assets/scss/_variables.scss
Normal file
19
assets/scss/_variables.scss
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
:root {
|
||||||
|
--dark-background: #2B303A;
|
||||||
|
--light-background: #F5F5F5;
|
||||||
|
|
||||||
|
--dark-text: #FFFFFF;
|
||||||
|
--light-text: #000000;
|
||||||
|
|
||||||
|
--dark-primary: #087E8B;
|
||||||
|
--light-primary: #67AEB5;
|
||||||
|
|
||||||
|
--dark-secondary: #7C7F85;
|
||||||
|
--light-secondary: #A4A6AA;
|
||||||
|
|
||||||
|
--dark-danger: #D64933;
|
||||||
|
--light-danger: #FF5A5F;
|
||||||
|
|
||||||
|
--dark-success: #4DA167;
|
||||||
|
--light-success: #77B68B;
|
||||||
|
}
|
26
assets/scss/style.scss
Normal file
26
assets/scss/style.scss
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
@use "node_modules/normalize.css/normalize";
|
||||||
|
@use "_variables";
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
background-color: var(--light-background);
|
||||||
|
color: var(--light-text);
|
||||||
|
|
||||||
|
&:dark {
|
||||||
|
background-color: var(--dark-background);
|
||||||
|
color: var(--dark-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth {
|
||||||
|
width: 100%;
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
max-width: 520px;
|
||||||
|
}
|
||||||
|
margin: 1rem auto;
|
||||||
|
|
||||||
|
p {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,10 @@ func run(c *cli.Context) error {
|
||||||
return errors.Wrap(err, "creating postgres database")
|
return errors.Wrap(err, "creating postgres database")
|
||||||
}
|
}
|
||||||
|
|
||||||
a := app.NewApp(cfg, db)
|
a, err := app.NewApp(cfg, db)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "creating app")
|
||||||
|
}
|
||||||
|
|
||||||
log.Debug().Msg("Creating account")
|
log.Debug().Msg("Creating account")
|
||||||
acct, err := a.Account().CreateLocal(c.Context, "testington", "no@mercury.example", []byte("password"))
|
acct, err := a.Account().CreateLocal(c.Context, "testington", "no@mercury.example", []byte("password"))
|
||||||
|
|
|
@ -39,7 +39,10 @@ func run(c *cli.Context) error {
|
||||||
return errors.Wrap(err, "creating postgres database")
|
return errors.Wrap(err, "creating postgres database")
|
||||||
}
|
}
|
||||||
|
|
||||||
a := app.NewApp(cfg, db)
|
a, err := app.NewApp(cfg, db)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "creating app")
|
||||||
|
}
|
||||||
|
|
||||||
log.Debug().Msg("Mounting routes")
|
log.Debug().Msg("Mounting routes")
|
||||||
web.Routes(a)
|
web.Routes(a)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + Svelte + TS</title>
|
<title>Vite + Svelte + TS</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
{
|
{
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"check": "svelte-check --tsconfig ./tsconfig.json"
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
||||||
"@tsconfig/svelte": "^5.0.0",
|
"@tsconfig/svelte": "^5.0.0",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"svelte": "^4.0.5",
|
"sass": "^1.66.1",
|
||||||
"svelte-check": "^3.4.6",
|
"svelte": "^4.0.5",
|
||||||
"tslib": "^2.6.0",
|
"svelte-check": "^3.4.6",
|
||||||
"typescript": "^5.0.2",
|
"tslib": "^2.6.0",
|
||||||
"vite": "^4.4.5"
|
"typescript": "^5.0.2",
|
||||||
}
|
"vite": "^4.4.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"normalize.css": "^8.0.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
lockfileVersion: "6.0"
|
lockfileVersion: "6.0"
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
normalize.css:
|
||||||
|
specifier: ^8.0.1
|
||||||
|
version: 8.0.1
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
"@sveltejs/vite-plugin-svelte":
|
"@sveltejs/vite-plugin-svelte":
|
||||||
specifier: ^2.4.2
|
specifier: ^2.4.2
|
||||||
|
@ -10,12 +15,15 @@ devDependencies:
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.0.3
|
specifier: ^3.0.3
|
||||||
version: 3.0.3
|
version: 3.0.3
|
||||||
|
sass:
|
||||||
|
specifier: ^1.66.1
|
||||||
|
version: 1.66.1
|
||||||
svelte:
|
svelte:
|
||||||
specifier: ^4.0.5
|
specifier: ^4.0.5
|
||||||
version: 4.0.5
|
version: 4.0.5
|
||||||
svelte-check:
|
svelte-check:
|
||||||
specifier: ^3.4.6
|
specifier: ^3.4.6
|
||||||
version: 3.4.6(svelte@4.0.5)
|
version: 3.4.6(sass@1.66.1)(svelte@4.0.5)
|
||||||
tslib:
|
tslib:
|
||||||
specifier: ^2.6.0
|
specifier: ^2.6.0
|
||||||
version: 2.6.0
|
version: 2.6.0
|
||||||
|
@ -24,7 +32,7 @@ devDependencies:
|
||||||
version: 5.0.2
|
version: 5.0.2
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.4.5
|
specifier: ^4.4.5
|
||||||
version: 4.4.5
|
version: 4.4.5(sass@1.66.1)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
/@ampproject/remapping@2.2.1:
|
/@ampproject/remapping@2.2.1:
|
||||||
|
@ -391,7 +399,7 @@ packages:
|
||||||
"@sveltejs/vite-plugin-svelte": 2.4.2(svelte@4.0.5)(vite@4.4.5)
|
"@sveltejs/vite-plugin-svelte": 2.4.2(svelte@4.0.5)(vite@4.4.5)
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
svelte: 4.0.5
|
svelte: 4.0.5
|
||||||
vite: 4.4.5
|
vite: 4.4.5(sass@1.66.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -413,7 +421,7 @@ packages:
|
||||||
magic-string: 0.30.3
|
magic-string: 0.30.3
|
||||||
svelte: 4.0.5
|
svelte: 4.0.5
|
||||||
svelte-hmr: 0.15.3(svelte@4.0.5)
|
svelte-hmr: 0.15.3(svelte@4.0.5)
|
||||||
vite: 4.4.5
|
vite: 4.4.5(sass@1.66.1)
|
||||||
vitefu: 0.2.4(vite@4.4.5)
|
vitefu: 0.2.4(vite@4.4.5)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -747,6 +755,13 @@ packages:
|
||||||
}
|
}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/immutable@4.3.4:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==,
|
||||||
|
}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/import-fresh@3.3.0:
|
/import-fresh@3.3.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -947,6 +962,13 @@ packages:
|
||||||
engines: { node: ">=0.10.0" }
|
engines: { node: ">=0.10.0" }
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/normalize.css@8.0.1:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==,
|
||||||
|
}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/once@1.4.0:
|
/once@1.4.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -1106,6 +1128,19 @@ packages:
|
||||||
rimraf: 2.7.1
|
rimraf: 2.7.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/sass@1.66.1:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==,
|
||||||
|
}
|
||||||
|
engines: { node: ">=14.0.0" }
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
chokidar: 3.5.3
|
||||||
|
immutable: 4.3.4
|
||||||
|
source-map-js: 1.0.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/sorcery@0.11.0:
|
/sorcery@0.11.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
@ -1137,7 +1172,7 @@ packages:
|
||||||
min-indent: 1.0.1
|
min-indent: 1.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/svelte-check@3.4.6(svelte@4.0.5):
|
/svelte-check@3.4.6(sass@1.66.1)(svelte@4.0.5):
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha512-OBlY8866Zh1zHQTkBMPS6psPi7o2umTUyj6JWm4SacnIHXpWFm658pG32m3dKvKFL49V4ntAkfFHKo4ztH07og==,
|
integrity: sha512-OBlY8866Zh1zHQTkBMPS6psPi7o2umTUyj6JWm4SacnIHXpWFm658pG32m3dKvKFL49V4ntAkfFHKo4ztH07og==,
|
||||||
|
@ -1153,7 +1188,7 @@ packages:
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
sade: 1.8.1
|
sade: 1.8.1
|
||||||
svelte: 4.0.5
|
svelte: 4.0.5
|
||||||
svelte-preprocess: 5.0.4(svelte@4.0.5)(typescript@5.2.2)
|
svelte-preprocess: 5.0.4(sass@1.66.1)(svelte@4.0.5)(typescript@5.2.2)
|
||||||
typescript: 5.2.2
|
typescript: 5.2.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- "@babel/core"
|
- "@babel/core"
|
||||||
|
@ -1179,7 +1214,7 @@ packages:
|
||||||
svelte: 4.0.5
|
svelte: 4.0.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/svelte-preprocess@5.0.4(svelte@4.0.5)(typescript@5.2.2):
|
/svelte-preprocess@5.0.4(sass@1.66.1)(svelte@4.0.5)(typescript@5.2.2):
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==,
|
integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==,
|
||||||
|
@ -1223,6 +1258,7 @@ packages:
|
||||||
"@types/pug": 2.0.6
|
"@types/pug": 2.0.6
|
||||||
detect-indent: 6.1.0
|
detect-indent: 6.1.0
|
||||||
magic-string: 0.27.0
|
magic-string: 0.27.0
|
||||||
|
sass: 1.66.1
|
||||||
sorcery: 0.11.0
|
sorcery: 0.11.0
|
||||||
strip-indent: 3.0.0
|
strip-indent: 3.0.0
|
||||||
svelte: 4.0.5
|
svelte: 4.0.5
|
||||||
|
@ -1286,7 +1322,7 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite@4.4.5:
|
/vite@4.4.5(sass@1.66.1):
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha512-4m5kEtAWHYr0O1Fu7rZp64CfO1PsRGZlD3TAB32UmQlpd7qg15VF7ROqGN5CyqN7HFuwr7ICNM2+fDWRqFEKaA==,
|
integrity: sha512-4m5kEtAWHYr0O1Fu7rZp64CfO1PsRGZlD3TAB32UmQlpd7qg15VF7ROqGN5CyqN7HFuwr7ICNM2+fDWRqFEKaA==,
|
||||||
|
@ -1320,6 +1356,7 @@ packages:
|
||||||
esbuild: 0.18.20
|
esbuild: 0.18.20
|
||||||
postcss: 8.4.29
|
postcss: 8.4.29
|
||||||
rollup: 3.28.1
|
rollup: 3.28.1
|
||||||
|
sass: 1.66.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -1335,7 +1372,7 @@ packages:
|
||||||
vite:
|
vite:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 4.4.5
|
vite: 4.4.5(sass@1.66.1)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/wrappy@1.0.2:
|
/wrappy@1.0.2:
|
||||||
|
|
|
@ -1,80 +1,80 @@
|
||||||
:root {
|
:root {
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
color: rgba(255, 255, 255, 0.87);
|
color: rgba(255, 255, 255, 0.87);
|
||||||
background-color: #242424;
|
background-color: #242424;
|
||||||
|
|
||||||
font-synthesis: none;
|
font-synthesis: none;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #646cff;
|
color: #646cff;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #535bf2;
|
color: #535bf2;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 3.2em;
|
font-size: 3.2em;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
padding: 2em;
|
padding: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
max-width: 1280px;
|
max-width: 1280px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
padding: 0.6em 1.2em;
|
padding: 0.6em 1.2em;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
background-color: #1a1a1a;
|
background-color: #1a1a1a;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: border-color 0.25s;
|
transition: border-color 0.25s;
|
||||||
}
|
}
|
||||||
button:hover {
|
button:hover {
|
||||||
border-color: #646cff;
|
border-color: #646cff;
|
||||||
}
|
}
|
||||||
button:focus,
|
button:focus,
|
||||||
button:focus-visible {
|
button:focus-visible {
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
outline: 4px auto -webkit-focus-ring-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
:root {
|
:root {
|
||||||
color: #213547;
|
color: #213547;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #747bff;
|
color: #747bff;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import "./app.css";
|
||||||
import App from "./App.svelte";
|
import App from "./App.svelte";
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: document.getElementById("app"),
|
target: document.getElementById("app"),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
||||||
// for more information about preprocessors
|
// for more information about preprocessors
|
||||||
preprocess: vitePreprocess(),
|
preprocess: vitePreprocess(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
{
|
{
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
/**
|
/**
|
||||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||||
* Disable checkJs if you'd like to use dynamic types in JS.
|
* Disable checkJs if you'd like to use dynamic types in JS.
|
||||||
* Note that setting allowJs false does not prevent the use
|
* Note that setting allowJs false does not prevent the use
|
||||||
* of JS in `.svelte` files.
|
* of JS in `.svelte` files.
|
||||||
*/
|
*/
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"isolatedModules": true
|
"isolatedModules": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
|
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "bundler"
|
"moduleResolution": "bundler"
|
||||||
},
|
},
|
||||||
"include": ["vite.config.ts"]
|
"include": ["vite.config.ts"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [svelte()],
|
plugins: [svelte()],
|
||||||
build: {
|
build: {
|
||||||
manifest: "manifest.json",
|
manifest: "manifest.json",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -5,6 +5,7 @@ go 1.19
|
||||||
require (
|
require (
|
||||||
emperror.dev/errors v0.8.1
|
emperror.dev/errors v0.8.1
|
||||||
github.com/BurntSushi/toml v1.2.1
|
github.com/BurntSushi/toml v1.2.1
|
||||||
|
github.com/flosch/pongo2/v6 v6.0.0
|
||||||
github.com/georgysavva/scany/v2 v2.0.0
|
github.com/georgysavva/scany/v2 v2.0.0
|
||||||
github.com/go-chi/chi/v5 v5.0.8
|
github.com/go-chi/chi/v5 v5.0.8
|
||||||
github.com/go-chi/render v1.0.2
|
github.com/go-chi/render v1.0.2
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -102,6 +102,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
|
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
|
||||||
|
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
|
||||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
|
16
package.json
Normal file
16
package.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "mercury",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"watch:style": "sass -I . -w assets/scss/:web/frontend/assets/css/ --style compressed"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "sam <sam@sleepycat.moe>",
|
||||||
|
"license": "APGL-3.0-only",
|
||||||
|
"devDependencies": {
|
||||||
|
"normalize.css": "^8.0.1",
|
||||||
|
"sass": "^1.66.1"
|
||||||
|
}
|
||||||
|
}
|
1028
pnpm-lock.yaml
Normal file
1028
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
3
pnpm-workspace.yaml
Normal file
3
pnpm-workspace.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
packages:
|
||||||
|
- .
|
||||||
|
- frontend
|
|
@ -1,8 +1,11 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"emperror.dev/errors"
|
||||||
"git.sleepycat.moe/sam/mercury/config"
|
"git.sleepycat.moe/sam/mercury/config"
|
||||||
"git.sleepycat.moe/sam/mercury/internal/database/sql"
|
"git.sleepycat.moe/sam/mercury/internal/database/sql"
|
||||||
|
"git.sleepycat.moe/sam/mercury/web/templates"
|
||||||
|
"github.com/flosch/pongo2/v6"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
)
|
)
|
||||||
|
@ -12,19 +15,27 @@ type App struct {
|
||||||
|
|
||||||
Config config.Config
|
Config config.Config
|
||||||
Database *sql.Base
|
Database *sql.Base
|
||||||
|
|
||||||
|
tmpl *pongo2.TemplateSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApp(cfg config.Config, db *sql.Base) *App {
|
func NewApp(cfg config.Config, db *sql.Base) (*App, error) {
|
||||||
app := &App{
|
app := &App{
|
||||||
Router: chi.NewRouter(),
|
Router: chi.NewRouter(),
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Database: db,
|
Database: db,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tmpl, err := templates.New(cfg.Core.Dev)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "creating templates")
|
||||||
|
}
|
||||||
|
app.tmpl = tmpl
|
||||||
|
|
||||||
app.Router.Use(app.Logger)
|
app.Router.Use(app.Logger)
|
||||||
app.Router.Use(middleware.Recoverer)
|
app.Router.Use(middleware.Recoverer)
|
||||||
|
|
||||||
return app
|
return app, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) Account(q ...sql.Querier) *sql.AccountStore {
|
func (a *App) Account(q ...sql.Querier) *sql.AccountStore {
|
||||||
|
|
52
web/app/template.go
Normal file
52
web/app/template.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/flosch/pongo2/v6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (app *App) Template(w http.ResponseWriter, r *http.Request, tmplName string, ctx pongo2.Context) error {
|
||||||
|
tmpl, err := app.tmpl.FromCache(tmplName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tctx := pongo2.Context{
|
||||||
|
"flash_message": app.getFlash(w, r),
|
||||||
|
}
|
||||||
|
tctx.Update(ctx)
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "text/html")
|
||||||
|
return tmpl.ExecuteWriter(tctx, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
const flashCookieName = "mercury-flash-message"
|
||||||
|
|
||||||
|
func (app *App) Flash(w http.ResponseWriter, msg string) {
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: flashCookieName,
|
||||||
|
Value: msg,
|
||||||
|
Path: "/",
|
||||||
|
HttpOnly: true,
|
||||||
|
Expires: time.Now().Add(time.Minute),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) getFlash(w http.ResponseWriter, r *http.Request) string {
|
||||||
|
cookie, err := r.Cookie(flashCookieName)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
defer http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: flashCookieName,
|
||||||
|
Value: "",
|
||||||
|
Path: "/",
|
||||||
|
HttpOnly: true,
|
||||||
|
Expires: time.Now(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return cookie.Value
|
||||||
|
}
|
15
web/auth/auth.go
Normal file
15
web/auth/auth.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import "git.sleepycat.moe/sam/mercury/web/app"
|
||||||
|
|
||||||
|
type Auth struct {
|
||||||
|
*app.App
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(app *app.App) *Auth {
|
||||||
|
auth := &Auth{
|
||||||
|
App: app,
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth
|
||||||
|
}
|
11
web/auth/login.go
Normal file
11
web/auth/login.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/flosch/pongo2/v6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (app *Auth) GetLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
app.Template(w, r, "auth/login.tpl", pongo2.Context{})
|
||||||
|
}
|
1
web/frontend/.gitignore
vendored
Normal file
1
web/frontend/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
assets
|
|
@ -1,13 +1,13 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>{{.Config.Name}}</title>
|
<title>{{.Config.Name}}</title>
|
||||||
|
|
||||||
{{.Vue.RenderTags}}
|
{{.Vue.RenderTags}}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
package frontend
|
package frontend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"git.sleepycat.moe/sam/mercury/frontend"
|
"git.sleepycat.moe/sam/mercury/frontend"
|
||||||
"git.sleepycat.moe/sam/mercury/internal/database"
|
"git.sleepycat.moe/sam/mercury/internal/database"
|
||||||
"git.sleepycat.moe/sam/mercury/web/app"
|
"git.sleepycat.moe/sam/mercury/web/app"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
vueglue "github.com/torenware/vite-go"
|
vueglue "github.com/torenware/vite-go"
|
||||||
|
|
||||||
_ "embed"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed app.html
|
//go:embed app.html
|
||||||
var htmlTemplate string
|
var htmlTemplate string
|
||||||
|
|
||||||
|
//go:embed assets
|
||||||
|
var assets embed.FS
|
||||||
|
|
||||||
type Frontend struct {
|
type Frontend struct {
|
||||||
*app.App
|
*app.App
|
||||||
glue *vueglue.VueGlue
|
glue *vueglue.VueGlue
|
||||||
|
@ -94,3 +98,14 @@ func (app *Frontend) ServeFrontend(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Err(err).Msg("executing frontend template")
|
log.Err(err).Msg("executing frontend template")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *Frontend) ServeStaticAssets(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if app.Config.Core.Dev {
|
||||||
|
// TODO: this is unsafe
|
||||||
|
path := filepath.Join("web/frontend/assets/", chi.URLParam(r, "*"))
|
||||||
|
http.ServeFile(w, r, path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = assets
|
||||||
|
}
|
||||||
|
|
|
@ -2,12 +2,23 @@ package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.sleepycat.moe/sam/mercury/web/app"
|
"git.sleepycat.moe/sam/mercury/web/app"
|
||||||
|
"git.sleepycat.moe/sam/mercury/web/auth"
|
||||||
"git.sleepycat.moe/sam/mercury/web/frontend"
|
"git.sleepycat.moe/sam/mercury/web/frontend"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Routes(app *app.App) {
|
func Routes(app *app.App) {
|
||||||
|
// auth
|
||||||
|
app.Router.Route("/auth", func(r chi.Router) {
|
||||||
|
auth := auth.New(app)
|
||||||
|
r.Get("/login", auth.GetLogin)
|
||||||
|
})
|
||||||
|
|
||||||
|
// web app handlers
|
||||||
|
// also assets
|
||||||
frontend := frontend.New(app)
|
frontend := frontend.New(app)
|
||||||
app.Router.HandleFunc(frontend.AssetsPath(), frontend.ServeAssets)
|
app.Router.HandleFunc(frontend.AssetsPath(), frontend.ServeAssets)
|
||||||
|
app.Router.HandleFunc("/static/*", frontend.ServeStaticAssets)
|
||||||
app.Router.HandleFunc("/web", frontend.ServeFrontend)
|
app.Router.HandleFunc("/web", frontend.ServeFrontend)
|
||||||
app.Router.HandleFunc("/web/*", frontend.ServeFrontend)
|
app.Router.HandleFunc("/web/*", frontend.ServeFrontend)
|
||||||
}
|
}
|
||||||
|
|
19
web/templates/auth/login.tpl
Normal file
19
web/templates/auth/login.tpl
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{% extends 'base.tpl' %}
|
||||||
|
{% block title %}
|
||||||
|
Log in
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="auth">
|
||||||
|
<form method="post">
|
||||||
|
<p>
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input type="text" name="username" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="username">Password</label>
|
||||||
|
<input type="password" name="password" />
|
||||||
|
</p>
|
||||||
|
<input type="submit" value="Log in" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
13
web/templates/base.tpl
Normal file
13
web/templates/base.tpl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
|
||||||
|
<title>{% block title %}Mercury{% endblock %}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
28
web/templates/templates.go
Normal file
28
web/templates/templates.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package templates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
|
||||||
|
"emperror.dev/errors"
|
||||||
|
"github.com/flosch/pongo2/v6"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
func New(dev bool) (*pongo2.TemplateSet, error) {
|
||||||
|
if dev {
|
||||||
|
loader, err := pongo2.NewLocalFileSystemLoader("web/templates")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "creating filesystem loader")
|
||||||
|
}
|
||||||
|
|
||||||
|
ts := pongo2.NewSet("web", loader)
|
||||||
|
ts.Debug = true
|
||||||
|
return ts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
loader := pongo2.NewFSLoader(fs)
|
||||||
|
ts := pongo2.NewSet("web", loader)
|
||||||
|
return ts, nil
|
||||||
|
}
|
Loading…
Reference in a new issue