diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 0c9462c..be0f8ed 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -13,6 +13,7 @@ import {RoleListComponent} from "./role/role-list/role-list.component";
import {RoleCreateComponent} from "./role/role-create/role-create.component"
import {RoleDeleteComponent} from "./role/role-delete/role-delete.component";
import {RoleDetailComponent} from "./role/role-detail/role-detail.component";
+import {ShelterCreateComponent} from "./shelter/shelter-create/shelter-create.component";
const routes: Routes = [
{ path: 'users/create', component: UserRegisterComponent},
@@ -28,6 +29,7 @@ const routes: Routes = [
{path: 'role/create', component:RoleCreateComponent},
{path:'role/:id/delete', component:RoleDeleteComponent},
{path:'role/:id', component:RoleDetailComponent},
+ { path: 'shelters/create', component: ShelterCreateComponent},
];
@NgModule({
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index a5d08df..ada9a08 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -28,6 +28,10 @@ import {RoleListComponent} from './role/role-list/role-list.component';
import {RoleCreateComponent} from './role/role-create/role-create.component';
import {RoleDeleteComponent} from "./role/role-delete/role-delete.component";
import {RoleDetailComponent} from "./role/role-detail/role-detail.component";
+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";
@NgModule({
declarations: [
@@ -45,6 +49,9 @@ import {RoleDetailComponent} from "./role/role-detail/role-detail.component";
RoleCreateComponent,
RoleDeleteComponent,
RoleDetailComponent,
+ ShelterListComponent,
+ ShelterCreateComponent,
+ ShelterDetailComponent
],
imports: [
BrowserModule,
@@ -58,12 +65,12 @@ import {RoleDetailComponent} from "./role/role-detail/role-detail.component";
LoginBasicModule,
ErrorHandlerModule,
NgbModule,
- ReactiveFormsModule,
+ ReactiveFormsModule
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true },
- AuthenticationBasicService, LoggedInGuard, UserService, provideAnimationsAsync()
+ AuthenticationBasicService, LoggedInGuard, UserService, ShelterService, provideAnimationsAsync()
],
bootstrap: [AppComponent]
})
diff --git a/src/app/navbar/navbar.component.html b/src/app/navbar/navbar.component.html
index 4bfacdc..7ac16ed 100644
--- a/src/app/navbar/navbar.component.html
+++ b/src/app/navbar/navbar.component.html
@@ -26,6 +26,14 @@
[routerLink]="['/role']"> List
Create
+ Shelters
+
+
diff --git a/src/app/shelter/shelter-create/shelter-create.component.html b/src/app/shelter/shelter-create/shelter-create.component.html
new file mode 100644
index 0000000..0d81e0b
--- /dev/null
+++ b/src/app/shelter/shelter-create/shelter-create.component.html
@@ -0,0 +1,97 @@
+
diff --git a/src/app/shelter/shelter-create/shelter-create.component.ts b/src/app/shelter/shelter-create/shelter-create.component.ts
new file mode 100644
index 0000000..9a88928
--- /dev/null
+++ b/src/app/shelter/shelter-create/shelter-create.component.ts
@@ -0,0 +1,129 @@
+import {Component, OnInit} from '@angular/core';
+import {Router} from "@angular/router";
+import {ShelterService} from "../shelter.service";
+import {Shelter} from "../shelter";
+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-shelter-create',
+ templateUrl: './shelter-create.component.html',
+})
+export class ShelterCreateComponent implements OnInit{
+
+ closeResult = '';
+ public isModalSaved: boolean = false;
+ public shelters: Shelter[] = [];
+ public shelter: Shelter;
+ public commonNameInput: string = '';
+ public commonEmailsList: any = [];
+ public shelterForm: FormGroup;
+
+ constructor(
+ private router: Router,
+ private shelterService: ShelterService,
+ private modalService: NgbModal
+ ) {}
+
+ ngOnInit(): void {
+ this.shelter = new Shelter();
+ this.shelterForm = new FormGroup({
+ name: new FormControl(this.shelter.name, [
+ Validators.required,
+ ]),
+ email: new FormControl(this.shelter.email, [
+ Validators.required,
+ this.emailValidator(),
+ ]),
+ mobile: new FormControl(this.shelter.mobile, [
+ Validators.required,
+ this.mobileValidator(),
+ ]),
+ });
+ this.loadShelterList();
+ }
+
+ loadShelterList() {
+ this.shelterService
+ .getPage({
+ sort: { name: 'ASC' },
+ })
+ .subscribe((shelters: PagedResourceCollection) => {
+ this.shelters = shelters.resources.sort((a, b) =>
+ a.name.localeCompare(b.name)
+ );
+ });
+ }
+
+ 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.shelterForm.get('name');
+ }
+
+ get email() {
+ return this.shelterForm.get('email');
+ }
+
+ get mobile() {
+ return this.shelterForm.get('mobile');
+ }
+
+ onSubmit(): void {
+ this.shelter.createdAt = new Date();
+ this.shelter.updatedAt = new Date();
+ this.shelterService
+ .createResource({ body: this.shelter })
+ .subscribe((shelter: Shelter) => {
+ console.log(shelter);
+ const uri = (shelter as any).uri;
+ this.router.navigate([uri]).then();
+ });
+ }
+
+}
diff --git a/src/app/shelter/shelter-delete/shelter-delete.component.html b/src/app/shelter/shelter-delete/shelter-delete.component.html
new file mode 100644
index 0000000..7725f68
--- /dev/null
+++ b/src/app/shelter/shelter-delete/shelter-delete.component.html
@@ -0,0 +1,25 @@
+
+
+
Please, confirm deletion:
+
+
+
+
+
+
+
+
diff --git a/src/app/shelter/shelter-delete/shelter-delete.component.ts b/src/app/shelter/shelter-delete/shelter-delete.component.ts
new file mode 100644
index 0000000..a26d8af
--- /dev/null
+++ b/src/app/shelter/shelter-delete/shelter-delete.component.ts
@@ -0,0 +1,37 @@
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute, Router} from "@angular/router";
+import {Shelter} from "../shelter";
+import {ShelterService} from "../shelter.service";
+
+@Component({
+ selector: 'app-shelter-delete',
+ templateUrl: './shelter-delete.component.html',
+})
+export class ShelterDeleteComponent implements OnInit {
+ idShelter: string;
+ shelter: Shelter;
+ constructor(
+ private router: Router,
+ private shelterService: ShelterService,
+ private route: ActivatedRoute
+ ) {}
+ ngOnInit(): void {
+ this.idShelter = this.route.snapshot.paramMap.get('id');
+ }
+ delete() {
+ this.shelterService.getResource(this.idShelter).subscribe((shelter: Shelter) => {
+ this.shelter = shelter;
+ this.shelterService
+ .patchResource(this.shelter)
+ .subscribe((patchedShelter: Shelter) => {
+ this.shelterService.deleteResourceById(patchedShelter.id).subscribe({
+ next: (e) => {
+ this.router.navigateByUrl('/shelters');
+ },
+ error: (err) => {
+ },
+ });
+ });
+ });
+ }
+}
diff --git a/src/app/shelter/shelter-detail/shelter-detail.component.html b/src/app/shelter/shelter-detail/shelter-detail.component.html
new file mode 100644
index 0000000..13250a5
--- /dev/null
+++ b/src/app/shelter/shelter-detail/shelter-detail.component.html
@@ -0,0 +1,45 @@
+
+
+
Shelter {{ shelterDetail.id }}
+
+
+
Name
+
+ {{ shelterDetail.name }}
+
+
+
+
Email
+
{{ shelterDetail.email }}
+
+
+
+
+
diff --git a/src/app/shelter/shelter-detail/shelter-detail.component.ts b/src/app/shelter/shelter-detail/shelter-detail.component.ts
new file mode 100644
index 0000000..8eaf462
--- /dev/null
+++ b/src/app/shelter/shelter-detail/shelter-detail.component.ts
@@ -0,0 +1,29 @@
+import {Component, OnInit} from '@angular/core';
+import {Shelter} from "../shelter";
+import {ActivatedRoute} from "@angular/router";
+import {AuthenticationBasicService} from "../../login-basic/authentication-basic.service";
+import {ShelterService} from "../shelter.service";
+
+@Component({
+ selector: 'app-shelter-detail',
+ templateUrl: './shelter-detail.component.html',
+})
+export class ShelterDetailComponent implements OnInit{
+ shelterDetail: Shelter;
+ constructor(
+ private route: ActivatedRoute,
+ private shelterService: ShelterService,
+ private authenticationService: AuthenticationBasicService
+ ) {}
+
+ ngOnInit(): void {
+ const id = this.route.snapshot.paramMap.get('id');
+ this.shelterService.getResource(id).subscribe((shelter: Shelter) => {
+ this.shelterDetail = shelter;
+ });
+ }
+
+ isRole(role: string): boolean {
+ return this.authenticationService.isRole(role);
+ }
+}
diff --git a/src/app/shelter/shelter-list/shelter-list.component.html b/src/app/shelter/shelter-list/shelter-list.component.html
index 31ee882..a5b98f8 100644
--- a/src/app/shelter/shelter-list/shelter-list.component.html
+++ b/src/app/shelter/shelter-list/shelter-list.component.html
@@ -1 +1,21 @@
-
+
+
+
+
+
+
E-mail
+
{{shelter.email}}
+
+
+
+
+
+
+
+
+
diff --git a/src/app/shelter/shelter-list/shelter-list.component.ts b/src/app/shelter/shelter-list/shelter-list.component.ts
index f5943c6..30c8add 100644
--- a/src/app/shelter/shelter-list/shelter-list.component.ts
+++ b/src/app/shelter/shelter-list/shelter-list.component.ts
@@ -1,11 +1,44 @@
-import { Component } from '@angular/core';
+import {Component, OnInit} from '@angular/core';
+import {Shelter} from "../shelter";
+import {Router} from "@angular/router";
+import {ShelterService} from "../shelter.service";
+import {PagedResourceCollection} from "@lagoshny/ngx-hateoas-client";
@Component({
selector: 'app-shelter-list',
- standalone: true,
- imports: [],
templateUrl: './shelter-list.component.html',
})
-export class ShelterListComponent {
+export class ShelterListComponent implements OnInit {
+ public shelters: Shelter[] = [];
+ public pageSize = 5;
+ public page = 1;
+ public totalShelters = 0;
+ constructor(
+ public router: Router,
+ private shelterService: ShelterService,
+ ) {}
+
+ ngOnInit(): void {
+ this.shelterService
+ .getPage({
+ pageParams: { size: this.pageSize },
+ sort: { name: 'ASC' },
+ })
+ .subscribe((page: PagedResourceCollection) => {
+ this.shelters = page.resources;
+ console.log(this.shelters);
+ this.totalShelters = page.totalElements;
+ });
+ }
+ changePage(): void {
+ this.shelterService
+ .getPage({
+ pageParams: { page: this.page - 1, size: this.pageSize },
+ sort: { name: 'ASC' },
+ })
+ .subscribe(
+ (page: PagedResourceCollection) => (this.shelters = page.resources)
+ );
+ }
}
diff --git a/src/app/shelter/shelter.service.ts b/src/app/shelter/shelter.service.ts
new file mode 100644
index 0000000..6df3803
--- /dev/null
+++ b/src/app/shelter/shelter.service.ts
@@ -0,0 +1,16 @@
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs/internal/Observable';
+import { HateoasResourceOperation, ResourceCollection } from '@lagoshny/ngx-hateoas-client';
+import {Shelter} from "./shelter";
+
+@Injectable({providedIn: 'root'})
+export class ShelterService extends HateoasResourceOperation {
+
+ constructor() {
+ super(Shelter);
+ }
+
+ public findByName(query: string): Observable> {
+ return this.searchCollection('findByName', { params: { text: query } });
+ }
+}
diff --git a/src/app/shelter/shelter.ts b/src/app/shelter/shelter.ts
new file mode 100644
index 0000000..368a723
--- /dev/null
+++ b/src/app/shelter/shelter.ts
@@ -0,0 +1,22 @@
+import { HateoasResource, Resource } from '@lagoshny/ngx-hateoas-client';
+
+@HateoasResource('shelters')
+export class Shelter extends Resource {
+ uri: string;
+ name: string;
+ email: string;
+ mobile: string;
+ createdAt: Date;
+ updatedAt: Date;
+ isActive: boolean;
+
+ constructor(values: object = {}) {
+ super();
+ Object.assign(this as any, values);
+ }
+
+ public get id(): string {
+ let uriArray = this.uri.split('/');
+ return uriArray.pop();
+ }
+}