Skip to content

Commit

Permalink
error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
maxime-urbanski committed Jun 25, 2024
1 parent 3469ad5 commit d6002bf
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 115 deletions.
8 changes: 8 additions & 0 deletions src/generators/AngularGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export default class extends BaseGenerator {
"app/components/common/svg/menu/menu.component.ts",
"app/components/common/back-to-list/back-to-list.component.html",
"app/components/common/back-to-list/back-to-list.component.ts",
"app/components/common/alert/alert.component.html",
"app/components/common/alert/alert.component.ts",

// COMPONENTS
"app/components/foo/create/create.component.html",
Expand Down Expand Up @@ -67,6 +69,9 @@ export default class extends BaseGenerator {

handlebars.registerHelper("compare", hbhComparison.compare);
handlebars.registerHelper("lowercase", hbhString.lowercase);
handlebars.registerHelper("get_length", function (obj) {
return obj.length;
});
}

help(resource) {
Expand Down Expand Up @@ -124,6 +129,7 @@ export default class extends BaseGenerator {
`${dir}/app/components/${lc}/list`,
`${dir}/app/components/${lc}/show`,
`${dir}/app/components/${lc}/table`,
`${dir}/app/components/common/alert`,
`${dir}/app/components/common/back-to-list`,
`${dir}/app/components/common/delete`,
`${dir}/app/components/common/header`,
Expand Down Expand Up @@ -158,6 +164,8 @@ export default class extends BaseGenerator {
"app/components/common/sidebar/sidebar.component.ts",
"app/components/common/back-to-list/back-to-list.component.html",
"app/components/common/back-to-list/back-to-list.component.ts",
"app/components/common/alert/alert.component.html",
"app/components/common/alert/alert.component.ts",
"app/interface/api.ts",
"app/service/api.service.ts",
"app/app.component.html",
Expand Down
10 changes: 10 additions & 0 deletions templates/angular/app/components/common/alert/alert.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="rounded py-4 px-4 text-sm mt-2"
[class]="type === 'loading' ? 'bg-blue-100 text-blue-700' : 'bg-red-100 text-red-700'">
@if (type === 'loading') {
Loading ...
}
@if (type === 'error') {
<h3 class="text-lg">\{{ error()?.['name'] }} <span class="text-sm">\{{ error()?.['status'] }}</span></h3>
<p>\{{ error()?.['message'] }}</p>
}
</div>
13 changes: 13 additions & 0 deletions templates/angular/app/components/common/alert/alert.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {Component, Input, WritableSignal} from '@angular/core';
import {SubmissionErrors} from "@interface/api";

@Component({
selector: 'app-alert',
standalone: true,
imports: [],
templateUrl: './alert.component.html'
})
export class AlertComponent {
@Input() type!: 'loading' | 'error';
@Input() error!: WritableSignal<SubmissionErrors | null>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
<app-back-to-list url="/{{lc}}s" />
</div>
@if (isLoading()) {
<div class="bg-blue-100 rounded py-4 px-4 text-blue-700 text-sm">Loading ...</div>
} @else {
<h1 class="text-3xl my-4">Create</h1>
<app-form-{{lc}} [item]="item()" (submit)="onSubmit($event)"/>
<app-alert type="loading"/>
}
@if (error()) {
<app-alert type="error" [error]="error"/>
}
<h1 class="text-3xl my-4">Create {{title}}</h1>
<app-form-{{lc}} [item]="item()" (submit)="onSubmit($event)"/>
</div>
17 changes: 10 additions & 7 deletions templates/angular/app/components/foo/create/create.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import {Location} from "@angular/common";
import {Component, inject, signal, WritableSignal} from '@angular/core';
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {RouterLink} from "@angular/router";
import {AlertComponent} from "@components/common/alert/alert.component"
import {BackToListComponent} from "@components/common/back-to-list/back-to-list.component";
import {DeleteComponent} from "@components/common/delete/delete.component";
import {FormComponent} from "@components/{{lc}}/form/form.component";
import {ApiItem} from "@interface/api";
import {ApiItem, SubmissionErrors} from "@interface/api";
import {ApiService} from "@service/api.service";

@Component({
selector: 'app-create-{{lc}}',
standalone: true,
imports: [
AlertComponent,
BackToListComponent,
DeleteComponent,
RouterLink,
Expand All @@ -26,16 +28,17 @@ export class CreateComponent {
private location: Location = inject(Location)
public item: WritableSignal<ApiItem> = signal({} as ApiItem)
public isLoading: WritableSignal<boolean> = signal(false)
public error: WritableSignal<SubmissionErrors | null> = signal(null)

onSubmit(data: any) {
return this.apiService
.add('/{{lc}}',
this.item()
).subscribe(
(item) => {
.add("/books", this.item())
.subscribe({
next: () => {
this.isLoading.set(true)
this.location.back()
}
)
},
error: (err: SubmissionErrors) => this.error.set(err)
})
}
}
24 changes: 14 additions & 10 deletions templates/angular/app/components/foo/edit/edit.component.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
<div class="px-4 mt-4">
<div class="flex items-center justify-end">
<app-back-to-list url="/{{lc}}s" />
<app-back-to-list url="/{{lc}}s"/>
</div>
@if (isLoading()) {
<div class="bg-blue-100 rounded py-4 px-4 text-blue-700 text-sm">Loading ...</div>
} @else if (error()) {
<div class="bg-red-100 rounded py-4 px-4 text-blue-700 text-sm">Error ...</div>
} @else {
<h1 class="text-3xl my-4">Edit \{{ item()['name'] }} <span class="text-xl">\{{ item()["@id"] }} </span></h1>
<app-form-{{lc}} [item]="item()"
(submit)="onSubmit($event)"
(delete)="delete()"
/>
<app-alert type="loading"/>
}
@if (error()) {
<app-alert type="error" [error]="error"/>
}
<h1 class="text-3xl my-4">
Edit \{{ item()['name'] }}
<span class="text-xl">\{{ item()["@id"] }}</span>
</h1>
<app-form-{{lc}}
[item]="item()"
(submit)="onSubmit($event)"
(delete)="delete()"
/>
</div>
66 changes: 42 additions & 24 deletions templates/angular/app/components/foo/edit/edit.component.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import {CommonModule, Location} from "@angular/common";
import {CommonModule, Location} from "@angular/common"
import {
Component,
DestroyRef,
inject,
OnInit,
signal,
WritableSignal
} from '@angular/core';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {Router, RouterLink} from "@angular/router";
import {BackToListComponent} from "@components/common/back-to-list/back-to-list.component";
import {DeleteComponent} from "@components/common/delete/delete.component";
import {FormComponent} from "@components/{{lc}}/form/form.component";
import {ApiItem} from "@interface/api";
import {ApiService} from "@service/api.service";
} from '@angular/core'
import {takeUntilDestroyed} from "@angular/core/rxjs-interop"
import {FormsModule, ReactiveFormsModule} from "@angular/forms"
import {Router, RouterLink} from "@angular/router"
import {AlertComponent} from "@components/common/alert/alert.component"
import {BackToListComponent} from "@components/common/back-to-list/back-to-list.component"
import {DeleteComponent} from "@components/common/delete/delete.component"
import {FormComponent} from "@components/{{lc}}/form/form.component"
import {ApiItem, SubmissionErrors} from "@interface/api"
import {ApiService} from "@service/api.service"

@Component({
selector: 'app-edit-{{lc}}',
standalone: true,
imports: [
AlertComponent,
BackToListComponent,
CommonModule,
DeleteComponent,
Expand All @@ -33,34 +35,50 @@ import {ApiService} from "@service/api.service";
export class EditComponent implements OnInit {
public item: WritableSignal<ApiItem> = signal({} as ApiItem);
public isLoading: WritableSignal<Boolean> = signal(false)
public error: WritableSignal<string> = signal('')

public error: WritableSignal<SubmissionErrors | null> = signal(null)
private destroy: DestroyRef = inject(DestroyRef)
private apiService: ApiService = inject(ApiService)
private router: Router = inject(Router)
private location: Location = inject(Location)


ngOnInit() {
const uri = this.router.url.split('/edit')[0]
this.isLoading.set(true)
this.apiService.fetchData(uri)
this.fetchData()
}

public fetchData() {
const uri = this.router.url.split("/edit")[0]
this.toggleIsLoading()
this.apiService
.fetchData(uri)
.pipe(takeUntilDestroyed(this.destroy))
.subscribe(value => {
this.item.set(value)
this.isLoading.set(false)
.subscribe({
next: (value) => {
this.item.set(value)
},
error: err => this.error.set(err)
})
this.toggleIsLoading()
}

onSubmit(data: any) {
public onSubmit(data: any) {
return this.apiService
.put(this.item()["@id"]!, this.item())
.subscribe(() => this.location.back());
.subscribe({
next: () => this.location.back(),
error: err => this.error.set(err)
})
}

delete() {
public delete() {
return this.apiService
.delete(this.item()['@id']!)
.subscribe(() => this.location.back())
.delete(this.item()["@id"]!)
.subscribe({
next: () => this.location.back(),
error: err => this.error.set(err)
})
}

private toggleIsLoading() {
return this.isLoading.update((value) => !value);
}
}
10 changes: 6 additions & 4 deletions templates/angular/app/components/foo/list/list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@ <h1 class="text-3xl mb-2">{{title}} List</h1>
</div>
</div>
@if (isLoading()) {
<div class="bg-blue-100 rounded py-4 px-4 text-blue-700 text-sm">Loading ...</div>
} @else {
<app-alert type="loading"/>
}
@if (error()) {
<app-alert type="error" [error]="error"/>
}
<app-table-{{lc}} [items]="items"
[bulk]="bulk()"
(addToBulkList)="addToBulk($event)"
(selectedAll)="selectedAll()"
/>
@if (pagination()) {
<app-pagination
[pagination]="pagination!"
[pagination]="pagination"
(handleChangePage)="changePage($event)"
/>
}
}
</div>
57 changes: 31 additions & 26 deletions templates/angular/app/components/foo/list/list.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import {
AsyncPipe,
Location,
NgFor,
NgIf
} from "@angular/common";
Expand All @@ -12,11 +10,12 @@ import {
signal,
WritableSignal
} from '@angular/core';
import {Router, RouterLink} from "@angular/router";
import {RouterLink} from "@angular/router";
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import {AlertComponent} from "@components/common/alert/alert.component";
import {DeleteComponent} from "@components/common/delete/delete.component";
import {TableComponent} from "@components/{{lc}}/table/table.component";
import {ApiItem, Pagination} from "@interface/api";
import {ApiItem, Pagination, SubmissionErrors} from "@interface/api";
import {ApiService} from "@service/api.service";
import {PaginationComponent} from "@components/common/pagination/pagination.component";

Expand All @@ -29,15 +28,16 @@ import {PaginationComponent} from "@components/common/pagination/pagination.comp
TableComponent,
NgIf,
DeleteComponent,
PaginationComponent
PaginationComponent,
AlertComponent
],
templateUrl: './list.component.html',
})
export class ListComponent implements OnInit {
public isLoading: WritableSignal<Boolean> = signal(false)
public pagination: WritableSignal<Pagination> = signal({} as Pagination)
public pagination: WritableSignal<Pagination | undefined> = signal(undefined)
public items: WritableSignal<ApiItem[]> = signal([])
public error: WritableSignal<String> = signal('')
public error: WritableSignal<SubmissionErrors | null> = signal(null)
public bulk: WritableSignal<Array<string>> = signal([])
public uri: WritableSignal<string> = signal('/{{lc}}s')
private apiService: ApiService = inject(ApiService)
Expand All @@ -48,43 +48,48 @@ export class ListComponent implements OnInit {
}

public fetchData() {
this.toggleIsLoading()
this.toggleIsLoading();
this.apiService
.fetchDataList(this.uri())
// Unsubscribe event for more performance
.pipe(takeUntilDestroyed(this.destroy))
.subscribe((items) => {
this.toggleIsLoading();
if (items['hydra:view']) this.pagination.set(items['hydra:view'])
this.items.set(items["hydra:member"])
.subscribe({
next: items => {
if (items["hydra:view"]) this.pagination.set(items["hydra:view"]);
this.items.set(items["hydra:member"]);
},
error: (err: SubmissionErrors) => this.error.set(err)
})
this.toggleIsLoading();
}

public addToBulk(id: string) {
if (this.isInBulkList(id)) {
const bulkFilter =
this.bulk()
.filter(element => element !== id)
return this.bulk.set(bulkFilter)
const bulkFilter = this.bulk().filter((element) => element !== id);
return this.bulk.set(bulkFilter);
}

this.bulk.update(uri => [...uri, id])
this.bulk.update((uri) => [...uri, id]);
}

public selectedAll() {
if (!this.bulk().length) {
this.items().forEach(item => {
this.bulk().push(<string>item["@id"])
})
this.items().forEach((item) => {
this.bulk().push(<string>item["@id"]);
});
} else {
this.bulk.set([])
this.bulk.set([]);
}
}

public delete() {
Promise.all(this.bulk()).then(items =>
items.forEach(uri =>
this.apiService.delete(uri).subscribe(() => {
window.location.reload()
Promise.all(this.bulk()).then((items) =>
items.forEach((uri) =>
this.apiService
.delete(uri).subscribe({
next: () => {
window.location.reload();
},
error: (err: SubmissionErrors) => this.error.set(err)
})
)
)
Expand Down
Loading

0 comments on commit d6002bf

Please sign in to comment.