iobroker.alias-workbench 0.9.0 → 0.9.8
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/README.md +44 -5
- package/admin/geraetewissen/tasmota-befehle.json +3 -1
- package/admin/i18n/de.json +17 -6
- package/admin/i18n/en.json +17 -6
- package/admin/js/aufzaehlungen.js +11 -1
- package/admin/js/baum.js +90 -32
- package/admin/js/detail.js +18 -3
- package/admin/js/entwurf.js +176 -42
- package/admin/js/enums.js +50 -7
- package/admin/js/ergebnis.js +47 -10
- package/admin/js/katalog.js +12 -3
- package/admin/js/mqtt.js +76 -13
- package/admin/js/musterwahl.js +10 -0
- package/admin/js/objekte.js +29 -3
- package/admin/js/pruefungen.js +10 -2
- package/admin/js/quellentausch.js +31 -2
- package/admin/js/schreiben.js +209 -24
- package/admin/js/sprache.js +51 -7
- package/admin/js/start.js +32 -2
- package/admin/js/vorlagen.js +92 -4
- package/admin/js/vorlagenblatt.js +193 -23
- package/admin/js/werte.js +113 -6
- package/admin/js/zuordnung.js +30 -9
- package/admin/js/zustandsliste.js +14 -10
- package/admin/tab.html +17 -3
- package/admin/vorlagen/hm-dimmer.json +1 -1
- package/admin/vorlagen/hm-schaltaktor-lampe.json +2 -2
- package/admin/vorlagen/hm-schaltaktor-mehrfach.json +2 -2
- package/admin/vorlagen/hm-schaltaktor-steckdose.json +2 -2
- package/io-package.json +27 -1
- package/package.json +1 -1
package/admin/js/entwurf.js
CHANGED
|
@@ -8,7 +8,9 @@ import { $ } from './basis.js';
|
|
|
8
8
|
import { txt, tr } from './sprache.js';
|
|
9
9
|
import './enums.js';
|
|
10
10
|
import { zusatzName, setzeModus, zeichneBaum, merkeKlappstand } from './baum.js';
|
|
11
|
-
import { kindZustaende, aliasQuellen, holeWerte
|
|
11
|
+
import { kindZustaende, aliasQuellen, holeWerte,
|
|
12
|
+
mitVorspann, schreibQuelle
|
|
13
|
+
} from './werte.js';
|
|
12
14
|
import { erkenneEntwurf } from './erkennung.js';
|
|
13
15
|
import { vorschlag , pruefeVorlage, zeigeAbozahl } from './vorlagen.js';
|
|
14
16
|
|
|
@@ -101,11 +103,7 @@ export function baueEntwurf(kanal) {
|
|
|
101
103
|
alias.0.Badezimmer.Rollladen.CLOSE). Belegt ist das Schreiben
|
|
102
104
|
durch `common.write` oder durch eine vorhandene Schreibformel -
|
|
103
105
|
wer eine hinterlegt hat, wollte schreiben. */
|
|
104
|
-
srcW: istAlias
|
|
105
|
-
? (q.einfach
|
|
106
|
-
? ((c.write === true || typeof a.write === 'string') ? (q.write || '') : '')
|
|
107
|
-
: (q.write || ''))
|
|
108
|
-
: (c.write ? id : ''),
|
|
106
|
+
srcW: istAlias ? schreibQuelle(o) : (c.write ? id : ''),
|
|
109
107
|
f: (typeof a.read === 'string') ? a.read : '',
|
|
110
108
|
fw: (typeof a.write === 'string') ? a.write : '',
|
|
111
109
|
caption: istAlias ? txt(c.name) : kanalBeschriftung(kanal, kurzName),
|
|
@@ -132,8 +130,8 @@ export function baueEntwurf(kanal) {
|
|
|
132
130
|
entstanden ist - dieselbe Regel wie in `waehle`. Ohne sie durfte eine
|
|
133
131
|
spaeter angelegte Vorlage beim Umschalten auf die Alle-Ansicht das
|
|
134
132
|
fertige Geraet still uebernehmen (26.08.2026). */
|
|
135
|
-
export function alleUndVorlage(kanal, vorlagenId) {
|
|
136
|
-
var v = vorschlag(kanal, vorlagenId);
|
|
133
|
+
export function alleUndVorlage(kanal, vorlagenId, instanz) {
|
|
134
|
+
var v = vorschlag(kanal, vorlagenId, instanz);
|
|
137
135
|
var roh = baueEntwurf(kanal);
|
|
138
136
|
if (!v) { return roh; }
|
|
139
137
|
|
|
@@ -550,7 +548,14 @@ export function steuerKanaele(dev) {
|
|
|
550
548
|
var pflicht = f[0].states.filter(function (st) { return st.id; })
|
|
551
549
|
.map(function (st) { return st.id; });
|
|
552
550
|
if (!f[0].states.some(function (st) { return st.required && st.id; })) { return; }
|
|
553
|
-
|
|
551
|
+
/* `name` ist der Anzeigename und darf alles enthalten, was ein Mensch
|
|
552
|
+
hinschreibt. `kennung` ist, was als Objekt-ID taugt — dieselbe
|
|
553
|
+
Saeuberung wie ueberall sonst (T19). Getrennt, weil beides
|
|
554
|
+
gebraucht wird: die Liste zeigt den Namen, das Ziel nimmt die
|
|
555
|
+
Kennung. */
|
|
556
|
+
var kn = eigenerKanalName(id);
|
|
557
|
+
raus.push({ id: id, typ: f[0].type, name: kn || id.slice(pre.length),
|
|
558
|
+
kennung: kennungtauglich(kn || '') || id.slice(pre.length),
|
|
554
559
|
pflicht: pflicht });
|
|
555
560
|
});
|
|
556
561
|
kanalGeraeteCache[dev] = raus;
|
|
@@ -643,6 +648,20 @@ export function entwurfFuer(id, gemeinsam, gemAn) {
|
|
|
643
648
|
return merkeHakenVorgabe(e2);
|
|
644
649
|
}
|
|
645
650
|
|
|
651
|
+
/* Alle laufenden Abos abmelden.
|
|
652
|
+
|
|
653
|
+
Stand nur in `waehle` — und damit meldete kein einziger der Wege ab,
|
|
654
|
+
die die Auswahl fallen lassen: der Moduswechsel, das Zuklappen eines
|
|
655
|
+
Zweigs, das Abschalten des Expertenmodus, das Loeschen eines Alias.
|
|
656
|
+
Danach lief ein Abo auf ein Geraet, das rechts gar nicht mehr steht,
|
|
657
|
+
der Zaehler in der Kopfleiste behauptete „ein Abo", und `S.werte`
|
|
658
|
+
fuellte sich weiter (gemessen 09.09.2026). */
|
|
659
|
+
export function aboLoesen() {
|
|
660
|
+
(S.abo || []).forEach(function (m) { socket.emit('unsubscribe', m); });
|
|
661
|
+
S.abo = [];
|
|
662
|
+
zeigeAbozahl();
|
|
663
|
+
}
|
|
664
|
+
|
|
646
665
|
export function waehle(id, fertig) {
|
|
647
666
|
/* Wer links etwas anderes anklickt, will es rechts sehen - auch wenn
|
|
648
667
|
der Fokus noch in einem Feld der rechten Seite steht. `tipptGerade`
|
|
@@ -702,11 +721,98 @@ export function waehle(id, fertig) {
|
|
|
702
721
|
bekaeme mit der Zeit Ereignisse fuer das halbe System. Die Zahl der
|
|
703
722
|
laufenden Abos steht in der Kopfleiste - dort sieht man sofort, ob
|
|
704
723
|
sich etwas ansammelt. */
|
|
705
|
-
(
|
|
724
|
+
aboLoesen();
|
|
706
725
|
var muster = [id + '.*'];
|
|
707
726
|
if (id.indexOf('alias.') === 0) {
|
|
708
|
-
|
|
709
|
-
|
|
727
|
+
/* Aus den Quellen, nicht aus der Anzeige-Verteilung.
|
|
728
|
+
|
|
729
|
+
`quellenVerteilung` fasst zusammen, was die rechte Seite als
|
|
730
|
+
„Quellen" zeigt — dafuer bildet sie den ELTERNknoten jeder
|
|
731
|
+
Quelle. Bei einem flachen MQTT-Geraet ist das der halbe Adapter:
|
|
732
|
+
gemessen 09.09.2026 wurde daraus `mqtt-client.0.*` mit 322
|
|
733
|
+
Objekten, an einem einzigen Alias. Und `S.werte` wird nie
|
|
734
|
+
geleert, das sammelt sich also.
|
|
735
|
+
|
|
736
|
+
Abonniert wird deshalb der Kanal jeder wirklich gelesenen Quelle.
|
|
737
|
+
Wo die Quellen ohnehin gebuendelt liegen, bleibt es bei einem
|
|
738
|
+
Muster; wo nicht, sind es ein paar mehr — aber jedes davon eng. */
|
|
739
|
+
var kanaele = [];
|
|
740
|
+
kindZustaende(id).forEach(function (kid) {
|
|
741
|
+
var q = aliasQuellen(S.objects[kid]);
|
|
742
|
+
[q.read, q.write].forEach(function (x) {
|
|
743
|
+
if (!x) { return; }
|
|
744
|
+
var t = String(x).split('.');
|
|
745
|
+
t.pop();
|
|
746
|
+
var kn = t.join('.');
|
|
747
|
+
if (kn && kanaele.indexOf(kn) === -1) { kanaele.push(kn); }
|
|
748
|
+
});
|
|
749
|
+
});
|
|
750
|
+
/* Ein schmaler Kanal wird als Muster abonniert, ein breiter nicht.
|
|
751
|
+
|
|
752
|
+
Bei einem flachen Geraet IST der Kanal der breite Knoten: Die
|
|
753
|
+
Quelle `mqtt-client.0.SmartHome.Lavalampe_POWER` liegt direkt
|
|
754
|
+
unter `SmartHome`, und `SmartHome.*` sind 320 Objekte. Ab dieser
|
|
755
|
+
Schwelle werden die Quellen einzeln abonniert — ein paar Abos
|
|
756
|
+
mehr, dafuer genau die, deren Werte auch angezeigt werden. */
|
|
757
|
+
var SCHWELLE = 30;
|
|
758
|
+
var wieBreit = function (knoten) {
|
|
759
|
+
var n = 0;
|
|
760
|
+
S.keysSorted.forEach(function (k0) { if (k0.indexOf(knoten + '.') === 0) { n++; } });
|
|
761
|
+
return n;
|
|
762
|
+
};
|
|
763
|
+
var drinSchon = function (was) {
|
|
764
|
+
return muster.some(function (m0) {
|
|
765
|
+
var p0 = m0.slice(-2) === '.*' ? m0.slice(0, -2) : m0;
|
|
766
|
+
return was === p0 || was.indexOf(p0 + '.') === 0;
|
|
767
|
+
});
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
/* Sparten desselben Geraets zu einem Muster zusammenfassen.
|
|
771
|
+
|
|
772
|
+
Ein Tasmota-Alias liest aus `…Licht.stat`, `…Licht.tele` und
|
|
773
|
+
`…Licht.cmnd` — drei Kanaele, ein Geraet, und in der Kopfleiste
|
|
774
|
+
gehoert dort „ein Abo" zu stehen, nicht drei. Zusammengefasst wird
|
|
775
|
+
aber nur, wo wirklich MEHRERE Kanaele unter demselben Knoten
|
|
776
|
+
haengen: Sonst waere aus `…Garten.Weihnachten_aussen` schlicht
|
|
777
|
+
`…Garten` geworden — breiter als noetig, ohne dass etwas
|
|
778
|
+
zusammenfaellt. */
|
|
779
|
+
for (var runde = 0; runde < 4; runde++) {
|
|
780
|
+
var unter = {};
|
|
781
|
+
kanaele.forEach(function (kn) {
|
|
782
|
+
var t = kn.split('.');
|
|
783
|
+
if (t.length <= 3) { return; }
|
|
784
|
+
var ob = t.slice(0, -1).join('.');
|
|
785
|
+
(unter[ob] = unter[ob] || []).push(kn);
|
|
786
|
+
});
|
|
787
|
+
var geaendert = false;
|
|
788
|
+
Object.keys(unter).forEach(function (ob) {
|
|
789
|
+
if (unter[ob].length < 2 || wieBreit(ob) > SCHWELLE) { return; }
|
|
790
|
+
kanaele = kanaele.filter(function (kn) { return unter[ob].indexOf(kn) === -1; });
|
|
791
|
+
if (kanaele.indexOf(ob) === -1) { kanaele.push(ob); }
|
|
792
|
+
geaendert = true;
|
|
793
|
+
});
|
|
794
|
+
if (!geaendert) { break; }
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/* Ein schmaler Kanal wird als Muster abonniert, ein breiter nicht.
|
|
798
|
+
|
|
799
|
+
Bei einem flachen Geraet IST der Kanal der breite Knoten: Die
|
|
800
|
+
Quelle `mqtt-client.0.SmartHome.Lavalampe_POWER` liegt direkt
|
|
801
|
+
unter `SmartHome`, und `SmartHome.*` sind 320 Objekte (gemessen
|
|
802
|
+
09.09.2026; vorher wurde daraus sogar `mqtt-client.0.*` mit 322).
|
|
803
|
+
Ab dieser Schwelle werden die Quellen einzeln abonniert — ein paar
|
|
804
|
+
Abos mehr, dafuer genau die, deren Werte auch angezeigt werden. */
|
|
805
|
+
kanaele.forEach(function (kn) {
|
|
806
|
+
if (drinSchon(kn)) { return; }
|
|
807
|
+
if (wieBreit(kn) > SCHWELLE) { return; }
|
|
808
|
+
muster.push(kn + '.*');
|
|
809
|
+
});
|
|
810
|
+
/* Was jetzt noch von keinem Muster gedeckt ist, kommt einzeln. */
|
|
811
|
+
kindZustaende(id).forEach(function (kid) {
|
|
812
|
+
var q = aliasQuellen(S.objects[kid]);
|
|
813
|
+
[q.read, q.write].forEach(function (x) {
|
|
814
|
+
if (x && !drinSchon(x) && muster.indexOf(x) === -1) { muster.push(x); }
|
|
815
|
+
});
|
|
710
816
|
});
|
|
711
817
|
}
|
|
712
818
|
S.abo = muster;
|
|
@@ -736,7 +842,17 @@ export function waehle(id, fertig) {
|
|
|
736
842
|
var werteDa = false;
|
|
737
843
|
holeWerte(id, quellen, function () {
|
|
738
844
|
werteDa = true;
|
|
739
|
-
if (id !== S.current) {
|
|
845
|
+
if (id !== S.current) {
|
|
846
|
+
/* Der Knoten hat gewechselt, waehrend die Werte unterwegs waren.
|
|
847
|
+
Am Entwurf ist hier nichts mehr zu tun — der Rueckruf muss aber
|
|
848
|
+
trotzdem kommen. Sonst bleibt `so59Laeuft` oder `abfrageLaeuft`
|
|
849
|
+
fuer immer gesetzt (der Knopf steht dauerhaft auf „laeuft"), und
|
|
850
|
+
der Trockenlauf nach dem Anlegen fehlender Sendepunkte geht nie
|
|
851
|
+
auf. Zwoelf Sekunden Wartezeit bei einer SetOption59-Abfrage
|
|
852
|
+
sind reichlich Gelegenheit dafuer (09.09.2026). */
|
|
853
|
+
if (typeof fertig === 'function') { fertig(); }
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
740
856
|
|
|
741
857
|
/* Wer schon Hand angelegt hat, behaelt seinen Entwurf.
|
|
742
858
|
|
|
@@ -948,13 +1064,40 @@ export function geraeteDarunter(wurzel) {
|
|
|
948
1064
|
angelegt" und erzeugt beim Klick ein zweites Geraet, waehrend das
|
|
949
1065
|
erste verwaist stehenbleibt. Beim Karbonator lag der Alias unter
|
|
950
1066
|
alias.0.Strom, vorgeschlagen wurde alias.0.SmartHome. */
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1067
|
+
/* Rueckwaertskarte Quelle -> Alias, einmal je Indexstand.
|
|
1068
|
+
|
|
1069
|
+
`aliasFuer` lief zweimal ueber alle Kennungen — und wird je
|
|
1070
|
+
Neuzeichnen mehrfach gerufen. Die Karte entsteht bei der ersten Frage
|
|
1071
|
+
nach einem Indexwechsel und beantwortet alle weiteren aus dem
|
|
1072
|
+
Gedaechtnis. Erkannt wird der Wechsel an Laenge und erster Kennung;
|
|
1073
|
+
`indexNeu()` sortiert ohnehin bei jeder Aenderung neu. */
|
|
1074
|
+
var alsQuelleKarte = null, alsQuelleStand = '';
|
|
1075
|
+
function alsQuelleKarten() {
|
|
1076
|
+
var stand = S.keysSorted.length + '|' + (S.keysSorted[0] || '');
|
|
1077
|
+
if (alsQuelleKarte && alsQuelleStand === stand) { return alsQuelleKarte; }
|
|
1078
|
+
var fest = {}, zweig = {};
|
|
1079
|
+
mitVorspann('alias.').forEach(function (id) {
|
|
955
1080
|
var o = S.objects[id];
|
|
956
|
-
if (o
|
|
1081
|
+
if (!o) { return; }
|
|
1082
|
+
if (o.native && o.native.quelle && fest[o.native.quelle] === undefined) {
|
|
1083
|
+
fest[o.native.quelle] = id;
|
|
1084
|
+
}
|
|
1085
|
+
if (o.type !== 'state') { return; }
|
|
1086
|
+
var q = aliasQuellen(o);
|
|
1087
|
+
[q.read, q.write].forEach(function (x) {
|
|
1088
|
+
if (!x) { return; }
|
|
1089
|
+
var kanal = id.split('.').slice(0, -1).join('.');
|
|
1090
|
+
(zweig[x] = zweig[x] || []).push(kanal);
|
|
1091
|
+
});
|
|
957
1092
|
});
|
|
1093
|
+
alsQuelleKarte = { fest: fest, zweig: zweig };
|
|
1094
|
+
alsQuelleStand = stand;
|
|
1095
|
+
return alsQuelleKarte;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
export function aliasFuer(quelle) {
|
|
1099
|
+
var karte = alsQuelleKarten();
|
|
1100
|
+
var treffer = karte.fest[quelle] || null;
|
|
958
1101
|
if (treffer) { return treffer; }
|
|
959
1102
|
|
|
960
1103
|
/* Welcher Aliaskanal liest oder schreibt am haeufigsten in diesen
|
|
@@ -963,17 +1106,19 @@ export function aliasFuer(quelle) {
|
|
|
963
1106
|
erste Treffer. */
|
|
964
1107
|
var zaehler = {}, bester = null, wieviel = 0;
|
|
965
1108
|
var pre = quelle + '.';
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
if (
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1109
|
+
/* Aus der Karte: welche Aliaskanaele lesen oder schreiben in diesen
|
|
1110
|
+
Zweig? Die Quellen stehen dort als volle Kennung, gesucht ist alles
|
|
1111
|
+
darunter — also die Kennungen des Zweigs abklappern statt aller
|
|
1112
|
+
Aliase. */
|
|
1113
|
+
var karte2 = alsQuelleKarten();
|
|
1114
|
+
var kanaele = [];
|
|
1115
|
+
Object.keys(karte2.zweig).forEach(function (q0) {
|
|
1116
|
+
if (q0.indexOf(pre) !== 0) { return; }
|
|
1117
|
+
karte2.zweig[q0].forEach(function (kanal) { kanaele.push(kanal); });
|
|
1118
|
+
});
|
|
1119
|
+
kanaele.forEach(function (kanal) {
|
|
1120
|
+
zaehler[kanal] = (zaehler[kanal] || 0) + 1;
|
|
1121
|
+
if (zaehler[kanal] > wieviel) { wieviel = zaehler[kanal]; bester = kanal; }
|
|
977
1122
|
});
|
|
978
1123
|
return bester;
|
|
979
1124
|
}
|
|
@@ -1033,9 +1178,7 @@ export function bestandVorrang(e, aliasId) {
|
|
|
1033
1178
|
s.f = (typeof a.read === 'string') ? a.read : '';
|
|
1034
1179
|
s.fw = (typeof a.write === 'string') ? a.write : '';
|
|
1035
1180
|
if (q.read) { s.srcR = q.read; }
|
|
1036
|
-
s.srcW =
|
|
1037
|
-
? ((c.write === true || typeof a.write === 'string') ? (q.write || '') : '')
|
|
1038
|
-
: (q.write || '');
|
|
1181
|
+
s.srcW = schreibQuelle(o);
|
|
1039
1182
|
s.on = true;
|
|
1040
1183
|
s.ausBestand = true;
|
|
1041
1184
|
});
|
|
@@ -1072,9 +1215,7 @@ export function bestandsAbweichung(s, aliasId) {
|
|
|
1072
1215
|
f: (typeof a.read === 'string') ? a.read : '',
|
|
1073
1216
|
fw: (typeof a.write === 'string') ? a.write : '',
|
|
1074
1217
|
srcR: q.read || '',
|
|
1075
|
-
srcW:
|
|
1076
|
-
? ((c.write === true || typeof a.write === 'string') ? (q.write || '') : '')
|
|
1077
|
-
: (q.write || '')
|
|
1218
|
+
srcW: schreibQuelle(o)
|
|
1078
1219
|
};
|
|
1079
1220
|
var raus = [];
|
|
1080
1221
|
['role', 'typ', 'unit', 'f', 'fw', 'srcR', 'srcW'].forEach(function (k) {
|
|
@@ -1084,13 +1225,6 @@ export function bestandsAbweichung(s, aliasId) {
|
|
|
1084
1225
|
return raus;
|
|
1085
1226
|
}
|
|
1086
1227
|
|
|
1087
|
-
/* Einen einzelnen Wert aus dem gespeicherten Alias zurueckholen. */
|
|
1088
|
-
export function bestandsWert(s, aliasId, feld) {
|
|
1089
|
-
var abw = bestandsAbweichung(s, aliasId);
|
|
1090
|
-
var tr0 = null;
|
|
1091
|
-
abw.forEach(function (x) { if (x.feld === feld) { tr0 = x; } });
|
|
1092
|
-
return tr0 ? tr0.bestand : null;
|
|
1093
|
-
}
|
|
1094
1228
|
|
|
1095
1229
|
/* Wo weicht die Vorlage vom Bestand ab? Liefert je Zeile die Felder, die
|
|
1096
1230
|
„Vorlage anwenden" aendern wuerde - die Beschriftung ausgenommen. */
|
package/admin/js/enums.js
CHANGED
|
@@ -9,15 +9,58 @@ import { socket } from './verbindung.js';
|
|
|
9
9
|
suchen haben. */
|
|
10
10
|
export var enums = {};
|
|
11
11
|
|
|
12
|
+
/* Wissen wir gerade, was in den Aufzaehlungen steht?
|
|
13
|
+
|
|
14
|
+
Das ist keine Feinheit, sondern die Bedingung dafuer, ueberhaupt eine
|
|
15
|
+
schreiben zu duerfen. Frueher setzte ein Ladefehler `enums` auf `{}`
|
|
16
|
+
und verschwieg es. Danach hielt die Werkbank jede Aufzaehlung fuer
|
|
17
|
+
nicht vorhanden - der Katalog bot `garden` weiter an, weil der
|
|
18
|
+
Dublettenfilter gegen nichts pruefte, und `enumAenderungen` baute sie
|
|
19
|
+
als NEU aus der Vorlage. `setObject` ersetzt ein Objekt vollstaendig:
|
|
20
|
+
Gemessen 09.09.2026 am Testsystem verlor `enum.rooms.garden` dabei
|
|
21
|
+
drei Mitglieder und behielt eines, dazu die Herkunftsmarke, die ihn
|
|
22
|
+
spaeter auch noch loeschbar macht. Bei Ricardo waeren das die aus der
|
|
23
|
+
CCU gespiegelten Raeume.
|
|
24
|
+
|
|
25
|
+
Solange diese Marke steht, wird keine Aufzaehlung angefasst. */
|
|
26
|
+
var unbekannt = false;
|
|
27
|
+
export function enumsUnbekannt() { return unbekannt; }
|
|
28
|
+
|
|
29
|
+
/* Ein Aussetzer soll die Werkbank nicht fuer den Rest der Sitzung
|
|
30
|
+
lahmlegen. Dreimal mit wachsendem Abstand, dann ist Schluss - eine
|
|
31
|
+
Schleife ohne Ende waere schlimmer als der Fehler. */
|
|
32
|
+
var versuch = 0;
|
|
33
|
+
var wiederTimer = null;
|
|
34
|
+
|
|
12
35
|
export function ladeEnums(danach) {
|
|
36
|
+
if (wiederTimer) { clearTimeout(wiederTimer); wiederTimer = null; }
|
|
13
37
|
socket.emit('getObjectView', 'system', 'enum',
|
|
14
|
-
{ startkey: 'enum.', endkey: 'enum
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
38
|
+
{ startkey: 'enum.', endkey: 'enum.香' }, function (err, doc) {
|
|
39
|
+
if (err || !doc || !doc.rows) {
|
|
40
|
+
/* Den alten Stand behalten. Er ist vielleicht veraltet, aber
|
|
41
|
+
veraltet ist naeher an der Wahrheit als leer. */
|
|
42
|
+
unbekannt = true;
|
|
43
|
+
console.warn('[alias-workbench] Aufzaehlungen nicht geladen: ' +
|
|
44
|
+
(err || 'keine Antwort'));
|
|
45
|
+
if (versuch < 3) {
|
|
46
|
+
versuch++;
|
|
47
|
+
wiederTimer = setTimeout(function () {
|
|
48
|
+
wiederTimer = null;
|
|
49
|
+
ladeEnums();
|
|
50
|
+
}, versuch * 4000);
|
|
51
|
+
}
|
|
52
|
+
if (typeof danach === 'function') { danach(err || 'leer'); }
|
|
53
|
+
return;
|
|
20
54
|
}
|
|
21
|
-
|
|
55
|
+
/* Erst sammeln, dann tauschen: ein Fehler mittendrin liesse sonst
|
|
56
|
+
einen halben Vorrat stehen. */
|
|
57
|
+
var frisch = {};
|
|
58
|
+
doc.rows.forEach(function (r) {
|
|
59
|
+
if (r.value && r.id) { frisch[r.id] = r.value; }
|
|
60
|
+
});
|
|
61
|
+
enums = frisch;
|
|
62
|
+
unbekannt = false;
|
|
63
|
+
versuch = 0;
|
|
64
|
+
if (typeof danach === 'function') { danach(null); }
|
|
22
65
|
});
|
|
23
66
|
}
|
package/admin/js/ergebnis.js
CHANGED
|
@@ -79,6 +79,14 @@ var warumAuf = false;
|
|
|
79
79
|
var werteTimer = null;
|
|
80
80
|
function werteGezeichnet() {
|
|
81
81
|
werteTimer = null;
|
|
82
|
+
/* Im Vorlagenmodus steht rechts das Vorlagenblatt, nicht die
|
|
83
|
+
Zustandsliste — ein eintreffender Wert hat dort nichts zu melden.
|
|
84
|
+
`setzeModus('vorlagen')` laesst `S.current` ausdruecklich stehen,
|
|
85
|
+
damit man seine Auswahl beim Zurueckwechseln wiederfindet; ohne
|
|
86
|
+
diese Zeile baute jeder Takt eines Solarzaehlers das ganze Blatt
|
|
87
|
+
neu, samt `probelauf` ueber alle Kandidaten und alle Vorlagen
|
|
88
|
+
(gemessen 09.09.2026: vier Werte, vier Neuaufbauten). */
|
|
89
|
+
if (S.baumModus === 'vorlagen') { return; }
|
|
82
90
|
if (document.querySelector('dialog[open]')) { return; }
|
|
83
91
|
if (tipptGerade()) { werteTimer = setTimeout(werteGezeichnet, 700); return; }
|
|
84
92
|
if (S.current) { zeichneErgebnis(); }
|
|
@@ -394,15 +402,29 @@ var warumAuf = false;
|
|
|
394
402
|
|
|
395
403
|
`mousedown` statt `click`, wie bei den Vorschlagslisten der
|
|
396
404
|
Zielleiste: der Mausdruck kommt vor dem Neuzeichnen. */
|
|
405
|
+
/* Gefragt wird das Dokument, nicht die Erinnerung.
|
|
406
|
+
|
|
407
|
+
Die Liste haengt am `body`, damit sie ein automatisches
|
|
408
|
+
Neuzeichnen ueberlebt. Der Knopf aber ist danach ein anderer,
|
|
409
|
+
und mit ihm diese Merkstelle: sie stand wieder auf „keine",
|
|
410
|
+
waehrend die alte Liste weiter am Body hing. Der zweite Klick
|
|
411
|
+
legte eine zweite Liste ueber die erste, und der Zuhoerer am
|
|
412
|
+
Body raeumte nicht auf, weil der Knopf das Ereignis abfaengt
|
|
413
|
+
(gemessen 09.09.2026). */
|
|
414
|
+
var offeneListe = function () { return document.querySelector('.sprungliste'); };
|
|
397
415
|
var listeQ = null;
|
|
398
416
|
var zuQ = function () {
|
|
399
|
-
|
|
417
|
+
var da = offeneListe();
|
|
418
|
+
while (da) {
|
|
419
|
+
if (da.parentNode) { da.parentNode.removeChild(da); }
|
|
420
|
+
da = offeneListe();
|
|
421
|
+
}
|
|
400
422
|
listeQ = null;
|
|
401
423
|
};
|
|
402
424
|
sprung.addEventListener('mousedown', function (ev) {
|
|
403
425
|
ev.preventDefault();
|
|
404
426
|
ev.stopPropagation();
|
|
405
|
-
if (
|
|
427
|
+
if (offeneListe()) { zuQ(); return; }
|
|
406
428
|
listeQ = el('div', 'vorschlaege sprungliste');
|
|
407
429
|
listeQ.appendChild(el('div', 'vzkopf', tr('result.pickSource')));
|
|
408
430
|
verteilung.forEach(function (q) {
|
|
@@ -665,8 +687,20 @@ var warumAuf = false;
|
|
|
665
687
|
var gid = S.objects[vorh].native.vorlage;
|
|
666
688
|
if (S.VORLAGEN.some(function (x) { return x.id === gid; })) { fest = gid; }
|
|
667
689
|
}
|
|
668
|
-
|
|
669
|
-
|
|
690
|
+
/* Ausgang und Handwahl gehoeren mit.
|
|
691
|
+
|
|
692
|
+
Ohne die Instanz kamen an einer Mehrfachvorlage die Zeilen von
|
|
693
|
+
Ausgang 1 zurueck, waehrend das Ziel weiter `…Ausgang_2` hiess.
|
|
694
|
+
Und `fest` allein reicht nicht: Es ist nur gesetzt, wenn schon
|
|
695
|
+
ein Alias mit Vorlage dasteht. Hatte die Automatik nichts
|
|
696
|
+
gefunden und man die Vorlage von Hand gewaehlt, suchte der
|
|
697
|
+
Neuaufbau wieder automatisch, fand nichts — und man landete im
|
|
698
|
+
Rohmodus, die Handwahl weg (gemessen 09.09.2026). Der
|
|
699
|
+
Ausgangswechsel eine Stelle weiter oben macht es laengst
|
|
700
|
+
richtig. */
|
|
701
|
+
var vid = fest || e.vorlage || null;
|
|
702
|
+
var neuE = rohJetzt ? alleUndVorlage(S.current, vid, e.instanz)
|
|
703
|
+
: vorschlag(S.current, vid, e.instanz);
|
|
670
704
|
if (!neuE) { return; }
|
|
671
705
|
neuE.roh = rohJetzt;
|
|
672
706
|
neuE.vorschlag = true;
|
|
@@ -721,8 +755,11 @@ var warumAuf = false;
|
|
|
721
755
|
der langen Erklaerung. Sie ist weg: dieselbe Auskunft haengt jetzt
|
|
722
756
|
am Hinweis der Legende, und die steht dort, wo die getoenten Zeilen
|
|
723
757
|
stehen. Zweimal dasselbe, einmal oben und einmal ganz unten, war
|
|
724
|
-
eine zu viel (Ricardo, 08.09.2026).
|
|
725
|
-
|
|
758
|
+
eine zu viel (Ricardo, 08.09.2026). Der Text `info.explain` bleibt in
|
|
759
|
+
Gebrauch — die Legende nutzt ihn. `info.notPartOf` dagegen rief nach
|
|
760
|
+
dem Umbau niemand mehr; dieser Satz behauptete das Gegenteil, und
|
|
761
|
+
der Schluessel stand noch ein Jahr in beiden Sprachdateien, weil der
|
|
762
|
+
Test nur die Richtung Code → JSON prueft (09.09.2026 entfernt). */
|
|
726
763
|
|
|
727
764
|
/* Was sich gegenueber dem gespeicherten Stand aendern wuerde. */
|
|
728
765
|
function baueDiffKarte(host, e) {
|
|
@@ -754,7 +791,7 @@ var warumAuf = false;
|
|
|
754
791
|
|
|
755
792
|
/* Pruefungen, Fusszeile und die Knopfleiste unten - beschriftet
|
|
756
793
|
nach dem, was der Klick tatsaechlich tut. */
|
|
757
|
-
function setzeKnoepfe(e, haupt, pflichtFehlt
|
|
794
|
+
function setzeKnoepfe(e, haupt, pflichtFehlt) {
|
|
758
795
|
baueChecks(e, haupt, pflichtFehlt);
|
|
759
796
|
|
|
760
797
|
/* Der Knopf soll sagen, was er tut — nicht, wie er es tut. */
|
|
@@ -885,19 +922,19 @@ var warumAuf = false;
|
|
|
885
922
|
}
|
|
886
923
|
|
|
887
924
|
var pl = berechnePlaetze(e, haupt);
|
|
888
|
-
|
|
925
|
+
|
|
889
926
|
|
|
890
927
|
baueListe(host, e, pl, rateKnopf, musterBlock);
|
|
891
928
|
rateKnopf = null;
|
|
892
929
|
musterBlock = null;
|
|
893
930
|
|
|
894
|
-
|
|
931
|
+
|
|
895
932
|
|
|
896
933
|
/* --- Änderungen gegenüber dem, was gespeichert ist --- */
|
|
897
934
|
baueDiffKarte(host, e);
|
|
898
935
|
|
|
899
936
|
/* --- Prüfungen, Fusszeile, Knopfleiste --- */
|
|
900
|
-
setzeKnoepfe(e, haupt, pflichtFehlt
|
|
937
|
+
setzeKnoepfe(e, haupt, pflichtFehlt);
|
|
901
938
|
}
|
|
902
939
|
|
|
903
940
|
/* Uebersicht ueber alle Geraete unterhalb eines Ordners. */
|
package/admin/js/katalog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { holeText } from './basis.js';
|
|
2
|
-
import { txt } from './sprache.js';
|
|
2
|
+
import { txt, alleTexte } from './sprache.js';
|
|
3
3
|
import { einst } from './einstellungen.js';
|
|
4
4
|
import './enums.js';
|
|
5
5
|
|
|
@@ -304,10 +304,19 @@ export function vorlageZu(id, art, name) {
|
|
|
304
304
|
var v = null;
|
|
305
305
|
liste.forEach(function (x) { if (!v && x._id === kurz) { v = x; } });
|
|
306
306
|
if (v) { return v; }
|
|
307
|
-
var n = String(name || '').toLowerCase();
|
|
307
|
+
var n = String(name || '').trim().toLowerCase();
|
|
308
308
|
if (!n) { return null; }
|
|
309
|
+
/* Alle Sprachfassungen, nicht nur die eingestellte.
|
|
310
|
+
|
|
311
|
+
Im Bestand steht, was jemand getippt hat — „Light" etwa, waehrend
|
|
312
|
+
die Vorlage auf einem deutschen Admin „Licht" heisst. Verglichen
|
|
313
|
+
wurde aber nur die eine Fassung, und ohne Treffer entsteht beim
|
|
314
|
+
naechsten Schreiben ein Doppelgaenger `enum.functions.light` neben
|
|
315
|
+
der vorhandenen Funktion (gefunden 09.09.2026). Der Vergleich war
|
|
316
|
+
schon immer unabhaengig von Gross- und Kleinschreibung; was fehlte,
|
|
317
|
+
waren die anderen Sprachen. */
|
|
309
318
|
liste.forEach(function (x) {
|
|
310
|
-
if (!v &&
|
|
319
|
+
if (!v && alleTexte(x.name).indexOf(n) !== -1) { v = x; }
|
|
311
320
|
});
|
|
312
321
|
return v;
|
|
313
322
|
}
|