Refactored loading state and animation

pull/3/head
Max Ehrlicher-Schmidt 4 years ago
parent 10bbf3281c
commit 0180322e41

@ -48,10 +48,14 @@
</ng-container> </ng-container>
<!-- Other Columns --> <!-- Other Columns -->
<ng-container *ngFor="let column of dataColumns;" [matColumnDef]="column" [sticky]=isStickyColumn(column)> <ng-container
*ngFor="let column of dataColumns"
[matColumnDef]="column"
[sticky]="isStickyColumn(column)"
>
<!-- add cdkDrag to make columns draggable--> <!-- add cdkDrag to make columns draggable-->
<th mat-header-cell *matHeaderCellDef mat-sort-header> <th mat-header-cell *matHeaderCellDef mat-sort-header>
{{getHeader(column)}} {{ getHeader(column) }}
</th> </th>
<td mat-cell *matCellDef="let element"> <td mat-cell *matCellDef="let element">
<app-cell <app-cell
@ -73,10 +77,8 @@
(click)="edit(element)" (click)="edit(element)"
*ngIf=" *ngIf="
!element.isLockedByMe && !element.isLockedByMe &&
!element.waitingForEditPermissions &&
!element.isLocked && !element.isLocked &&
!element.saving && !isLoading(element.id)
!element.unlocking
" "
> >
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
@ -85,10 +87,8 @@
mat-icon-button mat-icon-button
*ngIf=" *ngIf="
!element.isLockedByMe && !element.isLockedByMe &&
!element.waitingForEditPermissions && !isLoading(element.id) &&
!element.isLocked && !element.isLocked
!element.saving &&
!element.unlocking
" "
> >
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
@ -96,17 +96,13 @@
<mat-spinner <mat-spinner
[diameter]="32" [diameter]="32"
*ngIf=" *ngIf="isLoading(element.id)"
element.waitingForEditPermissions ||
element.saving ||
element.unlocking
"
></mat-spinner> ></mat-spinner>
<button <button
mat-icon-button mat-icon-button
*ngIf=" *ngIf="
element.isLockedByMe && !element.unlocking && !element.saving element.isLockedByMe && !isLoading(element.id)
" "
(click)="save(element)" (click)="save(element)"
> >
@ -116,7 +112,7 @@
mat-icon-button mat-icon-button
matTooltip="Alle ungespeicherten Änderungen verwerfen." matTooltip="Alle ungespeicherten Änderungen verwerfen."
*ngIf=" *ngIf="
element.isLockedByMe && !element.unlocking && !element.saving element.isLockedByMe && !isLoading(element.id)
" "
(click)="cancel(element)" (click)="cancel(element)"
> >

@ -9,12 +9,6 @@ import {
CargoBikeUpdateInput, CargoBikeUpdateInput,
} from 'src/generated/graphql'; } from 'src/generated/graphql';
type CargoBikeDataRow = CargoBikeResult & {
waitingForEditPermissions: boolean;
saving: boolean;
unlocking: boolean;
};
@Component({ @Component({
selector: 'app-bikes', selector: 'app-bikes',
templateUrl: './bikes.component.html', templateUrl: './bikes.component.html',
@ -40,8 +34,10 @@ export class BikesComponent {
additionalColumnsBack: string[] = ['buttons']; additionalColumnsBack: string[] = ['buttons'];
displayedColumns: string[] = []; displayedColumns: string[] = [];
loadingRowIds: string[] = [];
bikes = <Array<any>>[]; bikes = <Array<any>>[];
selection = new SelectionModel<CargoBikeDataRow>(true, []); selection = new SelectionModel<CargoBikeResult>(true, []);
reloadingTable = false; reloadingTable = false;
@ -58,15 +54,14 @@ export class BikesComponent {
).enumValues = groupEnum; ).enumValues = groupEnum;
}); });
bikesService.loadingRowIds.subscribe(rowIds => {
this.loadingRowIds = rowIds;
})
bikesService.bikes.subscribe((bikes) => { bikesService.bikes.subscribe((bikes) => {
this.reloadingTable = false; this.reloadingTable = false;
this.bikes = bikes.map((bike) => {
return <any>Object.assign({}, deepCopy(bike), { this.bikes = bikes;
waitingForEditPermissions: false,
saving: false,
unlocking: false,
});
});
if (bikes[0]) { if (bikes[0]) {
this.displayedColumns = []; this.displayedColumns = [];
this.dataColumns = []; this.dataColumns = [];
@ -109,9 +104,7 @@ export class BikesComponent {
addColumnsFromObject(prefix: string, object: Object) { addColumnsFromObject(prefix: string, object: Object) {
for (const prop in object) { for (const prop in object) {
let propName = prefix + prop; let propName = prefix + prop;
console.log(typeof object[prop]);
if (typeof object[prop] === 'object') { if (typeof object[prop] === 'object') {
console.log(object);
this.addColumnsFromObject(prefix + prop + '.', object[prop]); this.addColumnsFromObject(prefix + prop + '.', object[prop]);
} else if (!this.blacklistedColumns.includes(propName)) { } else if (!this.blacklistedColumns.includes(propName)) {
this.dataColumns.push(propName); this.dataColumns.push(propName);
@ -119,6 +112,10 @@ export class BikesComponent {
} }
} }
flatten(object: Object) {
return object;
}
getHeader(propertyName: string) { getHeader(propertyName: string) {
return ( return (
this.columnInfo.find((column) => column.name === propertyName)?.header || this.columnInfo.find((column) => column.name === propertyName)?.header ||
@ -135,8 +132,8 @@ export class BikesComponent {
isReadonly(propertyName: string) { isReadonly(propertyName: string) {
return ( return (
this.columnInfo.find((column) => column.name === propertyName)?.readonly || this.columnInfo.find((column) => column.name === propertyName)
false ?.readonly || false
); );
} }
@ -149,23 +146,25 @@ export class BikesComponent {
getEnumValues(propertyName: string) { getEnumValues(propertyName: string) {
return ( return (
this.columnInfo.find((column) => column.name === propertyName)?.enumValues || this.columnInfo.find((column) => column.name === propertyName)
[] ?.enumValues || []
); );
} }
isLoading(id: string) {
return this.loadingRowIds.includes(id);
}
reloadTable() { reloadTable() {
this.reloadingTable = true; this.reloadingTable = true;
this.bikesService.loadBikes(); this.bikesService.loadBikes();
} }
edit(row: CargoBikeDataRow) { edit(row: CargoBikeResult) {
row.waitingForEditPermissions = true;
this.bikesService.lockBike({ id: row.id }); this.bikesService.lockBike({ id: row.id });
} }
save(row: CargoBikeDataRow) { save(row: CargoBikeResult) {
row.saving = true;
const bike: CargoBikeUpdateInput = filter( const bike: CargoBikeUpdateInput = filter(
CargoBikeFieldsMutableFragmentDoc, CargoBikeFieldsMutableFragmentDoc,
row row
@ -173,8 +172,7 @@ export class BikesComponent {
this.bikesService.updateBike({ bike }); this.bikesService.updateBike({ bike });
} }
cancel(row: CargoBikeDataRow) { cancel(row: CargoBikeResult) {
row.unlocking = true;
this.bikesService.unlockBike({ id: row.id }); this.bikesService.unlockBike({ id: row.id });
} }

@ -10,7 +10,7 @@ import {
LockCargoBikeGQL, LockCargoBikeGQL,
LockCargoBikeMutationVariables, LockCargoBikeMutationVariables,
UnlockCargoBikeGQL, UnlockCargoBikeGQL,
UnlockCargoBikeMutationVariables UnlockCargoBikeMutationVariables,
} from 'src/generated/graphql'; } from 'src/generated/graphql';
import { DeepExtractTypeSkipArrays } from 'ts-deep-extract-types'; import { DeepExtractTypeSkipArrays } from 'ts-deep-extract-types';
@ -24,6 +24,7 @@ export type CargoBikeResult = DeepExtractTypeSkipArrays<
}) })
export class BikesService { export class BikesService {
bikes: BehaviorSubject<CargoBikeResult[]> = new BehaviorSubject([]); bikes: BehaviorSubject<CargoBikeResult[]> = new BehaviorSubject([]);
loadingRowIds: BehaviorSubject<string[]> = new BehaviorSubject([]);
groupEnum: BehaviorSubject<string[]> = new BehaviorSubject<string[]>([]); groupEnum: BehaviorSubject<string[]> = new BehaviorSubject<string[]>([]);
constructor( constructor(
@ -32,58 +33,94 @@ export class BikesService {
private updateCargoBikeGQL: UpdateCargoBikeGQL, private updateCargoBikeGQL: UpdateCargoBikeGQL,
private lockCargoBikeGQL: LockCargoBikeGQL, private lockCargoBikeGQL: LockCargoBikeGQL,
private unlockCargoBikeGQL: UnlockCargoBikeGQL private unlockCargoBikeGQL: UnlockCargoBikeGQL
) { } ) {}
addLoadingRowId(id: string) {
this.loadingRowIds.next([...this.loadingRowIds.value, id]);
}
removeLoadingRowId(id: string) {
this.loadingRowIds.value.forEach((item, index) => {
if (item === id) {
this.loadingRowIds.value.splice(index, 1);
}
});
}
loadBikes() { loadBikes() {
this.getCargoBikesGQL.fetch().subscribe((result) => { this.getCargoBikesGQL.fetch().subscribe((result) => {
this.bikes.next(result.data.cargoBikes); this.bikes.next(result.data.cargoBikes);
let enumValues = result.data.__type.enumValues.map(value => value.name); let enumValues = result.data.__type.enumValues.map((value) => value.name);
this.groupEnum.next(enumValues); this.groupEnum.next(enumValues);
}); });
} }
reloadBike(variables: GetCargoBikeByIdQueryVariables) { reloadBike(variables: GetCargoBikeByIdQueryVariables) {
this.getCargoBikeByIdGQL.fetch(variables).subscribe((result) => { this.addLoadingRowId(variables.id);
const newBike = result.data.cargoBikeById; this.getCargoBikeByIdGQL
this.bikes.next( .fetch(variables)
this.bikes.value.map((bike) => .subscribe((result) => {
newBike.id === bike.id ? newBike : bike const newBike = result.data.cargoBikeById;
) this.bikes.next(
); this.bikes.value.map((bike) =>
}); newBike.id === bike.id ? newBike : bike
)
);
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
} }
updateBike(variableValues: UpdateCargoBikeMutationVariables) { updateBike(variables: UpdateCargoBikeMutationVariables) {
this.updateCargoBikeGQL.mutate(variableValues).subscribe((result) => { this.addLoadingRowId(variables.bike.id);
const newBike = result.data.updateCargoBike; this.updateCargoBikeGQL
this.bikes.next( .mutate(variables)
this.bikes.value.map((bike) => .subscribe((result) => {
newBike.id === bike.id ? newBike : bike const newBike = result.data.updateCargoBike;
) this.bikes.next(
); this.bikes.value.map((bike) =>
}); newBike.id === bike.id ? newBike : bike
)
);
})
.add(() => {
this.removeLoadingRowId(variables.bike.id);
});
} }
lockBike(variables: LockCargoBikeMutationVariables) { lockBike(variables: LockCargoBikeMutationVariables) {
this.lockCargoBikeGQL.mutate(variables).subscribe((result) => { this.addLoadingRowId(variables.id);
const lockedBike = result.data.lockCargoBike; this.lockCargoBikeGQL
this.bikes.next( .mutate(variables)
this.bikes.value.map((bike) => .subscribe((result) => {
lockedBike.id === bike.id ? lockedBike : bike const lockedBike = result.data.lockCargoBike;
) this.bikes.next(
); this.bikes.value.map((bike) =>
}) lockedBike.id === bike.id ? lockedBike : bike
)
);
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
} }
unlockBike(variables: UnlockCargoBikeMutationVariables) { unlockBike(variables: UnlockCargoBikeMutationVariables) {
this.unlockCargoBikeGQL.mutate(variables).subscribe((result) => { this.addLoadingRowId(variables.id);
const unlockedBike = result.data.unlockCargoBike; this.unlockCargoBikeGQL
this.bikes.next( .mutate(variables)
this.bikes.value.map((bike) => .subscribe((result) => {
unlockedBike.id === bike.id ? unlockedBike : bike const unlockedBike = result.data.unlockCargoBike;
) this.bikes.next(
); this.bikes.value.map((bike) =>
}) unlockedBike.id === bike.id ? unlockedBike : bike
)
);
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
} }
relockBike(variables: LockCargoBikeMutationVariables) { relockBike(variables: LockCargoBikeMutationVariables) {

Loading…
Cancel
Save