Workspace: Creator-Profile (Onboarding aus dem Konzept)
/workspace/profil.html -- Stammdaten, Ziele und 90-Tage-Plan, genau nach Seite 5 des Konzepts. Management waehlt oben den Creator aus, ein Creator sieht nur sein eigenes Profil. Sicherheitskern ist das Feld admin_notiz. Das Konzept fordert "private Admin-Notizen separat". Die Notiz wird deshalb nicht im Browser ausgeblendet, sondern gar nicht erst gesendet: Die Spaltenliste der Abfrage haengt an der Rolle (FELDER_OFFEN / FELDER_ADMIN). Dasselbe gilt fuer Plan-Start und Review-Termin. Geprueft: - In der kompletten Rohantwort an den Creator kommt der Inhalt der internen Notiz 0-mal vor - Creator auf fremdes Profil: 404 (lesend wie schreibend) - Scout auf ein Profil: 404, profil.html leitet ihn weg - Creator setzt admin_notiz selbst: wird stillschweigend ignoriert, der Inhalt bleibt unveraendert - Profil einer Nicht-Creator-Person: 404 Dabei ist ein aelterer Fehler aufgefallen: /api/ich lieferte nur Name und Rolle, nicht die eigene Nummer. Dadurch rief die Profilseite eines Creators /api/profil/undefined auf und blieb leer. Derselbe Fehler machte in der Personenverwaltung den Selbstvergleich unwirksam -- beim eigenen Eintrag erschien ein "Sperren"-Knopf, den der Server dann ablehnte. /api/ich liefert jetzt zusaetzlich die id. Im Protokoll landen nur die Feldnamen, nie die Inhalte: Im Profil stehen persoenliche Angaben, die nicht zusaetzlich im Audit-Log auftauchen sollen.
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
/* ===================================================================
|
||||
Creator-Profil.
|
||||
|
||||
Welche Felder überhaupt ankommen, entscheidet der Server anhand der
|
||||
Rolle -- `admin_notiz` fehlt in der Antwort an einen Creator komplett.
|
||||
Diese Datei blendet deshalb nur aus, was ohnehin nicht da ist.
|
||||
=================================================================== */
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
const OFFEN = ['handles', 'nische', 'live_zeiten', 'technik',
|
||||
'ziel_live', 'ziel_content', 'ziel_community', 'ziel_technik',
|
||||
'plan_prio1', 'plan_prio2', 'plan_prio3'];
|
||||
const NUR_ADMIN = ['plan_start', 'naechster_review', 'admin_notiz'];
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
let ich = null;
|
||||
let aktuell = null;
|
||||
let darfAlles = false;
|
||||
|
||||
const melde = (t) => { $('fehler').textContent = t || ''; };
|
||||
|
||||
async function hole(pfad, optionen = {}) {
|
||||
const a = await fetch(pfad, { credentials: 'same-origin', ...optionen });
|
||||
if (a.status === 401) { location.assign('/workspace/'); throw new Error('abgemeldet'); }
|
||||
return a;
|
||||
}
|
||||
|
||||
function fuelle(profil) {
|
||||
for (const f of [...OFFEN, ...NUR_ADMIN]) {
|
||||
const feld = $(f);
|
||||
if (!feld) continue;
|
||||
/* undefined heißt: Der Server hat das Feld nicht geschickt (fehlende
|
||||
Berechtigung). Dann bleibt es leer und wird auch nicht gesendet. */
|
||||
feld.value = profil[f] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
function datumHuebsch(iso) {
|
||||
return iso.slice(0, 10).split('-').reverse().join('.');
|
||||
}
|
||||
|
||||
async function profilLaden(id) {
|
||||
melde('');
|
||||
try {
|
||||
const a = await hole('/workspace/api/profil/' + id);
|
||||
if (!a.ok) { melde('Profil konnte nicht geladen werden.'); return; }
|
||||
const daten = await a.json();
|
||||
aktuell = daten.person.id;
|
||||
darfAlles = daten.darf_alles;
|
||||
|
||||
$('titel').textContent = ich.rolle === 'admin'
|
||||
? 'Profil: ' + daten.person.name
|
||||
: 'Mein Profil';
|
||||
$('unterzeile').textContent = daten.profil.geaendert
|
||||
? 'Zuletzt geändert am ' + datumHuebsch(daten.profil.geaendert)
|
||||
: 'Noch nichts eingetragen.';
|
||||
|
||||
$('gruppe-intern').hidden = !darfAlles;
|
||||
$('termine').hidden = !darfAlles;
|
||||
fuelle(daten.profil);
|
||||
$('formular').hidden = false;
|
||||
} catch { /* umgeleitet */ }
|
||||
}
|
||||
|
||||
$('formular').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
melde('');
|
||||
const knopf = $('speichern');
|
||||
const daten = {};
|
||||
for (const f of darfAlles ? [...OFFEN, ...NUR_ADMIN] : OFFEN) {
|
||||
const feld = $(f);
|
||||
if (feld) daten[f] = feld.value;
|
||||
}
|
||||
knopf.disabled = true;
|
||||
$('stand').textContent = 'Speichere …';
|
||||
try {
|
||||
const a = await hole('/workspace/api/profil/' + aktuell, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(daten),
|
||||
});
|
||||
if (!a.ok) {
|
||||
melde((await a.json().catch(() => ({}))).fehler || 'Speichern ging nicht.');
|
||||
$('stand').textContent = '';
|
||||
return;
|
||||
}
|
||||
$('stand').textContent = 'Gespeichert ✓';
|
||||
setTimeout(() => { $('stand').textContent = ''; }, 2600);
|
||||
} catch { /* umgeleitet */ } finally { knopf.disabled = false; }
|
||||
});
|
||||
|
||||
$('abmelden').addEventListener('click', async () => {
|
||||
try { await fetch('/workspace/api/abmelden', { method: 'POST', credentials: 'same-origin' }); }
|
||||
catch { /* egal */ }
|
||||
location.assign('/workspace/');
|
||||
});
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const a = await hole('/workspace/api/ich');
|
||||
if (!a.ok) { location.assign('/workspace/'); return; }
|
||||
ich = await a.json();
|
||||
} catch { return; }
|
||||
if (ich.rolle === 'scout') { location.assign('/workspace/start.html'); return; }
|
||||
$('wer').textContent = ich.name + ' · ' + ich.rolle;
|
||||
|
||||
let liste;
|
||||
try { liste = await (await hole('/workspace/api/profil')).json(); } catch { return; }
|
||||
|
||||
if (ich.rolle === 'admin') {
|
||||
if (!liste.creator.length) {
|
||||
$('unterzeile').textContent =
|
||||
'Es gibt noch keinen Creator. Lege zuerst unter Personen & Zugänge einen an.';
|
||||
return;
|
||||
}
|
||||
$('auswahl-block').hidden = false;
|
||||
for (const c of liste.creator) {
|
||||
const o = document.createElement('option');
|
||||
o.value = String(c.id);
|
||||
o.textContent = c.name + (c.aktiv ? '' : ' (gesperrt)');
|
||||
$('auswahl').append(o);
|
||||
}
|
||||
$('auswahl').addEventListener('change', () => profilLaden(Number($('auswahl').value)));
|
||||
await profilLaden(liste.creator[0].id);
|
||||
} else {
|
||||
await profilLaden(ich.id);
|
||||
}
|
||||
})();
|
||||
})();
|
||||
Reference in New Issue
Block a user