iobroker.alias-workbench 0.8.0 → 0.8.2
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 +269 -224
- package/admin/alias-workbench.png +0 -0
- package/admin/alias-workbench.svg +13 -0
- package/admin/css/werkbank.css +69 -0
- package/admin/i18n/de.json +15 -1
- package/admin/i18n/en.json +15 -1
- package/admin/js/baum.js +12 -2
- package/admin/js/detail.js +119 -7
- package/admin/js/entwurf.js +93 -5
- package/admin/js/ergebnis.js +15 -2
- package/admin/js/erkennung.js +87 -0
- package/admin/js/quellentausch.js +16 -0
- package/admin/js/schreiben.js +30 -5
- package/admin/js/vorlagen.js +13 -4
- package/admin/js/zielleiste.js +70 -2
- package/admin/js/zuordnung.js +15 -0
- package/admin/js/zustandsliste.js +71 -16
- package/admin/tab.html +11 -0
- package/io-package.json +27 -14
- package/package.json +2 -3
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
|
2
|
+
<!-- hinten: die rohe Quelle, blasser Ton, Punkte ohne Ordnung -->
|
|
3
|
+
<rect x="4" y="4" width="74" height="74" rx="16" fill="#7CBCC1"/>
|
|
4
|
+
<circle cx="24.5" cy="27" r="6.2" fill="#fff" opacity=".8"/>
|
|
5
|
+
<circle cx="44" cy="36" r="6.2" fill="#fff" opacity=".8"/>
|
|
6
|
+
<circle cx="26" cy="56" r="6.2" fill="#fff" opacity=".8"/>
|
|
7
|
+
<!-- vorn: der fertige Alias, ausgerichtet und benannt -->
|
|
8
|
+
<rect x="46" y="46" width="78" height="78" rx="18" fill="#0E7C86"/>
|
|
9
|
+
<circle cx="67.5" cy="70" r="6.5" fill="#fff"/>
|
|
10
|
+
<rect x="82" y="64.5" width="27" height="11" rx="5.5" fill="#fff"/>
|
|
11
|
+
<circle cx="67.5" cy="100" r="6.5" fill="#fff"/>
|
|
12
|
+
<rect x="82" y="94.5" width="27" height="11" rx="5.5" fill="#fff"/>
|
|
13
|
+
</svg>
|
package/admin/css/werkbank.css
CHANGED
|
@@ -285,6 +285,43 @@
|
|
|
285
285
|
border-bottom:1px solid var(--line); font-family:var(--mono); font-size:11.5px;
|
|
286
286
|
}
|
|
287
287
|
.detail .dr { display:grid; grid-template-columns:88px 1fr; gap:8px; padding:3px 0; align-items:start; }
|
|
288
|
+
/* Feld, an dem die Vorlage etwas anderes will. Dieselbe Farbe wie die
|
|
289
|
+
Marke an der zugeklappten Zeile — wer sie dort gesehen hat, sucht
|
|
290
|
+
hier nach ihr. Die dritte Spalte traegt den Uebernahme-Knopf; sie
|
|
291
|
+
bleibt schmal und leer, solange nichts abweicht. */
|
|
292
|
+
.detail .dr.abw { grid-template-columns:88px 1fr 26px;
|
|
293
|
+
background:color-mix(in srgb, var(--warn-soft) 70%, transparent);
|
|
294
|
+
border-radius:var(--r-sm); padding:3px 4px; margin:0 -4px; }
|
|
295
|
+
.detail .dr.abw .k { color:var(--warn); }
|
|
296
|
+
/* Der Wert der Vorlage, sichtbar unter dem Feld — er stand vorher nur
|
|
297
|
+
im Tooltip der Zeile und war damit hinter jedem Feld versteckt. */
|
|
298
|
+
.detail .tplwert { grid-column:2 / -1; font-size:10.5px; color:var(--warn);
|
|
299
|
+
font-family:var(--sans); padding-top:1px; }
|
|
300
|
+
.detail .tplwert b { font-family:var(--mono); font-weight:600; }
|
|
301
|
+
/* Die Abweichung vom gespeicherten Alias — dieselbe Bauart wie die
|
|
302
|
+
Vorlagenabweichung, aber in der Akzentfarbe statt in der Warnfarbe:
|
|
303
|
+
Was in der Datenbank steht, ist kein Missstand, sondern der Stand,
|
|
304
|
+
mit dem man vergleicht. Eine Zeile kann beides tragen. */
|
|
305
|
+
.detail .dr.bstabw { grid-template-columns:88px 1fr 26px;
|
|
306
|
+
background:color-mix(in srgb, var(--accent) 8%, transparent);
|
|
307
|
+
border-radius:var(--r-sm); padding:3px 4px; margin:0 -4px; }
|
|
308
|
+
.detail .dr.abw.bstabw { background:linear-gradient(
|
|
309
|
+
to right,
|
|
310
|
+
color-mix(in srgb, var(--warn-soft) 70%, transparent) 0 50%,
|
|
311
|
+
color-mix(in srgb, var(--accent) 8%, transparent) 50% 100%); }
|
|
312
|
+
.detail .bstwert { grid-column:2 / -1; font-size:10.5px; color:var(--accent);
|
|
313
|
+
font-family:var(--sans); padding-top:1px; }
|
|
314
|
+
.detail .bstwert b { font-family:var(--mono); font-weight:600; }
|
|
315
|
+
.detail .bstnimm { align-self:center; border-color:var(--accent); color:var(--accent);
|
|
316
|
+
background:transparent; cursor:pointer; }
|
|
317
|
+
.detail .bstnimm:hover { background:var(--accent); color:var(--surface); }
|
|
318
|
+
.erow .geae.bstabw { border-color:var(--accent); color:var(--accent);
|
|
319
|
+
background:color-mix(in srgb, var(--accent) 10%, transparent); }
|
|
320
|
+
.btn.winzig { font-size:11px; line-height:1; padding:3px 6px; min-width:0;
|
|
321
|
+
border-radius:var(--r-sm); }
|
|
322
|
+
.detail .abwnimm { align-self:center; border-color:var(--warn); color:var(--warn);
|
|
323
|
+
background:transparent; cursor:pointer; }
|
|
324
|
+
.detail .abwnimm:hover { background:var(--warn); color:var(--surface); }
|
|
288
325
|
.detail .k {
|
|
289
326
|
font-family:var(--sans); font-size:9px; text-transform:uppercase; letter-spacing:.06em;
|
|
290
327
|
color:var(--ink-3); font-weight:700; padding-top:3px;
|
|
@@ -444,6 +481,28 @@
|
|
|
444
481
|
/* Abgewaehlt heisst ausgegraut, nicht durchgestrichen - der Haken
|
|
445
482
|
fehlt ja sichtbar, und durchgestrichen liest sich der Name schlecht. */
|
|
446
483
|
.erow.skip { opacity:.42; }
|
|
484
|
+
/* Angehakt, aber ohne Platz im Muster: die Zeile bekommt einen Ton,
|
|
485
|
+
statt in jeder einzelnen denselben Satz zu wiederholen.
|
|
486
|
+
|
|
487
|
+
Gedaempft, nicht laut: der Punkt wird ja angelegt und ist voll
|
|
488
|
+
benutzbar — nur Alexa & Co. zaehlen ihn separat. Das ist eine
|
|
489
|
+
Auskunft, keine Warnung. Ueber `transparent` gemischt, damit
|
|
490
|
+
derselbe Anteil in hell wie in dunkel traegt.
|
|
491
|
+
|
|
492
|
+
Der Hover braucht eine eigene Zeile: sonst gewaenne bei gleicher
|
|
493
|
+
Spezifitaet die spaeter stehende Regel, und die Zeile reagierte
|
|
494
|
+
nicht mehr auf den Zeiger. */
|
|
495
|
+
.erow.ohneplatz { background:color-mix(in srgb, var(--warn-soft) 80%, transparent); }
|
|
496
|
+
.erow.ohneplatz:hover, .erow.ohneplatz.open {
|
|
497
|
+
background:color-mix(in srgb, var(--warn-soft) 100%, transparent); }
|
|
498
|
+
.listbar .legende { display:inline-flex; align-items:center; gap:5px;
|
|
499
|
+
font-size:11px; color:var(--ink-3); white-space:nowrap; }
|
|
500
|
+
/* Dasselbe Feld wie die Zeile, nur klein — die Legende zeigt die Farbe,
|
|
501
|
+
nach der man in der Liste sucht. */
|
|
502
|
+
.listbar .legende .lgmarke { width:14px; height:11px; border-radius:3px;
|
|
503
|
+
border:1px solid var(--line);
|
|
504
|
+
background:color-mix(in srgb, var(--warn-soft) 80%, transparent);
|
|
505
|
+
display:inline-block; }
|
|
447
506
|
.erow input[type="checkbox"] { accent-color:var(--accent); cursor:pointer; margin:0; }
|
|
448
507
|
.erow .mk2 { text-align:center; font-size:11px; }
|
|
449
508
|
.erow .mk2.ok { color:var(--ok); } .erow .mk2.bad { color:var(--bad); } .erow .mk2.out { color:var(--ink-3); }
|
|
@@ -775,6 +834,16 @@
|
|
|
775
834
|
background:color-mix(in srgb, var(--accent) 14%, transparent);
|
|
776
835
|
}
|
|
777
836
|
}
|
|
837
|
+
/* Der Zwilling-Hinweis: es gibt schon einen Alias auf diese Quelle.
|
|
838
|
+
|
|
839
|
+
Das ist keine Frage wie das Raum-Angebot daneben, sondern eine
|
|
840
|
+
Auskunft - deshalb kein Pochen, sondern die ruhige Warnfarbe. Sie
|
|
841
|
+
haelt niemanden auf: der Knopf zum Anlegen bleibt, wo er war. */
|
|
842
|
+
.uebernahme.zwilling .zq {
|
|
843
|
+
color:var(--warn); font-weight:600;
|
|
844
|
+
background:color-mix(in srgb, var(--warn) 12%, transparent);
|
|
845
|
+
}
|
|
846
|
+
|
|
778
847
|
.enumbar .enumfeld { padding-right:22px; }
|
|
779
848
|
|
|
780
849
|
/* Trockenlauf: eine Zeile je Objekt, das JSON aufklappbar darunter. */
|
package/admin/i18n/de.json
CHANGED
|
@@ -45,6 +45,8 @@
|
|
|
45
45
|
"del.now": "Endgültig entfernen",
|
|
46
46
|
"del.objects": "Was verschwindet",
|
|
47
47
|
"del.title": "Alias entfernen",
|
|
48
|
+
"detail.aliasEmpty": "Im Alias ist dieses Feld leer.",
|
|
49
|
+
"detail.aliasHas": "Im Alias steht: ",
|
|
48
50
|
"detail.asDelivered": "wie geliefert",
|
|
49
51
|
"detail.attention": "Achtung",
|
|
50
52
|
"detail.caption": "Beschriftung",
|
|
@@ -80,6 +82,10 @@
|
|
|
80
82
|
"detail.separateHint": "getrennt — der Schalter zeigt den Zustand, nicht den Befehl",
|
|
81
83
|
"detail.sourceGone": "Quelle existiert nicht",
|
|
82
84
|
"detail.stateSays": "Zustand sagt {0}",
|
|
85
|
+
"detail.takeFromAlias": "Diesen einen Wert aus dem gespeicherten Alias zurückholen",
|
|
86
|
+
"detail.takeOne": "Diesen einen Wert aus der Vorlage übernehmen",
|
|
87
|
+
"detail.tplWants": "Die Vorlage will hier: ",
|
|
88
|
+
"detail.tplWantsEmpty": "Die Vorlage lässt dieses Feld leer.",
|
|
83
89
|
"detail.type": "Typ",
|
|
84
90
|
"detail.unit": "Einheit",
|
|
85
91
|
"detail.willBecome": "entsteht als",
|
|
@@ -160,7 +166,12 @@
|
|
|
160
166
|
"info.explain": "funktionieren ganz normal und liegen da, wo du sie angelegt hast. Es entsteht dadurch kein zusätzliches Objekt — der Alias bleibt, wie er ist. Sie gehören nur nicht zu dem, was ioBroker unter einem {0} versteht; dafür passt ihre Rolle nicht. Bedeutung hat das erst, wenn du den Alias an Alexa, Google Home oder eine Gerätesteuerung hängst: die sehen dann ein {0} ohne diese Punkte. In VIS, in Skripten und im Verlauf benutzt du sie wie jeden anderen Datenpunkt.",
|
|
161
167
|
"info.notPartOf": "Gehört nicht zum {0}",
|
|
162
168
|
"info.sameDatapoints": "{0} — ",
|
|
169
|
+
"leave.body": "An {0} sind Änderungen offen, die noch nicht geschrieben wurden. Wechselst du jetzt, sind sie weg.",
|
|
170
|
+
"leave.discard": "Verwerfen und wechseln",
|
|
171
|
+
"leave.stay": "Hierbleiben",
|
|
172
|
+
"leave.title": "Ungespeicherte Änderungen",
|
|
163
173
|
"list.addByHand": "Datenpunkt von Hand hinzufügen",
|
|
174
|
+
"list.aliasDiffers": "weicht vom gespeicherten Alias ab",
|
|
164
175
|
"list.all": "alle",
|
|
165
176
|
"list.byHand": "von Hand",
|
|
166
177
|
"list.changed": "geändert",
|
|
@@ -181,7 +192,7 @@
|
|
|
181
192
|
"list.sendPointMissing": "Sendepunkt fehlt noch",
|
|
182
193
|
"list.sourceMissing": "Quelle fehlt",
|
|
183
194
|
"list.tpl": "Vorlage",
|
|
184
|
-
"list.tplDiffers": "Vorlage
|
|
195
|
+
"list.tplDiffers": "weicht von der Vorlage ab",
|
|
185
196
|
"list.tplHint": "Hakt genau die Punkte an, die die Vorlage vorschlägt — unabhängig davon, was heute im Alias steht.",
|
|
186
197
|
"list.willBeCreated": "angelegt werden",
|
|
187
198
|
"move.button": "Verlegen …",
|
|
@@ -327,8 +338,11 @@
|
|
|
327
338
|
"target.folder": "Ablegen unter",
|
|
328
339
|
"target.folderHint": "Unterordner mit Punkt trennen, z. B. Haus.EG.Küche",
|
|
329
340
|
"target.folderPlaceholder": "leer = direkt unter alias.0",
|
|
341
|
+
"target.moveInstead": "stattdessen verlegen …",
|
|
342
|
+
"target.moveInsteadHint": "Den vorhandenen Alias auf die neue Kennung verlegen, statt einen zweiten daneben anzulegen.",
|
|
330
343
|
"target.name": "Name",
|
|
331
344
|
"target.openFolder": "„{0}\" öffnen",
|
|
345
|
+
"target.twinExists": "Für diese Quelle gibt es schon {0} — der bleibt stehen.",
|
|
332
346
|
"target.yes": "ja",
|
|
333
347
|
"tpl.applyTemplate": "Werte der Vorlage übernehmen ({0})",
|
|
334
348
|
"tpl.applyTemplateHint": "Setzt Rollen, Typen, Einheiten, Formeln und Quellen auf den Stand der Vorlage. Die Beschriftung bleibt, wie sie ist — die gehört dir. Geschrieben wird erst nach dem Trockenlauf.",
|
package/admin/i18n/en.json
CHANGED
|
@@ -45,6 +45,8 @@
|
|
|
45
45
|
"del.now": "Remove for good",
|
|
46
46
|
"del.objects": "What disappears",
|
|
47
47
|
"del.title": "Remove alias",
|
|
48
|
+
"detail.aliasEmpty": "The alias leaves this field empty.",
|
|
49
|
+
"detail.aliasHas": "The alias has: ",
|
|
48
50
|
"detail.asDelivered": "as delivered",
|
|
49
51
|
"detail.attention": "Attention",
|
|
50
52
|
"detail.caption": "Caption",
|
|
@@ -80,6 +82,10 @@
|
|
|
80
82
|
"detail.separateHint": "separate — the switch shows the state, not the command",
|
|
81
83
|
"detail.sourceGone": "source does not exist",
|
|
82
84
|
"detail.stateSays": "state says {0}",
|
|
85
|
+
"detail.takeFromAlias": "Take this one value back from the stored alias",
|
|
86
|
+
"detail.takeOne": "Take this one value from the template",
|
|
87
|
+
"detail.tplWants": "The template wants: ",
|
|
88
|
+
"detail.tplWantsEmpty": "The template leaves this field empty.",
|
|
83
89
|
"detail.type": "Type",
|
|
84
90
|
"detail.unit": "Unit",
|
|
85
91
|
"detail.willBecome": "will become",
|
|
@@ -160,7 +166,12 @@
|
|
|
160
166
|
"info.explain": "work perfectly normally and stay where you created them. Nothing extra is written — the alias stays as it is. They simply are not part of what ioBroker considers a {0}; their role does not fit any of its slots. It only starts to matter once you hand the alias to Alexa, Google Home or a device UI: those will see a {0} without these points. In VIS, in scripts and in history you use them like any other datapoint.",
|
|
161
167
|
"info.notPartOf": "Not part of the {0}",
|
|
162
168
|
"info.sameDatapoints": "{0} — ",
|
|
169
|
+
"leave.body": "There are changes on {0} that have not been written yet. Switching now discards them.",
|
|
170
|
+
"leave.discard": "Discard and switch",
|
|
171
|
+
"leave.stay": "Stay here",
|
|
172
|
+
"leave.title": "Unsaved changes",
|
|
163
173
|
"list.addByHand": "Add datapoint by hand",
|
|
174
|
+
"list.aliasDiffers": "differs from the stored alias",
|
|
164
175
|
"list.all": "all",
|
|
165
176
|
"list.byHand": "by hand",
|
|
166
177
|
"list.changed": "changed",
|
|
@@ -181,7 +192,7 @@
|
|
|
181
192
|
"list.sendPointMissing": "send datapoint not created yet",
|
|
182
193
|
"list.sourceMissing": "source missing",
|
|
183
194
|
"list.tpl": "template",
|
|
184
|
-
"list.tplDiffers": "template
|
|
195
|
+
"list.tplDiffers": "differs from the template",
|
|
185
196
|
"list.tplHint": "Checks exactly the points the template proposes — regardless of what the alias holds today.",
|
|
186
197
|
"list.willBeCreated": "will be created:",
|
|
187
198
|
"move.button": "Move …",
|
|
@@ -327,8 +338,11 @@
|
|
|
327
338
|
"target.folder": "Place under",
|
|
328
339
|
"target.folderHint": "separate subfolders with a dot, e.g. House.GF.Kitchen",
|
|
329
340
|
"target.folderPlaceholder": "empty = directly under alias.0",
|
|
341
|
+
"target.moveInstead": "move it instead …",
|
|
342
|
+
"target.moveInsteadHint": "Move the existing alias to the new id instead of creating a second one next to it.",
|
|
330
343
|
"target.name": "Name",
|
|
331
344
|
"target.openFolder": "open “{0}”",
|
|
345
|
+
"target.twinExists": "This source already has {0} — that one stays where it is.",
|
|
332
346
|
"target.yes": "yes",
|
|
333
347
|
"tpl.applyTemplate": "take template values ({0})",
|
|
334
348
|
"tpl.applyTemplateHint": "Sets roles, types, units, formulas and sources to what the template says. The caption stays as it is — that one is yours. Nothing is written before the dry run.",
|
package/admin/js/baum.js
CHANGED
|
@@ -8,7 +8,7 @@ import { S } from './zustand.js';
|
|
|
8
8
|
import { $, el } from './basis.js';
|
|
9
9
|
import { tr, txt, expertenVorgabe } from './sprache.js';
|
|
10
10
|
import './enums.js';
|
|
11
|
-
import {
|
|
11
|
+
import { mitNachfrage } from './entwurf.js';
|
|
12
12
|
import { zeichneErgebnis } from './ergebnis.js';
|
|
13
13
|
import { zeichneVorlagenListe } from './vorlagenblatt.js';
|
|
14
14
|
|
|
@@ -354,7 +354,17 @@ function renderKinder(knoten, filter, tiefe) {
|
|
|
354
354
|
if (waehlbar) {
|
|
355
355
|
d.tabIndex = 0;
|
|
356
356
|
d.setAttribute('role', 'button');
|
|
357
|
-
|
|
357
|
+
/* Erst fragen, dann wechseln — solange am aktuellen Entwurf etwas
|
|
358
|
+
offen ist. Vorher fielen Aenderungen bei einem Klick ins Leere,
|
|
359
|
+
ohne ein Wort (Ricardo, 06.09.2026): Rolle geaendert, im Baum
|
|
360
|
+
weitergeklickt, alles weg.
|
|
361
|
+
|
|
362
|
+
Die Frage haengt an `angefasst`, nicht an `geaendert` einer
|
|
363
|
+
einzelnen Zeile: Auch Raum, Funktion, Ordner und Name gehoeren
|
|
364
|
+
dazu, und die stehen nicht in den Zeilen. Geschrieben wird
|
|
365
|
+
dadurch nichts — es geht nur darum, dass niemand etwas verliert,
|
|
366
|
+
ohne gefragt zu werden. */
|
|
367
|
+
var go = function () { mitNachfrage(k.id); };
|
|
358
368
|
d.addEventListener('click', go);
|
|
359
369
|
d.addEventListener('keydown', function (e) {
|
|
360
370
|
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); go(); }
|
package/admin/js/detail.js
CHANGED
|
@@ -8,7 +8,7 @@ import { wertVon, jsonFelder, feldAusFormel, feldFormel, feldWert, jsonVon } fro
|
|
|
8
8
|
import { musterVon, erkenneEntwurf } from './erkennung.js';
|
|
9
9
|
import { musterName } from './musternamen.js';
|
|
10
10
|
import { rollenFeld } from './rollenwahl.js';
|
|
11
|
-
import { opt , quellenAuswahl } from './entwurf.js';
|
|
11
|
+
import { opt , quellenAuswahl, vorlagenAbweichung, bestandsAbweichung } from './entwurf.js';
|
|
12
12
|
import { zeichneErgebnis, entwurfAngefasst } from './ergebnis.js';
|
|
13
13
|
|
|
14
14
|
import { rateBehalten } from './vorschlagen.js';
|
|
@@ -28,6 +28,118 @@ export function detailZeile(e, s, idx) {
|
|
|
28
28
|
keine mehr und faellt beim Zuruecknehmen nicht mehr weg. */
|
|
29
29
|
function neu() { s.geaendert = true; rateBehalten(s); entwurfAngefasst(); zeichneErgebnis(); }
|
|
30
30
|
|
|
31
|
+
/* ---- Wo die Vorlage etwas anderes will --------------------------
|
|
32
|
+
|
|
33
|
+
Die zugeklappte Zeile sagt nur, DASS etwas abweicht. Welches Feld,
|
|
34
|
+
steht hier: die betroffene Zeile wird getoent, ihr Tooltip nennt den
|
|
35
|
+
Wert der Vorlage, und ein Knopf daneben uebernimmt genau diesen
|
|
36
|
+
einen Wert (Ricardo, 06.09.2026).
|
|
37
|
+
|
|
38
|
+
Vorher gab es die Uebernahme nur als Sammelaktion ueber der Liste —
|
|
39
|
+
alles oder nichts. Wer eine Rolle angleichen wollte, ohne die
|
|
40
|
+
Formeln mitzunehmen, musste tippen.
|
|
41
|
+
|
|
42
|
+
`geaendert` wird dabei ABSICHTLICH nicht gesetzt: Sonst faellt die
|
|
43
|
+
Marke an der Zeile weg (sie haengt an `!s.geaendert`), und die
|
|
44
|
+
restlichen Abweichungen waeren unsichtbar. Wer alle uebernimmt,
|
|
45
|
+
dessen Marke verschwindet von selbst — dann weicht ja nichts mehr
|
|
46
|
+
ab. */
|
|
47
|
+
var abwListe = vorlagenAbweichung(s);
|
|
48
|
+
var abwNach = {};
|
|
49
|
+
abwListe.forEach(function (x) { abwNach[x.feld] = x; });
|
|
50
|
+
|
|
51
|
+
function zeigeAbweichung(r, felder) {
|
|
52
|
+
if (!r) { return; }
|
|
53
|
+
var treffer = felder.filter(function (f) { return abwNach[f]; });
|
|
54
|
+
if (!treffer.length) { return; }
|
|
55
|
+
r.classList.add('abw');
|
|
56
|
+
|
|
57
|
+
var b = el('button', 'btn winzig abwnimm', '←');
|
|
58
|
+
b.addEventListener('click', function (ev) {
|
|
59
|
+
ev.stopPropagation();
|
|
60
|
+
var v = s.vorlagenWert;
|
|
61
|
+
if (!v) { return; }
|
|
62
|
+
treffer.forEach(function (f) { s[f] = v[f]; });
|
|
63
|
+
/* Uebernehmen ist eine Aenderung wie jede andere — die Zeile traegt
|
|
64
|
+
danach „geaendert". Dass die Marke „weicht von der Vorlage ab"
|
|
65
|
+
dabei nicht verschwindet, sorgt die Zeichenseite: sie haengt
|
|
66
|
+
seit dem 06.09.2026 daran, ob wirklich noch etwas abweicht, und
|
|
67
|
+
nicht mehr an `!geaendert`. Sonst waeren nach der ersten
|
|
68
|
+
Uebernahme die uebrigen Abweichungen unsichtbar. */
|
|
69
|
+
s.geaendert = true;
|
|
70
|
+
rateBehalten(s);
|
|
71
|
+
entwurfAngefasst();
|
|
72
|
+
zeichneErgebnis();
|
|
73
|
+
});
|
|
74
|
+
r.appendChild(b);
|
|
75
|
+
|
|
76
|
+
/* Der Wert der Vorlage gehoert HINGESCHRIEBEN, nicht in einen
|
|
77
|
+
Tooltip: der hing an der Zeile, und sobald der Zeiger ueber dem
|
|
78
|
+
Auswahlfeld oder dem Knopf stand, zeigte der Browser deren
|
|
79
|
+
Tooltip. Man musste die getoente Flaeche danebentreffen, um zu
|
|
80
|
+
erfahren, was man da uebernimmt (Ricardo, 06.09.2026). */
|
|
81
|
+
var hin = el('div', 'tplwert');
|
|
82
|
+
treffer.forEach(function (f, i) {
|
|
83
|
+
if (i) { hin.appendChild(document.createTextNode(' ')); }
|
|
84
|
+
var v = abwNach[f].vorlage;
|
|
85
|
+
hin.appendChild(document.createTextNode(
|
|
86
|
+
v ? tr('detail.tplWants', '') : tr('detail.tplWantsEmpty')));
|
|
87
|
+
if (v) { hin.appendChild(el('b', null, String(v))); }
|
|
88
|
+
});
|
|
89
|
+
b.title = tr('detail.takeOne');
|
|
90
|
+
r.appendChild(hin);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* Dasselbe gegen den gespeicherten Alias.
|
|
94
|
+
|
|
95
|
+
Getrennt von der Vorlagenabweichung, weil es eine andere Aussage ist:
|
|
96
|
+
dort steht, was die Vorlage wollte, hier, was in der Datenbank steht.
|
|
97
|
+
Eine Zeile kann beides tragen — etwa nach einem Musterwechsel, der
|
|
98
|
+
die Rolle anpasst: Die neue Rolle weicht dann vom Alias ab, und je
|
|
99
|
+
nachdem auch von der Vorlage (Ricardo, 06.09.2026). */
|
|
100
|
+
var bstListe = bestandsAbweichung(s, e.ziel);
|
|
101
|
+
var bstNach = {};
|
|
102
|
+
bstListe.forEach(function (x) { bstNach[x.feld] = x; });
|
|
103
|
+
|
|
104
|
+
function zeigeBestand(r, felder) {
|
|
105
|
+
if (!r) { return; }
|
|
106
|
+
var treffer = felder.filter(function (f) { return bstNach[f]; });
|
|
107
|
+
if (!treffer.length) { return; }
|
|
108
|
+
r.classList.add('bstabw');
|
|
109
|
+
|
|
110
|
+
var b2 = el('button', 'btn winzig bstnimm', '⟲');
|
|
111
|
+
b2.title = tr('detail.takeFromAlias');
|
|
112
|
+
b2.addEventListener('click', function (ev) {
|
|
113
|
+
ev.stopPropagation();
|
|
114
|
+
treffer.forEach(function (f) { s[f] = bstNach[f].bestand; });
|
|
115
|
+
/* Zurueckholen ist eine Entscheidung wie das Uebernehmen aus der
|
|
116
|
+
Vorlage — die Zeile traegt danach „geaendert". Die Marke bleibt,
|
|
117
|
+
solange noch etwas abweicht; sie haengt nicht an `geaendert`. */
|
|
118
|
+
s.geaendert = true;
|
|
119
|
+
rateBehalten(s);
|
|
120
|
+
entwurfAngefasst();
|
|
121
|
+
zeichneErgebnis();
|
|
122
|
+
});
|
|
123
|
+
r.appendChild(b2);
|
|
124
|
+
|
|
125
|
+
var hin2 = el('div', 'bstwert');
|
|
126
|
+
treffer.forEach(function (f, i) {
|
|
127
|
+
if (i) { hin2.appendChild(document.createTextNode(' ')); }
|
|
128
|
+
var v = bstNach[f].bestand;
|
|
129
|
+
hin2.appendChild(document.createTextNode(
|
|
130
|
+
v ? tr('detail.aliasHas', '') : tr('detail.aliasEmpty')));
|
|
131
|
+
if (v) { hin2.appendChild(el('b', null, String(v))); }
|
|
132
|
+
});
|
|
133
|
+
r.appendChild(hin2);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Beide Auskuenfte an derselben Zeile: erst was die Vorlage will,
|
|
137
|
+
dann was im Alias steht. */
|
|
138
|
+
function zeigeBeide(r, felder) {
|
|
139
|
+
zeigeAbweichung(r, felder);
|
|
140
|
+
zeigeBestand(r, felder);
|
|
141
|
+
}
|
|
142
|
+
|
|
31
143
|
/* --- Name, nur bei selbst angelegten --- */
|
|
32
144
|
if (s.manuell) {
|
|
33
145
|
var iN = el('input', 'tx w');
|
|
@@ -103,7 +215,7 @@ export function detailZeile(e, s, idx) {
|
|
|
103
215
|
lF.appendChild(selF);
|
|
104
216
|
qf.appendChild(lF);
|
|
105
217
|
}
|
|
106
|
-
zeile(tr('detail.readsFrom'), qf);
|
|
218
|
+
zeigeBeide(zeile(tr('detail.readsFrom'), qf), ['srcR']);
|
|
107
219
|
|
|
108
220
|
if (s.frei) {
|
|
109
221
|
var iFrei = el('input', 'tx w');
|
|
@@ -143,7 +255,7 @@ export function detailZeile(e, s, idx) {
|
|
|
143
255
|
if (s.srcW && s.srcW !== s.srcR) {
|
|
144
256
|
wf.appendChild(el('div', 'sugg', tr('detail.separateHint')));
|
|
145
257
|
}
|
|
146
|
-
zeile(tr('detail.writesTo'), wf);
|
|
258
|
+
zeigeBeide(zeile(tr('detail.writesTo'), wf), ['srcW']);
|
|
147
259
|
|
|
148
260
|
/* --- Leseformel --- */
|
|
149
261
|
var fb = el('div');
|
|
@@ -159,7 +271,7 @@ export function detailZeile(e, s, idx) {
|
|
|
159
271
|
if ((s.typ || '') === 'boolean') {
|
|
160
272
|
fb.appendChild(el('div', 'sugg', tr('detail.formulaHint')));
|
|
161
273
|
}
|
|
162
|
-
zeile(tr('detail.formula'), fb);
|
|
274
|
+
zeigeBeide(zeile(tr('detail.formula'), fb), ['f']);
|
|
163
275
|
|
|
164
276
|
if (s.srcW) {
|
|
165
277
|
var wb = el('div');
|
|
@@ -171,7 +283,7 @@ export function detailZeile(e, s, idx) {
|
|
|
171
283
|
iW.addEventListener('change', function () { s.fw = iW.value.trim(); neu(); });
|
|
172
284
|
wb.appendChild(iW);
|
|
173
285
|
wb.appendChild(el('div', 'sugg', tr('detail.writeFormulaHint')));
|
|
174
|
-
zeile(tr('detail.writeFormula'), wb);
|
|
286
|
+
zeigeBeide(zeile(tr('detail.writeFormula'), wb), ['fw']);
|
|
175
287
|
}
|
|
176
288
|
|
|
177
289
|
/* --- Rolle, mit Begründung --- */
|
|
@@ -211,7 +323,7 @@ export function detailZeile(e, s, idx) {
|
|
|
211
323
|
}
|
|
212
324
|
rb.appendChild(hin);
|
|
213
325
|
}
|
|
214
|
-
zeile(tr('detail.role'), rb);
|
|
326
|
+
zeigeBeide(zeile(tr('detail.role'), rb), ['role']);
|
|
215
327
|
|
|
216
328
|
/* --- Typ und Anzeige --- */
|
|
217
329
|
var af = el('div', 'fields');
|
|
@@ -268,7 +380,7 @@ export function detailZeile(e, s, idx) {
|
|
|
268
380
|
lC.appendChild(el('span', 'sugg', tr('detail.captionHint')));
|
|
269
381
|
af.appendChild(lC);
|
|
270
382
|
|
|
271
|
-
zeile(tr('detail.display'), af);
|
|
383
|
+
zeigeBeide(zeile(tr('detail.display'), af), ['typ', 'unit']);
|
|
272
384
|
|
|
273
385
|
/* --- Rohwert und Ergebnis --- */
|
|
274
386
|
var a = wertVon(s);
|
package/admin/js/entwurf.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { S } from './zustand.js';
|
|
6
6
|
import { socket } from './verbindung.js';
|
|
7
7
|
import { $ } from './basis.js';
|
|
8
|
-
import { txt } from './sprache.js';
|
|
8
|
+
import { txt, tr } from './sprache.js';
|
|
9
9
|
import './enums.js';
|
|
10
10
|
import { zusatzName, setzeModus, zeichneBaum, merkeKlappstand } from './baum.js';
|
|
11
11
|
import { kindZustaende, aliasQuellen, holeWerte } from './werte.js';
|
|
@@ -251,14 +251,56 @@ export function quelleVon(aliasId) {
|
|
|
251
251
|
return knotenDa(beste) ? beste : null;
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/* Vor dem Wechsel fragen, wenn am Entwurf etwas offen ist.
|
|
255
|
+
|
|
256
|
+
Drei Wege wechseln die Auswahl auf Wunsch des Nutzers, und alle drei
|
|
257
|
+
gehen hier durch: der Klick im Baum, „zur Quelle →" / „zum Alias →"
|
|
258
|
+
und die Zeilen der Ordneruebersicht. Vorher fielen Aenderungen dabei
|
|
259
|
+
ins Leere, ohne ein Wort (Ricardo, 06.09.2026).
|
|
260
|
+
|
|
261
|
+
Nicht hier durch gehen die Wechsel, die die Werkbank selbst ausloest:
|
|
262
|
+
nach dem Schreiben, nach dem Verlegen, nach dem Quellentausch. Dort
|
|
263
|
+
ist der Entwurf gerade geschrieben worden, es gibt nichts zu retten.
|
|
264
|
+
Ebenso wenig der Knopf „zuruecksetzen" — der WILL verwerfen, und wer
|
|
265
|
+
ihn drueckt, hat die Frage schon beantwortet.
|
|
266
|
+
|
|
267
|
+
Sie haengt an `angefasst`, nicht an `geaendert` einer einzelnen Zeile:
|
|
268
|
+
Raum, Funktion, Ordner und Name gehoeren genauso dazu und stehen in
|
|
269
|
+
keiner Zeile. */
|
|
270
|
+
export function mitNachfrage(id, dann) {
|
|
271
|
+
var lauf = function () { if (dann) { dann(); } else { waehle(id); } };
|
|
272
|
+
var e = S.entwurf;
|
|
273
|
+
if (!e || !e.angefasst || id === S.current) { lauf(); return; }
|
|
274
|
+
|
|
275
|
+
var dlg = $('#dlg-leave');
|
|
276
|
+
if (!dlg) { lauf(); return; } /* aeltere Fassung: nicht blockieren */
|
|
277
|
+
|
|
278
|
+
var was = (e.ziel || e.kanal || S.current || '').split('.').slice(-2).join('.');
|
|
279
|
+
$('#leave-titel').textContent = tr('leave.title');
|
|
280
|
+
$('#leave-body').textContent = tr('leave.body', was);
|
|
281
|
+
|
|
282
|
+
var bleib = $('#btn-leave-stay');
|
|
283
|
+
var weiter = $('#btn-leave-go');
|
|
284
|
+
bleib.textContent = tr('leave.stay');
|
|
285
|
+
weiter.textContent = tr('leave.discard');
|
|
286
|
+
|
|
287
|
+
/* Bei jedem Aufruf neu verkabeln — sonst haengt der Handler des
|
|
288
|
+
vorigen Aufrufs mit dem alten Ziel daran. */
|
|
289
|
+
bleib.onclick = function () { dlg.close(); };
|
|
290
|
+
weiter.onclick = function () { dlg.close(); lauf(); };
|
|
291
|
+
dlg.showModal();
|
|
292
|
+
}
|
|
293
|
+
|
|
254
294
|
/* Der Sprung selbst: Baummodus umstellen, Filter fallen lassen, waehlen.
|
|
255
295
|
Ohne das Leeren des Filters landet man auf einem Knoten, den der
|
|
256
296
|
Baum gerade ausblendet. */
|
|
257
297
|
export function springeZu(id, modus) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
298
|
+
mitNachfrage(id, function () {
|
|
299
|
+
var q0 = $('#q');
|
|
300
|
+
if (q0) { q0.value = ''; }
|
|
301
|
+
if (S.baumModus !== modus) { setzeModus(modus); }
|
|
302
|
+
waehle(id);
|
|
303
|
+
});
|
|
262
304
|
}
|
|
263
305
|
|
|
264
306
|
/* Was in `common` der Werkbank gehoert - und was nicht.
|
|
@@ -868,6 +910,52 @@ export function bestandVorrang(e, aliasId) {
|
|
|
868
910
|
return e;
|
|
869
911
|
}
|
|
870
912
|
|
|
913
|
+
/* Wo weicht der Entwurf vom gespeicherten Alias ab?
|
|
914
|
+
|
|
915
|
+
Das ist die Gegenrichtung zu `vorlagenAbweichung`: Dort wird gegen das
|
|
916
|
+
verglichen, was die Vorlage will, hier gegen das, was schon in der
|
|
917
|
+
Datenbank steht.
|
|
918
|
+
|
|
919
|
+
Der Fall, fuer den es gebaut ist: Wer das Muster oder die Vorlage
|
|
920
|
+
wechselt, bekommt die Rollen automatisch angepasst — `switch.light`
|
|
921
|
+
passt auf kein socket-SET, also baut die Werkbank sie um. Das ist
|
|
922
|
+
richtig so, nur sah man an der Zeile nicht, dass damit etwas anderes
|
|
923
|
+
geschrieben wuerde als bisher dasteht. Sichtbar war es allein an den
|
|
924
|
+
Sammelchips oben und im Trockenlauf (Ricardo, 06.09.2026).
|
|
925
|
+
|
|
926
|
+
Verglichen wird gegen das Objekt, nicht gegen eine Kopie: Nach einem
|
|
927
|
+
Vorlagenwechsel traegt die Zeile den Vorlagenstand, und `vorlagenWert`
|
|
928
|
+
haelt genau denselben — eine Kopie brachte hier also nichts. */
|
|
929
|
+
export function bestandsAbweichung(s, aliasId) {
|
|
930
|
+
if (!s || !s.n || !s.on || !aliasId) { return []; }
|
|
931
|
+
var o = S.objects[aliasId + '.' + s.n];
|
|
932
|
+
if (!o || !o.common) { return []; }
|
|
933
|
+
var c = o.common, a = c.alias || {}, q = aliasQuellen(o);
|
|
934
|
+
var ist = {
|
|
935
|
+
role: c.role || '', typ: c.type || '', unit: c.unit || '',
|
|
936
|
+
f: (typeof a.read === 'string') ? a.read : '',
|
|
937
|
+
fw: (typeof a.write === 'string') ? a.write : '',
|
|
938
|
+
srcR: q.read || '',
|
|
939
|
+
srcW: q.einfach
|
|
940
|
+
? ((c.write === true || typeof a.write === 'string') ? (q.write || '') : '')
|
|
941
|
+
: (q.write || '')
|
|
942
|
+
};
|
|
943
|
+
var raus = [];
|
|
944
|
+
['role', 'typ', 'unit', 'f', 'fw', 'srcR', 'srcW'].forEach(function (k) {
|
|
945
|
+
var jetzt = s[k] || '';
|
|
946
|
+
if (jetzt !== ist[k]) { raus.push({ feld: k, jetzt: jetzt, bestand: ist[k] }); }
|
|
947
|
+
});
|
|
948
|
+
return raus;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
/* Einen einzelnen Wert aus dem gespeicherten Alias zurueckholen. */
|
|
952
|
+
export function bestandsWert(s, aliasId, feld) {
|
|
953
|
+
var abw = bestandsAbweichung(s, aliasId);
|
|
954
|
+
var tr0 = null;
|
|
955
|
+
abw.forEach(function (x) { if (x.feld === feld) { tr0 = x; } });
|
|
956
|
+
return tr0 ? tr0.bestand : null;
|
|
957
|
+
}
|
|
958
|
+
|
|
871
959
|
/* Wo weicht die Vorlage vom Bestand ab? Liefert je Zeile die Felder, die
|
|
872
960
|
„Vorlage anwenden" aendern wuerde - die Beschriftung ausgenommen. */
|
|
873
961
|
export function vorlagenAbweichung(s) {
|
package/admin/js/ergebnis.js
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
quelleVon,
|
|
25
25
|
springeZu,
|
|
26
26
|
waehle,
|
|
27
|
+
mitNachfrage,
|
|
27
28
|
geraeteDarunter,
|
|
28
29
|
aliasFuer,
|
|
29
30
|
tipptGerade,
|
|
@@ -148,7 +149,10 @@ var warumAuf = false;
|
|
|
148
149
|
|
|
149
150
|
(function () {
|
|
150
151
|
var b = $('#btn-move');
|
|
151
|
-
|
|
152
|
+
/* Nicht direkt anhaengen: `zeigeVerlegen` nimmt seit dem Knopf
|
|
153
|
+
„stattdessen verlegen" zwei Vorgaben entgegen, und der Zuhoerer
|
|
154
|
+
wuerde ihm das Klickereignis als erste durchreichen. */
|
|
155
|
+
if (b) { b.addEventListener('click', function () { zeigeVerlegen(); }); }
|
|
152
156
|
var bt = $('#btn-swap');
|
|
153
157
|
if (bt) { bt.addEventListener('click', zeigeTausch); }
|
|
154
158
|
var btg = $('#btn-swap-go');
|
|
@@ -513,7 +517,16 @@ var warumAuf = false;
|
|
|
513
517
|
S.entwurf = v;
|
|
514
518
|
S.openRow = null;
|
|
515
519
|
zeichneErgebnis();
|
|
520
|
+
return;
|
|
516
521
|
}
|
|
522
|
+
/* Kommt kein Entwurf zurueck, bleibt die alte Vorlage in Kraft — das
|
|
523
|
+
Feld darf dann nicht die neue anzeigen. Bis 06.09.2026 fehlte
|
|
524
|
+
dieser Zweig: Der Wechsel scheiterte still, und wer das Feld las,
|
|
525
|
+
glaubte, die Vorlage sei gewechselt (Ricardo). Seit derselben
|
|
526
|
+
Aenderung entsteht ein Entwurf auch ohne jeden Treffer, der Fall
|
|
527
|
+
ist also selten geworden — aber nicht unmoeglich. */
|
|
528
|
+
selV.value = e.vorlage || '';
|
|
529
|
+
zeichneErgebnis();
|
|
517
530
|
});
|
|
518
531
|
lv.appendChild(selV);
|
|
519
532
|
acts.appendChild(lv);
|
|
@@ -862,7 +875,7 @@ var warumAuf = false;
|
|
|
862
875
|
row.appendChild(al);
|
|
863
876
|
row.appendChild(el('span', 'ca2', '›'));
|
|
864
877
|
|
|
865
|
-
var geh = function () {
|
|
878
|
+
var geh = function () { mitNachfrage(g.id); };
|
|
866
879
|
row.addEventListener('click', geh);
|
|
867
880
|
row.addEventListener('keydown', function (ev) {
|
|
868
881
|
if (ev.key === 'Enter' || ev.key === ' ') { ev.preventDefault(); geh(); }
|