From 323e0fa348ddd7c5f325c1c0aaafd8643bf8ffc2 Mon Sep 17 00:00:00 2001 From: Jonas Winkler Date: Mon, 2 Nov 2020 01:26:21 +0100 Subject: [PATCH] add a simple log viewer to the front end --- src-ui/package-lock.json | 19 ++++++++++++++ src-ui/package.json | 1 + src-ui/src/app/app.module.ts | 4 ++- .../components/manage/logs/logs.component.css | 12 +++++++++ .../manage/logs/logs.component.html | 14 ++++++++++- .../components/manage/logs/logs.component.ts | 22 +++++++++++++++- src-ui/src/app/data/paperless-log.ts | 25 +++++++++++++++++++ .../src/app/services/rest/log.service.spec.ts | 16 ++++++++++++ src-ui/src/app/services/rest/log.service.ts | 14 +++++++++++ 9 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 src-ui/src/app/services/rest/log.service.spec.ts create mode 100644 src-ui/src/app/services/rest/log.service.ts diff --git a/src-ui/package-lock.json b/src-ui/package-lock.json index 993d5c5cf..1d73a856f 100644 --- a/src-ui/package-lock.json +++ b/src-ui/package-lock.json @@ -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": { "version": "10.1.5", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-10.1.5.tgz", @@ -8263,6 +8268,15 @@ "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": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -8731,6 +8745,11 @@ "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": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", diff --git a/src-ui/package.json b/src-ui/package.json index 08fe6d33b..b2da7eabe 100644 --- a/src-ui/package.json +++ b/src-ui/package.json @@ -24,6 +24,7 @@ "bootstrap": "^4.5.0", "ng-bootstrap": "^1.6.3", "ngx-file-drop": "^10.0.0", + "ngx-infinite-scroll": "^9.1.0", "rxjs": "~6.6.0", "tslib": "^2.0.0", "uuid": "^8.3.1", diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts index 3c79fae30..dce6a9225 100644 --- a/src-ui/src/app/app.module.ts +++ b/src-ui/src/app/app.module.ts @@ -37,6 +37,7 @@ import { TextComponent } from './components/common/input/text/text.component'; import { SelectComponent } from './components/common/input/select/select.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 { InfiniteScrollModule } from 'ngx-infinite-scroll'; @NgModule({ declarations: [ @@ -77,7 +78,8 @@ import { SaveViewConfigDialogComponent } from './components/document-list/save-v HttpClientModule, FormsModule, ReactiveFormsModule, - NgxFileDropModule + NgxFileDropModule, + InfiniteScrollModule ], providers: [ DatePipe, diff --git a/src-ui/src/app/components/manage/logs/logs.component.css b/src-ui/src/app/components/manage/logs/logs.component.css index e69de29bb..1f0112fbc 100644 --- a/src-ui/src/app/components/manage/logs/logs.component.css +++ b/src-ui/src/app/components/manage/logs/logs.component.css @@ -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; +} \ No newline at end of file diff --git a/src-ui/src/app/components/manage/logs/logs.component.html b/src-ui/src/app/components/manage/logs/logs.component.html index 8b290fc0d..b84f55a8c 100644 --- a/src-ui/src/app/components/manage/logs/logs.component.html +++ b/src-ui/src/app/components/manage/logs/logs.component.html @@ -1,2 +1,14 @@ - \ No newline at end of file + + +
+

+ {{log.group}} + {{log.created | date:'short'}} + {{getLevelText(log.level)}} + {{log.message}} + (similar items) +

+
\ No newline at end of file diff --git a/src-ui/src/app/components/manage/logs/logs.component.ts b/src-ui/src/app/components/manage/logs/logs.component.ts index c546b8253..01da9dad2 100644 --- a/src-ui/src/app/components/manage/logs/logs.component.ts +++ b/src-ui/src/app/components/manage/logs/logs.component.ts @@ -1,4 +1,7 @@ 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({ selector: 'app-logs', @@ -7,9 +10,26 @@ import { Component, OnInit } from '@angular/core'; }) export class LogsComponent implements OnInit { - constructor() { } + constructor(private logService: LogService) { } + + logs: PaperlessLog[] = [] 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) + }) } } diff --git a/src-ui/src/app/data/paperless-log.ts b/src-ui/src/app/data/paperless-log.ts index b5691bcac..9c97975c2 100644 --- a/src-ui/src/app/data/paperless-log.ts +++ b/src-ui/src/app/data/paperless-log.ts @@ -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 { + + id?: number + + group?: string + + message?: string + + created?: Date + + level?: number + } diff --git a/src-ui/src/app/services/rest/log.service.spec.ts b/src-ui/src/app/services/rest/log.service.spec.ts new file mode 100644 index 000000000..4a99f7727 --- /dev/null +++ b/src-ui/src/app/services/rest/log.service.spec.ts @@ -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(); + }); +}); diff --git a/src-ui/src/app/services/rest/log.service.ts b/src-ui/src/app/services/rest/log.service.ts new file mode 100644 index 000000000..797d9b6b9 --- /dev/null +++ b/src-ui/src/app/services/rest/log.service.ts @@ -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 { + + constructor(http: HttpClient) { + super(http, 'logs') + } +}