Fix the MQTT node, suggest message names, and drop Items

- MQTT nodes failed to build: the topic map was renamed to talk in ports, but
  __slots__ still declared the old name, so every MQTT node raised
  AttributeError. Building one of each node type is now a test, since __slots__
  makes this failure invisible until someone places the node.
- Port names offer the messages already in play: everything published is worth
  reading, and an input nobody provides yet is worth publishing. A message only
  connects when both ends spell it the same way, so choosing beats typing.
- Adding a port focuses its name field.
- Dragging onto an input that already reads something offers the extra port as
  well as the replacement — an MQTT or InfluxDB node usually wants both.
- The template's Item model, its routes, screens and table are gone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WzrvW7rjQbynnhF6pxh6i
This commit is contained in:
Melvin Strobl
2026-08-15 18:43:17 +02:00
co-authored by Claude Fable 5
parent 8c82549cf6
commit 01af7787c1
27 changed files with 365 additions and 1433 deletions
+29
View File
@@ -0,0 +1,29 @@
import { chromium } from "@playwright/test"
const APP = "http://app.localhost"
const OUT = "/tmp/claude-1000/-home-lc3267-Documents-CodeWorkspace-fluksio/8b6d42d6-2889-4321-ac59-4e6692fcfe3c/scratchpad"
const browser = await chromium.launch()
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } })
const page = await ctx.newPage()
page.on("pageerror", (e) => console.log(`[pageerror] ${e.message}`))
await page.goto(`${APP}/login`)
await page.getByTestId("email-input").fill(process.env.FIRST_SUPERUSER)
await page.getByTestId("password-input").fill(process.env.FIRST_SUPERUSER_PASSWORD)
await page.getByRole("button", { name: /log in/i }).click()
await page.waitForURL(`${APP}/`)
console.log("sidebar items entry:", await page.getByRole("link", { name: "Items" }).count())
await page.goto(`${APP}/flows/heating`)
await page.waitForSelector(".react-flow__node")
await page.waitForTimeout(1200)
// A node that consumes: its Consumes list should suggest what others publish.
await page.locator(".react-flow__node").filter({ hasText: "Notify" }).first().click()
const panel = page.getByTestId("node-panel")
await panel.getByRole("button", { name: "Add" }).first().click()
await page.waitForTimeout(600)
console.log("focused after Add:", await page.evaluate(() => document.activeElement?.getAttribute("aria-label")))
const options = await page.getByRole("option").allInnerTexts()
console.log("suggestions offered:", options)
await page.screenshot({ path: `${OUT}/suggestions.png` })
await browser.close()