SP_12062024_AuthorUserInterFace
This commit is contained in:
parent
bbb10b436a
commit
a179a764d7
@ -28,6 +28,7 @@ const routes: Routes = [
|
||||
{ path: 'books', loadChildren: () => import('./book/book.module').then(m => m.BookModule) },
|
||||
{ path: 'customer', loadChildren: () => import('./customer/customer.module').then(m => m.CustomerModule) },
|
||||
{ path: 'book-issue', loadChildren: () => import('./book-issue/book-issue.module').then(m => m.BookIssueModule) },
|
||||
{ path: 'authors', loadChildren: () => import('./author/author.module').then(m => m.AuthorModule) },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
11
angular/src/app/author/author-routing.module.ts
Normal file
11
angular/src/app/author/author-routing.module.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthorComponent } from './author.component';
|
||||
|
||||
const routes: Routes = [{ path: '', component: AuthorComponent }];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AuthorRoutingModule { }
|
99
angular/src/app/author/author.component.html
Normal file
99
angular/src/app/author/author.component.html
Normal file
@ -0,0 +1,99 @@
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col col-md-6">
|
||||
<h5 class="card-title">
|
||||
{{ '::Menu:Authors' | abpLocalization }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="text-end col col-md-6">
|
||||
<div class="text-lg-end pt-2">
|
||||
<button *abpPermission="'BookStore.Authors.Create'" id="create" class="btn btn-primary" type="button" (click)="createAuthor()">
|
||||
<i class="fa fa-plus me-1"></i>
|
||||
<span>{{ '::NewAuthor' | abpLocalization }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ngx-datatable [rows]="author.items" [count]="author.totalCount" [list]="list" default>
|
||||
<ngx-datatable-column
|
||||
[name]="'::Actions' | abpLocalization"
|
||||
[maxWidth]="150"
|
||||
[sortable]="false"
|
||||
>
|
||||
<ng-template let-row="row" ngx-datatable-cell-template>
|
||||
<div ngbDropdown container="body" class="d-inline-block">
|
||||
<button
|
||||
class="btn btn-primary btn-sm dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
ngbDropdownToggle
|
||||
>
|
||||
<i class="fa fa-cog me-1"></i>{{ '::Actions' | abpLocalization }}
|
||||
</button>
|
||||
<div ngbDropdownMenu>
|
||||
<button *abpPermission="'BookStore.Authors.Edit'" ngbDropdownItem (click)="editAuthor(row.id)">
|
||||
{{ '::Edit' | abpLocalization }}
|
||||
</button>
|
||||
<button *abpPermission="'BookStore.Authors.Delete'" ngbDropdownItem (click)="delete(row.id)">
|
||||
{{ '::Delete' | abpLocalization }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [name]="'::Name' | abpLocalization" prop="name"></ngx-datatable-column>
|
||||
<ngx-datatable-column [name]="'::BirthDate' | abpLocalization">
|
||||
<ng-template let-row="row" ngx-datatable-cell-template>
|
||||
{{ row.birthDate | date }}
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<abp-modal [(visible)]="isModalOpen">
|
||||
<ng-template #abpHeader>
|
||||
<h3>{{ (selectedAuthor.id ? '::Edit' : '::NewAuthor') | abpLocalization }}</h3>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #abpBody>
|
||||
<form [formGroup]="form" (ngSubmit)="save()">
|
||||
<div class="form-group">
|
||||
<label for="author-name">Name</label><span> * </span>
|
||||
<input type="text" id="author-name" class="form-control" formControlName="name" autofocus />
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<label>Birth date</label><span> * </span>
|
||||
<input
|
||||
#datepicker="ngbDatepicker"
|
||||
class="form-control"
|
||||
name="datepicker"
|
||||
formControlName="birthDate"
|
||||
ngbDatepicker
|
||||
(click)="datepicker.toggle()"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="short-bio">Short Bio</label><span> * </span>
|
||||
<input type="text" id="short-bio" class="form-control" formControlName="shortBio" />
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #abpFooter>
|
||||
<button type="button" class="btn btn-secondary" abpClose>
|
||||
{{ '::Close' | abpLocalization }}
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary" (click)="save()" [disabled]="form.invalid">
|
||||
<i class="fa fa-check mr-1"></i>
|
||||
{{ '::Save' | abpLocalization }}
|
||||
</button>
|
||||
</ng-template>
|
||||
</abp-modal>
|
||||
|
0
angular/src/app/author/author.component.scss
Normal file
0
angular/src/app/author/author.component.scss
Normal file
23
angular/src/app/author/author.component.spec.ts
Normal file
23
angular/src/app/author/author.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AuthorComponent } from './author.component';
|
||||
|
||||
describe('AuthorComponent', () => {
|
||||
let component: AuthorComponent;
|
||||
let fixture: ComponentFixture<AuthorComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [AuthorComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AuthorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
93
angular/src/app/author/author.component.ts
Normal file
93
angular/src/app/author/author.component.ts
Normal file
@ -0,0 +1,93 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ListService, PagedResultDto } from '@abp/ng.core';
|
||||
import { AuthorService, AuthorDto } from '@proxy/authors';
|
||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared';
|
||||
|
||||
@Component({
|
||||
selector: 'app-author',
|
||||
templateUrl: './author.component.html',
|
||||
styleUrls: ['./author.component.scss'],
|
||||
providers: [ListService, { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }],
|
||||
})
|
||||
export class AuthorComponent implements OnInit {
|
||||
author = { items: [], totalCount: 0 } as PagedResultDto<AuthorDto>;
|
||||
|
||||
isModalOpen = false;
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
selectedAuthor = {} as AuthorDto;
|
||||
|
||||
constructor(
|
||||
public readonly list: ListService,
|
||||
private authorService: AuthorService,
|
||||
private fb: FormBuilder,
|
||||
private confirmation: ConfirmationService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
const authorStreamCreator = (query) => this.authorService.getList(query);
|
||||
|
||||
this.list.hookToQuery(authorStreamCreator).subscribe((response) => {
|
||||
this.author = response;
|
||||
});
|
||||
}
|
||||
|
||||
createAuthor() {
|
||||
this.selectedAuthor = {} as AuthorDto;
|
||||
this.buildForm();
|
||||
this.isModalOpen = true;
|
||||
}
|
||||
|
||||
editAuthor(id: string) {
|
||||
this.authorService.get(id).subscribe((author) => {
|
||||
this.selectedAuthor = author;
|
||||
this.buildForm();
|
||||
this.isModalOpen = true;
|
||||
});
|
||||
}
|
||||
|
||||
buildForm() {
|
||||
this.form = this.fb.group({
|
||||
name: [this.selectedAuthor.name || '', Validators.required],
|
||||
birthDate: [
|
||||
this.selectedAuthor.birthDate ? new Date(this.selectedAuthor.birthDate) : null,
|
||||
Validators.required,
|
||||
],
|
||||
shortBio:[this.selectedAuthor.shortBio || '', Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this.form.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selectedAuthor.id) {
|
||||
this.authorService
|
||||
.update(this.selectedAuthor.id, this.form.value)
|
||||
.subscribe(() => {
|
||||
this.isModalOpen = false;
|
||||
this.form.reset();
|
||||
this.list.get();
|
||||
});
|
||||
} else {
|
||||
this.authorService.create(this.form.value).subscribe(() => {
|
||||
this.isModalOpen = false;
|
||||
this.form.reset();
|
||||
this.list.get();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
delete(id: string) {
|
||||
this.confirmation.warn('::AreYouSureToDelete', '::AreYouSure')
|
||||
.subscribe((status) => {
|
||||
if (status === Confirmation.Status.confirm) {
|
||||
this.authorService.delete(id).subscribe(() => this.list.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
21
angular/src/app/author/author.module.ts
Normal file
21
angular/src/app/author/author.module.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { AuthorRoutingModule } from './author-routing.module';
|
||||
import { AuthorComponent } from './author.component';
|
||||
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AuthorComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
AuthorRoutingModule,
|
||||
NgbDatepickerModule,
|
||||
SharedModule
|
||||
]
|
||||
})
|
||||
export class AuthorModule { }
|
@ -63,6 +63,12 @@
|
||||
{{ row.price | currency }}
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column
|
||||
[name]="'::Author' | abpLocalization"
|
||||
prop="authorName"
|
||||
[sortable]="false"
|
||||
></ngx-datatable-column>
|
||||
|
||||
</ngx-datatable>
|
||||
</div>
|
||||
</div>
|
||||
@ -104,6 +110,16 @@
|
||||
(click)="datepicker.toggle()"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="author-id">Author</label><span> * </span>
|
||||
<select class="form-control" id="author-id" formControlName="authorId">
|
||||
<option [ngValue]="null">Select author</option>
|
||||
<option [ngValue]="author.id" *ngFor="let author of authors$ | async">
|
||||
{{ author.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</ng-template>
|
||||
|
||||
|
@ -1,32 +1,41 @@
|
||||
import { ListService, PagedResultDto } from '@abp/ng.core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { BookService, BookDto, bookTypeOptions } from '@proxy/books';
|
||||
import { BookService, BookDto, bookTypeOptions, AuthorLookupDto } from '@proxy/books';
|
||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'app-book',
|
||||
templateUrl: './book.component.html',
|
||||
styleUrls: ['./book.component.scss'],
|
||||
providers: [ListService,
|
||||
{ provide: NgbDateAdapter, useClass: NgbDateNativeAdapter } // add this line
|
||||
],
|
||||
providers: [ListService, { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }],
|
||||
})
|
||||
export class BookComponent implements OnInit {
|
||||
book = { items: [], totalCount: 0 } as PagedResultDto<BookDto>;
|
||||
selectedBook = {} as BookDto; // declare selectedBook
|
||||
isModalOpen = false; // add this line
|
||||
form: FormGroup; // add this line
|
||||
book = { items: [], totalCount: 0 } as PagedResultDto<BookDto>;
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
selectedBook = {} as BookDto;
|
||||
|
||||
authors$: Observable<AuthorLookupDto[]>;
|
||||
|
||||
bookTypes = bookTypeOptions;
|
||||
|
||||
constructor(public readonly list: ListService, private bookService: BookService, private fb: FormBuilder,
|
||||
private confirmation: ConfirmationService
|
||||
) {}
|
||||
isModalOpen = false;
|
||||
|
||||
constructor(
|
||||
public readonly list: ListService,
|
||||
private bookService: BookService,
|
||||
private fb: FormBuilder,
|
||||
private confirmation: ConfirmationService
|
||||
) {
|
||||
this.authors$ = bookService.getAuthorLookup().pipe(map((r) => r.items));
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
debugger;
|
||||
|
||||
const bookStreamCreator = (query) => this.bookService.getList(query);
|
||||
|
||||
this.list.hookToQuery(bookStreamCreator).subscribe((response) => {
|
||||
@ -34,55 +43,54 @@ export class BookComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// add new method
|
||||
createBook() {
|
||||
this.buildForm(); // add this line
|
||||
this.selectedBook = {} as BookDto; // reset the selected book
|
||||
|
||||
this.selectedBook = {} as BookDto;
|
||||
this.buildForm();
|
||||
this.isModalOpen = true;
|
||||
}
|
||||
buildForm() {
|
||||
this.form = this.fb.group({
|
||||
name: ['', Validators.required],
|
||||
type: [null, Validators.required],
|
||||
publishDate: [null, Validators.required],
|
||||
price: [null, Validators.required],
|
||||
|
||||
editBook(id: string) {
|
||||
this.bookService.get(id).subscribe((book) => {
|
||||
this.selectedBook = book;
|
||||
this.buildForm();
|
||||
this.isModalOpen = true;
|
||||
});
|
||||
}
|
||||
|
||||
buildForm() {
|
||||
this.form = this.fb.group({
|
||||
authorId: [this.selectedBook.authorId || null, Validators.required],
|
||||
name: [this.selectedBook.name || null, Validators.required],
|
||||
type: [this.selectedBook.type || null, Validators.required],
|
||||
publishDate: [
|
||||
this.selectedBook.publishDate ? new Date(this.selectedBook.publishDate) : null,
|
||||
Validators.required,
|
||||
],
|
||||
price: [this.selectedBook.price || null, Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
save() {
|
||||
if (this.form.invalid) {
|
||||
return;
|
||||
}
|
||||
const request = this.selectedBook.id
|
||||
? this.bookService.update(this.selectedBook.id, this.form.value)
|
||||
: this.bookService.create(this.form.value);
|
||||
|
||||
request.subscribe(() => {
|
||||
this.isModalOpen = false;
|
||||
this.form.reset();
|
||||
this.list.get();
|
||||
});
|
||||
const request = this.selectedBook.id
|
||||
? this.bookService.update(this.selectedBook.id, this.form.value)
|
||||
: this.bookService.create(this.form.value);
|
||||
|
||||
request.subscribe(() => {
|
||||
this.isModalOpen = false;
|
||||
this.form.reset();
|
||||
this.list.get();
|
||||
});
|
||||
}
|
||||
|
||||
// Add editBook method
|
||||
editBook(id: string) {
|
||||
this.bookService.get(id).subscribe((book) => {
|
||||
this.selectedBook = book;
|
||||
this.buildForm();
|
||||
this.form.controls["name"].setValue(this.selectedBook.name);
|
||||
this.form.controls["type"].setValue(this.selectedBook.type);
|
||||
this.form.controls["publishDate"].setValue(this.selectedBook.publishDate);
|
||||
this.form.controls["price"].setValue(this.selectedBook.price);
|
||||
this.isModalOpen = true;
|
||||
});
|
||||
}
|
||||
|
||||
delete(id: string) {
|
||||
this.confirmation.warn('::AreYouSureToDelete', '::AreYouSure').subscribe((status) => {
|
||||
if (status === Confirmation.Status.confirm) {
|
||||
this.bookService.delete(id).subscribe(() => this.list.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
delete(id: string) {
|
||||
this.confirmation.warn('::AreYouSureToDelete', 'AbpAccount::AreYouSure').subscribe((status) => {
|
||||
if (status === Confirmation.Status.confirm) {
|
||||
this.bookService.delete(id).subscribe(() => this.list.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { BookDto, CreateUpdateBookDto } from './models';
|
||||
import type { AuthorLookupDto, BookDto, CreateUpdateBookDto } from './models';
|
||||
import { RestService, Rest } from '@abp/ng.core';
|
||||
import type { PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
|
||||
import type { ListResultDto, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
@ -35,6 +35,14 @@ export class BookService {
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getAuthorLookup = (config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, ListResultDto<AuthorLookupDto>>({
|
||||
method: 'GET',
|
||||
url: '/api/app/book/author-lookup',
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getBookDropDown = (config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, BookDto[]>({
|
||||
method: 'GET',
|
||||
|
@ -1,11 +1,17 @@
|
||||
import type { AuditedEntityDto } from '@abp/ng.core';
|
||||
import type { AuditedEntityDto, EntityDto } from '@abp/ng.core';
|
||||
import type { BookType } from './book-type.enum';
|
||||
|
||||
export interface AuthorLookupDto extends EntityDto<string> {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface BookDto extends AuditedEntityDto<string> {
|
||||
name?: string;
|
||||
type: BookType;
|
||||
publishDate?: string;
|
||||
price: number;
|
||||
authorId?: string;
|
||||
authorName?: string;
|
||||
}
|
||||
|
||||
export interface CreateUpdateBookDto {
|
||||
@ -13,4 +19,5 @@ export interface CreateUpdateBookDto {
|
||||
type: BookType;
|
||||
publishDate: string;
|
||||
price: number;
|
||||
authorId?: string;
|
||||
}
|
||||
|
@ -1530,6 +1530,14 @@
|
||||
"typeSimple": "[Acme.BookStore.Books.BookDto]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "GetAuthorLookupAsync",
|
||||
"parametersOnMethod": [],
|
||||
"returnValue": {
|
||||
"type": "Volo.Abp.Application.Dtos.ListResultDto<Acme.BookStore.Books.AuthorLookupDto>",
|
||||
"typeSimple": "Volo.Abp.Application.Dtos.ListResultDto<Acme.BookStore.Books.AuthorLookupDto>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "GetAsync",
|
||||
"parametersOnMethod": [
|
||||
@ -1627,152 +1635,6 @@
|
||||
}
|
||||
],
|
||||
"actions": {
|
||||
"GetBookDropDown": {
|
||||
"uniqueName": "GetBookDropDown",
|
||||
"name": "GetBookDropDown",
|
||||
"httpMethod": "GET",
|
||||
"url": "api/app/book/book-drop-down",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [],
|
||||
"parameters": [],
|
||||
"returnValue": {
|
||||
"type": "System.Collections.Generic.List<Acme.BookStore.Books.BookDto>",
|
||||
"typeSimple": "[Acme.BookStore.Books.BookDto]"
|
||||
},
|
||||
"allowAnonymous": null,
|
||||
"implementFrom": "Acme.BookStore.Books.IBookAppService"
|
||||
},
|
||||
"CreateAsyncByInput": {
|
||||
"uniqueName": "CreateAsyncByInput",
|
||||
"name": "CreateAsync",
|
||||
"httpMethod": "POST",
|
||||
"url": "api/app/book",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [
|
||||
{
|
||||
"name": "input",
|
||||
"typeAsString": "Acme.BookStore.Books.CreateUpdateBookDto, Acme.BookStore.Application.Contracts",
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"nameOnMethod": "input",
|
||||
"name": "input",
|
||||
"jsonName": null,
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": null,
|
||||
"bindingSourceId": "Body",
|
||||
"descriptorName": ""
|
||||
}
|
||||
],
|
||||
"returnValue": {
|
||||
"type": "Acme.BookStore.Books.BookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.BookDto"
|
||||
},
|
||||
"allowAnonymous": null,
|
||||
"implementFrom": "Volo.Abp.Application.Services.ICreateAppService<Acme.BookStore.Books.BookDto,Acme.BookStore.Books.CreateUpdateBookDto>"
|
||||
},
|
||||
"UpdateAsyncByIdAndInput": {
|
||||
"uniqueName": "UpdateAsyncByIdAndInput",
|
||||
"name": "UpdateAsync",
|
||||
"httpMethod": "PUT",
|
||||
"url": "api/app/book/{id}",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [
|
||||
{
|
||||
"name": "id",
|
||||
"typeAsString": "System.Guid, System.Private.CoreLib",
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "input",
|
||||
"typeAsString": "Acme.BookStore.Books.CreateUpdateBookDto, Acme.BookStore.Application.Contracts",
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"nameOnMethod": "id",
|
||||
"name": "id",
|
||||
"jsonName": null,
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": [],
|
||||
"bindingSourceId": "Path",
|
||||
"descriptorName": ""
|
||||
},
|
||||
{
|
||||
"nameOnMethod": "input",
|
||||
"name": "input",
|
||||
"jsonName": null,
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": null,
|
||||
"bindingSourceId": "Body",
|
||||
"descriptorName": ""
|
||||
}
|
||||
],
|
||||
"returnValue": {
|
||||
"type": "Acme.BookStore.Books.BookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.BookDto"
|
||||
},
|
||||
"allowAnonymous": null,
|
||||
"implementFrom": "Volo.Abp.Application.Services.IUpdateAppService<Acme.BookStore.Books.BookDto,System.Guid,Acme.BookStore.Books.CreateUpdateBookDto>"
|
||||
},
|
||||
"DeleteAsyncById": {
|
||||
"uniqueName": "DeleteAsyncById",
|
||||
"name": "DeleteAsync",
|
||||
"httpMethod": "DELETE",
|
||||
"url": "api/app/book/{id}",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [
|
||||
{
|
||||
"name": "id",
|
||||
"typeAsString": "System.Guid, System.Private.CoreLib",
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"nameOnMethod": "id",
|
||||
"name": "id",
|
||||
"jsonName": null,
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": [],
|
||||
"bindingSourceId": "Path",
|
||||
"descriptorName": ""
|
||||
}
|
||||
],
|
||||
"returnValue": {
|
||||
"type": "System.Void",
|
||||
"typeSimple": "System.Void"
|
||||
},
|
||||
"allowAnonymous": null,
|
||||
"implementFrom": "Volo.Abp.Application.Services.IDeleteAppService<System.Guid>"
|
||||
},
|
||||
"GetAsyncById": {
|
||||
"uniqueName": "GetAsyncById",
|
||||
"name": "GetAsync",
|
||||
@ -1807,7 +1669,7 @@
|
||||
"type": "Acme.BookStore.Books.BookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.BookDto"
|
||||
},
|
||||
"allowAnonymous": null,
|
||||
"allowAnonymous": false,
|
||||
"implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService<Acme.BookStore.Books.BookDto,Acme.BookStore.Books.BookDto,System.Guid,Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto>"
|
||||
},
|
||||
"GetListAsyncByInput": {
|
||||
@ -1868,8 +1730,169 @@
|
||||
"type": "Volo.Abp.Application.Dtos.PagedResultDto<Acme.BookStore.Books.BookDto>",
|
||||
"typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto<Acme.BookStore.Books.BookDto>"
|
||||
},
|
||||
"allowAnonymous": null,
|
||||
"allowAnonymous": false,
|
||||
"implementFrom": "Volo.Abp.Application.Services.IReadOnlyAppService<Acme.BookStore.Books.BookDto,Acme.BookStore.Books.BookDto,System.Guid,Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto>"
|
||||
},
|
||||
"GetAuthorLookupAsync": {
|
||||
"uniqueName": "GetAuthorLookupAsync",
|
||||
"name": "GetAuthorLookupAsync",
|
||||
"httpMethod": "GET",
|
||||
"url": "api/app/book/author-lookup",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [],
|
||||
"parameters": [],
|
||||
"returnValue": {
|
||||
"type": "Volo.Abp.Application.Dtos.ListResultDto<Acme.BookStore.Books.AuthorLookupDto>",
|
||||
"typeSimple": "Volo.Abp.Application.Dtos.ListResultDto<Acme.BookStore.Books.AuthorLookupDto>"
|
||||
},
|
||||
"allowAnonymous": false,
|
||||
"implementFrom": "Acme.BookStore.Books.IBookAppService"
|
||||
},
|
||||
"GetBookDropDown": {
|
||||
"uniqueName": "GetBookDropDown",
|
||||
"name": "GetBookDropDown",
|
||||
"httpMethod": "GET",
|
||||
"url": "api/app/book/book-drop-down",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [],
|
||||
"parameters": [],
|
||||
"returnValue": {
|
||||
"type": "System.Collections.Generic.List<Acme.BookStore.Books.BookDto>",
|
||||
"typeSimple": "[Acme.BookStore.Books.BookDto]"
|
||||
},
|
||||
"allowAnonymous": false,
|
||||
"implementFrom": "Acme.BookStore.Books.IBookAppService"
|
||||
},
|
||||
"CreateAsyncByInput": {
|
||||
"uniqueName": "CreateAsyncByInput",
|
||||
"name": "CreateAsync",
|
||||
"httpMethod": "POST",
|
||||
"url": "api/app/book",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [
|
||||
{
|
||||
"name": "input",
|
||||
"typeAsString": "Acme.BookStore.Books.CreateUpdateBookDto, Acme.BookStore.Application.Contracts",
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"nameOnMethod": "input",
|
||||
"name": "input",
|
||||
"jsonName": null,
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": null,
|
||||
"bindingSourceId": "Body",
|
||||
"descriptorName": ""
|
||||
}
|
||||
],
|
||||
"returnValue": {
|
||||
"type": "Acme.BookStore.Books.BookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.BookDto"
|
||||
},
|
||||
"allowAnonymous": false,
|
||||
"implementFrom": "Volo.Abp.Application.Services.ICreateAppService<Acme.BookStore.Books.BookDto,Acme.BookStore.Books.CreateUpdateBookDto>"
|
||||
},
|
||||
"UpdateAsyncByIdAndInput": {
|
||||
"uniqueName": "UpdateAsyncByIdAndInput",
|
||||
"name": "UpdateAsync",
|
||||
"httpMethod": "PUT",
|
||||
"url": "api/app/book/{id}",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [
|
||||
{
|
||||
"name": "id",
|
||||
"typeAsString": "System.Guid, System.Private.CoreLib",
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "input",
|
||||
"typeAsString": "Acme.BookStore.Books.CreateUpdateBookDto, Acme.BookStore.Application.Contracts",
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"nameOnMethod": "id",
|
||||
"name": "id",
|
||||
"jsonName": null,
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": [],
|
||||
"bindingSourceId": "Path",
|
||||
"descriptorName": ""
|
||||
},
|
||||
{
|
||||
"nameOnMethod": "input",
|
||||
"name": "input",
|
||||
"jsonName": null,
|
||||
"type": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.CreateUpdateBookDto",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": null,
|
||||
"bindingSourceId": "Body",
|
||||
"descriptorName": ""
|
||||
}
|
||||
],
|
||||
"returnValue": {
|
||||
"type": "Acme.BookStore.Books.BookDto",
|
||||
"typeSimple": "Acme.BookStore.Books.BookDto"
|
||||
},
|
||||
"allowAnonymous": false,
|
||||
"implementFrom": "Volo.Abp.Application.Services.IUpdateAppService<Acme.BookStore.Books.BookDto,System.Guid,Acme.BookStore.Books.CreateUpdateBookDto>"
|
||||
},
|
||||
"DeleteAsyncById": {
|
||||
"uniqueName": "DeleteAsyncById",
|
||||
"name": "DeleteAsync",
|
||||
"httpMethod": "DELETE",
|
||||
"url": "api/app/book/{id}",
|
||||
"supportedVersions": [],
|
||||
"parametersOnMethod": [
|
||||
{
|
||||
"name": "id",
|
||||
"typeAsString": "System.Guid, System.Private.CoreLib",
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"nameOnMethod": "id",
|
||||
"name": "id",
|
||||
"jsonName": null,
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isOptional": false,
|
||||
"defaultValue": null,
|
||||
"constraintTypes": [],
|
||||
"bindingSourceId": "Path",
|
||||
"descriptorName": ""
|
||||
}
|
||||
],
|
||||
"returnValue": {
|
||||
"type": "System.Void",
|
||||
"typeSimple": "System.Void"
|
||||
},
|
||||
"allowAnonymous": false,
|
||||
"implementFrom": "Volo.Abp.Application.Services.IDeleteAppService<System.Guid>"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5036,6 +5059,27 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"Acme.BookStore.Books.AuthorLookupDto": {
|
||||
"baseType": "Volo.Abp.Application.Dtos.EntityDto<System.Guid>",
|
||||
"isEnum": false,
|
||||
"enumNames": null,
|
||||
"enumValues": null,
|
||||
"genericArguments": null,
|
||||
"properties": [
|
||||
{
|
||||
"name": "Name",
|
||||
"jsonName": null,
|
||||
"type": "System.String",
|
||||
"typeSimple": "string",
|
||||
"isRequired": false,
|
||||
"minLength": null,
|
||||
"maxLength": null,
|
||||
"minimum": null,
|
||||
"maximum": null,
|
||||
"regex": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"Acme.BookStore.Books.BookDto": {
|
||||
"baseType": "Volo.Abp.Application.Dtos.AuditedEntityDto<System.Guid>",
|
||||
"isEnum": false,
|
||||
@ -5090,6 +5134,30 @@
|
||||
"minimum": null,
|
||||
"maximum": null,
|
||||
"regex": null
|
||||
},
|
||||
{
|
||||
"name": "AuthorId",
|
||||
"jsonName": null,
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isRequired": false,
|
||||
"minLength": null,
|
||||
"maxLength": null,
|
||||
"minimum": null,
|
||||
"maximum": null,
|
||||
"regex": null
|
||||
},
|
||||
{
|
||||
"name": "AuthorName",
|
||||
"jsonName": null,
|
||||
"type": "System.String",
|
||||
"typeSimple": "string",
|
||||
"isRequired": false,
|
||||
"minLength": null,
|
||||
"maxLength": null,
|
||||
"minimum": null,
|
||||
"maximum": null,
|
||||
"regex": null
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -5175,6 +5243,18 @@
|
||||
"minimum": null,
|
||||
"maximum": null,
|
||||
"regex": null
|
||||
},
|
||||
{
|
||||
"name": "AuthorId",
|
||||
"jsonName": null,
|
||||
"type": "System.Guid",
|
||||
"typeSimple": "string",
|
||||
"isRequired": false,
|
||||
"minLength": null,
|
||||
"maxLength": null,
|
||||
"minimum": null,
|
||||
"maximum": null,
|
||||
"regex": null
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -14,38 +14,36 @@ function configureRoutes(routesService: RoutesService) {
|
||||
iconClass: 'fas fa-home',
|
||||
order: 1,
|
||||
layout: eLayoutType.application,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/book-store',
|
||||
name: '::Menu:BookStore',
|
||||
iconClass: 'fas fa-book',
|
||||
order: 2,
|
||||
path: '/authors',
|
||||
name: '::Menu:Authors',
|
||||
iconClass: 'fas fa-user-plus',
|
||||
order:2,
|
||||
layout: eLayoutType.application,
|
||||
requiredPolicy: 'BookStore.Books',
|
||||
requiredPolicy: 'BookStore.Authors',
|
||||
},
|
||||
{
|
||||
path: '/books',
|
||||
name: '::Menu:Books',
|
||||
parentName: '::Menu:BookStore',
|
||||
name: '::Menu:Books',
|
||||
iconClass: 'fas fa-book',
|
||||
order: 3,
|
||||
layout: eLayoutType.application,
|
||||
requiredPolicy: 'BookStore.Books',
|
||||
},
|
||||
|
||||
|
||||
|
||||
},
|
||||
{
|
||||
path: '/customer',
|
||||
name: 'Customer',
|
||||
name: '::Menu:Customer',
|
||||
iconClass: 'fas fa-user',
|
||||
order: 2,
|
||||
order: 4,
|
||||
layout: eLayoutType.application,
|
||||
requiredPolicy: 'BookStore.Customers',
|
||||
},
|
||||
{
|
||||
path: '/book-issue',
|
||||
name: 'book-issue',
|
||||
name: '::Menu:BookIssue',
|
||||
iconClass: 'fas fa-book',
|
||||
order: 2,
|
||||
order: 5,
|
||||
layout: eLayoutType.application,
|
||||
requiredPolicy: 'BookStore.BookIssued',
|
||||
},
|
||||
|
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Acme.BookStore.Books
|
||||
{
|
||||
public class AuthorLookupDto : EntityDto<Guid>
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -14,5 +14,9 @@ namespace Acme.BookStore.Books
|
||||
public DateTime PublishDate { get; set; }
|
||||
|
||||
public float Price { get; set; }
|
||||
|
||||
public Guid AuthorId { get; set; }
|
||||
public string AuthorName { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,5 +20,8 @@ namespace Acme.BookStore.Books
|
||||
|
||||
[Required]
|
||||
public float Price { get; set; }
|
||||
|
||||
public Guid AuthorId { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,5 +15,7 @@ namespace Acme.BookStore.Books
|
||||
CreateUpdateBookDto> //Used to create/update a book
|
||||
{
|
||||
Task<List<BookDto>> GetBookDropDown();
|
||||
Task<ListResultDto<AuthorLookupDto>> GetAuthorLookupAsync();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ public class BookStoreApplicationAutoMapperProfile : Profile
|
||||
// CreateMap<List<Customer>, List<CustomerDto>>().ReverseMap();
|
||||
CreateMap<BookIssue, BookIssueDto>().ReverseMap();
|
||||
CreateMap<BookIssueList, BookIssueListDto>().ReverseMap();
|
||||
CreateMap<Author, AuthorLookupDto>();
|
||||
|
||||
/* You can configure your AutoMapper mapping configuration here.
|
||||
* Alternatively, you can split your mapping configurations
|
||||
|
@ -1,43 +1,135 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
using Acme.BookStore.Authors;
|
||||
using Acme.BookStore.Permissions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Domain.Entities;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Acme.BookStore.Permissions;
|
||||
|
||||
namespace Acme.BookStore.Books
|
||||
namespace Acme.BookStore.Books;
|
||||
|
||||
[Authorize(BookStorePermissions.Books.Default)]
|
||||
public class BookAppService :
|
||||
CrudAppService<
|
||||
Book, //The Book entity
|
||||
BookDto, //Used to show books
|
||||
Guid, //Primary key of the book entity
|
||||
PagedAndSortedResultRequestDto, //Used for paging/sorting
|
||||
CreateUpdateBookDto>, //Used to create/update a book
|
||||
IBookAppService //implement the IBookAppService
|
||||
{
|
||||
|
||||
public class BookAppService :
|
||||
CrudAppService<
|
||||
Book, //The Book entity
|
||||
BookDto, //Used to show books
|
||||
Guid, //Primary key of the book entity
|
||||
PagedAndSortedResultRequestDto, //Used for paging/sorting
|
||||
CreateUpdateBookDto>, //Used to create/update a book
|
||||
IBookAppService //implement the IBookAppService
|
||||
private readonly IAuthorRepository _authorRepository;
|
||||
private readonly IRepository<Book, Guid> _bookRepository;
|
||||
public BookAppService(
|
||||
IRepository<Book, Guid> repository,
|
||||
IAuthorRepository authorRepository)
|
||||
: base(repository)
|
||||
{
|
||||
private readonly IRepository<Book, Guid> _bookRepository;
|
||||
public BookAppService(IRepository<Book, Guid> repository)
|
||||
: base(repository)
|
||||
_authorRepository = authorRepository;
|
||||
_bookRepository = repository;
|
||||
GetPolicyName = BookStorePermissions.Books.Default;
|
||||
GetListPolicyName = BookStorePermissions.Books.Default;
|
||||
CreatePolicyName = BookStorePermissions.Books.Create;
|
||||
UpdatePolicyName = BookStorePermissions.Books.Edit;
|
||||
DeletePolicyName = BookStorePermissions.Books.Delete;
|
||||
}
|
||||
|
||||
public override async Task<BookDto> GetAsync(Guid id)
|
||||
{
|
||||
//Get the IQueryable<Book> from the repository
|
||||
var queryable = await Repository.GetQueryableAsync();
|
||||
|
||||
//Prepare a query to join books and authors
|
||||
var query = from book in queryable
|
||||
join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id
|
||||
where book.Id == id
|
||||
select new { book, author };
|
||||
|
||||
//Execute the query and get the book with author
|
||||
var queryResult = await AsyncExecuter.FirstOrDefaultAsync(query);
|
||||
if (queryResult == null)
|
||||
{
|
||||
_bookRepository = repository;
|
||||
GetPolicyName = BookStorePermissions.Books.Default;
|
||||
GetListPolicyName = BookStorePermissions.Books.Default;
|
||||
CreatePolicyName = BookStorePermissions.Books.Create;
|
||||
UpdatePolicyName = BookStorePermissions.Books.Edit;
|
||||
DeletePolicyName = BookStorePermissions.Books.Delete;
|
||||
throw new EntityNotFoundException(typeof(Book), id);
|
||||
}
|
||||
|
||||
public async Task<List<BookDto>> GetBookDropDown()
|
||||
var bookDto = ObjectMapper.Map<Book, BookDto>(queryResult.book);
|
||||
bookDto.AuthorName = queryResult.author.Name;
|
||||
return bookDto;
|
||||
}
|
||||
|
||||
public override async Task<PagedResultDto<BookDto>> GetListAsync(PagedAndSortedResultRequestDto input)
|
||||
{
|
||||
//Get the IQueryable<Book> from the repository
|
||||
var queryable = await Repository.GetQueryableAsync();
|
||||
|
||||
//Prepare a query to join books and authors
|
||||
var query = from book in queryable
|
||||
join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id
|
||||
select new { book, author };
|
||||
|
||||
//Paging
|
||||
query = query
|
||||
.OrderBy(NormalizeSorting(input.Sorting))
|
||||
.Skip(input.SkipCount)
|
||||
.Take(input.MaxResultCount);
|
||||
|
||||
//Execute the query and get a list
|
||||
var queryResult = await AsyncExecuter.ToListAsync(query);
|
||||
|
||||
//Convert the query result to a list of BookDto objects
|
||||
var bookDtos = queryResult.Select(x =>
|
||||
{
|
||||
var cus = await _bookRepository.GetListAsync();
|
||||
cus = cus == null ? new List<Book>() : cus;
|
||||
return ObjectMapper.Map<List<Book>, List<BookDto>>(cus);
|
||||
var bookDto = ObjectMapper.Map<Book, BookDto>(x.book);
|
||||
bookDto.AuthorName = x.author.Name;
|
||||
return bookDto;
|
||||
}).ToList();
|
||||
|
||||
//Get the total count with another query
|
||||
var totalCount = await Repository.GetCountAsync();
|
||||
|
||||
return new PagedResultDto<BookDto>(
|
||||
totalCount,
|
||||
bookDtos
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<ListResultDto<AuthorLookupDto>> GetAuthorLookupAsync()
|
||||
{
|
||||
var authors = await _authorRepository.GetListAsync();
|
||||
|
||||
return new ListResultDto<AuthorLookupDto>(
|
||||
ObjectMapper.Map<List<Author>, List<AuthorLookupDto>>(authors)
|
||||
);
|
||||
}
|
||||
|
||||
private static string NormalizeSorting(string sorting)
|
||||
{
|
||||
if (sorting.IsNullOrEmpty())
|
||||
{
|
||||
return $"book.{nameof(Book.Name)}";
|
||||
}
|
||||
|
||||
if (sorting.Contains("authorName", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return sorting.Replace(
|
||||
"authorName",
|
||||
"author.Name",
|
||||
StringComparison.OrdinalIgnoreCase
|
||||
);
|
||||
}
|
||||
|
||||
return $"book.{sorting}";
|
||||
}
|
||||
|
||||
public async Task<List<BookDto>> GetBookDropDown()
|
||||
{
|
||||
var cus = await _bookRepository.GetListAsync();
|
||||
cus = cus == null ? new List<Book>() : cus;
|
||||
return ObjectMapper.Map<List<Book>, List<BookDto>>(cus);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.",
|
||||
"Menu:BookStore": "Book Store",
|
||||
"Menu:Books": "Books",
|
||||
"Menu:Customer": "Customer",
|
||||
"Menu:BookIssue": "Book Issue",
|
||||
"Actions": "Actions",
|
||||
"Close": "Close",
|
||||
"Delete": "Delete",
|
||||
@ -46,7 +48,12 @@
|
||||
"Permission:BookIssued": "Book Issued Management",
|
||||
"Permission:BookIssued.Create": "Creating new Issued Book",
|
||||
"Permission:BookIssued.Edit": "Editing the Issued Book",
|
||||
"Permission:BookIssued.Delete": "Deleting the Issued Book"
|
||||
"Permission:BookIssued.Delete": "Deleting the Issued Book",
|
||||
"Menu:Authors": "Authors",
|
||||
"Authors": "Authors",
|
||||
"AuthorDeletionConfirmationMessage": "Are you sure to delete the author '{0}'?",
|
||||
"BirthDate": "Birth date",
|
||||
"NewAuthor": "New author"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using Acme.BookStore.Books;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
@ -23,7 +23,7 @@ namespace Acme.BookStore
|
||||
private readonly CustomerManager _customerManager;
|
||||
|
||||
public BookStoreDataSeederContributor(IRepository<Book, Guid> bookRepository,
|
||||
IAuthorRepository authorRepository,
|
||||
IAuthorRepository authorRepository,
|
||||
AuthorManager authorManager,
|
||||
ICustomerRepository customerRepository,
|
||||
CustomerManager customerManager
|
||||
@ -40,48 +40,76 @@ namespace Acme.BookStore
|
||||
|
||||
public async Task SeedAsync(DataSeedContext context)
|
||||
{
|
||||
if (await _bookRepository.GetCountAsync() <= 0)
|
||||
{
|
||||
await _bookRepository.InsertAsync(
|
||||
new Book
|
||||
{
|
||||
Name = "1984",
|
||||
Type = BookType.Dystopia,
|
||||
PublishDate = new DateTime(1949, 6, 8),
|
||||
Price = 19.84f
|
||||
},
|
||||
autoSave: true
|
||||
);
|
||||
//if (await _bookRepository.GetCountAsync() <= 0)
|
||||
//{
|
||||
// await _bookRepository.InsertAsync(
|
||||
// new Book
|
||||
// {
|
||||
// Name = "1984",
|
||||
// Type = BookType.Dystopia,
|
||||
// PublishDate = new DateTime(1949, 6, 8),
|
||||
// Price = 19.84f
|
||||
// },
|
||||
// autoSave: true
|
||||
// );
|
||||
|
||||
await _bookRepository.InsertAsync(
|
||||
new Book
|
||||
{
|
||||
Name = "The Hitchhiker's Guide to the Galaxy",
|
||||
Type = BookType.ScienceFiction,
|
||||
PublishDate = new DateTime(1995, 9, 27),
|
||||
Price = 42.0f
|
||||
},
|
||||
autoSave: true
|
||||
);
|
||||
}
|
||||
// await _bookRepository.InsertAsync(
|
||||
// new Book
|
||||
// {
|
||||
// Name = "The Hitchhiker's Guide to the Galaxy",
|
||||
// Type = BookType.ScienceFiction,
|
||||
// PublishDate = new DateTime(1995, 9, 27),
|
||||
// Price = 42.0f
|
||||
// },
|
||||
// autoSave: true
|
||||
// );
|
||||
//}
|
||||
|
||||
|
||||
if (await _authorRepository.GetCountAsync() <= 0)
|
||||
{
|
||||
await _authorRepository.InsertAsync(
|
||||
var orwell = await _authorRepository.InsertAsync(
|
||||
await _authorManager.CreateAsync(
|
||||
"George Orwell",
|
||||
new DateTime(1903, 06, 25),
|
||||
"Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)."
|
||||
)
|
||||
);
|
||||
await _authorRepository.InsertAsync(
|
||||
var douglas = await _authorRepository.InsertAsync(
|
||||
await _authorManager.CreateAsync(
|
||||
"Douglas Adams",
|
||||
new DateTime(1952, 03, 11),
|
||||
"Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'."
|
||||
)
|
||||
);
|
||||
|
||||
if (await _bookRepository.GetCountAsync() <= 0)
|
||||
{
|
||||
await _bookRepository.InsertAsync(
|
||||
new Book
|
||||
{
|
||||
AuthorId = orwell.Id, // SET THE AUTHOR
|
||||
Name = "1984",
|
||||
Type = BookType.Dystopia,
|
||||
PublishDate = new DateTime(1949, 6, 8),
|
||||
Price = 19.84f
|
||||
},
|
||||
autoSave: true
|
||||
);
|
||||
|
||||
await _bookRepository.InsertAsync(
|
||||
new Book
|
||||
{
|
||||
AuthorId = douglas.Id, // SET THE AUTHOR
|
||||
Name = "The Hitchhiker's Guide to the Galaxy",
|
||||
Type = BookType.ScienceFiction,
|
||||
PublishDate = new DateTime(1995, 9, 27),
|
||||
Price = 42.0f
|
||||
},
|
||||
autoSave: true
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (await _customerRepository.GetCountAsync() <= 0)
|
||||
|
@ -16,5 +16,7 @@ namespace Acme.BookStore.Books
|
||||
public DateTime PublishDate { get; set; }
|
||||
|
||||
public float Price { get; set; }
|
||||
public Guid AuthorId { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ public class BookStoreDbContext :
|
||||
BookStoreConsts.DbSchema);
|
||||
b.ConfigureByConvention(); //auto configure for the base class props
|
||||
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
|
||||
|
||||
b.HasOne<Author>().WithMany().HasForeignKey(x => x.AuthorId).IsRequired();
|
||||
});
|
||||
|
||||
builder.Entity<Author>(b =>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Acme.BookStore.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Added_AuthorId_To_Book : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "AuthorId",
|
||||
table: "AppBooks",
|
||||
type: "uniqueidentifier",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AppBooks_AuthorId",
|
||||
table: "AppBooks",
|
||||
column: "AuthorId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_AppBooks_AppAuthors_AuthorId",
|
||||
table: "AppBooks",
|
||||
column: "AuthorId",
|
||||
principalTable: "AppAuthors",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_AppBooks_AppAuthors_AuthorId",
|
||||
table: "AppBooks");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_AppBooks_AuthorId",
|
||||
table: "AppBooks");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AuthorId",
|
||||
table: "AppBooks");
|
||||
}
|
||||
}
|
||||
}
|
@ -153,6 +153,9 @@ namespace Acme.BookStore.Migrations
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<Guid>("AuthorId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.IsRequired()
|
||||
@ -197,6 +200,8 @@ namespace Acme.BookStore.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AuthorId");
|
||||
|
||||
b.ToTable("AppBooks", (string)null);
|
||||
});
|
||||
|
||||
@ -2016,6 +2021,15 @@ namespace Acme.BookStore.Migrations
|
||||
b.ToTable("AbpTenantConnectionStrings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Acme.BookStore.Books.Book", b =>
|
||||
{
|
||||
b.HasOne("Acme.BookStore.Authors.Author", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b =>
|
||||
{
|
||||
b.HasOne("Volo.Abp.AuditLogging.AuditLog", null)
|
||||
|
Loading…
x
Reference in New Issue
Block a user