From cc9c2e6c1c607f2e407a8e70dc502b612d294ea2 Mon Sep 17 00:00:00 2001 From: kuuurt13 Date: Tue, 12 Nov 2019 21:01:32 -0500 Subject: [PATCH] refactor(BlockUI): Rewrite block queueing in more cohesive way --- .../block-ui-content.component.spec.ts | 42 +++---- .../block-ui-content.component.template.ts | 2 +- .../block-ui-content.component.ts | 115 +++++++----------- lib/models/block-ui-settings.model.ts | 2 +- 4 files changed, 61 insertions(+), 100 deletions(-) diff --git a/lib/components/block-ui-content/block-ui-content.component.spec.ts b/lib/components/block-ui-content/block-ui-content.component.spec.ts index 20a58e6..5ee5537 100644 --- a/lib/components/block-ui-content/block-ui-content.component.spec.ts +++ b/lib/components/block-ui-content/block-ui-content.component.spec.ts @@ -159,6 +159,8 @@ describe('block-ui-content component', () => { method(); }); + cf.detectChanges(); + jasmine.clock().tick(1); let blockWrapper = cf.debugElement.query(By.css('div.block-ui-wrapper')); expect(blockWrapper.classes.active).toBeTruthy(); }); @@ -438,17 +440,17 @@ describe('block-ui-content component', () => { testCmp.blockUI.start(); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); + expect(blkContComp.state.blockCount).toBe(0); jasmine.clock().tick(200); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); + expect(blkContComp.state.blockCount).toBe(0); jasmine.clock().tick(300); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); + expect(blkContComp.state.blockCount).toBe(1); })); it('blocker is active on blockUI.stop() until delay has passed', fakeAsync(() => { @@ -456,23 +458,22 @@ describe('block-ui-content component', () => { jasmine.clock().tick(500); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); + expect(blkContComp.state.blockCount).toBeTruthy(); testCmp.blockUI.stop(); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); + expect(blkContComp.state.blockCount).toBeTruthy(); jasmine.clock().tick(200); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); + expect(blkContComp.state.blockCount).toBeTruthy(); jasmine.clock().tick(300); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); - expectStateIsReset(blkContComp); + expect(blkContComp.state.blockCount).toBe(0); })); it('blocker is NOT active on blockUI.stop() and state is cleared if delayed start has not yet passed, ignoring delayStop', fakeAsync(() => { @@ -480,50 +481,46 @@ describe('block-ui-content component', () => { jasmine.clock().tick(300); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); + expect(blkContComp.state.blockCount).toBe(0); testCmp.blockUI.stop(); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); + expect(blkContComp.state.blockCount).toBe(0); jasmine.clock().tick(1000); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); - expectStateIsReset(blkContComp); + expect(blkContComp.state.blockCount).toBe(0); })); - it('blocker IS active on blockUI.stop() until all blocked calls have resolved', fakeAsync(() => { + it('blocker is active on blockUI.stop() until all blocked calls have resolved', fakeAsync(() => { testCmp.blockUI.start(); testCmp.blockUI.start(); testCmp.blockUI.start(); jasmine.clock().tick(500); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); expect(blkContComp.state.blockCount).toBe(3); testCmp.blockUI.stop(); jasmine.clock().tick(500); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); + expect(blkContComp.state.blockCount).toBeTruthy(); expect(blkContComp.state.blockCount).toBe(2); testCmp.blockUI.stop(); jasmine.clock().tick(500); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); expect(blkContComp.state.blockCount).toBe(1); testCmp.blockUI.stop(); jasmine.clock().tick(500); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); - expectStateIsReset(blkContComp); + expect(blkContComp.state.blockCount).toBe(0); })); it('blocker is no longer active on blockUI.reset(), ignoring any delays or outstanding calls', fakeAsync(() => { @@ -533,20 +530,13 @@ describe('block-ui-content component', () => { jasmine.clock().tick(500); cf.detectChanges(); - expect(blkContComp.active).toBeTruthy(); expect(blkContComp.state.blockCount).toBe(3); testCmp.blockUI.reset(); cf.detectChanges(); - expect(blkContComp.active).toBeFalsy(); - expectStateIsReset(blkContComp); + expect(blkContComp.state.blockCount).toBe(0); })); }); }); -function expectStateIsReset(blkContComp: BlockUIContentComponent) { - expect(blkContComp.state.startTimeout).toBeNull(); - expect(blkContComp.state.stopTimeout).toBeNull(); - expect(blkContComp.state.blockCount).toBe(0); -} diff --git a/lib/components/block-ui-content/block-ui-content.component.template.ts b/lib/components/block-ui-content/block-ui-content.component.template.ts index e8938e8..8d5bdc0 100644 --- a/lib/components/block-ui-content/block-ui-content.component.template.ts +++ b/lib/components/block-ui-content/block-ui-content.component.template.ts @@ -1,5 +1,5 @@ export const template = ` -
+
diff --git a/lib/components/block-ui-content/block-ui-content.component.ts b/lib/components/block-ui-content/block-ui-content.component.ts index 61d52fc..b6d3d1f 100644 --- a/lib/components/block-ui-content/block-ui-content.component.ts +++ b/lib/components/block-ui-content/block-ui-content.component.ts @@ -38,9 +38,14 @@ export class BlockUIContentComponent implements OnInit, AfterViewInit, AfterView @ViewChild('templateOutlet', { read: ViewContainerRef }) templateOutlet: ViewContainerRef; - state: any = { startTimeout: null, stopTimeout: null, blockCount: 0 }; + defaultState: any = { + startTimeout: null, + stopTimeout: null, + updateTimeout: null, + blockCount: 0 + }; + state: any = { ...this.defaultState }; className: string; - active: boolean = false; templateCompRef: ComponentRef<{ message?: any }> | TemplateRef<{}>; message: any; @@ -69,7 +74,6 @@ export class BlockUIContentComponent implements OnInit, AfterViewInit, AfterView } else { const templateComp = this.resolver.resolveComponentFactory(this.templateCmp); this.templateCompRef = this.templateOutlet.createComponent(templateComp); - this.updateBlockTemplate(this.message); } } catch (error) { @@ -82,29 +86,28 @@ export class BlockUIContentComponent implements OnInit, AfterViewInit, AfterView } private subscribeToBlockUI(blockUI$: Observable): Subscription { - return blockUI$ - .subscribe(event => this.onDispatchedEvent(event)); + return blockUI$.subscribe(event => this.onDispatchedEvent(event)); } private onDispatchedEvent(event: BlockUIEvent) { switch (event.action) { - case (BlockUIActions.START): + case BlockUIActions.START: this.onStart(event); break; - case (BlockUIActions.STOP): + case BlockUIActions.STOP: this.onStop(event); break; - case (BlockUIActions.UPDATE): + case BlockUIActions.UPDATE: this.onUpdate(event); break; - case (BlockUIActions.RESET): - this.onReset(); + case BlockUIActions.RESET: + this.resetState(); break; - case (BlockUIActions.UNSUBSCRIBE): + case BlockUIActions.UNSUBSCRIBE: this.onStop(event); this.onUnsubscribe(event.name); break; @@ -115,18 +118,11 @@ export class BlockUIContentComponent implements OnInit, AfterViewInit, AfterView if (name === this.name) { const delay = this.delayStart || this.settings.delayStart || 0; - if (this.state.startTimeout === null) { - if (delay === 0) { - this.showBlock(message); - } else { - this.state.startTimeout = setTimeout(() => { - this.showBlock(message); - }, delay); - } - } - - this.state.blockCount++; - this.updateInstanceBlockCount(); + this.state.startTimeout = setTimeout(() => { + this.state.blockCount += 1; + this.showBlock(message); + this.updateInstanceBlockCount(); + }, delay); } } @@ -134,80 +130,53 @@ export class BlockUIContentComponent implements OnInit, AfterViewInit, AfterView if (name === this.name) { const delay = this.delayStop || this.settings.delayStop || 0; - if (this.state.blockCount > 1) { - this.state.blockCount--; - } else { - if (!this.active) { - this.clearState(); - } else { - if (this.state.stopTimeout === null) { - if (delay === 0) { - this.hideBlock(); - } else { - this.state.stopTimeout = setTimeout(() => { - this.hideBlock(); - }, delay); - } - } + clearTimeout(this.state.stopTimeout); + this.state.stopTimeout = setTimeout(() => { + if (this.state.blockCount > 0) { + this.state.blockCount -= 1; } - } - - this.updateInstanceBlockCount(); + this.updateInstanceBlockCount(); + this.detectChanges(); + }, delay); } } - private onReset() { - this.hideBlock(); - } - private onUpdate({ name, message }: BlockUIEvent) { if (name === this.name) { const delay = this.delayStart || this.settings.delayStart || 0; - if (delay === 0) { + clearTimeout(this.state.updateTimeout); + this.state.updateTimeout = setTimeout(() => { this.updateMessage(message); - } else { - setTimeout(() => { - this.updateMessage(message); - }, delay); - } + }, delay); } } - updateMessage(message: string) { - this.message = message || this.defaultMessage || this.settings.message; - this.updateBlockTemplate(this.message); - this.detectChanges(); + private updateMessage(message: string) { + this.showBlock(message); } private showBlock(message: any) { - this.active = true; this.message = message || this.defaultMessage || this.settings.message; this.updateBlockTemplate(this.message); this.detectChanges(); } - private hideBlock() { - this.clearState(); - this.active = false; - this.detectChanges(); - } - - private clearState() { - this.state.startTimeout != null && clearTimeout(this.state.startTimeout); - this.state.stopTimeout != null && clearTimeout(this.state.stopTimeout); - this.state.blockCount = 0; - this.state.startTimeout = null; - this.state.stopTimeout = null; - this.updateInstanceBlockCount(); - } - private updateBlockTemplate(msg: any): void { if (this.templateCompRef && this.templateCompRef instanceof ComponentRef) { this.templateCompRef.instance.message = msg; } } + private resetState() { + clearTimeout(this.state.startTimeout); + clearTimeout(this.state.stopTimeout); + clearTimeout(this.state.updateTimeout); + this.state = { ...this.defaultState }; + this.updateInstanceBlockCount(); + this.detectChanges(); + } + private onUnsubscribe(name: string) { if (this.blockUISubscription && name === this.name) { this.blockUISubscription.unsubscribe(); @@ -216,7 +185,8 @@ export class BlockUIContentComponent implements OnInit, AfterViewInit, AfterView private updateInstanceBlockCount() { if (this.blockUI.blockUIInstances[this.name]) { - this.blockUI.blockUIInstances[this.name].blockCount = this.state.blockCount; + const { blockCount } = this.state; + this.blockUI.blockUIInstances[this.name].blockCount = blockCount; } } @@ -227,6 +197,7 @@ export class BlockUIContentComponent implements OnInit, AfterViewInit, AfterView } ngOnDestroy() { + this.resetState(); this.onUnsubscribe(this.name); } } diff --git a/lib/models/block-ui-settings.model.ts b/lib/models/block-ui-settings.model.ts index 4584ff3..3ae6c2e 100644 --- a/lib/models/block-ui-settings.model.ts +++ b/lib/models/block-ui-settings.model.ts @@ -1,4 +1,4 @@ -import { ComponentRef, TemplateRef } from '@angular/core'; +import { ComponentRef } from '@angular/core'; export interface BlockUISettings { message?: string;