From fef7bee038711ffcc671d66f9062b69d0507db1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Galicz?= Date: Fri, 31 Jan 2025 08:20:39 +0100 Subject: [PATCH] chore: dependency update fallout --- errs/artists.go | 3 +- handlers/artist/main.go | 141 ++++++++++------------ migrations/1687801090_initial_settings.go | 16 +++ utils/jsonld/main.go | 71 ++--------- utils/main.go | 4 +- 5 files changed, 94 insertions(+), 141 deletions(-) diff --git a/errs/artists.go b/errs/artists.go index f8fee9cd..09a93e3d 100644 --- a/errs/artists.go +++ b/errs/artists.go @@ -2,4 +2,5 @@ package errs import "errors" -var ErrArtistNotFound = errors.New("artist not found") +var ErrArtistNotFound = errors.New("Artist not found") +var ErrArtworkNotFound = errors.New("Artwork not found") diff --git a/handlers/artist/main.go b/handlers/artist/main.go index fe96b45d..2230173a 100644 --- a/handlers/artist/main.go +++ b/handlers/artist/main.go @@ -1,6 +1,7 @@ package artist import ( + "bytes" "cmp" "context" "encoding/json" @@ -12,14 +13,13 @@ import ( "github.com/blackfyre/wga/assets/templ/dto" "github.com/blackfyre/wga/assets/templ/pages" tmplUtils "github.com/blackfyre/wga/assets/templ/utils" - wgaModels "github.com/blackfyre/wga/models" + "github.com/blackfyre/wga/errs" "github.com/blackfyre/wga/utils" "github.com/blackfyre/wga/utils/jsonld" "github.com/blackfyre/wga/utils/url" "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/core" - "github.com/pocketbase/pocketbase/models" ) const ( @@ -77,24 +77,23 @@ func normalizedBioExcerpt(d BioExcerptDTO) string { // findArtworksByAuthorId retrieves a list of artworks by the given author ID. // It uses the provided PocketBase instance to query the database and returns // a slice of Record pointers and an error, if any. -func findArtworksByAuthorId(app *pocketbase.PocketBase, authorId string) ([]*models.Record, error) { - return app.Dao().FindRecordsByFilter("artworks", "author = '"+authorId+"'", "+title", 100, 0) +func findArtworksByAuthorId(app *pocketbase.PocketBase, authorId string) ([]*core.Record, error) { + return app.FindRecordsByFilter("artworks", "author = '"+authorId+"'", "+title", 100, 0) } // RenderArtistContent renders the content of an artist by generating a DTO (Data Transfer Object) that contains // information about the artist, their works, and JSON-LD metadata. It takes the PocketBase application instance, // the Echo context, and the artist record as input parameters. It returns the DTO representing the artist content // and an error if any occurred during the process. -func RenderArtistContent(app *pocketbase.PocketBase, c echo.Context, artist *models.Record, hxTarget string) (dto.Artist, error) { - id := artist.GetId() +func RenderArtistContent(app *pocketbase.PocketBase, c *core.RequestEvent, artist *core.Record, hxTarget string) (dto.Artist, error) { + id := artist.GetString("id") expectedSlug := utils.GenerateArtistSlug(artist) works, err := findArtworksByAuthorId(app, id) if err != nil { app.Logger().Error("Error finding artworks: ", "error", err.Error()) - - return dto.Artist{}, utils.NotFoundError(c) + return dto.Artist{}, errs.ErrArtistNotFound } schools := utils.RenderSchoolNames(app, artist.GetStringSlice("school")) @@ -119,21 +118,7 @@ func RenderArtistContent(app *pocketbase.PocketBase, c echo.Context, artist *mod HxTarget: hxTarget, } - artistReferenceModel := &wgaModels.Artist{ - Id: artist.GetId(), - Name: artist.GetString("name"), - Slug: artist.GetString("slug"), - Bio: artist.GetString("bio"), - YearOfBirth: artist.GetInt("year_of_birth"), - YearOfDeath: artist.GetInt("year_of_death"), - PlaceOfBirth: artist.GetString("place_of_birth"), - PlaceOfDeath: artist.GetString("place_of_death"), - Published: artist.GetBool("published"), - School: schools, - Profession: artist.GetString("profession"), - } - - JsonLd := jsonld.ArtistJsonLd(artistReferenceModel, c) + JsonLd := jsonld.ArtistJsonLd(artist) marshalled, err := json.Marshal(JsonLd) @@ -145,22 +130,22 @@ func RenderArtistContent(app *pocketbase.PocketBase, c echo.Context, artist *mod for _, w := range works { - artJsonLd := jsonld.ArtworkJsonLd(w, artistReferenceModel, c) + artJsonLd := jsonld.ArtworkJsonLd(w, artist) marshalled, err := json.Marshal(artJsonLd) if err != nil { - app.Logger().Error("Error marshalling artwork jsonld for"+w.GetId(), "error", err.Error()) + app.Logger().Error("Error marshalling artwork jsonld for"+w.GetString("id"), "error", err.Error()) } content.Works = append(content.Works, dto.Image{ - Id: w.GetId(), + Id: w.GetString("id"), Title: w.GetString("title"), Comment: w.GetString("comment"), Technique: w.GetString("technique"), Image: url.GenerateFileUrl("artworks", w.GetString("id"), w.GetString("image"), ""), Thumb: url.GenerateThumbUrl("artworks", w.GetString("id"), w.GetString("image"), "320x240", ""), - Url: c.Request().URL.String() + "/" + utils.Slugify(w.GetString("title")) + "-" + w.GetString("id"), + Url: utils.AssetUrl(utils.Slugify(w.GetString("title")) + "-" + w.GetString("id")), Jsonld: fmt.Sprintf(``, marshalled), HxTarget: hxTarget, }) @@ -175,13 +160,13 @@ func RenderArtistContent(app *pocketbase.PocketBase, c echo.Context, artist *mod // If the artist is not found, it returns a not found error. // If the rendering fails, it returns an error. // It also sets the HX-Push-Url header to enable Htmx push for the artist page. -func processArtist(c echo.Context, app *pocketbase.PocketBase) error { - slug := c.PathParam("name") +func processArtist(c *core.RequestEvent, app *pocketbase.PocketBase) error { + slug := c.Request.PathValue("name") id := utils.ExtractIdFromString(slug) fullUrl := utils.GenerateCurrentPageUrl(c) - artist, err := app.Dao().FindRecordById("artists", id) + artist, err := app.FindRecordById("artists", id) if err != nil { app.Logger().Error("Artist not found: ", slug, err) @@ -204,11 +189,14 @@ func processArtist(c echo.Context, app *pocketbase.PocketBase) error { ctx = tmplUtils.DecorateContext(ctx, tmplUtils.DescriptionKey, content.Bio) ctx = tmplUtils.DecorateContext(ctx, tmplUtils.OgUrlKey, fullUrl) if len(content.Works) > 0 { - ctx = tmplUtils.DecorateContext(ctx, tmplUtils.OgImageKey, c.Scheme()+"://"+c.Request().Host+content.Works[0].Image) + ctx = tmplUtils.DecorateContext(ctx, tmplUtils.OgImageKey, utils.AssetUrl(content.Works[0].Image)) } - c.Response().Header().Set("HX-Push-Url", fullUrl) - err = pages.ArtistPage(content).Render(ctx, c.Response().Writer) + c.Response.Header().Set("HX-Push-Url", fullUrl) + + var buff bytes.Buffer + + err = pages.ArtistPage(content).Render(ctx, &buff) if err != nil { app.Logger().Error("Error rendering artist page", "error", err.Error()) @@ -216,7 +204,7 @@ func processArtist(c echo.Context, app *pocketbase.PocketBase) error { return utils.ServerFaultError(c) } - return nil + return c.HTML(http.StatusOK, buff.String()) } // processArtwork processes the artwork based on the given context and PocketBase application. @@ -229,20 +217,20 @@ func processArtist(c echo.Context, app *pocketbase.PocketBase) error { // - app: The PocketBase application instance. // Returns: // - An error if any error occurs during the processing, or nil if the processing is successful. -func processArtwork(c echo.Context, app *pocketbase.PocketBase) error { - artistSlug := c.PathParam("name") - artworkSlug := c.PathParam("awid") +func processArtwork(c *core.RequestEvent, app *pocketbase.PocketBase) error { + artistSlug := c.Request.PathValue("name") + artworkSlug := c.Request.PathValue("awid") // split the slug on the last dash and use the last part as the artist id artistSlugParts := strings.Split(artistSlug, "-") artistId := artistSlugParts[len(artistSlugParts)-1] - artist, err := app.Dao().FindRecordById("artists", artistId) + artist, err := app.FindRecordById("artists", artistId) // if the artist is not found, return a not found error if err != nil { app.Logger().Error("Artist not found: ", artistSlug, err) - return utils.NotFoundError(c) + return errs.ErrArtistNotFound } // generate the expected slug for the artist @@ -253,11 +241,11 @@ func processArtwork(c echo.Context, app *pocketbase.PocketBase) error { artworkId := artworkSlugParts[len(artworkSlugParts)-1] // find the artwork by id - aw, err := app.Dao().FindRecordById("artworks", artworkId) + aw, err := app.FindRecordById("artworks", artworkId) if err != nil { app.Logger().Error("Error finding artwork: ", artworkSlug, err) - return utils.NotFoundError(c) + return errs.ErrArtworkNotFound } // generate the expected slug for the artwork @@ -269,14 +257,14 @@ func processArtwork(c echo.Context, app *pocketbase.PocketBase) error { } content := dto.Artwork{ - Id: aw.GetId(), + Id: aw.GetString("id"), Title: aw.GetString("title"), Comment: aw.GetString("comment"), Technique: aw.GetString("technique"), Url: url.GenerateFullArtworkUrl(url.ArtworkUrlDTO{ ArtistName: artist.GetString("name"), ArtistId: artist.Id, - ArtworkId: aw.GetId(), + ArtworkId: aw.GetString("id"), ArtworkTitle: aw.GetString("title"), }), Image: dto.Image{ @@ -288,25 +276,25 @@ func processArtwork(c echo.Context, app *pocketbase.PocketBase) error { Thumb: url.GenerateThumbUrl("artworks", aw.GetString("id"), aw.GetString("image"), "320x240", ""), }, Artist: dto.Artist{ - Id: artist.GetId(), + Id: artist.GetString("id"), Name: artist.GetString("name"), Bio: artist.GetString("bio"), Profession: artist.GetString("profession"), Url: url.GenerateArtistUrl(url.ArtistUrlDTO{ - ArtistId: artist.GetId(), + ArtistId: artist.GetString("id"), ArtistName: artist.GetString("name"), }), }, } - fullUrl := c.Scheme() + "://" + c.Request().Host + c.Request().URL.String() + fullUrl := c.Request.URL.Scheme + "://" + c.Request.URL.Host + c.Request.URL.String() school := artist.GetStringSlice("school") var schoolCollector []string for _, s := range school { - r, err := app.Dao().FindRecordById("schools", s) + r, err := app.FindRecordById("schools", s) if err != nil { app.Logger().Error("school not found", "error", err.Error()) @@ -317,24 +305,12 @@ func processArtwork(c echo.Context, app *pocketbase.PocketBase) error { } - jsonLd := jsonld.ArtworkJsonLd(aw, &wgaModels.Artist{ - Id: artist.GetId(), - Name: artist.GetString("name"), - Slug: artist.GetString("slug"), - Bio: artist.GetString("bio"), - YearOfBirth: artist.GetInt("year_of_birth"), - YearOfDeath: artist.GetInt("year_of_death"), - PlaceOfBirth: artist.GetString("place_of_birth"), - PlaceOfDeath: artist.GetString("place_of_death"), - Published: artist.GetBool("published"), - School: strings.Join(schoolCollector, ", "), - Profession: artist.GetString("profession"), - }, c) + jsonLd := jsonld.ArtworkJsonLd(aw, artist) marshalled, err := json.Marshal(jsonLd) if err != nil { - app.Logger().Error("Error marshalling artwork jsonld for"+aw.GetId(), "error", err.Error()) + app.Logger().Error("Error marshalling artwork jsonld for"+aw.GetString("id"), "error", err.Error()) } content.Jsonld = fmt.Sprintf(``, marshalled) @@ -342,49 +318,52 @@ func processArtwork(c echo.Context, app *pocketbase.PocketBase) error { ctx := tmplUtils.DecorateContext(context.Background(), tmplUtils.TitleKey, fmt.Sprintf("%s - %s", content.Title, content.Artist.Name)) ctx = tmplUtils.DecorateContext(ctx, tmplUtils.DescriptionKey, content.Comment) ctx = tmplUtils.DecorateContext(ctx, tmplUtils.CanonicalUrlKey, fullUrl) - ctx = tmplUtils.DecorateContext(ctx, tmplUtils.OgImageKey, c.Scheme()+"://"+c.Request().Host+content.Image.Image) + ctx = tmplUtils.DecorateContext(ctx, tmplUtils.OgImageKey, utils.AssetUrl(content.Image.Image)) + + c.Response.Header().Set("HX-Push-Url", fullUrl) - c.Response().Header().Set("HX-Push-Url", fullUrl) - err = pages.ArtworkPage(content).Render(ctx, c.Response().Writer) + var buff bytes.Buffer + + err = pages.ArtworkPage(content).Render(ctx, &buff) if err != nil { app.Logger().Error("Error rendering artwork page", "error", err.Error()) return c.String(http.StatusInternalServerError, "failed to render response template") } - return nil + return c.HTML(http.StatusOK, buff.String()) } -func RenderArtworkContent(app *pocketbase.PocketBase, c echo.Context, artwork *models.Record, hxTarget string) (dto.Artwork, error) { +func RenderArtworkContent(app *pocketbase.PocketBase, c echo.Context, artwork *core.Record, hxTarget string) (dto.Artwork, error) { artistId := cmp.Or(artwork.GetStringSlice("author")[0], "") var artworkUrl string - var artist *models.Record + var artist *core.Record if artistId != "" { - artist, err := app.Dao().FindRecordById("Artists", artistId) + artist, err := app.FindRecordById("Artists", artistId) if err != nil { - app.Logger().Error("Error finding artist: "+artistId, "error", err.Error()) + app.Logger().Error(fmt.Sprintf("Error finding artist (%s) related to artwork (%s)", artistId, &artwork.Id), "error", err.Error()) } artworkUrl = url.GenerateFullArtworkUrl(url.ArtworkUrlDTO{ ArtistName: artist.GetString("name"), - ArtistId: artist.GetId(), - ArtworkId: artwork.GetId(), + ArtistId: artist.GetString("id"), + ArtworkId: artwork.GetString("id"), ArtworkTitle: artwork.GetString("title"), }) } else { artworkUrl = url.GenerateArtworkUrl(url.ArtworkUrlDTO{ - ArtworkId: artwork.GetId(), + ArtworkId: artwork.GetString("id"), ArtworkTitle: artwork.GetString("title"), }) } content := dto.Artwork{ - Id: artwork.GetId(), + Id: artwork.GetString("id"), Title: artwork.GetString("title"), Comment: artwork.GetString("comment"), Technique: artwork.GetString("technique"), @@ -402,12 +381,12 @@ func RenderArtworkContent(app *pocketbase.PocketBase, c echo.Context, artwork *m // Check if artist pointer is nil if artist != nil { content.Artist = dto.Artist{ - Id: artist.GetId(), + Id: artist.GetString("id"), Name: artist.GetString("name"), Bio: artist.GetString("bio"), Profession: artist.GetString("profession"), Url: url.GenerateArtistUrl(url.ArtistUrlDTO{ - ArtistId: artist.GetId(), + ArtistId: artist.GetString("id"), ArtistName: artist.GetString("name"), }), } @@ -423,14 +402,16 @@ func RenderArtworkContent(app *pocketbase.PocketBase, c echo.Context, artwork *m // It also caches the HTML response for each route to improve performance. func RegisterHandlers(app *pocketbase.PocketBase) { - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + app.OnServe().BindFunc(func(se *core.ServeEvent) error { + + ag := se.Router.Group("artists") - e.Router.GET("artists/:name", func(c echo.Context) error { - return processArtist(c, app) + ag.GET("/:name", func(e *core.RequestEvent) error { + return processArtist(e, app) }) - e.Router.GET("artists/:name/:awid", func(c echo.Context) error { - return processArtwork(c, app) + ag.GET("/:name/:awid", func(e *core.RequestEvent) error { + return processArtwork(e, app) }) return nil }) diff --git a/migrations/1687801090_initial_settings.go b/migrations/1687801090_initial_settings.go index 4922f76d..1defd88a 100644 --- a/migrations/1687801090_initial_settings.go +++ b/migrations/1687801090_initial_settings.go @@ -40,3 +40,19 @@ func init() { return app.Save(settings) }, nil) } + +func deleteCollection(app core.App, name string) error { + collection, err := app.FindCollectionByNameOrId(name) + + if err != nil { + return nil + } + + err = app.Delete(collection) + + if err != nil { + app.Logger().Error("Error deleting collection %s: %v", name, err) + } + + return nil +} diff --git a/utils/jsonld/main.go b/utils/jsonld/main.go index 4f94810c..e2365391 100644 --- a/utils/jsonld/main.go +++ b/utils/jsonld/main.go @@ -3,64 +3,19 @@ package jsonld import ( "fmt" - wgaModels "github.com/blackfyre/wga/models" "github.com/blackfyre/wga/utils" - "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase/core" - "github.com/pocketbase/pocketbase/models" ) -// generateArtistJsonLdContent generates a JSON-LD content for an artist record. -// It takes a pointer to a models.Record and an echo.Context as input and returns a map[string]any. -// The returned map contains the JSON-LD content for the artist record, including the artist's name, URL, profession, -// birth and death dates, and birth and death places (if available). -// Deprecated: Use ArtistJsonLd instead. -func GenerateArtistJsonLdContent(r *core.Record, c echo.Context) map[string]any { - - fullUrl := c.Scheme() + "://" + c.Request().Host + "/artists/" + r.Slug + "-" + r.Id - - d := map[string]any{ - "@context": "https://schema.org", - "@type": "Person", - "name": r.Name, - "url": fullUrl, - "hasOccupation": r.Profession, - } - - if r.YearOfBirth > 0 { - d["birthDate"] = r.YearOfBirth - } - - if r.YearOfDeath > 0 { - d["deathDate"] = r.YearOfDeath - } - - if r.PlaceOfBirth != "" { - d["birthPlace"] = map[string]string{ - "@type": "Place", - "name": r.PlaceOfBirth, - } - } - - if r.PlaceOfDeath != "" { - d["deathPlace"] = map[string]string{ - "@type": "Place", - "name": r.PlaceOfDeath, - } - } - - return d -} - // ArtistJsonLd generates a JSON-LD representation of an artist. // It takes an instance of wgaModels.Artist and an echo.Context as input. // It returns a Person struct representing the artist in JSON-LD format. -func ArtistJsonLd(r *core.Record, c echo.Context) Person { +func ArtistJsonLd(r *core.Record) Person { return newPerson(Person{ Name: r.GetString("name"), - Url: c.Scheme() + "://" + c.Request().Host + "/artists/" + r.GetString("slug") + "-" + r.GetString("id"), - BirthDate: fmt.Sprint(r.GetString("yob")), - DeathDate: fmt.Sprint(r.GetString("yod")), + Url: utils.AssetUrl("/artists/" + r.GetString("slug") + "-" + r.GetString("id")), + BirthDate: fmt.Sprint(r.GetString("year_of_birth")), + DeathDate: fmt.Sprint(r.GetString("year_of_death")), PlaceOfBirth: newPlace(Place{ Name: r.GetString("place_of_birth"), }), @@ -76,7 +31,7 @@ func ArtistJsonLd(r *core.Record, c echo.Context) Person { // generateVisualArtworkJsonLdContent generates a map containing JSON-LD content for a visual artwork record. // It takes a models.Record pointer and an echo.Context as input and returns a map[string]any. -func GenerateVisualArtworkJsonLdContent(r *models.Record, c echo.Context) map[string]any { +func GenerateVisualArtworkJsonLdContent(r *core.Record) map[string]any { d := map[string]any{ "@context": "https://schema.org", @@ -89,16 +44,16 @@ func GenerateVisualArtworkJsonLdContent(r *models.Record, c echo.Context) map[st return d } -func ArtworkJsonLd(r *models.Record, a *wgaModels.Artist, c echo.Context) VisualArtwork { +func ArtworkJsonLd(artWork *core.Record, artist *core.Record) VisualArtwork { return VisualArtwork{ - Name: r.GetString("name"), - Description: utils.StrippedHTML(r.GetString("comment")), - Artform: r.GetString("technique"), - Url: c.Scheme() + "://" + c.Request().Host + "/artworks/" + r.GetString("slug") + "-" + r.GetId(), - Artist: ArtistJsonLd(a, c), - ArtMedium: r.GetString("medium"), + Name: artWork.GetString("name"), + Description: utils.StrippedHTML(artWork.GetString("comment")), + Artform: artWork.GetString("technique"), + Url: utils.AssetUrl("/artworks/" + artWork.GetString("slug") + "-" + artWork.GetString("id")), + Artist: ArtistJsonLd(artist), + ArtMedium: artWork.GetString("medium"), Image: ImageObject{ - Image: c.Scheme() + "://" + c.Request().Host + "/images/" + r.GetString("image"), + Image: utils.AssetUrl("/images/" + artWork.GetString("image")), }, } diff --git a/utils/main.go b/utils/main.go index 0455ac15..4acddd35 100644 --- a/utils/main.go +++ b/utils/main.go @@ -325,7 +325,7 @@ func NormalizedBirthDeathActivity(record *models.Record) string { return fmt.Sprintf("%d-%d", Start, End) } -func GenerateArtistSlug(artist *models.Record) string { +func GenerateArtistSlug(artist *core.Record) string { if artist == nil { return "" } @@ -337,7 +337,7 @@ func GenerateCurrentPageUrl(c *core.RequestEvent) string { return "" } - return c.Request.Scheme + "://" + c.Request.Host + c.Request.URL.String() + return c.Request.URL.Scheme + "://" + c.Request.Host + c.Request.URL.String() } // renderSchoolNames takes an instance of PocketBase and a slice of school IDs,