@@ -23,11 +23,13 @@
|
|
23 |
[src]="book.thumbnailUrl"
|
24 |
alt="Cover">
|
25 |
<a class="button arrow-left" routerLink="..">Back to list</a>
|
26 |
-
<
|
27 |
-
Remove book
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
33 |
</div>
|
23 |
[src]="book.thumbnailUrl"
|
24 |
alt="Cover">
|
25 |
<a class="button arrow-left" routerLink="..">Back to list</a>
|
26 |
+
<ng-container *bmLoggedinOnly>
|
27 |
+
<button class="red" bmConfirm="Remove book?" (confirm)="removeBook(book.isbn)">
|
28 |
+
Remove book
|
29 |
+
</button>
|
30 |
+
<a class="button"
|
31 |
+
[routerLink]="['/admin/edit', book.isbn]">
|
32 |
+
Edit book
|
33 |
+
</a>
|
34 |
+
</ng-container>
|
35 |
</div>
|
@@ -24,10 +24,8 @@ export class BookDetailsComponent {
|
|
24 |
}
|
25 |
|
26 |
removeBook(isbn: string) {
|
27 |
-
|
28 |
-
this.
|
29 |
-
|
30 |
-
});
|
31 |
-
}
|
32 |
}
|
33 |
}
|
24 |
}
|
25 |
|
26 |
removeBook(isbn: string) {
|
27 |
+
this.service.remove(isbn).subscribe(() => {
|
28 |
+
this.router.navigateByUrl('/books');
|
29 |
+
});
|
|
|
|
|
30 |
}
|
31 |
}
|
@@ -6,13 +6,17 @@ import { BookListComponent } from './book-list/book-list.component';
|
|
6 |
import { BookListItemComponent } from './book-list-item/book-list-item.component';
|
7 |
import { BookDetailsComponent } from './book-details/book-details.component';
|
8 |
import { IsbnPipe } from './shared/isbn.pipe';
|
|
|
|
|
9 |
|
10 |
@NgModule({
|
11 |
declarations: [
|
12 |
BookListComponent,
|
13 |
BookListItemComponent,
|
14 |
BookDetailsComponent,
|
15 |
-
IsbnPipe
|
|
|
|
|
16 |
],
|
17 |
imports: [
|
18 |
CommonModule,
|
6 |
import { BookListItemComponent } from './book-list-item/book-list-item.component';
|
7 |
import { BookDetailsComponent } from './book-details/book-details.component';
|
8 |
import { IsbnPipe } from './shared/isbn.pipe';
|
9 |
+
import { ConfirmDirective } from './shared/confirm.directive';
|
10 |
+
import { LoggedinOnlyDirective } from './shared/loggedin-only.directive';
|
11 |
|
12 |
@NgModule({
|
13 |
declarations: [
|
14 |
BookListComponent,
|
15 |
BookListItemComponent,
|
16 |
BookDetailsComponent,
|
17 |
+
IsbnPipe,
|
18 |
+
ConfirmDirective,
|
19 |
+
LoggedinOnlyDirective
|
20 |
],
|
21 |
imports: [
|
22 |
CommonModule,
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Directive, EventEmitter, HostListener, Input, Output } from '@angular/core';
|
2 |
+
|
3 |
+
@Directive({
|
4 |
+
selector: '[bmConfirm]',
|
5 |
+
standalone: false
|
6 |
+
})
|
7 |
+
export class ConfirmDirective {
|
8 |
+
@Input('bmConfirm') confirmText?: string;
|
9 |
+
@Output() confirm = new EventEmitter<void>();
|
10 |
+
|
11 |
+
@HostListener('click') onClick() {
|
12 |
+
if (window.confirm(this.confirmText)) {
|
13 |
+
this.confirm.emit();
|
14 |
+
}
|
15 |
+
}
|
16 |
+
}
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Directive, OnDestroy, TemplateRef, ViewContainerRef } from '@angular/core';
|
2 |
+
import { Subject, takeUntil } from 'rxjs';
|
3 |
+
|
4 |
+
import { AuthService } from '../../shared/auth.service';
|
5 |
+
|
6 |
+
@Directive({
|
7 |
+
selector: '[bmLoggedinOnly]',
|
8 |
+
standalone: false
|
9 |
+
})
|
10 |
+
export class LoggedinOnlyDirective implements OnDestroy {
|
11 |
+
private destroy$ = new Subject<void>();
|
12 |
+
|
13 |
+
constructor(
|
14 |
+
private template: TemplateRef<unknown>,
|
15 |
+
private viewContainer: ViewContainerRef,
|
16 |
+
private authService: AuthService
|
17 |
+
) {
|
18 |
+
this.authService.isAuthenticated$.pipe(
|
19 |
+
takeUntil(this.destroy$)
|
20 |
+
).subscribe(isAuthenticated => {
|
21 |
+
if (isAuthenticated) {
|
22 |
+
this.viewContainer.createEmbeddedView(this.template);
|
23 |
+
} else {
|
24 |
+
this.viewContainer.clear();
|
25 |
+
}
|
26 |
+
});
|
27 |
+
}
|
28 |
+
|
29 |
+
ngOnDestroy(): void {
|
30 |
+
this.destroy$.next();
|
31 |
+
}
|
32 |
+
}
|