Files
inter-hub/Web/View/CrossHubPropagations/Index.hs
Bernd Worsch 98fb159582
Some checks failed
Test / test (push) Has been cancelled
feat(P7): IHF Phase 7 complete — advanced observability and operational integration
T01 schema: friction_scores, bottleneck_records, hub_health_snapshots,
cross_hub_propagations + migration 1743552000.

T02 Widget Pain Heatmap: computeFrictionScore (formula documented), RecomputeFriction
action, colour-coded grid view (green/yellow/amber/red).

T03 Workflow Bottleneck Analysis: detectBottlenecks across 4 pipeline stages
(candidate 30d, requirement 60d, decision 30d, observation 14d), idempotent,
severity from age ratio, resolve action.

T04 Hub Health Correlation: computeHubHealth (deduction table documented),
append-only HubHealthSnapshot, health history view, badge on hub Show page.

T05 Cross-Hub Propagation: annotation_cluster + widget_type_friction heuristics,
idempotent detection, acknowledge/resolve lifecycle.

T06 Operational Review Board: 4-panel AutoRefresh global dashboard — health matrix,
top-10 friction, bottleneck stage counts, open propagations.

T07 gate: 5 describe blocks in Test/Integration.hs; SCOPE.md updated Phase 7
complete; docs/phase7-summary.md written.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 21:49:22 +00:00

89 lines
3.8 KiB
Haskell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
module Web.View.CrossHubPropagations.Index where
import Web.Types
import Generated.Types
import IHP.Prelude
import IHP.ViewPrelude
data IndexView = IndexView
{ propagations :: ![CrossHubPropagation]
, hubs :: ![Hub]
}
instance View IndexView where
html IndexView { .. } = [hsx|
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-semibold">Cross-Hub Propagations</h1>
<a href={DetectPropagationsAction}
class="text-sm bg-indigo-600 text-white px-3 py-1.5 rounded hover:bg-indigo-700">
Detect
</a>
</div>
{if null propagations
then [hsx|<p class="text-sm text-gray-400">No propagation events detected yet.</p>|]
else [hsx|
<div class="bg-white rounded-lg border border-gray-200 overflow-hidden">
<table class="w-full text-sm">
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="text-left px-4 py-3 font-medium text-gray-700">Pattern</th>
<th class="text-left px-4 py-3 font-medium text-gray-700">Summary</th>
<th class="text-left px-4 py-3 font-medium text-gray-700">Source Hub</th>
<th class="text-left px-4 py-3 font-medium text-gray-700">Status</th>
<th class="text-left px-4 py-3 font-medium text-gray-700">Detected</th>
<th class="px-4 py-3"></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
{forEach propagations renderRow}
</tbody>
</table>
</div>
|]}
|]
where
hubName hid = maybe "" (.name) (find (\h -> h.id == hid) hubs)
renderRow :: CrossHubPropagation -> Html
renderRow p = [hsx|
<tr class="hover:bg-gray-50">
<td class="px-4 py-3">
<span class="bg-purple-100 text-purple-700 text-xs px-1.5 py-0.5 rounded">
{p.patternType}
</span>
</td>
<td class="px-4 py-3 text-gray-700">{p.summary}</td>
<td class="px-4 py-3 text-gray-500 text-xs">
{maybe "" hubName p.sourceHubId}
</td>
<td class="px-4 py-3">
<span class={statusBadge p.status <> " text-xs px-2 py-0.5 rounded font-medium"}>
{p.status}
</span>
</td>
<td class="px-4 py-3 text-xs text-gray-400">{show p.detectedAt}</td>
<td class="px-4 py-3 text-right">
{if p.status == "open"
then [hsx|
<a href={AcknowledgePropagationAction { crossHubPropagationId = p.id }}
class="text-xs text-yellow-600 hover:underline mr-2">Acknowledge</a>
|]
else mempty}
{if p.status /= "resolved"
then [hsx|
<a href={ResolvePropagationAction { crossHubPropagationId = p.id }}
class="text-xs text-green-600 hover:underline">Resolve</a>
|]
else mempty}
</td>
</tr>
|]
statusBadge :: Text -> Text
statusBadge s = case s of
"open" -> "bg-yellow-100 text-yellow-800"
"acknowledged" -> "bg-blue-100 text-blue-800"
"resolved" -> "bg-green-100 text-green-800"
_ -> "bg-gray-100 text-gray-600"