Add delete functionallity

urls
Max Ehrlicher-Schmidt 4 years ago
parent daeb4b1a0a
commit bfa8a4f0ef

@ -26,13 +26,15 @@ import {MatTooltipModule} from '@angular/material/tooltip';
import {MatSelectModule} from '@angular/material/select';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import {MatDialogModule} from '@angular/material/dialog';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LoginComponent } from './pages/login/login.component';
import { BikesComponent } from './pages/tables/bikes/bikes.component';
import { BikesComponent, DeleteConfirmationDialog } from './pages/tables/bikes/bikes.component';
import { GraphQLModule } from './graphql.module';
import { ParticipantsComponent } from './pages/tables/participants/participants.component';
import { LendingStationsComponent } from './pages/tables/lending-stations/lending-stations.component';
@ -52,6 +54,7 @@ import { TokenInterceptor } from './helper/token.interceptor'
LendingStationsComponent,
TableOverviewComponent,
CellComponent,
DeleteConfirmationDialog
],
imports: [
BrowserModule,
@ -81,7 +84,8 @@ import { TokenInterceptor } from './helper/token.interceptor'
MatTooltipModule,
MatSelectModule,
MatPaginatorModule,
MatSortModule
MatSortModule,
MatDialogModule
],
providers: [NavService,
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }],

@ -27,3 +27,7 @@ mutation UnlockCargoBike($id: ID!) {
...CargoBikeFields
}
}
mutation DeleteCargoBike($id: ID!) {
deleteCargoBike(id: $id)
}

@ -1,6 +1,12 @@
<div class="table-page-wrapper">
<div class="table-control">
<button mat-raised-button color="primary" class="table-control-button" disabled i18n>
<button
mat-raised-button
color="primary"
class="table-control-button"
disabled
i18n
>
Alle ausgewählten Fahrräder bearbeiten
</button>
<button
@ -35,7 +41,6 @@
></mat-paginator>
</div>
<div class="table-container">
<table
mat-table
class="mat-elevation-z8"
@ -68,7 +73,6 @@
</td>
</ng-container>
<!-- Other Columns -->
<ng-container
*ngFor="let column of columnInfo"
@ -81,9 +85,17 @@
</th>
<td mat-cell *matCellDef="let element">
<app-cell
*ngIf="column.type === 'Boolean' || (element.newObject || !column.readonly && element.isLockedByMe); else stringValue"
[editable]="(element.newObject && column.acceptedForCreation) || !column.readonly && element.isLockedByMe"
[required]="(element.newObject && column.requiredForCreation)"
*ngIf="
column.type === 'Boolean' ||
element.newObject ||
(!column.readonly && element.isLockedByMe);
else stringValue
"
[editable]="
(element.newObject && column.acceptedForCreation) ||
(!column.readonly && element.isLockedByMe)
"
[required]="element.newObject && column.requiredForCreation"
(validityChange)="validityChange(element, column.name, $event)"
[(value)]="element[column.name]"
[inputType]="column.type"
@ -110,14 +122,21 @@
</button>
<button
mat-icon-button
[matMenuTriggerFor]="menu"
*ngIf="
!element.isLockedByMe &&
!isLoading(element.id) &&
!element.isLocked
"
>
<mat-icon>delete</mat-icon>
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="openDeleteConfirmationDialog(element)"><mat-icon>delete</mat-icon>Löschen</button>
<button mat-menu-item>
<mat-icon>content_copy</mat-icon>Duplizieren
</button>
</mat-menu>
<mat-spinner
[diameter]="32"
@ -146,7 +165,13 @@
>locked</mat-icon
>
</div>
<div class="button-wrapper" *ngIf="element.newObject" [matTooltip]="'Nicht ausgefüllte Felder: '+countUnvalidFields(element)">
<div
class="button-wrapper"
*ngIf="element.newObject"
[matTooltip]="
'Nicht ausgefüllte Felder: ' + countUnvalidFields(element)
"
>
<button
mat-icon-button
[disabled]="countUnvalidFields(element) > 0"
@ -164,13 +189,16 @@
</div>
</td>
</ng-container>
<!-- Table Definition -->
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<mat-card *ngIf="!isLoaded" style="display: flex; justify-content: center; align-items: center">
<mat-card
*ngIf="!isLoaded"
style="display: flex; justify-content: center; align-items: center"
>
<mat-spinner [diameter]="32"></mat-spinner>
</mat-card>
</div>

@ -1,5 +1,5 @@
import { SelectionModel } from '@angular/cdk/collections';
import { Component, ViewChild } from '@angular/core';
import { Component, Inject, ViewChild } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { BikesService, CargoBikeResult } from 'src/app/services/bikes.service';
import { flatten } from 'src/app/helperFunctions/flattenObject';
@ -11,6 +11,11 @@ import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { BehaviorSubject } from 'rxjs';
import {
MatDialog,
MatDialogRef,
MAT_DIALOG_DATA,
} from '@angular/material/dialog';
@Component({
selector: 'app-bikes',
@ -128,12 +133,13 @@ export class BikesComponent {
relockingInterval = null;
relockingDuration = 1000 * 60 * 1;
filterValue: string = "";
filterValue: string = '';
isLoaded = false;
constructor(
private bikesService: BikesService,
private schemaService: SchemaService
private schemaService: SchemaService,
public dialog: MatDialog
) {}
ngAfterViewInit() {
@ -143,9 +149,9 @@ export class BikesComponent {
if (typeof item[columnName] === 'string') {
return item[columnName].toLocaleLowerCase();
}
return item[columnName];
}
};
this.data.sort = this.sort;
this.columnInfo.forEach((column) =>
@ -177,7 +183,6 @@ export class BikesComponent {
});
this.bikesService.loadBikes();
this.relockingInterval = setInterval(() => {
for (const row of this.data.data) {
if (row.isLockedByMe) {
@ -265,19 +270,22 @@ export class BikesComponent {
this.paginator.firstPage();
this.resetFilter();
this.resetSorting();
this.data.data = [{ newObject: true, id: this.getNewId() }, ...this.data.data];
this.data.data = [
{ newObject: true, id: this.getNewId() },
...this.data.data,
];
}
getNewId(): string {
let id = -1;
while(this.getRowById(id.toString())) {
while (this.getRowById(id.toString())) {
id--;
}
return id.toString();
}
deleteNewObject(row: any) {
this.data.data = this.data.data.filter(element => row.id !== element.id);
this.data.data = this.data.data.filter((element) => row.id !== element.id);
}
create(row: any) {
@ -304,6 +312,22 @@ export class BikesComponent {
this.bikesService.unlockBike({ id: row.id });
}
delete(row: any) {
this.bikesService.deleteBike({ id: row.id });
}
openDeleteConfirmationDialog(row: any) {
const dialogRef = this.dialog.open(DeleteConfirmationDialog, {
width: '250px',
});
dialogRef.afterClosed().subscribe((result) => {
if (result === true) {
this.delete(row);
}
});
}
getRowById(id: string) {
return this.data.data.find((row) => row.id === id);
}
@ -335,11 +359,26 @@ export class BikesComponent {
}
resetFilter() {
this.filterValue = "";
this.filterValue = '';
this.applyFilter();
}
resetSorting() {
this.sort.sort({id: null, start: 'asc', disableClear: false });
this.sort.sort({ id: null, start: 'asc', disableClear: false });
}
}
@Component({
selector: 'delete-confirmation-dialog',
templateUrl: 'delete-confirmation-dialog.html',
})
export class DeleteConfirmationDialog {
constructor(public dialogRef: MatDialogRef<DeleteConfirmationDialog>) {}
onConfirmClick(): void {
this.dialogRef.close(true);
}
onNoClick(): void {
this.dialogRef.close(false);
}
}

@ -0,0 +1,7 @@
<div mat-dialog-content>
<p i18n>Soll das Element wirklich gelöscht werden?</p>
</div>
<div mat-dialog-actions>
<button mat-button (click)="onNoClick()" i18n>Nein</button>
<button mat-button (click)="onConfirmClick()" color="warn">Ja, löschen</button>
</div>

@ -15,6 +15,8 @@ import {
UnlockCargoBikeMutationVariables,
CreateCargoBikeGQL,
CreateCargoBikeMutationVariables,
DeleteCargoBikeGQL,
DeleteCargoBikeMutationVariables,
} from 'src/generated/graphql';
import { DeepExtractTypeSkipArrays } from 'ts-deep-extract-types';
@ -32,13 +34,13 @@ export class BikesService {
groupEnum: BehaviorSubject<string[]> = new BehaviorSubject<string[]>([]);
constructor(
private schemaService: SchemaService,
private getCargoBikesGQL: GetCargoBikesGQL,
private getCargoBikeByIdGQL: GetCargoBikeByIdGQL,
private updateCargoBikeGQL: UpdateCargoBikeGQL,
private lockCargoBikeGQL: LockCargoBikeGQL,
private unlockCargoBikeGQL: UnlockCargoBikeGQL,
private createCargoBikeGQL: CreateCargoBikeGQL,
private deleteCargoBikeGQL: DeleteCargoBikeGQL,
) {}
addLoadingRowId(id: string) {
@ -55,12 +57,6 @@ export class BikesService {
loadBikes() {
this.getCargoBikesGQL.fetch().subscribe((result) => {
// comment in for performance testing
/*for (let i = 1; i <= 500; i++) {
const newBike = deepCopy(result.data.cargoBikes[0]);
newBike.id = (i + 100).toString();
result.data.cargoBikes.push(newBike);
}*/
this.bikes.next(result.data.cargoBikes);
});
@ -146,6 +142,20 @@ export class BikesService {
});
}
deleteBike(variables: DeleteCargoBikeMutationVariables) {
this.addLoadingRowId(variables.id);
this.deleteCargoBikeGQL
.mutate(variables)
.subscribe((result) => {
if(result.data.deleteCargoBike) {
this.bikes.next([...this.bikes.value].filter(bike => bike.id !== variables.id));
}
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
}
relockBike(variables: LockCargoBikeMutationVariables) {
this.lockCargoBikeGQL.mutate(variables).subscribe();
}

@ -1,5 +1,6 @@
{
"__schema": {
"description": null,
"queryType": {
"name": "Query"
},

@ -1764,6 +1764,16 @@ export type UnlockCargoBikeMutation = (
) }
);
export type DeleteCargoBikeMutationVariables = Exact<{
id: Scalars['ID'];
}>;
export type DeleteCargoBikeMutation = (
{ __typename?: 'Mutation' }
& Pick<Mutation, 'deleteCargoBike'>
);
export type GetCargoBikesQueryVariables = Exact<{ [key: string]: never; }>;
@ -2078,6 +2088,22 @@ export const UnlockCargoBikeDocument = gql`
export class UnlockCargoBikeGQL extends Apollo.Mutation<UnlockCargoBikeMutation, UnlockCargoBikeMutationVariables> {
document = UnlockCargoBikeDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const DeleteCargoBikeDocument = gql`
mutation DeleteCargoBike($id: ID!) {
deleteCargoBike(id: $id)
}
`;
@Injectable({
providedIn: 'root'
})
export class DeleteCargoBikeGQL extends Apollo.Mutation<DeleteCargoBikeMutation, DeleteCargoBikeMutationVariables> {
document = DeleteCargoBikeDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}

Loading…
Cancel
Save