diff --git a/app/kgpz.go b/app/kgpz.go
index ef9adc8..08b5c6e 100644
--- a/app/kgpz.go
+++ b/app/kgpz.go
@@ -87,7 +87,7 @@ func (k *KGPZ) Enrich() error {
// INFO: We pass agents by value since we don't want to block the library
agents := k.Library.Agents.Everything()
- go func(agents []xmlprovider.Agent) {
+ go func(agents []*xmlprovider.Agent) {
k.GND.FetchPersons(agents)
k.GND.WriteCache(k.Config.GNDPath)
}(agents)
diff --git a/providers/gnd/gnd.go b/providers/gnd/gnd.go
index cf8e293..9299025 100644
--- a/providers/gnd/gnd.go
+++ b/providers/gnd/gnd.go
@@ -168,7 +168,7 @@ func (p *GNDProvider) Person(id string) *Person {
return &pers
}
-func (p *GNDProvider) FetchPersons(persons []xmlprovider.Agent) {
+func (p *GNDProvider) FetchPersons(persons []*xmlprovider.Agent) {
wg := sync.WaitGroup{}
for _, person := range persons {
if person.ID == "" || person.GND == "" {
@@ -187,9 +187,9 @@ func (p *GNDProvider) FetchPersons(persons []xmlprovider.Agent) {
p.errmu.Unlock()
wg.Add(1)
- go func(person xmlprovider.Agent) {
+ go func(person *xmlprovider.Agent) {
defer wg.Done()
- p.fetchPerson(person)
+ p.fetchPerson(*person)
}(person)
}
wg.Wait()
diff --git a/providers/xmlprovider/issues.go b/providers/xmlprovider/issues.go
index 5d76140..b4d6bc1 100644
--- a/providers/xmlprovider/issues.go
+++ b/providers/xmlprovider/issues.go
@@ -24,9 +24,9 @@ type Nummer struct {
type Additional struct {
XMLName xml.Name `xml:"beilage"`
- Nummer string `xml:"nummer,attr"`
- Von string `xml:"von"`
- Bis string `xml:"bis"`
+ Nummer int `xml:"nummer,attr"`
+ Von int `xml:"von"`
+ Bis int `xml:"bis"`
}
func (i Issue) GetIDs() []string {
diff --git a/providers/xmlprovider/xmlprovider.go b/providers/xmlprovider/xmlprovider.go
index d36fadd..da30bec 100644
--- a/providers/xmlprovider/xmlprovider.go
+++ b/providers/xmlprovider/xmlprovider.go
@@ -22,21 +22,18 @@ type XMLItem interface {
GetIDs() []string
}
-type Collection[T XMLItem] struct {
- Collection []T
- lock sync.Mutex
-}
-
// An XMLProvider is a struct that holds holds serialized XML data of a specific type. It combines multiple parses IF a succeeded parse can not serialize the data from a path.
type XMLProvider[T XMLItem] struct {
Paths []string
- // INFO: map is type [string]T
+ // INFO: map is type [string]*T
Items sync.Map
// INFO: map is type [string]ItemInfo
// It keeps information about parsing status of the items.
Infos sync.Map
- mu sync.Mutex
+ mu sync.Mutex
+ // TODO: This is not populated yet
+ Array []T
failed []string
parses []ParseMeta
}
@@ -74,13 +71,16 @@ func (p *XMLProvider[T]) Serialize(dataholder XMLRootElement[T], path string) er
// INFO: Mostly it's just one ID, so the double loop is not that bad.
for _, id := range item.GetIDs() {
p.Infos.Store(id, ItemInfo{Source: path, Parse: commit})
- p.Items.Store(id, item)
+ p.Items.Store(id, &item)
}
}
return nil
}
+// INFO: Cleanup is called after all paths have been serialized.
+// It deletes all items that have not been parsed in the last commit,
+// and whose filepath has not been marked as failed.
func (p *XMLProvider[T]) Cleanup() {
p.mu.Lock()
defer p.mu.Unlock()
@@ -147,26 +147,26 @@ func (p *XMLProvider[T]) Item(id string) *T {
return nil
}
- i := item.(T)
- return &i
+ i := item.(*T)
+ return i
}
-func (p *XMLProvider[T]) Find(fn func(T) bool) []T {
- var items []T
+func (p *XMLProvider[T]) Find(fn func(*T) bool) []*T {
+ var items []*T
p.Items.Range(func(key, value interface{}) bool {
- if fn(value.(T)) {
- items = append(items, value.(T))
+ if fn(value.(*T)) {
+ items = append(items, value.(*T))
}
return true
})
return items
}
-func (p *XMLProvider[T]) FindKey(fn func(string) bool) []T {
- var items []T
+func (p *XMLProvider[T]) FindKey(fn func(string) bool) []*T {
+ var items []*T
p.Items.Range(func(key, value interface{}) bool {
if fn(key.(string)) {
- items = append(items, value.(T))
+ items = append(items, value.(*T))
}
return true
})
@@ -177,10 +177,10 @@ func (p *XMLProvider[T]) FindKey(fn func(string) bool) []T {
// Maps are slow to iterate, but many of the Iterations can only be done once, so it doesn´t matter for a
// few thousand objects. We prefer to lookup objects by key and have multiple meaningful keys; along with
// sensible caching rules to keep the application responsive.
-func (p *XMLProvider[T]) Everything() []T {
- var items []T
+func (p *XMLProvider[T]) Everything() []*T {
+ var items []*T
p.Items.Range(func(key, value interface{}) bool {
- items = append(items, value.(T))
+ items = append(items, value.(*T))
return true
})
return items
diff --git a/server/server.go b/server/server.go
index 69d0a50..96b3203 100644
--- a/server/server.go
+++ b/server/server.go
@@ -20,17 +20,30 @@ import (
const (
// INFO: This timeout is stupid. Uploads can take a long time, others might not. It's messy.
- REQUEST_TIMEOUT = 8 * time.Second
- SERVER_TIMEOUT = 8 * time.Second
+ REQUEST_TIMEOUT = 16 * time.Second
+ SERVER_TIMEOUT = 16 * time.Second
+ // INFO: Maybe this is too long/short?
CACHE_TIME = 24 * time.Hour
+)
- STATIC_PREFIX = "/assets"
+const (
+ ASSETS_URL_PREFIX = "/assets"
EDITION_URL = "/edition/"
PRIVACY_URL = "/datenschutz/"
CONTACT_URL = "/kontakt/"
CITATION_URL = "/zitation/"
+
+ INDEX_URL = "/1764"
+
+ YEAR_OVERVIEW_URL = "/:year"
+ PLACE_OVERVIEW_URL = "/ort/:place"
+ AGENTS_OVERVIEW_URL = "/akteure/:letterorid"
+ CATEGORY_OVERVIEW_URL = "/kategorie/:category"
+
+ ISSSUE_URL = "/:year/:issue/:page?"
+ ADDITIONS_URL = "/:year/:issue/beilage/:page?"
)
const (
@@ -120,7 +133,7 @@ func (s *Server) Start() {
srv.Use(recover.New())
- srv.Use("assets", static(&views.StaticFS))
+ srv.Use(ASSETS_URL_PREFIX, static(&views.StaticFS))
// TODO: Dont cache static assets, bc storage gets huge
// INFO: Maybe fiber does this already?
@@ -144,18 +157,19 @@ func (s *Server) Start() {
// And probably creates problems with static files, and in case we add a front page later.
// That's why we redirect to /1764 on "/ " and don´t use an optional /:year?
srv.Get("/", func(c *fiber.Ctx) error {
- c.Redirect("/1764")
+ c.Redirect(INDEX_URL)
return nil
})
- srv.Get("/ort/:place?", controllers.GetPlace(s.kgpz))
- srv.Get("/kategorie/:category?", controllers.GetCategory(s.kgpz))
- srv.Get("/akteure/:letterorid?", controllers.GetAgents(s.kgpz))
+
+ srv.Get(PLACE_OVERVIEW_URL, controllers.GetPlace(s.kgpz))
+ srv.Get(CATEGORY_OVERVIEW_URL, controllers.GetCategory(s.kgpz))
+ srv.Get(AGENTS_OVERVIEW_URL, controllers.GetAgents(s.kgpz))
// TODO: Same here, this prob applies to all paths with two or three segments, which is bad.
// Prob better to do /ausgabe/:year/:issue/:page? here and /jahrgang/:year? above.
- srv.Get("/:year", controllers.GetYear(s.kgpz))
- srv.Get("/:year/:issue/:page?", controllers.GetIssue(s.kgpz))
- srv.Get("/:year/:issue/beilage/:page?", controllers.GetIssue(s.kgpz))
+ srv.Get(YEAR_OVERVIEW_URL, controllers.GetYear(s.kgpz))
+ srv.Get(ISSSUE_URL, controllers.GetIssue(s.kgpz))
+ srv.Get(ADDITIONS_URL, controllers.GetIssue(s.kgpz))
srv.Get(EDITION_URL, controllers.Get(EDITION_URL))
srv.Get(PRIVACY_URL, controllers.Get(PRIVACY_URL))
diff --git a/viewmodels/agentsvm.go b/viewmodels/agentsvm.go
index dc8d108..9a06b1a 100644
--- a/viewmodels/agentsvm.go
+++ b/viewmodels/agentsvm.go
@@ -8,6 +8,8 @@ import (
type AgentView struct {
Agents []xmlprovider.Agent
+ Works map[string][]xmlprovider.Work
+ Pieces map[string][]xmlprovider.Piece
}
func AgentsView(letterorid string, lib *xmlprovider.Library) *AgentView {
@@ -21,5 +23,36 @@ func AgentsView(letterorid string, lib *xmlprovider.Library) *AgentView {
return true
})
+ res.Works = make(map[string][]xmlprovider.Work)
+ res.Pieces = make(map[string][]xmlprovider.Piece)
+
+ lib.Works.Items.Range(func(key, value interface{}) bool {
+ w := value.(xmlprovider.Work)
+ for _, a := range res.Agents {
+ if strings.HasPrefix(a.ID, letterorid) {
+ _, ok := res.Works[a.ID]
+ if !ok {
+ res.Works[a.ID] = []xmlprovider.Work{}
+ }
+ res.Works[a.ID] = append(res.Works[a.ID], w)
+ }
+ }
+ return true
+ })
+
+ lib.Pieces.Items.Range(func(key, value interface{}) bool {
+ p := value.(xmlprovider.Piece)
+ for _, a := range res.Agents {
+ if strings.HasPrefix(a.ID, letterorid) {
+ _, ok := res.Pieces[a.ID]
+ if !ok {
+ res.Pieces[a.ID] = []xmlprovider.Piece{}
+ }
+ res.Pieces[a.ID] = append(res.Pieces[a.ID], p)
+ }
+ }
+ return true
+ })
+
return &res
}
diff --git a/viewmodels/issuevm.go b/viewmodels/issuevm.go
index 2193bda..3ade4b4 100644
--- a/viewmodels/issuevm.go
+++ b/viewmodels/issuevm.go
@@ -10,7 +10,7 @@ import (
const TLAYOUT = "2006-01-02"
type IssueViewModel struct {
- xmlprovider.Issue
+ *xmlprovider.Issue
Day int
Month int
Year int
@@ -23,11 +23,11 @@ func IssueView(y string, No string, lib *xmlprovider.Library) (*IssueViewModel,
return nil, errors.New("Issue not found")
}
- return FromIssue(*issue)
+ return FromIssue(issue)
}
-func FromIssue(i xmlprovider.Issue) (*IssueViewModel, error) {
+func FromIssue(i *xmlprovider.Issue) (*IssueViewModel, error) {
t, err := time.Parse(TLAYOUT, i.Datum.When)
if err != nil {
return nil, err
diff --git a/viewmodels/piecevm.go b/viewmodels/piecevm.go
index ac239fa..643c290 100644
--- a/viewmodels/piecevm.go
+++ b/viewmodels/piecevm.go
@@ -5,12 +5,12 @@ import (
)
type PieceViewModel struct {
- xmlprovider.Piece
+ *xmlprovider.Piece
// TODO: this is a bit hacky, but it refences the page number of the piece in the issue
Von int
Bis int
}
-func NewPieceView(p xmlprovider.Piece) (PieceViewModel, error) {
+func NewPieceView(p *xmlprovider.Piece) (PieceViewModel, error) {
return PieceViewModel{Piece: p}, nil
}
diff --git a/viewmodels/singleissuevm.go b/viewmodels/singleissuevm.go
index 9fffbb1..ae820f2 100644
--- a/viewmodels/singleissuevm.go
+++ b/viewmodels/singleissuevm.go
@@ -28,10 +28,6 @@ func NewSingleIssueView(y string, No string, lib *xmlprovider.Library) (*SingleI
return nil, err
}
- if err != nil {
- return nil, err
- }
-
no, err := strconv.Atoi(No)
if err != nil {
return nil, err
@@ -61,7 +57,7 @@ func (issue *SingleIssueViewModel) PiecesForIsssue(lib *xmlprovider.Library) err
lib.Pieces.Items.Range(func(key, value interface{}) bool {
k := key.(string)
if strings.HasPrefix(k, lookfor) {
- a := value.(xmlprovider.Piece)
+ a := value.(*xmlprovider.Piece)
p, err := NewPieceView(a)
if err != nil {
logging.ObjErr(&a, err)
diff --git a/viewmodels/yearvm.go b/viewmodels/yearvm.go
index 7ec0f95..3145bac 100644
--- a/viewmodels/yearvm.go
+++ b/viewmodels/yearvm.go
@@ -35,7 +35,7 @@ func YearView(year string, lib *xmlprovider.Library) (*YearViewModel, error) {
}
if date == year {
- issue := value.(xmlprovider.Issue)
+ issue := value.(*xmlprovider.Issue)
res.PushIssue(issue)
}
return true
@@ -55,7 +55,7 @@ func (y *YearViewModel) Sort() {
y.Issues.Sort()
}
-func (y *YearViewModel) PushIssue(i xmlprovider.Issue) {
+func (y *YearViewModel) PushIssue(i *xmlprovider.Issue) {
iv, err := FromIssue(i)
if err != nil {
return
diff --git a/views/assets/css/fonts.css b/views/assets/css/fonts.css
new file mode 100644
index 0000000..55440cd
--- /dev/null
+++ b/views/assets/css/fonts.css
@@ -0,0 +1,71 @@
+@font-face {
+ font-family: "Rancho";
+ font-style: normal;
+ font-weight: 500;
+ font-display: swap;
+ src: url(/assets/fonts/Rancho-Regular.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Merriweather";
+ font-style: normal;
+ font-weight: 500;
+ font-display: swap;
+ src: url(/assets/fonts/Merriweather-Regular.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Merriweather";
+ font-style: italic;
+ font-weight: 500;
+ font-display: swap;
+ src: url(/assets/fonts/Merriweather-Italic.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Merriweather";
+ font-style: normal;
+ font-weight: bold;
+ font-display: swap;
+ src: url(/assets/fonts/Merriweather-Bold.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Merriweather";
+ font-style: italic;
+ font-weight: bold;
+ font-display: swap;
+ src: url(/assets/fonts/SourceSans3-BoldItalic.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Source Sans 3";
+ font-style: normal;
+ font-weight: 500;
+ font-display: swap;
+ src: url(/assets/fonts/SourceSans3-Medium.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Source Sans 3";
+ font-style: italic;
+ font-weight: 500;
+ font-display: swap;
+ src: url(/assets/fonts/SourceSans3-MediumItalic.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Source Sans 3";
+ font-style: normal;
+ font-weight: bold;
+ font-display: swap;
+ src: url(/assets/fonts/SourceSans3-Bold.ttf) format("truetype");
+}
+
+@font-face {
+ font-family: "Source Sans 3";
+ font-style: italic;
+ font-weight: bold;
+ font-display: swap;
+ src: url(/assets/fonts/SourceSans3-BoldItalic.ttf) format("truetype");
+}
diff --git a/views/assets/scripts.js b/views/assets/scripts.js
index 5af9d6c..1c3f876 100644
--- a/views/assets/scripts.js
+++ b/views/assets/scripts.js
@@ -1,31 +1,22 @@
-function setup() {
- let templates = document.querySelectorAll("template[simple]");
- templates.forEach((template) => {
- let templateId = template.getAttribute("id");
- let templateContent = template.content;
- customElements.define(templateId, class extends HTMLElement {
+function a() {
+ document.querySelectorAll("template[simple]").forEach((l) => {
+ let s = l.getAttribute("id"), n = l.content;
+ customElements.define(s, class extends HTMLElement {
constructor() {
- super();
- this.appendChild(templateContent.cloneNode(true));
- this.slots = this.querySelectorAll("slot");
+ super(), this.appendChild(n.cloneNode(!0)), this.slots = this.querySelectorAll("slot");
}
connectedCallback() {
- let toremove = [];
- this.slots.forEach((tslot) => {
- let slotName = tslot.getAttribute("name");
- let slotContent = this.querySelector(`[slot="${slotName}"]`);
- if (slotContent) {
- tslot.replaceWith(slotContent.cloneNode(true));
- toremove.push(slotContent);
- }
- });
- toremove.forEach((element) => {
- element.remove();
+ let o = [];
+ this.slots.forEach((e) => {
+ let r = e.getAttribute("name"), t = this.querySelector(`[slot="${r}"]`);
+ t && (e.replaceWith(t.cloneNode(!0)), o.push(t));
+ }), o.forEach((e) => {
+ e.remove();
});
}
});
});
}
export {
- setup
+ a as setup
};
diff --git a/views/assets/style.css b/views/assets/style.css
index e6fb2f9..ef8d43d 100644
--- a/views/assets/style.css
+++ b/views/assets/style.css
@@ -554,114 +554,6 @@ video {
display: none;
}
-@font-face {
- font-family: "Rancho";
-
- font-style: normal;
-
- font-weight: 500;
-
- font-display: swap;
-
- src: url(/publi/public/fonts/Rancho-Regular.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Merriweather";
-
- font-style: normal;
-
- font-weight: 500;
-
- font-display: swap;
-
- src: url(/public/fonts/Merriweather-Regular.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Merriweather";
-
- font-style: italic;
-
- font-weight: 500;
-
- font-display: swap;
-
- src: url(/public/fonts/Merriweather-Italic.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Merriweather";
-
- font-style: normal;
-
- font-weight: bold;
-
- font-display: swap;
-
- src: url(/public/fonts/Merriweather-Bold.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Merriweather";
-
- font-style: italic;
-
- font-weight: bold;
-
- font-display: swap;
-
- src: url(/public/fonts/SourceSans3-BoldItalic.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Source Sans 3";
-
- font-style: normal;
-
- font-weight: 500;
-
- font-display: swap;
-
- src: url(/public/fonts/SourceSans3-Medium.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Source Sans 3";
-
- font-style: italic;
-
- font-weight: 500;
-
- font-display: swap;
-
- src: url(/public/fonts/SourceSans3-MediumItalic.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Source Sans 3";
-
- font-style: normal;
-
- font-weight: bold;
-
- font-display: swap;
-
- src: url(/public/fonts/SourceSans3-Bold.ttf) format("truetype");
-}
-
-@font-face {
- font-family: "Source Sans 3";
-
- font-style: italic;
-
- font-weight: bold;
-
- font-display: swap;
-
- src: url(/public/fonts/SourceSans3-BoldItalic.ttf) format("truetype");
-}
-
html {
font-size: 15.5px;
}
diff --git a/views/layouts/default/root.gohtml b/views/layouts/default/root.gohtml
index ba4f0c1..323c983 100644
--- a/views/layouts/default/root.gohtml
+++ b/views/layouts/default/root.gohtml
@@ -14,12 +14,14 @@
{{ end }}
-
+
+
+