Workspace: Aufgaben bearbeiten, Personenverwaltung im Browser
Aufgaben: - Bearbeiten-Dialog (Titel, Beschreibung, Prioritaet, Frist, Zuordnung). Als natives <dialog>: Fokusfang, Esc zum Schliessen und Abdunklung ohne eigenen Code. - Loeschen nur fuer Management, mit Rueckfrage und Protokolleintrag. Das Konzept will, dass Erledigtes stehen bleibt -- Loeschen ist der Ausnahmefall fuer Fehleintraege, nicht der normale Abschluss. Personen (/workspace/personen.html, nur Management): - Anlegen, Code erneuern, sperren/entsperren, Protokollansicht - Der Code wird genau einmal in der Antwort zurueckgegeben, nie gespeichert; beim Schliessen auch aus dem Dokument entfernt - Selbstschutz: niemand kann sich selbst sperren, und das letzte aktive Management laesst sich nicht sperren -- sonst kaeme niemand mehr hinein - Code fuer sich selbst tauschen nur mit ausdruecklicher Bestaetigung, weil es die eigene Sitzung sofort beendet Zwei Fehler, die beim Testen aufgefallen sind: 1. Rollenpruefung fehlte beim Ausliefern der Seiten. Ein Creator bekam personen.html mit HTTP 200 -- die Schnittstellen wiesen ihn zwar ab, das Geruest der Seite war aber sichtbar. GESCHUETZT ist jetzt eine Zuordnung Pfad -> erlaubte Rollen statt einer blossen Liste. 2. Das Protokoll nannte den falschen Verursacher. personAnlegen trug die NEU ANGELEGTE Person als person_id ein, der Eintrag las sich also so, als haette sie sich selbst angelegt. Akteur und Betroffener sind jetzt getrennt: Akteur in person_id, Betroffener im Text. Ueber die Kommandozeile angelegte Personen zeigen korrekt keinen Akteur.
This commit is contained in:
@@ -48,7 +48,15 @@
|
||||
function karte(a) {
|
||||
const k = el('article', 'karte');
|
||||
k.dataset.prio = a.prioritaet;
|
||||
k.append(el('h3', 'karte__titel', a.titel));
|
||||
|
||||
const kopf = el('div', 'karte__kopf');
|
||||
kopf.append(el('h3', 'karte__titel', a.titel));
|
||||
const stift = el('button', 'karte__stift', 'bearbeiten');
|
||||
stift.type = 'button';
|
||||
stift.setAttribute('aria-label', `${a.titel} bearbeiten`);
|
||||
stift.addEventListener('click', () => dialogOeffnen(a));
|
||||
kopf.append(stift);
|
||||
k.append(kopf);
|
||||
if (a.beschreibung) k.append(el('p', 'karte__text', a.beschreibung));
|
||||
|
||||
const zeile = el('div', 'karte__zeile');
|
||||
@@ -178,6 +186,70 @@
|
||||
} catch { /* bereits umgeleitet */ } finally { knopfEl.disabled = false; }
|
||||
});
|
||||
|
||||
/* ---------- Bearbeiten ------------------------------------------------ */
|
||||
|
||||
const dialog = $('bearbeiten-dialog');
|
||||
let bearbeitet = null;
|
||||
|
||||
function dialogOeffnen(a) {
|
||||
bearbeitet = a;
|
||||
$('b-titel').value = a.titel;
|
||||
$('b-text').value = a.beschreibung || '';
|
||||
$('b-prio').value = a.prioritaet;
|
||||
$('b-frist').value = a.frist || '';
|
||||
$('b-fehler').textContent = '';
|
||||
if (ich.rolle === 'admin') {
|
||||
$('b-creator').value = a.creator_id ? String(a.creator_id) : '';
|
||||
$('b-verant').value = a.verantwortlich_id ? String(a.verantwortlich_id) : '';
|
||||
$('b-loeschen').hidden = false;
|
||||
}
|
||||
dialog.showModal();
|
||||
$('b-titel').focus();
|
||||
}
|
||||
|
||||
$('b-abbrechen').addEventListener('click', () => dialog.close());
|
||||
|
||||
$('b-speichern').addEventListener('click', async () => {
|
||||
const daten = {
|
||||
titel: $('b-titel').value,
|
||||
beschreibung: $('b-text').value,
|
||||
prioritaet: $('b-prio').value,
|
||||
frist: $('b-frist').value,
|
||||
};
|
||||
if (ich.rolle === 'admin') {
|
||||
daten.creator_id = $('b-creator').value || null;
|
||||
daten.verantwortlich_id = $('b-verant').value || null;
|
||||
}
|
||||
$('b-speichern').disabled = true;
|
||||
try {
|
||||
const a = await hole(`/workspace/api/aufgaben/${bearbeitet.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(daten),
|
||||
});
|
||||
if (!a.ok) {
|
||||
$('b-fehler').textContent = (await a.json().catch(() => ({}))).fehler || 'Speichern ging nicht.';
|
||||
return;
|
||||
}
|
||||
dialog.close();
|
||||
await laden();
|
||||
} catch { /* umgeleitet */ } finally { $('b-speichern').disabled = false; }
|
||||
});
|
||||
|
||||
$('b-loeschen').addEventListener('click', async () => {
|
||||
if (!confirm(`Aufgabe wirklich loeschen?
|
||||
|
||||
"${bearbeitet.titel}"
|
||||
|
||||
Das laesst sich nicht rueckgaengig machen. Erledigte Aufgaben sollten normalerweise stehen bleiben.`)) return;
|
||||
try {
|
||||
const a = await hole(`/workspace/api/aufgaben/${bearbeitet.id}`, { method: 'DELETE' });
|
||||
if (!a.ok) { $('b-fehler').textContent = 'Loeschen ging nicht.'; return; }
|
||||
dialog.close();
|
||||
await laden();
|
||||
} catch { /* umgeleitet */ }
|
||||
});
|
||||
|
||||
/* ---------- Start ----------------------------------------------------- */
|
||||
|
||||
$('abmelden').addEventListener('click', async () => {
|
||||
@@ -198,10 +270,12 @@
|
||||
if (ich.rolle === 'admin') {
|
||||
$('feld-creator').hidden = false;
|
||||
$('feld-verant').hidden = false;
|
||||
$('b-feld-creator').hidden = false;
|
||||
$('b-feld-verant').hidden = false;
|
||||
try {
|
||||
const { personen } = await (await hole('/workspace/api/personen')).json();
|
||||
for (const p of personen) {
|
||||
for (const ziel of ['f-creator', 'f-verant']) {
|
||||
for (const ziel of ['f-creator', 'f-verant', 'b-creator', 'b-verant']) {
|
||||
const o = el('option', null, `${p.name} (${p.rolle})`);
|
||||
o.value = String(p.id);
|
||||
$(ziel).append(o);
|
||||
|
||||
Reference in New Issue
Block a user