From fc4639a2931f1662d52ce2b1498cfa277d3ed5d6 Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Sat, 7 Mar 2020 16:19:27 +0100 Subject: [PATCH] Add album path resolver --- api/graphql/generated.go | 73 +++++++++++++++++++++++++++++++--- api/graphql/models/album.go | 4 ++ api/graphql/resolvers/album.go | 16 ++++++++ api/graphql/schema.graphql | 3 +- 4 files changed, 89 insertions(+), 7 deletions(-) diff --git a/api/graphql/generated.go b/api/graphql/generated.go index 1b81f5a8..966dc9ea 100644 --- a/api/graphql/generated.go +++ b/api/graphql/generated.go @@ -52,6 +52,7 @@ type DirectiveRoot struct { type ComplexityRoot struct { Album struct { + FilePath func(childComplexity int) int ID func(childComplexity int) int Owner func(childComplexity int) int ParentAlbum func(childComplexity int) int @@ -191,6 +192,7 @@ type AlbumResolver interface { Owner(ctx context.Context, obj *models.Album) (*models.User, error) Thumbnail(ctx context.Context, obj *models.Album) (*models.Photo, error) + Path(ctx context.Context, obj *models.Album) ([]*models.Album, error) Shares(ctx context.Context, obj *models.Album) ([]*models.ShareToken, error) } type MutationResolver interface { @@ -250,6 +252,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in _ = ec switch typeName + "." + field { + case "Album.filePath": + if e.complexity.Album.FilePath == nil { + break + } + + return e.complexity.Album.FilePath(childComplexity), true + case "Album.id": if e.complexity.Album.ID == nil { break @@ -1213,9 +1222,10 @@ type Album { "The user who owns this album" owner: User! "The path on the filesystem of the server, where this album is located" - path: String! + filePath: String! "An image in this album used for previewing this album" thumbnail: Photo + path: [Album!]! shares: [ShareToken] } @@ -2007,7 +2017,7 @@ func (ec *executionContext) _Album_owner(ctx context.Context, field graphql.Coll return ec.marshalNUser2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) _Album_path(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) { +func (ec *executionContext) _Album_filePath(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { @@ -2020,13 +2030,13 @@ func (ec *executionContext) _Album_path(ctx context.Context, field graphql.Colle Object: "Album", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithResolverContext(ctx, rctx) ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Path, nil + return obj.FilePath(), nil }) if err != nil { ec.Error(ctx, err) @@ -2078,6 +2088,43 @@ func (ec *executionContext) _Album_thumbnail(ctx context.Context, field graphql. return ec.marshalOPhoto2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPhoto(ctx, field.Selections, res) } +func (ec *executionContext) _Album_path(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + ec.Tracer.EndFieldExecution(ctx) + }() + rctx := &graphql.ResolverContext{ + Object: "Album", + Field: field, + Args: nil, + IsMethod: true, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Album().Path(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*models.Album) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return ec.marshalNAlbum2ᚕᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐAlbumᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) _Album_shares(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { @@ -6509,8 +6556,8 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob } return res }) - case "path": - out.Values[i] = ec._Album_path(ctx, field, obj) + case "filePath": + out.Values[i] = ec._Album_filePath(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } @@ -6525,6 +6572,20 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob res = ec._Album_thumbnail(ctx, field, obj) return res }) + case "path": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Album_path(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "shares": field := field out.Concurrently(i, func() (res graphql.Marshaler) { diff --git a/api/graphql/models/album.go b/api/graphql/models/album.go index 5dcdfb3d..11491eaa 100644 --- a/api/graphql/models/album.go +++ b/api/graphql/models/album.go @@ -16,6 +16,10 @@ func (a *Album) ID() int { return a.AlbumID } +func (a *Album) FilePath() string { + return a.Path +} + func NewAlbumFromRow(row *sql.Row) (*Album, error) { album := Album{} diff --git a/api/graphql/resolvers/album.go b/api/graphql/resolvers/album.go index 32e96eaf..018c634d 100644 --- a/api/graphql/resolvers/album.go +++ b/api/graphql/resolvers/album.go @@ -163,3 +163,19 @@ func (r *albumResolver) Shares(ctx context.Context, obj *models.Album) ([]*model return models.NewShareTokensFromRows(rows) } + +func (r *albumResolver) Path(ctx context.Context, obj *models.Album) ([]*models.Album, error) { + rows, err := r.Database.Query(` + WITH recursive path_albums AS ( + SELECT * FROM album anchor WHERE anchor.album_id = ? + UNION + SELECT parent.* FROM path_albums child JOIN album parent ON parent.album_id = child.parent_album + ) + SELECT * FROM path_albums WHERE album_id != ? + `, obj.AlbumID, obj.AlbumID) + if err != nil { + return nil, err + } + + return models.NewAlbumsFromRows(rows) +} diff --git a/api/graphql/schema.graphql b/api/graphql/schema.graphql index ce2c4415..79803080 100644 --- a/api/graphql/schema.graphql +++ b/api/graphql/schema.graphql @@ -166,9 +166,10 @@ type Album { "The user who owns this album" owner: User! "The path on the filesystem of the server, where this album is located" - path: String! + filePath: String! "An image in this album used for previewing this album" thumbnail: Photo + path: [Album!]! shares: [ShareToken] }