mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Enhancement: auto-refresh logs & tasks (#4680)
This commit is contained in:
		| @@ -410,15 +410,26 @@ | ||||
|           <context context-type="linenumber">228</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8838884664569764142" datatype="html"> | ||||
|         <source>Auto refresh</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/logs/logs.component.html</context> | ||||
|           <context context-type="linenumber">4</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">15</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3894950702316166331" datatype="html"> | ||||
|         <source>Loading...</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/logs/logs.component.html</context> | ||||
|           <context context-type="linenumber">11</context> | ||||
|           <context context-type="linenumber">16</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/logs/logs.component.html</context> | ||||
|           <context context-type="linenumber">20</context> | ||||
|           <context context-type="linenumber">25</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/settings/settings.component.html</context> | ||||
| @@ -426,11 +437,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">19</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">27</context> | ||||
|           <context context-type="linenumber">22</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context> | ||||
| @@ -995,7 +1002,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">40</context> | ||||
|           <context context-type="linenumber">35</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context> | ||||
| @@ -1131,7 +1138,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">44</context> | ||||
|           <context context-type="linenumber">39</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/users-groups/users-groups.component.html</context> | ||||
| @@ -1462,18 +1469,11 @@ | ||||
|           <context context-type="linenumber">22</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1102717806459547726" datatype="html"> | ||||
|         <source>Refresh</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">20</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4207916966377787111" datatype="html"> | ||||
|         <source>Created</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">41</context> | ||||
|           <context context-type="linenumber">36</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.html</context> | ||||
| @@ -1496,130 +1496,130 @@ | ||||
|         <source>Results</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">42</context> | ||||
|           <context context-type="linenumber">37</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="314315645942131479" datatype="html"> | ||||
|         <source>Info</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">43</context> | ||||
|           <context context-type="linenumber">38</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8958063833276423847" datatype="html"> | ||||
|         <source>click for full output</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">66</context> | ||||
|           <context context-type="linenumber">61</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1536087519743707362" datatype="html"> | ||||
|         <source>Dismiss</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">81</context> | ||||
|           <context context-type="linenumber">76</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">63</context> | ||||
|           <context context-type="linenumber">66</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2134950584701094962" datatype="html"> | ||||
|         <source>Open Document</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">87</context> | ||||
|           <context context-type="linenumber">82</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="428536141871853903" datatype="html"> | ||||
|         <source>{VAR_PLURAL, plural, =1 {One <x id="INTERPOLATION"/> task} other {<x id="INTERPOLATION_1"/> total <x id="INTERPOLATION"/> tasks}}</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">103</context> | ||||
|           <context context-type="linenumber">98</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1830925490604698731" datatype="html"> | ||||
|         <source>Failed<x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span *ngIf="tasksService.failedFileTasks.length > 0" class="badge bg-danger ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.failedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">110</context> | ||||
|           <context context-type="linenumber">105</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6149567896789735123" datatype="html"> | ||||
|         <source>Complete<x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span *ngIf="tasksService.completedFileTasks.length > 0" class="badge bg-secondary ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.completedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">116</context> | ||||
|           <context context-type="linenumber">111</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7531670556122409927" datatype="html"> | ||||
|         <source>Started<x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span *ngIf="tasksService.startedFileTasks.length > 0" class="badge bg-secondary ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.startedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">122</context> | ||||
|           <context context-type="linenumber">117</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7252570681759700719" datatype="html"> | ||||
|         <source>Queued<x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span *ngIf="tasksService.queuedFileTasks.length > 0" class="badge bg-secondary ms-2">"/><x id="INTERPOLATION" equiv-text="{{tasksService.queuedFileTasks.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.html</context> | ||||
|           <context context-type="linenumber">128</context> | ||||
|           <context context-type="linenumber">123</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5404910960991552159" datatype="html"> | ||||
|         <source>Dismiss selected</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">28</context> | ||||
|           <context context-type="linenumber">30</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8829078752502782653" datatype="html"> | ||||
|         <source>Dismiss all</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">29</context> | ||||
|           <context context-type="linenumber">31</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1323591410517879795" datatype="html"> | ||||
|         <source>Confirm Dismiss All</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">60</context> | ||||
|           <context context-type="linenumber">63</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4157200209636243740" datatype="html"> | ||||
|         <source>Dismiss all <x id="PH" equiv-text="tasks.size"/> tasks?</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">61</context> | ||||
|           <context context-type="linenumber">64</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="9011556615675272238" datatype="html"> | ||||
|         <source>queued</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">129</context> | ||||
|           <context context-type="linenumber">132</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6415892379431855826" datatype="html"> | ||||
|         <source>started</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">131</context> | ||||
|           <context context-type="linenumber">134</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7510279840486540181" datatype="html"> | ||||
|         <source>completed</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">133</context> | ||||
|           <context context-type="linenumber">136</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4083337005045748464" datatype="html"> | ||||
|         <source>failed</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/admin/tasks/tasks.component.ts</context> | ||||
|           <context context-type="linenumber">135</context> | ||||
|           <context context-type="linenumber">138</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8119815638230251386" datatype="html"> | ||||
|   | ||||
| @@ -1,14 +1,19 @@ | ||||
| <pngx-page-header title="Logs" i18n-title> | ||||
|  | ||||
|   <div class="form-check form-switch" (click)="toggleAutoRefresh()"> | ||||
|     <input class="form-check-input" type="checkbox" role="switch" id="autoRefreshSwitch" [attr.checked]="autoRefreshInterval"> | ||||
|     <label class="form-check-label" for="autoRefreshSwitch" i18n>Auto refresh</label> | ||||
|   </div> | ||||
| </pngx-page-header> | ||||
|  | ||||
| <ul ngbNav #nav="ngbNav" [(activeId)]="activeLog" (activeIdChange)="reloadLogs()" class="nav-tabs"> | ||||
|   <li *ngFor="let logFile of logFiles" [ngbNavItem]="logFile"> | ||||
|     <a ngbNavLink>{{logFile}}.log</a> | ||||
|     <a ngbNavLink> | ||||
|       {{logFile}}.log | ||||
|     </a> | ||||
|   </li> | ||||
|   <div *ngIf="isLoading && !logFiles.length" class="pb-2"> | ||||
|   <div *ngIf="isLoading || !logFiles.length" class="ps-2 d-flex align-items-center"> | ||||
|     <div class="spinner-border spinner-border-sm me-2" role="status"></div> | ||||
|     <ng-container i18n>Loading...</ng-container> | ||||
|     <ng-container *ngIf="!logFiles.length" i18n>Loading...</ng-container> | ||||
|   </div> | ||||
| </ul> | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,9 @@ | ||||
| import { ComponentFixture, TestBed } from '@angular/core/testing' | ||||
| import { | ||||
|   ComponentFixture, | ||||
|   TestBed, | ||||
|   fakeAsync, | ||||
|   tick, | ||||
| } from '@angular/core/testing' | ||||
| import { LogService } from 'src/app/services/rest/log.service' | ||||
| import { PageHeaderComponent } from '../../common/page-header/page-header.component' | ||||
| import { LogsComponent } from './logs.component' | ||||
| @@ -26,6 +31,7 @@ describe('LogsComponent', () => { | ||||
|   let fixture: ComponentFixture<LogsComponent> | ||||
|   let logService: LogService | ||||
|   let logSpy | ||||
|   let reloadSpy | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     TestBed.configureTestingModule({ | ||||
| @@ -42,7 +48,9 @@ describe('LogsComponent', () => { | ||||
|     }) | ||||
|     fixture = TestBed.createComponent(LogsComponent) | ||||
|     component = fixture.componentInstance | ||||
|     reloadSpy = jest.spyOn(component, 'reloadLogs') | ||||
|     window.HTMLElement.prototype.scroll = function () {} // mock scroll | ||||
|     jest.useFakeTimers() | ||||
|     fixture.detectChanges() | ||||
|   }) | ||||
|  | ||||
| @@ -68,4 +76,14 @@ describe('LogsComponent', () => { | ||||
|     component.reloadLogs() | ||||
|     expect(component.logs).toHaveLength(0) | ||||
|   }) | ||||
|  | ||||
|   it('should auto refresh, allow toggle', () => { | ||||
|     jest.advanceTimersByTime(6000) | ||||
|     expect(reloadSpy).toHaveBeenCalledTimes(2) | ||||
|  | ||||
|     component.toggleAutoRefresh() | ||||
|     expect(component.autoRefreshInterval).toBeNull() | ||||
|     jest.advanceTimersByTime(6000) | ||||
|     expect(reloadSpy).toHaveBeenCalledTimes(2) | ||||
|   }) | ||||
| }) | ||||
|   | ||||
| @@ -27,6 +27,8 @@ export class LogsComponent implements OnInit, AfterViewChecked, OnDestroy { | ||||
|  | ||||
|   public isLoading: boolean = false | ||||
|  | ||||
|   public autoRefreshInterval: any | ||||
|  | ||||
|   @ViewChild('logContainer') logContainer: ElementRef | ||||
|  | ||||
|   ngOnInit(): void { | ||||
| @@ -41,6 +43,7 @@ export class LogsComponent implements OnInit, AfterViewChecked, OnDestroy { | ||||
|           this.activeLog = this.logFiles[0] | ||||
|           this.reloadLogs() | ||||
|         } | ||||
|         this.toggleAutoRefresh() | ||||
|       }) | ||||
|   } | ||||
|  | ||||
| @@ -91,4 +94,15 @@ export class LogsComponent implements OnInit, AfterViewChecked, OnDestroy { | ||||
|       behavior: 'auto', | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   toggleAutoRefresh(): void { | ||||
|     if (this.autoRefreshInterval) { | ||||
|       clearInterval(this.autoRefreshInterval) | ||||
|       this.autoRefreshInterval = null | ||||
|     } else { | ||||
|       this.autoRefreshInterval = setInterval(() => { | ||||
|         this.reloadLogs() | ||||
|       }, 5000) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <pngx-page-header title="File Tasks" i18n-title> | ||||
|   <div class="btn-toolbar col col-md-auto"> | ||||
|   <div class="btn-toolbar col col-md-auto align-items-center"> | ||||
|     <button class="btn btn-sm btn-outline-secondary me-2" (click)="clearSelection()" [hidden]="selectedTasks.size === 0"> | ||||
|       <svg class="sidebaricon" fill="currentColor"> | ||||
|         <use xlink:href="assets/bootstrap-icons.svg#x"/> | ||||
| @@ -10,15 +10,10 @@ | ||||
|         <use xlink:href="assets/bootstrap-icons.svg#check2-all"/> | ||||
|       </svg> <ng-container i18n>{{dismissButtonText}}</ng-container> | ||||
|     </button> | ||||
|     <button class="btn btn-sm btn-outline-primary" (click)="tasksService.reload()"> | ||||
|       <svg *ngIf="!tasksService.loading" class="sidebaricon" fill="currentColor"> | ||||
|         <use xlink:href="assets/bootstrap-icons.svg#arrow-clockwise"/> | ||||
|       </svg> | ||||
|       <ng-container *ngIf="tasksService.loading"> | ||||
|         <div class="spinner-border spinner-border-sm fw-normal" role="status"></div> | ||||
|         <div class="visually-hidden" i18n>Loading...</div> | ||||
|       </ng-container> <ng-container i18n>Refresh</ng-container> | ||||
|     </button> | ||||
|     <div class="form-check form-switch mb-0" (click)="toggleAutoRefresh()"> | ||||
|       <input class="form-check-input" type="checkbox" role="switch" id="autoRefreshSwitch" [attr.checked]="autoRefreshInterval"> | ||||
|       <label class="form-check-label" for="autoRefreshSwitch" i18n>Auto refresh</label> | ||||
|     </div> | ||||
|   </div> | ||||
| </pngx-page-header> | ||||
|  | ||||
|   | ||||
| @@ -112,6 +112,7 @@ describe('TasksComponent', () => { | ||||
|   let modalService: NgbModal | ||||
|   let router: Router | ||||
|   let httpTestingController: HttpTestingController | ||||
|   let reloadSpy | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     TestBed.configureTestingModule({ | ||||
| @@ -141,11 +142,13 @@ describe('TasksComponent', () => { | ||||
|     }).compileComponents() | ||||
|  | ||||
|     tasksService = TestBed.inject(TasksService) | ||||
|     reloadSpy = jest.spyOn(tasksService, 'reload') | ||||
|     httpTestingController = TestBed.inject(HttpTestingController) | ||||
|     modalService = TestBed.inject(NgbModal) | ||||
|     router = TestBed.inject(Router) | ||||
|     fixture = TestBed.createComponent(TasksComponent) | ||||
|     component = fixture.componentInstance | ||||
|     jest.useFakeTimers() | ||||
|     fixture.detectChanges() | ||||
|     httpTestingController | ||||
|       .expectOne(`${environment.apiBaseUrl}tasks/`) | ||||
| @@ -164,7 +167,7 @@ describe('TasksComponent', () => { | ||||
|       `Failed${currentTasksLength}` | ||||
|     ) | ||||
|     expect( | ||||
|       fixture.debugElement.queryAll(By.css('input[type="checkbox"]')) | ||||
|       fixture.debugElement.queryAll(By.css('table input[type="checkbox"]')) | ||||
|     ).toHaveLength(currentTasksLength + 1) | ||||
|  | ||||
|     currentTasksLength = tasks.filter( | ||||
| @@ -245,7 +248,7 @@ describe('TasksComponent', () => { | ||||
|  | ||||
|   it('should support toggle all tasks', () => { | ||||
|     const toggleCheck = fixture.debugElement.query( | ||||
|       By.css('input[type=checkbox]') | ||||
|       By.css('table input[type=checkbox]') | ||||
|     ) | ||||
|     toggleCheck.nativeElement.dispatchEvent(new MouseEvent('click')) | ||||
|     fixture.detectChanges() | ||||
| @@ -269,4 +272,15 @@ describe('TasksComponent', () => { | ||||
|       tasks[3].related_document, | ||||
|     ]) | ||||
|   }) | ||||
|  | ||||
|   it('should auto refresh, allow toggle', () => { | ||||
|     expect(reloadSpy).toHaveBeenCalledTimes(1) | ||||
|     jest.advanceTimersByTime(5000) | ||||
|     expect(reloadSpy).toHaveBeenCalledTimes(2) | ||||
|  | ||||
|     component.toggleAutoRefresh() | ||||
|     expect(component.autoRefreshInterval).toBeNull() | ||||
|     jest.advanceTimersByTime(6000) | ||||
|     expect(reloadSpy).toHaveBeenCalledTimes(2) | ||||
|   }) | ||||
| }) | ||||
|   | ||||
| @@ -23,6 +23,8 @@ export class TasksComponent | ||||
|   public pageSize: number = 25 | ||||
|   public page: number = 1 | ||||
|  | ||||
|   public autoRefreshInterval: any | ||||
|  | ||||
|   get dismissButtonText(): string { | ||||
|     return this.selectedTasks.size > 0 | ||||
|       ? $localize`Dismiss selected` | ||||
| @@ -39,6 +41,7 @@ export class TasksComponent | ||||
|  | ||||
|   ngOnInit() { | ||||
|     this.tasksService.reload() | ||||
|     this.toggleAutoRefresh() | ||||
|   } | ||||
|  | ||||
|   ngOnDestroy() { | ||||
| @@ -135,4 +138,15 @@ export class TasksComponent | ||||
|         return $localize`failed` | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   toggleAutoRefresh(): void { | ||||
|     if (this.autoRefreshInterval) { | ||||
|       clearInterval(this.autoRefreshInterval) | ||||
|       this.autoRefreshInterval = null | ||||
|     } else { | ||||
|       this.autoRefreshInterval = setInterval(() => { | ||||
|         this.tasksService.reload() | ||||
|       }, 5000) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 shamoon
					shamoon