prepare intranet for first Dokploy deployment
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
////==========================================//
|
||||
//// GLOBALER BEREICH //
|
||||
////////////////////////////////////////////////
|
||||
//// Globale Konstanten
|
||||
const url = new URL(window.location.href);
|
||||
const basisUrl = url.origin + url.pathname;
|
||||
////
|
||||
////////////////////////////////////////////////
|
||||
////==========================================//
|
||||
|
||||
|
||||
|
||||
////==========================================//
|
||||
//// FUNKTIONEN und LISTENER //
|
||||
////////////////////////////////////////////////
|
||||
////
|
||||
|
||||
// Position der Elemente – min-height wird jetzt vollständig per CSS gelöst (nak-design.css)
|
||||
// Die alte JS-Berechnung wurde entfernt, da sie nach dem Laden die Höhe reduzierte.
|
||||
|
||||
|
||||
// JavaScript zum Erkennen der Scroll-Richtung und zum Umschalten der Klasse
|
||||
// Funktioniert sowohl bei Body-Scroll als auch bei internem Container-Scroll (z.B. eventbox_table)
|
||||
var lastScrollTop = 0;
|
||||
var lastContainerScrollTop = 0;
|
||||
|
||||
function handleHeaderScroll(scrollTop, lastScroll) {
|
||||
const elemHeaderMenue = document.getElementById('header_menue');
|
||||
const elemHeaderTitle = document.getElementById('header_title');
|
||||
|
||||
// Dynamische Höhe aus CSS-Variable lesen
|
||||
const headerHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 64;
|
||||
|
||||
// Kein Einfahren, wenn der Content auf die Seite passt (kein Scrollen nötig)
|
||||
if (document.documentElement.scrollHeight <= window.innerHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Am unteren Ende der Seite: Header wieder einblenden
|
||||
const atBottom = (window.innerHeight + window.scrollY) >= (document.documentElement.scrollHeight - 5);
|
||||
|
||||
if (scrollTop > lastScroll && !atBottom) {
|
||||
// Menü raus bei Scroll nach unten
|
||||
if (elemHeaderMenue) {
|
||||
elemHeaderMenue.style.top = `-${headerHeight}px`;
|
||||
elemHeaderMenue.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
if (elemHeaderTitle) {
|
||||
elemHeaderTitle.style.top = "0";
|
||||
elemHeaderTitle.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
} else {
|
||||
// Menü wieder rein bei Scroll nach oben
|
||||
if (elemHeaderMenue) {
|
||||
elemHeaderMenue.style.top = "0";
|
||||
elemHeaderMenue.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
if (elemHeaderTitle) {
|
||||
elemHeaderTitle.style.top = `${headerHeight}px`;
|
||||
elemHeaderTitle.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Body/Document Scroll
|
||||
document.addEventListener("scroll", function() {
|
||||
var st = window.scrollY || document.documentElement.scrollTop;
|
||||
handleHeaderScroll(st, lastScrollTop);
|
||||
lastScrollTop = st <= 0 ? 0 : st;
|
||||
}, false);
|
||||
|
||||
// Auch bei internem Container-Scroll (eventbox_table, display_within_dev)
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const scrollContainers = document.querySelectorAll('.eventbox_table, form.display_within_dev');
|
||||
scrollContainers.forEach(function(container) {
|
||||
var lastCST = 0;
|
||||
container.addEventListener("scroll", function() {
|
||||
var st = container.scrollTop;
|
||||
handleHeaderScroll(st, lastCST);
|
||||
lastCST = st <= 0 ? 0 : st;
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function openCloseHeaderProfile() {
|
||||
if (window.innerWidth >= 769) {
|
||||
// Desktop: click on profile image goes to profile page
|
||||
window.location.href = '/intranet_repo/projects/intranet/profile.php';
|
||||
} else {
|
||||
// Mobile: toggle expand/collapse
|
||||
const hpElem = document.getElementById('header_profile');
|
||||
hpElem.classList.toggle('header_profile_slideLeft');
|
||||
}
|
||||
}
|
||||
|
||||
function openCloseOverlay(id) {
|
||||
//Overlay ein-/ausblenden - beim Ausblenden zurück auf eigene Seite
|
||||
const elem = document.getElementById(id);
|
||||
|
||||
if (elem.style.display === "flex") {
|
||||
elem.style.display = "none";
|
||||
} else {
|
||||
elem.style.display = "flex";
|
||||
}
|
||||
}
|
||||
|
||||
function openCloseProfile(id, name, overlay) {
|
||||
// Profil per Klick öffnen/schließen, alle anderen immer schließen
|
||||
|
||||
const profiles = document.getElementsByName(name); //Ausgewählter Profilbereich (visit, calendar, ...)
|
||||
const oProfile = document.getElementById(overlay); //Ausgewähltes Overlay
|
||||
const aProfile = document.getElementById(id); //Ausgewähltes Profil
|
||||
const aId = (id > 0) ? aProfile.id : 0; //Ausweichen, wenn kein Profil gewählt
|
||||
|
||||
console.log('id:' + id);
|
||||
console.log('overlay:' + overlay);
|
||||
console.log('name:' + name);
|
||||
|
||||
if (oProfile.style.display === "flex") { //Overlay ein-/ausblenden
|
||||
oProfile.style.display = "none";
|
||||
} else {
|
||||
oProfile.style.display = "flex";
|
||||
//TODO: folgender ScrollTop greift nicht, WARUM?
|
||||
//oProfile.scrollTop = 0; //Hinscrollen zum Beginn des Overlays, vor allem bei @Media
|
||||
}
|
||||
|
||||
for (let i = 0; i < profiles.length; i++) {
|
||||
|
||||
const cProfile = profiles[i]; //Aktuelles Profil (Style: profile_container)
|
||||
|
||||
if (cProfile.id === aId && cProfile.style.display !== "block") {
|
||||
profiles[i].style.display = "block";
|
||||
} else {
|
||||
profiles[i].style.display = "none";
|
||||
}
|
||||
}
|
||||
document.activeElement.blur(); //Fokus entfernen
|
||||
|
||||
// TEST console.log(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function mix(content) { //wird aktuell nicht eingesetzt, Daten werden per SQL randomized
|
||||
const list = document.getElementById(content);
|
||||
const items = Array.from(list.children);
|
||||
console.log('Vor dem Mischen:', items.map(item => item.textContent || item.innerText));
|
||||
|
||||
for (let i = items.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[items[i], items[j]] = [items[j], items[i]];
|
||||
}
|
||||
|
||||
console.log('Nach dem Mischen:', items.map(item => item.textContent || item.innerText));
|
||||
items.forEach(item => list.appendChild(item));
|
||||
}
|
||||
|
||||
|
||||
function showHideText(element) {
|
||||
element.classList.toggle("open");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Per Taste Overlay verlassen
|
||||
document.addEventListener('keydown', function(event) {
|
||||
const profileVisitOverlay = document.getElementById('profile_visit_overlay');
|
||||
const profileCalendarOverlay = document.getElementById('profile_calendar_overlay');
|
||||
const addNewUser = document.getElementById('addNewUser');
|
||||
const showMessage = document.getElementById('showMessage');
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
if (profileVisitOverlay && profileVisitOverlay.style.display === 'flex') {
|
||||
openCloseProfile(0, 'profile_visit', 'profile_visit_overlay');
|
||||
}
|
||||
if (profileCalendarOverlay && profileCalendarOverlay.style.display === 'flex') {
|
||||
openCloseProfile(0, 'profile_calendar', 'profile_calendar_overlay');
|
||||
}
|
||||
if (addNewUser && addNewUser.style.display === 'flex') {
|
||||
openCloseOverlay('addNewUser');
|
||||
}
|
||||
} else if (event.key === 'Enter' || event.key === 'Return' || event.key === " ") {
|
||||
if (showMessage && showMessage.style.display === 'flex') {
|
||||
openCloseOverlay('showMessage'); // ausblenden
|
||||
window.location.href=basisUrl; // zur aktuellen Seite zurückkehren
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Fokus auf passendes Element beim Laden der Intranet-Seiten
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
document.querySelector("#admintable tr[tabindex='0']")?.focus(); // Adminpanel
|
||||
document.querySelector("#visittable tr[tabindex='0']")?.focus(); // Besuchsstellen
|
||||
});
|
||||
@@ -0,0 +1,247 @@
|
||||
////==========================================//
|
||||
////GLOBALER BEREICH//
|
||||
////////////////////////////////////////////////
|
||||
////Globale Konstanten
|
||||
|
||||
////
|
||||
////////////////////////////////////////////////
|
||||
////==========================================//
|
||||
|
||||
|
||||
|
||||
////==========================================//
|
||||
////FUNKTIONEN und LISTENER//
|
||||
////////////////////////////////////////////////
|
||||
////
|
||||
|
||||
|
||||
// Warten, bis das DOM vollstaendig geladen ist
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var menuItems = document.querySelectorAll('.content-tab-bar__item[data-target]');
|
||||
|
||||
// Event-Listener fuer Klickereignisse auf Menueintraege
|
||||
menuItems.forEach(function(item) {
|
||||
item.addEventListener('click', function() {
|
||||
// Entferne die aktive Klasse von allen Menueintraegen
|
||||
menuItems.forEach(function(menuItem) {
|
||||
menuItem.classList.remove('active');
|
||||
});
|
||||
|
||||
// Fuege die aktive Klasse zum geklickten Menuelement hinzu
|
||||
item.classList.add('active');
|
||||
|
||||
// Verstecke alle Inhaltsbereiche
|
||||
document.querySelectorAll('.content_seelsorge').forEach(function(section) {
|
||||
section.classList.remove('active');
|
||||
});
|
||||
|
||||
// Zeige den entsprechenden Inhalt an
|
||||
var contentId = item.getAttribute('data-target');
|
||||
document.getElementById(contentId).classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
// ESC-Taste schliesst offene Modals
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeCalendarHelp();
|
||||
closeDayModal();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Wechsel der Kalenderblaetter Monat 1 und 2
|
||||
function switchCalendar(type) {
|
||||
const calendar_header_1 = document.querySelector('#calendar_header_1');
|
||||
const calendar_header_2 = document.querySelector('#calendar_header_2');
|
||||
const calendar_1 = document.querySelectorAll('[name="calendar_1"]');
|
||||
const calendar_2 = document.querySelectorAll('[name="calendar_2"]');
|
||||
|
||||
const isLeft = type === "left";
|
||||
calendar_header_1.style.display = isLeft ? "flex" : "none";
|
||||
calendar_header_2.style.display = isLeft ? "none" : "flex";
|
||||
|
||||
calendar_1.forEach(cal => cal.style.visibility = isLeft ? "visible" : "collapse");
|
||||
calendar_2.forEach(cal => cal.style.visibility = isLeft ? "collapse" : "visible");
|
||||
}
|
||||
|
||||
|
||||
// Tages-Modal oeffnen
|
||||
async function openDayModal(calendarDate) {
|
||||
if (!calendarDate) return;
|
||||
|
||||
const modal = document.getElementById('seelsorge-day-modal');
|
||||
const body = document.getElementById('modal-day-body');
|
||||
const title = document.getElementById('modal-day-title');
|
||||
const subtitle = document.getElementById('modal-day-subtitle');
|
||||
|
||||
if (!modal || !body || !title || !subtitle) {
|
||||
console.error('openDayModal: Modal-Elemente nicht gefunden.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Modal sofort anzeigen mit Ladezustand
|
||||
title.textContent = 'Laden...';
|
||||
subtitle.innerHTML = '';
|
||||
body.innerHTML = '<div class="seelsorge-modal-loading"><div class="loading-spinner"></div></div>';
|
||||
modal.style.display = 'flex';
|
||||
|
||||
try {
|
||||
const response = await fetch('content/calendar_day.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: 'calendarDate=' + encodeURIComponent(calendarDate)
|
||||
});
|
||||
|
||||
const html = await response.text();
|
||||
|
||||
if (response.ok) {
|
||||
body.innerHTML = html;
|
||||
|
||||
// Metadaten aus dem eingebetteten JSON lesen
|
||||
const metaEl = body.querySelector('#modal-meta');
|
||||
if (metaEl) {
|
||||
const meta = JSON.parse(metaEl.textContent);
|
||||
title.textContent = meta.title;
|
||||
|
||||
let chips = '<span class="seelsorge-modal-chip">KW ' + meta.kw + '</span>';
|
||||
if (meta.feiertag) {
|
||||
chips += '<span class="seelsorge-modal-chip seelsorge-chip-holiday">' + meta.feiertag + '</span>';
|
||||
}
|
||||
subtitle.innerHTML = chips;
|
||||
metaEl.remove();
|
||||
}
|
||||
} else {
|
||||
// PHP-Fehler direkt im Modal anzeigen
|
||||
title.textContent = 'Fehler ' + response.status;
|
||||
body.innerHTML = '<div style="padding:16px;font-family:monospace;font-size:0.85em;color:#d21400;white-space:pre-wrap;word-break:break-word;background:#fff5f5;border:1px solid #fcc;">'
|
||||
+ (html || 'Keine Antwort vom Server.') + '</div>';
|
||||
}
|
||||
} catch (error) {
|
||||
body.innerHTML = '<div class="seelsorge-modal-empty">Fehler beim Laden der Daten: ' + error.message + '</div>';
|
||||
console.error('Fehler beim Laden der Tagesdetails:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Modal schliessen
|
||||
function closeDayModal() {
|
||||
const modal = document.getElementById('seelsorge-day-modal');
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
|
||||
// Backdrop-Klick schliesst Modal
|
||||
function closeDayModalOnBackdrop(event) {
|
||||
if (event.target === event.currentTarget) {
|
||||
closeDayModal();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Verfuegbarkeit im Modal togglen (Modal bleibt offen)
|
||||
async function toggleAvailabilityModal(date) {
|
||||
const btn = document.getElementById('modal-toggle-btn');
|
||||
if (!btn) return;
|
||||
|
||||
const originalText = btn.textContent;
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Wird gespeichert\u2026';
|
||||
|
||||
try {
|
||||
const response = await fetch("toggle_availability.php", {
|
||||
method: "POST",
|
||||
headers: { "Content-type": "application/x-www-form-urlencoded" },
|
||||
body: "date=" + encodeURIComponent(date)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.ok) {
|
||||
// Modal-Inhalt neu laden um aktuellen Stand zu zeigen
|
||||
await openDayModal(date);
|
||||
|
||||
// Kalender-Tageszelle visuell aktualisieren
|
||||
updateCalendarCell(date, data.nowAvailable, data.availCount);
|
||||
} else {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
console.error("Fehler:", data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
console.error("Fehler beim Aktualisieren der Verfuegbarkeit:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Kalender-Tageszelle visuell aktualisieren ohne Page-Reload
|
||||
function updateCalendarCell(date, nowAvailable, availCount) {
|
||||
var cells = document.querySelectorAll('#calendar_day_item');
|
||||
cells.forEach(function(cell) {
|
||||
var onclick = cell.getAttribute('onclick') || '';
|
||||
if (onclick.indexOf(date) === -1) return;
|
||||
|
||||
// Alle Verfuegbarkeits-Klassen entfernen
|
||||
cell.classList.remove('available_single', 'available_multiple', 'normalday');
|
||||
|
||||
if (availCount >= 2) {
|
||||
cell.classList.add('available_multiple');
|
||||
} else if (availCount === 1) {
|
||||
cell.classList.add('available_single');
|
||||
} else {
|
||||
cell.classList.add('normalday');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Profil eines Diakons aus dem Kalender-Modal oeffnen
|
||||
var _lastCalendarDate = null;
|
||||
|
||||
function openCalendarProfile(userId) {
|
||||
// Datum merken, damit wir beim Schliessen zurueckkehren koennen
|
||||
var metaEl = document.getElementById('modal-meta');
|
||||
var bodyEl = document.getElementById('modal-day-body');
|
||||
if (!_lastCalendarDate && bodyEl) {
|
||||
// Datum aus dem Toggle-Button extrahieren
|
||||
var toggleBtn = bodyEl.querySelector('#modal-toggle-btn');
|
||||
if (toggleBtn) {
|
||||
var onclickAttr = toggleBtn.getAttribute('onclick') || '';
|
||||
var match = onclickAttr.match(/'(\d{4}-\d{2}-\d{2})'/);
|
||||
if (match) _lastCalendarDate = match[1];
|
||||
}
|
||||
}
|
||||
closeDayModal();
|
||||
openCloseProfile(userId, 'profile_calendar', 'profile_calendar_overlay');
|
||||
}
|
||||
|
||||
// Globalen Listener fuer Kalender-Profil-Overlay: bei Schliessen Tagesmodal wieder oeffnen
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// MutationObserver auf das Kalender-Profil-Overlay
|
||||
var calOverlay = document.getElementById('profile_calendar_overlay');
|
||||
if (calOverlay) {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(m) {
|
||||
if (m.attributeName === 'style' && calOverlay.style.display === 'none' && _lastCalendarDate) {
|
||||
var date = _lastCalendarDate;
|
||||
_lastCalendarDate = null;
|
||||
openDayModal(date);
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(calOverlay, { attributes: true, attributeFilter: ['style'] });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Hilfe-Modal oeffnen/schliessen
|
||||
function openCalendarHelp() {
|
||||
var modal = document.getElementById('calendar-help-modal');
|
||||
if (modal) modal.style.display = 'flex';
|
||||
}
|
||||
function closeCalendarHelp() {
|
||||
var modal = document.getElementById('calendar-help-modal');
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
Reference in New Issue
Block a user