defmodule TarakanWeb.InfestationComponents do
@moduledoc """
Functional infestation surfaces: ranked pattern table and per-pattern repo matrix.
"""
use Phoenix.Component
use Phoenix.VerifiedRoutes,
endpoint: TarakanWeb.Endpoint,
router: TarakanWeb.Router,
statics: TarakanWeb.static_paths()
alias TarakanWeb.RepositoryPaths
attr :infestations, :list, required: true
attr :id, :string, default: "infestation-constellation"
attr :compact, :boolean, default: false
@doc "Ranked multi-repo patterns (homepage / index)."
def constellation(assigns) do
max_repos =
assigns.infestations
|> Enum.map(& &1.repo_count)
|> Enum.max(fn -> 1 end)
assigns = assign(assigns, :max_repos, max(max_repos, 1))
~H"""
| # |
Pattern |
Spread |
Repos |
Open |
Ver |
Fix |
|
{i}
|
<.link
id={"#{@id}-hub-#{infestation.pattern_key}"}
navigate={~p"/infestations/#{infestation.pattern_key}"}
class="block min-w-0"
>
{infestation.severity}
{infestation.title}
{String.slice(infestation.pattern_key, 0, 12)}…
|
|
{infestation.repo_count}
|
{infestation.open_count}
|
{infestation.verified_count}
|
{infestation.fixed_count}
|
"""
end
attr :repos, :list, required: true, doc: "pattern_repos rows: one per repository"
attr :infestation, :map, required: true
attr :pattern_key, :string, required: true
attr :id, :string, default: "infestation-graph"
@doc """
Per-repo infestation matrix for one pattern.
One row per repository, rolled up from that repo's instances. The instance
grain (one row per finding) is the separate ledger on the same page.
"""
def infestation_graph(assigns) do
~H"""
No listed public repositories.
|
Repository |
Status |
Findings |
Open
|
|
|
|
<.link
:if={repo[:host]}
navigate={RepositoryPaths.repository_path(repo)}
class="block truncate font-mono text-xs font-semibold text-ink hover:text-signal hover:underline"
>
{repo.owner}/{repo.name}
{repo.owner}/{repo.name}
|
{repo.status}
|
{repo[:instance_count] || 1}
|
0 && "text-phosphor",
(repo[:open_count] || 0) == 0 && "text-ink-faint"
]}>
{repo[:open_count] || 0}
|
<.link
:if={repo.occurrence_public_id}
navigate={~p"/findings/#{repo.occurrence_public_id}"}
class="font-mono text-[11px] text-signal hover:underline"
>
Finding →
|
"""
end
defp bar_pct(count, max) when max > 0 do
count
|> Kernel./(max)
|> Kernel.*(100)
|> Float.round(1)
|> max(4)
|> min(100)
end
defp bar_pct(_, _), do: 0
end