feat(09-10): add typed relation manager
This commit is contained in:
@@ -111,7 +111,7 @@ func ExecuteList(ctx context.Context, db *gorm.DB, cc *CompiledController, in Li
|
||||
q = next
|
||||
}
|
||||
}
|
||||
q, err = applyListSearch(q, cc.List, model, in.Search)
|
||||
q, err = applyListSearch(q, cc.Controller, cc.List, model, in.Search)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func ExecuteList(ctx context.Context, db *gorm.DB, cc *CompiledController, in Li
|
||||
if err := q.Session(&gorm.Session{}).Count(&total).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q = applyListOrder(q, cc.List, model, sortCol, sortDesc)
|
||||
q = applyListOrder(q, cc.Controller, cc.List, model, sortCol, sortDesc)
|
||||
for _, col := range cc.List.Columns {
|
||||
if col.Relation == "" {
|
||||
continue
|
||||
@@ -140,7 +140,7 @@ func ExecuteList(ctx context.Context, db *gorm.DB, cc *CompiledController, in Li
|
||||
values := slice.Elem()
|
||||
data := make([]map[string]any, 0, values.Len())
|
||||
for i := 0; i < values.Len(); i++ {
|
||||
data = append(data, projectRow(values.Index(i).Addr().Interface(), cc.List.Columns))
|
||||
data = append(data, projectRow(values.Index(i).Addr().Interface(), cc.Controller, cc.List.Columns))
|
||||
}
|
||||
paged := lagoon.Paginate(data, page, per, total)
|
||||
return &ListResult{
|
||||
@@ -223,7 +223,7 @@ func normalizeSort(schema *ListSchema, in ListInput) (string, bool, error) {
|
||||
return match.Key, dir == "desc", nil
|
||||
}
|
||||
|
||||
func applyListOrder(db *gorm.DB, schema *ListSchema, model any, column string, desc bool) *gorm.DB {
|
||||
func applyListOrder(db *gorm.DB, controller pact.AdminController, schema *ListSchema, model any, column string, desc bool) *gorm.DB {
|
||||
table := tableName(model)
|
||||
pk := primaryColumn(model)
|
||||
if column != "" {
|
||||
@@ -238,7 +238,7 @@ func applyListOrder(db *gorm.DB, schema *ListSchema, model any, column string, d
|
||||
continue
|
||||
}
|
||||
orderTable = field
|
||||
orderColumn = col.Select
|
||||
orderColumn = listRelationColumn(controller, col.Relation, col.Select)
|
||||
db = db.Joins(field)
|
||||
break
|
||||
}
|
||||
@@ -253,7 +253,7 @@ func applyListOrder(db *gorm.DB, schema *ListSchema, model any, column string, d
|
||||
return db
|
||||
}
|
||||
|
||||
func applyListSearch(db *gorm.DB, schema *ListSchema, model any, term string) (*gorm.DB, error) {
|
||||
func applyListSearch(db *gorm.DB, controller pact.AdminController, schema *ListSchema, model any, term string) (*gorm.DB, error) {
|
||||
term = strings.TrimSpace(term)
|
||||
if term == "" {
|
||||
return db, nil
|
||||
@@ -277,12 +277,13 @@ func applyListSearch(db *gorm.DB, schema *ListSchema, model any, term string) (*
|
||||
column := col.Key
|
||||
if col.Relation != "" {
|
||||
field, ok := relationFieldName(model, col.Relation)
|
||||
if !ok || !identifier(col.Select) {
|
||||
physical := listRelationColumn(controller, col.Relation, col.Select)
|
||||
if !ok || !identifier(physical) {
|
||||
return nil, listInvalid("search", "is not searchable")
|
||||
}
|
||||
// GORM aliases the joined association with the Go field name.
|
||||
table = field
|
||||
column = col.Select
|
||||
column = physical
|
||||
if _, done := joined[field]; !done {
|
||||
db = db.Joins(field)
|
||||
joined[field] = struct{}{}
|
||||
@@ -496,7 +497,7 @@ func primaryColumn(model any) string {
|
||||
return "id"
|
||||
}
|
||||
|
||||
func relatedSelect(row reflect.Value, col ListColumn) (any, bool) {
|
||||
func relatedSelect(row reflect.Value, controller pact.AdminController, col ListColumn) (any, bool) {
|
||||
for row.Kind() == reflect.Pointer {
|
||||
if row.IsNil() {
|
||||
return nil, false
|
||||
@@ -523,9 +524,21 @@ func relatedSelect(row reflect.Value, col ListColumn) (any, bool) {
|
||||
if field.Kind() != reflect.Struct {
|
||||
return nil, false
|
||||
}
|
||||
selected := fieldByColumn(field, col.Select)
|
||||
selected := fieldByColumn(field, listRelationColumn(controller, col.Relation, col.Select))
|
||||
if !selected.IsValid() || !selected.CanInterface() {
|
||||
return nil, false
|
||||
}
|
||||
return selected.Interface(), true
|
||||
}
|
||||
|
||||
func listRelationColumn(controller pact.AdminController, relation, column string) string {
|
||||
mapper, ok := controller.(pact.ListRelationColumnMapper)
|
||||
if !ok || mapper == nil {
|
||||
return column
|
||||
}
|
||||
mapped, ok := mapper.ListRelationColumn(relation, column)
|
||||
if !ok || mapped == "" {
|
||||
return column
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user