mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 03:16:10 -06:00 
			
		
		
		
	add a simple log viewer to the front end
This commit is contained in:
		
							
								
								
									
										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": {
 | 
			
		||||
      "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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
</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 { 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)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user