Compare commits
	
		
			No commits in common. "server" and "map" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										15
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							|  | @ -1,15 +0,0 @@ | |||
| { | ||||
|     // Use IntelliSense to learn about possible attributes. | ||||
|     // Hover to view descriptions of existing attributes. | ||||
|     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|     "version": "0.2.0", | ||||
|     "configurations": [ | ||||
|         { | ||||
|             "type": "chrome", | ||||
|             "request": "launch", | ||||
|             "name": "Launch Chrome against localhost", | ||||
|             "url": "http://localhost:8080", | ||||
|             "webRoot": "${workspaceFolder}" | ||||
|         } | ||||
|     ] | ||||
| } | ||||
|  | @ -10,7 +10,8 @@ | |||
|     html,body,#map {height:100%;margin:0} | ||||
|     .coords{position:absolute;left:6px;bottom:6px;z-index:1000;background:rgba(255,255,255,.85); | ||||
|       padding:3px 6px;font-size:12px;border-radius:4px;font-family:system-ui,Segoe UI,Arial} | ||||
|       .center-dot{position:absolute;top:50%;left:50%;width:5px;height:5px;background:red;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 2px rgba(255,255,255,.95),0 0 2px rgba(0,0,0,.35);pointer-events:none;z-index:1001} | ||||
|       .center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;background:red;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 2px rgba(255,255,255,.95),0 0 6px rgba(0,0,0,.35);pointer-events:none;z-index:1001} | ||||
|       .center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;background:red;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 2px rgba(255,255,255,.95),0 0 6px rgba(0,0,0,.35);pointer-events:none;z-index:1001} | ||||
|     .copy-btn{position:absolute;left:6px;bottom:36px;z-index:1000;background:#ef4444;color:#fff;border:0;border-radius:6px;padding:6px 10px;font:600 12px/1 system-ui,Segoe UI,Arial;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.25)} | ||||
|     .copy-btn:active{transform:translateY(1px)} | ||||
|   </style> | ||||
|  | @ -179,8 +180,7 @@ if (hash.length >= 2) { | |||
|       }); | ||||
|     }); | ||||
|   </script> | ||||
|   <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | ||||
|   <script src="markers.js"></script> | ||||
| 
 | ||||
|   <script src="markers.js"></script> | ||||
| </body> | ||||
| </html> | ||||
|  |  | |||
							
								
								
									
										117
									
								
								markers.js
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								markers.js
									
									
									
									
									
								
							|  | @ -1,40 +1,91 @@ | |||
| let Data_api = "/webhook/data"; | ||||
| let freight = null; | ||||
| let testing = true; | ||||
| // === CONFIG ===
 | ||||
| const WIKI_API = 'https://wiki.arenos.danielnagel.at/api.php'; // dein Wiki-Host (mit index.php)
 | ||||
| const CATEGORY_TITLE = 'Kategorie:Orte';                          // Hauptkategorie
 | ||||
| const MAX_PAGES = 500;                                            // genug Luft
 | ||||
| 
 | ||||
| let ReqData = { Places: "Stadte"} | ||||
| 
 | ||||
| // Post to n8n Server to get Data from Grist in JSON format.
 | ||||
| async function GetMarkerData() { | ||||
|    | ||||
|   try { | ||||
|     const res = await axios.post(Data_api, ReqData); | ||||
|     console.log (res.data); | ||||
|     RenderMarkers(res.data); | ||||
| 
 | ||||
|   } catch (err) { | ||||
|     console.error (err); | ||||
| // Hilfsfunktion: MediaWiki API-URL bauen
 | ||||
| function apiURL(params) { | ||||
|   const u = new URL(WIKI_API); | ||||
|   u.search = new URLSearchParams({ ...params, format: 'json', origin: '*' }).toString(); | ||||
|   return u.toString(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| //Render Map Markers with the Position from Grist Database
 | ||||
| function RenderMarkers(rows){ | ||||
|   if (!Array.isArray(rows)) { | ||||
|     console.error('Erwarte ein Array, bekam:', rows); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   rows.forEach((row) => { | ||||
|     const x = Number(row.X); | ||||
|     const y = Number(row.Y); | ||||
|     if (!Number.isFinite(x) || !Number.isFinite(y)) return; | ||||
| 
 | ||||
|     L.marker([y, x])        // [lat, lng] -> [Y, X]
 | ||||
|       .addTo(map) | ||||
|       .bindPopup(`<b>${row.Name ?? ''}</b>`); | ||||
| // 1) Alle Mitglieder einer Kategorie holen
 | ||||
| async function fetchCategoryMembers(categoryTitle) { | ||||
|   const url = apiURL({ | ||||
|     action: 'query', | ||||
|     list: 'categorymembers', | ||||
|     cmtitle: categoryTitle, | ||||
|     cmlimit: String(MAX_PAGES) | ||||
|   }); | ||||
|   const res = await fetch(url); | ||||
|   if (!res.ok) throw new Error(`categorymembers failed: ${res.status}`); | ||||
|   const data = await res.json(); | ||||
|   return data?.query?.categorymembers || []; | ||||
| } | ||||
| 
 | ||||
| // 2) Gerendertes HTML einer Seite holen (damit <div class="place-data"> drin ist)
 | ||||
| async function fetchPageHTML(title) { | ||||
|   const url = apiURL({ | ||||
|     action: 'parse', | ||||
|     page: title, | ||||
|     prop: 'text' | ||||
|   }); | ||||
|   const res = await fetch(url); | ||||
|   if (!res.ok) throw new Error(`parse failed for ${title}: ${res.status}`); | ||||
|   const data = await res.json(); | ||||
|   const html = data?.parse?.text?.['*'] || ''; | ||||
|   const div = document.createElement('div'); | ||||
|   div.innerHTML = html; | ||||
|   return div; | ||||
| } | ||||
| 
 | ||||
| // 3) Daten aus dem versteckten Div extrahieren
 | ||||
| function extractPlaceData(container) { | ||||
|   const node = container.querySelector('.place-data'); | ||||
|   if (!node) return null; | ||||
|   const name = node.getAttribute('data-name') || ''; | ||||
|   const xStr = node.getAttribute('data-x') || ''; | ||||
|   const yStr = node.getAttribute('data-y') || ''; | ||||
|   const desc = node.getAttribute('data-description') || ''; | ||||
|   const link = node.getAttribute('data-link') || ''; | ||||
|   const x = parseFloat(xStr); | ||||
|   const y = parseFloat(yStr); | ||||
|   if (Number.isNaN(x) || Number.isNaN(y)) return null; | ||||
|   return { name, x, y, desc, link }; | ||||
| } | ||||
| 
 | ||||
| // 4) Marker laden + hinzufügen
 | ||||
| async function loadWikiMarkers(map) { | ||||
|   try { | ||||
|     const pages = await fetchCategoryMembers(CATEGORY_TITLE); | ||||
| 
 | ||||
|     // Optionales Bounding, falls du später auto-fit willst
 | ||||
|     const layers = []; | ||||
|     for (const p of pages) { | ||||
|       try { | ||||
|         const html = await fetchPageHTML(p.title); | ||||
|         const d = extractPlaceData(html); | ||||
|         if (!d) continue; | ||||
| 
 | ||||
|         // Leaflet: Bei CRS.Simple = [y, x]
 | ||||
|         const m = L.marker([d.y, d.x]).addTo(map); | ||||
|         const wikiLink = d.link || `https://wiki.arenos.danielnagel.at/index.php/${encodeURIComponent(p.title)}`; | ||||
|         const popup = ` | ||||
|           <b>${d.name || p.title}</b><br> | ||||
|           ${d.desc ? `${d.desc}<br>` : ''} | ||||
|           <a href="${wikiLink}" target="_blank" rel="noopener">Open in Wiki</a> | ||||
|         `;
 | ||||
|         m.bindPopup(popup); | ||||
|         layers.push(m); | ||||
| 
 | ||||
|       } catch (e) { | ||||
|         console.warn('skip page due to parse error:', p.title, e); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|   } catch (e) { | ||||
|     console.error('Failed to load wiki markers:', e); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| GetMarkerData(); | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user