From e8ff6d3d3725056c565dc3eeda2fc8b7868ab5f6 Mon Sep 17 00:00:00 2001 From: Simon Martens Date: Sat, 27 Sep 2025 17:44:34 +0200 Subject: [PATCH] Refined orte --- app/kgpz.go | 361 +++++++-- controllers/filter_controller.go | 2 + controllers/ort_controller.go | 15 +- providers/search/searchprovider.go | 27 + templating/engine.go | 2 +- views/assets/scripts.js | 185 +++-- views/assets/style.css | 2 +- views/routes/filter/body.gohtml | 14 +- views/routes/ort/body.gohtml | 722 ------------------ .../ort/components/_back_navigation.gohtml | 8 + .../routes/ort/components/_place_card.gohtml | 42 + .../ort/components/_place_header.gohtml | 71 ++ .../ort/components/_place_pieces.gohtml | 98 +++ views/routes/ort/detail/body.gohtml | 8 + views/routes/ort/detail/head.gohtml | 36 + views/routes/ort/head.gohtml | 42 - views/routes/ort/overview/body.gohtml | 27 + views/routes/ort/overview/head.gohtml | 3 + views/transform/main.js | 1 + views/transform/places.js | 122 +++ 20 files changed, 882 insertions(+), 906 deletions(-) delete mode 100644 views/routes/ort/body.gohtml create mode 100644 views/routes/ort/components/_back_navigation.gohtml create mode 100644 views/routes/ort/components/_place_card.gohtml create mode 100644 views/routes/ort/components/_place_header.gohtml create mode 100644 views/routes/ort/components/_place_pieces.gohtml create mode 100644 views/routes/ort/detail/body.gohtml create mode 100644 views/routes/ort/detail/head.gohtml delete mode 100644 views/routes/ort/head.gohtml create mode 100644 views/routes/ort/overview/body.gohtml create mode 100644 views/routes/ort/overview/head.gohtml create mode 100644 views/transform/places.js diff --git a/app/kgpz.go b/app/kgpz.go index 749401a..4ed43c2 100644 --- a/app/kgpz.go +++ b/app/kgpz.go @@ -221,6 +221,178 @@ func (k *KGPZ) Funcs() map[string]interface{} { e["contains"] = func(s, substr string) bool { return strings.Contains(s, substr) } e["lower"] = func(s string) string { return strings.ToLower(s) } + // Place helper functions + e["GetModernCountryName"] = func(geoID string) string { + if geoID == "" || k.Geonames == nil { + return "" + } + + geoPlace := k.Geonames.Place(geoID) + if geoPlace == nil { + return "" + } + + // Map country names to German translations + switch geoPlace.CountryName { + case "France": + return "heutiges Frankreich" + case "United Kingdom": + return "heutiges Großbritannien" + case "Russia": + return "heutiges Russland" + case "Czech Republic", "Czechia": + return "heutiges Tschechien" + case "Netherlands", "The Netherlands": + return "heutige Niederlande" + case "Poland": + return "heutiges Polen" + case "Switzerland": + return "heutige Schweiz" + case "Latvia": + return "heutiges Lettland" + case "Sweden": + return "heutiges Schweden" + case "Austria": + return "heutiges Österreich" + case "Belgium": + return "heutiges Belgien" + case "Slovakia": + return "heutige Slowakei" + case "Finland": + return "heutiges Finnland" + case "Denmark": + return "heutiges Dänemark" + default: + // Return original country name for unknown countries (excluding Germany) + if geoPlace.CountryName != "Germany" && geoPlace.CountryName != "" { + return geoPlace.CountryName + } + return "" + } + } + + e["GetFullPlaceInfo"] = func(geoID string, originalName string) string { + if geoID == "" || k.Geonames == nil { + return "" + } + + geoPlace := k.Geonames.Place(geoID) + if geoPlace == nil { + return "" + } + + // Only show info for places outside Germany + if geoPlace.CountryName == "Germany" || geoPlace.CountryName == "" { + return "" + } + + // Get the modern country name + countryName := "" + switch geoPlace.CountryName { + case "France": + countryName = "heutiges Frankreich" + case "United Kingdom": + countryName = "heutiges Großbritannien" + case "Russia": + countryName = "heutiges Russland" + case "Czech Republic", "Czechia": + countryName = "heutiges Tschechien" + case "Netherlands", "The Netherlands": + countryName = "heutige Niederlande" + case "Poland": + countryName = "heutiges Polen" + case "Switzerland": + countryName = "heutige Schweiz" + case "Latvia": + countryName = "heutiges Lettland" + case "Sweden": + countryName = "heutiges Schweden" + case "Austria": + countryName = "heutiges Österreich" + case "Belgium": + countryName = "heutiges Belgien" + case "Slovakia": + countryName = "heutige Slowakei" + case "Finland": + countryName = "heutiges Finnland" + case "Denmark": + countryName = "heutiges Dänemark" + default: + countryName = geoPlace.CountryName + } + + // Extract German alternate name (same logic as GetModernPlaceName) + modernName := "" + hasGermanName := false + + for _, altName := range geoPlace.AlternateNames { + if altName.Lang == "de" { + hasGermanName = true + if altName.IsPreferredName { + modernName = altName.Name + break + } else if modernName == "" { + modernName = altName.Name + } + } + } + + if !hasGermanName { + modernName = geoPlace.ToponymName + } + + // Combine country and modern place name + result := countryName + if modernName != "" && strings.ToLower(modernName) != strings.ToLower(originalName) { + result += ", " + modernName + } + + return result + } + + e["GetModernPlaceName"] = func(geoID string, originalName string) string { + if geoID == "" || k.Geonames == nil { + return "" + } + + geoPlace := k.Geonames.Place(geoID) + if geoPlace == nil { + return "" + } + + // Only show modern names for places outside Germany + if geoPlace.CountryName == "Germany" || geoPlace.CountryName == "" { + return "" + } + + // Extract German alternate name + modernName := "" + hasGermanName := false + + for _, altName := range geoPlace.AlternateNames { + if altName.Lang == "de" { + hasGermanName = true + if altName.IsPreferredName { + modernName = altName.Name + break + } else if modernName == "" { + modernName = altName.Name + } + } + } + + if !hasGermanName { + modernName = geoPlace.ToponymName + } + + // Only return if it's different from the original name + if modernName != "" && strings.ToLower(modernName) != strings.ToLower(originalName) { + return modernName + } + + return "" + } + e["LookupPieces"] = k.Library.Pieces.ReverseLookup e["LookupWorks"] = k.Library.Works.ReverseLookup e["LookupIssues"] = k.Library.Issues.ReverseLookup @@ -263,6 +435,126 @@ func (k *KGPZ) Enrich() error { return nil } +// EnrichAndRebuildIndex ensures enrichment completes before rebuilding search index +func (k *KGPZ) EnrichAndRebuildIndex() error { + if k.Library == nil || k.Library.Agents == nil { + return nil + } + + go func() { + k.fsmu.Lock() + defer k.fsmu.Unlock() + + logging.Info("Starting enrichment process...") + + // Fetch GND data for agents + data := xmlmodels.AgentsIntoDataset(k.Library.Agents) + k.GND.FetchPersons(data) + k.GND.WriteCache(filepath.Join(k.Config.BaseDIR, k.Config.GNDPath)) + + // Fetch Geonames data for places + if k.Library.Places != nil { + placeData := xmlmodels.PlacesIntoDataset(k.Library.Places) + k.Geonames.FetchPlaces(placeData) + k.Geonames.WriteCache(filepath.Join(k.Config.BaseDIR, k.Config.GeoPath)) + } + + logging.Info("Enrichment complete. Starting search index rebuild...") + + // Clear existing indices before rebuilding + k.ClearSearchIndices() + + // Rebuild search index after enrichment is complete + k.buildSearchIndexSync() + }() + + return nil +} + +// ClearSearchIndices removes all existing search indices +func (k *KGPZ) ClearSearchIndices() error { + if k.Search == nil { + return nil + } + + return k.Search.ClearAllIndices() +} + +// buildSearchIndexSync builds the search index synchronously (no goroutine) +func (k *KGPZ) buildSearchIndexSync() error { + if k.Library == nil || k.Library.Agents == nil || k.Search == nil { + return nil + } + + wg := new(sync.WaitGroup) + wg.Add(6) + + go func() { + for _, agent := range k.Library.Agents.Array { + err := k.Search.Index(agent, k.Library) + if err != nil { + logging.Error(err, "Error indexing agent") + } + } + wg.Done() + }() + + go func() { + for _, place := range k.Library.Places.Array { + err := k.Search.Index(place, k.Library) + if err != nil { + logging.Error(err, "Error indexing place") + } + } + wg.Done() + }() + + go func() { + for _, cat := range k.Library.Categories.Array { + err := k.Search.Index(cat, k.Library) + if err != nil { + logging.Error(err, "Error indexing category") + } + } + wg.Done() + }() + + go func() { + for _, work := range k.Library.Works.Array { + err := k.Search.Index(work, k.Library) + if err != nil { + logging.Error(err, "Error indexing work") + } + } + wg.Done() + }() + + go func() { + for _, issue := range k.Library.Issues.Array { + err := k.Search.Index(issue, k.Library) + if err != nil { + logging.Error(err, "Error indexing issue") + } + } + wg.Done() + }() + + go func() { + for _, piece := range k.Library.Pieces.Array { + err := k.Search.Index(piece, k.Library) + if err != nil { + logging.Error(err, "Error indexing piece") + } + } + wg.Done() + }() + + wg.Wait() + logging.Info("Search index built.") + + return nil +} + func (k *KGPZ) BuildSearchIndex() error { if k.Library == nil || k.Library.Agents == nil || k.Search == nil { return nil @@ -271,71 +563,7 @@ func (k *KGPZ) BuildSearchIndex() error { go func() { k.fsmu.Lock() defer k.fsmu.Unlock() - wg := new(sync.WaitGroup) - wg.Add(6) - go func() { - for _, agent := range k.Library.Agents.Array { - err := k.Search.Index(agent, k.Library) - if err != nil { - logging.Error(err, "Error indexing agent") - } - } - wg.Done() - }() - - go func() { - for _, place := range k.Library.Places.Array { - err := k.Search.Index(place, k.Library) - if err != nil { - logging.Error(err, "Error indexing place") - } - } - wg.Done() - }() - - go func() { - for _, cat := range k.Library.Categories.Array { - err := k.Search.Index(cat, k.Library) - if err != nil { - logging.Error(err, "Error indexing category") - } - } - wg.Done() - }() - - go func() { - for _, work := range k.Library.Works.Array { - err := k.Search.Index(work, k.Library) - if err != nil { - logging.Error(err, "Error indexing work") - } - } - wg.Done() - }() - - go func() { - for _, issue := range k.Library.Issues.Array { - err := k.Search.Index(issue, k.Library) - if err != nil { - logging.Error(err, "Error indexing issue") - } - } - wg.Done() - }() - - go func() { - for _, piece := range k.Library.Pieces.Array { - err := k.Search.Index(piece, k.Library) - if err != nil { - logging.Error(err, "Error indexing piece") - } - } - wg.Done() - }() - - wg.Wait() - logging.Info("Search index built.") - + k.buildSearchIndexSync() }() return nil } @@ -380,8 +608,7 @@ func (k *KGPZ) Pull() { if changed { logging.ObjDebug(&k.Repo, "Remote changed. Reparsing") k.Serialize() - k.Enrich() - k.BuildSearchIndex() + k.EnrichAndRebuildIndex() } } diff --git a/controllers/filter_controller.go b/controllers/filter_controller.go index 35f0da5..286b22e 100644 --- a/controllers/filter_controller.go +++ b/controllers/filter_controller.go @@ -127,6 +127,7 @@ func GetQuickFilter(kgpz *xmlmodels.Library) fiber.Handler { placeSummary := PlaceSummary{ ID: place.ID, Name: name, + Geo: place.Geo, } places = append(places, placeSummary) @@ -164,6 +165,7 @@ type PersonSummary struct { type PlaceSummary struct { ID string Name string + Geo string } // IssueSummary represents an issue for the Jahr/Ausgabe filter diff --git a/controllers/ort_controller.go b/controllers/ort_controller.go index ac3847d..f35193a 100644 --- a/controllers/ort_controller.go +++ b/controllers/ort_controller.go @@ -33,8 +33,17 @@ func GetPlace(kgpz *xmlmodels.Library) fiber.Handler { return c.SendStatus(fiber.StatusNotFound) } - return c.Render("/ort/", fiber.Map{ - "model": places, - }) + // Render different templates based on whether we're showing list or detail view + if places.SelectedPlace != nil { + // Individual place detail view + return c.Render("/ort/detail/", fiber.Map{ + "model": places, + }) + } else { + // Places overview/list view + return c.Render("/ort/overview/", fiber.Map{ + "model": places, + }) + } } } diff --git a/providers/search/searchprovider.go b/providers/search/searchprovider.go index 7b9c724..c855e20 100644 --- a/providers/search/searchprovider.go +++ b/providers/search/searchprovider.go @@ -2,6 +2,7 @@ package searchprovider import ( "errors" + "os" "path/filepath" "sync" @@ -161,3 +162,29 @@ func default_mapping() (*mapping.IndexMappingImpl, error) { indexMapping.DefaultAnalyzer = "customNgramAnalyzer" return indexMapping, nil } + +// ClearAllIndices closes and removes all search indices +func (sp *SearchProvider) ClearAllIndices() error { + // Close all open indices + sp.indeces.Range(func(key, value interface{}) bool { + if index, ok := value.(bleve.Index); ok { + index.Close() + } + return true + }) + + // Clear the sync.Map + sp.indeces = sync.Map{} + + // Remove all .bleve directories from disk + files, err := filepath.Glob(filepath.Join(sp.basepath, "*.bleve")) + if err != nil { + return err + } + + for _, file := range files { + os.RemoveAll(file) + } + + return nil +} diff --git a/templating/engine.go b/templating/engine.go index de04c85..705e518 100644 --- a/templating/engine.go +++ b/templating/engine.go @@ -497,7 +497,7 @@ func (e *Engine) Render(out io.Writer, path string, data interface{}, layout ... l = lay } else { if layout[0] == "clear" { - lay, err := template.New("clear").Parse(CLEAR_LAYOUT) + lay, err := template.New("clear").Funcs(e.FuncMap).Parse(CLEAR_LAYOUT) if err != nil { return err } diff --git a/views/assets/scripts.js b/views/assets/scripts.js index 6c6e6b9..73ecb5f 100644 --- a/views/assets/scripts.js +++ b/views/assets/scripts.js @@ -433,8 +433,8 @@ class O extends HTMLElement { if (!o && !r) { const c = n.querySelector("div:first-child"); if (c) { - const d = c.getBoundingClientRect(), u = d.top >= 0, g = d.bottom <= window.innerHeight; - u && g && (l = !0); + const d = c.getBoundingClientRect(), u = d.top >= 0, h = d.bottom <= window.innerHeight; + u && h && (l = !0); } } l && e.push(s); @@ -451,8 +451,8 @@ class O extends HTMLElement { const n = document.getElementById("scrollspy-nav"), s = n.getBoundingClientRect(); let o = 1 / 0, r = -1 / 0; t.forEach((c) => { - const d = c.getBoundingClientRect(), u = d.top - s.top + n.scrollTop, g = u + d.height; - o = Math.min(o, u), r = Math.max(r, g); + const d = c.getBoundingClientRect(), u = d.top - s.top + n.scrollTop, h = u + d.height; + o = Math.min(o, u), r = Math.max(r, h); }); let l = r - o; i.style.top = `${o}px`, i.style.height = `${l}px`, i.style.opacity = "1", setTimeout(() => this.ensureMarkerVisibility(), 100); @@ -490,8 +490,8 @@ class O extends HTMLElement { document.documentElement.offsetHeight ), s = window.innerHeight, o = n - s, r = o > 0 ? window.scrollY / o : 0, l = t.clientHeight, d = t.scrollHeight - l; if (d > 0) { - const u = r * d, g = i.getBoundingClientRect(), p = t.getBoundingClientRect(), f = g.top - p.top + t.scrollTop, m = l / 2, q = f - m, v = 0.7, I = v * u + (1 - v) * q, y = Math.max(0, Math.min(d, I)), T = t.scrollTop; - Math.abs(y - T) > 10 && t.scrollTo({ + const u = r * d, h = i.getBoundingClientRect(), p = t.getBoundingClientRect(), f = h.top - p.top + t.scrollTop, m = l / 2, I = f - m, v = 0.7, T = v * u + (1 - v) * I, y = Math.max(0, Math.min(d, T)), q = t.scrollTop; + Math.abs(y - q) > 10 && t.scrollTo({ top: y, behavior: "smooth" }); @@ -512,6 +512,59 @@ class O extends HTMLElement { } } customElements.define("akteure-scrollspy", O); +class $ extends HTMLElement { + constructor() { + super(), this.searchInput = null, this.placeCards = [], this.countElement = null, this.debounceTimer = null, this.originalCount = 0; + } + connectedCallback() { + this.render(), this.setupEventListeners(), this.initializePlaceCards(); + } + disconnectedCallback() { + this.cleanupEventListeners(), this.debounceTimer && clearTimeout(this.debounceTimer); + } + render() { + this.innerHTML = ` +
+ +
+ `; + } + setupEventListeners() { + this.searchInput = this.querySelector("#places-search"), this.searchInput && this.searchInput.addEventListener("input", this.handleSearchInput.bind(this)); + } + cleanupEventListeners() { + this.searchInput && this.searchInput.removeEventListener("input", this.handleSearchInput.bind(this)); + } + initializePlaceCards() { + const e = this.closest(".bg-white") || document; + this.placeCards = Array.from(e.querySelectorAll("[data-place-name]")), this.countElement = e.querySelector("[data-places-count]"), this.countElement && (this.originalCount = this.placeCards.length); + } + handleSearchInput(e) { + this.debounceTimer && clearTimeout(this.debounceTimer), this.debounceTimer = setTimeout(() => { + this.filterPlaces(e.target.value.trim()); + }, 150); + } + filterPlaces(e) { + if (!this.placeCards.length) return; + const t = e.toLowerCase(); + let i = 0; + this.placeCards.forEach((n) => { + var l, c; + const s = ((l = n.getAttribute("data-place-name")) == null ? void 0 : l.toLowerCase()) || "", o = ((c = n.getAttribute("data-modern-name")) == null ? void 0 : c.toLowerCase()) || ""; + e === "" || s.includes(t) || o.includes(t) ? (n.style.display = "", i++) : n.style.display = "none"; + }), this.updateCountDisplay(i, e); + } + updateCountDisplay(e, t) { + this.countElement && (t === "" ? this.countElement.textContent = `Alle Orte (${this.originalCount})` : e === 0 ? this.countElement.textContent = `Keine Orte gefunden für "${t}"` : this.countElement.textContent = `${e} von ${this.originalCount} Orten`); + } +} +customElements.define("places-filter", $); class V extends HTMLElement { constructor() { super(), this.resizeObserver = null; @@ -641,14 +694,14 @@ class V extends HTMLElement { show(e, t, i, n = !1, s = 0, o = null, r = null, l = null) { const c = this.querySelector("#single-page-image"), d = this.querySelector("#page-number"), u = this.querySelector("#page-icon"); this.querySelector("#page-indicator"), c.src = e, c.alt = t, this.currentPageNumber = i, this.currentIsBeilage = n, this.currentPartNumber = o; - let g; + let h; if (l) - g = l; + h = l; else { const f = this.getIssueContext(i); - g = f ? `${f}, ${i}` : `${i}`; + h = f ? `${f}, ${i}` : `${i}`; } - if (d.innerHTML = g, s && i === s) { + if (d.innerHTML = h, s && i === s) { d.style.position = "relative"; const f = d.querySelector(".target-page-dot"); f && f.remove(); @@ -843,9 +896,9 @@ class V extends HTMLElement { const d = c.textContent.trim(), u = d.match(/(\d{1,2}\.\d{1,2}\.\d{4}\s+Nr\.\s+\d+)/); if (u) return u[1]; - const g = d.match(/(\d{4})\s+Nr\.\s+(\d+)/); - if (g) - return `${g[1]} Nr. ${g[2]}`; + const h = d.match(/(\d{4})\s+Nr\.\s+(\d+)/); + if (h) + return `${h[1]} Nr. ${h[2]}`; } } const l = document.title.match(/(\d{4}).*Nr\.\s*(\d+)/); @@ -874,7 +927,7 @@ window.addEventListener("beforeunload", function() { const a = document.querySelector("single-page-viewer"); a && a.close(); }); -class $ extends HTMLElement { +class R extends HTMLElement { constructor() { super(), this.isVisible = !1, this.scrollHandler = null, this.htmxAfterSwapHandler = null; } @@ -915,8 +968,8 @@ class $ extends HTMLElement { }); } } -customElements.define("scroll-to-top-button", $); -class R extends HTMLElement { +customElements.define("scroll-to-top-button", R); +class z extends HTMLElement { constructor() { super(), this.pageObserver = null, this.pageContainers = /* @__PURE__ */ new Map(), this.singlePageViewerActive = !1, this.singlePageViewerCurrentPage = null, this.boundHandleSinglePageViewer = this.handleSinglePageViewer.bind(this); } @@ -1001,7 +1054,7 @@ class R extends HTMLElement { } const o = t.getBoundingClientRect(), r = e.getBoundingClientRect(); if (!(r.top >= o.top && r.bottom <= o.bottom)) { - const c = t.scrollTop, d = r.top - o.top + c, u = o.height, g = r.height, p = d - (u - g) / 2; + const c = t.scrollTop, d = r.top - o.top + c, u = o.height, h = r.height, p = d - (u - h) / 2; t.scrollTo({ top: Math.max(0, p), behavior: "smooth" @@ -1035,8 +1088,8 @@ class R extends HTMLElement { this.pageObserver && (this.pageObserver.disconnect(), this.pageObserver = null), document.removeEventListener("singlepageviewer:opened", this.boundHandleSinglePageViewer), document.removeEventListener("singlepageviewer:closed", this.boundHandleSinglePageViewer), document.removeEventListener("singlepageviewer:pagechanged", this.boundHandleSinglePageViewer), this.pageContainers.clear(); } } -customElements.define("inhaltsverzeichnis-scrollspy", R); -class z extends HTMLElement { +customElements.define("inhaltsverzeichnis-scrollspy", z); +class j extends HTMLElement { constructor() { super(), this.innerHTML = ` @@ -154,6 +156,10 @@
{{ $place.Name }} + {{ $modernName := GetModernPlaceName $place.Geo $place.Name }} + {{ if ne $modernName "" }} + {{ $modernName }} + {{ end }}
{{ end }} diff --git a/views/routes/ort/body.gohtml b/views/routes/ort/body.gohtml deleted file mode 100644 index 828d9e8..0000000 --- a/views/routes/ort/body.gohtml +++ /dev/null @@ -1,722 +0,0 @@ -{{ if .model.SelectedPlace }} - -
-
- - - - -
- {{ $geonames := GetGeonames .model.SelectedPlace.Place.Geo }} - - -
-
-

- {{ if .model.SelectedPlace.Place.Names }} - {{ index .model.SelectedPlace.Place.Names 0 }} - {{ else }} - {{ .model.SelectedPlace.Place.ID }} - {{ end }} -

- - - {{ if ne $geonames nil }} -
- - {{ if and (ne $geonames.CountryName "") (ne $geonames.CountryName "Germany") }} -
- {{ $mainPlaceName := "" }} - {{ if .model.SelectedPlace.Place.Names }} - {{ $mainPlaceName = index .model.SelectedPlace.Place.Names 0 }} - {{ end }} - {{ if eq $geonames.CountryName "France" }} - heutiges Frankreich{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "United Kingdom" }} - heutiges Großbritannien{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Russia" }} - heutiges Russland{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if or (eq $geonames.CountryName "Czech Republic") (eq $geonames.CountryName "Czechia") }} - heutiges Tschechien{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if or (eq $geonames.CountryName "Netherlands") (eq $geonames.CountryName "The Netherlands") }} - heutige Niederlande{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Poland" }} - heutiges Polen{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Switzerland" }} - heutige Schweiz{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Latvia" }} - heutiges Lettland{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Sweden" }} - heutiges Schweden{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Austria" }} - heutiges Österreich{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Belgium" }} - heutiges Belgien{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Slovakia" }} - heutige Slowakei{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Finland" }} - heutiges Finnland{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Denmark" }} - heutiges Dänemark{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else }} - {{ $geonames.CountryName }} - {{ end }} -
- {{ end }} - - -
- {{ if and (ne $geonames.Lat "") (ne $geonames.Lng "") }} - - {{ end }} -
-
- {{ else }} - - {{ if .model.SelectedPlace.Place.Geo }} -

- - - Geonames - -

- {{ end }} - {{ end }} -
- - -
- {{ if ne $geonames nil }} - - {{ if ne $geonames.WikipediaURL "" }} - - Wikipedia - - {{ end }} - {{ end }} - - - {{ if .model.SelectedPlace.Place.Geo }} - - - - {{ end }} -
-
-
- - -
-

- Verlinkte Beiträge ({{ len .model.SelectedPlace.Pieces }}) -

- - {{ if .model.SelectedPlace.Pieces }} -
- {{- /* Group pieces by their own title/incipit */ -}} - {{- $groupedPieces := dict -}} - {{- range $_, $p := .model.SelectedPlace.Pieces -}} - {{- $groupKey := "" -}} - {{- if $p.Title -}} - {{- $groupKey = index $p.Title 0 -}} - {{- else if $p.Incipit -}} - {{- $groupKey = index $p.Incipit 0 -}} - {{- else -}} - {{- $groupKey = printf "untitled-%s" $p.ID -}} - {{- end -}} - - {{- $existing := index $groupedPieces $groupKey -}} - {{- if $existing -}} - {{- $groupedPieces = merge $groupedPieces (dict $groupKey (append $existing $p)) -}} - {{- else -}} - {{- $groupedPieces = merge $groupedPieces (dict $groupKey (slice $p)) -}} - {{- end -}} - {{- end -}} - -
- {{- /* Display grouped pieces */ -}} - {{- range $groupKey, $groupedItems := $groupedPieces -}} -
-
- {{- /* Use first piece for display text with colon format for places */ -}} - {{ template "_piece_summary_for_place" (dict "Piece" (index $groupedItems 0) "CurrentActorID" "") }} - - {{- /* Show all citations from all pieces in this group inline with commas */ -}} - {{ " " }}{{- range $groupIndex, $groupItem := $groupedItems -}} - {{- range $issueIndex, $issue := $groupItem.IssueRefs -}} - {{- if or (gt $groupIndex 0) (gt $issueIndex 0) }}, {{ end -}} - {{- template "_citation" $issue -}}{{- end -}} - {{- end -}} - - {{- /* Add "Ganzer Beitrag" link if piece spans multiple issues */ -}} - {{- $firstGroupItem := index $groupedItems 0 -}} - {{- if gt (len $firstGroupItem.IssueRefs) 1 -}} - {{ " " }} - {{- end }} -
-
- {{- end -}} -
-
- {{ else }} -

Keine verlinkten Beiträge für diesen Ort gefunden.

- {{ end }} -
- -
-
- -{{ else }} - -
-
-

Orte

- - - - - {{ if .model.Places }} -
-

- Alle Orte ({{ len .model.Places }}) -

- -
- {{ range $placeID := .model.Sorted }} - {{ $place := index $.model.Places $placeID }} - {{ $geonames := GetGeonames $place.Geo }} -
- -
-
-

- {{ if $place.Names }} - {{ index $place.Names 0 }} - {{ else }} - {{ $place.ID }} - {{ end }} -

- - {{ if ne $geonames nil }} - {{ if and (ne $geonames.CountryName "") (ne $geonames.CountryName "Germany") }} -

- - {{ $mainPlaceName := "" }} - {{ if $place.Names }} - {{ $mainPlaceName = index $place.Names 0 }} - {{ end }} - {{ if eq $geonames.CountryName "France" }} - heutiges Frankreich{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "United Kingdom" }} - heutiges Großbritannien{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Russia" }} - heutiges Russland{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if or (eq $geonames.CountryName "Czech Republic") (eq $geonames.CountryName "Czechia") }} - heutiges Tschechien{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if or (eq $geonames.CountryName "Netherlands") (eq $geonames.CountryName "The Netherlands") }} - heutige Niederlande{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Poland" }} - heutiges Polen{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Switzerland" }} - heutige Schweiz{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Latvia" }} - heutiges Lettland{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Sweden" }} - heutiges Schweden{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Austria" }} - heutiges Österreich{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Belgium" }} - heutiges Belgien{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Slovakia" }} - heutige Slowakei{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Finland" }} - heutiges Finnland{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else if eq $geonames.CountryName "Denmark" }} - heutiges Dänemark{{- $modernName := "" -}} -{{- $hasGermanName := false -}} -{{- range $altName := $geonames.AlternateNames -}} -{{- if eq $altName.Lang "de" -}} -{{- $hasGermanName = true -}} -{{- if $altName.IsPreferredName -}} -{{- $modernName = $altName.Name -}} -{{- break -}} -{{- else if eq $modernName "" -}} -{{- $modernName = $altName.Name -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{- if not $hasGermanName -}} -{{- $modernName = $geonames.ToponymName -}} -{{- end -}} -{{- if and (ne $modernName "") (ne (lower $modernName) (lower $mainPlaceName)) -}}, {{ $modernName }}{{- end }} - {{ else }} - {{ $geonames.CountryName }} - {{ end }} -

- {{ end }} - {{ else if $place.Geo }} -

- Geonames verfügbar -

- {{ end }} -
- -
-
-
- {{ end }} -
-
- {{ else }} -

Keine Orte gefunden.

- {{ end }} -
-
-{{ end }} diff --git a/views/routes/ort/components/_back_navigation.gohtml b/views/routes/ort/components/_back_navigation.gohtml new file mode 100644 index 0000000..3a3f8b4 --- /dev/null +++ b/views/routes/ort/components/_back_navigation.gohtml @@ -0,0 +1,8 @@ +{{- /* Back navigation for individual place pages */ -}} + +
+ + + Orte + +
\ No newline at end of file diff --git a/views/routes/ort/components/_place_card.gohtml b/views/routes/ort/components/_place_card.gohtml new file mode 100644 index 0000000..d276d33 --- /dev/null +++ b/views/routes/ort/components/_place_card.gohtml @@ -0,0 +1,42 @@ +{{- /* Individual place card for overview grid */ -}} +{{ $geonames := GetGeonames .Geo }} +{{ $mainPlaceName := "" }} +{{ if .Names }} + {{ $mainPlaceName = index .Names 0 }} +{{ else }} + {{ $mainPlaceName = .ID }} +{{ end }} +{{ $modernName := GetModernPlaceName .Geo $mainPlaceName }} +
+ +
+
+

+ {{ if .Names }} + {{ index .Names 0 }} + {{ else }} + {{ .ID }} + {{ end }} +

+ + {{ if ne $geonames nil }} + {{ $mainPlaceName := "" }} + {{ if .Names }} + {{ $mainPlaceName = index .Names 0 }} + {{ end }} + {{ $fullInfo := GetFullPlaceInfo .Geo $mainPlaceName }} + {{ if ne $fullInfo "" }} +

+ {{ $fullInfo }} +

+ {{ end }} + {{ else if .Geo }} +

+ Geonames verfügbar +

+ {{ end }} +
+ +
+
+
\ No newline at end of file diff --git a/views/routes/ort/components/_place_header.gohtml b/views/routes/ort/components/_place_header.gohtml new file mode 100644 index 0000000..bb64379 --- /dev/null +++ b/views/routes/ort/components/_place_header.gohtml @@ -0,0 +1,71 @@ +{{- /* Place header with name, geographic info, and external links */ -}} + +
+ {{ $geonames := GetGeonames .Place.Geo }} + + +
+
+

+ {{ if .Place.Names }} + {{ index .Place.Names 0 }} + {{ else }} + {{ .Place.ID }} + {{ end }} +

+ + + {{ if ne $geonames nil }} +
+ + {{ $mainPlaceName := "" }} + {{ if .Place.Names }} + {{ $mainPlaceName = index .Place.Names 0 }} + {{ end }} + {{ $fullInfo := GetFullPlaceInfo .Place.Geo $mainPlaceName }} + {{ if ne $fullInfo "" }} +
{{ $fullInfo }}
+ {{ end }} + + +
+ {{ if and (ne $geonames.Lat "") (ne $geonames.Lng "") }} + + {{ end }} +
+
+ {{ else }} + + {{ if .Place.Geo }} +

+ + + Geonames + +

+ {{ end }} + {{ end }} +
+ + +
+ {{ if ne $geonames nil }} + + {{ if ne $geonames.WikipediaURL "" }} + + Wikipedia + + {{ end }} + {{ end }} + + + {{ if .Place.Geo }} + + + + {{ end }} +
+
+
\ No newline at end of file diff --git a/views/routes/ort/components/_place_pieces.gohtml b/views/routes/ort/components/_place_pieces.gohtml new file mode 100644 index 0000000..9758474 --- /dev/null +++ b/views/routes/ort/components/_place_pieces.gohtml @@ -0,0 +1,98 @@ +{{- /* Associated pieces section for place detail view */ -}} + +
+

+ Verlinkte Beiträge ({{ len .Pieces }}) +

+ + {{ if .Pieces }} + {{- /* Group pieces by year */ -}} + {{- $piecesByYear := dict -}} + {{- range $_, $p := .Pieces -}} + {{- range $issueRef := $p.IssueRefs -}} + {{- $year := printf "%d" $issueRef.When.Year -}} + {{- $existing := index $piecesByYear $year -}} + {{- if $existing -}} + {{- $piecesByYear = merge $piecesByYear (dict $year (append $existing $p)) -}} + {{- else -}} + {{- $piecesByYear = merge $piecesByYear (dict $year (slice $p)) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- /* Get sorted years */ -}} + {{- $sortedYears := slice -}} + {{- range $year, $pieces := $piecesByYear -}} + {{- $sortedYears = append $sortedYears $year -}} + {{- end -}} + {{- $sortedYears = sortStrings $sortedYears -}} + +
+ {{- range $year := $sortedYears -}} + {{- $yearPieces := index $piecesByYear $year -}} + + +
+

{{ $year }}

+ +
+ {{- /* Group pieces by title within each year */ -}} + {{- $groupedPieces := dict -}} + {{- range $_, $p := $yearPieces -}} + {{- $groupKey := "" -}} + {{- if $p.Title -}} + {{- $groupKey = index $p.Title 0 -}} + {{- else if $p.Incipit -}} + {{- $groupKey = index $p.Incipit 0 -}} + {{- else -}} + {{- $groupKey = printf "untitled-%s" $p.ID -}} + {{- end -}} + + {{- $existing := index $groupedPieces $groupKey -}} + {{- if $existing -}} + {{- $groupedPieces = merge $groupedPieces (dict $groupKey (append $existing $p)) -}} + {{- else -}} + {{- $groupedPieces = merge $groupedPieces (dict $groupKey (slice $p)) -}} + {{- end -}} + {{- end -}} + + {{- range $groupKey, $groupedItems := $groupedPieces -}} +
+
+ {{- /* Use first piece for display text with colon format for places */ -}} + {{ template "_piece_summary_for_place" (dict "Piece" (index $groupedItems 0) "CurrentActorID" "") }} + + {{- /* Show all citations from all pieces in this group inline with commas */ -}} + {{ " " }}{{- range $groupIndex, $groupItem := $groupedItems -}} + {{- range $issueIndex, $issue := $groupItem.IssueRefs -}} + {{- /* Only show citations for the current year */ -}} + {{- if eq (printf "%d" $issue.When.Year) $year -}} + {{- if or (gt $groupIndex 0) (gt $issueIndex 0) }}, {{ end -}} + {{- template "_citation" $issue -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- /* Add "Ganzer Beitrag" link if piece spans multiple issues */ -}} + {{- $firstGroupItem := index $groupedItems 0 -}} + {{- if gt (len $firstGroupItem.IssueRefs) 1 -}} + {{ " " }} + {{- end }} +
+
+ {{- end -}} +
+
+ {{- end -}} +
+ {{ else }} +

Keine verlinkten Beiträge für diesen Ort gefunden.

+ {{ end }} +
\ No newline at end of file diff --git a/views/routes/ort/detail/body.gohtml b/views/routes/ort/detail/body.gohtml new file mode 100644 index 0000000..fff4729 --- /dev/null +++ b/views/routes/ort/detail/body.gohtml @@ -0,0 +1,8 @@ + +
+
+ {{ template "_back_navigation" . }} + {{ template "_place_header" .model.SelectedPlace }} + {{ template "_place_pieces" .model.SelectedPlace }} +
+
\ No newline at end of file diff --git a/views/routes/ort/detail/head.gohtml b/views/routes/ort/detail/head.gohtml new file mode 100644 index 0000000..b91aa23 --- /dev/null +++ b/views/routes/ort/detail/head.gohtml @@ -0,0 +1,36 @@ +{{ $place := .model.SelectedPlace.Place }} +{{ if $place.Names }}{{ index $place.Names 0 }}{{ else }}{{ $place.ID }}{{ end }} - KGPZ + + + + + + + + + + +{{ $geonames := GetGeonames $place.Geo }} +{{ if ne $geonames nil }} + +{{ end }} \ No newline at end of file diff --git a/views/routes/ort/head.gohtml b/views/routes/ort/head.gohtml deleted file mode 100644 index 0e3e20c..0000000 --- a/views/routes/ort/head.gohtml +++ /dev/null @@ -1,42 +0,0 @@ -{{ if .model.SelectedPlace }} - {{ $place := .model.SelectedPlace.Place }} - {{ if $place.Names }}{{ index $place.Names 0 }}{{ else }}{{ $place.ID }}{{ end }} - KGPZ - - - - - - - - - - - {{ $geonames := GetGeonames $place.Geo }} - {{ if ne $geonames nil }} - - {{ end }} -{{ else }} - Orte - KGPZ - - -{{ end }} \ No newline at end of file diff --git a/views/routes/ort/overview/body.gohtml b/views/routes/ort/overview/body.gohtml new file mode 100644 index 0000000..d6cede3 --- /dev/null +++ b/views/routes/ort/overview/body.gohtml @@ -0,0 +1,27 @@ + +
+
+

Orte

+ + + {{ if .model.Places }} +
+ + + +

+ Alle Orte ({{ len .model.Places }}) +

+ +
+ {{ range $placeID := .model.Sorted }} + {{ $place := index $.model.Places $placeID }} + {{ template "_place_card" $place }} + {{ end }} +
+
+ {{ else }} +

Keine Orte gefunden.

+ {{ end }} +
+
\ No newline at end of file diff --git a/views/routes/ort/overview/head.gohtml b/views/routes/ort/overview/head.gohtml new file mode 100644 index 0000000..0f466a7 --- /dev/null +++ b/views/routes/ort/overview/head.gohtml @@ -0,0 +1,3 @@ +Orte - KGPZ + + \ No newline at end of file diff --git a/views/transform/main.js b/views/transform/main.js index d1971ca..4a627ab 100644 --- a/views/transform/main.js +++ b/views/transform/main.js @@ -1,6 +1,7 @@ import "./site.css"; import "./search.js"; import "./akteure.js"; +import "./places.js"; import { SinglePageViewer } from "./single-page-viewer.js"; import { ScrollToTopButton } from "./scroll-to-top.js"; import { InhaltsverzeichnisScrollspy } from "./inhaltsverzeichnis-scrollspy.js"; diff --git a/views/transform/places.js b/views/transform/places.js new file mode 100644 index 0000000..b892651 --- /dev/null +++ b/views/transform/places.js @@ -0,0 +1,122 @@ +/** + * Places Filter Web Component + * Provides search functionality for filtering place cards in the overview + */ +export class PlacesFilter extends HTMLElement { + constructor() { + super(); + this.searchInput = null; + this.placeCards = []; + this.countElement = null; + this.debounceTimer = null; + this.originalCount = 0; + } + + connectedCallback() { + this.render(); + this.setupEventListeners(); + this.initializePlaceCards(); + } + + disconnectedCallback() { + this.cleanupEventListeners(); + if (this.debounceTimer) { + clearTimeout(this.debounceTimer); + } + } + + render() { + this.innerHTML = ` +
+ +
+ `; + } + + setupEventListeners() { + this.searchInput = this.querySelector('#places-search'); + if (this.searchInput) { + this.searchInput.addEventListener('input', this.handleSearchInput.bind(this)); + } + } + + cleanupEventListeners() { + if (this.searchInput) { + this.searchInput.removeEventListener('input', this.handleSearchInput.bind(this)); + } + } + + initializePlaceCards() { + // Find all place cards and the count element + const container = this.closest('.bg-white') || document; + this.placeCards = Array.from(container.querySelectorAll('[data-place-name]')); + this.countElement = container.querySelector('[data-places-count]'); + + if (this.countElement) { + this.originalCount = this.placeCards.length; + } + } + + handleSearchInput(event) { + // Clear previous debounce timer + if (this.debounceTimer) { + clearTimeout(this.debounceTimer); + } + + // Debounce the search to avoid excessive filtering + this.debounceTimer = setTimeout(() => { + this.filterPlaces(event.target.value.trim()); + }, 150); + } + + filterPlaces(searchTerm) { + if (!this.placeCards.length) return; + + const normalizedSearch = searchTerm.toLowerCase(); + let visibleCount = 0; + + this.placeCards.forEach(card => { + const placeName = card.getAttribute('data-place-name')?.toLowerCase() || ''; + const modernName = card.getAttribute('data-modern-name')?.toLowerCase() || ''; + + // Check if search term matches either the place name or modern name + const isMatch = searchTerm === '' || + placeName.includes(normalizedSearch) || + modernName.includes(normalizedSearch); + + if (isMatch) { + card.style.display = ''; + visibleCount++; + } else { + card.style.display = 'none'; + } + }); + + // Update the count display + this.updateCountDisplay(visibleCount, searchTerm); + } + + updateCountDisplay(visibleCount, searchTerm) { + if (!this.countElement) return; + + if (searchTerm === '') { + // Show original count when no search + this.countElement.textContent = `Alle Orte (${this.originalCount})`; + } else if (visibleCount === 0) { + // Show no results message + this.countElement.textContent = `Keine Orte gefunden für "${searchTerm}"`; + } else { + // Show filtered count + this.countElement.textContent = `${visibleCount} von ${this.originalCount} Orten`; + } + } +} + +// Register the custom element +customElements.define('places-filter', PlacesFilter); \ No newline at end of file