diff --git a/src/app/features/jobs/jobs-list/jobs-list.html b/src/app/features/jobs/jobs-list/jobs-list.html index c30209d..1b70355 100644 --- a/src/app/features/jobs/jobs-list/jobs-list.html +++ b/src/app/features/jobs/jobs-list/jobs-list.html @@ -334,21 +334,16 @@

All jobs

{{ job.tool || "—" }} - @if (isInProgress(job.status)) { - - - In progress... - - } @else { - {{ job.status }} + @if (job.status === 'In progress') { + + } {{ job.status }} - } {{ job.submittedAt | date:'dd/MM/yyyy' }} diff --git a/src/app/features/jobs/jobs-list/jobs-list.spec.ts b/src/app/features/jobs/jobs-list/jobs-list.spec.ts index 040a2c3..2dbda09 100644 --- a/src/app/features/jobs/jobs-list/jobs-list.spec.ts +++ b/src/app/features/jobs/jobs-list/jobs-list.spec.ts @@ -421,18 +421,19 @@ describe("JobsListComponent", () => { expect(component.getStatusClass("Completed")).toBe( "bg-green-100 text-green-800" ); - expect(component.getStatusClass("In progress")).toBe("text-gray-700"); + expect(component.getStatusClass("In progress")).toBe( + "bg-sky-100 text-sky-800" + ); expect(component.getStatusClass("In queue")).toBe( - "bg-white text-black border border-black" + "bg-gray-100 text-gray-800" ); - expect(component.getStatusClass("Failed")).toBe("bg-red-600 text-white"); + expect(component.getStatusClass("Failed")).toBe("bg-red-100 text-red-800"); expect(component.getStatusClass("Stopped")).toBe( - "bg-amber-100 text-amber-700" + "bg-amber-100 text-amber-800" ); expect(component.getStatusClass("Unknown")).toBe( - "bg-gray-100 text-gray-900" + "bg-gray-100 text-gray-800" ); - expect(component.isInProgress("In progress")).toBeTrue(); }); it("should toggle individual and all job selections", () => { diff --git a/src/app/features/jobs/jobs-list/jobs-list.ts b/src/app/features/jobs/jobs-list/jobs-list.ts index e3ea323..e38dd0b 100644 --- a/src/app/features/jobs/jobs-list/jobs-list.ts +++ b/src/app/features/jobs/jobs-list/jobs-list.ts @@ -100,7 +100,7 @@ export default class JobsListComponent implements OnInit, OnDestroy { activeSort = signal<"score" | "submitted">("submitted"); // Available status options - statusOptions = ["Completed", "Failed", "Stopped", "In progress", "In queue"]; + statusOptions = ["Completed", "Failed", "Stopped", "In progress", "In queue", "Pending"]; // Debounce timer for the search input private searchDebounce?: ReturnType; @@ -372,22 +372,20 @@ export default class JobsListComponent implements OnInit, OnDestroy { case "Completed": return "bg-green-100 text-green-800"; case "In progress": - return "text-gray-700"; + return "bg-sky-100 text-sky-800"; case "In queue": - return "bg-white text-black border border-black"; + return "bg-gray-100 text-gray-800"; case "Failed": - return "bg-red-600 text-white"; + return "bg-red-100 text-red-800"; case "Stopped": - return "bg-amber-100 text-amber-700"; + return "bg-amber-100 text-amber-800"; + case "Pending": + return "bg-blue-600 text-white" default: - return "bg-gray-100 text-gray-900"; + return "bg-gray-100 text-gray-800"; } } - isInProgress(status: string): boolean { - return status === "In progress"; - } - /** * Toggle selection for a single job */ diff --git a/src/app/features/workflows/single-prediction/single-prediction.spec.ts b/src/app/features/workflows/single-prediction/single-prediction.spec.ts index 5b13bff..b8af5a3 100644 --- a/src/app/features/workflows/single-prediction/single-prediction.spec.ts +++ b/src/app/features/workflows/single-prediction/single-prediction.spec.ts @@ -488,7 +488,7 @@ describe("SinglePredictionComponent", () => { const datasetUploadRequest = datasetUploadService.uploadDataset.calls.mostRecent().args[0]; const samplesheetId = datasetUploadRequest.formData["id"]; - expect(samplesheetId).toMatch(/^single-prediction-[a-z0-9]{8}$/); + expect(samplesheetId).toBe("test-run"); expect(datasetUploadRequest.formData["fasta"]).toBe( MOCK_FASTA_RESPONSE.s3Uri ); diff --git a/src/app/features/workflows/single-prediction/single-prediction.ts b/src/app/features/workflows/single-prediction/single-prediction.ts index 0baa178..0d0bb01 100644 --- a/src/app/features/workflows/single-prediction/single-prediction.ts +++ b/src/app/features/workflows/single-prediction/single-prediction.ts @@ -120,7 +120,6 @@ export default class SinglePredictionComponent extends WorkflowPageBase { CCD_COMPOUNDS ).map(([code, name]) => ({ value: code, label: `${code} - ${name}` })); - private readonly samplesheetId = `single-prediction-${this.generateRandomSuffix()}`; private nextRowId = 1; ccdLookupState = signal>({}); ccdLookupNames = signal>({}); // compound name resolved from the local CCD dictionary via lookupCcdCompound() @@ -128,6 +127,10 @@ export default class SinglePredictionComponent extends WorkflowPageBase { private preparedFastaContent = signal(null); private preparedFastaUrl = signal(null); private preparedSamplesheetS3Key = signal(null); + private preparedSamplesheetId = signal(null); + private get samplesheetId(): string { + return this.jobName().trim(); + } readonly tools: ToolChip[] = [ { id: "colabfold", label: "ColabFold" }, @@ -683,18 +686,20 @@ export default class SinglePredictionComponent extends WorkflowPageBase { onPrepared: (fastaUrl: string, s3InputKey: string) => void ): void { const fastaContent = this.generatedFastaContent(); + const samplesheetId = this.samplesheetId; const cachedS3InputKey = this.preparedSamplesheetS3Key(); const cachedFastaUrl = this.preparedFastaUrl(); if ( cachedS3InputKey && cachedFastaUrl && - this.preparedFastaContent() === fastaContent + this.preparedFastaContent() === fastaContent && + this.preparedSamplesheetId() === samplesheetId ) { onPrepared(cachedFastaUrl, cachedS3InputKey); return; } - const fastaFile = new File([fastaContent], `${this.samplesheetId}.fasta`, { + const fastaFile = new File([fastaContent], `${samplesheetId}.fasta`, { type: "text/plain", }); @@ -712,7 +717,7 @@ export default class SinglePredictionComponent extends WorkflowPageBase { } return this.datasetUploadService .uploadDataset({ - formData: { id: this.samplesheetId, fasta: response.s3Uri }, + formData: { id: samplesheetId, fasta: response.s3Uri }, }) .pipe( map((datasetResponse) => ({ @@ -735,6 +740,7 @@ export default class SinglePredictionComponent extends WorkflowPageBase { this.preparedFastaContent.set(fastaContent); this.preparedFastaUrl.set(fastaUrl); this.preparedSamplesheetS3Key.set(s3InputKey); + this.preparedSamplesheetId.set(samplesheetId); onPrepared(fastaUrl, s3InputKey); }, error: (error: unknown) => { @@ -761,13 +767,6 @@ export default class SinglePredictionComponent extends WorkflowPageBase { ); } - private generateRandomSuffix(): string { - return ( - globalThis.crypto?.randomUUID?.().replace(/-/g, "") ?? - Math.random().toString(36).slice(2) - ).slice(0, 8); - } - private buildWorkflowPayload(): Omit< SinglePredictionPayload, "fastaFileUrl" | "sample_id"