diff --git a/src-ui/src/app/app.component.ts b/src-ui/src/app/app.component.ts index a6cd8bebe..5809968e8 100644 --- a/src-ui/src/app/app.component.ts +++ b/src-ui/src/app/app.component.ts @@ -1,14 +1,43 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { Subscription } from 'rxjs'; +import { ConsumerStatusService } from './services/consumer-status.service'; +import { Toast, ToastService } from './services/toast.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) -export class AppComponent { +export class AppComponent implements OnInit, OnDestroy { + + successSubscription: Subscription; + failedSubscription: Subscription; - constructor () { + constructor ( private consumerStatusService: ConsumerStatusService, private toastService: ToastService, private router: Router ) { } + ngOnDestroy(): void { + this.consumerStatusService.disconnect() + this.successSubscription.unsubscribe() + this.failedSubscription.unsubscribe() + } + + ngOnInit(): void { + this.consumerStatusService.connect() + + this.successSubscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => { + this.toastService.showToast({title: "Document added", content: `Document ${status.filename} was added to paperless.`, actionName: "Open document", action: () => { + this.router.navigate(['documents', status.document_id]) + }}) + }) + + this.failedSubscription = this.consumerStatusService.onDocumentConsumptionFailed().subscribe(status => { + this.toastService.showError(`Could not consume ${status.filename}: ${status.message}`) + }) + + } + + } diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts index e10bdbd0c..5cc59d567 100644 --- a/src-ui/src/app/app.module.ts +++ b/src-ui/src/app/app.module.ts @@ -40,6 +40,10 @@ import { SaveViewConfigDialogComponent } from './components/document-list/save-v import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { DateTimeComponent } from './components/common/input/date-time/date-time.component'; import { TagsComponent } from './components/common/input/tags/tags.component'; +import { SavedViewWidgetComponent } from './components/dashboard/widgets/saved-view-widget/saved-view-widget.component'; +import { ConsumerStatusWidgetComponent } from './components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component'; +import { StatisticsWidgetComponent } from './components/dashboard/widgets/statistics-widget/statistics-widget.component'; +import { FileUploadWidgetComponent } from './components/dashboard/widgets/file-upload-widget/file-upload-widget.component'; @NgModule({ declarations: [ @@ -73,7 +77,11 @@ import { TagsComponent } from './components/common/input/tags/tags.component'; CheckComponent, SaveViewConfigDialogComponent, DateTimeComponent, - TagsComponent + TagsComponent, + ConsumerStatusWidgetComponent, + SavedViewWidgetComponent, + StatisticsWidgetComponent, + FileUploadWidgetComponent ], imports: [ BrowserModule, diff --git a/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts b/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts index ba0d90847..04eb1f250 100644 --- a/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts +++ b/src-ui/src/app/components/common/edit-dialog/edit-dialog.component.ts @@ -5,7 +5,7 @@ import { Observable } from 'rxjs'; import { MATCHING_ALGORITHMS } from 'src/app/data/matching-model'; import { ObjectWithId } from 'src/app/data/object-with-id'; import { AbstractPaperlessService } from 'src/app/services/rest/abstract-paperless-service'; -import { Toast, ToastService } from 'src/app/services/toast.service'; +import { ToastService } from 'src/app/services/toast.service'; @Directive() export abstract class EditDialogComponent implements OnInit { @@ -66,7 +66,7 @@ export abstract class EditDialogComponent implements OnI this.activeModal.close() this.success.emit(result) }, error => { - this.toastService.showToast(Toast.makeError(`Could not save ${this.entityName}: ${error.error.name}`)) + this.toastService.showError(`Could not save ${this.entityName}: ${error.error.name}`) }) } diff --git a/src-ui/src/app/components/common/toasts/toasts.component.html b/src-ui/src/app/components/common/toasts/toasts.component.html index 04aa15a67..4e920877e 100644 --- a/src-ui/src/app/components/common/toasts/toasts.component.html +++ b/src-ui/src/app/components/common/toasts/toasts.component.html @@ -1,7 +1,8 @@ - {{toast.content}} +

{{toast.content}}

+

\ No newline at end of file diff --git a/src-ui/src/app/components/dashboard/dashboard.component.html b/src-ui/src/app/components/dashboard/dashboard.component.html index 694b431c4..4b732c9e8 100644 --- a/src-ui/src/app/components/dashboard/dashboard.component.html +++ b/src-ui/src/app/components/dashboard/dashboard.component.html @@ -6,59 +6,11 @@
- -

{{v.viewConfig.title}}

- - - - - - - - - - - - - -
Date createdDocument
{{doc.created | date}}{{doc.title}} -
- -
- -

Saved views

-

This space is reserved to display your saved views. Go to your documents and save a view to have it displayed here!

-
- +
-

Statistics

-

Documents in inbox: {{statistics.documents_inbox}}

-

Total documents: {{statistics.documents_total}}

-

Upload new Document

-
- - - -
-
Document conumser status
-

This is what it might look like in the future.

-
-
-

Filename.pdf: Running tesseract on page 4/8...

-

-
-
-
-
-

Filename2.pdf: Completed.

-

-
-
+ + +
diff --git a/src-ui/src/app/components/dashboard/dashboard.component.ts b/src-ui/src/app/components/dashboard/dashboard.component.ts index f8d5fb0ae..a9c72e496 100644 --- a/src-ui/src/app/components/dashboard/dashboard.component.ts +++ b/src-ui/src/app/components/dashboard/dashboard.component.ts @@ -4,14 +4,9 @@ import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop'; import { Observable } from 'rxjs'; import { DocumentService } from 'src/app/services/rest/document.service'; import { SavedViewConfigService } from 'src/app/services/saved-view-config.service'; -import { Toast, ToastService } from 'src/app/services/toast.service'; +import { ToastService } from 'src/app/services/toast.service'; import { environment } from 'src/environments/environment'; -export interface Statistics { - documents_total?: number - documents_inbox?: number -} - @Component({ selector: 'app-dashboard', templateUrl: './dashboard.component.html', @@ -19,53 +14,9 @@ export interface Statistics { }) export class DashboardComponent implements OnInit { - constructor(private documentService: DocumentService, private toastService: ToastService, - public savedViewConfigService: SavedViewConfigService, private http: HttpClient) { } - - - savedDashboardViews = [] - statistics: Statistics = {} + constructor(public savedViewConfigService: SavedViewConfigService) { } ngOnInit(): void { - this.savedViewConfigService.getDashboardConfigs().forEach(config => { - this.documentService.list(1,10,config.sortField,config.sortDirection,config.filterRules).subscribe(result => { - this.savedDashboardViews.push({viewConfig: config, documents: result.results}) - }) - }) - this.getStatistics().subscribe(statistics => { - this.statistics = statistics - }) } - getStatistics(): Observable { - return this.http.get(`${environment.apiBaseUrl}statistics/`) - } - - - public fileOver(event){ - console.log(event); - } - - public fileLeave(event){ - console.log(event); - } - - public dropped(files: NgxFileDropEntry[]) { - for (const droppedFile of files) { - if (droppedFile.fileEntry.isFile) { - const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; - console.log(fileEntry) - fileEntry.file((file: File) => { - console.log(file) - const formData = new FormData() - formData.append('document', file, file.name) - this.documentService.uploadDocument(formData).subscribe(result => { - this.toastService.showToast(Toast.make("Information", "The document has been uploaded and will be processed by the consumer shortly.")) - }, error => { - this.toastService.showToast(Toast.makeError("An error has occured while uploading the document. Sorry!")) - }) - }); - } - } - } } diff --git a/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.css b/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.html b/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.html new file mode 100644 index 000000000..9f6aa3b87 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.html @@ -0,0 +1,10 @@ +

Document consumer status

+ +
+
{{s.filename}}: {{s.message}}
+ +
+ + +
+
\ No newline at end of file diff --git a/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.spec.ts b/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.spec.ts new file mode 100644 index 000000000..02aa088f5 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConsumerStatusWidgetComponent } from './consumer-status-widget.component'; + +describe('ConsumerStatusWidgetComponent', () => { + let component: ConsumerStatusWidgetComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConsumerStatusWidgetComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConsumerStatusWidgetComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.ts new file mode 100644 index 000000000..0c4e35682 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/consumer-status-widget/consumer-status-widget.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit } from '@angular/core'; +import { ConsumerStatusService, FileStatus } from 'src/app/services/consumer-status.service'; + +@Component({ + selector: 'app-consumer-status-widget', + templateUrl: './consumer-status-widget.component.html', + styleUrls: ['./consumer-status-widget.component.css'] +}) +export class ConsumerStatusWidgetComponent implements OnInit { + + constructor(private consumerStatusService: ConsumerStatusService) { } + + ngOnInit(): void { + } + + getStatus() { + return this.consumerStatusService.consumerStatus + } + + isFinished(status: FileStatus) { + return status.status == "FAILED" || status.status == "SUCCESS" + } + + getType(status) { + switch (status) { + case "WORKING": return "primary" + case "FAILED": return "danger" + case "SUCCESS": return "success" + } + } + + dismiss(status: FileStatus) { + this.consumerStatusService.dismiss(status) + } +} diff --git a/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.css b/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.html b/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.html new file mode 100644 index 000000000..0c5ea634a --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.html @@ -0,0 +1,11 @@ +

Upload new Document

+
+ + + +
\ No newline at end of file diff --git a/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.spec.ts b/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.spec.ts new file mode 100644 index 000000000..847f5288b --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FileUploadWidgetComponent } from './file-upload-widget.component'; + +describe('FileUploadWidgetComponent', () => { + let component: FileUploadWidgetComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FileUploadWidgetComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FileUploadWidgetComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.ts new file mode 100644 index 000000000..5d4bac936 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/file-upload-widget/file-upload-widget.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit } from '@angular/core'; +import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop'; +import { DocumentService } from 'src/app/services/rest/document.service'; +import { ToastService } from 'src/app/services/toast.service'; + +@Component({ + selector: 'app-file-upload-widget', + templateUrl: './file-upload-widget.component.html', + styleUrls: ['./file-upload-widget.component.css'] +}) +export class FileUploadWidgetComponent implements OnInit { + + constructor(private documentService: DocumentService, private toastService: ToastService) { } + + ngOnInit(): void { + } + + public fileOver(event){ + console.log(event); + } + + public fileLeave(event){ + console.log(event); + } + + public dropped(files: NgxFileDropEntry[]) { + for (const droppedFile of files) { + if (droppedFile.fileEntry.isFile) { + const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; + console.log(fileEntry) + fileEntry.file((file: File) => { + console.log(file) + const formData = new FormData() + formData.append('document', file, file.name) + this.documentService.uploadDocument(formData).subscribe(result => { + this.toastService.showInfo("The document has been uploaded and will be processed by the consumer shortly.") + }, error => { + this.toastService.showError("An error has occured while uploading the document. Sorry!") + }) + }); + } + } + } +} diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.css b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html new file mode 100644 index 000000000..110464641 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html @@ -0,0 +1,16 @@ +

{{viewConfig.title}}

+ + + + + + + + + + + + + +
Date createdDocument
{{doc.created | date}}{{doc.title}} +
\ No newline at end of file diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts new file mode 100644 index 000000000..f0095b618 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SavedViewWidgetComponent } from './saved-view-widget.component'; + +describe('SavedViewWidgetComponent', () => { + let component: SavedViewWidgetComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SavedViewWidgetComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SavedViewWidgetComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts new file mode 100644 index 000000000..eb2d53aee --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts @@ -0,0 +1,41 @@ +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Subscription } from 'rxjs'; +import { PaperlessDocument } from 'src/app/data/paperless-document'; +import { SavedViewConfig } from 'src/app/data/saved-view-config'; +import { ConsumerStatusService } from 'src/app/services/consumer-status.service'; +import { DocumentService } from 'src/app/services/rest/document.service'; + +@Component({ + selector: 'app-saved-view-widget', + templateUrl: './saved-view-widget.component.html', + styleUrls: ['./saved-view-widget.component.css'] +}) +export class SavedViewWidgetComponent implements OnInit, OnDestroy { + + constructor(private documentService: DocumentService, private consumerStatusService: ConsumerStatusService) { } + + @Input() + viewConfig: SavedViewConfig + + documents: PaperlessDocument[] + + subscription: Subscription + + ngOnInit(): void { + this.reload() + this.subscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => { + this.reload() + }) + } + + ngOnDestroy(): void { + this.subscription.unsubscribe() + } + + reload() { + this.documentService.list(1,10,this.viewConfig.sortField,this.viewConfig.sortDirection,this.viewConfig.filterRules).subscribe(result => { + this.documents = result.results + }) + } + +} diff --git a/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.css b/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html b/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html new file mode 100644 index 000000000..2f89a2b34 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html @@ -0,0 +1,3 @@ +

Statistics

+

Documents in inbox: {{statistics.documents_inbox}}

+

Total documents: {{statistics.documents_total}}

\ No newline at end of file diff --git a/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.spec.ts b/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.spec.ts new file mode 100644 index 000000000..e8e44ca54 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StatisticsWidgetComponent } from './statistics-widget.component'; + +describe('StatisticsWidgetComponent', () => { + let component: StatisticsWidgetComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ StatisticsWidgetComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(StatisticsWidgetComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.ts new file mode 100644 index 000000000..4efb03895 --- /dev/null +++ b/src-ui/src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.ts @@ -0,0 +1,32 @@ +import { HttpClient } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { Observable } from 'rxjs'; +import { environment } from 'src/environments/environment'; + +export interface Statistics { + documents_total?: number + documents_inbox?: number +} + +@Component({ + selector: 'app-statistics-widget', + templateUrl: './statistics-widget.component.html', + styleUrls: ['./statistics-widget.component.css'] +}) +export class StatisticsWidgetComponent implements OnInit { + + constructor(private http: HttpClient) { } + + statistics: Statistics = {} + + ngOnInit(): void { + this.getStatistics().subscribe(statistics => { + this.statistics = statistics + }) + } + + getStatistics(): Observable { + return this.http.get(`${environment.apiBaseUrl}statistics/`) + } + +} diff --git a/src-ui/src/app/components/login/login.component.ts b/src-ui/src/app/components/login/login.component.ts index e74dcfb7f..a241543c7 100644 --- a/src-ui/src/app/components/login/login.component.ts +++ b/src-ui/src/app/components/login/login.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { Router } from '@angular/router'; import { AuthService } from 'src/app/services/auth.service'; -import { Toast, ToastService } from 'src/app/services/toast.service'; +import { ToastService } from 'src/app/services/toast.service'; @Component({ selector: 'app-login', @@ -26,7 +26,7 @@ export class LoginComponent implements OnInit { this.auth.login(this.loginForm.value.username, this.loginForm.value.password, this.loginForm.value.rememberMe).subscribe(result => { this.router.navigate(['']) }, (error) => { - this.toastService.showToast(Toast.makeError("Unable to log in with provided credentials.")) + this.toastService.showError("Unable to log in with provided credentials.") } ) } diff --git a/src-ui/src/app/services/auth.interceptor.ts b/src-ui/src/app/services/auth.interceptor.ts index 704b558ac..37d9e7906 100644 --- a/src-ui/src/app/services/auth.interceptor.ts +++ b/src-ui/src/app/services/auth.interceptor.ts @@ -28,7 +28,7 @@ export class AuthInterceptor implements HttpInterceptor { catchError((error: HttpErrorResponse) => { if (error.status == 401 && this.authService.isAuthenticated()) { this.authService.logout() - this.toastService.showToast(Toast.makeError("Your session has expired. Please log in again.")) + this.toastService.showError("Your session has expired. Please log in again.") } return throwError(error) }) diff --git a/src-ui/src/app/services/consumer-status.service.spec.ts b/src-ui/src/app/services/consumer-status.service.spec.ts new file mode 100644 index 000000000..d19f455e2 --- /dev/null +++ b/src-ui/src/app/services/consumer-status.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ConsumerStatusService } from './consumer-status.service'; + +describe('ConsumerStatusService', () => { + let service: ConsumerStatusService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ConsumerStatusService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/services/consumer-status.service.ts b/src-ui/src/app/services/consumer-status.service.ts new file mode 100644 index 000000000..070420b0f --- /dev/null +++ b/src-ui/src/app/services/consumer-status.service.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs'; + +export interface FileStatus { + filename?: string + current_progress?: number + max_progress?: number + status?: string + message?: string + document_id?: number +} + +@Injectable({ + providedIn: 'root' +}) +export class ConsumerStatusService { + + constructor() { } + + private statusWebSocked: WebSocket + + consumerStatus: FileStatus[] = [] + private documentConsumptionFinishedSubject = new Subject() + private documentConsumptionFailedSubject = new Subject() + + connect() { + this.disconnect() + this.statusWebSocked = new WebSocket("ws://localhost:8000/ws/status/"); + this.statusWebSocked.onmessage = (ev) => { + let statusUpdate: FileStatus = JSON.parse(ev['data']) + + let index = this.consumerStatus.findIndex(fs => fs.filename == statusUpdate.filename) + if (index > -1) { + this.consumerStatus[index] = statusUpdate + } else { + this.consumerStatus.push(statusUpdate) + } + + if (statusUpdate.status == "SUCCESS") { + this.documentConsumptionFinishedSubject.next(statusUpdate) + } + if (statusUpdate.status == "FAILED") { + this.documentConsumptionFailedSubject.next(statusUpdate) + } + } + } + + disconnect() { + if (this.statusWebSocked) { + this.statusWebSocked.close() + this.statusWebSocked = null + } + } + + dismiss(status: FileStatus) { + let index = this.consumerStatus.findIndex(s => s.filename == status.filename) + + if (index > -1) { + this.consumerStatus.splice(index, 1) + } + } + + onDocumentConsumptionFinished() { + return this.documentConsumptionFinishedSubject + } + + onDocumentConsumptionFailed() { + return this.documentConsumptionFailedSubject + } + +} diff --git a/src-ui/src/app/services/toast.service.ts b/src-ui/src/app/services/toast.service.ts index a3ce060a9..d5781139e 100644 --- a/src-ui/src/app/services/toast.service.ts +++ b/src-ui/src/app/services/toast.service.ts @@ -1,30 +1,17 @@ import { Injectable } from '@angular/core'; import { Subject, zip } from 'rxjs'; -export class Toast { - - static make(title: string, content: string, classname?: string, delay?: number): Toast { - let t = new Toast() - t.title = title - t.content = content - t.classname = classname - if (delay) { - t.delay = delay - } - return t - } - - static makeError(content: string) { - return Toast.make("Error", content, null, 10000) - } +export interface Toast { title: string - classname: string - content: string - delay: number = 5000 + delay?: number + + action?: any + + actionName?: string } @@ -44,6 +31,14 @@ export class ToastService { this.toastsSubject.next(this.toasts) } + showInfo(message: string) { + this.showToast({title: "Information", content: message, delay: 5000}) + } + + showError(message: string) { + this.showToast({title: "Error", content: message, delay: 10000}) + } + closeToast(toast: Toast) { let index = this.toasts.findIndex(t => t == toast) if (index > -1) { diff --git a/src-ui/src/environments/environment.ts b/src-ui/src/environments/environment.ts index a0877d69f..c945a0364 100644 --- a/src-ui/src/environments/environment.ts +++ b/src-ui/src/environments/environment.ts @@ -4,7 +4,8 @@ export const environment = { production: false, - apiBaseUrl: "http://localhost:8000/api/" + apiBaseUrl: "http://localhost:8000/api/", + wsBaseUrl: "ws://localhost:8000/ws/" }; /*