iobroker.alias-workbench 0.8.3 → 0.9.7
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 +146 -3
- package/admin/css/werkbank.css +57 -8
- package/admin/detector.js +1 -1
- package/admin/geraetewissen/tasmota-befehle.json +3 -1
- package/admin/i18n/de.json +30 -6
- package/admin/i18n/en.json +30 -6
- package/admin/js/aufzaehlungen.js +11 -1
- package/admin/js/baum.js +118 -37
- package/admin/js/detail.js +76 -9
- package/admin/js/entwurf.js +313 -43
- package/admin/js/enums.js +50 -7
- package/admin/js/ergebnis.js +161 -37
- package/admin/js/erkennung.js +54 -5
- package/admin/js/katalog.js +12 -3
- package/admin/js/mqtt.js +76 -13
- package/admin/js/musternamen.js +91 -26
- package/admin/js/musterwahl.js +10 -0
- package/admin/js/objekte.js +29 -3
- package/admin/js/pruefungen.js +10 -2
- package/admin/js/quellentausch.js +31 -2
- package/admin/js/schreiben.js +209 -24
- package/admin/js/sprache.js +54 -7
- package/admin/js/start.js +32 -2
- package/admin/js/vorlagen.js +114 -6
- package/admin/js/vorlagenblatt.js +195 -26
- package/admin/js/werte.js +113 -6
- package/admin/js/zuordnung.js +71 -17
- package/admin/js/zustand.js +7 -1
- package/admin/js/zustandsliste.js +157 -26
- package/admin/tab.html +25 -3
- package/admin/vorlagen/hm-dimmer.json +1 -1
- package/admin/vorlagen/hm-schaltaktor-lampe.json +2 -2
- package/admin/vorlagen/hm-schaltaktor-mehrfach.json +2 -2
- package/admin/vorlagen/hm-schaltaktor-steckdose.json +2 -2
- package/io-package.json +105 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,6 +44,63 @@ which pattern slots are filled and which are still free.
|
|
|
44
44
|
|
|
45
45
|
*One row opened: where it reads from, which JSON field, the read function, the role — and the pattern slot that role fills.*
|
|
46
46
|
|
|
47
|
+
**JSON is unpacked without you writing a formula.** Many devices do not deliver
|
|
48
|
+
their readings as separate datapoints but as a single JSON — a Tasmota puts
|
|
49
|
+
everything into `tele/SENSOR`. Where the workbench finds valid JSON in a
|
|
50
|
+
source, it takes it apart and offers its fields in a drop-down:
|
|
51
|
+
`ENERGY.Power`, `ENERGY.Total`, `Wifi.Signal`. One click is enough, the
|
|
52
|
+
matching formula appears by itself — and in the guarded form:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
JSON.parse(val)?.ENERGY?.Power ?? null
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The `?.` is not decoration. `tele/SENSOR` is a catch-all whose contents differ
|
|
59
|
+
from device to device and from message to message; the bare
|
|
60
|
+
`JSON.parse(val).ENERGY.Power` fails the moment `ENERGY` is absent — the alias
|
|
61
|
+
then delivers nothing at all and the controller writes a warning to the log.
|
|
62
|
+
With `?.` the result is simply `null`. And if the field is `0`, `0` is what
|
|
63
|
+
you get, not "no value": `??` only steps in for `null` and `undefined`.
|
|
64
|
+
|
|
65
|
+
It works in both directions. Where a row already carries a formula, the
|
|
66
|
+
workbench reads it back and shows the field it means instead of "custom
|
|
67
|
+
formula" — including the bare spelling without `?.`. Only something that
|
|
68
|
+
really does more than access a field (`JSON.parse(val)?.POWER === "ON"`) stays
|
|
69
|
+
a custom formula and is left alone. And what you wrote yourself stays: if your
|
|
70
|
+
formula differs from the one the template proposes, the row says so — it is
|
|
71
|
+
changed only when you ask for it.
|
|
72
|
+
|
|
73
|
+
**Role, room and function are kept in order too.** An alias is more than a
|
|
74
|
+
bundle of datapoints, and the workbench maintains the three things that make a
|
|
75
|
+
device recognisable as a device in ioBroker:
|
|
76
|
+
|
|
77
|
+
- **The roles of the points** come from the template or the pattern, and they
|
|
78
|
+
follow along when you switch the pattern — `switch.light` does not fit a
|
|
79
|
+
`socket` SET. The role picker is grouped by pattern slot and shows which
|
|
80
|
+
slot a role would fill and whether it is still free. Where a slot accepts
|
|
81
|
+
several spellings, all of them are offered: `LOWBAT` takes
|
|
82
|
+
`indicator.lowbat` just as well as `indicator.maintenance.lowbat` — so
|
|
83
|
+
whatever your own hardware writes is among them. Deprecated spellings stay
|
|
84
|
+
out.
|
|
85
|
+
- **The role of the channel** is the device type itself (`light`, `blind`,
|
|
86
|
+
`thermostat`), the way the admin's device adapter keeps it — that is what
|
|
87
|
+
other adapters recognise it by.
|
|
88
|
+
- **Room and function** do not live on the object but in `enum.rooms.*` and
|
|
89
|
+
`enum.functions.*`. The workbench proposes both — the room from the source,
|
|
90
|
+
its name or the target folder, the function from the template or the
|
|
91
|
+
detected device type — enters the alias there when writing, and takes it out
|
|
92
|
+
again when you change the assignment. Move the alias and the assignment
|
|
93
|
+
moves with it; other members of the same enumeration are left untouched.
|
|
94
|
+
- **And their pictures.** The admin ships ready-made room and function
|
|
95
|
+
templates with icons. Where an existing enumeration has none — ones mirrored
|
|
96
|
+
from a Homematic CCU never do — the workbench fills it in. Next to the field
|
|
97
|
+
you see beforehand what is going to happen. See
|
|
98
|
+
[Room and function](#room-and-function).
|
|
99
|
+
|
|
100
|
+
None of this happens out of sight: every one of these changes appears in the
|
|
101
|
+
dry run before anything is written — including the ones to enumerations, which
|
|
102
|
+
are, after all, other people's objects.
|
|
103
|
+
|
|
47
104
|
**Templates.** A template describes how a device source becomes a finished alias
|
|
48
105
|
device. Templates are plain JSON files, one per template — see
|
|
49
106
|
[Template format](#template-format). Sixteen ship with the adapter: four for
|
|
@@ -510,6 +567,95 @@ imported, and that both language files carry the same keys.
|
|
|
510
567
|
|
|
511
568
|
## Changelog
|
|
512
569
|
|
|
570
|
+
### 0.9.7
|
|
571
|
+
This version was measured on the **production system** — 24,786 objects, 140 aliases. None of it shows on the test system with 2,731 objects.
|
|
572
|
+
|
|
573
|
+
* The search box no longer blocks. The tree was rebuilt completely on **every** keystroke: a measured **236 ms per keystroke, 1.9 seconds for eight**. It now draws once, 180 ms after the last keystroke — typing stays responsive. Plus three savings in the tree itself: collapsed nodes are no longer built as DOM at all (previously every subtree was created and immediately thrown away), the question “can this be expanded?” is answered once per row instead of on every sort comparison, and an `Intl.Collator` replaces `localeCompare` with an options object. **The whole tree: 263 → 67 ms.**
|
|
574
|
+
* A redraw no longer costs half a second. `kindZustaende`, `aliasFuer` and their neighbours walked the sorted index **linearly** — 24,786 comparisons for ten hits, some twenty times per redraw, and with live values that is every 700 ms. The list is sorted and the range sits together: a binary search finds it in fifteen steps. Plus a reverse map source → alias built once per index state. **Drawing a source 15.8 → 1.6 ms, an alias with 50 points 51.9 → 14.2 ms.** Proven equal: 3,025 devices and all 727 alias points checked against the old versions, zero differences
|
|
575
|
+
* A read formula can no longer freeze the tab for good. Formulas from `common.alias.read` and from templates run as JavaScript in the admin — on every redraw, per row, unasked. That is no new privilege escalation (whoever may write the formula already has it running in the js-controller), but it is an execution site without limits: `try/catch` does not catch an endless loop. Results are now remembered per formula and raw value — 2000 evaluations in 0.6 ms — and whatever once took longer than 250 ms does not run again; the row says why
|
|
576
|
+
* The object counter in the header no longer gets stuck. Four places set the index directly instead of calling `indexNeu()`, so the short-name map kept deleted ids and `hatPunkt` returned hits on points that no longer existed
|
|
577
|
+
* A full detector run per redraw is gone. Its result travelled through two intermediate steps into a parameter nobody reads. Also removed: `e.andere` and the dead symbols `bestandsWert` and `anzeigeText`
|
|
578
|
+
* The write-source rule lives in one place instead of five. It was spelled out identically three times in `entwurf.js` and twice in `zuordnung.js` — and the comments at two of those sites each document a bug that came from exactly that
|
|
579
|
+
* **Correction to 0.9.6:** adapter and instance roots were meant to become unselectable there — but the check used `_tiefe`, which is the height of the subtree **below** a node, not its position in the tree. On the test system that excluded 131 nodes, exactly one of them rightly: the other 130 were branches such as `…Decklenlicht_RGB.cmnd` and folders such as `iot.0.smart`, whose data points sit directly below. Selectable nodes dropped from 449 to 320. The position is checked now; `mqtt-client` and `mqtt-client.0` stay locked, everything else is back
|
|
580
|
+
|
|
581
|
+
### 0.9.6
|
|
582
|
+
**Display and flow**
|
|
583
|
+
* “All data points” keeps the output and the manual choice. On a multi-output template at output 2 the rows of output 1 came back while the target still read `…Ausgang_2`; and if automatic matching had found nothing and you picked the template by hand, the click dropped you into raw mode with the choice gone
|
|
584
|
+
* “Differs from the alias” now also shows in alias mode. The marker was handed the target, which is never set there — you are already standing on the alias. So it never appeared exactly where it says the most
|
|
585
|
+
* Switching sources quickly no longer fetches the wrong value. The callback stored the value under whatever source was selected when it arrived — and since only missing values are fetched, it stayed that way
|
|
586
|
+
* The source jump list never appears twice. It hangs off the page body so it survives an automatic redraw; the button is a different one afterwards, and the second click laid a second list over the first
|
|
587
|
+
* A room is suggested even when it is the last segment. With a flat adapter such as `sonoff.0.Wohnzimmer` the search over the source path never ran at all
|
|
588
|
+
* Object names follow the admin language. There were two readers for the same question, one fixed on German before English — so on an English admin, objects, rooms and functions showed up in German. And the name match now looks at every language: “Light” in the system failed to find the function “Licht” and created a duplicate beside it
|
|
589
|
+
|
|
590
|
+
**MQTT and Tasmota**
|
|
591
|
+
* An empty `custom` entry no longer takes anything down. `common.custom` can hold an entry whose value is `null` — ioBroker does not clean it up when an instance disappears. Reaching into it took the whole result view with it
|
|
592
|
+
* `enabled: false` counts as switched off. The field did not appear in the reader at all: `{ enabled: false, publish: true }` counted as publishable although the instance does not serve that point
|
|
593
|
+
* No more false “cannot publish” for ioBroker.mqtt and sonoff. Their objects carry the topic in `native` only; that was reported as a firm “no” instead of “unknown”, the chip was red, and “allow publishing” wrote the object back unchanged — a message that could not be cleared
|
|
594
|
+
* “Answer received” only for a real answer. A `stat.RESULT` left retained from the day before yesterday was enough for the green feedback, even with the device switched off
|
|
595
|
+
* `Vcc` and `Command` are not commands. `{"Command":"Unknown"}` — the reply to an unknown command — stood there as a missing command point, with a create button
|
|
596
|
+
* Command names from foreign JSON no longer reach ids and topics unchecked. A key containing `#` would make a wildcard subscription, one containing `.` an extra level
|
|
597
|
+
|
|
598
|
+
**Templates and devices**
|
|
599
|
+
* The blind gets its STOP. A button press has no state to read, and that case was unknown to template application: without a read path the point dropped out — not a single blind alias ever had a STOP
|
|
600
|
+
* ON_TIME finds its slot. Four templates carried the role `level.timer` while the slot requires `level.timer.off`, so the point ended up in the info device instead of the switching device
|
|
601
|
+
* An explicit formula beats the field. Where a template gives both, the formula was discarded and a new one built from the field
|
|
602
|
+
|
|
603
|
+
**Subscriptions and tree**
|
|
604
|
+
* What is subscribed is what is read — not half the adapter. The patterns came from the display grouping: on a flat MQTT device that produced `mqtt-client.0.*` with over three hundred objects on a single alias. It is now the channels of the actual sources, branches of the same device folded into one pattern, and where even that is too wide, the sources one by one
|
|
605
|
+
* Adapter and instance roots can no longer be selected. `mqtt-client.0` is not a device; selecting it would have subscribed the whole namespace
|
|
606
|
+
* Dark admin themes are recognised. The detection knew four names; `blue` and `colored` fell through and landed on the system setting
|
|
607
|
+
* A late answer to `system.config` still counts. After 2.5 seconds it carries on without one — the answer arriving later was discarded entirely, and without it every expert object was missing from the tree
|
|
608
|
+
|
|
609
|
+
**Housekeeping**
|
|
610
|
+
* The checks touch nothing again. One of them wrote an object from inside the drawing path
|
|
611
|
+
* The delete dialog warns about channels of their own below the target. The hint spoke only of “data points below”
|
|
612
|
+
* Four dead language keys removed — and the test now checks both directions, not just code → JSON
|
|
613
|
+
|
|
614
|
+
### 0.9.5
|
|
615
|
+
* A broken name hint no longer takes down the whole source view. The text was evaluated as a regular expression unchecked, although neither the template sheet nor the save dialog validates it: after saving `Lampe (Bad`, template matching threw on **every** device selection, no caller caught it, and the right-hand side stayed empty — repairable only through the instance configuration by hand. An unusable expression now counts as “no match” and is flagged in red at the field. The same goes for the nested form `(a+)+`, where the expression engine stalls: a measured 3196 ms for one device name, now none
|
|
616
|
+
* The formula of a fallback source survives updating a template. It was stored under `formel` while every reader looks for `leseformel` — so updating from a device silently dropped it. With `tasmota-steckdose` the consequence was that on devices without `stat.POWER` the boolean alias ended up on the raw JSON text of `tele.STATE` instead of on `POWER`
|
|
617
|
+
* A device type this detector does not know no longer throws. The offered pattern list was filtered, the **selected** type was not — it comes from the template unchecked. An imported template naming a pattern from a newer type-detector made the pattern picker throw, and the draft was never drawn at all
|
|
618
|
+
* Importing now checks more than id and states. `erkennung.erforderlich` as a string instead of a list made template matching throw on **every** device afterwards; a missing `name` threw as soon as the sheet opened. And “import and save” was on screen long before that — you could save a template that then made the tab unusable. `erkennung`, `erforderlich`/`verboten`, `inhalt`, `name`, the name hint and the device type are checked now; a single string that unambiguously means a list is turned into one rather than rejected
|
|
619
|
+
* A hand-typed id no longer replaces someone else's template. Ids were only checked for collisions when switching modes, not after typing — and saving replaces without asking on a matching id, in “new” mode even with version 1. An own template at v7 silently became a different one at v1. The reason is now shown in red at the field and saving is blocked
|
|
620
|
+
* The `%N%` placeholder only hits the output number now. Replacement went purely by trailing digit: on a multi-output device at output 2 the IP row from `tele.INFO2` became `tele.INFO%N%` — and at output 1 that same row reported a foreign output, with “drop the others” throwing it out. Only what actually carries the output becomes a placeholder now: what the template already held as `%N%`, the prefix from `kanalname`, and what appears more than once with the same number
|
|
621
|
+
|
|
622
|
+
### 0.9.4
|
|
623
|
+
* The tab works again after a dropped connection. It does not load socket.io but the admin's WebSocket shim — and there `connect` fires exactly once per page lifetime, only `reconnect` afterwards. Nobody listened for that, and the shim renews no subscription on its own. After every outage — admin restart, network hiccup, standby — neither object nor state changes arrived, and the dot in the header stayed on “disconnected” although the connection had long been back. `reconnect` is now handled: the display goes back to “connected”, every subscription is renewed and the objects are re-read — anything could have changed while disconnected, and nobody was watching
|
|
624
|
+
* The template mode no longer rebuilds itself every second. Selecting a device with live values and switching to the templates tab rebuilt the whole sheet every 700 ms, including a trial run across all candidates and all templates — the selection deliberately survives the mode switch, but there is no state list on the right any more
|
|
625
|
+
* Where the selection goes, its subscriptions now go too. Unsubscribing only happened when selecting the next node; the four other paths — switching mode, collapsing a branch, leaving expert mode, deleting an alias — unsubscribed from nothing. A subscription then ran on a device no longer shown, and the header counter still claimed “one subscription”
|
|
626
|
+
* Switching nodes while loading no longer leaves the caller hanging. The callback never arrived in that case: “running” stayed on the button forever, and the dry run meant to open after creating missing command points never opened. Twelve seconds of waiting on a SetOption59 query is ample opportunity for that
|
|
627
|
+
|
|
628
|
+
### 0.9.3
|
|
629
|
+
* An error on the enumerations now stops the move. The first step — creating the new one — always aborted on error, “two rather than none”; the second did not: enumeration errors were collected and the old one was deleted anyway. Afterwards the old alias was gone and the new one sat in no enumeration at all, because the js-controller removes members itself on delete. The assignment was therefore lost outright, not merely orphaned. The same abort now applies one level down, and the button offers “Try again”
|
|
630
|
+
* A partial failure while deleting no longer turns the retry button into a prop. If one delete failed, **all** ids were dropped from the internal store anyway, empty folders and enumerations were cleaned up and the delete target was set to null — which is exactly what `loescheAlias` starts with, so it bailed out immediately. Whatever stayed in the database was out of reach: the workbench considered it deleted. Only what really went is dropped now, the cleanup is skipped, the target stays — and the second click actually finishes the job
|
|
631
|
+
* Orphaned points are deleted on the second attempt too. Their list was cleared after writing **always**, even after a failure; the retry button then wrote the objects but removed nothing, and the message no longer counted them either
|
|
632
|
+
* A load error on your own templates is reported instead of swallowed. If the instance configuration answered with an error, that counted as “no own templates” — the warning chip in the header stayed away, although the timeout path one line above sets it correctly. The consequence was the dangerous part: the workbench considered taken ids free, and the next save would have replaced an existing template with version 1. The chip's tooltip now says so
|
|
633
|
+
|
|
634
|
+
### 0.9.2
|
|
635
|
+
* Swapping the source no longer writes to the read source: if no new write target is found for a point with separate sources, a plain string was left in `alias.id` — and to the js-controller that means “read and write on the same id”. With Tasmota the command then went to the status topic instead of the command topic: the device does not switch and the feedback is falsified. Worse, the workbench guessed the write source by name and landed on `stat.POWER`, because that too contains “POWER”. A guessed write target now only counts if it is a different point from the read source, the object form is kept, and the row marks the missing match in red
|
|
636
|
+
* Moving recognises two more targets as a collision: one that exists only as a tree node carrying data points — existing points of the same name were overwritten there — and one that sits below the alias itself: `alias.0.X` to `alias.0.X.Sub` took its own parent node along on the final delete
|
|
637
|
+
* A rejected creation of a send point no longer counts as success. The silent path did not even accept the error and entered the object into its own store anyway; after that the guard no longer bit, and “Create now” wrote `alias.id.write` onto an id that never existed in the database — exactly the error the js-controller remembers for good
|
|
638
|
+
* Channel names are cleaned into ids when “Create all” builds one channel per output. “Licht Bar, oben” produced an id with a space and a comma, “Küche.Decke” an extra level including an intermediate folder. And the js-controller does not reject that, it cleans silently — so the object would have appeared under a different id than the one shown. The display name is left untouched
|
|
639
|
+
* A channel keeps its template link across an update, even when the template was deleted or renamed. `native` used to be replaced wholesale; template, version and device type only came back when a template happened to match. The role one line below had long been rescued, `native` had not
|
|
640
|
+
* Hardened: the cleanup of separated sources no longer switches off a point that is itself part of the alias. Whether it happened depended on the order of `Object.keys` — it was not reachable through the interface, because none of the bundled templates puts a reporting row before the controlling one, but the consequence would have been a deleted data point
|
|
641
|
+
|
|
642
|
+
### 0.9.1
|
|
643
|
+
* A load error on the enumerations can no longer overwrite one: until now a failed `getObjectView` set the store to empty and kept quiet about it. After that the workbench considered every enumeration absent, the catalogue kept offering them because the duplicate filter had nothing to check against, and on writing `setObject` replaced the existing object with a fresh one holding a single member — measured, a room lost three of its four members that way and was given the origin mark that makes it deletable later on. The previous state is now kept, no enumeration is touched, and both the field and the dry run say why room and function are not being written. The alias itself is still created, and a hiccup heals itself after three attempts
|
|
644
|
+
* An enumeration deleted from outside is no longer resurrected: the subscription compared against `objects`, where enumerations never live — on deletion old and new value were therefore both empty and the branch that removes it from the store was never reached. The next alias using that room recreated it with all its old members, including the foreign ones
|
|
645
|
+
* “Create all” now gives every channel its room and its function. The partial drafts carried neither, so not a single channel got an entry — the single route set it, the bulk route did not. A second object for the same enumeration was also discarded, so even then only the first channel would have made it in. And for a channel other than the one shown the assignment counted as empty: if its alias already sat in a room, the bulk route took it **out**. Every channel now keeps what it has, all others get what is set, and members are merged instead of discarded
|
|
646
|
+
|
|
647
|
+
### 0.9.0
|
|
648
|
+
* The role list is complete again: the detector hands out the expressions of its slots as text WITH slashes (`/^indicator…$/`), not as a regular expression. Take the slashes for part of the expression and you find neither start nor end afterwards — 210 roles instead of 232, and `indicator.lowbat` of all things was missing, the role every Homematic device writes. In the role picker, no slot of the pattern was offered at all any more, only the line "show all roles"
|
|
649
|
+
* From the same cause, BRIGHTNESS lost its role in six colour-light patterns — the slot could be added over and over and could not be filled by any route. Seven places in the code read a slot expression; they all go through one function now, and a test checks the role list against what the detector actually delivers instead of against hand-written expressions
|
|
650
|
+
* The deviation card tells the truth again when a point is deselected: it claimed "would not have counted anyway" even for points that do have a slot in the pattern (same cause)
|
|
651
|
+
* A point the template lists under a different name now keeps its role and its caption at the source: the workbench has two functions for the same job, and the second one bailed out when a template had matched. At the alias it said `state` and "Lavalampe ACTUAL", at the source `sensor.light` and nothing at all — updating would have overwritten both. What the template wanted instead now shows as a mark on the row, as everywhere else, and can be taken over field by field
|
|
652
|
+
* On load, the workbench no longer fetches two files that do not exist: it searched the admin's directory for file names and put `assets/` in front, although whole paths are listed there — and two entries expressly do not live in that folder (`"path": ""`). That produced two 404s in the browser console. It now looks for paths instead of names and strips a leading `./`: the manifest writes `assets/…`, the `index.html` `./assets/…`, and without that step the same file would sit twice in a list that ends after 25 entries
|
|
653
|
+
* The readme now mentions two things it used to keep quiet about: that the workbench proposes the read formula itself from recognised JSON — guarded against missing fields, and readable in both directions — and that it maintains roles, the channel role, room and function along with their pictures
|
|
654
|
+
* Values now keep running in the alias view: the workbench subscribed to the alias points but displays the values of their sources, so the numbers were fetched once and then stood still. It now subscribes to the sources as well. The header shows how many subscriptions are running — a subscription covers a whole branch, and its tooltip lists them, so it is visible right away if one is ever left behind
|
|
655
|
+
* The caption of a row now lives in a tooltip on its id instead of standing next to it — with the marks a row can carry, it had become so crowded that role and value were pushed off to the right. A dotted underline shows where a tooltip waits
|
|
656
|
+
* An alias whose points read from more than one node now says so: a chip "n sources" next to "to the source", listing every node with its number of points; the jump button asks where to go instead of silently taking the majority; and the individual rows that read from elsewhere carry a mark naming their adapter. Before, the only way to notice was to open every row. The way back holds too: from a secondary source, "to the alias" is there again — it used to require being at the majority source. Spartas of one and the same device (a Tasmota `stat` and `tele`) do not count as a second source. The choice appears only under "to the source" — jumping to the alias has exactly one destination. Spartas next to each other are merged as well now, not just against the main source — a Tasmota read through `stat` and `tele` counted as two. And both the way back and the row marks now go by the source you are standing at: "to the alias" is there at every source of an alias, including the device above a sparte, and a row is marked when it does not come from here. At the alias itself every row carries its tag — there is no place you are standing, so no source is the normal one; a tie no longer decides anything. The tag names the source, not the adapter, and no entry in the list is highlighted
|
|
657
|
+
* Nodes without datapoints are no longer left out of the tree: a channel, device or folder that exists but is empty now stands there greyed out, without a count and not clickable, with a tooltip saying so. Left out, it looked like the node did not exist at all — while in truth the adapter had not created its datapoints. They do not count as hits when filtering
|
|
658
|
+
|
|
513
659
|
### 0.8.3
|
|
514
660
|
* The dry run now shows enumerations as a comparison as well: the "before" column stayed empty for them, because enumerations live in their own store and the dry run only looked in the object store. Everything appeared as new, so it was impossible to see that eleven of twelve members were already there
|
|
515
661
|
* …and the interface no longer announces a creation where it changes: on such an alias the chip said "will be newly created", the button offered "create alias", the dry run was titled "what would come into being", the room and function were guessed instead of read, orphaned points went unnoticed and move/swap/remove did nothing. All of them asked whether the channel is an object instead of whether the alias exists
|
|
@@ -518,9 +664,6 @@ imported, and that both language files carry the same keys.
|
|
|
518
664
|
* Updating an existing alias no longer overwrites its caption with the bare row name, and no longer turns a read-only alias into a writable one: the function that takes the stored alias over into the draft was missing both rules its twin already had. The false "differs from the stored alias" mark that came with it is gone too
|
|
519
665
|
* A line that comes from the stored alias and reads from a source outside the selected node now gets its value: the values were fetched before that line even existed, so it claimed "source delivers nothing" while the alias was working fine. Only showed on aliases assembled from several adapters, and only until the node was clicked a second time
|
|
520
666
|
|
|
521
|
-
### **WORK IN PROGRESS**
|
|
522
|
-
* A line that comes from the stored alias and reads from a source outside the selected node now gets its value: the values were fetched before that line even existed, so it claimed "source delivers nothing" while the alias was working fine. Only showed on aliases assembled from several adapters, and only until the node was clicked a second time
|
|
523
|
-
|
|
524
667
|
### 0.8.2
|
|
525
668
|
* A source that already has an alias now says so when the target points elsewhere: "This source already has alias.0.… — that one stays where it is", with a button "move it instead …" that opens the move dialog prefilled. Nothing is forbidden — two aliases on one source remain possible, they are no longer silent
|
|
526
669
|
* The same line appears in the dry run, right above what cannot be written
|
package/admin/css/werkbank.css
CHANGED
|
@@ -185,6 +185,11 @@
|
|
|
185
185
|
.tree .node.pick:hover:not(.sel) .grp { color:inherit; opacity:.85; }
|
|
186
186
|
.tree .node.pick:hover:not(.sel) .kind { background:rgba(255,255,255,.3); color:inherit; }
|
|
187
187
|
.tree .node.pick:hover:not(.sel) .geraetepunkt { color:inherit; }
|
|
188
|
+
/* Ein Knoten ohne Datenpunkte: da, aber nichts drin. Gedaempft und
|
|
189
|
+
ohne Zahl - er soll die Luecke zeigen, nicht um Aufmerksamkeit
|
|
190
|
+
bitten. Kein Zeiger, kein Hover: waehlbar ist er ohnehin nicht. */
|
|
191
|
+
.tree .node.leer { opacity:.45; font-style:italic; }
|
|
192
|
+
.tree .node.leer .kind { background:transparent; border:1px solid var(--line); }
|
|
188
193
|
.tree .node.sel { background:var(--accent); color:var(--accent-ink); font-weight:600; }
|
|
189
194
|
.tree .node.sel .kind { background:rgba(255,255,255,.22); color:inherit; }
|
|
190
195
|
/* Die Vorlagenliste benutzt dieselben Knotenzeilen, hat aber statt
|
|
@@ -390,6 +395,24 @@
|
|
|
390
395
|
|
|
391
396
|
/* „Vorlage: x" an einer Zeile, deren Bestand von der Vorlage abweicht -
|
|
392
397
|
gedaempfter als die Marke „geaendert", es ist ja nur ein Angebot. */
|
|
398
|
+
/* Die Quelle dieses Punktes liegt woanders als die der uebrigen.
|
|
399
|
+
|
|
400
|
+
Keine Warnung, eine Auskunft: gedeckte Farbe, gestrichelter Rahmen -
|
|
401
|
+
unterscheidbar von „geaendert" (Akzent) und „weicht ab" (Warnung),
|
|
402
|
+
und vertraeglich mit der Toenung „kein Platz im Muster", die
|
|
403
|
+
unabhaengig davon an derselben Zeile stehen kann. */
|
|
404
|
+
.erow .geae.fremdquelle {
|
|
405
|
+
color:var(--ink-2); background:transparent;
|
|
406
|
+
border-style:dashed; border-color:var(--line-strong);
|
|
407
|
+
}
|
|
408
|
+
/* Der Kopfchip „n Quellen" und die Auswahlliste am Sprungknopf. */
|
|
409
|
+
.chip.quellenzahl { cursor:help; }
|
|
410
|
+
.sprungwahl { position:relative; display:inline-flex; }
|
|
411
|
+
.vorschlaege.sprungliste { min-width:300px; max-width:520px; z-index:60; }
|
|
412
|
+
.vorschlaege .vzkopf {
|
|
413
|
+
padding:4px 9px; font-size:11px; color:var(--ink-3);
|
|
414
|
+
border-bottom:1px solid var(--line);
|
|
415
|
+
}
|
|
393
416
|
.erow .geae.tplabw { color:var(--ink-3); background:var(--surface-2); }
|
|
394
417
|
.leerhilfe .lh2 { margin-top:11px; font-size:12px; color:var(--ink-3); }
|
|
395
418
|
|
|
@@ -495,18 +518,34 @@
|
|
|
495
518
|
.erow.ohneplatz { background:color-mix(in srgb, var(--warn-soft) 80%, transparent); }
|
|
496
519
|
.erow.ohneplatz:hover, .erow.ohneplatz.open {
|
|
497
520
|
background:color-mix(in srgb, var(--warn-soft) 100%, transparent); }
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
521
|
+
/* Die Legende steht in der Liste, nicht in der Leiste: dieselbe
|
|
522
|
+
Toenung wie die Zeilen, dieselbe Breite, unmittelbar ueber der
|
|
523
|
+
ersten. Sie beschreibt die Toenung nicht — sie ist ein Stueck
|
|
524
|
+
davon. Zwei blassere Anlaeufe davor scheiterten daran, dass
|
|
525
|
+
niemand sie mit den Zeilen darunter verband (Ricardo, 08.09.2026).
|
|
526
|
+
Der Zeiger zeigt einen Hinweis: der lange Text haengt daran. */
|
|
527
|
+
.legendenzeile { display:flex; align-items:center; gap:8px;
|
|
528
|
+
padding:5px 15px; border-bottom:1px solid var(--line);
|
|
529
|
+
font-size:11.5px; color:var(--warn);
|
|
530
|
+
background:color-mix(in srgb, var(--warn-soft) 80%, transparent); }
|
|
531
|
+
/* Das „i" oeffnet die lange Erklaerung als Dialog. Als Tooltip wurde
|
|
532
|
+
sie ueber zehn Zeilen hoch und legte sich ueber die Liste, die man
|
|
533
|
+
gerade lesen wollte (Ricardo, 08.09.2026). */
|
|
534
|
+
.legendenzeile .infoknopf {
|
|
535
|
+
width:15px; height:15px; flex:0 0 15px; padding:0; border-radius:50%;
|
|
536
|
+
border:1px solid color-mix(in srgb, var(--warn) 55%, transparent);
|
|
537
|
+
background:transparent; color:var(--warn); cursor:pointer;
|
|
538
|
+
font-family:var(--sans); font-size:10px; font-weight:700; font-style:italic;
|
|
539
|
+
line-height:1; display:inline-flex; align-items:center; justify-content:center; }
|
|
540
|
+
.legendenzeile .infoknopf:hover { background:var(--warn); color:var(--surface); }
|
|
506
541
|
.erow input[type="checkbox"] { accent-color:var(--accent); cursor:pointer; margin:0; }
|
|
507
542
|
.erow .mk2 { text-align:center; font-size:11px; }
|
|
508
543
|
.erow .mk2.ok { color:var(--ok); } .erow .mk2.bad { color:var(--bad); } .erow .mk2.out { color:var(--ink-3); }
|
|
509
544
|
.erow .nm3 { font-family:var(--mono); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
545
|
+
/* Traegt die Kennung eine Beschriftung, sagt der Mauszeiger es an:
|
|
546
|
+
ein zarter Unterstrich, wie bei einer Abkuerzung. Sonst raet
|
|
547
|
+
niemand, dass dort ein Hinweis haengt. */
|
|
548
|
+
.erow .nm3[title] { text-decoration:underline dotted var(--line-strong); text-underline-offset:3px; }
|
|
510
549
|
.erow .nm3 em { font-style:normal; font-weight:400; color:var(--ink-3); font-size:10.5px; margin-left:6px; }
|
|
511
550
|
.erow .nm3 .hand { font-family:var(--sans); font-size:8px; font-weight:700; letter-spacing:.05em;
|
|
512
551
|
text-transform:uppercase; background:var(--surface-3); color:var(--ink-3);
|
|
@@ -554,6 +593,16 @@
|
|
|
554
593
|
|
|
555
594
|
/* ---- Bearbeitungsfelder im Detail ---- */
|
|
556
595
|
.detail .fields { display:flex; gap:12px; flex-wrap:wrap; align-items:flex-end; }
|
|
596
|
+
/* Feld plus die volle Kennung darunter. Ein `select` zeigt zugeklappt
|
|
597
|
+
nur den Text seiner Option, und der traegt die Instanz nicht — die
|
|
598
|
+
steht sonst allein in der Gruppenueberschrift, die man erst beim
|
|
599
|
+
Aufklappen sieht (Ricardo, 08.09.2026). Hier darf sie umbrechen,
|
|
600
|
+
also gibt es keine Breitengrenze. */
|
|
601
|
+
.detail .feldstapel { display:flex; flex-direction:column; gap:3px; }
|
|
602
|
+
.detail .vollid { font-family:var(--mono); font-size:10.5px; color:var(--ink-3);
|
|
603
|
+
overflow-wrap:anywhere; line-height:1.35; }
|
|
604
|
+
.detail .vollid:empty { display:none; }
|
|
605
|
+
|
|
557
606
|
.detail .fld { display:flex; flex-direction:column; gap:2px; }
|
|
558
607
|
.detail .fld > span { font-family:var(--sans); font-size:8.5px; letter-spacing:.06em;
|
|
559
608
|
text-transform:uppercase; color:var(--ink-3); font-weight:700; }
|