fix: TLD Matrix shows own domain correctly as taken + Portfolio table responsive
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
1. TLD Matrix fix: - Pass original_is_taken flag to run_tld_matrix() - If main domain check shows taken, force same TLD to show as taken - Fixes incorrect "available" display for owned domains 2. Portfolio table: - Use minmax() for flexible column widths - Smaller gaps and padding for compact layout - Smaller action buttons (w-8 h-8) - Shorter column labels (Bought, Exp.)
This commit is contained in:
@ -10,7 +10,12 @@ class TldMatrixAnalyzer:
|
||||
ttl_seconds = 60 * 30 # 30m (availability can change)
|
||||
|
||||
async def analyze(self, ctx: AnalyzeContext) -> list[AnalyzerContribution]:
|
||||
rows = await run_tld_matrix(ctx.domain)
|
||||
# If main domain check says it's taken, pass that info to TLD matrix
|
||||
# This ensures the original TLD shows correctly as "taken" even if
|
||||
# DNS-based checks fail (e.g., domain registered but no DNS records)
|
||||
original_is_taken = ctx.check and not ctx.check.is_available
|
||||
|
||||
rows = await run_tld_matrix(ctx.domain, original_is_taken=original_is_taken)
|
||||
item = AnalyzeItem(
|
||||
key="tld_matrix",
|
||||
label="TLD Matrix",
|
||||
|
||||
@ -48,11 +48,21 @@ async def _check_one(domain: str) -> TldMatrixRow:
|
||||
)
|
||||
|
||||
|
||||
async def run_tld_matrix(domain: str, tlds: list[str] | None = None) -> list[TldMatrixRow]:
|
||||
sld = (domain or "").split(".")[0].lower().strip()
|
||||
async def run_tld_matrix(domain: str, tlds: list[str] | None = None, original_is_taken: bool = False) -> list[TldMatrixRow]:
|
||||
"""
|
||||
Check availability for the same SLD across multiple TLDs.
|
||||
|
||||
Args:
|
||||
domain: The full domain being analyzed (e.g., "akaya.ch")
|
||||
tlds: List of TLDs to check (defaults to DEFAULT_TLDS)
|
||||
original_is_taken: If True, force the original domain's TLD to show as taken
|
||||
"""
|
||||
parts = (domain or "").lower().strip().split(".")
|
||||
sld = parts[0] if parts else ""
|
||||
original_tld = parts[-1] if len(parts) > 1 else ""
|
||||
tlds = [t.lower().lstrip(".") for t in (tlds or DEFAULT_TLDS)]
|
||||
|
||||
# Avoid repeated checks and the original TLD duplication
|
||||
# Avoid repeated checks
|
||||
seen = set()
|
||||
candidates: list[str] = []
|
||||
for t in tlds:
|
||||
@ -62,5 +72,23 @@ async def run_tld_matrix(domain: str, tlds: list[str] | None = None) -> list[Tld
|
||||
seen.add(d)
|
||||
|
||||
rows = await asyncio.gather(*[_check_one(d) for d in candidates])
|
||||
return list(rows)
|
||||
result = list(rows)
|
||||
|
||||
# If the original domain is known to be taken, ensure its TLD shows as taken
|
||||
# This fixes cases where DNS-based quick checks incorrectly show "available"
|
||||
# for domains that are registered but have no DNS records
|
||||
if original_is_taken and original_tld:
|
||||
result = [
|
||||
TldMatrixRow(
|
||||
tld=r.tld,
|
||||
domain=r.domain,
|
||||
is_available=False,
|
||||
status="taken",
|
||||
method=r.method,
|
||||
error=r.error,
|
||||
) if r.tld == original_tld else r
|
||||
for r in result
|
||||
]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@ -1346,31 +1346,31 @@ export default function PortfolioPage() {
|
||||
) : (
|
||||
<div className="border border-white/[0.08] bg-[#020202] overflow-hidden">
|
||||
{/* Desktop Table Header */}
|
||||
<div className="hidden lg:grid grid-cols-[1fr_140px_90px_90px_100px_90px_80px_60px_160px] gap-6 px-6 py-4 text-[10px] font-mono text-white/40 uppercase tracking-[0.15em] border-b border-white/[0.08] bg-white/[0.02]">
|
||||
<div className="hidden lg:grid grid-cols-[minmax(150px,1.5fr)_minmax(100px,1fr)_80px_70px_90px_70px_70px_50px_auto] gap-4 px-5 py-3 text-[10px] font-mono text-white/40 uppercase tracking-[0.12em] border-b border-white/[0.08] bg-white/[0.02]">
|
||||
<button onClick={() => handleSort('domain')} className="flex items-center gap-2 hover:text-white transition-colors text-left">
|
||||
<span className={clsx(sortField === 'domain' && "text-accent font-bold")}>Domain</span>
|
||||
{sortField === 'domain' && (sortDirection === 'asc' ? <ChevronUp className="w-3 h-3 text-accent" /> : <ChevronDown className="w-3 h-3 text-accent" />)}
|
||||
</button>
|
||||
<div>Registrar</div>
|
||||
<button onClick={() => handleSort('purchased')} className="flex items-center gap-2 justify-center hover:text-white transition-colors">
|
||||
<span className={clsx(sortField === 'purchased' && "text-accent font-bold")}>Purchased</span>
|
||||
<button onClick={() => handleSort('purchased')} className="flex items-center gap-1 justify-center hover:text-white transition-colors">
|
||||
<span className={clsx(sortField === 'purchased' && "text-accent font-bold")}>Bought</span>
|
||||
{sortField === 'purchased' && (sortDirection === 'asc' ? <ChevronUp className="w-3 h-3 text-accent" /> : <ChevronDown className="w-3 h-3 text-accent" />)}
|
||||
</button>
|
||||
<button onClick={() => handleSort('renewal')} className="flex items-center gap-2 justify-center hover:text-white transition-colors">
|
||||
<span className={clsx(sortField === 'renewal' && "text-accent font-bold")}>Expires</span>
|
||||
<button onClick={() => handleSort('renewal')} className="flex items-center gap-1 justify-center hover:text-white transition-colors">
|
||||
<span className={clsx(sortField === 'renewal' && "text-accent font-bold")}>Exp.</span>
|
||||
{sortField === 'renewal' && (sortDirection === 'asc' ? <ChevronUp className="w-3 h-3 text-accent" /> : <ChevronDown className="w-3 h-3 text-accent" />)}
|
||||
</button>
|
||||
<button onClick={() => handleSort('value')} className="flex items-center gap-2 justify-end hover:text-white transition-colors">
|
||||
<button onClick={() => handleSort('value')} className="flex items-center gap-1 justify-end hover:text-white transition-colors">
|
||||
<span className={clsx(sortField === 'value' && "text-accent font-bold")}>Value</span>
|
||||
{sortField === 'value' && (sortDirection === 'asc' ? <ChevronUp className="w-3 h-3 text-accent" /> : <ChevronDown className="w-3 h-3 text-accent" />)}
|
||||
</button>
|
||||
<button onClick={() => handleSort('roi')} className="flex items-center gap-2 justify-end hover:text-white transition-colors">
|
||||
<button onClick={() => handleSort('roi')} className="flex items-center gap-1 justify-end hover:text-white transition-colors">
|
||||
<span className={clsx(sortField === 'roi' && "text-accent font-bold")}>ROI</span>
|
||||
{sortField === 'roi' && (sortDirection === 'asc' ? <ChevronUp className="w-3 h-3 text-accent" /> : <ChevronDown className="w-3 h-3 text-accent" />)}
|
||||
</button>
|
||||
<div className="text-center">Yield</div>
|
||||
<div className="text-center">Health</div>
|
||||
<div className="text-right">Actions</div>
|
||||
<div className="text-right pr-1">Actions</div>
|
||||
</div>
|
||||
|
||||
{/* Table Body */}
|
||||
@ -1393,7 +1393,7 @@ export default function PortfolioPage() {
|
||||
)}
|
||||
>
|
||||
{/* DESKTOP ROW */}
|
||||
<div className="hidden lg:grid grid-cols-[1fr_140px_90px_90px_100px_90px_80px_60px_160px] gap-6 px-6 py-4 items-center group-hover:bg-white/[0.02]">
|
||||
<div className="hidden lg:grid grid-cols-[minmax(150px,1.5fr)_minmax(100px,1fr)_80px_70px_90px_70px_70px_50px_auto] gap-4 px-5 py-3 items-center group-hover:bg-white/[0.02]">
|
||||
{/* Domain */}
|
||||
<div className="flex items-center gap-3 min-w-0">
|
||||
<button
|
||||
@ -1462,31 +1462,31 @@ export default function PortfolioPage() {
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center justify-end gap-2 opacity-40 group-hover:opacity-100 transition-all">
|
||||
<div className="flex items-center justify-end gap-1 opacity-40 group-hover:opacity-100 transition-all">
|
||||
<button
|
||||
onClick={() => openAnalyze(domain.domain)}
|
||||
title="Analyze"
|
||||
className="w-10 h-10 flex items-center justify-center text-white/40 hover:text-accent border border-white/10 hover:bg-accent/10 hover:border-accent/20 transition-all"
|
||||
className="w-8 h-8 flex items-center justify-center text-white/40 hover:text-accent border border-white/10 hover:bg-accent/10 hover:border-accent/20 transition-all"
|
||||
>
|
||||
<Shield className="w-4 h-4" />
|
||||
<Shield className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setEditingDomain(domain)}
|
||||
title="Edit"
|
||||
className="w-10 h-10 flex items-center justify-center text-white/40 hover:text-white border border-white/10 hover:bg-white/5 transition-all"
|
||||
className="w-8 h-8 flex items-center justify-center text-white/40 hover:text-white border border-white/10 hover:bg-white/5 transition-all"
|
||||
>
|
||||
<Edit3 className="w-4 h-4" />
|
||||
<Edit3 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDelete(domain.id, domain.domain)}
|
||||
disabled={deletingId === domain.id}
|
||||
title="Remove"
|
||||
className="w-10 h-10 flex items-center justify-center text-white/40 hover:text-rose-400 border border-white/10 hover:border-rose-400/20 hover:bg-rose-500/10 transition-all"
|
||||
className="w-8 h-8 flex items-center justify-center text-white/40 hover:text-rose-400 border border-white/10 hover:border-rose-400/20 hover:bg-rose-500/10 transition-all"
|
||||
>
|
||||
{deletingId === domain.id ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
<Loader2 className="w-3.5 h-3.5 animate-spin" />
|
||||
) : (
|
||||
<Trash2 className="w-4 h-4" />
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user