ran prettier
This commit is contained in:
parent
e7eeccd09e
commit
5f11126acd
@ -1,44 +1,53 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
let { replace_slot, accept, file, notExpand } = $props<{
|
let { replace_slot, accept, file, notExpand } = $props<{
|
||||||
replace_slot?: boolean,
|
replace_slot?: boolean;
|
||||||
accept?: string,
|
accept?: string;
|
||||||
file?: File,
|
file?: File;
|
||||||
notExpand?: boolean
|
notExpand?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
let fileInput: HTMLInputElement;
|
let fileInput: HTMLInputElement;
|
||||||
|
|
||||||
let fileData: string | undefined = $state(undefined);
|
let fileData: string | undefined = $state(undefined);
|
||||||
|
|
||||||
function onChange(e: Event & {currentTarget: HTMLInputElement}) {
|
function onChange(e: Event & { currentTarget: HTMLInputElement }) {
|
||||||
if (!e.currentTarget.files) {
|
if (!e.currentTarget.files) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = e.currentTarget.files[0];
|
file = e.currentTarget.files[0];
|
||||||
|
|
||||||
const fileReader = new FileReader();
|
|
||||||
fileReader.onloadend = () => {
|
|
||||||
fileData = String(fileReader.result);
|
|
||||||
//elm.classList.add("adapt");
|
|
||||||
}
|
|
||||||
fileReader.readAsDataURL(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onloadend = () => {
|
||||||
|
fileData = String(fileReader.result);
|
||||||
|
//elm.classList.add("adapt");
|
||||||
|
};
|
||||||
|
fileReader.readAsDataURL(file);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="icon-holder">
|
<div class="icon-holder">
|
||||||
<button class="icon" class:adapt={replace_slot && file && !notExpand} on:click={() => fileInput.click()}>
|
<button
|
||||||
{#if replace_slot && file}
|
class="icon"
|
||||||
<slot name="replaced" file={file}>
|
class:adapt={replace_slot && file && !notExpand}
|
||||||
<img src={fileData} alt="" />
|
on:click={() => fileInput.click()}
|
||||||
<slot name="replaced-name">
|
>
|
||||||
Image Uploaded
|
{#if replace_slot && file}
|
||||||
</slot>
|
<slot name="replaced" {file}>
|
||||||
</slot>
|
<img src={fileData} alt="" />
|
||||||
{:else}
|
<slot name="replaced-name">Image Uploaded</slot>
|
||||||
<slot></slot>
|
</slot>
|
||||||
{/if}
|
{:else}
|
||||||
</button>
|
<slot />
|
||||||
<input id="file" name="file" type="file" required accept={accept} bind:this={fileInput} on:change={onChange} />
|
{/if}
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
id="file"
|
||||||
|
name="file"
|
||||||
|
type="file"
|
||||||
|
required
|
||||||
|
{accept}
|
||||||
|
bind:this={fileInput}
|
||||||
|
on:change={onChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
|
|
||||||
let timeout: number | undefined = undefined;
|
let timeout: number | undefined = undefined;
|
||||||
|
|
||||||
export function clear() {
|
export function clear() {
|
||||||
if (timeout) clearTimeout(timeout);
|
if (timeout) clearTimeout(timeout);
|
||||||
message = undefined;
|
message = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function display(
|
export function display(
|
||||||
msg: string,
|
msg: string,
|
||||||
|
@ -1,73 +1,71 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
let {active, nobox} = $props<{active?: string, nobox?: boolean}>();
|
let { active, nobox } = $props<{ active?: string; nobox?: boolean }>();
|
||||||
|
|
||||||
function setActive(name: string) {
|
|
||||||
return () => active = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isActive(name: string) {
|
function setActive(name: string) {
|
||||||
return name == active;
|
return () => (active = name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isActive(name: string) {
|
||||||
|
return name == active;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="tabs" class:nobox>
|
<div class="tabs" class:nobox>
|
||||||
<div class="tab-buttons">
|
<div class="tab-buttons">
|
||||||
<slot name="buttons" {setActive} {isActive} />
|
<slot name="buttons" {setActive} {isActive} />
|
||||||
</div>
|
</div>
|
||||||
<slot {isActive} {active} />
|
<slot {isActive} {active} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.tabs {
|
.tabs {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
box-shadow: 0 2px 8px 1px #66666655;
|
box-shadow: 0 2px 8px 1px #66666655;
|
||||||
gap: 0 5px;
|
gap: 0 5px;
|
||||||
|
|
||||||
.tab-buttons {
|
.tab-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
:global(.buttons) {
|
:global(.buttons) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.tab) {
|
:global(.tab) {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background: var(--light-grey);
|
background: var(--light-grey);
|
||||||
border-radius: 5px 5px 0 0;
|
border-radius: 5px 5px 0 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.tab.selected) {
|
:global(.tab.selected) {
|
||||||
box-shadow: inset 0 2px 8px 1px #66666655;
|
box-shadow: inset 0 2px 8px 1px #66666655;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.content) {
|
:global(.content) {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.content.selected) {
|
:global(.content.selected) {
|
||||||
display: block;
|
display: block;
|
||||||
box-shadow: 0 2px 2px 1px #66666655;
|
box-shadow: 0 2px 2px 1px #66666655;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.nobox {
|
&.nobox {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|
||||||
|
:global(.content.selected) {
|
||||||
:global(.content.selected) {
|
box-shadow: none;
|
||||||
box-shadow: none;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import Page404 from './Page404.svelte';
|
import Page404 from './Page404.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $page.error}
|
{#if $page.error}
|
||||||
{#if $page.status == 404}
|
{#if $page.status == 404}
|
||||||
<Page404 />
|
<Page404 />
|
||||||
{:else}
|
{:else}
|
||||||
<h1>
|
<h1>
|
||||||
{$page.status}
|
{$page.status}
|
||||||
</h1>
|
</h1>
|
||||||
<h2>
|
<h2>
|
||||||
{$page.error.message}
|
{$page.error.message}
|
||||||
</h2>
|
</h2>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '../styles/fonts.css';
|
import '../styles/fonts.css';
|
||||||
import '../styles/app.css';
|
import '../styles/app.css';
|
||||||
import NavBar from "../NavBar.svelte";
|
import NavBar from '../NavBar.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<NavBar />
|
<NavBar />
|
||||||
|
@ -1,54 +1,46 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
let { message, goBackLink } = $props<{message?: string, goBackLink?: string}>();
|
let { message, goBackLink } = $props<{ message?: string; goBackLink?: string }>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="page404">
|
<div class="page404">
|
||||||
<div>
|
<div>
|
||||||
<h1>
|
<h1>404</h1>
|
||||||
404
|
{#if message}
|
||||||
</h1>
|
<h2>
|
||||||
{#if message}
|
{message}
|
||||||
<h2>
|
</h2>
|
||||||
{message}
|
{#if goBackLink}
|
||||||
</h2>
|
<div class="description">
|
||||||
{#if goBackLink}
|
<a href={goBackLink}> 👈 Go back </a>
|
||||||
<div class="description">
|
</div>
|
||||||
<a href={goBackLink}>
|
{/if}
|
||||||
👈 Go back
|
{:else}
|
||||||
</a>
|
<h2>Page Not found</h2>
|
||||||
</div>
|
<div class="description">The page you were looking for does not exist</div>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
</div>
|
||||||
<h2>
|
|
||||||
Page Not found
|
|
||||||
</h2>
|
|
||||||
<div class="description">
|
|
||||||
The page you were looking for does not exist
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.page404 {
|
.page404 {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
height: calc(100vh - 60px);
|
height: calc(100vh - 60px);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 10em;
|
font-size: 10em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 5em;
|
font-size: 5em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-bottom: 0.3em;
|
margin-bottom: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.description {
|
div.description {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,55 +1,55 @@
|
|||||||
import { goto } from "$app/navigation";
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
type User = {
|
type User = {
|
||||||
token: string,
|
token: string;
|
||||||
id: string,
|
id: string;
|
||||||
user_type: number,
|
user_type: number;
|
||||||
username: string,
|
username: string;
|
||||||
email: string,
|
email: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createUserStore() {
|
export function createUserStore() {
|
||||||
let user = $state<User | undefined>(undefined);
|
let user = $state<User | undefined>(undefined);
|
||||||
|
|
||||||
function getValue() {
|
function getValue() {
|
||||||
if (user == undefined) {
|
if (user == undefined) {
|
||||||
let storage = localStorage.getItem('user');
|
let storage = localStorage.getItem('user');
|
||||||
if (storage) {
|
if (storage) {
|
||||||
try {
|
try {
|
||||||
user = JSON.parse(storage);
|
user = JSON.parse(storage);
|
||||||
} catch {
|
} catch {
|
||||||
user = undefined;
|
user = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
get user() {
|
get user() {
|
||||||
return getValue();
|
return getValue();
|
||||||
},
|
},
|
||||||
set user(value: User | undefined) {
|
set user(value: User | undefined) {
|
||||||
if (value) {
|
if (value) {
|
||||||
localStorage.setItem('user', JSON.stringify(value));
|
localStorage.setItem('user', JSON.stringify(value));
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem('user');
|
localStorage.removeItem('user');
|
||||||
}
|
}
|
||||||
user = value;
|
user = value;
|
||||||
},
|
},
|
||||||
checkUser(pathOnFail: string, level?: number) {
|
checkUser(pathOnFail: string, level?: number) {
|
||||||
if (user && user.level > (level ?? 2) ) {
|
if (user && user.level > (level ?? 2)) {
|
||||||
goto(pathOnFail);
|
goto(pathOnFail);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
isLogin() {
|
isLogin() {
|
||||||
if (getValue()) return true;
|
if (getValue()) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const userStore = createUserStore();
|
export const userStore = createUserStore();
|
||||||
|
@ -1,83 +1,77 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { post } from 'src/lib/requests.svelte';
|
import { post } from 'src/lib/requests.svelte';
|
||||||
import 'src/styles/forms.css';
|
import 'src/styles/forms.css';
|
||||||
import { userStore } from '../UserStore.svelte';
|
import { userStore } from '../UserStore.svelte';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
let submitted = $state(false);
|
|
||||||
|
|
||||||
let loginData = $state({
|
let submitted = $state(false);
|
||||||
email: '',
|
|
||||||
password: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
let errorMessage = $state("");
|
let loginData = $state({
|
||||||
|
email: '',
|
||||||
|
password: ''
|
||||||
|
});
|
||||||
|
|
||||||
async function onSubmit() {
|
let errorMessage = $state('');
|
||||||
submitted = true;
|
|
||||||
errorMessage = "";
|
async function onSubmit() {
|
||||||
|
submitted = true;
|
||||||
try {
|
errorMessage = '';
|
||||||
const req = await post('login', loginData);
|
|
||||||
userStore.user = req;
|
try {
|
||||||
goto("/");
|
const req = await post('login', loginData);
|
||||||
} catch (e) {
|
userStore.user = req;
|
||||||
loginData.password = "";
|
goto('/');
|
||||||
if (e instanceof Response) {
|
} catch (e) {
|
||||||
errorMessage = await e.json();
|
loginData.password = '';
|
||||||
} else {
|
if (e instanceof Response) {
|
||||||
errorMessage = "Server could not perform login";
|
errorMessage = await e.json();
|
||||||
}
|
} else {
|
||||||
}
|
errorMessage = 'Server could not perform login';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title> Login </title>
|
<title>Login</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="login-page">
|
<div class="login-page">
|
||||||
<div>
|
<div>
|
||||||
<h1>
|
<h1>Login</h1>
|
||||||
Login
|
<form on:submit|preventDefault={onSubmit} class:submitted>
|
||||||
</h1>
|
<fieldset>
|
||||||
<form on:submit|preventDefault={onSubmit} class:submitted >
|
<label for="email">Email</label>
|
||||||
<fieldset>
|
<input type="email" required name="email" bind:value={loginData.email} />
|
||||||
<label for="email">Email</label>
|
</fieldset>
|
||||||
<input type="email" required name="email" bind:value={loginData.email} />
|
<fieldset>
|
||||||
</fieldset>
|
<label for="password">Password</label>
|
||||||
<fieldset>
|
<input required name="password" type="password" bind:value={loginData.password} />
|
||||||
<label for="password">Password</label>
|
{#if errorMessage}
|
||||||
<input required name="password" type="password" bind:value={loginData.password} />
|
<span class="form-msg error">
|
||||||
{#if errorMessage}
|
{errorMessage}
|
||||||
<span class="form-msg error">
|
<!--Either the password or the email are incorrect-->
|
||||||
{errorMessage}
|
</span>
|
||||||
<!--Either the password or the email are incorrect-->
|
{/if}
|
||||||
</span>
|
</fieldset>
|
||||||
{/if}
|
<button> Login </button>
|
||||||
</fieldset>
|
<div class="spacer"></div>
|
||||||
<button>
|
<a class="simple-link text-center w100 spacer" href="/register"> Register </a>
|
||||||
Login
|
</form>
|
||||||
</button>
|
</div>
|
||||||
<div class="spacer"></div>
|
|
||||||
<a class="simple-link text-center w100 spacer" href="/register">
|
|
||||||
Register
|
|
||||||
</a>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
/* Login Page */
|
/* Login Page */
|
||||||
.login-page {
|
.login-page {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
& > div {
|
& > div {
|
||||||
width: 40vw;
|
width: 40vw;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import { onMount } from 'svelte';
|
||||||
import { userStore } from "../UserStore.svelte";
|
import { userStore } from '../UserStore.svelte';
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
userStore.user = undefined;
|
userStore.user = undefined;
|
||||||
goto('/');
|
goto('/');
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,105 +1,94 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import MessageSimple from "src/lib/MessageSimple.svelte";
|
import MessageSimple from 'src/lib/MessageSimple.svelte';
|
||||||
import { onMount } from "svelte";
|
import { onMount } from 'svelte';
|
||||||
import { get } from '$lib/requests.svelte'
|
import { get } from '$lib/requests.svelte';
|
||||||
|
|
||||||
let list = $state<{
|
let list = $state<
|
||||||
name: string,
|
{
|
||||||
id: string,
|
name: string;
|
||||||
}[]>([]);
|
id: string;
|
||||||
|
}[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
let message: MessageSimple;
|
let message: MessageSimple;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
try {
|
try {
|
||||||
list = await get("models");
|
list = await get('models');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Response) {
|
if (e instanceof Response) {
|
||||||
message.display(await e.json())
|
message.display(await e.json());
|
||||||
} else {
|
} else {
|
||||||
message.display("Could not request list of models");
|
message.display('Could not request list of models');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>
|
<title>Models</title>
|
||||||
Models
|
|
||||||
</title>
|
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<MessageSimple bind:this={message} />
|
<MessageSimple bind:this={message} />
|
||||||
{#if list.length > 0}
|
{#if list.length > 0}
|
||||||
<div class="list-header">
|
<div class="list-header">
|
||||||
<h2>My Models</h2>
|
<h2>My Models</h2>
|
||||||
<div class="expand"></div>
|
<div class="expand"></div>
|
||||||
<a class="button" href="/models/add">
|
<a class="button" href="/models/add"> New </a>
|
||||||
New
|
</div>
|
||||||
</a>
|
<table class="table">
|
||||||
</div>
|
<thead>
|
||||||
<table class="table">
|
<tr>
|
||||||
<thead>
|
<th> Name </th>
|
||||||
<tr>
|
<th>
|
||||||
<th>
|
<!-- Open Button -->
|
||||||
Name
|
</th>
|
||||||
</th>
|
</tr>
|
||||||
<th>
|
</thead>
|
||||||
<!-- Open Button -->
|
<tbody>
|
||||||
</th>
|
{#each list as item}
|
||||||
</tr>
|
<tr>
|
||||||
</thead>
|
<td>
|
||||||
<tbody>
|
{item.name}
|
||||||
{#each list as item}
|
</td>
|
||||||
<tr>
|
<td class="text-center">
|
||||||
<td>
|
<a class="button simple" href="/models/edit?id={item.id}"> Edit </a>
|
||||||
{item.name}
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
<td class="text-center">
|
{/each}
|
||||||
<a class="button simple" href="/models/edit?id={item.id}">
|
</tbody>
|
||||||
Edit
|
</table>
|
||||||
</a>
|
{:else}
|
||||||
</td>
|
<h2 class="text-center">You don't have any models</h2>
|
||||||
</tr>
|
<div class="text-center">
|
||||||
{/each}
|
<a class="button padded" href="/models/add"> Create a new model </a>
|
||||||
</tbody>
|
</div>
|
||||||
</table>
|
{/if}
|
||||||
{:else}
|
|
||||||
<h2 class="text-center">
|
|
||||||
You don't have any models
|
|
||||||
</h2>
|
|
||||||
<div class="text-center">
|
|
||||||
<a class="button padded" href="/models/add">
|
|
||||||
Create a new model
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
main {
|
main {
|
||||||
padding: 20px 15vw;
|
padding: 20px 15vw;
|
||||||
}
|
}
|
||||||
.list-header {
|
.list-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-header h2 {
|
.list-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 10px 5px;
|
padding: 10px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-header .expand {
|
.list-header .expand {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-header .button,
|
|
||||||
.list-header button {
|
|
||||||
padding: 10px 10px;
|
|
||||||
height: calc(100% - 20px);
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.list-header .button,
|
||||||
|
.list-header button {
|
||||||
|
padding: 10px 10px;
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,101 +1,91 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import FileUpload from "src/lib/FileUpload.svelte";
|
import FileUpload from 'src/lib/FileUpload.svelte';
|
||||||
import MessageSimple from "src/lib/MessageSimple.svelte";
|
import MessageSimple from 'src/lib/MessageSimple.svelte';
|
||||||
import { postFormData } from "src/lib/requests.svelte";
|
import { postFormData } from 'src/lib/requests.svelte';
|
||||||
import {goto} from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
import "src/styles/forms.css";
|
import 'src/styles/forms.css';
|
||||||
|
|
||||||
let submitted = $state(false);
|
let submitted = $state(false);
|
||||||
|
|
||||||
let message: MessageSimple;
|
let message: MessageSimple;
|
||||||
|
|
||||||
let buttonClicked: Promise<void> = $state(Promise.resolve());
|
let buttonClicked: Promise<void> = $state(Promise.resolve());
|
||||||
|
|
||||||
let data = $state<{
|
let data = $state<{
|
||||||
name: string,
|
name: string;
|
||||||
file?: File,
|
file?: File;
|
||||||
}>({
|
}>({
|
||||||
name: '',
|
name: '',
|
||||||
file: undefined,
|
file: undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
message.display("");
|
message.display('');
|
||||||
buttonClicked = new Promise<void>(() => {});
|
buttonClicked = new Promise<void>(() => {});
|
||||||
|
|
||||||
if (!data.file || !data.name) return;
|
if (!data.file || !data.name) return;
|
||||||
|
|
||||||
let formData = new FormData();
|
|
||||||
formData.append("name", data.name);
|
|
||||||
formData.append("file", data.file, 'base-image.png')
|
|
||||||
|
|
||||||
try {
|
|
||||||
let id = await postFormData('models/add', formData);
|
|
||||||
goto(`/models/edit?id=${id}`)
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof Response) {
|
|
||||||
message.display(await e.json())
|
|
||||||
} else {
|
|
||||||
message.display("Was not able to create model")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buttonClicked = Promise.resolve();
|
let formData = new FormData();
|
||||||
}
|
formData.append('name', data.name);
|
||||||
|
formData.append('file', data.file, 'base-image.png');
|
||||||
|
|
||||||
|
try {
|
||||||
|
let id = await postFormData('models/add', formData);
|
||||||
|
goto(`/models/edit?id=${id}`);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Response) {
|
||||||
|
message.display(await e.json());
|
||||||
|
} else {
|
||||||
|
message.display('Was not able to create model');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonClicked = Promise.resolve();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>Create new Model</title>
|
<title>Create new Model</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<h1>
|
<h1>Create new Model</h1>
|
||||||
Create new Model
|
<form class:submitted on:submit|preventDefault={onSubmit}>
|
||||||
</h1>
|
<fieldset>
|
||||||
<form class:submitted on:submit|preventDefault={onSubmit}>
|
<label for="name">Name</label>
|
||||||
<fieldset>
|
<input id="name" name="name" required bind:value={data.name} />
|
||||||
<label for="name">Name</label>
|
<!--{{if .NameFoundError}}
|
||||||
<input id="name" name="name" required bind:value={data.name} />
|
|
||||||
<!--{{if .NameFoundError}}
|
|
||||||
<span class="form-msg error">
|
<span class="form-msg error">
|
||||||
You already have a model with that name.
|
You already have a model with that name.
|
||||||
</span>
|
</span>
|
||||||
{{end}}-->
|
{{end}}-->
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="file-upload" >
|
<fieldset class="file-upload">
|
||||||
<label for="file">Base image</label>
|
<label for="file">Base image</label>
|
||||||
<div class="form-msg">
|
<div class="form-msg">
|
||||||
Please provide a base image.<br/>
|
Please provide a base image.<br />
|
||||||
This image is a sample of the images that you are going to classfiy.
|
This image is a sample of the images that you are going to classfiy.
|
||||||
</div>
|
</div>
|
||||||
<FileUpload replace_slot bind:file={data.file} >
|
<FileUpload replace_slot bind:file={data.file}>
|
||||||
<img src="/imgs/upload-icon.png" alt="" />
|
<img src="/imgs/upload-icon.png" alt="" />
|
||||||
<span>
|
<span> Upload image </span>
|
||||||
Upload image
|
<div slot="replaced-name">
|
||||||
</span>
|
<span> Image selected </span>
|
||||||
<div slot="replaced-name">
|
</div>
|
||||||
<span>
|
</FileUpload>
|
||||||
Image selected
|
</fieldset>
|
||||||
</span>
|
<MessageSimple bind:this={message} />
|
||||||
</div>
|
{#await buttonClicked}
|
||||||
</FileUpload>
|
<div class="text-center">File Uploading</div>
|
||||||
</fieldset>
|
{:then}
|
||||||
<MessageSimple bind:this={message} />
|
<button> Create </button>
|
||||||
{#await buttonClicked}
|
{/await}
|
||||||
<div class="text-center">
|
</form>
|
||||||
File Uploading
|
|
||||||
</div>
|
|
||||||
{:then}
|
|
||||||
<button>
|
|
||||||
Create
|
|
||||||
</button>
|
|
||||||
{/await}
|
|
||||||
</form>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
main {
|
main {
|
||||||
padding: 20px 15vw;
|
padding: 20px 15vw;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
import 'src/styles/forms.css';
|
import 'src/styles/forms.css';
|
||||||
|
|
||||||
let model: Promise<Model> = $state(new Promise(() => {}));
|
let model: Promise<Model> = $state(new Promise(() => {}));
|
||||||
let _model: Model | undefined = $state(undefined);
|
let _model: Model | undefined = $state(undefined);
|
||||||
let definitions: Promise<Definitions[]> = $state(new Promise(() => {}));
|
let definitions: Promise<Definitions[]> = $state(new Promise(() => {}));
|
||||||
|
|
||||||
let id: string | undefined = $state();
|
let id: string | undefined = $state();
|
||||||
@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
model = Promise.resolve(temp_model);
|
model = Promise.resolve(temp_model);
|
||||||
_model = temp_model;
|
_model = temp_model;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Response) {
|
if (e instanceof Response) {
|
||||||
model = Promise.reject(await e.json());
|
model = Promise.reject(await e.json());
|
||||||
@ -160,10 +160,10 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if _model}
|
{#if _model}
|
||||||
<ModelDataPage model={_model} on:reload={getModel} active={isActive('model-data')} />
|
<ModelDataPage model={_model} on:reload={getModel} active={isActive('model-data')} />
|
||||||
<TasksDataPage model={_model} active={isActive('tasks')} />
|
<TasksDataPage model={_model} active={isActive('tasks')} />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="content" class:selected={isActive('model')}>
|
<div class="content" class:selected={isActive('model')}>
|
||||||
{#await model}
|
{#await model}
|
||||||
Loading
|
Loading
|
||||||
|
@ -23,21 +23,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.model-card {
|
.model-card {
|
||||||
h1 {
|
h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.second-line {
|
.second-line {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,41 +1,39 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import MessageSimple from 'src/lib/MessageSimple.svelte';
|
import MessageSimple from 'src/lib/MessageSimple.svelte';
|
||||||
import type { Model } from './+page.svelte';
|
import type { Model } from './+page.svelte';
|
||||||
import { rdelete } from '$lib/requests.svelte'
|
import { rdelete } from '$lib/requests.svelte';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
let { model } = $props<{ model: Model }>();
|
|
||||||
let name: string = $state("");
|
|
||||||
let submmited: boolean = $state(false);
|
|
||||||
|
|
||||||
let messageSimple: MessageSimple;
|
let { model } = $props<{ model: Model }>();
|
||||||
|
let name: string = $state('');
|
||||||
|
let submmited: boolean = $state(false);
|
||||||
|
|
||||||
async function deleteModel() {
|
let messageSimple: MessageSimple;
|
||||||
submmited = true;
|
|
||||||
messageSimple.display("");
|
|
||||||
|
|
||||||
try {
|
async function deleteModel() {
|
||||||
await rdelete("models/delete", {id: model.id, name});
|
submmited = true;
|
||||||
goto("/models");
|
messageSimple.display('');
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof Response) {
|
try {
|
||||||
messageSimple.display(await e.json());
|
await rdelete('models/delete', { id: model.id, name });
|
||||||
} else {
|
goto('/models');
|
||||||
messageSimple.display("Could not delete the model");
|
} catch (e) {
|
||||||
}
|
if (e instanceof Response) {
|
||||||
}
|
messageSimple.display(await e.json());
|
||||||
}
|
} else {
|
||||||
|
messageSimple.display('Could not delete the model');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form on:submit|preventDefault={deleteModel} class:submmited>
|
<form on:submit|preventDefault={deleteModel} class:submmited>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="name">
|
<label for="name">
|
||||||
To delete this model please type "{model.name}":
|
To delete this model please type "{model.name}":
|
||||||
</label>
|
</label>
|
||||||
<input name="name" id="name" required bind:value={name} />
|
<input name="name" id="name" required bind:value={name} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<MessageSimple bind:this={messageSimple} />
|
<MessageSimple bind:this={messageSimple} />
|
||||||
<button class="danger">
|
<button class="danger"> Delete </button>
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,45 +1,42 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { rdelete } from "src/lib/requests.svelte";
|
import { rdelete } from 'src/lib/requests.svelte';
|
||||||
import type { Model } from "./+page.svelte";
|
import type { Model } from './+page.svelte';
|
||||||
import MessageSimple from "src/lib/MessageSimple.svelte";
|
import MessageSimple from 'src/lib/MessageSimple.svelte';
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
let message: MessageSimple;
|
let message: MessageSimple;
|
||||||
|
|
||||||
let { model, expand } = $props<{model: Model, expand?: boolean}>();
|
let { model, expand } = $props<{ model: Model; expand?: boolean }>();
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{reload: void}>();
|
const dispatch = createEventDispatcher<{ reload: void }>();
|
||||||
|
|
||||||
async function deleteZip() {
|
async function deleteZip() {
|
||||||
message.clear();
|
message.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await rdelete("models/data/delete-zip-file", { id: model.id });
|
await rdelete('models/data/delete-zip-file', { id: model.id });
|
||||||
dispatch('reload');
|
dispatch('reload');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Response) {
|
if (e instanceof Response) {
|
||||||
message.display(await e.json());
|
message.display(await e.json());
|
||||||
} else {
|
} else {
|
||||||
message.display("Could not delete the zip file");
|
message.display('Could not delete the zip file');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<form on:submit|preventDefault={deleteZip}>
|
<form on:submit|preventDefault={deleteZip}>
|
||||||
{#if expand}
|
{#if expand}
|
||||||
Failed to proccess the zip file.<br/>
|
Failed to proccess the zip file.<br />
|
||||||
Delete file and upload a correct version do add more classes.<br/>
|
Delete file and upload a correct version do add more classes.<br />
|
||||||
<br/>
|
<br />
|
||||||
{:else}
|
{:else}
|
||||||
Failed to proccess the zip file.<br/>
|
Failed to proccess the zip file.<br />
|
||||||
Delete file and proccess again.<br/>
|
Delete file and proccess again.<br />
|
||||||
<br/>
|
<br />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="spacer" ></div>
|
<div class="spacer"></div>
|
||||||
<MessageSimple bind:this={message} />
|
<MessageSimple bind:this={message} />
|
||||||
<button class="danger">
|
<button class="danger"> Delete Zip File </button>
|
||||||
Delete Zip File
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,48 +1,46 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from 'svelte';
|
||||||
import type { Model } from "./+page.svelte";
|
import type { Model } from './+page.svelte';
|
||||||
import ModelData from "./ModelData.svelte";
|
import ModelData from './ModelData.svelte';
|
||||||
import { post } from "src/lib/requests.svelte";
|
import { post } from 'src/lib/requests.svelte';
|
||||||
import ModelDataPageStatsGraph from "./ModelDataPageStatsGraph.svelte";
|
import ModelDataPageStatsGraph from './ModelDataPageStatsGraph.svelte';
|
||||||
import type { ModelStats } from "./types";
|
import type { ModelStats } from './types';
|
||||||
import DeleteZip from "./DeleteZip.svelte";
|
import DeleteZip from './DeleteZip.svelte';
|
||||||
|
|
||||||
let { model, active } = $props<{model: Model, active?: boolean}>()
|
let { model, active } = $props<{ model: Model; active?: boolean }>();
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{ reload: void }>();
|
|
||||||
|
|
||||||
$effect(() => {
|
const dispatch = createEventDispatcher<{ reload: void }>();
|
||||||
if (active)
|
|
||||||
getData();
|
|
||||||
});
|
|
||||||
|
|
||||||
let stats: ModelStats | undefined = $state();
|
$effect(() => {
|
||||||
|
if (active) getData();
|
||||||
|
});
|
||||||
|
|
||||||
async function getData() {
|
let stats: ModelStats | undefined = $state();
|
||||||
if (!model) return;
|
|
||||||
try {
|
|
||||||
stats = await post(`models/class/stats`, { id: model.id });
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
async function getData() {
|
||||||
|
if (!model) return;
|
||||||
|
try {
|
||||||
|
stats = await post(`models/class/stats`, { id: model.id });
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="content" class:selected={active}>
|
<div class="content" class:selected={active}>
|
||||||
|
{#if stats}
|
||||||
{#if stats}
|
<ModelDataPageStatsGraph data={stats} />
|
||||||
<ModelDataPageStatsGraph data={stats} />
|
{/if}
|
||||||
{/if}
|
|
||||||
|
|
||||||
|
{#if [-6, -2].includes(model.status)}
|
||||||
|
<DeleteZip {model} on:reload={() => dispatch('reload')} expand />
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if [-6, -2].includes(model.status)}
|
<ModelData
|
||||||
<DeleteZip model={model} on:reload={() => dispatch('reload')} expand />
|
{model}
|
||||||
{/if}
|
on:reload={() => {
|
||||||
|
getData();
|
||||||
<ModelData model={model} on:reload={() => {
|
dispatch('reload');
|
||||||
getData();
|
}}
|
||||||
dispatch('reload');
|
/>
|
||||||
}} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (data && ctx) {
|
if (data && ctx) {
|
||||||
if (chart) {
|
if (chart) {
|
||||||
console.log("update")
|
console.log('update');
|
||||||
chart.data = {
|
chart.data = {
|
||||||
labels: data.map((a) => a.name),
|
labels: data.map((a) => a.name),
|
||||||
datasets: [
|
datasets: [
|
||||||
@ -48,7 +48,7 @@
|
|||||||
};
|
};
|
||||||
chart.update('resize');
|
chart.update('resize');
|
||||||
} else {
|
} else {
|
||||||
console.log("create")
|
console.log('create');
|
||||||
chart = new Chart(ctx, {
|
chart = new Chart(ctx, {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
data: {
|
data: {
|
||||||
|
@ -113,9 +113,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<form class:submitted on:submit|preventDefault={submitRetrain}>
|
<form class:submitted on:submit|preventDefault={submitRetrain}>
|
||||||
{#if has_data}
|
{#if has_data}
|
||||||
<h2>
|
<h2>This model has new classes and can be expanded</h2>
|
||||||
This model has new classes and can be expanded
|
|
||||||
</h2>
|
|
||||||
{#if number_of_invalid_images > 0}
|
{#if number_of_invalid_images > 0}
|
||||||
<p class="danger">
|
<p class="danger">
|
||||||
There are images {number_of_invalid_images} that were loaded that do not have the correct format.DeleteZip
|
There are images {number_of_invalid_images} that were loaded that do not have the correct format.DeleteZip
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export type ModelStats = Array<{
|
export type ModelStats = Array<{
|
||||||
name: string,
|
name: string;
|
||||||
training: number,
|
training: number;
|
||||||
testing: number,
|
testing: number;
|
||||||
}>
|
}>;
|
||||||
|
Loading…
Reference in New Issue
Block a user