zyratlo commented on code in PR #7601:
URL: https://github.com/apache/texera/pull/7601#discussion_r3778768950


##########
frontend/src/app/workspace/component/notebook-import-modal/notebook-import-modal.component.ts:
##########
@@ -90,24 +84,59 @@ export class NotebookImportModalComponent {
     this.modalRef.close();
   }
 
-  // Guards against a second submit while the opener callback (which may show 
an
-  // overwrite confirmation) is still pending, so a double-click cannot start 
two imports.
+  // True while generation runs: guards against a second submit and drives the 
loading overlay.
   public isSubmitting = false;
+  private startTime: number | null = null;
+  private timerHandle: ReturnType<typeof setInterval> | null = null;
+
+  public ngOnDestroy(): void {
+    this.stopTimer();
+  }
+
+  public get formattedElapsedTime(): string {
+    const diffMs = this.startTime === null ? 0 : Date.now() - this.startTime;
+    const totalSeconds = Math.floor(diffMs / 1000);
+    const minutes = Math.floor(totalSeconds / 60);
+    const seconds = totalSeconds % 60;
+    return `${minutes}:${seconds.toString().padStart(2, "0")}`;
+  }
+
+  // Empty body on purpose: the zone-patched event firing is itself what 
repaints the stopwatch,
+  // so it catches up when the user returns to a backgrounded tab. Same reason 
as the timer below.
+  @HostListener("document:visibilitychange")
+  public onVisibilityChange(): void {}
+
+  private startTimer(): void {
+    this.stopTimer();
+    this.startTime = Date.now();
+    // Empty body: elapsed is computed from startTime; the zone-patched tick 
just triggers a repaint.
+    this.timerHandle = setInterval(() => {}, 1000);
+  }
+
+  private stopTimer(): void {
+    if (this.timerHandle !== null) {
+      clearInterval(this.timerHandle);
+      this.timerHandle = null;
+    }
+  }
 
   public async onSubmit(): Promise<void> {
     if (this.isSubmitting || !this.importForm.valid) return;
     const file: NzUploadFile = this.importForm.get("file")?.value;
     const model: string = this.importForm.get("model")?.value;
     this.isSubmitting = true;
+    this.startTimer();
+    this.modalRef.updateConfig({ nzClosable: false, nzMaskClosable: false, 
nzKeyboard: false });

Review Comment:
   Fixed in 
[511d6c0](https://github.com/apache/texera/pull/7601/commits/511d6c06dd4380bc0abc21b52ac2db35f88f4146).
 I bounded the request in migration-llm.ts: callModel now takes an abortSignal 
and forwards it to generateText, and a callModelWithTimeout wrapper races it 
against a 10-minute timeout that both aborts the request and rejects. 
verifyConnection and sendPrompt go through it. A stall now surfaces on the 
existing "Error while communicating with the LLM" path, which restores the 
modal (X, mask, Esc, form). Added fake-timer tests for the timeout firing and 
for a call that resolves before it.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to