feat: #10 added the base for the class on the page

This commit is contained in:
Andre Henriques 2023-09-23 11:44:36 +01:00
parent 1964303dce
commit 04de6ad574
8 changed files with 273 additions and 13 deletions

View File

@ -15,22 +15,22 @@ type User struct {
var ErrUserNotFound = errors.New("User Not found") var ErrUserNotFound = errors.New("User Not found")
func UserFromToken(db *sql.DB, token string) (*User, error) { func UserFromToken(db *sql.DB, token string) (*User, error) {
row, err := db.Query("select users.id, users.username, users.email, users.user_type from users inner join tokens on tokens.user_id = users.id where tokens.token = $1;", token) rows, err := db.Query("select users.id, users.username, users.email, users.user_type from users inner join tokens on tokens.user_id = users.id where tokens.token = $1;", token)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close()
var id string var id string
var username string var username string
var email string var email string
var user_type int var user_type int
if !row.Next() { if !rows.Next() {
return nil, ErrUserNotFound return nil, ErrUserNotFound
} }
err = row.Scan(&id, &username, &email, &user_type) err = rows.Scan(&id, &username, &email, &user_type)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -0,0 +1,101 @@
package model_classes
import (
"fmt"
"net/http"
"strconv"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
)
func HandleList(handle *Handle) {
handle.Get("/models/data/list", func(w http.ResponseWriter, r *http.Request, c *Context) *Error {
if !CheckAuthLevel(1, w, r, c) {
return nil
}
if c.Mode == JSON {
panic("TODO JSON on /models/data/list")
}
id, err := GetIdFromUrl(r, "id")
if err != nil {
return ErrorCode(err, 400, c.AddMap(nil))
}
page := 0
if r.URL.Query().Has("page") {
page_url := r.URL.Query().Get("page")
page_url_number, err := strconv.Atoi(page_url)
if err != nil {
return ErrorCode(err, http.StatusBadRequest, c.AddMap(nil))
}
page = page_url_number
}
class_rows, err := handle.Db.Query("select name, model_id from model_classes where id=$1;", id)
if err != nil {
return Error500(err)
}
defer class_rows.Close()
if !class_rows.Next() {
return ErrorCode(nil, 404, c.AddMap(nil))
}
name := ""
model_id := ""
if err = class_rows.Scan(&name, &model_id); err != nil {
return Error500(nil)
}
rows, err := handle.Db.Query("select id, file_path, model_mode from model_data_point where class_id=$1 limit 10 offset $2;", id, page * 10)
if err != nil {
return Error500(err)
}
defer rows.Close()
type baserow struct {
Id string
FilePath string
Mode int
}
got := []baserow{}
for rows.Next() {
nrow := baserow{}
err = rows.Scan(&nrow.Id, &nrow.FilePath, &nrow.Mode)
if err != nil {
return Error500(err)
}
got = append(got, nrow)
}
rows_count, err := handle.Db.Query("select count(*) from model_data_point where class_id=$1;", id)
if err != nil {
return Error500(err)
}
defer rows_count.Close()
if !rows_count.Next() {
fmt.Printf("select count(*) from model_data_point where class_id='%s';\n", id)
return Error500(nil)
}
count := 0
err = rows_count.Scan(&count)
if err != nil {
return Error500(err)
}
LoadDefineTemplate(w, "/models/edit.html", "data-model-create-class-table-table", c.AddMap(AnyMap{
"List": got,
"Count": count,
"Page": page,
"Id": id,
"Name": name,
"ModelId": model_id,
}))
return nil
})
}

View File

@ -122,6 +122,8 @@ func processZipFile(handle *Handle, id string) {
file_data, err := io.ReadAll(data) file_data, err := io.ReadAll(data)
f.Write(file_data) f.Write(file_data)
// TODO check if the file is a valid photo that matched the defined photo on the database
parts := strings.Split(file.Name, "/") parts := strings.Split(file.Name, "/")
mode := model_classes.DATA_POINT_MODE_TRAINING mode := model_classes.DATA_POINT_MODE_TRAINING

View File

@ -92,7 +92,7 @@ func handleDelete(handle *Handle) {
name := f.Get("name") name := f.Get("name")
if name != model.Name { if name != model.Name {
LoadError(w, "/models/edit.html", "delete-model-card", c.AddMap(AnyMap{ LoadDefineTemplate(w, "/models/edit.html", "delete-model-card", c.AddMap(AnyMap{
"NameDoesNotMatch": true, "NameDoesNotMatch": true,
"Model": model, "Model": model,
})) }))

View File

@ -1,6 +1,7 @@
package models package models
import ( import (
model_classes "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/classes"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )
@ -12,5 +13,7 @@ func HandleModels (handle *Handle) {
// Data endpoints // Data endpoints
handleDataUpload(handle) handleDataUpload(handle)
model_classes.HandleList(handle)
} }

View File

@ -16,8 +16,22 @@ import (
dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
) )
func Mul (n1 int, n2 int) int {
return n1 * n2
}
func Add (n1 int, n2 int) int {
return n1 + n2
}
func baseLoadTemplate(base string, path string) (*template.Template, any) { func baseLoadTemplate(base string, path string) (*template.Template, any) {
return template.New(base).ParseFiles( funcs := map[string]any {
"startsWith": strings.HasPrefix,
"replace": strings.Replace,
"mul": Mul,
"add": Add,
}
return template.New(base).Funcs(funcs).ParseFiles(
"./views/"+base, "./views/"+base,
"./views/"+path, "./views/"+path,
"./views/partials/header.html", "./views/partials/header.html",
@ -82,7 +96,7 @@ func LoadHtml(writer http.ResponseWriter, path string, data interface{}) {
} }
} }
func LoadError(writer http.ResponseWriter, path string, base string, data AnyMap) { func LoadDefineTemplate(writer http.ResponseWriter, path string, base string, data AnyMap) {
if data == nil { if data == nil {
data = map[string]interface{} { data = map[string]interface{} {
"Error": true, "Error": true,
@ -91,7 +105,14 @@ func LoadError(writer http.ResponseWriter, path string, base string, data AnyMap
data["Error"] = true data["Error"] = true
} }
tmpl, err := template.New("").Parse("{{template \"" + base + "\" . }}") funcs := map[string]any {
"startsWith": strings.HasPrefix,
"mul": Mul,
"replace": strings.Replace,
"add": Add,
}
tmpl, err := template.New("").Funcs(funcs).Parse("{{template \"" + base + "\" . }}")
if err != nil { if err != nil {
panic("Lol") panic("Lol")
} }

View File

@ -22,7 +22,7 @@
{{ end }} {{ end }}
{{ define "delete-model-card" }} {{ define "delete-model-card" }}
<form hx-delete="/models/delete" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML" {{ if .Error }} class="submitted" {{end}} > <form hx-delete="/models/delete" hx-headers='{"REQUEST-TYPE": "html"}' hx-swap="outerHTML" {{ if .Error }} class="submitted" {{end}} >
<fieldset> <fieldset>
<span> <span>
To delete this model please type "{{ .Model.Name }}": To delete this model please type "{{ .Model.Name }}":
@ -42,6 +42,115 @@
</form> </form>
{{ end }} {{ 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>
</tr>
</thead>
<tbody>
{{range .List}}
<tr>
<td>
{{.FilePath}}
</td>
<td>
{{ if (eq .Mode 2) }}
Testing
{{ else }}
Training
{{ end }}
</td>
<td class="text-center">
{{ if startsWith .FilePath "file://" }}
<img src="/savedData/{{ $.ModelId }}/data/{{ if (eq .Mode 2) }}testing{{ else }}training{{ end }}/{{ $.Name }}/{{ replace .FilePath "file://" "" 1 }}" height="30px" width="30px" style="object-fit: contain;" />
{{ else }}
TODO
img {{ .FilePath }}
{{ 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">
{{/* Handle the case where there are to many buttons */}}
{{ 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"}'
class="tab"
data-tab="{{ .Name }}">
{{ .Name }}
</button>
{{ end }}
{{ range .Classes }}
<div
class="content"
data-tab="{{ .Name }}"
hx-get="/models/data/list?id={{ .Id }}"
hx-target=".content[data-tab='{{ .Name }}']"
hx-trigger="load"
hx-swap="innerHTML"
hx-headers='{"REQUEST-TYPE": "html"}'>
</div>
{{ end }}
</div>
{{end}}
{{ end }}
{{ define "data-model-card" }} {{ define "data-model-card" }}
<div class="card"> <div class="card">
<h3> <h3>
@ -114,7 +223,7 @@
</form> </form>
</div> </div>
<div class="content" data-tab="create_class"> <div class="content" data-tab="create_class">
TODO {{ template "data-model-create-class-table" . }}
</div> </div>
<div class="content" data-tab="api"> <div class="content" data-tab="api">
TODO TODO
@ -132,7 +241,7 @@
Api Api
</button> </button>
<div class="content" data-tab="create_class"> <div class="content" data-tab="create_class">
TODO {{ template "data-model-create-class-table" . }}
</div> </div>
<div class="content" data-tab="api"> <div class="content" data-tab="api">
TODO TODO

View File

@ -20,6 +20,30 @@ main {
padding: 20px 15vw; padding: 20px 15vw;
} }
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
.justify-start {
justify-content: start;
}
.justify-end {
justify-content: end;
}
.align-center {
align-items: center;
}
.grow-1 {
flex-grow: 1;
}
.w100 { .w100 {
width: 100%; width: 100%;
display: block; display: block;
@ -47,7 +71,7 @@ main {
button { button {
border-radius: 10px; border-radius: 10px;
text-align: center; text-align: center;
padding: 2px; padding: 3px 6px;
border: none; border: none;
box-shadow: 0 2px 8px 1px #66666655; box-shadow: 0 2px 8px 1px #66666655;
background: var(--main); background: var(--main);