mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
add a simple log viewer to the front end
This commit is contained in:
parent
2b0b3a70a7
commit
323e0fa348
19
src-ui/package-lock.json
generated
19
src-ui/package-lock.json
generated
@ -2140,6 +2140,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@scarf/scarf": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-b2iE8kjjzzUo2WZ0xuE2N77kfnTds7ClrDxcz3Atz7h2XrNVoAPUoT75i7CY0st5x++70V91Y+c6RpBX9MX7Jg=="
|
||||||
|
},
|
||||||
"@schematics/angular": {
|
"@schematics/angular": {
|
||||||
"version": "10.1.5",
|
"version": "10.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-10.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-10.1.5.tgz",
|
||||||
@ -8263,6 +8268,15 @@
|
|||||||
"tslib": "^2.0.0"
|
"tslib": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ngx-infinite-scroll": {
|
||||||
|
"version": "9.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-9.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZulbahgFsoPmP8cz7qPGDeFX9nKiSm74aav8vXNSI1ZoPiGYY5FQd8AK+yXqygY7tyCJRyt8Wp3DIg7zgP5dPA==",
|
||||||
|
"requires": {
|
||||||
|
"@scarf/scarf": "^1.1.0",
|
||||||
|
"opencollective-postinstall": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nice-try": {
|
"nice-try": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||||
@ -8731,6 +8745,11 @@
|
|||||||
"is-wsl": "^2.1.1"
|
"is-wsl": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"opencollective-postinstall": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q=="
|
||||||
|
},
|
||||||
"opn": {
|
"opn": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
"bootstrap": "^4.5.0",
|
"bootstrap": "^4.5.0",
|
||||||
"ng-bootstrap": "^1.6.3",
|
"ng-bootstrap": "^1.6.3",
|
||||||
"ngx-file-drop": "^10.0.0",
|
"ngx-file-drop": "^10.0.0",
|
||||||
|
"ngx-infinite-scroll": "^9.1.0",
|
||||||
"rxjs": "~6.6.0",
|
"rxjs": "~6.6.0",
|
||||||
"tslib": "^2.0.0",
|
"tslib": "^2.0.0",
|
||||||
"uuid": "^8.3.1",
|
"uuid": "^8.3.1",
|
||||||
|
@ -37,6 +37,7 @@ import { TextComponent } from './components/common/input/text/text.component';
|
|||||||
import { SelectComponent } from './components/common/input/select/select.component';
|
import { SelectComponent } from './components/common/input/select/select.component';
|
||||||
import { CheckComponent } from './components/common/input/check/check.component';
|
import { CheckComponent } from './components/common/input/check/check.component';
|
||||||
import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component';
|
import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component';
|
||||||
|
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -77,7 +78,8 @@ import { SaveViewConfigDialogComponent } from './components/document-list/save-v
|
|||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
NgxFileDropModule
|
NgxFileDropModule,
|
||||||
|
InfiniteScrollModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
DatePipe,
|
DatePipe,
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
.log-entry-30 {
|
||||||
|
color: yellow !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-entry-40 {
|
||||||
|
color: red !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-entry-50 {
|
||||||
|
color: lightcoral !important;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
@ -1,2 +1,14 @@
|
|||||||
<app-page-header title="Logs">
|
<app-page-header title="Logs">
|
||||||
</app-page-header>
|
</app-page-header>
|
||||||
|
|
||||||
|
<div class="bg-dark p-3 mb-3" infiniteScroll (scrolled)="onScroll()">
|
||||||
|
<p
|
||||||
|
class="text-light text-monospace m-0 p-0 log-entry-{{log.level}}"
|
||||||
|
*ngFor="let log of logs">
|
||||||
|
{{log.group}}
|
||||||
|
{{log.created | date:'short'}}
|
||||||
|
{{getLevelText(log.level)}}
|
||||||
|
{{log.message}}
|
||||||
|
<a *ngIf="log.group" [routerLink]="" (click)="applyGroup(log.group)">(similar items)</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
@ -1,4 +1,7 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { kMaxLength } from 'buffer';
|
||||||
|
import { LOG_LEVELS, PaperlessLog } from 'src/app/data/paperless-log';
|
||||||
|
import { LogService } from 'src/app/services/rest/log.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-logs',
|
selector: 'app-logs',
|
||||||
@ -7,9 +10,26 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class LogsComponent implements OnInit {
|
export class LogsComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor(private logService: LogService) { }
|
||||||
|
|
||||||
|
logs: PaperlessLog[] = []
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.logService.list(1, 50).subscribe(result => this.logs = result.results)
|
||||||
|
}
|
||||||
|
|
||||||
|
getLevelText(level: number) {
|
||||||
|
return LOG_LEVELS.find(l => l.id == level)?.name
|
||||||
|
}
|
||||||
|
|
||||||
|
onScroll() {
|
||||||
|
let lastCreated = null
|
||||||
|
if (this.logs.length > 0) {
|
||||||
|
lastCreated = this.logs[this.logs.length-1].created
|
||||||
|
}
|
||||||
|
this.logService.list(1, 25, null, {'created__lt': lastCreated}).subscribe(result => {
|
||||||
|
this.logs.push(...result.results)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,27 @@
|
|||||||
|
export const DEBUG = 10
|
||||||
|
export const INFO = 20
|
||||||
|
export const WARNING = 30
|
||||||
|
export const ERROR = 40
|
||||||
|
export const CRITICAL = 50
|
||||||
|
|
||||||
|
export const LOG_LEVELS = [
|
||||||
|
{id: DEBUG, name: "DEBUG"},
|
||||||
|
{id: INFO, name: "INFO"},
|
||||||
|
{id: WARNING, name: "WARNING"},
|
||||||
|
{id: ERROR, name: "ERROR"},
|
||||||
|
{id: CRITICAL, name: "CRITICAL"}
|
||||||
|
]
|
||||||
|
|
||||||
export interface PaperlessLog {
|
export interface PaperlessLog {
|
||||||
|
|
||||||
|
id?: number
|
||||||
|
|
||||||
|
group?: string
|
||||||
|
|
||||||
|
message?: string
|
||||||
|
|
||||||
|
created?: Date
|
||||||
|
|
||||||
|
level?: number
|
||||||
|
|
||||||
}
|
}
|
||||||
|
16
src-ui/src/app/services/rest/log.service.spec.ts
Normal file
16
src-ui/src/app/services/rest/log.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LogService } from './log.service';
|
||||||
|
|
||||||
|
describe('LogService', () => {
|
||||||
|
let service: LogService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(LogService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
14
src-ui/src/app/services/rest/log.service.ts
Normal file
14
src-ui/src/app/services/rest/log.service.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { PaperlessLog } from 'src/app/data/paperless-log';
|
||||||
|
import { AbstractPaperlessService } from './abstract-paperless-service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class LogService extends AbstractPaperlessService<PaperlessLog> {
|
||||||
|
|
||||||
|
constructor(http: HttpClient) {
|
||||||
|
super(http, 'logs')
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user