Implement client-side routing

This commit is contained in:
Kai Vogelgesang 2022-09-05 20:54:44 +02:00
parent 6f7279c049
commit c147b44b0c
Signed by: kai
GPG Key ID: 0A95D3B6E62C0879
6 changed files with 209 additions and 26 deletions

View File

@ -15,6 +15,7 @@
"sass": "^1.53.0",
"svelte": "^3.49.0",
"svelte-check": "^2.8.0",
"svelte-navigator": "^3.2.2",
"svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0",
"typescript": "^4.6.4",
@ -298,6 +299,12 @@
}
}
},
"node_modules/dedent-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
"dev": true
},
"node_modules/deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
@ -898,6 +905,15 @@
"node": ">=6"
}
},
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/magic-string": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
@ -998,6 +1014,16 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"dependencies": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -1028,6 +1054,16 @@
"node": ">=6"
}
},
"node_modules/pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -1341,6 +1377,19 @@
"svelte": ">=3.19.0"
}
},
"node_modules/svelte-navigator": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/svelte-navigator/-/svelte-navigator-3.2.2.tgz",
"integrity": "sha512-Xio4ohLUG1nQJ+ENNbLphXXu9L189fnI1WGg+2Q3CIMPe8Jm2ipytKQthdBs8t0mN7p3Eb03SE9hq0xZAqwQNQ==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"svelte2tsx": "^0.1.151"
},
"peerDependencies": {
"svelte": "3.x"
}
},
"node_modules/svelte-preprocess": {
"version": "4.10.7",
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz",
@ -1416,6 +1465,20 @@
"sourcemap-codec": "^1.4.8"
}
},
"node_modules/svelte2tsx": {
"version": "0.1.193",
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.1.193.tgz",
"integrity": "sha512-vzy4YQNYDnoqp2iZPnJy7kpPAY6y121L0HKrSBjU/IWW7DQ6T7RMJed2VVHFmVYm0zAGYMDl9urPc6R4DDUyhg==",
"dev": true,
"dependencies": {
"dedent-js": "^1.0.1",
"pascal-case": "^3.1.1"
},
"peerDependencies": {
"svelte": "^3.24",
"typescript": "^4.1.2"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -1698,6 +1761,12 @@
"ms": "2.1.2"
}
},
"dedent-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
"dev": true
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
@ -2056,6 +2125,15 @@
"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
"dev": true
},
"lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"requires": {
"tslib": "^2.0.3"
}
},
"magic-string": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
@ -2129,6 +2207,16 @@
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"dev": true
},
"no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"requires": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -2153,6 +2241,16 @@
"callsites": "^3.0.0"
}
},
"pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -2353,6 +2451,15 @@
"dev": true,
"requires": {}
},
"svelte-navigator": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/svelte-navigator/-/svelte-navigator-3.2.2.tgz",
"integrity": "sha512-Xio4ohLUG1nQJ+ENNbLphXXu9L189fnI1WGg+2Q3CIMPe8Jm2ipytKQthdBs8t0mN7p3Eb03SE9hq0xZAqwQNQ==",
"dev": true,
"requires": {
"svelte2tsx": "^0.1.151"
}
},
"svelte-preprocess": {
"version": "4.10.7",
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz",
@ -2378,6 +2485,16 @@
}
}
},
"svelte2tsx": {
"version": "0.1.193",
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.1.193.tgz",
"integrity": "sha512-vzy4YQNYDnoqp2iZPnJy7kpPAY6y121L0HKrSBjU/IWW7DQ6T7RMJed2VVHFmVYm0zAGYMDl9urPc6R4DDUyhg==",
"dev": true,
"requires": {
"dedent-js": "^1.0.1",
"pascal-case": "^3.1.1"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",

View File

@ -17,6 +17,7 @@
"sass": "^1.53.0",
"svelte": "^3.49.0",
"svelte-check": "^2.8.0",
"svelte-navigator": "^3.2.2",
"svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0",
"typescript": "^4.6.4",

View File

@ -1,4 +1,5 @@
<script lang="ts">
import { Router, Route } from "svelte-navigator";
import { onMount } from "svelte";
import { user } from "./stores";
@ -11,7 +12,37 @@
});
</script>
<Navbar />
<section class="section">
<p>Hallo i bims 1 frontend</p>
</section>
<Router>
<Navbar />
<Route path="/">
<section class="section">
<p>Hallo i bims 1 frontend</p>
</section>
</Route>
<Route path="/foo">foo</Route>
<Route path="/bar">bar</Route>
<Route path="/monitoring">monitoring</Route>
<Route path="/mining">mining</Route>
<Route path="/stats">stats</Route>
<Route>
<section class="section">
<div class="container has-text-centered">
<h1 class="title is-1">404</h1>
<h2 class="subtitle is-5">
The page you are trying to reach either
<strong>does not exist</strong>
or
<strong>you are not authorized</strong>
to view it.
</h2>
</div>
</section>
</Route>
</Router>

View File

@ -1,4 +1,7 @@
<script lang="ts">
import Navlink from "./Navlink.svelte";
import { Link } from "svelte-navigator";
import logo from "./assets/turtle.png";
import { user } from "./stores";
@ -8,12 +11,10 @@
<nav class="navbar">
<div class="navbar-brand">
<a class="navbar-item" href="/">
<span class="icon-text">
<img class="image is-24x24" src={logo} alt="logo" />
<span><strong>Control Panel</strong></span>
</span>
</a>
<Link class="navbar-item" to="/">
<img class="image is-24x24 mr-1" src={logo} alt="logo" />
<span><strong>Control Panel</strong></span>
</Link>
<!-- svelte-ignore a11y-missing-attribute -->
<a
role="button"
@ -29,10 +30,13 @@
</div>
<div class="navbar-menu {menu_open ? 'is-active' : ''}">
<div class="navbar-start">
<a class="navbar-item" href="/foo"> Foo </a>
<a class="navbar-item" href="/bar"> Bar </a>
<Navlink target="/foo" text="Foo" icon="fas fa-hippo" />
<Navlink target="/bar" text="Bar" icon="fas fa-otter" />
<Navlink target="/monitoring" text="Monitoring" icon="fas fa-binoculars" />
<Navlink target="/mining" text="Mining" icon="fas fa-person-digging" />
<Navlink target="/stats" text="Statistics" icon="fas fa-chart-line" />
</div>
<div class="navbar-end">
{#if $user !== null}
<div class="navbar-item has-dropdown is-hoverable">

View File

@ -0,0 +1,23 @@
<script lang="ts">
import { Link, useLocation } from "svelte-navigator";
const location = useLocation();
export let target: string;
export let icon: string;
export let text: string;
</script>
<Link
to={target}
class="navbar-item is-tab {$location.pathname === target
? 'is-active'
: ''}"
>
<span class="icon-text">
<span class="icon">
<i class={icon} />
</span>
<span>{text}</span>
</span>
</Link>

View File

@ -1,10 +1,7 @@
import json
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from starlette.config import Config
from starlette.middleware.sessions import SessionMiddleware
from starlette.responses import HTMLResponse, RedirectResponse
from authlib.integrations.starlette_client import OAuth, OAuthError
from fastapi.responses import HTMLResponse
from jinja2 import Environment, FileSystemLoader, select_autoescape
from .settings import settings
from .user import user_auth
@ -13,8 +10,6 @@ app = FastAPI()
app.mount("/user/", user_auth)
templates = Jinja2Templates(directory="templates")
manifest = dict()
if not settings.dev_mode:
from fastapi.staticfiles import StaticFiles
@ -23,12 +18,24 @@ if not settings.dev_mode:
manifest = json.load(f)
@app.get("/")
async def index(request: Request):
return templates.TemplateResponse(
"index.html",
{"request": request, "dev_mode": settings.dev_mode, "manifest": manifest},
)
j2env = Environment(
loader=FileSystemLoader("templates"),
autoescape=select_autoescape(),
)
index = j2env.get_template("index.html").render(
dev_mode=settings.dev_mode,
manifest=manifest,
)
@app.middleware("http")
async def index_catch_all(request: Request, call_next):
response = await call_next(request)
if response.status_code == 404:
return HTMLResponse(index)
return response
if not settings.dev_mode: