mirror of
				https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
				synced 2025-10-29 17:15:31 +00:00 
			
		
		
		
	Schellfilter; bugfixes; Tagewerk; Anfang Ort Controller
This commit is contained in:
		| @@ -9,8 +9,8 @@ | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{ else }} | ||||
| 	<div class="max-w-7xl mx-auto px-8 py-8"> | ||||
| 		<div class="bg-white px-6 py-6 rounded"> | ||||
| 	<div class="w-full max-w-7xl mx-auto px-8 py-8"> | ||||
| 		<div class="bg-white px-6 py-6 rounded w-full"> | ||||
| 			{{ template "_back_navigation" $agent }} | ||||
| 			{{ template "_akteur" $agent }} | ||||
| 		</div> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
| 		{{ $pageCount := len $pages }} | ||||
|  | ||||
| 		<!-- Historical printing layout grid --> | ||||
| 		<div class="grid grid-cols-2"> | ||||
| 		<div class="grid grid-cols-2 gap-x-2"> | ||||
| 			{{ template "_historical_layout" (dict "pages" $pages "pageCount" $pageCount "isBeilage" false "targetPage" $.targetPage) }} | ||||
| 		</div> | ||||
| 	{{ end }} | ||||
| @@ -26,7 +26,7 @@ | ||||
| 				{{ $pageCount := len $beilagePages }} | ||||
|  | ||||
| 				<!-- Historical printing layout grid for Beilage --> | ||||
| 				<div class="grid grid-cols-2"> | ||||
| 				<div class="grid grid-cols-2 gap-x-2"> | ||||
| 					{{ template "_historical_layout" (dict "pages" $beilagePages "pageCount" $pageCount "isBeilage" true "targetPage" $.targetPage) }} | ||||
| 				</div> | ||||
| 			</div> | ||||
| @@ -117,6 +117,9 @@ | ||||
| 	{{ $hoverColor := "hover:border-slate-300" }} | ||||
| 	{{ $bgColor := "bg-blue-50" }} | ||||
| 	{{ $idPrefix := "page" }} | ||||
| 	{{ if $isBeilage }} | ||||
| 		{{ $idPrefix = "beilage" }} | ||||
| 	{{ end }} | ||||
|  | ||||
| 	{{ if $isBeilage }} | ||||
| 		{{ $borderColor = "border-amber-200" }} | ||||
| @@ -127,11 +130,6 @@ | ||||
|  | ||||
| 	<div class="newspaper-page-container pt-4" id="{{ $idPrefix }}-{{ $page.PageNumber }}" data-page-container="{{ $page.PageNumber }}" data-page-icon-type="{{ $page.PageIcon }}"{{ if $isBeilage }} data-beilage="true"{{ end }}> | ||||
| 		<!-- Anchor for navigation --> | ||||
| 		{{ if $isBeilage }} | ||||
| 			<div id="beilage-{{ $page.PageNumber }}"></div> | ||||
| 		{{ else }} | ||||
| 			<div id="page-{{ $page.PageNumber }}"></div> | ||||
| 		{{ end }} | ||||
| 		<!-- Page indicator row --> | ||||
| 		<div class="flex {{ if $isLeft }}justify-end{{ else }}justify-start{{ end }} items-center gap-1 mb-2"> | ||||
| 			{{ if $isLeft }} | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| {{ $y := .model.Year }} | ||||
|  | ||||
|  | ||||
| <div class="mt-6 w-full"> | ||||
| 	<div class="mx-auto flex flex-row gap-x-4 w-fit items-end leading-none"> | ||||
| 		{{ range $year := .model.AvailableYears }} | ||||
| @@ -14,63 +13,6 @@ | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <!-- Page Jump Form --> | ||||
| <div class="mt-8 w-full"> | ||||
| 	<div class="mx-auto text-center"> | ||||
| 		<h3 class="text-lg font-medium text-slate-700 mb-6">Direkt zu Seite springen</h3> | ||||
|  | ||||
| 		<form hx-post="/jump" hx-target="#jump-errors" hx-swap="innerHTML" hx-target-4*="#jump-errors" hx-target-5*="#jump-errors" hx-ext="response-targets" class="inline-flex items-center gap-3"> | ||||
| 			<!-- Year Selection --> | ||||
| 			<div class="flex items-center gap-2"> | ||||
| 				<label for="jump-year" class="text-sm text-slate-600 whitespace-nowrap">Jahr</label> | ||||
| 				<select id="jump-year" name="year" value="{{ $y }}" class="px-2 py-1 border border-slate-300 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-400 focus:border-blue-400"> | ||||
| 					{{ range $year := .model.AvailableYears }} | ||||
| 						<option value="{{ $year }}" {{ if eq $year $y }}selected{{ end }}>{{ $year }}</option> | ||||
| 					{{ end }} | ||||
| 				</select> | ||||
| 			</div> | ||||
|  | ||||
| 			<!-- Page Input --> | ||||
| 			<div class="flex items-center gap-2"> | ||||
| 				<label for="jump-page" class="text-sm text-slate-600 whitespace-nowrap">Seite</label> | ||||
| 				<input type="number" id="jump-page" name="page" min="1" placeholder="42" class="w-20 px-2 py-1 border border-slate-300 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-400 focus:border-blue-400"> | ||||
| 			</div> | ||||
|  | ||||
| 			<!-- Submit Button --> | ||||
| 			<button type="submit" class="inline-flex items-center px-3 py-1 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1"> | ||||
| 				<i class="ri-arrow-right-line mr-1"></i> | ||||
| 				Springen | ||||
| 			</button> | ||||
| 		</form> | ||||
|  | ||||
| 		<!-- Error Display Area --> | ||||
| 		<div id="jump-errors" class="mt-3 min-h-[1.5rem]"></div> | ||||
|  | ||||
| 		<!-- Instructions --> | ||||
| 		<div class="mt-4 text-sm text-slate-500"> | ||||
| 			<p>Geben Sie Jahr und Seitenzahl ein, um direkt zur entsprechenden Ausgabe zu springen.</p> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <script> | ||||
| // Clear errors when user starts typing | ||||
| document.addEventListener('DOMContentLoaded', function() { | ||||
| 	const errorContainer = document.getElementById('jump-errors'); | ||||
| 	const yearSelect = document.getElementById('jump-year'); | ||||
| 	const pageInput = document.getElementById('jump-page'); | ||||
|  | ||||
| 	function clearErrors() { | ||||
| 		if (errorContainer) { | ||||
| 			errorContainer.innerHTML = ''; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (yearSelect) yearSelect.addEventListener('change', clearErrors); | ||||
| 	if (pageInput) pageInput.addEventListener('input', clearErrors); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <div class="grid grid-cols-11 gap-x-2 gap-y-4 pt-8"> | ||||
| 	{{ range $index, $month := .model.Issues }} | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,238 @@ | ||||
| <div class="container-normal"> | ||||
| 	<div class="text [&_*]:!indent-0 border px-8 py-7"> | ||||
| 		<h1 class="!mt-0">Impressum</h1> | ||||
| 		<div> | ||||
| 			<p> | ||||
| 				<strong>Telemedienanbieter im Sinne des § 5 TMG:</strong><br />Theodor Springmann | ||||
| 				Stiftung<br />Hirschgasse 2<br />69120 Heidelberg<br /><br />Telefon +49 6221 436235<br />Email <a | ||||
| 					href="mailto:info@theodor-springmann-stiftung.de" | ||||
| 					>info@theodor-springmann-stiftung.de</a | ||||
| 				> | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<strong>Rechtsform und Sitz:</strong><br />Die Theodor Springmann Stiftung ist eine | ||||
| 				rechtsfähige Stiftung bürgerlichen Rechts. Sitz der Stiftung ist Heidelberg. | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<strong>Vorstand der Theodor Springmann Stiftung:</strong><br />Dr. Randolf Straky | ||||
| 				(Präsident) | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<strong>Geschäftsführung:</strong><br />Dr. Randolf Straky<br />Theodor Springmann | ||||
| 				Stiftung<br />Hirschgasse 2<br />69120 Heidelberg | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<strong>Zuständige Aufsichtsbehörde:</strong><br />Regierungspräsidium Karlsruhe<br />Schlossplatz | ||||
| 				1-3<br />76131 Karlsruhe<br /><br /><a | ||||
| 					href="https://rp.baden-wuerttemberg.de/Themen/Stiftung/Seiten/Ansprechpartner.aspx" | ||||
| 					>Ansprechpartner</a | ||||
| 				> | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<strong>Redaktionelle Verantwortung nach § 55 Abs. 2 RStV:</strong><br />Janina Reibold | ||||
| 				<br />Theodor Springmann Stiftung<br />Hirschgasse 2<br />69120 Heidelberg | ||||
| 			</p> | ||||
| 		</div> | ||||
| 		2024-10-17 09:52:17.412Z | ||||
| 	</div> | ||||
| 	<div class="text"> | ||||
| 		<h1 class="mt-12">Datenschutzerklärung</h1> | ||||
| 		<div class="prose"> | ||||
| 			<div> | ||||
| 				<h2>Präambel</h2> | ||||
| 				<p> | ||||
| 					Diese Datenschutzerklärung informiert Sie über die Art, den Umfang und den Zweck der | ||||
| 					personenbezogenen Daten, die im Rahmen dieser Onlinepräsenz von Ihnen erhoben und von uns | ||||
| 					verarbeitet werden, sowie die Ihnen zustehenden Rechte.<br />Personenbezogene Daten sind | ||||
| 					alle Informationen, die sich auf eine identifizierte oder identifizierbare natürliche | ||||
| 					Person beziehen. Als identifizierbar wird eine natürliche Person angesehen, die direkt | ||||
| 					oder indirekt identifiziert werden kann. Im Hinblick auf weitere verwendete | ||||
| 					Begrifflichkeiten verweisen wir auf die Definitionen der Datenschutz-Grundverordnung | ||||
| 					(DSGVO), Artikel 4.<br />Erfolgt die Verarbeitung personenbezogener Daten auf Grundlage | ||||
| 					des Art. 6 Abs. 1 lit. f DSGVO, so besteht unser berechtigtes Interesse in der Erfüllung | ||||
| 					unseres satzungsgemäßen Stiftungszwecks. Zweck der Stiftung ist es, in gemeinnütziger | ||||
| 					Weise Wissenschaft und Kunst, Völkerverständigung und Entwicklungshilfe zu fördern und zum | ||||
| 					menschlichen Selbstverständnis sowie zum Erkennen und Lindern strukturell bedingter Not | ||||
| 					und Bedürftigkeit von Menschen in aller Welt beizutragen. | ||||
| 				</p> | ||||
| 				<h2>Verantwortlicher</h2> | ||||
| 				<p> | ||||
| 					Verantwortlich im Sinne von Art. 4 Abs. 7 DSGVO für die Verarbeitung personenbezogener | ||||
| 					Daten ist:<br />Theodor Springmann Stiftung<br />Hirschgasse 2<br />69120 Heidelberg<br /><br /><a | ||||
| 						href="mailto:info@theodor-springmann-stiftung.de" | ||||
| 						>info@theodor-springmann-stiftung.de</a | ||||
| 					> | ||||
| 				</p> | ||||
| 				<h2>Automatisch bei Nutzung unserer Onlinepräsenz erfasste Daten</h2> | ||||
| 				<p> | ||||
| 					Mit der Nutzung unserer Onlinepräsenz werden automatisch personenbezogene und allgemeine | ||||
| 					Daten vom Nutzer übermittelt und von uns erfasst und gespeichert. Die von uns erhobenen | ||||
| 					Daten umfassen: | ||||
| 				</p> | ||||
| 				<ol> | ||||
| 					<li> | ||||
| 						die IP-Adresse des ans Internet angeschlossenen Netzwerkgeräts (Computer oder Router des | ||||
| 						Nutzers), | ||||
| 					</li> | ||||
| 					<li>den verwendeten Browsertyp und dessen Version,</li> | ||||
| 					<li>das verwendete Betriebssystem und dessen Version,</li> | ||||
| 					<li>die Internetseite, die den Nutzer auf unsere Onlinepräsenz verweist (Referrer),</li> | ||||
| 					<li>die Unterwebseiten, die der Nutzer auf unserer Onlinepräsenz aufruft,</li> | ||||
| 					<li>das Datum und die Uhrzeit des Aufrufs,</li> | ||||
| 					<li>den Internet-Service-Provider des Nutzers,</li> | ||||
| 					<li>sonstige ähnliche Daten.</li> | ||||
| 				</ol> | ||||
| 				<p> | ||||
| 					Die Theodor Springmann Stiftung zieht aus diesen Daten keine Rückschlüsse auf die | ||||
| 					betroffenen Nutzer. Diese Informationen werden benötigt, um | ||||
| 				</p> | ||||
| 				<ol> | ||||
| 					<li>die vom Nutzer angeforderten Inhalte korrekt auszuliefern,</li> | ||||
| 					<li> | ||||
| 						technische Probleme zu diagnostizieren, unsere IT-Systeme vor Angriffen zu schützen und | ||||
| 						im Falle eines Angriffs den zuständigen Behörden notwendige Informationen zur | ||||
| 						Strafverfolgung bereitstellen zu können, | ||||
| 					</li> | ||||
| 					<li>die Inhalte und die Bedienung unserer Onlinepräsenz zu optimieren.</li> | ||||
| 				</ol> | ||||
| 				<p> | ||||
| 					Die oben genannten Verarbeitungszwecke werden von Subsystemen erfüllt, die unabhängig von | ||||
| 					anderen Subsystemen ihre jeweils eigene Kopie der vom Nutzer erhobenen Daten erhalten, | ||||
| 					verarbeiten und löschen. Dabei werden den Subsystemen lediglich die zur Ausführung ihrer | ||||
| 					Aufgabe erforderlichen Daten übergeben. Alle Subsysteme befinden sich auf Servern der | ||||
| 					Theodor Springmann Stiftung. | ||||
| 				</p> | ||||
| 				<h3>Auslieferung der vom Nutzer angeforderten Inhalte</h3> | ||||
| 				<p> | ||||
| 					Mit der Anforderung einer Seite dieser Onlinepräsenz übermittelt der Browser des Nutzers | ||||
| 					automatisch die IP-Adresse seines ans Internet angeschlossenen Netzwerkgeräts (Computer | ||||
| 					oder Router) und andere Daten. Ohne diese IP-Adresse können die Inhalte dieser | ||||
| 					Online-Präsenz nicht an den Nutzer zurückgesendet werden. Daher ist die Speicherung und | ||||
| 					Verarbeitung der IP-Adresse für den Betrieb dieser Onlinepräsenz notwendig. Ebenfalls | ||||
| 					übermittelte Daten über den verwendeten Browser usw. werden gegebenenfalls verwendet, um | ||||
| 					die Anzeige der Webseite an das Anzeigegerät oder den Browser anzupassen. Die zum Zwecke | ||||
| 					der Auslieferung von Inhalten gesammelten Daten werden direkt nach Übertragung der Inhalte | ||||
| 					vom Subsystem gelöscht. Die Verarbeitung dieser Daten erfolgt auf der Grundlage eines | ||||
| 					berechtigten Interesses nach Art. 6 Abs. 1 lit. f DSGVO. | ||||
| 				</p> | ||||
| 				<h3>Diagnose und Schutz der IT-Systeme</h3> | ||||
| 				<p> | ||||
| 					Daneben erfolgt eine Speicherung der oben genannten Daten in Diagnose-Protokollen. Die | ||||
| 					Protokollierung ist notwendig, um etwaige technische Probleme analysieren oder Angriffe | ||||
| 					erkennen und abwehren zu können. Bei Angriffen auf unsere IT-Systeme übergeben wir die | ||||
| 					Diagnose-Protokolle den zuständigen Strafverfolgungsbehörden. Die Diagnose-Protokolle | ||||
| 					werden nach 14 Tagen automatisch gelöscht. Die Speicherung und Verarbeitung dieser Daten | ||||
| 					erfolgt auf Grundlage eines berechtigten Interesses nach Art. 6 Abs. 1 lit. f DSGVO. | ||||
| 				</p> | ||||
| 				<h3>Analyse zur Optimierung der Inhalte und der Bedienung</h3> | ||||
| 				<p> | ||||
| 					Die oben genannten Daten werden von einem Webanalyseprogramm verarbeitet. Dabei werden die | ||||
| 					Daten pseudonymisiert und aggregiert, so dass sie einzelnen Nutzern nicht mehr zugeordnet | ||||
| 					werden können. Das Analyseprogramm wird auf einem von uns betriebenen Server ausgeführt, | ||||
| 					daher werden keine Daten an Dritte übermittelt. Der Zweck dieser Erfassung besteht in der | ||||
| 					Analyse der Nutzung unseres Angebots, durch die eine Verbesserung unserer Webseiten, der | ||||
| 					Inhalte und der Bedienung ermöglicht wird. Das Analyseprogramm speichert die | ||||
| 					anonymisierten Daten ohne zeitliche Begrenzung. Die Verarbeitung dieser Daten erfolgt auf | ||||
| 					der Grundlage eines berechtigten Interesses (Art. 6 Abs. 1 lit. f DSGVO). | ||||
| 				</p> | ||||
| 				<h2>Sonstige Daten</h2> | ||||
| 				<p> | ||||
| 					Sämtliche Daten, die mit dem Aufruf einer Webseite von unserer Onlinepräsenz an den Nutzer | ||||
| 					übertragen werden, werden von unseren Servern bereitgestellt. Wir nutzen kein von Dritten | ||||
| 					bereitgestelltes Content Delivery Network (CDN), um Teile unserer Onlinepräsenz (z. B. | ||||
| 					Javascript- oder Webfont-Dateien) von dort an den Nutzer zu übermitteln. Wir verlinken | ||||
| 					auch nicht in soziale Netzwerke. Insofern können von Dritten keine personenbezogenen Daten | ||||
| 					über unsere Onlinepräsenz erhoben werden, es sei denn, die Datenerfassung durch Dritte | ||||
| 					basiert auf einer gesetzlichen Grundlage und/oder wurde behördlich angeordnet.<br />In | ||||
| 					unseren Inhalten können sich jedoch Hyperlinks („Links“) auf fremde Onlineangebote | ||||
| 					befinden. Mit dem Anklicken eines solchen Links verlässt der Nutzer unsere Onlinepräsenz | ||||
| 					und damit den Geltungsbereich dieser Datenschutzerklärung. | ||||
| 				</p> | ||||
| 				<h2>Erhobene Daten bei Kontakt</h2> | ||||
| 				<p> | ||||
| 					Unsere Onlinepräsenz hält unter anderem aufgrund gesetzlicher Vorgaben verschiedene | ||||
| 					Möglichkeiten bereit, mit uns in Kontakt zu treten. Sofern eine betroffene Person Kontakt | ||||
| 					zu uns aufnimmt, werden die von der betroffenen Person übermittelten personenbezogenen | ||||
| 					Daten automatisch gespeichert (z. B. Telefonnummer, E-Mail-Adresse). Diese Angaben werden | ||||
| 					zum Zwecke der Bearbeitung sowie für sich möglicherweise anschließende Kommunikation von | ||||
| 					uns gespeichert. Sobald die Speicherung dieser Daten nicht mehr erforderlich ist und keine | ||||
| 					gesetzlichen Archivierungsgründe vorliegen, werden die Daten gelöscht. Die | ||||
| 					Erforderlichkeit wird alle zwei Jahre überprüft. Es erfolgt keine Weitergabe dieser | ||||
| 					personenbezogenen Daten an Dritte.<br />Von betroffenen Personen übermittelte | ||||
| 					Informationen zur Bearbeitung einer Kontaktanfrage werden gemäß Art. 6 Abs. 1 lit. b | ||||
| 					(vertragliche und vorvertragliche Beziehungen) oder lit. f (andere Anfragen) der DSGVO | ||||
| 					verarbeitet. | ||||
| 				</p> | ||||
| 				<h2>Speicherung und Löschung von personenbezogenen Daten</h2> | ||||
| 				<p> | ||||
| 					Personenbezogene Daten werden von uns für die Dauer der entsprechenden gesetzlichen | ||||
| 					Aufbewahrungspflichten oder für den zur Vertragserfüllung erforderlichen Zeitraum | ||||
| 					gespeichert. Liegen solche Gründe nicht vor, werden personenbezogene Daten für den | ||||
| 					Zeitraum, der zur Erreichung des Speicherzwecks erforderlich ist, verarbeitet und | ||||
| 					gespeichert, sofern in dieser Datenschutzerklärung nicht ausdrücklich anderes angegeben | ||||
| 					ist. Sobald die Daten für ihre Zweckbestimmung nicht mehr erforderlich sind oder der | ||||
| 					Speicherungszweck entfällt, werden sie nach Maßgabe der gesetzlichen Vorschriften gelöscht | ||||
| 					oder in ihrer Verarbeitung eingeschränkt.<br />Sollten die Daten nicht gelöscht werden | ||||
| 					dürfen, weil sie einer gesetzlichen Aufbewahrungspflicht unterliegen, wird deren | ||||
| 					Verarbeitung durch Archivierung eingeschränkt. Die Daten werden erst nach Ablauf der | ||||
| 					gesetzlich vorgeschriebenen Speicherfrist gelöscht.<br />Alle sechs Monate wird | ||||
| 					routinemäßig geprüft, ob der Speicherungszweck weggefallen bzw. die Aufbewahrungspflicht | ||||
| 					abgelaufen ist. Anschließend wird gegebenenfalls die Löschung durchgeführt. | ||||
| 				</p> | ||||
| 				<h2>Rechte der betroffenen Personen</h2> | ||||
| 				<p> | ||||
| 					Unter den angegebenen Kontaktdaten können betroffene Personen jederzeit nachgenannte | ||||
| 					Rechte ausüben. Eine betroffene Person kann von uns verlangen, dass | ||||
| 				</p> | ||||
| 				<ul> | ||||
| 					<li> | ||||
| 						Auskunft über sie betreffende, bei uns gespeicherte Daten und deren Verarbeitung erteilt | ||||
| 						wird (Art. 15 DSGVO), | ||||
| 					</li> | ||||
| 					<li> | ||||
| 						sie betreffende unrichtige personenbezogene Daten berichtigt werden (Art. 16 DSGVO), | ||||
| 					</li> | ||||
| 					<li> | ||||
| 						sie betreffende, bei uns gespeicherte personenbezogene Daten gelöscht werden (Art. 17 | ||||
| 						DSGVO), | ||||
| 					</li> | ||||
| 					<li> | ||||
| 						die Verarbeitung sie betreffender, bei uns gespeicherter Daten, die aufgrund | ||||
| 						gesetzlicher Vorschriften oder anderer Gründe nicht gelöscht werden dürfen, | ||||
| 						eingeschränkt wird (Art. 18 DSGVO), | ||||
| 					</li> | ||||
| 					<li> | ||||
| 						sie betreffende Daten übertragbar sind, soweit sie in die Datenverarbeitung eingewilligt | ||||
| 						oder einen Vertrag mit uns geschlossen hat (Art. 20 DSGVO), | ||||
| 					</li> | ||||
| 					<li> | ||||
| 						sie betreffende Daten nach einem Widerspruch nicht weiter von uns verarbeitet werden | ||||
| 						(Art. 21 DSGVO). | ||||
| 					</li> | ||||
| 				</ul> | ||||
| 				<p>Eine betroffene Person hat ferner jederzeit das Recht,</p> | ||||
| 				<ul> | ||||
| 					<li> | ||||
| 						eine erteilte Einwilligung in die Erhebung und Verarbeitung personenbezogener Daten nach | ||||
| 						Art. 6 Abs. 1 lit. a oder Art. 9 Abs. 2 lit. a DSGVO für die Zukunft zu widerrufen (Art. | ||||
| 						7 Abs. 3 DSGVO), | ||||
| 					</li> | ||||
| 					<li> | ||||
| 						sich mit einer Beschwerde an eine Aufsichtsbehörde zu wenden (Art. 15 Abs. 1 lit. f | ||||
| 						DSGVO). Eine Liste der Aufsichtsbehörden lässt sich unter <a | ||||
| 							href="https://www.bfdi.bund.de/DE/Infothek/Anschriften_Links/anschriften_links-node.html" | ||||
| 							>diesem Link</a | ||||
| 						> abrufen. | ||||
| 					</li> | ||||
| 				</ul> | ||||
| 				<h2>Änderung unserer Datenschutzerklärung</h2> | ||||
| 				<p> | ||||
| 					Wir behalten uns vor, diese Datenschutzerklärung ohne vorherige Ankündigung an neue | ||||
| 					rechtliche oder technische Sachverhalte sowie an Änderungen unserer Leistungen oder | ||||
| 					Prozesse anzupassen. Es gilt die jeweils auf der Onlinepräsenz veröffentlichte Version der | ||||
| 					Datenschutzerklärung. | ||||
| 				</p> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
							
								
								
									
										118
									
								
								views/routes/filter/body.gohtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								views/routes/filter/body.gohtml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| <div class="flex flex-row justify-center gap-4" id="filter"> | ||||
| 	<div class="bg-white border border-slate-200 rounded-lg shadow-sm p-4 w-full max-w-md"> | ||||
| 		<h3 class="text-lg font-semibold text-slate-800 mb-4 flex items-center gap-2"> | ||||
| 			<i class="ri-calendar-line text-slate-600"></i> | ||||
| 				Auswahl nach Datum, Nummer od. Seite | ||||
| 		</h3> | ||||
|  | ||||
| 		<!-- Unified Year Jump Filter --> | ||||
| 		<year-jump-filter data-issues="{{ .IssuesByYearJSON }}"> | ||||
| 			<div class="space-y-3"> | ||||
| 				<!-- Year Selection --> | ||||
| 				<div class="flex items-center gap-2 mb-4"> | ||||
| 					<label for="year-select" class="text-sm text-slate-600 w-12 hidden">Jahr wählen...</label> | ||||
| 					<select id="year-select" class="tabular-nums flex-1 px-2 py-1 border border-slate-300 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-400 focus:border-blue-400" style="max-height: 200px; overflow-y: auto;"> | ||||
| 						<option value="">Jahr wählen</option> | ||||
| 						{{ range $year := .AvailableYears }} | ||||
| 							<option value="{{ $year }}">{{ $year }}</option> | ||||
| 						{{ end }} | ||||
| 					</select> | ||||
| 				</div> | ||||
|  | ||||
| 				<!-- Ausgabe Selection - Two Selects --> | ||||
| 				<div class="flex items-center gap-2"> | ||||
| 					<select id="issue-number-select" disabled class="flex-1 px-2 py-1 border border-slate-300 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-400 focus:border-blue-400 disabled:bg-slate-100 disabled:cursor-not-allowed"> | ||||
| 						<option value="">Nr.</option> | ||||
| 					</select> | ||||
| 					<select id="issue-date-select" disabled class="flex-1 px-2 py-1 border border-slate-300 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-400 focus:border-blue-400 disabled:bg-slate-100 disabled:cursor-not-allowed"> | ||||
| 						<option value="">Datum</option> | ||||
| 					</select> | ||||
| 				</div> | ||||
|  | ||||
| 				<!-- OR Divider --> | ||||
| 				<div class="flex items-center my-3"> | ||||
| 					<div class="flex-1 border-t border-slate-300"></div> | ||||
| 					<span class="px-2 text-xs text-slate-500 bg-white">oder</span> | ||||
| 					<div class="flex-1 border-t border-slate-300"></div> | ||||
| 				</div> | ||||
|  | ||||
| 				<!-- Page Input --> | ||||
| 				<div class="flex items-center gap-2"> | ||||
| 					<label for="page-input" class="text-sm text-slate-600 w-12 hidden"> oder Seite eingeben...</label> | ||||
| 					<input type="number" id="page-input" min="1" placeholder="Seite eingeben" disabled class="flex-1 px-2 py-1 border border-slate-300 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-400 focus:border-blue-400 disabled:bg-slate-100 disabled:cursor-not-allowed disabled:text-slate-500"> | ||||
| 				</div> | ||||
|  | ||||
| 				<!-- Page Jump Button --> | ||||
| 				<button id="page-jump-btn" type="button" disabled class="w-full inline-flex items-center justify-center px-3 py-2 bg-slate-400 text-white text-sm rounded transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-slate-300 focus:ring-offset-1 disabled:bg-slate-400 disabled:cursor-not-allowed enabled:bg-blue-600 enabled:hover:bg-blue-700 enabled:focus:ring-blue-500"> | ||||
| 					<i class="ri-arrow-right-line mr-2"></i> | ||||
| 					Zur Seite springen | ||||
| 				</button> | ||||
|  | ||||
| 				<!-- Error Display Area --> | ||||
| 				<div id="jump-errors" class="mt-2 min-h-[1rem]"></div> | ||||
| 			</div> | ||||
| 		</year-jump-filter> | ||||
| 	</div> | ||||
|  | ||||
| 	<div class="bg-white border border-slate-200 rounded-lg shadow-sm p-4 w-full max-w-md"> | ||||
| 		<h3 class="text-lg font-semibold text-slate-800 mb-4 flex items-center gap-2"> | ||||
| 			<i class="ri-user-line text-slate-600"></i> | ||||
| 			Auswahl nach Person | ||||
| 		</h3> | ||||
|  | ||||
| 		<!-- Person Jump Filter --> | ||||
| 		<person-jump-filter> | ||||
| 			<div class="space-y-3"> | ||||
| 				<div class="flex items-center gap-2"> | ||||
| 					<label for="person-search" class="hidden text-sm text-slate-600 w-16">Filter</label> | ||||
| 					<input | ||||
| 						type="text" | ||||
| 						id="person-search" | ||||
| 						placeholder="Name oder Lebensdaten eingeben..." | ||||
| 						class="flex-1 px-2 py-1 border border-slate-300 rounded text-sm focus:outline-none focus:ring-1 focus:ring-blue-400 focus:border-blue-400" | ||||
| 					> | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="flex items-center gap-2"> | ||||
| 					<input | ||||
| 						type="checkbox" | ||||
| 						id="authors-only" | ||||
| 						class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 focus:ring-2" | ||||
| 					> | ||||
| 					<label for="authors-only" class="text-sm text-slate-600">Nur Autor:innen anzeigen</label> | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="max-h-48 overflow-y-auto border border-slate-300 rounded bg-white text-sm"> | ||||
| 					<!-- All Persons List --> | ||||
| 					<div id="all-persons"> | ||||
| 						{{ range $person := .Persons }} | ||||
| 							<div class="person-item odd:bg-slate-50 even:bg-white"> | ||||
| 								<a href="/akteure/{{ $person.ID }}" class="block px-2 py-1 hover:bg-blue-50 border-b border-slate-100 last:border-b-0"> | ||||
| 									<span class="person-name font-medium text-slate-800">{{ $person.Name }}</span> | ||||
| 									{{ if $person.Life }} | ||||
| 										<span class="person-life text-xs text-slate-500 ml-2">{{ $person.Life }}</span> | ||||
| 									{{ end }} | ||||
| 								</a> | ||||
| 							</div> | ||||
| 						{{ end }} | ||||
| 					</div> | ||||
|  | ||||
| 					<!-- Authors Only List (initially hidden) --> | ||||
| 					<div id="authors-only-list" style="display: none;"> | ||||
| 						{{ range $author := .Authors }} | ||||
| 							<div class="person-item odd:bg-slate-50 even:bg-white"> | ||||
| 								<a href="/akteure/{{ $author.ID }}" class="block px-2 py-1 hover:bg-blue-50 border-b border-slate-100 last:border-b-0"> | ||||
| 									<span class="person-name font-medium text-slate-800">{{ $author.Name }}</span> | ||||
| 									{{ if $author.Life }} | ||||
| 										<span class="person-life text-xs text-slate-500 ml-2">{{ $author.Life }}</span> | ||||
| 									{{ end }} | ||||
| 								</a> | ||||
| 							</div> | ||||
| 						{{ end }} | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</person-jump-filter> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| @@ -0,0 +1,125 @@ | ||||
| {{ if .model.SelectedPlace }} | ||||
| 	<!-- Single Place Detail View --> | ||||
| 	<div class="max-w-7xl mx-auto px-8 py-8"> | ||||
| 		<div class="bg-white px-6 py-6 rounded w-full"> | ||||
| 			<!-- Back Navigation --> | ||||
| 			<div class="mb-6"> | ||||
| 				<a href="/ort/" class="inline-flex items-center text-blue-600 hover:text-blue-700 text-sm"> | ||||
| 					<i class="ri-arrow-left-line mr-2"></i> | ||||
| 					Zur<75>ck zur <20>bersicht | ||||
| 				</a> | ||||
| 			</div> | ||||
|  | ||||
| 			<!-- Place Header --> | ||||
| 			<div class="mb-8"> | ||||
| 				<h1 class="text-3xl font-bold text-slate-800 mb-2"> | ||||
| 					{{ if .model.SelectedPlace.Place.Names }} | ||||
| 						{{ index .model.SelectedPlace.Place.Names 0 }} | ||||
| 					{{ else }} | ||||
| 						{{ .model.SelectedPlace.Place.ID }} | ||||
| 					{{ end }} | ||||
| 				</h1> | ||||
| 				{{ if .model.SelectedPlace.Place.Geo }} | ||||
| 					<p class="text-slate-600"> | ||||
| 						<i class="ri-map-pin-line mr-1"></i> | ||||
| 						Geonames: {{ .model.SelectedPlace.Place.Geo }} | ||||
| 					</p> | ||||
| 				{{ end }} | ||||
| 			</div> | ||||
|  | ||||
| 			<!-- Associated Pieces --> | ||||
| 			<div> | ||||
| 				<h2 class="text-xl font-semibold text-slate-800 mb-4"> | ||||
| 					Beitr<74>ge ({{ len .model.SelectedPlace.Pieces }}) | ||||
| 				</h2> | ||||
|  | ||||
| 				{{ if .model.SelectedPlace.Pieces }} | ||||
| 					<div class="space-y-4"> | ||||
| 						{{ range $piece := .model.SelectedPlace.Pieces }} | ||||
| 							<div class="border border-slate-200 rounded-lg p-4 hover:bg-slate-50"> | ||||
| 								<h3 class="font-medium text-slate-800 mb-2"> | ||||
| 									{{ if $piece.Title }} | ||||
| 										{{ index $piece.Title 0 }} | ||||
| 									{{ else }} | ||||
| 										Untitled | ||||
| 									{{ end }} | ||||
| 								</h3> | ||||
|  | ||||
| 								{{ if $piece.IssueRefs }} | ||||
| 									<div class="text-sm text-slate-600"> | ||||
| 										{{ range $issueRef := $piece.IssueRefs }} | ||||
| 											<span class="inline-block mr-4"> | ||||
| 												<i class="ri-calendar-line mr-1"></i> | ||||
| 												<a href="/{{ $issueRef.When.Year }}/{{ $issueRef.IssueNumber }}" class="text-blue-600 hover:text-blue-700"> | ||||
| 													{{ $issueRef.When.Year }} Nr. {{ $issueRef.IssueNumber }} | ||||
| 												</a> | ||||
| 											</span> | ||||
| 										{{ end }} | ||||
| 									</div> | ||||
| 								{{ end }} | ||||
| 							</div> | ||||
| 						{{ end }} | ||||
| 					</div> | ||||
| 				{{ else }} | ||||
| 					<p class="text-slate-500 italic">Keine Beitr<74>ge f<>r diesen Ort gefunden.</p> | ||||
| 				{{ end }} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | ||||
| {{ else }} | ||||
| 	<!-- Places Overview --> | ||||
| 	<div class="max-w-7xl mx-auto px-8 py-8"> | ||||
| 		<div class="bg-white px-6 py-6 rounded w-full"> | ||||
| 			<h1 class="text-3xl font-bold text-slate-800 mb-8">Orte</h1> | ||||
|  | ||||
| 			<!-- Available Letters Navigation --> | ||||
| 			{{ if .model.AvailableLetters }} | ||||
| 				<div class="mb-8"> | ||||
| 					<h2 class="text-lg font-semibold text-slate-700 mb-4">Nach Anfangsbuchstabe</h2> | ||||
| 					<div class="flex flex-wrap gap-2"> | ||||
| 						{{ range $letter := .model.AvailableLetters }} | ||||
| 							<span class="px-3 py-2 bg-slate-100 text-slate-700 rounded text-sm"> | ||||
| 								{{ $letter }} | ||||
| 							</span> | ||||
| 						{{ end }} | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			{{ end }} | ||||
|  | ||||
| 			<!-- Places List --> | ||||
| 			{{ if .model.Places }} | ||||
| 				<div> | ||||
| 					<h2 class="text-lg font-semibold text-slate-700 mb-4"> | ||||
| 						Alle Orte ({{ len .model.Places }}) | ||||
| 					</h2> | ||||
|  | ||||
| 					<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> | ||||
| 						{{ range $placeID := .model.Sorted }} | ||||
| 							{{ $place := index $.model.Places $placeID }} | ||||
| 							<div class="border border-slate-200 rounded-lg hover:bg-slate-50"> | ||||
| 								<a href="/ort/{{ $place.ID }}" class="block p-4"> | ||||
| 									<h3 class="font-medium text-slate-800 mb-1"> | ||||
| 										{{ if $place.Names }} | ||||
| 											{{ index $place.Names 0 }} | ||||
| 										{{ else }} | ||||
| 											{{ $place.ID }} | ||||
| 										{{ end }} | ||||
| 									</h3> | ||||
| 									{{ if $place.Geo }} | ||||
| 										<p class="text-sm text-slate-600"> | ||||
| 											<i class="ri-map-pin-line mr-1"></i> | ||||
| 											{{ $place.Geo }} | ||||
| 										</p> | ||||
| 									{{ end }} | ||||
| 								</a> | ||||
| 							</div> | ||||
| 						{{ end }} | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			{{ else }} | ||||
| 				<p class="text-slate-500 italic">Keine Orte gefunden.</p> | ||||
| 			{{ end }} | ||||
| 		</div> | ||||
| 	</div> | ||||
| {{ end }} | ||||
		Reference in New Issue
	
	Block a user
	 Simon Martens
					Simon Martens