|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { NgModule } from '@angular/core';
|
| 2 |
+
import { RouterModule, Routes } from '@angular/router';
|
| 3 |
+
import { BookCreateComponent } from './book-create/book-create.component';
|
| 4 |
+
|
| 5 |
+
const routes: Routes = [
|
| 6 |
+
{
|
| 7 |
+
path: 'admin',
|
| 8 |
+
redirectTo: 'admin/create'
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
path: 'admin/create',
|
| 12 |
+
component: BookCreateComponent,
|
| 13 |
+
}
|
| 14 |
+
];
|
| 15 |
+
|
| 16 |
+
@NgModule({
|
| 17 |
+
imports: [RouterModule.forChild(routes)],
|
| 18 |
+
exports: [RouterModule]
|
| 19 |
+
})
|
| 20 |
+
export class AdminRoutingModule { }
|
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { NgModule } from '@angular/core';
|
| 2 |
+
import { CommonModule } from '@angular/common';
|
| 3 |
+
import { FormsModule } from '@angular/forms';
|
| 4 |
+
|
| 5 |
+
import { AdminRoutingModule } from './admin-routing.module';
|
| 6 |
+
import { BookFormComponent } from './book-form/book-form.component';
|
| 7 |
+
import { BookCreateComponent } from './book-create/book-create.component';
|
| 8 |
+
|
| 9 |
+
@NgModule({
|
| 10 |
+
declarations: [
|
| 11 |
+
BookFormComponent,
|
| 12 |
+
BookCreateComponent
|
| 13 |
+
],
|
| 14 |
+
imports: [
|
| 15 |
+
CommonModule,
|
| 16 |
+
AdminRoutingModule,
|
| 17 |
+
FormsModule
|
| 18 |
+
],
|
| 19 |
+
})
|
| 20 |
+
export class AdminModule { }
|
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<h1>Create Book</h1>
|
| 2 |
+
|
| 3 |
+
<bm-book-form (submitBook)="create($event)"></bm-book-form>
|
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Component } from '@angular/core';
|
| 2 |
+
import { Router } from '@angular/router';
|
| 3 |
+
|
| 4 |
+
import { BookStoreService } from '../../shared/book-store.service';
|
| 5 |
+
import { Book } from '../../shared/book';
|
| 6 |
+
|
| 7 |
+
@Component({
|
| 8 |
+
selector: 'bm-book-create',
|
| 9 |
+
templateUrl: './book-create.component.html',
|
| 10 |
+
standalone: false,
|
| 11 |
+
styleUrl: './book-create.component.css'
|
| 12 |
+
})
|
| 13 |
+
export class BookCreateComponent {
|
| 14 |
+
|
| 15 |
+
constructor(
|
| 16 |
+
private service: BookStoreService,
|
| 17 |
+
private router: Router
|
| 18 |
+
) { }
|
| 19 |
+
|
| 20 |
+
create(book: Book) {
|
| 21 |
+
this.service.create(book).subscribe(createdBook => {
|
| 22 |
+
this.router.navigate(['/books', createdBook.isbn]);
|
| 23 |
+
});
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<form (ngSubmit)="submitForm()" #form="ngForm">
|
| 2 |
+
<label for="title">Title</label>
|
| 3 |
+
<input
|
| 4 |
+
name="title"
|
| 5 |
+
id="title"
|
| 6 |
+
[(ngModel)]="book.title"
|
| 7 |
+
required>
|
| 8 |
+
|
| 9 |
+
<label for="isbn">ISBN</label>
|
| 10 |
+
<input
|
| 11 |
+
name="isbn"
|
| 12 |
+
id="isbn"
|
| 13 |
+
[(ngModel)]="book.isbn"
|
| 14 |
+
required
|
| 15 |
+
minlength="10"
|
| 16 |
+
maxlength="13">
|
| 17 |
+
|
| 18 |
+
<label for="author">Author</label>
|
| 19 |
+
<input
|
| 20 |
+
name="author"
|
| 21 |
+
id="author"
|
| 22 |
+
[(ngModel)]="book.authors[0]"
|
| 23 |
+
required>
|
| 24 |
+
|
| 25 |
+
<button type="submit" [disabled]="form.invalid">
|
| 26 |
+
Save
|
| 27 |
+
</button>
|
| 28 |
+
</form>
|
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Component, Output, EventEmitter } from '@angular/core';
|
| 2 |
+
|
| 3 |
+
import { Book } from '../../shared/book';
|
| 4 |
+
|
| 5 |
+
@Component({
|
| 6 |
+
selector: 'bm-book-form',
|
| 7 |
+
templateUrl: './book-form.component.html',
|
| 8 |
+
standalone: false,
|
| 9 |
+
styleUrl: './book-form.component.css'
|
| 10 |
+
})
|
| 11 |
+
export class BookFormComponent {
|
| 12 |
+
book: Book = {
|
| 13 |
+
isbn: '',
|
| 14 |
+
title: '',
|
| 15 |
+
authors: ['']
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
@Output() submitBook = new EventEmitter<Book>();
|
| 19 |
+
|
| 20 |
+
submitForm() {
|
| 21 |
+
this.submitBook.emit(this.book);
|
| 22 |
+
}
|
| 23 |
+
}
|
|
@@ -1,6 +1,7 @@
|
|
| 1 |
<nav>
|
| 2 |
<a routerLink="/home" routerLinkActive="active" ariaCurrentWhenActive="page">Home</a>
|
| 3 |
<a routerLink="/books" routerLinkActive="active" ariaCurrentWhenActive="page">Books</a>
|
|
|
|
| 4 |
<div class="actions">
|
| 5 |
<button class="green"
|
| 6 |
(click)="auth.login()"
|
| 1 |
<nav>
|
| 2 |
<a routerLink="/home" routerLinkActive="active" ariaCurrentWhenActive="page">Home</a>
|
| 3 |
<a routerLink="/books" routerLinkActive="active" ariaCurrentWhenActive="page">Books</a>
|
| 4 |
+
<a routerLink="/admin" routerLinkActive="active" ariaCurrentWhenActive="page">Administration</a>
|
| 5 |
<div class="actions">
|
| 6 |
<button class="green"
|
| 7 |
(click)="auth.login()"
|
|
@@ -8,6 +8,7 @@ import { BooksModule } from './books/books.module';
|
|
| 8 |
import { HomeComponent } from './home/home.component';
|
| 9 |
import { SearchComponent } from './search/search.component';
|
| 10 |
import { AuthInterceptor } from './shared/auth.interceptor';
|
|
|
|
| 11 |
|
| 12 |
@NgModule({
|
| 13 |
declarations: [
|
|
@@ -18,7 +19,8 @@ import { AuthInterceptor } from './shared/auth.interceptor';
|
|
| 18 |
imports: [
|
| 19 |
BrowserModule,
|
| 20 |
AppRoutingModule,
|
| 21 |
-
BooksModule
|
|
|
|
| 22 |
],
|
| 23 |
providers: [
|
| 24 |
provideHttpClient(withInterceptorsFromDi()),
|
| 8 |
import { HomeComponent } from './home/home.component';
|
| 9 |
import { SearchComponent } from './search/search.component';
|
| 10 |
import { AuthInterceptor } from './shared/auth.interceptor';
|
| 11 |
+
import { AdminModule } from './admin/admin.module';
|
| 12 |
|
| 13 |
@NgModule({
|
| 14 |
declarations: [
|
| 19 |
imports: [
|
| 20 |
BrowserModule,
|
| 21 |
AppRoutingModule,
|
| 22 |
+
BooksModule,
|
| 23 |
+
AdminModule
|
| 24 |
],
|
| 25 |
providers: [
|
| 26 |
provideHttpClient(withInterceptorsFromDi()),
|
|
@@ -37,4 +37,8 @@ export class BookStoreService {
|
|
| 37 |
})
|
| 38 |
);
|
| 39 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
}
|
| 37 |
})
|
| 38 |
);
|
| 39 |
}
|
| 40 |
+
|
| 41 |
+
create(book: Book): Observable<Book> {
|
| 42 |
+
return this.http.post<Book>(`${this.apiUrl}/books`, book);
|
| 43 |
+
}
|
| 44 |
}
|