iobroker.alias-workbench 0.8.0
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 +21 -0
- package/README.md +516 -0
- package/admin/alias-workbench.png +0 -0
- package/admin/css/werkbank.css +916 -0
- package/admin/detector.js +1 -0
- package/admin/geraetewissen/tasmota-befehle.json +116 -0
- package/admin/i18n/de.json +552 -0
- package/admin/i18n/en.json +552 -0
- package/admin/js/aufzaehlungen.js +332 -0
- package/admin/js/basis.js +36 -0
- package/admin/js/baum.js +453 -0
- package/admin/js/detail.js +335 -0
- package/admin/js/einstellungen.js +40 -0
- package/admin/js/entwurf.js +908 -0
- package/admin/js/enums.js +23 -0
- package/admin/js/ergebnis.js +934 -0
- package/admin/js/erkennung.js +126 -0
- package/admin/js/katalog.js +313 -0
- package/admin/js/mqtt.js +885 -0
- package/admin/js/musternamen.js +94 -0
- package/admin/js/musterwahl.js +334 -0
- package/admin/js/objekte.js +243 -0
- package/admin/js/pruefungen.js +130 -0
- package/admin/js/quellentausch.js +570 -0
- package/admin/js/rollenwahl.js +199 -0
- package/admin/js/schreiben.js +1537 -0
- package/admin/js/sprache.js +137 -0
- package/admin/js/start.js +39 -0
- package/admin/js/verbindung.js +10 -0
- package/admin/js/vorlagen.js +572 -0
- package/admin/js/vorlagenblatt.js +1907 -0
- package/admin/js/vorschlagen.js +391 -0
- package/admin/js/werte.js +193 -0
- package/admin/js/zielleiste.js +339 -0
- package/admin/js/zuordnung.js +695 -0
- package/admin/js/zustand.js +47 -0
- package/admin/js/zustandsliste.js +515 -0
- package/admin/jsonConfig.json +249 -0
- package/admin/tab.html +148 -0
- package/admin/vorlagen/hm-dimmer.json +204 -0
- package/admin/vorlagen/hm-fensterkontakt-hm.json +176 -0
- package/admin/vorlagen/hm-fensterkontakt-hmip.json +191 -0
- package/admin/vorlagen/hm-heizgruppe.json +214 -0
- package/admin/vorlagen/hm-heizkoerper.json +236 -0
- package/admin/vorlagen/hm-rollladen.json +190 -0
- package/admin/vorlagen/hm-schaltaktor-lampe.json +197 -0
- package/admin/vorlagen/hm-schaltaktor-mehrfach.json +203 -0
- package/admin/vorlagen/hm-schaltaktor-steckdose.json +197 -0
- package/admin/vorlagen/hm-temperatur-feuchte.json +166 -0
- package/admin/vorlagen/hm-wandthermostat.json +228 -0
- package/admin/vorlagen/index.json +21 -0
- package/admin/vorlagen/messpunkt.json +225 -0
- package/admin/vorlagen/tasmota-lampe.json +263 -0
- package/admin/vorlagen/tasmota-mehrfach.json +203 -0
- package/admin/vorlagen/tasmota-rgb.json +239 -0
- package/admin/vorlagen/tasmota-steckdose.json +265 -0
- package/io-package.json +122 -0
- package/package.json +48 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/* Raum und Funktion als Fachlichkeit: Listen, Zuordnung, Vorschlag.
|
|
2
|
+
|
|
3
|
+
Die Oberflaeche dazu (Felder, Angebote) liegt beim Ergebnis - hier nur,
|
|
4
|
+
was aus Bestand und Katalog folgt. */
|
|
5
|
+
|
|
6
|
+
import { S } from './zustand.js';
|
|
7
|
+
import { txt } from './sprache.js';
|
|
8
|
+
import { enums } from './enums.js';
|
|
9
|
+
import { enumVorlagen, ikonCache, vorlageZu } from './katalog.js';
|
|
10
|
+
import { zusatzName } from './baum.js';
|
|
11
|
+
import { aliasFuer, quelleVon } from './entwurf.js';
|
|
12
|
+
|
|
13
|
+
/* Eine Aufzaehlung, die es noch nicht gibt.
|
|
14
|
+
|
|
15
|
+
Steht sie im Vorlagenkatalog, uebernehmen wir den mehrsprachigen Namen
|
|
16
|
+
und das Icon - dann sieht sie hinterher aus wie eine im Admin
|
|
17
|
+
angelegte, nicht wie ein Fremdkoerper. Sonst bleibt der eingetippte
|
|
18
|
+
Name allein. */
|
|
19
|
+
export function neueEnum(id, art) {
|
|
20
|
+
var kurz = id.slice(('enum.' + art + '.').length);
|
|
21
|
+
var v = null;
|
|
22
|
+
(enumVorlagen[art] || []).forEach(function (x) { if (x._id === kurz) { v = x; } });
|
|
23
|
+
var c = { name: v ? JSON.parse(JSON.stringify(v.name)) : kurz };
|
|
24
|
+
var ik = (v && v.icon) ? ikonCache[art + ':' + v.icon] : null;
|
|
25
|
+
if (ik) { c.icon = ik; }
|
|
26
|
+
/* Die Herkunftsmarke erlaubt dem Loeschweg, eine selbst angelegte
|
|
27
|
+
Aufzaehlung wieder mitzunehmen, wenn ihr letztes Mitglied faellt.
|
|
28
|
+
Ohne Marke blieb `enum.functions.socket` als leere Huelle stehen
|
|
29
|
+
(25.08.2026 am Produktivsystem gefunden). Fremde und vorbestehende
|
|
30
|
+
Aufzaehlungen tragen sie nicht und bleiben darum unangetastet. */
|
|
31
|
+
return { type: 'enum', common: c, native: { angelegtVon: 'alias-workbench' } };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Alle Aufzaehlungen einer Art, benutzte zuerst.
|
|
35
|
+
|
|
36
|
+
Die Reihenfolge ist kein Schmuck: ioBroker legt bei der Erstinstallation
|
|
37
|
+
leere englische Raeume an (`bathroom`, `bedroom` …), deren deutscher Name
|
|
38
|
+
genau so lautet wie der eines benutzten Raums. Ricardo hat „Badezimmer"
|
|
39
|
+
zweimal - einmal mit fuenf Mitgliedern, einmal leer. Wer nur Namen zeigt,
|
|
40
|
+
schickt den Nutzer ins Leere. Deshalb steht die Kennung mit dabei, und
|
|
41
|
+
was schon benutzt wird, kommt zuerst. */
|
|
42
|
+
export function enumListe(art, nurBestand) {
|
|
43
|
+
var pre = 'enum.' + art + '.';
|
|
44
|
+
/* `autocreate` haelt der ping-Adapter als Sammelbecken mit hunderten
|
|
45
|
+
Mitgliedern - als Ablageort taugt es nie und stand durch die
|
|
46
|
+
Benutzt-zuerst-Sortierung ganz oben. Es faellt aus der Liste;
|
|
47
|
+
wer es wirklich am Geraet hat, sieht es weiter im Feld stehen. */
|
|
48
|
+
var raus = Object.keys(enums).filter(function (k) {
|
|
49
|
+
return k.indexOf(pre) === 0 && k.slice(pre.length) !== 'autocreate';
|
|
50
|
+
})
|
|
51
|
+
.map(function (k) {
|
|
52
|
+
var c = enums[k].common || {};
|
|
53
|
+
return { id: k, kurz: k.slice(pre.length), name: txt(c.name) || k.slice(pre.length),
|
|
54
|
+
anzahl: (c.members || []).length };
|
|
55
|
+
})
|
|
56
|
+
.sort(function (a, b) {
|
|
57
|
+
return (b.anzahl > 0) - (a.anzahl > 0) || a.name.localeCompare(b.name);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
/* Fuer den Vorschlag ist hier Schluss.
|
|
61
|
+
|
|
62
|
+
Ein Vorschlag darf nur auf Vorhandenes zeigen. Sonst legt die
|
|
63
|
+
Werkbank ungefragt Aufzaehlungen an: `Weihnachten_aussen` liegt im
|
|
64
|
+
Pfad unter „Garten", es gibt eine Vorlage dieses Namens - und schon
|
|
65
|
+
stand `enum.rooms.garden` als Vorschlag im Feld, obwohl Ricardo
|
|
66
|
+
keinen Raum „Garten" fuehrt. Wer dann nur noch auf Anlegen drueckt,
|
|
67
|
+
bekommt einen Raum, den er nie gewaehlt hat. Gefunden im Test zu
|
|
68
|
+
0.0.78, nachdem der Vorschlag dieselbe Liste benutzte wie die
|
|
69
|
+
Auswahl. */
|
|
70
|
+
if (nurBestand) { return raus; }
|
|
71
|
+
|
|
72
|
+
/* Hinter dem Bestand steht, was der Admin anbietet und es hier noch
|
|
73
|
+
nicht gibt: Rollladen, Steckdose, Waschmaschine. Sie stehen hinten,
|
|
74
|
+
weil das Vorhandene naeher liegt - wer eine Vorlage sucht, tippt.
|
|
75
|
+
|
|
76
|
+
Gleicher Name, andere Kennung ist die Falle: der Admin legt beim
|
|
77
|
+
Klick auf HEIZUNG ein `enum.functions.heating` an, waehrend die
|
|
78
|
+
Geraete in `enum.functions.Heizung` haengen. Solche Doppelgaenger
|
|
79
|
+
kommen gar nicht erst in die Liste - wer sie anlegte, bekam zwei
|
|
80
|
+
gleichnamige Aufzaehlungen und sah nie, warum die eine leer bleibt.
|
|
81
|
+
(Vorher stand nur ein Warnvermerk dran; Ricardos Befund 25.08.2026:
|
|
82
|
+
„gibt es schon und neu anlegen wird angezeigt".) */
|
|
83
|
+
var da = {}, nachName = {};
|
|
84
|
+
raus.forEach(function (x) {
|
|
85
|
+
da[x.id] = true;
|
|
86
|
+
nachName[x.name.toLowerCase()] = x.id;
|
|
87
|
+
});
|
|
88
|
+
(enumVorlagen[art] || []).forEach(function (v) {
|
|
89
|
+
var id = pre + v._id;
|
|
90
|
+
if (da[id]) { return; }
|
|
91
|
+
var name = txt(v.name) || v._id;
|
|
92
|
+
/* Auch der Katalog selbst fuehrt Namensvettern (zweimal
|
|
93
|
+
„Stromverbrauch" unter verschiedenen Kennungen) - einer reicht. */
|
|
94
|
+
if (nachName[name.toLowerCase()]) { return; }
|
|
95
|
+
nachName[name.toLowerCase()] = id;
|
|
96
|
+
raus.push({ id: id, kurz: v._id, name: name, anzahl: 0, vorlage: v });
|
|
97
|
+
});
|
|
98
|
+
return raus;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* In welchen Aufzaehlungen dieser Art steckt die Kennung? */
|
|
102
|
+
export function enumsVon(id, art) {
|
|
103
|
+
var pre = 'enum.' + art + '.';
|
|
104
|
+
return Object.keys(enums).filter(function (k) {
|
|
105
|
+
if (k.indexOf(pre) !== 0) { return false; }
|
|
106
|
+
var m = (enums[k].common || {}).members || [];
|
|
107
|
+
return m.indexOf(id) > -1;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Der Raum einer Quelle - auch wenn er an einem ihrer Kanaele haengt.
|
|
112
|
+
|
|
113
|
+
Gemessen: die Raeume stehen bei Homematic fast immer am Kanal
|
|
114
|
+
(`hm-rpc.0.000A9D89900001.0`), nicht am Geraet. Wer nur die Geraete-ID
|
|
115
|
+
sucht, findet bei 61 zugeordneten Quellen fast keine. */
|
|
116
|
+
export function enumVonQuelle(quelle, art) {
|
|
117
|
+
var direkt = enumsVon(quelle, art);
|
|
118
|
+
if (direkt.length) { return direkt[0]; }
|
|
119
|
+
var pre = 'enum.' + art + '.';
|
|
120
|
+
var treffer = null;
|
|
121
|
+
Object.keys(enums).forEach(function (k) {
|
|
122
|
+
if (treffer || k.indexOf(pre) !== 0) { return; }
|
|
123
|
+
var m = (enums[k].common || {}).members || [];
|
|
124
|
+
if (m.some(function (x) { return String(x).indexOf(quelle + '.') === 0; })) { treffer = k; }
|
|
125
|
+
});
|
|
126
|
+
return treffer;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
/* Welche Funktion passt zu welchem Geraetetyp.
|
|
131
|
+
|
|
132
|
+
Bewusst eine Zuordnung ueber den *Namen* der Aufzaehlung, nicht ueber
|
|
133
|
+
ihre Kennung: Ricardos Funktionen heissen „Licht", „Heizung",
|
|
134
|
+
„Verschluss" - auf einer englischen Anlage heissen sie anders. Deshalb
|
|
135
|
+
wird nur vorgeschlagen, was es auch gibt. */
|
|
136
|
+
/* Welche Funktion zu einem Geraetetyp gehoert.
|
|
137
|
+
|
|
138
|
+
Hier stand eine Tabelle, die Gewerke auf Typen abbildete - „Verschluss“
|
|
139
|
+
auf blind, window, door, lock, gate. Sie hatte zwei Fehler: Sie war zu
|
|
140
|
+
grob (ein Fensterkontakt ist ein Fenster, kein „Verschluss“), und sie
|
|
141
|
+
zeigte auf Namen aus Ricardos CCU. Auf einer Anlage ohne Homematic
|
|
142
|
+
traf sie nichts.
|
|
143
|
+
|
|
144
|
+
Jetzt wird abgeleitet, in dieser Reihenfolge:
|
|
145
|
+
|
|
146
|
+
1. was in der Vorlage steht `"funktion": "window"`
|
|
147
|
+
2. Typkennung = Vorlagenkennung window, door, socket, light, …
|
|
148
|
+
3. diese Ausnahmeliste was im Admin anders heisst
|
|
149
|
+
4. nichts
|
|
150
|
+
|
|
151
|
+
Gemessen: 9 der 53 Detector-Typen heissen genauso wie eine
|
|
152
|
+
Admin-Vorlage und brauchen keinen Eintrag - door, fan, gate, humidity,
|
|
153
|
+
light, lock, pump, socket, window. Fuer den Rest steht hier, was
|
|
154
|
+
gemeint ist, und zwar als Vorlagenkennung, nicht als Anzeigename:
|
|
155
|
+
daraus loest die Werkbank beides auf, den vorhandenen Eintrag und die
|
|
156
|
+
Vorlage samt Uebersetzung und Bild. */
|
|
157
|
+
export var TYP_ZU_VORLAGE = {
|
|
158
|
+
blind: 'shutters',
|
|
159
|
+
windowTilt: 'window',
|
|
160
|
+
thermostat: 'heating',
|
|
161
|
+
temperature: 'temperature_sensor',
|
|
162
|
+
dimmer: 'light',
|
|
163
|
+
rgb: 'light',
|
|
164
|
+
rgbSingle: 'light',
|
|
165
|
+
rgbwSingle: 'light',
|
|
166
|
+
ct: 'light',
|
|
167
|
+
hue: 'light',
|
|
168
|
+
cie: 'light',
|
|
169
|
+
fireAlarm: 'smoke_detector',
|
|
170
|
+
floodAlarm: 'water',
|
|
171
|
+
vacuumCleaner: 'vacuum_cleaner',
|
|
172
|
+
weatherCurrent: 'weather',
|
|
173
|
+
weatherForecast: 'weather',
|
|
174
|
+
airCondition: 'climate',
|
|
175
|
+
volume: 'speaker',
|
|
176
|
+
volumeGroup: 'speaker',
|
|
177
|
+
media: 'music'
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/* Der vorgeschlagene Raum. Vier Wege, der erste Treffer gewinnt.
|
|
181
|
+
|
|
182
|
+
Der erste ist der wichtigste: was die Quelle schon weiss, muss man nicht
|
|
183
|
+
erraten. Die drei danach lesen den Namen - erst den Zielordner, dann den
|
|
184
|
+
Pfad der Quelle (bei Tasmota steht der Raum im Topic), zuletzt den
|
|
185
|
+
Geraetenamen selbst (`HK_Bastelzimmer` trifft bei Homematic fast immer). */
|
|
186
|
+
export function raumVorschlag(e) {
|
|
187
|
+
if (!e || !e.kanal) { return ''; }
|
|
188
|
+
|
|
189
|
+
/* 1. Von der Quelle erben */
|
|
190
|
+
var quelle = (e.kanal.indexOf('alias.') === 0) ? quelleVon(e.kanal) : e.kanal;
|
|
191
|
+
if (quelle) {
|
|
192
|
+
var geerbt = enumVonQuelle(quelle, 'rooms');
|
|
193
|
+
if (geerbt) { return geerbt; }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
var liste = enumListe('rooms', true);
|
|
197
|
+
var suche = function (wort) {
|
|
198
|
+
if (!wort) { return ''; }
|
|
199
|
+
var w = String(wort).toLowerCase();
|
|
200
|
+
var t = liste.filter(function (r) {
|
|
201
|
+
return r.name.toLowerCase() === w || r.kurz.toLowerCase() === w;
|
|
202
|
+
});
|
|
203
|
+
return t.length ? t[0].id : '';
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/* 2. Aus dem Zielordner.
|
|
207
|
+
|
|
208
|
+
Nur wenn der Ordner von Hand gesetzt wurde oder der Alias schon
|
|
209
|
+
liegt. Sonst dreht es sich im Kreis: der Ordner kommt aus dem Raum,
|
|
210
|
+
und der Raum kaeme aus dem Ordner. Abgeleitet wird immer nur aus
|
|
211
|
+
dem, was jemand entschieden hat. */
|
|
212
|
+
var ziel = (e.ordnerVonHand || aliasFuer(e.kanal)) ? (e.ziel || '') : '';
|
|
213
|
+
if (ziel.indexOf('alias.0.') === 0) {
|
|
214
|
+
var teile = ziel.slice('alias.0.'.length).split('.');
|
|
215
|
+
teile.pop();
|
|
216
|
+
for (var i = teile.length - 1; i >= 0; i--) {
|
|
217
|
+
var tr = suche(teile[i]);
|
|
218
|
+
if (tr) { return tr; }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* 3. Aus dem Pfad der Quelle */
|
|
223
|
+
if (quelle) {
|
|
224
|
+
var qt = quelle.split('.');
|
|
225
|
+
for (var j = qt.length - 2; j >= 2; j--) {
|
|
226
|
+
var qr = suche(qt[j]);
|
|
227
|
+
if (qr) { return qr; }
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* 4. Aus dem Geraetenamen: „HK_Bastelzimmer" -> Bastelzimmer.
|
|
232
|
+
Von hinten, weil der Raum am Ende steht, und stueckweise, weil
|
|
233
|
+
„Max_Spielzimmer" aus zwei Teilen besteht. */
|
|
234
|
+
var name = zusatzName(e.kanal) || (quelle ? zusatzName(quelle) : '') || '';
|
|
235
|
+
if (name) {
|
|
236
|
+
var nt = String(name).split(/[_ .]+/);
|
|
237
|
+
for (var k = 0; k < nt.length; k++) {
|
|
238
|
+
var rest = nt.slice(k).join('_');
|
|
239
|
+
var nr = suche(rest);
|
|
240
|
+
if (nr) { return nr; }
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return '';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Die vorgeschlagene Funktion, aus dem erkannten Geraetetyp. */
|
|
247
|
+
/* Zu einer Vorlagenkennung die Aufzaehlung, die gemeint ist.
|
|
248
|
+
|
|
249
|
+
Der Bestand hat Vorrang: heisst eine vorhandene Funktion so oder
|
|
250
|
+
traegt sie den Namen der Vorlage, wird die genommen. Sonst die
|
|
251
|
+
Vorlage selbst - sie entsteht dann beim Schreiben, sichtbar als NEU
|
|
252
|
+
im Trockenlauf. */
|
|
253
|
+
export function funktionZuKennung(kennung) {
|
|
254
|
+
if (!kennung) { return ''; }
|
|
255
|
+
var vorlage = null;
|
|
256
|
+
(enumVorlagen.functions || []).forEach(function (v) {
|
|
257
|
+
if (v._id === kennung) { vorlage = v; }
|
|
258
|
+
});
|
|
259
|
+
var name = vorlage ? String(txt(vorlage.name) || '').toLowerCase() : '';
|
|
260
|
+
var da = '';
|
|
261
|
+
enumListe('functions', true).forEach(function (f) {
|
|
262
|
+
if (da) { return; }
|
|
263
|
+
if (f.kurz === kennung) { da = f.id; return; }
|
|
264
|
+
if (name && f.name.toLowerCase() === name) { da = f.id; }
|
|
265
|
+
});
|
|
266
|
+
if (da) { return da; }
|
|
267
|
+
return vorlage ? ('enum.functions.' + kennung) : '';
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* Die Auswahlliste der Funktionen - einmal gebaut, zweimal gebraucht:
|
|
271
|
+
im Vorlagenblatt und im Dialog „Als Vorlage speichern".
|
|
272
|
+
|
|
273
|
+
Gespeichert wird die Kennung aus dem Katalog des Admin, nicht der
|
|
274
|
+
Anzeigename; daraus loest die Werkbank beides auf, den vorhandenen
|
|
275
|
+
Eintrag und die Vorlage samt Uebersetzung und Bild. */
|
|
276
|
+
export function funktionsAuswahl(gewaehlt) {
|
|
277
|
+
var raus = [], da = false;
|
|
278
|
+
(enumVorlagen.functions || []).slice()
|
|
279
|
+
.sort(function (a, b) {
|
|
280
|
+
return String(txt(a.name) || a._id).localeCompare(String(txt(b.name) || b._id));
|
|
281
|
+
})
|
|
282
|
+
.forEach(function (fv) {
|
|
283
|
+
if (fv._id === gewaehlt) { da = true; }
|
|
284
|
+
raus.push({ wert: fv._id,
|
|
285
|
+
text: (txt(fv.name) || fv._id) + ' · ' + fv._id,
|
|
286
|
+
gewaehlt: fv._id === gewaehlt });
|
|
287
|
+
});
|
|
288
|
+
/* Steht in der Vorlage etwas, das der Katalog nicht kennt, geht es
|
|
289
|
+
nicht verloren - sonst waere es beim ersten Speichern weg. */
|
|
290
|
+
if (gewaehlt && !da) { raus.push({ wert: gewaehlt, text: gewaehlt, gewaehlt: true }); }
|
|
291
|
+
return raus;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* Der Rueckweg: aus `enum.functions.Klima` wird `climate`.
|
|
295
|
+
|
|
296
|
+
`funktionZuKennung` geht die eine Richtung, hier die andere. Gebraucht
|
|
297
|
+
wird sie beim Speichern einer Vorlage: was am Geraet als Funktion
|
|
298
|
+
steht, soll im Dialog schon vorgeschlagen sein.
|
|
299
|
+
|
|
300
|
+
Gespeichert wird die Kennung des Katalogs, nicht die der Anlage - eine
|
|
301
|
+
Vorlage, die `Klima` sagt, passt nur auf eine Anlage mit genau diesem
|
|
302
|
+
deutschen Namen. Findet sich im Katalog nichts, bleibt die kurze
|
|
303
|
+
Kennung der Aufzaehlung; `funktionZuKennung` findet auch die wieder. */
|
|
304
|
+
export function kennungZuFunktion(enumId) {
|
|
305
|
+
if (!enumId) { return ''; }
|
|
306
|
+
var kurz = enumId.slice('enum.functions.'.length);
|
|
307
|
+
var o = enums[enumId];
|
|
308
|
+
var v = vorlageZu(enumId, 'functions', txt(o && o.common && o.common.name));
|
|
309
|
+
return v ? v._id : kurz;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function funktionVorschlag(e) {
|
|
313
|
+
if (!e) { return ''; }
|
|
314
|
+
|
|
315
|
+
/* 1. Was die Vorlage sagt. Sie weiss mehr als der Typ: `socket` kann
|
|
316
|
+
eine Steckdose sein, eine Waschmaschine oder eine Druckerleiste -
|
|
317
|
+
der Detector sieht keinen Unterschied, die Vorlage schon. */
|
|
318
|
+
if (e.vorlage) {
|
|
319
|
+
var vq = null;
|
|
320
|
+
S.VORLAGEN.forEach(function (v) { if (v.id === e.vorlage) { vq = v; } });
|
|
321
|
+
if (vq && vq.funktion) {
|
|
322
|
+
var ausVorlage = funktionZuKennung(vq.funktion);
|
|
323
|
+
if (ausVorlage) { return ausVorlage; }
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (!e.want) { return ''; }
|
|
328
|
+
|
|
329
|
+
/* 2. Der Typ heisst wie eine Vorlage. 3. Sonst die Ausnahmeliste. */
|
|
330
|
+
return funktionZuKennung(e.want) ||
|
|
331
|
+
funktionZuKennung(TYP_ZU_VORLAGE[e.want]);
|
|
332
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* Zustandsfreie Helfer, die jedes Modul brauchen darf.
|
|
2
|
+
|
|
3
|
+
Hier liegt nichts, was sich aendert - nur Werkzeug. */
|
|
4
|
+
|
|
5
|
+
export var D = window.AWDetector;
|
|
6
|
+
export var $ = function (s) { return document.querySelector(s); };
|
|
7
|
+
|
|
8
|
+
/* Plus und Minus in der Form, die auch der Admin verwendet. Fuer
|
|
9
|
+
Abschnitte, die man auf- und zuklappt — im Gegensatz zum Baum, wo ein
|
|
10
|
+
Dreieck die gewohnte Form ist. „Mehr davon" und „hier geht es weiter"
|
|
11
|
+
sind zwei verschiedene Aussagen. */
|
|
12
|
+
var WEG_PLUS = 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z';
|
|
13
|
+
var WEG_MINUS = 'M19 13H5v-2h14z';
|
|
14
|
+
|
|
15
|
+
export function klappZeichen(offen) {
|
|
16
|
+
var sp = document.createElement('span');
|
|
17
|
+
sp.className = 'klappz';
|
|
18
|
+
sp.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="' +
|
|
19
|
+
(offen ? WEG_MINUS : WEG_PLUS) + '"/></svg>';
|
|
20
|
+
return sp;
|
|
21
|
+
}
|
|
22
|
+
export function el(tag, cls, txt) {
|
|
23
|
+
var e = document.createElement(tag);
|
|
24
|
+
if (cls) { e.className = cls; }
|
|
25
|
+
if (txt !== undefined) { e.textContent = txt; }
|
|
26
|
+
return e;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function holeText(pfad) {
|
|
30
|
+
return fetch(pfad).then(function (r) {
|
|
31
|
+
if (!r.ok) { throw new Error(String(r.status)); }
|
|
32
|
+
return r.text();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function kurz(id, kanal) { return id.slice(kanal.length + 1); }
|