mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-28 16:45:32 +00:00
Var changes, mor robustness against inputs
This commit is contained in:
20
app/kgpz.go
20
app/kgpz.go
@@ -48,6 +48,9 @@ const (
|
||||
ADDITIONS_URL = "/:year/:issue/beilage/:page?"
|
||||
)
|
||||
|
||||
// GitUpdateCallback is called when git data changes
|
||||
type GitUpdateCallback func(commit string, date string, url string)
|
||||
|
||||
type KGPZ struct {
|
||||
// INFO: We need to prevent concurrent reads and writes to the fs here since
|
||||
// - Git is accessing the FS
|
||||
@@ -62,6 +65,9 @@ type KGPZ struct {
|
||||
Geonames *geonames.GeonamesProvider
|
||||
Library *xmlmodels.Library
|
||||
Search *searchprovider.SearchProvider
|
||||
|
||||
// Callback for when git data is updated
|
||||
gitUpdateCallback GitUpdateCallback
|
||||
}
|
||||
|
||||
func NewKGPZ(config *providers.ConfigProvider) (*KGPZ, error) {
|
||||
@@ -590,6 +596,11 @@ func (k *KGPZ) GetWebHookSecret() string {
|
||||
return k.Config.WebHookSecret
|
||||
}
|
||||
|
||||
// SetGitUpdateCallback sets the callback function to be called when git data is updated
|
||||
func (k *KGPZ) SetGitUpdateCallback(callback GitUpdateCallback) {
|
||||
k.gitUpdateCallback = callback
|
||||
}
|
||||
|
||||
func (k *KGPZ) Pull() {
|
||||
if k.Repo == nil {
|
||||
return
|
||||
@@ -606,6 +617,15 @@ func (k *KGPZ) Pull() {
|
||||
logging.ObjDebug(&k.Repo, "Remote changed. Reparsing")
|
||||
k.Serialize()
|
||||
k.EnrichAndRebuildIndex()
|
||||
|
||||
// Notify about git data update
|
||||
if k.gitUpdateCallback != nil {
|
||||
k.gitUpdateCallback(
|
||||
k.Repo.Commit,
|
||||
k.Repo.Date.Format("2006-01-02T15:04:05Z07:00"),
|
||||
k.Config.Config.GitURL,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
kgpz_web.go
16
kgpz_web.go
@@ -55,6 +55,11 @@ func Init(cfg *providers.ConfigProvider) (*App, error) {
|
||||
engine := Engine(kgpz, cfg)
|
||||
server := server.Create(cfg, engine)
|
||||
|
||||
// Set up callback to update engine globals when git data changes
|
||||
kgpz.SetGitUpdateCallback(func(commit, date, url string) {
|
||||
engine.UpdateGitGlobals(commit, date, url)
|
||||
})
|
||||
|
||||
server.AddPre(engine)
|
||||
server.AddPre(kgpz)
|
||||
server.AddMux(kgpz)
|
||||
@@ -152,6 +157,15 @@ func Engine(kgpz *app.KGPZ, c *providers.ConfigProvider) *templating.Engine {
|
||||
e := templating.NewEngine(&views.LayoutFS, &views.RoutesFS)
|
||||
e.AddFuncs(kgpz.Funcs())
|
||||
timestamp := time.Now().Unix()
|
||||
e.Globals(fiber.Map{"isDev": c.Config.Debug, "name": "KGPZ", "lang": "de", "timestamp": timestamp})
|
||||
|
||||
// Add git commit information to global data
|
||||
globals := fiber.Map{"isDev": c.Config.Debug, "name": "KGPZ", "lang": "de", "timestamp": timestamp}
|
||||
if kgpz.Repo != nil {
|
||||
globals["gitCommit"] = kgpz.Repo.Commit
|
||||
globals["gitDate"] = kgpz.Repo.Date.Format("2006-01-02T15:04:05Z07:00")
|
||||
globals["gitURL"] = c.Config.GitURL
|
||||
}
|
||||
|
||||
e.Globals(globals)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -196,7 +196,9 @@ func (p *GeonamesProvider) FetchPlaces(places []GeonamesData) {
|
||||
}
|
||||
|
||||
func (p *GeonamesProvider) fetchPlace(ID, GeonamesURL string) {
|
||||
SPLITURL := strings.Split(GeonamesURL, "/")
|
||||
// Remove trailing slash if present
|
||||
cleanURL := strings.TrimSuffix(GeonamesURL, "/")
|
||||
SPLITURL := strings.Split(cleanURL, "/")
|
||||
if len(SPLITURL) < 2 {
|
||||
logging.Error(nil, "Error parsing Geonames ID from: "+GeonamesURL)
|
||||
return
|
||||
|
||||
@@ -195,7 +195,9 @@ func (p *GNDProvider) FetchPersons(persons []GNDData) {
|
||||
}
|
||||
|
||||
func (p *GNDProvider) fetchPerson(ID, GND string) {
|
||||
SPLITURL := strings.Split(GND, "/")
|
||||
// Remove trailing slash if present
|
||||
cleanURL := strings.TrimSuffix(GND, "/")
|
||||
SPLITURL := strings.Split(cleanURL, "/")
|
||||
if len(SPLITURL) < 2 {
|
||||
logging.Error(nil, "Error parsing GND ID from: "+GND)
|
||||
return
|
||||
|
||||
@@ -425,6 +425,18 @@ func (e *Engine) Globals(data fiber.Map) {
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateGitGlobals updates the git-related global data
|
||||
func (e *Engine) UpdateGitGlobals(commit, date, url string) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
if e.GlobalData == nil {
|
||||
e.GlobalData = make(fiber.Map)
|
||||
}
|
||||
e.GlobalData["gitCommit"] = commit
|
||||
e.GlobalData["gitDate"] = date
|
||||
e.GlobalData["gitURL"] = url
|
||||
}
|
||||
|
||||
func (e *Engine) Load() error {
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
@@ -180,7 +180,7 @@ class V extends HTMLElement {
|
||||
}
|
||||
}
|
||||
customElements.define("year-jump-filter", V);
|
||||
class z extends HTMLElement {
|
||||
class D extends HTMLElement {
|
||||
constructor() {
|
||||
super(), this.isOpen = !1;
|
||||
}
|
||||
@@ -242,11 +242,37 @@ class z extends HTMLElement {
|
||||
this.isOpen && t && i && !t.contains(e.target) && !this.contains(e.target) && this.hideFilter();
|
||||
}
|
||||
}
|
||||
customElements.define("schnellauswahl-button", z);
|
||||
class D extends HTMLElement {
|
||||
customElements.define("schnellauswahl-button", D);
|
||||
class z extends HTMLElement {
|
||||
constructor() {
|
||||
super(), this.isOpen = !1;
|
||||
}
|
||||
static get observedAttributes() {
|
||||
return ["git-commit", "git-date", "git-url"];
|
||||
}
|
||||
get gitCommit() {
|
||||
return this.getAttribute("git-commit");
|
||||
}
|
||||
get gitDate() {
|
||||
return this.getAttribute("git-date");
|
||||
}
|
||||
get gitUrl() {
|
||||
return this.getAttribute("git-url");
|
||||
}
|
||||
formatCommitInfo() {
|
||||
if (!this.gitCommit)
|
||||
return "Keine Commit-Info";
|
||||
const e = this.gitCommit.substring(0, 7);
|
||||
if (this.gitDate) {
|
||||
const i = new Date(this.gitDate).toLocaleDateString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric"
|
||||
});
|
||||
return `${e} (${i})`;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
connectedCallback() {
|
||||
this.createMenu(), this.setupEventListeners();
|
||||
}
|
||||
@@ -271,10 +297,18 @@ class D extends HTMLElement {
|
||||
<a href="/ort/">Orten</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-y-2 mt-2">
|
||||
<a href="/edition/">Geschichte & Edition der KGPZ</a>
|
||||
<a href="/zitation/">Zitation</a>
|
||||
<a href="/kontakt/">Kontakt</a>
|
||||
<div class="border-t border-slate-300 pt-2 mt-2">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<a href="/edition/">Geschichte & Edition der KGPZ</a>
|
||||
<a href="/zitation/">Zitation</a>
|
||||
<a href="/kontakt/">Kontakt</a>
|
||||
</div>
|
||||
<div class="mt-3 pt-2 border-t border-slate-200 text-xs text-slate-600">
|
||||
<a href="${this.gitUrl || "https://github.com/Theodor-Springmann-Stiftung/KGPZ.git"}" target="_blank" class="flex items-center gap-1 hover:text-slate-800">
|
||||
<i class="ri-git-branch-line"></i>
|
||||
<span>${this.formatCommitInfo()}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -319,7 +353,7 @@ class D extends HTMLElement {
|
||||
this.isOpen && !this.contains(e.target) && this.hideMenu();
|
||||
}
|
||||
}
|
||||
customElements.define("navigation-menu", D);
|
||||
customElements.define("navigation-menu", z);
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
document.addEventListener("click", function(a) {
|
||||
const e = a.target.closest('a[href^="/akteure/"], a[href^="/ort/"]'), t = document.getElementById("filter-container");
|
||||
@@ -668,7 +702,7 @@ class _ extends HTMLElement {
|
||||
this.isExpanded ? this.classList.add("border-b", "border-slate-100") : this.classList.add("border-b", "border-slate-100"), !this.nextElementSibling && this.classList.remove("border-b");
|
||||
}
|
||||
}
|
||||
class W extends HTMLElement {
|
||||
class K extends HTMLElement {
|
||||
constructor() {
|
||||
super(), this.places = [], this.mapElement = null, this.pointsContainer = null, this.intersectionObserver = null, this.mapPoints = /* @__PURE__ */ new Map(), this.tooltip = null, this.showTimeout = null, this.hideTimeout = null, this.isTooltipVisible = !1, this.currentHoveredPlaceId = "", this.boundHandleHeadingHoverEvent = this.handleHeadingHoverEvent.bind(this);
|
||||
}
|
||||
@@ -709,8 +743,8 @@ class W extends HTMLElement {
|
||||
const e = { xmin: 2555e3, ymin: 135e4, xmax: 7405e3, ymax: 55e5 }, t = { lon: 10, lat: 52 }, i = (s, o) => {
|
||||
const h = t.lon * Math.PI / 180, d = t.lat * Math.PI / 180, u = o * Math.PI / 180, p = s * Math.PI / 180, m = Math.sqrt(
|
||||
2 / (1 + Math.sin(d) * Math.sin(p) + Math.cos(d) * Math.cos(p) * Math.cos(u - h))
|
||||
), g = 6371e3 * m * Math.cos(p) * Math.sin(u - h), w = 6371e3 * m * (Math.cos(d) * Math.sin(p) - Math.sin(d) * Math.cos(p) * Math.cos(u - h)), x = g + 4321e3, f = w + 321e4, v = e.xmax - e.xmin, E = e.ymax - e.ymin, S = (x - e.xmin) / v * 100, L = (e.ymax - f) / E * 100;
|
||||
return { x: S, y: L };
|
||||
), g = 6371e3 * m * Math.cos(p) * Math.sin(u - h), w = 6371e3 * m * (Math.cos(d) * Math.sin(p) - Math.sin(d) * Math.cos(p) * Math.cos(u - h)), x = g + 4321e3, f = w + 321e4, v = e.xmax - e.xmin, E = e.ymax - e.ymin, S = (x - e.xmin) / v * 100, C = (e.ymax - f) / E * 100;
|
||||
return { x: S, y: C };
|
||||
}, n = [];
|
||||
this.places.forEach((s) => {
|
||||
if (s.lat && s.lng) {
|
||||
@@ -740,7 +774,7 @@ class W extends HTMLElement {
|
||||
const y = w * x;
|
||||
v.x = d - (y - g) / 2, v.width = y;
|
||||
}
|
||||
const E = 100 / v.width, S = -v.x, L = -v.y, T = `scale(${E}) translate(${S}%, ${L}%)`, P = this.querySelector(".transform-wrapper");
|
||||
const E = 100 / v.width, S = -v.x, C = -v.y, T = `scale(${E}) translate(${S}%, ${C}%)`, P = this.querySelector(".transform-wrapper");
|
||||
P && (P.style.transform = T);
|
||||
}
|
||||
initializeScrollspy() {
|
||||
@@ -833,7 +867,7 @@ class W extends HTMLElement {
|
||||
this.intersectionObserver && (this.intersectionObserver.disconnect(), this.intersectionObserver = null), this.clearTimeouts(), document.removeEventListener("place-heading-hover", this.boundHandleHeadingHoverEvent), window.removeEventListener("scroll", this.boundHandleScroll), document.removeEventListener("scroll", this.boundHandleScroll);
|
||||
}
|
||||
}
|
||||
class K extends HTMLElement {
|
||||
class W extends HTMLElement {
|
||||
constructor() {
|
||||
super(), this.place = null, this.mapElement = null, this.pointsContainer = null, this.tooltip = null;
|
||||
}
|
||||
@@ -872,7 +906,7 @@ class K extends HTMLElement {
|
||||
const e = { xmin: 2555e3, ymin: 135e4, xmax: 7405e3, ymax: 55e5 }, t = { lon: 10, lat: 52 }, i = (r, l) => {
|
||||
const u = t.lon * Math.PI / 180, p = t.lat * Math.PI / 180, m = l * Math.PI / 180, g = r * Math.PI / 180, w = Math.sqrt(
|
||||
2 / (1 + Math.sin(p) * Math.sin(g) + Math.cos(p) * Math.cos(g) * Math.cos(m - u))
|
||||
), x = 6371e3 * w * Math.cos(g) * Math.sin(m - u), f = 6371e3 * w * (Math.cos(p) * Math.sin(g) - Math.sin(p) * Math.cos(g) * Math.cos(m - u)), v = x + 4321e3, E = f + 321e4, S = e.xmax - e.xmin, L = e.ymax - e.ymin, T = (v - e.xmin) / S * 100, P = (e.ymax - E) / L * 100;
|
||||
), x = 6371e3 * w * Math.cos(g) * Math.sin(m - u), f = 6371e3 * w * (Math.cos(p) * Math.sin(g) - Math.sin(p) * Math.cos(g) * Math.cos(m - u)), v = x + 4321e3, E = f + 321e4, S = e.xmax - e.xmin, C = e.ymax - e.ymin, T = (v - e.xmin) / S * 100, P = (e.ymax - E) / C * 100;
|
||||
return { x: T, y: P };
|
||||
}, n = parseFloat(this.place.lat), s = parseFloat(this.place.lng), o = i(n, s);
|
||||
if (o.x >= 0 && o.x <= 100 && o.y >= 0 && o.y <= 100) {
|
||||
@@ -921,8 +955,8 @@ class K extends HTMLElement {
|
||||
}
|
||||
customElements.define("places-filter", j);
|
||||
customElements.define("place-accordion", _);
|
||||
customElements.define("places-map", W);
|
||||
customElements.define("places-map-single", K);
|
||||
customElements.define("places-map", K);
|
||||
customElements.define("places-map-single", W);
|
||||
class Y extends HTMLElement {
|
||||
constructor() {
|
||||
super(), this.searchInput = null, this.itemCards = [], this.countElement = null, this.debounceTimer = null, this.originalCount = 0;
|
||||
@@ -1582,7 +1616,7 @@ function M() {
|
||||
document.getElementById("pageModal").classList.add("hidden");
|
||||
}
|
||||
function Q() {
|
||||
if (window.pageObserver && (window.pageObserver.disconnect(), window.pageObserver = null), window.currentPageContainers = Array.from(document.querySelectorAll(".newspaper-page-container")), window.currentActiveIndex = 0, C(), document.querySelector(".newspaper-page-container")) {
|
||||
if (window.pageObserver && (window.pageObserver.disconnect(), window.pageObserver = null), window.currentPageContainers = Array.from(document.querySelectorAll(".newspaper-page-container")), window.currentActiveIndex = 0, L(), document.querySelector(".newspaper-page-container")) {
|
||||
let e = /* @__PURE__ */ new Set();
|
||||
window.pageObserver = new IntersectionObserver(
|
||||
(t) => {
|
||||
@@ -1591,7 +1625,7 @@ function Q() {
|
||||
n !== -1 && (i.isIntersecting ? e.add(n) : e.delete(n));
|
||||
}), e.size > 0) {
|
||||
const n = Array.from(e).sort((s, o) => s - o)[0];
|
||||
n !== window.currentActiveIndex && (window.currentActiveIndex = n, C());
|
||||
n !== window.currentActiveIndex && (window.currentActiveIndex = n, L());
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1619,7 +1653,7 @@ function ee() {
|
||||
a === -1 && t > 0 && (a = t - 1), a >= 0 && (window.currentActiveIndex = a, window.currentPageContainers[window.currentActiveIndex].scrollIntoView({
|
||||
block: "start"
|
||||
}), setTimeout(() => {
|
||||
C();
|
||||
L();
|
||||
}, 100));
|
||||
}
|
||||
}
|
||||
@@ -1640,7 +1674,7 @@ function te() {
|
||||
a === -1 && t < window.currentPageContainers.length - 1 && (a = t + 1), a >= 0 && a < window.currentPageContainers.length && (window.currentActiveIndex = a, window.currentPageContainers[window.currentActiveIndex].scrollIntoView({
|
||||
block: "start"
|
||||
}), setTimeout(() => {
|
||||
C();
|
||||
L();
|
||||
}, 100));
|
||||
}
|
||||
}
|
||||
@@ -1677,7 +1711,7 @@ function q() {
|
||||
}
|
||||
return !1;
|
||||
}
|
||||
function C() {
|
||||
function L() {
|
||||
const a = document.getElementById("prevPageBtn"), e = document.getElementById("nextPageBtn"), t = document.getElementById("beilageBtn");
|
||||
if (a && (a.style.display = "flex", window.currentActiveIndex <= 0 ? (a.disabled = !0, a.classList.add("opacity-50", "cursor-not-allowed"), a.classList.remove("hover:bg-gray-200")) : (a.disabled = !1, a.classList.remove("opacity-50", "cursor-not-allowed"), a.classList.add("hover:bg-gray-200"))), e && (e.style.display = "flex", window.currentActiveIndex >= window.currentPageContainers.length - 1 ? (e.disabled = !0, e.classList.add("opacity-50", "cursor-not-allowed"), e.classList.remove("hover:bg-gray-200")) : (e.disabled = !1, e.classList.remove("opacity-50", "cursor-not-allowed"), e.classList.add("hover:bg-gray-200"))), t) {
|
||||
const i = q(), n = t.querySelector("i");
|
||||
@@ -1835,7 +1869,7 @@ function re(a, e) {
|
||||
function A() {
|
||||
Q(), window.addEventListener("scroll", function() {
|
||||
clearTimeout(window.scrollTimeout), window.scrollTimeout = setTimeout(() => {
|
||||
C();
|
||||
L();
|
||||
}, 50);
|
||||
}), document.addEventListener("keydown", function(a) {
|
||||
a.key === "Escape" && M();
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -15,6 +15,10 @@
|
||||
hx-target="main" />
|
||||
</div>
|
||||
|
||||
<navigation-menu></navigation-menu>
|
||||
<navigation-menu
|
||||
{{ if .gitCommit }}git-commit="{{ .gitCommit }}"{{ end }}
|
||||
{{ if .gitDate }}git-date="{{ .gitDate }}"{{ end }}
|
||||
{{ if .gitURL }}git-url="{{ .gitURL }}"{{ end }}
|
||||
></navigation-menu>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
{{- $placeObj := GetPlace $placeRef.Ref -}}
|
||||
{{- if gt (len $placeObj.Names) 0 -}}
|
||||
{{- $placeName := index $placeObj.Names 0 -}}
|
||||
{{- $placeTag = printf "%s <a href=\"/ort/%s\" class=\"ml-0\"><span class=\"place-tag inline-block bg-slate-200 text-slate-700 text-xs px-2 py-0.5 rounded-md whitespace-nowrap hover:bg-slate-300 hover:text-slate-800 transition-colors duration-150\">%s</span></a>" $placeTag $placeObj.ID $placeName -}}
|
||||
{{- $placeTag = printf "%s <a href=\"/ort/%s\" class=\"ml-0\"><span class=\"place-tag inline-block bg-slate-200 text-slate-700 text-xs px-2 py-0.5 rounded-md whitespace-nowrap hover:bg-slate-300 hover:text-slate-800 transition-colors duration-150 !indent-0\">%s</span></a>" $placeTag $placeObj.ID $placeName -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -542,6 +542,42 @@ class NavigationMenu extends HTMLElement {
|
||||
this.isOpen = false;
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['git-commit', 'git-date', 'git-url'];
|
||||
}
|
||||
|
||||
get gitCommit() {
|
||||
return this.getAttribute('git-commit');
|
||||
}
|
||||
|
||||
get gitDate() {
|
||||
return this.getAttribute('git-date');
|
||||
}
|
||||
|
||||
get gitUrl() {
|
||||
return this.getAttribute('git-url');
|
||||
}
|
||||
|
||||
formatCommitInfo() {
|
||||
if (!this.gitCommit) {
|
||||
return 'Keine Commit-Info';
|
||||
}
|
||||
|
||||
const shortCommit = this.gitCommit.substring(0, 7);
|
||||
|
||||
if (this.gitDate) {
|
||||
const date = new Date(this.gitDate);
|
||||
const formattedDate = date.toLocaleDateString('de-DE', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
});
|
||||
return `${shortCommit} (${formattedDate})`;
|
||||
}
|
||||
|
||||
return shortCommit;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.createMenu();
|
||||
this.setupEventListeners();
|
||||
@@ -570,10 +606,18 @@ class NavigationMenu extends HTMLElement {
|
||||
<a href="/ort/">Orten</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-y-2 mt-2">
|
||||
<a href="/edition/">Geschichte & Edition der KGPZ</a>
|
||||
<a href="/zitation/">Zitation</a>
|
||||
<a href="/kontakt/">Kontakt</a>
|
||||
<div class="border-t border-slate-300 pt-2 mt-2">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<a href="/edition/">Geschichte & Edition der KGPZ</a>
|
||||
<a href="/zitation/">Zitation</a>
|
||||
<a href="/kontakt/">Kontakt</a>
|
||||
</div>
|
||||
<div class="mt-3 pt-2 border-t border-slate-200 text-xs text-slate-600">
|
||||
<a href="${this.gitUrl || 'https://github.com/Theodor-Springmann-Stiftung/KGPZ.git'}" target="_blank" class="flex items-center gap-1 hover:text-slate-800">
|
||||
<i class="ri-git-branch-line"></i>
|
||||
<span>${this.formatCommitInfo()}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user