Skip to content

Commit

Permalink
add child-node schema mutation operation
Browse files Browse the repository at this point in the history
  • Loading branch information
Southclaws committed Feb 4, 2025
1 parent 320adfa commit 6ef9ba0
Show file tree
Hide file tree
Showing 16 changed files with 717 additions and 514 deletions.
6 changes: 4 additions & 2 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5156,7 +5156,7 @@ components:
allOf:
- $ref: "#/components/schemas/Node"
- $ref: "#/components/schemas/DatagraphRecommendations"
- required: [properties, children]
- required: [properties, child_property_schema, children]
properties:
properties: {$ref: "#/components/schemas/PropertyList"}
child_property_schema:
Expand Down Expand Up @@ -5252,12 +5252,14 @@ components:

Property:
type: object
required: [id, name, type]
required: [id, name, type, sort]
properties:
id: {$ref: "#/components/schemas/Identifier"}
name: {$ref: "#/components/schemas/PropertyName"}
type: {$ref: "#/components/schemas/PropertyType"}
value: {$ref: "#/components/schemas/PropertyValue"}
sort:
type: string

PropertyList:
type: array
Expand Down
62 changes: 46 additions & 16 deletions app/resources/library/node_properties/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/Southclaws/opt"
"github.com/Southclaws/storyden/app/resources/library"
"github.com/Southclaws/storyden/internal/ent"
"github.com/Southclaws/storyden/internal/ent/node"
"github.com/Southclaws/storyden/internal/ent/propertyschemafield"
"github.com/rs/xid"
"github.com/samber/lo"
Expand Down Expand Up @@ -62,23 +63,22 @@ func (w *SchemaWriter) UpdateChildren(ctx context.Context, qk library.QueryKey,

creates := SchemaMutations{}
updates := SchemaMutations{}
deletes := lo.KeyBy(currentSchema.Edges.Fields, func(f *ent.PropertySchemaField) xid.ID { return f.ID })
deletes := map[xid.ID]*ent.PropertySchemaField{}

if currentSchema != nil {
deletes = lo.KeyBy(currentSchema.Edges.Fields, func(f *ent.PropertySchemaField) xid.ID { return f.ID })
}

for _, s := range schemas {
id, ok := s.ID.Get()
delete(deletes, id)
if !ok {
creates = append(creates, s)
continue
}

updates = append(updates, s)

delete(deletes, id)
}

deleteIDs := dt.Map(lo.Values(deletes), func(f *ent.PropertySchemaField) xid.ID { return f.ID })
_, err = w.db.PropertySchemaField.Delete().Where(propertyschemafield.IDIn(deleteIDs...)).Exec(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

tx, err := w.db.Tx(ctx)
Expand All @@ -89,25 +89,55 @@ func (w *SchemaWriter) UpdateChildren(ctx context.Context, qk library.QueryKey,
err = tx.Rollback()
}()

// Update fields
for _, s := range updates {
// we know this is non-zero already.
id := s.ID.OrZero()
// Create schema if it doesn't exist
if currentSchema == nil {
currentSchema, err = tx.PropertySchema.Create().Save(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

childIDs := dt.Map(children, func(n *ent.Node) xid.ID { return n.ID })

err = tx.PropertySchemaField.UpdateOneID(id).SetName(s.Name).SetSort(s.Sort).SetType(s.Type).Exec(ctx)
// assign schema to all child nodes
err = tx.Node.Update().Where(node.IDIn(childIDs...)).SetPropertySchemas(currentSchema).Exec(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
}

// Create fields
for _, s := range creates {
err = tx.PropertySchemaField.Create().SetName(s.Name).SetSort(s.Sort).SetType(s.Type).Exec(ctx)
// Delete fields

if len(deletes) > 0 {
deleteIDs := dt.Map(lo.Values(deletes), func(f *ent.PropertySchemaField) xid.ID { return f.ID })
_, err = tx.PropertySchemaField.Delete().Where(propertyschemafield.IDIn(deleteIDs...)).Exec(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
}

// Update fields
if len(updates) > 0 {
for _, s := range updates {
// we know this is non-zero already.
id := s.ID.OrZero()

err = tx.PropertySchemaField.UpdateOneID(id).SetName(s.Name).SetSort(s.Sort).SetType(s.Type).Exec(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
}
}

// Create fields
if len(creates) > 0 {
for _, s := range creates {
err = tx.PropertySchemaField.Create().SetName(s.Name).SetSort(s.Sort).SetType(s.Type).SetSchemaID(currentSchema.ID).Exec(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
}
}

if err := tx.Commit(); err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
Expand Down
2 changes: 1 addition & 1 deletion app/resources/library/node_querier/node_querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ order by sort asc
`

func (q *Querier) Get(ctx context.Context, qk library.QueryKey, opts ...Option) (*library.Node, error) {
query := q.db.Node.Query()
query := q.db.Debug().Node.Query()

query.Where(qk.Predicate())

Expand Down
12 changes: 8 additions & 4 deletions app/resources/library/properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package library
import (
"github.com/Southclaws/dt"
"github.com/Southclaws/opt"
"github.com/rs/xid"
"github.com/samber/lo"

"github.com/Southclaws/storyden/internal/ent"
)

type PropertySchema struct {
ID xid.ID
Name string
Type string
Sort string
Expand All @@ -25,6 +27,7 @@ type PropertySchemas []*PropertySchema

func MapPropertySchema(in PropertySchemaQueryRow) PropertySchema {
return PropertySchema{
ID: in.FieldID,
Name: in.Name,
Type: in.Type,
Sort: in.Sort,
Expand All @@ -34,7 +37,7 @@ func MapPropertySchema(in PropertySchemaQueryRow) PropertySchema {
// PropertySchemaQueryRow is a row from the property schema query which pulls
// all the property schemas for both sibling and child properties of a node.
type PropertySchemaQueryRow struct {
FieldID string `db:"id"`
FieldID xid.ID `db:"id"`
Name string `db:"name"`
Type string `db:"type"`
Sort string `db:"sort"`
Expand Down Expand Up @@ -74,14 +77,14 @@ func (r *PropertySchemaTable) BuildPropertyTable(in []*ent.Property, isRoot bool
if !isRoot {
schemas = r.childSchemas
}
propMap := lo.KeyBy(schemas, func(r PropertySchemaQueryRow) string { return r.FieldID })
propMap := lo.KeyBy(schemas, func(r PropertySchemaQueryRow) xid.ID { return r.FieldID })

out := PropertyTable{}

// Add all the properties that have values.
for _, p := range in {
if s, ok := propMap[p.FieldID.String()]; ok {
delete(propMap, p.FieldID.String())
if s, ok := propMap[p.FieldID]; ok {
delete(propMap, p.FieldID)
out = append(out, &Property{
PropertySchema: MapPropertySchema(s),
Value: opt.New(p.Value),
Expand All @@ -104,6 +107,7 @@ func (r *PropertySchemaTable) BuildPropertyTable(in []*ent.Property, isRoot bool
func (r PropertySchemaTable) ChildSchemas() PropertySchemas {
return dt.Map(r.childSchemas, func(r PropertySchemaQueryRow) *PropertySchema {
return &PropertySchema{
ID: r.FieldID,
Name: r.Name,
Type: r.Type,
Sort: r.Sort,
Expand Down
11 changes: 7 additions & 4 deletions app/transports/http/bindings/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Nodes struct {
nv *node_visibility.Controller
ntree nodetree.Graph
ntr node_traversal.Repository
nsr node_properties.SchemaWriter
nsr *node_properties.SchemaWriter
}

func NewNodes(
Expand All @@ -48,7 +48,7 @@ func NewNodes(
nv *node_visibility.Controller,
ntree nodetree.Graph,
ntr node_traversal.Repository,
nsr node_properties.SchemaWriter,
nsr *node_properties.SchemaWriter,
) Nodes {
return Nodes{
accountQuery: accountQuery,
Expand Down Expand Up @@ -518,6 +518,7 @@ func serialiseProperty(in *library.Property) openapi.Property {
return openapi.Property{
Name: in.Name,
Type: in.Type,
Sort: in.Sort,
Value: opt.Map(in.Value, func(v string) string { return v }).Ptr(),
}
}
Expand All @@ -528,21 +529,23 @@ func serialisePropertyList(in library.PropertyTable) openapi.PropertyList {

func serialisePropertySchema(in *library.PropertySchema) openapi.PropertySchema {
return openapi.PropertySchema{
Id: in.ID.String(),
Name: in.Name,
Type: in.Type,
Sort: in.Sort,
}
}

func serialisePropertySchemas(in library.PropertySchemas) openapi.PropertySchemaList {
return dt.Map(in, serialisePropertySchema)
}

func serialisePropertySchemaList(in library.PropertySchemas) *openapi.PropertySchemaList {
func serialisePropertySchemaList(in library.PropertySchemas) openapi.PropertySchemaList {
if len(in) == 0 {
return nil
}
schemas := dt.Map(in, serialisePropertySchema)
return &schemas
return schemas
}

func getContentFillRuleSourceCommand(contentFillRuleParam *openapi.ContentFillRule, contentFillSourceParam *openapi.FillSourceQuery) (opt.Optional[asset.ContentFillCommand], error) {
Expand Down
6 changes: 3 additions & 3 deletions app/transports/http/bindings/openapi_rbac/openapi_rbac_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ type OperationPermissions interface {
NodeGet() (bool, *rbac.Permission)
NodeUpdate() (bool, *rbac.Permission)
NodeDelete() (bool, *rbac.Permission)
NodeUpdateProperties() (bool, *rbac.Permission)
NodeUpdateChildrenPropertySchema() (bool, *rbac.Permission)
NodeUpdateProperties() (bool, *rbac.Permission)
NodeUpdateVisibility() (bool, *rbac.Permission)
NodeAddAsset() (bool, *rbac.Permission)
NodeRemoveAsset() (bool, *rbac.Permission)
Expand Down Expand Up @@ -311,10 +311,10 @@ func GetOperationPermission(optable OperationPermissions, op string) (bool, *rba
return optable.NodeUpdate()
case "NodeDelete":
return optable.NodeDelete()
case "NodeUpdateProperties":
return optable.NodeUpdateProperties()
case "NodeUpdateChildrenPropertySchema":
return optable.NodeUpdateChildrenPropertySchema()
case "NodeUpdateProperties":
return optable.NodeUpdateProperties()
case "NodeUpdateVisibility":
return optable.NodeUpdateVisibility()
case "NodeAddAsset":
Expand Down
Loading

0 comments on commit 6ef9ba0

Please sign in to comment.