mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
feat: refactor logs (#2555)
* feat: refactor logs * chore: comments * feat: add system logs * feat: update shared logs
This commit is contained in:
@@ -25,9 +25,7 @@
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
<div class="logs-container">
|
||||
<logs-window></logs-window>
|
||||
</div>
|
||||
<logs-window class="logs" />
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
@@ -8,11 +8,15 @@ ion-card-title {
|
||||
margin: auto auto 40px;
|
||||
}
|
||||
|
||||
.logs-container {
|
||||
margin-top: 24px;
|
||||
height: 280px;
|
||||
.logs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 18rem;
|
||||
padding: 1rem;
|
||||
margin: 1.5rem 0.75rem;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
border-radius: 31px;
|
||||
margin-inline: 10px;
|
||||
border-radius: 2rem;
|
||||
// TODO: Theme
|
||||
background: #181818;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { TuiLetModule } from '@taiga-ui/cdk'
|
||||
|
||||
import { LogsWindowComponent } from './logs-window/logs-window.component'
|
||||
import { LogsWindowComponent } from './logs-window.component'
|
||||
import { InitializingComponent } from './initializing.component'
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, IonicModule, TuiLetModule],
|
||||
declarations: [InitializingComponent, LogsWindowComponent],
|
||||
imports: [CommonModule, IonicModule, TuiLetModule, LogsWindowComponent],
|
||||
declarations: [InitializingComponent],
|
||||
exports: [InitializingComponent],
|
||||
})
|
||||
export class InitializingModule {}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import { Component, ElementRef, inject } from '@angular/core'
|
||||
import {
|
||||
IntersectionObserverModule,
|
||||
INTERSECTION_ROOT,
|
||||
} from '@ng-web-apis/intersection-observer'
|
||||
import { MutationObserverModule } from '@ng-web-apis/mutation-observer'
|
||||
import { TuiScrollbarModule } from '@taiga-ui/core'
|
||||
import { NgDompurifyModule } from '@tinkoff/ng-dompurify'
|
||||
import { SetupLogsService } from '../../services/setup-logs.service'
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'logs-window',
|
||||
template: `
|
||||
<tui-scrollbar childList subtree (waMutationObserver)="scrollTo(bottom)">
|
||||
@for (log of logs$ | async; track log) {
|
||||
<pre [innerHTML]="log | dompurify"></pre>
|
||||
}
|
||||
<section
|
||||
#bottom
|
||||
waIntersectionObserver
|
||||
[style.padding.rem]="1"
|
||||
(waIntersectionObservee)="onBottom($event)"
|
||||
></section>
|
||||
</tui-scrollbar>
|
||||
`,
|
||||
imports: [
|
||||
AsyncPipe,
|
||||
MutationObserverModule,
|
||||
IntersectionObserverModule,
|
||||
NgDompurifyModule,
|
||||
TuiScrollbarModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: INTERSECTION_ROOT,
|
||||
useExisting: ElementRef,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class LogsWindowComponent {
|
||||
readonly logs$ = inject(SetupLogsService)
|
||||
scroll = true
|
||||
|
||||
scrollTo(bottom: HTMLElement) {
|
||||
if (this.scroll) bottom.scrollIntoView({ behavior: 'smooth' })
|
||||
}
|
||||
|
||||
onBottom([{ isIntersecting }]: readonly IntersectionObserverEntry[]) {
|
||||
this.scroll = isIntersecting
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<ion-content
|
||||
[scrollEvents]="true"
|
||||
(ionScroll)="handleScroll($event)"
|
||||
(ionScrollEnd)="handleScrollEnd()"
|
||||
class="ion-padding"
|
||||
color="light"
|
||||
>
|
||||
<div id="container"></div>
|
||||
</ion-content>
|
||||
|
||||
<div id="template"></div>
|
||||
@@ -1,10 +0,0 @@
|
||||
// Hide scrollbar for Chrome, Safari and Opera
|
||||
ion-content::part(scroll)::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Hide scrollbar for IE, Edge and Firefox
|
||||
ion-content::part(scroll) {
|
||||
-ms-overflow-style: none; // IE and Edge
|
||||
scrollbar-width: none; // Firefox
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Component, ViewChild } from '@angular/core'
|
||||
import { IonContent } from '@ionic/angular'
|
||||
import { map, takeUntil } from 'rxjs'
|
||||
import { TuiDestroyService } from '@taiga-ui/cdk'
|
||||
import { SetupLogsService } from '../../../services/setup-logs.service'
|
||||
import { Log } from '../../../types/api'
|
||||
import { toLocalIsoString } from '../../../util/to-local-iso-string'
|
||||
import Convert from 'ansi-to-html'
|
||||
const convert = new Convert({
|
||||
bg: 'transparent',
|
||||
})
|
||||
|
||||
@Component({
|
||||
selector: 'logs-window',
|
||||
templateUrl: 'logs-window.component.html',
|
||||
styleUrls: ['logs-window.component.scss'],
|
||||
providers: [TuiDestroyService],
|
||||
})
|
||||
export class LogsWindowComponent {
|
||||
@ViewChild(IonContent)
|
||||
private content?: IonContent
|
||||
|
||||
autoScroll = true
|
||||
|
||||
constructor(
|
||||
private readonly logs: SetupLogsService,
|
||||
private readonly destroy$: TuiDestroyService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.logs
|
||||
.pipe(
|
||||
map(log => this.convertToAnsi(log)),
|
||||
takeUntil(this.destroy$),
|
||||
)
|
||||
.subscribe(innerHTML => {
|
||||
const container = document.getElementById('container')
|
||||
const newLogs = document.getElementById('template')?.cloneNode()
|
||||
|
||||
if (!(newLogs instanceof HTMLElement)) return
|
||||
|
||||
newLogs.innerHTML = innerHTML
|
||||
container?.append(newLogs)
|
||||
|
||||
if (this.autoScroll) {
|
||||
setTimeout(() => this.content?.scrollToBottom(250))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleScroll(e: any) {
|
||||
if (e.detail.deltaY < 0) this.autoScroll = false
|
||||
}
|
||||
|
||||
async handleScrollEnd() {
|
||||
const elem = await this.content?.getScrollElement()
|
||||
if (elem && elem.scrollHeight - elem.scrollTop - elem.clientHeight < 64) {
|
||||
this.autoScroll = true
|
||||
}
|
||||
}
|
||||
|
||||
private convertToAnsi(log: Log) {
|
||||
return `<span style="color: #FFF; font-weight: bold;">${toLocalIsoString(
|
||||
new Date(log.timestamp),
|
||||
)}</span> ${convert.toHtml(log.message)}<br />`
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user