iobroker.alias-workbench 0.8.1 → 0.8.3

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.
@@ -11,7 +11,7 @@ import { el } from './basis.js';
11
11
  import { tr } from './sprache.js';
12
12
  import { erkenneEntwurf, musterVon, rolleVonPlatz } from './erkennung.js';
13
13
  import { kindZustaende, wertVon, fmt } from './werte.js';
14
- import { steuerKanaele, vorlagenAbweichung, waehle } from './entwurf.js';
14
+ import { steuerKanaele, vorlagenAbweichung, bestandsAbweichung, waehle } from './entwurf.js';
15
15
  import { musterName } from './musternamen.js';
16
16
  import { detailZeile } from './detail.js';
17
17
  import { rateAnzahl, rateZurueck, rateZurueckEine, rateBehalten } from './vorschlagen.js';
@@ -97,7 +97,7 @@ export function berechnePlaetze(e, haupt) {
97
97
  - und die Vorbelegung machte es sofort wieder zunichte: die neun
98
98
  uebernommenen Zeilen hatten im thermostat-Muster keinen Platz und
99
99
  wurden abgewaehlt, uebrig blieben zwei. */
100
- var bestandDa = e.ziel && S.objects[e.ziel] && kindZustaende(e.ziel).length > 0;
100
+ var bestandDa = !!(e.ziel && kindZustaende(e.ziel).length > 0);
101
101
  if (!e.vorbelegt && !e.vorlage && S.current.indexOf('alias.') !== 0) {
102
102
  e.vorbelegt = true;
103
103
  if (bestandDa) {
@@ -206,6 +206,10 @@ export function baueListe(host, e, pl, rateKnopf, musterBlock) {
206
206
  }
207
207
 
208
208
  var bar = el('div', 'listbar');
209
+ /* Wird beim Zeichnen der Zeilen weiter unten hochgezaehlt; die Legende
210
+ dazu haengt sich erst danach in die Leiste, weil vorher niemand
211
+ weiss, ob es ueberhaupt eine braucht. */
212
+ var ohnePlatzZahl = 0;
209
213
  var an = e.states.filter(function (s) { return s.on; }).length;
210
214
  bar.appendChild(document.createTextNode(tr('list.willBeCreated')));
211
215
  bar.appendChild(el('span', 'cnt', tr('list.countOf', an, e.states.length)));
@@ -325,8 +329,19 @@ export function baueListe(host, e, pl, rateKnopf, musterBlock) {
325
329
  e.states.forEach(function (s, i) {
326
330
  var pl = platzVon[s.n];
327
331
  var unfertig = (!s.n || !s.srcR);
328
- var row = el('div', 'erow' + (s.on ? '' : ' skip') + (S.openRow === i ? ' open' : ''));
332
+ /* Angehakt, vollstaendig, aber ohne Platz im Muster. Frueher stand
333
+ dazu in JEDER betroffenen Zeile derselbe Satz — bei einem
334
+ Thermostat mit 42 Punkten zwanzigmal dasselbe, und die Spalte
335
+ wurde so breit, dass Rolle und Wert wegrutschten (Ricardo,
336
+ 06.09.2026). Jetzt traegt die Zeile eine Marke, der Satz steht
337
+ einmal als Legende ueber der Liste, und der lange Text haengt als
338
+ Hinweis an der Zeile. */
339
+ var ohnePlatz = (s.on && !unfertig && !pl);
340
+ if (ohnePlatz) { ohnePlatzZahl++; }
341
+ var row = el('div', 'erow' + (s.on ? '' : ' skip') + (S.openRow === i ? ' open' : '') +
342
+ (ohnePlatz ? ' ohneplatz' : ''));
329
343
  row.tabIndex = 0;
344
+ if (ohnePlatz) { row.title = tr('pattern.noPlaceLong', musterName(e.want) || e.want || '?'); }
330
345
 
331
346
  var cbw = el('span');
332
347
  var cb = document.createElement('input');
@@ -359,20 +374,49 @@ export function baueListe(host, e, pl, rateKnopf, musterBlock) {
359
374
  if (s.manuell) { n3.appendChild(el('span', 'hand', tr('list.byHand'))); }
360
375
  if (s.geaendert) { n3.appendChild(el('span', 'geae', tr('list.changed'))); }
361
376
  /* Was die Vorlage anders will, steht an der Zeile - sonst sieht man
362
- es erst im Trockenlauf (Ricardo, 25.08.2026). */
363
- if (s.on && !s.geaendert) {
377
+ es erst im Trockenlauf (Ricardo, 25.08.2026).
378
+
379
+ Nicht mehr an `!s.geaendert` gebunden: Seit man ein einzelnes Feld
380
+ aus der Vorlage uebernehmen kann, ist die Zeile danach „geaendert"
381
+ — und haette die Marke daran gehangen, waeren die uebrigen
382
+ Abweichungen in dem Moment unsichtbar geworden. Massgeblich ist,
383
+ ob wirklich noch etwas abweicht. Eine Zeile kann beides tragen:
384
+ „geaendert" und „weicht von der Vorlage ab" (06.09.2026). */
385
+ if (s.on) {
364
386
  var abw = vorlagenAbweichung(s);
365
387
  if (abw.length) {
366
- /* Formeln koennen lang sein - die Marke soll die Zeile nicht
367
- sprengen; der Tooltip zeigt alles. */
368
- var wert = String(abw[0].vorlage || '—');
369
- if (wert.length > 28) { wert = wert.slice(0, 27) + '…'; }
370
- var av = el('span', 'geae tplabw', tr('list.tplDiffers', wert));
388
+ /* Nur, DASS etwas abweicht — nicht was.
389
+
390
+ Die Marke nannte frueher den Wert der ersten Abweichung
391
+ („Vorlage: indicator.lowbat"). Bei mehreren Feldern log sie
392
+ damit: sie zeigte eines und verschwieg die anderen, und lang
393
+ war sie obendrein. Welches Feld es betrifft, sieht man
394
+ aufgeklappt an der Markierung; der Tooltip hier zaehlt alle
395
+ auf (Ricardo, 06.09.2026). */
396
+ var av = el('span', 'geae tplabw', tr('list.tplDiffers'));
371
397
  av.title = abw.map(function (x) {
372
398
  return x.feld + ': ' + (x.jetzt || '—') + ' → ' + (x.vorlage || '—');
373
399
  }).join(String.fromCharCode(10));
374
400
  n3.appendChild(av);
375
401
  }
402
+ /* Und dieselbe Auskunft gegen den gespeicherten Alias.
403
+
404
+ Wer das Muster oder die Vorlage wechselt, bekommt die Rollen
405
+ angepasst — das ist gewollt (`switch.light` passt auf kein
406
+ socket-SET). Nur sah man an der Zeile nicht, dass damit etwas
407
+ anderes geschrieben wuerde als bisher dasteht; sichtbar war es
408
+ allein an den Chips oben und im Trockenlauf. Drei Aussagen, drei
409
+ Marken, jede mit eigener Bedeutung: „geaendert" heisst, der
410
+ Nutzer war es; „weicht von der Vorlage ab" vergleicht mit der
411
+ Vorlage; diese hier mit der Datenbank (Ricardo, 06.09.2026). */
412
+ var bAbw = bestandsAbweichung(s, e.ziel);
413
+ if (bAbw.length) {
414
+ var bv = el('span', 'geae bstabw', tr('list.aliasDiffers'));
415
+ bv.title = bAbw.map(function (x) {
416
+ return x.feld + ': ' + (x.bestand || '—') + ' → ' + (x.jetzt || '—');
417
+ }).join(String.fromCharCode(10));
418
+ n3.appendChild(bv);
419
+ }
376
420
  }
377
421
  /* Die Marke ist zugleich der Griff: solange sie steht, ist die Zeile
378
422
  unbestaetigt und faellt beim Zuruecknehmen. Ein Haken laesst sie
@@ -418,14 +462,12 @@ export function baueListe(host, e, pl, rateKnopf, musterBlock) {
418
462
  var pe = el('em', null, pl);
419
463
  pe.title = tr('pattern.slotName', pl, musterName(e.want) || e.want || '?');
420
464
  n3.appendChild(pe);
421
- } else if (!pl) {
422
- /* Frueher stand der Vermerk nur an Zeilen, die das info-Muster
423
- aufnaehme (imInfo). SABOTAGE mit indicator.alarm nimmt aber
424
- nicht mal das - solche Zeilen blieben stumm, und oben stand
425
- „3/7 belegt“ bei vier Haken ohne jede Erklaerung (Ricardo,
426
- 25.08.2026). Angehakt ohne Platz heisst immer: sagen. */
427
- n3.appendChild(el('em', null, tr('pattern.noPlaceIn', musterName(e.want) || e.want || '?')));
428
465
  }
466
+ /* Kein Vermerk mehr je Zeile: die Marke an der Zeile und die
467
+ Legende ueber der Liste sagen dasselbe, einmal statt zwanzigmal.
468
+ Dass es ueberhaupt gesagt wird, bleibt wichtig — frueher blieben
469
+ solche Zeilen stumm, und oben stand „3/7 belegt“ bei vier Haken
470
+ ohne jede Erklaerung (Ricardo, 25.08.2026). */
429
471
  }
430
472
  row.appendChild(n3);
431
473
 
@@ -511,5 +553,18 @@ export function baueListe(host, e, pl, rateKnopf, musterBlock) {
511
553
  zeichneErgebnis();
512
554
  });
513
555
  card.appendChild(add);
556
+
557
+ /* Die Legende zum Streifen — einmal, und nur wenn es etwas zu erklaeren
558
+ gibt. Sie steht in der Leiste ueber der Liste, gleich neben der Zahl:
559
+ dort sucht man die Erklaerung fuer „11 von 42", nicht am Fuss. */
560
+ if (ohnePlatzZahl) {
561
+ var lg = el('span', 'legende');
562
+ lg.appendChild(el('span', 'lgmarke'));
563
+ lg.appendChild(document.createTextNode(
564
+ tr('pattern.noPlaceIn', musterName(e.want) || e.want || '?')));
565
+ lg.title = tr('pattern.noPlaceLong', musterName(e.want) || e.want || '?');
566
+ bar.insertBefore(lg, bar.querySelector('.sp2'));
567
+ }
568
+
514
569
  host.appendChild(card);
515
570
  }
package/admin/tab.html CHANGED
@@ -144,5 +144,16 @@
144
144
  <div class="dfoot"><button class="btn" data-close>Schlie&szlig;en</button></div>
145
145
  </dialog>
146
146
 
147
+ <!-- Wer im Baum weiterklickt, verlor bis zum 06.09.2026 seine Aenderungen
148
+ ohne ein Wort (Ricardo). Der Text wird zur Laufzeit gesetzt. -->
149
+ <dialog id="dlg-leave">
150
+ <h3 id="leave-titel">Ungespeicherte &Auml;nderungen</h3>
151
+ <div class="dbody"><p id="leave-body"></p></div>
152
+ <div class="dfoot">
153
+ <button class="btn" id="btn-leave-stay">Hierbleiben</button>
154
+ <button class="btn primary" id="btn-leave-go">Verwerfen und wechseln</button>
155
+ </div>
156
+ </dialog>
157
+
147
158
  </body>
148
159
  </html>
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "alias-workbench",
4
- "version": "0.8.1",
4
+ "version": "0.8.3",
5
5
  "news": {
6
+ "0.8.3": {
7
+ "en": "What is stored in an existing alias now holds: its caption stays, a read-only alias stays read-only, and that applies to every point, including several pointing at one and the same source. An alias whose channel exists only as an id is compared at all now, and the interface no longer announces a creation where it changes. The dry run shows enumerations as a comparison, and a line reading from another adapter gets its value on the first click.",
8
+ "de": "Was in einem vorhandenen Alias steht, gilt jetzt: die Beschriftung bleibt, ein Nur-Lese-Alias bleibt lesend, und das für jeden Punkt — auch wenn mehrere auf dieselbe Quelle zeigen. Ein Alias, dessen Kanal nur als Kennung besteht, wird überhaupt verglichen, und die Oberfläche kündigt kein Anlegen mehr an, wo sie ändert. Der Trockenlauf zeigt Aufzählungen im Vergleich, und eine Zeile aus einem anderen Adapter bekommt ihren Wert schon beim ersten Klick.",
9
+ "ru": "То, что записано в существующем алиасе, теперь имеет приоритет: подпись сохраняется, алиас только для чтения остаётся таким же, и это касается каждой точки — даже если несколько указывают на один источник. Алиас, канал которого существует лишь как идентификатор, теперь вообще сравнивается, а интерфейс больше не объявляет создание там, где он изменяет. Пробный прогон показывает перечисления в сравнении, а строка из другого адаптера получает значение уже при первом щелчке.",
10
+ "pt": "O que está guardado num alias existente passa a valer: a legenda mantém-se, um alias só de leitura continua só de leitura, e isso para cada ponto — mesmo quando vários apontam para a mesma fonte. Um alias cujo canal existe apenas como identificador passa a ser comparado, e a interface deixa de anunciar uma criação onde altera. A simulação mostra as enumerações em comparação, e uma linha de outro adaptador recebe o seu valor logo no primeiro clique.",
11
+ "nl": "Wat in een bestaande alias staat, geldt nu: het opschrift blijft, een alleen-lezen alias blijft alleen-lezen, en dat voor elk punt — ook als meerdere naar dezelfde bron wijzen. Een alias waarvan het kanaal alleen als id bestaat, wordt nu überhaupt vergeleken, en de interface kondigt geen aanmaak meer aan waar zij wijzigt. De proefronde toont opsommingen in vergelijking, en een regel uit een andere adapter krijgt zijn waarde al bij de eerste klik.",
12
+ "fr": "Ce qui figure dans un alias existant fait désormais foi : la légende reste, un alias en lecture seule le demeure, et cela pour chaque point — même lorsque plusieurs pointent vers la même source. Un alias dont le canal n’existe que comme identifiant est enfin comparé, et l’interface n’annonce plus une création là où elle modifie. La simulation montre les énumérations en comparaison, et une ligne provenant d’un autre adaptateur obtient sa valeur dès le premier clic.",
13
+ "it": "Quello che è memorizzato in un alias esistente ora vale: la didascalia resta, un alias di sola lettura rimane tale, e questo per ogni punto — anche quando più punti indicano la stessa sorgente. Un alias il cui canale esiste solo come identificatore viene finalmente confrontato, e l’interfaccia non annuncia più una creazione dove modifica. La prova a vuoto mostra le enumerazioni a confronto, e una riga che legge da un altro adattatore ottiene il suo valore già al primo clic.",
14
+ "es": "Lo que está guardado en un alias existente ahora manda: el rótulo se mantiene, un alias de solo lectura sigue siéndolo, y eso para cada punto — incluso cuando varios apuntan a la misma fuente. Un alias cuyo canal existe solo como identificador por fin se compara, y la interfaz ya no anuncia una creación donde modifica. La simulación muestra las enumeraciones en comparación, y una línea que lee de otro adaptador obtiene su valor ya en el primer clic.",
15
+ "pl": "To, co zapisano w istniejącym aliasie, teraz obowiązuje: podpis zostaje, alias tylko do odczytu pozostaje taki, i dotyczy to każdego punktu — także gdy kilka wskazuje to samo źródło. Alias, którego kanał istnieje wyłącznie jako identyfikator, jest wreszcie porównywany, a interfejs nie zapowiada już tworzenia tam, gdzie zmienia. Przebieg próbny pokazuje wyliczenia w porównaniu, a wiersz czytający z innego adaptera dostaje wartość już przy pierwszym kliknięciu.",
16
+ "uk": "Те, що записано в наявному аліасі, тепер має силу: підпис залишається, аліас лише для читання таким і лишається, і це для кожної точки — навіть коли кілька вказують на те саме джерело. Аліас, канал якого існує лише як ідентифікатор, нарешті порівнюється, а інтерфейс більше не оголошує створення там, де змінює. Пробний прогін показує переліки в порівнянні, а рядок з іншого адаптера отримує значення вже при першому кліку.",
17
+ "zh-cn": "现有别名中已保存的内容现在具有优先权:标题保留,只读别名仍为只读,并且对每个数据点都适用——即使多个点指向同一数据源。通道仅以标识符形式存在的别名现在也会被比对,界面不再在修改时宣告“新建”。试运行会以对比方式显示枚举,来自其他适配器的数据行在第一次点击时就能取到值。"
18
+ },
19
+ "0.8.2": {
20
+ "en": "A second alias on the same source is now announced instead of created silently — with a button to move the existing one instead. Switching to a template that finds nothing now works. Roles the workbench adapted are marked and can be taken back. Escape discards in every field of the target bar. New adapter icon.",
21
+ "de": "Ein zweiter Alias auf dieselbe Quelle wird jetzt angesagt statt stillschweigend angelegt — daneben ein Knopf, der stattdessen den vorhandenen verlegt. Der Wechsel auf eine Vorlage, die nichts findet, greift jetzt. Angepasste Rollen sind markiert und lassen sich zurückholen. Escape verwirft in jedem Feld des Zielbalkens. Neues Adaptersymbol.",
22
+ "ru": "Второй алиас на тот же источник теперь объявляется, а не создаётся молча — рядом кнопка, чтобы вместо этого перенести существующий. Переключение на шаблон, который ничего не находит, теперь работает. Изменённые роли помечаются и могут быть возвращены. Escape отменяет ввод в каждом поле целевой строки. Новый значок адаптера.",
23
+ "pt": "Um segundo alias sobre a mesma fonte passa a ser anunciado em vez de criado em silêncio — com um botão para mover o existente. A mudança para um modelo que não encontra nada passa a funcionar. Os papéis adaptados são assinalados e podem ser revertidos. Escape descarta em todos os campos da barra de destino. Novo ícone do adaptador.",
24
+ "nl": "Een tweede alias op dezelfde bron wordt nu gemeld in plaats van stil aangemaakt — met een knop om de bestaande te verplaatsen. Overschakelen naar een sjabloon dat niets vindt werkt nu. Aangepaste rollen worden gemarkeerd en kunnen worden teruggehaald. Escape verwerpt in elk veld van de doelbalk. Nieuw adapterpictogram.",
25
+ "fr": "Un deuxième alias sur la même source est désormais signalé au lieu d’être créé en silence — avec un bouton pour déplacer celui qui existe. Le passage à un modèle qui ne trouve rien fonctionne maintenant. Les rôles adaptés sont marqués et peuvent être repris. Échap annule dans chaque champ de la barre de destination. Nouvelle icône d’adaptateur.",
26
+ "it": "Un secondo alias sulla stessa sorgente viene ora annunciato invece che creato in silenzio — con un pulsante per spostare quello esistente. Il passaggio a un modello che non trova nulla ora funziona. I ruoli adattati sono contrassegnati e si possono ripristinare. Esc annulla in ogni campo della barra di destinazione. Nuova icona dell’adattatore.",
27
+ "es": "Un segundo alias sobre la misma fuente ahora se anuncia en lugar de crearse en silencio — con un botón para mover el existente. Cambiar a una plantilla que no encuentra nada ya funciona. Los roles adaptados se marcan y se pueden recuperar. Escape descarta en cada campo de la barra de destino. Nuevo icono del adaptador.",
28
+ "pl": "Drugi alias na to samo źródło jest teraz zapowiadany, a nie tworzony po cichu — obok przycisk, który zamiast tego przenosi istniejący. Przełączenie na szablon, który nic nie znajduje, teraz działa. Zmienione role są oznaczone i można je cofnąć. Escape odrzuca w każdym polu paska celu. Nowa ikona adaptera.",
29
+ "uk": "Другий аліас на те саме джерело тепер оголошується, а не створюється мовчки — поруч кнопка, щоб натомість перенести наявний. Перемикання на шаблон, який нічого не знаходить, тепер працює. Змінені ролі позначені й їх можна повернути. Escape скасовує в кожному полі цільового рядка. Нова піктограма адаптера.",
30
+ "zh-cn": "同一数据源上的第二个别名现在会有提示,而不是被静默创建——旁边有按钮可改为移动已有的别名。切换到没有匹配项的模板现在也能生效。被调整过的角色会被标记,并可撤回。Escape 在目标栏的每个字段中都会放弃输入。新的适配器图标。"
31
+ },
6
32
  "0.8.1": {
7
33
  "en": "Published through npm trusted publishing (OIDC) — releases are signed with provenance from now on. No functional changes.",
8
34
  "de": "Veröffentlichung über npm Trusted Publishing (OIDC) — Ausgaben sind ab jetzt mit Herkunftsnachweis signiert. Keine funktionalen Änderungen.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.alias-workbench",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "Creates aliases the comfortable way — devices that vis, Alexa and the device adapter understand. Templates do the work: shipped ones for HomeMatic and Tasmota, your own for everything else. Live values while you build, dry run before anything is written.",
5
5
  "author": {
6
6
  "name": "Ricardo Hipp",