Kleine fehler beseitigt

This commit is contained in:
erik committed 2026-08-14 11:47:19 +02:00
1 parent 57e201b8fc
commit 115f0f5671
15 files changed
+220 -115

No files matched your search

+47 -19
View File
@@ -24,11 +24,23 @@ function delProjectFromList(id){
// editProjectField: ändert ein Feld eines Projekts (z.B. Name oder Gruppe).
// Parameter: `id` (Projekt-ID), `field` (Feldname), `val` (neuer Wert).
// Keine Rückgabe.
// Beim Wechsel der Gruppe wird das Projekt ans Ende der Zielgruppe angehängt
// (neue `order` = höchste Order der Zielgruppe + 1), damit es nicht anhand
// seiner alten `order` in der Liste landet. Keine Rückgabe.
function editProjectField(id,field,val){
if(guardWeekLocked()) return;
const p = currentWeek().projects.find(x=>x.id===id);
if(p){ p[field]=val; save(); renderProjects(); renderBoard(); }
const w = currentWeek();
const p = w.projects.find(x=>x.id===id);
if(!p) return;
if(field === 'group' && val && val !== p.group){
p.group = val;
const targetProjects = w.projects.filter(x => x.id !== id && x.group === val);
const maxOrder = targetProjects.reduce((m,x)=>Math.max(m, x.order || 0), -1);
p.order = maxOrder + 1;
} else {
p[field] = val;
}
save(); renderProjects(); renderBoard();
}
// editProjectActiveLP: setzt bzw. hebt die amtierende Leistungsphase eines
@@ -59,9 +71,9 @@ function renderProjects(){
sortGroups(Object.keys(groups)).forEach(g=>{
html += `<div class="section-title">${esc(g)}</div>`;
html += `<div class="projects-sortable" data-group="${g}">`;
html += `<div class="projects-sortable" data-group="${g}" ondragover="handleDragOver(event)" ondrop="handleDrop(event)">`;
groups[g].forEach(p=>{
html += `<div class="person-list-item" draggable="true" data-project-id="${p.id}" ondragstart="handleDragStart(event)" ondragover="handleDragOver(event)" ondrop="handleDrop(event)" ondragend="handleDragEnd(event)">
html += `<div class="person-list-item" draggable="true" data-project-id="${p.id}" ondragstart="handleDragStart(event)" ondragend="handleDragEnd(event)">
<span class="drag-handle" style="cursor:grab;color:#999;margin-right:8px">⋮⋮</span>
<input type="text" value="${esc(p.nr)}" onchange="editProjectField('${p.id}','nr',this.value)" style="width:100px" placeholder="Proj-Nr">
<input type="text" value="${esc(p.name)}" onchange="editProjectField('${p.id}','name',this.value)" style="width:200px" placeholder="Bezeichnung">
@@ -106,18 +118,31 @@ function handleDragOver(event){
event.dataTransfer.dropEffect = 'move';
}
// handleDrop: legt die gezogene Projekt-Zeile an der Position ab, die
// `getDragAfterElement` relativ zur Mausposition ermittelt, und speichert
// die neue Reihenfolge über `reorderProjects()`.
// handleDrop: legt die gezogene Projekt-Zeile ab. Der Handler hängt am
// Gruppen-Container (`.projects-sortable`), sodass das Ablegen über der
// gesamten Gruppe inklusive leerer Flächen möglich ist. Beim Wechsel zwischen
// Gruppen (z. B. "Kleine Projekte" → "Aktive Projekte") wird das Projekt ans
// Ende der Zielgruppe angehängt; innerhalb derselben Gruppe wird die Position
// per `getDragAfterElement` relativ zur Mausposition bestimmt. Danach speichert
// `reorderProjects()` die neue Reihenfolge.
function handleDrop(event){
event.preventDefault();
if(!draggedProject || draggedProject === event.currentTarget) return;
const sortable = event.currentTarget.parentElement;
const afterElement = getDragAfterElement(sortable, event.clientY);
if(afterElement == null){
sortable.appendChild(draggedProject);
if(!draggedProject) return;
const sortable = event.currentTarget;
const sourceSortable = draggedProject.parentElement;
const isSameGroup = sourceSortable &&
sourceSortable.dataset && sortable.dataset &&
sourceSortable.dataset.group === sortable.dataset.group;
if(isSameGroup){
const afterElement = getDragAfterElement(sortable, event.clientY);
if(afterElement == null){
sortable.appendChild(draggedProject);
} else {
sortable.insertBefore(draggedProject, afterElement);
}
} else {
sortable.insertBefore(draggedProject, afterElement);
// Gruppenwechsel: ans Ende der Zielgruppe anhängen
sortable.appendChild(draggedProject);
}
reorderProjects();
}
@@ -131,11 +156,14 @@ function handleDragEnd(event){
// getDragAfterElement: ermittelt das Element in `container`, vor dem die
// gezogene Zeile bei Mausposition `y` abgelegt werden soll (Suche nach dem
// Element mit der kleinsten negativen Distanz zur Mitte). Rückgabe:
// Ziel-Element oder undefined (→ ans Ende anfügen). Wird auch von
// `js/people/people.js` für die Personen-Sortierung verwendet.
function getDragAfterElement(container, y){
const draggableElements = [...container.querySelectorAll('.person-list-item:not([style*="opacity"])')];
// Element mit der kleinsten negativen Distanz zur Mitte). Parameter:
// `selector` = CSS-Selektor der sortierbaren Elemente (standardmäßig die
// Projekt-Zeilen, steht aber auch der Personen-Liste für `.person-card` zur
// Verfügung). Rückgabe: Ziel-Element oder undefined (→ ans Ende anfügen).
// Wird auch von `js/people/people.js` für die Personen-Sortierung verwendet.
function getDragAfterElement(container, y, selector){
const sel = selector || '.person-list-item:not([style*="opacity"])';
const draggableElements = [...container.querySelectorAll(sel)];
return draggableElements.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;