restructured viewmodels, better serialization

This commit is contained in:
Simon Martens
2024-11-19 15:20:15 +01:00
parent 84fa6f7fa4
commit 7dc603df2c
26 changed files with 51479 additions and 198 deletions

View File

@@ -13,7 +13,7 @@ tmp_dir = "tmp"
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_dir = [ "views/assets" ]
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
@@ -42,9 +42,9 @@ tmp_dir = "tmp"
clean_on_exit = false
[proxy]
app_port = 0
app_port = 8080
enabled = false
proxy_port = 0
proxy_port = 8081
[screen]
clear_on_rebuild = false

View File

@@ -8,6 +8,7 @@ import (
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
)
const (
@@ -25,7 +26,7 @@ type KGPZ struct {
gmu sync.Mutex
Config *providers.ConfigProvider
Repo *providers.GitProvider
Library *providers.Library
Library *xmlprovider.Library
}
func (k *KGPZ) Init() {
@@ -68,7 +69,7 @@ func (k *KGPZ) Serialize() {
pieces, err := getXMLFiles(filepath.Join(k.Config.FolderPath, PIECES_DIR))
helpers.Assert(err, "Error getting pieces")
lib := providers.NewLibrary(
lib := xmlprovider.NewLibrary(
[]string{filepath.Join(k.Config.FolderPath, AGENTS_PATH)},
[]string{filepath.Join(k.Config.FolderPath, PLACES_PATH)},
[]string{filepath.Join(k.Config.FolderPath, WORKS_PATH)},
@@ -135,7 +136,7 @@ func (k *KGPZ) Pull() {
k.gmu.Unlock()
if changed {
logging.ObjDebug(&k.Repo, "Remote changed. Reparsing...")
logging.ObjDebug(&k.Repo, "Remote changed. Reparsing")
k.Serialize()
}
}()

33
controllers/issue.go Normal file
View File

@@ -0,0 +1,33 @@
package controllers
import (
"github.com/Theodor-Springmann-Stiftung/kgpz_web/app"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/viewmodels"
"github.com/gofiber/fiber/v2"
)
func GetIssue(kgpz *app.KGPZ) fiber.Handler {
return func(c *fiber.Ctx) error {
y := c.Params("year")
if len(y) != 4 {
logging.Error(nil, "Year is not 4 characters long")
return c.SendStatus(fiber.StatusNotFound)
}
d := c.Params("issue")
if d == "" {
logging.Error(nil, "Issue number is empty")
return c.SendStatus(fiber.StatusNotFound)
}
issue, err := viewmodels.IssueView(y, d, kgpz.Library)
if err != nil {
logging.Error(err, "Issue could not be found")
return c.SendStatus(fiber.StatusNotFound)
}
return c.Render("/issue/", fiber.Map{"model": issue})
}
}

View File

@@ -2,6 +2,8 @@ package controllers
import (
"github.com/Theodor-Springmann-Stiftung/kgpz_web/app"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/viewmodels"
"github.com/gofiber/fiber/v2"
)
@@ -16,8 +18,9 @@ func GetYear(kgpz *app.KGPZ) fiber.Handler {
return c.SendStatus(fiber.StatusBadRequest)
}
issues := kgpz.Library.Issues.GetYear(y)
if len(issues.Issues) == 0 {
issues, err := viewmodels.YearView(y, kgpz.Library)
if err != nil {
logging.Error(err, "Keine Ausgaben für das Jahr "+y)
return c.SendStatus(fiber.StatusNotFound)
}

305
lobid_example.json Normal file
View File

@@ -0,0 +1,305 @@
> curl --header "Accept: application/json" https://lobid.org/gnd/11854523X > lobid_example.json
{
"gender" : [ {
"id" : "https://d-nb.info/standards/vocab/gnd/gender#male",
"label" : "Männlich"
} ],
"dateOfDeath" : [ "1788-06-21" ],
"placeOfDeath" : [ {
"id" : "https://d-nb.info/gnd/4040608-8",
"label" : "Münster (Westf)"
} ],
"familialRelationship" : [ {
"id" : "https://d-nb.info/gnd/124138004",
"label" : "Hamann, Johann Georg"
} ],
"type" : [ "Person", "AuthorityResource", "DifferentiatedPerson" ],
"gndSubjectCategory" : [ {
"id" : "https://d-nb.info/standards/vocab/gnd/gnd-sc#4.7p",
"label" : "Personen zu Philosophie"
}, {
"id" : "https://d-nb.info/standards/vocab/gnd/gnd-sc#3.6p",
"label" : "Personen zu Kirchengeschichte, Systematischer und Praktischer Theologie, Kirche und Konfession"
}, {
"id" : "https://d-nb.info/standards/vocab/gnd/gnd-sc#12.2p",
"label" : "Personen zu Literaturgeschichte (Schriftsteller)"
} ],
"oldAuthorityNumber" : [ "(DE-588a)11854523X", "(DE-588c)4023109-4", "(DE-588a)126364664" ],
"geographicAreaCode" : [ {
"id" : "https://d-nb.info/standards/vocab/gnd/geographic-area-code#XA-RU",
"label" : "Russland"
}, {
"id" : "https://d-nb.info/standards/vocab/gnd/geographic-area-code#XA-DE",
"label" : "Deutschland"
} ],
"biographicalOrHistoricalInformation" : [ "Lutherischer Theologe und aufklärungskritischer Philosoph nach einem Erweckungserlebnis" ],
"hasAuntUncle" : [ {
"id" : "https://d-nb.info/gnd/124138004",
"label" : "Hamann, Johann Georg"
} ],
"publication" : [ "Hamann, Johann G.: Golgatha und Scheblimini", "Rink, Friedrich T.: [Mancherlei zur Geschichte der metakritischen Invasion]", "Hamann, Johann G.: Kreuzzüge der Philologen", "Hamann, Johann G.: Beobachtungen über die heilige Schrift", "Hamann, Johann G.: Versuch einer Sibylle über die Ehe", "Weisheits-Sprüche und Witzreden aus J. Georg Hamanns und Imanuel Kants Schriften", "Hamann, Johann G.: Sibyllinische Blätter des Magus im Norden" ],
"describedBy" : {
"id" : "https://d-nb.info/gnd/11854523X/about",
"license" : {
"id" : "http://creativecommons.org/publicdomain/zero/1.0/",
"label" : "http://creativecommons.org/publicdomain/zero/1.0/"
},
"dateModified" : "2024-01-08T10:50:15.000",
"descriptionLevel" : {
"id" : "https://d-nb.info/standards/vocab/gnd/description-level#1",
"label" : "Allgemeines, Interdisziplinäre Allgemeinwörter"
}
},
"gndIdentifier" : "11854523X",
"id" : "https://d-nb.info/gnd/11854523X",
"preferredName" : "Hamann, Johann Georg",
"wikipedia" : [ {
"id" : "https://de.wikipedia.org/wiki/Johann_Georg_Hamann",
"label" : "https://de.wikipedia.org/wiki/Johann_Georg_Hamann"
} ],
"preferredNameEntityForThePerson" : {
"forename" : [ "Johann Georg" ],
"surname" : [ "Hamann" ]
},
"depiction" : [ {
"id" : "https://commons.wikimedia.org/wiki/Special:FilePath/Johann%20Georg%20Hamann%20%281730%E2%80%931788%29.jpg",
"url" : "https://commons.wikimedia.org/wiki/File:Johann%20Georg%20Hamann%20%281730%E2%80%931788%29.jpg?uselang=de",
"thumbnail" : "https://commons.wikimedia.org/wiki/Special:FilePath/Johann%20Georg%20Hamann%20%281730%E2%80%931788%29.jpg?width=270"
} ],
"professionOrOccupation" : [ {
"id" : "https://d-nb.info/gnd/4045790-4",
"label" : "Philosoph"
}, {
"id" : "https://d-nb.info/gnd/4053309-8",
"label" : "Schriftsteller"
}, {
"id" : "https://d-nb.info/gnd/1041366884",
"label" : "Lutherischer Theologe"
}, {
"id" : "https://d-nb.info/gnd/4128272-3",
"label" : "Kaufmann"
}, {
"id" : "https://d-nb.info/gnd/4061414-1",
"label" : "Übersetzer"
}, {
"id" : "https://d-nb.info/gnd/7719046-4",
"label" : "Selbstverleger"
} ],
"placeOfBirth" : [ {
"id" : "https://d-nb.info/gnd/4031541-1",
"label" : "Königsberg"
} ],
"dateOfBirth" : [ "1730-08-27" ],
"variantNameEntityForThePerson" : [ {
"forename" : [ "Vettius" ],
"surname" : [ "Epagathus" ]
}, {
"forename" : [ "Iogann Georg" ],
"surname" : [ "Gaman" ]
}, {
"forename" : [ "J. G." ],
"surname" : [ "Hamann" ]
}, {
"personalName" : [ "Hamann" ]
}, {
"forename" : [ "Abälardus" ],
"surname" : [ "Virbius" ]
}, {
"forename" : [ "Yohan Geʼorg" ],
"surname" : [ "Haman" ]
}, {
"nameAddition" : [ "Magus des Nordens" ],
"personalName" : [ "Hamann" ]
}, {
"personalName" : [ "Magus des Nordens" ]
}, {
"forename" : [ "Johann George" ],
"surname" : [ "Hamann" ]
}, {
"forename" : [ "Johann G." ],
"surname" : [ "Haman" ]
}, {
"forename" : [ "Christian Z." ],
"surname" : [ "Telonarcha" ]
}, {
"forename" : [ "Georg" ],
"surname" : [ "Hamann" ]
}, {
"forename" : [ "I. G." ],
"surname" : [ "Gaman" ]
}, {
"forename" : [ "Johann Georg" ],
"surname" : [ "Haman" ]
}, {
"forename" : [ "Johann Georg" ],
"nameAddition" : [ "der Jüngere" ],
"surname" : [ "Hamann" ]
}, {
"forename" : [ "Johann G." ],
"surname" : [ "Hamann" ]
}, {
"personalName" : [ "Aristobulus" ]
}, {
"forename" : [ "Vetius" ],
"surname" : [ "Epagathus" ]
} ],
"languageCode" : [ {
"id" : "http://id.loc.gov/vocabulary/iso639-2/ger",
"label" : "http://id.loc.gov/vocabulary/iso639-2/ger"
} ],
"@context" : "https://lobid.org/gnd/context.jsonld",
"professionalRelationship" : [ {
"id" : "https://d-nb.info/gnd/118549553",
"label" : "Herder, Johann Gottfried von"
} ],
"relatedSubjectHeading" : [ {
"id" : "https://d-nb.info/gnd/4165591-6",
"label" : "Kreis von Münster"
} ],
"variantName" : [ "Hamann, J. G.", "Magus des Nordens", "Haman, Johann G.", "Virbius, Abälardus", "Hamann", "Gaman, Iogann Georg", "Hamann, Johann Georg, der Jüngere", "Hamann, Johann G.", "Aristobulus", "Hamann, Johann George", "Haman, Johann Georg", "Hamann, Magus des Nordens", "Epagathus, Vettius", "Haman, Yohan Geʼorg", "Gaman, I. G.", "Epagathus, Vetius", "Telonarcha, Christian Z.", "Hamann, Georg" ],
"sameAs" : [ {
"collection" : {
"abbr" : "BNF",
"name" : "Bibliothèque nationale de France",
"publisher" : "Bibliothèque nationale de France",
"icon" : "https://www.bnf.fr/themes/custom/bnfsi/favicon.ico",
"id" : "http://www.wikidata.org/entity/Q19938912"
},
"id" : "http://catalogue.bnf.fr/ark:/12148/cb12359677d"
}, {
"id" : "http://id.loc.gov/rwo/agents/n78093468",
"collection" : {
"id" : "http://www.wikidata.org/entity/Q13219454",
"abbr" : "LC",
"publisher" : "Library of Congress",
"icon" : "http://www.loc.gov/favicon.ico",
"name" : "NACO Authority File"
}
}, {
"collection" : {
"abbr" : "OSTDEBIB",
"name" : "Ostdeutsche Biographie",
"publisher" : "Kulturportal West-Ost",
"id" : "http://www.wikidata.org/entity/Q52617553"
},
"id" : "http://kulturportal-west-ost.eu/persons/hamann-johann-georg/"
}, {
"id" : "http://viaf.org/viaf/69006033",
"collection" : {
"id" : "http://www.wikidata.org/entity/Q54919",
"abbr" : "VIAF",
"publisher" : "OCLC",
"icon" : "http://viaf.org/viaf/images/viaf.ico",
"name" : "Virtual International Authority File (VIAF)"
}
}, {
"id" : "http://www.wikidata.org/entity/Q76499",
"collection" : {
"id" : "http://www.wikidata.org/entity/Q2013",
"abbr" : "WIKIDATA",
"publisher" : "Wikimedia Foundation Inc.",
"icon" : "https://www.wikidata.org/static/favicon/wikidata.ico",
"name" : "Wikidata"
}
}, {
"collection" : {
"abbr" : "DNB",
"name" : "Gemeinsame Normdatei (GND) im Katalog der Deutschen Nationalbibliothek",
"publisher" : "Deutsche Nationalbibliothek",
"icon" : "https://www.dnb.de/SiteGlobals/Frontend/DNBWeb/Images/favicon.png?__blob=normal&v=4",
"id" : "http://www.wikidata.org/entity/Q36578"
},
"id" : "https://d-nb.info/gnd/11854523X/about"
}, {
"id" : "https://dbpedia.org/resource/Johann_Georg_Hamann",
"collection" : {
"id" : "https://dbpedia.org"
}
}, {
"collection" : {
"abbr" : "dewiki",
"name" : "Wikipedia (Deutsch)",
"publisher" : "Wikimedia Foundation Inc.",
"icon" : "https://de.wikipedia.org/static/favicon/wikipedia.ico",
"id" : "http://www.wikidata.org/entity/Q48183"
},
"id" : "https://de.wikipedia.org/wiki/Johann_Georg_Hamann"
}, {
"collection" : {
"abbr" : "WIKISOURCE",
"name" : "Wikisource",
"publisher" : "Wikimedia Foundation Inc.",
"icon" : "https://wikisource.org/static/favicon/wikisource.ico",
"id" : "http://www.wikidata.org/entity/Q263"
},
"id" : "https://de.wikisource.org/wiki/Johann_Georg_Hamann"
}, {
"collection" : {
"abbr" : "enwiki",
"name" : "Wikipedia (English)",
"publisher" : "Wikimedia Foundation Inc.",
"icon" : "https://en.wikipedia.org/static/favicon/wikipedia.ico",
"id" : "http://www.wikidata.org/entity/Q328"
},
"id" : "https://en.wikipedia.org/wiki/Johann_Georg_Hamann"
}, {
"id" : "https://isni.org/isni/0000000121021204",
"collection" : {
"id" : "https://isni.org"
}
}, {
"collection" : {
"abbr" : "DE-611",
"name" : "Kalliope Verbundkatalog",
"publisher" : "Staatsbibliothek zu Berlin - Preußischer Kulturbesitz",
"icon" : "https://kalliope-verbund.info/img/favicon.ico",
"id" : "https://kalliope-verbund.info"
},
"id" : "https://kalliope-verbund.info/gnd/11854523X"
}, {
"collection" : {
"abbr" : "ARCHIV-D",
"name" : "Archivportal-D",
"publisher" : "Deutsche Digitale Bibliothek",
"icon" : "https://www.archivportal-d.de/favicon.ico",
"id" : "https://www.archivportal-d.de"
},
"id" : "https://www.archivportal-d.de/person/gnd/11854523X"
}, {
"collection" : {
"abbr" : "ADB",
"name" : "Allgemeine Deutsche Biographie (ADB)",
"publisher" : "Historische Kommission bei der Bayerischen Akademie der Wissenschaften und Bayerische Staatsbibliothek",
"icon" : "https://www.deutsche-biographie.de/favicon.ico",
"id" : "https://www.deutsche-biographie.de"
},
"id" : "https://www.deutsche-biographie.de/pnd11854523X.html#adbcontent"
}, {
"collection" : {
"abbr" : "NDB",
"name" : "Neue Deutsche Biographie (NDB)",
"publisher" : "Historische Kommission bei der Bayerischen Akademie der Wissenschaften und Bayerische Staatsbibliothek",
"icon" : "https://www.deutsche-biographie.de/favicon.ico",
"id" : "https://www.deutsche-biographie.de"
},
"id" : "https://www.deutsche-biographie.de/pnd11854523X.html#ndbcontent"
}, {
"collection" : {
"abbr" : "DDB",
"name" : "Deutsche Digitale Bibliothek",
"publisher" : "Deutsche Digitale Bibliothek",
"icon" : "https://www.deutsche-digitale-bibliothek.de/favicon.ico",
"id" : "http://www.wikidata.org/entity/Q621630"
},
"id" : "https://www.deutsche-digitale-bibliothek.de/person/gnd/11854523X"
}, {
"collection" : {
"abbr" : "Portraitindex",
"name" : "Digitaler Portraitindex der druckgraphischen Bildnisse der Frühen Neuzeit",
"publisher" : "Deutsches Dokumentationszentrum für Kunstgeschichte - Bildarchiv Foto Marburg",
"icon" : "https://www.portraitindex.de/favicon.ico",
"id" : "https://www.portraitindex.de"
},
"id" : "https://www.portraitindex.de/dokumente/pnd/11854523X"
} ]
}

50783
log.out Normal file

File diff suppressed because it is too large Load Diff

4
providers/gnd/model.go Normal file
View File

@@ -0,0 +1,4 @@
package gnd
type Person struct {
}

View File

@@ -1,4 +1,4 @@
package providers
package xmlprovider
import (
"encoding/xml"

View File

@@ -1,4 +1,4 @@
package providers
package xmlprovider
import (
"encoding/xml"

View File

@@ -1,4 +1,4 @@
package providers
package xmlprovider
import (
"encoding/xml"
@@ -14,44 +14,19 @@ type Issues struct {
Issues []Issue `xml:"stueck"`
}
func (i *IssueProvider) GetYear(year string) YearViewModel {
res := YearViewModel{Year: year}
last := ""
for _, issue := range i.Items.Issues {
if len(issue.Datum.When) < 4 {
continue
}
date := issue.Datum.When[0:4]
if date != last {
res.PushAvailable(date)
last = date
}
if date == year {
res.PushIssue(issue)
}
}
res.SortAvailableYears()
return res
}
type Issue struct {
XMLName xml.Name `xml:"stueck"`
Number IssueNumber `xml:"nummer"`
Number Nummer `xml:"nummer"`
Datum KGPZDate `xml:"datum"`
Von string `xml:"von"`
Bis string `xml:"bis"`
Von int `xml:"von"`
Bis int `xml:"bis"`
Additionals []Additional `xml:"beilage"`
Identifier
AnnotationNote
}
type IssueNumber struct {
XMLName xml.Name `xml:"nummer"`
Value
type Nummer struct {
No int `xml:",chardata"`
Corrected string `xml:"korrigiert,attr"`
}
@@ -76,8 +51,8 @@ func (i Issues) String() string {
return fmt.Sprintf("Issues: %v", res)
}
func (i *Issue) String() string {
return fmt.Sprintf("ID: %s\nNumber: %v\nDatum: %v\nVon: %s\nBis: %s\nAdditionals: %v\n", i.ID, i.Number, i.Datum, i.Von, i.Bis, i.Additionals)
func (i Issue) String() string {
return fmt.Sprintf("Number: %v, Datum: %v, Von: %d, Bis: %d, Additionals: %v, Identifier: %v, AnnotationNote: %v\n", i.Number, i.Datum, i.Von, i.Bis, i.Additionals, i.Identifier, i.AnnotationNote)
}
func NewIssueProvider(paths []string) *IssueProvider {

View File

@@ -1,4 +1,4 @@
package providers
package xmlprovider
import (
"encoding/xml"
@@ -44,7 +44,7 @@ func (p Pieces) String() string {
return fmt.Sprintf("Pieces: %v", res)
}
func (p *Piece) String() string {
func (p Piece) String() string {
return fmt.Sprintf("ID: %s\nIssueRefs: %v\nPlaceRefs: %v\nCategoryRefs: %v\nAgentRefs: %v\nWorkRefs: %v\nPieceRefs: %v\nAdditionalRef: %v\nIncipit: %v\nTitle: %v\nAnnotations: %v\nNotes: %v\n", p.ID, p.IssueRefs, p.PlaceRefs, p.CategoryRefs, p.AgentRefs, p.WorkRefs, p.PieceRefs, p.AdditionalRef, p.Incipit, p.Title, p.Annotations, p.Notes)
}

View File

@@ -1,4 +1,4 @@
package providers
package xmlprovider
import (
"encoding/xml"

View File

@@ -1,4 +1,4 @@
package providers
package xmlprovider
import (
"encoding/xml"
@@ -15,14 +15,23 @@ type Works struct {
}
type Work struct {
XMLName xml.Name `xml:"werk"`
URLs []URL `xml:"url"`
Citation []string `xml:"zitation"`
Akteur []AgentRef `xml:"akteur"`
XMLName xml.Name `xml:"werk"`
URLs []URL `xml:"url"`
Citation Citation `xml:"zitation"`
PreferredTitle string `xml:"preferred"`
Akteur []AgentRef `xml:"akteur"`
Identifier
AnnotationNote
}
type Citation struct {
XMLName xml.Name `xml:"zitation"`
Title string `xml:"title"`
Year []string `xml:"year"`
Value
Inner
}
func (w Works) Append(data Works) Works {
w.Work = append(w.Work, data.Work...)
return w
@@ -38,7 +47,7 @@ func (w Works) String() string {
}
func (w *Work) String() string {
return fmt.Sprintf("ID: %s\nURLs: %v\nCitation: %v\nAnnotations: %v\nNotes: %v\n", w.ID, w.URLs, w.Citation, w.Annotations, w.Notes)
return fmt.Sprintf("URLs: %v, Citation: %v, PreferredTitle: %s, Akteur: %v, Identifier: %v, AnnotationNote: %v\n", w.URLs, w.Citation, w.PreferredTitle, w.Akteur, w.Identifier, w.AnnotationNote)
}
func NewWorkProvider(paths []string) *WorkProvider {

View File

@@ -0,0 +1,55 @@
package xmlprovider
import "encoding/xml"
type KGPZDate struct {
XMLName xml.Name `xml:"datum"`
When string `xml:"when,attr"`
NotBefore string `xml:"notBefore,attr"`
NotAfter string `xml:"notAfter,attr"`
From string `xml:"from,attr"`
To string `xml:"to,attr"`
Value
}
type URL struct {
XMLName xml.Name `xml:"url"`
Address string `xml:"address,attr"`
Value
}
type AnnotationNote struct {
Annotations []Annotation `xml:"anmerkung"`
Notes []Note `xml:"vermerk"`
}
type Annotation struct {
XMLName xml.Name `xml:"anmerkung"`
Value
Inner
}
type Note struct {
XMLName xml.Name `xml:"vermerk"`
Value
Inner
}
type Identifier struct {
ID string `xml:"id,attr"`
}
type Reference struct {
Ref string `xml:"ref,attr"`
Category string `xml:"kat,attr"`
Unsicher bool `xml:"unsicher,attr"`
Value
}
type Value struct {
Chardata string `xml:",chardata"`
}
type Inner struct {
InnerXML string `xml:",innerxml"`
}

View File

@@ -1,4 +1,4 @@
package providers
package xmlprovider
import (
"encoding/xml"
@@ -50,7 +50,6 @@ func (l *Library) Serialize() {
err := l.Agents.Serialize()
if err != nil {
l.Agents = nil
}
}()
@@ -59,7 +58,6 @@ func (l *Library) Serialize() {
err := l.Places.Serialize()
if err != nil {
l.Places = nil
}
}()
@@ -68,7 +66,6 @@ func (l *Library) Serialize() {
err := l.Works.Serialize()
if err != nil {
l.Works = nil
}
}()
@@ -77,7 +74,6 @@ func (l *Library) Serialize() {
err := l.Categories.Serialize()
if err != nil {
l.Categories = nil
}
}()
@@ -86,7 +82,6 @@ func (l *Library) Serialize() {
err := l.Issues.Serialize()
if err != nil {
l.Issues = nil
}
}()
@@ -95,7 +90,6 @@ func (l *Library) Serialize() {
err := l.Pieces.Serialize()
if err != nil {
l.Pieces = nil
}
}()
@@ -111,7 +105,6 @@ func (p *XMLProvider[T]) Serialize() error {
defer wg.Done()
var data T
if err := UnmarshalFile(path, &data); err != nil {
return
}
p.mu.Lock()
@@ -121,6 +114,7 @@ func (p *XMLProvider[T]) Serialize() error {
}
wg.Wait()
fmt.Println(p.Items)
return nil
}
@@ -133,10 +127,11 @@ func (a *XMLProvider[T]) String() string {
func UnmarshalFile[T any](filename string, data *T) error {
xmlFile, err := os.Open(filename)
if err != nil {
logging.Error(err, "Could not deserialize file: "+filename)
return err
}
defer xmlFile.Close()
logging.Info("Opened " + filename)
logging.Info("Deserialization: " + filename)
byteValue, _ := io.ReadAll(xmlFile)
xml.Unmarshal(byteValue, data)

View File

@@ -1,28 +1,12 @@
package providers
package xmlprovider
import "encoding/xml"
type KGPZDate struct {
XMLName xml.Name `xml:"datum"`
When string `xml:"when,attr"`
NotBefore string `xml:"notBefore,attr"`
NotAfter string `xml:"notAfter,attr"`
From string `xml:"from,attr"`
To string `xml:"to,attr"`
Value
}
type AgentRef struct {
XMLName xml.Name `xml:"akteur"`
Reference
}
type URL struct {
XMLName xml.Name `xml:"url"`
Address string `xml:"address,attr"`
Value
}
type AdditionalRef struct {
XMLName xml.Name `xml:"beilage"`
Reference
@@ -63,23 +47,3 @@ type PieceRef struct {
Page string `xml:"s,attr"`
Reference
}
type AnnotationNote struct {
Annotations []string `xml:"anmerkung"`
Notes []string `xml:"vermerk"`
}
type Identifier struct {
ID string `xml:"id,attr"`
}
type Reference struct {
Ref string `xml:"ref,attr"`
Category string `xml:"kat,attr"`
Unsicher bool `xml:"unsicher,attr"`
Value
}
type Value struct {
Chardata string `xml:",chardata"`
}

View File

@@ -1,84 +0,0 @@
package providers
import (
"slices"
"strconv"
"time"
)
const TLAYOUT = "2006-01-02"
var TRANSLM = map[string][]string{
"January": {"Januar", "Jan"},
"February": {"Februar", "Feb"},
"March": {"März", "Mär"},
"April": {"April", "Apr"},
"May": {"Mai", "Mai"},
"June": {"Juni", "Jun"},
"July": {"Juli", "Jul"},
"August": {"August", "Aug"},
"September": {"September", "Sep"},
"October": {"Oktober", "Okt"},
"November": {"November", "Nov"},
"December": {"Dezember", "Dez"},
}
var TRANSLD = map[string][]string{
"Monday": {"Montag", "Mo"},
"Tuesday": {"Dienstag", "Di"},
"Wednesday": {"Mittwoch", "Mi"},
"Thursday": {"Donnerstag", "Do"},
"Friday": {"Freitag", "Fr"},
"Saturday": {"Samstag", "Sa"},
"Sunday": {"Sonntag", "So"},
}
type IssueViewModel struct {
Issue
Weekday []string
Day int
Month []string
}
func NewIssueView(i Issue) (IssueViewModel, error) {
t, err := time.Parse(TLAYOUT, i.Datum.When)
if err != nil {
return IssueViewModel{}, err
}
return IssueViewModel{
Issue: i,
Weekday: append(TRANSLD[t.Weekday().String()], t.Weekday().String()),
Day: t.Day(),
Month: append(TRANSLM[t.Month().String()], i.Datum.When[5:7]),
}, nil
}
type YearViewModel struct {
Year string
AvailableYears []int
Issues []IssueViewModel
}
func (y *YearViewModel) PushIssue(i Issue) {
iv, err := NewIssueView(i)
if err != nil {
return
}
y.Issues = append(y.Issues, iv)
}
func (y *YearViewModel) PushAvailable(s string) {
i, err := strconv.Atoi(s)
if err != nil {
return
}
if !slices.Contains(y.AvailableYears, i) {
y.AvailableYears = append(y.AvailableYears, i)
}
}
func (y *YearViewModel) SortAvailableYears() {
slices.Sort(y.AvailableYears)
}

View File

@@ -142,7 +142,8 @@ func (s *Server) Start() {
} else {
srv.Use(cache.New(cache.Config{
Next: func(c *fiber.Ctx) bool {
return c.Query("noCache") == "true"
// We do not cache error responses
return c.Query("noCache") == "true" || c.Response().StatusCode() != fiber.StatusOK
},
Expiration: 30 * time.Minute,
CacheControl: true,
@@ -153,6 +154,8 @@ func (s *Server) Start() {
srv.Use(STATIC_PREFIX, static(&views.StaticFS))
srv.Get("/:year?", controllers.GetYear(s.kgpz))
srv.Get("/:year/:issue/:page?", controllers.GetIssue(s.kgpz))
srv.Get("/:year/:issue/beilage/:subpage?", controllers.GetIssue(s.kgpz))
s.runner(srv)

View File

@@ -1 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

BIN
tmp/main

Binary file not shown.

78
viewmodels/issue.go Normal file
View File

@@ -0,0 +1,78 @@
package viewmodels
import (
"errors"
"strconv"
"time"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
)
const TLAYOUT = "2006-01-02"
var TRANSLM = map[string][]string{
"January": {"Januar", "Jan", "1"},
"February": {"Februar", "Feb", "2"},
"March": {"März", "Mär", "3"},
"April": {"April", "Apr", "4"},
"May": {"Mai", "Mai", "5"},
"June": {"Juni", "Jun", "6"},
"July": {"Juli", "Jul", "7"},
"August": {"August", "Aug", "8"},
"September": {"September", "Sep", "9"},
"October": {"Oktober", "Okt", "10"},
"November": {"November", "Nov", "11"},
"December": {"Dezember", "Dez", "12"},
}
var TRANSLD = map[string][]string{
"Monday": {"Montag", "Mo"},
"Tuesday": {"Dienstag", "Di"},
"Wednesday": {"Mittwoch", "Mi"},
"Thursday": {"Donnerstag", "Do"},
"Friday": {"Freitag", "Fr"},
"Saturday": {"Samstag", "Sa"},
"Sunday": {"Sonntag", "So"},
}
type IssueViewModel struct {
xmlprovider.Issue
Weekday []string
Day int
Month []string
}
func IssueView(y string, No string, lib *xmlprovider.Library) (*IssueViewModel, error) {
n, err := strconv.Atoi(No)
if err != nil {
return nil, err
}
for _, i := range lib.Issues.Items.Issues {
if len(i.Datum.When) < 4 {
continue
}
d := i.Datum.When[:4]
if d == y && i.Number.No == n {
return FromIssue(i)
}
}
return nil, errors.New("Issue not found")
}
func FromIssue(i xmlprovider.Issue) (*IssueViewModel, error) {
t, err := time.Parse(TLAYOUT, i.Datum.When)
if err != nil {
return nil, err
}
ivm := IssueViewModel{
Issue: i,
Weekday: append(TRANSLD[t.Weekday().String()], t.Weekday().String()),
Day: t.Day(),
Month: TRANSLM[t.Month().String()]}
return &ivm, nil
}

11
viewmodels/piece.go Normal file
View File

@@ -0,0 +1,11 @@
package viewmodels
import "github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
type PieceViewModel struct {
xmlprovider.Piece
}
func NewPieceView(p xmlprovider.Piece) (PieceViewModel, error) {
return PieceViewModel{Piece: p}, nil
}

51
viewmodels/singleissue.go Normal file
View File

@@ -0,0 +1,51 @@
package viewmodels
import (
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
)
type SingleIssueViewModel struct {
IssueViewModel
No string
Year string
Additionals []PieceViewModel
Pieces []PieceViewModel
Next IssueViewModel
Prev IssueViewModel
}
func NewSingleIssueView(y string, No string, lib *xmlprovider.Library) (*SingleIssueViewModel, error) {
ivm, err := IssueView(y, No, lib)
if err != nil {
return nil, err
}
sivm := SingleIssueViewModel{IssueViewModel: *ivm}
for _, a := range lib.Pieces.Items.Piece {
for _, r := range a.IssueRefs {
if r.Datum == y && r.Nr == No {
p, err := NewPieceView(a)
if err != nil {
logging.ObjErr(&a, err)
continue
}
sivm.Pieces = append(sivm.Pieces, p)
}
}
for _, r := range a.AdditionalRef {
if r.Datum == y && r.Nr == No {
p, err := NewPieceView(a)
if err != nil {
logging.ObjErr(&a, err)
continue
}
sivm.Additionals = append(sivm.Additionals, p)
}
}
}
return &sivm, nil
}

87
viewmodels/year.go Normal file
View File

@@ -0,0 +1,87 @@
package viewmodels
import (
"errors"
"slices"
"sort"
"strconv"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers/xmlprovider"
)
type IssuesByMonth map[int][]IssueViewModel
type YearViewModel struct {
Year string
AvailableYears []string
Issues IssuesByMonth
}
func (y *YearViewModel) PushIssue(i xmlprovider.Issue) {
iv, err := FromIssue(i)
if err != nil {
return
}
month, _ := strconv.Atoi(iv.Month[2])
list, ok := y.Issues[month]
if !ok {
list = []IssueViewModel{}
}
y.Issues[month] = append(list, *iv)
}
func (y *YearViewModel) PushAvailable(s string) {
if !slices.Contains(y.AvailableYears, s) {
y.AvailableYears = append(y.AvailableYears, s)
}
}
func (y *YearViewModel) SortAvailableYears() {
sort.Slice(y.AvailableYears, func(i, j int) bool {
iint, err := strconv.Atoi(y.AvailableYears[i])
if err != nil {
return true
}
jint, err := strconv.Atoi(y.AvailableYears[j])
if err != nil {
return false
}
return iint < jint
})
}
func YearView(year string, lib *xmlprovider.Library) (*YearViewModel, error) {
res := YearViewModel{Year: year}
res.Issues = make(IssuesByMonth, 12)
last := ""
for _, issue := range lib.Issues.Items.Issues {
logging.ObjDebug(&issue, "Issue")
if len(issue.Datum.When) < 4 {
continue
}
date := issue.Datum.When[0:4]
if date != last {
res.PushAvailable(date)
last = date
}
if date == year {
res.PushIssue(issue)
}
}
if len(res.Issues) == 0 {
return nil, errors.New("No issues found")
}
res.SortAvailableYears()
return &res, nil
}

View File

@@ -1,19 +1,26 @@
{{ define "body" }}
{{ $y := .model.Year }}
{{ range $year := .model.AvailableYears }}
<a href="/{{ $year }}">{{ $year }}</a>
<a href="/{{ $year }}" aria-active="{{ eq $year $y }}">{{ $year }}</a>
{{ end }}
{{ range $issue := .model.Issues }}
<div>
<div>
{{ $issue.Number.Chardata }}
</div>
<div>
{{ index $issue.Month 1 }}
</div>
<div>
{{ index $issue.Weekday 1 }}
</div>
<div>{{ $issue.Day }}.{{ index $issue.Month 2 }}.</div>
</div>
{{ range $index, $month := .model.Issues }}
<!-- Month Header -->
{{ $first := index $month 0 }}
<h2>{{ index $first.Month 1 }}</h2>
<!-- Issues -->
{{ range $issue := $month }}
<a href="/{{ $y }}/{{ $issue.Number.Chardata }}">
<div>
{{ $issue.Number.Chardata }}
</div>
<div>
{{ index $issue.Weekday 1 }}
</div>
<div>{{ $issue.Day }}.{{ index $issue.Month 2 }}.</div>
</a>
{{ end }}
{{ end }}
{{ end }}

View File

@@ -0,0 +1 @@
Hello from an issue!