diff --git a/pruef-uebersicht-computer.png b/pruef-uebersicht-computer.png new file mode 100644 index 00000000..80f03190 Binary files /dev/null and b/pruef-uebersicht-computer.png differ diff --git a/pruef-uebersicht-creator.png b/pruef-uebersicht-creator.png new file mode 100644 index 00000000..134c3c99 Binary files /dev/null and b/pruef-uebersicht-creator.png differ diff --git a/pruef-uebersicht-handy.png b/pruef-uebersicht-handy.png new file mode 100644 index 00000000..a90444c5 Binary files /dev/null and b/pruef-uebersicht-handy.png differ diff --git a/pruef-uebersicht.mjs b/pruef-uebersicht.mjs deleted file mode 100644 index 05f6f67f..00000000 --- a/pruef-uebersicht.mjs +++ /dev/null @@ -1,251 +0,0 @@ -/* ===================================================================== - pruef-uebersicht.mjs — die neue Startansicht der Verwaltung - - Zwei Dinge werden hier geprüft, und beide haben eine Vorgeschichte: - - 1. STEHEN DIE REITER WIRKLICH UNTER DEM TITEL? - Das ist der ausdrückliche Wunsch vom 23.08.2026. Es wäre bequem, - dafür das Vorhandensein einer CSS-Regel zu prüfen — das beweist - aber nichts. Am 22.08.2026 waren 37 von 37 Prüfungen grün, während - jede Aufgabenzeile im Browser verkehrt herum stand: Die Regeln - waren da, das Ergebnis war falsch. Deshalb wird hier die - tatsächliche Lage im Fenster gemessen — der Reiter MUSS weiter - unten liegen als der Titel. - - 2. FÜHREN DIE KACHELN AUCH WIRKLICH IRGENDWOHIN? - Eine Kachel, die aussieht wie ein Knopf und keiner ist, ist - schlimmer als gar kein Knopf. Also wird geklickt und geprüft, dass - danach die richtige Ansicht offen ist. - ===================================================================== */ -import { chromium } from "playwright"; -import { createServer } from "node:http"; -import { readFileSync, existsSync } from "node:fs"; -import { join, extname } from "node:path"; - -const W = process.cwd(); -const T = { ".html": "text/html", ".css": "text/css", ".js": "text/javascript", - ".png": "image/png", ".jpg": "image/jpeg", ".svg": "image/svg+xml", - ".webp": "image/webp", ".ico": "image/x-icon", ".json": "application/json" }; -const srv = createServer((q, r) => { - const p = join(W, decodeURIComponent(q.url.split("?")[0])); - if (existsSync(p) && !p.endsWith("/")) { - r.writeHead(200, { "content-type": T[extname(p)] || "text/plain" }); - return r.end(readFileSync(p)); - } - r.writeHead(404).end(""); -}); -await new Promise((r) => srv.listen(4337, r)); - -const ergebnisse = []; -function pruefe(name, ok, zusatz) { - ergebnisse.push({ name, ok }); - console.log((ok ? " ok " : " FEHL ") + name + (zusatz !== undefined ? " -> " + zusatz : "")); -} - -const vorTagen = (n) => new Date(Date.now() - n * 864e5).toISOString(); - -/* Absichtlich unbequeme Testdaten: eine Anfrage, die seit acht Tagen - liegt (muss rot werden), eine Nachricht seit drei Tagen (gelb), und - ein offener Widerruf von heute (muss trotzdem rot sein, weil eine - gesetzliche Frist läuft). Ein Datensatz, in dem alles in Ordnung ist, - würde die Warnstufen gar nicht erst auslösen. */ -const UEBERSICHT = { - ok: true, - beiMir: { - anfragen: { n: 3, aeltestes: vorTagen(8) }, - nachrichten: { n: 2, aeltestes: vorTagen(3) }, - wuensche: { n: 0, aeltestes: null }, - widerrufe: { n: 1, aeltestes: vorTagen(0) }, - projekte: 2, - }, - beiKunde: { - projekte: 1, - aufgaben: 4, - zahlungen: { n: 2, summe: 120000, aeltestes: vorTagen(5) }, - zahlungenText: "1.200,00 €", - }, - geld: { - monat: { n: 3, brutto: 250000, netto: 241000, bruttoText: "2.500,00 €", nettoText: "2.410,00 €" }, - gesamt: { n: 11, brutto: 980000, bruttoText: "9.800,00 €" }, - gebuehrenText: "90,00 €", - }, - projekte: [ - { id: "p1", nummer: "P-2026-001", titel: "Website für Musterbau", status: "bau", - wartet_auf: "dogfather", richttermin: "2026-09-15", kunde_name: "Anna Muster", - aufg_gesamt: 20, aufg_fertig: 13 }, - { id: "p2", nummer: "P-2026-002", titel: "Shop für Beispiel GmbH", status: "bau", - wartet_auf: "kunde", richttermin: null, kunde_name: "Bert Beispiel", - aufg_gesamt: 18, aufg_fertig: 4 }, - ], - verlauf: [ - { bereich: "projekt", aktion: "Aufgabe erledigt: Startseite gebaut", wer: "dogfather", erstellt_am: vorTagen(0) }, - { bereich: "zahlung", aktion: "Zahlung eingegangen", wer: "paypal", erstellt_am: vorTagen(1) }, - ], - bestand: { kunden: 5, projekte: 2, anfragenGesamt: 9 }, - paypal: { eingerichtet: true, live: true }, -}; - -const browser = await chromium.launch(); - -for (const [wo, breite, hoehe] of [["Computer", 1440, 950], ["Handy", 390, 844]]) { - const seite = await browser.newPage({ viewport: { width: breite, height: hoehe } }); - const fehlerImProtokoll = []; - seite.on("pageerror", (e) => fehlerImProtokoll.push(e.message)); - - await seite.route("**/webdesign/admin/**", (route) => { - const u = new URL(route.request().url()).pathname; - if (u.endsWith("/admin/uebersicht")) return route.fulfill({ json: UEBERSICHT }); - if (u.includes("/admin/postfach-zaehler")) return route.fulfill({ json: { ok: true, ungelesen: 2 } }); - if (u.includes("/admin/anfragen")) return route.fulfill({ json: { ok: true, anfragen: [] } }); - if (u.includes("/admin/kunden")) return route.fulfill({ json: { ok: true, kunden: [] } }); - if (u.includes("/admin/projekte")) return route.fulfill({ json: { ok: true, projekte: [] } }); - if (u.includes("/admin/zahlungen")) return route.fulfill({ json: { ok: true, zahlungen: [] } }); - if (u.includes("/admin/postfach")) return route.fulfill({ json: { ok: true, ungelesen: 2, verlaeufe: [] } }); - return route.fulfill({ json: { ok: true } }); - }); - await seite.route("**/auth/**", (r) => r.fulfill({ json: { ok: true, user: { name: "Test" } } })); - await seite.addInitScript(() => { - sessionStorage.setItem("wd-vw-token", "t"); - sessionStorage.setItem("wd-sitzung-aktiv", "1"); - }); - - await seite.goto("http://127.0.0.1:4337/webdesign/verwaltung.html"); - await seite.waitForTimeout(900); - console.log("\n=== " + wo + " ==="); - - /* ---- 1. Die Verwaltung startet in der Übersicht ---- */ - const titel = await seite.locator("#vw-titel").innerText(); - pruefe(wo + ": die Verwaltung öffnet in der Übersicht", titel.trim() === "Übersicht", titel); - pruefe(wo + ": das Cockpit ist sichtbar", - await seite.locator("#vw-ub-inhalt").isVisible()); - pruefe(wo + ": die Anfragenliste liegt NICHT darunter", - !(await seite.locator("#vw-liste").isVisible())); - - /* ---- 2. Reiter UNTER dem Titel — gemessen, nicht behauptet ---- */ - const lage = await seite.evaluate(() => { - const t = document.getElementById("vw-titel").getBoundingClientRect(); - /* Gemessen wird der erste KNOPF, nicht der Streifen um ihn herum. - - Auf dem Handy sind die Reiter ein Wischstreifen, der bewusst 4px - ueber den Containerrand hinauslaeuft -- sonst endet er optisch - mitten auf der Seite, obwohl es weitergeht. Sichtbar ausgerichtet - ist aber der Knopf, und nur der zaehlt fuer das Auge. */ - const r = document.querySelector(".vw-tabs [data-tab]").getBoundingClientRect(); - return { titelUnten: t.bottom, titelLinks: t.left, reiterOben: r.top, reiterLinks: r.left }; - }); - pruefe(wo + ": die Reiter beginnen UNTERHALB des Titels", - lage.reiterOben >= lage.titelUnten - 1, - "Titel endet bei " + Math.round(lage.titelUnten) + ", Reiter beginnen bei " + Math.round(lage.reiterOben)); - /* Zusatzbedingung, sonst wäre "darunter" auch erfüllt, wenn die Reiter - weit nach rechts eingerückt stünden statt am Seitenrand zu beginnen. */ - pruefe(wo + ": die Reiter beginnen am selben linken Rand wie der Titel", - Math.abs(lage.reiterLinks - lage.titelLinks) < 3, - "Titel " + Math.round(lage.titelLinks) + " vs. Reiter " + Math.round(lage.reiterLinks)); - - /* ---- 2b. Groessenverhaeltnisse ---- - Eine Zwischenueberschrift darf nicht groesser sein als die Zahl, um - die es geht. Genau das war der Fall, solange die Regel .wd h2 die - eigene ueberstimmte: 44px Ueberschrift ueber 33px Zahl -- die Seite - las sich wie ein Plakat statt wie ein Arbeitsplatz. */ - const groessen = await seite.evaluate(() => ({ - h: parseFloat(getComputedStyle(document.querySelector(".vw-ub-h")).fontSize), - zahl: parseFloat(getComputedStyle(document.querySelector(".vw-ub-zahl")).fontSize), - })); - pruefe(wo + ": die Zwischenueberschrift ist kleiner als die Zahl darunter", - groessen.h < groessen.zahl, - "Ueberschrift " + groessen.h + "px, Zahl " + groessen.zahl + "px"); - - /* ---- 3. Inhalt der Kacheln ---- */ - const kacheln = await seite.locator("#vw-ub-beimir .vw-ub-kachel").allInnerTexts(); - pruefe(wo + ": alle fünf Kacheln 'bei mir' sind da (inkl. Widerruf)", - kacheln.length === 5, kacheln.length); - pruefe(wo + ": die drei offenen Anfragen stehen drin", - kacheln.some((k) => k.includes("3") && k.includes("offene Anfragen"))); - pruefe(wo + ": das Alter steht als TEXT dabei, nicht nur als Farbe", - kacheln.some((k) => k.includes("seit 8 Tagen")), - kacheln.find((k) => k.includes("Anfragen"))); - - /* ---- 4. Die Warnstufen greifen wirklich ---- */ - const stufen = await seite.evaluate(() => { - const raus = {}; - document.querySelectorAll("#vw-ub-beimir .vw-ub-kachel").forEach((k) => { - const t = (k.querySelector(".vw-ub-titel") || {}).textContent || ""; - raus[t] = k.className; - }); - return raus; - }); - pruefe(wo + ": 8 Tage alte Anfrage ist rot", - /vw-ub-kachel--rot/.test(stufen["offene Anfragen"] || ""), stufen["offene Anfragen"]); - pruefe(wo + ": 3 Tage alte Nachricht ist nur gelb, nicht rot", - /--warn/.test(stufen["ungelesene Nachrichten"] || "") && - !/--rot/.test(stufen["ungelesene Nachrichten"] || ""), stufen["ungelesene Nachrichten"]); - pruefe(wo + ": ein Widerruf von HEUTE ist trotzdem rot (Frist läuft)", - /--rot/.test(stufen["Widerrufe unbearbeitet"] || ""), stufen["Widerrufe unbearbeitet"]); - pruefe(wo + ": eine Null-Kachel nimmt sich zurück statt zu warnen", - /--leer/.test(stufen["Änderungswünsche zu prüfen"] || ""), - stufen["Änderungswünsche zu prüfen"]); - - /* ---- 5. Geld ---- */ - const geld = (await seite.locator("#vw-ub-geld").innerText()); - pruefe(wo + ": der Monatsumsatz steht da", geld.includes("2.500,00")); - pruefe(wo + ": die PayPal-Gebühr wird offen ausgewiesen", geld.includes("90,00")); - pruefe(wo + ": das tatsächlich angekommene Netto steht dabei", geld.includes("2.410,00")); - - /* ---- 6. Projekte mit Fortschritt ---- */ - const proj = await seite.locator("#vw-ub-projekte .vw-ub-projekt").allInnerTexts(); - pruefe(wo + ": beide laufenden Projekte erscheinen", proj.length === 2, proj.length); - pruefe(wo + ": der Fortschritt steht als Zahl da, nicht nur als Balken", - proj[0].includes("13 von 20") && proj[0].includes("65"), proj[0].replace(/\n/g, " | ")); - pruefe(wo + ": man sieht, wer am Zug ist", - proj[0].includes("du bist dran") && proj[1].includes("wartet auf Kunden")); - const balken = await seite.evaluate(() => - document.querySelector(".vw-ub-balken-voll").style.width); - pruefe(wo + ": der Balken zeigt denselben Wert wie der Text", balken === "65%", balken); - - /* ---- 7. Die Kacheln sind echte Knöpfe und führen irgendwohin ---- */ - const istKnopf = await seite.evaluate(() => - document.querySelector("#vw-ub-beimir .vw-ub-kachel").tagName); - pruefe(wo + ": eine Kachel ist ein +

Creator Workspace · Dashboard

+
+ … + +
+ + +
+ +
+
+

Alles zentral

+

Dashboard

+

+ Eine Karte je Creator – mit einem Blick sehen, wo es hakt und wo es läuft. +

+
+
+ + + + + + +

Übersicht wird geladen …

+ + + +
+ + + + + diff --git a/workspace/wissen.html b/workspace/wissen.html index 7e9310dd..fb584c53 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -170,8 +170,8 @@ - - - + + +