Skip to content

Commit 6db3745

Browse files
Delete CRUD
1 parent 5eaf815 commit 6db3745

File tree

14 files changed

+134
-69
lines changed

14 files changed

+134
-69
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<button
2+
(click)="delete()"
3+
class="px-6 py-2 bg-red-600 text-white text-xs rounded shadow-md hover:bg-red-700">
4+
Delete
5+
</button>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {Component, Input, Output} from '@angular/core';
2+
import {HeroService} from "../../../service/hero.service";
3+
import {Location} from "@angular/common";
4+
5+
@Component({
6+
selector: 'app-delete',
7+
standalone: true,
8+
imports: [],
9+
templateUrl: './delete.component.html',
10+
})
11+
export class DeleteComponent {
12+
@Input() id: string = '';
13+
14+
constructor(
15+
private heroService: HeroService,
16+
private location: Location
17+
) {
18+
}
19+
20+
delete() {
21+
console.log('delete component id',this.id)
22+
this.heroService.delete(this.id).subscribe(() => this.location.back())
23+
}
24+
}

src/app/components/common/table/table.component.html

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,51 @@
1010
</tr>
1111
</thead>
1212
<tbody>
13-
<tr *ngFor="let item of items?.items">
14-
<td>{{ item['id'] }}</td>
15-
<td>{{ item['name'] }}</td>
16-
<td class="w-8">
17-
<a [routerLink]="[item['id']]" class="text-cyan-500">
18-
Show
19-
<svg
20-
xmlns="http://www.w3.org/2000/svg"
21-
viewBox="0 0 24 24"
22-
fill="currentColor"
23-
class="w-6 h-6"
24-
>
25-
<path d="M12 15a3 3 0 100-6 3 3 0 000 6z"/>
26-
<path
27-
fill-rule="evenodd"
28-
d="M1.323 11.447C2.811 6.976 7.028 3.75 12.001 3.75c4.97 0 9.185 3.223 10.675 7.69.12.362.12.752 0 1.113-1.487 4.471-5.705 7.697-10.677 7.697-4.97 0-9.186-3.223-10.675-7.69a1.762 1.762 0 010-1.113zM17.25 12a5.25 5.25 0 11-10.5 0 5.25 5.25 0 0110.5 0z"
29-
clip-rule="evenodd"
30-
/>
31-
</svg>
32-
</a>
33-
</td>
34-
<td class="w-8">
35-
<a [routerLink]="['edit', item['id']]" class="text-cyan-500">
36-
Edit
37-
<svg
38-
xmlns="http://www.w3.org/2000/svg"
39-
viewBox="0 0 24 24"
40-
fill="currentColor"
41-
class="w-6 h-6"
42-
>
43-
<path
44-
d="M21.731 2.269a2.625 2.625 0 00-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 000-3.712zM19.513 8.199l-3.712-3.712-8.4 8.4a5.25 5.25 0 00-1.32 2.214l-.8 2.685a.75.75 0 00.933.933l2.685-.8a5.25 5.25 0 002.214-1.32l8.4-8.4z"/>
45-
<path
46-
d="M5.25 5.25a3 3 0 00-3 3v10.5a3 3 0 003 3h10.5a3 3 0 003-3V13.5a.75.75 0 00-1.5 0v5.25a1.5 1.5 0 01-1.5 1.5H5.25a1.5 1.5 0 01-1.5-1.5V8.25a1.5 1.5 0 011.5-1.5h5.25a.75.75 0 000-1.5H5.25z"/>
47-
</svg>
48-
</a>
49-
</td>
50-
</tr>
13+
@for (item of items?.items; track item) {
14+
<tr>
15+
<td>{{ item['id'] }}</td>
16+
<td>{{ item['name'] }}</td>
17+
<td class="w-8">
18+
<a [routerLink]="[item['@id']]" class="text-cyan-500">
19+
Show
20+
<svg
21+
xmlns="http://www.w3.org/2000/svg"
22+
viewBox="0 0 24 24"
23+
fill="currentColor"
24+
class="w-6 h-6"
25+
>
26+
<path d="M12 15a3 3 0 100-6 3 3 0 000 6z"/>
27+
<path
28+
fill-rule="evenodd"
29+
d="M1.323 11.447C2.811 6.976 7.028 3.75 12.001 3.75c4.97 0 9.185 3.223 10.675 7.69.12.362.12.752 0 1.113-1.487 4.471-5.705 7.697-10.677 7.697-4.97 0-9.186-3.223-10.675-7.69a1.762 1.762 0 010-1.113zM17.25 12a5.25 5.25 0 11-10.5 0 5.25 5.25 0 0110.5 0z"
30+
clip-rule="evenodd"
31+
/>
32+
</svg>
33+
</a>
34+
</td>
35+
<td class="w-8">
36+
<a [routerLink]="['edit', item['id']]" class="text-cyan-500">
37+
Edit
38+
<svg
39+
xmlns="http://www.w3.org/2000/svg"
40+
viewBox="0 0 24 24"
41+
fill="currentColor"
42+
class="w-6 h-6"
43+
>
44+
<path
45+
d="M21.731 2.269a2.625 2.625 0 00-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 000-3.712zM19.513 8.199l-3.712-3.712-8.4 8.4a5.25 5.25 0 00-1.32 2.214l-.8 2.685a.75.75 0 00.933.933l2.685-.8a5.25 5.25 0 002.214-1.32l8.4-8.4z"/>
46+
<path
47+
d="M5.25 5.25a3 3 0 00-3 3v10.5a3 3 0 003 3h10.5a3 3 0 003-3V13.5a.75.75 0 00-1.5 0v5.25a1.5 1.5 0 01-1.5 1.5H5.25a1.5 1.5 0 01-1.5-1.5V8.25a1.5 1.5 0 011.5-1.5h5.25a.75.75 0 000-1.5H5.25z"/>
48+
</svg>
49+
</a>
50+
</td>
51+
</tr>
52+
} @empty {
53+
<tr>
54+
<td colspan="2" class="text-center italic p-6">
55+
Pas de données.
56+
</td>
57+
</tr>
58+
}
5159
</tbody>
5260
</table>

src/app/components/common/table/table.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {List} from "../../../interface/list.model";
77
selector: 'app-table',
88
standalone: true,
99
imports: [
10-
NgForOf,
1110
RouterLink
1211
],
1312
templateUrl: './table.component.html',

src/app/components/foo/list/list.component.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ export class ListComponent implements OnInit {
2929

3030
ngOnInit() {
3131
this.heroService
32-
.getHeroes()
32+
.getHeroes('/heroes')
3333
.subscribe(
3434
(items) =>
35-
this.store.dispatch(HeroesActions.getHeroes({items: items['hydra:member']}))
35+
this.store.dispatch(HeroesActions.getHeroes({
36+
items: items['hydra:member'],
37+
isLoading: false
38+
}))
3639
)
3740
}
3841
}

src/app/components/foo/show/show.component.html

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,10 @@
88
</a>
99
<div>
1010
<a [routerLink]="['/heroes/edit', (item|async)?.id]"
11-
class="px-6 py-2 mr-2 bg-green-600 text-white text-xs rounded shadow-md hover:bg-green-700">
11+
class="px-6 py-2 mr-2 bg-green-600 text-white text-xs rounded shadow-md hover:bg-green-700">
1212
Edit
1313
</a>
14-
<button
15-
class="px-6 py-2 bg-red-600 text-white text-xs rounded shadow-md hover:bg-red-700">
16-
Delete
17-
</button>
14+
<app-delete [id]="(item|async)?.['@id']!"></app-delete>
1815
</div>
1916
</div>
2017

@@ -33,7 +30,7 @@ <h1 class="text-3xl my-4">Show {{ (item|async)?.["@id"] }}</h1>
3330
</tr>
3431
</thead>
3532
<tbody>
36-
<tr *ngIf="(item | async)"class="border-b">
33+
<tr *ngIf="(item | async)" class="border-b">
3734
<th
3835
class="text-sm font-medium px-6 py-4 text-left capitalize"
3936
scope="row"
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,40 @@
11
import {Component, OnInit} from '@angular/core';
2-
import {ActivatedRoute, RouterLink} from "@angular/router";
2+
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
33
import {CommonModule, NgIf} from "@angular/common";
44
import {Store} from "@ngrx/store";
55
import {HeroService} from "../../../service/hero.service";
66
import {Show} from "../../../interface/show.model";
77
import {selectorShowItem, selectorShowLoading} from "../../../store/selector/show.selectors";
88
import {HeroesActions} from "../../../store/action/heroes.actions";
9+
import {DeleteComponent} from "../../common/delete/delete.component";
910

1011
@Component({
1112
selector: 'app-show',
1213
standalone: true,
1314
imports: [
1415
CommonModule,
1516
RouterLink,
16-
NgIf
17+
NgIf,
18+
DeleteComponent
1719
],
1820
templateUrl: './show.component.html',
1921
})
2022
export class ShowComponent implements OnInit {
21-
isLoading = this.store.select(selectorShowLoading)
22-
item = this.store.select(selectorShowItem)
23+
public isLoading = this.store.select(selectorShowLoading)
24+
public item = this.store.select(selectorShowItem)
2325

2426
constructor(
2527
private store: Store<{ show: Show }>,
2628
private heroService: HeroService,
27-
private router: ActivatedRoute
29+
private router: Router
2830
) {
2931
}
3032

3133
ngOnInit() {
32-
const id = this.router.snapshot.paramMap.get('id')
34+
const id = this.router.url
3335
this.heroService
3436
.getHero(id)
3537
.subscribe((item) =>
36-
this.store.dispatch(HeroesActions.getHero({item})))
38+
this.store.dispatch(HeroesActions.getHero({item, isLoading: false})))
3739
}
3840
}

src/app/interface/api.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {Hero} from "./hero.model";
22

33
export interface Api {
4-
"@context": String,
5-
"@id": String,
6-
"@type": String,
4+
"@context": string,
5+
"@id": string,
6+
"@type": string,
77
}
88

99
export interface ApiList extends Api {
@@ -13,5 +13,5 @@ export interface ApiList extends Api {
1313

1414
export interface ApiShow extends Api {
1515
id: Number,
16-
name: String
16+
name: string
1717
}

src/app/interface/hero.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import {Api} from "./api";
22

33
export interface Hero extends Api {
44
id: Number,
5-
name: String
5+
name: string
66
}

src/app/interface/list.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import {Hero} from "./hero.model";
33
export interface List {
44
isLoading: Boolean | undefined | null,
55
items?: Hero[],
6-
error?: String,
6+
error?: string,
77
}

src/app/interface/show.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import {Hero} from "./hero.model";
33
export interface Show {
44
isLoading?: Boolean,
55
item?: Hero,
6-
error?: String,
6+
error?: string,
77
}

src/app/service/hero.service.ts

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import {HttpClient} from "@angular/common/http";
2-
import {Observable} from "rxjs";
1+
import {HttpClient, HttpErrorResponse} from "@angular/common/http";
2+
import {catchError, Observable, throwError} from "rxjs";
33
import {Injectable} from "@angular/core";
44
import {List} from "../interface/list.model";
55
import {ApiList, ApiShow} from "../interface/api";
@@ -20,15 +20,42 @@ export class HeroService {
2020
) {
2121
}
2222

23-
getHeroes(): Observable<ApiList> {
23+
getHeroes(id: string): Observable<ApiList> {
2424
this.store.dispatch(HeroesActions.getHeroes({isLoading: true}))
2525
return this.http
26-
.get<ApiList>(this.baseUrl + '/heroes')
26+
.get<ApiList>(this.baseUrl + id)
27+
.pipe(
28+
catchError(
29+
this.handleError
30+
)
31+
)
2732
}
2833

29-
getHero(id: string | null) {
34+
getHero(id: string): Observable<ApiShow> {
3035
this.store.dispatch(HeroesActions.getHero({isLoading: true}))
3136
return this.http
32-
.get<ApiShow>(this.baseUrl + `/heroes/${id}`)
37+
.get<ApiShow>(this.baseUrl + id)
38+
.pipe(
39+
catchError(this.handleError)
40+
)
41+
}
42+
43+
delete(id: string) {
44+
return this.http
45+
.delete(this.baseUrl + id)
46+
.pipe(
47+
catchError(this.handleError)
48+
)
49+
}
50+
51+
private handleError(error: HttpErrorResponse) {
52+
if (error.status === 0) {
53+
console.error('An error occurred:', error.error);
54+
} else {
55+
console.error(
56+
`Backend returned code ${error.status}, body was:`);
57+
}
58+
// Return an observable with a user-facing error message.
59+
return throwError(() => new Error(error.error));
3360
}
3461
}

src/app/store/action/heroes.actions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import {Hero} from "../../interface/hero.model";
44
export const HeroesActions = createActionGroup({
55
source: 'Heroes',
66
events: {
7-
'Get Heroes': props<{ items?: Array<Hero>, isLoading?: Boolean, error?: String }>(),
8-
'Get Hero': props<{ item?: Hero, isLoading?: Boolean, error?: String }>(),
7+
'Get Heroes': props<{ items?: Array<Hero>, isLoading?: Boolean, error?: string }>(),
8+
'Get Hero': props<{ item?: Hero, isLoading?: Boolean, error?: string }>(),
99
'Put Hero': props<{ hero: Hero }>(),
1010
'Delete Hero': props<{ id: Number }>(),
1111
}

src/app/store/reducer/delete.reducer.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)