refactor: extract email path into standalone card component

Move the received chain display out of BlacklistCard into EmailPathCard,
giving it its own card styling and placing it as a dedicated section on
the report page.
This commit is contained in:
nemunaire 2026-03-09 13:09:07 +07:00
commit d9b9ea87c6
3 changed files with 26 additions and 13 deletions

View file

@ -1,18 +1,16 @@
<script lang="ts"> <script lang="ts">
import type { BlacklistCheck, ReceivedHop } from "$lib/api/types.gen"; import type { BlacklistCheck } from "$lib/api/types.gen";
import { getScoreColorClass } from "$lib/score"; import { getScoreColorClass } from "$lib/score";
import { theme } from "$lib/stores/theme"; import { theme } from "$lib/stores/theme";
import EmailPathCard from "./EmailPathCard.svelte";
import GradeDisplay from "./GradeDisplay.svelte"; import GradeDisplay from "./GradeDisplay.svelte";
interface Props { interface Props {
blacklists: Record<string, BlacklistCheck[]>; blacklists: Record<string, BlacklistCheck[]>;
blacklistGrade?: string; blacklistGrade?: string;
blacklistScore?: number; blacklistScore?: number;
receivedChain?: ReceivedHop[];
} }
let { blacklists, blacklistGrade, blacklistScore, receivedChain }: Props = $props(); let { blacklists, blacklistGrade, blacklistScore }: Props = $props();
</script> </script>
<div class="card shadow-sm" id="rbl-details"> <div class="card shadow-sm" id="rbl-details">
@ -35,10 +33,6 @@
</h4> </h4>
</div> </div>
<div class="card-body"> <div class="card-body">
{#if receivedChain}
<EmailPathCard {receivedChain} />
{/if}
<div class="row row-cols-1 row-cols-lg-2"> <div class="row row-cols-1 row-cols-lg-2">
{#each Object.entries(blacklists) as [ip, checks]} {#each Object.entries(blacklists) as [ip, checks]}
<div class="col mb-3"> <div class="col mb-3">

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { ReceivedHop } from "$lib/api/types.gen"; import type { ReceivedHop } from "$lib/api/types.gen";
import { theme } from "$lib/stores/theme";
interface Props { interface Props {
receivedChain: ReceivedHop[]; receivedChain: ReceivedHop[];
@ -9,9 +10,18 @@
</script> </script>
{#if receivedChain && receivedChain.length > 0} {#if receivedChain && receivedChain.length > 0}
<div class="mb-3" id="email-path"> <div class="card shadow-sm" id="email-path">
<h5>Email Path (Received Chain)</h5> <div
<div class="list-group"> class="card-header"
class:bg-white={$theme === "light"}
class:bg-dark={$theme !== "light"}
>
<h4 class="mb-0">
<i class="bi bi-pin-map me-2"></i>
Email Path
</h4>
</div>
<div class="list-group list-group-flush">
{#each receivedChain as hop, i} {#each receivedChain as hop, i}
<div class="list-group-item"> <div class="list-group-item">
<div class="d-flex w-100 justify-content-between"> <div class="d-flex w-100 justify-content-between">
@ -30,7 +40,7 @@
: "-"} : "-"}
</small> </small>
</div> </div>
{#if hop.with || hop.id} {#if hop.with || hop.id || hop.from}
<p class="mb-1 small d-flex gap-3"> <p class="mb-1 small d-flex gap-3">
{#if hop.with} {#if hop.with}
<span> <span>

View file

@ -9,6 +9,7 @@
BlacklistCard, BlacklistCard,
ContentAnalysisCard, ContentAnalysisCard,
DnsRecordsCard, DnsRecordsCard,
EmailPathCard,
ErrorDisplay, ErrorDisplay,
HeaderAnalysisCard, HeaderAnalysisCard,
PendingState, PendingState,
@ -294,6 +295,15 @@
</div> </div>
</div> </div>
<!-- Received Chain -->
{#if report.header_analysis?.received_chain && report.header_analysis.received_chain.length > 0}
<div class="row mb-4" id="received-chain">
<div class="col-12">
<EmailPathCard receivedChain={report.header_analysis.received_chain} />
</div>
</div>
{/if}
<!-- DNS Records --> <!-- DNS Records -->
{#if report.dns_results} {#if report.dns_results}
<div class="row mb-4" id="dns"> <div class="row mb-4" id="dns">
@ -329,7 +339,6 @@
{blacklists} {blacklists}
blacklistGrade={report.summary?.blacklist_grade} blacklistGrade={report.summary?.blacklist_grade}
blacklistScore={report.summary?.blacklist_score} blacklistScore={report.summary?.blacklist_score}
receivedChain={report.header_analysis?.received_chain}
/> />
{/snippet} {/snippet}