Skip to content

Commit

Permalink
fix(820): Searchbar working again
Browse files Browse the repository at this point in the history
  • Loading branch information
Schottkyc137 authored Jun 9, 2021
1 parent 94d0b80 commit fb79105
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 92 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<button
mat-icon-button
class="sync-icon"
[hidden]="!taskCounter"
[hidden]="allTasksFinished | async"
[matMenuTriggerFor]="taskListDropdown"
(menuClosed)="wasClosed = true"
>
<span
[matBadge]="taskCounter"
[matBadge]="taskCounterObservable | async"
matBadgeColor="accent"
[matBadgeHidden]="taskCounter <= 1"
[matBadgeHidden]="allTasksFinished | async"
>
<mat-icon class="header-icon" fontIcon="fa-refresh"></mat-icon>
</span>
Expand All @@ -20,7 +21,7 @@
</div>

<div
*ngFor="let process of backgroundProcesses"
*ngFor="let process of filteredProcesses | async"
class="details-line details-container"
fxLayout="row"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { MatTooltipModule } from "@angular/material/tooltip";
import { MatIconModule } from "@angular/material/icon";
import { MatBadgeModule } from "@angular/material/badge";
import { MatProgressSpinnerModule } from "@angular/material/progress-spinner";
import { SimpleChange } from "@angular/core";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { EMPTY, of } from "rxjs";

describe("BackgroundProcessingIndicatorComponent", () => {
let component: BackgroundProcessingIndicatorComponent;
Expand All @@ -32,6 +32,7 @@ describe("BackgroundProcessingIndicatorComponent", () => {
beforeEach(() => {
fixture = TestBed.createComponent(BackgroundProcessingIndicatorComponent);
component = fixture.componentInstance;
component.backgroundProcesses = EMPTY;

fixture.detectChanges();
});
Expand All @@ -41,26 +42,22 @@ describe("BackgroundProcessingIndicatorComponent", () => {
});

it("should aggregate process states by title if set to summarize", async () => {
spyOn(component.taskListDropdownTrigger, "openMenu");
const p1 = { title: "sync", pending: true };
const p2a = { title: "indexing", details: "A", pending: false };
const p2b = { title: "indexing", details: "B", pending: true };
const p2c = { title: "indexing", details: "C", pending: false };
const p3 = { title: "completed other stuff", pending: false };
component.backgroundProcesses = [p1, p2a, p2b, p2c, p3];

component.backgroundProcesses = of([p1, p2a, p2b, p2c, p3]);
component.summarize = true;
spyOn(component.taskListDropdownTrigger, "openMenu");
component.ngOnInit();

component.ngOnChanges({
backgroundProcesses: new SimpleChange(
[],
component.backgroundProcesses,
false
),
});
fixture.detectChanges();
const taskCounter = await component.taskCounterObservable.toPromise();
expect(taskCounter).toBe(2);

expect(component.taskCounter).toBe(2); // not counting the pending === false
expect(component.backgroundProcesses).toEqual([
const filteredProcesses = await component.filteredProcesses.toPromise();
expect(filteredProcesses).toEqual([
p1,
{ title: p2a.title, pending: true },
p3,
Expand All @@ -69,42 +66,24 @@ describe("BackgroundProcessingIndicatorComponent", () => {
});

it("should automatically close details after all processes finished", async () => {
component.backgroundProcesses = [{ title: "sync", pending: false }];
component.backgroundProcesses = of([{ title: "sync", pending: false }]);
spyOn(component.taskListDropdownTrigger, "closeMenu");
component.ngOnInit();

component.ngOnChanges({
backgroundProcesses: new SimpleChange(
[],
component.backgroundProcesses,
false
),
});
fixture.detectChanges();
const tasks = await component.taskCounterObservable.toPromise();

expect(component.taskCounter).toBe(0);
expect(tasks).toBe(0);
expect(component.taskListDropdownTrigger.closeMenu).toHaveBeenCalled();
});

it("should not open details again if they the state before was already pending (and user may have manually closed)", async () => {
component.backgroundProcesses = [
component.backgroundProcesses = of([
{ title: "sync", pending: true },
{ title: "other", pending: true },
{ title: "yet another", pending: true },
];
]);
spyOn(component.taskListDropdownTrigger, "openMenu");

component.ngOnChanges({
backgroundProcesses: new SimpleChange(
[
{ title: "sync", pending: true },
{ title: "other", pending: true },
],
component.backgroundProcesses,
false
),
});
fixture.detectChanges();

expect(component.taskListDropdownTrigger.openMenu).not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,81 +1,88 @@
import {
Component,
Input,
OnChanges,
SimpleChanges,
ViewChild,
} from "@angular/core";
import { Component, Input, OnInit, ViewChild } from "@angular/core";
import { MatMenuTrigger } from "@angular/material/menu";
import { BackgroundProcessState } from "../background-process-state.interface";
import { Observable } from "rxjs";
import { map, startWith } from "rxjs/operators";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";

/**
* A dumb component handling presentation of the sync indicator icon
* and an additional details dropdown listing all currently running background processes.
*/
@UntilDestroy()
@Component({
selector: "app-background-processing-indicator",
templateUrl: "./background-processing-indicator.component.html",
styleUrls: ["./background-processing-indicator.component.scss"],
})
export class BackgroundProcessingIndicatorComponent implements OnChanges {
export class BackgroundProcessingIndicatorComponent implements OnInit {
/** details on current background processes to be displayed to user */
@Input() backgroundProcesses: BackgroundProcessState[] = [];
@Input() backgroundProcesses: Observable<BackgroundProcessState[]>;
filteredProcesses: Observable<BackgroundProcessState[]>;
taskCounterObservable: Observable<number>;
allTasksFinished: Observable<boolean>;

/** whether processes of with the same title shall be summarized into one line */
@Input() summarize: boolean = true;

/** how many special tasks (e.g. index creations) are currently being processed */
taskCounter: number;
wasClosed: boolean = false;

/** handle to programmatically open/close the details dropdown */
@ViewChild(MatMenuTrigger) taskListDropdownTrigger: MatMenuTrigger;

constructor() {}

ngOnChanges(changes: SimpleChanges) {
if (!changes.backgroundProcesses) {
return;
}

if (this.summarize && this.backgroundProcesses) {
this.backgroundProcesses = this.summarizeProcesses(
this.backgroundProcesses
);
}

this.taskCounter = this.backgroundProcesses?.filter(
(s) => s.pending
).length;
ngOnInit() {
this.filteredProcesses = this.backgroundProcesses.pipe(
map((processes) => this.summarizeProcesses(processes))
);
this.taskCounterObservable = this.filteredProcesses.pipe(
map((processes) => processes.filter((p) => p.pending).length)
);
this.allTasksFinished = this.taskCounterObservable.pipe(
startWith(0),
map((tc) => tc === 0)
);
this.taskCounterObservable
.pipe(untilDestroyed(this))
.subscribe((amount) => {
if (amount === 0) {
this.taskListDropdownTrigger.closeMenu();
} else {
if (!this.wasClosed) {
this.taskListDropdownTrigger.openMenu();
}
}
});
}

if (this.taskCounter > 1) {
if (
!(
changes.backgroundProcesses.previousValue?.filter((s) => s.pending)
.length > 1
)
) {
// open menu automatically only if it has not been opened previously, to avoid reopening after user closed it
this.taskListDropdownTrigger?.openMenu();
}
} else if (this.taskCounter === 0) {
this.taskListDropdownTrigger?.closeMenu();
}
private combineProcesses(
first: BackgroundProcessState,
second: BackgroundProcessState
): BackgroundProcessState {
return {
title: first.title,
pending: first.pending || second.pending,
};
}

private summarizeProcesses(
processes: BackgroundProcessState[]
): BackgroundProcessState[] {
return processes.reduce((accumulator, currentEntry) => {
const summaryEntry = accumulator.find(
(i) => i.title === currentEntry.title
if (!this.summarize) {
return processes;
}
const accumulator: BackgroundProcessState[] = [];
for (const process of processes) {
const summaryEntry = accumulator.findIndex(
(i) => i.title === process.title
);
if (!summaryEntry) {
accumulator.push(currentEntry);
if (summaryEntry === -1) {
accumulator.push(process);
} else {
delete summaryEntry.details;
summaryEntry.pending = summaryEntry.pending || currentEntry.pending;
accumulator[summaryEntry] = this.combineProcesses(
accumulator[summaryEntry],
process
);
}
return accumulator;
}, []);
}
return accumulator;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
-->

<app-background-processing-indicator
[backgroundProcesses]="backgroundProcesses | async"
[backgroundProcesses]="backgroundProcesses"
>
</app-background-processing-indicator>

0 comments on commit fb79105

Please sign in to comment.