diff --git a/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.html b/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.html
index df021e8dc8..b05dff22ea 100644
--- a/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.html
+++ b/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.html
@@ -6,10 +6,14 @@
- Output
+
+ Output
+
+
diff --git a/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.scss b/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.scss
index 0ddcbfe0f0..9fc2ca84a1 100644
--- a/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.scss
+++ b/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.scss
@@ -14,4 +14,21 @@ code-editor-control {
border: 1px solid black;
height: 100%;
}
+
+ .terminal-active-indicator {
+ display: inline-block;
+ font-weight: bold;
+ color: var(--df-recommend-warning-color);
+ transform: rotate(0);
+ animation: rotate-animation 1s linear infinite;
+ }
+
+ @keyframes rotate-animation {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+ }
}
diff --git a/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.ts b/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.ts
index 50436435d2..901a88b7e8 100644
--- a/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.ts
+++ b/apps/showcase/src/components/training/code-editor-control/code-editor-control.component.ts
@@ -9,7 +9,9 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
+import {toSignal} from '@angular/core/rxjs-interop';
import {NgbNav, NgbNavContent, NgbNavItem, NgbNavLink, NgbNavOutlet} from '@ng-bootstrap/ng-bootstrap';
+import {distinctUntilChanged, map, of, repeat, Subject, throttleTime, timeout} from 'rxjs';
import {WebContainerService} from '../../../services';
import {CodeEditorTerminalComponent} from '../code-editor-terminal';
@@ -56,6 +58,16 @@ export class CodeEditorControlComponent implements OnDestroy, AfterViewInit {
*/
public activeTab: 'preview' | 'output' | 'terminal' = 'preview';
+ public readonly terminalActivity = new Subject();
+
+ public readonly terminalActive = toSignal(this.terminalActivity.asObservable().pipe(
+ throttleTime(50),
+ map(() => true),
+ timeout({each: 2000, with: () => of(false)}),
+ distinctUntilChanged(),
+ repeat()
+ ));
+
/**
* @inheritDoc
*/
diff --git a/apps/showcase/src/components/training/code-editor-terminal/code-editor-terminal.component.ts b/apps/showcase/src/components/training/code-editor-terminal/code-editor-terminal.component.ts
index e266bb9299..cc0c0b606e 100644
--- a/apps/showcase/src/components/training/code-editor-terminal/code-editor-terminal.component.ts
+++ b/apps/showcase/src/components/training/code-editor-terminal/code-editor-terminal.component.ts
@@ -3,8 +3,10 @@ import {
type AfterViewInit,
ChangeDetectionStrategy,
Component,
+ DestroyRef,
ElementRef,
EventEmitter,
+ inject,
type OnDestroy,
Output,
ViewChild
@@ -40,6 +42,11 @@ export class CodeEditorTerminalComponent implements OnDestroy, AfterViewChecked,
*/
@Output()
public readonly terminalUpdated = new EventEmitter();
+ /**
+ * Inform the parent that something got written in the terminal
+ */
+ @Output()
+ public readonly terminalActivity = new EventEmitter();
/**
* Inform the parent that the terminal of the component has been disposed of
*/
@@ -48,6 +55,10 @@ export class CodeEditorTerminalComponent implements OnDestroy, AfterViewChecked,
constructor() {
this.terminal.loadAddon(this.fitAddon);
+ const disposable = this.terminal.onWriteParsed(() => {
+ this.terminalActivity.emit();
+ });
+ inject(DestroyRef).onDestroy(() => disposable.dispose());
}
/**