Skip to content

Commit 1544fb1

Browse files
Izak88jkuri
authored andcommitted
feat(): collapse/expand commands log in terminal
1 parent 9fd48a3 commit 1544fb1

File tree

5 files changed

+165
-15
lines changed

5 files changed

+165
-15
lines changed
Lines changed: 44 additions & 0 deletions
Loading
Lines changed: 44 additions & 0 deletions
Loading
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
1-
<pre class="window-terminal-container batman-ansi-theme" [ngClass]="{ large: options.size === 'large' }" slimScroll [options]="scrollOptions" [scrollEvents]="scrollEvents"></pre>
1+
<pre class="window-terminal-container dracula-ansi-theme" [ngClass]="{ large: options.size === 'large' }" slimScroll [options]="scrollOptions" [scrollEvents]="scrollEvents">
2+
<div class="command columns log" *ngFor="let cmd of commands; let i = index;" [id]="i">
3+
<div class="terminal">
4+
<span class="icon">
5+
<img *ngIf="cmd.visible" src="images/icons/collapse.svg" (click)="toogleCommand(i)">
6+
<img *ngIf="!cmd.visible" src="images/icons/expand.svg" (click)="toogleCommand(i)">
7+
</span>
8+
<div class="output" [class.is-hidden]="!cmd.visible" [innerHTML]="cmd.output"></div>
9+
<div class="output" [class.is-hidden]="cmd.visible" [innerHTML]="cmd.command"></div>
10+
</div>
11+
</div>
12+
</pre>

src/app/components/app-terminal/app-terminal.component.ts

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { Component, ElementRef, OnInit, Input, SimpleChange, EventEmitter } from '@angular/core';
1+
import {
2+
Component, ElementRef, OnInit, Input, SimpleChange, EventEmitter, NgZone } from '@angular/core';
23
import { ISlimScrollOptions, SlimScrollEvent } from 'ngx-slimscroll';
4+
35
import * as AnsiUp from 'ansi_up';
46

57
@Component({
@@ -12,8 +14,9 @@ export class AppTerminalComponent implements OnInit {
1214
au: any;
1315
scrollOptions: ISlimScrollOptions;
1416
scrollEvents: EventEmitter<SlimScrollEvent>;
17+
commands: { command: string, visible: boolean, output: string }[];
1518

16-
constructor(private elementRef: ElementRef) {
19+
constructor(private elementRef: ElementRef, private ngZone: NgZone) {
1720
this.scrollOptions = {
1821
position: 'right',
1922
barBackground: '#11121A',
@@ -35,26 +38,63 @@ export class AppTerminalComponent implements OnInit {
3538
ngOnInit() {
3639
this.au = new AnsiUp.default();
3740
this.au.use_classes = true;
41+
this.commands = [];
3842
}
3943

4044
ngOnChanges(changes: SimpleChange) {
4145
if (!this.data) {
4246
return;
4347
}
4448

45-
const el = this.elementRef.nativeElement.querySelector('.window-terminal-container');
46-
if (typeof this.data.clear !== 'undefined') {
47-
el.innerHTML = '';
48-
} else {
49-
el.innerHTML += this.au.ansi_to_html(this.data);
49+
this.ngZone.run(() => {
50+
const el = this.elementRef.nativeElement.querySelector('.window-terminal-container');
51+
if (typeof this.data.clear !== 'undefined') {
52+
el.innerHTML = '';
53+
} else {
54+
let output: string = this.au.ansi_to_html(this.data);
55+
if (output) {
56+
if (this.commands.length > 0) {
57+
if (output.indexOf('==&gt;') !== -1) {
58+
let command = output.split('</span>')[0] + '</span>';
59+
this.commands.push({
60+
command: command,
61+
visible: true,
62+
output: output
63+
});
64+
} else {
65+
this.commands[this.commands.length - 1].command += ` ${output}`;
66+
}
67+
} else {
68+
let regexp = /<span(.*)==&gt;/gi;
69+
regexp.lastIndex = 1;
70+
let match = regexp.exec(output);
71+
if (match) {
72+
let indexEnd = match.index;
73+
let indexStart = 0;
74+
while (indexEnd >= 0) {
75+
let log = output.substring(indexStart, indexEnd);
76+
let command = log.split('</span>')[0] + '</span>';
77+
this.commands.push({
78+
command: command,
79+
visible: true,
80+
output: log
81+
});
82+
indexStart = indexEnd;
83+
indexEnd = regexp.exec(output).index;
84+
}
85+
}
86+
}
87+
}
5088

51-
const recalculateEvent = new SlimScrollEvent({ type: 'recalculate' });
52-
const bottomEvent = new SlimScrollEvent({ type: 'scrollToBottom', duration: 300 });
89+
const recalculateEvent = new SlimScrollEvent({ type: 'recalculate' });
90+
const bottomEvent = new SlimScrollEvent({ type: 'scrollToBottom', duration: 300 });
5391

54-
setTimeout(() => {
55-
this.scrollEvents.emit(recalculateEvent);
56-
this.scrollEvents.emit(bottomEvent);
57-
});
58-
}
92+
setTimeout(() => el.scrollTop = el.scrollHeight);
93+
}
94+
});
95+
}
96+
97+
toogleCommand(index: number) {
98+
this.commands[index].visible = !this.commands[index].visible;
5999
}
60100
}

src/app/styles/terminal.sass

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,14 @@
1818

1919
&.large
2020
height: 700px
21+
22+
.output
23+
padding: 0
24+
margin: 0
25+
26+
.terminal
27+
display: flex
28+
align-items: left
29+
height: 100%
30+
width: 100%
31+
text-align: left

0 commit comments

Comments
 (0)