Reviewed-on: #102 Co-authored-by: Andre Henriques <andr3h3nriqu3s@gmail.com> Co-committed-by: Andre Henriques <andr3h3nriqu3s@gmail.com>
180 lines
5.2 KiB
Svelte
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>
|