Aus der Probe wird ein Zugang - und die Seite sagt nicht mehr "Agentur"
Die drei offenen Punkte aus Abschnitt 9 des Plans, plus Filipes zweite
Ansage: "auf dieser seite soll nichts stehen von agentur, diese seite
hier ist nur fuer mich meine modis und meine community."
1. PROBE -> ZUGANG (ein Knopf statt eines Satzes)
Auf der Stufe "Probe" stand bisher "Zugang in Personen & Zugaenge
anlegen, Rolle Modi" - und wer das vergass, hatte eine Karte auf "Im
Team" und keinen Menschen darin. Jetzt haengt das Anlegen am Schritt
selbst.
Ueber DENSELBEN Weg wie in "Personen & Zugaenge", nicht ueber einen
zweiten: POST /workspace/api/verwaltung/personen, mit ihrer
Rechtepruefung, ihrem Protokolleintrag und ihrem genau einmal
angezeigten Code. Der Talente-Server legt selbst keinen einzigen Zugang
an, und die Pruefung zaehlt nach, dass es bei einem Weg bleibt.
Der Code steht im gleichen Kasten wie dort - die Gestaltung ist aus
personen.css nach start.css umgezogen, weil talente.html sie sonst nicht
laedt. Ein Geheimnis sieht im ganzen Haus gleich aus. Er steht
ausserhalb der Liste, sonst waere er in dem Moment weg, in dem er
entsteht: wenn die Karte auf "Im Team" springt.
Die rechte Hand bekommt an dieser Stelle KEINEN Knopf, sondern einen
Satz. Ein Knopf, der ihr jedes Mal "darfst du nicht" antwortet, waere
schlechter als gar keiner - er verspricht etwas.
2. DIE EIGENE KARTE (Abschnitt "Deine Karte")
Wer beschrieben wird, darf es lesen - aber erst, wenn ALLE gesetzt
haben (sonst waere die erste Einschaetzung eine Vorgabe fuer die
zweite), und ohne Namen und ohne Anlasstext. Gemessen in beide
Richtungen: vorher nicht sichtbar, nachher sichtbar.
3. DER VORLAGENTEXT
Gebaut aus den angeklickten Merkmalen, in einem Feld zum Aendern, nicht
zum Abschicken. Ohne Merkmale steht auch keines drin.
4. "GILT FUER" SAGT DER SERVER
In bereich.js stand woertlich "Agentur" - richtig auf der
Agenturadresse, falsch auf jeder anderen. Jetzt liefert der Server
`gehoert` ("Der Treff" / "Team Dogi" / "Agentur"); gemessen mit einem
einzigen Menschen auf zwei Adressen.
PRUEFUNGEN: treff 58 -> 66, nachwuchs 69 -> 109, neue-seiten 70 -> 93.
Die Katalogseiten werden jetzt auch mit den Augen der rechten Hand
angesehen - ohne das waere "Deine Karte" nie auf einem Bildschirm
gewesen. Und pruef-neue-seiten wartet nicht mehr 900 ms, sondern bis
sich der Text nicht mehr aendert: Die Karte stand da und wurde
trotzdem als fehlend gemeldet, weil zu frueh gelesen wurde.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -363,3 +363,67 @@
|
||||
.t-karte__warn { margin-left: 0; }
|
||||
.e-punkt__text, .e-block__satz { font-size: .88rem; }
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
DER VORLAGENTEXT UND DIE EIGENE KARTE (11.09.2026)
|
||||
===================================================================== */
|
||||
|
||||
.t-text {
|
||||
margin: 14px 0 0; padding: 15px 17px;
|
||||
background: rgba(0, 0, 0, .3);
|
||||
border: 1px solid var(--rand-hell);
|
||||
}
|
||||
.t-text__titel { margin: 0 0 5px; font-size: .95rem; font-weight: 640; color: var(--text); }
|
||||
.t-text__satz {
|
||||
margin: 0 0 11px; max-width: 62ch;
|
||||
font-size: .82rem; line-height: 1.6; color: var(--text-leise);
|
||||
}
|
||||
.t-text__feld {
|
||||
display: block; width: 100%;
|
||||
font: inherit; font-size: .86rem; line-height: 1.65;
|
||||
padding: 11px 13px; resize: vertical;
|
||||
color: var(--text);
|
||||
background: rgba(0, 0, 0, .35);
|
||||
border: 1px solid var(--rand);
|
||||
}
|
||||
.t-text__knoepfe { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 11px; }
|
||||
|
||||
/* Zwei, die seit dem Bau der Seite ohne eigene Regel dastanden: der
|
||||
Knopf am naechsten Schritt und die Beschriftung eines Merkmals. Sie
|
||||
sahen richtig aus, weil .schritt und .t-merkmal sie getragen haben --
|
||||
aber wer eines davon umbaut, merkt es hier nicht. */
|
||||
.t-schritt__knopf { margin-top: 2px; }
|
||||
.t-schritt__text { margin-top: 2px; }
|
||||
.t-merkmal__titel { text-align: left; line-height: 1.35; }
|
||||
|
||||
/* DIE EIGENE KARTE HAT KEINE KNOEPFE. Hier wird nichts gesetzt, hier
|
||||
wird gelesen -- deshalb ein anderer Grund als auf der Karte, auf der
|
||||
man klickt, und kein einziges anklickbares Feld darin. */
|
||||
.e-meine {
|
||||
margin: 30px 0 0; padding: 20px 22px;
|
||||
border: 1px solid var(--rand);
|
||||
background: color-mix(in srgb, var(--tinte) 94%, #ffffff 6%);
|
||||
}
|
||||
.e-meine__satz {
|
||||
margin: 0 0 16px; max-width: 64ch;
|
||||
font-size: .88rem; line-height: 1.65; color: var(--text-leise);
|
||||
}
|
||||
.e-punkt--meine { background: rgba(0, 0, 0, .2); }
|
||||
.e-meine__antworten { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
|
||||
.e-meine__antwort {
|
||||
font-size: .8rem; font-weight: 600; padding: 4px 11px; border-radius: 999px;
|
||||
color: var(--text-leise);
|
||||
border: 1px solid var(--rand-hell);
|
||||
}
|
||||
.e-meine__antwort[data-stufe="laeuft"] {
|
||||
color: var(--text); border-color: color-mix(in srgb, #668e6e 55%, transparent);
|
||||
}
|
||||
.e-meine__antwort[data-stufe="waechst"] {
|
||||
color: var(--text); border-color: color-mix(in srgb, #8ec9ff 50%, transparent);
|
||||
}
|
||||
.e-meine__antwort[data-stufe="hakt"] {
|
||||
color: var(--text); border-color: color-mix(in srgb, #cc9451 55%, transparent);
|
||||
}
|
||||
/* „Darüber seid ihr euch nicht einig“ ist keine Warnung, sondern eine
|
||||
Einladung zu fragen – deshalb leise und ohne Farbe. */
|
||||
.e-meine__uneinig { font-size: .78rem; color: var(--text-still); font-style: italic; }
|
||||
|
||||
@@ -41,27 +41,13 @@
|
||||
|
||||
.person__knoepfe { display: flex; gap: 7px; flex-wrap: wrap; justify-content: flex-end; }
|
||||
|
||||
/* ---------- Code-Anzeige ---------------------------------------------- */
|
||||
/* ---------- Code-Anzeige ----------------------------------------------
|
||||
|
||||
.code-kasten {
|
||||
margin: 0 0 26px; padding: 20px 22px;
|
||||
background: linear-gradient(100deg, rgba(63, 189, 245, .12), rgba(138, 118, 255, .09));
|
||||
border: 1px solid rgba(63, 189, 245, .5);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
.code-kasten__schild {
|
||||
margin: 0 0 8px; font-size: .78rem; font-weight: 600;
|
||||
letter-spacing: .06em; text-transform: uppercase; color: var(--text-leise);
|
||||
}
|
||||
.code-kasten__code {
|
||||
margin: 0 0 12px;
|
||||
font-family: "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
|
||||
font-size: clamp(1.3rem, 3.4vw, 1.9rem); font-weight: 700;
|
||||
letter-spacing: .12em; color: #eaf4fd;
|
||||
user-select: all; /* ein Klick markiert den ganzen Code */
|
||||
word-break: break-all;
|
||||
}
|
||||
.code-kasten__hinweis { margin: 0 0 14px; font-size: .85rem; color: var(--text-leise); }
|
||||
STEHT SEIT DEM 11.09.2026 IN start.css. Nicht aufgeraeumt, sondern
|
||||
umgezogen: Seit dem Talente-Trichter entsteht ein Zugang an zwei
|
||||
Stellen, und talente.html laedt diese Datei nicht. Der Kasten waere
|
||||
dort unsichtbar gewesen -- ein Code in weisser Grundschrift, ohne
|
||||
Rahmen, mitten im Text. Gesucht unter ".code-kasten" in start.css. */
|
||||
|
||||
/* ---------- Protokoll --------------------------------------------------- */
|
||||
|
||||
|
||||
@@ -7845,3 +7845,36 @@ body.start .k-leiste .feldschild::after {
|
||||
fill: none; stroke: currentColor; stroke-width: 1.8;
|
||||
stroke-linecap: round; stroke-linejoin: round;
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
DIE CODE-ANZEIGE (umgezogen aus personen.css, 11.09.2026)
|
||||
|
||||
Ein Zugangscode wird im ganzen Haus nur an zwei Stellen sichtbar:
|
||||
in "Personen & Zugaenge" und am Ende des Talente-Trichters. Beide
|
||||
zeigen ihn gleich -- gleiche Kante, gleiche Schrift, gleicher Satz
|
||||
darunter. Zwei Gestaltungen fuer dasselbe Geheimnis waeren zwei
|
||||
Gelegenheiten, eine davon zu vergessen.
|
||||
|
||||
Er steht hier und nicht in module.css: module.css beschreibt die
|
||||
Form ALLER Karten, das hier ist ein einzelner Baustein.
|
||||
===================================================================== */
|
||||
|
||||
.code-kasten {
|
||||
margin: 0 0 26px; padding: 20px 22px;
|
||||
background: linear-gradient(100deg, rgba(63, 189, 245, .12), rgba(138, 118, 255, .09));
|
||||
border: 1px solid rgba(63, 189, 245, .5);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
.code-kasten__schild {
|
||||
margin: 0 0 8px; font-size: .78rem; font-weight: 600;
|
||||
letter-spacing: .06em; text-transform: uppercase; color: var(--text-leise);
|
||||
}
|
||||
.code-kasten__code {
|
||||
margin: 0 0 12px;
|
||||
font-family: "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
|
||||
font-size: clamp(1.3rem, 3.4vw, 1.9rem); font-weight: 700;
|
||||
letter-spacing: .12em; color: #eaf4fd;
|
||||
user-select: all; /* ein Klick markiert den ganzen Code */
|
||||
word-break: break-all;
|
||||
}
|
||||
.code-kasten__hinweis { margin: 0 0 14px; font-size: .85rem; color: var(--text-leise); }
|
||||
|
||||
@@ -861,14 +861,28 @@
|
||||
NICHT aufgesetzt -- sie erlaubt getippte Namen, und genau das
|
||||
soll es hier nicht geben. */
|
||||
if (einstellung.ohneCreatorBezug) {
|
||||
/* DAS WORT KOMMT VOM SERVER (11.09.2026).
|
||||
|
||||
Hier stand fest "Agentur" -- richtig auf der Agenturadresse,
|
||||
falsch auf jeder anderen. Filipe, mit Bildschirmfoto: "auf
|
||||
dieser seite soll nichts stehen von agentur, diese seite hier
|
||||
ist nur für mich meine modis und meine community."
|
||||
|
||||
Der Server weiss, welches Brett es ist und in welchem Haus
|
||||
die Person steht; er schickt das Wort mit (daten.gehoert).
|
||||
Faellt die Angabe aus, bleibt das Feld LEER statt falsch --
|
||||
ein fehlendes Wort sieht man, ein falsches nicht. */
|
||||
const gehoert = daten?.gehoert || '';
|
||||
$('schild-creator').textContent = 'Gilt für';
|
||||
$('f-creator').textContent = '';
|
||||
const o = document.createElement('option');
|
||||
o.value = ''; o.textContent = 'Agentur';
|
||||
o.value = ''; o.textContent = gehoert || '—';
|
||||
$('f-creator').append(o);
|
||||
const hinweis = $('hinweis-creator');
|
||||
hinweis.textContent = 'Agentur-Einträge gehören allen – jeder im Workspace sieht sie.';
|
||||
hinweis.hidden = false;
|
||||
hinweis.textContent = gehoert
|
||||
? `Gehört allen hier – wer ${gehoert} sieht, sieht auch diesen Eintrag.`
|
||||
: '';
|
||||
hinweis.hidden = !gehoert;
|
||||
} else {
|
||||
try {
|
||||
const { personen } = await (await hole('/workspace/api/personen')).json();
|
||||
|
||||
@@ -244,6 +244,72 @@
|
||||
return z;
|
||||
}
|
||||
|
||||
/* ---- Deine eigene Karte -----------------------------------------------
|
||||
|
||||
WAS HIER STEHT UND WAS NICHT: die Antworten, nicht die Namen, und
|
||||
nicht der Anlass. „2 × Läuft" oder „1 × Läuft, 1 × Wächst gerade".
|
||||
|
||||
Der Anlass ist für ein Gespräch aufgeschrieben, nicht zum Lesen
|
||||
ohne den Menschen dazu — deshalb steht hier stattdessen der Satz,
|
||||
dass man danach fragen soll. Ein Satz aus einer Notiz, aus dem
|
||||
Zusammenhang gerissen, richtet mehr an, als er erklärt. */
|
||||
async function meineKarte() {
|
||||
let a;
|
||||
try { a = await hole('/workspace/api/entwicklung/meine-karte'); } catch { return; }
|
||||
if (!a.ok) return;
|
||||
const r = await a.json();
|
||||
if (!r.hat_karte) return; // DogFather hat keine
|
||||
|
||||
$('karte-block').hidden = false;
|
||||
const satz = $('karte-satz');
|
||||
const ziel = $('meine-karte');
|
||||
ziel.textContent = '';
|
||||
ziel.setAttribute('aria-busy', 'false');
|
||||
|
||||
if (!r.beurteiler) {
|
||||
satz.textContent = 'Es gibt gerade niemanden, der sie führt. Sobald jemand '
|
||||
+ 'da ist, steht hier etwas.';
|
||||
return;
|
||||
}
|
||||
if (!r.fertig) {
|
||||
satz.textContent = `Noch nichts fertig. Eine Beobachtung erscheint hier erst, `
|
||||
+ `wenn alle ${r.beurteiler} sie gesetzt haben – eine halbe Karte ist `
|
||||
+ `schlimmer als keine.`;
|
||||
return;
|
||||
}
|
||||
|
||||
satz.textContent = `${r.fertig} von ${r.gesamt} Beobachtungen sind durch. `
|
||||
+ 'Du siehst die Antworten, nicht wer was gesetzt hat – und nicht, was '
|
||||
+ 'danebengeschrieben steht. Das gehört ins Gespräch: frag danach.';
|
||||
|
||||
for (const b of r.bloecke) {
|
||||
const fertige = b.punkte.filter((pt) => !pt.offen);
|
||||
if (!fertige.length) continue;
|
||||
const abschnitt = el('section', 'e-block');
|
||||
abschnitt.append(el('h3', 'e-block__titel', b.name));
|
||||
for (const pt of fertige) {
|
||||
const zeile = el('article', 'e-punkt e-punkt--meine');
|
||||
if (pt.einig) zeile.dataset.stufe = pt.antworten[0].stufe;
|
||||
zeile.append(el('h4', 'e-punkt__titel', pt.titel));
|
||||
const antw = el('div', 'e-meine__antworten');
|
||||
for (const x of pt.antworten) {
|
||||
const chip = el('span', 'e-meine__antwort', `${x.anzahl} × ${x.name}`);
|
||||
chip.dataset.stufe = x.stufe;
|
||||
antw.append(chip);
|
||||
}
|
||||
if (!pt.einig) {
|
||||
const hin = el('span', 'e-meine__uneinig', 'darüber seid ihr euch nicht einig');
|
||||
hin.title = 'Zwei Leute haben dasselbe verschieden gesehen. Das ist normal – '
|
||||
+ 'und ein guter Anlass, danach zu fragen.';
|
||||
antw.append(hin);
|
||||
}
|
||||
zeile.append(antw);
|
||||
abschnitt.append(zeile);
|
||||
}
|
||||
ziel.append(abschnitt);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Die eigenen sechs Fragen ---------------------------------------- */
|
||||
async function meins() {
|
||||
const a = await hole('/workspace/api/entwicklung/mich');
|
||||
@@ -305,6 +371,7 @@
|
||||
'Sechs Fragen über dich. Niemand aus dem Team sieht deine Antworten.';
|
||||
}
|
||||
|
||||
await meineKarte();
|
||||
await meins();
|
||||
} catch { /* umgeleitet */ }
|
||||
})();
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
}
|
||||
|
||||
let lage = null;
|
||||
let darfAnlegen = false; // darf ich hier einen Modi-Zugang anlegen?
|
||||
const offen = new Set(); // welche Karten aufgeklappt sind
|
||||
|
||||
/* ---- Der Trichter oben ---------------------------------------------- */
|
||||
@@ -86,23 +87,64 @@
|
||||
ist, und nicht erst eine Entscheidung treffen müssen. */
|
||||
const schritt = el('div', 't-schritt');
|
||||
schritt.append(el('p', 't-schritt__satz', k.schritt));
|
||||
if (k.knopf && k.naechste) {
|
||||
const b = el('button', 'schritt t-schritt__knopf', k.knopf);
|
||||
/* DER LETZTE SCHRITT IST KEIN SCHRITT, SONDERN EINE ENTSCHEIDUNG.
|
||||
Aus einem Namen wird ein Mensch mit einem Zugang. Deshalb haengt
|
||||
genau daran das Anlegen selbst -- und nicht ein Satz, den man
|
||||
danach von Hand nachbaut. Bis heute stand hier "Zugang in
|
||||
Personen & Zugaenge anlegen, Rolle Modi", und wer das vergass,
|
||||
hatte eine Karte auf "Im Team" und keinen Menschen darin. */
|
||||
const zugangNoetig = k.naechste === 'imteam';
|
||||
if (k.knopf && k.naechste && (!zugangNoetig || darfAnlegen)) {
|
||||
const b = el('button', 'schritt t-schritt__knopf',
|
||||
zugangNoetig ? 'Ins Team holen · Zugang anlegen' : k.knopf);
|
||||
b.type = 'button';
|
||||
b.addEventListener('click', async () => {
|
||||
b.disabled = true;
|
||||
let zugang = null;
|
||||
if (zugangNoetig) {
|
||||
zugang = await zugangAnlegen(k);
|
||||
if (!zugang) { b.disabled = false; return; }
|
||||
}
|
||||
const r = await hole(`/workspace/api/talente/${k.id}/stufe`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ stufe: k.naechste }),
|
||||
});
|
||||
b.disabled = false;
|
||||
if (!r.ok) { melde('Ging nicht.'); return; }
|
||||
if (!r.ok) {
|
||||
/* ZWEI DINGE SIND PASSIERT, EINES DAVON HAT GEKLAPPT. Ein
|
||||
blosses "ging nicht" waere hier die gefaehrlichste
|
||||
Auskunft von allen -- der Zugang steht ja, und niemand
|
||||
wuesste es. */
|
||||
melde(zugang
|
||||
? `Der Zugang für ${zugang.name} steht – der Code steht oben. Nur die Karte `
|
||||
+ 'blieb auf „Probe“. Bitte den Schritt gleich noch einmal setzen.'
|
||||
: 'Ging nicht.');
|
||||
return;
|
||||
}
|
||||
offen.add(k.id);
|
||||
await laden();
|
||||
});
|
||||
schritt.append(b);
|
||||
} else if (zugangNoetig && k.knopf) {
|
||||
/* KEIN KNOPF INS LEERE. Die rechte Hand sieht den Trichter
|
||||
vollstaendig, aber Zugaenge vergibt nur DogFather. Ein Knopf,
|
||||
der ihr jedes Mal "darfst du nicht" antwortet, waere schlechter
|
||||
als gar keiner -- er verspricht etwas. */
|
||||
schritt.append(el('p', 't-schritt__liegt',
|
||||
'Den Zugang legt DogFather an – sag ihm Bescheid. Die Karte bleibt so '
|
||||
+ 'lange auf „Probe“.'));
|
||||
}
|
||||
/* DER VORLAGENTEXT -- genau auf der Stufe, auf der er gebraucht
|
||||
wird. Eine Schaltfläche „Text anzeigen" auf jeder Stufe wäre auf
|
||||
vier von fünf davon eine Ablenkung. */
|
||||
if (k.stufe === 'beobachtet' && k.ansprechtext) {
|
||||
const b = el('button', 'schritt t-schritt__text', 'Vorlagentext');
|
||||
b.type = 'button';
|
||||
b.addEventListener('click', () => textZeigen(k));
|
||||
schritt.append(b);
|
||||
}
|
||||
|
||||
if (k.liegt) {
|
||||
schritt.append(el('p', 't-schritt__liegt',
|
||||
'Das liegt länger, als es sollte. Entweder weiter – oder bewusst beenden.'));
|
||||
@@ -150,6 +192,139 @@
|
||||
return a;
|
||||
}
|
||||
|
||||
/* ---- Aus der Probe wird ein Zugang ---------------------------------
|
||||
|
||||
DERSELBE WEG WIE IN "PERSONEN & ZUGAENGE", nicht ein zweiter.
|
||||
/workspace/api/verwaltung/personen ist die einzige Stelle im ganzen
|
||||
Haus, an der ein Zugang entsteht -- mit ihrer Rechtepruefung, ihrer
|
||||
Rollenpruefung, ihrem Protokolleintrag und ihrem genau einmal
|
||||
angezeigten Code. Ein eigener Weg von hier waere eine zweite Tuer
|
||||
zu genau dem, was am wenigsten zwei Tueren haben darf.
|
||||
|
||||
NICHT ueber hole(): Diese Adresse antwortet Nicht-DogFather mit
|
||||
404, und hole() versteht ein 404 als "Seite gibt es nicht" und
|
||||
schickt zur Startseite. Ein Rechtefehler wuerde die rechte Hand
|
||||
also aus dem Trichter werfen. Hier wird deshalb selbst gelesen.
|
||||
|
||||
@returns {object|null} die angelegte Person, oder null bei Abbruch. */
|
||||
async function zugangAnlegen(k) {
|
||||
if (!darfAnlegen) { melde('Zugänge legt DogFather an.'); return null; }
|
||||
|
||||
const vorschlag = String(k.titel || '').split(/[\s,(–-]+/)[0] || '';
|
||||
const name = prompt(
|
||||
'Wie soll die Person im Workspace heißen?\n\n'
|
||||
+ 'Das ist der Name, den euer Team sieht. Gleich danach bekommst du '
|
||||
+ 'einmalig ihren Zugangscode – danach nie wieder.',
|
||||
vorschlag);
|
||||
if (name === null) return null; // abgebrochen
|
||||
if (String(name).trim().length < 2) { melde('Der Name ist zu kurz.'); return null; }
|
||||
|
||||
let a;
|
||||
try {
|
||||
a = await fetch('/workspace/api/verwaltung/personen', {
|
||||
credentials: 'same-origin',
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name: String(name).trim(), rolle: 'modi' }),
|
||||
});
|
||||
} catch { melde('Keine Verbindung – der Zugang wurde nicht angelegt.'); return null; }
|
||||
|
||||
if (a.status === 404 || a.status === 403) {
|
||||
melde('Zugänge legt DogFather an – sag ihm Bescheid.');
|
||||
return null;
|
||||
}
|
||||
if (!a.ok) {
|
||||
const grund = (await a.json().catch(() => ({}))).fehler;
|
||||
melde(grund || 'Der Zugang ließ sich nicht anlegen.');
|
||||
return null;
|
||||
}
|
||||
const neu = await a.json();
|
||||
codeZeigen(neu);
|
||||
return neu;
|
||||
}
|
||||
|
||||
/* Der Code steht in einem Kasten, den man SCHLIESSEN muss -- nicht in
|
||||
einer Meldung, die von selbst verschwindet. Er ist das Einzige auf
|
||||
dieser Seite, das es nur ein einziges Mal gibt. */
|
||||
function codeZeigen(neu) {
|
||||
$('code-name').textContent = `${neu.name} · Modi`;
|
||||
$('code-wert').textContent = neu.code;
|
||||
$('code-kasten').hidden = false;
|
||||
$('code-kasten').scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
$('code-kopieren').focus();
|
||||
}
|
||||
|
||||
$('code-kopieren')?.addEventListener('click', async () => {
|
||||
const code = $('code-wert').textContent;
|
||||
try { await navigator.clipboard.writeText(code); melde('Code kopiert.'); }
|
||||
catch {
|
||||
/* Ohne Zwischenablage-Recht: markieren, dann geht Strg+C. Der
|
||||
Code steht ja da -- "ging nicht" waere hier unbrauchbar. */
|
||||
getSelection()?.removeAllRanges();
|
||||
const r = document.createRange();
|
||||
r.selectNodeContents($('code-wert'));
|
||||
getSelection()?.addRange(r);
|
||||
melde('Markiert – mit Strg+C kopieren.');
|
||||
}
|
||||
});
|
||||
|
||||
$('code-schliessen')?.addEventListener('click', () => {
|
||||
$('code-kasten').hidden = true;
|
||||
$('code-wert').textContent = ''; // auch aus der Seite raus
|
||||
melde('');
|
||||
});
|
||||
|
||||
/* DER TEXT WIRD GEZEIGT, NICHT VERSCHICKT.
|
||||
|
||||
Eine Nachricht, die ein Programm abschickt, liest sich wie eine
|
||||
Nachricht, die ein Programm abgeschickt hat — und genau das soll
|
||||
dieser Text nicht sein. Er steht da zum Lesen, Ändern und
|
||||
Kopieren, in einem Feld, das man bearbeiten kann. */
|
||||
function textZeigen(k) {
|
||||
const alt = document.getElementById('t-textfeld');
|
||||
if (alt) alt.closest('.t-text')?.remove();
|
||||
|
||||
const kasten = el('div', 't-text');
|
||||
kasten.append(el('h3', 't-text__titel', `Vorschlag für ${k.titel}`));
|
||||
kasten.append(el('p', 't-text__satz',
|
||||
'Gebaut aus den Merkmalen, die du angeklickt hast. Ändere ihn ruhig – '
|
||||
+ 'er soll nach dir klingen, nicht nach einer Vorlage. Abgeschickt wird '
|
||||
+ 'hier nichts.'));
|
||||
const feld = el('textarea', 't-text__feld');
|
||||
feld.id = 't-textfeld';
|
||||
feld.rows = 14;
|
||||
feld.value = k.ansprechtext;
|
||||
kasten.append(feld);
|
||||
|
||||
const reihe = el('div', 't-text__knoepfe');
|
||||
const kopieren = el('button', 'schritt', 'Kopieren');
|
||||
kopieren.type = 'button';
|
||||
kopieren.addEventListener('click', async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(feld.value);
|
||||
melde('Kopiert. Jetzt einfügen, wo du ihn ansprichst.');
|
||||
} catch {
|
||||
/* Ohne Zwischenablage-Recht: markieren, dann geht Strg+C.
|
||||
Eine Fehlermeldung „ging nicht" wäre hier unbrauchbar — der
|
||||
Text ist ja da. */
|
||||
feld.select();
|
||||
melde('Markiert – mit Strg+C kopieren.');
|
||||
}
|
||||
});
|
||||
reihe.append(kopieren);
|
||||
|
||||
const zu = el('button', 'schritt', 'Schließen');
|
||||
zu.type = 'button';
|
||||
zu.addEventListener('click', () => kasten.remove());
|
||||
reihe.append(zu);
|
||||
kasten.append(reihe);
|
||||
|
||||
const karte = [...document.querySelectorAll('.t-karte')]
|
||||
.find((x) => x.querySelector('.t-karte__titel')?.textContent === k.titel);
|
||||
(karte || $('liste')).append(kasten);
|
||||
feld.focus();
|
||||
}
|
||||
|
||||
function merkmal(k, m, istWarnung) {
|
||||
const gesetzt = (istWarnung ? k.warnzeichen : k.merkmale).includes(m.schluessel);
|
||||
const b = el('button', 't-merkmal');
|
||||
@@ -210,5 +385,24 @@
|
||||
zeichne();
|
||||
}
|
||||
|
||||
(async () => { try { await laden(); } catch { /* umgeleitet */ } })();
|
||||
/* WER ZUGAENGE ANLEGEN DARF, SAGT DER SERVER -- dieselbe Auskunft,
|
||||
aus der auch "Personen & Zugaenge" ihre Rollenknoepfe baut. Eine
|
||||
eigene Rollenabfrage hier waere eine zweite Meinung darueber, und
|
||||
die zweite ist die, die irgendwann mehr durchlaesst.
|
||||
|
||||
VOR dem ersten Zeichnen, nicht daneben: Sonst steht der Knopf
|
||||
einen Wimpernschlag lang da und verschwindet wieder. */
|
||||
async function ichHolen() {
|
||||
try {
|
||||
const a = await hole('/workspace/api/ich');
|
||||
if (!a.ok) return;
|
||||
const ich = await a.json();
|
||||
window.werZeigen?.(ich);
|
||||
darfAnlegen = Array.isArray(ich?.darf_anlegen) && ich.darf_anlegen.includes('modi');
|
||||
} catch { /* umgeleitet */ }
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try { await ichHolen(); await laden(); } catch { /* umgeleitet */ }
|
||||
})();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user