File size: 1,592 Bytes
20b15f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"""
ui/search_progress.py
---------------------
Live checklist renderer for the SEARCHING stage: turns the set of completed
LangGraph node names + per-source paper counts into the step-by-step HTML
checklist markup.
"""

_SEARCH_STEPS = [
    ("arxiv", "Searching arXiv"),
    ("semantic_scholar", "Searching Semantic Scholar"),
    ("open_alex", "Searching OpenAlex"),
    ("aggregation", "Merging & deduplicating"),
    ("reranker", "Re-ranking by relevance (SPECTER)"),
    ("clustering", "Clustering by approach"),
]


def search_steps_html(completed: set, counts: dict) -> str:
    sources_done = all(s in completed for s in ("arxiv", "semantic_scholar", "open_alex"))

    def state_of(key):
        if key in completed:
            return "done"
        if key in ("arxiv", "semantic_scholar", "open_alex"):
            return "active"
        if key == "aggregation":
            return "active" if sources_done else "pending"
        if key == "reranker":
            return "active" if "aggregation" in completed else "pending"
        if key == "clustering":
            return "active" if "reranker" in completed else "pending"
        return "pending"

    rows = []
    for key, label in _SEARCH_STEPS:
        s = state_of(key)
        ic = "✓" if s == "done" else ("•" if s == "pending" else "")
        cnt = f'<span class="step-count">{counts[key]} papers</span>' if key in counts else ""
        rows.append(f'<div class="step-row {s}"><div class="step-ic">{ic}</div><div>{label}</div>{cnt}</div>')
    return '<div class="search-wrap">' + "".join(rows) + "</div>"