Add ability to add hard drives
All checks were successful
Build / build (push) Successful in 1m30s

This commit is contained in:
2025-03-24 16:15:52 +01:00
parent 982943fac3
commit ff1d95edab
9 changed files with 354 additions and 120 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
*.db3
*.db3-*
*.db3.*
*.iml
.idea
pcinv

81
data.go
View File

@@ -1,25 +1,14 @@
package main
import "gitea.seeseepuff.be/seeseemelk/mysqlite"
import (
"fmt"
"gitea.seeseepuff.be/seeseemelk/mysqlite"
)
func (a *App) GetAllBrands() ([]string, error) {
var brands []string
var err error
for row := range a.db.Query("SELECT brand FROM assets GROUP BY brand ORDER BY brand ASC").Range(&err) {
var name string
err := row.Scan(&name)
if err != nil {
return nil, err
}
brands = append(brands, name)
}
return brands, err
}
func (a *App) GetAllRAMTypes() ([]string, error) {
func (a *App) getAllTypes(column, table string) ([]string, error) {
var types []string
var err error
for row := range a.db.Query("SELECT type FROM info_ram GROUP BY type ORDER BY type ASC").Range(&err) {
for row := range a.db.Query(fmt.Sprintf("SELECT %s FROM %s GROUP BY %s ORDER BY %s ASC", column, table, column, column)).Range(&err) {
var name string
err := row.Scan(&name)
if err != nil {
@@ -30,6 +19,64 @@ func (a *App) GetAllRAMTypes() ([]string, error) {
return types, err
}
func (a *App) GetAllBrands() ([]string, error) {
return a.getAllTypes("brand", "assets")
}
func (a *App) GetAllRamTypes() ([]string, error) {
return a.getAllTypes("type", "info_ram")
}
func (a *App) GetAllHddTypes() ([]string, error) {
return a.getAllTypes("type", "info_hdd")
}
func (a *App) GetAllHddFormFactors() ([]string, error) {
return a.getAllTypes("form_factor", "info_hdd")
}
func (a *App) GetAllHddConnections() ([]string, error) {
return a.getAllTypes("connection", "info_hdd")
}
func (a *App) GetAllHddSpeeds() ([]string, error) {
return a.getAllTypes("rpm", "info_hdd")
}
func (a *App) GetAllGroups(vm *CreateDeviceVM) error {
var err error
vm.AssetBrands, err = a.GetAllBrands()
if err != nil {
return err
}
vm.RamTypes, err = a.GetAllRamTypes()
if err != nil {
return err
}
vm.HddTypes, err = a.GetAllHddTypes()
if err != nil {
return err
}
vm.HddFormFactors, err = a.GetAllHddFormFactors()
if err != nil {
return err
}
vm.HddFormFactors, err = a.GetAllHddConnections()
if err != nil {
return err
}
vm.HddRpms, err = a.GetAllHddSpeeds()
if err != nil {
return err
}
return nil
}
func (a *App) GetAllTypes() ([]string, error) {
var types []string
var err error

14
main.go
View File

@@ -43,12 +43,14 @@ func main() {
templates, err := template.New("undefined.gohtml").
Funcs(template.FuncMap{
"statusText": http.StatusText,
"createDeviceLink": createDeviceLink,
"formatMemorySize": formatMemorySize,
"formatMemoryPlainSize": formatMemoryPlainSize,
"formatType": formatType,
"isRamType": isRamType,
"statusText": http.StatusText,
"createDeviceLink": createDeviceLink,
"formatMemorySize": formatMemorySize,
"formatMemoryPlainSize": formatMemoryPlainSize,
"formatType": formatType,
"isRamType": isRamType,
"createSelectMenu": createSelectMenu,
"createSelectMenuDefault": createSelectMenuDefault,
}).
ParseFS(templateFS, "templates/*.gohtml")

View File

@@ -0,0 +1,8 @@
create table info_hdd (
asset integer not null unique,
capacity integer,
type text,
form_factor text,
connection text,
rpm integer
);

View File

@@ -91,7 +91,31 @@ func formatType(t string) string {
switch t {
case "ram":
return "Random Access Memory"
case "hdd":
return "Hard Disk Drive"
default:
return t
}
}
type SelectMenu struct {
Name string
Label string
Selected string
Options []string
DefaultValue string
}
func createSelectMenu(name, label, selected string, options []string) SelectMenu {
return createSelectMenuDefault(name, label, selected, options, "Unknown")
}
func createSelectMenuDefault(name, label, selected string, options []string, defaultValue string) SelectMenu {
return SelectMenu{
Name: name,
Label: label,
Selected: selected,
Options: options,
DefaultValue: defaultValue,
}
}

View File

@@ -9,8 +9,10 @@
{{define "create_device_link"}}
{{if .Qr}}
<li><a href="/create?type=ram&qr={{.Qr}}">Random Access Memory</a></li>
<li><a href="/create?type=ram&qr={{.Qr}}">{{"ram" | formatType}}</a></li>
<li><a href="/create?type=hdd&qr={{.Qr}}">{{"hdd" | formatType}}</a></li>
{{- else}}
<li><a href="/create?type=ram">Random Access Memory</a></li>
<li><a href="/create?type=ram">{{"ram" | formatType}}</a></li>
<li><a href="/create?type=hdd">{{"hdd" | formatType}}</a></li>
{{- end}}
{{end}}

View File

@@ -1,4 +1,4 @@
{{- /*gotype: main.CreateDeviceVM */}}
{{- /*gotype: pcinv.CreateDeviceVM*/}}
{{define "create_device_step2"}}
{{template "header" "Create Device - Enter Device Data"}}
<form action="/create" method="post">
@@ -21,7 +21,7 @@
<td>
<select id="asset_brand" name="asset_brand" onchange="newOption('asset_brand', 'Brand')">
<option value="Unknown" {{if eq .AssetBrand "Unknown"}}selected{{end}}>Unknown</option>
{{range .Brands}}
{{range .AssetBrands}}
{{if ne . "Unknown"}}
<option value="{{.}}" {{if eq . $.AssetBrand}}selected{{end}}>{{.}}</option>
{{end}}
@@ -40,36 +40,73 @@
</tr>
</table>
<h2>Memory Information</h2>
<table>
<tr>
<td><label for="ram_type">Type:</label></td>
<td>
<select id="ram_type" name="ram_type" onchange="newOption('ram_type', 'Memory Type')">
<option value="Unknown" {{if eq .RamType "Unknown"}}selected{{end}}>Unknown</option>
{{range .RamTypes}}
{{if ne . "Unknown"}}
<option value="{{.}}" {{if eq . $.RamType}}selected{{end}}>{{.}}</option>
{{if eq .Type "ram"}}
<h2>Memory Information</h2>
<table>
<tr>
<td><label for="ram_type">Type:</label></td>
<td>
<select id="ram_type" name="ram_type" onchange="newOption('ram_type', 'Memory Type')">
<option value="Unknown" {{if eq .RamType "Unknown"}}selected{{end}}>Unknown</option>
{{range .RamTypes}}
{{if ne . "Unknown"}}
<option value="{{.}}" {{if eq . $.RamType}}selected{{end}}>{{.}}</option>
{{end}}
{{end}}
{{end}}
<option>New...</option>
</select>
</td>
</tr>
<tr>
<td><label for="ram_capacity">Capacity:</label></td>
<td>
<input type="number" id="ram_capacity" name="ram_capacity" value="{{if .RamCapacity}}{{.RamCapacity | formatMemoryPlainSize}}{{end}}">
<select id="ram_capacity_unit" name="ram_capacity_unit">
<option value="B" {{if isRamType .RamCapacity "B"}}selected{{end}}>B</option>
<option value="KB" {{if isRamType .RamCapacity "KB"}}selected{{end}}>KB</option>
<option value="MB" {{if isRamType .RamCapacity "MB"}}selected{{end}} selected>MB</option>
<option value="GB" {{if isRamType .RamCapacity "GB"}}selected{{end}}>GB</option>
<option value="TB" {{if isRamType .RamCapacity "TB"}}selected{{end}}>TB</option>
</select>
</td>
</tr>
</table>
<option>New...</option>
</select>
</td>
</tr>
<tr>
<td><label for="ram_capacity">Capacity:</label></td>
<td>
<input type="number" id="ram_capacity" name="ram_capacity" value="{{if .RamCapacity}}{{.RamCapacity | formatMemoryPlainSize}}{{end}}">
<select id="ram_capacity_unit" name="ram_capacity_unit">
<option value="B" {{if isRamType .RamCapacity "B"}}selected{{end}}>B</option>
<option value="KB" {{if isRamType .RamCapacity "KB"}}selected{{end}}>KB</option>
<option value="MB" {{if isRamType .RamCapacity "MB"}}selected{{end}} selected>MB</option>
<option value="GB" {{if isRamType .RamCapacity "GB"}}selected{{end}}>GB</option>
<option value="TB" {{if isRamType .RamCapacity "TB"}}selected{{end}}>TB</option>
</select>
</td>
</tr>
</table>
{{end}}
{{if eq .Type "hdd"}}
<h2>Hard Drive Information</h2>
<table>
<tr>
<td><label for="hdd_capacity">Capacity:</label></td>
<td>
<input type="number" id="hdd_capacity" name="hdd_capacity" value="{{if .HddCapacity}}{{.HddCapacity | formatMemoryPlainSize}}{{end}}">
<select id="hdd_capacity_unit" name="hdd_capacity_unit">
<option value="B" {{if isRamType .HddCapacity "B"}}selected{{end}}>B</option>
<option value="KB" {{if isRamType .HddCapacity "KB"}}selected{{end}}>KB</option>
<option value="MB" {{if isRamType .HddCapacity "MB"}}selected{{end}} selected>MB</option>
<option value="GB" {{if isRamType .HddCapacity "GB"}}selected{{end}}>GB</option>
<option value="TB" {{if isRamType .HddCapacity "TB"}}selected{{end}}>TB</option>
</select>
</td>
</tr>
<tr>
<td><label for="hdd_type">Type:</label></td>
<td>{{template "create_device_select" createSelectMenu "hdd_type" "HDD Type" .HddType .HddTypes}}</td>
</tr>
<tr>
<td><label for="hdd_form_factor">Form Factor:</label></td>
<td>{{template "create_device_select" createSelectMenu "hdd_form_factor" "HDD Form Factor" .HddFormFactor .HddFormFactors}}</td>
</tr>
<tr>
<td><label for="hdd_connection">Connection:</label></td>
<td>{{template "create_device_select" createSelectMenu "hdd_connection" "HDD Connection" .HddConnection .HddConnections}}</td>
</tr>
<tr>
<td><label for="hdd_rpm">RPM:</label></td>
<td>{{template "create_device_select" createSelectMenuDefault "hdd_rpm" "HDD RPM" .HddRpm .HddRpms "Not Applicable"}}</td>
</tr>
</table>
{{end}}
{{if .IsEdit}}
<button type="submit">Edit</button>
@@ -79,3 +116,15 @@
</form>
{{template "footer"}}
{{end}}
{{define "create_device_select"}}
<select id="{{.Name}}" name="{{.Name}}" onchange="newOption('{{.Name}}', '{{.Label}}')">
<option value="Unknown" {{if eq .Selected "Unknown"}}selected{{end}}>{{.DefaultValue}}</option>
{{range .Options}}
{{if ne . "Unknown"}}
<option value="{{.}}" {{if eq . $.Selected}}selected{{end}}>{{.}}</option>
{{end}}
{{end}}
<option>New...</option>
</select>
{{end}}

View File

@@ -19,14 +19,36 @@
<td>{{.Description}}</td>
</tr>
{{if eq .Type "ram"}}
<tr>
<td>RAM Type:</td>
<td>{{.RamType}}</td>
</tr>
<tr>
<td>RAM Capacity:</td>
<td>{{.RamCapacity | formatMemorySize}}</td>
</tr>
<tr>
<td>RAM Type:</td>
<td>{{.RamType}}</td>
</tr>
<tr>
<td>RAM Capacity:</td>
<td>{{.RamCapacity | formatMemorySize}}</td>
</tr>
{{end}}
{{if eq .Type "hdd"}}
<tr>
<td>HDD Capacity:</td>
<td>{{.HddCapacity}}</td>
</tr>
<tr>
<td>HDD Type:</td>
<td>{{.HddType}}</td>
</tr>
<tr>
<td>Form Factor:</td>
<td>{{.HddFormFactor}}</td>
</tr>
<tr>
<td>Connection:</td>
<td>{{.HddConnection}}</td>
</tr>
<tr>
<td>RPM:</td>
<td>{{.HddRpm}}</td>
</tr>
{{end}}
</table>
<a href="/create?id={{.Qr}}&edit=true"><button>Edit</button></a>

191
views.go
View File

@@ -59,13 +59,18 @@ func (a *App) getIndex(c *gin.Context) {
}
type DeviceVM struct {
Qr int
Name string
Brand string
Type string
Description string
RamType string
RamCapacity int
Qr int
Name string
Brand string
Type string
Description string
RamType string
RamCapacity int
HddCapacity int
HddType string
HddFormFactor string
HddConnection string
HddRpm int
}
func (a *App) getDevice(c *gin.Context) {
@@ -106,26 +111,55 @@ func (a *App) getDevice(c *gin.Context) {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
} else if vm.Type == "hdd" {
err = a.db.Query("SELECT capacity, type, form_factor, connection, rpm FROM info_hdd WHERE asset = ?").
Bind(qr).
ScanSingle(&vm.HddCapacity, &vm.HddType, &vm.HddFormFactor, &vm.HddConnection, &vm.HddRpm)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
}
c.HTML(http.StatusOK, "device", vm)
}
type CreateDeviceVM struct {
Qr *int
Type string
Brands []string
RamTypes []string
IsEdit bool
// Assets
Qr *int
Type string
AssetBrand string
AssetBrands []string
AssetName string
AssetBrand string
AssetDescription string
RamType string
RamCapacity int
IsEdit bool
// RAM
RamType string
RamTypes []string
RamCapacity int
// HDD
HddCapacity int
HddType string
HddTypes []string
HddFormFactor string
HddFormFactors []string
HddConnection string
HddConnections []string
HddRpm string
HddRpms []string
}
func (a *App) getCreateDevice(c *gin.Context) {
var err error
vm := &CreateDeviceVM{}
vm.Type = c.Query("type")
qr := c.Query("id")
if qr != "" {
@@ -137,22 +171,12 @@ func (a *App) getCreateDevice(c *gin.Context) {
vm.Qr = &qrInt
}
brands, err := a.GetAllBrands()
err = a.GetAllGroups(vm)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
types, err := a.GetAllRAMTypes()
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
vm.Type = c.Query("type")
vm.Brands = brands
vm.RamTypes = types
if c.Query("edit") != "" && vm.Qr != nil {
vm.IsEdit = true
err = a.db.Query("SELECT name, type, brand, description FROM assets WHERE qr = ?").
@@ -170,6 +194,14 @@ func (a *App) getCreateDevice(c *gin.Context) {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
} else if vm.Type == "hdd" {
err = a.db.Query("SELECT capacity, type, form_factor, connection, rpm FROM info_hdd WHERE asset = ?").
Bind(*vm.Qr).
ScanSingle(&vm.HddCapacity, &vm.HddType, &vm.HddFormFactor, &vm.HddConnection, &vm.HddRpm)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
}
}
@@ -183,13 +215,41 @@ func (a *App) postCreateDevice(c *gin.Context) {
}
assetType := c.PostForm("asset_type")
tx, err := a.db.Begin()
defer tx.MustRollback()
if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("error beginning tx: %v", err))
return
}
err = a.DeleteAsset(tx, qr)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("error removing assets: %v", err))
return
}
err = tx.Query("INSERT INTO assets (qr, type, brand, name, description) VALUES (?, ?, ?, ?, ?)").
Bind(qr, c.PostForm("asset_type"), c.PostForm("asset_brand"), c.PostForm("asset_name"), c.PostForm("asset_description")).
Exec()
if err != nil {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("error inserting assets: %v", err))
return
}
if assetType == "ram" {
err = a.postCreateDeviceRam(c, qr)
err = a.postCreateDeviceRam(c, qr, tx)
} else if assetType == "hdd" {
err = a.postCreateDeviceHdd(c, qr, tx)
} else {
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("invalid type: %s", assetType))
return
}
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
err = tx.Commit()
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
@@ -197,7 +257,7 @@ func (a *App) postCreateDevice(c *gin.Context) {
c.Redirect(http.StatusSeeOther, "/")
}
func (a *App) postCreateDeviceRam(c *gin.Context, qr int) error {
func (a *App) postCreateDeviceRam(c *gin.Context, qr int, tx *mysqlite.Tx) error {
var err error
capacity := 0
capacityString := c.PostForm("ram_capacity")
@@ -219,27 +279,37 @@ func (a *App) postCreateDeviceRam(c *gin.Context, qr int) error {
return errors.New("invalid ram_capacity_unit")
}
tx, err := a.db.Begin()
defer tx.MustRollback()
if err != nil {
return err
}
err = a.DeleteAsset(tx, qr)
err = tx.Query("INSERT INTO assets (qr, type, brand, name, description) VALUES (?, ?, ?, ?, ?)").
Bind(qr, c.PostForm("asset_type"), c.PostForm("asset_brand"), c.PostForm("asset_name"), c.PostForm("asset_description")).
Exec()
if err != nil {
return err
}
err = tx.Query("INSERT INTO info_ram (asset, type, capacity) VALUES (?, ?, ?)").
Bind(qr, c.PostForm("ram_type"), capacity).Exec()
if err != nil {
return err
return err
}
func (a *App) postCreateDeviceHdd(c *gin.Context, qr int, tx *mysqlite.Tx) error {
var err error
capacity := 0
capacityString := c.PostForm("hdd_capacity")
if capacityString != "" {
capacity, err = strconv.Atoi(c.PostForm("hdd_capacity"))
if err != nil {
return err
}
}
return tx.Commit()
switch c.PostForm("hdd_capacity_unit") {
case "B":
case "KB":
capacity *= 1024
case "MB":
capacity *= 1024 * 1024
case "GB":
capacity *= 1024 * 1024 * 1024
default:
return errors.New("invalid hdd_capacity_unit")
}
err = tx.Query("INSERT INTO info_hdd (asset, capacity, type, form_factor, connection, rpm) VALUES (?, ?, ?, ?, ?, ?)").
Bind(qr, capacity, c.PostForm("hdd_type"), c.PostForm("hdd_form_factor"), c.PostForm("hdd_connection"), c.PostForm("hdd_rpm")).
Exec()
return err
}
type BrowseVM struct {
@@ -248,13 +318,18 @@ type BrowseVM struct {
}
type Asset struct {
Qr int
Name string
Brand string
Type string
Description string
RamType string
RamCapacity int
Qr int
Name string
Brand string
Type string
Description string
RamType string
RamCapacity int
HddCapacity int
HddType string
HddFormFactor string
HddConnection string
HddRpm int
}
func (a *App) getBrowse(c *gin.Context) {
@@ -262,9 +337,11 @@ func (a *App) getBrowse(c *gin.Context) {
types := c.QueryArray("type")
query := `SELECT assets.qr, assets.name, assets.brand, assets.type, assets.description,
info_ram.type, info_ram.capacity
info_ram.type, info_ram.capacity,
info_hdd.capacity, info_hdd.type, info_hdd.form_factor, info_hdd.connection, info_hdd.rpm
FROM assets
JOIN info_ram ON info_ram.asset = assets.qr
LEFT JOIN info_ram ON info_ram.asset = assets.qr
LEFT JOIN info_hdd ON info_hdd.asset = assets.qr
WHERE 1=1`
if len(brands) > 0 {
query += " AND assets.brand IN (" + placeholders(len(brands)) + ")"
@@ -280,7 +357,9 @@ func (a *App) getBrowse(c *gin.Context) {
q := a.db.Query(query).Bind(brands, types)
for row := range q.Range(&err) {
var asset Asset
err := row.Scan(&asset.Qr, &asset.Name, &asset.Brand, &asset.Type, &asset.Description, &asset.RamType, &asset.RamCapacity)
err := row.Scan(&asset.Qr, &asset.Name, &asset.Brand, &asset.Type, &asset.Description,
&asset.RamType, &asset.RamCapacity,
&asset.HddCapacity, &asset.HddType, &asset.HddFormFactor, &asset.HddConnection, &asset.HddRpm)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return