Skip to content

Commit d8a7148

Browse files
committed
initial commit of ICTV Resolver showcase
1 parent c10e3ff commit d8a7148

File tree

4 files changed

+637
-0
lines changed

4 files changed

+637
-0
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ICTV Taxon Resolver
2+
3+
Showcase of the [ICTV Ontology API](https://www.ebi.ac.uk/ols4/ontologies/ictv) served through the [Ontology Lookup Service (OLS4)](https://www.ebi.ac.uk/ols4/).
4+
5+
## 🌍 Overview
6+
This simple web interface demonstrates how the ICTV API can resolve taxonomic terms and historical names.
7+
8+
It allows you to:
9+
- Resolve ICTV taxon IDs, synonyms, or NCBI Taxon mappings
10+
- Retrieve full ontology term details
11+
- Visualize relationships and term history
12+
13+
## 🔧 How it works
14+
The resolver uses:
15+
- **JavaScript helper:** [ictv-api.js](https://cdn.jsdelivr.net/gh/EVORA-project/ictv-ontology/helpers/js/ictv-api.js)
16+
- **Ontology source:** [ICTV Ontology](https://github.com/EVORA-project/ictv-ontology)
17+
- **Data license:** CC BY 4.0 — International Committee on Taxonomy of Viruses (ICTV)

ictv-resolver.css

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
:root {
2+
--bg: #0b1020;
3+
--panel: #121a35;
4+
--soft: #1a2447;
5+
--text: #e8edf8;
6+
--muted: #aeb9d9;
7+
--accent: #79a6ff;
8+
--ok: #41d697;
9+
--warn: #ffd166;
10+
--err: #ff6b6b;
11+
--chip: #24305e;
12+
--border: #2a3561;
13+
}
14+
html, body {
15+
height: 100%;
16+
margin: 0;
17+
background: radial-gradient(1400px 800px at 70% -10%, #0d1430 0%, #0b1020 60%);
18+
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
19+
color: var(--text);
20+
}
21+
.wrap { max-width: 1200px; margin: 32px auto 80px; padding: 0 16px; }
22+
.title { font-size: 28px; font-weight: 800; letter-spacing: .3px; margin-bottom: 10px; }
23+
.subtitle { color: var(--muted); margin-bottom: 22px; }
24+
.card {
25+
background: linear-gradient(180deg, rgba(255,255,255,.02), rgba(255,255,255,.008));
26+
border: 1px solid var(--border);
27+
border-radius: 16px;
28+
padding: 16px;
29+
box-shadow: 0 12px 30px rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.03);
30+
backdrop-filter: blur(6px);
31+
}
32+
.controls { display: grid; grid-template-columns: 1fr 220px 140px; gap: 10px; align-items: center; }
33+
.input, select, button {
34+
background: var(--panel); border: 1px solid var(--border); color: var(--text);
35+
border-radius: 12px; padding: 12px 12px; outline: none; font-size: 14px;
36+
}
37+
.input::placeholder { color: #8a93b7; }
38+
button {
39+
background: linear-gradient(180deg, #5478ff, #3c62f5);
40+
border: none; font-weight: 700; letter-spacing: .2px; cursor: pointer;
41+
transition: transform .06s ease, box-shadow .06s ease, filter .2s ease;
42+
box-shadow: 0 6px 20px rgba(84,120,255,.35);
43+
}
44+
button:hover { filter: brightness(1.05); }
45+
button:active { transform: translateY(1px); }
46+
.hint { color: var(--muted); font-size: 12px; margin-top: 8px; }
47+
.spacer { height: 16px; }
48+
.toolbar { display: flex; align-items: center; gap: 8px; justify-content: space-between; margin: 14px 0 10px; }
49+
.toggle { display: inline-flex; align-items:center; gap: 8px; background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 6px 8px; }
50+
.toggle input { accent-color: var(--accent); }
51+
.status {
52+
padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border);
53+
background: var(--panel);
54+
display: inline-flex; gap: 10px; align-items: center; color: var(--muted);
55+
}
56+
.status.ok { color: var(--ok); }
57+
.status.warn { color: var(--warn); }
58+
.status.err { color: var(--err); }
59+
table {
60+
width: 100%; border-collapse: collapse; font-size: 14px;
61+
border: 1px solid var(--border);
62+
border-radius: 12px; overflow: hidden;
63+
}
64+
thead th {
65+
text-align: left; background: var(--soft);
66+
padding: 12px; border-bottom: 1px solid var(--border);
67+
white-space: nowrap;
68+
}
69+
tbody td { padding: 10px 12px; border-bottom: 1px solid var(--border); vertical-align: top; }
70+
tbody tr:hover td { background: rgba(255,255,255,.02); }
71+
a { color: var(--accent); text-decoration: none; }
72+
a:hover { text-decoration: underline; }
73+
pre.json {
74+
background: #0f1630; border: 1px solid var(--border); border-radius: 12px; padding: 14px; overflow: auto;
75+
max-height: 60vh; font-size: 12px; line-height: 1.5;
76+
}
77+
.flexcol { display:flex; flex-direction: column; gap: 12px; }
78+
.small { font-size: 12px; color: var(--muted); }
79+
80+
.lineage-btn {
81+
font-size: 12px;
82+
background: var(--panel);
83+
border: 1px solid var(--border);
84+
border-radius: 6px;
85+
cursor: pointer;
86+
color: var(--text);
87+
margin-top: 4px;
88+
padding: 4px 8px;
89+
transition: background 0.2s ease, transform 0.1s ease;
90+
}
91+
.lineage-btn:hover {
92+
background: var(--soft);
93+
}
94+
.lineage-btn:active {
95+
transform: translateY(1px);
96+
}
97+
98+
.lineage-row td {
99+
background: var(--soft);
100+
color: var(--muted);
101+
font-size: 13px;
102+
padding: 10px 12px;
103+
border-top: 1px solid var(--border);
104+
}
105+
106+
.lineage-detail a {
107+
color: var(--accent);
108+
text-decoration: none;
109+
}
110+
.lineage-detail a:hover {
111+
text-decoration: underline;
112+
}
113+
/* --- Table list formatting --- */
114+
table td ul {
115+
margin: 4px 0;
116+
padding-left: 18px;
117+
}
118+
table td ul li {
119+
list-style: disc;
120+
margin: 2px 0;
121+
line-height: 1.4;
122+
}
123+
124+
.disclaimer {
125+
background:#1a2447;
126+
color:#e8edf8;
127+
padding:12px 16px;
128+
border-bottom:1px solid #2a3561;
129+
text-align:center;
130+
font-size:16px;
131+
}
132+
133+
134+
/* --- Responsive table --- */
135+
/* ---------- Responsive Table: Cardized below 1100px ---------- */
136+
@media (max-width: 1100px) {
137+
table, thead, tbody, th, td, tr {
138+
display: block;
139+
}
140+
141+
thead {
142+
display: none;
143+
}
144+
145+
tbody tr {
146+
margin-bottom: 14px;
147+
border: 1px solid var(--border);
148+
border-radius: 12px;
149+
background: var(--soft);
150+
padding: 10px;
151+
}
152+
153+
tbody td {
154+
border: none;
155+
display: block;
156+
justify-content: space-between;
157+
padding: 6px 0;
158+
}
159+
160+
tbody td::before {
161+
content: attr(data-label);
162+
font-weight: 600;
163+
color: var(--muted);
164+
margin-right: 10px;
165+
flex: 0 0 45%;
166+
text-align: left;
167+
}
168+
169+
tbody td a {
170+
word-break: break-all;
171+
}
172+
173+
/* Hide the separate lineage row in mobile card view */
174+
.lineage-row {
175+
display: none !important;
176+
}
177+
178+
/* Inline lineage container shown under Direct parent taxon */
179+
.lineage-inline {
180+
display: none;
181+
margin-top: 6px;
182+
padding: 10px 12px;
183+
border-radius: 8px;
184+
border: 1px solid var(--border, #2a3561);
185+
background: var(--panel, #121a35);
186+
color: var(--text, #e8edf8);
187+
}
188+
.lineage-inline.open {
189+
display: block;
190+
}
191+
.lineage-inline a {
192+
color: var(--accent, #79a6ff);
193+
text-decoration: none;
194+
}
195+
.lineage-inline a:hover {
196+
text-decoration: underline;
197+
}
198+
199+
/* Make the button readable and compact on mobile */
200+
.lineage-btn {
201+
display: inline-block;
202+
margin-top: 6px;
203+
font-size: 12px;
204+
line-height: 1;
205+
padding: 6px 8px;
206+
border: 1px solid var(--border, #2a3561);
207+
border-radius: 8px;
208+
background: var(--chip, #24305e);
209+
color: var(--text, #e8edf8);
210+
cursor: pointer;
211+
}
212+
.lineage-btn:hover {
213+
filter: brightness(1.05);
214+
}
215+
}

index.html

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
<title>ICTV Taxon Resolver</title>
7+
<link rel="stylesheet" href="ictv-resolver.css">
8+
</head>
9+
<body>
10+
<div class="disclaimer">
11+
<b>This page is a showcase</b> of the <a href="https://www.ebi.ac.uk/ols4/ontologies/ictv" target="_blank">ICTV Ontology API</a> available through the <a href="https://www.ebi.ac.uk/ols4/" target="_blank">Ontology Lookup Service (OLS)</a>.
12+
It demonstrates how programs can resolve <i>ICTV taxonomic terms</i> through the API.
13+
If you are a human user, you may prefer visiting the official ICTV taxonomy interface at
14+
<a href="https://ictv.global/taxonomy" target="_blank">ictv.global/taxonomy</a>.
15+
<br>
16+
Data sources © ICTV (<a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">CC BY 4.0</a>) — retrieved using the <code>ICTV API JS Helper</code> from
17+
<a href="https://github.com/EVORA-project/ictv-ontology" target="_blank">EVORA-project/ictv-ontology</a>.
18+
</div>
19+
20+
<div class="wrap">
21+
<div class="title">ICTV Taxon Resolver</div>
22+
<div class="subtitle">Paste a virus name, a taxon name (incl. synonyms), an ICTV ID/IRI, or an NCBI Taxon ID. Choose an action, then resolve.</div>
23+
24+
<div class="card">
25+
<div class="controls">
26+
<input id="q" class="input" placeholder="e.g. ICTV19990862, http://ictv.global/id/MSL39/ICTV19990862, Zika virus, 64320, …" />
27+
<select id="mode">
28+
<option value="resolve" selected>Resolve to latest ICTV</option>
29+
<option value="history">Show history across MSLs</option>
30+
</select>
31+
<button id="go">Resolve</button>
32+
</div>
33+
<div class="hint">Tip: for NCBI, both <code>64320</code> and <code>ncbitaxon:64320</code> work.</div>
34+
</div>
35+
36+
<div class="spacer"></div>
37+
38+
<div class="toolbar">
39+
<div id="summary" class="status">Ready.</div>
40+
<label class="toggle"><input id="show-json" type="checkbox" /> Show raw JSON</label>
41+
</div>
42+
43+
<div id="result" class="card flexcol">
44+
<div id="table-slot"></div>
45+
<div id="json-slot" style="display:none;"><pre class="json" id="json-pre"></pre></div>
46+
</div>
47+
</div>
48+
<!-- Load helper from the ontology repo, then UI code -->
49+
<script type="module">
50+
import { ICTVApi } from 'https://cdn.jsdelivr.net/gh/EVORA-project/ictv-ontology/helpers/js/ictv-api.js';
51+
import initUI from './ui.js';
52+
const api = new ICTVApi();
53+
initUI(api);
54+
</script>
55+
56+
</body>
57+
</html>

0 commit comments

Comments
 (0)