From 4152055a8da49bf9f83f7681f1bc32df98af378d Mon Sep 17 00:00:00 2001 From: minottic Date: Wed, 28 Feb 2024 16:40:22 +0100 Subject: [PATCH 1/4] Add spinner when api call is not complete --- .../app/logbook/core/scroll-base.service.spec.ts | 15 +++++++++++++++ .../src/app/logbook/core/scroll-base.service.ts | 16 +++++++++++++++- .../search-window/search-window.component.css | 10 +++++++++- .../search-window/search-window.component.html | 1 + .../search-window.component.spec.ts | 11 ++++++++++- .../search-window/search-window.component.ts | 5 ++--- .../logbook-icon-scroll-service.service.spec.ts | 7 +++++++ scilog/src/app/overview/overview.component.css | 8 ++++++++ scilog/src/app/overview/overview.component.html | 1 + 9 files changed, 68 insertions(+), 6 deletions(-) diff --git a/scilog/src/app/logbook/core/scroll-base.service.spec.ts b/scilog/src/app/logbook/core/scroll-base.service.spec.ts index bebcb6bd..d6ffd705 100644 --- a/scilog/src/app/logbook/core/scroll-base.service.spec.ts +++ b/scilog/src/app/logbook/core/scroll-base.service.spec.ts @@ -1,6 +1,7 @@ import { TestBed } from '@angular/core/testing'; import { ScrollBaseService } from './scroll-base.service'; +import { IDatasource } from 'ngx-ui-scroll'; describe('ScrollBaseService', () => { let service: ScrollBaseService; @@ -15,4 +16,18 @@ describe('ScrollBaseService', () => { it('should be created', () => { expect(service).toBeTruthy(); }); + + it('should decorate with isLoadedDecorator', async () => { + const toDecorate = async (index, count, config) => index + count + config; + const decorated = await service.isLoadedDecorator(toDecorate)(1, 2, 3); + expect(decorated).toEqual(6); + }); + + it('should reset isLoaded flag after reset', async () => { + service.datasource = { adapter: { reset: async () => ({}) } } as IDatasource; + service.isLoaded = true; + service.reset(); + expect(service.isLoaded).toEqual(false); + }); + }); diff --git a/scilog/src/app/logbook/core/scroll-base.service.ts b/scilog/src/app/logbook/core/scroll-base.service.ts index cdef7eb5..9ad8d175 100644 --- a/scilog/src/app/logbook/core/scroll-base.service.ts +++ b/scilog/src/app/logbook/core/scroll-base.service.ts @@ -8,8 +8,11 @@ export class ScrollBaseService { datasource: IDatasource = null; startIndex = 0; config: WidgetItemConfig = null; + isLoaded = false; - constructor() { } + constructor() { + this.getDataBuffer = this.isLoadedDecorator(this.getDataBuffer.bind(this)); + } public async initialize(config: WidgetItemConfig) { // console.log("Config: ", this.config); @@ -64,6 +67,16 @@ export class ScrollBaseService { throw new Error("Abstract method needs to be implemented in derived class.") } + isLoadedDecorator(func: Function) { + const decorated = async (index: number, count: number, config: any) => { + this.isLoaded = false; + const data = await func(index, count, config); + this.isLoaded = true; + return data; + } + return decorated; + } + async updateViewportEstimate() { await this.datasource.adapter.relax(); this.datasource.adapter.check(); @@ -75,6 +88,7 @@ export class ScrollBaseService { reset() { if (this.datasource != null) { + this.isLoaded = false; this.datasource.adapter.reset(); } } diff --git a/scilog/src/app/logbook/core/search-window/search-window.component.css b/scilog/src/app/logbook/core/search-window/search-window.component.css index 7d166bf2..4edbc05d 100644 --- a/scilog/src/app/logbook/core/search-window/search-window.component.css +++ b/scilog/src/app/logbook/core/search-window/search-window.component.css @@ -97,4 +97,12 @@ border: unset; padding: 4px; margin-left: 4px; -} \ No newline at end of file +} + +.spinner { + position: fixed; + z-index: 1031; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} diff --git a/scilog/src/app/logbook/core/search-window/search-window.component.html b/scilog/src/app/logbook/core/search-window/search-window.component.html index 79257645..4e66c8dc 100644 --- a/scilog/src/app/logbook/core/search-window/search-window.component.html +++ b/scilog/src/app/logbook/core/search-window/search-window.component.html @@ -61,6 +61,7 @@
Logbook view: +
{ it('should create', () => { expect(component).toBeTruthy(); }); + + it('should call _prepareConfig on searchString emission', fakeAsync(() => { + const prepareConfigSpy = spyOn(component, '_prepareConfig'); + component.searchString = ''; + component.searchString = 'someSearch'; + tick(501); + expect(prepareConfigSpy).toHaveBeenCalledTimes(1); + })); + }); diff --git a/scilog/src/app/logbook/core/search-window/search-window.component.ts b/scilog/src/app/logbook/core/search-window/search-window.component.ts index 4bee9aba..cc10cc5a 100644 --- a/scilog/src/app/logbook/core/search-window/search-window.component.ts +++ b/scilog/src/app/logbook/core/search-window/search-window.component.ts @@ -65,13 +65,12 @@ export class SearchWindowComponent implements OnInit { this.subscriptions.push(this.searchStringSubject.pipe(debounceTime(500)).subscribe(() => { if (this._searchString.length > 0) { this.showResults = !this.showHelp; + this.searchScrollService.config = this._prepareConfig(); + this.searchScrollService.reset(); } else { this.showHelp = true; this.showResults = false; } - this.searchScrollService.config = this._prepareConfig(); - this.searchScrollService.reset(); - })); this._initialize_help(); diff --git a/scilog/src/app/overview/logbook-icon-scroll-service.service.spec.ts b/scilog/src/app/overview/logbook-icon-scroll-service.service.spec.ts index eada2641..1447b5ea 100644 --- a/scilog/src/app/overview/logbook-icon-scroll-service.service.spec.ts +++ b/scilog/src/app/overview/logbook-icon-scroll-service.service.spec.ts @@ -28,4 +28,11 @@ describe('LogbookIconScrollServiceService', () => { expect(await service.getData(0, 10, {})).toEqual([[1, 2, 3], [4, 5, 6], [7]]); }); + it('should test getDataBuffer after decoration', async () => { + expect(service['isLoaded']).toEqual(false); + spyOn(service, 'getData').and.resolveTo([]); + await service.getDataBuffer(1, 2, 3); + expect(service['isLoaded']).toEqual(true); + }); + }); diff --git a/scilog/src/app/overview/overview.component.css b/scilog/src/app/overview/overview.component.css index 222b0d11..1f186ac7 100644 --- a/scilog/src/app/overview/overview.component.css +++ b/scilog/src/app/overview/overview.component.css @@ -38,3 +38,11 @@ mat-button-toggle-group { transform: scale(75%) translate(18px, -50%); margin-right: 0; } + +.spinner { + position: fixed; + z-index: 1031; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} diff --git a/scilog/src/app/overview/overview.component.html b/scilog/src/app/overview/overview.component.html index b05ca477..3e953a03 100644 --- a/scilog/src/app/overview/overview.component.html +++ b/scilog/src/app/overview/overview.component.html @@ -17,6 +17,7 @@

Logbooks

view_headline
+
From 29e57eda183a6e87acfe59aecd0d69c4781df8ae Mon Sep 17 00:00:00 2001 From: minottic Date: Wed, 28 Feb 2024 16:45:04 +0100 Subject: [PATCH 2/4] Add try catch block to set loaded true on failure --- scilog/src/app/logbook/core/scroll-base.service.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scilog/src/app/logbook/core/scroll-base.service.ts b/scilog/src/app/logbook/core/scroll-base.service.ts index 9ad8d175..b8a8822f 100644 --- a/scilog/src/app/logbook/core/scroll-base.service.ts +++ b/scilog/src/app/logbook/core/scroll-base.service.ts @@ -70,9 +70,17 @@ export class ScrollBaseService { isLoadedDecorator(func: Function) { const decorated = async (index: number, count: number, config: any) => { this.isLoaded = false; - const data = await func(index, count, config); - this.isLoaded = true; - return data; + let data; + try { + data = await func(index, count, config); + } + catch { + console.log('scroller get data returned an error'); + } + finally { + this.isLoaded = true; + return data; + } } return decorated; } From fba7df63c0f23a8b8d83fe3c135c51c86a4cb14c Mon Sep 17 00:00:00 2001 From: minottic Date: Thu, 29 Feb 2024 16:24:01 +0100 Subject: [PATCH 3/4] Add spinner delay to aviod page overload at start --- .../core/search-window/search-window.component.html | 2 +- .../core/search-window/search-window.component.ts | 11 ++++++++++- scilog/src/app/overview/overview.component.html | 2 +- scilog/src/app/overview/overview.component.ts | 12 ++++++++++-- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/scilog/src/app/logbook/core/search-window/search-window.component.html b/scilog/src/app/logbook/core/search-window/search-window.component.html index 4e66c8dc..81b16714 100644 --- a/scilog/src/app/logbook/core/search-window/search-window.component.html +++ b/scilog/src/app/logbook/core/search-window/search-window.component.html @@ -61,7 +61,7 @@
Logbook view: - +
Logbooks view_headline
- +
diff --git a/scilog/src/app/overview/overview.component.ts b/scilog/src/app/overview/overview.component.ts index 33f260d5..42d339c9 100644 --- a/scilog/src/app/overview/overview.component.ts +++ b/scilog/src/app/overview/overview.component.ts @@ -12,6 +12,7 @@ import { LogbookDataService } from '@shared/remote-data.service'; import { LogbookIconScrollService } from './logbook-icon-scroll-service.service'; import { debounceTime } from 'rxjs/operators'; import { ResizedEvent } from '@shared/directives/resized.directive'; +import { animate, style, transition, trigger } from '@angular/animations'; enum ContentType { COLLECTION = 'collection', @@ -24,8 +25,15 @@ export type MatCardType = 'logbook-module' | 'logbook-headline'; selector: 'app-overview', templateUrl: './overview.component.html', styleUrls: ['./overview.component.css'], - providers: [LogbookIconScrollService] - + providers: [LogbookIconScrollService], + animations: [ + trigger('spinner', [ + transition(':enter', [ + style({opacity: 0}), + animate('1ms 0.2s ease-out', style({opacity: 1})) + ]) + ]), + ] }) export class OverviewComponent implements OnInit { From aa0646088cabf75e5d5991443b714873f7b66e90 Mon Sep 17 00:00:00 2001 From: minottic Date: Thu, 29 Feb 2024 18:36:30 +0100 Subject: [PATCH 4/4] Add browserAnimationModule import in test --- scilog/src/app/overview/overview.component.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scilog/src/app/overview/overview.component.spec.ts b/scilog/src/app/overview/overview.component.spec.ts index 7b962301..4c99d529 100644 --- a/scilog/src/app/overview/overview.component.spec.ts +++ b/scilog/src/app/overview/overview.component.spec.ts @@ -11,6 +11,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import {Pipe, PipeTransform} from '@angular/core'; import { Logbooks } from '@model/logbooks'; import { ResizedEvent } from '@shared/directives/resized.directive'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @Pipe({name: 'logbookSearch'}) class LogbookSearchMockPipe implements PipeTransform { @@ -47,7 +48,7 @@ describe('OverviewComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ OverviewComponent, LogbookSearchMockPipe], - imports: [MatDialogModule, RouterTestingModule], + imports: [MatDialogModule, RouterTestingModule, BrowserAnimationsModule], providers: [ { provide: MAT_DIALOG_DATA, useValue: {} }, {provide: LogbookInfoService, useValue: logbookInfoSpy},