Performance optimization WIP

pull/4/head
Max 4 years ago
parent 044e9634e2
commit 56d6272236

@ -1,4 +1,4 @@
import { Component, Input, Output, EventEmitter } from '@angular/core'; import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
@Component({ @Component({
selector: 'app-cell', selector: 'app-cell',

@ -1,14 +1,14 @@
import { DocumentNode } from 'graphql'; import { DocumentNode } from 'graphql';
export function isPartOfGraphQLDoc( export function isPartOfGraphQLDoc(
variableName: String, variableName: string,
doc: DocumentNode doc: DocumentNode
): boolean { ): boolean {
return isPartOfSelectionSet(variableName, doc.definitions[0]); return isPartOfSelectionSet(variableName, doc.definitions[0]);
} }
function isPartOfSelectionSet( function isPartOfSelectionSet(
variableName: String, variableName: string,
selectionObject: any selectionObject: any
): boolean { ): boolean {
const variablePath = variableName.split('.'); const variablePath = variableName.split('.');

@ -17,12 +17,12 @@
<div class="table-container"> <div class="table-container">
<table <table
mat-table mat-table
[dataSource]="data"
class="mat-elevation-z8" class="mat-elevation-z8"
matSort matSort
cdkDropList cdkDropList
cdkDropListOrientation="horizontal" cdkDropListOrientation="horizontal"
(cdkDropListDropped)="drop($event)" (cdkDropListDropped)="drop($event)"
[dataSource]="data"
> >
<!--- Note that these columns can be defined in any order. <!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" --> The actual rendered columns are set as a property on the row definition" -->
@ -59,10 +59,12 @@
</th> </th>
<td mat-cell *matCellDef="let element"> <td mat-cell *matCellDef="let element">
<app-cell <app-cell
[editable]="element.isLockedByMe && !isReadonly(column.name)" *ngIf="!column.readonly && element.isLockedByMe; else stringValue"
[editable]="true"
[(value)]="element[column.name]" [(value)]="element[column.name]"
[inputType]="getType(column.name)" [inputType]="column.type"
></app-cell> ></app-cell>
<ng-template #stringValue>{{ element[column.name] }}</ng-template>
</td> </td>
</ng-container> </ng-container>
@ -100,9 +102,7 @@
<button <button
mat-icon-button mat-icon-button
*ngIf=" *ngIf="element.isLockedByMe && !isLoading(element.id)"
element.isLockedByMe && !isLoading(element.id)
"
(click)="save(element)" (click)="save(element)"
> >
<mat-icon>save</mat-icon> <mat-icon>save</mat-icon>
@ -110,9 +110,7 @@
<button <button
mat-icon-button mat-icon-button
matTooltip="Alle ungespeicherten Änderungen verwerfen." matTooltip="Alle ungespeicherten Änderungen verwerfen."
*ngIf=" *ngIf="element.isLockedByMe && !isLoading(element.id)"
element.isLockedByMe && !isLoading(element.id)
"
(click)="cancel(element)" (click)="cancel(element)"
> >
<mat-icon>cancel</mat-icon> <mat-icon>cancel</mat-icon>

@ -1,5 +1,5 @@
import { SelectionModel } from '@angular/cdk/collections'; import { SelectionModel } from '@angular/cdk/collections';
import { Component } from '@angular/core'; import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { BikesService, CargoBikeResult } from 'src/app/services/bikes.service'; import { BikesService, CargoBikeResult } from 'src/app/services/bikes.service';
import { flatten } from 'src/app/helperFunctions/flattenObject'; import { flatten } from 'src/app/helperFunctions/flattenObject';
@ -13,15 +13,23 @@ import {
import { SchemaService } from 'src/app/services/schema.service'; import { SchemaService } from 'src/app/services/schema.service';
import { logArrayInColumnInfoForm } from 'src/app/helperFunctions/logArrayInColumnInfoForm'; import { logArrayInColumnInfoForm } from 'src/app/helperFunctions/logArrayInColumnInfoForm';
import { MatTableDataSource } from '@angular/material/table';
@Component({ @Component({
selector: 'app-bikes', selector: 'app-bikes',
templateUrl: './bikes.component.html', templateUrl: './bikes.component.html',
styleUrls: ['./bikes.component.scss'], styleUrls: ['./bikes.component.scss'],
//changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class BikesComponent { export class BikesComponent {
/** this array defines the columns and headers of the table and the order they are displayed */ /** this array defines the columns and headers of the table and the order they are displayed */
columnInfo = [ columnInfo: {
name: string;
header: string;
sticky?: boolean;
readonly?: boolean;
type?: string;
}[] = [
{ name: 'name', header: 'Name', sticky: true }, { name: 'name', header: 'Name', sticky: true },
{ name: 'id', header: 'ID', readonly: true }, { name: 'id', header: 'ID', readonly: true },
{ name: 'group', header: 'Gruppe' }, { name: 'group', header: 'Gruppe' },
@ -90,7 +98,7 @@ export class BikesComponent {
loadingRowIds: string[] = []; loadingRowIds: string[] = [];
/** data source of the table */ /** data source of the table */
data = [] as Array<any>; data: MatTableDataSource<any> = new MatTableDataSource() ;
selection = new SelectionModel<CargoBikeResult>(true, []); selection = new SelectionModel<CargoBikeResult>(true, []);
reloadingTable = false; reloadingTable = false;
@ -100,41 +108,53 @@ export class BikesComponent {
constructor( constructor(
private bikesService: BikesService, private bikesService: BikesService,
private schemaService: SchemaService private schemaService: SchemaService,
) { //private cdr: ChangeDetectorRef
) {}
ngAfterViewInit() {
//this.cdr.detach();
this.addTypesToColumnInfo();
this.addReadOnlyPropertiesToColumnInfo();
this.columnInfo.forEach((column) => this.columnInfo.forEach((column) =>
this.displayedColumns.push(column.name) this.displayedColumns.push(column.name)
); );
this.displayedColumns.unshift(this.additionalColumnsFront[0]); this.displayedColumns.unshift(this.additionalColumnsFront[0]);
this.displayedColumns.push(this.additionalColumnsBack[0]); this.displayedColumns.push(this.additionalColumnsBack[0]);
bikesService.loadingRowIds.subscribe((rowIds) => { this.bikesService.loadingRowIds.subscribe((rowIds) => {
this.loadingRowIds = rowIds; this.loadingRowIds = rowIds;
}); });
bikesService.bikes.subscribe((newTableDataSource) => { this.bikesService.bikes.subscribe((newTableDataSource) => {
console.time("newBikes");
this.reloadingTable = false; this.reloadingTable = false;
const tempDataSource = []; const tempDataSource = [];
console.time("overwriteCheck");
for (const row of newTableDataSource) { for (const row of newTableDataSource) {
const oldRow = this.getRowById(row.id); const oldRow = this.getRowById(row.id);
/** make sure to not overwrite a row that is being edited */ /** make sure to not overwrite a row that is being edited */
if (!oldRow) { if (!oldRow) {
tempDataSource.push(flatten(row)); tempDataSource.push(flatten(row));
} } else if (!(oldRow.isLockedByMe && row.isLockedByMe)) {
else if (!(oldRow.isLockedByMe && row.isLockedByMe)) {
tempDataSource.push(flatten(row)); tempDataSource.push(flatten(row));
} else if (!!oldRow) { } else if (!!oldRow) {
tempDataSource.push(oldRow); tempDataSource.push(oldRow);
} }
} }
this.data = tempDataSource; console.timeEnd("overwriteCheck");
console.time("assignData");
this.data.data = tempDataSource;
console.timeEnd("assignData");
console.timeEnd("newBikes");
}); });
bikesService.loadBikes(); this.bikesService.loadBikes();
}
ngOnInit() {
this.relockingInterval = setInterval(() => { this.relockingInterval = setInterval(() => {
for (const row of this.data) { for (const row of this.data.data) {
if (row.isLockedByMe) { if (row.isLockedByMe) {
this.bikesService.relockBike({ id: row.id }); this.bikesService.relockBike({ id: row.id });
} }
@ -146,6 +166,22 @@ export class BikesComponent {
clearInterval(this.relockingInterval); clearInterval(this.relockingInterval);
} }
addTypesToColumnInfo() {
for (const column of this.columnInfo) {
if (!column.type) {
column.type = this.getType(column.name);
}
}
}
addReadOnlyPropertiesToColumnInfo() {
for (const column of this.columnInfo) {
if (!column.readonly) {
column.readonly = this.isReadonly(column.name);
}
}
}
getHeader(propertyName: string) { getHeader(propertyName: string) {
return ( return (
this.columnInfo.find((column) => column.name === propertyName)?.header || this.columnInfo.find((column) => column.name === propertyName)?.header ||
@ -163,8 +199,7 @@ export class BikesComponent {
isReadonly(propertyName: string) { isReadonly(propertyName: string) {
return ( return (
this.columnInfo.find((column) => column.name === propertyName) this.columnInfo.find((column) => column.name === propertyName).readonly ||
?.readonly ||
!isPartOfGraphQLDoc(propertyName, CargoBikeFieldsMutableFragmentDoc) !isPartOfGraphQLDoc(propertyName, CargoBikeFieldsMutableFragmentDoc)
); );
} }
@ -202,7 +237,7 @@ export class BikesComponent {
} }
getRowById(id: string) { getRowById(id: string) {
return this.data.find(row => row.id === id); return this.data.data.find((row) => row.id === id);
} }
drop(event: CdkDragDrop<string[]>) { drop(event: CdkDragDrop<string[]>) {
@ -216,7 +251,7 @@ export class BikesComponent {
/** Whether the number of selected elements matches the total number of rows. */ /** Whether the number of selected elements matches the total number of rows. */
isAllSelected() { isAllSelected() {
const numSelected = this.selection.selected.length; const numSelected = this.selection.selected.length;
const numRows = this.data.length; const numRows = this.data.data.length;
return numSelected === numRows; return numSelected === numRows;
} }
@ -224,6 +259,6 @@ export class BikesComponent {
masterToggle() { masterToggle() {
this.isAllSelected() this.isAllSelected()
? this.selection.clear() ? this.selection.clear()
: this.data.forEach((row) => this.selection.select(row)); : this.data.data.forEach((row) => this.selection.select(row));
} }
} }

@ -1,6 +1,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { SchemaService } from './schema.service'; import { SchemaService } from './schema.service';
import { deepCopy } from 'src/app/helperFunctions/deepCopy';
import { import {
GetCargoBikesGQL, GetCargoBikesGQL,
GetCargoBikesQuery, GetCargoBikesQuery,
@ -51,7 +52,15 @@ export class BikesService {
loadBikes() { loadBikes() {
this.getCargoBikesGQL.fetch().subscribe((result) => { this.getCargoBikesGQL.fetch().subscribe((result) => {
console.time("addMoreBikes");
for (let i = 1; i <= 500; i++) {
const newBike = deepCopy(result.data.cargoBikes[0]);
newBike.id = (i + 100).toString();
result.data.cargoBikes.push(newBike);
}
console.timeEnd("addMoreBikes");
this.bikes.next(result.data.cargoBikes); this.bikes.next(result.data.cargoBikes);
}); });
} }

Loading…
Cancel
Save