Skip to content

Commit daf5cf8

Browse files
committed
fix(ui): keep both read-index columns stable while extractions resolve
R1 and R2 are separate extraction runs and finish at different times. The table keyed its columns off the reads resolved so far, so it briefly showed a single R1 column and then flipped to two when R2 arrived. Drive the column layout from the dataset's declared read indices instead, and mark a column still being processed with a "loading" tag.
1 parent efed4f0 commit daf5cf8

1 file changed

Lines changed: 29 additions & 8 deletions

File tree

ui/src/pages/ReadViewer.vue

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,26 @@ const pairedOptions: ListOption<"R1" | "R2" | "both">[] = [
3232
const reads = computed<Record<string, ReadsResult> | undefined>(() => app.model.outputs.reads);
3333
const isFasta = computed(() => app.model.outputs.isFasta ?? false);
3434
35+
// Column layout is driven by the dataset's DECLARED read indices (known up
36+
// front), not by which extractions have resolved so far. R1 and R2 are separate
37+
// runs and finish at different times; keying off resolved reads made the table
38+
// briefly show only R1 and then flip to two columns. Falls back to resolved
39+
// reads if the declared list isn't available yet.
40+
const expectedIndices = computed<string[]>(() => app.model.outputs.readIndices ?? []);
41+
3542
const availableIndices = computed<string[]>(() => {
36-
const r = reads.value;
37-
if (!r) return [];
38-
const known = READ_INDEX_ORDER.filter((ri) => r[ri] !== undefined);
39-
const extra = Object.keys(r)
40-
.filter((k) => !READ_INDEX_ORDER.includes(k))
41-
.sort();
43+
const src =
44+
expectedIndices.value.length > 0 ? expectedIndices.value : Object.keys(reads.value ?? {});
45+
const known = READ_INDEX_ORDER.filter((ri) => src.includes(ri));
46+
const extra = src.filter((k) => !READ_INDEX_ORDER.includes(k)).sort();
4247
return [...known, ...extra];
4348
});
4449
50+
/** A shown index whose extraction hasn't resolved yet (e.g. R2 still running). */
51+
function isIndexPending(ri: string): boolean {
52+
return reads.value?.[ri] === undefined;
53+
}
54+
4555
const isPaired = computed(
4656
() => availableIndices.value.includes("R1") && availableIndices.value.includes("R2"),
4757
);
@@ -211,7 +221,10 @@ function onDownload() {
211221
<!-- Single column (single-end / fasta / R1-only / R2-only) -->
212222
<div v-if="shownIndices.length === 1" class="reads-grid">
213223
<div class="grid-head">
214-
<div class="cell">{{ isFasta ? "Sequences" : shownIndices[0] }}</div>
224+
<div class="cell">
225+
{{ isFasta ? "Sequences" : shownIndices[0] }}
226+
<span v-if="isIndexPending(shownIndices[0])" class="pending-tag">· loading…</span>
227+
</div>
215228
</div>
216229
<div v-for="rec in reads[shownIndices[0]]?.reads ?? []" :key="rec.number" class="grid-row">
217230
<pre class="cell-pre">{{ recordLines(rec) }}</pre>
@@ -222,7 +235,9 @@ function onDownload() {
222235
two columns scroll together and pairs stay aligned. -->
223236
<div v-else class="reads-grid">
224237
<div class="grid-head">
225-
<div v-for="ri in shownIndices" :key="ri" class="cell">{{ ri }}</div>
238+
<div v-for="ri in shownIndices" :key="ri" class="cell">
239+
{{ ri }}<span v-if="isIndexPending(ri)" class="pending-tag">· loading…</span>
240+
</div>
226241
</div>
227242
<div v-for="row in maxRows" :key="row" class="grid-row">
228243
<pre v-for="ri in shownIndices" :key="ri" class="cell-pre">{{
@@ -245,6 +260,12 @@ function onDownload() {
245260
flex-wrap: wrap;
246261
align-items: flex-end;
247262
}
263+
.pending-tag {
264+
margin-left: 6px;
265+
font-weight: 400;
266+
font-size: 11px;
267+
color: var(--txt-03, #6b7280);
268+
}
248269
.raw-bar {
249270
margin-bottom: 12px;
250271
}

0 commit comments

Comments
 (0)