Move files around
This commit is contained in:
41
.gitignore
vendored
41
.gitignore
vendored
@@ -1,6 +1,37 @@
|
|||||||
*.db3
|
HELP.md
|
||||||
*.db3-*
|
.gradle
|
||||||
*.db3.*
|
build/
|
||||||
*.iml
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
.idea
|
.idea
|
||||||
pcinv
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|||||||
13
Dockerfile
13
Dockerfile
@@ -1,13 +0,0 @@
|
|||||||
FROM golang:1.24.1-alpine3.21
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
RUN go mod download
|
|
||||||
|
|
||||||
COPY migrations ./migrations
|
|
||||||
COPY static ./static
|
|
||||||
COPY templates ./templates
|
|
||||||
COPY *.go ./
|
|
||||||
RUN go build -o /pcinv
|
|
||||||
|
|
||||||
CMD ["/pcinv"]
|
|
||||||
124
data.go
124
data.go
@@ -1,124 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"gitea.seeseepuff.be/seeseemelk/mysqlite"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a *App) getAllTypes(column, table string) ([]string, error) {
|
|
||||||
var types []string
|
|
||||||
var err error
|
|
||||||
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 {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
types = append(types, name)
|
|
||||||
}
|
|
||||||
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
|
|
||||||
for row := range a.db.Query("SELECT type FROM assets GROUP BY type ORDER BY type ASC").Range(&err) {
|
|
||||||
var name string
|
|
||||||
err := row.Scan(&name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
types = append(types, name)
|
|
||||||
}
|
|
||||||
return types, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) GetAssetCount() (int, error) {
|
|
||||||
var count int
|
|
||||||
err := a.db.Query("SELECT COUNT(*) FROM assets").ScanSingle(&count)
|
|
||||||
return count, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) GetBrandCount() (int, error) {
|
|
||||||
var count int
|
|
||||||
err := a.db.Query("SELECT COUNT(DISTINCT brand) FROM assets").ScanSingle(&count)
|
|
||||||
return count, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) GetTotalRamCapacity() (int, error) {
|
|
||||||
var capacity int
|
|
||||||
err := a.db.Query("SELECT SUM(capacity) FROM info_ram").ScanSingle(&capacity)
|
|
||||||
return capacity, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) DeleteAsset(tx *mysqlite.Tx, qr int) error {
|
|
||||||
err := tx.Query("DELETE FROM assets WHERE qr=?").Bind(qr).Exec()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tx.Query("DELETE FROM info_ram WHERE asset=?").Bind(qr).Exec()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
130
descriptors.go
130
descriptors.go
@@ -1,130 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
var DescriptorTree = createDescriptorTree(DescriptorRoot{
|
|
||||||
AssetTypes: []AssetType{
|
|
||||||
{
|
|
||||||
Id: "asset",
|
|
||||||
Table: "assets",
|
|
||||||
Name: "General Information",
|
|
||||||
Abstract: true,
|
|
||||||
Fields: []AssetField{
|
|
||||||
{
|
|
||||||
Id: "qr",
|
|
||||||
Name: "QR Code",
|
|
||||||
Type: Number,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "type",
|
|
||||||
Name: "Type",
|
|
||||||
Type: Type,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "brand",
|
|
||||||
Name: "Brand",
|
|
||||||
Type: Selection,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "name",
|
|
||||||
Name: "Name",
|
|
||||||
Type: String,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "description",
|
|
||||||
Name: "Description",
|
|
||||||
Type: String,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "ram",
|
|
||||||
Name: "Random Access Memory",
|
|
||||||
Table: "info_ram",
|
|
||||||
Fields: []AssetField{
|
|
||||||
{
|
|
||||||
Id: "type",
|
|
||||||
Name: "Type",
|
|
||||||
Type: String,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "capacity",
|
|
||||||
Name: "Capacity",
|
|
||||||
Type: Capacity,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "hdd",
|
|
||||||
Name: "Hard Disk Drive",
|
|
||||||
Table: "info_hdd",
|
|
||||||
Fields: []AssetField{
|
|
||||||
{
|
|
||||||
Id: "type",
|
|
||||||
Name: "Type",
|
|
||||||
Type: Selection,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "capacity",
|
|
||||||
Name: "Capacity",
|
|
||||||
Type: Capacity,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "form_factor",
|
|
||||||
Name: "Form Factor",
|
|
||||||
Type: Selection,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "interface",
|
|
||||||
Name: "Interface",
|
|
||||||
Type: Selection,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Id: "rpm",
|
|
||||||
Name: "RPM",
|
|
||||||
Type: Selection,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
func createDescriptorTree(tree DescriptorRoot) *DescriptorRoot {
|
|
||||||
return &tree
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAssetTypeById(id string) *AssetType {
|
|
||||||
for _, assetType := range DescriptorTree.AssetTypes {
|
|
||||||
if assetType.Id == id {
|
|
||||||
return &assetType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type DescriptorRoot struct {
|
|
||||||
AssetTypes []AssetType
|
|
||||||
}
|
|
||||||
|
|
||||||
type AssetType struct {
|
|
||||||
Id string
|
|
||||||
Name string
|
|
||||||
Table string
|
|
||||||
Fields []AssetField
|
|
||||||
Abstract bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type AssetField struct {
|
|
||||||
Id string
|
|
||||||
Name string
|
|
||||||
Type FieldType
|
|
||||||
}
|
|
||||||
|
|
||||||
type FieldType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
Number FieldType = "number"
|
|
||||||
String = "string"
|
|
||||||
Type = "type"
|
|
||||||
Selection = "selection"
|
|
||||||
Bool = "bool"
|
|
||||||
Capacity = "capacity"
|
|
||||||
)
|
|
||||||
48
go.mod
48
go.mod
@@ -1,48 +0,0 @@
|
|||||||
module pcinv
|
|
||||||
|
|
||||||
go 1.24
|
|
||||||
|
|
||||||
toolchain go1.24.1
|
|
||||||
|
|
||||||
require (
|
|
||||||
gitea.seeseepuff.be/seeseemelk/mysqlite v0.15.0
|
|
||||||
github.com/gin-gonic/gin v1.10.1
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/bytedance/sonic v1.13.2 // indirect
|
|
||||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
|
||||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
|
||||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
|
||||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
|
||||||
github.com/ugorji/go/codec v1.2.14 // indirect
|
|
||||||
golang.org/x/arch v0.17.0 // indirect
|
|
||||||
golang.org/x/crypto v0.38.0 // indirect
|
|
||||||
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b // indirect
|
|
||||||
golang.org/x/net v0.40.0 // indirect
|
|
||||||
golang.org/x/sys v0.33.0 // indirect
|
|
||||||
golang.org/x/text v0.25.0 // indirect
|
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
|
||||||
modernc.org/libc v1.65.8 // indirect
|
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
|
||||||
modernc.org/memory v1.11.0 // indirect
|
|
||||||
modernc.org/sqlite v1.37.1 // indirect
|
|
||||||
zombiezen.com/go/sqlite v1.4.2 // indirect
|
|
||||||
)
|
|
||||||
170
go.sum
170
go.sum
@@ -1,170 +0,0 @@
|
|||||||
gitea.seeseepuff.be/seeseemelk/mysqlite v0.9.0 h1:GaU2DSrgDfZEqST3HdnNgfKSI4sNXvMm8SSfeMvBxA4=
|
|
||||||
gitea.seeseepuff.be/seeseemelk/mysqlite v0.9.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE=
|
|
||||||
gitea.seeseepuff.be/seeseemelk/mysqlite v0.14.0 h1:aRItVfUj48fBmuec7rm/jY9KCfvHW2VzJfItVk4t8sw=
|
|
||||||
gitea.seeseepuff.be/seeseemelk/mysqlite v0.14.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE=
|
|
||||||
gitea.seeseepuff.be/seeseemelk/mysqlite v0.15.0 h1:+k0iBYM/aZJxz7++EKi/G9e66E9u4bPS3DFLrBeDb9Y=
|
|
||||||
gitea.seeseepuff.be/seeseemelk/mysqlite v0.15.0/go.mod h1:cgswydOxJjMlNwfcBIXnKjr47LwXnMT9BInkiHb0tXE=
|
|
||||||
github.com/bytedance/sonic v1.13.1 h1:Jyd5CIvdFnkOWuKXr+wm4Nyk2h0yAFsr8ucJgEasO3g=
|
|
||||||
github.com/bytedance/sonic v1.13.1/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
|
||||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
|
||||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
|
||||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
|
||||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
|
||||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
|
||||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
|
||||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
|
||||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
|
||||||
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
|
||||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
|
||||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
|
||||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
|
||||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
|
||||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
|
||||||
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
|
|
||||||
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
|
||||||
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
|
|
||||||
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
|
||||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
|
||||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
|
||||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
|
||||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
|
||||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
|
||||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
|
||||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
|
||||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
|
||||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
|
||||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
|
||||||
github.com/ugorji/go/codec v1.2.14 h1:yOQvXCBc3Ij46LRkRoh4Yd5qK6LVOgi0bYOXfb7ifjw=
|
|
||||||
github.com/ugorji/go/codec v1.2.14/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
|
||||||
golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
|
|
||||||
golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
|
|
||||||
golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU=
|
|
||||||
golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
|
||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
|
||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
|
||||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
|
||||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
|
||||||
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b h1:QoALfVG9rhQ/M7vYDScfPdWjGL9dlsVVM5VGh7aKoAA=
|
|
||||||
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
|
||||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
|
||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
|
||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
|
||||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
|
||||||
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
|
||||||
modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y=
|
|
||||||
modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s=
|
|
||||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
|
||||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
|
||||||
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
|
||||||
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
|
||||||
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
|
|
||||||
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
|
|
||||||
modernc.org/libc v1.65.8 h1:7PXRJai0TXZ8uNA3srsmYzmTyrLoHImV5QxHeni108Q=
|
|
||||||
modernc.org/libc v1.65.8/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
|
|
||||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
|
||||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
|
||||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
|
||||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
|
||||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
|
||||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
|
||||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
|
||||||
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
|
||||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
|
||||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
|
||||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
|
||||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
|
||||||
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
|
|
||||||
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
|
|
||||||
modernc.org/sqlite v1.37.1 h1:EgHJK/FPoqC+q2YBXg7fUmES37pCHFc97sI7zSayBEs=
|
|
||||||
modernc.org/sqlite v1.37.1/go.mod h1:XwdRtsE1MpiBcL54+MbKcaDvcuej+IYSMfLN6gSKV8g=
|
|
||||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
|
||||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
|
||||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
|
||||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
|
||||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
|
||||||
zombiezen.com/go/sqlite v1.4.0 h1:N1s3RIljwtp4541Y8rM880qgGIgq3fTD2yks1xftnKU=
|
|
||||||
zombiezen.com/go/sqlite v1.4.0/go.mod h1:0w9F1DN9IZj9AcLS9YDKMboubCACkwYCGkzoy3eG5ik=
|
|
||||||
zombiezen.com/go/sqlite v1.4.2 h1:KZXLrBuJ7tKNEm+VJcApLMeQbhmAUOKA5VWS93DfFRo=
|
|
||||||
zombiezen.com/go/sqlite v1.4.2/go.mod h1:5Kd4taTAD4MkBzT25mQ9uaAlLjyR0rFhsR6iINO70jc=
|
|
||||||
0
pcinvj/pcinv/gradlew → gradlew
vendored
0
pcinvj/pcinv/gradlew → gradlew
vendored
0
pcinvj/pcinv/gradlew.bat → gradlew.bat
vendored
0
pcinvj/pcinv/gradlew.bat → gradlew.bat
vendored
94
main.go
94
main.go
@@ -1,94 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
"html/template"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"gitea.seeseepuff.be/seeseemelk/mysqlite"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed migrations/*.sql
|
|
||||||
var migrations embed.FS
|
|
||||||
|
|
||||||
//go:embed templates/*.gohtml
|
|
||||||
var templateFS embed.FS
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.Println("Starting...")
|
|
||||||
|
|
||||||
// Get database path from environment variable or use default
|
|
||||||
dbPath := os.Getenv("PCINV_DB")
|
|
||||||
if dbPath == "" {
|
|
||||||
dbPath = "pcinv.db3"
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := mysqlite.OpenDb(dbPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error opening db: %v", err)
|
|
||||||
}
|
|
||||||
defer db.MustClose()
|
|
||||||
|
|
||||||
err = db.MigrateDb(migrations, "migrations")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error migrating db: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
app := &App{
|
|
||||||
db: db,
|
|
||||||
}
|
|
||||||
|
|
||||||
templates, err := template.New("undefined.gohtml").
|
|
||||||
Funcs(template.FuncMap{
|
|
||||||
"statusText": http.StatusText,
|
|
||||||
"createDeviceLink": createDeviceLink,
|
|
||||||
"formatMemorySize": formatMemorySize,
|
|
||||||
"formatMemoryPlainSize": formatMemoryPlainSize,
|
|
||||||
"formatType": formatType,
|
|
||||||
"isRamType": isRamType,
|
|
||||||
"createSelectMenu": createSelectMenu,
|
|
||||||
"createSelectMenuDefault": createSelectMenuDefault,
|
|
||||||
}).
|
|
||||||
ParseFS(templateFS, "templates/*.gohtml")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error parsing templates: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gin.DebugPrintFunc = log.Printf
|
|
||||||
gin.SetMode(gin.ReleaseMode)
|
|
||||||
r := gin.Default()
|
|
||||||
r.SetHTMLTemplate(templates)
|
|
||||||
r.StaticFS("/static", staticFiles)
|
|
||||||
r.Use(errorHandler)
|
|
||||||
r.GET("/", app.getIndex)
|
|
||||||
r.GET("/device", app.getDevice)
|
|
||||||
r.GET("/create", app.getCreateDevice)
|
|
||||||
r.POST("/create", app.postCreateDevice)
|
|
||||||
r.GET("/browse", app.getBrowse)
|
|
||||||
r.GET("/delete", app.getDelete)
|
|
||||||
r.POST("/delete", app.postDelete)
|
|
||||||
err = r.Run()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error serving website: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ErrorVM struct {
|
|
||||||
Errors []*gin.Error
|
|
||||||
StatusCode int
|
|
||||||
}
|
|
||||||
|
|
||||||
func errorHandler(c *gin.Context) {
|
|
||||||
c.Next()
|
|
||||||
if len(c.Errors) != 0 {
|
|
||||||
vm := ErrorVM{
|
|
||||||
Errors: c.Errors,
|
|
||||||
StatusCode: c.Writer.Status(),
|
|
||||||
}
|
|
||||||
c.HTML(vm.StatusCode, "errors", vm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
create table assets (
|
|
||||||
qr integer unique,
|
|
||||||
type text not null,
|
|
||||||
brand text,
|
|
||||||
name text,
|
|
||||||
description text
|
|
||||||
) strict;
|
|
||||||
|
|
||||||
create table worklog (
|
|
||||||
asset integer not null,
|
|
||||||
timestamp integer not null,
|
|
||||||
action text not null
|
|
||||||
) strict;
|
|
||||||
|
|
||||||
create table info_ram (
|
|
||||||
asset integer not null unique,
|
|
||||||
capacity integer,
|
|
||||||
type text
|
|
||||||
) strict;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
create table info_hdd (
|
|
||||||
asset integer not null unique,
|
|
||||||
capacity integer,
|
|
||||||
type text,
|
|
||||||
form_factor text,
|
|
||||||
connection text,
|
|
||||||
rpm integer
|
|
||||||
);
|
|
||||||
37
pcinvj/pcinv/.gitignore
vendored
37
pcinvj/pcinv/.gitignore
vendored
@@ -1,37 +0,0 @@
|
|||||||
HELP.md
|
|
||||||
.gradle
|
|
||||||
build/
|
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
|
||||||
!**/src/main/**/build/
|
|
||||||
!**/src/test/**/build/
|
|
||||||
|
|
||||||
### STS ###
|
|
||||||
.apt_generated
|
|
||||||
.classpath
|
|
||||||
.factorypath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.springBeans
|
|
||||||
.sts4-cache
|
|
||||||
bin/
|
|
||||||
!**/src/main/**/bin/
|
|
||||||
!**/src/test/**/bin/
|
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
|
||||||
.idea
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
out/
|
|
||||||
!**/src/main/**/out/
|
|
||||||
!**/src/test/**/out/
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
/nbproject/private/
|
|
||||||
/nbbuild/
|
|
||||||
/dist/
|
|
||||||
/nbdist/
|
|
||||||
/.nb-gradle/
|
|
||||||
|
|
||||||
### VS Code ###
|
|
||||||
.vscode/
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
|||||||
#Wed Jun 04 05:47:48 CEST 2025
|
|
||||||
gradle.version=8.14
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,30 +0,0 @@
|
|||||||
# Getting Started
|
|
||||||
|
|
||||||
### Reference Documentation
|
|
||||||
|
|
||||||
For further reference, please consider the following sections:
|
|
||||||
|
|
||||||
* [Official Gradle documentation](https://docs.gradle.org)
|
|
||||||
* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/3.5.0/gradle-plugin)
|
|
||||||
* [Create an OCI image](https://docs.spring.io/spring-boot/3.5.0/gradle-plugin/packaging-oci-image.html)
|
|
||||||
* [Spring Configuration Processor](https://docs.spring.io/spring-boot/3.5.0/specification/configuration-metadata/annotation-processor.html)
|
|
||||||
* [Spring Data JPA](https://docs.spring.io/spring-boot/3.5.0/reference/data/sql.html#data.sql.jpa-and-spring-data)
|
|
||||||
* [Spring Boot DevTools](https://docs.spring.io/spring-boot/3.5.0/reference/using/devtools.html)
|
|
||||||
* [Thymeleaf](https://docs.spring.io/spring-boot/3.5.0/reference/web/servlet.html#web.servlet.spring-mvc.template-engines)
|
|
||||||
* [Spring Web](https://docs.spring.io/spring-boot/3.5.0/reference/web/servlet.html)
|
|
||||||
|
|
||||||
### Guides
|
|
||||||
|
|
||||||
The following guides illustrate how to use some features concretely:
|
|
||||||
|
|
||||||
* [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/)
|
|
||||||
* [Handling Form Submission](https://spring.io/guides/gs/handling-form-submission/)
|
|
||||||
* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
|
|
||||||
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
|
|
||||||
* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)
|
|
||||||
|
|
||||||
### Additional Links
|
|
||||||
|
|
||||||
These additional references should also help you:
|
|
||||||
|
|
||||||
* [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle)
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="JAVA_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
spring.application.name=pcinv
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>PC Inventory</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Hello, world!</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
function newOption(elementId, name) {
|
|
||||||
var el = document.getElementById(elementId)
|
|
||||||
if (el.value !== "New...") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var newValue = window.prompt("Enter " + name + " Name")
|
|
||||||
if (newValue === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var child = document.createElement("option")
|
|
||||||
child.value = newValue
|
|
||||||
child.innerText = newValue
|
|
||||||
el.prepend(child)
|
|
||||||
el.value = newValue
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
var elements = document.getElementsByClassName("to-delete")
|
|
||||||
while (elements.length > 0) {
|
|
||||||
elements[0].remove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// / +build !release
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
const staticFiles = http.Dir("./static")
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createDeviceLink(deviceType, name string, qr *int) CreateDeviceLink {
|
|
||||||
return CreateDeviceLink{
|
|
||||||
Type: deviceType,
|
|
||||||
Name: name,
|
|
||||||
Qr: qr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateDeviceLink struct {
|
|
||||||
Type string
|
|
||||||
Name string
|
|
||||||
Qr *int
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatMemoryUnit(size int) string {
|
|
||||||
const (
|
|
||||||
KB = 1024
|
|
||||||
MB = KB * 1024
|
|
||||||
GB = MB * 1024
|
|
||||||
)
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case size >= GB:
|
|
||||||
return "GB"
|
|
||||||
case size >= MB:
|
|
||||||
return "MB"
|
|
||||||
case size >= KB:
|
|
||||||
return "KB"
|
|
||||||
default:
|
|
||||||
return "B"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatMemorySize(size int) string {
|
|
||||||
const (
|
|
||||||
KB = 1024
|
|
||||||
MB = KB * 1024
|
|
||||||
GB = MB * 1024
|
|
||||||
)
|
|
||||||
|
|
||||||
switch formatMemoryUnit(size) {
|
|
||||||
case "GB":
|
|
||||||
return fmt.Sprintf("%.2f GB", float64(size)/GB)
|
|
||||||
case "MB":
|
|
||||||
return fmt.Sprintf("%.2f MB", float64(size)/MB)
|
|
||||||
case "KB":
|
|
||||||
return fmt.Sprintf("%.2f KB", float64(size)/KB)
|
|
||||||
case "B":
|
|
||||||
return fmt.Sprintf("%d B", size)
|
|
||||||
default:
|
|
||||||
panic("invalid memory size")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatMemoryPlainSize(size int) int {
|
|
||||||
const (
|
|
||||||
KB = 1024
|
|
||||||
MB = KB * 1024
|
|
||||||
GB = MB * 1024
|
|
||||||
)
|
|
||||||
|
|
||||||
switch formatMemoryUnit(size) {
|
|
||||||
case "GB":
|
|
||||||
return size / GB
|
|
||||||
case "MB":
|
|
||||||
return size / MB
|
|
||||||
case "KB":
|
|
||||||
return size / KB
|
|
||||||
case "B":
|
|
||||||
return size
|
|
||||||
default:
|
|
||||||
panic("invalid memory size")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isRamType(size int, unit string) bool {
|
|
||||||
if size == 0 && unit == "MB" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
actualUnit := formatMemoryUnit(size)
|
|
||||||
return unit == actualUnit
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatType(t string) string {
|
|
||||||
for _, assetType := range DescriptorTree.AssetTypes {
|
|
||||||
if assetType.Id == t {
|
|
||||||
return assetType.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("unknown type")
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{{- /*gotype: main.BrowseVM */}}
|
|
||||||
{{define "browse"}}
|
|
||||||
{{template "header" "Search Results"}}
|
|
||||||
<table border="1">
|
|
||||||
<tr>
|
|
||||||
<th>QR</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Brand</th>
|
|
||||||
<th>Description</th>
|
|
||||||
{{if .HasRam}}
|
|
||||||
<th>RAM Type</th>
|
|
||||||
<th>RAM Capacity</th>
|
|
||||||
{{end}}
|
|
||||||
</tr>
|
|
||||||
{{range .Assets}}
|
|
||||||
<tr>
|
|
||||||
<td><a href="/device?id={{.Qr}}">{{.Qr}}</a></td>
|
|
||||||
<td><a href="/device?id={{.Qr}}">{{.Type | formatType}}</a></td>
|
|
||||||
<td>{{.Name}}</td>
|
|
||||||
<td>{{.Brand}}</td>
|
|
||||||
<td>{{.Description}}</td>
|
|
||||||
{{if $.HasRam}}
|
|
||||||
<td>{{.RamType}}</td>
|
|
||||||
<td>{{.RamCapacity | formatMemorySize}}</td>
|
|
||||||
{{end}}
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</table>
|
|
||||||
{{template "footer"}}
|
|
||||||
{{end}}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{{- /*gotype: main.CreateDeviceVM */}}
|
|
||||||
{{define "create_device"}}
|
|
||||||
{{if .Type}}
|
|
||||||
{{template "create_device_step2" .}}
|
|
||||||
{{else}}
|
|
||||||
{{template "create_device_step1" .}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{{- /*gotype: pcinv.CreateDeviceVM*/ -}}
|
|
||||||
{{define "create_device_step1"}}
|
|
||||||
{{template "header" "Create Device - Choose Device Type"}}
|
|
||||||
<ul>
|
|
||||||
{{if .Qr}}
|
|
||||||
{{range .DescriptorTree.AssetTypes}}
|
|
||||||
{{if not .Abstract}}
|
|
||||||
<li><a href="/create?type={{.Id}}&qr={{.Qr}}">{{.Name}}</a></li>
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
{{else}}
|
|
||||||
{{range .DescriptorTree.AssetTypes}}
|
|
||||||
{{if not .Abstract}}
|
|
||||||
<li><a href="/create?type={{.Id}}">{{.Name}}</a></li>
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
{{template "footer"}}
|
|
||||||
{{end}}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
{{- /*gotype: pcinv.CreateDeviceVM*/}}
|
|
||||||
{{define "create_device_step2"}}
|
|
||||||
{{template "header" "Create Device - Enter Device Data"}}
|
|
||||||
<form action="/create" method="post">
|
|
||||||
|
|
||||||
{{range .DescriptorTree.AssetTypes}}
|
|
||||||
{{if $.IsPartOf .Id}}
|
|
||||||
<h2>{{.Name}}</h2>
|
|
||||||
{{$asset := .}}
|
|
||||||
<table>
|
|
||||||
{{range .Fields}}
|
|
||||||
<tr>
|
|
||||||
<td><label for="{{$asset.Id}}-{{.Id}}">{{.Name}}</label></td>
|
|
||||||
<td>
|
|
||||||
{{if eq .Type "type"}}
|
|
||||||
<span>{{$.NiceType}}</span>
|
|
||||||
<input type="hidden" name="{{$asset.Id}}-{{.Id}}" value="{{$.Type}}">
|
|
||||||
{{else if eq .Type "number"}}
|
|
||||||
<input type="number"
|
|
||||||
id="{{$asset.Id}}-{{.Id}}"
|
|
||||||
name="{{$asset.Id}}-{{.Id}}"
|
|
||||||
{{/* value="{{.Qr}}"*/}}
|
|
||||||
required>
|
|
||||||
{{else if eq .Type "string"}}
|
|
||||||
<input type="text"
|
|
||||||
id="{{$asset.Id}}-{{.Id}}"
|
|
||||||
name="{{$asset.Id}}-{{.Id}}"
|
|
||||||
required>
|
|
||||||
{{else if eq .Type "selection"}}
|
|
||||||
<select id="{{$asset.Id}}-{{.Id}}"
|
|
||||||
name="{{$asset.Id}}-{{.Id}}"
|
|
||||||
onchange="newOption('{{$asset.Id}}-{{.Id}}', '{{.Name}}')">
|
|
||||||
<option value="Unknown" selected>Unknown</option>
|
|
||||||
{{/* {{range .Options}}*/}}
|
|
||||||
{{/* {{if ne . "Unknown"}}*/}}
|
|
||||||
{{/* <option value="{{.}}" {{if eq . $.Selected}}selected{{end}}>{{.}}</option>*/}}
|
|
||||||
{{/* {{end}}*/}}
|
|
||||||
{{/* {{end}}*/}}
|
|
||||||
<option>New...</option>
|
|
||||||
</select>
|
|
||||||
<label for="{{$asset.Id}}-{{.Id}}-custom" class="to-delete"> (Custom:
|
|
||||||
<input type="text"
|
|
||||||
id="{{$asset.Id}}-{{.Id}}-custom"
|
|
||||||
name="{{$asset.Id}}-{{.Id}}-custom">
|
|
||||||
)
|
|
||||||
</label>
|
|
||||||
{{else if eq .Type "capacity"}}
|
|
||||||
<input type="number" id="{{$asset.Id}}-{{.Id}}" name="{{$asset.Id}}-{{.Id}}">
|
|
||||||
<select id="{{$asset.Id}}-{{.Id}}" name="{{$asset.Id}}-{{.Id}}-unit">
|
|
||||||
<option value="B">B</option>
|
|
||||||
<option value="KB">KB</option>
|
|
||||||
<option value="MB">MB</option>
|
|
||||||
<option value="GB">GB</option>
|
|
||||||
<option value="TB">TB</option>
|
|
||||||
</select>
|
|
||||||
{{end}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</table>
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{/* <table>*/}}
|
|
||||||
{{/* <tr>*/}}
|
|
||||||
{{/* <td><label for="qr">QR Code:</label></td>*/}}
|
|
||||||
{{/* {{if .Qr}}*/}}
|
|
||||||
{{/* <td><input type="number" id="qr" name="qr" value="{{.Qr}}" required readonly></td>*/}}
|
|
||||||
{{/* {{else}}*/}}
|
|
||||||
{{/* <td><input type="number" id="qr" name="qr" required></td>*/}}
|
|
||||||
{{/* {{end}}*/}}
|
|
||||||
{{/* </tr>*/}}
|
|
||||||
{{/* <tr>*/}}
|
|
||||||
{{/* <td><label for="asset_type">Type:</label></td>*/}}
|
|
||||||
{{/* <td><input type="text" id="asset_type" name="asset_type" required readonly value="{{.Type}}"></td>*/}}
|
|
||||||
{{/* </tr>*/}}
|
|
||||||
{{/* <tr>*/}}
|
|
||||||
{{/* <td><label for="asset_brand">Brand:</label></td>*/}}
|
|
||||||
{{/* <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 .AssetBrands}}*/}}
|
|
||||||
{{/* {{if ne . "Unknown"}}*/}}
|
|
||||||
{{/* <option value="{{.}}" {{if eq . $.AssetBrand}}selected{{end}}>{{.}}</option>*/}}
|
|
||||||
{{/* {{end}}*/}}
|
|
||||||
{{/* {{end}}*/}}
|
|
||||||
{{/* <option>New...</option>*/}}
|
|
||||||
{{/* </select>*/}}
|
|
||||||
{{/* </td>*/}}
|
|
||||||
{{/* </tr>*/}}
|
|
||||||
{{/* <tr>*/}}
|
|
||||||
{{/* <td><label for="asset_name">Name:</label></td>*/}}
|
|
||||||
{{/* <td><input type="text" id="asset_name" name="asset_name" value="{{.AssetName}}"></td>*/}}
|
|
||||||
{{/* </tr>*/}}
|
|
||||||
{{/* <tr>*/}}
|
|
||||||
{{/* <td><label for="asset_description">Description:</label></td>*/}}
|
|
||||||
{{/* <td><textarea id="asset_description" name="asset_description">{{.AssetDescription}}</textarea></td>*/}}
|
|
||||||
{{/* </tr>*/}}
|
|
||||||
{{/* </table>*/}}
|
|
||||||
|
|
||||||
{{/* {{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}}*/}}
|
|
||||||
{{/* <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}}
|
|
||||||
<input type="submit" value="Edit">
|
|
||||||
{{else}}
|
|
||||||
<input type="submit" value="Create">
|
|
||||||
{{end}}
|
|
||||||
</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}}*/}}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{{- /*gotype: pcinv.DeleteVM*/ -}}
|
|
||||||
{{define "delete"}}
|
|
||||||
{{template "header" "Delete Device"}}
|
|
||||||
<h2>Are you sure you want to delete this device?</h2>
|
|
||||||
<form id="confirmForm" method="post" action="/delete?id={{.Qr}}"></form>
|
|
||||||
<a href="/device?id={{.Qr}}"><button><b>No</b></button></a>
|
|
||||||
<button form="confirmForm">Yes</button>
|
|
||||||
{{template "footer"}}
|
|
||||||
{{end}}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
{{- /*gotype: main.DeviceVM */}}
|
|
||||||
{{define "device"}}
|
|
||||||
{{template "header" "Device Details"}}
|
|
||||||
<table border="1">
|
|
||||||
<tr>
|
|
||||||
<td>Name:</td>
|
|
||||||
<td>{{.Name}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Brand:</td>
|
|
||||||
<td>{{.Brand}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Type:</td>
|
|
||||||
<td>{{.Type}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Description:</td>
|
|
||||||
<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>
|
|
||||||
{{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>
|
|
||||||
{{template "footer"}}
|
|
||||||
{{end}}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{{- /*gotype: main.ErrorVM*/}}
|
|
||||||
{{define "errors"}}
|
|
||||||
{{template "header" .StatusCode | statusText}}
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{{range .Errors}}
|
|
||||||
<li>{{.}}</li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{{template "footer"}}
|
|
||||||
{{end}}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{{define "footer"}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
{{end}}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{{define "header"}}
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>PC Inventory{{if .}} - {{.}}{{end}}</title>
|
|
||||||
<script src="/static/scripts.js" type="application/javascript"></script>
|
|
||||||
</head>
|
|
||||||
<body bgcolor="beige">
|
|
||||||
<h1><a href="/">PC Inventory</a>{{if .}} - <i>{{.}}{{end}}</i></h1>
|
|
||||||
<form action="/device" method="get">
|
|
||||||
<label for="id">Device ID:</label>
|
|
||||||
<input type="text" id="id" name="id">
|
|
||||||
<input type="submit" value="Find by ID">
|
|
||||||
<a href="/create">Create Device</a>
|
|
||||||
</form>
|
|
||||||
<hr>
|
|
||||||
{{end}}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{{- /*gotype: main.IndexVM*/}}
|
|
||||||
{{define "index"}}
|
|
||||||
{{template "header"}}
|
|
||||||
<h2>Statistics</h2>
|
|
||||||
The inventory contains:
|
|
||||||
<ul>
|
|
||||||
<li><b>{{.AssetCount}}</b> assets in total.</li>
|
|
||||||
<li><b>{{.BrandCount}}</b> unique brands.</li>
|
|
||||||
<li>a combined <b>{{.TotalRamCapacity | formatMemorySize}}</b> of RAM.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2>Filter Devices</h2>
|
|
||||||
<form action="/browse" method="get">
|
|
||||||
<h3>Select Brands:</h3>
|
|
||||||
{{range .Brands}}
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" name="brand" checked value="{{.}}">
|
|
||||||
{{.}}
|
|
||||||
</label><br>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<h3>Select Types:</h3>
|
|
||||||
{{range .Types}}
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" name="type" checked value="{{.}}">
|
|
||||||
{{. | formatType}}
|
|
||||||
</label><br>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<button type="submit">Browse</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{{template "footer"}}
|
|
||||||
{{end}}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CreateDeviceVM struct {
|
|
||||||
IsEdit bool
|
|
||||||
DescriptorTree *DescriptorRoot
|
|
||||||
|
|
||||||
// Assets
|
|
||||||
Qr *int
|
|
||||||
Type string
|
|
||||||
|
|
||||||
Values map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vm *CreateDeviceVM) SetValue(assetType string, field string, value string) {
|
|
||||||
if vm.Values == nil {
|
|
||||||
vm.Values = make(map[string]string)
|
|
||||||
}
|
|
||||||
vm.Values[assetType+"-"+field] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vm *CreateDeviceVM) GetValue(assetType string, field string) string {
|
|
||||||
if vm.Values == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return vm.Values[assetType+"-"+field]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vm *CreateDeviceVM) NiceType() string {
|
|
||||||
return getAssetTypeById(vm.Type).Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vm *CreateDeviceVM) IsPartOf(assertType string) bool {
|
|
||||||
if assertType == "asset" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return assertType == vm.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) getCreateDevice(c *gin.Context) {
|
|
||||||
var err error
|
|
||||||
vm := &CreateDeviceVM{}
|
|
||||||
vm.DescriptorTree = DescriptorTree
|
|
||||||
vm.Type = c.Query("type")
|
|
||||||
|
|
||||||
qr := c.Query("id")
|
|
||||||
if qr != "" {
|
|
||||||
qrInt, err := strconv.Atoi(qr)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("invalid qr: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
vm.Qr = &qrInt
|
|
||||||
}
|
|
||||||
|
|
||||||
err = a.GetAllGroups(vm)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Query("edit") != "" && vm.Qr != nil {
|
|
||||||
vm.IsEdit = true
|
|
||||||
err := a.pullDataFromDb(*vm.Qr, "asset", vm)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("failed to load asset data: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//// Load the asset data from the database
|
|
||||||
//err = a.db.Query("SELECT * FROM assets WHERE qr = ?").
|
|
||||||
// Bind(*vm.Qr).
|
|
||||||
// ScanColumns(&columns).
|
|
||||||
// ScanSingle(&vm.Qr, &vm.Type, &vm.Values)
|
|
||||||
//if err != nil {
|
|
||||||
// c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("failed to load asset: %v", err))
|
|
||||||
// return
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
|
|
||||||
//err = a.db.Query("SELECT name, type, brand, description FROM assets WHERE qr = ?").
|
|
||||||
// Bind(*vm.Qr).
|
|
||||||
// ScanSingle(&vm.AssetName, &vm.Type, &vm.AssetBrand, &vm.AssetDescription)
|
|
||||||
//if err != nil {
|
|
||||||
// c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//if vm.Type == "ram" {
|
|
||||||
// err = a.db.Query("SELECT type, capacity FROM info_ram WHERE asset = ?").
|
|
||||||
// Bind(*vm.Qr).
|
|
||||||
// ScanSingle(&vm.RamType, &vm.RamCapacity)
|
|
||||||
// if err != nil {
|
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "create_device", vm)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) pullDataFromDb(qr int, assetType string, vm *CreateDeviceVM) error {
|
|
||||||
var fields []string
|
|
||||||
assetDescriptor := getAssetTypeById(assetType)
|
|
||||||
for _, field := range assetDescriptor.Fields {
|
|
||||||
fields = append(fields, field.Id)
|
|
||||||
}
|
|
||||||
values := make([]any, len(fields))
|
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT %s FROM %s WHERE qr = ?", strings.Join(fields, ", "), assetDescriptor.Table)
|
|
||||||
err := a.db.Query(query).Bind(qr).ScanSingle(values...)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to load asset data: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, field := range fields {
|
|
||||||
vm.SetValue(assetType, field, fmt.Sprintf("%v", values[i]))
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DeviceVM struct {
|
|
||||||
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) {
|
|
||||||
qr, err := strconv.Atoi(c.Query("id"))
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusBadRequest, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var count int
|
|
||||||
err = a.db.Query("SELECT COUNT(*) FROM assets WHERE qr = ?").
|
|
||||||
Bind(qr).
|
|
||||||
ScanSingle(&count)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if count == 0 {
|
|
||||||
c.Redirect(http.StatusTemporaryRedirect, "/create?id="+strconv.Itoa(qr))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vm := &DeviceVM{Qr: qr}
|
|
||||||
err = a.db.Query("SELECT name, brand, type, description FROM assets WHERE qr = ?").
|
|
||||||
Bind(qr).
|
|
||||||
ScanSingle(&vm.Name, &vm.Brand, &vm.Type, &vm.Description)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if vm.Type == "ram" {
|
|
||||||
err = a.db.Query("SELECT type, capacity FROM info_ram WHERE asset = ?").
|
|
||||||
Bind(qr).
|
|
||||||
ScanSingle(&vm.RamType, &vm.RamCapacity)
|
|
||||||
if err != nil {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IndexVM struct {
|
|
||||||
AssetCount int
|
|
||||||
BrandCount int
|
|
||||||
TotalRamCapacity int
|
|
||||||
Brands []string
|
|
||||||
Types []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) getIndex(c *gin.Context) {
|
|
||||||
vm := &IndexVM{}
|
|
||||||
var err error
|
|
||||||
vm.AssetCount, err = a.GetAssetCount()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.BrandCount, err = a.GetBrandCount()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.TotalRamCapacity, err = a.GetTotalRamCapacity()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Brands, err = a.GetAllBrands()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Types, err = a.GetAllTypes()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "index", vm)
|
|
||||||
}
|
|
||||||
276
views.go
276
views.go
@@ -1,276 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"gitea.seeseepuff.be/seeseemelk/mysqlite"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type App struct {
|
|
||||||
db *mysqlite.Db
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) postCreateDevice(c *gin.Context) {
|
|
||||||
qr, err := strconv.Atoi(c.PostForm("asset-qr"))
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("invalid qr: %v", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the asset into the database
|
|
||||||
var id int
|
|
||||||
err = a.createAsset("asset", tx, c, &id)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("error inserting asset: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
assetType := c.PostForm("asset-type")
|
|
||||||
err = a.createAsset(assetType, tx, c, &id)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, fmt.Errorf("error inserting asset type: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tx.Commit()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Redirect(http.StatusSeeOther, "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) createAsset(assetType string, tx *mysqlite.Tx, c *gin.Context, assetId *int) error {
|
|
||||||
for _, assetDescriptor := range DescriptorTree.AssetTypes {
|
|
||||||
if assetDescriptor.Id != assetType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var fields []string
|
|
||||||
var questions []string
|
|
||||||
var values []string
|
|
||||||
|
|
||||||
for _, field := range assetDescriptor.Fields {
|
|
||||||
fields = append(fields, field.Id)
|
|
||||||
questions = append(questions, "?")
|
|
||||||
values = append(values, c.PostForm(assetType+"-"+field.Id))
|
|
||||||
}
|
|
||||||
|
|
||||||
if *assetId != 0 {
|
|
||||||
fields = append(fields, "asset")
|
|
||||||
questions = append(questions, "?")
|
|
||||||
values = append(values, strconv.Itoa(*assetId))
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldsStr := strings.Join(fields, ", ")
|
|
||||||
questionsStr := strings.Join(questions, ", ")
|
|
||||||
err := tx.Query(fmt.Sprintf("INSERT INTO %s (%s) values (%s)", assetDescriptor.Table, fieldsStr, questionsStr)).
|
|
||||||
Bind(values).
|
|
||||||
Exec()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if *assetId == 0 {
|
|
||||||
err := tx.Query("SELECT LAST_INSERT_ROWID()").ScanSingle(assetId)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting last insert id: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errors.New("Create Asset not implemented for type: " + assetType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) postCreateDeviceRam(c *gin.Context, qr int, tx *mysqlite.Tx) error {
|
|
||||||
var err error
|
|
||||||
capacity := 0
|
|
||||||
capacityString := c.PostForm("ram_capacity")
|
|
||||||
if capacityString != "" {
|
|
||||||
capacity, err = strconv.Atoi(c.PostForm("ram_capacity"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch c.PostForm("ram_capacity_unit") {
|
|
||||||
case "B":
|
|
||||||
case "KB":
|
|
||||||
capacity *= 1024
|
|
||||||
case "MB":
|
|
||||||
capacity *= 1024 * 1024
|
|
||||||
case "GB":
|
|
||||||
capacity *= 1024 * 1024 * 1024
|
|
||||||
default:
|
|
||||||
return errors.New("invalid ram_capacity_unit")
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
Assets []Asset
|
|
||||||
HasRam bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Asset struct {
|
|
||||||
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) {
|
|
||||||
brands := c.QueryArray("brand")
|
|
||||||
types := c.QueryArray("type")
|
|
||||||
|
|
||||||
query := `SELECT assets.qr, assets.name, assets.brand, assets.type, assets.description,
|
|
||||||
info_ram.type, info_ram.capacity,
|
|
||||||
info_hdd.capacity, info_hdd.type, info_hdd.form_factor, info_hdd.connection, info_hdd.rpm
|
|
||||||
FROM assets
|
|
||||||
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)) + ")"
|
|
||||||
}
|
|
||||||
if len(types) > 0 {
|
|
||||||
query += " AND assets.type IN (" + placeholders(len(types)) + ")"
|
|
||||||
}
|
|
||||||
query += "ORDER BY assets.type, assets.brand, assets.name, assets.qr"
|
|
||||||
|
|
||||||
vm := &BrowseVM{}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
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,
|
|
||||||
&asset.HddCapacity, &asset.HddType, &asset.HddFormFactor, &asset.HddConnection, &asset.HddRpm)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
vm.Assets = append(vm.Assets, asset)
|
|
||||||
if asset.Type == "ram" {
|
|
||||||
vm.HasRam = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "browse", vm)
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeleteVM struct {
|
|
||||||
Qr int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) getDelete(c *gin.Context) {
|
|
||||||
qr, err := strconv.Atoi(c.Query("id"))
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid qr: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
vm := &DeleteVM{Qr: qr}
|
|
||||||
c.HTML(http.StatusOK, "delete", vm)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) postDelete(c *gin.Context) {
|
|
||||||
qr, err := strconv.Atoi(c.Query("id"))
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid qr: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tx, err := a.db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = a.DeleteAsset(tx, qr)
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tx.Commit()
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Redirect(http.StatusSeeOther, "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
func placeholders(count int) string {
|
|
||||||
if count == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
placeholder := "?"
|
|
||||||
for count > 1 {
|
|
||||||
placeholder += ", ?"
|
|
||||||
count--
|
|
||||||
}
|
|
||||||
return placeholder
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user