add basic frontend connection

This commit is contained in:
Maxi Quoß
2023-01-16 00:09:39 +01:00
parent 3bddd8f521
commit a51157f0f3
9 changed files with 161 additions and 87 deletions

View File

@@ -59,6 +59,19 @@ func init() {
"pattern": ""
}
},
{
"system": false,
"id": "s8c5z7n0",
"name": "netmask",
"type": "text",
"required": true,
"unique": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
},
{
"system": false,
"id": "gdctb8hj",
@@ -109,19 +122,6 @@ func init() {
"max": null,
"pattern": ""
}
},
{
"system": false,
"id": "s8c5z7n0",
"name": "netmask",
"type": "text",
"required": true,
"unique": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
}
],
"listRule": "",

View File

@@ -17,15 +17,18 @@
"eslint-plugin-svelte3": "^4.0.0",
"prettier": "^2.8.3",
"prettier-plugin-svelte": "^2.9.0",
"svelte": "^3.55.0",
"svelte-preprocess": "^4.10.7",
"svelte": "^3.55.0",
"svelte-preprocess": "^4.10.7",
"vite": "^4.0.4"
},
"type": "module",
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@popperjs/core": "^2.11.6",
"bootstrap": "5.3.0-alpha1",
"date-fns": "^2.29.3",
"pocketbase": "^0.10.0",
"sass": "^1.57.1"
"sass": "^1.57.1",
"svelte-fa": "^3.0.3"
}
}

View File

@@ -1,10 +1,12 @@
lockfileVersion: 5.4
specifiers:
'@fortawesome/free-solid-svg-icons': ^6.2.1
'@popperjs/core': ^2.11.6
'@sveltejs/adapter-auto': ^1.0.1
'@sveltejs/kit': ^1.1.1
bootstrap: 5.3.0-alpha1
date-fns: ^2.29.3
eslint: ^8.32.0
eslint-config-prettier: ^8.6.0
eslint-plugin-svelte3: ^4.0.0
@@ -13,14 +15,18 @@ specifiers:
prettier-plugin-svelte: ^2.9.0
sass: ^1.57.1
svelte: ^3.55.0
svelte-fa: ^3.0.3
svelte-preprocess: ^4.10.7
vite: ^4.0.4
dependencies:
'@fortawesome/free-solid-svg-icons': 6.2.1
'@popperjs/core': 2.11.6
bootstrap: 5.3.0-alpha1_@popperjs+core@2.11.6
date-fns: 2.29.3
pocketbase: 0.10.0
sass: 1.57.1
svelte-fa: 3.0.3
devDependencies:
'@sveltejs/adapter-auto': 1.0.1_@sveltejs+kit@1.1.1
@@ -251,6 +257,20 @@ packages:
- supports-color
dev: true
/@fortawesome/fontawesome-common-types/6.2.1:
resolution: {integrity: sha512-Sz07mnQrTekFWLz5BMjOzHl/+NooTdW8F8kDQxjWwbpOJcnoSg4vUDng8d/WR1wOxM0O+CY9Zw0nR054riNYtQ==}
engines: {node: '>=6'}
requiresBuild: true
dev: false
/@fortawesome/free-solid-svg-icons/6.2.1:
resolution: {integrity: sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==}
engines: {node: '>=6'}
requiresBuild: true
dependencies:
'@fortawesome/fontawesome-common-types': 6.2.1
dev: false
/@humanwhocodes/config-array/0.11.8:
resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==}
engines: {node: '>=10.10.0'}
@@ -520,6 +540,11 @@ packages:
which: 2.0.2
dev: true
/date-fns/2.29.3:
resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==}
engines: {node: '>=0.11'}
dev: false
/debug/4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@@ -1308,6 +1333,10 @@ packages:
engines: {node: '>= 0.4'}
dev: true
/svelte-fa/3.0.3:
resolution: {integrity: sha512-GIikJjcVCD+5Y/x9hZc2R4gvuA0gVftacuWu1a+zVQWSFjFYZ+hhU825x+QNs2slsppfrgmFiUyU9Sz9gj4Rdw==}
dev: false
/svelte-hmr/0.15.1_svelte@3.55.1:
resolution: {integrity: sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==}
engines: {node: ^12.20 || ^14.13.1 || >= 16}

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />

View File

@@ -0,0 +1,31 @@
<script>
import { parseISO, formatDistance } from 'date-fns';
import Fa from 'svelte-fa';
import { faPowerOff } from '@fortawesome/free-solid-svg-icons';
export let device;
export let now;
</script>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 g-4">
<div class="card border-0 rounded-5 px-2 bg-body-secondary text-dark-emphasis">
<div class="card-body">
<p
class="m-0 fs-4"
class:text-danger={device.status == 'offline' ? true : false}
class:text-success={device.status == 'online' ? true : false}
class:text-warning={device.status == 'pending' ? true : false}
>
<Fa icon={faPowerOff} />
</p>
<p class="m-0 fw-bold fs-5">{device.name} ({device.status})</p>
<p class="m-0 text-muted">{device.ip}</p>
</div>
<div class="card-footer mb-2 bg-transparent fst-italic">
Last change: {formatDistance(parseISO(device.updated), now, {
includeSeconds: true,
addSuffix: true
})}
</div>
</div>
</div>

View File

@@ -1,50 +0,0 @@
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon" />
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a
class="nav-link dropdown-toggle"
href="#"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Dropdown
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider" /></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search" />
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>

View File

@@ -2,6 +2,17 @@
import Navbar from '@components/Navbar.svelte';
</script>
<svelte:head>
<script>
if (document) {
theme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
document.documentElement.setAttribute('data-bs-theme', theme);
}
</script>
</svelte:head>
<Navbar />
<slot />

View File

@@ -1,16 +1,41 @@
<script>
import PocketBase from 'pocketbase';
import { onMount } from 'svelte';
import DeviceCard from '@components/DeviceCard.svelte';
let devices = [];
let devices = {};
onMount(async () => {
const pb = new PocketBase('http://127.0.0.1:8090');
// get all devices in pocketbase
const result = await pb.collection('devices').getFullList();
devices = result;
result.forEach(device => {
devices[device.id] = device
});
// subscribe to database events
pb.collection('devices').subscribe('*', function (e) {
devices[e.record.id] = e.record
});
});
// update device date
let now = Date.now();
let clear;
$: {
clearInterval(clear)
clear = setInterval(() => {
now = Date.now()
}, 1000);
}
</script>
{#each devices as device}
{device.name}
{/each}
<div class="container">
<div class="row">
{#each Object.entries(devices) as [_, device]}
<DeviceCard {device} {now} />
{/each}
</div>
</div>

View File

@@ -1,15 +1,40 @@
// @import "../../node_modules/bootstrap/scss/functions";
// @import "../../node_modules/bootstrap/scss/variables";
// @import "../../node_modules/bootstrap/scss/variables-dark";
// @import "../../node_modules/bootstrap/scss/maps";
// @import "../../node_modules/bootstrap/scss/mixins";
// @import "../../node_modules/bootstrap/scss/root";
// @import "../../node_modules/bootstrap/scss/utilities";
// @import "../../node_modules/bootstrap/scss/reboot";
// @import "../../node_modules/bootstrap/scss/type";
// @import "../../node_modules/bootstrap/scss/images";
// @import "../../node_modules/bootstrap/scss/containers";
// @import "../../node_modules/bootstrap/scss/grid";
// @import "../../node_modules/bootstrap/scss/helpers";
// @import "../../node_modules/bootstrap/scss/utilities/api";
@import "../../node_modules/bootstrap/scss/bootstrap";
// import bootstrap functions and variables
@import '../../node_modules/bootstrap/scss/functions';
@import '../../node_modules/bootstrap/scss/variables';
@import '../../node_modules/bootstrap/scss/variables-dark';
// custom colors
$gray-1000: #111;
$grays: (
'100': $gray-100,
'200': $gray-200,
'300': $gray-300,
'400': $gray-400,
'500': $gray-500,
'600': $gray-600,
'700': $gray-700,
'800': $gray-800,
'900': $gray-900,
'1000': $gray-1000
) !default;
$body-bg-dark: $gray-1000;
// import rest
@import '../../node_modules/bootstrap/scss/maps';
@import '../../node_modules/bootstrap/scss/mixins';
@import '../../node_modules/bootstrap/scss/root';
@import '../../node_modules/bootstrap/scss/utilities';
@import '../../node_modules/bootstrap/scss/reboot';
@import '../../node_modules/bootstrap/scss/type';
@import '../../node_modules/bootstrap/scss/images';
@import '../../node_modules/bootstrap/scss/containers';
@import '../../node_modules/bootstrap/scss/grid';
@import '../../node_modules/bootstrap/scss/helpers';
@import '../../node_modules/bootstrap/scss/card';
@import '../../node_modules/bootstrap/scss/utilities/api';
.text-success {
color: $teal-500 !important;
}