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

View File

@@ -49,6 +49,8 @@ func main() {
"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,6 +40,7 @@
</tr>
</table>
{{if eq .Type "ram"}}
<h2>Memory Information</h2>
<table>
<tr>
@@ -70,6 +71,42 @@
</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

@@ -28,6 +28,28 @@
<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>
<a href="/delete?id={{.Qr}}"><button>Delete</button></a>

151
views.go
View File

@@ -66,6 +66,11 @@ type DeviceVM struct {
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 {
IsEdit bool
// Assets
Qr *int
Type string
Brands []string
RamTypes []string
AssetName string
AssetBrand string
AssetBrands []string
AssetName string
AssetDescription string
// RAM
RamType string
RamTypes []string
RamCapacity int
IsEdit bool
// 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()
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 {
@@ -255,6 +325,11 @@ type Asset struct {
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