Implement client-side routing
This commit is contained in:
parent
6f7279c049
commit
c147b44b0c
117
frontend/package-lock.json
generated
117
frontend/package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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>
|
||||
|
||||
<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>
|
||||
|
@ -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" />
|
||||
<Link class="navbar-item" to="/">
|
||||
<img class="image is-24x24 mr-1" src={logo} alt="logo" />
|
||||
<span><strong>Control Panel</strong></span>
|
||||
</span>
|
||||
</a>
|
||||
</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">
|
||||
|
23
frontend/src/Navlink.svelte
Normal file
23
frontend/src/Navlink.svelte
Normal 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>
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user