540 lines
21 KiB
HTML
540 lines
21 KiB
HTML
{{ define "title" }}
|
|
Model: {{ .Model.Name }}
|
|
{{ end }}
|
|
|
|
{{ define "base-model-card" }}
|
|
<div class="card model-card">
|
|
<h1>
|
|
{{ .Model.Name }}
|
|
</h1>
|
|
<div class="second-line">
|
|
<img src="/savedData/{{ .Model.Id }}/baseimage.png" />
|
|
<div class="info">
|
|
<div>
|
|
<span class="bold bigger">Image Type:</span> {{ .Model.Color_mode }}
|
|
</div>
|
|
<div>
|
|
<span class="bold bigger">Image Size:</span> {{ .Model.Width }}x{{ .Model.Height }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{ end }}
|
|
|
|
{{ define "delete-model-card" }}
|
|
<form hx-delete="/models/delete" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML" {{ if .Error }} class="submitted" {{end}} >
|
|
<fieldset>
|
|
<span>
|
|
To delete this model please type "{{ .Model.Name }}":
|
|
</span>
|
|
<label for="name">Name</label>
|
|
<input name="name" id="name" required />
|
|
{{ if .NameDoesNotMatch }}
|
|
<span class="form-msg red">
|
|
Name does not match "{{ .Model.Name }}"
|
|
</span>
|
|
{{ end }}
|
|
</fieldset>
|
|
<input type="hidden" name="id" value="{{ .Model.Id }}" />
|
|
<button class="danger">
|
|
Delete
|
|
</button>
|
|
</form>
|
|
{{ end }}
|
|
|
|
{{/* Is called from a diffrent endpoint so that it does not matter where this is from :) which means that . can mean what ever I want */}}
|
|
{{ define "data-model-create-class-table-table" }}
|
|
<div>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>
|
|
File Path
|
|
</th>
|
|
<th>
|
|
Mode
|
|
</th>
|
|
<th>
|
|
<!-- Img -->
|
|
</th>
|
|
<th>
|
|
<!-- Status -->
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{range .List}}
|
|
<tr>
|
|
<td>
|
|
{{ if eq .FilePath "id://" }}
|
|
Managed
|
|
{{ else }}
|
|
{{.FilePath}}
|
|
{{ end }}
|
|
</td>
|
|
<td>
|
|
{{ if (eq .Mode 2) }}
|
|
Testing
|
|
{{ else }}
|
|
Training
|
|
{{ end }}
|
|
</td>
|
|
<td class="text-center">
|
|
{{ if startsWith .FilePath "id://" }}
|
|
<img src="/savedData/{{ $.Model.Id }}/data/{{ .Id }}.{{ $.Model.Format }}" height="30px" width="30px" style="object-fit: contain;" />
|
|
{{ else }}
|
|
TODO
|
|
img {{ .FilePath }}
|
|
{{ end }}
|
|
</td>
|
|
<td class="text-center">
|
|
{{ if eq .Status 1 }}
|
|
<span class="bi bi-check-circle-fill" style="color: green"></span>
|
|
{{ else }}
|
|
<span class="bi bi-exclamation-triangle-fill" style="color: red"></span>
|
|
{{ end }}
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
<div class="flex justify-center align-center">
|
|
<div class="grow-1 flex justify-end align-center ">
|
|
{{ if gt .Page 0 }}
|
|
<button
|
|
hx-get="/models/data/list?id={{ .Id }}&page={{ add .Page -1 }}"
|
|
hx-target=".content[data-tab='{{ .Name }}']"
|
|
hx-swap="innerHTML"
|
|
hx-headers='{"REQUEST-TYPE": "html"}'
|
|
data-tab="{{ .Name }}">
|
|
Prev
|
|
</button>
|
|
{{ end }}
|
|
</div>
|
|
|
|
<div style="padding: 10px;">
|
|
{{ .Page }}
|
|
</div>
|
|
|
|
<div class="grow-1 flex justify-start align-center">
|
|
{{ if lt (mul .Page 10) .Count }}
|
|
<button
|
|
hx-get="/models/data/list?id={{ .Id }}&page={{ add .Page 1 }}"
|
|
hx-target=".content[data-tab='{{ .Name }}']"
|
|
hx-swap="innerHTML"
|
|
hx-headers='{"REQUEST-TYPE": "html"}'
|
|
data-tab="{{ .Name }}">
|
|
Next
|
|
</button>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{ end }}
|
|
|
|
{{ define "data-model-create-class-table" }}
|
|
{{ if eq (len .Classes) 0 }}
|
|
TODO CREATE TABLE
|
|
{{else}}
|
|
<div class="tabs-header">
|
|
{{/* Handle the case where there are to many buttons */}}
|
|
<div class="header">
|
|
{{ range .Classes }}
|
|
{{/* TODO Auto Load 1st */}}
|
|
<button
|
|
hx-get="/models/data/list?id={{ .Id }}"
|
|
hx-target=".content[data-tab='{{ .Name }}']"
|
|
hx-swap="innerHTML"
|
|
hx-headers='{"REQUEST-TYPE": "html"}'
|
|
hx-trigger="click"
|
|
class="tab"
|
|
data-tab="{{ .Name }}">
|
|
{{ .Name }}
|
|
</button>
|
|
{{ end }}
|
|
</div>
|
|
{{ range $i, $a := .Classes }}
|
|
{{ if eq $i 0}}
|
|
<div
|
|
hx-get="/models/data/list?id={{ .Id }}"
|
|
hx-target=".content[data-tab='{{ $a.Name }}']"
|
|
hx-swap="innerHTML"
|
|
hx-headers='{"REQUEST-TYPE": "html"}'
|
|
hx-trigger="load"
|
|
class="content"
|
|
data-tab="{{ $a.Name }}">
|
|
</div>
|
|
{{ else }}
|
|
<div
|
|
class="content"
|
|
data-tab="{{ $a.Name }}" >
|
|
</div>
|
|
{{ end }}
|
|
{{ end }}
|
|
</div>
|
|
{{end}}
|
|
{{ end }}
|
|
|
|
{{ define "data-model-card" }}
|
|
<div class="card">
|
|
<h3>
|
|
Training data
|
|
</h3>
|
|
{{ if eq (len .Classes) 0 }}
|
|
<p>
|
|
You need to upload data so the model can train.
|
|
</p>
|
|
<div class="tabs">
|
|
<button class="tab" data-tab="upload">
|
|
Upload
|
|
</button>
|
|
<button class="tab" data-tab="create_class">
|
|
Create Class
|
|
</button>
|
|
<button class="tab" data-tab="api">
|
|
Api
|
|
</button>
|
|
<div class="content" data-tab="upload">
|
|
<form hx-headers='{"REQUEST-TYPE": "htmlfull"}' enctype="multipart/form-data" hx-post="/models/data/upload">
|
|
<input type="hidden" name="id" value={{.Model.Id}} />
|
|
<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.
|
|
<pre>
|
|
training\
|
|
class1\
|
|
img1.png
|
|
img2.png
|
|
img2.png
|
|
...
|
|
class2\
|
|
img1.png
|
|
img2.png
|
|
img2.png
|
|
...
|
|
...
|
|
testing\
|
|
class1\
|
|
img1.png
|
|
img2.png
|
|
img2.png
|
|
...
|
|
class2\
|
|
img1.png
|
|
img2.png
|
|
img2.png
|
|
...
|
|
...
|
|
</pre>
|
|
</div>
|
|
<div class="icon-holder">
|
|
<button class="icon">
|
|
<img replace="icon" src="/imgs/upload-icon.png" />
|
|
<span replace="File Selected">
|
|
Upload Zip File
|
|
</span>
|
|
</button>
|
|
<input id="file" name="file" type="file" required accept="application/zip" />
|
|
</div>
|
|
</fieldset>
|
|
<button>
|
|
Add
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="content" data-tab="create_class">
|
|
{{ template "data-model-create-class-table" . }}
|
|
</div>
|
|
<div class="content" data-tab="api">
|
|
TODO
|
|
</div>
|
|
</div>
|
|
{{ else }}
|
|
<p>
|
|
You need to upload data so the model can train.
|
|
</p>
|
|
{{ if gt .NumberOfInvalidImages 0 }}
|
|
<p class="danger">
|
|
There are images {{ .NumberOfInvalidImages }} that were loaded that do not have the correct format. These images will be delete when the model trains.
|
|
</p>
|
|
{{ end }}
|
|
<div class="tabs">
|
|
<button class="tab" data-tab="create_class">
|
|
Create Class
|
|
</button>
|
|
<button class="tab" data-tab="api">
|
|
Api
|
|
</button>
|
|
<div class="content" data-tab="create_class">
|
|
{{ template "data-model-create-class-table" . }}
|
|
</div>
|
|
<div class="content" data-tab="api">
|
|
TODO
|
|
</div>
|
|
</div>
|
|
{{ end }}
|
|
</div>
|
|
{{ end }}
|
|
|
|
{{ define "train-model-card" }}
|
|
<form hx-post="/models/train" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML" {{ if .Error }} class="submitted" {{end}} >
|
|
{{ if .HasData }}
|
|
{{ if gt .NumberOfInvalidImages 0 }}
|
|
<p class="danger">
|
|
There are images {{ .NumberOfInvalidImages }} that were loaded that do not have the correct format. These images will be delete when the model trains.
|
|
</p>
|
|
{{ end }}
|
|
{{/* TODO expading mode */}}
|
|
<input type="hidden" value="{{ .Model.Id }}" name="id" />
|
|
<fieldset>
|
|
<legend>
|
|
Model Type
|
|
</legend>
|
|
<div class="input-radial">
|
|
<input id="model_type_simple" value="simple" name="model_type" type="radio" checked />
|
|
<label for="model_type_simple">Simple</label>
|
|
</div>
|
|
</fieldset>
|
|
{{/* TODO allow more models to be created */}}
|
|
<fieldset>
|
|
<label for="number_of_models">Number of Models</label>
|
|
<input id="number_of_models" type="number" name="number_of_models" value="1" />
|
|
</fieldset>
|
|
{{/* TODO to Change the acc */}}
|
|
<fieldset>
|
|
<label for="accuracy">Target accuracy</label>
|
|
<input id="accuracy" type="number" name="accuracy" value="95" />
|
|
</fieldset>
|
|
{{/* TODO allow to chose the base of the model */}}
|
|
{{/* TODO allow to change the shape of the model */}}
|
|
<button>
|
|
Train
|
|
</button>
|
|
{{ else }}
|
|
<h2>
|
|
To train the model please provide data to the model first
|
|
</h2>
|
|
{{ end }}
|
|
</form>
|
|
{{ end }}
|
|
|
|
{{ define "run-model-card" }}
|
|
<form hx-headers='{"REQUEST-TYPE": "html"}' enctype="multipart/form-data" hx-post="/models/run" hx-swap="outerHTML">
|
|
{{ if .NotFound }}
|
|
<div>
|
|
The class was not found
|
|
</div>
|
|
{{ else if .Result }}
|
|
<div>
|
|
Img Class: {{.Result}}
|
|
</div>
|
|
{{ end }}
|
|
<input type="hidden" name="id" value={{.Model.Id}} />
|
|
<fieldset class="file-upload" >
|
|
<label for="file">Image</label>
|
|
<div class="form-msg">
|
|
Run image through them model and get the result
|
|
</div>
|
|
<div class="icon-holder">
|
|
<button class="icon">
|
|
<img replace="icon" src="/imgs/upload-icon.png" />
|
|
<span replace="File Selected">
|
|
Image File
|
|
</span>
|
|
</button>
|
|
{{ if .ImageError }}
|
|
<span class="form-msg error">
|
|
The provided image was not valid for this model
|
|
</span>
|
|
{{ end }}
|
|
<input id="file" name="file" type="file" required accept="image/png" />
|
|
</div>
|
|
</fieldset>
|
|
<button>
|
|
Run
|
|
</button>
|
|
</form>
|
|
{{ end }}
|
|
|
|
{{ define "mainbody" }}
|
|
<main>
|
|
{{ if (eq .Model.Status 1) }}
|
|
<div>
|
|
<h1 class="text-center">
|
|
{{ .Model.Name }}
|
|
</h1>
|
|
<!-- TODO add cool animation -->
|
|
<h2 class="text-center">
|
|
Preparing the model
|
|
</h2>
|
|
</div>
|
|
{{ else if (eq .Model.Status -1) }}
|
|
<div>
|
|
<h1 class="text-center">
|
|
{{ .Model.Name }}
|
|
</h1>
|
|
<!-- TODO improve message -->
|
|
<h2 class="text-center">
|
|
Failed to prepare model
|
|
</h2>
|
|
|
|
<form hx-delete="/models/delete">
|
|
<input type="hidden" name="id" value="{{ .Model.Id }}" />
|
|
<button class="danger">
|
|
Delete
|
|
</button>
|
|
</form>
|
|
</div>
|
|
{{/* PRE TRAINING STATUS */}}
|
|
{{ else if (eq .Model.Status 2) }}
|
|
{{ template "base-model-card" . }}
|
|
{{ template "data-model-card" . }}
|
|
{{ template "train-model-card" . }}
|
|
{{ template "delete-model-card" . }}
|
|
{{/* FAILED TO PROCCESS THE ZIPFILE */}}
|
|
{{ else if (eq .Model.Status -2)}}
|
|
{{ template "base-model-card" . }}
|
|
<form hx-delete="/models/data/delete-zip-file" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML">
|
|
Failed to proccess the zip file.<br/>
|
|
Delete file and proccess afain.<br/>
|
|
<br/>
|
|
<div class="spacer" ></div>
|
|
<input type="hidden" name="id" value="{{ .Model.Id }}" />
|
|
<button class="danger">
|
|
Delete Zip File
|
|
</button>
|
|
</form>
|
|
{{ template "delete-model-card" . }}
|
|
{{/* PROCCESS THE ZIPFILE */}}
|
|
{{ else if (eq .Model.Status 3)}}
|
|
{{ template "base-model-card" . }}
|
|
<div class="card" hx-get="/models/edit?id={{ .Model.Id }}" hx-headers='{"REQUEST-TYPE": "htmlfull"}' hx-push="true" hx-swap="outerHTML" hx-target=".app" hx-trigger="load delay:2s" >
|
|
{{/* TODO improve this */}}
|
|
Processing zip file...
|
|
</div>
|
|
{{/* FAILED TO Prepare for training */}}
|
|
{{ else if or (eq .Model.Status -3) (eq .Model.Status -4)}}
|
|
{{ template "base-model-card" . }}
|
|
<form hx-delete="/models/train/reset" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML">
|
|
Failed Prepare for training.<br/>
|
|
<div class="spacer" ></div>
|
|
<input type="hidden" name="id" value="{{ .Model.Id }}" />
|
|
<button class="danger">
|
|
Try Again
|
|
</button>
|
|
</form>
|
|
{{ template "delete-model-card" . }}
|
|
{{ else if (eq .Model.Status 4)}}
|
|
{{ template "base-model-card" . }}
|
|
<div class="card" hx-get="/models/edit?id={{ .Model.Id }}" hx-headers='{"REQUEST-TYPE": "htmlfull"}' hx-push="true" hx-swap="outerHTML" hx-target=".app" hx-trigger="load delay:2s" >
|
|
{{/* TODO improve this */}}
|
|
Training the model...<br/>
|
|
{{/* TODO Add progress status on definitions */}}
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>
|
|
Done Progress
|
|
</th>
|
|
<th>
|
|
Training Round Progress
|
|
</th>
|
|
<th>
|
|
Accuracy
|
|
</th>
|
|
<th>
|
|
Status
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{ range .Defs}}
|
|
<tr>
|
|
<td>
|
|
{{.Epoch}}
|
|
</td>
|
|
<td>
|
|
{{.EpochProgress}}/20
|
|
</td>
|
|
<td>
|
|
{{.Accuracy}}%
|
|
</td>
|
|
<td style="text-align: center;">
|
|
{{ if (eq .Status 2) }}
|
|
<span class="bi bi-book" style="color: green;"></span>
|
|
{{ else if (eq .Status 3) }}
|
|
<span class="bi bi-book-half" style="color: green;"></span>
|
|
{{ else if (eq .Status 6) }}
|
|
<span class="bi bi-book-half" style="color: orange;"></span>
|
|
{{ else if (eq .Status -3) }}
|
|
<span class="bi bi-book-half" style="color: red;"></span>
|
|
{{ else }}
|
|
{{.Status}}
|
|
{{ end }}
|
|
</td>
|
|
</tr>
|
|
{{ if (eq .Status 3) }}
|
|
<tr>
|
|
<td colspan="4">
|
|
<svg viewBox="0 200 1000 600">
|
|
{{ range $i, $layer := $.Layers }}
|
|
{{ if (eq $layer.LayerType 1)}}
|
|
<polygon
|
|
points="50,450 200,250 200,550 50,750"
|
|
stroke="black"
|
|
stroke-width="2"
|
|
fill="green"></polygon>
|
|
{{ else if (eq $layer.LayerType 4)}}
|
|
<polygon
|
|
points="{{add 50 (mul $i $.SepMod) }},450 {{ add 200 (mul $i $.SepMod) }},250 {{add 200 (mul $i $.SepMod)}},550 {{ add 50 (mul $i $.SepMod) }},750"
|
|
stroke="black"
|
|
stroke-width="2"
|
|
fill="orange">
|
|
</polygon>
|
|
{{ else if (eq $layer.LayerType 3)}}
|
|
<polygon
|
|
points="{{add 50 (mul $i $.SepMod) }},450 {{ add 200 (mul $i $.SepMod) }},250 {{add 200 (mul $i $.SepMod)}},550 {{ add 50 (mul $i $.SepMod) }},750"
|
|
stroke="black"
|
|
stroke-width="2"
|
|
fill="red">
|
|
</polygon>
|
|
{{ else if (eq $layer.LayerType 2)}}
|
|
<polygon
|
|
points="{{add 50 (mul $i $.SepMod) }},550 {{ add 200 (mul $i $.SepMod) }},350 {{add 200 (mul $i $.SepMod)}},450 {{ add 50 (mul $i $.SepMod) }},650"
|
|
stroke="black"
|
|
stroke-width="2"
|
|
fill="blue">
|
|
</polygon>
|
|
{{ else }}
|
|
<div>
|
|
{{ .LayerType }}
|
|
{{ .Shape }}
|
|
</div>
|
|
{{ end }}
|
|
{{ end }}
|
|
</svg>
|
|
</td>
|
|
</tr>
|
|
{{ end }}
|
|
{{ end }}
|
|
</tbody>
|
|
</table>
|
|
{{/* TODO Add ability to stop training */}}
|
|
</div>
|
|
{{/* Model Ready */}}
|
|
{{ else if (eq .Model.Status 5)}}
|
|
{{ template "base-model-card" . }}
|
|
{{ template "run-model-card" . }}
|
|
{{ template "delete-model-card" . }}
|
|
{{ else }}
|
|
<h1>
|
|
Unknown Status of the model.
|
|
</h1>
|
|
{{ end }}
|
|
</main>
|
|
{{ end }}
|