feat: allow nested relationships for locations and items (#102)

Basic implementation that allows organizing Locations and Items within each other.
This commit is contained in:
Hayden 2022-10-23 20:54:39 -08:00 committed by GitHub
parent fe6cd431a6
commit a4b4fe3454
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 2329 additions and 126 deletions

View file

@ -845,6 +845,15 @@ const docTemplate = `{
"name": "id", "name": "id",
"in": "path", "in": "path",
"required": true "required": true
},
{
"description": "Location Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/repo.LocationUpdate"
}
} }
], ],
"responses": { "responses": {
@ -1232,6 +1241,10 @@ const docTemplate = `{
}, },
"name": { "name": {
"type": "string" "type": "string"
},
"parentId": {
"type": "string",
"x-nullable": true
} }
} }
}, },
@ -1270,6 +1283,12 @@ const docTemplate = `{
"$ref": "#/definitions/repo.ItemAttachment" "$ref": "#/definitions/repo.ItemAttachment"
} }
}, },
"children": {
"type": "array",
"items": {
"$ref": "#/definitions/repo.ItemSummary"
}
},
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
@ -1277,7 +1296,6 @@ const docTemplate = `{
"type": "string" "type": "string"
}, },
"fields": { "fields": {
"description": "Future",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/repo.ItemField" "$ref": "#/definitions/repo.ItemField"
@ -1301,6 +1319,8 @@ const docTemplate = `{
}, },
"location": { "location": {
"description": "Edges", "description": "Edges",
"x-nullable": true,
"x-omitempty": true,
"$ref": "#/definitions/repo.LocationSummary" "$ref": "#/definitions/repo.LocationSummary"
}, },
"manufacturer": { "manufacturer": {
@ -1316,6 +1336,11 @@ const docTemplate = `{
"description": "Extras", "description": "Extras",
"type": "string" "type": "string"
}, },
"parent": {
"x-nullable": true,
"x-omitempty": true,
"$ref": "#/definitions/repo.ItemSummary"
},
"purchaseFrom": { "purchaseFrom": {
"type": "string" "type": "string"
}, },
@ -1381,6 +1406,8 @@ const docTemplate = `{
}, },
"location": { "location": {
"description": "Edges", "description": "Edges",
"x-nullable": true,
"x-omitempty": true,
"$ref": "#/definitions/repo.LocationSummary" "$ref": "#/definitions/repo.LocationSummary"
}, },
"name": { "name": {
@ -1439,6 +1466,11 @@ const docTemplate = `{
"description": "Extras", "description": "Extras",
"type": "string" "type": "string"
}, },
"parentId": {
"type": "string",
"x-nullable": true,
"x-omitempty": true
},
"purchaseFrom": { "purchaseFrom": {
"type": "string" "type": "string"
}, },
@ -1553,6 +1585,12 @@ const docTemplate = `{
"repo.LocationOut": { "repo.LocationOut": {
"type": "object", "type": "object",
"properties": { "properties": {
"children": {
"type": "array",
"items": {
"$ref": "#/definitions/repo.LocationSummary"
}
},
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
@ -1571,6 +1609,9 @@ const docTemplate = `{
"name": { "name": {
"type": "string" "type": "string"
}, },
"parent": {
"$ref": "#/definitions/repo.LocationSummary"
},
"updatedAt": { "updatedAt": {
"type": "string" "type": "string"
} }
@ -1619,6 +1660,24 @@ const docTemplate = `{
} }
} }
}, },
"repo.LocationUpdate": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"parentId": {
"type": "string",
"x-nullable": true
}
}
},
"repo.PaginationResult-repo_ItemSummary": { "repo.PaginationResult-repo_ItemSummary": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -837,6 +837,15 @@
"name": "id", "name": "id",
"in": "path", "in": "path",
"required": true "required": true
},
{
"description": "Location Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/repo.LocationUpdate"
}
} }
], ],
"responses": { "responses": {
@ -1224,6 +1233,10 @@
}, },
"name": { "name": {
"type": "string" "type": "string"
},
"parentId": {
"type": "string",
"x-nullable": true
} }
} }
}, },
@ -1262,6 +1275,12 @@
"$ref": "#/definitions/repo.ItemAttachment" "$ref": "#/definitions/repo.ItemAttachment"
} }
}, },
"children": {
"type": "array",
"items": {
"$ref": "#/definitions/repo.ItemSummary"
}
},
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
@ -1269,7 +1288,6 @@
"type": "string" "type": "string"
}, },
"fields": { "fields": {
"description": "Future",
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/repo.ItemField" "$ref": "#/definitions/repo.ItemField"
@ -1293,6 +1311,8 @@
}, },
"location": { "location": {
"description": "Edges", "description": "Edges",
"x-nullable": true,
"x-omitempty": true,
"$ref": "#/definitions/repo.LocationSummary" "$ref": "#/definitions/repo.LocationSummary"
}, },
"manufacturer": { "manufacturer": {
@ -1308,6 +1328,11 @@
"description": "Extras", "description": "Extras",
"type": "string" "type": "string"
}, },
"parent": {
"x-nullable": true,
"x-omitempty": true,
"$ref": "#/definitions/repo.ItemSummary"
},
"purchaseFrom": { "purchaseFrom": {
"type": "string" "type": "string"
}, },
@ -1373,6 +1398,8 @@
}, },
"location": { "location": {
"description": "Edges", "description": "Edges",
"x-nullable": true,
"x-omitempty": true,
"$ref": "#/definitions/repo.LocationSummary" "$ref": "#/definitions/repo.LocationSummary"
}, },
"name": { "name": {
@ -1431,6 +1458,11 @@
"description": "Extras", "description": "Extras",
"type": "string" "type": "string"
}, },
"parentId": {
"type": "string",
"x-nullable": true,
"x-omitempty": true
},
"purchaseFrom": { "purchaseFrom": {
"type": "string" "type": "string"
}, },
@ -1545,6 +1577,12 @@
"repo.LocationOut": { "repo.LocationOut": {
"type": "object", "type": "object",
"properties": { "properties": {
"children": {
"type": "array",
"items": {
"$ref": "#/definitions/repo.LocationSummary"
}
},
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
@ -1563,6 +1601,9 @@
"name": { "name": {
"type": "string" "type": "string"
}, },
"parent": {
"$ref": "#/definitions/repo.LocationSummary"
},
"updatedAt": { "updatedAt": {
"type": "string" "type": "string"
} }
@ -1611,6 +1652,24 @@
} }
} }
}, },
"repo.LocationUpdate": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"parentId": {
"type": "string",
"x-nullable": true
}
}
},
"repo.PaginationResult-repo_ItemSummary": { "repo.PaginationResult-repo_ItemSummary": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -62,6 +62,9 @@ definitions:
type: string type: string
name: name:
type: string type: string
parentId:
type: string
x-nullable: true
type: object type: object
repo.ItemField: repo.ItemField:
properties: properties:
@ -86,12 +89,15 @@ definitions:
items: items:
$ref: '#/definitions/repo.ItemAttachment' $ref: '#/definitions/repo.ItemAttachment'
type: array type: array
children:
items:
$ref: '#/definitions/repo.ItemSummary'
type: array
createdAt: createdAt:
type: string type: string
description: description:
type: string type: string
fields: fields:
description: Future
items: items:
$ref: '#/definitions/repo.ItemField' $ref: '#/definitions/repo.ItemField'
type: array type: array
@ -109,6 +115,8 @@ definitions:
location: location:
$ref: '#/definitions/repo.LocationSummary' $ref: '#/definitions/repo.LocationSummary'
description: Edges description: Edges
x-nullable: true
x-omitempty: true
manufacturer: manufacturer:
type: string type: string
modelNumber: modelNumber:
@ -118,6 +126,10 @@ definitions:
notes: notes:
description: Extras description: Extras
type: string type: string
parent:
$ref: '#/definitions/repo.ItemSummary'
x-nullable: true
x-omitempty: true
purchaseFrom: purchaseFrom:
type: string type: string
purchasePrice: purchasePrice:
@ -164,6 +176,8 @@ definitions:
location: location:
$ref: '#/definitions/repo.LocationSummary' $ref: '#/definitions/repo.LocationSummary'
description: Edges description: Edges
x-nullable: true
x-omitempty: true
name: name:
type: string type: string
quantity: quantity:
@ -202,6 +216,10 @@ definitions:
notes: notes:
description: Extras description: Extras
type: string type: string
parentId:
type: string
x-nullable: true
x-omitempty: true
purchaseFrom: purchaseFrom:
type: string type: string
purchasePrice: purchasePrice:
@ -278,6 +296,10 @@ definitions:
type: object type: object
repo.LocationOut: repo.LocationOut:
properties: properties:
children:
items:
$ref: '#/definitions/repo.LocationSummary'
type: array
createdAt: createdAt:
type: string type: string
description: description:
@ -290,6 +312,8 @@ definitions:
type: array type: array
name: name:
type: string type: string
parent:
$ref: '#/definitions/repo.LocationSummary'
updatedAt: updatedAt:
type: string type: string
type: object type: object
@ -321,6 +345,18 @@ definitions:
updatedAt: updatedAt:
type: string type: string
type: object type: object
repo.LocationUpdate:
properties:
description:
type: string
id:
type: string
name:
type: string
parentId:
type: string
x-nullable: true
type: object
repo.PaginationResult-repo_ItemSummary: repo.PaginationResult-repo_ItemSummary:
properties: properties:
items: items:
@ -976,6 +1012,12 @@ paths:
name: id name: id
required: true required: true
type: string type: string
- description: Location Data
in: body
name: payload
required: true
schema:
$ref: '#/definitions/repo.LocationUpdate'
produces: produces:
- application/json - application/json
responses: responses:

View file

@ -88,8 +88,9 @@ func (ctrl *V1Controller) HandleLocationGet() http.HandlerFunc {
// @Summary updates a location // @Summary updates a location
// @Tags Locations // @Tags Locations
// @Produce json // @Produce json
// @Param id path string true "Location ID" // @Param id path string true "Location ID"
// @Success 200 {object} repo.LocationOut // @Param payload body repo.LocationUpdate true "Location Data"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [PUT] // @Router /v1/locations/{id} [PUT]
// @Security Bearer // @Security Bearer
func (ctrl *V1Controller) HandleLocationUpdate() http.HandlerFunc { func (ctrl *V1Controller) HandleLocationUpdate() http.HandlerFunc {

View file

@ -1043,6 +1043,38 @@ func (c *ItemClient) GetX(ctx context.Context, id uuid.UUID) *Item {
return obj return obj
} }
// QueryParent queries the parent edge of a Item.
func (c *ItemClient) QueryParent(i *Item) *ItemQuery {
query := &ItemQuery{config: c.config}
query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) {
id := i.ID
step := sqlgraph.NewStep(
sqlgraph.From(item.Table, item.FieldID, id),
sqlgraph.To(item.Table, item.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, item.ParentTable, item.ParentColumn),
)
fromV = sqlgraph.Neighbors(i.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryChildren queries the children edge of a Item.
func (c *ItemClient) QueryChildren(i *Item) *ItemQuery {
query := &ItemQuery{config: c.config}
query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) {
id := i.ID
step := sqlgraph.NewStep(
sqlgraph.From(item.Table, item.FieldID, id),
sqlgraph.To(item.Table, item.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, item.ChildrenTable, item.ChildrenColumn),
)
fromV = sqlgraph.Neighbors(i.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryGroup queries the group edge of a Item. // QueryGroup queries the group edge of a Item.
func (c *ItemClient) QueryGroup(i *Item) *GroupQuery { func (c *ItemClient) QueryGroup(i *Item) *GroupQuery {
query := &GroupQuery{config: c.config} query := &GroupQuery{config: c.config}
@ -1441,6 +1473,38 @@ func (c *LocationClient) GetX(ctx context.Context, id uuid.UUID) *Location {
return obj return obj
} }
// QueryParent queries the parent edge of a Location.
func (c *LocationClient) QueryParent(l *Location) *LocationQuery {
query := &LocationQuery{config: c.config}
query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) {
id := l.ID
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, id),
sqlgraph.To(location.Table, location.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, location.ParentTable, location.ParentColumn),
)
fromV = sqlgraph.Neighbors(l.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryChildren queries the children edge of a Location.
func (c *LocationClient) QueryChildren(l *Location) *LocationQuery {
query := &LocationQuery{config: c.config}
query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) {
id := l.ID
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, id),
sqlgraph.To(location.Table, location.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, location.ChildrenTable, location.ChildrenColumn),
)
fromV = sqlgraph.Neighbors(l.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryGroup queries the group edge of a Location. // QueryGroup queries the group edge of a Location.
func (c *LocationClient) QueryGroup(l *Location) *GroupQuery { func (c *LocationClient) QueryGroup(l *Location) *GroupQuery {
query := &GroupQuery{config: c.config} query := &GroupQuery{config: c.config}

View file

@ -65,11 +65,16 @@ type Item struct {
// The values are being populated by the ItemQuery when eager-loading is set. // The values are being populated by the ItemQuery when eager-loading is set.
Edges ItemEdges `json:"edges"` Edges ItemEdges `json:"edges"`
group_items *uuid.UUID group_items *uuid.UUID
item_children *uuid.UUID
location_items *uuid.UUID location_items *uuid.UUID
} }
// ItemEdges holds the relations/edges for other nodes in the graph. // ItemEdges holds the relations/edges for other nodes in the graph.
type ItemEdges struct { type ItemEdges struct {
// Parent holds the value of the parent edge.
Parent *Item `json:"parent,omitempty"`
// Children holds the value of the children edge.
Children []*Item `json:"children,omitempty"`
// Group holds the value of the group edge. // Group holds the value of the group edge.
Group *Group `json:"group,omitempty"` Group *Group `json:"group,omitempty"`
// Label holds the value of the label edge. // Label holds the value of the label edge.
@ -82,13 +87,35 @@ type ItemEdges struct {
Attachments []*Attachment `json:"attachments,omitempty"` Attachments []*Attachment `json:"attachments,omitempty"`
// loadedTypes holds the information for reporting if a // loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not. // type was loaded (or requested) in eager-loading or not.
loadedTypes [5]bool loadedTypes [7]bool
}
// ParentOrErr returns the Parent value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e ItemEdges) ParentOrErr() (*Item, error) {
if e.loadedTypes[0] {
if e.Parent == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: item.Label}
}
return e.Parent, nil
}
return nil, &NotLoadedError{edge: "parent"}
}
// ChildrenOrErr returns the Children value or an error if the edge
// was not loaded in eager-loading.
func (e ItemEdges) ChildrenOrErr() ([]*Item, error) {
if e.loadedTypes[1] {
return e.Children, nil
}
return nil, &NotLoadedError{edge: "children"}
} }
// GroupOrErr returns the Group value or an error if the edge // GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found. // was not loaded in eager-loading, or loaded but was not found.
func (e ItemEdges) GroupOrErr() (*Group, error) { func (e ItemEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[0] { if e.loadedTypes[2] {
if e.Group == nil { if e.Group == nil {
// Edge was loaded but was not found. // Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label} return nil, &NotFoundError{label: group.Label}
@ -101,7 +128,7 @@ func (e ItemEdges) GroupOrErr() (*Group, error) {
// LabelOrErr returns the Label value or an error if the edge // LabelOrErr returns the Label value or an error if the edge
// was not loaded in eager-loading. // was not loaded in eager-loading.
func (e ItemEdges) LabelOrErr() ([]*Label, error) { func (e ItemEdges) LabelOrErr() ([]*Label, error) {
if e.loadedTypes[1] { if e.loadedTypes[3] {
return e.Label, nil return e.Label, nil
} }
return nil, &NotLoadedError{edge: "label"} return nil, &NotLoadedError{edge: "label"}
@ -110,7 +137,7 @@ func (e ItemEdges) LabelOrErr() ([]*Label, error) {
// LocationOrErr returns the Location value or an error if the edge // LocationOrErr returns the Location value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found. // was not loaded in eager-loading, or loaded but was not found.
func (e ItemEdges) LocationOrErr() (*Location, error) { func (e ItemEdges) LocationOrErr() (*Location, error) {
if e.loadedTypes[2] { if e.loadedTypes[4] {
if e.Location == nil { if e.Location == nil {
// Edge was loaded but was not found. // Edge was loaded but was not found.
return nil, &NotFoundError{label: location.Label} return nil, &NotFoundError{label: location.Label}
@ -123,7 +150,7 @@ func (e ItemEdges) LocationOrErr() (*Location, error) {
// FieldsOrErr returns the Fields value or an error if the edge // FieldsOrErr returns the Fields value or an error if the edge
// was not loaded in eager-loading. // was not loaded in eager-loading.
func (e ItemEdges) FieldsOrErr() ([]*ItemField, error) { func (e ItemEdges) FieldsOrErr() ([]*ItemField, error) {
if e.loadedTypes[3] { if e.loadedTypes[5] {
return e.Fields, nil return e.Fields, nil
} }
return nil, &NotLoadedError{edge: "fields"} return nil, &NotLoadedError{edge: "fields"}
@ -132,7 +159,7 @@ func (e ItemEdges) FieldsOrErr() ([]*ItemField, error) {
// AttachmentsOrErr returns the Attachments value or an error if the edge // AttachmentsOrErr returns the Attachments value or an error if the edge
// was not loaded in eager-loading. // was not loaded in eager-loading.
func (e ItemEdges) AttachmentsOrErr() ([]*Attachment, error) { func (e ItemEdges) AttachmentsOrErr() ([]*Attachment, error) {
if e.loadedTypes[4] { if e.loadedTypes[6] {
return e.Attachments, nil return e.Attachments, nil
} }
return nil, &NotLoadedError{edge: "attachments"} return nil, &NotLoadedError{edge: "attachments"}
@ -157,7 +184,9 @@ func (*Item) scanValues(columns []string) ([]any, error) {
values[i] = new(uuid.UUID) values[i] = new(uuid.UUID)
case item.ForeignKeys[0]: // group_items case item.ForeignKeys[0]: // group_items
values[i] = &sql.NullScanner{S: new(uuid.UUID)} values[i] = &sql.NullScanner{S: new(uuid.UUID)}
case item.ForeignKeys[1]: // location_items case item.ForeignKeys[1]: // item_children
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
case item.ForeignKeys[2]: // location_items
values[i] = &sql.NullScanner{S: new(uuid.UUID)} values[i] = &sql.NullScanner{S: new(uuid.UUID)}
default: default:
return nil, fmt.Errorf("unexpected column %q for type Item", columns[i]) return nil, fmt.Errorf("unexpected column %q for type Item", columns[i])
@ -314,6 +343,13 @@ func (i *Item) assignValues(columns []string, values []any) error {
*i.group_items = *value.S.(*uuid.UUID) *i.group_items = *value.S.(*uuid.UUID)
} }
case item.ForeignKeys[1]: case item.ForeignKeys[1]:
if value, ok := values[j].(*sql.NullScanner); !ok {
return fmt.Errorf("unexpected type %T for field item_children", values[j])
} else if value.Valid {
i.item_children = new(uuid.UUID)
*i.item_children = *value.S.(*uuid.UUID)
}
case item.ForeignKeys[2]:
if value, ok := values[j].(*sql.NullScanner); !ok { if value, ok := values[j].(*sql.NullScanner); !ok {
return fmt.Errorf("unexpected type %T for field location_items", values[j]) return fmt.Errorf("unexpected type %T for field location_items", values[j])
} else if value.Valid { } else if value.Valid {
@ -325,6 +361,16 @@ func (i *Item) assignValues(columns []string, values []any) error {
return nil return nil
} }
// QueryParent queries the "parent" edge of the Item entity.
func (i *Item) QueryParent() *ItemQuery {
return (&ItemClient{config: i.config}).QueryParent(i)
}
// QueryChildren queries the "children" edge of the Item entity.
func (i *Item) QueryChildren() *ItemQuery {
return (&ItemClient{config: i.config}).QueryChildren(i)
}
// QueryGroup queries the "group" edge of the Item entity. // QueryGroup queries the "group" edge of the Item entity.
func (i *Item) QueryGroup() *GroupQuery { func (i *Item) QueryGroup() *GroupQuery {
return (&ItemClient{config: i.config}).QueryGroup(i) return (&ItemClient{config: i.config}).QueryGroup(i)

View file

@ -55,6 +55,10 @@ const (
FieldSoldPrice = "sold_price" FieldSoldPrice = "sold_price"
// FieldSoldNotes holds the string denoting the sold_notes field in the database. // FieldSoldNotes holds the string denoting the sold_notes field in the database.
FieldSoldNotes = "sold_notes" FieldSoldNotes = "sold_notes"
// EdgeParent holds the string denoting the parent edge name in mutations.
EdgeParent = "parent"
// EdgeChildren holds the string denoting the children edge name in mutations.
EdgeChildren = "children"
// EdgeGroup holds the string denoting the group edge name in mutations. // EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group" EdgeGroup = "group"
// EdgeLabel holds the string denoting the label edge name in mutations. // EdgeLabel holds the string denoting the label edge name in mutations.
@ -67,6 +71,14 @@ const (
EdgeAttachments = "attachments" EdgeAttachments = "attachments"
// Table holds the table name of the item in the database. // Table holds the table name of the item in the database.
Table = "items" Table = "items"
// ParentTable is the table that holds the parent relation/edge.
ParentTable = "items"
// ParentColumn is the table column denoting the parent relation/edge.
ParentColumn = "item_children"
// ChildrenTable is the table that holds the children relation/edge.
ChildrenTable = "items"
// ChildrenColumn is the table column denoting the children relation/edge.
ChildrenColumn = "item_children"
// GroupTable is the table that holds the group relation/edge. // GroupTable is the table that holds the group relation/edge.
GroupTable = "items" GroupTable = "items"
// GroupInverseTable is the table name for the Group entity. // GroupInverseTable is the table name for the Group entity.
@ -132,6 +144,7 @@ var Columns = []string{
// table and are not defined as standalone fields in the schema. // table and are not defined as standalone fields in the schema.
var ForeignKeys = []string{ var ForeignKeys = []string{
"group_items", "group_items",
"item_children",
"location_items", "location_items",
} }

View file

@ -2040,6 +2040,62 @@ func SoldNotesContainsFold(v string) predicate.Item {
}) })
} }
// HasParent applies the HasEdge predicate on the "parent" edge.
func HasParent() predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(ParentTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasParentWith applies the HasEdge predicate on the "parent" edge with a given conditions (other predicates).
func HasParentWith(preds ...predicate.Item) predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasChildren applies the HasEdge predicate on the "children" edge.
func HasChildren() predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(ChildrenTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasChildrenWith applies the HasEdge predicate on the "children" edge with a given conditions (other predicates).
func HasChildrenWith(preds ...predicate.Item) predicate.Item {
return predicate.Item(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasGroup applies the HasEdge predicate on the "group" edge. // HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Item { func HasGroup() predicate.Item {
return predicate.Item(func(s *sql.Selector) { return predicate.Item(func(s *sql.Selector) {

View file

@ -326,6 +326,40 @@ func (ic *ItemCreate) SetNillableID(u *uuid.UUID) *ItemCreate {
return ic return ic
} }
// SetParentID sets the "parent" edge to the Item entity by ID.
func (ic *ItemCreate) SetParentID(id uuid.UUID) *ItemCreate {
ic.mutation.SetParentID(id)
return ic
}
// SetNillableParentID sets the "parent" edge to the Item entity by ID if the given value is not nil.
func (ic *ItemCreate) SetNillableParentID(id *uuid.UUID) *ItemCreate {
if id != nil {
ic = ic.SetParentID(*id)
}
return ic
}
// SetParent sets the "parent" edge to the Item entity.
func (ic *ItemCreate) SetParent(i *Item) *ItemCreate {
return ic.SetParentID(i.ID)
}
// AddChildIDs adds the "children" edge to the Item entity by IDs.
func (ic *ItemCreate) AddChildIDs(ids ...uuid.UUID) *ItemCreate {
ic.mutation.AddChildIDs(ids...)
return ic
}
// AddChildren adds the "children" edges to the Item entity.
func (ic *ItemCreate) AddChildren(i ...*Item) *ItemCreate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return ic.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID. // SetGroupID sets the "group" edge to the Group entity by ID.
func (ic *ItemCreate) SetGroupID(id uuid.UUID) *ItemCreate { func (ic *ItemCreate) SetGroupID(id uuid.UUID) *ItemCreate {
ic.mutation.SetGroupID(id) ic.mutation.SetGroupID(id)
@ -790,6 +824,45 @@ func (ic *ItemCreate) createSpec() (*Item, *sqlgraph.CreateSpec) {
}) })
_node.SoldNotes = value _node.SoldNotes = value
} }
if nodes := ic.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.ParentTable,
Columns: []string{item.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.item_children = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := ic.mutation.ChildrenIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: item.ChildrenTable,
Columns: []string{item.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := ic.mutation.GroupIDs(); len(nodes) > 0 { if nodes := ic.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2O,

View file

@ -30,6 +30,8 @@ type ItemQuery struct {
order []OrderFunc order []OrderFunc
fields []string fields []string
predicates []predicate.Item predicates []predicate.Item
withParent *ItemQuery
withChildren *ItemQuery
withGroup *GroupQuery withGroup *GroupQuery
withLabel *LabelQuery withLabel *LabelQuery
withLocation *LocationQuery withLocation *LocationQuery
@ -72,6 +74,50 @@ func (iq *ItemQuery) Order(o ...OrderFunc) *ItemQuery {
return iq return iq
} }
// QueryParent chains the current query on the "parent" edge.
func (iq *ItemQuery) QueryParent() *ItemQuery {
query := &ItemQuery{config: iq.config}
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := iq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := iq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(item.Table, item.FieldID, selector),
sqlgraph.To(item.Table, item.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, item.ParentTable, item.ParentColumn),
)
fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryChildren chains the current query on the "children" edge.
func (iq *ItemQuery) QueryChildren() *ItemQuery {
query := &ItemQuery{config: iq.config}
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := iq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := iq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(item.Table, item.FieldID, selector),
sqlgraph.To(item.Table, item.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, item.ChildrenTable, item.ChildrenColumn),
)
fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryGroup chains the current query on the "group" edge. // QueryGroup chains the current query on the "group" edge.
func (iq *ItemQuery) QueryGroup() *GroupQuery { func (iq *ItemQuery) QueryGroup() *GroupQuery {
query := &GroupQuery{config: iq.config} query := &GroupQuery{config: iq.config}
@ -363,6 +409,8 @@ func (iq *ItemQuery) Clone() *ItemQuery {
offset: iq.offset, offset: iq.offset,
order: append([]OrderFunc{}, iq.order...), order: append([]OrderFunc{}, iq.order...),
predicates: append([]predicate.Item{}, iq.predicates...), predicates: append([]predicate.Item{}, iq.predicates...),
withParent: iq.withParent.Clone(),
withChildren: iq.withChildren.Clone(),
withGroup: iq.withGroup.Clone(), withGroup: iq.withGroup.Clone(),
withLabel: iq.withLabel.Clone(), withLabel: iq.withLabel.Clone(),
withLocation: iq.withLocation.Clone(), withLocation: iq.withLocation.Clone(),
@ -375,6 +423,28 @@ func (iq *ItemQuery) Clone() *ItemQuery {
} }
} }
// WithParent tells the query-builder to eager-load the nodes that are connected to
// the "parent" edge. The optional arguments are used to configure the query builder of the edge.
func (iq *ItemQuery) WithParent(opts ...func(*ItemQuery)) *ItemQuery {
query := &ItemQuery{config: iq.config}
for _, opt := range opts {
opt(query)
}
iq.withParent = query
return iq
}
// WithChildren tells the query-builder to eager-load the nodes that are connected to
// the "children" edge. The optional arguments are used to configure the query builder of the edge.
func (iq *ItemQuery) WithChildren(opts ...func(*ItemQuery)) *ItemQuery {
query := &ItemQuery{config: iq.config}
for _, opt := range opts {
opt(query)
}
iq.withChildren = query
return iq
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to // WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge. // the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (iq *ItemQuery) WithGroup(opts ...func(*GroupQuery)) *ItemQuery { func (iq *ItemQuery) WithGroup(opts ...func(*GroupQuery)) *ItemQuery {
@ -499,7 +569,9 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
nodes = []*Item{} nodes = []*Item{}
withFKs = iq.withFKs withFKs = iq.withFKs
_spec = iq.querySpec() _spec = iq.querySpec()
loadedTypes = [5]bool{ loadedTypes = [7]bool{
iq.withParent != nil,
iq.withChildren != nil,
iq.withGroup != nil, iq.withGroup != nil,
iq.withLabel != nil, iq.withLabel != nil,
iq.withLocation != nil, iq.withLocation != nil,
@ -507,7 +579,7 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
iq.withAttachments != nil, iq.withAttachments != nil,
} }
) )
if iq.withGroup != nil || iq.withLocation != nil { if iq.withParent != nil || iq.withGroup != nil || iq.withLocation != nil {
withFKs = true withFKs = true
} }
if withFKs { if withFKs {
@ -531,6 +603,19 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
if len(nodes) == 0 { if len(nodes) == 0 {
return nodes, nil return nodes, nil
} }
if query := iq.withParent; query != nil {
if err := iq.loadParent(ctx, query, nodes, nil,
func(n *Item, e *Item) { n.Edges.Parent = e }); err != nil {
return nil, err
}
}
if query := iq.withChildren; query != nil {
if err := iq.loadChildren(ctx, query, nodes,
func(n *Item) { n.Edges.Children = []*Item{} },
func(n *Item, e *Item) { n.Edges.Children = append(n.Edges.Children, e) }); err != nil {
return nil, err
}
}
if query := iq.withGroup; query != nil { if query := iq.withGroup; query != nil {
if err := iq.loadGroup(ctx, query, nodes, nil, if err := iq.loadGroup(ctx, query, nodes, nil,
func(n *Item, e *Group) { n.Edges.Group = e }); err != nil { func(n *Item, e *Group) { n.Edges.Group = e }); err != nil {
@ -567,6 +652,66 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e
return nodes, nil return nodes, nil
} }
func (iq *ItemQuery) loadParent(ctx context.Context, query *ItemQuery, nodes []*Item, init func(*Item), assign func(*Item, *Item)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Item)
for i := range nodes {
if nodes[i].item_children == nil {
continue
}
fk := *nodes[i].item_children
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
query.Where(item.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "item_children" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (iq *ItemQuery) loadChildren(ctx context.Context, query *ItemQuery, nodes []*Item, init func(*Item), assign func(*Item, *Item)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Item)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
query.withFKs = true
query.Where(predicate.Item(func(s *sql.Selector) {
s.Where(sql.InValues(item.ChildrenColumn, fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.item_children
if fk == nil {
return fmt.Errorf(`foreign-key "item_children" is nil for node %v`, n.ID)
}
node, ok := nodeids[*fk]
if !ok {
return fmt.Errorf(`unexpected foreign-key "item_children" returned %v for node %v`, *fk, n.ID)
}
assign(node, n)
}
return nil
}
func (iq *ItemQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Item, init func(*Item), assign func(*Item, *Group)) error { func (iq *ItemQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Item, init func(*Item), assign func(*Item, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes)) ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Item) nodeids := make(map[uuid.UUID][]*Item)

View file

@ -377,6 +377,40 @@ func (iu *ItemUpdate) ClearSoldNotes() *ItemUpdate {
return iu return iu
} }
// SetParentID sets the "parent" edge to the Item entity by ID.
func (iu *ItemUpdate) SetParentID(id uuid.UUID) *ItemUpdate {
iu.mutation.SetParentID(id)
return iu
}
// SetNillableParentID sets the "parent" edge to the Item entity by ID if the given value is not nil.
func (iu *ItemUpdate) SetNillableParentID(id *uuid.UUID) *ItemUpdate {
if id != nil {
iu = iu.SetParentID(*id)
}
return iu
}
// SetParent sets the "parent" edge to the Item entity.
func (iu *ItemUpdate) SetParent(i *Item) *ItemUpdate {
return iu.SetParentID(i.ID)
}
// AddChildIDs adds the "children" edge to the Item entity by IDs.
func (iu *ItemUpdate) AddChildIDs(ids ...uuid.UUID) *ItemUpdate {
iu.mutation.AddChildIDs(ids...)
return iu
}
// AddChildren adds the "children" edges to the Item entity.
func (iu *ItemUpdate) AddChildren(i ...*Item) *ItemUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return iu.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID. // SetGroupID sets the "group" edge to the Group entity by ID.
func (iu *ItemUpdate) SetGroupID(id uuid.UUID) *ItemUpdate { func (iu *ItemUpdate) SetGroupID(id uuid.UUID) *ItemUpdate {
iu.mutation.SetGroupID(id) iu.mutation.SetGroupID(id)
@ -457,6 +491,33 @@ func (iu *ItemUpdate) Mutation() *ItemMutation {
return iu.mutation return iu.mutation
} }
// ClearParent clears the "parent" edge to the Item entity.
func (iu *ItemUpdate) ClearParent() *ItemUpdate {
iu.mutation.ClearParent()
return iu
}
// ClearChildren clears all "children" edges to the Item entity.
func (iu *ItemUpdate) ClearChildren() *ItemUpdate {
iu.mutation.ClearChildren()
return iu
}
// RemoveChildIDs removes the "children" edge to Item entities by IDs.
func (iu *ItemUpdate) RemoveChildIDs(ids ...uuid.UUID) *ItemUpdate {
iu.mutation.RemoveChildIDs(ids...)
return iu
}
// RemoveChildren removes "children" edges to Item entities.
func (iu *ItemUpdate) RemoveChildren(i ...*Item) *ItemUpdate {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return iu.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity. // ClearGroup clears the "group" edge to the Group entity.
func (iu *ItemUpdate) ClearGroup() *ItemUpdate { func (iu *ItemUpdate) ClearGroup() *ItemUpdate {
iu.mutation.ClearGroup() iu.mutation.ClearGroup()
@ -899,6 +960,95 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) {
Column: item.FieldSoldNotes, Column: item.FieldSoldNotes,
}) })
} }
if iu.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.ParentTable,
Columns: []string{item.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iu.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.ParentTable,
Columns: []string{item.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iu.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: item.ChildrenTable,
Columns: []string{item.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iu.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !iu.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: item.ChildrenTable,
Columns: []string{item.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iu.mutation.ChildrenIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: item.ChildrenTable,
Columns: []string{item.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iu.mutation.GroupCleared() { if iu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2O,
@ -1493,6 +1643,40 @@ func (iuo *ItemUpdateOne) ClearSoldNotes() *ItemUpdateOne {
return iuo return iuo
} }
// SetParentID sets the "parent" edge to the Item entity by ID.
func (iuo *ItemUpdateOne) SetParentID(id uuid.UUID) *ItemUpdateOne {
iuo.mutation.SetParentID(id)
return iuo
}
// SetNillableParentID sets the "parent" edge to the Item entity by ID if the given value is not nil.
func (iuo *ItemUpdateOne) SetNillableParentID(id *uuid.UUID) *ItemUpdateOne {
if id != nil {
iuo = iuo.SetParentID(*id)
}
return iuo
}
// SetParent sets the "parent" edge to the Item entity.
func (iuo *ItemUpdateOne) SetParent(i *Item) *ItemUpdateOne {
return iuo.SetParentID(i.ID)
}
// AddChildIDs adds the "children" edge to the Item entity by IDs.
func (iuo *ItemUpdateOne) AddChildIDs(ids ...uuid.UUID) *ItemUpdateOne {
iuo.mutation.AddChildIDs(ids...)
return iuo
}
// AddChildren adds the "children" edges to the Item entity.
func (iuo *ItemUpdateOne) AddChildren(i ...*Item) *ItemUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return iuo.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID. // SetGroupID sets the "group" edge to the Group entity by ID.
func (iuo *ItemUpdateOne) SetGroupID(id uuid.UUID) *ItemUpdateOne { func (iuo *ItemUpdateOne) SetGroupID(id uuid.UUID) *ItemUpdateOne {
iuo.mutation.SetGroupID(id) iuo.mutation.SetGroupID(id)
@ -1573,6 +1757,33 @@ func (iuo *ItemUpdateOne) Mutation() *ItemMutation {
return iuo.mutation return iuo.mutation
} }
// ClearParent clears the "parent" edge to the Item entity.
func (iuo *ItemUpdateOne) ClearParent() *ItemUpdateOne {
iuo.mutation.ClearParent()
return iuo
}
// ClearChildren clears all "children" edges to the Item entity.
func (iuo *ItemUpdateOne) ClearChildren() *ItemUpdateOne {
iuo.mutation.ClearChildren()
return iuo
}
// RemoveChildIDs removes the "children" edge to Item entities by IDs.
func (iuo *ItemUpdateOne) RemoveChildIDs(ids ...uuid.UUID) *ItemUpdateOne {
iuo.mutation.RemoveChildIDs(ids...)
return iuo
}
// RemoveChildren removes "children" edges to Item entities.
func (iuo *ItemUpdateOne) RemoveChildren(i ...*Item) *ItemUpdateOne {
ids := make([]uuid.UUID, len(i))
for j := range i {
ids[j] = i[j].ID
}
return iuo.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity. // ClearGroup clears the "group" edge to the Group entity.
func (iuo *ItemUpdateOne) ClearGroup() *ItemUpdateOne { func (iuo *ItemUpdateOne) ClearGroup() *ItemUpdateOne {
iuo.mutation.ClearGroup() iuo.mutation.ClearGroup()
@ -2045,6 +2256,95 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error)
Column: item.FieldSoldNotes, Column: item.FieldSoldNotes,
}) })
} }
if iuo.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.ParentTable,
Columns: []string{item.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iuo.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: item.ParentTable,
Columns: []string{item.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iuo.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: item.ChildrenTable,
Columns: []string{item.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iuo.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !iuo.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: item.ChildrenTable,
Columns: []string{item.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := iuo.mutation.ChildrenIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: item.ChildrenTable,
Columns: []string{item.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: item.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if iuo.mutation.GroupCleared() { if iuo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2O,

View file

@ -28,25 +28,52 @@ type Location struct {
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
// Edges holds the relations/edges for other nodes in the graph. // Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the LocationQuery when eager-loading is set. // The values are being populated by the LocationQuery when eager-loading is set.
Edges LocationEdges `json:"edges"` Edges LocationEdges `json:"edges"`
group_locations *uuid.UUID group_locations *uuid.UUID
location_children *uuid.UUID
} }
// LocationEdges holds the relations/edges for other nodes in the graph. // LocationEdges holds the relations/edges for other nodes in the graph.
type LocationEdges struct { type LocationEdges struct {
// Parent holds the value of the parent edge.
Parent *Location `json:"parent,omitempty"`
// Children holds the value of the children edge.
Children []*Location `json:"children,omitempty"`
// Group holds the value of the group edge. // Group holds the value of the group edge.
Group *Group `json:"group,omitempty"` Group *Group `json:"group,omitempty"`
// Items holds the value of the items edge. // Items holds the value of the items edge.
Items []*Item `json:"items,omitempty"` Items []*Item `json:"items,omitempty"`
// loadedTypes holds the information for reporting if a // loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not. // type was loaded (or requested) in eager-loading or not.
loadedTypes [2]bool loadedTypes [4]bool
}
// ParentOrErr returns the Parent value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e LocationEdges) ParentOrErr() (*Location, error) {
if e.loadedTypes[0] {
if e.Parent == nil {
// Edge was loaded but was not found.
return nil, &NotFoundError{label: location.Label}
}
return e.Parent, nil
}
return nil, &NotLoadedError{edge: "parent"}
}
// ChildrenOrErr returns the Children value or an error if the edge
// was not loaded in eager-loading.
func (e LocationEdges) ChildrenOrErr() ([]*Location, error) {
if e.loadedTypes[1] {
return e.Children, nil
}
return nil, &NotLoadedError{edge: "children"}
} }
// GroupOrErr returns the Group value or an error if the edge // GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found. // was not loaded in eager-loading, or loaded but was not found.
func (e LocationEdges) GroupOrErr() (*Group, error) { func (e LocationEdges) GroupOrErr() (*Group, error) {
if e.loadedTypes[0] { if e.loadedTypes[2] {
if e.Group == nil { if e.Group == nil {
// Edge was loaded but was not found. // Edge was loaded but was not found.
return nil, &NotFoundError{label: group.Label} return nil, &NotFoundError{label: group.Label}
@ -59,7 +86,7 @@ func (e LocationEdges) GroupOrErr() (*Group, error) {
// ItemsOrErr returns the Items value or an error if the edge // ItemsOrErr returns the Items value or an error if the edge
// was not loaded in eager-loading. // was not loaded in eager-loading.
func (e LocationEdges) ItemsOrErr() ([]*Item, error) { func (e LocationEdges) ItemsOrErr() ([]*Item, error) {
if e.loadedTypes[1] { if e.loadedTypes[3] {
return e.Items, nil return e.Items, nil
} }
return nil, &NotLoadedError{edge: "items"} return nil, &NotLoadedError{edge: "items"}
@ -78,6 +105,8 @@ func (*Location) scanValues(columns []string) ([]any, error) {
values[i] = new(uuid.UUID) values[i] = new(uuid.UUID)
case location.ForeignKeys[0]: // group_locations case location.ForeignKeys[0]: // group_locations
values[i] = &sql.NullScanner{S: new(uuid.UUID)} values[i] = &sql.NullScanner{S: new(uuid.UUID)}
case location.ForeignKeys[1]: // location_children
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
default: default:
return nil, fmt.Errorf("unexpected column %q for type Location", columns[i]) return nil, fmt.Errorf("unexpected column %q for type Location", columns[i])
} }
@ -130,11 +159,28 @@ func (l *Location) assignValues(columns []string, values []any) error {
l.group_locations = new(uuid.UUID) l.group_locations = new(uuid.UUID)
*l.group_locations = *value.S.(*uuid.UUID) *l.group_locations = *value.S.(*uuid.UUID)
} }
case location.ForeignKeys[1]:
if value, ok := values[i].(*sql.NullScanner); !ok {
return fmt.Errorf("unexpected type %T for field location_children", values[i])
} else if value.Valid {
l.location_children = new(uuid.UUID)
*l.location_children = *value.S.(*uuid.UUID)
}
} }
} }
return nil return nil
} }
// QueryParent queries the "parent" edge of the Location entity.
func (l *Location) QueryParent() *LocationQuery {
return (&LocationClient{config: l.config}).QueryParent(l)
}
// QueryChildren queries the "children" edge of the Location entity.
func (l *Location) QueryChildren() *LocationQuery {
return (&LocationClient{config: l.config}).QueryChildren(l)
}
// QueryGroup queries the "group" edge of the Location entity. // QueryGroup queries the "group" edge of the Location entity.
func (l *Location) QueryGroup() *GroupQuery { func (l *Location) QueryGroup() *GroupQuery {
return (&LocationClient{config: l.config}).QueryGroup(l) return (&LocationClient{config: l.config}).QueryGroup(l)

View file

@ -21,12 +21,24 @@ const (
FieldName = "name" FieldName = "name"
// FieldDescription holds the string denoting the description field in the database. // FieldDescription holds the string denoting the description field in the database.
FieldDescription = "description" FieldDescription = "description"
// EdgeParent holds the string denoting the parent edge name in mutations.
EdgeParent = "parent"
// EdgeChildren holds the string denoting the children edge name in mutations.
EdgeChildren = "children"
// EdgeGroup holds the string denoting the group edge name in mutations. // EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group" EdgeGroup = "group"
// EdgeItems holds the string denoting the items edge name in mutations. // EdgeItems holds the string denoting the items edge name in mutations.
EdgeItems = "items" EdgeItems = "items"
// Table holds the table name of the location in the database. // Table holds the table name of the location in the database.
Table = "locations" Table = "locations"
// ParentTable is the table that holds the parent relation/edge.
ParentTable = "locations"
// ParentColumn is the table column denoting the parent relation/edge.
ParentColumn = "location_children"
// ChildrenTable is the table that holds the children relation/edge.
ChildrenTable = "locations"
// ChildrenColumn is the table column denoting the children relation/edge.
ChildrenColumn = "location_children"
// GroupTable is the table that holds the group relation/edge. // GroupTable is the table that holds the group relation/edge.
GroupTable = "locations" GroupTable = "locations"
// GroupInverseTable is the table name for the Group entity. // GroupInverseTable is the table name for the Group entity.
@ -56,6 +68,7 @@ var Columns = []string{
// table and are not defined as standalone fields in the schema. // table and are not defined as standalone fields in the schema.
var ForeignKeys = []string{ var ForeignKeys = []string{
"group_locations", "group_locations",
"location_children",
} }
// ValidColumn reports if the column name is valid (part of the table columns). // ValidColumn reports if the column name is valid (part of the table columns).

View file

@ -450,6 +450,62 @@ func DescriptionContainsFold(v string) predicate.Location {
}) })
} }
// HasParent applies the HasEdge predicate on the "parent" edge.
func HasParent() predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(ParentTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasParentWith applies the HasEdge predicate on the "parent" edge with a given conditions (other predicates).
func HasParentWith(preds ...predicate.Location) predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasChildren applies the HasEdge predicate on the "children" edge.
func HasChildren() predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(ChildrenTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasChildrenWith applies the HasEdge predicate on the "children" edge with a given conditions (other predicates).
func HasChildrenWith(preds ...predicate.Location) predicate.Location {
return predicate.Location(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn),
)
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasGroup applies the HasEdge predicate on the "group" edge. // HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Location { func HasGroup() predicate.Location {
return predicate.Location(func(s *sql.Selector) { return predicate.Location(func(s *sql.Selector) {

View file

@ -85,6 +85,40 @@ func (lc *LocationCreate) SetNillableID(u *uuid.UUID) *LocationCreate {
return lc return lc
} }
// SetParentID sets the "parent" edge to the Location entity by ID.
func (lc *LocationCreate) SetParentID(id uuid.UUID) *LocationCreate {
lc.mutation.SetParentID(id)
return lc
}
// SetNillableParentID sets the "parent" edge to the Location entity by ID if the given value is not nil.
func (lc *LocationCreate) SetNillableParentID(id *uuid.UUID) *LocationCreate {
if id != nil {
lc = lc.SetParentID(*id)
}
return lc
}
// SetParent sets the "parent" edge to the Location entity.
func (lc *LocationCreate) SetParent(l *Location) *LocationCreate {
return lc.SetParentID(l.ID)
}
// AddChildIDs adds the "children" edge to the Location entity by IDs.
func (lc *LocationCreate) AddChildIDs(ids ...uuid.UUID) *LocationCreate {
lc.mutation.AddChildIDs(ids...)
return lc
}
// AddChildren adds the "children" edges to the Location entity.
func (lc *LocationCreate) AddChildren(l ...*Location) *LocationCreate {
ids := make([]uuid.UUID, len(l))
for i := range l {
ids[i] = l[i].ID
}
return lc.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID. // SetGroupID sets the "group" edge to the Group entity by ID.
func (lc *LocationCreate) SetGroupID(id uuid.UUID) *LocationCreate { func (lc *LocationCreate) SetGroupID(id uuid.UUID) *LocationCreate {
lc.mutation.SetGroupID(id) lc.mutation.SetGroupID(id)
@ -294,6 +328,45 @@ func (lc *LocationCreate) createSpec() (*Location, *sqlgraph.CreateSpec) {
}) })
_node.Description = value _node.Description = value
} }
if nodes := lc.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.ParentTable,
Columns: []string{location.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.location_children = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := lc.mutation.ChildrenIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: location.ChildrenTable,
Columns: []string{location.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := lc.mutation.GroupIDs(); len(nodes) > 0 { if nodes := lc.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2O,

View file

@ -21,15 +21,17 @@ import (
// LocationQuery is the builder for querying Location entities. // LocationQuery is the builder for querying Location entities.
type LocationQuery struct { type LocationQuery struct {
config config
limit *int limit *int
offset *int offset *int
unique *bool unique *bool
order []OrderFunc order []OrderFunc
fields []string fields []string
predicates []predicate.Location predicates []predicate.Location
withGroup *GroupQuery withParent *LocationQuery
withItems *ItemQuery withChildren *LocationQuery
withFKs bool withGroup *GroupQuery
withItems *ItemQuery
withFKs bool
// intermediate query (i.e. traversal path). // intermediate query (i.e. traversal path).
sql *sql.Selector sql *sql.Selector
path func(context.Context) (*sql.Selector, error) path func(context.Context) (*sql.Selector, error)
@ -66,6 +68,50 @@ func (lq *LocationQuery) Order(o ...OrderFunc) *LocationQuery {
return lq return lq
} }
// QueryParent chains the current query on the "parent" edge.
func (lq *LocationQuery) QueryParent() *LocationQuery {
query := &LocationQuery{config: lq.config}
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := lq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := lq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, selector),
sqlgraph.To(location.Table, location.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, location.ParentTable, location.ParentColumn),
)
fromU = sqlgraph.SetNeighbors(lq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryChildren chains the current query on the "children" edge.
func (lq *LocationQuery) QueryChildren() *LocationQuery {
query := &LocationQuery{config: lq.config}
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := lq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := lq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(location.Table, location.FieldID, selector),
sqlgraph.To(location.Table, location.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, location.ChildrenTable, location.ChildrenColumn),
)
fromU = sqlgraph.SetNeighbors(lq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryGroup chains the current query on the "group" edge. // QueryGroup chains the current query on the "group" edge.
func (lq *LocationQuery) QueryGroup() *GroupQuery { func (lq *LocationQuery) QueryGroup() *GroupQuery {
query := &GroupQuery{config: lq.config} query := &GroupQuery{config: lq.config}
@ -286,13 +332,15 @@ func (lq *LocationQuery) Clone() *LocationQuery {
return nil return nil
} }
return &LocationQuery{ return &LocationQuery{
config: lq.config, config: lq.config,
limit: lq.limit, limit: lq.limit,
offset: lq.offset, offset: lq.offset,
order: append([]OrderFunc{}, lq.order...), order: append([]OrderFunc{}, lq.order...),
predicates: append([]predicate.Location{}, lq.predicates...), predicates: append([]predicate.Location{}, lq.predicates...),
withGroup: lq.withGroup.Clone(), withParent: lq.withParent.Clone(),
withItems: lq.withItems.Clone(), withChildren: lq.withChildren.Clone(),
withGroup: lq.withGroup.Clone(),
withItems: lq.withItems.Clone(),
// clone intermediate query. // clone intermediate query.
sql: lq.sql.Clone(), sql: lq.sql.Clone(),
path: lq.path, path: lq.path,
@ -300,6 +348,28 @@ func (lq *LocationQuery) Clone() *LocationQuery {
} }
} }
// WithParent tells the query-builder to eager-load the nodes that are connected to
// the "parent" edge. The optional arguments are used to configure the query builder of the edge.
func (lq *LocationQuery) WithParent(opts ...func(*LocationQuery)) *LocationQuery {
query := &LocationQuery{config: lq.config}
for _, opt := range opts {
opt(query)
}
lq.withParent = query
return lq
}
// WithChildren tells the query-builder to eager-load the nodes that are connected to
// the "children" edge. The optional arguments are used to configure the query builder of the edge.
func (lq *LocationQuery) WithChildren(opts ...func(*LocationQuery)) *LocationQuery {
query := &LocationQuery{config: lq.config}
for _, opt := range opts {
opt(query)
}
lq.withChildren = query
return lq
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to // WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge. // the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (lq *LocationQuery) WithGroup(opts ...func(*GroupQuery)) *LocationQuery { func (lq *LocationQuery) WithGroup(opts ...func(*GroupQuery)) *LocationQuery {
@ -391,12 +461,14 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc
nodes = []*Location{} nodes = []*Location{}
withFKs = lq.withFKs withFKs = lq.withFKs
_spec = lq.querySpec() _spec = lq.querySpec()
loadedTypes = [2]bool{ loadedTypes = [4]bool{
lq.withParent != nil,
lq.withChildren != nil,
lq.withGroup != nil, lq.withGroup != nil,
lq.withItems != nil, lq.withItems != nil,
} }
) )
if lq.withGroup != nil { if lq.withParent != nil || lq.withGroup != nil {
withFKs = true withFKs = true
} }
if withFKs { if withFKs {
@ -420,6 +492,19 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc
if len(nodes) == 0 { if len(nodes) == 0 {
return nodes, nil return nodes, nil
} }
if query := lq.withParent; query != nil {
if err := lq.loadParent(ctx, query, nodes, nil,
func(n *Location, e *Location) { n.Edges.Parent = e }); err != nil {
return nil, err
}
}
if query := lq.withChildren; query != nil {
if err := lq.loadChildren(ctx, query, nodes,
func(n *Location) { n.Edges.Children = []*Location{} },
func(n *Location, e *Location) { n.Edges.Children = append(n.Edges.Children, e) }); err != nil {
return nil, err
}
}
if query := lq.withGroup; query != nil { if query := lq.withGroup; query != nil {
if err := lq.loadGroup(ctx, query, nodes, nil, if err := lq.loadGroup(ctx, query, nodes, nil,
func(n *Location, e *Group) { n.Edges.Group = e }); err != nil { func(n *Location, e *Group) { n.Edges.Group = e }); err != nil {
@ -436,6 +521,66 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc
return nodes, nil return nodes, nil
} }
func (lq *LocationQuery) loadParent(ctx context.Context, query *LocationQuery, nodes []*Location, init func(*Location), assign func(*Location, *Location)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Location)
for i := range nodes {
if nodes[i].location_children == nil {
continue
}
fk := *nodes[i].location_children
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
query.Where(location.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "location_children" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (lq *LocationQuery) loadChildren(ctx context.Context, query *LocationQuery, nodes []*Location, init func(*Location), assign func(*Location, *Location)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Location)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
query.withFKs = true
query.Where(predicate.Location(func(s *sql.Selector) {
s.Where(sql.InValues(location.ChildrenColumn, fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.location_children
if fk == nil {
return fmt.Errorf(`foreign-key "location_children" is nil for node %v`, n.ID)
}
node, ok := nodeids[*fk]
if !ok {
return fmt.Errorf(`unexpected foreign-key "location_children" returned %v for node %v`, *fk, n.ID)
}
assign(node, n)
}
return nil
}
func (lq *LocationQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Location, init func(*Location), assign func(*Location, *Group)) error { func (lq *LocationQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Location, init func(*Location), assign func(*Location, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes)) ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Location) nodeids := make(map[uuid.UUID][]*Location)

View file

@ -63,6 +63,40 @@ func (lu *LocationUpdate) ClearDescription() *LocationUpdate {
return lu return lu
} }
// SetParentID sets the "parent" edge to the Location entity by ID.
func (lu *LocationUpdate) SetParentID(id uuid.UUID) *LocationUpdate {
lu.mutation.SetParentID(id)
return lu
}
// SetNillableParentID sets the "parent" edge to the Location entity by ID if the given value is not nil.
func (lu *LocationUpdate) SetNillableParentID(id *uuid.UUID) *LocationUpdate {
if id != nil {
lu = lu.SetParentID(*id)
}
return lu
}
// SetParent sets the "parent" edge to the Location entity.
func (lu *LocationUpdate) SetParent(l *Location) *LocationUpdate {
return lu.SetParentID(l.ID)
}
// AddChildIDs adds the "children" edge to the Location entity by IDs.
func (lu *LocationUpdate) AddChildIDs(ids ...uuid.UUID) *LocationUpdate {
lu.mutation.AddChildIDs(ids...)
return lu
}
// AddChildren adds the "children" edges to the Location entity.
func (lu *LocationUpdate) AddChildren(l ...*Location) *LocationUpdate {
ids := make([]uuid.UUID, len(l))
for i := range l {
ids[i] = l[i].ID
}
return lu.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID. // SetGroupID sets the "group" edge to the Group entity by ID.
func (lu *LocationUpdate) SetGroupID(id uuid.UUID) *LocationUpdate { func (lu *LocationUpdate) SetGroupID(id uuid.UUID) *LocationUpdate {
lu.mutation.SetGroupID(id) lu.mutation.SetGroupID(id)
@ -94,6 +128,33 @@ func (lu *LocationUpdate) Mutation() *LocationMutation {
return lu.mutation return lu.mutation
} }
// ClearParent clears the "parent" edge to the Location entity.
func (lu *LocationUpdate) ClearParent() *LocationUpdate {
lu.mutation.ClearParent()
return lu
}
// ClearChildren clears all "children" edges to the Location entity.
func (lu *LocationUpdate) ClearChildren() *LocationUpdate {
lu.mutation.ClearChildren()
return lu
}
// RemoveChildIDs removes the "children" edge to Location entities by IDs.
func (lu *LocationUpdate) RemoveChildIDs(ids ...uuid.UUID) *LocationUpdate {
lu.mutation.RemoveChildIDs(ids...)
return lu
}
// RemoveChildren removes "children" edges to Location entities.
func (lu *LocationUpdate) RemoveChildren(l ...*Location) *LocationUpdate {
ids := make([]uuid.UUID, len(l))
for i := range l {
ids[i] = l[i].ID
}
return lu.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity. // ClearGroup clears the "group" edge to the Group entity.
func (lu *LocationUpdate) ClearGroup() *LocationUpdate { func (lu *LocationUpdate) ClearGroup() *LocationUpdate {
lu.mutation.ClearGroup() lu.mutation.ClearGroup()
@ -253,6 +314,95 @@ func (lu *LocationUpdate) sqlSave(ctx context.Context) (n int, err error) {
Column: location.FieldDescription, Column: location.FieldDescription,
}) })
} }
if lu.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.ParentTable,
Columns: []string{location.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := lu.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.ParentTable,
Columns: []string{location.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if lu.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: location.ChildrenTable,
Columns: []string{location.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := lu.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !lu.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: location.ChildrenTable,
Columns: []string{location.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := lu.mutation.ChildrenIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: location.ChildrenTable,
Columns: []string{location.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if lu.mutation.GroupCleared() { if lu.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2O,
@ -393,6 +543,40 @@ func (luo *LocationUpdateOne) ClearDescription() *LocationUpdateOne {
return luo return luo
} }
// SetParentID sets the "parent" edge to the Location entity by ID.
func (luo *LocationUpdateOne) SetParentID(id uuid.UUID) *LocationUpdateOne {
luo.mutation.SetParentID(id)
return luo
}
// SetNillableParentID sets the "parent" edge to the Location entity by ID if the given value is not nil.
func (luo *LocationUpdateOne) SetNillableParentID(id *uuid.UUID) *LocationUpdateOne {
if id != nil {
luo = luo.SetParentID(*id)
}
return luo
}
// SetParent sets the "parent" edge to the Location entity.
func (luo *LocationUpdateOne) SetParent(l *Location) *LocationUpdateOne {
return luo.SetParentID(l.ID)
}
// AddChildIDs adds the "children" edge to the Location entity by IDs.
func (luo *LocationUpdateOne) AddChildIDs(ids ...uuid.UUID) *LocationUpdateOne {
luo.mutation.AddChildIDs(ids...)
return luo
}
// AddChildren adds the "children" edges to the Location entity.
func (luo *LocationUpdateOne) AddChildren(l ...*Location) *LocationUpdateOne {
ids := make([]uuid.UUID, len(l))
for i := range l {
ids[i] = l[i].ID
}
return luo.AddChildIDs(ids...)
}
// SetGroupID sets the "group" edge to the Group entity by ID. // SetGroupID sets the "group" edge to the Group entity by ID.
func (luo *LocationUpdateOne) SetGroupID(id uuid.UUID) *LocationUpdateOne { func (luo *LocationUpdateOne) SetGroupID(id uuid.UUID) *LocationUpdateOne {
luo.mutation.SetGroupID(id) luo.mutation.SetGroupID(id)
@ -424,6 +608,33 @@ func (luo *LocationUpdateOne) Mutation() *LocationMutation {
return luo.mutation return luo.mutation
} }
// ClearParent clears the "parent" edge to the Location entity.
func (luo *LocationUpdateOne) ClearParent() *LocationUpdateOne {
luo.mutation.ClearParent()
return luo
}
// ClearChildren clears all "children" edges to the Location entity.
func (luo *LocationUpdateOne) ClearChildren() *LocationUpdateOne {
luo.mutation.ClearChildren()
return luo
}
// RemoveChildIDs removes the "children" edge to Location entities by IDs.
func (luo *LocationUpdateOne) RemoveChildIDs(ids ...uuid.UUID) *LocationUpdateOne {
luo.mutation.RemoveChildIDs(ids...)
return luo
}
// RemoveChildren removes "children" edges to Location entities.
func (luo *LocationUpdateOne) RemoveChildren(l ...*Location) *LocationUpdateOne {
ids := make([]uuid.UUID, len(l))
for i := range l {
ids[i] = l[i].ID
}
return luo.RemoveChildIDs(ids...)
}
// ClearGroup clears the "group" edge to the Group entity. // ClearGroup clears the "group" edge to the Group entity.
func (luo *LocationUpdateOne) ClearGroup() *LocationUpdateOne { func (luo *LocationUpdateOne) ClearGroup() *LocationUpdateOne {
luo.mutation.ClearGroup() luo.mutation.ClearGroup()
@ -613,6 +824,95 @@ func (luo *LocationUpdateOne) sqlSave(ctx context.Context) (_node *Location, err
Column: location.FieldDescription, Column: location.FieldDescription,
}) })
} }
if luo.mutation.ParentCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.ParentTable,
Columns: []string{location.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := luo.mutation.ParentIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: location.ParentTable,
Columns: []string{location.ParentColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if luo.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: location.ChildrenTable,
Columns: []string{location.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := luo.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !luo.mutation.ChildrenCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: location.ChildrenTable,
Columns: []string{location.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := luo.mutation.ChildrenIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: location.ChildrenTable,
Columns: []string{location.ChildrenColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: &sqlgraph.FieldSpec{
Type: field.TypeUUID,
Column: location.FieldID,
},
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if luo.mutation.GroupCleared() { if luo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{ edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O, Rel: sqlgraph.M2O,

View file

@ -184,6 +184,7 @@ var (
{Name: "sold_price", Type: field.TypeFloat64, Default: 0}, {Name: "sold_price", Type: field.TypeFloat64, Default: 0},
{Name: "sold_notes", Type: field.TypeString, Nullable: true, Size: 1000}, {Name: "sold_notes", Type: field.TypeString, Nullable: true, Size: 1000},
{Name: "group_items", Type: field.TypeUUID}, {Name: "group_items", Type: field.TypeUUID},
{Name: "item_children", Type: field.TypeUUID, Nullable: true},
{Name: "location_items", Type: field.TypeUUID, Nullable: true}, {Name: "location_items", Type: field.TypeUUID, Nullable: true},
} }
// ItemsTable holds the schema information for the "items" table. // ItemsTable holds the schema information for the "items" table.
@ -199,8 +200,14 @@ var (
OnDelete: schema.Cascade, OnDelete: schema.Cascade,
}, },
{ {
Symbol: "items_locations_items", Symbol: "items_items_children",
Columns: []*schema.Column{ItemsColumns[23]}, Columns: []*schema.Column{ItemsColumns[23]},
RefColumns: []*schema.Column{ItemsColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "items_locations_items",
Columns: []*schema.Column{ItemsColumns[24]},
RefColumns: []*schema.Column{LocationsColumns[0]}, RefColumns: []*schema.Column{LocationsColumns[0]},
OnDelete: schema.Cascade, OnDelete: schema.Cascade,
}, },
@ -288,6 +295,7 @@ var (
{Name: "name", Type: field.TypeString, Size: 255}, {Name: "name", Type: field.TypeString, Size: 255},
{Name: "description", Type: field.TypeString, Nullable: true, Size: 1000}, {Name: "description", Type: field.TypeString, Nullable: true, Size: 1000},
{Name: "group_locations", Type: field.TypeUUID}, {Name: "group_locations", Type: field.TypeUUID},
{Name: "location_children", Type: field.TypeUUID, Nullable: true},
} }
// LocationsTable holds the schema information for the "locations" table. // LocationsTable holds the schema information for the "locations" table.
LocationsTable = &schema.Table{ LocationsTable = &schema.Table{
@ -301,6 +309,12 @@ var (
RefColumns: []*schema.Column{GroupsColumns[0]}, RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.Cascade, OnDelete: schema.Cascade,
}, },
{
Symbol: "locations_locations_children",
Columns: []*schema.Column{LocationsColumns[6]},
RefColumns: []*schema.Column{LocationsColumns[0]},
OnDelete: schema.SetNull,
},
}, },
} }
// UsersColumns holds the columns for the "users" table. // UsersColumns holds the columns for the "users" table.
@ -381,10 +395,12 @@ func init() {
DocumentTokensTable.ForeignKeys[0].RefTable = DocumentsTable DocumentTokensTable.ForeignKeys[0].RefTable = DocumentsTable
GroupInvitationTokensTable.ForeignKeys[0].RefTable = GroupsTable GroupInvitationTokensTable.ForeignKeys[0].RefTable = GroupsTable
ItemsTable.ForeignKeys[0].RefTable = GroupsTable ItemsTable.ForeignKeys[0].RefTable = GroupsTable
ItemsTable.ForeignKeys[1].RefTable = LocationsTable ItemsTable.ForeignKeys[1].RefTable = ItemsTable
ItemsTable.ForeignKeys[2].RefTable = LocationsTable
ItemFieldsTable.ForeignKeys[0].RefTable = ItemsTable ItemFieldsTable.ForeignKeys[0].RefTable = ItemsTable
LabelsTable.ForeignKeys[0].RefTable = GroupsTable LabelsTable.ForeignKeys[0].RefTable = GroupsTable
LocationsTable.ForeignKeys[0].RefTable = GroupsTable LocationsTable.ForeignKeys[0].RefTable = GroupsTable
LocationsTable.ForeignKeys[1].RefTable = LocationsTable
UsersTable.ForeignKeys[0].RefTable = GroupsTable UsersTable.ForeignKeys[0].RefTable = GroupsTable
LabelItemsTable.ForeignKeys[0].RefTable = LabelsTable LabelItemsTable.ForeignKeys[0].RefTable = LabelsTable
LabelItemsTable.ForeignKeys[1].RefTable = ItemsTable LabelItemsTable.ForeignKeys[1].RefTable = ItemsTable

View file

@ -4149,6 +4149,11 @@ type ItemMutation struct {
addsold_price *float64 addsold_price *float64
sold_notes *string sold_notes *string
clearedFields map[string]struct{} clearedFields map[string]struct{}
parent *uuid.UUID
clearedparent bool
children map[uuid.UUID]struct{}
removedchildren map[uuid.UUID]struct{}
clearedchildren bool
group *uuid.UUID group *uuid.UUID
clearedgroup bool clearedgroup bool
label map[uuid.UUID]struct{} label map[uuid.UUID]struct{}
@ -5256,6 +5261,99 @@ func (m *ItemMutation) ResetSoldNotes() {
delete(m.clearedFields, item.FieldSoldNotes) delete(m.clearedFields, item.FieldSoldNotes)
} }
// SetParentID sets the "parent" edge to the Item entity by id.
func (m *ItemMutation) SetParentID(id uuid.UUID) {
m.parent = &id
}
// ClearParent clears the "parent" edge to the Item entity.
func (m *ItemMutation) ClearParent() {
m.clearedparent = true
}
// ParentCleared reports if the "parent" edge to the Item entity was cleared.
func (m *ItemMutation) ParentCleared() bool {
return m.clearedparent
}
// ParentID returns the "parent" edge ID in the mutation.
func (m *ItemMutation) ParentID() (id uuid.UUID, exists bool) {
if m.parent != nil {
return *m.parent, true
}
return
}
// ParentIDs returns the "parent" edge IDs in the mutation.
// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
// ParentID instead. It exists only for internal usage by the builders.
func (m *ItemMutation) ParentIDs() (ids []uuid.UUID) {
if id := m.parent; id != nil {
ids = append(ids, *id)
}
return
}
// ResetParent resets all changes to the "parent" edge.
func (m *ItemMutation) ResetParent() {
m.parent = nil
m.clearedparent = false
}
// AddChildIDs adds the "children" edge to the Item entity by ids.
func (m *ItemMutation) AddChildIDs(ids ...uuid.UUID) {
if m.children == nil {
m.children = make(map[uuid.UUID]struct{})
}
for i := range ids {
m.children[ids[i]] = struct{}{}
}
}
// ClearChildren clears the "children" edge to the Item entity.
func (m *ItemMutation) ClearChildren() {
m.clearedchildren = true
}
// ChildrenCleared reports if the "children" edge to the Item entity was cleared.
func (m *ItemMutation) ChildrenCleared() bool {
return m.clearedchildren
}
// RemoveChildIDs removes the "children" edge to the Item entity by IDs.
func (m *ItemMutation) RemoveChildIDs(ids ...uuid.UUID) {
if m.removedchildren == nil {
m.removedchildren = make(map[uuid.UUID]struct{})
}
for i := range ids {
delete(m.children, ids[i])
m.removedchildren[ids[i]] = struct{}{}
}
}
// RemovedChildren returns the removed IDs of the "children" edge to the Item entity.
func (m *ItemMutation) RemovedChildrenIDs() (ids []uuid.UUID) {
for id := range m.removedchildren {
ids = append(ids, id)
}
return
}
// ChildrenIDs returns the "children" edge IDs in the mutation.
func (m *ItemMutation) ChildrenIDs() (ids []uuid.UUID) {
for id := range m.children {
ids = append(ids, id)
}
return
}
// ResetChildren resets all changes to the "children" edge.
func (m *ItemMutation) ResetChildren() {
m.children = nil
m.clearedchildren = false
m.removedchildren = nil
}
// SetGroupID sets the "group" edge to the Group entity by id. // SetGroupID sets the "group" edge to the Group entity by id.
func (m *ItemMutation) SetGroupID(id uuid.UUID) { func (m *ItemMutation) SetGroupID(id uuid.UUID) {
m.group = &id m.group = &id
@ -6074,7 +6172,13 @@ func (m *ItemMutation) ResetField(name string) error {
// AddedEdges returns all edge names that were set/added in this mutation. // AddedEdges returns all edge names that were set/added in this mutation.
func (m *ItemMutation) AddedEdges() []string { func (m *ItemMutation) AddedEdges() []string {
edges := make([]string, 0, 5) edges := make([]string, 0, 7)
if m.parent != nil {
edges = append(edges, item.EdgeParent)
}
if m.children != nil {
edges = append(edges, item.EdgeChildren)
}
if m.group != nil { if m.group != nil {
edges = append(edges, item.EdgeGroup) edges = append(edges, item.EdgeGroup)
} }
@ -6097,6 +6201,16 @@ func (m *ItemMutation) AddedEdges() []string {
// name in this mutation. // name in this mutation.
func (m *ItemMutation) AddedIDs(name string) []ent.Value { func (m *ItemMutation) AddedIDs(name string) []ent.Value {
switch name { switch name {
case item.EdgeParent:
if id := m.parent; id != nil {
return []ent.Value{*id}
}
case item.EdgeChildren:
ids := make([]ent.Value, 0, len(m.children))
for id := range m.children {
ids = append(ids, id)
}
return ids
case item.EdgeGroup: case item.EdgeGroup:
if id := m.group; id != nil { if id := m.group; id != nil {
return []ent.Value{*id} return []ent.Value{*id}
@ -6129,7 +6243,10 @@ func (m *ItemMutation) AddedIDs(name string) []ent.Value {
// RemovedEdges returns all edge names that were removed in this mutation. // RemovedEdges returns all edge names that were removed in this mutation.
func (m *ItemMutation) RemovedEdges() []string { func (m *ItemMutation) RemovedEdges() []string {
edges := make([]string, 0, 5) edges := make([]string, 0, 7)
if m.removedchildren != nil {
edges = append(edges, item.EdgeChildren)
}
if m.removedlabel != nil { if m.removedlabel != nil {
edges = append(edges, item.EdgeLabel) edges = append(edges, item.EdgeLabel)
} }
@ -6146,6 +6263,12 @@ func (m *ItemMutation) RemovedEdges() []string {
// the given name in this mutation. // the given name in this mutation.
func (m *ItemMutation) RemovedIDs(name string) []ent.Value { func (m *ItemMutation) RemovedIDs(name string) []ent.Value {
switch name { switch name {
case item.EdgeChildren:
ids := make([]ent.Value, 0, len(m.removedchildren))
for id := range m.removedchildren {
ids = append(ids, id)
}
return ids
case item.EdgeLabel: case item.EdgeLabel:
ids := make([]ent.Value, 0, len(m.removedlabel)) ids := make([]ent.Value, 0, len(m.removedlabel))
for id := range m.removedlabel { for id := range m.removedlabel {
@ -6170,7 +6293,13 @@ func (m *ItemMutation) RemovedIDs(name string) []ent.Value {
// ClearedEdges returns all edge names that were cleared in this mutation. // ClearedEdges returns all edge names that were cleared in this mutation.
func (m *ItemMutation) ClearedEdges() []string { func (m *ItemMutation) ClearedEdges() []string {
edges := make([]string, 0, 5) edges := make([]string, 0, 7)
if m.clearedparent {
edges = append(edges, item.EdgeParent)
}
if m.clearedchildren {
edges = append(edges, item.EdgeChildren)
}
if m.clearedgroup { if m.clearedgroup {
edges = append(edges, item.EdgeGroup) edges = append(edges, item.EdgeGroup)
} }
@ -6193,6 +6322,10 @@ func (m *ItemMutation) ClearedEdges() []string {
// was cleared in this mutation. // was cleared in this mutation.
func (m *ItemMutation) EdgeCleared(name string) bool { func (m *ItemMutation) EdgeCleared(name string) bool {
switch name { switch name {
case item.EdgeParent:
return m.clearedparent
case item.EdgeChildren:
return m.clearedchildren
case item.EdgeGroup: case item.EdgeGroup:
return m.clearedgroup return m.clearedgroup
case item.EdgeLabel: case item.EdgeLabel:
@ -6211,6 +6344,9 @@ func (m *ItemMutation) EdgeCleared(name string) bool {
// if that edge is not defined in the schema. // if that edge is not defined in the schema.
func (m *ItemMutation) ClearEdge(name string) error { func (m *ItemMutation) ClearEdge(name string) error {
switch name { switch name {
case item.EdgeParent:
m.ClearParent()
return nil
case item.EdgeGroup: case item.EdgeGroup:
m.ClearGroup() m.ClearGroup()
return nil return nil
@ -6225,6 +6361,12 @@ func (m *ItemMutation) ClearEdge(name string) error {
// It returns an error if the edge is not defined in the schema. // It returns an error if the edge is not defined in the schema.
func (m *ItemMutation) ResetEdge(name string) error { func (m *ItemMutation) ResetEdge(name string) error {
switch name { switch name {
case item.EdgeParent:
m.ResetParent()
return nil
case item.EdgeChildren:
m.ResetChildren()
return nil
case item.EdgeGroup: case item.EdgeGroup:
m.ResetGroup() m.ResetGroup()
return nil return nil
@ -7886,22 +8028,27 @@ func (m *LabelMutation) ResetEdge(name string) error {
// LocationMutation represents an operation that mutates the Location nodes in the graph. // LocationMutation represents an operation that mutates the Location nodes in the graph.
type LocationMutation struct { type LocationMutation struct {
config config
op Op op Op
typ string typ string
id *uuid.UUID id *uuid.UUID
created_at *time.Time created_at *time.Time
updated_at *time.Time updated_at *time.Time
name *string name *string
description *string description *string
clearedFields map[string]struct{} clearedFields map[string]struct{}
group *uuid.UUID parent *uuid.UUID
clearedgroup bool clearedparent bool
items map[uuid.UUID]struct{} children map[uuid.UUID]struct{}
removeditems map[uuid.UUID]struct{} removedchildren map[uuid.UUID]struct{}
cleareditems bool clearedchildren bool
done bool group *uuid.UUID
oldValue func(context.Context) (*Location, error) clearedgroup bool
predicates []predicate.Location items map[uuid.UUID]struct{}
removeditems map[uuid.UUID]struct{}
cleareditems bool
done bool
oldValue func(context.Context) (*Location, error)
predicates []predicate.Location
} }
var _ ent.Mutation = (*LocationMutation)(nil) var _ ent.Mutation = (*LocationMutation)(nil)
@ -8165,6 +8312,99 @@ func (m *LocationMutation) ResetDescription() {
delete(m.clearedFields, location.FieldDescription) delete(m.clearedFields, location.FieldDescription)
} }
// SetParentID sets the "parent" edge to the Location entity by id.
func (m *LocationMutation) SetParentID(id uuid.UUID) {
m.parent = &id
}
// ClearParent clears the "parent" edge to the Location entity.
func (m *LocationMutation) ClearParent() {
m.clearedparent = true
}
// ParentCleared reports if the "parent" edge to the Location entity was cleared.
func (m *LocationMutation) ParentCleared() bool {
return m.clearedparent
}
// ParentID returns the "parent" edge ID in the mutation.
func (m *LocationMutation) ParentID() (id uuid.UUID, exists bool) {
if m.parent != nil {
return *m.parent, true
}
return
}
// ParentIDs returns the "parent" edge IDs in the mutation.
// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
// ParentID instead. It exists only for internal usage by the builders.
func (m *LocationMutation) ParentIDs() (ids []uuid.UUID) {
if id := m.parent; id != nil {
ids = append(ids, *id)
}
return
}
// ResetParent resets all changes to the "parent" edge.
func (m *LocationMutation) ResetParent() {
m.parent = nil
m.clearedparent = false
}
// AddChildIDs adds the "children" edge to the Location entity by ids.
func (m *LocationMutation) AddChildIDs(ids ...uuid.UUID) {
if m.children == nil {
m.children = make(map[uuid.UUID]struct{})
}
for i := range ids {
m.children[ids[i]] = struct{}{}
}
}
// ClearChildren clears the "children" edge to the Location entity.
func (m *LocationMutation) ClearChildren() {
m.clearedchildren = true
}
// ChildrenCleared reports if the "children" edge to the Location entity was cleared.
func (m *LocationMutation) ChildrenCleared() bool {
return m.clearedchildren
}
// RemoveChildIDs removes the "children" edge to the Location entity by IDs.
func (m *LocationMutation) RemoveChildIDs(ids ...uuid.UUID) {
if m.removedchildren == nil {
m.removedchildren = make(map[uuid.UUID]struct{})
}
for i := range ids {
delete(m.children, ids[i])
m.removedchildren[ids[i]] = struct{}{}
}
}
// RemovedChildren returns the removed IDs of the "children" edge to the Location entity.
func (m *LocationMutation) RemovedChildrenIDs() (ids []uuid.UUID) {
for id := range m.removedchildren {
ids = append(ids, id)
}
return
}
// ChildrenIDs returns the "children" edge IDs in the mutation.
func (m *LocationMutation) ChildrenIDs() (ids []uuid.UUID) {
for id := range m.children {
ids = append(ids, id)
}
return
}
// ResetChildren resets all changes to the "children" edge.
func (m *LocationMutation) ResetChildren() {
m.children = nil
m.clearedchildren = false
m.removedchildren = nil
}
// SetGroupID sets the "group" edge to the Group entity by id. // SetGroupID sets the "group" edge to the Group entity by id.
func (m *LocationMutation) SetGroupID(id uuid.UUID) { func (m *LocationMutation) SetGroupID(id uuid.UUID) {
m.group = &id m.group = &id
@ -8436,7 +8676,13 @@ func (m *LocationMutation) ResetField(name string) error {
// AddedEdges returns all edge names that were set/added in this mutation. // AddedEdges returns all edge names that were set/added in this mutation.
func (m *LocationMutation) AddedEdges() []string { func (m *LocationMutation) AddedEdges() []string {
edges := make([]string, 0, 2) edges := make([]string, 0, 4)
if m.parent != nil {
edges = append(edges, location.EdgeParent)
}
if m.children != nil {
edges = append(edges, location.EdgeChildren)
}
if m.group != nil { if m.group != nil {
edges = append(edges, location.EdgeGroup) edges = append(edges, location.EdgeGroup)
} }
@ -8450,6 +8696,16 @@ func (m *LocationMutation) AddedEdges() []string {
// name in this mutation. // name in this mutation.
func (m *LocationMutation) AddedIDs(name string) []ent.Value { func (m *LocationMutation) AddedIDs(name string) []ent.Value {
switch name { switch name {
case location.EdgeParent:
if id := m.parent; id != nil {
return []ent.Value{*id}
}
case location.EdgeChildren:
ids := make([]ent.Value, 0, len(m.children))
for id := range m.children {
ids = append(ids, id)
}
return ids
case location.EdgeGroup: case location.EdgeGroup:
if id := m.group; id != nil { if id := m.group; id != nil {
return []ent.Value{*id} return []ent.Value{*id}
@ -8466,7 +8722,10 @@ func (m *LocationMutation) AddedIDs(name string) []ent.Value {
// RemovedEdges returns all edge names that were removed in this mutation. // RemovedEdges returns all edge names that were removed in this mutation.
func (m *LocationMutation) RemovedEdges() []string { func (m *LocationMutation) RemovedEdges() []string {
edges := make([]string, 0, 2) edges := make([]string, 0, 4)
if m.removedchildren != nil {
edges = append(edges, location.EdgeChildren)
}
if m.removeditems != nil { if m.removeditems != nil {
edges = append(edges, location.EdgeItems) edges = append(edges, location.EdgeItems)
} }
@ -8477,6 +8736,12 @@ func (m *LocationMutation) RemovedEdges() []string {
// the given name in this mutation. // the given name in this mutation.
func (m *LocationMutation) RemovedIDs(name string) []ent.Value { func (m *LocationMutation) RemovedIDs(name string) []ent.Value {
switch name { switch name {
case location.EdgeChildren:
ids := make([]ent.Value, 0, len(m.removedchildren))
for id := range m.removedchildren {
ids = append(ids, id)
}
return ids
case location.EdgeItems: case location.EdgeItems:
ids := make([]ent.Value, 0, len(m.removeditems)) ids := make([]ent.Value, 0, len(m.removeditems))
for id := range m.removeditems { for id := range m.removeditems {
@ -8489,7 +8754,13 @@ func (m *LocationMutation) RemovedIDs(name string) []ent.Value {
// ClearedEdges returns all edge names that were cleared in this mutation. // ClearedEdges returns all edge names that were cleared in this mutation.
func (m *LocationMutation) ClearedEdges() []string { func (m *LocationMutation) ClearedEdges() []string {
edges := make([]string, 0, 2) edges := make([]string, 0, 4)
if m.clearedparent {
edges = append(edges, location.EdgeParent)
}
if m.clearedchildren {
edges = append(edges, location.EdgeChildren)
}
if m.clearedgroup { if m.clearedgroup {
edges = append(edges, location.EdgeGroup) edges = append(edges, location.EdgeGroup)
} }
@ -8503,6 +8774,10 @@ func (m *LocationMutation) ClearedEdges() []string {
// was cleared in this mutation. // was cleared in this mutation.
func (m *LocationMutation) EdgeCleared(name string) bool { func (m *LocationMutation) EdgeCleared(name string) bool {
switch name { switch name {
case location.EdgeParent:
return m.clearedparent
case location.EdgeChildren:
return m.clearedchildren
case location.EdgeGroup: case location.EdgeGroup:
return m.clearedgroup return m.clearedgroup
case location.EdgeItems: case location.EdgeItems:
@ -8515,6 +8790,9 @@ func (m *LocationMutation) EdgeCleared(name string) bool {
// if that edge is not defined in the schema. // if that edge is not defined in the schema.
func (m *LocationMutation) ClearEdge(name string) error { func (m *LocationMutation) ClearEdge(name string) error {
switch name { switch name {
case location.EdgeParent:
m.ClearParent()
return nil
case location.EdgeGroup: case location.EdgeGroup:
m.ClearGroup() m.ClearGroup()
return nil return nil
@ -8526,6 +8804,12 @@ func (m *LocationMutation) ClearEdge(name string) error {
// It returns an error if the edge is not defined in the schema. // It returns an error if the edge is not defined in the schema.
func (m *LocationMutation) ResetEdge(name string) error { func (m *LocationMutation) ResetEdge(name string) error {
switch name { switch name {
case location.EdgeParent:
m.ResetParent()
return nil
case location.EdgeChildren:
m.ResetChildren()
return nil
case location.EdgeGroup: case location.EdgeGroup:
m.ResetGroup() m.ResetGroup()
return nil return nil

View file

@ -94,6 +94,9 @@ func (Item) Fields() []ent.Field {
// Edges of the Item. // Edges of the Item.
func (Item) Edges() []ent.Edge { func (Item) Edges() []ent.Edge {
return []ent.Edge{ return []ent.Edge{
edge.To("children", Item.Type).
From("parent").
Unique(),
edge.From("group", Group.Type). edge.From("group", Group.Type).
Ref("items"). Ref("items").
Required(). Required().

View file

@ -27,6 +27,9 @@ func (Location) Fields() []ent.Field {
// Edges of the Location. // Edges of the Location.
func (Location) Edges() []ent.Edge { func (Location) Edges() []ent.Edge {
return []ent.Edge{ return []ent.Edge{
edge.To("children", Location.Type).
From("parent").
Unique(),
edge.From("group", Group.Type). edge.From("group", Group.Type).
Ref("locations"). Ref("locations").
Unique(). Unique().

View file

@ -61,11 +61,13 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -75,6 +77,8 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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.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.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

View file

@ -0,0 +1,28 @@
-- disable the enforcement of foreign-keys constraints
PRAGMA foreign_keys = off;
-- create "new_items" table
CREATE TABLE `new_items` (`id` uuid NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `name` text NOT NULL, `description` text NULL, `import_ref` text NULL, `notes` text NULL, `quantity` integer NOT NULL DEFAULT 1, `insured` bool NOT NULL DEFAULT false, `serial_number` text NULL, `model_number` text NULL, `manufacturer` text NULL, `lifetime_warranty` bool NOT NULL DEFAULT false, `warranty_expires` datetime NULL, `warranty_details` text NULL, `purchase_time` datetime NULL, `purchase_from` text NULL, `purchase_price` real NOT NULL DEFAULT 0, `sold_time` datetime NULL, `sold_to` text NULL, `sold_price` real NOT NULL DEFAULT 0, `sold_notes` text NULL, `group_items` uuid NOT NULL, `item_children` uuid NULL, `location_items` uuid NULL, PRIMARY KEY (`id`), CONSTRAINT `items_groups_items` FOREIGN KEY (`group_items`) REFERENCES `groups` (`id`) ON DELETE CASCADE, CONSTRAINT `items_items_children` FOREIGN KEY (`item_children`) REFERENCES `items` (`id`) ON DELETE SET NULL, CONSTRAINT `items_locations_items` FOREIGN KEY (`location_items`) REFERENCES `locations` (`id`) ON DELETE CASCADE);
-- copy rows from old table "items" to new temporary table "new_items"
INSERT INTO `new_items` (`id`, `created_at`, `updated_at`, `name`, `description`, `import_ref`, `notes`, `quantity`, `insured`, `serial_number`, `model_number`, `manufacturer`, `lifetime_warranty`, `warranty_expires`, `warranty_details`, `purchase_time`, `purchase_from`, `purchase_price`, `sold_time`, `sold_to`, `sold_price`, `sold_notes`, `group_items`, `location_items`) SELECT `id`, `created_at`, `updated_at`, `name`, `description`, `import_ref`, `notes`, `quantity`, `insured`, `serial_number`, `model_number`, `manufacturer`, `lifetime_warranty`, `warranty_expires`, `warranty_details`, `purchase_time`, `purchase_from`, `purchase_price`, `sold_time`, `sold_to`, `sold_price`, `sold_notes`, `group_items`, `location_items` FROM `items`;
-- drop "items" table after copying rows
DROP TABLE `items`;
-- rename temporary table "new_items" to "items"
ALTER TABLE `new_items` RENAME TO `items`;
-- create index "item_name" to table: "items"
CREATE INDEX `item_name` ON `items` (`name`);
-- create index "item_manufacturer" to table: "items"
CREATE INDEX `item_manufacturer` ON `items` (`manufacturer`);
-- create index "item_model_number" to table: "items"
CREATE INDEX `item_model_number` ON `items` (`model_number`);
-- create index "item_serial_number" to table: "items"
CREATE INDEX `item_serial_number` ON `items` (`serial_number`);
-- create "new_locations" table
CREATE TABLE `new_locations` (`id` uuid NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `name` text NOT NULL, `description` text NULL, `group_locations` uuid NOT NULL, `location_children` uuid NULL, PRIMARY KEY (`id`), CONSTRAINT `locations_groups_locations` FOREIGN KEY (`group_locations`) REFERENCES `groups` (`id`) ON DELETE CASCADE, CONSTRAINT `locations_locations_children` FOREIGN KEY (`location_children`) REFERENCES `locations` (`id`) ON DELETE SET NULL);
-- copy rows from old table "locations" to new temporary table "new_locations"
INSERT INTO `new_locations` (`id`, `created_at`, `updated_at`, `name`, `description`, `group_locations`) SELECT `id`, `created_at`, `updated_at`, `name`, `description`, `group_locations` FROM `locations`;
-- drop "locations" table after copying rows
DROP TABLE `locations`;
-- rename temporary table "new_locations" to "locations"
ALTER TABLE `new_locations` RENAME TO `locations`;
-- enable back the enforcement of foreign-keys constraints
PRAGMA foreign_keys = on;

View file

@ -1,4 +1,5 @@
h1:nN8ZUHScToap+2yJKsb+AnKu8o2DubUoiKc9neQJ93M= h1:mYTnmyrnBDST/r93NGJM33mIJqhp/U9qR440zI99eqQ=
20220929052825_init.sql h1:ZlCqm1wzjDmofeAcSX3jE4h4VcdTNGpRg2eabztDy9Q= 20220929052825_init.sql h1:ZlCqm1wzjDmofeAcSX3jE4h4VcdTNGpRg2eabztDy9Q=
20221001210956_group_invitations.sql h1:YQKJFtE39wFOcRNbZQ/d+ZlHwrcfcsZlcv/pLEYdpjw= 20221001210956_group_invitations.sql h1:YQKJFtE39wFOcRNbZQ/d+ZlHwrcfcsZlcv/pLEYdpjw=
20221009173029_add_user_roles.sql h1:vWmzAfgEWQeGk0Vn70zfVPCcfEZth3E0JcvyKTjpYyU= 20221009173029_add_user_roles.sql h1:vWmzAfgEWQeGk0Vn70zfVPCcfEZth3E0JcvyKTjpYyU=
20221020043305_allow_nesting_types.sql h1:4AyJpZ7l7SSJtJAQETYY802FHJ64ufYPJTqvwdiGn3M=

View file

@ -39,15 +39,17 @@ type (
} }
ItemCreate struct { ItemCreate struct {
ImportRef string `json:"-"` ImportRef string `json:"-"`
Name string `json:"name"` ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
Description string `json:"description"` Name string `json:"name"`
Description string `json:"description"`
// Edges // Edges
LocationID uuid.UUID `json:"locationId"` LocationID uuid.UUID `json:"locationId"`
LabelIDs []uuid.UUID `json:"labelIds"` LabelIDs []uuid.UUID `json:"labelIds"`
} }
ItemUpdate struct { ItemUpdate struct {
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"`
ID uuid.UUID `json:"id"` ID uuid.UUID `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
@ -95,11 +97,12 @@ type (
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
// Edges // Edges
Location LocationSummary `json:"location"` Location *LocationSummary `json:"location,omitempty" extensions:"x-nullable,x-omitempty"`
Labels []LabelSummary `json:"labels"` Labels []LabelSummary `json:"labels"`
} }
ItemOut struct { ItemOut struct {
Parent *ItemSummary `json:"parent,omitempty" extensions:"x-nullable,x-omitempty"`
ItemSummary ItemSummary
SerialNumber string `json:"serialNumber"` SerialNumber string `json:"serialNumber"`
@ -126,8 +129,8 @@ type (
Notes string `json:"notes"` Notes string `json:"notes"`
Attachments []ItemAttachment `json:"attachments"` Attachments []ItemAttachment `json:"attachments"`
// Future Fields []ItemField `json:"fields"`
Fields []ItemField `json:"fields"` Children []ItemSummary `json:"children"`
} }
) )
@ -136,12 +139,13 @@ var (
) )
func mapItemSummary(item *ent.Item) ItemSummary { func mapItemSummary(item *ent.Item) ItemSummary {
var location LocationSummary var location *LocationSummary
if item.Edges.Location != nil { if item.Edges.Location != nil {
location = mapLocationSummary(item.Edges.Location) loc := mapLocationSummary(item.Edges.Location)
location = &loc
} }
var labels []LabelSummary labels := make([]LabelSummary, len(item.Edges.Label))
if item.Edges.Label != nil { if item.Edges.Label != nil {
labels = mapEach(item.Edges.Label, mapLabelSummary) labels = mapEach(item.Edges.Label, mapLabelSummary)
} }
@ -194,7 +198,19 @@ func mapItemOut(item *ent.Item) ItemOut {
fields = mapFields(item.Edges.Fields) fields = mapFields(item.Edges.Fields)
} }
var children []ItemSummary
if item.Edges.Children != nil {
children = mapEach(item.Edges.Children, mapItemSummary)
}
var parent *ItemSummary
if item.Edges.Parent != nil {
v := mapItemSummary(item.Edges.Parent)
parent = &v
}
return ItemOut{ return ItemOut{
Parent: parent,
ItemSummary: mapItemSummary(item), ItemSummary: mapItemSummary(item),
LifetimeWarranty: item.LifetimeWarranty, LifetimeWarranty: item.LifetimeWarranty,
WarrantyExpires: item.WarrantyExpires, WarrantyExpires: item.WarrantyExpires,
@ -220,6 +236,7 @@ func mapItemOut(item *ent.Item) ItemOut {
Notes: item.Notes, Notes: item.Notes,
Attachments: attachments, Attachments: attachments,
Fields: fields, Fields: fields,
Children: children,
} }
} }
@ -231,6 +248,8 @@ func (e *ItemsRepository) getOne(ctx context.Context, where ...predicate.Item) (
WithLabel(). WithLabel().
WithLocation(). WithLocation().
WithGroup(). WithGroup().
WithChildren().
WithParent().
WithAttachments(func(aq *ent.AttachmentQuery) { WithAttachments(func(aq *ent.AttachmentQuery) {
aq.WithDocument() aq.WithDocument()
}). }).
@ -398,6 +417,12 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data
q.RemoveLabelIDs(set.Slice()...) q.RemoveLabelIDs(set.Slice()...)
} }
if data.ParentID != uuid.Nil {
q.SetParentID(data.ParentID)
} else {
q.ClearParent()
}
err = q.Exec(ctx) err = q.Exec(ctx)
if err != nil { if err != nil {
return ItemOut{}, err return ItemOut{}, err

View file

@ -41,6 +41,42 @@ func useItems(t *testing.T, len int) []ItemOut {
return items return items
} }
func TestItemsRepository_RecursiveRelationships(t *testing.T) {
parent := useItems(t, 1)[0]
children := useItems(t, 3)
for _, child := range children {
update := ItemUpdate{
ID: child.ID,
ParentID: parent.ID,
Name: "note-important",
Description: "This is a note",
LocationID: child.Location.ID,
}
// Append Parent ID
_, err := tRepos.Items.UpdateByGroup(context.Background(), tGroup.ID, update)
assert.NoError(t, err)
// Check Parent ID
updated, err := tRepos.Items.GetOne(context.Background(), child.ID)
assert.NoError(t, err)
assert.Equal(t, parent.ID, updated.Parent.ID)
// Remove Parent ID
update.ParentID = uuid.Nil
_, err = tRepos.Items.UpdateByGroup(context.Background(), tGroup.ID, update)
assert.NoError(t, err)
// Check Parent ID
updated, err = tRepos.Items.GetOne(context.Background(), child.ID)
assert.NoError(t, err)
assert.Nil(t, updated.Parent)
}
}
func TestItemsRepository_GetOne(t *testing.T) { func TestItemsRepository_GetOne(t *testing.T) {
entity := useItems(t, 3) entity := useItems(t, 3)

View file

@ -22,6 +22,7 @@ type (
} }
LocationUpdate struct { LocationUpdate struct {
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
ID uuid.UUID `json:"id"` ID uuid.UUID `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
@ -41,8 +42,10 @@ type (
} }
LocationOut struct { LocationOut struct {
Parent *LocationSummary `json:"parent,omitempty"`
LocationSummary LocationSummary
Items []ItemSummary `json:"items"` Items []ItemSummary `json:"items"`
Children []LocationSummary `json:"children"`
} }
) )
@ -61,7 +64,20 @@ var (
) )
func mapLocationOut(location *ent.Location) LocationOut { func mapLocationOut(location *ent.Location) LocationOut {
var parent *LocationSummary
if location.Edges.Parent != nil {
p := mapLocationSummary(location.Edges.Parent)
parent = &p
}
children := make([]LocationSummary, 0, len(location.Edges.Children))
for _, c := range location.Edges.Children {
children = append(children, mapLocationSummary(c))
}
return LocationOut{ return LocationOut{
Parent: parent,
Children: children,
LocationSummary: LocationSummary{ LocationSummary: LocationSummary{
ID: location.ID, ID: location.ID,
Name: location.Name, Name: location.Name,
@ -125,6 +141,8 @@ func (r *LocationRepository) getOne(ctx context.Context, where ...predicate.Loca
WithItems(func(iq *ent.ItemQuery) { WithItems(func(iq *ent.ItemQuery) {
iq.WithLabel() iq.WithLabel()
}). }).
WithParent().
WithChildren().
Only(ctx)) Only(ctx))
} }
@ -152,10 +170,17 @@ func (r *LocationRepository) Create(ctx context.Context, gid uuid.UUID, data Loc
} }
func (r *LocationRepository) Update(ctx context.Context, data LocationUpdate) (LocationOut, error) { func (r *LocationRepository) Update(ctx context.Context, data LocationUpdate) (LocationOut, error) {
_, err := r.db.Location.UpdateOneID(data.ID). q := r.db.Location.UpdateOneID(data.ID).
SetName(data.Name). SetName(data.Name).
SetDescription(data.Description). SetDescription(data.Description)
Save(ctx)
if data.ParentID != uuid.Nil {
q.SetParentID(data.ParentID)
} else {
q.ClearParent()
}
_, err := q.Save(ctx)
if err != nil { if err != nil {
return LocationOut{}, err return LocationOut{}, err

View file

@ -3,7 +3,6 @@
v-if="to" v-if="to"
v-bind="attributes" v-bind="attributes"
ref="submitBtn" ref="submitBtn"
:to="to"
class="btn" class="btn"
:class="{ :class="{
loading: loading, loading: loading,
@ -64,7 +63,7 @@
const attributes = computed(() => { const attributes = computed(() => {
if (props.to) { if (props.to) {
return { return {
href: props.to, to: props.to,
}; };
} }
return { return {

View file

@ -0,0 +1,149 @@
<template>
<div ref="menu" class="form-control w-full">
<label class="label">
<span class="label-text">{{ label }}</span>
</label>
<div class="dropdown dropdown-top sm:dropdown-end">
<div class="relative">
<input
v-model="isearch"
tabindex="0"
class="input w-full items-center flex flex-wrap border border-gray-400 rounded-lg"
@keyup.enter="selectFirst"
/>
<button
v-if="!!modelValue && Object.keys(modelValue).length !== 0"
style="transform: translateY(-50%)"
class="top-1/2 absolute right-2 btn btn-xs btn-circle no-animation"
@click="clear"
>
x
</button>
</div>
<ul
tabindex="0"
style="display: inline"
class="dropdown-content mb-1 menu shadow border border-gray-400 rounded bg-base-100 w-full z-[9999] max-h-60 overflow-y-scroll"
>
<li v-for="(obj, idx) in filtered" :key="idx">
<button type="button" @click="select(obj)">
{{ usingObjects ? obj[itemText] : obj }}
</button>
</li>
<li class="hidden first:flex">
<button disabled>
{{ noResultsText }}
</button>
</li>
</ul>
</div>
</div>
</template>
<script lang="ts" setup>
type ItemsObject = {
text?: string;
value?: string;
[key: string]: unknown;
};
interface Props {
label: string;
modelValue: string | ItemsObject;
items: ItemsObject[] | string[];
itemText?: keyof ItemsObject;
itemValue?: keyof ItemsObject;
search?: string;
noResultsText?: string;
}
const emit = defineEmits(["update:modelValue", "update:search"]);
const props = withDefaults(defineProps<Props>(), {
label: "",
modelValue: "",
items: () => [],
itemText: "text",
itemValue: "value",
search: "",
noResultsText: "No Results Found",
});
function clear() {
select(value.value);
}
const isearch = ref("");
watch(isearch, () => {
internalSearch.value = isearch.value;
});
const internalSearch = useVModel(props, "search", emit);
const value = useVModel(props, "modelValue", emit);
const usingObjects = computed(() => {
return props.items.length > 0 && typeof props.items[0] === "object";
});
/**
* isStrings is a type guard function to check if the items are an array of string
*/
function isStrings(_arr: string[] | ItemsObject[]): _arr is string[] {
return !usingObjects.value;
}
function selectFirst() {
if (filtered.value.length > 0) {
select(filtered.value[0]);
}
}
watch(
value,
() => {
if (value.value) {
if (typeof value.value === "string") {
isearch.value = value.value;
} else {
isearch.value = value.value[props.itemText] as string;
}
}
},
{
immediate: true,
}
);
function select(obj: string | ItemsObject) {
if (isStrings(props.items)) {
if (obj === value.value) {
value.value = "";
return;
}
value.value = obj;
} else {
if (obj === value.value) {
value.value = {};
return;
}
value.value = obj;
}
}
const filtered = computed(() => {
if (!isearch.value || isearch.value === "") {
return props.items;
}
if (isStrings(props.items)) {
return props.items.filter(item => item.toLowerCase().includes(isearch.value.toLowerCase()));
} else {
return props.items.filter(item => {
if (props.itemText && props.itemText in item) {
return (item[props.itemText] as string).toLowerCase().includes(isearch.value.toLowerCase());
}
return false;
});
}
});
</script>

View file

@ -45,6 +45,10 @@
type: String, type: String,
default: "", default: "",
}, },
compareKey: {
type: String,
default: null,
},
}); });
const selectedIdx = ref(-1); const selectedIdx = ref(-1);
@ -52,36 +56,34 @@
const internalSelected = useVModel(props, "modelValue", emit); const internalSelected = useVModel(props, "modelValue", emit);
const internalValue = useVModel(props, "value", emit); const internalValue = useVModel(props, "value", emit);
watch(selectedIdx, newVal => {
internalSelected.value = props.items[newVal];
});
watch(selectedIdx, newVal => {
if (props.valueKey) {
internalValue.value = props.items[newVal][props.valueKey];
}
});
watch( watch(
internalSelected, selectedIdx,
() => { newVal => {
const idx = props.items.findIndex(item => compare(item, internalSelected.value)); if (newVal === -1) {
selectedIdx.value = idx; return;
}
if (props.value) {
internalValue.value = props.items[newVal][props.valueKey];
}
internalSelected.value = props.items[newVal];
}, },
{ { immediate: true }
immediate: true,
}
); );
watch( watch(
internalValue, [internalSelected, () => props.value],
() => { () => {
const idx = props.items.findIndex(item => compare(item[props.valueKey], internalValue.value)); if (props.valueKey) {
const idx = props.items.findIndex(item => compare(item, internalValue.value));
selectedIdx.value = idx;
return;
}
const idx = props.items.findIndex(item => compare(item, internalSelected.value));
selectedIdx.value = idx; selectedIdx.value = idx;
}, },
{ { immediate: true }
immediate: true,
}
); );
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -90,8 +92,13 @@
return true; return true;
} }
if (!a || !b) { if (props.valueKey) {
return false; return a[props.valueKey] === b;
}
// Try compare key
if (props.compareKey && a && b) {
return a[props.compareKey] === b[props.compareKey];
} }
return JSON.stringify(a) === JSON.stringify(b); return JSON.stringify(a) === JSON.stringify(b);

View file

@ -17,20 +17,18 @@
<Icon name="heroicons-map-pin" class="swap-off" /> <Icon name="heroicons-map-pin" class="swap-off" />
</label> </label>
{{ location.name }} {{ location.name }}
<span v-if="location.itemCount" class="badge badge-secondary badge-lg ml-auto text-secondary-content"> <span v-if="hasCount" class="badge badge-secondary badge-lg ml-auto text-secondary-content"> {{ count }}</span>
{{ location.itemCount }}</span
>
</h2> </h2>
</div> </div>
</NuxtLink> </NuxtLink>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { LocationOutCount } from "~~/lib/api/types/data-contracts"; import { LocationOut, LocationOutCount, LocationSummary } from "~~/lib/api/types/data-contracts";
defineProps({ const props = defineProps({
location: { location: {
type: Object as () => LocationOutCount, type: Object as () => LocationOutCount | LocationOut | LocationSummary,
required: true, required: true,
}, },
dense: { dense: {
@ -39,6 +37,16 @@
}, },
}); });
const hasCount = computed(() => {
return !!(props.location as LocationOutCount).itemCount;
});
const count = computed(() => {
if (hasCount.value) {
return (props.location as LocationOutCount).itemCount;
}
});
const card = ref(null); const card = ref(null);
const isHover = useElementHover(card); const isHover = useElementHover(card);
const { focused } = useFocus(card); const { focused } = useFocus(card);

View file

@ -0,0 +1,36 @@
import { ItemSummary, LabelSummary, LocationSummary } from "~~/lib/api/types/data-contracts";
import { UserClient } from "~~/lib/api/user";
type SearchOptions = {
immediate?: boolean;
};
export function useItemSearch(client: UserClient, opts?: SearchOptions) {
const query = ref("");
const locations = ref<LocationSummary[]>([]);
const labels = ref<LabelSummary[]>([]);
const results = ref<ItemSummary[]>([]);
watchDebounced(query, search, { debounce: 250, maxWait: 1000 });
async function search() {
const locIds = locations.value.map(l => l.id);
const labelIds = labels.value.map(l => l.id);
const { data, error } = await client.items.getAll({ q: query.value, locations: locIds, labels: labelIds });
if (error) {
return;
}
results.value = data.items;
}
if (opts?.immediate) {
search();
}
return {
query,
results,
locations,
labels,
};
}

View file

@ -1,9 +1,7 @@
import { BaseAPI, route } from "../base"; import { BaseAPI, route } from "../base";
import { LocationOutCount, LocationCreate, LocationOut } from "../types/data-contracts"; import { LocationOutCount, LocationCreate, LocationOut, LocationUpdate } from "../types/data-contracts";
import { Results } from "../types/non-generated"; import { Results } from "../types/non-generated";
export type LocationUpdate = LocationCreate;
export class LocationsApi extends BaseAPI { export class LocationsApi extends BaseAPI {
getAll() { getAll() {
return this.http.get<Results<LocationOutCount>>({ url: route("/locations") }); return this.http.get<Results<LocationOutCount>>({ url: route("/locations") });

View file

@ -49,6 +49,7 @@ export interface ItemCreate {
/** Edges */ /** Edges */
locationId: string; locationId: string;
name: string; name: string;
parentId: string | null;
} }
export interface ItemField { export interface ItemField {
@ -63,10 +64,9 @@ export interface ItemField {
export interface ItemOut { export interface ItemOut {
attachments: ItemAttachment[]; attachments: ItemAttachment[];
children: ItemSummary[];
createdAt: Date; createdAt: Date;
description: string; description: string;
/** Future */
fields: ItemField[]; fields: ItemField[];
id: string; id: string;
insured: boolean; insured: boolean;
@ -76,13 +76,14 @@ export interface ItemOut {
lifetimeWarranty: boolean; lifetimeWarranty: boolean;
/** Edges */ /** Edges */
location: LocationSummary; location: LocationSummary | null;
manufacturer: string; manufacturer: string;
modelNumber: string; modelNumber: string;
name: string; name: string;
/** Extras */ /** Extras */
notes: string; notes: string;
parent: ItemSummary | null;
purchaseFrom: string; purchaseFrom: string;
/** @example 0 */ /** @example 0 */
@ -113,7 +114,7 @@ export interface ItemSummary {
labels: LabelSummary[]; labels: LabelSummary[];
/** Edges */ /** Edges */
location: LocationSummary; location: LocationSummary | null;
name: string; name: string;
quantity: number; quantity: number;
updatedAt: Date; updatedAt: Date;
@ -137,6 +138,7 @@ export interface ItemUpdate {
/** Extras */ /** Extras */
notes: string; notes: string;
parentId: string | null;
purchaseFrom: string; purchaseFrom: string;
/** @example 0 */ /** @example 0 */
@ -189,11 +191,13 @@ export interface LocationCreate {
} }
export interface LocationOut { export interface LocationOut {
children: LocationSummary[];
createdAt: Date; createdAt: Date;
description: string; description: string;
id: string; id: string;
items: ItemSummary[]; items: ItemSummary[];
name: string; name: string;
parent: LocationSummary;
updatedAt: Date; updatedAt: Date;
} }
@ -214,6 +218,13 @@ export interface LocationSummary {
updatedAt: Date; updatedAt: Date;
} }
export interface LocationUpdate {
description: string;
id: string;
name: string;
parentId: string | null;
}
export interface PaginationResultRepoItemSummary { export interface PaginationResultRepoItemSummary {
items: ItemSummary[]; items: ItemSummary[];
page: number; page: number;

View file

@ -4,6 +4,7 @@
import { useLabelStore } from "~~/stores/labels"; import { useLabelStore } from "~~/stores/labels";
import { useLocationStore } from "~~/stores/locations"; import { useLocationStore } from "~~/stores/locations";
import { capitalize } from "~~/lib/strings"; import { capitalize } from "~~/lib/strings";
import Autocomplete from "~~/components/Form/Autocomplete.vue";
definePageMeta({ definePageMeta({
middleware: ["auth"], middleware: ["auth"],
@ -37,8 +38,13 @@
} }
} }
if (data.parent) {
parent.value = data.parent;
}
return data; return data;
}); });
onMounted(() => { onMounted(() => {
refresh(); refresh();
}); });
@ -48,6 +54,7 @@
...item.value, ...item.value,
locationId: item.value.location?.id, locationId: item.value.location?.id,
labelIds: item.value.labels.map(l => l.id), labelIds: item.value.labels.map(l => l.id),
parentId: parent.value ? parent.value.id : null,
}; };
const { error } = await api.items.update(itemId.value, payload); const { error } = await api.items.update(itemId.value, payload);
@ -256,7 +263,6 @@
async function updateAttachment() { async function updateAttachment() {
editState.loading = true; editState.loading = true;
console.log(editState.type);
const { error, data } = await api.items.updateAttachment(itemId.value, editState.id, { const { error, data } = await api.items.updateAttachment(itemId.value, editState.id, {
title: editState.title, title: editState.title,
type: editState.type, type: editState.type,
@ -306,6 +312,9 @@
timeValue: null, timeValue: null,
}); });
} }
const { query, results } = useItemSearch(api, { immediate: false });
const parent = ref();
</script> </script>
<template> <template>
@ -314,8 +323,8 @@
<template #title> Attachment Edit </template> <template #title> Attachment Edit </template>
<FormTextField v-model="editState.title" label="Attachment Title" /> <FormTextField v-model="editState.title" label="Attachment Title" />
{{ editState.type }}
<FormSelect <FormSelect
v-model="editState.obj"
v-model:value="editState.type" v-model:value="editState.type"
label="Attachment Type" label="Attachment Type"
value-key="value" value-key="value"
@ -354,8 +363,24 @@
</template> </template>
</BaseSectionHeader> </BaseSectionHeader>
<div class="px-5 mb-6 grid md:grid-cols-2 gap-4"> <div class="px-5 mb-6 grid md:grid-cols-2 gap-4">
<FormSelect v-if="item" v-model="item.location" label="Location" :items="locations ?? []" /> <FormSelect
v-if="item"
v-model="item.location"
label="Location"
:items="locations ?? []"
compare-key="id"
/>
<FormMultiselect v-model="item.labels" label="Labels" :items="labels ?? []" /> <FormMultiselect v-model="item.labels" label="Labels" :items="labels ?? []" />
<Autocomplete
v-if="!preferences.editorSimpleView"
v-model="parent"
v-model:search="query"
:items="results"
item-text="name"
label="Parent Item"
no-results-text="Type to search..."
/>
</div> </div>
<div class="border-t border-gray-300 sm:p-0"> <div class="border-t border-gray-300 sm:p-0">

View file

@ -76,6 +76,10 @@
name: "Description", name: "Description",
text: item.value?.description, text: item.value?.description,
}, },
{
name: "Quantity",
text: item.value?.quantity,
},
{ {
name: "Serial Number", name: "Serial Number",
text: item.value?.serialNumber, text: item.value?.serialNumber,
@ -287,12 +291,23 @@
<span class="text-base-content"> <span class="text-base-content">
{{ item ? item.name : "" }} {{ item ? item.name : "" }}
</span> </span>
<div v-if="item.parent" class="text-sm breadcrumbs pb-0">
<ul class="text-base-content/70">
<li>
<NuxtLink :to="`/item/${item.parent.id}`"> {{ item.parent.name }}</NuxtLink>
</li>
<li>{{ item.name }}</li>
</ul>
</div>
<template #description> <template #description>
<p class="text-sm text-base-content font-bold pb-0 mb-0"> <div class="flex flex-wrap gap-2 mt-3">
{{ item.location.name }} - Quantity {{ item.quantity }} <NuxtLink ref="badge" class="badge p-3" :to="`/location/${item.location.id}`">
</p> <Icon name="heroicons-map-pin" class="mr-2 swap-on"></Icon>
<div v-if="item.labels && item.labels.length > 0" class="flex flex-wrap gap-3 mt-3"> {{ item.location.name }}
<LabelChip v-for="label in item.labels" :key="label.id" class="badge-primary" :label="label" /> </NuxtLink>
<template v-if="item.labels && item.labels.length > 0">
<LabelChip v-for="label in item.labels" :key="label.id" class="badge-primary" :label="label" />
</template>
</div> </div>
</template> </template>
</BaseSectionHeader> </BaseSectionHeader>
@ -378,5 +393,12 @@
</BaseCard> </BaseCard>
</div> </div>
</section> </section>
<section class="my-6 px-3">
<BaseSectionHeader v-if="item && item.children && item.children.length > 0"> Child Items </BaseSectionHeader>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<ItemCard v-for="child in item.children" :key="child.id" :item="child" />
</div>
</section>
</BaseContainer> </BaseContainer>
</template> </template>

View file

@ -1,5 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Detail, CustomDetail } from "~~/components/global/DetailsSection/types"; import { Detail, CustomDetail } from "~~/components/global/DetailsSection/types";
import { LocationSummary, LocationUpdate } from "~~/lib/api/types/data-contracts";
import { useLocationStore } from "~~/stores/locations";
definePageMeta({ definePageMeta({
middleware: ["auth"], middleware: ["auth"],
@ -20,6 +22,11 @@
navigateTo("/home"); navigateTo("/home");
return; return;
} }
if (data.parent) {
parent.value = locations.value.find(l => l.id === data.parent.id);
}
return data; return data;
}); });
@ -62,7 +69,7 @@
async function confirmDelete() { async function confirmDelete() {
const { isCanceled } = await confirm.open( const { isCanceled } = await confirm.open(
"Are you sure you want to delete this location? This action cannot be undone." "Are you sure you want to delete this location and all of its items? This action cannot be undone."
); );
if (isCanceled) { if (isCanceled) {
return; return;
@ -80,9 +87,11 @@
const updateModal = ref(false); const updateModal = ref(false);
const updating = ref(false); const updating = ref(false);
const updateData = reactive({ const updateData = reactive<LocationUpdate>({
id: locationId.value,
name: "", name: "",
description: "", description: "",
parentId: null,
}); });
function openUpdate() { function openUpdate() {
@ -93,6 +102,7 @@
async function update() { async function update() {
updating.value = true; updating.value = true;
updateData.parentId = parent.value?.id || null;
const { error, data } = await api.locations.update(locationId.value, updateData); const { error, data } = await api.locations.update(locationId.value, updateData);
if (error) { if (error) {
@ -105,6 +115,12 @@
updateModal.value = false; updateModal.value = false;
updating.value = false; updating.value = false;
} }
const locationStore = useLocationStore();
const locations = computed(() => locationStore.locations);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parent = ref<LocationSummary | any>({});
</script> </script>
<template> <template>
@ -114,6 +130,7 @@
<form v-if="location" @submit.prevent="update"> <form v-if="location" @submit.prevent="update">
<FormTextField v-model="updateData.name" :autofocus="true" label="Location Name" /> <FormTextField v-model="updateData.name" :autofocus="true" label="Location Name" />
<FormTextArea v-model="updateData.description" label="Location Description" /> <FormTextArea v-model="updateData.description" label="Location Description" />
<FormAutocomplete v-model="parent" :items="locations" item-text="name" item-value="id" label="Parent" />
<div class="modal-action"> <div class="modal-action">
<BaseButton type="submit" :loading="updating"> Update </BaseButton> <BaseButton type="submit" :loading="updating"> Update </BaseButton>
</div> </div>
@ -127,6 +144,14 @@
<span class="text-base-content"> <span class="text-base-content">
{{ location ? location.name : "" }} {{ location ? location.name : "" }}
</span> </span>
<div v-if="location && location.parent" class="text-sm breadcrumbs pb-0">
<ul class="text-base-content/70">
<li>
<NuxtLink :to="`/location/${location.parent.id}`"> {{ location.parent.name }}</NuxtLink>
</li>
<li>{{ location.name }}</li>
</ul>
</div>
</BaseSectionHeader> </BaseSectionHeader>
</template> </template>
@ -152,11 +177,18 @@
<DetailsSection :details="details" /> <DetailsSection :details="details" />
</BaseCard> </BaseCard>
<section v-if="location"> <section v-if="location && location.items.length > 0">
<BaseSectionHeader class="mb-5"> Items </BaseSectionHeader> <BaseSectionHeader class="mb-5"> Items </BaseSectionHeader>
<div class="grid gap-2 grid-cols-1 sm:grid-cols-2"> <div class="grid gap-2 grid-cols-1 sm:grid-cols-2">
<ItemCard v-for="item in location.items" :key="item.id" :item="item" /> <ItemCard v-for="item in location.items" :key="item.id" :item="item" />
</div> </div>
</section> </section>
<section v-if="location && location.children.length > 0">
<BaseSectionHeader class="mb-5"> Child Locations </BaseSectionHeader>
<div class="grid gap-2 grid-cols-1 sm:grid-cols-3">
<LocationCard v-for="item in location.children" :key="item.id" :location="item" />
</div>
</section>
</BaseContainer> </BaseContainer>
</template> </template>