This commit is contained in:
Drew Ansbacher
2021-08-25 13:00:02 -06:00
committed by Aiden McClelland
parent 37a6df0815
commit 95c95a9fe4
12 changed files with 183 additions and 138 deletions

View File

@@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { BadgeMenuComponent } from './badge-menu.component'
import { IonicModule } from '@ionic/angular'
import { RouterModule } from '@angular/router'
import { SharingModule } from 'src/app/modules/sharing.module'
@NgModule({
@@ -12,7 +11,6 @@ import { SharingModule } from 'src/app/modules/sharing.module'
imports: [
CommonModule,
IonicModule,
RouterModule.forChild([]),
SharingModule,
],
exports: [BadgeMenuComponent],

View File

@@ -0,0 +1,16 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { IonicModule } from '@ionic/angular'
import { LogsPage } from './logs.page'
import { SharingModule } from 'src/app/modules/sharing.module'
@NgModule({
declarations: [LogsPage],
imports: [
CommonModule,
IonicModule,
SharingModule,
],
exports: [LogsPage],
})
export class LogsPageModule { }

View File

@@ -0,0 +1,42 @@
<ion-content
[scrollEvents]="true"
(ionScroll)="scrollEvent($event)"
style="height: 100%;"
id="ion-content"
class="ion-padding"
>
<ion-infinite-scroll id="scroller" *ngIf="!loading && needInfinite" position="top" threshold="0" (ionInfinite)="loadData($event)">
<ion-infinite-scroll-content
loadingSpinner="bubbles">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
<text-spinner *ngIf="loading" text="Loading Logs"></text-spinner>
<div id="container">
<div id="template" style="white-space: pre-line;"></div>
</div>
<div id="button-div" *ngIf="!loading" style="width: 100%; text-align: center;">
<ion-button *ngIf="!loadingMore" (click)="loadMore()" strong color="dark">
Load More
<ion-icon slot="end" name="refresh"></ion-icon>
</ion-button>
<ion-spinner *ngIf="loadingMore" name="lines" color="warning"></ion-spinner>
</div>
<div
[ngStyle]="{
'position': 'fixed',
'bottom': '50px',
'right': isOnBottom ? '-50px' : '30px',
'background-color': 'var(--ion-color-medium)',
'border-radius': '100%',
'transition': 'right 0.4s ease-out'
}"
>
<ion-button style="width: 50px; height: 50px; --padding-start: 0px; --padding-end: 0px; --border-radius: 100%;" fill="clear" (click)="scrollToBottom()">
<ion-icon style="font-size: 60px; --ionicon-stroke-width: 8px;" name="chevron-down-circle-outline"></ion-icon>
</ion-button>
</div>
</ion-content>

View File

@@ -0,0 +1,95 @@
import { Component, Input, ViewChild } from '@angular/core'
import { IonContent } from '@ionic/angular'
import { ErrorToastService } from 'src/app/services/error-toast.service'
import { Log } from 'src/app/services/api/api.types'
@Component({
selector: 'logs',
templateUrl: './logs.page.html',
styleUrls: ['./logs.page.scss'],
})
export class LogsPage {
@ViewChild(IonContent) private content: IonContent
@Input() fetchLogs: (params: { before?: string, after?: string, limit: number }) => Promise<Log[]>
loading = true
loadingMore = false
logs: string
needInfinite = true
before: string
after: string
limit = 200
scrollToBottomButton = false
isOnBottom = true
constructor (
private readonly errToast: ErrorToastService,
) { }
ngOnInit () {
this.getLogs()
}
async fetch (isBefore: boolean = true) {
const logs = await this.fetchLogs({
before: isBefore ? this.before : undefined,
after: !isBefore ? this.after : undefined,
limit: this.limit,
})
this.before = logs[0]?.timestamp
this.after = logs[logs.length - 1]?.timestamp
this.loading = false
return logs
}
async getLogs () {
try {
// get logs
const logs = await this.fetch()
this.before = logs[0].timestamp
const container = document.getElementById('container')
const beforeContainerHeight = container.scrollHeight
const newLogs = document.getElementById('template').cloneNode(true) as HTMLElement
newLogs.innerHTML = logs.map(l => `${l.timestamp} ${l.log}`).join('\n\n') + (logs.length ? '\n\n' : '')
container.prepend(newLogs)
const afterContainerHeight = container.scrollHeight
// scroll down
scrollBy(0, afterContainerHeight - beforeContainerHeight)
this.content.scrollToPoint(0, afterContainerHeight - beforeContainerHeight)
if (logs.length < this.limit) {
this.needInfinite = false
}
} catch (e) {
this.errToast.present(e)
}
}
async loadMore () {
this.loadingMore = true
const logs = await this.fetch(false)
const container = document.getElementById('container')
const newLogs = document.getElementById('template').cloneNode(true) as HTMLElement
newLogs.innerHTML = logs.map(l => `${l.timestamp} ${l.log}`).join('\n\n') + (logs.length ? '\n\n' : '')
container.append(newLogs)
this.loadingMore = false
this.scrollEvent()
}
scrollEvent () {
const buttonDiv = document.getElementById('button-div')
this.isOnBottom = buttonDiv.getBoundingClientRect().top < window.innerHeight
}
scrollToBottom () {
this.content.scrollToBottom(500)
}
async loadData (e: any): Promise<void> {
await this.getLogs()
e.target.complete()
}
}