mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2026-01-01 18:47:20 +01:00
* feat: Add item templates feature (#435) Add ability to create and manage item templates for quick item creation. Templates store default values and custom fields that can be applied when creating new items. Backend changes: - New ItemTemplate and TemplateField Ent schemas - Template CRUD API endpoints - Create item from template endpoint Frontend changes: - Templates management page with create/edit/delete - Template selector in item creation modal - 'Use as Template' action on item detail page - Templates link in navigation menu * refactor: Improve template item creation with a single query - Add `CreateFromTemplate` method to ItemsRepository that creates items with all template data (including custom fields) in a single atomic transaction, replacing the previous two-phase create-then-update pattern - Fix `GetOne` to require group ID parameter so templates can only be accessed by users in the owning group (security fix) - Simplify `HandleItemTemplatesCreateItem` handler using the new transactional method * Refactor item template types and formatting Updated type annotations in CreateModal.vue to use specific ItemTemplate types instead of 'any'. Improved code formatting for template fields and manufacturer display. Also refactored warranty field logic in item details page for better readability. This resolves the linter issues as well that the bot in github keeps nagging at. * Add 'id' property to template fields Introduces an 'id' property to each field object in CreateModal.vue and item details page to support unique identification of fields. This change prepares the codebase for future enhancements that may require field-level identification. * Removed redundant SQL migrations. Removed redundant SQL migrations per @tankerkiller125's findings. * Updates to PR #1099. Regarding pull #1099. Fixed an issue causing some conflict with GUIDs and old rows in the migration files. * Add new fields and location edge to ItemTemplate Addresses recommendations from @tonyaellie. * Relocated add template button * Added more default fields to the template * Added translation of all strings (think so?) * Make oval buttons round * Added duplicate button to the template (this required a rewrite of the migration files, I made sure only 1 exists per DB type) * Added a Save as template button to a item detail view (this creates a template with all the current data of that item) * Changed all occurrences of space to gap and flex where applicable. * Made template selection persistent after item created. * Collapsible template info on creation view. * Updates to translation and fix for labels/locations I also added a test in here because I keep missing small function tests. That should prevent that from happening again. * Linted * Bring up to date with main, fix some lint/type check issues * In theory fix playwright tests * Fix defaults being unable to be nullable/empty (and thus limiting flexibility) * Last few fixes I think * Forgot to fix the golang tests --------- Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
202 lines
7.2 KiB
Go
Generated
202 lines
7.2 KiB
Go
Generated
// Code generated by ent, DO NOT EDIT.
|
|
|
|
package ent
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"entgo.io/ent"
|
|
"entgo.io/ent/dialect/sql"
|
|
"github.com/google/uuid"
|
|
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/itemtemplate"
|
|
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/templatefield"
|
|
)
|
|
|
|
// TemplateField is the model entity for the TemplateField schema.
|
|
type TemplateField struct {
|
|
config `json:"-"`
|
|
// ID of the ent.
|
|
ID uuid.UUID `json:"id,omitempty"`
|
|
// CreatedAt holds the value of the "created_at" field.
|
|
CreatedAt time.Time `json:"created_at,omitempty"`
|
|
// UpdatedAt holds the value of the "updated_at" field.
|
|
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
|
// Name holds the value of the "name" field.
|
|
Name string `json:"name,omitempty"`
|
|
// Description holds the value of the "description" field.
|
|
Description string `json:"description,omitempty"`
|
|
// Type holds the value of the "type" field.
|
|
Type templatefield.Type `json:"type,omitempty"`
|
|
// TextValue holds the value of the "text_value" field.
|
|
TextValue string `json:"text_value,omitempty"`
|
|
// Edges holds the relations/edges for other nodes in the graph.
|
|
// The values are being populated by the TemplateFieldQuery when eager-loading is set.
|
|
Edges TemplateFieldEdges `json:"edges"`
|
|
item_template_fields *uuid.UUID
|
|
selectValues sql.SelectValues
|
|
}
|
|
|
|
// TemplateFieldEdges holds the relations/edges for other nodes in the graph.
|
|
type TemplateFieldEdges struct {
|
|
// ItemTemplate holds the value of the item_template edge.
|
|
ItemTemplate *ItemTemplate `json:"item_template,omitempty"`
|
|
// loadedTypes holds the information for reporting if a
|
|
// type was loaded (or requested) in eager-loading or not.
|
|
loadedTypes [1]bool
|
|
}
|
|
|
|
// ItemTemplateOrErr returns the ItemTemplate value or an error if the edge
|
|
// was not loaded in eager-loading, or loaded but was not found.
|
|
func (e TemplateFieldEdges) ItemTemplateOrErr() (*ItemTemplate, error) {
|
|
if e.ItemTemplate != nil {
|
|
return e.ItemTemplate, nil
|
|
} else if e.loadedTypes[0] {
|
|
return nil, &NotFoundError{label: itemtemplate.Label}
|
|
}
|
|
return nil, &NotLoadedError{edge: "item_template"}
|
|
}
|
|
|
|
// scanValues returns the types for scanning values from sql.Rows.
|
|
func (*TemplateField) scanValues(columns []string) ([]any, error) {
|
|
values := make([]any, len(columns))
|
|
for i := range columns {
|
|
switch columns[i] {
|
|
case templatefield.FieldName, templatefield.FieldDescription, templatefield.FieldType, templatefield.FieldTextValue:
|
|
values[i] = new(sql.NullString)
|
|
case templatefield.FieldCreatedAt, templatefield.FieldUpdatedAt:
|
|
values[i] = new(sql.NullTime)
|
|
case templatefield.FieldID:
|
|
values[i] = new(uuid.UUID)
|
|
case templatefield.ForeignKeys[0]: // item_template_fields
|
|
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
|
|
default:
|
|
values[i] = new(sql.UnknownType)
|
|
}
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// assignValues assigns the values that were returned from sql.Rows (after scanning)
|
|
// to the TemplateField fields.
|
|
func (_m *TemplateField) assignValues(columns []string, values []any) error {
|
|
if m, n := len(values), len(columns); m < n {
|
|
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
|
|
}
|
|
for i := range columns {
|
|
switch columns[i] {
|
|
case templatefield.FieldID:
|
|
if value, ok := values[i].(*uuid.UUID); !ok {
|
|
return fmt.Errorf("unexpected type %T for field id", values[i])
|
|
} else if value != nil {
|
|
_m.ID = *value
|
|
}
|
|
case templatefield.FieldCreatedAt:
|
|
if value, ok := values[i].(*sql.NullTime); !ok {
|
|
return fmt.Errorf("unexpected type %T for field created_at", values[i])
|
|
} else if value.Valid {
|
|
_m.CreatedAt = value.Time
|
|
}
|
|
case templatefield.FieldUpdatedAt:
|
|
if value, ok := values[i].(*sql.NullTime); !ok {
|
|
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
|
|
} else if value.Valid {
|
|
_m.UpdatedAt = value.Time
|
|
}
|
|
case templatefield.FieldName:
|
|
if value, ok := values[i].(*sql.NullString); !ok {
|
|
return fmt.Errorf("unexpected type %T for field name", values[i])
|
|
} else if value.Valid {
|
|
_m.Name = value.String
|
|
}
|
|
case templatefield.FieldDescription:
|
|
if value, ok := values[i].(*sql.NullString); !ok {
|
|
return fmt.Errorf("unexpected type %T for field description", values[i])
|
|
} else if value.Valid {
|
|
_m.Description = value.String
|
|
}
|
|
case templatefield.FieldType:
|
|
if value, ok := values[i].(*sql.NullString); !ok {
|
|
return fmt.Errorf("unexpected type %T for field type", values[i])
|
|
} else if value.Valid {
|
|
_m.Type = templatefield.Type(value.String)
|
|
}
|
|
case templatefield.FieldTextValue:
|
|
if value, ok := values[i].(*sql.NullString); !ok {
|
|
return fmt.Errorf("unexpected type %T for field text_value", values[i])
|
|
} else if value.Valid {
|
|
_m.TextValue = value.String
|
|
}
|
|
case templatefield.ForeignKeys[0]:
|
|
if value, ok := values[i].(*sql.NullScanner); !ok {
|
|
return fmt.Errorf("unexpected type %T for field item_template_fields", values[i])
|
|
} else if value.Valid {
|
|
_m.item_template_fields = new(uuid.UUID)
|
|
*_m.item_template_fields = *value.S.(*uuid.UUID)
|
|
}
|
|
default:
|
|
_m.selectValues.Set(columns[i], values[i])
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Value returns the ent.Value that was dynamically selected and assigned to the TemplateField.
|
|
// This includes values selected through modifiers, order, etc.
|
|
func (_m *TemplateField) Value(name string) (ent.Value, error) {
|
|
return _m.selectValues.Get(name)
|
|
}
|
|
|
|
// QueryItemTemplate queries the "item_template" edge of the TemplateField entity.
|
|
func (_m *TemplateField) QueryItemTemplate() *ItemTemplateQuery {
|
|
return NewTemplateFieldClient(_m.config).QueryItemTemplate(_m)
|
|
}
|
|
|
|
// Update returns a builder for updating this TemplateField.
|
|
// Note that you need to call TemplateField.Unwrap() before calling this method if this TemplateField
|
|
// was returned from a transaction, and the transaction was committed or rolled back.
|
|
func (_m *TemplateField) Update() *TemplateFieldUpdateOne {
|
|
return NewTemplateFieldClient(_m.config).UpdateOne(_m)
|
|
}
|
|
|
|
// Unwrap unwraps the TemplateField entity that was returned from a transaction after it was closed,
|
|
// so that all future queries will be executed through the driver which created the transaction.
|
|
func (_m *TemplateField) Unwrap() *TemplateField {
|
|
_tx, ok := _m.config.driver.(*txDriver)
|
|
if !ok {
|
|
panic("ent: TemplateField is not a transactional entity")
|
|
}
|
|
_m.config.driver = _tx.drv
|
|
return _m
|
|
}
|
|
|
|
// String implements the fmt.Stringer.
|
|
func (_m *TemplateField) String() string {
|
|
var builder strings.Builder
|
|
builder.WriteString("TemplateField(")
|
|
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
|
|
builder.WriteString("created_at=")
|
|
builder.WriteString(_m.CreatedAt.Format(time.ANSIC))
|
|
builder.WriteString(", ")
|
|
builder.WriteString("updated_at=")
|
|
builder.WriteString(_m.UpdatedAt.Format(time.ANSIC))
|
|
builder.WriteString(", ")
|
|
builder.WriteString("name=")
|
|
builder.WriteString(_m.Name)
|
|
builder.WriteString(", ")
|
|
builder.WriteString("description=")
|
|
builder.WriteString(_m.Description)
|
|
builder.WriteString(", ")
|
|
builder.WriteString("type=")
|
|
builder.WriteString(fmt.Sprintf("%v", _m.Type))
|
|
builder.WriteString(", ")
|
|
builder.WriteString("text_value=")
|
|
builder.WriteString(_m.TextValue)
|
|
builder.WriteByte(')')
|
|
return builder.String()
|
|
}
|
|
|
|
// TemplateFields is a parsable slice of TemplateField.
|
|
type TemplateFields []*TemplateField
|