Das Suchfeld nimmt wieder Eingaben, eigene Kanalnamen, Community in Kanälen
screen1, drei Teile. === 1. „bei suchen kann man nichts reinschreiben" === MEIN FEHLER VOM SELBEN TAG. Beim Popover-Umbau heute frueh hing die Liste am <body>, damit sie nicht hinter dem modalen Dialog verschwindet. Gemessen: Das Suchfeld war da, der Fokus landete nicht darin, ein getipptes Zeichen kam nicht an. DER GRUND IST DER FOKUS-KAEFIG. Ein Dialog aus showModal() sperrt den Fokus auf seinen eigenen DOM-Baum ein. Die Liste lag im Top Layer -- sichtbar und anklickbar, aber ausserhalb des Kaefigs. Klicken braucht keinen Fokus, Tippen schon. Deshalb fiel es niemandem auf: Die Liste stand da, sie filterte auf Knopfdruck, nur eine Eingabe kam nicht an. DIE LOESUNG WAR EINE KOMBINATION, die ich vorher fuer unmoeglich hielt. Im Dialog wurde die Liste vom clip-path der abgeschraegten Ecke abgeschnitten, draussen war sie nicht bedienbar. Ein POPOVER wird aber in die Top Layer gehoben und dort gezeichnet -- der Beschnitt des Elternteils erreicht es nicht mehr, waehrend der DOM-Baum (und damit der Fokus) der des Dialogs bleibt. Jetzt haengt sie wieder im Dialog UND ist ein Popover: bedienbar und unbeschnitten. Gemessen beides gegeneinander: „comm" getippt -> kommt an, filtert auf 1 Treffer; und die LETZTE Zeile der vollen Liste ist wirklich anklickbar (elementFromPoint trifft sie selbst, nicht den Dialog). Daraus ist pruef-suchfeld geworden -- der Fehler war von aussen nicht zu sehen, und gefunden hat ihn Filipe, nicht ich. === 2. „einen neuen namen erstellen den es noch nicht gibt" === `data-frei="ja"` war in wahl.js seit langem gebaut und wurde NIE GESETZT -- dieselbe Sorte Lueue wie `grund_min` heute Morgen. Jetzt gesetzt; der getippte Text erscheint als eigener Eintrag ganz oben. Der Server nahm bisher nur die neun festen Zustaendigkeiten. Jetzt auch einen eigenen Namen: Der SCHLUESSEL wird daraus abgeleitet („Technik & Ton" -> "eigen-technik-ton"), der ANGEZEIGTE Name bleibt wie geschrieben. Das Praefix ist kein Schmuck -- ohne es entstuende aus dem Namen „Community" derselbe Schluessel wie beim festen Thema, und der eindeutige Index lehnte ihn ab, obwohl der Kanal nicht existiert. Gemessen: genau dieser Fall antwortet jetzt mit 201. Der alte Kommentar sprach sich gegen freie Namen aus („der sichere Weg zu Clipping neben Clipping-Team"). Das Risiko bleibt und wird begrenzt: Derselbe Name zweimal ergibt denselben Schluessel und damit 409. === 3. „kanäle mit den leuten mit der community rolle" === Seit dem 19.09. nimmt `ohneAussen()` die Community aus den Listen aller anderen. Die Begruendung dort ist ausdruecklich: „Ein Zweier-Gespraech ist kein Kanal. Es hat keine Nachtruhe, kein Modi liest mit, und niemand koennte moderieren." Genau diese Begruendung laesst den Kanal offen. Die Sperre bleibt fuer GESPRAECHE und faellt fuer KANAELE -- `?fuer=kanal` an der Partnerliste, und nur fuer den, der Kanaele ueberhaupt aufmachen darf. Sonst waere der Parameter ein Weg, an `ohneAussen` vorbei Namen zu erfahren. Gemessen: DogFather sieht im Gespraech VanVan und Miss, im Kanal zusaetzlich Kessi und Tom (beide Community). Ein Modi bekommt die erweiterte Liste auch mit dem Parameter nicht. Gruen: pruef-suchfeld (8, neu), pruef-chat-kanaele (81), pruef-treffchat, pruef-chat-neu, pruef-freie-namen (32), pruef-nachfrage (53), pruef-css-klassen. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -2741,7 +2741,12 @@
|
||||
|
||||
let personen = [];
|
||||
try {
|
||||
const a = await hole('/workspace/api/chat/partner');
|
||||
/* FUER EINEN KANAL FRAGEN WIR ANDERS (24.09.2026): Dort duerfen
|
||||
auch Leute aus der Community dabei sein -- ein Kanal wird
|
||||
moderiert, ein Zweier-Gespraech nicht. Der Server entscheidet,
|
||||
ob er die erweiterte Liste herausgibt. */
|
||||
const fuer = neuArt === 'kanal' ? '?fuer=kanal' : '';
|
||||
const a = await hole('/workspace/api/chat/partner' + fuer);
|
||||
if (a.ok) personen = (await a.json()).personen || [];
|
||||
} catch { return; }
|
||||
|
||||
@@ -2814,21 +2819,44 @@
|
||||
Server; steht nichts darin, gibt es alle schon. */
|
||||
function kanalWahlFuellen() {
|
||||
const feld = $('kanal-kategorie');
|
||||
/* EIGENE NAMEN SIND ERLAUBT (24.09.2026).
|
||||
|
||||
Filipe: „ich will dass man die option hat einen neuen namen zu
|
||||
erstellen den es noch nicht da in der liste gibt."
|
||||
|
||||
`data-frei="ja"` schaltet in wahl.js den Weg frei: Die Liste
|
||||
bekommt ein Suchfeld, das auch bei kurzer Liste dasteht, und
|
||||
der getippte Text erscheint als eigener Eintrag ganz oben.
|
||||
Gebaut war das laengst -- gesetzt hat das Merkmal bisher
|
||||
niemand, genau wie `grund_min` beim Meldeweg. */
|
||||
feld.dataset.frei = 'ja';
|
||||
feld.textContent = '';
|
||||
for (const k of kanalFrei) {
|
||||
const o = document.createElement('option');
|
||||
o.value = k.wert; o.textContent = k.name;
|
||||
feld.append(o);
|
||||
}
|
||||
/* DER HINWEIS „für jede Zuständigkeit gibt es schon einen Kanal"
|
||||
steht nur noch da, wenn die Liste leer ist -- und das Feld
|
||||
bleibt TROTZDEM sichtbar. Seit man eigene Namen vergeben darf,
|
||||
ist eine belegte Liste kein Grund mehr, die Auswahl
|
||||
wegzunehmen: Genau dann braucht man den eigenen Namen. */
|
||||
$('kanal-alle').hidden = kanalFrei.length > 0;
|
||||
feld.hidden = kanalFrei.length === 0;
|
||||
feld.hidden = false;
|
||||
}
|
||||
|
||||
/* Umschalten zwischen "Gespräch" und "Kanal". Ein zweiter Dialog
|
||||
waere dieselbe Personenwahl ein zweites Mal -- und die zweite
|
||||
Fassung waere die, in der eine Regel fehlt. */
|
||||
function neuArtSetzen(art) {
|
||||
const vorher = neuArt;
|
||||
neuArt = art;
|
||||
/* DIE PERSONENLISTE HAENGT AN DER ART (24.09.2026). Fuer einen
|
||||
Kanal stehen auch Leute aus der Community darin, fuer ein
|
||||
Gespraech nicht. Ohne dieses Nachladen zeigte die Liste, was
|
||||
beim Oeffnen des Dialogs gerade galt -- und wer erst auf
|
||||
„Kanal" umschaltet, saehe die Community nicht. */
|
||||
if (vorher && vorher !== art) partnerLaden();
|
||||
for (const b of document.querySelectorAll('#neu-art [data-art]')) {
|
||||
const an = b.dataset.art === art;
|
||||
b.dataset.an = an ? 'ja' : '';
|
||||
@@ -2858,7 +2886,11 @@
|
||||
auch niemanden -- man legt ihn an und fuellt ihn spaeter. Nur
|
||||
eine Kategorie muss es geben, sonst gibt es nichts anzulegen. */
|
||||
$('gruppenname-zeile').hidden = true;
|
||||
$('neu-los').disabled = !kanalUmbau && !$('kanal-kategorie').value;
|
||||
/* Auch ein frei getippter Name macht den Knopf scharf -- er
|
||||
steht in `data-extern`, nicht im Wert. Ohne diese Zeile
|
||||
haette man tippen koennen und waere nicht weitergekommen. */
|
||||
$('neu-los').disabled = !kanalUmbau && !$('kanal-kategorie').value
|
||||
&& !($('kanal-kategorie').dataset.extern || '').trim();
|
||||
$('neu-los').textContent = kanalUmbau ? 'Übernehmen' : 'Kanal anlegen';
|
||||
return;
|
||||
}
|
||||
@@ -2896,11 +2928,19 @@
|
||||
await raumOeffnen(raumId, { sanft: true });
|
||||
return;
|
||||
}
|
||||
const kategorie = $('kanal-kategorie').value;
|
||||
if (!kategorie) { $('neu-fehler').textContent = 'Wähle eine Kategorie.'; return; }
|
||||
/* EIN FREI GETIPPTER NAME STEHT IN `data-extern`, nicht im
|
||||
Wert -- so legt wahl.js ihn ab (siehe externSetzen). Beides
|
||||
geht an den Server; er entscheidet, was daraus wird. */
|
||||
const feldK = $('kanal-kategorie');
|
||||
const kategorie = feldK.value;
|
||||
const eigener = (feldK.dataset.extern || '').trim();
|
||||
if (!kategorie && !eigener) {
|
||||
$('neu-fehler').textContent = 'Wähle eine Zuständigkeit oder tipp einen eigenen Namen.';
|
||||
return;
|
||||
}
|
||||
const a = await hole('/workspace/api/chat/kanal', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ kategorie, mit: ids }),
|
||||
body: JSON.stringify({ kategorie, eigener_name: eigener, mit: ids }),
|
||||
});
|
||||
if (!a.ok) {
|
||||
$('neu-fehler').textContent = sagWas((await a.json().catch(() => ({}))).fehler, 'Ging nicht.');
|
||||
|
||||
@@ -324,7 +324,34 @@
|
||||
beide Regeln, ohne eine davon anzufassen -- und gilt auch fuer
|
||||
jeden kuenftigen Dialog. */
|
||||
const dlg = z.knopf.closest("dialog");
|
||||
document.body.append(liste);
|
||||
/* ==== IN DEN DIALOG, NICHT DANEBEN (24.09.2026) ================
|
||||
|
||||
Filipe: „bei suchen kann man nichts reinschreiben."
|
||||
|
||||
Er hatte recht, und es war die Folge des Umbaus von gestern.
|
||||
Gemessen: Das Suchfeld war da, der Fokus landete nicht darin,
|
||||
ein getipptes Zeichen kam nicht an.
|
||||
|
||||
DER GRUND IST DER FOKUS-KAEFIG. Ein Dialog, der mit showModal()
|
||||
geoeffnet wurde, sperrt den Fokus auf seinen eigenen DOM-Baum
|
||||
ein. Die Liste hing am <body> -- sichtbar (der Popover hebt sie
|
||||
in die Top Layer), aber ausserhalb des Kaefigs und damit nicht
|
||||
bedienbar. Klicken ging, Tippen nicht: Ein Klick braucht keinen
|
||||
Fokus, eine Eingabe schon.
|
||||
|
||||
WARUM SIE FRUEHER DRAUSSEN HING: Als direktes Kind des Dialogs
|
||||
wurde sie vom clip-path der abgeschraegten Ecke abgeschnitten
|
||||
(siehe der Absatz weiter unten). Das galt aber fuer eine Liste
|
||||
im normalen Fluss. EIN POPOVER WIRD IN DIE TOP LAYER GEHOBEN
|
||||
und dort gezeichnet -- der Beschnitt des Elternteils erreicht
|
||||
es nicht mehr. Der DOM-Baum bleibt trotzdem der des Dialogs,
|
||||
und damit gilt auch sein Fokus.
|
||||
|
||||
Beides zusammen loest, was einzeln nicht ging:
|
||||
draussen -> sichtbar, aber nicht bedienbar
|
||||
drinnen -> bedienbar, aber abgeschnitten
|
||||
drinnen + Popover -> beides. */
|
||||
(dlg || document.body).append(liste);
|
||||
liste.style.position = "fixed";
|
||||
/* IN EINEM DIALOG BRAUCHT DIE LISTE DIE TOP LAYER.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user