Files
fyp/webpage/src/routes/models/edit/ModelData.svelte

136 lines
4.2 KiB
Svelte

<script lang="ts">
import FileUpload from 'src/lib/FileUpload.svelte';
import Tabs from 'src/lib/Tabs.svelte';
import type { Model } from './+page.svelte';
import type { Class } from './types';
import { postFormData, get, showMessage } from 'src/lib/requests.svelte';
import ModelTable from './ModelTable.svelte';
import TrainModel from './TrainModel.svelte';
import ZipStructure from './ZipStructure.svelte';
import { notificationStore } from 'src/lib/NotificationsStore.svelte';
import { preventDefault } from 'src/lib/utils';
let {
model,
simple,
onreload = () => {}
}: { model: Model; simple?: boolean; onreload?: () => void } = $props();
let classes: Class[] = $state([]);
let has_data: boolean = $state(false);
let file: File | undefined = $state();
let uploading: Promise<void> = $state(Promise.resolve());
let numberOfInvalidImages = $state(0);
async function uploadZip() {
if (!file) return;
uploading = new Promise(() => {});
let form = new FormData();
form.append('id', model.id);
form.append('file', file, 'upload.zip');
try {
await postFormData('models/data/upload', form);
onreload();
} catch (e) {
showMessage(e, notificationStore, 'Could not upload data');
}
uploading = Promise.resolve();
}
$effect(() => {
getData();
});
async function getData() {
if (!model) return;
try {
let data = await get(`models/edit/classes?id=${model.id}`);
classes = data.classes;
numberOfInvalidImages = data.number_of_invalid_images;
has_data = data.has_data;
} catch (e) {
showMessage(e, notificationStore, 'Could not get information on classes');
}
}
</script>
{#if !simple}
<div class="card">
<h3>Training data</h3>
{#if classes.length == 0}
<p>You need to upload data so the model can train.</p>
<Tabs active="upload" let:isActive>
<div slot="buttons" let:setActive let:isActive>
<button class="tab" class:selected={isActive('upload')} onclick={setActive('upload')}>
Upload
</button>
<!--button
class="tab"
class:selected={isActive('create-class')}
onclick={setActive('create-class')}
>
Create Class
</button-->
<!--button class="tab" class:selected={isActive('api')} onclick={setActive('api')}>
Api
</button-->
</div>
<div class="content" class:selected={isActive('upload')}>
<form onsubmit={preventDefault(uploadZip)}>
<fieldset class="file-upload">
<label for="file">Data file</label>
<div class="form-msg">
Please provide a file that has the training and testing data<br />
The file must have 2 folders one with testing images and one with training images.
<br />
Each of the folders will contain the classes of the model. The folders must be the same
in testing and training. The class folders must have the images for the classes.
<ZipStructure />
</div>
<FileUpload replace_slot bind:file accept="application/zip" notExpand>
<img src="/imgs/upload-icon.png" alt="" />
<span> Upload Zip File </span>
<div slot="replaced" style="display: inline;">
<img src="/imgs/upload-icon.png" alt="" />
<span> File selected </span>
</div>
</FileUpload>
</fieldset>
{#if file}
{#await uploading}
<button disabled> Uploading </button>
{:then}
<button> Add </button>
{/await}
{/if}
</form>
</div>
<!--div class="content" class:selected={isActive('create-class')}>
<ModelTable {classes} {model} {onreload} />
</div-->
<!--div class="content" class:selected={isActive('api')}>TODO</div-->
</Tabs>
<div class="tabs"></div>
{:else}
<p>You need to upload data so the model can train.</p>
{#if numberOfInvalidImages > 0}
<p class="danger">
There are images {numberOfInvalidImages} that were loaded that do not have the correct format.
These images will be deleted when the model trains.
</p>
{/if}
<ModelTable {classes} {model} {onreload} />
{/if}
</div>
{/if}
{#if classes.some((item) => item.status == 1) && ![-6, 6].includes(model.status)}
<TrainModel number_of_invalid_images={numberOfInvalidImages} {model} {has_data} {onreload} />
{/if}