created a basic home page #97
This commit is contained in:
parent
a3913ccdf5
commit
f41cdf78df
44
logic/stats/PublicStats.go
Normal file
44
logic/stats/PublicStats.go
Normal file
@ -0,0 +1,44 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||
)
|
||||
|
||||
func HandlePublicStats(handle *Handle) {
|
||||
handle.Post("/stats/public/main", func(c *Context) *Error {
|
||||
if handle.DataMap["PublicMainLastUpdate"] != nil && handle.DataMap["PublicMainLastUpdate"].(int64) > time.Now().UnixMilli() {
|
||||
c.ShowMessage = false
|
||||
return c.SendJSON(handle.DataMap["PublicMain"])
|
||||
}
|
||||
number_of_models, err := GetDbVar[int](c, "count(*)", "models")
|
||||
if err != nil {
|
||||
return c.E500M("Could not get statistics", err)
|
||||
}
|
||||
number_of_classfications, err := GetDbVar[int](c, "count(*)", "tasks where task_type=$1", TASK_TYPE_CLASSIFICATION)
|
||||
if err != nil {
|
||||
return c.E500M("Could not get statistics", err)
|
||||
}
|
||||
number_of_images_processed, err := GetDbVar[int](c, "count(*)", "model_data_point")
|
||||
if err != nil {
|
||||
return c.E500M("Could not get statistics", err)
|
||||
}
|
||||
|
||||
handle.DataMap["PublicMainLastUpdate"] = time.Now().UnixNano() + 60*60*1000*1000
|
||||
handle.DataMap["PublicMain"] = struct {
|
||||
NumberOfModels int `json:"number_of_models"`
|
||||
NumberOfClassfications int `json:"number_of_classfications"`
|
||||
NumberOfImagesProcessed int `json:"number_of_images_processed"`
|
||||
}{
|
||||
*number_of_models,
|
||||
*number_of_classfications,
|
||||
*number_of_images_processed,
|
||||
}
|
||||
|
||||
c.ShowMessage = false
|
||||
return c.SendJSON(handle.DataMap["PublicMain"])
|
||||
})
|
||||
}
|
9
logic/stats/index.go
Normal file
9
logic/stats/index.go
Normal file
@ -0,0 +1,9 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||
)
|
||||
|
||||
func HandleStats(handle *Handle) {
|
||||
HandlePublicStats(handle)
|
||||
}
|
@ -46,6 +46,7 @@ type Handle struct {
|
||||
gets []HandleFunc
|
||||
posts []HandleFunc
|
||||
deletes []HandleFunc
|
||||
DataMap map[string]interface{}
|
||||
Config Config
|
||||
validate *validator.Validate
|
||||
}
|
||||
@ -523,7 +524,7 @@ func NewHandler(db db.Db, config Config) *Handle {
|
||||
var posts []HandleFunc
|
||||
var deletes []HandleFunc
|
||||
validate := validator.New()
|
||||
x := &Handle{db, gets, posts, deletes, config, validate}
|
||||
x := &Handle{db, gets, posts, deletes, map[string]interface{}{}, config, validate}
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
|
2
main.go
2
main.go
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"git.andr3h3nriqu3s.com/andr3/fyp/logic/db"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/stats"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/runner"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/users"
|
||||
@ -48,6 +49,7 @@ func main() {
|
||||
UsersEndpints(db, handle)
|
||||
HandleModels(handle)
|
||||
HandleTasks(handle)
|
||||
HandleStats(handle)
|
||||
|
||||
handle.Startup()
|
||||
}
|
||||
|
@ -6,22 +6,22 @@
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/"> Index </a>
|
||||
<a href="/"> <span class="bi bi-house-fill"></span> Home </a>
|
||||
</li>
|
||||
{#if userStore.user}
|
||||
<li>
|
||||
<a href="/models"> Models </a>
|
||||
<a href="/models"> <span class="bi bi-card-image"></span> Models </a>
|
||||
</li>
|
||||
{/if}
|
||||
<li class="expand"></li>
|
||||
{#if userStore.user}
|
||||
<li>
|
||||
<a href="/user/info"> User Info </a>
|
||||
<a href="/logout"> Logout </a>
|
||||
<a href="/user/info"> <span class="bi bi-person-fill"></span> {userStore.user.username} </a>
|
||||
<a href="/logout"> <span class="bi bi-box-arrow-right"></span> Logout </a>
|
||||
</li>
|
||||
{:else}
|
||||
<li>
|
||||
<a href="/login"> Login </a>
|
||||
<a href="/login"> <span class="bi bi-box-arrow-in-left"></span> Login</a>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
|
@ -3,9 +3,25 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Andada+Pro:ital,wght@0,400..840;1,400..840&family=Bebas+Neue&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"
|
||||
/>
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { userStore } from 'routes/UserStore.svelte';
|
||||
import { notificationStore } from './NotificationsStore.svelte';
|
||||
|
||||
const API = '/api';
|
||||
|
||||
@ -102,7 +103,7 @@ export async function postFormData(url: string, body: FormData) {
|
||||
|
||||
export async function showMessage(
|
||||
e: any,
|
||||
messages: any,
|
||||
messages: any = notificationStore,
|
||||
message = 'Could not complete request'
|
||||
): Promise<boolean> {
|
||||
if (e == null) {
|
||||
|
@ -1 +1,48 @@
|
||||
<h1>Main Web Page</h1>
|
||||
<script>
|
||||
import Spinner from 'src/lib/Spinner.svelte';
|
||||
import Counter from './Counter.svelte';
|
||||
import { post, showMessage } from 'src/lib/requests.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let _counters = $state(new Promise(() => {}));
|
||||
|
||||
async function publicStats() {
|
||||
try {
|
||||
const r = await post('stats/public/main', {});
|
||||
_counters = Promise.resolve(r);
|
||||
} catch (e) {
|
||||
showMessage(e);
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
publicStats();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="title">
|
||||
<h1>Classify Your Images</h1>
|
||||
<h2>A software as a service platform for image classification</h2>
|
||||
</div>
|
||||
|
||||
<div class="counters">
|
||||
{#await _counters}
|
||||
<Spinner />
|
||||
{:then counters}
|
||||
<Counter value={counters.number_of_models}>Number of models created</Counter>
|
||||
<Counter value={counters.number_of_classfications}>Number of images classified</Counter>
|
||||
<Counter value={counters.number_of_images_processed}>Number of images processed</Counter>
|
||||
{/await}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
.counters {
|
||||
height: 180px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
41
webpage/src/routes/Counter.svelte
Normal file
41
webpage/src/routes/Counter.svelte
Normal file
@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
import { tweened } from 'svelte/motion';
|
||||
|
||||
const { value, children }: { value: number; children: unknown } = $props();
|
||||
|
||||
const t_value = tweened(0, {
|
||||
duration: 300,
|
||||
easing: cubicOut
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
t_value.set(value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="counter">
|
||||
<div class="number">
|
||||
{Math.floor($t_value)}
|
||||
</div>
|
||||
<div class="description">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.counter {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
box-shadow: 1px 1px 8px 2px #33333333;
|
||||
border-radius: 30px;
|
||||
padding: 20px;
|
||||
margin: 0 10px;
|
||||
text-align: center;
|
||||
|
||||
.number {
|
||||
font-family: 'Bebas Neue';
|
||||
font-size: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,6 +1,7 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-family: 'Andada Pro', sans-serif;
|
||||
/* font-family: 'Roboto', sans-serif; */
|
||||
}
|
||||
|
||||
:root {
|
||||
|
Loading…
Reference in New Issue
Block a user