Initial implementation of inventree
A small IT asset inventory system built around a nested folder tree, matching the project brief: Go + html/template + Bootstrap 5 + vanilla JS, SQLite storage (WAL, FKs, migrations), embedded templates/static assets, single compiled binary. - AJAX-driven inventory tree: lazy-loaded folder expansion with per-user persisted expand state, drag-and-drop move for folders/assets, safe delete-with-relocate-or-cascade confirmation, search with breadcrumbs. - Assets: CRUD, duplicate, move, auto-generated IT-000001-style IDs, CSV import (with optional folder auto-create) and export. - Admin-defined item types with custom fields (text/long_text/number/date/ boolean/dropdown/url/ip_address). - Configurable statuses, session-based auth (bcrypt, secure cookies), admin/user roles, user management. - CLI: serve, version, database migrate, database backup; /healthz; graceful shutdown; Dockerfile/docker-compose/systemd unit; Go test suite.
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
// Package models defines the core domain types shared across inventree.
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type Role string
|
||||
|
||||
const (
|
||||
RoleAdmin Role = "admin"
|
||||
RoleUser Role = "user"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID int64
|
||||
Username string
|
||||
PasswordHash string
|
||||
Role Role
|
||||
Enabled bool
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (u User) IsAdmin() bool { return u.Role == RoleAdmin }
|
||||
|
||||
type Folder struct {
|
||||
ID int64
|
||||
Name string
|
||||
ParentID *int64
|
||||
Description string
|
||||
Icon string
|
||||
SortOrder int
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
|
||||
// Populated by list/tree queries; not persisted directly on this table.
|
||||
FolderCount int
|
||||
AssetCount int
|
||||
}
|
||||
|
||||
type Status struct {
|
||||
ID int64
|
||||
Name string
|
||||
Color string
|
||||
SortOrder int
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type FieldType string
|
||||
|
||||
const (
|
||||
FieldTypeText FieldType = "text"
|
||||
FieldTypeLongText FieldType = "long_text"
|
||||
FieldTypeNumber FieldType = "number"
|
||||
FieldTypeDate FieldType = "date"
|
||||
FieldTypeBoolean FieldType = "boolean"
|
||||
FieldTypeDropdown FieldType = "dropdown"
|
||||
FieldTypeURL FieldType = "url"
|
||||
FieldTypeIPAddress FieldType = "ip_address"
|
||||
)
|
||||
|
||||
var AllFieldTypes = []FieldType{
|
||||
FieldTypeText, FieldTypeLongText, FieldTypeNumber, FieldTypeDate,
|
||||
FieldTypeBoolean, FieldTypeDropdown, FieldTypeURL, FieldTypeIPAddress,
|
||||
}
|
||||
|
||||
func (t FieldType) Label() string {
|
||||
switch t {
|
||||
case FieldTypeText:
|
||||
return "Text"
|
||||
case FieldTypeLongText:
|
||||
return "Long Text"
|
||||
case FieldTypeNumber:
|
||||
return "Number"
|
||||
case FieldTypeDate:
|
||||
return "Date"
|
||||
case FieldTypeBoolean:
|
||||
return "Boolean"
|
||||
case FieldTypeDropdown:
|
||||
return "Dropdown"
|
||||
case FieldTypeURL:
|
||||
return "URL"
|
||||
case FieldTypeIPAddress:
|
||||
return "IP Address"
|
||||
}
|
||||
return string(t)
|
||||
}
|
||||
|
||||
type ItemType struct {
|
||||
ID int64
|
||||
Name string
|
||||
Description string
|
||||
Icon string
|
||||
Enabled bool
|
||||
SortOrder int
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
|
||||
Fields []CustomFieldDef
|
||||
}
|
||||
|
||||
type CustomFieldDef struct {
|
||||
ID int64
|
||||
ItemTypeID int64
|
||||
Name string
|
||||
FieldKey string
|
||||
FieldType FieldType
|
||||
Required bool
|
||||
DefaultValue string
|
||||
Options []string
|
||||
SortOrder int
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type CustomFieldValue struct {
|
||||
ID int64
|
||||
AssetID int64
|
||||
FieldDefID int64
|
||||
Value string
|
||||
}
|
||||
|
||||
type Asset struct {
|
||||
ID int64
|
||||
AssetTag string
|
||||
Name string
|
||||
ItemTypeID int64
|
||||
FolderID *int64
|
||||
StatusID int64
|
||||
AssignedUserID *int64
|
||||
Notes string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
|
||||
// Populated by joined list/detail queries.
|
||||
ItemTypeName string
|
||||
ItemTypeIcon string
|
||||
StatusName string
|
||||
StatusColor string
|
||||
AssignedUsername string
|
||||
FolderPath []BreadcrumbItem
|
||||
CustomFields []AssetFieldValue
|
||||
}
|
||||
|
||||
type AssetFieldValue struct {
|
||||
Def CustomFieldDef
|
||||
Value string
|
||||
}
|
||||
|
||||
type BreadcrumbItem struct {
|
||||
ID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// TreeNode is a folder-or-asset node used to render the inventory tree.
|
||||
type TreeNode struct {
|
||||
Type string // "folder" or "asset"
|
||||
ID int64
|
||||
Name string
|
||||
Icon string
|
||||
ParentID *int64
|
||||
HasChildren bool
|
||||
AssetTag string
|
||||
StatusName string
|
||||
StatusColor string
|
||||
|
||||
// Populated only when the node is pre-expanded for server-side
|
||||
// recursive rendering (see web.buildTree); empty otherwise, in which
|
||||
// case the client lazy-loads children via /app/tree/children.
|
||||
Expanded bool
|
||||
Children []TreeNode
|
||||
MoreAssets int // count of additional assets beyond the tree display cap, if any
|
||||
}
|
||||
Reference in New Issue
Block a user