Sanjana Vekhande commited on
Commit Β·
7c2f04d
1
Parent(s): 932f7e0
add species prefix mismatch validation
Browse files- frontend/index.html +43 -0
frontend/index.html
CHANGED
|
@@ -339,6 +339,20 @@ input[type="range"]::-webkit-slider-thumb:hover {
|
|
| 339 |
font-weight: 500;
|
| 340 |
}
|
| 341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
/* ββ Run section βββββββββββββββββββββββ */
|
| 343 |
.run-section {
|
| 344 |
margin-top: 2.5rem;
|
|
@@ -598,6 +612,9 @@ footer a:hover { color: var(--ink); }
|
|
| 598 |
</div>
|
| 599 |
</div>
|
| 600 |
|
|
|
|
|
|
|
|
|
|
| 601 |
<!-- Run -->
|
| 602 |
<div class="run-section">
|
| 603 |
<button class="btn-run" id="runBtn" onclick="startJob()">
|
|
@@ -660,6 +677,30 @@ function updateSlider(val) {
|
|
| 660 |
|
| 661 |
window.addEventListener('DOMContentLoaded', () => updateSlider(1000));
|
| 662 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 663 |
function handleFiles(type, files) {
|
| 664 |
state[type] = Array.from(files);
|
| 665 |
const key = { model: 'chipsModel', mapping: 'chipsMapping', expr: 'chipsExpr' }[type];
|
|
@@ -667,6 +708,7 @@ function handleFiles(type, files) {
|
|
| 667 |
document.getElementById(key).innerHTML =
|
| 668 |
state[type].map(f => `<div class="chip">β ${f.name}</div>`).join('');
|
| 669 |
document.getElementById(num).classList.add('done');
|
|
|
|
| 670 |
}
|
| 671 |
|
| 672 |
['dropModel','dropMapping','dropExpr'].forEach(id => {
|
|
@@ -680,6 +722,7 @@ async function startJob() {
|
|
| 680 |
if (!state.model.length) { alert('Please upload at least one model file.'); return; }
|
| 681 |
if (!state.mapping.length) { alert('Please upload at least one mapping file.'); return; }
|
| 682 |
if (!state.expr.length) { alert('Please upload a gene expression CSV.'); return; }
|
|
|
|
| 683 |
|
| 684 |
document.getElementById('runBtn').disabled = true;
|
| 685 |
document.getElementById('progressSection').classList.remove('hidden');
|
|
|
|
| 339 |
font-weight: 500;
|
| 340 |
}
|
| 341 |
|
| 342 |
+
.mismatch-warning {
|
| 343 |
+
display: flex;
|
| 344 |
+
align-items: flex-start;
|
| 345 |
+
gap: 8px;
|
| 346 |
+
background: #FFF7ED;
|
| 347 |
+
border: 1.5px solid #FED7AA;
|
| 348 |
+
border-radius: 8px;
|
| 349 |
+
padding: 0.75rem 1rem;
|
| 350 |
+
margin-top: 0.75rem;
|
| 351 |
+
font-size: 13px;
|
| 352 |
+
color: #9A3412;
|
| 353 |
+
line-height: 1.5;
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
/* ββ Run section βββββββββββββββββββββββ */
|
| 357 |
.run-section {
|
| 358 |
margin-top: 2.5rem;
|
|
|
|
| 612 |
</div>
|
| 613 |
</div>
|
| 614 |
|
| 615 |
+
<!-- Prefix mismatch warning -->
|
| 616 |
+
<div class="mismatch-warning hidden" id="prefixWarning"></div>
|
| 617 |
+
|
| 618 |
<!-- Run -->
|
| 619 |
<div class="run-section">
|
| 620 |
<button class="btn-run" id="runBtn" onclick="startJob()">
|
|
|
|
| 677 |
|
| 678 |
window.addEventListener('DOMContentLoaded', () => updateSlider(1000));
|
| 679 |
|
| 680 |
+
function getPrefix(filename) {
|
| 681 |
+
return filename.split('_')[0].toLowerCase();
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
function checkPrefixMatch() {
|
| 685 |
+
const warn = document.getElementById('prefixWarning');
|
| 686 |
+
if (!state.model.length || !state.mapping.length) {
|
| 687 |
+
warn.classList.add('hidden');
|
| 688 |
+
return true;
|
| 689 |
+
}
|
| 690 |
+
const modelPrefixes = state.model.map(f => getPrefix(f.name)).sort();
|
| 691 |
+
const mappingPrefixes = state.mapping.map(f => getPrefix(f.name)).sort();
|
| 692 |
+
const mismatch =
|
| 693 |
+
modelPrefixes.length !== mappingPrefixes.length ||
|
| 694 |
+
modelPrefixes.some((p, i) => p !== mappingPrefixes[i]);
|
| 695 |
+
if (mismatch) {
|
| 696 |
+
warn.innerHTML = `β οΈ <span>Species prefix mismatch β model files (${modelPrefixes.join(', ')}) don't match mapping files (${mappingPrefixes.join(', ')}). Make sure files are uploaded in the same order and belong to the same species.</span>`;
|
| 697 |
+
warn.classList.remove('hidden');
|
| 698 |
+
return false;
|
| 699 |
+
}
|
| 700 |
+
warn.classList.add('hidden');
|
| 701 |
+
return true;
|
| 702 |
+
}
|
| 703 |
+
|
| 704 |
function handleFiles(type, files) {
|
| 705 |
state[type] = Array.from(files);
|
| 706 |
const key = { model: 'chipsModel', mapping: 'chipsMapping', expr: 'chipsExpr' }[type];
|
|
|
|
| 708 |
document.getElementById(key).innerHTML =
|
| 709 |
state[type].map(f => `<div class="chip">β ${f.name}</div>`).join('');
|
| 710 |
document.getElementById(num).classList.add('done');
|
| 711 |
+
checkPrefixMatch();
|
| 712 |
}
|
| 713 |
|
| 714 |
['dropModel','dropMapping','dropExpr'].forEach(id => {
|
|
|
|
| 722 |
if (!state.model.length) { alert('Please upload at least one model file.'); return; }
|
| 723 |
if (!state.mapping.length) { alert('Please upload at least one mapping file.'); return; }
|
| 724 |
if (!state.expr.length) { alert('Please upload a gene expression CSV.'); return; }
|
| 725 |
+
if (!checkPrefixMatch()) { alert('Fix the species prefix mismatch before running.'); return; }
|
| 726 |
|
| 727 |
document.getElementById('runBtn').disabled = true;
|
| 728 |
document.getElementById('progressSection').classList.remove('hidden');
|