mirror of
https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
synced 2025-12-16 14:35:32 +00:00
212 lines
4.8 KiB
Go
212 lines
4.8 KiB
Go
package controllers
|
||
|
||
import (
|
||
"encoding/json"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/Theodor-Springmann-Stiftung/lenz-web/xmlmodels"
|
||
"github.com/gofiber/fiber/v2"
|
||
)
|
||
|
||
type filterItem struct {
|
||
ID int `json:"id"`
|
||
Name string `json:"name"`
|
||
}
|
||
|
||
func GetLetters(c *fiber.Ctx) error {
|
||
lib := xmlmodels.Get()
|
||
_, yearmap := lib.Years()
|
||
rangeParam := c.Query("range", "")
|
||
personParam := strings.TrimSpace(c.Query("person", ""))
|
||
placeParam := strings.TrimSpace(c.Query("ort", ""))
|
||
|
||
personID := 0
|
||
if personParam != "" {
|
||
if id, err := strconv.Atoi(personParam); err == nil && id > 0 {
|
||
personID = id
|
||
} else {
|
||
personParam = ""
|
||
}
|
||
}
|
||
|
||
placeID := 0
|
||
if placeParam != "" {
|
||
if id, err := strconv.Atoi(placeParam); err == nil && id > 0 {
|
||
placeID = id
|
||
} else {
|
||
placeParam = ""
|
||
}
|
||
}
|
||
|
||
rawQuery := string(c.Context().URI().QueryString())
|
||
lastPerson := strings.LastIndex(rawQuery, "person=")
|
||
lastPlace := strings.LastIndex(rawQuery, "ort=")
|
||
if lastPerson >= 0 && lastPlace >= 0 {
|
||
if lastPlace > lastPerson {
|
||
personID = 0
|
||
personParam = ""
|
||
} else {
|
||
placeID = 0
|
||
placeParam = ""
|
||
}
|
||
}
|
||
|
||
if personID > 0 && placeID > 0 {
|
||
// Fallback if we couldn't determine query order.
|
||
placeID = 0
|
||
placeParam = ""
|
||
}
|
||
|
||
personOptions := make(map[int]filterItem)
|
||
placeOptions := make(map[int]filterItem)
|
||
|
||
addPerson := func(id int) {
|
||
if id <= 0 {
|
||
return
|
||
}
|
||
if _, ok := personOptions[id]; ok {
|
||
return
|
||
}
|
||
if def := lib.Person(id); def != nil {
|
||
name := strings.TrimSpace(def.Name)
|
||
if name == "" {
|
||
name = strings.TrimSpace(def.FirstName + " " + def.LastName)
|
||
}
|
||
if name == "" {
|
||
name = strings.TrimSpace(def.Ref)
|
||
}
|
||
if name == "" {
|
||
name = "Person " + strconv.Itoa(id)
|
||
}
|
||
personOptions[id] = filterItem{ID: id, Name: name}
|
||
}
|
||
}
|
||
|
||
addPlace := func(id int) {
|
||
if id <= 0 {
|
||
return
|
||
}
|
||
if _, ok := placeOptions[id]; ok {
|
||
return
|
||
}
|
||
if def := lib.Place(id); def != nil {
|
||
name := strings.TrimSpace(def.Name)
|
||
if name == "" {
|
||
name = strings.TrimSpace(def.Ref)
|
||
}
|
||
if name == "" {
|
||
name = "Ort " + strconv.Itoa(id)
|
||
}
|
||
placeOptions[id] = filterItem{ID: id, Name: name}
|
||
}
|
||
}
|
||
|
||
collectRefs := func(meta xmlmodels.Meta) {
|
||
for _, action := range meta.Sent {
|
||
for _, ref := range action.Persons {
|
||
addPerson(ref.Reference)
|
||
}
|
||
for _, ref := range action.Places {
|
||
addPlace(ref.Reference)
|
||
}
|
||
}
|
||
for _, action := range meta.Recieved {
|
||
for _, ref := range action.Persons {
|
||
addPerson(ref.Reference)
|
||
}
|
||
for _, ref := range action.Places {
|
||
addPlace(ref.Reference)
|
||
}
|
||
}
|
||
}
|
||
|
||
filterLetter := func(meta xmlmodels.Meta) bool {
|
||
if personID > 0 && !meta.HasPerson(personID) {
|
||
return false
|
||
}
|
||
if placeID > 0 && !meta.HasPlace(placeID) {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
// TODO: does not work ATM
|
||
c.Locals("path", c.Path())
|
||
|
||
// Define the date ranges
|
||
ranges := []DateRange{
|
||
{Label: "1756–1770", Start: 1756, End: 1770, Letters: []xmlmodels.Meta{}},
|
||
{Label: "1771–1775", Start: 1771, End: 1775, Letters: []xmlmodels.Meta{}},
|
||
{Label: "1776", Start: 1776, End: 1776, Letters: []xmlmodels.Meta{}},
|
||
{Label: "1777–1779", Start: 1777, End: 1779, Letters: []xmlmodels.Meta{}},
|
||
{Label: "1780–1792", Start: 1780, End: 1792, Letters: []xmlmodels.Meta{}},
|
||
}
|
||
|
||
// Group letters by date ranges
|
||
for year, letters := range yearmap {
|
||
for i := range ranges {
|
||
if year >= ranges[i].Start && year <= ranges[i].End {
|
||
for _, letter := range letters {
|
||
collectRefs(letter)
|
||
if filterLetter(letter) {
|
||
ranges[i].Letters = append(ranges[i].Letters, letter)
|
||
}
|
||
}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
if personID > 0 || placeID > 0 {
|
||
rangeParam = "all"
|
||
}
|
||
|
||
// Handle specific range selection
|
||
selectedRange := -1
|
||
for i, r := range ranges {
|
||
if r.Label == rangeParam {
|
||
selectedRange = i
|
||
break
|
||
}
|
||
}
|
||
|
||
querySuffix := ""
|
||
if personParam != "" {
|
||
querySuffix += "&person=" + personParam
|
||
}
|
||
if placeParam != "" {
|
||
querySuffix += "&ort=" + placeParam
|
||
}
|
||
|
||
personList := make([]filterItem, 0, len(personOptions))
|
||
for _, item := range personOptions {
|
||
personList = append(personList, item)
|
||
}
|
||
sort.Slice(personList, func(i, j int) bool {
|
||
return strings.ToLower(personList[i].Name) < strings.ToLower(personList[j].Name)
|
||
})
|
||
|
||
placeList := make([]filterItem, 0, len(placeOptions))
|
||
for _, item := range placeOptions {
|
||
placeList = append(placeList, item)
|
||
}
|
||
sort.Slice(placeList, func(i, j int) bool {
|
||
return strings.ToLower(placeList[i].Name) < strings.ToLower(placeList[j].Name)
|
||
})
|
||
|
||
personJSON, _ := json.Marshal(personList)
|
||
placeJSON, _ := json.Marshal(placeList)
|
||
|
||
return c.Render(LETTERS_URL+"/", fiber.Map{
|
||
"ranges": ranges,
|
||
"selectedRange": selectedRange,
|
||
"all": rangeParam == "all",
|
||
"person": personParam,
|
||
"ort": placeParam,
|
||
"query": querySuffix,
|
||
"personJSON": string(personJSON),
|
||
"placeJSON": string(placeJSON),
|
||
})
|
||
}
|