iobroker.alias-workbench 0.9.9 → 0.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +29 -0
- package/admin/css/werkbank.css +88 -3
- package/admin/js/baum.js +8 -0
- package/admin/js/detail.js +53 -6
- package/admin/js/entwurf.js +60 -20
- package/admin/js/ergebnis.js +83 -5
- package/admin/js/erkennung.js +46 -2
- package/admin/js/mqtt.js +23 -2
- package/admin/js/musterwahl.js +208 -31
- package/admin/js/objekte.js +31 -0
- package/admin/js/pruefungen.js +28 -2
- package/admin/js/quellentausch.js +179 -19
- package/admin/js/schreiben.js +194 -52
- package/admin/js/sprache.js +6 -1
- package/admin/js/verwendung.js +478 -0
- package/admin/js/vorlagen.js +87 -8
- package/admin/js/vorlagenblatt.js +199 -20
- package/admin/js/vorschlagen.js +50 -17
- package/admin/js/werte.js +157 -5
- package/admin/js/zuordnung.js +32 -36
- package/admin/js/zustand.js +3 -0
- package/admin/js/zustandsliste.js +59 -7
- package/admin/sprachen/de.json +67 -3
- package/admin/sprachen/en.json +67 -3
- package/admin/vorlagen/messpunkt.json +2 -1
- package/admin/vorlagen/tasmota-lampe.json +2 -1
- package/admin/vorlagen/tasmota-mehrfach.json +2 -1
- package/admin/vorlagen/tasmota-rgb.json +2 -1
- package/admin/vorlagen/tasmota-steckdose.json +2 -1
- package/io-package.json +27 -27
- package/package.json +1 -1
|
@@ -92,6 +92,15 @@ function ausVorlage(punktId, neuKanal) {
|
|
|
92
92
|
|
|
93
93
|
/* Stufe 3: gleicher Punktname irgendwo unter dem neuen Geraet, oder
|
|
94
94
|
gleiche Rolle. Bewusst schwach - deshalb nur als Vorschlag. */
|
|
95
|
+
/* Und WORUEBER geraten wurde, wird mitgegeben.
|
|
96
|
+
|
|
97
|
+
„vermutet" allein sagt nur, dass die Zuordnung schwach ist - nicht,
|
|
98
|
+
woran sie haengt. Ueber den Namen geraten heisst: irgendein Punkt
|
|
99
|
+
heisst hinten gleich; das kann weit danebenliegen (ein Fensterkontakt
|
|
100
|
+
`…1.STATE` landete so auf `…tele.STATE`, dem Telemetrie-JSON einer
|
|
101
|
+
Tasmota). Ueber die Rolle geraten ist etwas anderes und muss anders
|
|
102
|
+
geprueft werden. Der Tooltip an der Marke sagt es jetzt (Ricardo,
|
|
103
|
+
12.09.2026). */
|
|
95
104
|
function geraten(altQuelle, neuKanal) {
|
|
96
105
|
var name = altQuelle.split('.').pop();
|
|
97
106
|
var kandidaten = kindZustaende(neuKanal);
|
|
@@ -99,7 +108,7 @@ function geraten(altQuelle, neuKanal) {
|
|
|
99
108
|
kandidaten.forEach(function (id) {
|
|
100
109
|
if (!treffer && id.split('.').pop() === name) { treffer = id; }
|
|
101
110
|
});
|
|
102
|
-
if (treffer) { return treffer; }
|
|
111
|
+
if (treffer) { return { id: treffer, ueber: 'name' }; }
|
|
103
112
|
var altO = S.objects[altQuelle];
|
|
104
113
|
var rolle = altO && altO.common && altO.common.role;
|
|
105
114
|
if (rolle) {
|
|
@@ -108,7 +117,7 @@ function geraten(altQuelle, neuKanal) {
|
|
|
108
117
|
if (!treffer && o && o.common && o.common.role === rolle) { treffer = id; }
|
|
109
118
|
});
|
|
110
119
|
}
|
|
111
|
-
return treffer;
|
|
120
|
+
return treffer ? { id: treffer, ueber: 'rolle', rolle: rolle } : null;
|
|
112
121
|
}
|
|
113
122
|
|
|
114
123
|
/* Die Zuordnungstabelle: je Alias-Punkt, was heute gilt und was danach
|
|
@@ -158,10 +167,14 @@ export function tauschPlan(kanal, neuKanal) {
|
|
|
158
167
|
/* 3. geraten */
|
|
159
168
|
if (!zeile.neuR && zeile.altR) {
|
|
160
169
|
var g = geraten(zeile.altR, neuKanal);
|
|
161
|
-
if (g) {
|
|
170
|
+
if (g) {
|
|
171
|
+
zeile.neuR = g.id; zeile.stufe = 3;
|
|
172
|
+
zeile.geratenUeber = g.ueber; zeile.geratenRolle = g.rolle || '';
|
|
173
|
+
}
|
|
162
174
|
}
|
|
163
175
|
if (!zeile.neuW && zeile.altW) {
|
|
164
|
-
var
|
|
176
|
+
var gwT = geraten(zeile.altW, neuKanal);
|
|
177
|
+
var gw = gwT && gwT.id;
|
|
165
178
|
/* Was hier geraten wird, muss ein anderer Punkt sein als die
|
|
166
179
|
Lesequelle. Bei getrennten Quellen heissen Melder und Befehl oft
|
|
167
180
|
gleich - `stat.POWER` und `cmnd.POWER` -, und das Raten greift
|
|
@@ -172,6 +185,21 @@ export function tauschPlan(kanal, neuKanal) {
|
|
|
172
185
|
(gemessen 09.09.2026). Lieber kein Treffer als dieser. */
|
|
173
186
|
if (gw && gw !== zeile.neuR) { zeile.neuW = gw; }
|
|
174
187
|
}
|
|
188
|
+
/* Bei getrennten Quellen darf das Schreibziel nie die Lesequelle
|
|
189
|
+
sein - egal, aus welcher der drei Stufen es kam.
|
|
190
|
+
|
|
191
|
+
Beim Raten stand diese Regel schon (siehe oben), beim PFADTREFFER
|
|
192
|
+
fehlte sie: `suchePfad` probiert als letzte Form den blossen
|
|
193
|
+
Punktnamen, und `cmnd.POWER` findet so `…Stumm.stat.POWER` - den
|
|
194
|
+
Melder. Sichtbar wird es, wenn man beim Tauschen nicht das Geraet,
|
|
195
|
+
sondern einen Unterknoten waehlt (`…Stumm.stat` statt `…Stumm`):
|
|
196
|
+
dann verschwand der rote Hinweis, der Knopf wurde frei, und
|
|
197
|
+
geschrieben haette der Alias auf seine eigene Lesequelle - genau
|
|
198
|
+
der Fehler, den W20 abschaffen sollte (Ricardo, 12.09.2026).
|
|
199
|
+
|
|
200
|
+
Danach steht `neuW` leer, und die Sperre aus W20 greift: der
|
|
201
|
+
Nutzer entscheidet, ob der Punkt entfernt wird. */
|
|
202
|
+
if (!zeile.einfach && zeile.neuW && zeile.neuW === zeile.neuR) { zeile.neuW = ''; }
|
|
175
203
|
/* Bei einfacher Quelle gilt die Lesequelle fuer beides. */
|
|
176
204
|
if (zeile.einfach && zeile.neuR) { zeile.neuW = zeile.neuR; }
|
|
177
205
|
return zeile;
|
|
@@ -339,6 +367,25 @@ function zeichneAuswahlbaum(host, filter, beiWahl) {
|
|
|
339
367
|
if (!host.childNodes.length) {
|
|
340
368
|
host.appendChild(el('div', 'empty', tr('swap.noDevice')));
|
|
341
369
|
}
|
|
370
|
+
|
|
371
|
+
/* Die Liste bleibt stehen, wo sie stand.
|
|
372
|
+
|
|
373
|
+
Beim Aufklappen fiel das nicht auf: derselbe Behaelter, nur neu
|
|
374
|
+
gefuellt, und `scrollTop` ueberlebt das. Beim WAEHLEN schon -
|
|
375
|
+
`zeichneTausch` baut den ganzen Dialog neu, der Baum ist danach ein
|
|
376
|
+
anderes Element und faengt bei 0 an. Wer weit unten ein Geraet
|
|
377
|
+
anklickte, sah danach den Anfang der Liste und seinen eben
|
|
378
|
+
gewaehlten Eintrag gar nicht mehr (Ricardo, 12.09.2026, an einer
|
|
379
|
+
Liste mit 42 Zeilen: scrollTop 700 -> 0).
|
|
380
|
+
|
|
381
|
+
Gemerkt wird an `S`, nicht am Element: das Element gibt es beim
|
|
382
|
+
naechsten Zeichnen nicht mehr. `block: 'nearest'` schiebt nur, wenn
|
|
383
|
+
die Zeile wirklich draussen ist - sonst springt die Liste bei jedem
|
|
384
|
+
Klick ein Stueck, und das waere die naechste Unruhe. */
|
|
385
|
+
if (S.tauschScroll) { host.scrollTop = S.tauschScroll; }
|
|
386
|
+
var gewaehlteZeile = host.querySelector('.node.sel');
|
|
387
|
+
if (gewaehlteZeile) { gewaehlteZeile.scrollIntoView({ block: 'nearest' }); }
|
|
388
|
+
host.addEventListener('scroll', function () { S.tauschScroll = host.scrollTop; });
|
|
342
389
|
}
|
|
343
390
|
|
|
344
391
|
export function zeigeTausch() {
|
|
@@ -355,6 +402,9 @@ export function zeigeTausch() {
|
|
|
355
402
|
schlimmsten Fall genau dann, wenn im Feld noch das eben getauschte,
|
|
356
403
|
inzwischen geloeschte Geraet stand (W13, gemessen 26.08.2026). */
|
|
357
404
|
S.tauschFilter = '';
|
|
405
|
+
/* Und die Liste faengt oben an - sonst startet der naechste Tausch
|
|
406
|
+
dort, wo der letzte aufgehoert hat. */
|
|
407
|
+
S.tauschScroll = 0;
|
|
358
408
|
var b = $('#btn-swap-go');
|
|
359
409
|
if (b) { b.hidden = false; b.textContent = tr('swap.now'); }
|
|
360
410
|
zeichneTausch();
|
|
@@ -420,6 +470,10 @@ function zeichneTausch() {
|
|
|
420
470
|
zeichneAuswahlbaum(baumHost, S.tauschFilter, gewaehlt);
|
|
421
471
|
feld.addEventListener('input', function () {
|
|
422
472
|
S.tauschFilter = feld.value;
|
|
473
|
+
/* Andere Suche, andere Liste - die alte Scrollhoehe passt nicht mehr
|
|
474
|
+
und zeigte sonst ins Leere. */
|
|
475
|
+
S.tauschScroll = 0;
|
|
476
|
+
baumHost.scrollTop = 0;
|
|
423
477
|
zeichneAuswahlbaum(baumHost, S.tauschFilter, gewaehlt);
|
|
424
478
|
});
|
|
425
479
|
|
|
@@ -434,6 +488,40 @@ function zeichneTausch() {
|
|
|
434
488
|
/* Die Zuordnung, Zeile fuer Zeile. */
|
|
435
489
|
if (!S.tauschPlan) { S.tauschPlan = tauschPlan(kanal, S.tauschNeu); }
|
|
436
490
|
var plan = S.tauschPlan;
|
|
491
|
+
|
|
492
|
+
/* Steht die Wahl eine Ebene zu tief?
|
|
493
|
+
|
|
494
|
+
Der Baum laesst jeden Knoten waehlen, unter dem Datenpunkte haengen -
|
|
495
|
+
absichtlich, denn welche Ebene beim fremden Adapter das Geraet ist,
|
|
496
|
+
kann die Werkbank nicht wissen; bei einem flachen Adapter ist der
|
|
497
|
+
Kanal die richtige (Kommentar in `tauschPlan`). Bei MQTT sind
|
|
498
|
+
`stat`, `tele` und `cmnd` aber Themenordner, keine Geraete, und wer
|
|
499
|
+
dort landet, bekommt schlechtere Treffer: am RGB-Deckenlicht fanden
|
|
500
|
+
ueber das Geraet alle sieben Punkte ein Ziel, ueber `…Licht.tele`
|
|
501
|
+
nur fuenf - die beiden aus `stat` gar nichts (12.09.2026).
|
|
502
|
+
|
|
503
|
+
Verboten wird nichts. Aber die Werkbank kann nachrechnen, was eine
|
|
504
|
+
Ebene hoeher herauskaeme, und es sagen - sonst hakt man zwei Punkte
|
|
505
|
+
zum Entfernen an und opfert seinen Schalter, statt den Knoten
|
|
506
|
+
darueber zu nehmen (Ricardos Frage, 12.09.2026). */
|
|
507
|
+
var eltern = S.tauschNeu.split('.').slice(0, -1).join('.');
|
|
508
|
+
if (eltern.split('.').length > 2 && S.tauschNeu !== alt) {
|
|
509
|
+
var trefferHier = plan.filter(function (z) { return z.neuR; }).length;
|
|
510
|
+
var planOben = tauschPlan(kanal, eltern);
|
|
511
|
+
var trefferOben = planOben.filter(function (z) { return z.neuR; }).length;
|
|
512
|
+
if (trefferOben > trefferHier) {
|
|
513
|
+
var eb = el('div', 'aside w');
|
|
514
|
+
eb.style.borderLeftColor = 'var(--warn)';
|
|
515
|
+
eb.appendChild(el('b', null, tr('swap.higherLevel',
|
|
516
|
+
eltern, trefferOben, plan.length, trefferHier)));
|
|
517
|
+
var knopf = el('button', 'btn mini wichtig', tr('swap.goHigher'));
|
|
518
|
+
knopf.style.marginTop = '5px';
|
|
519
|
+
knopf.addEventListener('click', function () { gewaehlt(eltern); });
|
|
520
|
+
eb.appendChild(el('div', null, ''));
|
|
521
|
+
eb.appendChild(knopf);
|
|
522
|
+
body.appendChild(eb);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
437
525
|
var k = el('div', 'card');
|
|
438
526
|
k.style.marginTop = '11px';
|
|
439
527
|
var ch = el('div', 'ch');
|
|
@@ -460,9 +548,49 @@ function zeichneTausch() {
|
|
|
460
548
|
&& (z.einfach || (z.neuW || '') === (z.altW || ''));
|
|
461
549
|
var nm = el('span', 'sn', z.name);
|
|
462
550
|
if (gleich) { nm.appendChild(el('span', 'rat', tr('swap.unchanged'))); }
|
|
463
|
-
else if (z.stufe === 3) {
|
|
551
|
+
else if (z.stufe === 3) {
|
|
552
|
+
/* Die Marke sagt jetzt auch, WORUEBER geraten wurde - ueber den
|
|
553
|
+
blossen Punktnamen oder ueber die Rolle. Das sind zwei sehr
|
|
554
|
+
verschiedene Vermutungen, und sie pruefen sich verschieden. */
|
|
555
|
+
var rm = el('span', 'rat', tr('guess.mark'));
|
|
556
|
+
rm.title = z.geratenUeber === 'rolle'
|
|
557
|
+
? tr('swap.guessedByRole', z.geratenRolle || '?')
|
|
558
|
+
: tr('swap.guessedByName', (z.altR || '').split('.').pop());
|
|
559
|
+
nm.appendChild(rm);
|
|
560
|
+
}
|
|
464
561
|
r.appendChild(nm);
|
|
465
562
|
var rechts = el('span');
|
|
563
|
+
/* Das Kaestchen „entfernen" - an zwei Stellen gebraucht, deshalb hier.
|
|
564
|
+
|
|
565
|
+
Es gab es bisher nur, wenn GAR NICHTS gefunden wurde. Der zweite
|
|
566
|
+
Fall braucht es genauso: Lesequelle gefunden, Schreibziel nicht.
|
|
567
|
+
Ein Punkt mit Schreibrecht ohne Schreibziel laesst sich in ioBroker
|
|
568
|
+
nicht ausdruecken - jede Form, die der js-controller annimmt,
|
|
569
|
+
schreibt irgendwohin, und `{read: X}` ohne `write` lehnt er ab
|
|
570
|
+
(„The id is empty", gemessen 12.09.2026). Also entscheidet der
|
|
571
|
+
Nutzer: mitnehmen geht nicht, entfernen schon (Ricardo). */
|
|
572
|
+
var entfernenKaestchen = function () {
|
|
573
|
+
var lb = document.createElement('label');
|
|
574
|
+
lb.style.display = 'flex';
|
|
575
|
+
lb.style.gap = '6px';
|
|
576
|
+
lb.style.alignItems = 'center';
|
|
577
|
+
lb.style.marginTop = '3px';
|
|
578
|
+
lb.style.cursor = 'pointer';
|
|
579
|
+
var cb = document.createElement('input');
|
|
580
|
+
cb.type = 'checkbox';
|
|
581
|
+
cb.checked = !!S.tauschWeg[z.id];
|
|
582
|
+
cb.addEventListener('change', function () {
|
|
583
|
+
S.tauschWeg[z.id] = cb.checked;
|
|
584
|
+
/* Der Knopf haengt daran - also neu rechnen, nicht erst beim
|
|
585
|
+
naechsten Oeffnen. `zeichneTausch`, nicht `zeigeTausch`: das
|
|
586
|
+
zweite setzt Auswahl, Plan und Haken zurueck und faengt von
|
|
587
|
+
vorn an. */
|
|
588
|
+
zeichneTausch();
|
|
589
|
+
});
|
|
590
|
+
lb.appendChild(cb);
|
|
591
|
+
lb.appendChild(el('span', 'hint', tr('swap.removeIt')));
|
|
592
|
+
return lb;
|
|
593
|
+
};
|
|
466
594
|
/* Beschriftet, sonst raet man, welche der beiden Zeilen die neue ist. */
|
|
467
595
|
var paarZeile = function (beschriftung, text, klasse, farbe) {
|
|
468
596
|
var zz = el('div');
|
|
@@ -489,6 +617,7 @@ function zeichneTausch() {
|
|
|
489
617
|
kw.style.color = 'var(--bad)';
|
|
490
618
|
kw.textContent = tr('swap.noWriteMatch');
|
|
491
619
|
rechts.appendChild(kw);
|
|
620
|
+
rechts.appendChild(entfernenKaestchen());
|
|
492
621
|
}
|
|
493
622
|
} else {
|
|
494
623
|
var fehlt = el('div');
|
|
@@ -497,19 +626,7 @@ function zeichneTausch() {
|
|
|
497
626
|
rechts.appendChild(fehlt);
|
|
498
627
|
/* Was nichts findet, laesst sich mit entfernen - sonst bliebe ein
|
|
499
628
|
Punkt zurueck, der ins Leere zeigt (Ricardos Wahl, 25.08.2026). */
|
|
500
|
-
|
|
501
|
-
lb.style.display = 'flex';
|
|
502
|
-
lb.style.gap = '6px';
|
|
503
|
-
lb.style.alignItems = 'center';
|
|
504
|
-
lb.style.marginTop = '3px';
|
|
505
|
-
lb.style.cursor = 'pointer';
|
|
506
|
-
var cb = document.createElement('input');
|
|
507
|
-
cb.type = 'checkbox';
|
|
508
|
-
cb.checked = !!S.tauschWeg[z.id];
|
|
509
|
-
cb.addEventListener('change', function () { S.tauschWeg[z.id] = cb.checked; });
|
|
510
|
-
lb.appendChild(cb);
|
|
511
|
-
lb.appendChild(el('span', 'hint', tr('swap.removeIt')));
|
|
512
|
-
rechts.appendChild(lb);
|
|
629
|
+
rechts.appendChild(entfernenKaestchen());
|
|
513
630
|
}
|
|
514
631
|
r.appendChild(rechts);
|
|
515
632
|
k.appendChild(r);
|
|
@@ -556,7 +673,39 @@ function zeichneTausch() {
|
|
|
556
673
|
if (plan.some(function (z) { return z.stufe === 3; })) {
|
|
557
674
|
body.appendChild(el('div', 'aside', tr('swap.guessHint')));
|
|
558
675
|
}
|
|
559
|
-
|
|
676
|
+
|
|
677
|
+
/* Punkte, die nicht mitkoennen, halten den Tausch auf - bis der Nutzer
|
|
678
|
+
sagt, was mit ihnen geschehen soll.
|
|
679
|
+
|
|
680
|
+
Zwei Faelle, beide mit demselben Ausgang (das Kaestchen daneben):
|
|
681
|
+
gar kein Treffer, oder getrennte Quellen mit Lesetreffer und ohne
|
|
682
|
+
Schreibziel. Frueher lief der Tausch in beiden Faellen los. Der
|
|
683
|
+
zweite endete dabei im Fehler des js-controllers, und weil
|
|
684
|
+
`tauscheAus` Objekt fuer Objekt schrieb, stand der Alias danach
|
|
685
|
+
halb auf der alten und halb auf der neuen Quelle (W20, gemessen
|
|
686
|
+
12.09.2026). Der erste lief still durch und liess den Punkt auf der
|
|
687
|
+
alten Quelle stehen - derselbe Mischzustand, nur ohne Meldung.
|
|
688
|
+
|
|
689
|
+
Gesperrt wird mit Begruendung am Knopf, nicht bloss grau: ein
|
|
690
|
+
Knopf, der nicht sagt warum, ist der Fehler aus I32. */
|
|
691
|
+
var offeneStolper = plan.filter(function (z) {
|
|
692
|
+
if (S.tauschWeg[z.id]) { return false; }
|
|
693
|
+
if (!z.neuR) { return true; }
|
|
694
|
+
return !!(z.altW && z.altW !== z.altR && !z.neuW);
|
|
695
|
+
});
|
|
696
|
+
if (go) {
|
|
697
|
+
if (offeneStolper.length) {
|
|
698
|
+
go.disabled = true;
|
|
699
|
+
go.title = tr('swap.blocked', offeneStolper.map(function (z) { return z.name; }).join(', '));
|
|
700
|
+
var sp = el('div', 'aside w');
|
|
701
|
+
sp.style.borderLeftColor = 'var(--bad)';
|
|
702
|
+
sp.appendChild(el('b', null, go.title));
|
|
703
|
+
body.appendChild(sp);
|
|
704
|
+
} else {
|
|
705
|
+
go.disabled = false;
|
|
706
|
+
go.title = '';
|
|
707
|
+
}
|
|
708
|
+
}
|
|
560
709
|
}
|
|
561
710
|
|
|
562
711
|
export function tauscheAus() {
|
|
@@ -585,6 +734,17 @@ export function tauscheAus() {
|
|
|
585
734
|
};
|
|
586
735
|
|
|
587
736
|
var weiter = function () {
|
|
737
|
+
/* Schlug beim Umschreiben etwas fehl, wird nichts geloescht.
|
|
738
|
+
|
|
739
|
+
Dieselbe Regel wie beim Verlegen (T11): erst alles Neue, und geht
|
|
740
|
+
dabei etwas schief, bleibt der Rest unberuehrt. Hier fehlte sie -
|
|
741
|
+
`weiter` loeschte auch dann, wenn die Haelfte der Punkte noch auf
|
|
742
|
+
der alten Quelle stand. Zurueck kann die Werkbank nichts nehmen,
|
|
743
|
+
aber sie kann aufhoeren, es schlimmer zu machen: der Nutzer sieht
|
|
744
|
+
die Fehler und drueckt „Noch einmal versuchen", und die schon
|
|
745
|
+
umgeschriebenen Punkte stoeren dabei nicht - sie stehen ja bereits
|
|
746
|
+
richtig (12.09.2026). */
|
|
747
|
+
if (fehler.length) { return fertig(); }
|
|
588
748
|
if (!loeschen.length) { return fertig(); }
|
|
589
749
|
var offen2 = loeschen.length;
|
|
590
750
|
loeschen.forEach(function (id) {
|
package/admin/js/schreiben.js
CHANGED
|
@@ -28,6 +28,7 @@ import { zeichneErgebnis } from './ergebnis.js';
|
|
|
28
28
|
import { uebernehmeBestand , enumAenderungen, setzeZiel } from './zuordnung.js';
|
|
29
29
|
|
|
30
30
|
import { mqttEinzelnStill } from './mqtt.js';
|
|
31
|
+
import { sucheInSkripten, sucheInSkriptenMehrere, skriptListe } from './verwendung.js';
|
|
31
32
|
|
|
32
33
|
import { rateBehalten } from './vorschlagen.js';
|
|
33
34
|
|
|
@@ -270,20 +271,33 @@ export function baueObjekte(e) {
|
|
|
270
271
|
} });
|
|
271
272
|
|
|
272
273
|
e.states.forEach(function (s) {
|
|
273
|
-
if (!s.on || !s.n
|
|
274
|
+
if (!s.on || !s.n) { return; }
|
|
275
|
+
/* Ohne Lesequelle faellt die Zeile heraus - ausser sie ist ein
|
|
276
|
+
Taster, der nur schreibt (K23). */
|
|
277
|
+
if (!s.srcR && !taster(s)) { return; }
|
|
274
278
|
var id = ziel + '.' + s.n;
|
|
275
279
|
|
|
276
280
|
var alias = {};
|
|
277
|
-
|
|
281
|
+
/* ioBroker verlangt immer eine `alias.id`; ein reines `{ write: … }`
|
|
282
|
+
weist der js-controller ab („Alias id is invalid: The id is
|
|
283
|
+
empty!", gemessen 15.09.2026). Beim Taster steht deshalb das
|
|
284
|
+
Schreibziel darin, und `common.read: false` sagt, dass dort nichts
|
|
285
|
+
abzuholen ist. */
|
|
286
|
+
if (!s.srcR) { alias.id = s.srcW; }
|
|
287
|
+
else if (s.srcW && s.srcW !== s.srcR) { alias.id = { read: s.srcR, write: s.srcW }; }
|
|
278
288
|
else { alias.id = s.srcR; }
|
|
279
289
|
if (s.f) { alias.read = s.f; }
|
|
280
290
|
if (s.fw && s.srcW) { alias.write = s.fw; }
|
|
281
291
|
|
|
292
|
+
/* Ein Taster meldet nichts — dann sagt der Alias-Punkt das auch.
|
|
293
|
+
Sonst malen vis, Alexa und matter einen Kippschalter, der ewig auf
|
|
294
|
+
„aus" steht, statt eines Knopfes. */
|
|
295
|
+
var istTaster = taster(s);
|
|
282
296
|
var common = {
|
|
283
297
|
name: s.caption || s.n,
|
|
284
298
|
role: s.role,
|
|
285
299
|
type: s.typ || 'mixed',
|
|
286
|
-
read:
|
|
300
|
+
read: !istTaster,
|
|
287
301
|
write: !!s.srcW,
|
|
288
302
|
alias: alias
|
|
289
303
|
};
|
|
@@ -349,6 +363,19 @@ export function verwaiste(e) {
|
|
|
349
363
|
}
|
|
350
364
|
|
|
351
365
|
/* Was dem Schreiben im Weg steht. */
|
|
366
|
+
/* Ein Taster: keine Lesequelle, ein Schreibziel, und das Ziel sagt
|
|
367
|
+
selbst, dass es nichts zu melden hat (`common.read === false`).
|
|
368
|
+
|
|
369
|
+
Nicht ueber die Rolle entschieden: `button.stop` ist Konvention, aber
|
|
370
|
+
nur der Adapter weiss wirklich, ob am Punkt etwas abzulesen ist. An
|
|
371
|
+
`hm-rpc.2.NEQ1795694.1.STOP` steht `read: false` — hingeschrieben von
|
|
372
|
+
hm-rpc, nicht von uns. */
|
|
373
|
+
export function taster(s) {
|
|
374
|
+
if (!s || s.srcR || !s.srcW) { return false; }
|
|
375
|
+
var o = S.objects[s.srcW];
|
|
376
|
+
return !!(o && o.common && o.common.read === false);
|
|
377
|
+
}
|
|
378
|
+
|
|
352
379
|
export function pruefeSchreiben(e) {
|
|
353
380
|
var probleme = [];
|
|
354
381
|
var an = e.states.filter(function (s) { return s.on; });
|
|
@@ -361,7 +388,20 @@ export function pruefeSchreiben(e) {
|
|
|
361
388
|
namen[s.n] = 1;
|
|
362
389
|
|
|
363
390
|
if (!s.srcR) {
|
|
364
|
-
|
|
391
|
+
/* Ein Taster hat keinen Zustand zum Lesen.
|
|
392
|
+
|
|
393
|
+
`STOP` am Rollladen schreibt nur; am Geraet traegt der Punkt
|
|
394
|
+
`read: false`, der hm-rpc-Adapter setzt das selbst. Die Sperre
|
|
395
|
+
hier war deshalb richtig UND falsch zugleich: richtig, weil
|
|
396
|
+
ioBroker ohne `alias.id` keinen Punkt anlegt — falsch, weil sie
|
|
397
|
+
damit jeden Rollladen-Alias mit STOP unmoeglich machte. Kein
|
|
398
|
+
einziger ist je entstanden (gefunden 14.09.2026, K23).
|
|
399
|
+
|
|
400
|
+
Massgeblich ist, was das ZIEL kann, nicht was die Rolle
|
|
401
|
+
nahelegt: `read: false` ist eine Tatsache am Objekt, die der
|
|
402
|
+
Adapter hinschreibt. Beim Schreiben nimmt `alias.id` dann das
|
|
403
|
+
Schreibziel, und der Alias-Punkt bekommt selbst `read: false`. */
|
|
404
|
+
if (!(s.srcW && taster(s))) { probleme.push(tr('write.noSourceChosen', s.n)); }
|
|
365
405
|
} else if (!S.objects[s.srcR]) {
|
|
366
406
|
/* Der teuerste Fehler: der js-controller merkt sich „Quelle fehlt"
|
|
367
407
|
dauerhaft und korrigiert das nie. Nur loeschen und neu anlegen
|
|
@@ -445,12 +485,31 @@ export function zuSchreiben(alleAusgaenge) {
|
|
|
445
485
|
}).filter(Boolean);
|
|
446
486
|
}
|
|
447
487
|
if (!alleAusgaenge || !S.entwurf.instanzen || S.entwurf.instanzen.length < 2) { return [S.entwurf]; }
|
|
488
|
+
/* Der Kanalname wird zur Kennung - und zwei koennen dabei gleich werden.
|
|
489
|
+
|
|
490
|
+
`ausgangName` saeubert seit dem 12.09.2026 selbst (G31), und damit
|
|
491
|
+
ergeben „Licht Bar" und „Licht, Bar" beide `Licht_Bar`: der zweite
|
|
492
|
+
Kanal ueberschriebe den ersten, still und ohne Meldung. Deshalb
|
|
493
|
+
wird hier mitgezaehlt, was schon vergeben ist - der zweite bekommt
|
|
494
|
+
`_2`, der dritte `_3`. Der Anzeigename bleibt der des Kanals. */
|
|
495
|
+
var vergeben = {};
|
|
496
|
+
var eindeutig = function (name) {
|
|
497
|
+
if (!vergeben[name]) { vergeben[name] = 1; return name; }
|
|
498
|
+
var z = 1, n2;
|
|
499
|
+
do { z++; n2 = name + '_' + z; } while (vergeben[n2]);
|
|
500
|
+
vergeben[n2] = 1;
|
|
501
|
+
return n2;
|
|
502
|
+
};
|
|
448
503
|
return S.entwurf.instanzen.map(function (n) {
|
|
449
|
-
if (String(n) === String(S.entwurf.instanz)) {
|
|
504
|
+
if (String(n) === String(S.entwurf.instanz)) {
|
|
505
|
+
S.entwurf.zielName = eindeutig(S.entwurf.zielName);
|
|
506
|
+
S.entwurf.ziel = S.entwurf.zielOrdner + '.' + S.entwurf.zielName;
|
|
507
|
+
return S.entwurf;
|
|
508
|
+
}
|
|
450
509
|
var v = vorschlag(S.current, S.entwurf.vorlage, n);
|
|
451
510
|
if (v) {
|
|
452
511
|
v.zielOrdner = S.entwurf.zielOrdner;
|
|
453
|
-
v.zielName = ausgangName(v, n);
|
|
512
|
+
v.zielName = eindeutig(ausgangName(v, n));
|
|
454
513
|
v.ziel = v.zielOrdner + '.' + v.zielName;
|
|
455
514
|
enumsUebertragen(v);
|
|
456
515
|
}
|
|
@@ -487,6 +546,35 @@ function sammle(liste, o) {
|
|
|
487
546
|
vorh.neu = vorh.neu && o.neu;
|
|
488
547
|
}
|
|
489
548
|
|
|
549
|
+
/* Eine selbst angelegte Aufzaehlung, die durch diesen Schreibvorgang
|
|
550
|
+
leer wird, geht mit.
|
|
551
|
+
|
|
552
|
+
Beim LOESCHEN eines Alias tut das `enumsDieLeerWuerden` seit jeher.
|
|
553
|
+
Beim blossen WECHSEL der Funktion nicht: wer „Stehlampe" waehlte,
|
|
554
|
+
schrieb, dann auf „Licht" umstellte, hinterliess ein leeres
|
|
555
|
+
`enum.functions.floor_lamp` - von der Werkbank angelegt, von der
|
|
556
|
+
Werkbank geleert, und trotzdem stehengeblieben (gemessen 12.09.2026).
|
|
557
|
+
|
|
558
|
+
Dieselbe Regel wie dort: nur was `angelegtVon` traegt, und nur wenn
|
|
559
|
+
hinterher kein Mitglied uebrig ist. Der Eintrag wandert aus der
|
|
560
|
+
Schreibliste in die Loeschliste - sonst schriebe ihn `setObject`
|
|
561
|
+
parallel zum `delObject` wieder hin.
|
|
562
|
+
|
|
563
|
+
Gerufen von `zeigeTrockenlauf` UND `schreibeObjekte`: beide bauen ihre
|
|
564
|
+
Liste selbst, und was der Trockenlauf zeigt, muss das Schreiben tun. */
|
|
565
|
+
function leereEigeneEnums(liste, weg) {
|
|
566
|
+
liste.slice().forEach(function (x) {
|
|
567
|
+
if (!x.istEnum || !x.weg) { return; }
|
|
568
|
+
var o = enums[x.id];
|
|
569
|
+
if (!o || !o.native || o.native.angelegtVon !== 'alias-workbench') { return; }
|
|
570
|
+
if (((x.obj.common || {}).members || []).length) { return; }
|
|
571
|
+
liste.splice(liste.indexOf(x), 1);
|
|
572
|
+
if (!weg.some(function (y) { return y.id === x.id; })) {
|
|
573
|
+
weg.push({ id: x.id, vorgabe: true, grund: tr('enums.nowEmpty') });
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
490
578
|
export function zeigeTrockenlauf(alleAusgaenge) {
|
|
491
579
|
if (!S.entwurf) { return; }
|
|
492
580
|
S.trockenAlle = !!alleAusgaenge;
|
|
@@ -532,6 +620,7 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
532
620
|
if (!weg.some(function (x) { return x.id === v.id; })) { weg.push(v); }
|
|
533
621
|
});
|
|
534
622
|
});
|
|
623
|
+
leereEigeneEnums(liste, weg);
|
|
535
624
|
S.loeschListe = weg;
|
|
536
625
|
var body = $('#dry-body');
|
|
537
626
|
body.textContent = '';
|
|
@@ -600,6 +689,20 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
600
689
|
body.appendChild(zwK);
|
|
601
690
|
}
|
|
602
691
|
|
|
692
|
+
/* Was beim letzten Anlegen der Sendepunkte schiefging - hier oben, wo
|
|
693
|
+
man es sieht, und nicht als Tooltip an einem Knopf, den derselbe
|
|
694
|
+
Rueckruf gleich wieder wegwirft (H17). */
|
|
695
|
+
if (S.mqFehler && S.mqFehler.length) {
|
|
696
|
+
var mk = el('div', 'aside w');
|
|
697
|
+
mk.style.borderLeftColor = 'var(--bad)';
|
|
698
|
+
mk.style.marginBottom = '11px';
|
|
699
|
+
mk.appendChild(el('b', null, tr('write.failed', S.mqFehler.length)));
|
|
700
|
+
var mul = el('ul');
|
|
701
|
+
S.mqFehler.forEach(function (x) { mul.appendChild(el('li', null, x)); });
|
|
702
|
+
mk.appendChild(mul);
|
|
703
|
+
body.appendChild(mk);
|
|
704
|
+
}
|
|
705
|
+
|
|
603
706
|
/* Die Aufzaehlungen sind gerade nicht bekannt — dann wird auch keine
|
|
604
707
|
geschrieben. Das gehoert hierher und nicht in eine Sperre: der Alias
|
|
605
708
|
selbst braucht sie nicht, und aus einem stillen Datenverlust eine
|
|
@@ -618,7 +721,12 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
618
721
|
var wch = el('div', 'ch');
|
|
619
722
|
wch.appendChild(el('span', 'typ', tr('write.remove')));
|
|
620
723
|
wch.appendChild(el('span', 'chip bad', tr('write.removeCount', weg.length)));
|
|
621
|
-
|
|
724
|
+
/* Der Satz gilt fuer Datenpunkte. Steht eine leer gewordene
|
|
725
|
+
Aufzaehlung mit in der Liste, waere er dort falsch - die liegt
|
|
726
|
+
nicht im Alias und stand nie im Entwurf (12.09.2026). */
|
|
727
|
+
if (weg.some(function (v) { return String(v.id).indexOf('enum.') !== 0; })) {
|
|
728
|
+
wch.appendChild(el('span', 'chip mut', tr('write.removeHint')));
|
|
729
|
+
}
|
|
622
730
|
wk.appendChild(wch);
|
|
623
731
|
weg.forEach(function (v, i) {
|
|
624
732
|
var r = el('div', 'slot');
|
|
@@ -685,6 +793,19 @@ export function zeigeTrockenlauf(alleAusgaenge) {
|
|
|
685
793
|
kn2.disabled = false;
|
|
686
794
|
kn2.textContent = tr('write.retry');
|
|
687
795
|
kn2.title = mqFehler.join(' | ');
|
|
796
|
+
/* Und zwar so, dass es den Neuaufbau ueberlebt.
|
|
797
|
+
|
|
798
|
+
Drei Zeilen weiter unten wird der Entwurf neu gebaut
|
|
799
|
+
und der Trockenlauf noch einmal gerechnet - dabei
|
|
800
|
+
verschwindet dieser Knopf samt seiner Begruendung aus
|
|
801
|
+
dem DOM. Gemessen 12.09.2026: nach rund 120 ms war er
|
|
802
|
+
weg. Der neue Dialog sperrte wieder und sagte, welcher
|
|
803
|
+
Sendepunkt fehlt, aber nicht mehr, WARUM er nicht
|
|
804
|
+
entstanden ist (H17). Am Zustand gemerkt, zeichnet
|
|
805
|
+
`zeigeTrockenlauf` ihn oben wieder hin. */
|
|
806
|
+
S.mqFehler = mqFehler.slice();
|
|
807
|
+
} else {
|
|
808
|
+
S.mqFehler = null;
|
|
688
809
|
}
|
|
689
810
|
/* Erst den Entwurf neu aufbauen lassen, dann den
|
|
690
811
|
Trockenlauf noch einmal rechnen. Sofort geoeffnet zeigte
|
|
@@ -988,6 +1109,32 @@ export function zeichneLoeschen() {
|
|
|
988
1109
|
body.appendChild(ew);
|
|
989
1110
|
}
|
|
990
1111
|
|
|
1112
|
+
/* Wer nennt diese Kennungen sonst noch?
|
|
1113
|
+
|
|
1114
|
+
Beim Verlegen steht die Liste seit jeher da, beim Loeschen fehlte
|
|
1115
|
+
sie - dabei ist die Folge hier endgueltig: ein Skript, das den
|
|
1116
|
+
Alias anspricht, laeuft danach ins Leere. Gesucht wird nur im
|
|
1117
|
+
Klartext und nur in den Skripten; der Hinweis darunter sagt das. */
|
|
1118
|
+
var skriptFeld = el('div');
|
|
1119
|
+
skriptFeld.style.marginTop = '11px';
|
|
1120
|
+
body.appendChild(skriptFeld);
|
|
1121
|
+
var wurzeln = [ziel].concat(S.loeschAlleAusgaenge ? geschwisterVon(ziel) : []);
|
|
1122
|
+
sucheInSkriptenMehrere(wurzeln, function (treffer) {
|
|
1123
|
+
if (S.loeschZiel !== ziel) { return; }
|
|
1124
|
+
skriptFeld.textContent = '';
|
|
1125
|
+
if (!treffer.length) {
|
|
1126
|
+
skriptFeld.appendChild(el('div', 'aside', tr('move.noScripts')));
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
var w = el('div', 'aside w');
|
|
1130
|
+
w.appendChild(el('b', null, treffer.length === 1
|
|
1131
|
+
? tr('del.scriptsHead1')
|
|
1132
|
+
: tr('del.scriptsHead', treffer.length)));
|
|
1133
|
+
w.appendChild(skriptListe(treffer));
|
|
1134
|
+
w.appendChild(el('div', 'hint', tr('del.scriptsHint')));
|
|
1135
|
+
skriptFeld.appendChild(w);
|
|
1136
|
+
});
|
|
1137
|
+
|
|
991
1138
|
var b = $('#btn-del-go');
|
|
992
1139
|
b.disabled = false;
|
|
993
1140
|
b.hidden = false;
|
|
@@ -1024,6 +1171,16 @@ export function loescheAlias() {
|
|
|
1024
1171
|
m.style.fontSize = '13px';
|
|
1025
1172
|
if (fehler.length) {
|
|
1026
1173
|
m.appendChild(el('b', null, tr('write.failed', fehler.length)));
|
|
1174
|
+
/* Und WAS schiefging, nicht nur wie viel.
|
|
1175
|
+
|
|
1176
|
+
Beim Schreiben steht die Liste seit jeher da (`melden` beim
|
|
1177
|
+
Verlegen, der Trockenlauf-Dialog beim Anlegen); beim Loeschen
|
|
1178
|
+
fehlte sie, und zurueck blieb die blosse Zahl. Wer wissen
|
|
1179
|
+
will, welcher Punkt haengt — etwa weil ein Skript ihn sperrt
|
|
1180
|
+
—, erfuhr es nicht (G44, gemessen 12.09.2026). */
|
|
1181
|
+
var ul = el('ul');
|
|
1182
|
+
fehler.forEach(function (x) { ul.appendChild(el('li', null, x)); });
|
|
1183
|
+
m.appendChild(ul);
|
|
1027
1184
|
} else {
|
|
1028
1185
|
m.appendChild(el('b', null, tr('del.done', alle.length)));
|
|
1029
1186
|
}
|
|
@@ -1135,41 +1292,6 @@ function verlegeUmfang(alt) {
|
|
|
1135
1292
|
});
|
|
1136
1293
|
}
|
|
1137
1294
|
|
|
1138
|
-
/* Wer nennt diese Kennung sonst noch?
|
|
1139
|
-
|
|
1140
|
-
Die Skripte des javascript-Adapters lassen sich durchsuchen; sie sind
|
|
1141
|
-
der haeufigste Ort, an dem eine Kennung im Klartext steht. vis-
|
|
1142
|
-
Ansichten und fremde Adapter kann die Werkbank nicht durchsehen -
|
|
1143
|
-
darauf weist der Dialog eigens hin, statt Vollstaendigkeit
|
|
1144
|
-
vorzutaeuschen. */
|
|
1145
|
-
export function sucheInSkripten(kennung, fertig) {
|
|
1146
|
-
var treffer = [];
|
|
1147
|
-
var fertigMit = function () { fertig(treffer); };
|
|
1148
|
-
try {
|
|
1149
|
-
socket.emit('getObjectView', 'script', 'javascript',
|
|
1150
|
-
{ startkey: 'script.js.', endkey: 'script.js.\u9999' }, function (err, doc) {
|
|
1151
|
-
if (err || !doc || !doc.rows) { return fertigMit(); }
|
|
1152
|
-
doc.rows.forEach(function (r) {
|
|
1153
|
-
var o = r.value;
|
|
1154
|
-
var q = o && o.common && o.common.source;
|
|
1155
|
-
if (!q || q.indexOf(kennung) === -1) { return; }
|
|
1156
|
-
var zeilen = String(q).split('\n');
|
|
1157
|
-
var stellen = [];
|
|
1158
|
-
zeilen.forEach(function (z, i) {
|
|
1159
|
-
if (z.indexOf(kennung) > -1) { stellen.push(i + 1); }
|
|
1160
|
-
});
|
|
1161
|
-
treffer.push({
|
|
1162
|
-
id: r.id,
|
|
1163
|
-
name: txt((o.common || {}).name) || r.id.split('.').pop(),
|
|
1164
|
-
an: !!(o.common && o.common.enabled),
|
|
1165
|
-
zeilen: stellen
|
|
1166
|
-
});
|
|
1167
|
-
});
|
|
1168
|
-
fertigMit();
|
|
1169
|
-
});
|
|
1170
|
-
} catch { fertigMit(); }
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
1295
|
export function zeigeVerlegen(altVorgabe, zielVorgabe) {
|
|
1174
1296
|
/* Der Knopf steht auch an der Quelle, sobald es den Alias gibt (T1).
|
|
1175
1297
|
Dort ist S.current die Quelle, nicht der Alias - gemeint ist immer
|
|
@@ -1440,14 +1562,7 @@ export function zeigeVerlegen(altVorgabe, zielVorgabe) {
|
|
|
1440
1562
|
w3.appendChild(el('b', null, treffer.length === 1
|
|
1441
1563
|
? tr('move.scriptsHead1')
|
|
1442
1564
|
: tr('move.scriptsHead', treffer.length)));
|
|
1443
|
-
|
|
1444
|
-
treffer.forEach(function (t) {
|
|
1445
|
-
ul3.appendChild(el('li', null, t.name + (t.an ? '' : ' (' + tr('move.scriptOff') + ')') +
|
|
1446
|
-
' \u2014 ' + (t.zeilen.length === 1
|
|
1447
|
-
? tr('move.scriptLines', t.zeilen[0])
|
|
1448
|
-
: tr('move.scriptLinesN', t.zeilen.join(', ')))));
|
|
1449
|
-
});
|
|
1450
|
-
w3.appendChild(ul3);
|
|
1565
|
+
w3.appendChild(skriptListe(treffer));
|
|
1451
1566
|
skriptFeld.appendChild(w3);
|
|
1452
1567
|
});
|
|
1453
1568
|
};
|
|
@@ -1674,6 +1789,10 @@ export function schreibeObjekte() {
|
|
|
1674
1789
|
schlecht += pruefeSchreiben(en).length;
|
|
1675
1790
|
});
|
|
1676
1791
|
if (schlecht) { return; }
|
|
1792
|
+
/* Dieselbe Bereinigung wie im Trockenlauf - diese Liste entsteht neu,
|
|
1793
|
+
und ohne den Griff hier schriebe `setObject` die leere Aufzaehlung
|
|
1794
|
+
parallel zum `delObject` wieder hin. */
|
|
1795
|
+
leereEigeneEnums(liste, S.loeschListe);
|
|
1677
1796
|
|
|
1678
1797
|
var body = $('#dry-body');
|
|
1679
1798
|
var offen = liste.length;
|
|
@@ -1754,9 +1873,32 @@ export function schreibeObjekte() {
|
|
|
1754
1873
|
stehen, bis man den Reiter neu lud, und behauptete damit eine
|
|
1755
1874
|
Abweichung, die es nicht mehr gibt. Nur bei Erfolg loeschen: ging
|
|
1756
1875
|
etwas schief, ist die Aenderung tatsaechlich noch nicht drin. */
|
|
1757
|
-
if (!fehler.length && S.entwurf
|
|
1758
|
-
S.entwurf.states
|
|
1876
|
+
if (!fehler.length && S.entwurf) {
|
|
1877
|
+
if (S.entwurf.states) {
|
|
1878
|
+
S.entwurf.states.forEach(function (s) { s.geaendert = false; rateBehalten(s); });
|
|
1879
|
+
}
|
|
1759
1880
|
S.entwurf.rateMeldung = null;
|
|
1881
|
+
/* Und dasselbe eine Ebene hoeher (G51, Ricardo, 15.09.2026).
|
|
1882
|
+
|
|
1883
|
+
`angefasst` sagt „hier steht etwas Ungeschriebenes". Die Marke
|
|
1884
|
+
wurde im ganzen Programm nur gesetzt, nie geloescht - weg war
|
|
1885
|
+
sie allein, wenn der Entwurf ganz wegfiel (Loeschen, Verlegen).
|
|
1886
|
+
Nach einem gelungenen Schreibvorgang blieb sie also stehen, und
|
|
1887
|
+
der naechste Klick im Baum fragte „Ungespeicherte Aenderungen …
|
|
1888
|
+
Wechselst du jetzt, sind sie weg" - ueber einen Alias, der
|
|
1889
|
+
gerade eben geschrieben worden war.
|
|
1890
|
+
|
|
1891
|
+
Die Marke faellt nur bei Erfolg. Ging etwas schief, ist die
|
|
1892
|
+
Aenderung tatsaechlich noch nicht drin, und die Frage ist dann
|
|
1893
|
+
berechtigt.
|
|
1894
|
+
|
|
1895
|
+
Sie hat eine zweite Aufgabe, und die erledigt sich mit: Solange
|
|
1896
|
+
`angefasst` steht, baut `neuZeichnenOderAufbauen` den Entwurf
|
|
1897
|
+
absichtlich NICHT neu auf - es soll ja nichts Ungeschriebenes
|
|
1898
|
+
ueberbuegeln. Das `holeZweig` unten laeuft gleich danach; jetzt
|
|
1899
|
+
baut es den Entwurf am frisch geschriebenen Alias neu auf,
|
|
1900
|
+
statt den alten stehenzulassen. */
|
|
1901
|
+
S.entwurf.angefasst = false;
|
|
1760
1902
|
}
|
|
1761
1903
|
|
|
1762
1904
|
/* Nur der Aliaszweig, nicht die ganze Datenbank. */
|
package/admin/js/sprache.js
CHANGED
|
@@ -56,7 +56,12 @@ export function ladeSprache(fertig) {
|
|
|
56
56
|
|
|
57
57
|
var beantwortet = false;
|
|
58
58
|
socket.emit('getObject', 'system.config', function (err, obj) {
|
|
59
|
-
if (beantwortet) { return; }
|
|
59
|
+
/* Hier stand `if (beantwortet) { return; }` - der Waechter aus der
|
|
60
|
+
Zeit vor dem Nachziehen. Er stieg genau im Fall aus, fuer den der
|
|
61
|
+
Zweig weiter unten gebaut wurde, und machte ihn zu totem Text
|
|
62
|
+
(gemessen 12.09.2026: mit `expertMode: true` am System und einer
|
|
63
|
+
um 4 s verzoegerten Antwort blieb `expertenVorgabe` auch nach
|
|
64
|
+
zehn Sekunden auf `false`). */
|
|
60
65
|
/* Auch eine spaete Antwort gilt noch.
|
|
61
66
|
|
|
62
67
|
Nach 2,5 Sekunden geht es ohne weiter — richtig, sonst haengt der
|