diff --git a/api/graphql/generated.go b/api/graphql/generated.go index 1268a467..a41d3c4a 100644 --- a/api/graphql/generated.go +++ b/api/graphql/generated.go @@ -55,12 +55,12 @@ type ComplexityRoot struct { Album struct { FilePath func(childComplexity int) int ID func(childComplexity int) int - Media func(childComplexity int, filter *models.Filter, onlyFavorites *bool) int + Media func(childComplexity int, order *models.Ordering, paginate *models.Pagination, onlyFavorites *bool) int Owner func(childComplexity int) int ParentAlbum func(childComplexity int) int Path func(childComplexity int) int Shares func(childComplexity int) int - SubAlbums func(childComplexity int, filter *models.Filter) int + SubAlbums func(childComplexity int, order *models.Ordering, paginate *models.Pagination) int Thumbnail func(childComplexity int) int Title func(childComplexity int) int } @@ -149,16 +149,16 @@ type ComplexityRoot struct { MapboxToken func(childComplexity int) int Media func(childComplexity int, id int) int MediaList func(childComplexity int, ids []int) int - MyAlbums func(childComplexity int, filter *models.Filter, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) int - MyMedia func(childComplexity int, filter *models.Filter) int + MyAlbums func(childComplexity int, order *models.Ordering, paginate *models.Pagination, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) int + MyMedia func(childComplexity int, order *models.Ordering, paginate *models.Pagination) int MyMediaGeoJSON func(childComplexity int) int - MyTimeline func(childComplexity int, limit *int, offset *int, onlyFavorites *bool) int + MyTimeline func(childComplexity int, paginate *models.Pagination, onlyFavorites *bool) int MyUser func(childComplexity int) int Search func(childComplexity int, query string, limitMedia *int, limitAlbums *int) int ShareToken func(childComplexity int, token string, password *string) int ShareTokenValidatePassword func(childComplexity int, token string, password *string) int SiteInfo func(childComplexity int) int - User func(childComplexity int, filter *models.Filter) int + User func(childComplexity int, order *models.Ordering, paginate *models.Pagination) int } ScannerResult struct { @@ -224,8 +224,8 @@ type ComplexityRoot struct { } type AlbumResolver interface { - Media(ctx context.Context, obj *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error) - SubAlbums(ctx context.Context, obj *models.Album, filter *models.Filter) ([]*models.Album, error) + Media(ctx context.Context, obj *models.Album, order *models.Ordering, paginate *models.Pagination, onlyFavorites *bool) ([]*models.Media, error) + SubAlbums(ctx context.Context, obj *models.Album, order *models.Ordering, paginate *models.Pagination) ([]*models.Album, error) Owner(ctx context.Context, obj *models.Album) (*models.User, error) @@ -265,14 +265,14 @@ type MutationResolver interface { } type QueryResolver interface { SiteInfo(ctx context.Context) (*models.SiteInfo, error) - User(ctx context.Context, filter *models.Filter) ([]*models.User, error) + User(ctx context.Context, order *models.Ordering, paginate *models.Pagination) ([]*models.User, error) MyUser(ctx context.Context) (*models.User, error) - MyAlbums(ctx context.Context, filter *models.Filter, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) ([]*models.Album, error) + MyAlbums(ctx context.Context, order *models.Ordering, paginate *models.Pagination, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) ([]*models.Album, error) Album(ctx context.Context, id int) (*models.Album, error) - MyMedia(ctx context.Context, filter *models.Filter) ([]*models.Media, error) + MyMedia(ctx context.Context, order *models.Ordering, paginate *models.Pagination) ([]*models.Media, error) Media(ctx context.Context, id int) (*models.Media, error) MediaList(ctx context.Context, ids []int) ([]*models.Media, error) - MyTimeline(ctx context.Context, limit *int, offset *int, onlyFavorites *bool) ([]*models.TimelineGroup, error) + MyTimeline(ctx context.Context, paginate *models.Pagination, onlyFavorites *bool) ([]*models.TimelineGroup, error) MyMediaGeoJSON(ctx context.Context) (interface{}, error) MapboxToken(ctx context.Context) (*string, error) ShareToken(ctx context.Context, token string, password *string) (*models.ShareToken, error) @@ -329,7 +329,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Album.Media(childComplexity, args["filter"].(*models.Filter), args["onlyFavorites"].(*bool)), true + return e.complexity.Album.Media(childComplexity, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination), args["onlyFavorites"].(*bool)), true case "Album.owner": if e.complexity.Album.Owner == nil { @@ -369,7 +369,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Album.SubAlbums(childComplexity, args["filter"].(*models.Filter)), true + return e.complexity.Album.SubAlbums(childComplexity, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination)), true case "Album.thumbnail": if e.complexity.Album.Thumbnail == nil { @@ -919,7 +919,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.MyAlbums(childComplexity, args["filter"].(*models.Filter), args["onlyRoot"].(*bool), args["showEmpty"].(*bool), args["onlyWithFavorites"].(*bool)), true + return e.complexity.Query.MyAlbums(childComplexity, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination), args["onlyRoot"].(*bool), args["showEmpty"].(*bool), args["onlyWithFavorites"].(*bool)), true case "Query.myMedia": if e.complexity.Query.MyMedia == nil { @@ -931,7 +931,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.MyMedia(childComplexity, args["filter"].(*models.Filter)), true + return e.complexity.Query.MyMedia(childComplexity, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination)), true case "Query.myMediaGeoJson": if e.complexity.Query.MyMediaGeoJSON == nil { @@ -950,7 +950,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.MyTimeline(childComplexity, args["limit"].(*int), args["offset"].(*int), args["onlyFavorites"].(*bool)), true + return e.complexity.Query.MyTimeline(childComplexity, args["paginate"].(*models.Pagination), args["onlyFavorites"].(*bool)), true case "Query.myUser": if e.complexity.Query.MyUser == nil { @@ -1012,7 +1012,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.User(childComplexity, args["filter"].(*models.Filter)), true + return e.complexity.Query.User(childComplexity, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination)), true case "ScannerResult.finished": if e.complexity.ScannerResult.Finished == nil { @@ -1364,24 +1364,28 @@ enum OrderDirection { DESC } -input Filter { - order_by: String - order_direction: OrderDirection +input Pagination { limit: Int offset: Int } +input Ordering { + order_by: String + order_direction: OrderDirection +} + type Query { siteInfo: SiteInfo! "List of registered users, must be admin to call" - user(filter: Filter): [User!]! @isAdmin + user(order: Ordering, paginate: Pagination): [User!]! @isAdmin "Information about the currently logged in user" myUser: User! "List of albums owned by the logged in user." myAlbums( - filter: Filter + order: Ordering, + paginate: Pagination "Return only albums from the root directory of the user" onlyRoot: Boolean "Return also albums with no media directly in them" @@ -1393,14 +1397,14 @@ type Query { album(id: ID!): Album! "List of media owned by the logged in user" - myMedia(filter: Filter): [Media!]! + myMedia(order: Ordering, paginate: Pagination): [Media!]! "Get media by id, user must own the media or be admin" media(id: ID!): Media! "Get a list of media by their ids, user must own the media or be admin" mediaList(ids: [ID!]!): [Media!]! - myTimeline(limit: Int, offset: Int, onlyFavorites: Boolean): [TimelineGroup!]! + myTimeline(paginate: Pagination, onlyFavorites: Boolean): [TimelineGroup!]! "Get media owned by the logged in user, returned in GeoJson format" myMediaGeoJson: Any! @@ -1545,14 +1549,21 @@ type User { type Album { id: ID! title: String! + "The media inside this album" media( - filter: Filter, + order: Ordering, + paginate: Pagination "Return only the favorited media" onlyFavorites: Boolean ): [Media!]! + "The albums contained in this album" - subAlbums(filter: Filter): [Album!]! + subAlbums( + order: Ordering, + paginate: Pagination + ): [Album!]! + "The album witch contains this album" parentAlbum: Album "The user who owns this album" @@ -1670,39 +1681,57 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) func (ec *executionContext) field_Album_media_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *models.Filter - if tmp, ok := rawArgs["filter"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOFilter2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐFilter(ctx, tmp) + var arg0 *models.Ordering + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg0, err = ec.unmarshalOOrdering2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐOrdering(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 - var arg1 *bool + args["order"] = arg0 + var arg1 *models.Pagination + if tmp, ok := rawArgs["paginate"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("paginate")) + arg1, err = ec.unmarshalOPagination2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPagination(ctx, tmp) + if err != nil { + return nil, err + } + } + args["paginate"] = arg1 + var arg2 *bool if tmp, ok := rawArgs["onlyFavorites"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("onlyFavorites")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err } } - args["onlyFavorites"] = arg1 + args["onlyFavorites"] = arg2 return args, nil } func (ec *executionContext) field_Album_subAlbums_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *models.Filter - if tmp, ok := rawArgs["filter"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOFilter2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐFilter(ctx, tmp) + var arg0 *models.Ordering + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg0, err = ec.unmarshalOOrdering2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐOrdering(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 + args["order"] = arg0 + var arg1 *models.Pagination + if tmp, ok := rawArgs["paginate"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("paginate")) + arg1, err = ec.unmarshalOPagination2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPagination(ctx, tmp) + if err != nil { + return nil, err + } + } + args["paginate"] = arg1 return args, nil } @@ -2138,90 +2167,99 @@ func (ec *executionContext) field_Query_media_args(ctx context.Context, rawArgs func (ec *executionContext) field_Query_myAlbums_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *models.Filter - if tmp, ok := rawArgs["filter"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOFilter2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐFilter(ctx, tmp) + var arg0 *models.Ordering + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg0, err = ec.unmarshalOOrdering2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐOrdering(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 - var arg1 *bool + args["order"] = arg0 + var arg1 *models.Pagination + if tmp, ok := rawArgs["paginate"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("paginate")) + arg1, err = ec.unmarshalOPagination2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPagination(ctx, tmp) + if err != nil { + return nil, err + } + } + args["paginate"] = arg1 + var arg2 *bool if tmp, ok := rawArgs["onlyRoot"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("onlyRoot")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["onlyRoot"] = arg1 - var arg2 *bool - if tmp, ok := rawArgs["showEmpty"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("showEmpty")) arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err } } - args["showEmpty"] = arg2 + args["onlyRoot"] = arg2 var arg3 *bool - if tmp, ok := rawArgs["onlyWithFavorites"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("onlyWithFavorites")) + if tmp, ok := rawArgs["showEmpty"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("showEmpty")) arg3, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err } } - args["onlyWithFavorites"] = arg3 + args["showEmpty"] = arg3 + var arg4 *bool + if tmp, ok := rawArgs["onlyWithFavorites"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("onlyWithFavorites")) + arg4, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["onlyWithFavorites"] = arg4 return args, nil } func (ec *executionContext) field_Query_myMedia_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *models.Filter - if tmp, ok := rawArgs["filter"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOFilter2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐFilter(ctx, tmp) + var arg0 *models.Ordering + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg0, err = ec.unmarshalOOrdering2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐOrdering(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 + args["order"] = arg0 + var arg1 *models.Pagination + if tmp, ok := rawArgs["paginate"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("paginate")) + arg1, err = ec.unmarshalOPagination2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPagination(ctx, tmp) + if err != nil { + return nil, err + } + } + args["paginate"] = arg1 return args, nil } func (ec *executionContext) field_Query_myTimeline_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *int - if tmp, ok := rawArgs["limit"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - arg0, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + var arg0 *models.Pagination + if tmp, ok := rawArgs["paginate"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("paginate")) + arg0, err = ec.unmarshalOPagination2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPagination(ctx, tmp) if err != nil { return nil, err } } - args["limit"] = arg0 - var arg1 *int - if tmp, ok := rawArgs["offset"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["offset"] = arg1 - var arg2 *bool + args["paginate"] = arg0 + var arg1 *bool if tmp, ok := rawArgs["onlyFavorites"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("onlyFavorites")) - arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err } } - args["onlyFavorites"] = arg2 + args["onlyFavorites"] = arg1 return args, nil } @@ -2309,15 +2347,24 @@ func (ec *executionContext) field_Query_shareToken_args(ctx context.Context, raw func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *models.Filter - if tmp, ok := rawArgs["filter"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOFilter2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐFilter(ctx, tmp) + var arg0 *models.Ordering + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg0, err = ec.unmarshalOOrdering2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐOrdering(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 + args["order"] = arg0 + var arg1 *models.Pagination + if tmp, ok := rawArgs["paginate"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("paginate")) + arg1, err = ec.unmarshalOPagination2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPagination(ctx, tmp) + if err != nil { + return nil, err + } + } + args["paginate"] = arg1 return args, nil } @@ -2454,7 +2501,7 @@ func (ec *executionContext) _Album_media(ctx context.Context, field graphql.Coll fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Album().Media(rctx, obj, args["filter"].(*models.Filter), args["onlyFavorites"].(*bool)) + return ec.resolvers.Album().Media(rctx, obj, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination), args["onlyFavorites"].(*bool)) }) if err != nil { ec.Error(ctx, err) @@ -2496,7 +2543,7 @@ func (ec *executionContext) _Album_subAlbums(ctx context.Context, field graphql. fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Album().SubAlbums(rctx, obj, args["filter"].(*models.Filter)) + return ec.resolvers.Album().SubAlbums(rctx, obj, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination)) }) if err != nil { ec.Error(ctx, err) @@ -4943,7 +4990,7 @@ func (ec *executionContext) _Query_user(ctx context.Context, field graphql.Colle resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().User(rctx, args["filter"].(*models.Filter)) + return ec.resolvers.Query().User(rctx, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination)) } directive1 := func(ctx context.Context) (interface{}, error) { if ec.directives.IsAdmin == nil { @@ -5039,7 +5086,7 @@ func (ec *executionContext) _Query_myAlbums(ctx context.Context, field graphql.C fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().MyAlbums(rctx, args["filter"].(*models.Filter), args["onlyRoot"].(*bool), args["showEmpty"].(*bool), args["onlyWithFavorites"].(*bool)) + return ec.resolvers.Query().MyAlbums(rctx, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination), args["onlyRoot"].(*bool), args["showEmpty"].(*bool), args["onlyWithFavorites"].(*bool)) }) if err != nil { ec.Error(ctx, err) @@ -5123,7 +5170,7 @@ func (ec *executionContext) _Query_myMedia(ctx context.Context, field graphql.Co fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().MyMedia(rctx, args["filter"].(*models.Filter)) + return ec.resolvers.Query().MyMedia(rctx, args["order"].(*models.Ordering), args["paginate"].(*models.Pagination)) }) if err != nil { ec.Error(ctx, err) @@ -5249,7 +5296,7 @@ func (ec *executionContext) _Query_myTimeline(ctx context.Context, field graphql fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().MyTimeline(rctx, args["limit"].(*int), args["offset"].(*int), args["onlyFavorites"].(*bool)) + return ec.resolvers.Query().MyTimeline(rctx, args["paginate"].(*models.Pagination), args["onlyFavorites"].(*bool)) }) if err != nil { ec.Error(ctx, err) @@ -7972,8 +8019,8 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co // region **************************** input.gotpl ***************************** -func (ec *executionContext) unmarshalInputFilter(ctx context.Context, obj interface{}) (models.Filter, error) { - var it models.Filter +func (ec *executionContext) unmarshalInputOrdering(ctx context.Context, obj interface{}) (models.Ordering, error) { + var it models.Ordering var asMap = obj.(map[string]interface{}) for k, v := range asMap { @@ -7994,6 +8041,18 @@ func (ec *executionContext) unmarshalInputFilter(ctx context.Context, obj interf if err != nil { return it, err } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputPagination(ctx context.Context, obj interface{}) (models.Pagination, error) { + var it models.Pagination + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { case "limit": var err error @@ -10205,14 +10264,6 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return graphql.MarshalBoolean(*v) } -func (ec *executionContext) unmarshalOFilter2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐFilter(ctx context.Context, v interface{}) (*models.Filter, error) { - if v == nil { - return nil, nil - } - res, err := ec.unmarshalInputFilter(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) unmarshalOFloat2ᚖfloat64(ctx context.Context, v interface{}) (*float64, error) { if v == nil { return nil, nil @@ -10280,6 +10331,22 @@ func (ec *executionContext) marshalOOrderDirection2ᚖgithubᚗcomᚋphotoview return v } +func (ec *executionContext) unmarshalOOrdering2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐOrdering(ctx context.Context, v interface{}) (*models.Ordering, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputOrdering(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOPagination2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐPagination(ctx context.Context, v interface{}) (*models.Pagination, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputPagination(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalOShareToken2ᚕᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐShareToken(ctx context.Context, sel ast.SelectionSet, v []*models.ShareToken) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/api/graphql/models/generated.go b/api/graphql/models/generated.go index 4d0ffd51..920c080a 100644 --- a/api/graphql/models/generated.go +++ b/api/graphql/models/generated.go @@ -15,13 +15,6 @@ type AuthorizeResult struct { Token *string `json:"token"` } -type Filter struct { - OrderBy *string `json:"order_by"` - OrderDirection *OrderDirection `json:"order_direction"` - Limit *int `json:"limit"` - Offset *int `json:"offset"` -} - type MediaDownload struct { Title string `json:"title"` MediaURL *MediaURL `json:"mediaUrl"` @@ -39,6 +32,16 @@ type Notification struct { Timeout *int `json:"timeout"` } +type Ordering struct { + OrderBy *string `json:"order_by"` + OrderDirection *OrderDirection `json:"order_direction"` +} + +type Pagination struct { + Limit *int `json:"limit"` + Offset *int `json:"offset"` +} + type ScannerResult struct { Finished bool `json:"finished"` Success bool `json:"success"` diff --git a/api/graphql/models/media.go b/api/graphql/models/media.go index 2ca874aa..5085f23f 100644 --- a/api/graphql/models/media.go +++ b/api/graphql/models/media.go @@ -11,17 +11,15 @@ import ( type Media struct { Model - Title string `gorm:"not null"` - Path string `gorm:"not null"` - PathHash string `gorm:"not null;unique"` - AlbumID int `gorm:"not null;index"` - Album Album `gorm:"constraint:OnDelete:CASCADE;"` - ExifID *int `gorm:"index"` - Exif *MediaEXIF `gorm:"constraint:OnDelete:CASCADE;"` - MediaURL []MediaURL `gorm:"constraint:OnDelete:CASCADE;"` - DateShot time.Time `gorm:"not null"` - DateImported time.Time `gorm:"not null"` - // Favorite bool `gorm:"not null, default:false"` + Title string `gorm:"not null"` + Path string `gorm:"not null"` + PathHash string `gorm:"not null;unique"` + AlbumID int `gorm:"not null;index"` + Album Album `gorm:"constraint:OnDelete:CASCADE;"` + ExifID *int `gorm:"index"` + Exif *MediaEXIF `gorm:"constraint:OnDelete:CASCADE;"` + MediaURL []MediaURL `gorm:"constraint:OnDelete:CASCADE;"` + DateShot time.Time `gorm:"not null"` Type MediaType `gorm:"not null;index"` VideoMetadataID *int `gorm:"index"` VideoMetadata *VideoMetadata `gorm:"constraint:OnDelete:CASCADE;"` diff --git a/api/graphql/models/utils.go b/api/graphql/models/utils.go index 93caf5a5..ba1345dd 100644 --- a/api/graphql/models/utils.go +++ b/api/graphql/models/utils.go @@ -8,32 +8,29 @@ import ( "gorm.io/gorm/clause" ) -func (filter *Filter) FormatSQL(tx *gorm.DB) *gorm.DB { +func FormatSQL(tx *gorm.DB, order *Ordering, paginate *Pagination) *gorm.DB { - if filter == nil { - return tx + if paginate != nil { + if paginate.Limit != nil { + tx.Limit(*paginate.Limit) + } + + if paginate.Offset != nil { + tx.Offset(*paginate.Offset) + } } - if filter.Limit != nil { - tx.Limit(*filter.Limit) - } - - if filter.Offset != nil { - tx.Offset(*filter.Offset) - } - - if filter.OrderBy != nil { - + if order != nil && order.OrderBy != nil { desc := true - if filter.OrderDirection != nil && filter.OrderDirection.IsValid() { - if *filter.OrderDirection == OrderDirectionAsc { + if order.OrderDirection != nil && order.OrderDirection.IsValid() { + if *order.OrderDirection == OrderDirectionAsc { desc = false } } tx.Order(clause.OrderByColumn{ Column: clause.Column{ - Name: *filter.OrderBy, + Name: *order.OrderBy, }, Desc: desc, }) diff --git a/api/graphql/resolvers/album.go b/api/graphql/resolvers/album.go index 92064925..04ab7cfe 100644 --- a/api/graphql/resolvers/album.go +++ b/api/graphql/resolvers/album.go @@ -10,7 +10,7 @@ import ( "gorm.io/gorm" ) -func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) ([]*models.Album, error) { +func (r *queryResolver) MyAlbums(ctx context.Context, order *models.Ordering, paginate *models.Pagination, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) ([]*models.Album, error) { user := auth.UserFromContext(ctx) if user == nil { return nil, auth.ErrUnauthorized @@ -50,7 +50,7 @@ func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onl query = query.Where("EXISTS (?)", subQuery) } - query = filter.FormatSQL(query) + query = models.FormatSQL(query, order, paginate) var albums []*models.Album if err := query.Scan(&albums).Error; err != nil { @@ -92,7 +92,7 @@ func (r *Resolver) Album() api.AlbumResolver { type albumResolver struct{ *Resolver } -func (r *albumResolver) Media(ctx context.Context, album *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error) { +func (r *albumResolver) Media(ctx context.Context, album *models.Album, order *models.Ordering, paginate *models.Pagination, onlyFavorites *bool) ([]*models.Media, error) { query := r.Database. Where("media.album_id = ?", album.ID). @@ -111,7 +111,7 @@ func (r *albumResolver) Media(ctx context.Context, album *models.Album, filter * query = query.Where("EXISTS (?)", favoriteQuery) } - query = filter.FormatSQL(query) + query = models.FormatSQL(query, order, paginate) var media []*models.Media if err := query.Find(&media).Error; err != nil { @@ -146,12 +146,12 @@ func (r *albumResolver) Thumbnail(ctx context.Context, obj *models.Album) (*mode return &media, nil } -func (r *albumResolver) SubAlbums(ctx context.Context, parent *models.Album, filter *models.Filter) ([]*models.Album, error) { +func (r *albumResolver) SubAlbums(ctx context.Context, parent *models.Album, order *models.Ordering, paginate *models.Pagination) ([]*models.Album, error) { var albums []*models.Album query := r.Database.Where("parent_album_id = ?", parent.ID) - query = filter.FormatSQL(query) + query = models.FormatSQL(query, order, paginate) if err := query.Find(&albums).Error; err != nil { return nil, err diff --git a/api/graphql/resolvers/media.go b/api/graphql/resolvers/media.go index 0f2109f3..bb0d2706 100644 --- a/api/graphql/resolvers/media.go +++ b/api/graphql/resolvers/media.go @@ -11,7 +11,7 @@ import ( "gorm.io/gorm/clause" ) -func (r *queryResolver) MyMedia(ctx context.Context, filter *models.Filter) ([]*models.Media, error) { +func (r *queryResolver) MyMedia(ctx context.Context, order *models.Ordering, paginate *models.Pagination) ([]*models.Media, error) { user := auth.UserFromContext(ctx) if user == nil { return nil, errors.New("unauthorized") @@ -33,7 +33,7 @@ func (r *queryResolver) MyMedia(ctx context.Context, filter *models.Filter) ([]* Where("albums.id IN (?)", userAlbumIDs). Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("id").Where("media_url.media_id = media.id")) - query = filter.FormatSQL(query) + query = models.FormatSQL(query, order, paginate) if err := query.Scan(&media).Error; err != nil { return nil, err diff --git a/api/graphql/resolvers/timeline.go b/api/graphql/resolvers/timeline.go index ba8819a4..e9002fec 100644 --- a/api/graphql/resolvers/timeline.go +++ b/api/graphql/resolvers/timeline.go @@ -9,7 +9,7 @@ import ( "gorm.io/gorm" ) -func (r *queryResolver) MyTimeline(ctx context.Context, limit *int, offset *int, onlyFavorites *bool) ([]*models.TimelineGroup, error) { +func (r *queryResolver) MyTimeline(ctx context.Context, paginate *models.Pagination, onlyFavorites *bool) ([]*models.TimelineGroup, error) { user := auth.UserFromContext(ctx) if user == nil { return nil, auth.ErrUnauthorized @@ -33,12 +33,14 @@ func (r *queryResolver) MyTimeline(ctx context.Context, limit *int, offset *int, daysQuery.Where("media.id IN (?)", tx.Table("user_media_data").Select("user_media_data.media_id").Where("user_media_data.user_id = ?", user.ID).Where("user_media_data.favorite = 1")) } - if limit != nil { - daysQuery.Limit(*limit) - } + if paginate != nil { + if paginate.Limit != nil { + daysQuery.Limit(*paginate.Limit) + } - if offset != nil { - daysQuery.Offset(*offset) + if paginate.Offset != nil { + daysQuery.Offset(*paginate.Offset) + } } rows, err := daysQuery.Group("albums.id, YEAR(media.date_shot), MONTH(media.date_shot), DAY(media.date_shot)"). diff --git a/api/graphql/resolvers/user.go b/api/graphql/resolvers/user.go index bf23d936..95406b8b 100644 --- a/api/graphql/resolvers/user.go +++ b/api/graphql/resolvers/user.go @@ -25,11 +25,11 @@ func (r *Resolver) User() api.UserResolver { return &userResolver{r} } -func (r *queryResolver) User(ctx context.Context, filter *models.Filter) ([]*models.User, error) { +func (r *queryResolver) User(ctx context.Context, order *models.Ordering, paginate *models.Pagination) ([]*models.User, error) { var users []*models.User - if err := filter.FormatSQL(r.Database.Model(models.User{})).Scan(&users).Error; err != nil { + if err := models.FormatSQL(r.Database.Model(models.User{}), order, paginate).Scan(&users).Error; err != nil { return nil, err } diff --git a/api/graphql/schema.graphql b/api/graphql/schema.graphql index 4317c95b..fe67538a 100644 --- a/api/graphql/schema.graphql +++ b/api/graphql/schema.graphql @@ -8,24 +8,28 @@ enum OrderDirection { DESC } -input Filter { - order_by: String - order_direction: OrderDirection +input Pagination { limit: Int offset: Int } +input Ordering { + order_by: String + order_direction: OrderDirection +} + type Query { siteInfo: SiteInfo! "List of registered users, must be admin to call" - user(filter: Filter): [User!]! @isAdmin + user(order: Ordering, paginate: Pagination): [User!]! @isAdmin "Information about the currently logged in user" myUser: User! "List of albums owned by the logged in user." myAlbums( - filter: Filter + order: Ordering, + paginate: Pagination "Return only albums from the root directory of the user" onlyRoot: Boolean "Return also albums with no media directly in them" @@ -37,14 +41,14 @@ type Query { album(id: ID!): Album! "List of media owned by the logged in user" - myMedia(filter: Filter): [Media!]! + myMedia(order: Ordering, paginate: Pagination): [Media!]! "Get media by id, user must own the media or be admin" media(id: ID!): Media! "Get a list of media by their ids, user must own the media or be admin" mediaList(ids: [ID!]!): [Media!]! - myTimeline(limit: Int, offset: Int, onlyFavorites: Boolean): [TimelineGroup!]! + myTimeline(paginate: Pagination, onlyFavorites: Boolean): [TimelineGroup!]! "Get media owned by the logged in user, returned in GeoJson format" myMediaGeoJson: Any! @@ -189,14 +193,21 @@ type User { type Album { id: ID! title: String! + "The media inside this album" media( - filter: Filter, + order: Ordering, + paginate: Pagination "Return only the favorited media" onlyFavorites: Boolean ): [Media!]! + "The albums contained in this album" - subAlbums(filter: Filter): [Album!]! + subAlbums( + order: Ordering, + paginate: Pagination + ): [Album!]! + "The album witch contains this album" parentAlbum: Album "The user who owns this album" diff --git a/ui/src/Pages/AlbumPage/AlbumPage.js b/ui/src/Pages/AlbumPage/AlbumPage.js index e513ea1d..81a0279f 100644 --- a/ui/src/Pages/AlbumPage/AlbumPage.js +++ b/ui/src/Pages/AlbumPage/AlbumPage.js @@ -20,7 +20,7 @@ const albumQuery = gql` album(id: $id) { id title - subAlbums(filter: { order_by: "title" }) { + subAlbums(order: { order_by: "title" }) { id title thumbnail { @@ -30,9 +30,8 @@ const albumQuery = gql` } } media( - filter: { - limit: $limit - offset: $offset + paginate: { limit: $limit, offset: $offset } + order: { order_by: $mediaOrderBy order_direction: $mediaOrderDirection } diff --git a/ui/src/Pages/AllAlbumsPage/AlbumsPage.js b/ui/src/Pages/AllAlbumsPage/AlbumsPage.js index bdb8ade1..871bbe8a 100644 --- a/ui/src/Pages/AllAlbumsPage/AlbumsPage.js +++ b/ui/src/Pages/AllAlbumsPage/AlbumsPage.js @@ -5,7 +5,7 @@ import { useQuery, gql } from '@apollo/client' const getAlbumsQuery = gql` query getMyAlbums { - myAlbums(filter: { order_by: "title" }, onlyRoot: true, showEmpty: true) { + myAlbums(order: { order_by: "title" }, onlyRoot: true, showEmpty: true) { id title thumbnail { diff --git a/ui/src/Pages/SharePage/SharePage.js b/ui/src/Pages/SharePage/SharePage.js index e303d9f8..328930ab 100644 --- a/ui/src/Pages/SharePage/SharePage.js +++ b/ui/src/Pages/SharePage/SharePage.js @@ -36,7 +36,7 @@ export const SHARE_TOKEN_QUERY = gql` url } } - media(filter: { order_by: "title", order_direction: DESC }) { + media(order: { order_by: "title", order_direction: DESC }) { ...MediaProps } } diff --git a/ui/src/apolloClient.js b/ui/src/apolloClient.js index b1128b43..be9fb688 100644 --- a/ui/src/apolloClient.js +++ b/ui/src/apolloClient.js @@ -120,7 +120,7 @@ const memoryCache = new InMemoryCache({ Album: { fields: { media: { - keyArgs: ['onlyFavorites'], + keyArgs: ['onlyFavorites', 'order'], merge(existing = [], incoming) { return [...existing, ...incoming] }, diff --git a/ui/src/components/AlbumFilter.js b/ui/src/components/AlbumFilter.js index 4f2b52fa..4c3ea09f 100644 --- a/ui/src/components/AlbumFilter.js +++ b/ui/src/components/AlbumFilter.js @@ -11,8 +11,8 @@ const sortingOptions = [ text: 'Date shot', }, { - key: 'date_imported', - value: 'date_imported', + key: 'updated_at', + value: 'updated_at', text: 'Date imported', }, { @@ -21,7 +21,7 @@ const sortingOptions = [ text: 'Title', }, { - key: 'kind', + key: 'type', value: 'type', text: 'Kind', }, diff --git a/ui/src/components/photoGallery/GalleryGroups.js b/ui/src/components/photoGallery/GalleryGroups.js deleted file mode 100644 index 315cd774..00000000 --- a/ui/src/components/photoGallery/GalleryGroups.js +++ /dev/null @@ -1,187 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react' -import { useLocation } from 'react-router-dom' -import { useQuery, gql } from '@apollo/client' -import PhotoGallery from '../../components/photoGallery/PhotoGallery' -import AlbumTitle from '../../components/AlbumTitle' -import { authToken } from '../../authentication' -import PropTypes from 'prop-types' -import AlbumFilter from '../../components/AlbumFilter' - -const photoQuery = gql` - query allGalleryGroups( - $onlyWithFavorites: Boolean - $mediaOrderBy: String - $mediaOrderDirection: OrderDirection - ) { - myAlbums( - filter: { order_by: "title", order_direction: ASC, limit: 100 } - onlyWithFavorites: $onlyWithFavorites - ) { - title - id - media( - filter: { - order_by: $mediaOrderBy - order_direction: $mediaOrderDirection - limit: 12 - } - onlyFavorites: $onlyWithFavorites - ) { - id - title - type - thumbnail { - url - width - height - } - highRes { - url - width - height - } - videoWeb { - url - } - favorite - } - } - } -` - -const GalleryGroups = ({ subPage }) => { - const [activeIndex, setActiveIndex] = useState({ album: -1, media: -1 }) - const [presenting, setPresenting] = useState(false) - const [onlyWithFavorites, setOnlyWithFavorites] = useState( - subPage === 'favorites' - ) - - const urlParams = new URLSearchParams(useLocation().search) - const [ordering, setOrdering] = useState({ - orderBy: urlParams.get('orderBy') || 'date_shot', - orderDirection: urlParams.get('orderDirection') || 'ASC', - }) - - const setOrderingCallback = useCallback( - ordering => { - setOrdering(prevState => { - return { - ...prevState, - ...ordering, - } - }) - }, - [setOrdering] - ) - - const refetchNeeded = useRef({ all: false, favorites: false }) - - const { loading, error, data, refetch } = useQuery(photoQuery, { - variables: { - onlyWithFavorites: onlyWithFavorites, - mediaOrderBy: ordering.orderBy, - mediaOrderDirection: ordering.orderDirection, - }, - }) - - const nextImage = useCallback(() => { - setActiveIndex(index => { - const albumMediaCount = data.myAlbums[index.album].media.length - - if (index.media + 1 < albumMediaCount) { - return { - ...index, - media: index.media + 1, - } - } else { - return index - } - }) - }, [data]) - - const previousImage = useCallback(() => { - setActiveIndex(index => - index.media > 0 ? { ...index, media: index.media - 1 } : index - ) - }) - - const setOnlyFavorites = useCallback( - onlyWithFavorites => { - history.replaceState( - {}, - '', - '/photos' + (onlyWithFavorites ? '/favorites' : '') - ) - - if ( - (refetchNeeded.current.all && !onlyWithFavorites) || - (refetchNeeded.current.favorites && onlyWithFavorites) - ) { - refetch({ onlyWithFavorites: onlyWithFavorites }).then(() => { - if (onlyWithFavorites) { - refetchNeeded.current.favorites = false - } else { - refetchNeeded.current.all = false - } - setOnlyWithFavorites(onlyWithFavorites) - }) - } else { - setOnlyWithFavorites(onlyWithFavorites) - } - }, - [setOnlyWithFavorites] - ) - - useEffect(() => { - const pathName = `/photos${onlyWithFavorites ? '/favorites' : ''}` - const queryString = `orderBy=${ordering.orderBy}&orderDirection=${ordering.orderDirection}` - - history.replaceState({}, '', pathName + '?' + queryString) - }, [onlyWithFavorites, ordering]) - - if (error) return error - let galleryGroups = [] - - if (!loading && data.myAlbums && authToken()) { - galleryGroups = data.myAlbums.map((album, index) => ( -
- - { - setActiveIndex({ album: index, media: mediaIndex }) - }} - onFavorite={() => { - refetchNeeded.current.all = true - refetchNeeded.current.favorites = true - }} - activeIndex={activeIndex.album === index ? activeIndex.media : -1} - presenting={presenting === index} - setPresenting={presenting => - setPresenting(presenting ? index : false) - } - loading={loading} - media={album.media} - nextImage={nextImage} - previousImage={previousImage} - /> -
- )) - } - - return ( - <> - - {galleryGroups} - - ) -} - -GalleryGroups.propTypes = { - subPage: PropTypes.string, -} - -export default GalleryGroups diff --git a/ui/src/components/timelineGallery/TimelineGallery.js b/ui/src/components/timelineGallery/TimelineGallery.js index 094cfa29..db6bff13 100644 --- a/ui/src/components/timelineGallery/TimelineGallery.js +++ b/ui/src/components/timelineGallery/TimelineGallery.js @@ -11,7 +11,10 @@ import useScrollPagination from '../../hooks/useScrollPagination' const MY_TIMELINE_QUERY = gql` query myTimeline($onlyFavorites: Boolean, $limit: Int, $offset: Int) { - myTimeline(onlyFavorites: $onlyFavorites, limit: $limit, offset: $offset) { + myTimeline( + onlyFavorites: $onlyFavorites + paginate: { limit: $limit, offset: $offset } + ) { album { id title