mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 09:05:30 +00:00
+logging audit +imageprovider
This commit is contained in:
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
FROM golang:1.25
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN go build
|
||||||
|
EXPOSE 8082
|
||||||
|
|
||||||
|
CMD ["./lenz-web"]
|
||||||
|
|
||||||
32
app/kgpz.go
32
app/kgpz.go
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/geonames"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/geonames"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/gnd"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/gnd"
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/pictures"
|
||||||
searchprovider "github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/search"
|
searchprovider "github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/search"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
||||||
@@ -64,6 +65,7 @@ type KGPZ struct {
|
|||||||
Repo *providers.GitProvider
|
Repo *providers.GitProvider
|
||||||
GND *gnd.GNDProvider
|
GND *gnd.GNDProvider
|
||||||
Geonames *geonames.GeonamesProvider
|
Geonames *geonames.GeonamesProvider
|
||||||
|
Pictures *pictures.PicturesProvider
|
||||||
Library *xmlmodels.Library
|
Library *xmlmodels.Library
|
||||||
Search *searchprovider.SearchProvider
|
Search *searchprovider.SearchProvider
|
||||||
|
|
||||||
@@ -98,14 +100,15 @@ func (k *KGPZ) Pre(srv *fiber.App) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serve newspaper pictures from pictures directory
|
// Serve newspaper pictures from pictures directory
|
||||||
if _, err := os.Stat("pictures"); err == nil {
|
picturesPath := k.Config.Config.PicturesPath
|
||||||
picturesFS := os.DirFS("pictures")
|
if _, err := os.Stat(picturesPath); err == nil {
|
||||||
|
picturesFS := os.DirFS(picturesPath)
|
||||||
srv.Use(PICTURES_PREFIX, compress.New(compress.Config{
|
srv.Use(PICTURES_PREFIX, compress.New(compress.Config{
|
||||||
Level: compress.LevelBestSpeed,
|
Level: compress.LevelBestSpeed,
|
||||||
}), etag.New(), helpers.StaticHandler(&picturesFS))
|
}), etag.New(), helpers.StaticHandler(&picturesFS))
|
||||||
logging.Info("Serving newspaper pictures from pictures/ directory.")
|
logging.Info("Serving newspaper pictures from " + picturesPath + " directory.")
|
||||||
} else {
|
} else {
|
||||||
logging.Info("Pictures folder not found. Skipping picture serving.")
|
logging.Info("Pictures folder not found at " + picturesPath + ". Skipping picture serving.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -132,6 +135,9 @@ func (k *KGPZ) Init() error {
|
|||||||
if err := k.initGeonames(); err != nil {
|
if err := k.initGeonames(); err != nil {
|
||||||
logging.Error(err, "Error reading Geonames-Cache. Continuing.")
|
logging.Error(err, "Error reading Geonames-Cache. Continuing.")
|
||||||
}
|
}
|
||||||
|
if err := k.initPictures(); err != nil {
|
||||||
|
logging.Error(err, "Error scanning pictures directory. Continuing without pictures.")
|
||||||
|
}
|
||||||
|
|
||||||
if sp, err := searchprovider.NewSearchProvider(filepath.Join(k.Config.Config.BaseDIR, k.Config.SearchPath)); err != nil {
|
if sp, err := searchprovider.NewSearchProvider(filepath.Join(k.Config.Config.BaseDIR, k.Config.SearchPath)); err != nil {
|
||||||
logging.Error(err, "Error initializing SearchProvider. Continuing without Search.")
|
logging.Error(err, "Error initializing SearchProvider. Continuing without Search.")
|
||||||
@@ -162,6 +168,11 @@ func (k *KGPZ) initGeonames() error {
|
|||||||
return k.Geonames.ReadCache(filepath.Join(k.Config.BaseDIR, k.Config.GeoPath))
|
return k.Geonames.ReadCache(filepath.Join(k.Config.BaseDIR, k.Config.GeoPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *KGPZ) initPictures() error {
|
||||||
|
k.Pictures = pictures.NewPicturesProvider()
|
||||||
|
return k.Pictures.Scan(k.Config.Config.PicturesPath)
|
||||||
|
}
|
||||||
|
|
||||||
func (k *KGPZ) Routes(srv *fiber.App) error {
|
func (k *KGPZ) Routes(srv *fiber.App) error {
|
||||||
srv.Get("/", func(c *fiber.Ctx) error {
|
srv.Get("/", func(c *fiber.Ctx) error {
|
||||||
c.Redirect(INDEX_URL)
|
c.Redirect(INDEX_URL)
|
||||||
@@ -174,8 +185,8 @@ func (k *KGPZ) Routes(srv *fiber.App) error {
|
|||||||
srv.Get(PLACE_OVERVIEW_URL, controllers.GetPlace(k.Library, k.Geonames))
|
srv.Get(PLACE_OVERVIEW_URL, controllers.GetPlace(k.Library, k.Geonames))
|
||||||
srv.Get(CATEGORY_OVERVIEW_URL, controllers.GetCategory(k.Library))
|
srv.Get(CATEGORY_OVERVIEW_URL, controllers.GetCategory(k.Library))
|
||||||
srv.Get(AGENTS_OVERVIEW_URL, controllers.GetAgents(k.Library))
|
srv.Get(AGENTS_OVERVIEW_URL, controllers.GetAgents(k.Library))
|
||||||
srv.Get(PIECE_PAGE_URL, controllers.GetPieceWithPage(k.Library))
|
srv.Get(PIECE_PAGE_URL, controllers.GetPieceWithPage(k.Library, k.Pictures))
|
||||||
srv.Get(PIECE_URL, controllers.GetPiece(k.Library))
|
srv.Get(PIECE_URL, controllers.GetPiece(k.Library, k.Pictures))
|
||||||
|
|
||||||
// Page jump routes for direct navigation
|
// Page jump routes for direct navigation
|
||||||
srv.Get(PAGE_JUMP_URL, controllers.GetPageJump(k.Library))
|
srv.Get(PAGE_JUMP_URL, controllers.GetPageJump(k.Library))
|
||||||
@@ -188,8 +199,8 @@ func (k *KGPZ) Routes(srv *fiber.App) error {
|
|||||||
// This applies to all paths with two or three segments without a static prefix:
|
// This applies to all paths with two or three segments without a static prefix:
|
||||||
// Prob better to do /ausgabe/:year/:issue/:page? and /jahrgang/:year? respectively.
|
// Prob better to do /ausgabe/:year/:issue/:page? and /jahrgang/:year? respectively.
|
||||||
srv.Get(YEAR_OVERVIEW_URL, controllers.GetYear(k.Library))
|
srv.Get(YEAR_OVERVIEW_URL, controllers.GetYear(k.Library))
|
||||||
srv.Get(ISSSUE_URL, controllers.GetIssue(k.Library))
|
srv.Get(ISSSUE_URL, controllers.GetIssue(k.Library, k.Pictures))
|
||||||
srv.Get(ADDITIONS_URL, controllers.GetIssue(k.Library))
|
srv.Get(ADDITIONS_URL, controllers.GetIssue(k.Library, k.Pictures))
|
||||||
|
|
||||||
srv.Get(EDITION_URL, controllers.Get(EDITION_URL))
|
srv.Get(EDITION_URL, controllers.Get(EDITION_URL))
|
||||||
srv.Get(PRIVACY_URL, controllers.Get(PRIVACY_URL))
|
srv.Get(PRIVACY_URL, controllers.Get(PRIVACY_URL))
|
||||||
@@ -621,6 +632,11 @@ func (k *KGPZ) Pull() {
|
|||||||
k.Serialize()
|
k.Serialize()
|
||||||
k.EnrichAndRebuildIndex()
|
k.EnrichAndRebuildIndex()
|
||||||
|
|
||||||
|
// Rescan pictures after pull
|
||||||
|
if err := k.initPictures(); err != nil {
|
||||||
|
logging.Error(err, "Error rescanning pictures directory after pull.")
|
||||||
|
}
|
||||||
|
|
||||||
// Notify about git data update
|
// Notify about git data update
|
||||||
if k.gitUpdateCallback != nil {
|
if k.gitUpdateCallback != nil {
|
||||||
k.gitUpdateCallback(
|
k.gitUpdateCallback(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/pictures"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/viewmodels"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/viewmodels"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@@ -16,7 +17,7 @@ const (
|
|||||||
MAXYEAR = 1779
|
MAXYEAR = 1779
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetIssue(kgpz *xmlmodels.Library) fiber.Handler {
|
func GetIssue(kgpz *xmlmodels.Library, pics *pictures.PicturesProvider) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
y := c.Params("year")
|
y := c.Params("year")
|
||||||
yi, err := strconv.Atoi(y)
|
yi, err := strconv.Atoi(y)
|
||||||
@@ -67,7 +68,7 @@ func GetIssue(kgpz *xmlmodels.Library) fiber.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issue, err := viewmodels.NewSingleIssueView(yi, di, kgpz)
|
issue, err := viewmodels.NewSingleIssueView(yi, di, kgpz, pics)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Error(err, "Issue could not be found")
|
logging.Error(err, "Issue could not be found")
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func GetYear(kgpz *xmlmodels.Library) fiber.Handler {
|
|||||||
|
|
||||||
view, err := viewmodels.YearView(yi, kgpz)
|
view, err := viewmodels.YearView(yi, kgpz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.ErrorDebug(err, "Keine Ausgaben für das Jahr "+y)
|
logging.Error(err, "Keine Ausgaben für das Jahr "+y)
|
||||||
return c.SendStatus(fiber.StatusNotFound)
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/pictures"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/viewmodels"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/viewmodels"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPiece(kgpz *xmlmodels.Library) fiber.Handler {
|
func GetPiece(kgpz *xmlmodels.Library, pics *pictures.PicturesProvider) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
id := c.Params("id")
|
id := c.Params("id")
|
||||||
if id == "" {
|
if id == "" {
|
||||||
@@ -25,7 +26,7 @@ func GetPiece(kgpz *xmlmodels.Library) fiber.Handler {
|
|||||||
return c.SendStatus(fiber.StatusNotFound)
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
pieceView, err := viewmodels.NewPieceView(*piece, kgpz)
|
pieceView, err := viewmodels.NewPieceView(*piece, kgpz, pics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Error(err, "Piece view could not be created")
|
logging.Error(err, "Piece view could not be created")
|
||||||
return c.SendStatus(fiber.StatusInternalServerError)
|
return c.SendStatus(fiber.StatusInternalServerError)
|
||||||
@@ -36,7 +37,7 @@ func GetPiece(kgpz *xmlmodels.Library) fiber.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPieceWithPage handles piece URLs with optional page parameter: /beitrag/:id/:page?
|
// GetPieceWithPage handles piece URLs with optional page parameter: /beitrag/:id/:page?
|
||||||
func GetPieceWithPage(kgpz *xmlmodels.Library) fiber.Handler {
|
func GetPieceWithPage(kgpz *xmlmodels.Library, pics *pictures.PicturesProvider) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
id := c.Params("id")
|
id := c.Params("id")
|
||||||
if id == "" {
|
if id == "" {
|
||||||
@@ -86,7 +87,7 @@ func GetPieceWithPage(kgpz *xmlmodels.Library) fiber.Handler {
|
|||||||
return c.SendStatus(fiber.StatusNotFound)
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
pieceView, err := viewmodels.NewPieceView(*piece, kgpz)
|
pieceView, err := viewmodels.NewPieceView(*piece, kgpz, pics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Error(err, "Piece view could not be created")
|
logging.Error(err, "Piece view could not be created")
|
||||||
return c.SendStatus(fiber.StatusInternalServerError)
|
return c.SendStatus(fiber.StatusInternalServerError)
|
||||||
|
|||||||
@@ -51,20 +51,6 @@ func Error(err error, msg ...string) {
|
|||||||
slog.Error(err.Error())
|
slog.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrorDebug(err error, msg ...string) {
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(msg) > 0 {
|
|
||||||
for _, m := range msg {
|
|
||||||
slog.Debug(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slog.Debug(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
func Info(msg ...string) {
|
func Info(msg ...string) {
|
||||||
if len(msg) > 0 {
|
if len(msg) > 0 {
|
||||||
for _, m := range msg {
|
for _, m := range msg {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const (
|
|||||||
DEFAULT_GEO_CACHE_DIR = "geo"
|
DEFAULT_GEO_CACHE_DIR = "geo"
|
||||||
DEFAULT_SEARCH_CACHE_DIR = "search"
|
DEFAULT_SEARCH_CACHE_DIR = "search"
|
||||||
DEFAULT_IMG_DIR = "data_bilder"
|
DEFAULT_IMG_DIR = "data_bilder"
|
||||||
|
DEFAULT_PICTURES_DIR = "pictures"
|
||||||
|
|
||||||
DEFAULT_PORT = "8080"
|
DEFAULT_PORT = "8080"
|
||||||
DEFAULT_ADDR = "localhost"
|
DEFAULT_ADDR = "localhost"
|
||||||
@@ -43,6 +44,7 @@ type Config struct {
|
|||||||
GeoPath string `json:"geo_path" envconfig:"GEO_PATH"`
|
GeoPath string `json:"geo_path" envconfig:"GEO_PATH"`
|
||||||
SearchPath string `json:"search_path" envconfig:"SEARCH_PATH"`
|
SearchPath string `json:"search_path" envconfig:"SEARCH_PATH"`
|
||||||
ImgPath string `json:"img_path" envconfig:"IMG_PATH"`
|
ImgPath string `json:"img_path" envconfig:"IMG_PATH"`
|
||||||
|
PicturesPath string `json:"pictures_path" envconfig:"PICTURES_PATH"`
|
||||||
WebHookEndpoint string `json:"webhook_endpoint" envconfig:"WEBHOOK_ENDPOINT"`
|
WebHookEndpoint string `json:"webhook_endpoint" envconfig:"WEBHOOK_ENDPOINT"`
|
||||||
WebHookSecret string `json:"webhook_secret" envconfig:"WEBHOOK_SECRET"`
|
WebHookSecret string `json:"webhook_secret" envconfig:"WEBHOOK_SECRET"`
|
||||||
Debug bool `json:"debug" envconfig:"DEBUG"`
|
Debug bool `json:"debug" envconfig:"DEBUG"`
|
||||||
@@ -134,6 +136,10 @@ func readDefaults(cfg *Config) *Config {
|
|||||||
cfg.SearchPath = DEFAULT_SEARCH_CACHE_DIR
|
cfg.SearchPath = DEFAULT_SEARCH_CACHE_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(cfg.PicturesPath) == "" {
|
||||||
|
cfg.PicturesPath = DEFAULT_PICTURES_DIR
|
||||||
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ package viewmodels
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/functions"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/functions"
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/pictures"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,32 +52,15 @@ type IssuePage struct {
|
|||||||
PageIcon string // Icon type: "first", "last", "even", "odd"
|
PageIcon string // Icon type: "first", "last", "even", "odd"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use pictures.ImageFile from provider instead
|
||||||
|
type ImageFile = pictures.ImageFile
|
||||||
|
|
||||||
type IssueImages struct {
|
type IssueImages struct {
|
||||||
MainPages []IssuePage
|
MainPages []IssuePage
|
||||||
AdditionalPages map[int][]IssuePage // Beilage number -> pages
|
AdditionalPages map[int][]IssuePage // Beilage number -> pages
|
||||||
HasImages bool
|
HasImages bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageFile struct {
|
|
||||||
Year int
|
|
||||||
Issue int
|
|
||||||
Page int
|
|
||||||
IsBeilage bool
|
|
||||||
BeilageNo int
|
|
||||||
Filename string
|
|
||||||
Path string // Primary path (prefers WebP over JPEG)
|
|
||||||
PreviewPath string // Path to compressed WebP version for layout views
|
|
||||||
JpegPath string // Path to JPEG version (for download button)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ImageRegistry struct {
|
|
||||||
Files []ImageFile
|
|
||||||
ByYearIssue map[string][]ImageFile // "year-issue" -> files
|
|
||||||
ByYearPage map[string]ImageFile // "year-page" -> file
|
|
||||||
}
|
|
||||||
|
|
||||||
var imageRegistry *ImageRegistry
|
|
||||||
|
|
||||||
// TODO: Next & Prev
|
// TODO: Next & Prev
|
||||||
type IssueVM struct {
|
type IssueVM struct {
|
||||||
xmlmodels.Issue
|
xmlmodels.Issue
|
||||||
@@ -90,7 +72,7 @@ type IssueVM struct {
|
|||||||
HasBeilageButton bool // Whether to show beilage navigation button
|
HasBeilageButton bool // Whether to show beilage navigation button
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSingleIssueView(y, no int, lib *xmlmodels.Library) (*IssueVM, error) {
|
func NewSingleIssueView(y, no int, lib *xmlmodels.Library, pics *pictures.PicturesProvider) (*IssueVM, error) {
|
||||||
lib.Issues.Lock()
|
lib.Issues.Lock()
|
||||||
var issue *xmlmodels.Issue = nil
|
var issue *xmlmodels.Issue = nil
|
||||||
var next *xmlmodels.Issue = nil
|
var next *xmlmodels.Issue = nil
|
||||||
@@ -123,7 +105,7 @@ func NewSingleIssueView(y, no int, lib *xmlmodels.Library) (*IssueVM, error) {
|
|||||||
slices.Sort(ppi.Pages)
|
slices.Sort(ppi.Pages)
|
||||||
slices.Sort(ppa.Pages)
|
slices.Sort(ppa.Pages)
|
||||||
|
|
||||||
images, err := LoadIssueImages(*issue)
|
images, err := LoadIssueImages(*issue, pics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -152,7 +134,7 @@ func PiecesForIssue(lib *xmlmodels.Library, issue xmlmodels.Issue) (PiecesByPage
|
|||||||
if issueRef.Nr == issue.Number.No && issueRef.When.Year == year {
|
if issueRef.Nr == issue.Number.No && issueRef.When.Year == year {
|
||||||
// DEBUG: Log piece details for specific issue
|
// DEBUG: Log piece details for specific issue
|
||||||
if year == 1771 && issue.Number.No == 29 {
|
if year == 1771 && issue.Number.No == 29 {
|
||||||
fmt.Printf("DEBUG PiecesForIssue: Piece ID=%s, Von=%d, Bis=%d, Beilage=%d\n", piece.Identifier.ID, issueRef.Von, issueRef.Bis, issueRef.Beilage)
|
logging.Debug(fmt.Sprintf("PiecesForIssue: Piece ID=%s, Von=%d, Bis=%d, Beilage=%d", piece.Identifier.ID, issueRef.Von, issueRef.Bis, issueRef.Beilage))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add main entry on starting page
|
// Add main entry on starting page
|
||||||
@@ -477,12 +459,7 @@ func determinePageIconForLayout(pageNum int) string {
|
|||||||
return "odd"
|
return "odd"
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadIssueImages(issue xmlmodels.Issue) (IssueImages, error) {
|
func LoadIssueImages(issue xmlmodels.Issue, pics *pictures.PicturesProvider) (IssueImages, error) {
|
||||||
// Initialize registry if not already done
|
|
||||||
if err := initImageRegistry(); err != nil {
|
|
||||||
return IssueImages{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
year := issue.Datum.When.Year
|
year := issue.Datum.When.Year
|
||||||
issueNo := issue.Number.No
|
issueNo := issue.Number.No
|
||||||
|
|
||||||
@@ -493,12 +470,11 @@ func LoadIssueImages(issue xmlmodels.Issue) (IssueImages, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all image files for this year-issue combination
|
// Get all image files for this year-issue combination
|
||||||
yearIssueKey := fmt.Sprintf("%d-%d", year, issueNo)
|
issueFiles := pics.GetByYearIssue(year, issueNo)
|
||||||
issueFiles := imageRegistry.ByYearIssue[yearIssueKey]
|
|
||||||
|
|
||||||
// Separate main pages from beilage pages
|
// Separate main pages from beilage pages
|
||||||
var mainFiles []ImageFile
|
var mainFiles []pictures.ImageFile
|
||||||
var beilageFiles []ImageFile
|
var beilageFiles []pictures.ImageFile
|
||||||
|
|
||||||
for _, file := range issueFiles {
|
for _, file := range issueFiles {
|
||||||
if file.IsBeilage {
|
if file.IsBeilage {
|
||||||
@@ -510,12 +486,13 @@ func LoadIssueImages(issue xmlmodels.Issue) (IssueImages, error) {
|
|||||||
|
|
||||||
// Create main pages - match with issue page range
|
// Create main pages - match with issue page range
|
||||||
for page := issue.Von; page <= issue.Bis; page++ {
|
for page := issue.Von; page <= issue.Bis; page++ {
|
||||||
var foundFile *ImageFile
|
var foundFile *pictures.ImageFile
|
||||||
|
|
||||||
// Look for a file that has this page number
|
// Look for a file that has this page number
|
||||||
for _, file := range mainFiles {
|
for _, file := range mainFiles {
|
||||||
if file.Page == page {
|
if file.Page == page {
|
||||||
foundFile = &file
|
fileCopy := file
|
||||||
|
foundFile = &fileCopy
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,161 +568,3 @@ func LoadIssueImages(issue xmlmodels.Issue) (IssueImages, error) {
|
|||||||
|
|
||||||
return images, nil
|
return images, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initImageRegistry() error {
|
|
||||||
if imageRegistry != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
imageRegistry = &ImageRegistry{
|
|
||||||
Files: make([]ImageFile, 0),
|
|
||||||
ByYearIssue: make(map[string][]ImageFile),
|
|
||||||
ByYearPage: make(map[string]ImageFile),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temporary map to collect all files by their base name (year-issue-page)
|
|
||||||
tempFiles := make(map[string]*ImageFile)
|
|
||||||
|
|
||||||
err := filepath.Walk("pictures", func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
filename := info.Name()
|
|
||||||
filenamelower := strings.ToLower(filename)
|
|
||||||
|
|
||||||
// Only process .jpg and .webp files (but skip preview files)
|
|
||||||
var nameWithoutExt string
|
|
||||||
var isWebP bool
|
|
||||||
|
|
||||||
if strings.HasSuffix(filenamelower, ".jpg") {
|
|
||||||
nameWithoutExt = strings.TrimSuffix(filename, ".jpg")
|
|
||||||
isWebP = false
|
|
||||||
} else if strings.HasSuffix(filenamelower, ".webp") && !strings.HasSuffix(filenamelower, "-preview.webp") {
|
|
||||||
nameWithoutExt = strings.TrimSuffix(filename, ".webp")
|
|
||||||
isWebP = true
|
|
||||||
} else {
|
|
||||||
return nil // Skip non-image files and preview files
|
|
||||||
}
|
|
||||||
|
|
||||||
parts := strings.Split(nameWithoutExt, "-")
|
|
||||||
|
|
||||||
// Need at least 3 parts: year-issue-page
|
|
||||||
if len(parts) != 3 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse year
|
|
||||||
year, err := strconv.Atoi(strings.TrimSpace(parts[0]))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if second part ends with 'b' (beilage)
|
|
||||||
issueStr := strings.TrimSpace(parts[1])
|
|
||||||
isBeilage := strings.HasSuffix(issueStr, "b")
|
|
||||||
|
|
||||||
if isBeilage {
|
|
||||||
issueStr = strings.TrimSuffix(issueStr, "b")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse issue number
|
|
||||||
issue, err := strconv.Atoi(issueStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse page number
|
|
||||||
page, err := strconv.Atoi(strings.TrimSpace(parts[2]))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create unique key for this image (handles both regular and beilage)
|
|
||||||
var uniqueKey string
|
|
||||||
if isBeilage {
|
|
||||||
uniqueKey = fmt.Sprintf("%d-%db-%d", year, issue, page)
|
|
||||||
} else {
|
|
||||||
uniqueKey = fmt.Sprintf("%d-%d-%d", year, issue, page)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get or create the ImageFile entry
|
|
||||||
imageFile, exists := tempFiles[uniqueKey]
|
|
||||||
if !exists {
|
|
||||||
imageFile = &ImageFile{
|
|
||||||
Year: year,
|
|
||||||
Issue: issue,
|
|
||||||
Page: page,
|
|
||||||
IsBeilage: isBeilage,
|
|
||||||
BeilageNo: 1, // Default beilage number
|
|
||||||
}
|
|
||||||
tempFiles[uniqueKey] = imageFile
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set paths based on file type
|
|
||||||
currentPath := fmt.Sprintf("/static/pictures/%s", path[9:]) // Remove "pictures/" prefix
|
|
||||||
if isWebP {
|
|
||||||
// WebP is the primary path for single page viewer
|
|
||||||
imageFile.Path = currentPath
|
|
||||||
imageFile.Filename = filename
|
|
||||||
} else {
|
|
||||||
// JPEG is the fallback path for download
|
|
||||||
imageFile.JpegPath = currentPath
|
|
||||||
// If no WebP path is set yet, use JPEG as primary
|
|
||||||
if imageFile.Path == "" {
|
|
||||||
imageFile.Path = currentPath
|
|
||||||
imageFile.Filename = filename
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second pass: set PreviewPath for each ImageFile by checking for preview files
|
|
||||||
for _, imageFile := range tempFiles {
|
|
||||||
// Extract the base name from the filename to preserve original format
|
|
||||||
baseNameWithExt := imageFile.Filename
|
|
||||||
var baseName string
|
|
||||||
|
|
||||||
// Remove extension to get base name
|
|
||||||
if strings.HasSuffix(strings.ToLower(baseNameWithExt), ".webp") {
|
|
||||||
baseName = strings.TrimSuffix(baseNameWithExt, ".webp")
|
|
||||||
} else if strings.HasSuffix(strings.ToLower(baseNameWithExt), ".jpg") {
|
|
||||||
baseName = strings.TrimSuffix(baseNameWithExt, ".jpg")
|
|
||||||
} else {
|
|
||||||
baseName = baseNameWithExt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate preview filename using the original base name format
|
|
||||||
previewFilename := baseName + "-preview.webp"
|
|
||||||
|
|
||||||
// Check if preview file exists
|
|
||||||
previewFullPath := filepath.Join("pictures", fmt.Sprintf("%d", imageFile.Year), previewFilename)
|
|
||||||
if _, err := os.Stat(previewFullPath); err == nil {
|
|
||||||
imageFile.PreviewPath = fmt.Sprintf("/static/pictures/%d/%s", imageFile.Year, previewFilename)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert temp map to final registry structures
|
|
||||||
for _, imageFile := range tempFiles {
|
|
||||||
imageRegistry.Files = append(imageRegistry.Files, *imageFile)
|
|
||||||
|
|
||||||
yearIssueKey := fmt.Sprintf("%d-%d", imageFile.Year, imageFile.Issue)
|
|
||||||
imageRegistry.ByYearIssue[yearIssueKey] = append(imageRegistry.ByYearIssue[yearIssueKey], *imageFile)
|
|
||||||
|
|
||||||
if !imageFile.IsBeilage {
|
|
||||||
yearPageKey := fmt.Sprintf("%d-%d", imageFile.Year, imageFile.Page)
|
|
||||||
imageRegistry.ByYearPage[yearPageKey] = *imageFile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
||||||
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/pictures"
|
||||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
"github.com/Theodor-Springmann-Stiftung/kgpz_web/xmlmodels"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -38,7 +40,7 @@ type PieceVM struct {
|
|||||||
IssueContexts []string // List of issue contexts for display
|
IssueContexts []string // List of issue contexts for display
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPieceView(piece xmlmodels.Piece, lib *xmlmodels.Library) (*PieceVM, error) {
|
func NewPieceView(piece xmlmodels.Piece, lib *xmlmodels.Library, pics *pictures.PicturesProvider) (*PieceVM, error) {
|
||||||
pvm := &PieceVM{
|
pvm := &PieceVM{
|
||||||
Piece: piece,
|
Piece: piece,
|
||||||
AllIssueRefs: piece.IssueRefs,
|
AllIssueRefs: piece.IssueRefs,
|
||||||
@@ -47,10 +49,10 @@ func NewPieceView(piece xmlmodels.Piece, lib *xmlmodels.Library) (*PieceVM, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG: Log piece details
|
// DEBUG: Log piece details
|
||||||
fmt.Printf("DEBUG PieceView: Creating view for piece ID=%s\n", piece.Identifier.ID)
|
logging.Debug(fmt.Sprintf("PieceView: Creating view for piece ID=%s", piece.Identifier.ID))
|
||||||
fmt.Printf("DEBUG PieceView: Piece has %d IssueRefs\n", len(piece.IssueRefs))
|
logging.Debug(fmt.Sprintf("PieceView: Piece has %d IssueRefs", len(piece.IssueRefs)))
|
||||||
for i, ref := range piece.IssueRefs {
|
for i, ref := range piece.IssueRefs {
|
||||||
fmt.Printf("DEBUG PieceView: IssueRef[%d]: Year=%d, Nr=%d, Von=%d, Bis=%d, Beilage=%d\n", i, ref.When.Year, ref.Nr, ref.Von, ref.Bis, ref.Beilage)
|
logging.Debug(fmt.Sprintf("PieceView: IssueRef[%d]: Year=%d, Nr=%d, Von=%d, Bis=%d, Beilage=%d", i, ref.When.Year, ref.Nr, ref.Von, ref.Bis, ref.Beilage))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract title from piece
|
// Extract title from piece
|
||||||
@@ -98,8 +100,8 @@ func NewPieceView(piece xmlmodels.Piece, lib *xmlmodels.Library) (*PieceVM, erro
|
|||||||
PartNumber: partIndex + 1, // Part number (1-based)
|
PartNumber: partIndex + 1, // Part number (1-based)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get actual image path, preview path, and JPEG path from registry
|
// Get actual image path, preview path, and JPEG path from provider
|
||||||
pageEntry.ImagePath, pageEntry.PreviewPath, pageEntry.JpegPath = getImagePathsFromRegistryWithBeilage(issueRef.When.Year, issueRef.Nr, pageNum, issueRef.Beilage > 0)
|
pageEntry.ImagePath, pageEntry.PreviewPath, pageEntry.JpegPath = getImagePathsFromProvider(pics, issueRef.When.Year, issueRef.Nr, pageNum, issueRef.Beilage > 0)
|
||||||
|
|
||||||
pvm.AllPages = append(pvm.AllPages, pageEntry)
|
pvm.AllPages = append(pvm.AllPages, pageEntry)
|
||||||
}
|
}
|
||||||
@@ -108,11 +110,11 @@ func NewPieceView(piece xmlmodels.Piece, lib *xmlmodels.Library) (*PieceVM, erro
|
|||||||
pvm.TotalPageCount = len(pvm.AllPages)
|
pvm.TotalPageCount = len(pvm.AllPages)
|
||||||
|
|
||||||
// DEBUG: Log final counts
|
// DEBUG: Log final counts
|
||||||
fmt.Printf("DEBUG PieceView: Final counts - %d issue contexts, %d total pages\n", len(pvm.IssueContexts), pvm.TotalPageCount)
|
logging.Debug(fmt.Sprintf("PieceView: Final counts - %d issue contexts, %d total pages", len(pvm.IssueContexts), pvm.TotalPageCount))
|
||||||
fmt.Printf("DEBUG PieceView: Issue contexts: %v\n", pvm.IssueContexts)
|
logging.Debug(fmt.Sprintf("PieceView: Issue contexts: %v", pvm.IssueContexts))
|
||||||
|
|
||||||
// Load images and update availability
|
// Load images and update availability
|
||||||
if err := pvm.loadImages(); err != nil {
|
if err := pvm.loadImages(pics); err != nil {
|
||||||
return nil, fmt.Errorf("failed to load images: %w", err)
|
return nil, fmt.Errorf("failed to load images: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,12 +132,7 @@ func NewPieceView(piece xmlmodels.Piece, lib *xmlmodels.Library) (*PieceVM, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// loadImages loads and validates all page images for the piece
|
// loadImages loads and validates all page images for the piece
|
||||||
func (pvm *PieceVM) loadImages() error {
|
func (pvm *PieceVM) loadImages(pics *pictures.PicturesProvider) error {
|
||||||
// Initialize image registry if needed
|
|
||||||
if err := initImageRegistry(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
issuePages := []IssuePage{}
|
issuePages := []IssuePage{}
|
||||||
hasAnyImages := false
|
hasAnyImages := false
|
||||||
|
|
||||||
@@ -150,15 +147,12 @@ func (pvm *PieceVM) loadImages() error {
|
|||||||
PageIcon: "single", // Simplified icon for piece view
|
PageIcon: "single", // Simplified icon for piece view
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if image actually exists using the registry
|
// Check if image actually exists using the provider
|
||||||
key := fmt.Sprintf("%d-%d", pageEntry.IssueYear, pageEntry.PageNumber)
|
if _, exists := pics.GetByYearPage(pageEntry.IssueYear, pageEntry.PageNumber); exists {
|
||||||
if imageRegistry != nil {
|
hasAnyImages = true
|
||||||
if _, exists := imageRegistry.ByYearPage[key]; exists {
|
} else {
|
||||||
hasAnyImages = true
|
issuePage.Available = false
|
||||||
} else {
|
pvm.AllPages[i].Available = false
|
||||||
issuePage.Available = false
|
|
||||||
pvm.AllPages[i].Available = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
issuePages = append(issuePages, issuePage)
|
issuePages = append(issuePages, issuePage)
|
||||||
@@ -218,110 +212,37 @@ func (pvm *PieceVM) createContinuousPages(lib *xmlmodels.Library) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getImagePathFromRegistry gets the actual image path from the image registry
|
// getImagePathsFromProvider gets image paths: primary (WebP preferred), preview (compressed), and JPEG, handling both regular and Beilage pages
|
||||||
func getImagePathFromRegistry(year, page int) string {
|
func getImagePathsFromProvider(pics *pictures.PicturesProvider, year, issue, page int, isBeilage bool) (string, string, string) {
|
||||||
// Initialize registry if needed
|
// Get image file from provider
|
||||||
if err := initImageRegistry(); err != nil {
|
imageFile, exists := pics.GetByYearIssuePage(year, issue, page, isBeilage)
|
||||||
return ""
|
if !exists {
|
||||||
}
|
// Fallback for regular pages
|
||||||
|
if !isBeilage {
|
||||||
// Look up the image by year and page
|
fallbackPath := fmt.Sprintf("/static/pictures/%d/seite_%d.jpg", year, page)
|
||||||
key := fmt.Sprintf("%d-%d", year, page)
|
return fallbackPath, fallbackPath, fallbackPath
|
||||||
if imageFile, exists := imageRegistry.ByYearPage[key]; exists {
|
}
|
||||||
return imageFile.Path
|
// No file found for beilage
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: generate a default path (though this probably won't exist)
|
|
||||||
return fmt.Sprintf("/static/pictures/%d/seite_%d.jpg", year, page)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getImagePathsFromRegistryWithBeilage gets image paths: primary (WebP preferred), preview (compressed), and JPEG, handling both regular and Beilage pages
|
|
||||||
func getImagePathsFromRegistryWithBeilage(year, issue, page int, isBeilage bool) (string, string, string) {
|
|
||||||
// Initialize registry if needed
|
|
||||||
if err := initImageRegistry(); err != nil {
|
|
||||||
return "", "", ""
|
return "", "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// For regular pages, use the year-page lookup
|
// Return paths from found image file
|
||||||
if !isBeilage {
|
previewPath := imageFile.PreviewPath
|
||||||
key := fmt.Sprintf("%d-%d", year, page)
|
if previewPath == "" {
|
||||||
if imageFile, exists := imageRegistry.ByYearPage[key]; exists {
|
previewPath = imageFile.Path // Fallback to original if no preview
|
||||||
previewPath := imageFile.PreviewPath
|
|
||||||
if previewPath == "" {
|
|
||||||
previewPath = imageFile.Path // Fallback to original if no preview
|
|
||||||
}
|
|
||||||
jpegPath := imageFile.JpegPath
|
|
||||||
if jpegPath == "" {
|
|
||||||
jpegPath = imageFile.Path // Fallback to primary if no separate JPEG
|
|
||||||
}
|
|
||||||
return imageFile.Path, previewPath, jpegPath
|
|
||||||
}
|
|
||||||
// Fallback for regular pages
|
|
||||||
fallbackPath := fmt.Sprintf("/static/pictures/%d/seite_%d.jpg", year, page)
|
|
||||||
return fallbackPath, fallbackPath, fallbackPath
|
|
||||||
}
|
}
|
||||||
|
jpegPath := imageFile.JpegPath
|
||||||
// For Beilage pages, search through all files for this year-issue
|
if jpegPath == "" {
|
||||||
yearIssueKey := fmt.Sprintf("%d-%d", year, issue)
|
jpegPath = imageFile.Path // Fallback to primary if no separate JPEG
|
||||||
if issueFiles, exists := imageRegistry.ByYearIssue[yearIssueKey]; exists {
|
|
||||||
for _, file := range issueFiles {
|
|
||||||
if file.IsBeilage && file.Page == page {
|
|
||||||
previewPath := file.PreviewPath
|
|
||||||
if previewPath == "" {
|
|
||||||
previewPath = file.Path // Fallback to original if no preview
|
|
||||||
}
|
|
||||||
jpegPath := file.JpegPath
|
|
||||||
if jpegPath == "" {
|
|
||||||
jpegPath = file.Path // Fallback to primary if no separate JPEG
|
|
||||||
}
|
|
||||||
return file.Path, previewPath, jpegPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return imageFile.Path, previewPath, jpegPath
|
||||||
// No file found
|
|
||||||
return "", "", ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// getImagePathFromRegistryWithBeilage gets the actual image path, handling both regular and Beilage pages
|
|
||||||
// Kept for backward compatibility
|
|
||||||
func getImagePathFromRegistryWithBeilage(year, issue, page int, isBeilage bool) string {
|
|
||||||
// Initialize registry if needed
|
|
||||||
if err := initImageRegistry(); err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// For regular pages, use the old method
|
|
||||||
if !isBeilage {
|
|
||||||
key := fmt.Sprintf("%d-%d", year, page)
|
|
||||||
if imageFile, exists := imageRegistry.ByYearPage[key]; exists {
|
|
||||||
return imageFile.Path
|
|
||||||
}
|
|
||||||
// Fallback for regular pages
|
|
||||||
return fmt.Sprintf("/static/pictures/%d/seite_%d.jpg", year, page)
|
|
||||||
}
|
|
||||||
|
|
||||||
// For Beilage pages, search through all files for this year-issue
|
|
||||||
yearIssueKey := fmt.Sprintf("%d-%d", year, issue)
|
|
||||||
if issueFiles, exists := imageRegistry.ByYearIssue[yearIssueKey]; exists {
|
|
||||||
for _, file := range issueFiles {
|
|
||||||
if file.IsBeilage && file.Page == page {
|
|
||||||
fmt.Printf("DEBUG: Found Beilage image for year=%d, issue=%d, page=%d: %s\n", year, issue, page, file.Path)
|
|
||||||
return file.Path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback for Beilage pages
|
|
||||||
fmt.Printf("DEBUG: No Beilage image found for year=%d, issue=%d, page=%d\n", year, issue, page)
|
|
||||||
return fmt.Sprintf("/static/pictures/%d/%db-beilage-seite_%d.jpg", year, issue, page)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// populateOtherPieces finds and populates other pieces that appear on the same pages as this piece
|
// populateOtherPieces finds and populates other pieces that appear on the same pages as this piece
|
||||||
func (pvm *PieceVM) populateOtherPieces(lib *xmlmodels.Library) error {
|
func (pvm *PieceVM) populateOtherPieces(lib *xmlmodels.Library) error {
|
||||||
fmt.Printf("DEBUG: Starting populateOtherPieces for piece %s\n", pvm.Piece.Identifier.ID)
|
logging.Debug(fmt.Sprintf("Starting populateOtherPieces for piece %s", pvm.Piece.Identifier.ID))
|
||||||
for i, pageEntry := range pvm.AllPages {
|
for i, pageEntry := range pvm.AllPages {
|
||||||
fmt.Printf("DEBUG: Processing page %d from issue %d/%d\n", pageEntry.PageNumber, pageEntry.IssueYear, pageEntry.IssueNumber)
|
logging.Debug(fmt.Sprintf("Processing page %d from issue %d/%d", pageEntry.PageNumber, pageEntry.IssueYear, pageEntry.IssueNumber))
|
||||||
|
|
||||||
// Find the issue this page belongs to
|
// Find the issue this page belongs to
|
||||||
var issue *xmlmodels.Issue
|
var issue *xmlmodels.Issue
|
||||||
@@ -335,41 +256,41 @@ func (pvm *PieceVM) populateOtherPieces(lib *xmlmodels.Library) error {
|
|||||||
lib.Issues.Unlock()
|
lib.Issues.Unlock()
|
||||||
|
|
||||||
if issue == nil {
|
if issue == nil {
|
||||||
fmt.Printf("DEBUG: Issue not found for %d/%d\n", pageEntry.IssueYear, pageEntry.IssueNumber)
|
logging.Debug(fmt.Sprintf("Issue not found for %d/%d", pageEntry.IssueYear, pageEntry.IssueNumber))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all pieces for this issue using the same approach as the ausgabe view
|
// Get all pieces for this issue using the same approach as the ausgabe view
|
||||||
piecesForIssue, _, err := PiecesForIssue(lib, *issue)
|
piecesForIssue, _, err := PiecesForIssue(lib, *issue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("DEBUG: Error getting pieces for issue: %v\n", err)
|
logging.Error(err, fmt.Sprintf("Error getting pieces for issue %d/%d", pageEntry.IssueYear, pageEntry.IssueNumber))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Printf("DEBUG: Found %d total pieces for issue %d/%d\n", len(piecesForIssue.Pages), pageEntry.IssueYear, pageEntry.IssueNumber)
|
logging.Debug(fmt.Sprintf("Found %d total pieces for issue %d/%d", len(piecesForIssue.Pages), pageEntry.IssueYear, pageEntry.IssueNumber))
|
||||||
fmt.Printf("DEBUG: PiecesForIssue.Pages = %v\n", piecesForIssue.Pages)
|
logging.Debug(fmt.Sprintf("PiecesForIssue.Pages = %v", piecesForIssue.Pages))
|
||||||
|
|
||||||
// Create IndividualPiecesByPage using the same function as ausgabe view
|
// Create IndividualPiecesByPage using the same function as ausgabe view
|
||||||
individualPieces := CreateIndividualPagesWithMetadata(piecesForIssue, lib)
|
individualPieces := CreateIndividualPagesWithMetadata(piecesForIssue, lib)
|
||||||
fmt.Printf("DEBUG: CreateIndividualPagesWithMetadata created %d pages with pieces\n", len(individualPieces.Pages))
|
logging.Debug(fmt.Sprintf("CreateIndividualPagesWithMetadata created %d pages with pieces", len(individualPieces.Pages)))
|
||||||
fmt.Printf("DEBUG: Pages with pieces: %v\n", individualPieces.Pages)
|
logging.Debug(fmt.Sprintf("Pages with pieces: %v", individualPieces.Pages))
|
||||||
|
|
||||||
// DEBUG: Show what pages are available in the map
|
// DEBUG: Show what pages are available in the map
|
||||||
if pageEntry.PageNumber == 113 {
|
if pageEntry.PageNumber == 113 {
|
||||||
fmt.Printf("DEBUG: Available pages in individualPieces.Items: %v\n", individualPieces.Pages)
|
logging.Debug(fmt.Sprintf("Available pages in individualPieces.Items: %v", individualPieces.Pages))
|
||||||
for pageNum := range individualPieces.Items {
|
for pageNum := range individualPieces.Items {
|
||||||
fmt.Printf("DEBUG: Page %d has %d pieces\n", pageNum, len(individualPieces.Items[pageNum]))
|
logging.Debug(fmt.Sprintf("Page %d has %d pieces", pageNum, len(individualPieces.Items[pageNum])))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get pieces that appear on this specific page
|
// Get pieces that appear on this specific page
|
||||||
if individualPiecesOnPage, exists := individualPieces.Items[pageEntry.PageNumber]; exists {
|
if individualPiecesOnPage, exists := individualPieces.Items[pageEntry.PageNumber]; exists {
|
||||||
fmt.Printf("DEBUG: Found %d pieces on page %d\n", len(individualPiecesOnPage), pageEntry.PageNumber)
|
logging.Debug(fmt.Sprintf("Found %d pieces on page %d", len(individualPiecesOnPage), pageEntry.PageNumber))
|
||||||
otherPieces := []IndividualPieceByIssue{}
|
otherPieces := []IndividualPieceByIssue{}
|
||||||
|
|
||||||
for _, individualPiece := range individualPiecesOnPage {
|
for _, individualPiece := range individualPiecesOnPage {
|
||||||
// Skip the current piece itself using comprehensive comparison
|
// Skip the current piece itself using comprehensive comparison
|
||||||
if IsSamePiece(individualPiece.PieceByIssue.Piece, pvm.Piece) {
|
if IsSamePiece(individualPiece.PieceByIssue.Piece, pvm.Piece) {
|
||||||
fmt.Printf("DEBUG: Skipping current piece (comprehensive field match)\n")
|
logging.Debug("Skipping current piece (comprehensive field match)")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,14 +302,14 @@ func (pvm *PieceVM) populateOtherPieces(lib *xmlmodels.Library) error {
|
|||||||
pieceTitle = individualPiece.PieceByIssue.Piece.Incipit[0]
|
pieceTitle = individualPiece.PieceByIssue.Piece.Incipit[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("DEBUG: Adding other piece title='%s'\n", pieceTitle)
|
logging.Debug(fmt.Sprintf("Adding other piece title='%s'", pieceTitle))
|
||||||
otherPieces = append(otherPieces, individualPiece)
|
otherPieces = append(otherPieces, individualPiece)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("DEBUG: Found %d other pieces on page %d\n", len(otherPieces), pageEntry.PageNumber)
|
logging.Debug(fmt.Sprintf("Found %d other pieces on page %d", len(otherPieces), pageEntry.PageNumber))
|
||||||
pvm.AllPages[i].OtherPieces = otherPieces
|
pvm.AllPages[i].OtherPieces = otherPieces
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("DEBUG: No pieces found on page %d\n", pageEntry.PageNumber)
|
logging.Debug(fmt.Sprintf("No pieces found on page %d", pageEntry.PageNumber))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user