fyp/webpage/src/routes/models/edit/RunModel.svelte
Andre Henriques 0ac6ac8dce runner-go (#102)
Reviewed-on: #102
Co-authored-by: Andre Henriques <andr3h3nriqu3s@gmail.com>
Co-committed-by: Andre Henriques <andr3h3nriqu3s@gmail.com>
2024-05-10 02:13:02 +01:00

180 lines
5.2 KiB
Svelte

<script lang="ts">
import { post, postFormData, showMessage } from 'src/lib/requests.svelte';
import type { Model } from './+page.svelte';
import FileUpload from 'src/lib/FileUpload.svelte';
import MessageSimple from 'src/lib/MessageSimple.svelte';
import { createEventDispatcher, onDestroy } from 'svelte';
import Spinner from 'src/lib/Spinner.svelte';
import type { Task } from './tasks/TasksTable.svelte';
import Tabs from 'src/lib/Tabs.svelte';
import hljs from 'highlight.js';
import { notificationStore } from 'src/lib/NotificationsStore.svelte';
let { model } = $props<{ model: Model }>();
let file: File | undefined = $state();
const dispatch = createEventDispatcher<{ upload: void; taskReload: void }>();
let _result: Promise<Task> = $state(new Promise(() => {}));
let run = $state(false);
let last_task: string | undefined = $state();
let last_task_timeout: number | null = null;
async function reloadLastTimeout() {
if (!last_task) {
return;
}
last_task_timeout = null;
try {
const r = await post('tasks/task', { id: last_task });
if ([0, 1, 2, 3].includes(r.status)) {
setTimeout(reloadLastTimeout, 500);
setTimeout(() => dispatch('taskReload'), 500);
} else {
_result = Promise.resolve(r);
}
} catch (e) {
console.error('Failed to get data');
}
}
async function submit() {
if (!file) return;
let form = new FormData();
form.append('json_data', JSON.stringify({ id: model.id }));
form.append('file', file, 'file');
run = true;
try {
const r = await postFormData('tasks/start/image', form);
last_task = r.id;
file = undefined;
last_task_timeout = setTimeout(() => reloadLastTimeout());
} catch (e) {
showMessage(e, notificationStore, 'Could not run the model');
}
dispatch('upload');
}
onDestroy(() => {
if (last_task_timeout) {
clearTimeout(last_task_timeout);
}
});
</script>
<Tabs active="upload" let:isActive>
<div class="buttons" slot="buttons" let:setActive let:isActive>
<button class="tab" class:selected={isActive('upload')} on:click={setActive('upload')}>
Upload
</button>
<button class="tab" class:selected={isActive('api')} on:click={setActive('api')}> Api </button>
</div>
<div class="content" class:selected={isActive('api')}>
<div class="codeinfo">
To perform an image classfication please follow the example bellow:
<pre style="font-family: Fira Code;">{@html hljs.highlight(
`let form = new FormData();
form.append('json_data', JSON.stringify({ id: '${model.id}' }));
form.append('file', file, 'file');
const headers = new Headers();
headers.append('response-type', 'application/json');
headers.append('token', token);
const r = await fetch('${window.location.protocol}//${window.location.hostname}/api/tasks/start/image', {
method: 'POST',
headers: headers,
body: form
});`,
{ language: 'javascript' }
).value}</pre>
On Success the request will return a json with this format:
<pre style="font-family: Fira Code;">{@html hljs.highlight(
`{ id "00000000-0000-0000-0000-000000000000" }`,
{ language: 'json' }
).value}</pre>
This id can be used to query the API for the result of the task:
<pre style="font-family: Fira Code;">{@html hljs.highlight(
`const headers = new Headers();
headers.append('content-type', 'application/json');
headers.append('token', token);
const r = await fetch('${window.location.protocol}//${window.location.hostname}/api/tasks/task', {
method: 'POST',
headers: headers,
body: JSON.stringify({ id: '00000000-0000-0000-0000-000000000000' })
});`,
{ language: 'javascript' }
).value}</pre>
Once the task shows the status as 4 then the data can be obatined in the result field: The successful
return value has this type:
<pre style="font-family: Fira Code;">{@html hljs.highlight(
`{
"id": string,
"user_id": string,
"model_id": string,
"status": number,
"status_message": string,
"user_confirmed": number,
"compacted": number,
"type": number,
"extra_task_info": string,
"result": string,
"created": string
}`,
{ language: 'javascript' }
).value}</pre>
</div>
</div>
<div class="content" class:selected={isActive('upload')}>
<form on:submit|preventDefault={submit} style="box-shadow: none;">
<fieldset class="file-upload">
<label for="file">Image</label>
<div class="form-msg">Run image through them model and get the result</div>
<FileUpload replace_slot bind:file accept="image/*">
<img src="/imgs/upload-icon.png" alt="" />
<span> Upload image </span>
<div slot="replaced-name">
<span> Image selected </span>
</div>
</FileUpload>
</fieldset>
<button> Run </button>
{#if run}
{#await _result}
<h1>
Processing Image! <Spinner />
</h1>
{:then result}
{#if result.status == 4}
{@const res = JSON.parse(result.result)}
<div>
<h1>Result</h1>
The image was classified as {res.class} with confidence: {res.confidence}
</div>
{:else}
<div class="result">
<h1>There was a problem running the task:</h1>
{result?.status_message}
</div>
{/if}
{/await}
{/if}
</form>
</div>
</Tabs>
<style lang="scss">
.codeinfo {
padding: 20px;
}
</style>