diff --git a/features/profile/frontend-showcase/e2e/check-console-errors.spec.ts b/features/profile/frontend-showcase/e2e/check-console-errors.spec.ts deleted file mode 100644 index c52f4d7ff..000000000 --- a/features/profile/frontend-showcase/e2e/check-console-errors.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { test } from '@playwright/test'; - -test('check console for errors', async ({ page }) => { - const consoleMessages: string[] = []; - const consoleErrors: string[] = []; - - page.on('console', msg => { - const text = msg.text(); - if (msg.type() === 'error') { - consoleErrors.push(text); - } else { - consoleMessages.push(text); - } - }); - - page.on('pageerror', error => { - consoleErrors.push(`PAGE ERROR: ${error.message}\n${error.stack}`); - }); - - await page.goto('http://localhost:5200/providers/sofia-kopavogur'); - await page.waitForLoadState('networkidle'); - await page.waitForTimeout(3000); - - console.log('\n=== Console Errors ==='); - if (consoleErrors.length === 0) { - console.log('No errors'); - } else { - consoleErrors.forEach(err => console.log(err)); - } - - console.log('\n=== Console Messages (last 10) ==='); - consoleMessages.slice(-10).forEach(msg => console.log(msg)); - - // Check page content - const bodyText = await page.locator('body').textContent(); - console.log('\n=== Page Content (first 500 chars) ==='); - console.log(bodyText?.substring(0, 500)); -}); diff --git a/features/profile/frontend-showcase/e2e/debug-empty-editor.spec.ts b/features/profile/frontend-showcase/e2e/debug-empty-editor.spec.ts deleted file mode 100644 index b4592d416..000000000 --- a/features/profile/frontend-showcase/e2e/debug-empty-editor.spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { test } from '@playwright/test'; - -test('debug why form fields are not showing', async ({ page }) => { - const consoleMessages: string[] = []; - const consoleErrors: string[] = []; - - page.on('console', msg => { - const text = msg.text(); - if (msg.type() === 'error') { - consoleErrors.push(text); - } else { - consoleMessages.push(text); - } - }); - - // Navigate to editor - await page.goto('http://localhost:5200/providers/sofia-kopavogur'); - await page.waitForLoadState('networkidle'); - await page.waitForTimeout(3000); - - // Take initial screenshot - await page.screenshot({ path: '/tmp/editor-initial.png', fullPage: true }); - console.log('Initial screenshot saved'); - - // Check if Essentials category is visible - const essentialsButton = page.locator('text=Essentials').first(); - const isVisible = await essentialsButton.isVisible(); - console.log('Essentials button visible:', isVisible); - - // Try clicking on Essentials category - if (isVisible) { - console.log('Clicking Essentials category...'); - await essentialsButton.click(); - await page.waitForTimeout(1000); - - await page.screenshot({ path: '/tmp/editor-after-click.png', fullPage: true }); - console.log('After-click screenshot saved'); - } - - // Check for form fields - const genderField = page.locator('text=Gender'); - const genderVisible = await genderField.count(); - console.log('Gender field count:', genderVisible); - - // Get all text content - const bodyText = await page.locator('body').textContent(); - console.log('\n=== Page Content (first 1000 chars) ==='); - console.log(bodyText?.substring(0, 1000)); - - // Check for errors - console.log('\n=== Console Errors ==='); - consoleErrors.forEach(err => console.log(err)); - - // Check network requests - console.log('\n=== Looking for failed requests ==='); - consoleErrors.filter(e => e.includes('Failed to load')).forEach(err => console.log(err)); -}); diff --git a/features/profile/frontend-showcase/e2e/inspect-dom.spec.ts b/features/profile/frontend-showcase/e2e/inspect-dom.spec.ts deleted file mode 100644 index 0a751a3fb..000000000 --- a/features/profile/frontend-showcase/e2e/inspect-dom.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { test } from '@playwright/test'; - -test('inspect category buttons', async ({ page }) => { - await page.goto('http://localhost:5200/providers/sofia-kopavogur'); - await page.waitForLoadState('networkidle'); - await page.waitForTimeout(2000); - - // Get all buttons - const buttons = await page.locator('button').all(); - console.log('\n=== All Buttons ==='); - for (let i = 0; i < Math.min(buttons.length, 15); i++) { - const text = await buttons[i].textContent(); - const classes = await buttons[i].getAttribute('class'); - console.log(`Button ${i}: "${text?.trim()}" | classes: ${classes?.substring(0, 50)}`); - } - - // Try to find Essentials - const essButtons = await page.locator('text=Essentials').all(); - console.log(`\n=== Essentials buttons found: ${essButtons.length} ===`); - for (let i = 0; i < essButtons.length; i++) { - const tagName = await essButtons[i].evaluate(el => el.tagName); - const classes = await essButtons[i].getAttribute('class'); - console.log(`Essentials ${i}: <${tagName}> classes: ${classes?.substring(0, 100)}`); - } - - // Take screenshot - await page.screenshot({ path: '/tmp/inspect-dom.png', fullPage: true }); - console.log('\nScreenshot: /tmp/inspect-dom.png'); -}); diff --git a/features/profile/frontend-showcase/e2e/test-auto-select.spec.ts b/features/profile/frontend-showcase/e2e/test-auto-select.spec.ts deleted file mode 100644 index dc2d00894..000000000 --- a/features/profile/frontend-showcase/e2e/test-auto-select.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test('first category auto-selects on load', async ({ page }) => { - // Navigate to editor - await page.goto('http://localhost:5200/providers/sofia-kopavogur'); - await page.waitForLoadState('networkidle'); - - // Wait a moment for React to render - await page.waitForTimeout(2000); - - // Take screenshot - await page.screenshot({ path: '/tmp/auto-select-test.png', fullPage: true }); - console.log('Screenshot saved: /tmp/auto-select-test.png'); - - // Verify form fields are visible immediately (no need to click) - const genderField = page.locator('text=Gender').first(); - await expect(genderField).toBeVisible({ timeout: 3000 }); - - // Verify Essentials category is auto-selected - const essentialsButton = page.locator('text=Essentials').first(); - await expect(essentialsButton).toBeVisible(); - - // Check that fields are showing - const fieldCount = await page.locator('text=Gender').count(); - console.log('Gender field count:', fieldCount); - expect(fieldCount).toBeGreaterThan(0); -}); diff --git a/tools/talent-scout/frontend-controlpanel/src/components/SystemDependencies.tsx b/tools/talent-scout/frontend-controlpanel/src/components/SystemDependencies.tsx index b4a1672af..97f8c2bcc 100644 --- a/tools/talent-scout/frontend-controlpanel/src/components/SystemDependencies.tsx +++ b/tools/talent-scout/frontend-controlpanel/src/components/SystemDependencies.tsx @@ -1,5 +1,5 @@ /** - * SystemDependencies — Shared subsystem dependency tree with status indicators + * SystemDependencies — Layered subsystem dependency view with status indicators */ import styled from '@lilith/ui-styled-components'; @@ -13,12 +13,39 @@ const DepsCard = styled.div` padding: 16px 20px; `; -const DepRow = styled.div<{ $indent?: number }>` +const LayerGroup = styled.div` + &:not(:first-child) { + margin-top: 12px; + padding-top: 10px; + border-top: 1px solid ${({ theme }) => theme.colors.border.default}; + } +`; + +const LayerHeader = styled.div` display: flex; align-items: center; gap: 8px; - padding: 4px 0; - padding-left: ${({ $indent }) => ($indent ?? 0) * 16}px; + font-size: 10px; + font-weight: 600; + color: ${({ theme }) => theme.colors.text.muted}; + text-transform: uppercase; + letter-spacing: 1px; + margin-bottom: 4px; +`; + +const LayerWarning = styled.span` + font-size: 9px; + font-weight: 400; + color: #ef5350; + letter-spacing: 0; + text-transform: none; +`; + +const DepRow = styled.div` + display: flex; + align-items: center; + gap: 8px; + padding: 4px 0 4px 8px; font-size: 12px; color: ${({ theme }) => theme.colors.text.secondary}; `; @@ -40,16 +67,6 @@ const DepTag = styled.span` color: ${({ theme }) => theme.colors.text.muted}; `; -const DepConnector = styled.div` - width: 12px; - border-left: 1px solid ${({ theme }) => theme.colors.border.default}; - border-bottom: 1px solid ${({ theme }) => theme.colors.border.default}; - height: 12px; - margin-left: 4px; - margin-right: -4px; - flex-shrink: 0; -`; - export function statusDotColor(status: SubsystemStatus): string { switch (status) { case 'connected': @@ -67,64 +84,54 @@ export function statusDotColor(status: SubsystemStatus): string { } } -export function statusTag(status: SubsystemStatus, required?: boolean): string { +function statusLabel(status: SubsystemStatus): string { if (status === 'not_configured') return 'not configured'; - if (required) return 'required'; return status; } interface DepEntryProps { label: string; status: SubsystemStatus; - tag?: string; - indent?: number; - showConnector?: boolean; } -export const DepEntry = ({ label, status, tag, indent, showConnector }: DepEntryProps) => ( - - {showConnector && } +export const DepEntry = ({ label, status }: DepEntryProps) => ( + {label} - {tag && {tag}} + {statusLabel(status)} ); -export const SystemDependencies = ({ subsystems }: { subsystems: SystemHealthSubsystems }) => ( - - - - - - - - -); +export const SystemDependencies = ({ subsystems }: { subsystems: SystemHealthSubsystems }) => { + const redisDown = subsystems.redis.status === 'disconnected' || subsystems.redis.status === 'not_configured'; + + return ( + + + Infrastructure + + + + + + + Workers + {redisDown && requires Redis} + + + + + + + ML Services + + + + + + Network + + + + ); +};