diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index a4616a2..0d7fa49 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -14,8 +14,10 @@ import {AdoptionEditComponent} from './adoptions/adoption-edit/adoption-edit.com
import {AdoptionDetailComponent} from './adoptions/adoption-detail/adoption-detail.component';
import {AdoptionDeleteComponent} from './adoptions/adoption-delete/adoption-delete.component';
import {AdoptionCreateComponent} from "./adoptions/adoption-create/adoption-create.component";
-import { ShelterListComponent } from './shelter/shelter-list/shelter-list.component'
+import {ShelterListComponent} from './shelter/shelter-list/shelter-list.component'
import {ShelterCreateComponent} from "./shelter/shelter-create/shelter-create.component";
+import {LocationListComponent} from "./location/location-list/location-list.component";
+import {LocationCreateComponent} from "./location/location-create/location-create.component";
const routes: Routes = [
{ path: 'users/create', component: UserRegisterComponent},
@@ -23,9 +25,8 @@ const routes: Routes = [
{ path: 'users/:id/edit', component: UserEditComponent, canActivate: [LoggedInGuard]},
{ path: 'users/:id', component: UserDetailComponent, canActivate: [LoggedInGuard]},
{ path: 'users', component: UserListComponent, canActivate: [LoggedInGuard]},
- { path: 'about', component: AboutComponent},
- { path: '404', component: NotFoundComponent},
- { path: '', redirectTo: 'about', pathMatch: 'full'},
+ { path: 'locations', component: LocationListComponent, canActivate: [LoggedInGuard]},
+ { path: 'locations/create', component: LocationCreateComponent, canActivate: [LoggedInGuard]},
{ path: 'adoptions' , component: AdoptionListComponent },
{ path: 'adoptions/create', component: AdoptionCreateComponent },
{ path: 'adoptions/edit', component: AdoptionEditComponent },
@@ -34,6 +35,9 @@ const routes: Routes = [
{ path: 'adoptions/search', component: AdoptionSearchComponent },
{ path: 'shelters', component: ShelterListComponent},
{ path: 'shelters/create', component: ShelterCreateComponent},
+ { path: 'about', component: AboutComponent},
+ { path: '404', component: NotFoundComponent},
+ { path: '', redirectTo: 'about', pathMatch: 'full'},
];
@NgModule({
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index bf37af6..e3945b5 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -23,17 +23,21 @@ import {HttpErrorInterceptor} from './error-handler/http-error-interceptor';
import {AuthenticationBasicService} from './login-basic/authentication-basic.service';
import {LoggedInGuard} from './login-basic/loggedin.guard';
import {UserService} from './user/user.service';
+import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import {AdoptionSearchComponent} from './adoptions/adoption-search/adoption-search.component';
import {AdoptionListComponent} from './adoptions/adoption-list/adoption-list.component';
import {AdoptionEditComponent} from './adoptions/adoption-edit/adoption-edit.component';
import {AdoptionDetailComponent} from './adoptions/adoption-detail/adoption-detail.component';
import {AdoptionDeleteComponent} from './adoptions/adoption-delete/adoption-delete.component';
import {AdoptionCreateComponent} from "./adoptions/adoption-create/adoption-create.component";
-import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import {ShelterService} from "./shelter/shelter.service";
import {ShelterListComponent} from "./shelter/shelter-list/shelter-list.component";
import {ShelterCreateComponent} from "./shelter/shelter-create/shelter-create.component";
import {ShelterDetailComponent} from "./shelter/shelter-detail/shelter-detail.component";
+import {LocationService} from './location/location.service'
+import {LocationListComponent} from './location/location-list/location-list.component';
+import {LocationSearchComponent} from './location/location-search/location-search.component';
+import {LocationCreateComponent} from "./location/location-create/location-create.component";
@NgModule({
declarations: [
@@ -55,7 +59,10 @@ import {ShelterDetailComponent} from "./shelter/shelter-detail/shelter-detail.co
AdoptionListComponent,
ShelterListComponent,
ShelterCreateComponent,
- ShelterDetailComponent
+ ShelterDetailComponent,
+ LocationListComponent,
+ LocationSearchComponent,
+ LocationCreateComponent
],
imports: [
BrowserModule,
@@ -74,7 +81,8 @@ import {ShelterDetailComponent} from "./shelter/shelter-detail/shelter-detail.co
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true },
- AuthenticationBasicService, LoggedInGuard, UserService, ShelterService, provideAnimationsAsync()
+ AuthenticationBasicService, LoggedInGuard, UserService, ShelterService, LocationService,
+ provideAnimationsAsync()
],
bootstrap: [AppComponent]
})
diff --git a/src/app/location/location-create/location-create.component.html b/src/app/location/location-create/location-create.component.html
new file mode 100644
index 0000000..1b19f20
--- /dev/null
+++ b/src/app/location/location-create/location-create.component.html
@@ -0,0 +1,87 @@
+
+
diff --git a/src/app/location/location-create/location-create.component.ts b/src/app/location/location-create/location-create.component.ts
new file mode 100644
index 0000000..a49a6b2
--- /dev/null
+++ b/src/app/location/location-create/location-create.component.ts
@@ -0,0 +1,122 @@
+import {Component, OnInit} from '@angular/core';
+import {Router} from "@angular/router";
+import {LocationService} from "../location.service";
+import {Location} from "../location";
+import {AbstractControl, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators} from "@angular/forms";
+import {ModalDismissReasons, NgbModal} from "@ng-bootstrap/ng-bootstrap";
+import {PagedResourceCollection} from "@lagoshny/ngx-hateoas-client";
+import {formatDate} from "@angular/common";
+
+@Component({
+ selector: 'app-location-create',
+ templateUrl: './location-create.component.html',
+})
+export class LocationCreateComponent implements OnInit{
+
+ closeResult = '';
+ public isModalSaved: boolean = false;
+ public locations: Location[] = [];
+ public location: Location;
+ public commonNameInput: string = '';
+ public commonEmailsList: any = [];
+ public locationForm: FormGroup;
+
+ constructor(
+ private router: Router,
+ private locationService: LocationService,
+ private modalService: NgbModal
+ ) {}
+
+ ngOnInit(): void {
+ this.location = new Location();
+ this.locationForm = new FormGroup({
+ address: new FormControl(this.location.address),
+ city: new FormControl(this.location.city),
+ province: new FormControl(this.location.province),
+ postalCode: new FormControl(this.location.postalCode),
+ });
+ this.loadLocationList();
+ }
+
+ loadLocationList() {
+ this.locationService
+ .getPage({
+ sort: { address: 'ASC' },
+ })
+ .subscribe((locations: PagedResourceCollection) => {
+ this.locations = locations.resources.sort((a, b) =>
+ a.address.localeCompare(b.address)
+ );
+ });
+ }
+
+ open(content) {
+ this.modalService
+ .open(content, { ariaLabelledBy: 'modal-basic-title' })
+ .result.then(
+ (result) => {
+ this.closeResult = `Closed with: ${result}`;
+ },
+ (reason) => {
+ this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
+ }
+ );
+ }
+
+ private getDismissReason(reason: any): string {
+ if (reason === ModalDismissReasons.ESC) {
+ return 'by pressing ESC';
+ } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
+ return 'by clicking on a backdrop';
+ } else {
+ return `with: ${reason}`;
+ }
+ }
+
+ saveAndClose(modal: any) {
+ this.isModalSaved = true;
+ modal.close('Save click');
+ }
+
+ emailValidator(): ValidatorFn {
+ const nameRe: RegExp = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/;
+ return (control: AbstractControl): ValidationErrors | null => {
+ const invalid = !nameRe.test(control.value);
+ return invalid ? { invalidName: { value: control.value } } : null;
+ };
+ }
+
+ mobileValidator(): ValidatorFn {
+ const nameRe: RegExp = /^$|[0-9]{11}/;
+ return (control: AbstractControl): ValidationErrors | null => {
+ const invalid = !nameRe.test(control.value);
+ return invalid ? { invalidName: { value: control.value } } : null;
+ };
+
+ }
+
+ get name() {
+ return this.locationForm.get('name');
+ }
+
+ get email() {
+ return this.locationForm.get('email');
+ }
+
+ get mobile() {
+ return this.locationForm.get('mobile');
+ }
+
+ onSubmit(): void {
+ this.location.latitude = 555;
+ this.location.longitude = 555;
+ this.locationService
+ .createResource({ body: this.location })
+ .subscribe((location: Location) => {
+ console.log(location);
+ const uri = (location as any).uri;
+ this.router.navigate([uri]).then();
+ });
+ }
+
+}
diff --git a/src/app/location/location-list/location-list.component.html b/src/app/location/location-list/location-list.component.html
new file mode 100644
index 0000000..83e76c1
--- /dev/null
+++ b/src/app/location/location-list/location-list.component.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
City
+
{{location["city"]}}
+
+
+
PostalCode
+
{{location["postalCode"]}}
+
+
+
Address
+
{{location.address}}
+
+
+
Province
+
{{location["province"]}}
+
+
+
+
+
+
+
diff --git a/src/app/location/location-list/location-list.component.ts b/src/app/location/location-list/location-list.component.ts
new file mode 100644
index 0000000..d909edb
--- /dev/null
+++ b/src/app/location/location-list/location-list.component.ts
@@ -0,0 +1,39 @@
+
+import { Router } from '@angular/router';
+import { Component, OnInit } from '@angular/core';
+import { LocationService } from '../location.service';
+import { PagedResourceCollection } from '@lagoshny/ngx-hateoas-client';
+import {Location} from "../location";
+
+@Component({
+ selector: 'app-location-list',
+ templateUrl: './location-list.component.html'
+})
+export class LocationListComponent implements OnInit {
+ public locations: Location[] = [];
+ public pageSize = 5;
+ public page = 1;
+ public totalLocations = 0;
+
+ constructor(
+ public router: Router,
+ private locationService: LocationService) {
+ }
+
+ ngOnInit(): void {
+ this.locationService.getPage({ pageParams: { size: this.pageSize }, sort: { id: 'ASC' } }).subscribe(
+ (page: PagedResourceCollection
) => {
+ this.locations = page.resources;
+ this.totalLocations = page.totalElements;
+ });
+ }
+
+ changePage(): void {
+ this.locationService.getPage({ pageParams: { page: this.page - 1, size: this.pageSize }, sort: { id: 'ASC' } }).subscribe(
+ (page: PagedResourceCollection) => this.locations = page.resources);
+ }
+
+ detail(location: Location): void {
+ this.router.navigate(['locations', location.id]);
+ }
+}
diff --git a/src/app/location/location-search/location-search.component.html b/src/app/location/location-search/location-search.component.html
new file mode 100644
index 0000000..441a363
--- /dev/null
+++ b/src/app/location/location-search/location-search.component.html
@@ -0,0 +1,11 @@
+
+
+
+
+ {{r.email}}
+ยบ
diff --git a/src/app/location/location-search/location-search.component.ts b/src/app/location/location-search/location-search.component.ts
new file mode 100644
index 0000000..b31088f
--- /dev/null
+++ b/src/app/location/location-search/location-search.component.ts
@@ -0,0 +1,43 @@
+
+import { Component, EventEmitter, Output } from '@angular/core';
+import { LocationService } from '../location.service';
+import { Observable, of, OperatorFunction } from 'rxjs';
+import { catchError, debounceTime, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
+import { ResourceCollection } from '@lagoshny/ngx-hateoas-client';
+import {Location} from "../location";
+
+@Component({
+ selector: 'app-location-search',
+ templateUrl: './location-search.component.html'
+})
+
+export class LocationSearchComponent {
+ @Output() emitResults: EventEmitter = new EventEmitter();
+ searchFailed = false;
+ searching = false;
+
+ constructor(private locationService: LocationService) {
+ }
+
+ autocomplete: OperatorFunction = (text$: Observable) =>
+ text$.pipe(
+ debounceTime(500),
+ distinctUntilChanged(),
+ tap(() => this.searching = true),
+ switchMap(term => term.length < 3 ? of([]) :
+ this.locationService.findById(term).pipe(
+ map((collection: ResourceCollection) => collection.resources),
+ tap(() => this.searchFailed = false),
+ catchError(() => {
+ this.searchFailed = true;
+ return of([]);
+ })
+ )
+ ),
+ tap(() => this.searching = false )
+ )
+
+ select(item: any): void {
+ this.emitResults.emit(item as Location);
+ }
+}
diff --git a/src/app/location/location.service.ts b/src/app/location/location.service.ts
new file mode 100644
index 0000000..68a1364
--- /dev/null
+++ b/src/app/location/location.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from "@angular/core";
+import { Observable } from "rxjs/internal/Observable";
+import { HateoasResourceOperation, ResourceCollection } from "@lagoshny/ngx-hateoas-client";
+import { Location } from "./location";
+
+@Injectable({providedIn: "root"})
+export class LocationService extends HateoasResourceOperation {
+
+ constructor() {
+ super(Location);
+ }
+
+ public findLocationByAddressAndProvinceAndCityAndPostalCode(address:string, province:string, city:string, postalcode:number): Observable> {
+ const params = {
+ address: address,
+ province: province,
+ city: city,
+ postalcode: postalcode.toString()
+ };
+ return this.searchCollection('findLocationByAddressAndProvinceAndCityAndPostalCode', {params});
+
+ }
+
+ public findById(id: string): Observable> {
+ return this.searchCollection("findById", { params: { id: id } })
+ }
+
+ public findByPostalCode(postalCode: string): Observable> {
+ return this.searchCollection("findByPostalCode", { params: { postalCode: postalCode } })
+ }
+
+ public findByProvince(province: string): Observable> {
+ return this.searchCollection("findByProvince", { params: { province: province } })
+ }
+
+
+
+ public findByCity(city: string): Observable> {
+ return this.searchCollection("findByCity", { params: { city: city } })
+ }
+ public findByAddress(address: string): Observable> {
+ return this.searchCollection("findByAddress", { params: { address: address } })
+ }
+
+}
+
+
+
diff --git a/src/app/location/location.ts b/src/app/location/location.ts
new file mode 100644
index 0000000..ea4b325
--- /dev/null
+++ b/src/app/location/location.ts
@@ -0,0 +1,22 @@
+import { HateoasResource, Resource } from '@lagoshny/ngx-hateoas-client';
+
+@HateoasResource('locations')
+export class Location extends Resource {
+ address: string;
+ latitude: number;
+ longitude: number;
+ province: string;
+ city: string;
+ postalCode:number;
+ uri: string;
+
+ constructor(values: object = {}) {
+ super();
+ Object.assign(this as any, values);
+ }
+
+ public get id(): string {
+ let uriArray = this.uri.split('/');
+ return uriArray.pop();
+ }
+}
diff --git a/src/app/navbar/navbar.component.html b/src/app/navbar/navbar.component.html
index 418ef19..adbc437 100644
--- a/src/app/navbar/navbar.component.html
+++ b/src/app/navbar/navbar.component.html
@@ -11,7 +11,7 @@
About
- Users
+
+ Locations
+
+