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,695 @@
|
|
|
1
|
+
/* Raum, Funktion und Ziel am Entwurf: die Felderzeile, was sich an den
|
|
2
|
+
Aufzaehlungen aendert, und was der Bestand dem Vorschlag voraus hat. */
|
|
3
|
+
|
|
4
|
+
import { S } from './zustand.js';
|
|
5
|
+
import { el } from './basis.js';
|
|
6
|
+
import { tr, txt } from './sprache.js';
|
|
7
|
+
import { enums } from './enums.js';
|
|
8
|
+
import {
|
|
9
|
+
enumListe,
|
|
10
|
+
enumsVon,
|
|
11
|
+
neueEnum,
|
|
12
|
+
raumVorschlag,
|
|
13
|
+
funktionVorschlag
|
|
14
|
+
} from './aufzaehlungen.js';
|
|
15
|
+
import { enumVorlagen, katalogFehlt, ikonCache, ikonErlaubt, ikonNachtrag,
|
|
16
|
+
ikonTaugt, vorlageZu, holeIkon } from './katalog.js';
|
|
17
|
+
import { kindZustaende, aliasQuellen } from './werte.js';
|
|
18
|
+
import { aliasFuer, zielId } from './entwurf.js';
|
|
19
|
+
import { zeichneErgebnis, entwurfAngefasst, angebotFrisch } from './ergebnis.js';
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
import { ausgangName } from './vorlagen.js';
|
|
23
|
+
import { musterVon } from './erkennung.js';
|
|
24
|
+
|
|
25
|
+
/* Welche Aufzaehlungen aendern sich, wenn dieser Entwurf geschrieben wird?
|
|
26
|
+
|
|
27
|
+
Liefert je Aufzaehlung das fertige Objekt, so wie es hinterher aussehen
|
|
28
|
+
soll. Damit kann der Trockenlauf es zeigen wie jedes andere Objekt auch,
|
|
29
|
+
und geschrieben wird genau das, was dort stand.
|
|
30
|
+
|
|
31
|
+
Wichtig: gelesen wird der *aktuelle* Stand und nur die eigene Kennung
|
|
32
|
+
hinzugefuegt oder entfernt. Eine Aufzaehlung ist geteiltes Gut - in
|
|
33
|
+
`enum.rooms.Bastelzimmer` stehen acht fremde Eintraege. Wer die Liste neu
|
|
34
|
+
baut, statt sie zu ergaenzen, loescht anderer Leute Zuordnungen. */
|
|
35
|
+
export function enumAenderungen(e) {
|
|
36
|
+
var raus = [];
|
|
37
|
+
if (!e || !e.kanal) { return raus; }
|
|
38
|
+
/* Im Aliasmodus gibt es kein gewaehltes Ziel — der Alias *ist* das Ziel.
|
|
39
|
+
Eine frueher hier stehende Abfrage brach in genau diesem Fall ab, und
|
|
40
|
+
eine im Aliasmodus geaenderte Zuordnung wurde stillschweigend nicht
|
|
41
|
+
geschrieben. */
|
|
42
|
+
var ziel = e.ziel || e.kanal;
|
|
43
|
+
|
|
44
|
+
[['rooms', e.raum], ['functions', e.funktion]].forEach(function (paar) {
|
|
45
|
+
var art = paar[0], gewaehlt = paar[1] || '';
|
|
46
|
+
var betroffen = {};
|
|
47
|
+
|
|
48
|
+
/* die, in denen das Ziel jetzt steht */
|
|
49
|
+
enumsVon(ziel, art).forEach(function (id) { betroffen[id] = true; });
|
|
50
|
+
/* und die gewaehlte */
|
|
51
|
+
if (gewaehlt) { betroffen[gewaehlt] = true; }
|
|
52
|
+
|
|
53
|
+
Object.keys(betroffen).forEach(function (id) {
|
|
54
|
+
var o = enums[id];
|
|
55
|
+
var mAlt = (o && o.common && o.common.members) ? o.common.members.slice() : [];
|
|
56
|
+
var mNeu = mAlt.filter(function (x) {
|
|
57
|
+
/* Nur die eigene Kennung anfassen: sie bleibt, wenn diese
|
|
58
|
+
Aufzaehlung die gewaehlte ist, sonst faellt sie heraus. Alles
|
|
59
|
+
andere ist fremdes Eigentum und wird nicht beruehrt. */
|
|
60
|
+
if (x === ziel) { return id === gewaehlt; }
|
|
61
|
+
return true;
|
|
62
|
+
});
|
|
63
|
+
if (id === gewaehlt && mNeu.indexOf(ziel) === -1) { mNeu.push(ziel); mNeu.sort(); }
|
|
64
|
+
/* Sonst faellt das nachgetragene Bild durch: die Mitglieder
|
|
65
|
+
aendern sich dabei ja nicht. */
|
|
66
|
+
if (JSON.stringify(mAlt) === JSON.stringify(mNeu) && !ikonNachtrag(id, art, o)) { return; }
|
|
67
|
+
|
|
68
|
+
var obj = o ? JSON.parse(JSON.stringify(o)) : neueEnum(id, art);
|
|
69
|
+
obj.common = obj.common || {};
|
|
70
|
+
obj.common.members = mNeu;
|
|
71
|
+
|
|
72
|
+
/* Einer vorhandenen Aufzaehlung das fehlende Bild nachtragen.
|
|
73
|
+
|
|
74
|
+
Neu angelegte bekommen ihres aus der Vorlage. Vorhandene nicht -
|
|
75
|
+
bis hierher wurde nur die Mitgliederliste ergaenzt, und das Feld
|
|
76
|
+
blieb, wie es war. Bei Ricardo heisst das: keine einzige seiner
|
|
77
|
+
elf Funktionen und keiner seiner vierzehn Raeume hat je ein Bild
|
|
78
|
+
bekommen, denn hm-rega spiegelt aus der CCU nur Namen und
|
|
79
|
+
Mitglieder. Und die sieben Vorgaberaeume zeigen ein kaputtes
|
|
80
|
+
Kaestchen, weil dort ein blosser Name steht.
|
|
81
|
+
|
|
82
|
+
Angefasst wird nur, wo gar nichts Brauchbares steht. Ein Bild,
|
|
83
|
+
das der Nutzer selbst gesetzt hat, bleibt unberuehrt. */
|
|
84
|
+
var ikonDazu = false;
|
|
85
|
+
if (o && ikonErlaubt(art, obj)) {
|
|
86
|
+
var vv = vorlageZu(id, art, txt(obj.common.name));
|
|
87
|
+
if (vv && vv.icon) {
|
|
88
|
+
var ik = ikonCache[art + ':' + vv.icon];
|
|
89
|
+
if (ik) { obj.common.icon = ik; ikonDazu = true; }
|
|
90
|
+
/* Noch nicht da? Dann wenigstens jetzt holen, damit es beim
|
|
91
|
+
naechsten Schreiben bereitsteht. */
|
|
92
|
+
else { holeIkon(art, vv.icon); }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
delete obj.ts; delete obj.from; delete obj.user; delete obj.acl;
|
|
96
|
+
raus.push({ id: id, neu: !o, obj: obj, istEnum: true, ikonDazu: ikonDazu,
|
|
97
|
+
dazu: mNeu.indexOf(ziel) > -1 && mAlt.indexOf(ziel) === -1,
|
|
98
|
+
weg: mAlt.indexOf(ziel) > -1 && mNeu.indexOf(ziel) === -1 });
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
return raus;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Die Zeile mit Raum und Funktion.
|
|
105
|
+
|
|
106
|
+
Steht sowohl an der Quelle als auch am fertigen Alias. An der Quelle
|
|
107
|
+
gehoert sie unter das Ziel — dort entscheidet sich, wohin der Alias
|
|
108
|
+
kommt und wozu er zaehlt. Am Alias ist sie der einzige Weg, die
|
|
109
|
+
Zuordnung spaeter noch zu aendern; ohne sie waere die Sache eine
|
|
110
|
+
Einbahnstrasse. */
|
|
111
|
+
export function enumZeile(host, e) {
|
|
112
|
+
setzeEnums(e);
|
|
113
|
+
|
|
114
|
+
/* Die Bilder der beiden gewaehlten Aufzaehlungen schon jetzt holen.
|
|
115
|
+
|
|
116
|
+
Beim Klick auf eine Vorlagenzeile geschieht das ohnehin. Eine
|
|
117
|
+
vorhandene Aufzaehlung stoesst aber niemand an - und genau die
|
|
118
|
+
braucht das Bild, wenn ihr eines fehlt. Ohne diesen Anstoss traegt
|
|
119
|
+
der erste Schreibvorgang nichts nach und erst der zweite tut es, was
|
|
120
|
+
von aussen wie Zufall aussieht.
|
|
121
|
+
|
|
122
|
+
`holeIkon` haelt sich selbst zurueck, wenn es laeuft oder das Bild
|
|
123
|
+
vorliegt - hier entsteht kein wiederholtes Laden. */
|
|
124
|
+
[['rooms', e.raum], ['functions', e.funktion]].forEach(function (paar) {
|
|
125
|
+
var art = paar[0], id = paar[1];
|
|
126
|
+
if (!id) { return; }
|
|
127
|
+
var o = enums[id];
|
|
128
|
+
if (o && !ikonErlaubt(art, o)) { return; }
|
|
129
|
+
var v = vorlageZu(id, art, o ? txt(o.common && o.common.name) : '');
|
|
130
|
+
if (v && v.icon) { holeIkon(art, v.icon, zeichneErgebnis); }
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
/* --- Raum und Funktion ---
|
|
134
|
+
|
|
135
|
+
Eigene Zeile unter dem Ziel, weil beides zum Alias gehoert, aber
|
|
136
|
+
woanders abgelegt wird: nicht am Objekt, sondern in einer
|
|
137
|
+
Aufzaehlung. Aufbau wie das Ordnerfeld daneben - Eingabefeld mit
|
|
138
|
+
eigener Liste, kein <select>, damit man tippen und suchen kann. */
|
|
139
|
+
var ebar = el('div', 'zielbar enumbar');
|
|
140
|
+
/* Das Angebot wird in der Schleife gebaut, aber erst danach angehaengt -
|
|
141
|
+
sonst stuende es zwischen Raum und Funktion und schoebe das zweite
|
|
142
|
+
Feld in die naechste Zeile. */
|
|
143
|
+
var enumAngebot = null;
|
|
144
|
+
[{ art: 'rooms', feld: 'raum', her: 'raumHer',
|
|
145
|
+
label: tr('enums.room'), hint: tr('enums.roomHint') },
|
|
146
|
+
{ art: 'functions', feld: 'funktion', her: 'funktionHer',
|
|
147
|
+
label: tr('enums.function'), hint: tr('enums.functionHint') }
|
|
148
|
+
].forEach(function (spec) {
|
|
149
|
+
ebar.appendChild(el('span', 'zl', spec.label));
|
|
150
|
+
var ew = el('div', 'feldwrap');
|
|
151
|
+
var ei = el('input', 'tx enumfeld');
|
|
152
|
+
ei.type = 'text';
|
|
153
|
+
ei.setAttribute('autocomplete', 'off');
|
|
154
|
+
ei.placeholder = tr('enums.placeholder');
|
|
155
|
+
ei.title = spec.hint;
|
|
156
|
+
|
|
157
|
+
var gew = e[spec.feld] || '';
|
|
158
|
+
var nameVon = function (id) {
|
|
159
|
+
if (!id) { return ''; }
|
|
160
|
+
if (enums[id]) { return txt((enums[id].common || {}).name) || id.split('.').pop(); }
|
|
161
|
+
/* Noch nicht angelegt: dann steht der Name in der Vorlage. Ohne
|
|
162
|
+
das zeigte das Feld nach der Wahl von „Stehlampe“ die nackte
|
|
163
|
+
Kennung „floor_lamp“ - der Nutzer sieht etwas anderes, als er
|
|
164
|
+
angeklickt hat. */
|
|
165
|
+
var kurz = id.split('.').pop(), gefunden = '';
|
|
166
|
+
(enumVorlagen[spec.art] || []).forEach(function (v) {
|
|
167
|
+
if (v._id === kurz) { gefunden = txt(v.name) || kurz; }
|
|
168
|
+
});
|
|
169
|
+
/* Und dass es sie noch nicht gibt, steht dahinter - im Feld, nicht
|
|
170
|
+
als Marke am Zeilenende. Dort hing sie zuerst und rutschte durch
|
|
171
|
+
den Umbruch unter das Raumfeld, wo sie aussah, als gehoere sie
|
|
172
|
+
zum Raum. Was ueber ein Feld etwas aussagt, gehoert in das Feld.
|
|
173
|
+
|
|
174
|
+
Zurueckgelesen wird der Feldinhalt nie: beim Hineinklicken leert
|
|
175
|
+
er sich zum Tippen, beim Verlassen wird er neu aufgebaut. */
|
|
176
|
+
return (gefunden || kurz) + ' (' + tr('enums.newSuffix') + ')';
|
|
177
|
+
};
|
|
178
|
+
ei.value = nameVon(gew);
|
|
179
|
+
ew.appendChild(ei);
|
|
180
|
+
|
|
181
|
+
/* Das Bild der gewaehlten Aufzaehlung - rechts NEBEN dem Feld, nicht
|
|
182
|
+
darin. Dort steht es frei: zwischen Feldende und der naechsten
|
|
183
|
+
Beschriftung liegen 54 px, hinter dem Funktionsfeld 91 px
|
|
184
|
+
(gemessen 26.08.2026). Im Feld haette es Text verdraengt, und der
|
|
185
|
+
ist knapper als der Platz daneben (Ricardo, 26.08.2026).
|
|
186
|
+
|
|
187
|
+
Absolut zum Feldrahmen, damit das Raster unangetastet bleibt -
|
|
188
|
+
sonst stuende die Zielzeile darunter nicht mehr buendig.
|
|
189
|
+
|
|
190
|
+
Drei Lagen, und man sieht sie am Feld statt erst im Trockenlauf:
|
|
191
|
+
|
|
192
|
+
- die Aufzaehlung hat schon ein taugliches Bild -> es steht da
|
|
193
|
+
- sie hat keins, die Werkbank wuerde eins nachtragen -> blass,
|
|
194
|
+
und weil das eine Aussage ueber diese eine Aufzaehlung ist,
|
|
195
|
+
mit einem kleinen „neu" daneben
|
|
196
|
+
- sonst nichts: kein Bild im Katalog, oder der Schalter ist aus.
|
|
197
|
+
Dann sieht das Feld aus wie frueher, und das ist die Wahrheit.
|
|
198
|
+
|
|
199
|
+
Eine Aufzaehlung, die es noch gar nicht gibt, bekommt ihr Bild
|
|
200
|
+
ohnehin aus der Vorlage (`neueEnum`) - dort steht das „neu" schon
|
|
201
|
+
im Feldtext, also hier nur blass und ohne Wort. */
|
|
202
|
+
var bild = '', blass = false, marke = false;
|
|
203
|
+
if (gew) {
|
|
204
|
+
var oIk = enums[gew];
|
|
205
|
+
var daIk = oIk && oIk.common && oIk.common.icon;
|
|
206
|
+
if (ikonTaugt(daIk)) {
|
|
207
|
+
bild = daIk;
|
|
208
|
+
} else if (oIk ? ikonErlaubt(spec.art, oIk) : true) {
|
|
209
|
+
var vIk = vorlageZu(gew, spec.art,
|
|
210
|
+
oIk ? txt(oIk.common && oIk.common.name) : '');
|
|
211
|
+
var bIk = (vIk && vIk.icon) ? ikonCache[spec.art + ':' + vIk.icon] : null;
|
|
212
|
+
if (bIk) { bild = bIk; blass = true; marke = !!oIk; }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (bild) {
|
|
216
|
+
var iw = el('div', 'feldikon' + (blass ? ' blass' : ''));
|
|
217
|
+
var img = document.createElement('img');
|
|
218
|
+
img.src = bild;
|
|
219
|
+
img.alt = '';
|
|
220
|
+
iw.appendChild(img);
|
|
221
|
+
if (marke) { iw.appendChild(el('span', 'ikneu', tr('enums.iconNewMark'))); }
|
|
222
|
+
iw.title = blass ? tr('enums.iconNew') : tr('enums.iconThere');
|
|
223
|
+
ew.appendChild(iw);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
var ex = el('button', 'feldx');
|
|
227
|
+
ex.type = 'button';
|
|
228
|
+
ex.title = tr('enums.clear');
|
|
229
|
+
ex.setAttribute('aria-label', tr('enums.clear'));
|
|
230
|
+
ex.hidden = !ei.value;
|
|
231
|
+
ex.addEventListener('mousedown', function (ev) {
|
|
232
|
+
ev.preventDefault();
|
|
233
|
+
e[spec.feld] = '';
|
|
234
|
+
e[spec.her] = 'hand';
|
|
235
|
+
entwurfAngefasst();
|
|
236
|
+
zeichneErgebnis();
|
|
237
|
+
});
|
|
238
|
+
ew.appendChild(ex);
|
|
239
|
+
|
|
240
|
+
var el2 = el('div', 'vorschlaege');
|
|
241
|
+
el2.hidden = true;
|
|
242
|
+
ew.appendChild(el2);
|
|
243
|
+
ebar.appendChild(ew);
|
|
244
|
+
|
|
245
|
+
/* Ist das ein Vorschlag oder steht es schon so im Bestand? Ohne
|
|
246
|
+
diesen Unterschied sieht ein Vorschlag aus wie eine Tatsache.
|
|
247
|
+
Die Marke bekommt im Raster die Spalte ihres Feldes zugewiesen -
|
|
248
|
+
frei fliessend landete sie unter dem falschen Feld, und in den
|
|
249
|
+
Feldrahmen gehaengt schob sie Kreuz und Aufklappliste aus der
|
|
250
|
+
Position. */
|
|
251
|
+
if (gew && e[spec.her] === 'vorschlag') {
|
|
252
|
+
ebar.appendChild(el('span', 'chip mut vorschlagsmarke '
|
|
253
|
+
+ (spec.art === 'rooms' ? 'raum' : 'funktion'), tr('enums.suggested')));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
/* Die Gegenrichtung, nach derselben Regel: wer den Raum geaendert
|
|
258
|
+
hat, bekommt hier angeboten, den Ablageort nachzuziehen. Nur im
|
|
259
|
+
Quellenmodus - am fertigen Alias gibt es kein Ziel zu waehlen. */
|
|
260
|
+
if (spec.art === 'rooms' && e.zuletzt === 'raum' && e.ziel && !aliasFuer(e.kanal)) {
|
|
261
|
+
var ro2 = enumAlsOrdner(e.raum);
|
|
262
|
+
if (ro2 && e.zielOrdner !== 'alias.0.' + ro2) {
|
|
263
|
+
var oz = el('div', 'uebernahme' +
|
|
264
|
+
(angebotFrisch('raum:' + ro2) ? ' frisch' : ''));
|
|
265
|
+
oz.appendChild(el('span', 'zq', tr('enums.alsoFolder', ro2)));
|
|
266
|
+
var ob = el('button', 'btn mini wichtig', tr('target.yes'));
|
|
267
|
+
ob.addEventListener('click', function () {
|
|
268
|
+
e.zielOrdner = 'alias.0.' + ro2;
|
|
269
|
+
e.ordnerVonHand = true;
|
|
270
|
+
entwurfAngefasst();
|
|
271
|
+
zeichneErgebnis();
|
|
272
|
+
});
|
|
273
|
+
oz.appendChild(ob);
|
|
274
|
+
enumAngebot = oz;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
var mListe = [];
|
|
279
|
+
var mMark = -1;
|
|
280
|
+
var zu = function () { el2.hidden = true; mMark = -1; };
|
|
281
|
+
|
|
282
|
+
var malen = function () {
|
|
283
|
+
var such = String(ei.value || '').trim().toLowerCase();
|
|
284
|
+
var alle = enumListe(spec.art);
|
|
285
|
+
mListe = such
|
|
286
|
+
? alle.filter(function (x) {
|
|
287
|
+
return x.name.toLowerCase().indexOf(such) > -1 ||
|
|
288
|
+
x.kurz.toLowerCase().indexOf(such) > -1; })
|
|
289
|
+
: alle;
|
|
290
|
+
el2.textContent = '';
|
|
291
|
+
|
|
292
|
+
if (!mListe.length) {
|
|
293
|
+
/* Was es nicht gibt, laesst sich anlegen - aber nur hier, im Feld
|
|
294
|
+
selbst. Wer im Raumfeld steht und einen Namen tippt, will einen
|
|
295
|
+
Raum; das ist eine Entscheidung, kein Nebeneffekt. Aus einem
|
|
296
|
+
Ordnernamen entsteht dagegen nie von allein eine Aufzaehlung -
|
|
297
|
+
sonst faenden sich bald „test“, „alt“ und „neu“ unter den
|
|
298
|
+
Raeumen wieder.
|
|
299
|
+
|
|
300
|
+
Der Name wird nur gesaeubert, wo er als Kennung nicht taugt:
|
|
301
|
+
Punkte machten eine weitere Ebene auf. */
|
|
302
|
+
var frei = String(ei.value || '').trim().replace(/\./g, '_');
|
|
303
|
+
if (frei) {
|
|
304
|
+
var nz = el('div', 'vz');
|
|
305
|
+
nz.appendChild(el('span', null, frei));
|
|
306
|
+
nz.appendChild(el('span', 'tiefer', tr('enums.willCreate')));
|
|
307
|
+
nz.addEventListener('mousedown', function (ev) {
|
|
308
|
+
ev.preventDefault();
|
|
309
|
+
e[spec.feld] = 'enum.' + spec.art + '.' + frei;
|
|
310
|
+
e[spec.her] = 'hand';
|
|
311
|
+
if (spec.art === 'rooms') { e.zuletzt = 'raum'; }
|
|
312
|
+
entwurfAngefasst();
|
|
313
|
+
zu();
|
|
314
|
+
zeichneErgebnis();
|
|
315
|
+
});
|
|
316
|
+
el2.appendChild(nz);
|
|
317
|
+
} else {
|
|
318
|
+
var neu2 = el('div', 'vz zurueck');
|
|
319
|
+
neu2.appendChild(el('span', null, tr('enums.noMatch', ei.value)));
|
|
320
|
+
el2.appendChild(neu2);
|
|
321
|
+
}
|
|
322
|
+
el2.hidden = false;
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
mListe.forEach(function (x, n) {
|
|
327
|
+
var z = el('div', 'vz' + (n === mMark ? ' an' : '') + (x.id === e[spec.feld] ? ' gewaehlt' : ''));
|
|
328
|
+
z.appendChild(el('span', null, x.name));
|
|
329
|
+
z.appendChild(el('span', 'tiefer',
|
|
330
|
+
x.vorlage ? tr('enums.willCreate')
|
|
331
|
+
: (x.anzahl ? tr('enums.members', x.anzahl) : tr('enums.unused'))));
|
|
332
|
+
z.addEventListener('mousedown', function (ev) {
|
|
333
|
+
ev.preventDefault();
|
|
334
|
+
e[spec.feld] = x.id;
|
|
335
|
+
e[spec.her] = 'hand';
|
|
336
|
+
if (spec.art === 'rooms') { e.zuletzt = 'raum'; }
|
|
337
|
+
/* Das Icon jetzt holen, nicht erst beim Schreiben: dort ist
|
|
338
|
+
kein Warten mehr moeglich, der Objektbau laeuft synchron. */
|
|
339
|
+
if (x.vorlage && x.vorlage.icon) { holeIkon(spec.art, x.vorlage.icon); }
|
|
340
|
+
entwurfAngefasst();
|
|
341
|
+
zu();
|
|
342
|
+
zeichneErgebnis();
|
|
343
|
+
});
|
|
344
|
+
el2.appendChild(z);
|
|
345
|
+
});
|
|
346
|
+
if (katalogFehlt) {
|
|
347
|
+
var kf = el('div', 'vz zurueck');
|
|
348
|
+
kf.appendChild(el('span', null, tr('catalog.missing')));
|
|
349
|
+
el2.appendChild(kf);
|
|
350
|
+
}
|
|
351
|
+
el2.hidden = false;
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
ei.addEventListener('focus', function () { ei.value = ''; mMark = -1; malen(); });
|
|
355
|
+
ei.addEventListener('input', function () { mMark = -1; malen(); });
|
|
356
|
+
ei.addEventListener('blur', function () {
|
|
357
|
+
setTimeout(function () { zu(); ei.value = nameVon(e[spec.feld] || ''); }, 140);
|
|
358
|
+
});
|
|
359
|
+
ei.addEventListener('keydown', function (ev) {
|
|
360
|
+
if (ev.key === 'Escape') { zu(); ei.value = nameVon(e[spec.feld] || ''); ei.blur(); return; }
|
|
361
|
+
if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') {
|
|
362
|
+
if (el2.hidden) { malen(); return; }
|
|
363
|
+
ev.preventDefault();
|
|
364
|
+
if (!mListe.length) { return; }
|
|
365
|
+
mMark += (ev.key === 'ArrowDown' ? 1 : -1);
|
|
366
|
+
if (mMark < 0) { mMark = mListe.length - 1; }
|
|
367
|
+
if (mMark >= mListe.length) { mMark = 0; }
|
|
368
|
+
malen();
|
|
369
|
+
var akt = el2.children[mMark];
|
|
370
|
+
if (akt && akt.scrollIntoView) { akt.scrollIntoView({ block: 'nearest' }); }
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (ev.key === 'Enter' && !el2.hidden && mListe.length) {
|
|
374
|
+
ev.preventDefault();
|
|
375
|
+
e[spec.feld] = mListe[mMark >= 0 ? mMark : 0].id;
|
|
376
|
+
e[spec.her] = 'hand';
|
|
377
|
+
entwurfAngefasst();
|
|
378
|
+
zu();
|
|
379
|
+
zeichneErgebnis();
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
if (enumAngebot) { ebar.appendChild(enumAngebot); }
|
|
384
|
+
host.appendChild(ebar);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/* Welcher Raum, welche Funktion - und woher.
|
|
388
|
+
|
|
389
|
+
Gibt es den Alias schon, gilt, was dort steht: seine Zuordnung ist eine
|
|
390
|
+
Tatsache, kein Vorschlag. Gibt es ihn noch nicht, wird vorgeschlagen.
|
|
391
|
+
`raumHer`/`funktionHer` haelt fest, welcher Fall es war - die Zeile sagt
|
|
392
|
+
das dazu, damit ein Vorschlag nicht wie eine bestehende Zuordnung
|
|
393
|
+
aussieht. */
|
|
394
|
+
export function setzeEnums(e) {
|
|
395
|
+
if (e.raum !== undefined && e.funktion !== undefined) { return; }
|
|
396
|
+
var ziel = e.ziel || e.kanal;
|
|
397
|
+
var da = !!S.objects[ziel];
|
|
398
|
+
|
|
399
|
+
if (e.raum === undefined) {
|
|
400
|
+
var r = da ? (enumsVon(ziel, 'rooms')[0] || '') : '';
|
|
401
|
+
e.raumHer = r ? 'bestand' : '';
|
|
402
|
+
if (!r) { r = raumVorschlag(e); if (r) { e.raumHer = 'vorschlag'; } }
|
|
403
|
+
e.raum = r || '';
|
|
404
|
+
}
|
|
405
|
+
if (e.funktion === undefined) {
|
|
406
|
+
var f = da ? (enumsVon(ziel, 'functions')[0] || '') : '';
|
|
407
|
+
e.funktionHer = f ? 'bestand' : '';
|
|
408
|
+
if (!f) { f = funktionVorschlag(e); if (f) { e.funktionHer = 'vorschlag'; } }
|
|
409
|
+
e.funktion = f || '';
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/* Der Name einer Aufzaehlung, so wie er als Ordner taugen wuerde.
|
|
414
|
+
|
|
415
|
+
Ein Ordner unter `alias.0` darf keine Punkte enthalten - sie wuerden
|
|
416
|
+
eine weitere Ebene aufmachen. Alles andere bleibt, wie der Nutzer es
|
|
417
|
+
kennt: „Wohnkueche“ heisst auch im Pfad „Wohnkueche“. */
|
|
418
|
+
export function enumAlsOrdner(id) {
|
|
419
|
+
if (!id) { return ''; }
|
|
420
|
+
var o = enums[id];
|
|
421
|
+
var n = o ? (txt((o.common || {}).name) || '') : '';
|
|
422
|
+
if (!n) {
|
|
423
|
+
/* Noch nicht angelegt? Dann steht der Name in der Vorlage. */
|
|
424
|
+
var art = id.indexOf('enum.rooms.') === 0 ? 'rooms' : 'functions';
|
|
425
|
+
var v = vorlageZu(id, art, '');
|
|
426
|
+
n = v ? (txt(v.name) || '') : '';
|
|
427
|
+
}
|
|
428
|
+
if (!n) { n = id.split('.').pop(); }
|
|
429
|
+
return String(n).replace(/\./g, '_').trim();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export function setzeZiel(e) {
|
|
433
|
+
if (S.current.indexOf('alias.') === 0) { return; }
|
|
434
|
+
if (e.zielOrdner === undefined) {
|
|
435
|
+
var zt0 = (e.ziel || zielId(S.current)).split('.');
|
|
436
|
+
var geraet = zt0.pop();
|
|
437
|
+
|
|
438
|
+
/* Gibt es fuer diese Quelle schon einen Alias, ist der das Ziel —
|
|
439
|
+
auch wenn er woanders liegt als der Vorschlag. Sonst zeigt die
|
|
440
|
+
Werkbank auf einen freien Platz, meldet „wird neu angelegt" und
|
|
441
|
+
legt beim Klick ein zweites Geraet an, waehrend das erste
|
|
442
|
+
verwaist stehenbleibt. Beim Karbonator lag der Alias unter
|
|
443
|
+
alias.0.Strom, vorgeschlagen wurde alias.0.SmartHome. */
|
|
444
|
+
var vorhanden = aliasFuer(S.current);
|
|
445
|
+
/* Hier stand einmal ein `e.altesZiel = vorhanden`, damit beim
|
|
446
|
+
Verschieben die alte Kennung aus den Aufzaehlungen fliegt. Gemessen
|
|
447
|
+
hat sich das als falsch erwiesen: die Werkbank verschiebt nicht,
|
|
448
|
+
sie legt am neuen Ort an - der alte Alias bleibt stehen. Ihm dabei
|
|
449
|
+
den Raum wegzunehmen, waere ein stiller Schaden an einem Objekt,
|
|
450
|
+
das es weiterhin gibt.
|
|
451
|
+
|
|
452
|
+
Wer wirklich verschwindet, wird geloescht, und dabei traegt der
|
|
453
|
+
js-controller selbst aus allen Aufzaehlungen aus. Es gibt also
|
|
454
|
+
nichts zu tun. */
|
|
455
|
+
|
|
456
|
+
if (e.instanzen && e.instanzen.length > 1) {
|
|
457
|
+
/* Mehrere Ausgaenge: das Geraet wird zum Ordner, jeder Ausgang
|
|
458
|
+
ein Kanal darin. Ein folder darueber, kein device — sonst
|
|
459
|
+
rutscht die Erkennung hoch und macht aus dreien wieder eins. */
|
|
460
|
+
if (vorhanden) {
|
|
461
|
+
/* Der gefundene Kanal ist einer der Ausgaenge; der Ordner liegt
|
|
462
|
+
darueber. Wie der einzelne Ausgang heisst, kann die Werkbank
|
|
463
|
+
nicht wissen — wer sie umbenannt hat, sieht den Vorschlag in
|
|
464
|
+
der Zielzeile und kann ihn anpassen. */
|
|
465
|
+
var tm = vorhanden.split('.');
|
|
466
|
+
tm.pop();
|
|
467
|
+
e.zielOrdner = tm.join('.');
|
|
468
|
+
} else {
|
|
469
|
+
e.zielOrdner = zt0.join('.') + '.' + geraet;
|
|
470
|
+
}
|
|
471
|
+
e.zielName = ausgangName(e, e.instanz);
|
|
472
|
+
} else if (vorhanden) {
|
|
473
|
+
var te = vorhanden.split('.');
|
|
474
|
+
e.zielName = te.pop();
|
|
475
|
+
e.zielOrdner = te.join('.');
|
|
476
|
+
} else {
|
|
477
|
+
e.zielOrdner = zt0.join('.');
|
|
478
|
+
e.zielName = geraet;
|
|
479
|
+
|
|
480
|
+
/* Steht ein Raum fest, gehoert der Alias dorthin.
|
|
481
|
+
|
|
482
|
+
Das ist der haeufigste Fall bei Homematic: der Kanal haengt in
|
|
483
|
+
„Bastelzimmer“, und dann soll der Alias nicht unter dem
|
|
484
|
+
Adapterpfad landen, sondern unter `alias.0.Bastelzimmer`. Nur
|
|
485
|
+
beim Vorschlag - wer den Ordner selbst tippt, behaelt ihn
|
|
486
|
+
(`e.ordnerVonHand`), und wer schon einen Alias hat, wird nicht
|
|
487
|
+
umgezogen (der Zweig hier greift nur, wenn es keinen gibt). */
|
|
488
|
+
if (!e.ordnerVonHand) {
|
|
489
|
+
setzeEnums(e);
|
|
490
|
+
var ro = enumAlsOrdner(e.raum);
|
|
491
|
+
if (ro) { e.zielOrdner = 'alias.0.' + ro; }
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
e.ziel = e.zielOrdner + '.' + e.zielName;
|
|
496
|
+
uebernehmeBestand(e);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export function uebernehmeBestand(e) {
|
|
500
|
+
if (!e.ziel || e.bestandGeprueft === e.ziel) { return; }
|
|
501
|
+
e.bestandGeprueft = e.ziel;
|
|
502
|
+
if (!S.objects[e.ziel]) { return; }
|
|
503
|
+
/* Im Aliasmodus ist der Entwurf schon der Bestand. */
|
|
504
|
+
if (e.kanal === e.ziel) { return; }
|
|
505
|
+
|
|
506
|
+
var kennt = {};
|
|
507
|
+
var kenntQuelle = {};
|
|
508
|
+
e.states.forEach(function (s) {
|
|
509
|
+
if (s.n) { kennt[s.n] = s; }
|
|
510
|
+
if (s.srcR) { kenntQuelle[s.srcR] = s; }
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
/* Was im Alias steht, gilt - nicht nur, wie er heisst.
|
|
514
|
+
|
|
515
|
+
Uebernommen wurde bisher allein der Name. Rolle, Typ, Einheit,
|
|
516
|
+
Werteliste, Formeln und vor allem die Schreibquelle blieben die der
|
|
517
|
+
Quelle. Solange jeder Alias entweder aus einer Vorlage entstand oder
|
|
518
|
+
die Rollen der Quelle uebernahm, fiel das nicht auf - beide waren
|
|
519
|
+
gleich. Beim ersten Alias, dessen Rollen sich von denen der Quelle
|
|
520
|
+
unterscheiden (geratene Plaetze), fiel es sofort auf: der Sprung zur
|
|
521
|
+
Quelle zeigte `thermostat` statt `airCondition`, die Schreibquelle
|
|
522
|
+
war weg, und von neun Punkten blieben zwei angehakt.
|
|
523
|
+
|
|
524
|
+
Nur ohne Vorlage. Hat eine gegriffen, ist ihr Vorschlag gemeint -
|
|
525
|
+
sonst uebertoente der Bestand sie stillschweigend, und „aendert
|
|
526
|
+
sich" haette nichts mehr zu melden. */
|
|
527
|
+
function vomAliasUebernehmen(z, o) {
|
|
528
|
+
if (e.vorlage) { return; }
|
|
529
|
+
var c = o.common || {}, a = c.alias || {}, q2 = aliasQuellen(o);
|
|
530
|
+
if (c.role) { z.role = c.role; }
|
|
531
|
+
if (c.type) { z.typ = c.type; }
|
|
532
|
+
z.unit = c.unit || '';
|
|
533
|
+
z.states = c.states || undefined;
|
|
534
|
+
z.f = (typeof a.read === 'string') ? a.read : '';
|
|
535
|
+
z.fw = (typeof a.write === 'string') ? a.write : '';
|
|
536
|
+
if (q2.read) { z.srcR = q2.read; }
|
|
537
|
+
if (q2.write && !q2.einfach && q2.write !== q2.read) {
|
|
538
|
+
z.srcW = q2.write;
|
|
539
|
+
/* Die Gegenzeile eines Paars ist keine eigene mehr - ihre Quelle
|
|
540
|
+
steckt jetzt als Schreibquelle in dieser Zeile. */
|
|
541
|
+
e.states.forEach(function (x) {
|
|
542
|
+
if (x !== z && x.srcR === q2.write) { x.on = false; }
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
e.bestandZog = true;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/* Erstens: was der Vorschlag kennt und im Alias steht, wird angehakt. */
|
|
549
|
+
Object.keys(kennt).forEach(function (n) {
|
|
550
|
+
var s = kennt[n];
|
|
551
|
+
var o0 = S.objects[e.ziel + '.' + n];
|
|
552
|
+
if (!o0) { return; }
|
|
553
|
+
if (!s.on) { s.on = true; }
|
|
554
|
+
s.ausBestand = true;
|
|
555
|
+
vomAliasUebernehmen(s, o0);
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
/* Zweitens — und das ist das Wichtigere: was NUR im Alias steht, kommt
|
|
559
|
+
als eigene Zeile dazu. Vorher war es unsichtbar. Man sah seine selbst
|
|
560
|
+
angelegten Punkte nie wieder, konnte sie weder aendern noch
|
|
561
|
+
entfernen, die Aenderungs-Karte war blind fuer sie, und beim
|
|
562
|
+
Aktualisieren standen sie stumm unter „Entfernen". */
|
|
563
|
+
kindZustaende(e.ziel).forEach(function (id) {
|
|
564
|
+
var n = id.slice(e.ziel.length + 1);
|
|
565
|
+
if (n.indexOf('.') !== -1 || kennt[n]) { return; }
|
|
566
|
+
var o = S.objects[id], c = o.common || {}, a = c.alias || {}, q = aliasQuellen(o);
|
|
567
|
+
|
|
568
|
+
/* Derselbe Punkt unter anderem Namen? Dann ist es kein zweiter,
|
|
569
|
+
sondern derselbe — und der Name, der schon im Alias steht, gilt.
|
|
570
|
+
|
|
571
|
+
Sonst entstuenden Dubletten, sobald die Werkbank ihre Namensgebung
|
|
572
|
+
aendert: der Entwurf nennt einen Punkt heute `Licht_Bar_STATE`, im
|
|
573
|
+
Alias steht er als `1_STATE`, und beide kaemen in die Liste. Und
|
|
574
|
+
schlimmer: ein Aktualisieren wuerde `1_STATE` loeschen und
|
|
575
|
+
`Licht_Bar_STATE` anlegen — jedes Widget und jedes Skript, das auf
|
|
576
|
+
den alten Namen zeigt, liefe ins Leere. Was einmal steht, bleibt
|
|
577
|
+
stehen; neue Punkte bekommen den neuen Namen. */
|
|
578
|
+
if (q.read && kenntQuelle[q.read] && !S.objects[e.ziel + '.' + kenntQuelle[q.read].n]) {
|
|
579
|
+
var vorhanden = kenntQuelle[q.read];
|
|
580
|
+
vorhanden.n = n;
|
|
581
|
+
vorhanden.on = true;
|
|
582
|
+
vorhanden.ausBestand = true;
|
|
583
|
+
vomAliasUebernehmen(vorhanden, o);
|
|
584
|
+
kennt[n] = vorhanden;
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
var nm = txt(c.name);
|
|
588
|
+
e.states.push({
|
|
589
|
+
n: n, on: true, ausBestand: true, nurImAlias: true,
|
|
590
|
+
role: c.role || '', typ: c.type || '', unit: c.unit || '',
|
|
591
|
+
states: c.states || undefined,
|
|
592
|
+
wr: !!c.write,
|
|
593
|
+
srcR: q.read || '', srcW: q.einfach ? '' : (q.write || ''),
|
|
594
|
+
f: (typeof a.read === 'string') ? a.read : '',
|
|
595
|
+
fw: (typeof a.write === 'string') ? a.write : '',
|
|
596
|
+
caption: (nm && nm !== n) ? nm : '',
|
|
597
|
+
manuell: false
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
/* Einmal nachzeichnen.
|
|
602
|
+
|
|
603
|
+
Die Uebernahme aendert Rollen, auf denen die Erkennung dieses
|
|
604
|
+
Durchgangs schon aufgesetzt hatte. `wantAuto` und `want` zieht der
|
|
605
|
+
Aufrufer sofort nach, die Platzhinweise der einzelnen Zeilen und das
|
|
606
|
+
Infogeraet aber stammen aus dem Lauf davor - beim ersten Aufbau
|
|
607
|
+
stand deshalb an der ACTUAL-Zeile „kein Platz im airCondition-Muster",
|
|
608
|
+
obwohl das Feld darueber 9/29 meldete. Nach einem beliebigen
|
|
609
|
+
Neuzeichnen war es weg. Einmal von selbst neu zeichnen, statt den
|
|
610
|
+
Nutzer darauf zu stossen. */
|
|
611
|
+
if (e.bestandZog && !e.bestandNachgezeichnet) {
|
|
612
|
+
e.bestandNachgezeichnet = true;
|
|
613
|
+
setTimeout(function () { if (S.entwurf === e) { zeichneErgebnis(); } }, 0);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
export function unterschiede(e) {
|
|
618
|
+
var raus = [];
|
|
619
|
+
var mu = e.want && musterVon(e.want);
|
|
620
|
+
function hatPlatz(rolle) {
|
|
621
|
+
if (!mu || !rolle) { return false; }
|
|
622
|
+
return mu.states.some(function (st) {
|
|
623
|
+
if (!st.role) { return false; }
|
|
624
|
+
try { return new RegExp(st.role.source || st.role).test(rolle); } catch { return false; }
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
/* Was die Vorlage von sich aus vorgeschlagen hat. Ein Punkt, der
|
|
628
|
+
dort schon auf „Vorgabe aus" steht, ist nicht abgewaehlt worden —
|
|
629
|
+
er war nie an. Vorher landeten bei einer Tasmota alle zwoelf
|
|
630
|
+
Diagnosepunkte in dieser Liste, obwohl niemand etwas geaendert
|
|
631
|
+
hatte. */
|
|
632
|
+
var vorlage = null;
|
|
633
|
+
S.VORLAGEN.forEach(function (v) { if (v.id === e.vorlage) { vorlage = v; } });
|
|
634
|
+
function warVorgabeAn(s) {
|
|
635
|
+
/* Ein Punkt, der nur zu sehen ist, weil „alle Datenpunkte des
|
|
636
|
+
Geraets" eingeschaltet wurde, war nie Teil des Vorschlags. Ihn
|
|
637
|
+
abgewaehlt zu lassen ist keine Abweichung, sondern der Zustand
|
|
638
|
+
von vorher - vorher stand er ueberhaupt nicht in der Liste.
|
|
639
|
+
Gemeldet wird er erst, wenn jemand ihn anhakt. */
|
|
640
|
+
if (s.ausAnsicht) { return false; }
|
|
641
|
+
if (!vorlage) { return true; } /* ohne Vorlage zaehlt jedes Abwaehlen */
|
|
642
|
+
var z = null;
|
|
643
|
+
(vorlage.zustaende || []).forEach(function (x) {
|
|
644
|
+
if (x.name === (s.ausVorlage || s.n)) { z = x; }
|
|
645
|
+
});
|
|
646
|
+
if (!z) { return true; }
|
|
647
|
+
return !z.vorgabeAus;
|
|
648
|
+
}
|
|
649
|
+
var zielBasis = e.ziel || e.kanal;
|
|
650
|
+
|
|
651
|
+
/* Womit wird verglichen? Gibt es den Alias schon, ist er die
|
|
652
|
+
Grundlinie — dann zaehlt, was sich gegenueber dem Gespeicherten
|
|
653
|
+
aendert. Gibt es ihn noch nicht, ist es der Vorschlag der
|
|
654
|
+
Vorlage. */
|
|
655
|
+
var aliasDa = !!S.objects[zielBasis];
|
|
656
|
+
|
|
657
|
+
e.states.forEach(function (s) {
|
|
658
|
+
if (s.manuell) { raus.push({ n: s.n || '(ohne Namen)', was: tr('diff.newByHand') }); return; }
|
|
659
|
+
|
|
660
|
+
var imAlias = !!S.objects[zielBasis + '.' + s.n];
|
|
661
|
+
var grundlinieAn = aliasDa ? imAlias : warVorgabeAn(s);
|
|
662
|
+
|
|
663
|
+
/* Beide Richtungen melden. Vorher wurde nur das Abwaehlen
|
|
664
|
+
betrachtet — wer einen Punkt zusaetzlich anhakte, sah davon
|
|
665
|
+
nichts, obwohl das genauso eine Abweichung ist. */
|
|
666
|
+
if (!s.on && grundlinieAn) {
|
|
667
|
+
raus.push({ n: s.n, was: imAlias ? tr('diff.wouldBeRemoved')
|
|
668
|
+
: (hatPlatz(s.role) ? tr('diff.deselectedWithPlace', e.want)
|
|
669
|
+
: tr('diff.deselectedNoPlace', e.want)) });
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
if (s.on && !grundlinieAn) {
|
|
673
|
+
raus.push({ n: s.n, was: aliasDa ? tr('diff.wouldBeAdded')
|
|
674
|
+
: (hatPlatz(s.role) ? tr('diff.addedWithPlace', e.want)
|
|
675
|
+
: tr('diff.addedNoPlace', e.want)) });
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
if (!s.on) { return; }
|
|
679
|
+
|
|
680
|
+
/* Der Vergleich der Einzelheiten lief bisher ueber s.urId, das
|
|
681
|
+
nur bei einem Entwurf aus einem fertigen Alias gesetzt ist. Bei
|
|
682
|
+
einem Entwurf aus der Quelle blieb er stumm, obwohl es den
|
|
683
|
+
Alias gibt — Rollenwechsel fielen dort durch. */
|
|
684
|
+
var o = S.objects[s.urId] || S.objects[zielBasis + '.' + s.n];
|
|
685
|
+
if (!o) { return; }
|
|
686
|
+
var c = o.common || {}, a = c.alias || {}, q = aliasQuellen(o);
|
|
687
|
+
if ((c.role || '') !== s.role) { raus.push({ n: s.n, was: tr('diff.roleChange', c.role || '—', s.role) }); }
|
|
688
|
+
if ((c.unit || '') !== s.unit) { raus.push({ n: s.n, was: tr('diff.unitChange', c.unit || '—', s.unit || '—') }); }
|
|
689
|
+
var altF = (typeof a.read === 'string') ? a.read : '';
|
|
690
|
+
if (altF !== s.f) { raus.push({ n: s.n, was: tr('diff.formulaChange', altF || '—', s.f || '—') }); }
|
|
691
|
+
var altR = q.read || '';
|
|
692
|
+
if (altR !== s.srcR) { raus.push({ n: s.n, was: tr('diff.sourceChange', altR || '—', s.srcR || '—') }); }
|
|
693
|
+
});
|
|
694
|
+
return raus;
|
|
695
|
+
}
|