fix(hubs): exclude chat/wizard-step flows and tighten hub regexes
- loadPublishedFlows: drop source_context EA2_CHAT_THREAD/_MSG and EA2_WIZARD_STEP so chat threads and wizard fragments don't leak into the business catalogue - procurement match: require word boundaries on PO/P2P; add requisition/ invoice - HR match: word-bound HR; add offboard/employee/payroll - IT match: word-bound IT; explicit access/laptop/password tokens; drop the over-broad bare 'service' and 'account' tokens
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
import { chromium } from "playwright";
|
||||||
|
|
||||||
|
const URL = "https://canvas.flow-master.ai/";
|
||||||
|
const args = ["--host-resolver-rules=MAP canvas.flow-master.ai 65.21.71.186", "--ignore-certificate-errors"];
|
||||||
|
|
||||||
|
const b = await chromium.launch({ headless: true, args });
|
||||||
|
const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
|
||||||
|
|
||||||
|
await p.goto(URL, { waitUntil: "networkidle" });
|
||||||
|
await p.waitForTimeout(800);
|
||||||
|
await p.locator(".persona-chip", { hasText: /Mariana/ }).click();
|
||||||
|
await p.locator(".dev-login-btn").click();
|
||||||
|
await p.waitForTimeout(2500);
|
||||||
|
|
||||||
|
const chips = await p.locator(".hub-chip").allTextContents();
|
||||||
|
console.log("[landing] hub chips:", chips);
|
||||||
|
|
||||||
|
for (const hub of ["Procurement Hub", "People Hub", "IT Hub"]) {
|
||||||
|
await p.locator(".hub-chip", { hasText: hub }).click();
|
||||||
|
await p.waitForTimeout(2200);
|
||||||
|
const title = await p.locator(".mc-hero-title").first().textContent();
|
||||||
|
const quickActions = await p.locator(".hub-quick-title").allTextContents();
|
||||||
|
const flowCards = await p.locator(".hub-flow-title").allTextContents();
|
||||||
|
console.log(`\n[${hub}] title=${title?.trim()} | quick=${quickActions.length} | flows=${flowCards.length}`);
|
||||||
|
console.log(` flows visible (top 3): ${flowCards.slice(0, 3).join(" | ")}`);
|
||||||
|
// navigate back to landing
|
||||||
|
await p.locator(".tab", { hasText: /Home/ }).first().click().catch(() => {});
|
||||||
|
await p.waitForTimeout(700);
|
||||||
|
}
|
||||||
|
await b.close();
|
||||||
+16
-4
@@ -20,7 +20,7 @@ const HUBS: Record<HubKey, HubSpec> = {
|
|||||||
eyebrow: "Purchase requests, vendor approvals, three-way match",
|
eyebrow: "Purchase requests, vendor approvals, three-way match",
|
||||||
intro:
|
intro:
|
||||||
"Everything a store manager needs to buy something — from a laptop to a forklift — and watch it move through the approval chain.",
|
"Everything a store manager needs to buy something — from a laptop to a forklift — and watch it move through the approval chain.",
|
||||||
match: /procure|purchase|vendor|po\b|payment/i,
|
match: /procure|purchase|vendor|\bpo\b|\bp2p\b|requisition|payment|invoice/i,
|
||||||
quickActions: [
|
quickActions: [
|
||||||
{ label: "Request a new laptop", subject: "store-204-laptop", processHint: "procurement" },
|
{ label: "Request a new laptop", subject: "store-204-laptop", processHint: "procurement" },
|
||||||
{ label: "Submit a quote for review", subject: "vendor-quote-Q3", processHint: "procurement" },
|
{ label: "Submit a quote for review", subject: "vendor-quote-Q3", processHint: "procurement" },
|
||||||
@@ -31,7 +31,7 @@ const HUBS: Record<HubKey, HubSpec> = {
|
|||||||
eyebrow: "Hiring, onboarding, leave, performance",
|
eyebrow: "Hiring, onboarding, leave, performance",
|
||||||
intro:
|
intro:
|
||||||
"All people movements run here. Start an onboarding for a new hire, file a leave request, or kick off a review cycle.",
|
"All people movements run here. Start an onboarding for a new hire, file a leave request, or kick off a review cycle.",
|
||||||
match: /onboard|leave|people|hr\b|hiring|payroll/i,
|
match: /onboard|offboard|leave|\bhr\b|hiring|payroll|employee|people operations/i,
|
||||||
quickActions: [
|
quickActions: [
|
||||||
{ label: "Onboard a new hire", subject: "new-hire-2026Q3", processHint: "onboard" },
|
{ label: "Onboard a new hire", subject: "new-hire-2026Q3", processHint: "onboard" },
|
||||||
{ label: "Request annual leave", subject: "leave-7d-may", processHint: "leave" },
|
{ label: "Request annual leave", subject: "leave-7d-may", processHint: "leave" },
|
||||||
@@ -42,7 +42,7 @@ const HUBS: Record<HubKey, HubSpec> = {
|
|||||||
eyebrow: "Tickets, access requests, incident response",
|
eyebrow: "Tickets, access requests, incident response",
|
||||||
intro:
|
intro:
|
||||||
"When something breaks, request access, or you need a new account — file it here and route it to the right on-call.",
|
"When something breaks, request access, or you need a new account — file it here and route it to the right on-call.",
|
||||||
match: /it\b|ticket|incident|access|account|service/i,
|
match: /\bit\b|ticket|incident|service operations|access request|sap access|laptop request|hardware request|software request|password reset|account provisioning/i,
|
||||||
quickActions: [
|
quickActions: [
|
||||||
{ label: "Open an incident", subject: "incident-store-204", processHint: "service" },
|
{ label: "Open an incident", subject: "incident-store-204", processHint: "service" },
|
||||||
{ label: "Request system access", subject: "access-sap-RW", processHint: "access" },
|
{ label: "Request system access", subject: "access-sap-RW", processHint: "access" },
|
||||||
@@ -57,6 +57,12 @@ interface PublishedFlow {
|
|||||||
name?: string;
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NON_BUSINESS_SOURCE_CONTEXTS = new Set([
|
||||||
|
"EA2_CHAT_THREAD",
|
||||||
|
"EA2_CHAT_MSG",
|
||||||
|
"EA2_WIZARD_STEP",
|
||||||
|
]);
|
||||||
|
|
||||||
async function loadPublishedFlows(): Promise<PublishedFlow[]> {
|
async function loadPublishedFlows(): Promise<PublishedFlow[]> {
|
||||||
const res = await fetch(`${api.config.baseUrl}/api/ea2/flow/processes?limit=200`, {
|
const res = await fetch(`${api.config.baseUrl}/api/ea2/flow/processes?limit=200`, {
|
||||||
headers: { Authorization: `Bearer ${sessionStorage.getItem("fm.mc.token.v1")}` },
|
headers: { Authorization: `Bearer ${sessionStorage.getItem("fm.mc.token.v1")}` },
|
||||||
@@ -64,7 +70,13 @@ async function loadPublishedFlows(): Promise<PublishedFlow[]> {
|
|||||||
if (!res.ok) throw new Error(`processes ${res.status}`);
|
if (!res.ok) throw new Error(`processes ${res.status}`);
|
||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
return ((body?.items || []) as any[])
|
return ((body?.items || []) as any[])
|
||||||
.filter((it) => it.status === "published" && it.kind === "definition" && it.display_name)
|
.filter(
|
||||||
|
(it) =>
|
||||||
|
it.status === "published" &&
|
||||||
|
it.kind === "definition" &&
|
||||||
|
it.display_name &&
|
||||||
|
!NON_BUSINESS_SOURCE_CONTEXTS.has(it.source_context)
|
||||||
|
)
|
||||||
.map((it) => ({
|
.map((it) => ({
|
||||||
_key: it._key,
|
_key: it._key,
|
||||||
display_name: it.display_name,
|
display_name: it.display_name,
|
||||||
|
|||||||
Reference in New Issue
Block a user